/* 这个和pipe功能有相似之处,pipe是单工的,socketpair是双工的 * family只能是UNIX域的。 */ static int sock_socketpair(int family, int type, int protocol, unsigned long usockvec[2]) { int fd1, fd2, i; struct socket *sock1, *sock2; int er; DPRINTF((net_debug, "NET: sock_socketpair: family = %d, type = %d, protocol = %d\n", family, type, protocol)); /* * Obtain the first socket and check if the underlying protocol * supports the socketpair call. */ /* 如果创建失败,则直接返回 */ if ((fd1 = sock_socket(family, type, protocol)) < 0) return(fd1); sock1 = sockfd_lookup(fd1, NULL); if (!sock1->ops->socketpair) { sys_close(fd1); return(-EINVAL); } /* Now grab another socket and try to connect the two together. */ if ((fd2 = sock_socket(family, type, protocol)) < 0) { sys_close(fd1); return(-EINVAL); } sock2 = sockfd_lookup(fd2, NULL); if ((i = sock1->ops->socketpair(sock1, sock2)) < 0) { sys_close(fd1); sys_close(fd2); return(i); } sock1->conn = sock2; sock2->conn = sock1; /* 完成socketpair操作后,则这只套接字的状态为连接状态 */ sock1->state = SS_CONNECTED; sock2->state = SS_CONNECTED; er=verify_area(VERIFY_WRITE, usockvec, 2 * sizeof(int)); if(er) return er; put_fs_long(fd1, &usockvec[0]); put_fs_long(fd2, &usockvec[1]); return(0); }
static struct socket *get_raw_socket(int fd) { struct { struct sockaddr_ll sa; char buf[MAX_ADDR_LEN]; } uaddr; int uaddr_len = sizeof uaddr, r; struct socket *sock = sockfd_lookup(fd, &r); if (!sock) return ERR_PTR(-ENOTSOCK); /* Parameter checking */ if (sock->sk->sk_type != SOCK_RAW) { r = -ESOCKTNOSUPPORT; goto err; } r = sock->ops->getname(sock, (struct sockaddr *)&uaddr.sa, &uaddr_len, 0); if (r) goto err; if (uaddr.sa.sll_family != AF_PACKET) { r = -EPFNOSUPPORT; goto err; } return sock; err: sockfd_put(sock); return ERR_PTR(r); }
COMPAT_SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname, char __user *, optval, int __user *, optlen) { int err; struct socket *sock = sockfd_lookup(fd, &err); if (sock) { err = security_socket_getsockopt(sock, level, optname); if (err) { sockfd_put(sock); return err; } if (level == SOL_SOCKET) err = compat_sock_getsockopt(sock, level, optname, optval, optlen); else if (sock->ops->compat_getsockopt) err = sock->ops->compat_getsockopt(sock, level, optname, optval, optlen); else err = sock->ops->getsockopt(sock, level, optname, optval, optlen); sockfd_put(sock); } return err; }
/* 去连接服务器 * fd是连接套接字的文件描述符 * uservaddr是服务器地址 * addrlen地址长度 */ static int sock_connect(int fd, struct sockaddr *uservaddr, int addrlen) { struct socket *sock; struct file *file; int i; DPRINTF((net_debug, "NET: sock_connect: fd = %d\n", fd)); if (fd < 0 || fd >= NR_OPEN || (file=current->filp[fd]) == NULL) return(-EBADF); if (!(sock = sockfd_lookup(fd, &file))) return(-ENOTSOCK); switch(sock->state) { case SS_UNCONNECTED: /* This is ok... continue with connect */ break; case SS_CONNECTED: /* Socket is already connected */ return -EISCONN; case SS_CONNECTING: /* Not yet connected... we will check this. */ return(sock->ops->connect(sock, uservaddr, addrlen, file->f_flags)); default: DPRINTF((net_debug, "NET: sock_connect: socket not unconnected\n")); return(-EINVAL); } /* 开始真正的连接服务器 */ i = sock->ops->connect(sock, uservaddr, addrlen, file->f_flags); if (i < 0) { DPRINTF((net_debug, "NET: sock_connect: connect failed\n")); return(i); } return(0); }
asmlinkage long compat_sys_setsockopt(int fd, int level, int optname, char __user *optval, int optlen) { int err; struct socket *sock; if (level == SOL_IPV6 && optname == IPT_SO_SET_REPLACE) return do_netfilter_replace(fd, level, optname, optval, optlen); if (optlen < 0) return -EINVAL; if ((sock = sockfd_lookup(fd, &err))!=NULL) { err = security_socket_setsockopt(sock,level,optname); if (err) { sockfd_put(sock); return err; } if (level == SOL_SOCKET) err = compat_sock_setsockopt(sock, level, optname, optval, optlen); else if (sock->ops->compat_setsockopt) err = sock->ops->compat_setsockopt(sock, level, optname, optval, optlen); else err = sock->ops->setsockopt(sock, level, optname, optval, optlen); sockfd_put(sock); } return err; }
/** Handle some skbs on a varp socket (if any). * * @param fd socket file descriptor * @param n maximum number of skbs to handle * @return number of skbs handled */ static int handle_varp_sock(int fd, int n){ int ret = 0; int err = 0; struct sk_buff *skb; struct socket *sock = NULL; sock = sockfd_lookup(fd, &err); if (!sock){ wprintf("> no sock for fd=%d\n", fd); goto exit; } for( ; ret < n; ret++){ if(!sock->sk) break; skb = skb_dequeue(&sock->sk->sk_receive_queue); if(!skb) break; // Call the skb destructor so it isn't charged to the socket anymore. // An skb from a socket receive queue is charged to the socket // by skb_set_owner_r() until its destructor is called. // If the destructor is not called the socket will run out of // receive queue space and be unable to accept incoming skbs. // The destructor used is sock_rfree(), see 'include/net/sock.h'. // Other destructors: sock_wfree, sk_stream_rfree. skb_orphan(skb); handle_varp_skb(skb); } sockfd_put(sock); exit: dprintf("< ret=%d\n", ret); return ret; }
asmlinkage long compat_sys_getsockopt(int fd, int level, int optname, char __user *optval, int __user *optlen) { int err; struct socket *sock = sockfd_lookup(fd, &err); if (sock) { err = security_socket_getsockopt(sock, level, optname); if (err) { sockfd_put(sock); return err; } if (level == SOL_SOCKET) err = compat_sock_getsockopt(sock, level, optname, optval, optlen); else if (sock->ops->compat_getsockopt) err = sock->ops->compat_getsockopt(sock, level, optname, optval, optlen); else err = sock->ops->getsockopt(sock, level, optname, optval, optlen); sockfd_put(sock); } return err; }
asmlinkage long compat_sys_setsockopt(int fd, int level, int optname, char __user *optval, unsigned int optlen) { int err; struct socket *sock; if (optlen < 0) return -EINVAL; if ((sock = sockfd_lookup(fd, &err))!=NULL) { err = security_socket_setsockopt(sock,level,optname); if (err) { sockfd_put(sock); return err; } if (level == SOL_SOCKET) err = compat_sock_setsockopt(sock, level, optname, optval, optlen); else if (sock->ops->compat_setsockopt) err = sock->ops->compat_setsockopt(sock, level, optname, optval, optlen); else err = sock->ops->setsockopt(sock, level, optname, optval, optlen); sockfd_put(sock); } return err; }
static int sock_socketpair(int family, int type, int protocol, int usockvec[2]) { int fd1, fd2, i; struct socket *sock1, *sock2; PRINTK("sys_socketpair: family = %d, type = %d, protocol = %d\n", family, type, protocol); /* * obtain the first socket and check if the underlying protocol * supports the socketpair call */ if ((fd1 = sock_socket(family, type, protocol)) < 0) return fd1; sock1 = sockfd_lookup(fd1, NULL); if (!sock1->ops->socketpair) { sys_close(fd1); return -EINVAL; } /* * now grab another socket and try to connect the two together */ if ((fd2 = sock_socket(family, type, protocol)) < 0) { sys_close(fd1); return -EINVAL; } sock2 = sockfd_lookup(fd2, NULL); if ((i = sock1->ops->socketpair(sock1, sock2)) < 0) { sys_close(fd1); sys_close(fd2); return i; } sock1->conn = sock2; sock2->conn = sock1; sock1->state = SS_CONNECTED; sock2->state = SS_CONNECTED; verify_area(usockvec, 2 * sizeof(int)); put_fs_long(fd1, &usockvec[0]); put_fs_long(fd2, &usockvec[1]); return 0; }
/* fd是监听的套接字,该函数的执行过程为,首先在sockets数组当中申请一个 * struct socket,在申请struct socket的过程中就给socket分配了inode节点, * 然后在分配一个struct file结构,最后就返回一个新的文件描述符,该过程是一个 * 反向的过程 */ static int sock_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_addrlen) { struct file *file; struct socket *sock, *newsock; int i; DPRINTF((net_debug, "NET: sock_accept: fd = %d\n", fd)); if (fd < 0 || fd >= NR_OPEN || ((file = current->filp[fd]) == NULL)) return(-EBADF); /* 找到监听fd的socket结构 */ if (!(sock = sockfd_lookup(fd, &file))) return(-ENOTSOCK); if (sock->state != SS_UNCONNECTED) { DPRINTF((net_debug, "NET: sock_accept: socket isn't unconnected\n")); return(-EINVAL); } if (!(sock->flags & SO_ACCEPTCON)) { DPRINTF((net_debug, "NET: sock_accept: socket not accepting connections!\n")); return(-EINVAL); } /* 非阻塞的获取一个socket结构 */ if (!(newsock = sock_alloc(0))) { printk("NET: sock_accept: no more sockets\n"); return(-EAGAIN); } /* 两个socket的类型,协议族操作函数相同 */ newsock->type = sock->type; newsock->ops = sock->ops; if ((i = sock->ops->dup(newsock, sock)) < 0) { sock_release(newsock); return(i); } i = newsock->ops->accept(sock, newsock, file->f_flags); if ( i < 0) { sock_release(newsock); return(i); } /* 给新的socket分配一个文件描述符 */ if ((fd = get_fd(SOCK_INODE(newsock))) < 0) { sock_release(newsock); return(-EINVAL); } DPRINTF((net_debug, "NET: sock_accept: connected socket 0x%x via 0x%x\n", sock, newsock)); if (upeer_sockaddr) newsock->ops->getname(newsock, upeer_sockaddr, upeer_addrlen, 1); /* 返回新的socket文件描述符 */ return(fd); }
static int sock_getpeername(int fd, struct sockaddr *usockaddr, int *usockaddr_len) { struct socket *sock; PRINTK("sys_getpeername: fd = %d\n", fd); if (!(sock = sockfd_lookup(fd, NULL))) return -EBADF; return sock->ops->getname(sock, usockaddr, usockaddr_len, 1); }
static int sock_getpeername(int fd, struct sockaddr *usockaddr, int *usockaddr_len) { struct socket *sock; DPRINTF((net_debug, "NET: sock_getpeername: fd = %d\n", fd)); if (fd < 0 || fd >= NR_OPEN || current->filp[fd] == NULL) return(-EBADF); if (!(sock = sockfd_lookup(fd, NULL))) return(-ENOTSOCK); return(sock->ops->getname(sock, usockaddr, usockaddr_len, 1)); }
static int hidp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *) arg; struct hidp_connadd_req ca; struct hidp_conndel_req cd; struct hidp_connlist_req cl; struct hidp_conninfo ci; struct socket *csock; struct socket *isock; int err; BT_DBG("cmd %x arg %lx", cmd, arg); switch (cmd) { case HIDPCONNADD: if (!capable(CAP_NET_ADMIN)) return -EACCES; if (copy_from_user(&ca, argp, sizeof(ca))) return -EFAULT; csock = sockfd_lookup(ca.ctrl_sock, &err); if (!csock) return err; isock = sockfd_lookup(ca.intr_sock, &err); if (!isock) { sockfd_put(csock); return err; } <<<<<<< HEAD if (csock->sk->sk_state != BT_CONNECTED || isock->sk->sk_state != BT_CONNECTED) { ======= if (csock->sk->sk_state != BT_CONNECTED || isock->sk->sk_state != BT_CONNECTED) { >>>>>>> 296c66da8a02d52243f45b80521febece5ed498a sockfd_put(csock); sockfd_put(isock); return -EBADFD; }
/** Remove a wait queue from a socket. * * @param fd socket file descriptor * @param waitq queue * @return 0 on success, error code otherwise */ int sock_remove_wait_queue(int fd, wait_queue_t *waitq){ int err = -EINVAL; struct socket *sock = NULL; if(fd < 0) goto exit; sock = sockfd_lookup(fd, &err); if (!sock) goto exit; remove_wait_queue(sock->sk->sk_sleep, waitq); sockfd_put(sock); err = 0; exit: return err; }
/** Set the data ready callback on a socket. */ int sock_set_callback(int fd){ int err = -EINVAL; struct socket *sock = NULL; if(fd < 0) goto exit; sock = sockfd_lookup(fd, &err); if (!sock) goto exit; sock->sk->sk_data_ready = sock_data_ready; sockfd_put(sock); err = 0; exit: return err; }
static int hone_ioctl(struct inode *inode, struct file *file, unsigned int num, unsigned long param) #endif { struct hone_reader *reader = file->private_data; int err; if (_IOC_TYPE(num) != 0xE0) return -EINVAL; switch (num) { case HEIO_RESTART: atomic_set_mask(READER_RESTART, &reader->flags); wake_up_interruptible_all(&reader->event_wait_queue); return 0; case HEIO_GET_AT_HEAD: return atomic_read(&reader->flags) & READER_HEAD ? 1 : 0; case HEIO_GET_SNAPLEN: return put_user(reader->info.snaplen, (unsigned int __user *) param); case HEIO_SET_SNAPLEN: reader->info.snaplen = (unsigned int) param; atomic_set_mask(READER_HEAD, &reader->flags); return 0; case HEIO_SET_FILTER_SOCK: { int fd = (int) param; struct sock *sk; if (fd != -1) { struct socket *sock; if (!(sock = sockfd_lookup(fd, &err))) return err; sk = sock->sk; sock_hold(sk); fput(sock->file); } else { sk = NULL; } for (;;) { struct sock *old_sk = reader->filter_sk; if (cmpxchg(&reader->filter_sk, old_sk, sk) == old_sk) { if (old_sk) sock_put(old_sk); break; } } return 0; } } return -EINVAL; }
/* * for accept, we attempt to create a new socket, set up the link with the * client, wake up the client, then return the new connected fd. */ static int sock_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_addrlen) { struct file *file; struct socket *sock, *newsock; int i; PRINTK("sys_accept: fd = %d\n", fd); if (!(sock = sockfd_lookup(fd, &file))) return -EBADF; if (sock->state != SS_UNCONNECTED) { PRINTK("sys_accept: socket isn't unconnected\n"); return -EINVAL; } if (!(sock->flags & SO_ACCEPTCON)) { PRINTK("sys_accept: socket not accepting connections!\n"); return -EINVAL; } if (!(newsock = sock_alloc(0))) { printk("sys_accept: no more sockets\n"); return -EAGAIN; } newsock->type = sock->type; newsock->ops = sock->ops; if ((i = sock->ops->dup(newsock, sock)) < 0) { sock_release(newsock); return i; } if ((fd = get_fd(SOCK_INODE(newsock))) < 0) { sock_release(newsock); return -EINVAL; } i = newsock->ops->accept(sock, newsock, file->f_flags); if ( i < 0) { sys_close (fd); return (i); } PRINTK("sys_accept: connected socket 0x%x via 0x%x\n", sock, newsock); if (upeer_sockaddr) newsock->ops->getname(newsock, upeer_sockaddr, upeer_addrlen, 1); return fd; }
/* * binds a name to a socket. nothing much to do here since its the * protocol's responsibility to handle the local address */ static int sock_bind(int fd, struct sockaddr *umyaddr, int addrlen) { struct socket *sock; int i; PRINTK("sys_bind: fd = %d\n", fd); if (!(sock = sockfd_lookup(fd, NULL))) return -EBADF; if ((i = sock->ops->bind(sock, umyaddr, addrlen)) < 0) { PRINTK("sys_bind: bind failed\n"); return i; } return 0; }
/* 关闭套接字 */ static int sock_shutdown(int fd, int how) { struct socket *sock; struct file *file; DPRINTF((net_debug, "NET: sock_shutdown(fd = %d, how = %d)\n", fd, how)); if (fd < 0 || fd >= NR_OPEN || ((file = current->filp[fd]) == NULL)) return(-EBADF); if (!(sock = sockfd_lookup(fd, NULL))) return(-ENOTSOCK); return(sock->ops->shutdown(sock, how)); }
static int sock_send(int fd, void * buff, int len, unsigned flags) { struct socket *sock; struct file *file; DPRINTF((net_debug, "NET: sock_send(fd = %d, buff = %X, len = %d, flags = %X)\n", fd, buff, len, flags)); if (fd < 0 || fd >= NR_OPEN || ((file = current->filp[fd]) == NULL)) return(-EBADF); if (!(sock = sockfd_lookup(fd, NULL))) return(-ENOTSOCK); return(sock->ops->send(sock, buff, len, (file->f_flags & O_NONBLOCK), flags)); }
/* * Bind a name to a socket. Nothing much to do here since its * the protocol's responsibility to handle the local address. */ static int sock_bind(int fd, struct sockaddr *umyaddr, int addrlen) { struct socket *sock; int i; DPRINTF((net_debug, "NET: sock_bind: fd = %d\n", fd)); if (fd < 0 || fd >= NR_OPEN || current->filp[fd] == NULL) return(-EBADF); if (!(sock = sockfd_lookup(fd, NULL))) return(-ENOTSOCK); if ((i = sock->ops->bind(sock, umyaddr, addrlen)) < 0) { DPRINTF((net_debug, "NET: sock_bind: bind failed\n")); return(i); } return(0); }
static int sock_setsockopt(int fd, int level, int optname, char *optval, int optlen) { struct socket *sock; struct file *file; DPRINTF((net_debug, "NET: sock_setsockopt(fd=%d, level=%d, optname=%d,\n", fd, level, optname)); DPRINTF((net_debug, " optval = %X, optlen = %d)\n", optval, optlen)); if (fd < 0 || fd >= NR_OPEN || ((file = current->filp[fd]) == NULL)) return(-EBADF); if (!(sock = sockfd_lookup(fd, NULL))) return(-ENOTSOCK); return(sock->ops->setsockopt(sock, level, optname, optval, optlen)); }
/* * Perform a listen. Basically, we allow the protocol to do anything * necessary for a listen, and if that works, we mark the socket as * ready for listening. */ static int sock_listen(int fd, int backlog) { struct socket *sock; DPRINTF((net_debug, "NET: sock_listen: fd = %d\n", fd)); if (fd < 0 || fd >= NR_OPEN || current->filp[fd] == NULL) return(-EBADF); if (!(sock = sockfd_lookup(fd, NULL))) return(-ENOTSOCK); if (sock->state != SS_UNCONNECTED) { DPRINTF((net_debug, "NET: sock_listen: socket isn't unconnected\n")); return(-EINVAL); } if (sock->ops && sock->ops->listen) sock->ops->listen(sock, backlog); sock->flags |= SO_ACCEPTCON; return(0); }
static int sys_shutdown( int fd, int how) { struct socket *sock; struct file *file; PRINTK("sys_shutdown (fd = %d, how = %d)\n",fd, how); file = current->filp[fd]; if (fd < 0 || fd >= NR_OPEN || file == NULL) return (-EBADF); if (!(sock = sockfd_lookup(fd, NULL))) return (-ENOTSOCK); return (sock->ops->shutdown (sock, how)); }
static int sock_recvfrom(int fd, void * buff, int len, unsigned flags, struct sockaddr *addr, int *addr_len) { struct socket *sock; struct file *file; DPRINTF((net_debug, "NET: sock_recvfrom(fd = %d, buff = %X, len = %d, flags = %X," " addr=%X, alen=%X\n", fd, buff, len, flags, addr, addr_len)); if (fd < 0 || fd >= NR_OPEN || ((file = current->filp[fd]) == NULL)) return(-EBADF); if (!(sock = sockfd_lookup(fd, NULL))) return(-ENOTSOCK); return(sock->ops->recvfrom(sock, buff, len, (file->f_flags & O_NONBLOCK), flags, addr, addr_len)); }
static int sys_getsockopt (int fd, int level, int optname, char *optval, int *optlen) { struct socket *sock; struct file *file; PRINTK ("sys_getsockopt(fd=%d, level=%d, optname=%d,\n",fd, level, optname); PRINTK (" optval = %X, optlen = %X)\n", optval, optlen); if (fd < 0 || fd >= NR_OPEN || ((file = current->filp[fd]) == NULL)) return (-EBADF); if (!(sock = sockfd_lookup(fd, NULL))) return (-ENOTSOCK); return (0); return (sock->ops->getsockopt (sock, level, optname, optval, optlen)); }
struct socket *usnic_transport_get_socket(int sock_fd) { struct socket *sock; int err; char buf[25]; /* sockfd_lookup will internally do a fget */ sock = sockfd_lookup(sock_fd, &err); if (!sock) { usnic_err("Unable to lookup socket for fd %d with err %d\n", sock_fd, err); return ERR_PTR(-ENOENT); } usnic_transport_sock_to_str(buf, sizeof(buf), sock); usnic_dbg("Get sock %s\n", buf); return sock; }
/* * attempt to connect to a socket with the server address. */ static int sock_connect(int fd, struct sockaddr *uservaddr, int addrlen) { struct socket *sock; struct file *file; int i; PRINTK("sys_connect: fd = %d\n", fd); if (!(sock = sockfd_lookup(fd, &file))) return -EBADF; if (sock->state != SS_UNCONNECTED) { PRINTK("sys_connect: socket not unconnected\n"); return -EINVAL; } i = sock->ops->connect(sock, uservaddr, addrlen, file->f_flags); if (i < 0) { PRINTK("sys_connect: connect failed\n"); return i; } return 0; }
static int sys_sendto( int fd, void * buff, int len, unsigned flags, struct sockaddr *addr, int addr_len) { struct socket *sock; struct file *file; PRINTK("sys_sendto (fd = %d, buff = %X, len = %d, flags = %X," " addr=%X, alen = %d\n", fd, buff, len, flags, addr, addr_len); if (fd < 0 || fd >= NR_OPEN || ((file = current->filp[fd]) == NULL)) return (-EBADF); if (!(sock = sockfd_lookup(fd, NULL))) return (-ENOTSOCK); return (sock->ops->sendto (sock, buff, len, (file->f_flags & O_NONBLOCK), flags, addr, addr_len)); }
/* * perform a listen. basically, we allow the protocol to do anything * necessary for a listen, and if that works, we mark the socket as * ready for listening. */ static int sock_listen(int fd, int backlog) { struct socket *sock; PRINTK("sys_listen: fd = %d\n", fd); if (!(sock = sockfd_lookup(fd, NULL))) return -EBADF; if (sock->state != SS_UNCONNECTED) { PRINTK("sys_listen: socket isn't unconnected\n"); return -EINVAL; } if (sock->flags & SO_ACCEPTCON) { PRINTK("sys_listen: socket already accepting connections!\n"); return -EINVAL; } if (sock->ops && sock->ops->listen) sock->ops->listen (sock, backlog); sock->flags |= SO_ACCEPTCON; return 0; }