bind(sockscap,(structsockscapaddxCaret=max(xCaret-1,0);

3、套接字的实现套接字最先是在UNIX的BSD版本实现的,所以也叫做BSD套接字,它隐藏了各个协议之间的差异,并向上提供统一的接口。Linux中实现套接字的基本结构:3.1、BSD套接字3.1.1、核心数据结构为了实现BSD套接字,内核提供一个重要的数据结构struct socket,它的定义如下:&//BSD套接字(include/linux/net.h)struct&socket&{&&&&socket_state&&&&&&&&&&//套接字状态&&&&unsigned&long&&&&&&&&&&&&struct&proto_ops&&&&*&//操作函数集&&&&struct&fasync_struct&&&&*fasync_&&&&struct&file&&&&&&&&*//每个BSD套接字都有一个inode结点,通过文件对象与其关联起来&&&&&&struct&sock&&&&&&&&*&//socket内部结构,与具体的协议簇(比如PF_INET)相关&&&&wait_queue_head_t&&&&&&&&short&&&&&&&&&&&&&&&&//套接字类型:如SOCK_STREAM,&SOCK_DGRAM,&SOCK_RAW,&SOCK_RDM,&SOCK_SEQPACKET,&and&SOCK_PACKET&&&&unsigned&char&&&&&&&&&};//BSD套接字操作函数集struct&proto_ops&{&&&&int&&&&&&&&&&&&struct&module&&&&*&&&&int&&&&&&&&(*release)&&&(struct&socket&*sock);&&&&int&&&&&&&&(*bind)&&&&&&&&&(struct&socket&*sock,&&&&&&&&&&&&&&&&&&&&&&struct&sockaddr&*myaddr,&&&&&&&&&&&&&&&&&&&&&&int&sockaddr_len);&&&&int&&&&&&&&(*connect)&&&(struct&socket&*sock,&&&&&&&&&&&&&&&&&&&&&&struct&sockaddr&*vaddr,&&&&&&&&&&&&&&&&&&&&&&int&sockaddr_len,&int&flags);&&&&int&&&&&&&&(*socketpair)(struct&socket&*sock1,&&&&&&&&&&&&&&&&&&&&&&struct&socket&*sock2);&&&&int&&&&&&&&(*accept)&&&&(struct&socket&*sock,&&&&&&&&&&&&&&&&&&&&&&struct&socket&*newsock,&int&flags);&&&&int&&&&&&&&(*getname)&&&(struct&socket&*sock,&&&&&&&&&&&&&&&&&&&&&&struct&sockaddr&*addr,&&&&&&&&&&&&&&&&&&&&&&int&*sockaddr_len,&int&peer);&&&&unsigned&int&&&&(*poll)&&&&&&&&&(struct&file&*file,&struct&socket&*sock,&&&&&&&&&&&&&&&&&&&&&&struct&poll_table_struct&*wait);&&&&int&&&&&&&&(*ioctl)&&&&&(struct&socket&*sock,&unsigned&int&cmd,&&&&&&&&&&&&&&&&&&&&&&unsigned&long&arg);&&&&int&&&&&&&&(*listen)&&&&(struct&socket&*sock,&int&len);&&&&int&&&&&&&&(*shutdown)&&(struct&socket&*sock,&int&flags);&&&&int&&&&&&&&(*setsockopt)(struct&socket&*sock,&int&level,&&&&&&&&&&&&&&&&&&&&&&int&optname,&char&__user&*optval,&int&optlen);&&&&int&&&&&&&&(*getsockopt)(struct&socket&*sock,&int&level,&&&&&&&&&&&&&&&&&&&&&&int&optname,&char&__user&*optval,&int&__user&*optlen);&&&&int&&&&&&&&(*sendmsg)&&&(struct&kiocb&*iocb,&struct&socket&*sock,&&&&&&&&&&&&&&&&&&&&&&struct&msghdr&*m,&size_t&total_len);&&&&int&&&&&&&&(*recvmsg)&&&(struct&kiocb&*iocb,&struct&socket&*sock,&&&&&&&&&&&&&&&&&&&&&&struct&msghdr&*m,&size_t&total_len,&&&&&&&&&&&&&&&&&&&&&&int&flags);&&&&int&&&&&&&&(*mmap)&&&&&&&&&(struct&file&*file,&struct&socket&*sock,&&&&&&&&&&&&&&&&&&&&&&struct&vm_area_struct&*&vma);&&&&ssize_t&&&&&&&&(*sendpage)&&(struct&socket&*sock,&struct&page&*page,&&&&&&&&&&&&&&&&&&&&&&int&offset,&size_t&size,&int&flags);};//BSD套接字状态typedef&enum&{&&&&SS_FREE&=&0,&&&&&&&&&&&&/*&not&allocated&&&&&&&&*/&&&&SS_UNCONNECTED,&&&&&&&&&&&&/*&unconnected&to&any&socket&&&&*/&&&&SS_CONNECTING,&&&&&&&&&&&&/*&in&process&of&connecting&&&&*/&&&&SS_CONNECTED,&&&&&&&&&&&&/*&connected&to&socket&&&&&&&&*/&&&&SS_DISCONNECTING&&&&&&&&/*&in&process&of&disconnecting&&&&*/}&socket_ 3.1.2、BSD套接字初始化//net/socket.c//BSD套接字的初始化void&__init&sock_init(void){&&&&int&i;&&&&/*&&&&&*&&&&Initialize&all&address&(protocol)&families.&&&&&&*/&&&&&&&&&for&(i&=&0;&i&&&NPROTO;&i++)&&&&&&&&&net_families[i]&=&NULL;&//协议簇数组初始化&&&&/*&&&&&*&&&&Initialize&sock&SLAB&cache.&&&&&*/&&&&&//分配sock缓存&&&&sk_init();#ifdef&SLAB_SKB&&&&/*&&&&&*&&&&Initialize&skbuff&SLAB&cache&&&&&&*/&&&&skb_init();#endif&&&&/*&&&&&*&&&&Initialize&the&protocols&module.&&&&&&*/&&&&init_inodecache();&&&&//注册sockfs文件系统&&&&register_filesystem(&sock_fs_type);&&&&//安装sockfs&&&&sock_mnt&=&kern_mount(&sock_fs_type);&&&&/*&The&real&protocol&initialization&is&performed&when&&&&&*&&do_initcalls&is&run.&&&&&&&*/#ifdef&CONFIG_NETFILTER&&&&netfilter_init();#endif}//net/socket.c//sockfs文件系统的安装点static&struct&vfsmount&*sock_//sockfs文件系统类型static&struct&file_system_type&sock_fs_type&=&{&&&&.name&=&&&&&&&&"sockfs",&&&&.get_sb&=&&&&sockfs_get_sb,&&&&.kill_sb&=&&&&kill_anon_super,};&//地址簇及协议信息static&struct&net_proto_family&*net_families[NPROTO]; sock_init在系统初始化的被调用:3.1.3、BSD套接字的系统调用实际上,Linux内核只提供了一个与套接字相关的系统调用,即sys_socketcall,应用程序的所有套接字调用都会映射到这个系统调用上。//BSD套接字调用入口(net/socket.c)asmlinkage&long&sys_socketcall(int&call,&unsigned&long&__user&*args){&&&&unsigned&long&a[6];&&&&unsigned&long&a0,a1;&&&&int&&&&&if(call&1||call&SYS_RECVMSG)&&&&&&&&return&-EINVAL;&&&&/*&copy_from_user&should&be&SMP&safe.&*/&&&&if&(copy_from_user(a,&args,&nargs[call]))//从用户区拷贝参数&&&&&&&&return&-EFAULT;&&&&&&&&&&&&a0=a[0];&&&&a1=a[1];&&&&&&&&switch(call)&&//调用相应的函数&&&&{&&&&&&&&case&SYS_SOCKET:&&&&&&&&&&&&err&=&sys_socket(a0,a1,a[2]);&&&&&&&&&&&&break;&&&&&&&&case&SYS_BIND:&&&&&&&&&&&&err&=&sys_bind(a0,(struct&sockaddr&__user&*)a1,&a[2]);&&&&&&&&&&&&break;&&&&&&&&case&SYS_CONNECT:&&&&&&&&&&&&err&=&sys_connect(a0,&(struct&sockaddr&__user&*)a1,&a[2]);&&&&&&&&&&&&break;&&&&&&&&case&SYS_LISTEN:&&&&&&&&&&&&err&=&sys_listen(a0,a1);&&&&&&&&&&&&break;&&&&&&&&case&SYS_ACCEPT:&&&&&&&&&&&&err&=&sys_accept(a0,(struct&sockaddr&__user&*)a1,&(int&__user&*)a[2]);&&&&&&&&&&&&break;&&&&&&&&case&SYS_GETSOCKNAME:&&&&&&&&&&&&err&=&sys_getsockname(a0,(struct&sockaddr&__user&*)a1,&(int&__user&*)a[2]);&&&&&&&&&&&&break;&&&&&&&&case&SYS_GETPEERNAME:&&&&&&&&&&&&err&=&sys_getpeername(a0,&(struct&sockaddr&__user&*)a1,&(int&__user&*)a[2]);&&&&&&&&&&&&break;&&&&&&&&case&SYS_SOCKETPAIR:&&&&&&&&&&&&err&=&sys_socketpair(a0,a1,&a[2],&(int&__user&*)a[3]);&&&&&&&&&&&&break;&&&&&&&&case&SYS_SEND:&&&&&&&&&&&&err&=&sys_send(a0,&(void&__user&*)a1,&a[2],&a[3]);&&&&&&&&&&&&break;&&&&&&&&case&SYS_SENDTO:&&&&&&&&&&&&err&=&sys_sendto(a0,(void&__user&*)a1,&a[2],&a[3],&&&&&&&&&&&&&&&&&&&&&(struct&sockaddr&__user&*)a[4],&a[5]);&&&&&&&&&&&&break;&&&&&&&&case&SYS_RECV:&&&&&&&&&&&&err&=&sys_recv(a0,&(void&__user&*)a1,&a[2],&a[3]);&&&&&&&&&&&&break;&&&&&&&&case&SYS_RECVFROM:&&&&&&&&&&&&err&=&sys_recvfrom(a0,&(void&__user&*)a1,&a[2],&a[3],&&&&&&&&&&&&&&&&&&&&&&&(struct&sockaddr&__user&*)a[4],&(int&__user&*)a[5]);&&&&&&&&&&&&break;&&&&&&&&case&SYS_SHUTDOWN:&&&&&&&&&&&&err&=&sys_shutdown(a0,a1);&&&&&&&&&&&&break;&&&&&&&&case&SYS_SETSOCKOPT:&&&&&&&&&&&&err&=&sys_setsockopt(a0,&a1,&a[2],&(char&__user&*)a[3],&a[4]);&&&&&&&&&&&&break;&&&&&&&&case&SYS_GETSOCKOPT:&&&&&&&&&&&&err&=&sys_getsockopt(a0,&a1,&a[2],&(char&__user&*)a[3],&(int&__user&*)a[4]);&&&&&&&&&&&&break;&&&&&&&&case&SYS_SENDMSG:&&&&&&&&&&&&err&=&sys_sendmsg(a0,&(struct&msghdr&__user&*)&a1,&a[2]);&&&&&&&&&&&&break;&&&&&&&&case&SYS_RECVMSG:&&&&&&&&&&&&err&=&sys_recvmsg(a0,&(struct&msghdr&__user&*)&a1,&a[2]);&&&&&&&&&&&&break;&&&&&&&&default:&&&&&&&&&&&&err&=&-EINVAL;&&&&&&&&&&&&break;&&&&}&&&&return&}//include/asm/unistd.h#define&__NR_socketcall&&&&&&&&102&&//系统调用号下面来看一下sys_socket的实现:Code//net/socket.c/*创建socket**首先建立一个socket数据结构,然后将其“映射”到一个已打开的文件.*/asmlinkage&long&sys_socket(int&family,&int&type,&int&protocol){&&&&int&&&&&struct&socket&*&&&&//创建socket&&&&retval&=&sock_create(family,&type,&protocol,&&sock);&&&&if&(retval&&&0)&&&&&&&&goto&out;&&&&//将socket映射到文件描述符&&&&retval&=&sock_map_fd(sock);&&&&if&(retval&&&0)&&&&&&&&goto&out_out:&&&&/*&It&may&be&already&another&descriptor&8)&Not&kernel&problem.&*/&&&&return&out_release:&&&&sock_release(sock);&&&&return&}int&sock_create(int&family,&int&type,&int&protocol,&struct&socket&**res){&&&&return&__sock_create(family,&type,&protocol,&res,&0);}static&int&__sock_create(int&family,&int&type,&int&protocol,&struct&socket&**res,&int&kern){&&&&int&i;&&&&int&&&&&struct&socket&*&&&&/*&&&&&*&&&&Check&protocol&is&in&range&&&&&*/&&&&&//检查协议是否可用&&&&if&(family&&&0&||&family&&=&NPROTO)&&&&&&&&return&-EAFNOSUPPORT;&&&&if&(type&&&0&||&type&&=&SOCK_MAX)&&&&&&&&return&-EINVAL;&&&&/*&Compatibility.&&&&&&&This&uglymoron&is&moved&from&INET&layer&to&here&to&avoid&&&&&&&deadlock&in&module&load.&&&&&*/&&&&if&(family&==&PF_INET&&&&type&==&SOCK_PACKET)&{&&&&&&&&static&int&&&&&&&&&&if&(!warned)&{&&&&&&&&&&&&warned&=&1;&&&&&&&&&&&&printk(KERN_INFO&"%s&uses&obsolete&(PF_INET,SOCK_PACKET)\n",&current-&comm);&&&&&&&&}&&&&&&&&family&=&PF_PACKET;&&&&}&&&&err&=&security_socket_create(family,&type,&protocol,&kern);&&&&if&(err)&&&&&&&&return&&&&&&&&&#if&defined(CONFIG_KMOD)&&&&/*&Attempt&to&load&a&protocol&module&if&the&find&failed.&&&&&&*&&&&&&*&12/09/1996&Marcin:&But!&this&makes&REALLY&only&sense,&if&the&user&&&&&&*&requested&real,&full-featured&networking&support&upon&configuration.&&&&&*&Otherwise&module&support&will&break!&&&&&*/&&&&if&(net_families[family]==NULL)&&&&{&&&&&&&&request_module("net-pf-%d",family);&&&&}#endif&&&&net_family_read_lock();&&&&if&(net_families[family]&==&NULL)&{&&&&&&&&i&=&-EAFNOSUPPORT;&&&&&&&&goto&out;&&&&}/*&*&&&&Allocate&the&socket&and&allow&the&family&to&set&things&up.&if&*&&&&the&protocol&is&0,&the&family&is&instructed&to&select&an&appropriate&*&&&&default.&*/&&&&//从sockfs分配一个inode,并为之分配一个套接字结构&&&&if&(!(sock&=&sock_alloc()))&&&&&{&&&&&&&&printk(KERN_WARNING&"socket:&no&more&sockets\n");&&&&&&&&i&=&-ENFILE;&&&&&&&&/*&Not&exactly&a&match,&but&its&the&&&&&&&&&&&&&&&&&&&&&&&closest&posix&thing&*/&&&&&&&&goto&out;&&&&}&&&&//设置类型&&&&sock-&type&&=&&&&&/*&&&&&*&We&will&call&the&-&create&function,&that&possibly&is&in&a&loadable&&&&&*&module,&so&we&have&to&bump&that&loadable&module&refcnt&first.&&&&&*/&&&&i&=&-EAFNOSUPPORT;&&&&if&(!try_module_get(net_families[family]-&owner))&&&&&&&&goto&out_&&&&&&&&//调用具体协议的create函数&&&&if&((i&=&net_families[family]-&create(sock,&protocol))&&&0)&&&&&&&&goto&out_module_&&&&/*&&&&&*&Now&to&bump&the&refcnt&of&the&[loadable]&module&that&owns&this&&&&&*&socket&at&sock_release&time&we&decrement&its&refcnt.&&&&&*/&&&&if&(!try_module_get(sock-&ops-&owner))&{&&&&&&&&sock-&ops&=&NULL;&&&&&&&&goto&out_module_&&&&}&&&&/*&&&&&*&Now&that&we're&done&with&the&-&create&function,&the&[loadable]&&&&&*&module&can&have&its&refcnt&decremented&&&&&*/&&&&module_put(net_families[family]-&owner);&&&&*res&=&&&&&security_socket_post_create(sock,&family,&type,&protocol,&kern);out:&&&&net_family_read_unlock();&&&&return&i;out_module_put:&&&&module_put(net_families[family]-&owner);out_release:&&&&sock_release(sock);&&&&goto&out;}///////////////////////////////////////////////////////////int&sock_map_fd(struct&socket&*sock){&&&&int&&&&&struct&qstr&this;&&&&char&name[32];&&&&/*&&&&&*&&&&Find&a&file&descriptor&suitable&for&return&to&the&user.&&&&&&*/&&&&//分配一个没有使用的描述符&&&&fd&=&get_unused_fd();&&&&if&(fd&&=&0)&{&&&&&&&&struct&file&*file&=&get_empty_filp();&&&&&&&&if&(!file)&{&&&&&&&&&&&&put_unused_fd(fd);&&&&&&&&&&&&fd&=&-ENFILE;&&&&&&&&&&&&goto&out;&&&&&&&&}&&&&&&&&sprintf(name,&"[%lu]",&SOCK_INODE(sock)-&i_ino);&&&&&&&&this.name&=&&&&&&&&&this.len&=&strlen(name);&&&&&&&&this.hash&=&SOCK_INODE(sock)-&i_&&&&&&&&&&&&&&&&//从sockfs文件系统中分配一个目录项对象&&&&&&&&file-&f_dentry&=&d_alloc(sock_mnt-&mnt_sb-&s_root,&&this);&&&&&&&&if&(!file-&f_dentry)&{&&&&&&&&&&&&put_filp(file);&&&&&&&&&&&&put_unused_fd(fd);&&&&&&&&&&&&fd&=&-ENOMEM;&&&&&&&&&&&&goto&out;&&&&&&&&}&&&&&&&&file-&f_dentry-&d_op&=&&sockfs_dentry_&&&&&&&&&&&&&&&&//将目录项对象与sock的索引节点关联起来&&&&&&&&d_add(file-&f_dentry,&SOCK_INODE(sock));&&&&&&&&file-&f_vfsmnt&=&mntget(sock_mnt);&&&&&&&&file-&f_mapping&=&file-&f_dentry-&d_inode-&i_&&&&&&&&&&&&&&&&//设置sock对应的文件对象&&&&&&&&sock-&file&=&&&&&&&&&&&&&&&&&//设置文件对象的操作函数&&&&&&&&file-&f_op&=&SOCK_INODE(sock)-&i_fop&=&&socket_file_&&&&&&&&file-&f_mode&=&FMODE_READ&|&FMODE_WRITE;&&&&&&&&file-&f_flags&=&O_RDWR;&&&&&&&&file-&f_pos&=&0;&&&&&&&&fd_install(fd,&file);&&&&}out:&&&&return&}3.2、INET套接字INET套接字就是支持 Internet 地址族的套接字,它位于TCP协议之上, BSD套接字之下,如下:3.2.1、数据结构Code//include/net/sock.h//与特定协议相关的socketstruct&sock&{&&&&/*&&&&&*&Now&struct&tcp_tw_bucket&also&uses&sock_common,&so&please&just&&&&&*&don't&add&nothing&before&this&first&member&(__sk_common)&--acme&&&&&*/&&&&struct&sock_common&&&&__sk_#define&sk_family&&&&&&&&__sk_common.skc_family#define&sk_state&&&&&&&&__sk_common.skc_state#define&sk_reuse&&&&&&&&__sk_common.skc_reuse#define&sk_bound_dev_if&&&&&&&&__sk_common.skc_bound_dev_if#define&sk_node&&&&&&&&&&&&__sk_common.skc_node#define&sk_bind_node&&&&&&&&__sk_common.skc_bind_node#define&sk_refcnt&&&&&&&&__sk_common.skc_refcnt&&&&volatile&unsigned&char&&&&sk_&&&&unsigned&char&&&&&&&&sk_&&&&unsigned&char&&&&&&&&sk_use_write_&&&&unsigned&char&&&&&&&&sk_&&&&socket_lock_t&&&&&&&&sk_&&&&int&&&&&&&&&&&&sk_&&&&wait_queue_head_t&&&&*sk_&&&&struct&dst_entry&&&&*sk_dst_&&&&rwlock_t&&&&&&&&sk_dst_&&&&struct&xfrm_policy&&&&*sk_policy[2];&&&&atomic_t&&&&&&&&sk_rmem_&&&&struct&sk_buff_head&&&&sk_receive_&&&&atomic_t&&&&&&&&sk_wmem_&&&&struct&sk_buff_head&&&&sk_write_&&&&atomic_t&&&&&&&&sk_omem_&&&&int&&&&&&&&&&&&sk_wmem_&&&&int&&&&&&&&&&&&sk_forward_&&&&unsigned&int&&&&&&&&sk_&&&&int&&&&&&&&&&&&sk_&&&&unsigned&long&&&&&&&&&sk_&&&&char&&&&&&&&&&&&&sk_no_&&&&unsigned&char&&&&&&&&sk_&&&&unsigned&char&&&&&&&&sk_&&&&unsigned&char&&&&&&&&sk_no_&&&&int&&&&&&&&&&&&sk_route_&&&&unsigned&long&&&&&&&&&&&&sk_&&&&int&&&&&&&&&&&&sk_&&&&/*&&&&&*&The&backlog&queue&is&special,&it&is&always&used&with&&&&&*&the&per-socket&spinlock&held&and&requires&low&latency&&&&&*&access.&Therefore&we&special&case&it's&implementation.&&&&&*/&&&&struct&{&&&&&&&&struct&sk_buff&*&&&&&&&&struct&sk_buff&*&&&&}&sk_&&&&rwlock_t&&&&&&&&sk_callback_&&&&struct&sk_buff_head&&&&sk_error_&&&&&&&&struct&proto&&&&&&&&*sk_&&&&&&&&int&&&&&&&&&&&&sk_err,&&&&&&&&&&&&&&&&sk_err_&&&&unsigned&short&&&&&&&&sk_ack_&&&&unsigned&short&&&&&&&&sk_max_ack_&&&&__u32&&&&&&&&&&&&sk_&&&&unsigned&short&&&&&&&&sk_&&&&unsigned&char&&&&&&&&sk_&&&&unsigned&char&&&&&&&&sk_&&&&struct&ucred&&&&&&&&sk_&&&&int&&&&&&&&&&&&sk_&&&&long&&&&&&&&&&&&sk_&&&&long&&&&&&&&&&&&sk_&&&&struct&sk_filter&&&&&&&&&&*sk_&&&&void&&&&&&&&&&&&*sk_&&&&kmem_cache_t&&&&&&&&*sk_&&&&struct&timer_list&&&&sk_&&&&struct&timeval&&&&&&&&sk_&&&&struct&socket&&&&&&&&*sk_&&&&void&&&&&&&&&&&&*sk_user_&&&&struct&module&&&&&&&&*sk_&&&&struct&page&&&&&&&&*sk_sndmsg_&&&&__u32&&&&&&&&&&&&sk_sndmsg_&&&&struct&sk_buff&&&&&&&&*sk_send_&&&&int&&&&&&&&&&&&sk_write_&&&&void&&&&&&&&&&&&*sk_&&&&__u8&&&&&&&&&&&&sk_queue_&&&&/*&three&bytes&hole,&try&to&pack&*/&&&&void&&&&&&&&&&&&(*sk_state_change)(struct&sock&*sk);&&&&void&&&&&&&&&&&&(*sk_data_ready)(struct&sock&*sk,&int&bytes);&&&&void&&&&&&&&&&&&(*sk_write_space)(struct&sock&*sk);&&&&void&&&&&&&&&&&&(*sk_error_report)(struct&sock&*sk);&&&&&&int&&&&&&&&&&&&(*sk_backlog_rcv)(struct&sock&*sk,&&&&&&&&&&&&&&&&&&&&&&&&&&struct&sk_buff&*skb);&&&&&&void&&&&&&&&&&&&&&&&&&&&(*sk_destruct)(struct&sock&*sk);};//底层协议的操作函数struct&proto&{&&&&void&&&&&&&&&&&&(*close)(struct&sock&*sk,&&&&&&&&&&&&&&&&&&&&&long&timeout);&&&&int&&&&&&&&&&&&(*connect)(struct&sock&*sk,&&&&&&&&&&&&&&&&&&&&&&&&struct&sockaddr&*uaddr,&&&&&&&&&&&&&&&&&&&&&int&addr_len);&&&&int&&&&&&&&&&&&(*disconnect)(struct&sock&*sk,&int&flags);&&&&struct&sock&*&&&&&&&&(*accept)&(struct&sock&*sk,&int&flags,&int&*err);&&&&int&&&&&&&&&&&&(*ioctl)(struct&sock&*sk,&int&cmd,&&&&&&&&&&&&&&&&&&&&&unsigned&long&arg);&&&&int&&&&&&&&&&&&(*init)(struct&sock&*sk);&&&&int&&&&&&&&&&&&(*destroy)(struct&sock&*sk);&&&&void&&&&&&&&&&&&(*shutdown)(struct&sock&*sk,&int&how);&&&&int&&&&&&&&&&&&(*setsockopt)(struct&sock&*sk,&int&level,&&&&&&&&&&&&&&&&&&&&&int&optname,&char&__user&*optval,&&&&&&&&&&&&&&&&&&&&int&optlen);&&&&int&&&&&&&&&&&&(*getsockopt)(struct&sock&*sk,&int&level,&&&&&&&&&&&&&&&&&&&&&int&optname,&char&__user&*optval,&&&&&&&&&&&&&&&&&&&&&int&__user&*option);&&&&&&&&&&&int&&&&&&&&&&&&(*sendmsg)(struct&kiocb&*iocb,&struct&sock&*sk,&&&&&&&&&&&&&&&&&&&&&&&struct&msghdr&*msg,&size_t&len);&&&&int&&&&&&&&&&&&(*recvmsg)(struct&kiocb&*iocb,&struct&sock&*sk,&&&&&&&&&&&&&&&&&&&&&&&struct&msghdr&*msg,&&&&&&&&&&&&&&&&&&&&size_t&len,&int&noblock,&int&flags,&&&&&&&&&&&&&&&&&&&&&int&*addr_len);&&&&int&&&&&&&&&&&&(*sendpage)(struct&sock&*sk,&struct&page&*page,&&&&&&&&&&&&&&&&&&&&int&offset,&size_t&size,&int&flags);&&&&int&&&&&&&&&&&&(*bind)(struct&sock&*sk,&&&&&&&&&&&&&&&&&&&&&struct&sockaddr&*uaddr,&int&addr_len);&&&&int&&&&&&&&&&&&(*backlog_rcv)&(struct&sock&*sk,&&&&&&&&&&&&&&&&&&&&&&&&&struct&sk_buff&*skb);&&&&/*&Keeping&track&of&sk's,&looking&them&up,&and&port&selection&methods.&*/&&&&void&&&&&&&&&&&&(*hash)(struct&sock&*sk);&&&&void&&&&&&&&&&&&(*unhash)(struct&sock&*sk);&&&&int&&&&&&&&&&&&(*get_port)(struct&sock&*sk,&unsigned&short&snum);&&&&/*&Memory&pressure&*/&&&&void&&&&&&&&&&&&(*enter_memory_pressure)(void);&&&&atomic_t&&&&&&&&*memory_&&&&/*&Current&allocated&memory.&*/&&&&atomic_t&&&&&&&&*sockets_&&&&/*&Current&number&of&sockets.&*/&&&&/*&&&&&*&Pressure&flag:&try&to&collapse.&&&&&*&Technical&note:&it&is&used&by&multiple&contexts&non&atomically.&&&&&*&All&the&sk_stream_mem_schedule()&is&of&this&nature:&accounting&&&&&*&is&strict,&actions&are&advisory&and&have&some&latency.&&&&&*/&&&&int&&&&&&&&&&&&*memory_&&&&int&&&&&&&&&&&&*sysctl_&&&&int&&&&&&&&&&&&*sysctl_&&&&int&&&&&&&&&&&&*sysctl_&&&&int&&&&&&&&&&&&max_&&&&kmem_cache_t&&&&&&&&*&&&&int&&&&&&&&&&&&slab_obj_&&&&struct&module&&&&&&&&*&&&&char&&&&&&&&&&&&name[32];&&&&struct&{&&&&&&&&int&&&&&&&&&u8&&__pad[SMP_CACHE_BYTES&-&sizeof(int)];&&&&}&stats[NR_CPUS];};inet_init()函数:Code//net/ipv4/af_inet.c/*系统初始化时被调用**调用路径:start_kernel()&--&init()&--&do_basic_setup()&--&do_initcalls()--&inet_init()*/static&int&__init&inet_init(void){&&&&struct&sk_buff&*dummy_&&&&struct&inet_protosw&*q;&&&&struct&list_head&*r;&&&&int&rc&=&-EINVAL;&&&&if&(sizeof(struct&inet_skb_parm)&&&sizeof(dummy_skb-&cb))&{&&&&&&&&printk(KERN_CRIT&"%s:&panic\n",&__FUNCTION__);&&&&&&&&goto&out;&&&&}&&&&rc&=&sk_alloc_slab(&tcp_prot,&"tcp_sock");&&&&if&(rc)&{&&&&&&&&sk_alloc_slab_error(&tcp_prot);&&&&&&&&goto&out;&&&&}&&&&rc&=&sk_alloc_slab(&udp_prot,&"udp_sock");&&&&if&(rc)&{&&&&&&&&sk_alloc_slab_error(&udp_prot);&&&&&&&&goto&out_tcp_free_&&&&}&&&&rc&=&sk_alloc_slab(&raw_prot,&"raw_sock");&&&&if&(rc)&{&&&&&&&&sk_alloc_slab_error(&raw_prot);&&&&&&&&goto&out_udp_free_&&&&}&&&&/*&&&&&*&&&&Tell&SOCKET&that&we&are&alive&&&&&&*/&&&&//注册Internet协议簇的相关信息&&&&&&(void)sock_register(&inet_family_ops);&&&&/*&&&&&*&&&&Add&all&the&base&protocols.&&&&&*/&&&&//添加基本的协议&&&&if&(inet_add_protocol(&icmp_protocol,&IPPROTO_ICMP)&&&0)&&&&&&&&printk(KERN_CRIT&"inet_init:&Cannot&add&ICMP&protocol\n");&&&&if&(inet_add_protocol(&udp_protocol,&IPPROTO_UDP)&&&0)&&&&&&&&printk(KERN_CRIT&"inet_init:&Cannot&add&UDP&protocol\n");&&&&if&(inet_add_protocol(&tcp_protocol,&IPPROTO_TCP)&&&0)&&&&&&&&printk(KERN_CRIT&"inet_init:&Cannot&add&TCP&protocol\n");#ifdef&CONFIG_IP_MULTICAST&&&&if&(inet_add_protocol(&igmp_protocol,&IPPROTO_IGMP)&&&0)&&&&&&&&printk(KERN_CRIT&"inet_init:&Cannot&add&IGMP&protocol\n");#endif&&&&/*&Register&the&socket-side&information&for&inet_create.&*/&&&&for&(r&=&&inetsw[0];&r&&&&inetsw[SOCK_MAX];&++r)&&&&&&&&INIT_LIST_HEAD(r);&&&&&&&&&&//将inetsw_array中元素加入到inetsw链表中&&&&for&(q&=&inetsw_&q&&&&inetsw_array[INETSW_ARRAY_LEN];&++q)&&&&&&&&inet_register_protosw(q);&&&&/*&&&&&*&&&&Set&the&ARP&module&up&&&&&*/&&&&arp_init();&//ARP协议初始化&&&&&&/*&&&&&&&*&&&&Set&the&IP&module&up&&&&&&&*/&&&&ip_init();&//IP协议初始化&&&&tcp_v4_init(&inet_family_ops);&&&&/*&Setup&TCP&slab&cache&for&open&requests.&*/&&&&tcp_init();&&&&/*&&&&&*&&&&Set&the&ICMP&layer&up&&&&&*/&&&&icmp_init(&inet_family_ops);&&&&/*&&&&&*&&&&Initialise&the&multicast&router&&&&&*/#if&defined(CONFIG_IP_MROUTE)&&&&ip_mr_init();#endif&&&&/*&&&&&*&&&&Initialise&per-cpu&ipv4&mibs&&&&&*/&&&&&if(init_ipv4_mibs())&&&&&&&&printk(KERN_CRIT&"inet_init:&Cannot&init&ipv4&mibs\n");&;&&&&&&&&ipv4_proc_init();&&&&ipfrag_init();&&&&rc&=&0;out:&&&&return&out_tcp_free_slab:&&&&sk_free_slab(&tcp_prot);out_udp_free_slab:&&&&sk_free_slab(&udp_prot);&&&&goto&out;}//net/ipv4/af_inet.c//INET协议簇信息static&struct&net_proto_family&inet_family_ops&=&{&&&&.family&=&PF_INET,&&&&.create&=&inet_create,&&&&.owner&&&&=&THIS_MODULE,};static&struct&list_head&inetsw[SOCK_MAX];//该数组中的所有元素都会插入到inetsw的链表中static&struct&inet_protosw&inetsw_array[]&={&&&&&&&&{&&&&&&&&&&&&&&&&.type&=&&&&&&&SOCK_STREAM,&&&&&&&&&&&&&&&&.protocol&=&&&IPPROTO_TCP,&&&&&&&&&&&&&&&&.prot&=&&&&&&&&tcp_prot,&&&&&&&&&&&&&&&&.ops&=&&&&&&&&&inet_stream_ops,&&&&&&&&&&&&&&&&.capability&=&-1,&&&&&&&&&&&&&&&&.no_check&=&&&0,&&&&&&&&&&&&&&&&.flags&=&&&&&&INET_PROTOSW_PERMANENT,&&&&&&&&},&&&&&&&&{&&&&&&&&&&&&&&&&.type&=&&&&&&&SOCK_DGRAM,&&&&&&&&&&&&&&&&.protocol&=&&&IPPROTO_UDP,&&&&&&&&&&&&&&&&.prot&=&&&&&&&&udp_prot,&&&&&&&&&&&&&&&&.ops&=&&&&&&&&&inet_dgram_ops,&&&&&&&&&&&&&&&&.capability&=&-1,&&&&&&&&&&&&&&&&.no_check&=&&&UDP_CSUM_DEFAULT,&&&&&&&&&&&&&&&&.flags&=&&&&&&INET_PROTOSW_PERMANENT,&&&&&&&},&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&.type&=&&&&&&&SOCK_RAW,&&&&&&&&&&&&&&&.protocol&=&&&IPPROTO_IP,&&&&/*&wild&card&*/&&&&&&&&&&&&&&&.prot&=&&&&&&&&raw_prot,&&&&&&&&&&&&&&&.ops&=&&&&&&&&&inet_sockraw_ops,&&&&&&&&&&&&&&&.capability&=&CAP_NET_RAW,&&&&&&&&&&&&&&&.no_check&=&&&UDP_CSUM_DEFAULT,&&&&&&&&&&&&&&&.flags&=&&&&&&INET_PROTOSW_REUSE,&&&&&&&}};//流套接字操作函数struct&proto_ops&inet_stream_ops&=&{&&&&.family&=&&&&PF_INET,&&&&.owner&=&&&&THIS_MODULE,&&&&.release&=&&&&inet_release,&&&&.bind&=&&&&&&&&inet_bind,&&&&.connect&=&&&&inet_stream_connect,&&&&.socketpair&=&&&&sock_no_socketpair,&&&&.accept&=&&&&inet_accept,&&&&.getname&=&&&&inet_getname,&&&&.poll&=&&&&&&&&tcp_poll,&&&&.ioctl&=&&&&inet_ioctl,&&&&.listen&=&&&&inet_listen,&&&&.shutdown&=&&&&inet_shutdown,&&&&.setsockopt&=&&&&sock_common_setsockopt,&&&&.getsockopt&=&&&&sock_common_getsockopt,&&&&.sendmsg&=&&&&inet_sendmsg,&&&&.recvmsg&=&&&&sock_common_recvmsg,&&&&.mmap&=&&&&&&&&sock_no_mmap,&&&&.sendpage&=&&&&tcp_sendpage};//tcp协议static&struct&net_protocol&tcp_protocol&=&{&&&&.handler&=&&&&tcp_v4_rcv,&&&&.err_handler&=&&&&tcp_v4_err,&&&&.no_policy&=&&&&1,};static&struct&net_protocol&udp_protocol&=&{&&&&.handler&=&&&&udp_rcv,&&&&.err_handler&=&&&&udp_err,&&&&.no_policy&=&&&&1,};static&struct&net_protocol&icmp_protocol&=&{&&&&.handler&=&&&&icmp_rcv,};//net/ipv4/tcp_ipv4.c//tcp协议的操作函数struct&proto&tcp_prot&=&{&&&&.name&&&&&&&&&&&&=&"TCP",&&&&.owner&&&&&&&&&&&&=&THIS_MODULE,&&&&.close&&&&&&&&&&&&=&tcp_close,&&&&.connect&&&&&&&&=&tcp_v4_connect,&&&&.disconnect&&&&&&&&=&tcp_disconnect,&&&&.accept&&&&&&&&&&&&=&tcp_accept,&&&&.ioctl&&&&&&&&&&&&=&tcp_ioctl,&&&&.init&&&&&&&&&&&&=&tcp_v4_init_sock,&&&&.destroy&&&&&&&&=&tcp_v4_destroy_sock,&&&&.shutdown&&&&&&&&=&tcp_shutdown,&&&&.setsockopt&&&&&&&&=&tcp_setsockopt,&&&&.getsockopt&&&&&&&&=&tcp_getsockopt,&&&&.sendmsg&&&&&&&&=&tcp_sendmsg,&&&&.recvmsg&&&&&&&&=&tcp_recvmsg,&&&&.backlog_rcv&&&&&&&&=&tcp_v4_do_rcv,&&&&.hash&&&&&&&&&&&&=&tcp_v4_hash,&&&&.unhash&&&&&&&&&&&&=&tcp_unhash,&&&&.get_port&&&&&&&&=&tcp_v4_get_port,&&&&.enter_memory_pressure&&&&=&tcp_enter_memory_pressure,&&&&.sockets_allocated&&&&=&&tcp_sockets_allocated,&&&&.memory_allocated&&&&=&&tcp_memory_allocated,&&&&.memory_pressure&&&&=&&tcp_memory_pressure,&&&&.sysctl_mem&&&&&&&&=&sysctl_tcp_mem,&&&&.sysctl_wmem&&&&&&&&=&sysctl_tcp_wmem,&&&&.sysctl_rmem&&&&&&&&=&sysctl_tcp_rmem,&&&&.max_header&&&&&&&&=&MAX_TCP_HEADER,&&&&.slab_obj_size&&&&&&&&=&sizeof(struct&tcp_sock),};sock_register()函数:Code//注册协议簇int&sock_register(struct&net_proto_family&*ops){&&&&int&&&&&if&(ops-&family&&=&NPROTO)&{&&&&&&&&printk(KERN_CRIT&"protocol&%d&&=&NPROTO(%d)\n",&ops-&family,&NPROTO);&&&&&&&&return&-ENOBUFS;&&&&}&&&&net_family_write_lock();&&&&err&=&-EEXIST;&&&&if&(net_families[ops-&family]&==&NULL)&{&&&&&&&&net_families[ops-&family]=&&&&&&&&err&=&0;&&&&}&&&&net_family_write_unlock();&&&&printk(KERN_INFO&"NET:&Registered&protocol&family&%d\n",&&&&&&&&&&&ops-&family);&&&&return&}inet_create()函数Code//创建一个INET套接字static&int&inet_create(struct&socket&*sock,&int&protocol){&&&&struct&sock&*&&&&struct&list_head&*p;&&&&struct&inet_protosw&*&&&&struct&inet_opt&*&&&&struct&proto&*answer_&&&&unsigned&char&answer_&&&&char&answer_no_&&&&int&&&&&sock-&state&=&SS_UNCONNECTED;&&&&/*&Look&for&the&requested&type/protocol&pair.&*/&&&&answer&=&NULL;&&&&rcu_read_lock();&&&&list_for_each_rcu(p,&&inetsw[sock-&type])&{&&&&&&&&answer&=&list_entry(p,&struct&inet_protosw,&list);&&&&&&&&/*&Check&the&non-wild&match.&*/&&&&&&&&if&(protocol&==&answer-&protocol)&{&&&&&&&&&&&&if&(protocol&!=&IPPROTO_IP)&&&&&&&&&&&&&&&&break;&&&&&&&&}&else&{&&&&&&&&&&&&/*&Check&for&the&two&wild&cases.&*/&&&&&&&&&&&&if&(IPPROTO_IP&==&protocol)&{&&&&&&&&&&&&&&&&protocol&=&answer-&&&&&&&&&&&&&&&&&break;&&&&&&&&&&&&}&&&&&&&&&&&&if&(IPPROTO_IP&==&answer-&protocol)&&&&&&&&&&&&&&&&break;&&&&&&&&}&&&&&&&&answer&=&NULL;&&&&}&&&&err&=&-ESOCKTNOSUPPORT;&&&&if&(!answer)&&&&&&&&goto&out_rcu_&&&&err&=&-EPERM;&&&&if&(answer-&capability&&&0&&&&!capable(answer-&capability))&&&&&&&&goto&out_rcu_&&&&err&=&-EPROTONOSUPPORT;&&&&if&(!protocol)&&&&&&&&goto&out_rcu_&&&&&&&&//BSD&socket的操作函数&&&&sock-&ops&=&answer-&&&&&answer_prot&=&answer-&&&&&&&&&answer_no_check&=&answer-&no_&&&&answer_flags&=&answer-&&&&&rcu_read_unlock();&&&&BUG_TRAP(answer_prot-&slab&!=&NULL);&&&&err&=&-ENOBUFS;&&&&sk&=&sk_alloc(PF_INET,&GFP_KERNEL,&&&&&&&&&&&&&&answer_prot-&slab_obj_size,&&&&&&&&&&&&&&answer_prot-&slab);&&&&if&(sk&==&NULL)&&&&&&&&goto&out;&&&&err&=&0;&&&&//特定协议套接字的操作函数&&&&sk-&sk_prot&=&answer_&&&&sk-&sk_no_check&=&answer_no_&&&&if&(INET_PROTOSW_REUSE&&&answer_flags)&&&&&&&&sk-&sk_reuse&=&1;&&&&inet&=&inet_sk(sk);&&&&if&(SOCK_RAW&==&sock-&type)&{&&&&&&&&inet-&num&=&&&&&&&&&if&(IPPROTO_RAW&==&protocol)&&&&&&&&&&&&inet-&hdrincl&=&1;&&&&}&&&&if&(ipv4_config.no_pmtu_disc)&&&&&&&&inet-&pmtudisc&=&IP_PMTUDISC_DONT;&&&&else&&&&&&&&inet-&pmtudisc&=&IP_PMTUDISC_WANT;&&&&inet-&id&=&0;&&&&//将sock与sk关联起来&&&&sock_init_data(sock,&sk);&&&&sk_set_owner(sk,&sk-&sk_prot-&owner);&&&&sk-&sk_destruct&&&&&&&=&inet_sock_&&&&sk-&sk_family&&&&&&&=&PF_INET;&&&&sk-&sk_protocol&&&&&&&=&&&&&sk-&sk_backlog_rcv&=&sk-&sk_prot-&backlog_&&&&inet-&uc_ttl&&&&=&-1;&&&&inet-&mc_loop&&&&=&1;&&&&inet-&mc_ttl&&&&=&1;&&&&inet-&mc_index&&&&=&0;&&&&inet-&mc_list&&&&=&NULL;#ifdef&INET_REFCNT_DEBUG&&&&atomic_inc(&inet_sock_nr);#endif&&&&if&(inet-&num)&{&&&&&&&&/*&It&assumes&that&any&protocol&which&allows&&&&&&&&&*&the&user&to&assign&a&number&at&socket&&&&&&&&&*&creation&time&automatically&&&&&&&&&*&shares.&&&&&&&&&*/&&&&&&&&inet-&sport&=&htons(inet-&num);&&&&&&&&/*&Add&to&protocol&hash&chains.&*/&&&&&&&&sk-&sk_prot-&hash(sk);&&&&}&&&&//调用init函数&&&&if&(sk-&sk_prot-&init)&{&&&&&&&&err&=&sk-&sk_prot-&init(sk);&&&&&&&&if&(err)&&&&&&&&&&&&sk_common_release(sk);&&&&}out:&&&&return&out_rcu_unlock:&&&&rcu_read_unlock();&&&&goto&out;}
阅读(...) 评论()

我要回帖

更多关于 sockscap 的文章

 

随机推荐