📄 sock.c
字号:
sk->sk_state = TCP_CLOSE; sk->sk_socket = sock; sock_set_flag(sk, SOCK_ZAPPED); if (sock) { sk->sk_type = sock->type; sk->sk_sleep = &sock->wait; sock->sk = sk; } else sk->sk_sleep = NULL; rwlock_init(&sk->sk_dst_lock); rwlock_init(&sk->sk_callback_lock); lockdep_set_class_and_name(&sk->sk_callback_lock, af_callback_keys + sk->sk_family, af_family_clock_key_strings[sk->sk_family]); 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_stamp = ktime_set(-1L, -1L); atomic_set(&sk->sk_refcnt, 1);}void fastcall lock_sock_nested(struct sock *sk, int subclass){ might_sleep(); spin_lock_bh(&sk->sk_lock.slock); if (sk->sk_lock.owned) __lock_sock(sk); sk->sk_lock.owned = 1; spin_unlock(&sk->sk_lock.slock); /* * The sk_lock has mutex_lock() semantics here: */ mutex_acquire(&sk->sk_lock.dep_map, subclass, 0, _RET_IP_); local_bh_enable();}EXPORT_SYMBOL(lock_sock_nested);void fastcall release_sock(struct sock *sk){ /* * The sk_lock has mutex_unlock() semantics: */ mutex_release(&sk->sk_lock.dep_map, 1, _RET_IP_); spin_lock_bh(&sk->sk_lock.slock); if (sk->sk_backlog.tail) __release_sock(sk); sk->sk_lock.owned = 0; if (waitqueue_active(&sk->sk_lock.wq)) wake_up(&sk->sk_lock.wq); spin_unlock_bh(&sk->sk_lock.slock);}EXPORT_SYMBOL(release_sock);int sock_get_timestamp(struct sock *sk, struct timeval __user *userstamp){ struct timeval tv; if (!sock_flag(sk, SOCK_TIMESTAMP)) sock_enable_timestamp(sk); tv = ktime_to_timeval(sk->sk_stamp); if (tv.tv_sec == -1) return -ENOENT; if (tv.tv_sec == 0) { sk->sk_stamp = ktime_get_real(); tv = ktime_to_timeval(sk->sk_stamp); } return copy_to_user(userstamp, &tv, sizeof(tv)) ? -EFAULT : 0;}EXPORT_SYMBOL(sock_get_timestamp);int sock_get_timestampns(struct sock *sk, struct timespec __user *userstamp){ struct timespec ts; if (!sock_flag(sk, SOCK_TIMESTAMP)) sock_enable_timestamp(sk); ts = ktime_to_timespec(sk->sk_stamp); if (ts.tv_sec == -1) return -ENOENT; if (ts.tv_sec == 0) { sk->sk_stamp = ktime_get_real(); ts = ktime_to_timespec(sk->sk_stamp); } return copy_to_user(userstamp, &ts, sizeof(ts)) ? -EFAULT : 0;}EXPORT_SYMBOL(sock_get_timestampns);void sock_enable_timestamp(struct sock *sk){ if (!sock_flag(sk, SOCK_TIMESTAMP)) { sock_set_flag(sk, SOCK_TIMESTAMP); net_enable_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);#ifdef CONFIG_COMPATint compat_sock_common_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen){ struct sock *sk = sock->sk; if (sk->sk_prot->compat_getsockopt != NULL) return sk->sk_prot->compat_getsockopt(sk, level, optname, optval, optlen); return sk->sk_prot->getsockopt(sk, level, optname, optval, optlen);}EXPORT_SYMBOL(compat_sock_common_getsockopt);#endifint 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);#ifdef CONFIG_COMPATint compat_sock_common_setsockopt(struct socket *sock, int level, int optname, char __user *optval, int optlen){ struct sock *sk = sock->sk; if (sk->sk_prot->compat_setsockopt != NULL) return sk->sk_prot->compat_setsockopt(sk, level, optname, optval, optlen); return sk->sk_prot->setsockopt(sk, level, optname, optval, optlen);}EXPORT_SYMBOL(compat_sock_common_setsockopt);#endifvoid 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); sk_refcnt_debug_release(sk); sock_put(sk);}EXPORT_SYMBOL(sk_common_release);static DEFINE_RWLOCK(proto_list_lock);static LIST_HEAD(proto_list);#ifdef CONFIG_SMP/* * Define default functions to keep track of inuse sockets per protocol * Note that often used protocols use dedicated functions to get a speed increase. * (see DEFINE_PROTO_INUSE/REF_PROTO_INUSE) */static void inuse_add(struct proto *prot, int inc){ per_cpu_ptr(prot->inuse_ptr, smp_processor_id())[0] += inc;}static int inuse_get(const struct proto *prot){ int res = 0, cpu; for_each_possible_cpu(cpu) res += per_cpu_ptr(prot->inuse_ptr, cpu)[0]; return res;}static int inuse_init(struct proto *prot){ if (!prot->inuse_getval || !prot->inuse_add) { prot->inuse_ptr = alloc_percpu(int); if (prot->inuse_ptr == NULL) return -ENOBUFS; prot->inuse_getval = inuse_get; prot->inuse_add = inuse_add; } return 0;}static void inuse_fini(struct proto *prot){ if (prot->inuse_ptr != NULL) { free_percpu(prot->inuse_ptr); prot->inuse_ptr = NULL; prot->inuse_getval = NULL; prot->inuse_add = NULL; }}#elsestatic inline int inuse_init(struct proto *prot){ return 0;}static inline void inuse_fini(struct proto *prot){}#endifint proto_register(struct proto *prot, int alloc_slab){ char *request_sock_slab_name = NULL; char *timewait_sock_slab_name; if (inuse_init(prot)) goto out; if (alloc_slab) { prot->slab = kmem_cache_create(prot->name, prot->obj_size, 0, SLAB_HWCACHE_ALIGN, NULL); if (prot->slab == NULL) { printk(KERN_CRIT "%s: Can't create sock SLAB cache!\n", prot->name); goto out_free_inuse; } if (prot->rsk_prot != NULL) { static const char mask[] = "request_sock_%s"; request_sock_slab_name = kmalloc(strlen(prot->name) + sizeof(mask) - 1, GFP_KERNEL); if (request_sock_slab_name == NULL) goto out_free_sock_slab; sprintf(request_sock_slab_name, mask, prot->name); prot->rsk_prot->slab = kmem_cache_create(request_sock_slab_name, prot->rsk_prot->obj_size, 0, SLAB_HWCACHE_ALIGN, NULL); if (prot->rsk_prot->slab == NULL) { printk(KERN_CRIT "%s: Can't create request sock SLAB cache!\n", prot->name); goto out_free_request_sock_slab_name; } } if (prot->twsk_prot != NULL) { static const char mask[] = "tw_sock_%s"; timewait_sock_slab_name = kmalloc(strlen(prot->name) + sizeof(mask) - 1, GFP_KERNEL); if (timewait_sock_slab_name == NULL) goto out_free_request_sock_slab; sprintf(timewait_sock_slab_name, mask, prot->name); prot->twsk_prot->twsk_slab = kmem_cache_create(timewait_sock_slab_name, prot->twsk_prot->twsk_obj_size, 0, SLAB_HWCACHE_ALIGN, NULL); if (prot->twsk_prot->twsk_slab == NULL) goto out_free_timewait_sock_slab_name; } } write_lock(&proto_list_lock); list_add(&prot->node, &proto_list); write_unlock(&proto_list_lock); return 0;out_free_timewait_sock_slab_name: kfree(timewait_sock_slab_name);out_free_request_sock_slab: if (prot->rsk_prot && prot->rsk_prot->slab) { kmem_cache_destroy(prot->rsk_prot->slab); prot->rsk_prot->slab = NULL; }out_free_request_sock_slab_name: kfree(request_sock_slab_name);out_free_sock_slab: kmem_cache_destroy(prot->slab); prot->slab = NULL;out_free_inuse: inuse_fini(prot);out: return -ENOBUFS;}EXPORT_SYMBOL(proto_register);void proto_unregister(struct proto *prot){ write_lock(&proto_list_lock); list_del(&prot->node); write_unlock(&proto_list_lock); inuse_fini(prot); if (prot->slab != NULL) { kmem_cache_destroy(prot->slab); prot->slab = NULL; } if (prot->rsk_prot != NULL && prot->rsk_prot->slab != NULL) { const char *name = kmem_cache_name(prot->rsk_prot->slab); kmem_cache_destroy(prot->rsk_prot->slab); kfree(name); prot->rsk_prot->slab = NULL; } if (prot->twsk_prot != NULL && prot->twsk_prot->twsk_slab != NULL) { const char *name = kmem_cache_name(prot->twsk_prot->twsk_slab); kmem_cache_destroy(prot->twsk_prot->twsk_slab); kfree(name); prot->twsk_prot->twsk_slab = NULL; }}EXPORT_SYMBOL(proto_unregister);#ifdef CONFIG_PROC_FSstatic void *proto_seq_start(struct seq_file *seq, loff_t *pos){ read_lock(&proto_list_lock); return seq_list_start_head(&proto_list, *pos);}static void *proto_seq_next(struct seq_file *seq, void *v, loff_t *pos){ return seq_list_next(v, &proto_list, pos);}static void proto_seq_stop(struct seq_file *seq, void *v){ read_unlock(&proto_list_lock);}static char proto_method_implemented(const void *method){ return method == NULL ? 'n' : 'y';}static void proto_seq_printf(struct seq_file *seq, struct proto *proto){ seq_printf(seq, "%-9s %4u %6d %6d %-3s %6u %-3s %-10s " "%2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c\n", proto->name, proto->obj_size, proto->sockets_allocated != NULL ? atomic_read(proto->sockets_allocated) : -1, proto->memory_allocated != NULL ? atomic_read(proto->memory_allocated) : -1, proto->memory_pressure != NULL ? *proto->memory_pressure ? "yes" : "no" : "NI", proto->max_header, proto->slab == NULL ? "no" : "yes", module_name(proto->owner), proto_method_implemented(proto->close), proto_method_implemented(proto->connect), proto_method_implemented(proto->disconnect), proto_method_implemented(proto->accept), proto_method_implemented(proto->ioctl), proto_method_implemented(proto->init), proto_method_implemented(proto->destroy), proto_method_implemented(proto->shutdown), proto_method_implemented(proto->setsockopt), proto_method_implemented(proto->getsockopt), proto_method_implemented(proto->sendmsg), proto_method_implemented(proto->recvmsg), proto_method_implemented(proto->sendpage), proto_method_implemented(proto->bind), proto_method_implemented(proto->backlog_rcv), proto_method_implemented(proto->hash), proto_method_implemented(proto->unhash), proto_method_implemented(proto->get_port), proto_method_implemented(proto->enter_memory_pressure));}static int proto_seq_show(struct seq_file *seq, void *v){ if (v == &proto_list) seq_printf(seq, "%-9s %-4s %-8s %-6s %-5s %-7s %-4s %-10s %s", "protocol", "size", "sockets", "memory", "press", "maxhdr", "slab", "module", "cl co di ac io in de sh ss gs se re sp bi br ha uh gp em\n"); else proto_seq_printf(seq, list_entry(v, struct proto, node)); return 0;}static const struct seq_operations proto_seq_ops = { .start = proto_seq_start, .next = proto_seq_next, .stop = proto_seq_stop, .show = proto_seq_show,};static int proto_seq_open(struct inode *inode, struct file *file){ return seq_open(file, &proto_seq_ops);}static const struct file_operations proto_seq_fops = { .owner = THIS_MODULE, .open = proto_seq_open, .read = seq_read, .llseek = seq_lseek, .release = seq_release,};static int __init proto_init(void){ /* register /proc/net/protocols */ return proc_net_fops_create(&init_net, "protocols", S_IRUGO, &proto_seq_fops) == NULL ? -ENOBUFS : 0;}subsys_initcall(proto_init);#endif /* PROC_FS */EXPORT_SYMBOL(sk_alloc);EXPORT_SYMBOL(sk_free);EXPORT_SYMBOL(sk_send_sigurg);EXPORT_SYMBOL(sock_alloc_send_skb);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_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_setsockopt);EXPORT_SYMBOL(sock_wfree);EXPORT_SYMBOL(sock_wmalloc);EXPORT_SYMBOL(sock_i_uid);EXPORT_SYMBOL(sock_i_ino);EXPORT_SYMBOL(sysctl_optmem_max);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -