af_netlink.c (3527a86b7ae17c949307d00e1eb7087604bca1b4) | af_netlink.c (49f7b33e63fec9d16e7ee62ba8f8ab4159cbdc26) |
---|---|
1/* 2 * NETLINK Kernel-user communication protocol. 3 * 4 * Authors: Alan Cox <alan@lxorguk.ukuu.org.uk> 5 * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> 6 * Patrick McHardy <kaber@trash.net> 7 * 8 * This program is free software; you can redistribute it and/or --- 102 unchanged lines hidden (view full) --- 111 112#define nl_deref_protected(X) rcu_dereference_protected(X, lockdep_is_held(&nl_table_lock)); 113 114static ATOMIC_NOTIFIER_HEAD(netlink_chain); 115 116static DEFINE_SPINLOCK(netlink_tap_lock); 117static struct list_head netlink_tap_all __read_mostly; 118 | 1/* 2 * NETLINK Kernel-user communication protocol. 3 * 4 * Authors: Alan Cox <alan@lxorguk.ukuu.org.uk> 5 * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> 6 * Patrick McHardy <kaber@trash.net> 7 * 8 * This program is free software; you can redistribute it and/or --- 102 unchanged lines hidden (view full) --- 111 112#define nl_deref_protected(X) rcu_dereference_protected(X, lockdep_is_held(&nl_table_lock)); 113 114static ATOMIC_NOTIFIER_HEAD(netlink_chain); 115 116static DEFINE_SPINLOCK(netlink_tap_lock); 117static struct list_head netlink_tap_all __read_mostly; 118 |
119static const struct rhashtable_params netlink_rhashtable_params; 120 |
|
119static inline u32 netlink_group_mask(u32 group) 120{ 121 return group ? 1 << (group - 1) : 0; 122} 123 124int netlink_add_tap(struct netlink_tap *nt) 125{ 126 if (unlikely(nt->dev->type != ARPHRD_NETLINK)) --- 838 unchanged lines hidden (view full) --- 965netlink_unlock_table(void) 966{ 967 if (atomic_dec_and_test(&nl_table_users)) 968 wake_up(&nl_table_wait); 969} 970 971struct netlink_compare_arg 972{ | 121static inline u32 netlink_group_mask(u32 group) 122{ 123 return group ? 1 << (group - 1) : 0; 124} 125 126int netlink_add_tap(struct netlink_tap *nt) 127{ 128 if (unlikely(nt->dev->type != ARPHRD_NETLINK)) --- 838 unchanged lines hidden (view full) --- 967netlink_unlock_table(void) 968{ 969 if (atomic_dec_and_test(&nl_table_users)) 970 wake_up(&nl_table_wait); 971} 972 973struct netlink_compare_arg 974{ |
973 struct net *net; | 975 possible_net_t pnet; |
974 u32 portid; 975}; 976 | 976 u32 portid; 977}; 978 |
977static bool netlink_compare(void *ptr, void *arg) | 979/* Doing sizeof directly may yield 4 extra bytes on 64-bit. */ 980#define netlink_compare_arg_len \ 981 (offsetof(struct netlink_compare_arg, portid) + sizeof(u32)) 982 983static inline int netlink_compare(struct rhashtable_compare_arg *arg, 984 const void *ptr) |
978{ | 985{ |
979 struct netlink_compare_arg *x = arg; 980 struct sock *sk = ptr; | 986 const struct netlink_compare_arg *x = arg->key; 987 const struct netlink_sock *nlk = ptr; |
981 | 988 |
982 return nlk_sk(sk)->portid == x->portid && 983 net_eq(sock_net(sk), x->net); | 989 return nlk->portid != x->portid || 990 !net_eq(sock_net(&nlk->sk), read_pnet(&x->pnet)); |
984} 985 | 991} 992 |
993static void netlink_compare_arg_init(struct netlink_compare_arg *arg, 994 struct net *net, u32 portid) 995{ 996 memset(arg, 0, sizeof(*arg)); 997 write_pnet(&arg->pnet, net); 998 arg->portid = portid; 999} 1000 |
|
986static struct sock *__netlink_lookup(struct netlink_table *table, u32 portid, 987 struct net *net) 988{ | 1001static struct sock *__netlink_lookup(struct netlink_table *table, u32 portid, 1002 struct net *net) 1003{ |
989 struct netlink_compare_arg arg = { 990 .net = net, 991 .portid = portid, 992 }; | 1004 struct netlink_compare_arg arg; |
993 | 1005 |
994 return rhashtable_lookup_compare(&table->hash, &portid, 995 &netlink_compare, &arg); | 1006 netlink_compare_arg_init(&arg, net, portid); 1007 return rhashtable_lookup_fast(&table->hash, &arg, 1008 netlink_rhashtable_params); |
996} 997 | 1009} 1010 |
998static bool __netlink_insert(struct netlink_table *table, struct sock *sk) | 1011static int __netlink_insert(struct netlink_table *table, struct sock *sk) |
999{ | 1012{ |
1000 struct netlink_compare_arg arg = { 1001 .net = sock_net(sk), 1002 .portid = nlk_sk(sk)->portid, 1003 }; | 1013 struct netlink_compare_arg arg; |
1004 | 1014 |
1005 return rhashtable_lookup_compare_insert(&table->hash, 1006 &nlk_sk(sk)->node, 1007 &netlink_compare, &arg); | 1015 netlink_compare_arg_init(&arg, sock_net(sk), nlk_sk(sk)->portid); 1016 return rhashtable_lookup_insert_key(&table->hash, &arg, 1017 &nlk_sk(sk)->node, 1018 netlink_rhashtable_params); |
1008} 1009 1010static struct sock *netlink_lookup(struct net *net, int protocol, u32 portid) 1011{ 1012 struct netlink_table *table = &nl_table[protocol]; 1013 struct sock *sk; 1014 1015 rcu_read_lock(); --- 45 unchanged lines hidden (view full) --- 1061 err = -ENOMEM; 1062 if (BITS_PER_LONG > 32 && 1063 unlikely(atomic_read(&table->hash.nelems) >= UINT_MAX)) 1064 goto err; 1065 1066 nlk_sk(sk)->portid = portid; 1067 sock_hold(sk); 1068 | 1019} 1020 1021static struct sock *netlink_lookup(struct net *net, int protocol, u32 portid) 1022{ 1023 struct netlink_table *table = &nl_table[protocol]; 1024 struct sock *sk; 1025 1026 rcu_read_lock(); --- 45 unchanged lines hidden (view full) --- 1072 err = -ENOMEM; 1073 if (BITS_PER_LONG > 32 && 1074 unlikely(atomic_read(&table->hash.nelems) >= UINT_MAX)) 1075 goto err; 1076 1077 nlk_sk(sk)->portid = portid; 1078 sock_hold(sk); 1079 |
1069 err = 0; 1070 if (!__netlink_insert(table, sk)) { 1071 err = -EADDRINUSE; | 1080 err = __netlink_insert(table, sk); 1081 if (err) { 1082 if (err == -EEXIST) 1083 err = -EADDRINUSE; |
1072 sock_put(sk); 1073 } 1074 1075err: 1076 release_sock(sk); 1077 return err; 1078} 1079 1080static void netlink_remove(struct sock *sk) 1081{ 1082 struct netlink_table *table; 1083 1084 table = &nl_table[sk->sk_protocol]; | 1084 sock_put(sk); 1085 } 1086 1087err: 1088 release_sock(sk); 1089 return err; 1090} 1091 1092static void netlink_remove(struct sock *sk) 1093{ 1094 struct netlink_table *table; 1095 1096 table = &nl_table[sk->sk_protocol]; |
1085 if (rhashtable_remove(&table->hash, &nlk_sk(sk)->node)) { | 1097 if (!rhashtable_remove_fast(&table->hash, &nlk_sk(sk)->node, 1098 netlink_rhashtable_params)) { |
1086 WARN_ON(atomic_read(&sk->sk_refcnt) == 1); 1087 __sock_put(sk); 1088 } 1089 1090 netlink_table_grab(); 1091 if (nlk_sk(sk)->subscriptions) { 1092 __sk_del_bind_node(sk); 1093 netlink_update_listeners(sk); --- 1157 unchanged lines hidden (view full) --- 2251static void netlink_cmsg_recv_pktinfo(struct msghdr *msg, struct sk_buff *skb) 2252{ 2253 struct nl_pktinfo info; 2254 2255 info.group = NETLINK_CB(skb).dst_group; 2256 put_cmsg(msg, SOL_NETLINK, NETLINK_PKTINFO, sizeof(info), &info); 2257} 2258 | 1099 WARN_ON(atomic_read(&sk->sk_refcnt) == 1); 1100 __sock_put(sk); 1101 } 1102 1103 netlink_table_grab(); 1104 if (nlk_sk(sk)->subscriptions) { 1105 __sk_del_bind_node(sk); 1106 netlink_update_listeners(sk); --- 1157 unchanged lines hidden (view full) --- 2264static void netlink_cmsg_recv_pktinfo(struct msghdr *msg, struct sk_buff *skb) 2265{ 2266 struct nl_pktinfo info; 2267 2268 info.group = NETLINK_CB(skb).dst_group; 2269 put_cmsg(msg, SOL_NETLINK, NETLINK_PKTINFO, sizeof(info), &info); 2270} 2271 |
2259static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, 2260 struct msghdr *msg, size_t len) | 2272static int netlink_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) |
2261{ 2262 struct sock *sk = sock->sk; 2263 struct netlink_sock *nlk = nlk_sk(sk); 2264 DECLARE_SOCKADDR(struct sockaddr_nl *, addr, msg->msg_name); 2265 u32 dst_portid; 2266 u32 dst_group; 2267 struct sk_buff *skb; 2268 int err; --- 72 unchanged lines hidden (view full) --- 2341 } 2342 err = netlink_unicast(sk, skb, dst_portid, msg->msg_flags&MSG_DONTWAIT); 2343 2344out: 2345 scm_destroy(&scm); 2346 return err; 2347} 2348 | 2273{ 2274 struct sock *sk = sock->sk; 2275 struct netlink_sock *nlk = nlk_sk(sk); 2276 DECLARE_SOCKADDR(struct sockaddr_nl *, addr, msg->msg_name); 2277 u32 dst_portid; 2278 u32 dst_group; 2279 struct sk_buff *skb; 2280 int err; --- 72 unchanged lines hidden (view full) --- 2353 } 2354 err = netlink_unicast(sk, skb, dst_portid, msg->msg_flags&MSG_DONTWAIT); 2355 2356out: 2357 scm_destroy(&scm); 2358 return err; 2359} 2360 |
2349static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock, 2350 struct msghdr *msg, size_t len, | 2361static int netlink_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, |
2351 int flags) 2352{ 2353 struct scm_cookie scm; 2354 struct sock *sk = sock->sk; 2355 struct netlink_sock *nlk = nlk_sk(sk); 2356 int noblock = flags&MSG_DONTWAIT; 2357 size_t copied; 2358 struct sk_buff *skb, *data_skb; --- 752 unchanged lines hidden (view full) --- 3111 netlink_table_ungrab(); 3112} 3113 3114static struct pernet_operations __net_initdata netlink_net_ops = { 3115 .init = netlink_net_init, 3116 .exit = netlink_net_exit, 3117}; 3118 | 2362 int flags) 2363{ 2364 struct scm_cookie scm; 2365 struct sock *sk = sock->sk; 2366 struct netlink_sock *nlk = nlk_sk(sk); 2367 int noblock = flags&MSG_DONTWAIT; 2368 size_t copied; 2369 struct sk_buff *skb, *data_skb; --- 752 unchanged lines hidden (view full) --- 3122 netlink_table_ungrab(); 3123} 3124 3125static struct pernet_operations __net_initdata netlink_net_ops = { 3126 .init = netlink_net_init, 3127 .exit = netlink_net_exit, 3128}; 3129 |
3130static inline u32 netlink_hash(const void *data, u32 len, u32 seed) 3131{ 3132 const struct netlink_sock *nlk = data; 3133 struct netlink_compare_arg arg; 3134 3135 netlink_compare_arg_init(&arg, sock_net(&nlk->sk), nlk->portid); 3136 return jhash2((u32 *)&arg, netlink_compare_arg_len / sizeof(u32), seed); 3137} 3138 3139static const struct rhashtable_params netlink_rhashtable_params = { 3140 .head_offset = offsetof(struct netlink_sock, node), 3141 .key_len = netlink_compare_arg_len, 3142 .obj_hashfn = netlink_hash, 3143 .obj_cmpfn = netlink_compare, 3144 .max_size = 65536, 3145 .automatic_shrinking = true, 3146}; 3147 |
|
3119static int __init netlink_proto_init(void) 3120{ 3121 int i; 3122 int err = proto_register(&netlink_proto, 0); | 3148static int __init netlink_proto_init(void) 3149{ 3150 int i; 3151 int err = proto_register(&netlink_proto, 0); |
3123 struct rhashtable_params ht_params = { 3124 .head_offset = offsetof(struct netlink_sock, node), 3125 .key_offset = offsetof(struct netlink_sock, portid), 3126 .key_len = sizeof(u32), /* portid */ 3127 .hashfn = jhash, 3128 .max_shift = 16, /* 64K */ 3129 }; | |
3130 3131 if (err != 0) 3132 goto out; 3133 3134 BUILD_BUG_ON(sizeof(struct netlink_skb_parms) > FIELD_SIZEOF(struct sk_buff, cb)); 3135 3136 nl_table = kcalloc(MAX_LINKS, sizeof(*nl_table), GFP_KERNEL); 3137 if (!nl_table) 3138 goto panic; 3139 3140 for (i = 0; i < MAX_LINKS; i++) { | 3152 3153 if (err != 0) 3154 goto out; 3155 3156 BUILD_BUG_ON(sizeof(struct netlink_skb_parms) > FIELD_SIZEOF(struct sk_buff, cb)); 3157 3158 nl_table = kcalloc(MAX_LINKS, sizeof(*nl_table), GFP_KERNEL); 3159 if (!nl_table) 3160 goto panic; 3161 3162 for (i = 0; i < MAX_LINKS; i++) { |
3141 if (rhashtable_init(&nl_table[i].hash, &ht_params) < 0) { | 3163 if (rhashtable_init(&nl_table[i].hash, 3164 &netlink_rhashtable_params) < 0) { |
3142 while (--i > 0) 3143 rhashtable_destroy(&nl_table[i].hash); 3144 kfree(nl_table); 3145 goto panic; 3146 } 3147 } 3148 3149 INIT_LIST_HEAD(&netlink_tap_all); --- 14 unchanged lines hidden --- | 3165 while (--i > 0) 3166 rhashtable_destroy(&nl_table[i].hash); 3167 kfree(nl_table); 3168 goto panic; 3169 } 3170 } 3171 3172 INIT_LIST_HEAD(&netlink_tap_all); --- 14 unchanged lines hidden --- |