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 ---