• Aucun résultat trouvé

Creation of an AF_INET Socket

Dans le document Chapter 3: TCP/IP in Embedded Systems (Page 126-130)

Chapter 5: Linux Sockets

5.11 Creation of a Socket

5.11.1 Creation of an AF_INET Socket

The create function for the TCP/IP protocol family, AF_INET is inet_create, is defined in file af_inet.c.

static int inet_create(struct socket *sock, int protocol);

Inet_create is defined as static because it is not called directly. Instead, it is called through the create field in the net_proto_family structure for the AF_INET protocol family. Inet_create is called from sys_socket when family is set to AF_INET. In inet_create, we create a new sock structure called sk and initialize a few more fields. The new sock structure is allocated from the slab cache, inet_sk_slab. Linux has multiple inet_sk_slabs, one for each protocol. Linux slab caches are more efficient if they are specific for the purpose, so most fields can be pre-initialized to common values. We call sk_alloc to allocate the sock structure from the slab cache that is specific to the protocol for this socket.

sk = sk_alloc(PF_INET, GFP_KERNEL, inet_sk_size(protocol) inet_sk_slab(protocol));

Sk points to the new slab cache. Next, inet_create searches the protocol switch table to look for a match from the protocol.

After getting the result from the search of the protocol switch table, the capability flags are checked against the capabilities of the current process, and if the caller doesn’t have permission to create this type of socket, the user level socket call will return the EPERM error.

Now, inet_create will set some fields in the new sock data structure, however, many fields are pre-initialized when allocation is done from the slab cache. The field sk_family is set to

PF_INET. The prot field is set to the protocol’s protocol block structure that defines the specific function for each of the transport protocols. No_check and ops are set according to their

respective values in the protocol switch table. If the type of the socket is SOCK_RAW, the num field is set to the protocol number. As will be shown in later chapters, this field is used by IP to route packets internally depending on whether there is a raw socket open. The sk_destruct field of sk is set to inet_sock_destruct, the sock structure destructor. The sk_backlog_rcv field is set to point to the protocol-specific backlog receive function. Next, some fields in the protocol family-specific part of the sock structure are initialized. As discussed in Section 5.3.1, the sock structure is followed by a protocol-specific portion for each of the two protocol families, IPv4 and IPv6,

and this part is accessed through a macro, inet_sk, which is defined in the file linux/include/linux/ip.h.

#define inet_sk(__sk) (&((struct inet_sock *)__sk)->inet)

The inet_opt structure for IPv4 is also defined in the file linux/include/linux/ip.h.

struct inet_opt {

These first few fields are for socket layer de-multiplexing of incoming packets. Daddr is the peer IPv4 address, and rcv_saddr is the bound local IPv4 address. Dport is the destination port, num is the local port, and saddr is the source address.

__u32 daddr;

__u32 rcv_saddr;

__u16 dport;

__u16 num;

__u32 saddr;

The uc_ttl field is for setting the time-to-live field in the IP header.

int uc_ttl;

Tos is for setting the type of service field in the IP header. The cmsg_flags field is used by setsockopt and getsockopt to communicate network layer IP socket options to the IP protocol layer. In addition, ip_options points to the values associated with the options set in the cmsg_flags field.

int tos;

unsigned cmsg_flags;

struct ip_options *opt;

Sport is the source port number.

__u16 sport;

Hdrincl is for raw sockets. It states that the IP header is included in the packet delivered to the application level.

unsigned char hdrincl;

This field is the multicasting time-to-live.

__u8 mc_ttl;

The next field indicates whether multicast packets should be looped back. Pmtudisc indicates whether MTU discovery should be performed on this interface.

__u8 mc_loop;

__u8 pmtudisc;

The next field, id, contains the counter for identification field in the IP header. This field is used by the receiving machine for re-assembling fragmented IP packets.

__u16 id;

unsigned recverr : 1, freebind : 1;

Mc_index is the index for the output network interface used for transmission of multicast packets, and mc_addr is the source address used for outgoing packets sent to a multicast address.

int mc_index;

__u32 mc_addr;

This field, mc_list, points to the list of multicast address groups to which the interface has subscribed.

struct ip_mc_socklist *mc_list;

The next field is the cached page from the sendmsg socket function, and sndmsg_off is the offset into the page.

struct page *sndmsg_page;

u32 sndmsg_off;

The following structure keeps information about the IP options needed to build an IP header on each outgoing IP fragment. Since all the fragments have almost identical headers, the options are kept here to speed the process of building IP headers on consecutive fragments. It is called cork, because the socket is "corked," waiting for all fragments of the total IP datagram to be

transmitted.

struct {

unsigned int flags;

unsigned int fragsize;

struct ip_options *opt;

struct rtable *rt;

This field, length, is the total length of all frames in the fragmented IP datagram.

int length;

u32 addr;

struct flowi fl;

} cork;

} ;

Some fields in the inet_opt are initialized by inet_create. Some of these fields are related to multicast transmission, which is covered in more detail in Chapter 9. In each case, inet points to the instance of the inet_opt structure shown previously.

inet->uc_ttl = -1;

inet->mc_loop = 1;

inet->mc_ttl = 1;

inet->mc_index = 0;

inet->mc_list = NULL;

The default live field, mc_ttl is initialized because this value will be used in the time-to-live IP header field for multicast packets. Even though these values are initialized here, the application may change the values in these fields later through the setsockopt call. Finally, inet_create calls the protocol-specific initialization function through the init field in the protocol block structure, proto, defined in file linux/include/net/sock.h.

Here is the proto structure.

struct proto {

Most of the fields in this structure point to the protocol-specific operations. We will explain a few of these functions in a little more detail.

void (*close)(struct sock *sk,

Init points to the protocol’s specific initialization function. This function is called when a socket is created for this protocol. Destroy points to the destructor function for this protocol. The destructor is executed when a socket for this protocol is closed.

int (*init)(struct sock *sk);

struct sk_buff *skb);

The following three functions are for keeping track of sock structures, looking them up, and getting the port number associated with the sock, respectively.

void (*hash)(struct sock *sk);

void (*unhash)(struct sock *sk);

int (*get_port)(struct sock *sk, unsigned short snum);

char name[32];

Inuse indicates whether this sock structure is being used. For SMP implementations, there is one per CPU.

struct {

int inuse;

u8 __pad[SMP_CACHE_BYTES - sizeof(int)];

} stats[NR_CPUS];

} ;

The sk_prot field in the sock structure points to the protocol block structure. The init field in the proto structure is specific for each protocol and socket type within the AF_INET protocol family.

Dans le document Chapter 3: TCP/IP in Embedded Systems (Page 126-130)