Linux内核网络协议栈5-socket地址绑定
?
一、socket绑定入口
1、示例代码struct sockaddr_in server_address;server_address.sin_family = AF_INET;server_address.sin_addr.s_addr = inet_addr("0.0.0.0");server_address.sin_port = htons(9734);server_len = sizeof(server_address);bind(server_sockfd, (struct sockaddr *)&server_address, server_len);?
asmlinkage long sys_socketcall(int call, unsigned long __user *args){ unsigned long a[6]; unsigned long a0, a1; int err; if (copy_from_user(a, args, nargs[call])) return -EFAULT; a0 = a[0]; a1 = a[1]; switch (call) { …... case SYS_BIND: err = sys_bind(a0, (struct sockaddr __user *)a1, a[2]); …...}?
asmlinkage long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen){ struct socket *sock; char address[MAX_SOCK_ADDR]; int err, fput_needed; // 1, 根据fd查找相应的socket结构 sock = sockfd_lookup_light(fd, &err, &fput_needed); if (sock) { // 2, 将用户空间的地址结构拷贝到内核空间 err = move_addr_to_kernel(umyaddr, addrlen, address); if (err >= 0) { err = security_socket_bind(sock, (struct sockaddr *)address, addrlen); if (!err) // 3, 根据协议域及socket类型,调用相应的bind函数 err = sock->ops->bind(sock, (struct sockaddr *) address, addrlen); } fput_light(sock->file, fput_needed); } return err;}
static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed){ struct file *file; struct socket *sock; *err = -EBADF; file = fget_light(fd, fput_needed); if (file) { sock = sock_from_file(file, err); if (sock) return sock; fput_light(file, *fput_needed); } return NULL;}
struct file *fget_light(unsigned int fd, int *fput_needed){ struct file *file; struct files_struct *files = current->files; …... file = fcheck_files(files, fd); …... return file;}
a)这两个结构体到底是什么关系?
b)为什么要强制转化为struct sockaddr结构?
c)bind()库函数最后一个参数,为什么要把结构体长度传进去呢?
struct sockaddr_in { sa_family_t sin_family;/* Address family */ __be16 sin_port; /* Port number */ struct in_addr sin_addr; /* Internet address */ /* Pad to size of `struct sockaddr'. */ unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) - sizeof(unsigned short int) - sizeof(struct in_addr)];}; struct sockaddr { sa_family_t sa_family;/* address family, AF_xxx */ char sa_data[14]; /* 14 bytes of protocol address */};