Newer
Older
void sock_init_data(struct socket *sock, struct sock *sk)
{
timer_setup(&sk->sk_timer, NULL, 0);
sk->sk_allocation = GFP_KERNEL;
sk->sk_rcvbuf = sysctl_rmem_default;
sk->sk_sndbuf = sysctl_wmem_default;
sk->sk_state = TCP_CLOSE;
RCU_INIT_POINTER(sk->sk_wq, &sock->wq);
sk->sk_uid = SOCK_INODE(sock)->i_uid;
} else {
RCU_INIT_POINTER(sk->sk_wq, NULL);
sk->sk_uid = make_kuid(sock_net(sk)->user_ns, 0);
}
if (sk->sk_kern_sock)
lockdep_set_class_and_name(
&sk->sk_callback_lock,
af_kern_callback_keys + sk->sk_family,
af_family_kern_clock_key_strings[sk->sk_family]);
else
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_frag.page = NULL;
sk->sk_frag.offset = 0;
sk->sk_peer_pid = NULL;
sk->sk_peer_cred = NULL;
sk->sk_write_pending = 0;
sk->sk_rcvlowat = 1;
sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT;
sk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT;
sk->sk_stamp = SK_DEFAULT_STAMP;
#if BITS_PER_LONG==32
seqlock_init(&sk->sk_stamp_seq);
#endif
#ifdef CONFIG_NET_RX_BUSY_POLL
sk->sk_ll_usec = sysctl_net_busy_read;
sk->sk_max_pacing_rate = ~0UL;
sk->sk_pacing_rate = ~0UL;
WRITE_ONCE(sk->sk_pacing_shift, 10);
sk_rx_queue_clear(sk);
/*
* Before updating sk_refcnt, we must commit prior changes to memory
* (Documentation/RCU/rculist_nulls.rst for details)
refcount_set(&sk->sk_refcnt, 1);
void lock_sock_nested(struct sock *sk, int subclass)
if (sk->sk_lock.owned)
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_);
EXPORT_SYMBOL(lock_sock_nested);
/* Warning : release_cb() might need to release sk ownership,
* ie call sock_release_ownership(sk) before us.
*/
if (sk->sk_prot->release_cb)
sk->sk_prot->release_cb(sk);
sock_release_ownership(sk);
if (waitqueue_active(&sk->sk_lock.wq))
wake_up(&sk->sk_lock.wq);
spin_unlock_bh(&sk->sk_lock.slock);
/**
* lock_sock_fast - fast version of lock_sock
* @sk: socket
*
* This version should be used for very small section, where process wont block
* return false if fast path is taken:
*
* sk_lock.slock locked, owned = 0, BH disabled
*
* return true if slow path is taken:
*
* sk_lock.slock unlocked, owned = 1, BH enabled
*/
bool lock_sock_fast(struct sock *sk) __acquires(&sk->sk_lock.slock)
{
might_sleep();
spin_lock_bh(&sk->sk_lock.slock);
if (!sk->sk_lock.owned)
/*
* Note : We must disable BH
*/
return false;
__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, 0, 0, _RET_IP_);
__acquire(&sk->sk_lock.slock);
local_bh_enable();
return true;
}
EXPORT_SYMBOL(lock_sock_fast);
int sock_gettstamp(struct socket *sock, void __user *userstamp,
bool timeval, bool time32)
struct sock *sk = sock->sk;
struct timespec64 ts;
sock_enable_timestamp(sk, SOCK_TIMESTAMP);
ts = ktime_to_timespec64(sock_read_timestamp(sk));
if (ts.tv_sec == -1)
if (timeval)
ts.tv_nsec /= 1000;
#ifdef CONFIG_COMPAT_32BIT_TIME
if (time32)
return put_old_timespec32(&ts, userstamp);
#endif
#ifdef CONFIG_SPARC64
/* beware of padding in sparc64 timeval */
if (timeval && !in_compat_syscall()) {
struct __kernel_old_timeval __user tv = {
.tv_sec = ts.tv_sec,
.tv_usec = ts.tv_nsec,
if (copy_to_user(userstamp, &tv, sizeof(tv)))
Eric Dumazet
committed
}
#endif
return put_timespec64(&ts, userstamp);
Eric Dumazet
committed
}
Eric Dumazet
committed
void sock_enable_timestamp(struct sock *sk, enum sock_flags flag)
if (!sock_flag(sk, flag)) {
unsigned long previous_flags = sk->sk_flags;
sock_set_flag(sk, flag);
/*
* we just set one of the two flags which require net
* time stamping, but time stamping might have been on
* already because of the other one
*/
if (sock_needs_netstamp(sk) &&
!(previous_flags & SK_FLAGS_TIMESTAMP))
Richard Cochran
committed
int sock_recv_errqueue(struct sock *sk, struct msghdr *msg, int len,
int level, int type)
{
struct sock_exterr_skb *serr;
Richard Cochran
committed
int copied, err;
err = -EAGAIN;
Richard Cochran
committed
if (skb == NULL)
goto out;
copied = skb->len;
if (copied > len) {
msg->msg_flags |= MSG_TRUNC;
copied = len;
}
err = skb_copy_datagram_msg(skb, 0, msg, copied);
Richard Cochran
committed
if (err)
goto out_free_skb;
sock_recv_timestamp(msg, sk, skb);
serr = SKB_EXT_ERR(skb);
put_cmsg(msg, level, type, sizeof(serr->ee), &serr->ee);
msg->msg_flags |= MSG_ERRQUEUE;
err = copied;
out_free_skb:
kfree_skb(skb);
out:
return err;
}
EXPORT_SYMBOL(sock_recv_errqueue);
/*
* 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 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(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,
sockptr_t optval, unsigned 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 sk_common_release is called, processes have
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
* 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);
void sk_get_meminfo(const struct sock *sk, u32 *mem)
{
memset(mem, 0, sizeof(*mem) * SK_MEMINFO_VARS);
mem[SK_MEMINFO_RMEM_ALLOC] = sk_rmem_alloc_get(sk);
mem[SK_MEMINFO_RCVBUF] = READ_ONCE(sk->sk_rcvbuf);
mem[SK_MEMINFO_WMEM_ALLOC] = sk_wmem_alloc_get(sk);
mem[SK_MEMINFO_SNDBUF] = READ_ONCE(sk->sk_sndbuf);
mem[SK_MEMINFO_FWD_ALLOC] = sk->sk_forward_alloc;
mem[SK_MEMINFO_WMEM_QUEUED] = READ_ONCE(sk->sk_wmem_queued);
mem[SK_MEMINFO_OPTMEM] = atomic_read(&sk->sk_omem_alloc);
mem[SK_MEMINFO_BACKLOG] = READ_ONCE(sk->sk_backlog.len);
mem[SK_MEMINFO_DROPS] = atomic_read(&sk->sk_drops);
}
Pavel Emelyanov
committed
#ifdef CONFIG_PROC_FS
#define PROTO_INUSE_NR 64 /* should be enough for the first time */
struct prot_inuse {
int val[PROTO_INUSE_NR];
};
Pavel Emelyanov
committed
static DECLARE_BITMAP(proto_inuse_idx, PROTO_INUSE_NR);
void sock_prot_inuse_add(struct net *net, struct proto *prot, int val)
{
__this_cpu_add(net->core.prot_inuse->val[prot->inuse_idx], val);
}
EXPORT_SYMBOL_GPL(sock_prot_inuse_add);
int sock_prot_inuse_get(struct net *net, struct proto *prot)
{
int cpu, idx = prot->inuse_idx;
int res = 0;
for_each_possible_cpu(cpu)
res += per_cpu_ptr(net->core.prot_inuse, cpu)->val[idx];
return res >= 0 ? res : 0;
}
EXPORT_SYMBOL_GPL(sock_prot_inuse_get);
static void sock_inuse_add(struct net *net, int val)
{
this_cpu_add(*net->core.sock_inuse, val);
}
int sock_inuse_get(struct net *net)
{
int cpu, res = 0;
for_each_possible_cpu(cpu)
res += *per_cpu_ptr(net->core.sock_inuse, cpu);
return res;
}
EXPORT_SYMBOL_GPL(sock_inuse_get);
static int __net_init sock_inuse_init_net(struct net *net)
{
net->core.prot_inuse = alloc_percpu(struct prot_inuse);
if (net->core.prot_inuse == NULL)
return -ENOMEM;
net->core.sock_inuse = alloc_percpu(int);
if (net->core.sock_inuse == NULL)
goto out;
return 0;
out:
free_percpu(net->core.prot_inuse);
return -ENOMEM;
}
static void __net_exit sock_inuse_exit_net(struct net *net)
{
free_percpu(net->core.prot_inuse);
free_percpu(net->core.sock_inuse);
}
static struct pernet_operations net_inuse_ops = {
.init = sock_inuse_init_net,
.exit = sock_inuse_exit_net,
};
static __init int net_inuse_init(void)
{
if (register_pernet_subsys(&net_inuse_ops))
panic("Cannot initialize net inuse counters");
return 0;
}
core_initcall(net_inuse_init);
Pavel Emelyanov
committed
static int assign_proto_idx(struct proto *prot)
Pavel Emelyanov
committed
{
prot->inuse_idx = find_first_zero_bit(proto_inuse_idx, PROTO_INUSE_NR);
if (unlikely(prot->inuse_idx == PROTO_INUSE_NR - 1)) {
Pavel Emelyanov
committed
}
set_bit(prot->inuse_idx, proto_inuse_idx);
Pavel Emelyanov
committed
}
static void release_proto_idx(struct proto *prot)
{
if (prot->inuse_idx != PROTO_INUSE_NR - 1)
clear_bit(prot->inuse_idx, proto_inuse_idx);
}
#else
static inline int assign_proto_idx(struct proto *prot)
Pavel Emelyanov
committed
{
Pavel Emelyanov
committed
}
static inline void release_proto_idx(struct proto *prot)
{
}
static void sock_inuse_add(struct net *net, int val)
{
}
Pavel Emelyanov
committed
#endif
static void tw_prot_cleanup(struct timewait_sock_ops *twsk_prot)
{
if (!twsk_prot)
return;
kfree(twsk_prot->twsk_slab_name);
twsk_prot->twsk_slab_name = NULL;
kmem_cache_destroy(twsk_prot->twsk_slab);
twsk_prot->twsk_slab = NULL;
}
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
static int tw_prot_init(const struct proto *prot)
{
struct timewait_sock_ops *twsk_prot = prot->twsk_prot;
if (!twsk_prot)
return 0;
twsk_prot->twsk_slab_name = kasprintf(GFP_KERNEL, "tw_sock_%s",
prot->name);
if (!twsk_prot->twsk_slab_name)
return -ENOMEM;
twsk_prot->twsk_slab =
kmem_cache_create(twsk_prot->twsk_slab_name,
twsk_prot->twsk_obj_size, 0,
SLAB_ACCOUNT | prot->slab_flags,
NULL);
if (!twsk_prot->twsk_slab) {
pr_crit("%s: Can't create timewait sock SLAB cache!\n",
prot->name);
return -ENOMEM;
}
return 0;
}
static void req_prot_cleanup(struct request_sock_ops *rsk_prot)
{
if (!rsk_prot)
return;
kfree(rsk_prot->slab_name);
rsk_prot->slab_name = NULL;
kmem_cache_destroy(rsk_prot->slab);
rsk_prot->slab = NULL;
}
static int req_prot_init(const struct proto *prot)
{
struct request_sock_ops *rsk_prot = prot->rsk_prot;
if (!rsk_prot)
return 0;
rsk_prot->slab_name = kasprintf(GFP_KERNEL, "request_sock_%s",
prot->name);
if (!rsk_prot->slab_name)
return -ENOMEM;
rsk_prot->slab = kmem_cache_create(rsk_prot->slab_name,
rsk_prot->obj_size, 0,
SLAB_ACCOUNT | prot->slab_flags,
NULL);
if (!rsk_prot->slab) {
pr_crit("%s: Can't create request sock SLAB cache!\n",
prot->name);
return -ENOMEM;
}
return 0;
}
int proto_register(struct proto *prot, int alloc_slab)
{
int ret = -ENOBUFS;
prot->slab = kmem_cache_create_usercopy(prot->name,
prot->obj_size, 0,
SLAB_HWCACHE_ALIGN | SLAB_ACCOUNT |
prot->slab_flags,
prot->useroffset, prot->usersize,
pr_crit("%s: Can't create sock SLAB cache!\n",
prot->name);
Arnaldo Carvalho de Melo
committed
if (req_prot_init(prot))
goto out_free_request_sock_slab;
if (tw_prot_init(prot))
goto out_free_timewait_sock_slab;
mutex_lock(&proto_list_mutex);
ret = assign_proto_idx(prot);
if (ret) {
mutex_unlock(&proto_list_mutex);
goto out_free_timewait_sock_slab;
mutex_unlock(&proto_list_mutex);
out_free_timewait_sock_slab:
if (alloc_slab)
tw_prot_cleanup(prot->twsk_prot);
out_free_request_sock_slab:
if (alloc_slab) {
req_prot_cleanup(prot->rsk_prot);
kmem_cache_destroy(prot->slab);
prot->slab = NULL;
}
}
EXPORT_SYMBOL(proto_register);
void proto_unregister(struct proto *prot)
{
mutex_lock(&proto_list_mutex);
Pavel Emelyanov
committed
release_proto_idx(prot);
list_del(&prot->node);
mutex_unlock(&proto_list_mutex);
kmem_cache_destroy(prot->slab);
prot->slab = NULL;
req_prot_cleanup(prot->rsk_prot);
tw_prot_cleanup(prot->twsk_prot);
Xin Long
committed
int sock_load_diag_module(int family, int protocol)
{
if (!protocol) {
if (!sock_is_registered(family))
return -ENOENT;
return request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK,
NETLINK_SOCK_DIAG, family);
}
#ifdef CONFIG_INET
if (family == AF_INET &&
protocol != IPPROTO_RAW &&
protocol < MAX_INET_PROTOS &&
Xin Long
committed
!rcu_access_pointer(inet_protos[protocol]))
return -ENOENT;
#endif
return request_module("net-pf-%d-proto-%d-type-%d-%d", PF_NETLINK,
NETLINK_SOCK_DIAG, family, protocol);
}
EXPORT_SYMBOL(sock_load_diag_module);
#ifdef CONFIG_PROC_FS
static void *proto_seq_start(struct seq_file *seq, loff_t *pos)
__acquires(proto_list_mutex)
mutex_lock(&proto_list_mutex);
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)
__releases(proto_list_mutex)
mutex_unlock(&proto_list_mutex);
}
static char proto_method_implemented(const void *method)
{
return method == NULL ? 'n' : 'y';
}
static long sock_prot_memory_allocated(struct proto *proto)
{
return proto->memory_allocated != NULL ? proto_memory_allocated(proto) : -1L;
static const char *sock_prot_memory_pressure(struct proto *proto)
{
return proto->memory_pressure != NULL ?
proto_memory_pressure(proto) ? "yes" : "no" : "NI";
}
static void proto_seq_printf(struct seq_file *seq, struct proto *proto)
{
seq_printf(seq, "%-9s %4u %6d %6ld %-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,
sock_prot_inuse_get(seq_file_net(seq), proto),
sock_prot_memory_allocated(proto),
sock_prot_memory_pressure(proto),
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
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));
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 __net_init int proto_init_net(struct net *net)
{
if (!proc_create_net("protocols", 0444, net->proc_net, &proto_seq_ops,
sizeof(struct seq_net_private)))
return -ENOMEM;
return 0;
}
static __net_exit void proto_exit_net(struct net *net)
{
remove_proc_entry("protocols", net->proc_net);
}
static __net_initdata struct pernet_operations proto_net_ops = {
.init = proto_init_net,
.exit = proto_exit_net,
};
static int __init proto_init(void)
{
return register_pernet_subsys(&proto_net_ops);
}
subsys_initcall(proto_init);
#endif /* PROC_FS */
#ifdef CONFIG_NET_RX_BUSY_POLL
bool sk_busy_loop_end(void *p, unsigned long start_time)
{
struct sock *sk = p;
return !skb_queue_empty_lockless(&sk->sk_receive_queue) ||
sk_busy_loop_timeout(sk, start_time);
}
EXPORT_SYMBOL(sk_busy_loop_end);
#endif /* CONFIG_NET_RX_BUSY_POLL */
int sock_bind_add(struct sock *sk, struct sockaddr *addr, int addr_len)
{
if (!sk->sk_prot->bind_add)
return -EOPNOTSUPP;
return sk->sk_prot->bind_add(sk, addr, addr_len);
}
EXPORT_SYMBOL(sock_bind_add);