📄 sock.c
字号:
bh_lock_sock(sk); } while((skb = sk->sk_backlog.head) != NULL);}/** * sk_wait_data - wait for data to arrive at sk_receive_queue * sk - sock to wait on * timeo - for how long * * Now socket state including sk->sk_err is changed only under lock, * hence we may omit checks after joining wait queue. * We check receive queue before schedule() only as optimization; * it is very likely that release_sock() added new data. */int sk_wait_data(struct sock *sk, long *timeo){ int rc; DEFINE_WAIT(wait); prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); rc = sk_wait_event(sk, timeo, !skb_queue_empty(&sk->sk_receive_queue)); clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); finish_wait(sk->sk_sleep, &wait); return rc;}EXPORT_SYMBOL(sk_wait_data);/* * Set of default routines for initialising struct proto_ops when * the protocol does not support a particular function. In certain * cases where it makes no sense for a protocol to have a "do nothing" * function, some default processing is provided. */int sock_no_release(struct socket *sock){ return 0;}int sock_no_bind(struct socket *sock, struct sockaddr *saddr, int len){ return -EOPNOTSUPP;}int sock_no_connect(struct socket *sock, struct sockaddr *saddr, int len, int flags){ return -EOPNOTSUPP;}int sock_no_socketpair(struct socket *sock1, struct socket *sock2){ return -EOPNOTSUPP;}int sock_no_accept(struct socket *sock, struct socket *newsock, int flags){ return -EOPNOTSUPP;}int sock_no_getname(struct socket *sock, struct sockaddr *saddr, int *len, int peer){ return -EOPNOTSUPP;}unsigned int sock_no_poll(struct file * file, struct socket *sock, poll_table *pt){ return 0;}int sock_no_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg){ return -EOPNOTSUPP;}int sock_no_listen(struct socket *sock, int backlog){ return -EOPNOTSUPP;}int sock_no_shutdown(struct socket *sock, int how){ return -EOPNOTSUPP;}int sock_no_setsockopt(struct socket *sock, int level, int optname, char __user *optval, int optlen){ return -EOPNOTSUPP;}int sock_no_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen){ return -EOPNOTSUPP;}int sock_no_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t len){ return -EOPNOTSUPP;}int sock_no_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t len, int flags){ return -EOPNOTSUPP;}int sock_no_mmap(struct file *file, struct socket *sock, struct vm_area_struct *vma){ /* Mirror missing mmap method error code */ return -ENODEV;}ssize_t sock_no_sendpage(struct socket *sock, struct page *page, int offset, size_t size, int flags){ ssize_t res; struct msghdr msg = {.msg_flags = flags}; struct kvec iov; char *kaddr = kmap(page); iov.iov_base = kaddr + offset; iov.iov_len = size; res = kernel_sendmsg(sock, &msg, &iov, 1, size); kunmap(page); return res;}/* * Default Socket Callbacks */void sock_def_wakeup(struct sock *sk){ read_lock(&sk->sk_callback_lock); if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) wake_up_interruptible_all(sk->sk_sleep); read_unlock(&sk->sk_callback_lock);}void sock_def_error_report(struct sock *sk){ read_lock(&sk->sk_callback_lock); if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) wake_up_interruptible(sk->sk_sleep); sk_wake_async(sk,0,POLL_ERR); read_unlock(&sk->sk_callback_lock);}void sock_def_readable(struct sock *sk, int len){ read_lock(&sk->sk_callback_lock); if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) wake_up_interruptible(sk->sk_sleep); sk_wake_async(sk,1,POLL_IN); read_unlock(&sk->sk_callback_lock);}void sock_def_write_space(struct sock *sk){ read_lock(&sk->sk_callback_lock); /* Do not wake up a writer until he can make "significant" * progress. --DaveM */ if((atomic_read(&sk->sk_wmem_alloc) << 1) <= sk->sk_sndbuf) { if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) wake_up_interruptible(sk->sk_sleep); /* Should agree with poll, otherwise some programs break */ if (sock_writeable(sk)) sk_wake_async(sk, 2, POLL_OUT); } read_unlock(&sk->sk_callback_lock);}void sock_def_destruct(struct sock *sk){ if (sk->sk_protinfo) kfree(sk->sk_protinfo);}void sk_send_sigurg(struct sock *sk){ if (sk->sk_socket && sk->sk_socket->file) if (send_sigurg(&sk->sk_socket->file->f_owner)) sk_wake_async(sk, 3, POLL_PRI);}void sk_reset_timer(struct sock *sk, struct timer_list* timer, unsigned long expires){ if (!mod_timer(timer, expires)) sock_hold(sk);}EXPORT_SYMBOL(sk_reset_timer);void sk_stop_timer(struct sock *sk, struct timer_list* timer){ if (timer_pending(timer) && del_timer(timer)) __sock_put(sk);}EXPORT_SYMBOL(sk_stop_timer);void sock_init_data(struct socket *sock, struct sock *sk){ skb_queue_head_init(&sk->sk_receive_queue); skb_queue_head_init(&sk->sk_write_queue); skb_queue_head_init(&sk->sk_error_queue); sk->sk_send_head = NULL; init_timer(&sk->sk_timer); sk->sk_allocation = GFP_KERNEL; sk->sk_rcvbuf = sysctl_rmem_default; sk->sk_sndbuf = sysctl_wmem_default; sk->sk_state = TCP_CLOSE; sk->sk_zapped = 1; sk->sk_socket = sock; if(sock) { sk->sk_type = sock->type; sk->sk_sleep = &sock->wait; sock->sk = sk; } else sk->sk_sleep = NULL; sk->sk_dst_lock = RW_LOCK_UNLOCKED; sk->sk_callback_lock = RW_LOCK_UNLOCKED; sk->sk_state_change = sock_def_wakeup; sk->sk_data_ready = sock_def_readable; sk->sk_write_space = sock_def_write_space; sk->sk_error_report = sock_def_error_report; sk->sk_destruct = sock_def_destruct; sk->sk_sndmsg_page = NULL; sk->sk_sndmsg_off = 0; sk->sk_peercred.pid = 0; sk->sk_peercred.uid = -1; sk->sk_peercred.gid = -1; sk->sk_write_pending = 0; sk->sk_rcvlowat = 1; sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT; sk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT; sk->sk_owner = NULL; sk->sk_stamp.tv_sec = -1L; sk->sk_stamp.tv_usec = -1L; atomic_set(&sk->sk_refcnt, 1);}void fastcall lock_sock(struct sock *sk){ might_sleep(); spin_lock_bh(&(sk->sk_lock.slock)); if (sk->sk_lock.owner) __lock_sock(sk); sk->sk_lock.owner = (void *)1; spin_unlock_bh(&(sk->sk_lock.slock));}EXPORT_SYMBOL(lock_sock);void fastcall release_sock(struct sock *sk){ spin_lock_bh(&(sk->sk_lock.slock)); if (sk->sk_backlog.tail) __release_sock(sk); sk->sk_lock.owner = NULL; if (waitqueue_active(&(sk->sk_lock.wq))) wake_up(&(sk->sk_lock.wq)); spin_unlock_bh(&(sk->sk_lock.slock));}EXPORT_SYMBOL(release_sock);/* When > 0 there are consumers of rx skb time stamps */atomic_t netstamp_needed = ATOMIC_INIT(0); int sock_get_timestamp(struct sock *sk, struct timeval __user *userstamp){ if (!sock_flag(sk, SOCK_TIMESTAMP)) sock_enable_timestamp(sk); if (sk->sk_stamp.tv_sec == -1) return -ENOENT; if (sk->sk_stamp.tv_sec == 0) do_gettimeofday(&sk->sk_stamp); return copy_to_user(userstamp, &sk->sk_stamp, sizeof(struct timeval)) ? -EFAULT : 0; } EXPORT_SYMBOL(sock_get_timestamp);void sock_enable_timestamp(struct sock *sk){ if (!sock_flag(sk, SOCK_TIMESTAMP)) { sock_set_flag(sk, SOCK_TIMESTAMP); atomic_inc(&netstamp_needed); }}EXPORT_SYMBOL(sock_enable_timestamp); void sock_disable_timestamp(struct sock *sk){ if (sock_flag(sk, SOCK_TIMESTAMP)) { sock_reset_flag(sk, SOCK_TIMESTAMP); atomic_dec(&netstamp_needed); }}EXPORT_SYMBOL(sock_disable_timestamp);/* * Get a socket option on an socket. * * FIX: POSIX 1003.1g is very ambiguous here. It states that * asynchronous errors should be reported by getsockopt. We assume * this means if you specify SO_ERROR (otherwise whats the point of it). */int sock_common_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen){ struct sock *sk = sock->sk; return sk->sk_prot->getsockopt(sk, level, optname, optval, optlen);}EXPORT_SYMBOL(sock_common_getsockopt);int sock_common_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t size, int flags){ struct sock *sk = sock->sk; int addr_len = 0; int err; err = sk->sk_prot->recvmsg(iocb, sk, msg, size, flags & MSG_DONTWAIT, flags & ~MSG_DONTWAIT, &addr_len); if (err >= 0) msg->msg_namelen = addr_len; return err;}EXPORT_SYMBOL(sock_common_recvmsg);/* * Set socket options on an inet socket. */int sock_common_setsockopt(struct socket *sock, int level, int optname, char __user *optval, int optlen){ struct sock *sk = sock->sk; return sk->sk_prot->setsockopt(sk, level, optname, optval, optlen);}EXPORT_SYMBOL(sock_common_setsockopt);void sk_common_release(struct sock *sk){ if (sk->sk_prot->destroy) sk->sk_prot->destroy(sk); /* * Observation: when sock_common_release is called, processes have * no access to socket. But net still has. * Step one, detach it from networking: * * A. Remove from hash tables. */ sk->sk_prot->unhash(sk); /* * In this point socket cannot receive new packets, but it is possible * that some packets are in flight because some CPU runs receiver and * did hash table lookup before we unhashed socket. They will achieve * receive queue and will be purged by socket destructor. * * Also we still have packets pending on receive queue and probably, * our own packets waiting in device queues. sock_destroy will drain * receive queue, but transmitted packets will delay socket destruction * until the last reference will be released. */ sock_orphan(sk); xfrm_sk_free_policy(sk);#ifdef INET_REFCNT_DEBUG if (atomic_read(&sk->sk_refcnt) != 1) printk(KERN_DEBUG "Destruction of the socket %p delayed, c=%d\n", sk, atomic_read(&sk->sk_refcnt));#endif sock_put(sk);}EXPORT_SYMBOL(sk_common_release);int sk_alloc_slab(struct proto *prot, char *name){ prot->slab = kmem_cache_create(name, prot->slab_obj_size, 0, SLAB_HWCACHE_ALIGN, NULL, NULL); return prot->slab != NULL ? 0 : -ENOBUFS;}EXPORT_SYMBOL(sk_alloc_slab);void sk_free_slab(struct proto *prot){ if (prot->slab != NULL) { kmem_cache_destroy(prot->slab); prot->slab = NULL; }}EXPORT_SYMBOL(sk_free_slab);EXPORT_SYMBOL(__lock_sock);EXPORT_SYMBOL(__release_sock);EXPORT_SYMBOL(sk_alloc);EXPORT_SYMBOL(sk_free);EXPORT_SYMBOL(sk_send_sigurg);EXPORT_SYMBOL(sock_alloc_send_pskb);EXPORT_SYMBOL(sock_alloc_send_skb);EXPORT_SYMBOL(sock_getsockopt);EXPORT_SYMBOL(sock_init_data);EXPORT_SYMBOL(sock_kfree_s);EXPORT_SYMBOL(sock_kmalloc);EXPORT_SYMBOL(sock_no_accept);EXPORT_SYMBOL(sock_no_bind);EXPORT_SYMBOL(sock_no_connect);EXPORT_SYMBOL(sock_no_getname);EXPORT_SYMBOL(sock_no_getsockopt);EXPORT_SYMBOL(sock_no_ioctl);EXPORT_SYMBOL(sock_no_listen);EXPORT_SYMBOL(sock_no_mmap);EXPORT_SYMBOL(sock_no_poll);EXPORT_SYMBOL(sock_no_recvmsg);EXPORT_SYMBOL(sock_no_release);EXPORT_SYMBOL(sock_no_sendmsg);EXPORT_SYMBOL(sock_no_sendpage);EXPORT_SYMBOL(sock_no_setsockopt);EXPORT_SYMBOL(sock_no_shutdown);EXPORT_SYMBOL(sock_no_socketpair);EXPORT_SYMBOL(sock_rfree);EXPORT_SYMBOL(sock_rmalloc);EXPORT_SYMBOL(sock_setsockopt);EXPORT_SYMBOL(sock_wfree);EXPORT_SYMBOL(sock_wmalloc);EXPORT_SYMBOL(sock_i_uid);EXPORT_SYMBOL(sock_i_ino);#ifdef CONFIG_SYSCTLEXPORT_SYMBOL(sysctl_optmem_max);EXPORT_SYMBOL(sysctl_rmem_max);EXPORT_SYMBOL(sysctl_wmem_max);#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -