Blame view

net/netlink/af_netlink.c 64.3 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
  /*
   * NETLINK      Kernel-user communication protocol.
   *
113aa838e   Alan Cox   net: Rationalise ...
4
   * 		Authors:	Alan Cox <alan@lxorguk.ukuu.org.uk>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5
   * 				Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
cd1df525d   Patrick McHardy   netlink: add flow...
6
   * 				Patrick McHardy <kaber@trash.net>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
7
8
9
10
11
   *
   *		This program is free software; you can redistribute it and/or
   *		modify it under the terms of the GNU General Public License
   *		as published by the Free Software Foundation; either version
   *		2 of the License, or (at your option) any later version.
746fac4dc   YOSHIFUJI Hideaki   [NET] NETLINK: Fi...
12
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
13
14
15
16
   * Tue Jun 26 14:36:48 MEST 2001 Herbert "herp" Rosmanith
   *                               added netlink_proto_exit
   * Tue Jan 22 18:32:44 BRST 2002 Arnaldo C. de Melo <acme@conectiva.com.br>
   * 				 use nlk_sk, as sk->protinfo is on a diet 8)
4fdb3bb72   Harald Welte   [NETLINK]: Add pr...
17
18
19
20
21
22
   * Fri Jul 22 19:51:12 MEST 2005 Harald Welte <laforge@gnumonks.org>
   * 				 - inc module use count of module that owns
   * 				   the kernel socket in case userspace opens
   * 				   socket of same protocol
   * 				 - remove all module support, since netlink is
   * 				   mandatory if CONFIG_NET=y these days
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24
  #include <linux/module.h>
4fc268d24   Randy Dunlap   [PATCH] capable/c...
25
  #include <linux/capability.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
27
  #include <linux/kernel.h>
  #include <linux/init.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
29
30
31
32
33
34
35
36
37
38
39
40
  #include <linux/signal.h>
  #include <linux/sched.h>
  #include <linux/errno.h>
  #include <linux/string.h>
  #include <linux/stat.h>
  #include <linux/socket.h>
  #include <linux/un.h>
  #include <linux/fcntl.h>
  #include <linux/termios.h>
  #include <linux/sockios.h>
  #include <linux/net.h>
  #include <linux/fs.h>
  #include <linux/slab.h>
7c0f6ba68   Linus Torvalds   Replace <asm/uacc...
41
  #include <linux/uaccess.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
43
44
45
46
  #include <linux/skbuff.h>
  #include <linux/netdevice.h>
  #include <linux/rtnetlink.h>
  #include <linux/proc_fs.h>
  #include <linux/seq_file.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47
48
49
50
51
52
53
54
  #include <linux/notifier.h>
  #include <linux/security.h>
  #include <linux/jhash.h>
  #include <linux/jiffies.h>
  #include <linux/random.h>
  #include <linux/bitops.h>
  #include <linux/mm.h>
  #include <linux/types.h>
54e0f520e   Andrew Morton   netlink audit war...
55
  #include <linux/audit.h>
af65bdfce   Patrick McHardy   [NETLINK]: Switch...
56
  #include <linux/mutex.h>
ccdfcc398   Patrick McHardy   netlink: mmaped n...
57
  #include <linux/vmalloc.h>
bcbde0d44   Daniel Borkmann   net: netlink: vir...
58
  #include <linux/if_arp.h>
e341694e3   Thomas Graf   netlink: Convert ...
59
  #include <linux/rhashtable.h>
9652e931e   Patrick McHardy   netlink: add mmap...
60
  #include <asm/cacheflush.h>
e341694e3   Thomas Graf   netlink: Convert ...
61
  #include <linux/hash.h>
ee1c24421   Johannes Berg   genetlink: synchr...
62
  #include <linux/genetlink.h>
7212462fa   Nicolas Dichtel   netlink: don't se...
63
  #include <linux/net_namespace.h>
1828cb3d1   Jeremy Cline   netlink: Fix spec...
64
  #include <linux/nospec.h>
54e0f520e   Andrew Morton   netlink audit war...
65

457c4cbc5   Eric W. Biederman   [NET]: Make /proc...
66
  #include <net/net_namespace.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
67
68
  #include <net/sock.h>
  #include <net/scm.h>
82ace47a7   Thomas Graf   [NETLINK]: Generi...
69
  #include <net/netlink.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70

0f29c7686   Andrey Vagin   net: prepare netl...
71
  #include "af_netlink.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72

5c398dc8f   Eric Dumazet   netlink: fix netl...
73
74
75
  struct listeners {
  	struct rcu_head		rcu;
  	unsigned long		masks[0];
6c04bb18d   Johannes Berg   netlink: use call...
76
  };
cd967e057   Patrick McHardy   netlink: add symb...
77
  /* state bits */
cc3a572fe   Nicolas Dichtel   netlink: rename p...
78
  #define NETLINK_S_CONGESTED		0x0
cd967e057   Patrick McHardy   netlink: add symb...
79

035c4c16b   David S. Miller   netlink: Undo con...
80
  static inline int netlink_is_kernel(struct sock *sk)
aed815601   Denis V. Lunev   [NET]: unify netl...
81
  {
cc3a572fe   Nicolas Dichtel   netlink: rename p...
82
  	return nlk_sk(sk)->flags & NETLINK_F_KERNEL_SOCKET;
aed815601   Denis V. Lunev   [NET]: unify netl...
83
  }
91dd93f95   Eric Dumazet   netlink: move nl_...
84
  struct netlink_table *nl_table __read_mostly;
0f29c7686   Andrey Vagin   net: prepare netl...
85
  EXPORT_SYMBOL_GPL(nl_table);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86
87
  
  static DECLARE_WAIT_QUEUE_HEAD(nl_table_wait);
8a0f5ccfb   Herbert Xu   crypto: deadlock ...
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
  static struct lock_class_key nlk_cb_mutex_keys[MAX_LINKS];
  
  static const char *const nlk_cb_mutex_key_strings[MAX_LINKS + 1] = {
  	"nlk_cb_mutex-ROUTE",
  	"nlk_cb_mutex-1",
  	"nlk_cb_mutex-USERSOCK",
  	"nlk_cb_mutex-FIREWALL",
  	"nlk_cb_mutex-SOCK_DIAG",
  	"nlk_cb_mutex-NFLOG",
  	"nlk_cb_mutex-XFRM",
  	"nlk_cb_mutex-SELINUX",
  	"nlk_cb_mutex-ISCSI",
  	"nlk_cb_mutex-AUDIT",
  	"nlk_cb_mutex-FIB_LOOKUP",
  	"nlk_cb_mutex-CONNECTOR",
  	"nlk_cb_mutex-NETFILTER",
  	"nlk_cb_mutex-IP6_FW",
  	"nlk_cb_mutex-DNRTMSG",
  	"nlk_cb_mutex-KOBJECT_UEVENT",
  	"nlk_cb_mutex-GENERIC",
  	"nlk_cb_mutex-17",
  	"nlk_cb_mutex-SCSITRANSPORT",
  	"nlk_cb_mutex-ECRYPTFS",
  	"nlk_cb_mutex-RDMA",
  	"nlk_cb_mutex-CRYPTO",
  	"nlk_cb_mutex-SMC",
  	"nlk_cb_mutex-23",
  	"nlk_cb_mutex-24",
  	"nlk_cb_mutex-25",
  	"nlk_cb_mutex-26",
  	"nlk_cb_mutex-27",
  	"nlk_cb_mutex-28",
  	"nlk_cb_mutex-29",
  	"nlk_cb_mutex-30",
  	"nlk_cb_mutex-31",
  	"nlk_cb_mutex-MAX_LINKS"
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
125
  static int netlink_dump(struct sock *sk);
9652e931e   Patrick McHardy   netlink: add mmap...
126
  static void netlink_skb_destructor(struct sk_buff *skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
127

78fd1d0ab   Thomas Graf   netlink: Re-add l...
128
  /* nl_table locking explained:
21e4902ae   Thomas Graf   netlink: Lockless...
129
   * Lookup and traversal are protected with an RCU read-side lock. Insertion
c5adde946   Ying Xue   netlink: eliminat...
130
   * and removal are protected with per bucket lock while using RCU list
21e4902ae   Thomas Graf   netlink: Lockless...
131
132
133
134
   * modification primitives and may run in parallel to RCU protected lookups.
   * Destruction of the Netlink socket may only occur *after* nl_table_lock has
   * been acquired * either during or after the socket has been removed from
   * the list and after an RCU grace period.
78fd1d0ab   Thomas Graf   netlink: Re-add l...
135
   */
0f29c7686   Andrey Vagin   net: prepare netl...
136
137
  DEFINE_RWLOCK(nl_table_lock);
  EXPORT_SYMBOL_GPL(nl_table_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
138
  static atomic_t nl_table_users = ATOMIC_INIT(0);
6d772ac55   Eric Dumazet   netlink: use kfre...
139
  #define nl_deref_protected(X) rcu_dereference_protected(X, lockdep_is_held(&nl_table_lock));
efa172f42   WANG Cong   netlink: use bloc...
140
  static BLOCKING_NOTIFIER_HEAD(netlink_chain);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
141

bcbde0d44   Daniel Borkmann   net: netlink: vir...
142
143
  static DEFINE_SPINLOCK(netlink_tap_lock);
  static struct list_head netlink_tap_all __read_mostly;
c428ecd1a   Herbert Xu   netlink: Move nam...
144
  static const struct rhashtable_params netlink_rhashtable_params;
b57ef81ff   stephen hemminger   netlink: af_netli...
145
  static inline u32 netlink_group_mask(u32 group)
d629b836d   Patrick McHardy   [NETLINK]: Use gr...
146
147
148
  {
  	return group ? 1 << (group - 1) : 0;
  }
1853c9496   Daniel Borkmann   netlink, mmap: tr...
149
150
151
152
153
154
155
156
157
158
159
160
161
  static struct sk_buff *netlink_to_full_skb(const struct sk_buff *skb,
  					   gfp_t gfp_mask)
  {
  	unsigned int len = skb_end_offset(skb);
  	struct sk_buff *new;
  
  	new = alloc_skb(len, gfp_mask);
  	if (new == NULL)
  		return NULL;
  
  	NETLINK_CB(new).portid = NETLINK_CB(skb).portid;
  	NETLINK_CB(new).dst_group = NETLINK_CB(skb).dst_group;
  	NETLINK_CB(new).creds = NETLINK_CB(skb).creds;
59ae1d127   Johannes Berg   networking: intro...
162
  	skb_put_data(new, skb->data, len);
1853c9496   Daniel Borkmann   netlink, mmap: tr...
163
164
  	return new;
  }
bcbde0d44   Daniel Borkmann   net: netlink: vir...
165
166
167
168
169
170
171
172
  int netlink_add_tap(struct netlink_tap *nt)
  {
  	if (unlikely(nt->dev->type != ARPHRD_NETLINK))
  		return -EINVAL;
  
  	spin_lock(&netlink_tap_lock);
  	list_add_rcu(&nt->list, &netlink_tap_all);
  	spin_unlock(&netlink_tap_lock);
fcd4d35ec   Markus Elfring   netlink: Deletion...
173
  	__module_get(nt->module);
bcbde0d44   Daniel Borkmann   net: netlink: vir...
174
175
176
177
  
  	return 0;
  }
  EXPORT_SYMBOL_GPL(netlink_add_tap);
2173f8d95   stephen hemminger   netlink: cleanup ...
178
  static int __netlink_remove_tap(struct netlink_tap *nt)
bcbde0d44   Daniel Borkmann   net: netlink: vir...
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
  {
  	bool found = false;
  	struct netlink_tap *tmp;
  
  	spin_lock(&netlink_tap_lock);
  
  	list_for_each_entry(tmp, &netlink_tap_all, list) {
  		if (nt == tmp) {
  			list_del_rcu(&nt->list);
  			found = true;
  			goto out;
  		}
  	}
  
  	pr_warn("__netlink_remove_tap: %p not found
  ", nt);
  out:
  	spin_unlock(&netlink_tap_lock);
92b80eb33   Markus Elfring   netlink: Delete a...
197
  	if (found)
bcbde0d44   Daniel Borkmann   net: netlink: vir...
198
199
200
201
  		module_put(nt->module);
  
  	return found ? 0 : -ENODEV;
  }
bcbde0d44   Daniel Borkmann   net: netlink: vir...
202
203
204
205
206
207
208
209
210
211
212
  
  int netlink_remove_tap(struct netlink_tap *nt)
  {
  	int ret;
  
  	ret = __netlink_remove_tap(nt);
  	synchronize_net();
  
  	return ret;
  }
  EXPORT_SYMBOL_GPL(netlink_remove_tap);
5ffd5cddd   Daniel Borkmann   net: netlink: fil...
213
214
215
  static bool netlink_filter_tap(const struct sk_buff *skb)
  {
  	struct sock *sk = skb->sk;
5ffd5cddd   Daniel Borkmann   net: netlink: fil...
216
217
218
219
220
221
222
223
224
225
226
227
228
  
  	/* We take the more conservative approach and
  	 * whitelist socket protocols that may pass.
  	 */
  	switch (sk->sk_protocol) {
  	case NETLINK_ROUTE:
  	case NETLINK_USERSOCK:
  	case NETLINK_SOCK_DIAG:
  	case NETLINK_NFLOG:
  	case NETLINK_XFRM:
  	case NETLINK_FIB_LOOKUP:
  	case NETLINK_NETFILTER:
  	case NETLINK_GENERIC:
498044bb2   Varka Bhadram   netlink: remove b...
229
  		return true;
5ffd5cddd   Daniel Borkmann   net: netlink: fil...
230
  	}
498044bb2   Varka Bhadram   netlink: remove b...
231
  	return false;
5ffd5cddd   Daniel Borkmann   net: netlink: fil...
232
  }
bcbde0d44   Daniel Borkmann   net: netlink: vir...
233
234
235
236
  static int __netlink_deliver_tap_skb(struct sk_buff *skb,
  				     struct net_device *dev)
  {
  	struct sk_buff *nskb;
5ffd5cddd   Daniel Borkmann   net: netlink: fil...
237
  	struct sock *sk = skb->sk;
bcbde0d44   Daniel Borkmann   net: netlink: vir...
238
  	int ret = -ENOMEM;
e3fb538e5   Kevin Cernekee   netlink: Add netn...
239
240
  	if (!net_eq(dev_net(dev), sock_net(sk)))
  		return 0;
bcbde0d44   Daniel Borkmann   net: netlink: vir...
241
  	dev_hold(dev);
1853c9496   Daniel Borkmann   netlink, mmap: tr...
242

d1b4c689d   Florian Westphal   netlink: remove m...
243
  	if (is_vmalloc_addr(skb->head))
1853c9496   Daniel Borkmann   netlink, mmap: tr...
244
245
246
  		nskb = netlink_to_full_skb(skb, GFP_ATOMIC);
  	else
  		nskb = skb_clone(skb, GFP_ATOMIC);
bcbde0d44   Daniel Borkmann   net: netlink: vir...
247
248
  	if (nskb) {
  		nskb->dev = dev;
5ffd5cddd   Daniel Borkmann   net: netlink: fil...
249
  		nskb->protocol = htons((u16) sk->sk_protocol);
604d13c97   Daniel Borkmann   netlink: specify ...
250
251
  		nskb->pkt_type = netlink_is_kernel(sk) ?
  				 PACKET_KERNEL : PACKET_USER;
4e48ed883   Daniel Borkmann   netlink: reset ne...
252
  		skb_reset_network_header(nskb);
bcbde0d44   Daniel Borkmann   net: netlink: vir...
253
254
255
256
257
258
259
260
261
262
263
264
265
  		ret = dev_queue_xmit(nskb);
  		if (unlikely(ret > 0))
  			ret = net_xmit_errno(ret);
  	}
  
  	dev_put(dev);
  	return ret;
  }
  
  static void __netlink_deliver_tap(struct sk_buff *skb)
  {
  	int ret;
  	struct netlink_tap *tmp;
5ffd5cddd   Daniel Borkmann   net: netlink: fil...
266
267
  	if (!netlink_filter_tap(skb))
  		return;
bcbde0d44   Daniel Borkmann   net: netlink: vir...
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
  	list_for_each_entry_rcu(tmp, &netlink_tap_all, list) {
  		ret = __netlink_deliver_tap_skb(skb, tmp->dev);
  		if (unlikely(ret))
  			break;
  	}
  }
  
  static void netlink_deliver_tap(struct sk_buff *skb)
  {
  	rcu_read_lock();
  
  	if (unlikely(!list_empty(&netlink_tap_all)))
  		__netlink_deliver_tap(skb);
  
  	rcu_read_unlock();
  }
73bfd370c   Daniel Borkmann   netlink: only do ...
284
285
286
287
288
289
  static void netlink_deliver_tap_kernel(struct sock *dst, struct sock *src,
  				       struct sk_buff *skb)
  {
  	if (!(netlink_is_kernel(dst) && netlink_is_kernel(src)))
  		netlink_deliver_tap(skb);
  }
cd1df525d   Patrick McHardy   netlink: add flow...
290
291
292
  static void netlink_overrun(struct sock *sk)
  {
  	struct netlink_sock *nlk = nlk_sk(sk);
cc3a572fe   Nicolas Dichtel   netlink: rename p...
293
294
295
  	if (!(nlk->flags & NETLINK_F_RECV_NO_ENOBUFS)) {
  		if (!test_and_set_bit(NETLINK_S_CONGESTED,
  				      &nlk_sk(sk)->state)) {
cd1df525d   Patrick McHardy   netlink: add flow...
296
297
298
299
300
301
302
303
304
305
306
307
  			sk->sk_err = ENOBUFS;
  			sk->sk_error_report(sk);
  		}
  	}
  	atomic_inc(&sk->sk_drops);
  }
  
  static void netlink_rcv_wake(struct sock *sk)
  {
  	struct netlink_sock *nlk = nlk_sk(sk);
  
  	if (skb_queue_empty(&sk->sk_receive_queue))
cc3a572fe   Nicolas Dichtel   netlink: rename p...
308
309
  		clear_bit(NETLINK_S_CONGESTED, &nlk->state);
  	if (!test_bit(NETLINK_S_CONGESTED, &nlk->state))
cd1df525d   Patrick McHardy   netlink: add flow...
310
311
  		wake_up_interruptible(&nlk->wait);
  }
cf0a018ac   Patrick McHardy   netlink: add netl...
312
313
  static void netlink_skb_destructor(struct sk_buff *skb)
  {
c05cdb1b8   Pablo Neira Ayuso   netlink: allow la...
314
  	if (is_vmalloc_addr(skb->head)) {
3a36515f7   Pablo Neira   netlink: fix spla...
315
316
317
  		if (!skb->cloned ||
  		    !atomic_dec_return(&(skb_shinfo(skb)->dataref)))
  			vfree(skb->head);
c05cdb1b8   Pablo Neira Ayuso   netlink: allow la...
318
319
  		skb->head = NULL;
  	}
9652e931e   Patrick McHardy   netlink: add mmap...
320
321
  	if (skb->sk != NULL)
  		sock_rfree(skb);
cf0a018ac   Patrick McHardy   netlink: add netl...
322
323
324
325
326
327
328
329
330
331
  }
  
  static void netlink_skb_set_owner_r(struct sk_buff *skb, struct sock *sk)
  {
  	WARN_ON(skb->sk != NULL);
  	skb->sk = sk;
  	skb->destructor = netlink_skb_destructor;
  	atomic_add(skb->truesize, &sk->sk_rmem_alloc);
  	sk_mem_charge(sk, skb->truesize);
  }
ed5d7788a   Herbert Xu   netlink: Do not s...
332
  static void netlink_sock_destruct(struct sock *sk)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
333
  {
3f660d66d   Herbert Xu   [NETLINK]: Kill C...
334
  	struct netlink_sock *nlk = nlk_sk(sk);
16b304f34   Pravin B Shelar   netlink: Eliminat...
335
  	if (nlk->cb_running) {
ed5d7788a   Herbert Xu   netlink: Do not s...
336
337
  		if (nlk->cb.done)
  			nlk->cb.done(&nlk->cb);
16b304f34   Pravin B Shelar   netlink: Eliminat...
338
339
  		module_put(nlk->cb.module);
  		kfree_skb(nlk->cb.skb);
3f660d66d   Herbert Xu   [NETLINK]: Kill C...
340
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
341
342
343
  	skb_queue_purge(&sk->sk_receive_queue);
  
  	if (!sock_flag(sk, SOCK_DEAD)) {
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
344
345
  		printk(KERN_ERR "Freeing alive netlink socket %p
  ", sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
346
347
  		return;
  	}
547b792ca   Ilpo Järvinen   net: convert BUG_...
348
349
  
  	WARN_ON(atomic_read(&sk->sk_rmem_alloc));
14afee4b6   Reshetova, Elena   net: convert sock...
350
  	WARN_ON(refcount_read(&sk->sk_wmem_alloc));
547b792ca   Ilpo Järvinen   net: convert BUG_...
351
  	WARN_ON(nlk_sk(sk)->groups);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
352
  }
707693c8a   Herbert Xu   netlink: Call cb-...
353
354
355
356
  static void netlink_sock_destruct_work(struct work_struct *work)
  {
  	struct netlink_sock *nlk = container_of(work, struct netlink_sock,
  						work);
ed5d7788a   Herbert Xu   netlink: Do not s...
357
  	sk_free(&nlk->sk);
707693c8a   Herbert Xu   netlink: Call cb-...
358
  }
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
359
360
  /* This lock without WQ_FLAG_EXCLUSIVE is good on UP and it is _very_ bad on
   * SMP. Look, when several writers sleep and reader wakes them up, all but one
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
361
362
363
   * immediately hit write lock and grab all the cpus. Exclusive sleep solves
   * this, _but_ remember, it adds useless work on UP machines.
   */
d136f1bd3   Johannes Berg   genetlink: fix ne...
364
  void netlink_table_grab(void)
9a429c498   Eric Dumazet   [NET]: Add some a...
365
  	__acquires(nl_table_lock)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
366
  {
d136f1bd3   Johannes Berg   genetlink: fix ne...
367
  	might_sleep();
6abd219c6   Arjan van de Ven   [PATCH] bcm43xx: ...
368
  	write_lock_irq(&nl_table_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
369
370
371
372
373
  
  	if (atomic_read(&nl_table_users)) {
  		DECLARE_WAITQUEUE(wait, current);
  
  		add_wait_queue_exclusive(&nl_table_wait, &wait);
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
374
  		for (;;) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
375
376
377
  			set_current_state(TASK_UNINTERRUPTIBLE);
  			if (atomic_read(&nl_table_users) == 0)
  				break;
6abd219c6   Arjan van de Ven   [PATCH] bcm43xx: ...
378
  			write_unlock_irq(&nl_table_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
379
  			schedule();
6abd219c6   Arjan van de Ven   [PATCH] bcm43xx: ...
380
  			write_lock_irq(&nl_table_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
381
382
383
384
385
386
  		}
  
  		__set_current_state(TASK_RUNNING);
  		remove_wait_queue(&nl_table_wait, &wait);
  	}
  }
d136f1bd3   Johannes Berg   genetlink: fix ne...
387
  void netlink_table_ungrab(void)
9a429c498   Eric Dumazet   [NET]: Add some a...
388
  	__releases(nl_table_lock)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
389
  {
6abd219c6   Arjan van de Ven   [PATCH] bcm43xx: ...
390
  	write_unlock_irq(&nl_table_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
391
392
  	wake_up(&nl_table_wait);
  }
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
393
  static inline void
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
394
395
396
397
398
399
400
401
  netlink_lock_table(void)
  {
  	/* read_lock() synchronizes us to netlink_table_grab */
  
  	read_lock(&nl_table_lock);
  	atomic_inc(&nl_table_users);
  	read_unlock(&nl_table_lock);
  }
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
402
  static inline void
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
403
404
405
406
407
  netlink_unlock_table(void)
  {
  	if (atomic_dec_and_test(&nl_table_users))
  		wake_up(&nl_table_wait);
  }
e341694e3   Thomas Graf   netlink: Convert ...
408
  struct netlink_compare_arg
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
409
  {
c428ecd1a   Herbert Xu   netlink: Move nam...
410
  	possible_net_t pnet;
e341694e3   Thomas Graf   netlink: Convert ...
411
412
  	u32 portid;
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
413

8f2ddaac3   Herbert Xu   netlink: Remove n...
414
415
416
  /* Doing sizeof directly may yield 4 extra bytes on 64-bit. */
  #define netlink_compare_arg_len \
  	(offsetof(struct netlink_compare_arg, portid) + sizeof(u32))
c428ecd1a   Herbert Xu   netlink: Move nam...
417
418
419
  
  static inline int netlink_compare(struct rhashtable_compare_arg *arg,
  				  const void *ptr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
420
  {
c428ecd1a   Herbert Xu   netlink: Move nam...
421
422
  	const struct netlink_compare_arg *x = arg->key;
  	const struct netlink_sock *nlk = ptr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
423

da314c992   Herbert Xu   netlink: Replace ...
424
  	return nlk->portid != x->portid ||
c428ecd1a   Herbert Xu   netlink: Move nam...
425
426
427
428
429
430
431
432
433
  	       !net_eq(sock_net(&nlk->sk), read_pnet(&x->pnet));
  }
  
  static void netlink_compare_arg_init(struct netlink_compare_arg *arg,
  				     struct net *net, u32 portid)
  {
  	memset(arg, 0, sizeof(*arg));
  	write_pnet(&arg->pnet, net);
  	arg->portid = portid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
434
  }
e341694e3   Thomas Graf   netlink: Convert ...
435
436
  static struct sock *__netlink_lookup(struct netlink_table *table, u32 portid,
  				     struct net *net)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
437
  {
c428ecd1a   Herbert Xu   netlink: Move nam...
438
  	struct netlink_compare_arg arg;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
439

c428ecd1a   Herbert Xu   netlink: Move nam...
440
441
442
  	netlink_compare_arg_init(&arg, net, portid);
  	return rhashtable_lookup_fast(&table->hash, &arg,
  				      netlink_rhashtable_params);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
443
  }
c428ecd1a   Herbert Xu   netlink: Move nam...
444
  static int __netlink_insert(struct netlink_table *table, struct sock *sk)
c5adde946   Ying Xue   netlink: eliminat...
445
  {
c428ecd1a   Herbert Xu   netlink: Move nam...
446
  	struct netlink_compare_arg arg;
c5adde946   Ying Xue   netlink: eliminat...
447

da314c992   Herbert Xu   netlink: Replace ...
448
  	netlink_compare_arg_init(&arg, sock_net(sk), nlk_sk(sk)->portid);
c428ecd1a   Herbert Xu   netlink: Move nam...
449
450
451
  	return rhashtable_lookup_insert_key(&table->hash, &arg,
  					    &nlk_sk(sk)->node,
  					    netlink_rhashtable_params);
c5adde946   Ying Xue   netlink: eliminat...
452
  }
e341694e3   Thomas Graf   netlink: Convert ...
453
  static struct sock *netlink_lookup(struct net *net, int protocol, u32 portid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
454
  {
e341694e3   Thomas Graf   netlink: Convert ...
455
456
  	struct netlink_table *table = &nl_table[protocol];
  	struct sock *sk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
457

e341694e3   Thomas Graf   netlink: Convert ...
458
459
460
461
462
  	rcu_read_lock();
  	sk = __netlink_lookup(table, portid, net);
  	if (sk)
  		sock_hold(sk);
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
463

e341694e3   Thomas Graf   netlink: Convert ...
464
  	return sk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
465
  }
90ddc4f04   Eric Dumazet   [NET]: move struc...
466
  static const struct proto_ops netlink_ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
467

4277a083e   Patrick McHardy   [NETLINK]: Add ne...
468
469
470
471
  static void
  netlink_update_listeners(struct sock *sk)
  {
  	struct netlink_table *tbl = &nl_table[sk->sk_protocol];
4277a083e   Patrick McHardy   [NETLINK]: Add ne...
472
473
  	unsigned long mask;
  	unsigned int i;
6d772ac55   Eric Dumazet   netlink: use kfre...
474
475
476
477
478
  	struct listeners *listeners;
  
  	listeners = nl_deref_protected(tbl->listeners);
  	if (!listeners)
  		return;
4277a083e   Patrick McHardy   [NETLINK]: Add ne...
479

b4ff4f041   Johannes Berg   [NETLINK]: alloca...
480
  	for (i = 0; i < NLGRPLONGS(tbl->groups); i++) {
4277a083e   Patrick McHardy   [NETLINK]: Add ne...
481
  		mask = 0;
b67bfe0d4   Sasha Levin   hlist: drop the n...
482
  		sk_for_each_bound(sk, &tbl->mc_list) {
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
483
484
485
  			if (i < NLGRPLONGS(nlk_sk(sk)->ngroups))
  				mask |= nlk_sk(sk)->groups[i];
  		}
6d772ac55   Eric Dumazet   netlink: use kfre...
486
  		listeners->masks[i] = mask;
4277a083e   Patrick McHardy   [NETLINK]: Add ne...
487
488
489
490
  	}
  	/* this function is only called with the netlink table "grabbed", which
  	 * makes sure updates are visible before bind or setsockopt return. */
  }
8ea65f4a2   Herbert Xu   netlink: Kill red...
491
  static int netlink_insert(struct sock *sk, u32 portid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
492
  {
da12c90e0   Gao feng   netlink: Add comp...
493
  	struct netlink_table *table = &nl_table[sk->sk_protocol];
919d9db95   Herbert Xu   netlink: Fix netl...
494
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
495

c5adde946   Ying Xue   netlink: eliminat...
496
  	lock_sock(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
497

da314c992   Herbert Xu   netlink: Replace ...
498
499
  	err = nlk_sk(sk)->portid == portid ? 0 : -EBUSY;
  	if (nlk_sk(sk)->bound)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
500
501
502
  		goto err;
  
  	err = -ENOMEM;
97defe1ec   Thomas Graf   rhashtable: Per b...
503
504
  	if (BITS_PER_LONG > 32 &&
  	    unlikely(atomic_read(&table->hash.nelems) >= UINT_MAX))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
505
  		goto err;
da314c992   Herbert Xu   netlink: Replace ...
506
  	nlk_sk(sk)->portid = portid;
e341694e3   Thomas Graf   netlink: Convert ...
507
  	sock_hold(sk);
919d9db95   Herbert Xu   netlink: Fix netl...
508

c428ecd1a   Herbert Xu   netlink: Move nam...
509
510
  	err = __netlink_insert(table, sk);
  	if (err) {
4e7c13306   Daniel Borkmann   netlink: make sur...
511
512
513
514
515
  		/* In case the hashtable backend returns with -EBUSY
  		 * from here, it must not escape to the caller.
  		 */
  		if (unlikely(err == -EBUSY))
  			err = -EOVERFLOW;
c428ecd1a   Herbert Xu   netlink: Move nam...
516
517
  		if (err == -EEXIST)
  			err = -EADDRINUSE;
c5adde946   Ying Xue   netlink: eliminat...
518
  		sock_put(sk);
1f770c0a0   Herbert Xu   netlink: Fix auto...
519
  		goto err;
919d9db95   Herbert Xu   netlink: Fix netl...
520
  	}
da314c992   Herbert Xu   netlink: Replace ...
521
522
523
  	/* We need to ensure that the socket is hashed and visible. */
  	smp_wmb();
  	nlk_sk(sk)->bound = portid;
1f770c0a0   Herbert Xu   netlink: Fix auto...
524

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
525
  err:
c5adde946   Ying Xue   netlink: eliminat...
526
  	release_sock(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
527
528
529
530
531
  	return err;
  }
  
  static void netlink_remove(struct sock *sk)
  {
e341694e3   Thomas Graf   netlink: Convert ...
532
  	struct netlink_table *table;
e341694e3   Thomas Graf   netlink: Convert ...
533
  	table = &nl_table[sk->sk_protocol];
c428ecd1a   Herbert Xu   netlink: Move nam...
534
535
  	if (!rhashtable_remove_fast(&table->hash, &nlk_sk(sk)->node,
  				    netlink_rhashtable_params)) {
41c6d650f   Reshetova, Elena   net: convert sock...
536
  		WARN_ON(refcount_read(&sk->sk_refcnt) == 1);
e341694e3   Thomas Graf   netlink: Convert ...
537
538
  		__sock_put(sk);
  	}
e341694e3   Thomas Graf   netlink: Convert ...
539

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
540
  	netlink_table_grab();
b10dcb3b9   Johannes Berg   netlink: update l...
541
  	if (nlk_sk(sk)->subscriptions) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
542
  		__sk_del_bind_node(sk);
b10dcb3b9   Johannes Berg   netlink: update l...
543
544
  		netlink_update_listeners(sk);
  	}
ee1c24421   Johannes Berg   genetlink: synchr...
545
546
  	if (sk->sk_protocol == NETLINK_GENERIC)
  		atomic_inc(&genl_sk_destructing_cnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
547
548
549
550
551
552
553
554
  	netlink_table_ungrab();
  }
  
  static struct proto netlink_proto = {
  	.name	  = "NETLINK",
  	.owner	  = THIS_MODULE,
  	.obj_size = sizeof(struct netlink_sock),
  };
1b8d7ae42   Eric W. Biederman   [NET]: Make socke...
555
  static int __netlink_create(struct net *net, struct socket *sock,
11aa9c28b   Eric W. Biederman   net: Pass kern fr...
556
557
  			    struct mutex *cb_mutex, int protocol,
  			    int kern)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
558
559
560
  {
  	struct sock *sk;
  	struct netlink_sock *nlk;
ab33a1711   Patrick McHardy   [NETLINK]: Return...
561
562
  
  	sock->ops = &netlink_ops;
11aa9c28b   Eric W. Biederman   net: Pass kern fr...
563
  	sk = sk_alloc(net, PF_NETLINK, GFP_KERNEL, &netlink_proto, kern);
ab33a1711   Patrick McHardy   [NETLINK]: Return...
564
565
566
567
568
569
  	if (!sk)
  		return -ENOMEM;
  
  	sock_init_data(sock, sk);
  
  	nlk = nlk_sk(sk);
658cb354e   Eric Dumazet   af_netlink: cleanups
570
  	if (cb_mutex) {
ffa4d7216   Patrick McHardy   [NETLINK]: don't ...
571
  		nlk->cb_mutex = cb_mutex;
658cb354e   Eric Dumazet   af_netlink: cleanups
572
  	} else {
ffa4d7216   Patrick McHardy   [NETLINK]: don't ...
573
574
  		nlk->cb_mutex = &nlk->cb_def_mutex;
  		mutex_init(nlk->cb_mutex);
8a0f5ccfb   Herbert Xu   crypto: deadlock ...
575
576
577
  		lockdep_set_class_and_name(nlk->cb_mutex,
  					   nlk_cb_mutex_keys + protocol,
  					   nlk_cb_mutex_key_strings[protocol]);
ffa4d7216   Patrick McHardy   [NETLINK]: don't ...
578
  	}
ab33a1711   Patrick McHardy   [NETLINK]: Return...
579
580
581
582
583
584
  	init_waitqueue_head(&nlk->wait);
  
  	sk->sk_destruct = netlink_sock_destruct;
  	sk->sk_protocol = protocol;
  	return 0;
  }
3f378b684   Eric Paris   net: pass kern to...
585
586
  static int netlink_create(struct net *net, struct socket *sock, int protocol,
  			  int kern)
ab33a1711   Patrick McHardy   [NETLINK]: Return...
587
588
  {
  	struct module *module = NULL;
af65bdfce   Patrick McHardy   [NETLINK]: Switch...
589
  	struct mutex *cb_mutex;
f7fa9b10e   Patrick McHardy   [NETLINK]: Suppor...
590
  	struct netlink_sock *nlk;
023e2cfa3   Johannes Berg   netlink/genetlink...
591
592
  	int (*bind)(struct net *net, int group);
  	void (*unbind)(struct net *net, int group);
ab33a1711   Patrick McHardy   [NETLINK]: Return...
593
  	int err = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
594
595
596
597
598
  
  	sock->state = SS_UNCONNECTED;
  
  	if (sock->type != SOCK_RAW && sock->type != SOCK_DGRAM)
  		return -ESOCKTNOSUPPORT;
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
599
  	if (protocol < 0 || protocol >= MAX_LINKS)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
600
  		return -EPROTONOSUPPORT;
1828cb3d1   Jeremy Cline   netlink: Fix spec...
601
  	protocol = array_index_nospec(protocol, MAX_LINKS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
602

77247bbb3   Patrick McHardy   [NETLINK]: Fix mo...
603
  	netlink_lock_table();
95a5afca4   Johannes Berg   net: Remove CONFI...
604
  #ifdef CONFIG_MODULES
ab33a1711   Patrick McHardy   [NETLINK]: Return...
605
  	if (!nl_table[protocol].registered) {
77247bbb3   Patrick McHardy   [NETLINK]: Fix mo...
606
  		netlink_unlock_table();
4fdb3bb72   Harald Welte   [NETLINK]: Add pr...
607
  		request_module("net-pf-%d-proto-%d", PF_NETLINK, protocol);
77247bbb3   Patrick McHardy   [NETLINK]: Fix mo...
608
  		netlink_lock_table();
4fdb3bb72   Harald Welte   [NETLINK]: Add pr...
609
  	}
ab33a1711   Patrick McHardy   [NETLINK]: Return...
610
611
612
613
  #endif
  	if (nl_table[protocol].registered &&
  	    try_module_get(nl_table[protocol].module))
  		module = nl_table[protocol].module;
974c37e9d   Alexey Dobriyan   netlink: fix for ...
614
615
  	else
  		err = -EPROTONOSUPPORT;
af65bdfce   Patrick McHardy   [NETLINK]: Switch...
616
  	cb_mutex = nl_table[protocol].cb_mutex;
03292745b   Pablo Neira Ayuso   netlink: add nlk-...
617
  	bind = nl_table[protocol].bind;
4f5209005   Richard Guy Briggs   netlink: have net...
618
  	unbind = nl_table[protocol].unbind;
77247bbb3   Patrick McHardy   [NETLINK]: Fix mo...
619
  	netlink_unlock_table();
4fdb3bb72   Harald Welte   [NETLINK]: Add pr...
620

974c37e9d   Alexey Dobriyan   netlink: fix for ...
621
622
  	if (err < 0)
  		goto out;
11aa9c28b   Eric W. Biederman   net: Pass kern fr...
623
  	err = __netlink_create(net, sock, cb_mutex, protocol, kern);
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
624
  	if (err < 0)
f7fa9b10e   Patrick McHardy   [NETLINK]: Suppor...
625
  		goto out_module;
6f756a8c3   David S. Miller   net: Make sure BH...
626
  	local_bh_disable();
c1fd3b945   Eric Dumazet   net: af_netlink s...
627
  	sock_prot_inuse_add(net, &netlink_proto, 1);
6f756a8c3   David S. Miller   net: Make sure BH...
628
  	local_bh_enable();
f7fa9b10e   Patrick McHardy   [NETLINK]: Suppor...
629
  	nlk = nlk_sk(sock->sk);
f7fa9b10e   Patrick McHardy   [NETLINK]: Suppor...
630
  	nlk->module = module;
03292745b   Pablo Neira Ayuso   netlink: add nlk-...
631
  	nlk->netlink_bind = bind;
4f5209005   Richard Guy Briggs   netlink: have net...
632
  	nlk->netlink_unbind = unbind;
ab33a1711   Patrick McHardy   [NETLINK]: Return...
633
634
  out:
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
635

ab33a1711   Patrick McHardy   [NETLINK]: Return...
636
637
638
  out_module:
  	module_put(module);
  	goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
639
  }
21e4902ae   Thomas Graf   netlink: Lockless...
640
641
642
  static void deferred_put_nlk_sk(struct rcu_head *head)
  {
  	struct netlink_sock *nlk = container_of(head, struct netlink_sock, rcu);
ed5d7788a   Herbert Xu   netlink: Do not s...
643
  	struct sock *sk = &nlk->sk;
be82485fb   Xin Long   netlink: fix an u...
644
645
  	kfree(nlk->groups);
  	nlk->groups = NULL;
41c6d650f   Reshetova, Elena   net: convert sock...
646
  	if (!refcount_dec_and_test(&sk->sk_refcnt))
ed5d7788a   Herbert Xu   netlink: Do not s...
647
648
649
650
651
652
653
  		return;
  
  	if (nlk->cb_running && nlk->cb.done) {
  		INIT_WORK(&nlk->work, netlink_sock_destruct_work);
  		schedule_work(&nlk->work);
  		return;
  	}
21e4902ae   Thomas Graf   netlink: Lockless...
654

ed5d7788a   Herbert Xu   netlink: Do not s...
655
  	sk_free(sk);
21e4902ae   Thomas Graf   netlink: Lockless...
656
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
657
658
659
660
661
662
663
664
665
  static int netlink_release(struct socket *sock)
  {
  	struct sock *sk = sock->sk;
  	struct netlink_sock *nlk;
  
  	if (!sk)
  		return 0;
  
  	netlink_remove(sk);
ac57b3a9c   Denis Lunev   [NETLINK]: Don't ...
666
  	sock_orphan(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
667
  	nlk = nlk_sk(sk);
3f660d66d   Herbert Xu   [NETLINK]: Kill C...
668
669
670
671
  	/*
  	 * OK. Socket is unlinked, any packets that arrive now
  	 * will be purged.
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
672

ee1c24421   Johannes Berg   genetlink: synchr...
673
674
675
676
677
678
679
680
681
682
683
684
685
  	/* must not acquire netlink_table_lock in any way again before unbind
  	 * and notifying genetlink is done as otherwise it might deadlock
  	 */
  	if (nlk->netlink_unbind) {
  		int i;
  
  		for (i = 0; i < nlk->ngroups; i++)
  			if (test_bit(i, nlk->groups))
  				nlk->netlink_unbind(sock_net(sk), i + 1);
  	}
  	if (sk->sk_protocol == NETLINK_GENERIC &&
  	    atomic_dec_return(&genl_sk_destructing_cnt) == 0)
  		wake_up(&genl_sk_destructing_waitq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
686
687
688
689
  	sock->sk = NULL;
  	wake_up_interruptible_all(&nlk->wait);
  
  	skb_queue_purge(&sk->sk_write_queue);
e27260203   Dmitry Ivanov   netlink: don't se...
690
  	if (nlk->portid && nlk->bound) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
691
  		struct netlink_notify n = {
3b1e0a655   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
692
  						.net = sock_net(sk),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
693
  						.protocol = sk->sk_protocol,
15e473046   Eric W. Biederman   netlink: Rename p...
694
  						.portid = nlk->portid,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
695
  					  };
efa172f42   WANG Cong   netlink: use bloc...
696
  		blocking_notifier_call_chain(&netlink_chain,
e041c6834   Alan Stern   [PATCH] Notifier ...
697
  				NETLINK_URELEASE, &n);
746fac4dc   YOSHIFUJI Hideaki   [NET] NETLINK: Fi...
698
  	}
4fdb3bb72   Harald Welte   [NETLINK]: Add pr...
699

5e7c001c6   Mariusz Kozlowski   [AF_NETLINK]: mod...
700
  	module_put(nlk->module);
4fdb3bb72   Harald Welte   [NETLINK]: Add pr...
701

aed815601   Denis V. Lunev   [NET]: unify netl...
702
  	if (netlink_is_kernel(sk)) {
b10dcb3b9   Johannes Berg   netlink: update l...
703
  		netlink_table_grab();
869e58f87   Denis V. Lunev   [NETNS]: Double f...
704
705
  		BUG_ON(nl_table[sk->sk_protocol].registered == 0);
  		if (--nl_table[sk->sk_protocol].registered == 0) {
6d772ac55   Eric Dumazet   netlink: use kfre...
706
707
708
709
710
  			struct listeners *old;
  
  			old = nl_deref_protected(nl_table[sk->sk_protocol].listeners);
  			RCU_INIT_POINTER(nl_table[sk->sk_protocol].listeners, NULL);
  			kfree_rcu(old, rcu);
869e58f87   Denis V. Lunev   [NETNS]: Double f...
711
  			nl_table[sk->sk_protocol].module = NULL;
9785e10ae   Pablo Neira Ayuso   netlink: kill net...
712
  			nl_table[sk->sk_protocol].bind = NULL;
4f5209005   Richard Guy Briggs   netlink: have net...
713
  			nl_table[sk->sk_protocol].unbind = NULL;
9785e10ae   Pablo Neira Ayuso   netlink: kill net...
714
  			nl_table[sk->sk_protocol].flags = 0;
869e58f87   Denis V. Lunev   [NETNS]: Double f...
715
716
  			nl_table[sk->sk_protocol].registered = 0;
  		}
b10dcb3b9   Johannes Berg   netlink: update l...
717
  		netlink_table_ungrab();
658cb354e   Eric Dumazet   af_netlink: cleanups
718
  	}
77247bbb3   Patrick McHardy   [NETLINK]: Fix mo...
719

3755810ce   Eric Dumazet   net: Make sure BH...
720
  	local_bh_disable();
c1fd3b945   Eric Dumazet   net: af_netlink s...
721
  	sock_prot_inuse_add(sock_net(sk), &netlink_proto, -1);
3755810ce   Eric Dumazet   net: Make sure BH...
722
  	local_bh_enable();
21e4902ae   Thomas Graf   netlink: Lockless...
723
  	call_rcu(&nlk->rcu, deferred_put_nlk_sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
724
725
726
727
728
729
  	return 0;
  }
  
  static int netlink_autobind(struct socket *sock)
  {
  	struct sock *sk = sock->sk;
3b1e0a655   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
730
  	struct net *net = sock_net(sk);
da12c90e0   Gao feng   netlink: Add comp...
731
  	struct netlink_table *table = &nl_table[sk->sk_protocol];
15e473046   Eric W. Biederman   netlink: Rename p...
732
  	s32 portid = task_tgid_vnr(current);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
733
  	int err;
b9fbe709d   Herbert Xu   netlink: Use rand...
734
735
  	s32 rover = -4096;
  	bool ok;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
736
737
738
  
  retry:
  	cond_resched();
e341694e3   Thomas Graf   netlink: Convert ...
739
  	rcu_read_lock();
b9fbe709d   Herbert Xu   netlink: Use rand...
740
741
742
  	ok = !__netlink_lookup(table, portid, net);
  	rcu_read_unlock();
  	if (!ok) {
e341694e3   Thomas Graf   netlink: Convert ...
743
  		/* Bind collision, search negative portid values. */
b9fbe709d   Herbert Xu   netlink: Use rand...
744
745
746
747
  		if (rover == -4096)
  			/* rover will be in range [S32_MIN, -4097] */
  			rover = S32_MIN + prandom_u32_max(-4096 - S32_MIN);
  		else if (rover >= -4096)
e341694e3   Thomas Graf   netlink: Convert ...
748
  			rover = -4097;
b9fbe709d   Herbert Xu   netlink: Use rand...
749
  		portid = rover--;
e341694e3   Thomas Graf   netlink: Convert ...
750
  		goto retry;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
751
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
752

8ea65f4a2   Herbert Xu   netlink: Kill red...
753
  	err = netlink_insert(sk, portid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
754
755
  	if (err == -EADDRINUSE)
  		goto retry;
d470e3b48   David S. Miller   [NETLINK]: Fix tw...
756
757
758
759
760
761
  
  	/* If 2 threads race to autobind, that is fine.  */
  	if (err == -EBUSY)
  		err = 0;
  
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
762
  }
aa4cf9452   Eric W. Biederman   net: Add variants...
763
764
765
766
767
768
769
770
771
772
773
774
775
  /**
   * __netlink_ns_capable - General netlink message capability test
   * @nsp: NETLINK_CB of the socket buffer holding a netlink command from userspace.
   * @user_ns: The user namespace of the capability to use
   * @cap: The capability to use
   *
   * Test to see if the opener of the socket we received the message
   * from had when the netlink socket was created and the sender of the
   * message has has the capability @cap in the user namespace @user_ns.
   */
  bool __netlink_ns_capable(const struct netlink_skb_parms *nsp,
  			struct user_namespace *user_ns, int cap)
  {
2d7a85f4b   Eric W. Biederman   netlink: Only che...
776
777
778
  	return ((nsp->flags & NETLINK_SKB_DST) ||
  		file_ns_capable(nsp->sk->sk_socket->file, user_ns, cap)) &&
  		ns_capable(user_ns, cap);
aa4cf9452   Eric W. Biederman   net: Add variants...
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
  }
  EXPORT_SYMBOL(__netlink_ns_capable);
  
  /**
   * netlink_ns_capable - General netlink message capability test
   * @skb: socket buffer holding a netlink command from userspace
   * @user_ns: The user namespace of the capability to use
   * @cap: The capability to use
   *
   * Test to see if the opener of the socket we received the message
   * from had when the netlink socket was created and the sender of the
   * message has has the capability @cap in the user namespace @user_ns.
   */
  bool netlink_ns_capable(const struct sk_buff *skb,
  			struct user_namespace *user_ns, int cap)
  {
  	return __netlink_ns_capable(&NETLINK_CB(skb), user_ns, cap);
  }
  EXPORT_SYMBOL(netlink_ns_capable);
  
  /**
   * netlink_capable - Netlink global message capability test
   * @skb: socket buffer holding a netlink command from userspace
   * @cap: The capability to use
   *
   * Test to see if the opener of the socket we received the message
   * from had when the netlink socket was created and the sender of the
   * message has has the capability @cap in all user namespaces.
   */
  bool netlink_capable(const struct sk_buff *skb, int cap)
  {
  	return netlink_ns_capable(skb, &init_user_ns, cap);
  }
  EXPORT_SYMBOL(netlink_capable);
  
  /**
   * netlink_net_capable - Netlink network namespace message capability test
   * @skb: socket buffer holding a netlink command from userspace
   * @cap: The capability to use
   *
   * Test to see if the opener of the socket we received the message
   * from had when the netlink socket was created and the sender of the
   * message has has the capability @cap over the network namespace of
   * the socket we received the message from.
   */
  bool netlink_net_capable(const struct sk_buff *skb, int cap)
  {
  	return netlink_ns_capable(skb, sock_net(skb->sk)->user_ns, cap);
  }
  EXPORT_SYMBOL(netlink_net_capable);
5187cd055   Eric W. Biederman   netlink: Rename n...
829
  static inline int netlink_allowed(const struct socket *sock, unsigned int flag)
746fac4dc   YOSHIFUJI Hideaki   [NET] NETLINK: Fi...
830
  {
9785e10ae   Pablo Neira Ayuso   netlink: kill net...
831
  	return (nl_table[sock->sk->sk_protocol].flags & flag) ||
df008c91f   Eric W. Biederman   net: Allow userns...
832
  		ns_capable(sock_net(sock->sk)->user_ns, CAP_NET_ADMIN);
746fac4dc   YOSHIFUJI Hideaki   [NET] NETLINK: Fi...
833
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
834

f7fa9b10e   Patrick McHardy   [NETLINK]: Suppor...
835
836
837
838
839
840
841
842
843
844
845
  static void
  netlink_update_subscriptions(struct sock *sk, unsigned int subscriptions)
  {
  	struct netlink_sock *nlk = nlk_sk(sk);
  
  	if (nlk->subscriptions && !subscriptions)
  		__sk_del_bind_node(sk);
  	else if (!nlk->subscriptions && subscriptions)
  		sk_add_bind_node(sk, &nl_table[sk->sk_protocol].mc_list);
  	nlk->subscriptions = subscriptions;
  }
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
846
  static int netlink_realloc_groups(struct sock *sk)
513c25000   Patrick McHardy   [NETLINK]: Don't ...
847
848
849
  {
  	struct netlink_sock *nlk = nlk_sk(sk);
  	unsigned int groups;
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
850
  	unsigned long *new_groups;
513c25000   Patrick McHardy   [NETLINK]: Don't ...
851
  	int err = 0;
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
852
  	netlink_table_grab();
513c25000   Patrick McHardy   [NETLINK]: Don't ...
853
  	groups = nl_table[sk->sk_protocol].groups;
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
854
  	if (!nl_table[sk->sk_protocol].registered) {
513c25000   Patrick McHardy   [NETLINK]: Don't ...
855
  		err = -ENOENT;
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
856
857
  		goto out_unlock;
  	}
513c25000   Patrick McHardy   [NETLINK]: Don't ...
858

b4ff4f041   Johannes Berg   [NETLINK]: alloca...
859
860
  	if (nlk->ngroups >= groups)
  		goto out_unlock;
513c25000   Patrick McHardy   [NETLINK]: Don't ...
861

b4ff4f041   Johannes Berg   [NETLINK]: alloca...
862
863
864
865
866
  	new_groups = krealloc(nlk->groups, NLGRPSZ(groups), GFP_ATOMIC);
  	if (new_groups == NULL) {
  		err = -ENOMEM;
  		goto out_unlock;
  	}
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
867
  	memset((char *)new_groups + NLGRPSZ(nlk->ngroups), 0,
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
868
869
870
  	       NLGRPSZ(groups) - NLGRPSZ(nlk->ngroups));
  
  	nlk->groups = new_groups;
513c25000   Patrick McHardy   [NETLINK]: Don't ...
871
  	nlk->ngroups = groups;
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
872
873
874
   out_unlock:
  	netlink_table_ungrab();
  	return err;
513c25000   Patrick McHardy   [NETLINK]: Don't ...
875
  }
02c81ab95   Johannes Berg   netlink: rename n...
876
  static void netlink_undo_bind(int group, long unsigned int groups,
023e2cfa3   Johannes Berg   netlink/genetlink...
877
  			      struct sock *sk)
4f5209005   Richard Guy Briggs   netlink: have net...
878
  {
023e2cfa3   Johannes Berg   netlink/genetlink...
879
  	struct netlink_sock *nlk = nlk_sk(sk);
4f5209005   Richard Guy Briggs   netlink: have net...
880
881
882
883
884
885
  	int undo;
  
  	if (!nlk->netlink_unbind)
  		return;
  
  	for (undo = 0; undo < group; undo++)
6251edd93   Hiroaki SHIMODA   netlink: Properly...
886
  		if (test_bit(undo, &groups))
8b7c36d81   Pablo Neira   netlink: fix wron...
887
  			nlk->netlink_unbind(sock_net(sk), undo + 1);
4f5209005   Richard Guy Briggs   netlink: have net...
888
  }
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
889
890
  static int netlink_bind(struct socket *sock, struct sockaddr *addr,
  			int addr_len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
891
892
  {
  	struct sock *sk = sock->sk;
3b1e0a655   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
893
  	struct net *net = sock_net(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
894
895
  	struct netlink_sock *nlk = nlk_sk(sk);
  	struct sockaddr_nl *nladdr = (struct sockaddr_nl *)addr;
f77360802   Xin Long   netlink: access n...
896
  	int err = 0;
4f5209005   Richard Guy Briggs   netlink: have net...
897
  	long unsigned int groups = nladdr->nl_groups;
da314c992   Herbert Xu   netlink: Replace ...
898
  	bool bound;
746fac4dc   YOSHIFUJI Hideaki   [NET] NETLINK: Fi...
899

4e4b53768   Hannes Frederic Sowa   netlink: validate...
900
901
  	if (addr_len < sizeof(struct sockaddr_nl))
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
902
903
904
905
  	if (nladdr->nl_family != AF_NETLINK)
  		return -EINVAL;
  
  	/* Only superuser is allowed to listen multicasts */
4f5209005   Richard Guy Briggs   netlink: have net...
906
  	if (groups) {
5187cd055   Eric W. Biederman   netlink: Rename n...
907
  		if (!netlink_allowed(sock, NL_CFG_F_NONROOT_RECV))
513c25000   Patrick McHardy   [NETLINK]: Don't ...
908
  			return -EPERM;
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
909
910
911
  		err = netlink_realloc_groups(sk);
  		if (err)
  			return err;
513c25000   Patrick McHardy   [NETLINK]: Don't ...
912
  	}
fffd3058e   Dmitry Safonov   netlink: Don't sh...
913
914
915
  
  	if (nlk->ngroups == 0)
  		groups = 0;
09901e570   Dmitry Safonov   netlink: Don't sh...
916
917
  	else if (nlk->ngroups < 8*sizeof(groups))
  		groups &= (1UL << nlk->ngroups) - 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
918

da314c992   Herbert Xu   netlink: Replace ...
919
920
921
922
  	bound = nlk->bound;
  	if (bound) {
  		/* Ensure nlk->portid is up-to-date. */
  		smp_rmb();
15e473046   Eric W. Biederman   netlink: Rename p...
923
  		if (nladdr->nl_pid != nlk->portid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
924
  			return -EINVAL;
da314c992   Herbert Xu   netlink: Replace ...
925
  	}
4f5209005   Richard Guy Briggs   netlink: have net...
926

f77360802   Xin Long   netlink: access n...
927
  	netlink_lock_table();
4f5209005   Richard Guy Briggs   netlink: have net...
928
929
930
931
932
933
  	if (nlk->netlink_bind && groups) {
  		int group;
  
  		for (group = 0; group < nlk->ngroups; group++) {
  			if (!test_bit(group, &groups))
  				continue;
8b7c36d81   Pablo Neira   netlink: fix wron...
934
  			err = nlk->netlink_bind(net, group + 1);
4f5209005   Richard Guy Briggs   netlink: have net...
935
936
  			if (!err)
  				continue;
023e2cfa3   Johannes Berg   netlink/genetlink...
937
  			netlink_undo_bind(group, groups, sk);
f77360802   Xin Long   netlink: access n...
938
  			goto unlock;
4f5209005   Richard Guy Briggs   netlink: have net...
939
940
  		}
  	}
da314c992   Herbert Xu   netlink: Replace ...
941
942
943
944
  	/* No need for barriers here as we return to user-space without
  	 * using any of the bound attributes.
  	 */
  	if (!bound) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
945
  		err = nladdr->nl_pid ?
8ea65f4a2   Herbert Xu   netlink: Kill red...
946
  			netlink_insert(sk, nladdr->nl_pid) :
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
947
  			netlink_autobind(sock);
4f5209005   Richard Guy Briggs   netlink: have net...
948
  		if (err) {
023e2cfa3   Johannes Berg   netlink/genetlink...
949
  			netlink_undo_bind(nlk->ngroups, groups, sk);
f77360802   Xin Long   netlink: access n...
950
  			goto unlock;
4f5209005   Richard Guy Briggs   netlink: have net...
951
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
952
  	}
4f5209005   Richard Guy Briggs   netlink: have net...
953
  	if (!groups && (nlk->groups == NULL || !(u32)nlk->groups[0]))
f77360802   Xin Long   netlink: access n...
954
955
  		goto unlock;
  	netlink_unlock_table();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
956
957
  
  	netlink_table_grab();
f7fa9b10e   Patrick McHardy   [NETLINK]: Suppor...
958
  	netlink_update_subscriptions(sk, nlk->subscriptions +
4f5209005   Richard Guy Briggs   netlink: have net...
959
  					 hweight32(groups) -
746fac4dc   YOSHIFUJI Hideaki   [NET] NETLINK: Fi...
960
  					 hweight32(nlk->groups[0]));
4f5209005   Richard Guy Briggs   netlink: have net...
961
  	nlk->groups[0] = (nlk->groups[0] & ~0xffffffffUL) | groups;
4277a083e   Patrick McHardy   [NETLINK]: Add ne...
962
  	netlink_update_listeners(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
963
964
965
  	netlink_table_ungrab();
  
  	return 0;
f77360802   Xin Long   netlink: access n...
966
967
968
969
  
  unlock:
  	netlink_unlock_table();
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
970
971
972
973
974
975
976
977
  }
  
  static int netlink_connect(struct socket *sock, struct sockaddr *addr,
  			   int alen, int flags)
  {
  	int err = 0;
  	struct sock *sk = sock->sk;
  	struct netlink_sock *nlk = nlk_sk(sk);
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
978
  	struct sockaddr_nl *nladdr = (struct sockaddr_nl *)addr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
979

6503d9616   Changli Gao   net: check the le...
980
981
  	if (alen < sizeof(addr->sa_family))
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
982
983
  	if (addr->sa_family == AF_UNSPEC) {
  		sk->sk_state	= NETLINK_UNCONNECTED;
15e473046   Eric W. Biederman   netlink: Rename p...
984
  		nlk->dst_portid	= 0;
d629b836d   Patrick McHardy   [NETLINK]: Use gr...
985
  		nlk->dst_group  = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
986
987
988
989
  		return 0;
  	}
  	if (addr->sa_family != AF_NETLINK)
  		return -EINVAL;
787b94062   Alexander Potapenko   netlink: make sur...
990
991
  	if (alen < sizeof(struct sockaddr_nl))
  		return -EINVAL;
46833a86f   Mike Pecovnik   net: Fix permissi...
992
  	if ((nladdr->nl_groups || nladdr->nl_pid) &&
5187cd055   Eric W. Biederman   netlink: Rename n...
993
  	    !netlink_allowed(sock, NL_CFG_F_NONROOT_SEND))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
994
  		return -EPERM;
da314c992   Herbert Xu   netlink: Replace ...
995
996
997
998
  	/* No need for barriers here as we return to user-space without
  	 * using any of the bound attributes.
  	 */
  	if (!nlk->bound)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
999
1000
1001
1002
  		err = netlink_autobind(sock);
  
  	if (err == 0) {
  		sk->sk_state	= NETLINK_CONNECTED;
15e473046   Eric W. Biederman   netlink: Rename p...
1003
  		nlk->dst_portid = nladdr->nl_pid;
d629b836d   Patrick McHardy   [NETLINK]: Use gr...
1004
  		nlk->dst_group  = ffs(nladdr->nl_groups);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1005
1006
1007
1008
  	}
  
  	return err;
  }
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
1009
1010
  static int netlink_getname(struct socket *sock, struct sockaddr *addr,
  			   int *addr_len, int peer)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1011
1012
1013
  {
  	struct sock *sk = sock->sk;
  	struct netlink_sock *nlk = nlk_sk(sk);
13cfa97be   Cyrill Gorcunov   net: netlink_getn...
1014
  	DECLARE_SOCKADDR(struct sockaddr_nl *, nladdr, addr);
746fac4dc   YOSHIFUJI Hideaki   [NET] NETLINK: Fi...
1015

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1016
1017
1018
1019
1020
  	nladdr->nl_family = AF_NETLINK;
  	nladdr->nl_pad = 0;
  	*addr_len = sizeof(*nladdr);
  
  	if (peer) {
15e473046   Eric W. Biederman   netlink: Rename p...
1021
  		nladdr->nl_pid = nlk->dst_portid;
d629b836d   Patrick McHardy   [NETLINK]: Use gr...
1022
  		nladdr->nl_groups = netlink_group_mask(nlk->dst_group);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1023
  	} else {
15e473046   Eric W. Biederman   netlink: Rename p...
1024
  		nladdr->nl_pid = nlk->portid;
f77360802   Xin Long   netlink: access n...
1025
  		netlink_lock_table();
513c25000   Patrick McHardy   [NETLINK]: Don't ...
1026
  		nladdr->nl_groups = nlk->groups ? nlk->groups[0] : 0;
f77360802   Xin Long   netlink: access n...
1027
  		netlink_unlock_table();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1028
1029
1030
  	}
  	return 0;
  }
025c68186   David Decotigny   netlink: add supp...
1031
1032
1033
1034
1035
1036
1037
  static int netlink_ioctl(struct socket *sock, unsigned int cmd,
  			 unsigned long arg)
  {
  	/* try to hand this ioctl down to the NIC drivers.
  	 */
  	return -ENOIOCTLCMD;
  }
15e473046   Eric W. Biederman   netlink: Rename p...
1038
  static struct sock *netlink_getsockbyportid(struct sock *ssk, u32 portid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1039
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1040
1041
  	struct sock *sock;
  	struct netlink_sock *nlk;
15e473046   Eric W. Biederman   netlink: Rename p...
1042
  	sock = netlink_lookup(sock_net(ssk), ssk->sk_protocol, portid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1043
1044
1045
1046
1047
  	if (!sock)
  		return ERR_PTR(-ECONNREFUSED);
  
  	/* Don't bother queuing skb if kernel socket has no input function */
  	nlk = nlk_sk(sock);
cd40b7d39   Denis V. Lunev   [NET]: make netli...
1048
  	if (sock->sk_state == NETLINK_CONNECTED &&
15e473046   Eric W. Biederman   netlink: Rename p...
1049
  	    nlk->dst_portid != nlk_sk(ssk)->portid) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1050
1051
1052
1053
1054
1055
1056
1057
  		sock_put(sock);
  		return ERR_PTR(-ECONNREFUSED);
  	}
  	return sock;
  }
  
  struct sock *netlink_getsockbyfilp(struct file *filp)
  {
496ad9aa8   Al Viro   new helper: file_...
1058
  	struct inode *inode = file_inode(filp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
  	struct sock *sock;
  
  	if (!S_ISSOCK(inode->i_mode))
  		return ERR_PTR(-ENOTSOCK);
  
  	sock = SOCKET_I(inode)->sk;
  	if (sock->sk_family != AF_NETLINK)
  		return ERR_PTR(-EINVAL);
  
  	sock_hold(sock);
  	return sock;
  }
3a36515f7   Pablo Neira   netlink: fix spla...
1071
1072
  static struct sk_buff *netlink_alloc_large_skb(unsigned int size,
  					       int broadcast)
c05cdb1b8   Pablo Neira Ayuso   netlink: allow la...
1073
1074
1075
  {
  	struct sk_buff *skb;
  	void *data;
3a36515f7   Pablo Neira   netlink: fix spla...
1076
  	if (size <= NLMSG_GOODSIZE || broadcast)
c05cdb1b8   Pablo Neira Ayuso   netlink: allow la...
1077
  		return alloc_skb(size, GFP_KERNEL);
3a36515f7   Pablo Neira   netlink: fix spla...
1078
1079
  	size = SKB_DATA_ALIGN(size) +
  	       SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
c05cdb1b8   Pablo Neira Ayuso   netlink: allow la...
1080
1081
1082
  
  	data = vmalloc(size);
  	if (data == NULL)
3a36515f7   Pablo Neira   netlink: fix spla...
1083
  		return NULL;
c05cdb1b8   Pablo Neira Ayuso   netlink: allow la...
1084

2ea2f62c8   Eric Dumazet   net: fix crash in...
1085
  	skb = __build_skb(data, size);
3a36515f7   Pablo Neira   netlink: fix spla...
1086
1087
  	if (skb == NULL)
  		vfree(data);
2ea2f62c8   Eric Dumazet   net: fix crash in...
1088
  	else
3a36515f7   Pablo Neira   netlink: fix spla...
1089
  		skb->destructor = netlink_skb_destructor;
c05cdb1b8   Pablo Neira Ayuso   netlink: allow la...
1090
1091
  
  	return skb;
c05cdb1b8   Pablo Neira Ayuso   netlink: allow la...
1092
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
  /*
   * Attach a skb to a netlink socket.
   * The caller must hold a reference to the destination socket. On error, the
   * reference is dropped. The skb is not send to the destination, just all
   * all error checks are performed and memory in the queue is reserved.
   * Return values:
   * < 0: error. skb freed, reference to sock dropped.
   * 0: continue
   * 1: repeat lookup - reference dropped while waiting for socket memory.
   */
9457afee8   Denis V. Lunev   netlink: Remove n...
1103
  int netlink_attachskb(struct sock *sk, struct sk_buff *skb,
c3d8d1e30   Patrick McHardy   [NETLINK]: Fix un...
1104
  		      long *timeo, struct sock *ssk)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1105
1106
1107
1108
  {
  	struct netlink_sock *nlk;
  
  	nlk = nlk_sk(sk);
5fd96123e   Patrick McHardy   netlink: implemen...
1109
  	if ((atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf ||
d1b4c689d   Florian Westphal   netlink: remove m...
1110
  	     test_bit(NETLINK_S_CONGESTED, &nlk->state))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1111
  		DECLARE_WAITQUEUE(wait, current);
c3d8d1e30   Patrick McHardy   [NETLINK]: Fix un...
1112
  		if (!*timeo) {
aed815601   Denis V. Lunev   [NET]: unify netl...
1113
  			if (!ssk || netlink_is_kernel(ssk))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
  				netlink_overrun(sk);
  			sock_put(sk);
  			kfree_skb(skb);
  			return -EAGAIN;
  		}
  
  		__set_current_state(TASK_INTERRUPTIBLE);
  		add_wait_queue(&nlk->wait, &wait);
  
  		if ((atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf ||
cc3a572fe   Nicolas Dichtel   netlink: rename p...
1124
  		     test_bit(NETLINK_S_CONGESTED, &nlk->state)) &&
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1125
  		    !sock_flag(sk, SOCK_DEAD))
c3d8d1e30   Patrick McHardy   [NETLINK]: Fix un...
1126
  			*timeo = schedule_timeout(*timeo);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1127
1128
1129
1130
1131
1132
1133
  
  		__set_current_state(TASK_RUNNING);
  		remove_wait_queue(&nlk->wait, &wait);
  		sock_put(sk);
  
  		if (signal_pending(current)) {
  			kfree_skb(skb);
c3d8d1e30   Patrick McHardy   [NETLINK]: Fix un...
1134
  			return sock_intr_errno(*timeo);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1135
1136
1137
  		}
  		return 1;
  	}
cf0a018ac   Patrick McHardy   netlink: add netl...
1138
  	netlink_skb_set_owner_r(skb, sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1139
1140
  	return 0;
  }
4a7e7c2ad   Eric Dumazet   netlink: fix race...
1141
  static int __netlink_sendskb(struct sock *sk, struct sk_buff *skb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1142
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1143
  	int len = skb->len;
bcbde0d44   Daniel Borkmann   net: netlink: vir...
1144
  	netlink_deliver_tap(skb);
d1b4c689d   Florian Westphal   netlink: remove m...
1145
  	skb_queue_tail(&sk->sk_receive_queue, skb);
676d23690   David S. Miller   net: Fix use afte...
1146
  	sk->sk_data_ready(sk);
4a7e7c2ad   Eric Dumazet   netlink: fix race...
1147
1148
1149
1150
1151
1152
  	return len;
  }
  
  int netlink_sendskb(struct sock *sk, struct sk_buff *skb)
  {
  	int len = __netlink_sendskb(sk, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1153
1154
1155
1156
1157
1158
1159
1160
1161
  	sock_put(sk);
  	return len;
  }
  
  void netlink_detachskb(struct sock *sk, struct sk_buff *skb)
  {
  	kfree_skb(skb);
  	sock_put(sk);
  }
b57ef81ff   stephen hemminger   netlink: af_netli...
1162
  static struct sk_buff *netlink_trim(struct sk_buff *skb, gfp_t allocation)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1163
1164
  {
  	int delta;
1298ca467   Patrick McHardy   netlink: don't or...
1165
  	WARN_ON(skb->sk != NULL);
4305b5413   Arnaldo Carvalho de Melo   [SK_BUFF]: Conver...
1166
  	delta = skb->end - skb->tail;
c05cdb1b8   Pablo Neira Ayuso   netlink: allow la...
1167
  	if (is_vmalloc_addr(skb->head) || delta * 2 < skb->truesize)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1168
1169
1170
1171
1172
1173
  		return skb;
  
  	if (skb_shared(skb)) {
  		struct sk_buff *nskb = skb_clone(skb, allocation);
  		if (!nskb)
  			return skb;
8460c00f6   Eric Dumazet   netlink: dont dro...
1174
  		consume_skb(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1175
1176
  		skb = nskb;
  	}
158f323b9   Eric Dumazet   net: adjust skb->...
1177
1178
1179
  	pskb_expand_head(skb, 0, -delta,
  			 (allocation & ~__GFP_DIRECT_RECLAIM) |
  			 __GFP_NOWARN | __GFP_NORETRY);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1180
1181
  	return skb;
  }
3fbc29054   Eric W. Biederman   netlink: Make the...
1182
1183
  static int netlink_unicast_kernel(struct sock *sk, struct sk_buff *skb,
  				  struct sock *ssk)
cd40b7d39   Denis V. Lunev   [NET]: make netli...
1184
1185
1186
1187
1188
1189
1190
  {
  	int ret;
  	struct netlink_sock *nlk = nlk_sk(sk);
  
  	ret = -ECONNREFUSED;
  	if (nlk->netlink_rcv != NULL) {
  		ret = skb->len;
cf0a018ac   Patrick McHardy   netlink: add netl...
1191
  		netlink_skb_set_owner_r(skb, sk);
e32123e59   Patrick McHardy   netlink: rename s...
1192
  		NETLINK_CB(skb).sk = ssk;
73bfd370c   Daniel Borkmann   netlink: only do ...
1193
  		netlink_deliver_tap_kernel(sk, ssk, skb);
cd40b7d39   Denis V. Lunev   [NET]: make netli...
1194
  		nlk->netlink_rcv(skb);
bfb253c9b   Eric Dumazet   af_netlink: drop_...
1195
1196
1197
  		consume_skb(skb);
  	} else {
  		kfree_skb(skb);
cd40b7d39   Denis V. Lunev   [NET]: make netli...
1198
  	}
cd40b7d39   Denis V. Lunev   [NET]: make netli...
1199
1200
1201
1202
1203
  	sock_put(sk);
  	return ret;
  }
  
  int netlink_unicast(struct sock *ssk, struct sk_buff *skb,
15e473046   Eric W. Biederman   netlink: Rename p...
1204
  		    u32 portid, int nonblock)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1205
1206
1207
1208
1209
1210
1211
1212
1213
  {
  	struct sock *sk;
  	int err;
  	long timeo;
  
  	skb = netlink_trim(skb, gfp_any());
  
  	timeo = sock_sndtimeo(ssk, nonblock);
  retry:
15e473046   Eric W. Biederman   netlink: Rename p...
1214
  	sk = netlink_getsockbyportid(ssk, portid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1215
1216
1217
1218
  	if (IS_ERR(sk)) {
  		kfree_skb(skb);
  		return PTR_ERR(sk);
  	}
cd40b7d39   Denis V. Lunev   [NET]: make netli...
1219
  	if (netlink_is_kernel(sk))
3fbc29054   Eric W. Biederman   netlink: Make the...
1220
  		return netlink_unicast_kernel(sk, skb, ssk);
cd40b7d39   Denis V. Lunev   [NET]: make netli...
1221

b1153f29e   Stephen Hemminger   netlink: make soc...
1222
  	if (sk_filter(sk, skb)) {
848746072   Wang Chen   netlink: Unneeded...
1223
  		err = skb->len;
b1153f29e   Stephen Hemminger   netlink: make soc...
1224
1225
1226
1227
  		kfree_skb(skb);
  		sock_put(sk);
  		return err;
  	}
9457afee8   Denis V. Lunev   netlink: Remove n...
1228
  	err = netlink_attachskb(sk, skb, &timeo, ssk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1229
1230
1231
1232
  	if (err == 1)
  		goto retry;
  	if (err)
  		return err;
7ee015e0f   Denis V. Lunev   [NET]: cleanup 3r...
1233
  	return netlink_sendskb(sk, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1234
  }
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
1235
  EXPORT_SYMBOL(netlink_unicast);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1236

4277a083e   Patrick McHardy   [NETLINK]: Add ne...
1237
1238
1239
  int netlink_has_listeners(struct sock *sk, unsigned int group)
  {
  	int res = 0;
5c398dc8f   Eric Dumazet   netlink: fix netl...
1240
  	struct listeners *listeners;
4277a083e   Patrick McHardy   [NETLINK]: Add ne...
1241

aed815601   Denis V. Lunev   [NET]: unify netl...
1242
  	BUG_ON(!netlink_is_kernel(sk));
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
1243
1244
1245
  
  	rcu_read_lock();
  	listeners = rcu_dereference(nl_table[sk->sk_protocol].listeners);
6d772ac55   Eric Dumazet   netlink: use kfre...
1246
  	if (listeners && group - 1 < nl_table[sk->sk_protocol].groups)
5c398dc8f   Eric Dumazet   netlink: fix netl...
1247
  		res = test_bit(group - 1, listeners->masks);
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
1248
1249
  
  	rcu_read_unlock();
4277a083e   Patrick McHardy   [NETLINK]: Add ne...
1250
1251
1252
  	return res;
  }
  EXPORT_SYMBOL_GPL(netlink_has_listeners);
b57ef81ff   stephen hemminger   netlink: af_netli...
1253
  static int netlink_broadcast_deliver(struct sock *sk, struct sk_buff *skb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1254
1255
1256
1257
  {
  	struct netlink_sock *nlk = nlk_sk(sk);
  
  	if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf &&
cc3a572fe   Nicolas Dichtel   netlink: rename p...
1258
  	    !test_bit(NETLINK_S_CONGESTED, &nlk->state)) {
cf0a018ac   Patrick McHardy   netlink: add netl...
1259
  		netlink_skb_set_owner_r(skb, sk);
4a7e7c2ad   Eric Dumazet   netlink: fix race...
1260
  		__netlink_sendskb(sk, skb);
2c6458004   stephen hemminger   netlink: wake up ...
1261
  		return atomic_read(&sk->sk_rmem_alloc) > (sk->sk_rcvbuf >> 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1262
1263
1264
1265
1266
1267
  	}
  	return -1;
  }
  
  struct netlink_broadcast_data {
  	struct sock *exclude_sk;
b4b510290   Eric W. Biederman   [NET]: Support mu...
1268
  	struct net *net;
15e473046   Eric W. Biederman   netlink: Rename p...
1269
  	u32 portid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1270
1271
  	u32 group;
  	int failure;
ff491a733   Pablo Neira Ayuso   netlink: change r...
1272
  	int delivery_failure;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1273
1274
  	int congested;
  	int delivered;
7d877f3bd   Al Viro   [PATCH] gfp_t: net/*
1275
  	gfp_t allocation;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1276
  	struct sk_buff *skb, *skb2;
910a7e905   Eric W. Biederman   netlink: Implment...
1277
1278
  	int (*tx_filter)(struct sock *dsk, struct sk_buff *skb, void *data);
  	void *tx_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1279
  };
46c9521fc   Rami Rosen   netlink: Fix do_o...
1280
1281
  static void do_one_broadcast(struct sock *sk,
  				    struct netlink_broadcast_data *p)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1282
1283
1284
1285
1286
  {
  	struct netlink_sock *nlk = nlk_sk(sk);
  	int val;
  
  	if (p->exclude_sk == sk)
46c9521fc   Rami Rosen   netlink: Fix do_o...
1287
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1288

15e473046   Eric W. Biederman   netlink: Rename p...
1289
  	if (nlk->portid == p->portid || p->group - 1 >= nlk->ngroups ||
f7fa9b10e   Patrick McHardy   [NETLINK]: Suppor...
1290
  	    !test_bit(p->group - 1, nlk->groups))
46c9521fc   Rami Rosen   netlink: Fix do_o...
1291
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1292

59324cf35   Nicolas Dichtel   netlink: allow to...
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
  	if (!net_eq(sock_net(sk), p->net)) {
  		if (!(nlk->flags & NETLINK_F_LISTEN_ALL_NSID))
  			return;
  
  		if (!peernet_has_id(sock_net(sk), p->net))
  			return;
  
  		if (!file_ns_capable(sk->sk_socket->file, p->net->user_ns,
  				     CAP_NET_BROADCAST))
  			return;
  	}
b4b510290   Eric W. Biederman   [NET]: Support mu...
1304

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1305
1306
  	if (p->failure) {
  		netlink_overrun(sk);
46c9521fc   Rami Rosen   netlink: Fix do_o...
1307
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1308
1309
1310
1311
  	}
  
  	sock_hold(sk);
  	if (p->skb2 == NULL) {
68acc024e   Tommy S. Christensen   [NETLINK]: Move b...
1312
  		if (skb_shared(p->skb)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1313
1314
  			p->skb2 = skb_clone(p->skb, p->allocation);
  		} else {
68acc024e   Tommy S. Christensen   [NETLINK]: Move b...
1315
1316
1317
1318
1319
1320
  			p->skb2 = skb_get(p->skb);
  			/*
  			 * skb ownership may have been set when
  			 * delivered to a previous socket.
  			 */
  			skb_orphan(p->skb2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1321
1322
1323
1324
1325
1326
  		}
  	}
  	if (p->skb2 == NULL) {
  		netlink_overrun(sk);
  		/* Clone failed. Notify ALL listeners. */
  		p->failure = 1;
cc3a572fe   Nicolas Dichtel   netlink: rename p...
1327
  		if (nlk->flags & NETLINK_F_BROADCAST_SEND_ERROR)
be0c22a46   Pablo Neira Ayuso   netlink: add NETL...
1328
  			p->delivery_failure = 1;
59324cf35   Nicolas Dichtel   netlink: allow to...
1329
1330
1331
  		goto out;
  	}
  	if (p->tx_filter && p->tx_filter(sk, p->skb2, p->tx_data)) {
910a7e905   Eric W. Biederman   netlink: Implment...
1332
1333
  		kfree_skb(p->skb2);
  		p->skb2 = NULL;
59324cf35   Nicolas Dichtel   netlink: allow to...
1334
1335
1336
  		goto out;
  	}
  	if (sk_filter(sk, p->skb2)) {
b1153f29e   Stephen Hemminger   netlink: make soc...
1337
1338
  		kfree_skb(p->skb2);
  		p->skb2 = NULL;
59324cf35   Nicolas Dichtel   netlink: allow to...
1339
1340
1341
  		goto out;
  	}
  	NETLINK_CB(p->skb2).nsid = peernet2id(sock_net(sk), p->net);
7212462fa   Nicolas Dichtel   netlink: don't se...
1342
1343
  	if (NETLINK_CB(p->skb2).nsid != NETNSA_NSID_NOT_ASSIGNED)
  		NETLINK_CB(p->skb2).nsid_is_set = true;
59324cf35   Nicolas Dichtel   netlink: allow to...
1344
1345
  	val = netlink_broadcast_deliver(sk, p->skb2);
  	if (val < 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1346
  		netlink_overrun(sk);
cc3a572fe   Nicolas Dichtel   netlink: rename p...
1347
  		if (nlk->flags & NETLINK_F_BROADCAST_SEND_ERROR)
be0c22a46   Pablo Neira Ayuso   netlink: add NETL...
1348
  			p->delivery_failure = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1349
1350
1351
1352
1353
  	} else {
  		p->congested |= val;
  		p->delivered = 1;
  		p->skb2 = NULL;
  	}
59324cf35   Nicolas Dichtel   netlink: allow to...
1354
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1355
  	sock_put(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1356
  }
15e473046   Eric W. Biederman   netlink: Rename p...
1357
  int netlink_broadcast_filtered(struct sock *ssk, struct sk_buff *skb, u32 portid,
910a7e905   Eric W. Biederman   netlink: Implment...
1358
1359
1360
  	u32 group, gfp_t allocation,
  	int (*filter)(struct sock *dsk, struct sk_buff *skb, void *data),
  	void *filter_data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1361
  {
3b1e0a655   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
1362
  	struct net *net = sock_net(ssk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1363
  	struct netlink_broadcast_data info;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1364
1365
1366
1367
1368
  	struct sock *sk;
  
  	skb = netlink_trim(skb, allocation);
  
  	info.exclude_sk = ssk;
b4b510290   Eric W. Biederman   [NET]: Support mu...
1369
  	info.net = net;
15e473046   Eric W. Biederman   netlink: Rename p...
1370
  	info.portid = portid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1371
1372
  	info.group = group;
  	info.failure = 0;
ff491a733   Pablo Neira Ayuso   netlink: change r...
1373
  	info.delivery_failure = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1374
1375
1376
1377
1378
  	info.congested = 0;
  	info.delivered = 0;
  	info.allocation = allocation;
  	info.skb = skb;
  	info.skb2 = NULL;
910a7e905   Eric W. Biederman   netlink: Implment...
1379
1380
  	info.tx_filter = filter;
  	info.tx_data = filter_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1381
1382
1383
1384
  
  	/* While we sleep in clone, do not allow to change socket list */
  
  	netlink_lock_table();
b67bfe0d4   Sasha Levin   hlist: drop the n...
1385
  	sk_for_each_bound(sk, &nl_table[ssk->sk_protocol].mc_list)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1386
  		do_one_broadcast(sk, &info);
70d4bf6d4   Neil Horman   drop_monitor: con...
1387
  	consume_skb(skb);
aa1c6a6f7   Tommy S. Christensen   [NETLINK]: Defer ...
1388

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1389
  	netlink_unlock_table();
70d4bf6d4   Neil Horman   drop_monitor: con...
1390
1391
  	if (info.delivery_failure) {
  		kfree_skb(info.skb2);
ff491a733   Pablo Neira Ayuso   netlink: change r...
1392
  		return -ENOBUFS;
658cb354e   Eric Dumazet   af_netlink: cleanups
1393
1394
  	}
  	consume_skb(info.skb2);
ff491a733   Pablo Neira Ayuso   netlink: change r...
1395

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1396
  	if (info.delivered) {
d0164adc8   Mel Gorman   mm, page_alloc: d...
1397
  		if (info.congested && gfpflags_allow_blocking(allocation))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1398
1399
1400
  			yield();
  		return 0;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1401
1402
  	return -ESRCH;
  }
910a7e905   Eric W. Biederman   netlink: Implment...
1403
  EXPORT_SYMBOL(netlink_broadcast_filtered);
15e473046   Eric W. Biederman   netlink: Rename p...
1404
  int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 portid,
910a7e905   Eric W. Biederman   netlink: Implment...
1405
1406
  		      u32 group, gfp_t allocation)
  {
15e473046   Eric W. Biederman   netlink: Rename p...
1407
  	return netlink_broadcast_filtered(ssk, skb, portid, group, allocation,
910a7e905   Eric W. Biederman   netlink: Implment...
1408
1409
  		NULL, NULL);
  }
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
1410
  EXPORT_SYMBOL(netlink_broadcast);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1411
1412
1413
  
  struct netlink_set_err_data {
  	struct sock *exclude_sk;
15e473046   Eric W. Biederman   netlink: Rename p...
1414
  	u32 portid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1415
1416
1417
  	u32 group;
  	int code;
  };
b57ef81ff   stephen hemminger   netlink: af_netli...
1418
  static int do_one_set_err(struct sock *sk, struct netlink_set_err_data *p)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1419
1420
  {
  	struct netlink_sock *nlk = nlk_sk(sk);
1a50307ba   Pablo Neira Ayuso   netlink: fix NETL...
1421
  	int ret = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1422
1423
1424
  
  	if (sk == p->exclude_sk)
  		goto out;
09ad9bc75   Octavian Purdila   net: use net_eq t...
1425
  	if (!net_eq(sock_net(sk), sock_net(p->exclude_sk)))
b4b510290   Eric W. Biederman   [NET]: Support mu...
1426
  		goto out;
15e473046   Eric W. Biederman   netlink: Rename p...
1427
  	if (nlk->portid == p->portid || p->group - 1 >= nlk->ngroups ||
f7fa9b10e   Patrick McHardy   [NETLINK]: Suppor...
1428
  	    !test_bit(p->group - 1, nlk->groups))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1429
  		goto out;
cc3a572fe   Nicolas Dichtel   netlink: rename p...
1430
  	if (p->code == ENOBUFS && nlk->flags & NETLINK_F_RECV_NO_ENOBUFS) {
1a50307ba   Pablo Neira Ayuso   netlink: fix NETL...
1431
1432
1433
  		ret = 1;
  		goto out;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1434
1435
1436
  	sk->sk_err = p->code;
  	sk->sk_error_report(sk);
  out:
1a50307ba   Pablo Neira Ayuso   netlink: fix NETL...
1437
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1438
  }
4843b93c9   Pablo Neira Ayuso   netlink: invert e...
1439
1440
1441
  /**
   * netlink_set_err - report error to broadcast listeners
   * @ssk: the kernel netlink socket, as returned by netlink_kernel_create()
15e473046   Eric W. Biederman   netlink: Rename p...
1442
   * @portid: the PORTID of a process that we want to skip (if any)
840e93f2e   Johannes Berg   netlink: fix docu...
1443
   * @group: the broadcast group that will notice the error
4843b93c9   Pablo Neira Ayuso   netlink: invert e...
1444
   * @code: error code, must be negative (as usual in kernelspace)
1a50307ba   Pablo Neira Ayuso   netlink: fix NETL...
1445
1446
   *
   * This function returns the number of broadcast listeners that have set the
cc3a572fe   Nicolas Dichtel   netlink: rename p...
1447
   * NETLINK_NO_ENOBUFS socket option.
4843b93c9   Pablo Neira Ayuso   netlink: invert e...
1448
   */
15e473046   Eric W. Biederman   netlink: Rename p...
1449
  int netlink_set_err(struct sock *ssk, u32 portid, u32 group, int code)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1450
1451
  {
  	struct netlink_set_err_data info;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1452
  	struct sock *sk;
1a50307ba   Pablo Neira Ayuso   netlink: fix NETL...
1453
  	int ret = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1454
1455
  
  	info.exclude_sk = ssk;
15e473046   Eric W. Biederman   netlink: Rename p...
1456
  	info.portid = portid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1457
  	info.group = group;
4843b93c9   Pablo Neira Ayuso   netlink: invert e...
1458
1459
  	/* sk->sk_err wants a positive error value */
  	info.code = -code;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1460
1461
  
  	read_lock(&nl_table_lock);
b67bfe0d4   Sasha Levin   hlist: drop the n...
1462
  	sk_for_each_bound(sk, &nl_table[ssk->sk_protocol].mc_list)
1a50307ba   Pablo Neira Ayuso   netlink: fix NETL...
1463
  		ret += do_one_set_err(sk, &info);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1464
1465
  
  	read_unlock(&nl_table_lock);
1a50307ba   Pablo Neira Ayuso   netlink: fix NETL...
1466
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1467
  }
dd5b6ce6f   Pablo Neira Ayuso   nefilter: nfnetli...
1468
  EXPORT_SYMBOL(netlink_set_err);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1469

84659eb52   Johannes Berg   [NETLIKN]: Allow ...
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
  /* must be called with netlink table grabbed */
  static void netlink_update_socket_mc(struct netlink_sock *nlk,
  				     unsigned int group,
  				     int is_new)
  {
  	int old, new = !!is_new, subscriptions;
  
  	old = test_bit(group - 1, nlk->groups);
  	subscriptions = nlk->subscriptions - old + new;
  	if (new)
  		__set_bit(group - 1, nlk->groups);
  	else
  		__clear_bit(group - 1, nlk->groups);
  	netlink_update_subscriptions(&nlk->sk, subscriptions);
  	netlink_update_listeners(&nlk->sk);
  }
9a4595bc7   Patrick McHardy   [NETLINK]: Add se...
1486
  static int netlink_setsockopt(struct socket *sock, int level, int optname,
b7058842c   David S. Miller   net: Make setsock...
1487
  			      char __user *optval, unsigned int optlen)
9a4595bc7   Patrick McHardy   [NETLINK]: Add se...
1488
1489
1490
  {
  	struct sock *sk = sock->sk;
  	struct netlink_sock *nlk = nlk_sk(sk);
eb4965344   Johannes Berg   [NETLINK]: negati...
1491
1492
  	unsigned int val = 0;
  	int err;
9a4595bc7   Patrick McHardy   [NETLINK]: Add se...
1493
1494
1495
  
  	if (level != SOL_NETLINK)
  		return -ENOPROTOOPT;
d1b4c689d   Florian Westphal   netlink: remove m...
1496
  	if (optlen >= sizeof(int) &&
eb4965344   Johannes Berg   [NETLINK]: negati...
1497
  	    get_user(val, (unsigned int __user *)optval))
9a4595bc7   Patrick McHardy   [NETLINK]: Add se...
1498
1499
1500
1501
1502
  		return -EFAULT;
  
  	switch (optname) {
  	case NETLINK_PKTINFO:
  		if (val)
cc3a572fe   Nicolas Dichtel   netlink: rename p...
1503
  			nlk->flags |= NETLINK_F_RECV_PKTINFO;
9a4595bc7   Patrick McHardy   [NETLINK]: Add se...
1504
  		else
cc3a572fe   Nicolas Dichtel   netlink: rename p...
1505
  			nlk->flags &= ~NETLINK_F_RECV_PKTINFO;
9a4595bc7   Patrick McHardy   [NETLINK]: Add se...
1506
1507
1508
1509
  		err = 0;
  		break;
  	case NETLINK_ADD_MEMBERSHIP:
  	case NETLINK_DROP_MEMBERSHIP: {
5187cd055   Eric W. Biederman   netlink: Rename n...
1510
  		if (!netlink_allowed(sock, NL_CFG_F_NONROOT_RECV))
9a4595bc7   Patrick McHardy   [NETLINK]: Add se...
1511
  			return -EPERM;
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
1512
1513
1514
  		err = netlink_realloc_groups(sk);
  		if (err)
  			return err;
9a4595bc7   Patrick McHardy   [NETLINK]: Add se...
1515
1516
  		if (!val || val - 1 >= nlk->ngroups)
  			return -EINVAL;
7774d5e03   Richard Guy Briggs   netlink: implemen...
1517
  		if (optname == NETLINK_ADD_MEMBERSHIP && nlk->netlink_bind) {
023e2cfa3   Johannes Berg   netlink/genetlink...
1518
  			err = nlk->netlink_bind(sock_net(sk), val);
4f5209005   Richard Guy Briggs   netlink: have net...
1519
1520
1521
  			if (err)
  				return err;
  		}
9a4595bc7   Patrick McHardy   [NETLINK]: Add se...
1522
  		netlink_table_grab();
84659eb52   Johannes Berg   [NETLIKN]: Allow ...
1523
1524
  		netlink_update_socket_mc(nlk, val,
  					 optname == NETLINK_ADD_MEMBERSHIP);
9a4595bc7   Patrick McHardy   [NETLINK]: Add se...
1525
  		netlink_table_ungrab();
7774d5e03   Richard Guy Briggs   netlink: implemen...
1526
  		if (optname == NETLINK_DROP_MEMBERSHIP && nlk->netlink_unbind)
023e2cfa3   Johannes Berg   netlink/genetlink...
1527
  			nlk->netlink_unbind(sock_net(sk), val);
03292745b   Pablo Neira Ayuso   netlink: add nlk-...
1528

9a4595bc7   Patrick McHardy   [NETLINK]: Add se...
1529
1530
1531
  		err = 0;
  		break;
  	}
be0c22a46   Pablo Neira Ayuso   netlink: add NETL...
1532
1533
  	case NETLINK_BROADCAST_ERROR:
  		if (val)
cc3a572fe   Nicolas Dichtel   netlink: rename p...
1534
  			nlk->flags |= NETLINK_F_BROADCAST_SEND_ERROR;
be0c22a46   Pablo Neira Ayuso   netlink: add NETL...
1535
  		else
cc3a572fe   Nicolas Dichtel   netlink: rename p...
1536
  			nlk->flags &= ~NETLINK_F_BROADCAST_SEND_ERROR;
be0c22a46   Pablo Neira Ayuso   netlink: add NETL...
1537
1538
  		err = 0;
  		break;
38938bfe3   Pablo Neira Ayuso   netlink: add NETL...
1539
1540
  	case NETLINK_NO_ENOBUFS:
  		if (val) {
cc3a572fe   Nicolas Dichtel   netlink: rename p...
1541
1542
  			nlk->flags |= NETLINK_F_RECV_NO_ENOBUFS;
  			clear_bit(NETLINK_S_CONGESTED, &nlk->state);
38938bfe3   Pablo Neira Ayuso   netlink: add NETL...
1543
  			wake_up_interruptible(&nlk->wait);
658cb354e   Eric Dumazet   af_netlink: cleanups
1544
  		} else {
cc3a572fe   Nicolas Dichtel   netlink: rename p...
1545
  			nlk->flags &= ~NETLINK_F_RECV_NO_ENOBUFS;
658cb354e   Eric Dumazet   af_netlink: cleanups
1546
  		}
38938bfe3   Pablo Neira Ayuso   netlink: add NETL...
1547
1548
  		err = 0;
  		break;
59324cf35   Nicolas Dichtel   netlink: allow to...
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
  	case NETLINK_LISTEN_ALL_NSID:
  		if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_BROADCAST))
  			return -EPERM;
  
  		if (val)
  			nlk->flags |= NETLINK_F_LISTEN_ALL_NSID;
  		else
  			nlk->flags &= ~NETLINK_F_LISTEN_ALL_NSID;
  		err = 0;
  		break;
0a6a3a23e   Christophe Ricard   netlink: add NETL...
1559
1560
1561
1562
1563
1564
1565
  	case NETLINK_CAP_ACK:
  		if (val)
  			nlk->flags |= NETLINK_F_CAP_ACK;
  		else
  			nlk->flags &= ~NETLINK_F_CAP_ACK;
  		err = 0;
  		break;
2d4bc9336   Johannes Berg   netlink: extended...
1566
1567
1568
1569
1570
1571
1572
  	case NETLINK_EXT_ACK:
  		if (val)
  			nlk->flags |= NETLINK_F_EXT_ACK;
  		else
  			nlk->flags &= ~NETLINK_F_EXT_ACK;
  		err = 0;
  		break;
9a4595bc7   Patrick McHardy   [NETLINK]: Add se...
1573
1574
1575
1576
1577
1578
1579
  	default:
  		err = -ENOPROTOOPT;
  	}
  	return err;
  }
  
  static int netlink_getsockopt(struct socket *sock, int level, int optname,
746fac4dc   YOSHIFUJI Hideaki   [NET] NETLINK: Fi...
1580
  			      char __user *optval, int __user *optlen)
9a4595bc7   Patrick McHardy   [NETLINK]: Add se...
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
  {
  	struct sock *sk = sock->sk;
  	struct netlink_sock *nlk = nlk_sk(sk);
  	int len, val, err;
  
  	if (level != SOL_NETLINK)
  		return -ENOPROTOOPT;
  
  	if (get_user(len, optlen))
  		return -EFAULT;
  	if (len < 0)
  		return -EINVAL;
  
  	switch (optname) {
  	case NETLINK_PKTINFO:
  		if (len < sizeof(int))
  			return -EINVAL;
  		len = sizeof(int);
cc3a572fe   Nicolas Dichtel   netlink: rename p...
1599
  		val = nlk->flags & NETLINK_F_RECV_PKTINFO ? 1 : 0;
a27b58fed   Heiko Carstens   [NET]: fix uacces...
1600
1601
1602
  		if (put_user(len, optlen) ||
  		    put_user(val, optval))
  			return -EFAULT;
9a4595bc7   Patrick McHardy   [NETLINK]: Add se...
1603
1604
  		err = 0;
  		break;
be0c22a46   Pablo Neira Ayuso   netlink: add NETL...
1605
1606
1607
1608
  	case NETLINK_BROADCAST_ERROR:
  		if (len < sizeof(int))
  			return -EINVAL;
  		len = sizeof(int);
cc3a572fe   Nicolas Dichtel   netlink: rename p...
1609
  		val = nlk->flags & NETLINK_F_BROADCAST_SEND_ERROR ? 1 : 0;
be0c22a46   Pablo Neira Ayuso   netlink: add NETL...
1610
1611
1612
1613
1614
  		if (put_user(len, optlen) ||
  		    put_user(val, optval))
  			return -EFAULT;
  		err = 0;
  		break;
38938bfe3   Pablo Neira Ayuso   netlink: add NETL...
1615
1616
1617
1618
  	case NETLINK_NO_ENOBUFS:
  		if (len < sizeof(int))
  			return -EINVAL;
  		len = sizeof(int);
cc3a572fe   Nicolas Dichtel   netlink: rename p...
1619
  		val = nlk->flags & NETLINK_F_RECV_NO_ENOBUFS ? 1 : 0;
38938bfe3   Pablo Neira Ayuso   netlink: add NETL...
1620
1621
1622
1623
1624
  		if (put_user(len, optlen) ||
  		    put_user(val, optval))
  			return -EFAULT;
  		err = 0;
  		break;
b42be38b2   David Herrmann   netlink: add API ...
1625
1626
1627
1628
  	case NETLINK_LIST_MEMBERSHIPS: {
  		int pos, idx, shift;
  
  		err = 0;
47191d65b   David Herrmann   netlink: fix lock...
1629
  		netlink_lock_table();
b42be38b2   David Herrmann   netlink: add API ...
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
  		for (pos = 0; pos * 8 < nlk->ngroups; pos += sizeof(u32)) {
  			if (len - pos < sizeof(u32))
  				break;
  
  			idx = pos / sizeof(unsigned long);
  			shift = (pos % sizeof(unsigned long)) * 8;
  			if (put_user((u32)(nlk->groups[idx] >> shift),
  				     (u32 __user *)(optval + pos))) {
  				err = -EFAULT;
  				break;
  			}
  		}
  		if (put_user(ALIGN(nlk->ngroups / 8, sizeof(u32)), optlen))
  			err = -EFAULT;
47191d65b   David Herrmann   netlink: fix lock...
1644
  		netlink_unlock_table();
b42be38b2   David Herrmann   netlink: add API ...
1645
1646
  		break;
  	}
0a6a3a23e   Christophe Ricard   netlink: add NETL...
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
  	case NETLINK_CAP_ACK:
  		if (len < sizeof(int))
  			return -EINVAL;
  		len = sizeof(int);
  		val = nlk->flags & NETLINK_F_CAP_ACK ? 1 : 0;
  		if (put_user(len, optlen) ||
  		    put_user(val, optval))
  			return -EFAULT;
  		err = 0;
  		break;
2d4bc9336   Johannes Berg   netlink: extended...
1657
1658
1659
1660
1661
1662
1663
1664
1665
  	case NETLINK_EXT_ACK:
  		if (len < sizeof(int))
  			return -EINVAL;
  		len = sizeof(int);
  		val = nlk->flags & NETLINK_F_EXT_ACK ? 1 : 0;
  		if (put_user(len, optlen) || put_user(val, optval))
  			return -EFAULT;
  		err = 0;
  		break;
9a4595bc7   Patrick McHardy   [NETLINK]: Add se...
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
  	default:
  		err = -ENOPROTOOPT;
  	}
  	return err;
  }
  
  static void netlink_cmsg_recv_pktinfo(struct msghdr *msg, struct sk_buff *skb)
  {
  	struct nl_pktinfo info;
  
  	info.group = NETLINK_CB(skb).dst_group;
  	put_cmsg(msg, SOL_NETLINK, NETLINK_PKTINFO, sizeof(info), &info);
  }
59324cf35   Nicolas Dichtel   netlink: allow to...
1679
1680
1681
1682
1683
1684
1685
1686
1687
  static void netlink_cmsg_listen_all_nsid(struct sock *sk, struct msghdr *msg,
  					 struct sk_buff *skb)
  {
  	if (!NETLINK_CB(skb).nsid_is_set)
  		return;
  
  	put_cmsg(msg, SOL_NETLINK, NETLINK_LISTEN_ALL_NSID, sizeof(int),
  		 &NETLINK_CB(skb).nsid);
  }
1b7841404   Ying Xue   net: Remove iocb ...
1688
  static int netlink_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1689
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1690
1691
  	struct sock *sk = sock->sk;
  	struct netlink_sock *nlk = nlk_sk(sk);
342dfc306   Steffen Hurrle   net: add build-ti...
1692
  	DECLARE_SOCKADDR(struct sockaddr_nl *, addr, msg->msg_name);
15e473046   Eric W. Biederman   netlink: Rename p...
1693
  	u32 dst_portid;
d629b836d   Patrick McHardy   [NETLINK]: Use gr...
1694
  	u32 dst_group;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1695
1696
1697
  	struct sk_buff *skb;
  	int err;
  	struct scm_cookie scm;
2d7a85f4b   Eric W. Biederman   netlink: Only che...
1698
  	u32 netlink_skb_flags = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1699
1700
1701
  
  	if (msg->msg_flags&MSG_OOB)
  		return -EOPNOTSUPP;
7cc056626   Christoph Hellwig   net: remove sock_...
1702
  	err = scm_send(sock, msg, &scm, true);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1703
1704
1705
1706
  	if (err < 0)
  		return err;
  
  	if (msg->msg_namelen) {
b47030c71   Eric W. Biederman   af_netlink: Add n...
1707
  		err = -EINVAL;
bf2ecb934   Eric Dumazet   netlink: fix unin...
1708
1709
  		if (msg->msg_namelen < sizeof(struct sockaddr_nl))
  			goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1710
  		if (addr->nl_family != AF_NETLINK)
b47030c71   Eric W. Biederman   af_netlink: Add n...
1711
  			goto out;
15e473046   Eric W. Biederman   netlink: Rename p...
1712
  		dst_portid = addr->nl_pid;
d629b836d   Patrick McHardy   [NETLINK]: Use gr...
1713
  		dst_group = ffs(addr->nl_groups);
b47030c71   Eric W. Biederman   af_netlink: Add n...
1714
  		err =  -EPERM;
15e473046   Eric W. Biederman   netlink: Rename p...
1715
  		if ((dst_group || dst_portid) &&
5187cd055   Eric W. Biederman   netlink: Rename n...
1716
  		    !netlink_allowed(sock, NL_CFG_F_NONROOT_SEND))
b47030c71   Eric W. Biederman   af_netlink: Add n...
1717
  			goto out;
2d7a85f4b   Eric W. Biederman   netlink: Only che...
1718
  		netlink_skb_flags |= NETLINK_SKB_DST;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1719
  	} else {
15e473046   Eric W. Biederman   netlink: Rename p...
1720
  		dst_portid = nlk->dst_portid;
d629b836d   Patrick McHardy   [NETLINK]: Use gr...
1721
  		dst_group = nlk->dst_group;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1722
  	}
da314c992   Herbert Xu   netlink: Replace ...
1723
  	if (!nlk->bound) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1724
1725
1726
  		err = netlink_autobind(sock);
  		if (err)
  			goto out;
da314c992   Herbert Xu   netlink: Replace ...
1727
1728
1729
  	} else {
  		/* Ensure nlk is hashed and visible. */
  		smp_rmb();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1730
1731
1732
1733
1734
1735
  	}
  
  	err = -EMSGSIZE;
  	if (len > sk->sk_sndbuf - 32)
  		goto out;
  	err = -ENOBUFS;
3a36515f7   Pablo Neira   netlink: fix spla...
1736
  	skb = netlink_alloc_large_skb(len, dst_group);
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
1737
  	if (skb == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1738
  		goto out;
15e473046   Eric W. Biederman   netlink: Rename p...
1739
  	NETLINK_CB(skb).portid	= nlk->portid;
d629b836d   Patrick McHardy   [NETLINK]: Use gr...
1740
  	NETLINK_CB(skb).dst_group = dst_group;
7cc056626   Christoph Hellwig   net: remove sock_...
1741
  	NETLINK_CB(skb).creds	= scm.creds;
2d7a85f4b   Eric W. Biederman   netlink: Only che...
1742
  	NETLINK_CB(skb).flags	= netlink_skb_flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1743

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1744
  	err = -EFAULT;
6ce8e9ce5   Al Viro   new helper: memcp...
1745
  	if (memcpy_from_msg(skb_put(skb, len), msg, len)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1746
1747
1748
1749
1750
1751
1752
1753
1754
  		kfree_skb(skb);
  		goto out;
  	}
  
  	err = security_netlink_send(sk, skb);
  	if (err) {
  		kfree_skb(skb);
  		goto out;
  	}
d629b836d   Patrick McHardy   [NETLINK]: Use gr...
1755
  	if (dst_group) {
633547973   Reshetova, Elena   net: convert sk_b...
1756
  		refcount_inc(&skb->users);
15e473046   Eric W. Biederman   netlink: Rename p...
1757
  		netlink_broadcast(sk, skb, dst_portid, dst_group, GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1758
  	}
15e473046   Eric W. Biederman   netlink: Rename p...
1759
  	err = netlink_unicast(sk, skb, dst_portid, msg->msg_flags&MSG_DONTWAIT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1760
1761
  
  out:
7cc056626   Christoph Hellwig   net: remove sock_...
1762
  	scm_destroy(&scm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1763
1764
  	return err;
  }
1b7841404   Ying Xue   net: Remove iocb ...
1765
  static int netlink_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1766
1767
  			   int flags)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1768
1769
1770
1771
1772
  	struct scm_cookie scm;
  	struct sock *sk = sock->sk;
  	struct netlink_sock *nlk = nlk_sk(sk);
  	int noblock = flags&MSG_DONTWAIT;
  	size_t copied;
68d6ac6d2   Johannes Berg   netlink: fix comp...
1773
  	struct sk_buff *skb, *data_skb;
b44d211e1   Andrey Vagin   netlink: handle e...
1774
  	int err, ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1775
1776
1777
1778
1779
  
  	if (flags&MSG_OOB)
  		return -EOPNOTSUPP;
  
  	copied = 0;
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
1780
1781
  	skb = skb_recv_datagram(sk, flags, noblock, &err);
  	if (skb == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1782
  		goto out;
68d6ac6d2   Johannes Berg   netlink: fix comp...
1783
  	data_skb = skb;
1dacc76d0   Johannes Berg   net/compat/wext: ...
1784
1785
  #ifdef CONFIG_COMPAT_NETLINK_MESSAGES
  	if (unlikely(skb_shinfo(skb)->frag_list)) {
1dacc76d0   Johannes Berg   net/compat/wext: ...
1786
  		/*
68d6ac6d2   Johannes Berg   netlink: fix comp...
1787
1788
1789
  		 * If this skb has a frag_list, then here that means that we
  		 * will have to use the frag_list skb's data for compat tasks
  		 * and the regular skb's data for normal (non-compat) tasks.
1dacc76d0   Johannes Berg   net/compat/wext: ...
1790
  		 *
68d6ac6d2   Johannes Berg   netlink: fix comp...
1791
1792
1793
1794
  		 * If we need to send the compat skb, assign it to the
  		 * 'data_skb' variable so that it will be used below for data
  		 * copying. We keep 'skb' for everything else, including
  		 * freeing both later.
1dacc76d0   Johannes Berg   net/compat/wext: ...
1795
  		 */
68d6ac6d2   Johannes Berg   netlink: fix comp...
1796
1797
  		if (flags & MSG_CMSG_COMPAT)
  			data_skb = skb_shinfo(skb)->frag_list;
1dacc76d0   Johannes Berg   net/compat/wext: ...
1798
1799
  	}
  #endif
9063e21fb   Eric Dumazet   netlink: autosize...
1800
1801
1802
  	/* Record the max length of recvmsg() calls for future allocations */
  	nlk->max_recvmsg_len = max(nlk->max_recvmsg_len, len);
  	nlk->max_recvmsg_len = min_t(size_t, nlk->max_recvmsg_len,
d35c99ff7   Eric Dumazet   netlink: do not e...
1803
  				     SKB_WITH_OVERHEAD(32768));
9063e21fb   Eric Dumazet   netlink: autosize...
1804

68d6ac6d2   Johannes Berg   netlink: fix comp...
1805
  	copied = data_skb->len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1806
1807
1808
1809
  	if (len < copied) {
  		msg->msg_flags |= MSG_TRUNC;
  		copied = len;
  	}
68d6ac6d2   Johannes Berg   netlink: fix comp...
1810
  	skb_reset_transport_header(data_skb);
51f3d02b9   David S. Miller   net: Add and use ...
1811
  	err = skb_copy_datagram_msg(data_skb, 0, msg, copied);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1812
1813
  
  	if (msg->msg_name) {
342dfc306   Steffen Hurrle   net: add build-ti...
1814
  		DECLARE_SOCKADDR(struct sockaddr_nl *, addr, msg->msg_name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1815
1816
  		addr->nl_family = AF_NETLINK;
  		addr->nl_pad    = 0;
15e473046   Eric W. Biederman   netlink: Rename p...
1817
  		addr->nl_pid	= NETLINK_CB(skb).portid;
d629b836d   Patrick McHardy   [NETLINK]: Use gr...
1818
  		addr->nl_groups	= netlink_group_mask(NETLINK_CB(skb).dst_group);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1819
1820
  		msg->msg_namelen = sizeof(*addr);
  	}
cc3a572fe   Nicolas Dichtel   netlink: rename p...
1821
  	if (nlk->flags & NETLINK_F_RECV_PKTINFO)
cc9a06cd8   Patrick McHardy   [NETLINK]: Fix us...
1822
  		netlink_cmsg_recv_pktinfo(msg, skb);
59324cf35   Nicolas Dichtel   netlink: allow to...
1823
1824
  	if (nlk->flags & NETLINK_F_LISTEN_ALL_NSID)
  		netlink_cmsg_listen_all_nsid(sk, msg, skb);
cc9a06cd8   Patrick McHardy   [NETLINK]: Fix us...
1825

7cc056626   Christoph Hellwig   net: remove sock_...
1826
1827
  	memset(&scm, 0, sizeof(scm));
  	scm.creds = *NETLINK_CREDS(skb);
188ccb558   Patrick McHardy   [NETLINK]: Fix us...
1828
  	if (flags & MSG_TRUNC)
68d6ac6d2   Johannes Berg   netlink: fix comp...
1829
  		copied = data_skb->len;
daa3766e7   David S. Miller   Revert "netlink: ...
1830

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1831
  	skb_free_datagram(sk, skb);
16b304f34   Pravin B Shelar   netlink: Eliminat...
1832
1833
  	if (nlk->cb_running &&
  	    atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf / 2) {
b44d211e1   Andrey Vagin   netlink: handle e...
1834
1835
  		ret = netlink_dump(sk);
  		if (ret) {
ac30ef832   Ben Pfaff   netlink: Fix hand...
1836
  			sk->sk_err = -ret;
b44d211e1   Andrey Vagin   netlink: handle e...
1837
1838
1839
  			sk->sk_error_report(sk);
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1840

7cc056626   Christoph Hellwig   net: remove sock_...
1841
  	scm_recv(sock, msg, &scm, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1842
1843
1844
1845
  out:
  	netlink_rcv_wake(sk);
  	return err ? : copied;
  }
676d23690   David S. Miller   net: Fix use afte...
1846
  static void netlink_data_ready(struct sock *sk)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1847
  {
cd40b7d39   Denis V. Lunev   [NET]: make netli...
1848
  	BUG();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1849
1850
1851
  }
  
  /*
746fac4dc   YOSHIFUJI Hideaki   [NET] NETLINK: Fi...
1852
   *	We export these functions to other modules. They provide a
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1853
1854
1855
1856
1857
   *	complete set of kernel non-blocking support for message
   *	queueing.
   */
  
  struct sock *
9f00d9776   Pablo Neira Ayuso   netlink: hide str...
1858
1859
  __netlink_kernel_create(struct net *net, int unit, struct module *module,
  			struct netlink_kernel_cfg *cfg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1860
1861
1862
  {
  	struct socket *sock;
  	struct sock *sk;
77247bbb3   Patrick McHardy   [NETLINK]: Fix mo...
1863
  	struct netlink_sock *nlk;
5c398dc8f   Eric Dumazet   netlink: fix netl...
1864
  	struct listeners *listeners = NULL;
a31f2d17b   Pablo Neira Ayuso   netlink: add netl...
1865
1866
  	struct mutex *cb_mutex = cfg ? cfg->cb_mutex : NULL;
  	unsigned int groups;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1867

fab2caf62   Akinobu Mita   [NETLINK]: Call p...
1868
  	BUG_ON(!nl_table);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1869

6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
1870
  	if (unit < 0 || unit >= MAX_LINKS)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1871
1872
1873
1874
  		return NULL;
  
  	if (sock_create_lite(PF_NETLINK, SOCK_DGRAM, unit, &sock))
  		return NULL;
13d3078e2   Eric W. Biederman   netlink: Create k...
1875
1876
  
  	if (__netlink_create(net, sock, cb_mutex, unit, 1) < 0)
23fe18669   Pavel Emelyanov   [NETNS]: Fix race...
1877
1878
1879
  		goto out_sock_release_nosk;
  
  	sk = sock->sk;
4fdb3bb72   Harald Welte   [NETLINK]: Add pr...
1880

a31f2d17b   Pablo Neira Ayuso   netlink: add netl...
1881
  	if (!cfg || cfg->groups < 32)
4277a083e   Patrick McHardy   [NETLINK]: Add ne...
1882
  		groups = 32;
a31f2d17b   Pablo Neira Ayuso   netlink: add netl...
1883
1884
  	else
  		groups = cfg->groups;
4277a083e   Patrick McHardy   [NETLINK]: Add ne...
1885

5c398dc8f   Eric Dumazet   netlink: fix netl...
1886
  	listeners = kzalloc(sizeof(*listeners) + NLGRPSZ(groups), GFP_KERNEL);
4277a083e   Patrick McHardy   [NETLINK]: Add ne...
1887
1888
  	if (!listeners)
  		goto out_sock_release;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1889
  	sk->sk_data_ready = netlink_data_ready;
a31f2d17b   Pablo Neira Ayuso   netlink: add netl...
1890
1891
  	if (cfg && cfg->input)
  		nlk_sk(sk)->netlink_rcv = cfg->input;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1892

8ea65f4a2   Herbert Xu   netlink: Kill red...
1893
  	if (netlink_insert(sk, 0))
77247bbb3   Patrick McHardy   [NETLINK]: Fix mo...
1894
  		goto out_sock_release;
4fdb3bb72   Harald Welte   [NETLINK]: Add pr...
1895

77247bbb3   Patrick McHardy   [NETLINK]: Fix mo...
1896
  	nlk = nlk_sk(sk);
cc3a572fe   Nicolas Dichtel   netlink: rename p...
1897
  	nlk->flags |= NETLINK_F_KERNEL_SOCKET;
4fdb3bb72   Harald Welte   [NETLINK]: Add pr...
1898

4fdb3bb72   Harald Welte   [NETLINK]: Add pr...
1899
  	netlink_table_grab();
b4b510290   Eric W. Biederman   [NET]: Support mu...
1900
1901
  	if (!nl_table[unit].registered) {
  		nl_table[unit].groups = groups;
5c398dc8f   Eric Dumazet   netlink: fix netl...
1902
  		rcu_assign_pointer(nl_table[unit].listeners, listeners);
b4b510290   Eric W. Biederman   [NET]: Support mu...
1903
1904
  		nl_table[unit].cb_mutex = cb_mutex;
  		nl_table[unit].module = module;
9785e10ae   Pablo Neira Ayuso   netlink: kill net...
1905
1906
  		if (cfg) {
  			nl_table[unit].bind = cfg->bind;
6251edd93   Hiroaki SHIMODA   netlink: Properly...
1907
  			nl_table[unit].unbind = cfg->unbind;
9785e10ae   Pablo Neira Ayuso   netlink: kill net...
1908
  			nl_table[unit].flags = cfg->flags;
da12c90e0   Gao feng   netlink: Add comp...
1909
1910
  			if (cfg->compare)
  				nl_table[unit].compare = cfg->compare;
9785e10ae   Pablo Neira Ayuso   netlink: kill net...
1911
  		}
b4b510290   Eric W. Biederman   [NET]: Support mu...
1912
  		nl_table[unit].registered = 1;
f937f1f46   Jesper Juhl   [NETLINK]: Don't ...
1913
1914
  	} else {
  		kfree(listeners);
869e58f87   Denis V. Lunev   [NETNS]: Double f...
1915
  		nl_table[unit].registered++;
b4b510290   Eric W. Biederman   [NET]: Support mu...
1916
  	}
4fdb3bb72   Harald Welte   [NETLINK]: Add pr...
1917
  	netlink_table_ungrab();
77247bbb3   Patrick McHardy   [NETLINK]: Fix mo...
1918
  	return sk;
4fdb3bb72   Harald Welte   [NETLINK]: Add pr...
1919
  out_sock_release:
4277a083e   Patrick McHardy   [NETLINK]: Add ne...
1920
  	kfree(listeners);
9dfbec1fb   Denis V. Lunev   [NETLINK]: No nee...
1921
  	netlink_kernel_release(sk);
23fe18669   Pavel Emelyanov   [NETNS]: Fix race...
1922
1923
1924
  	return NULL;
  
  out_sock_release_nosk:
4fdb3bb72   Harald Welte   [NETLINK]: Add pr...
1925
  	sock_release(sock);
77247bbb3   Patrick McHardy   [NETLINK]: Fix mo...
1926
  	return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1927
  }
9f00d9776   Pablo Neira Ayuso   netlink: hide str...
1928
  EXPORT_SYMBOL(__netlink_kernel_create);
b7c6ba6eb   Denis V. Lunev   [NETNS]: Consolid...
1929
1930
1931
1932
  
  void
  netlink_kernel_release(struct sock *sk)
  {
13d3078e2   Eric W. Biederman   netlink: Create k...
1933
1934
1935
1936
  	if (sk == NULL || sk->sk_socket == NULL)
  		return;
  
  	sock_release(sk->sk_socket);
b7c6ba6eb   Denis V. Lunev   [NETNS]: Consolid...
1937
1938
  }
  EXPORT_SYMBOL(netlink_kernel_release);
d136f1bd3   Johannes Berg   genetlink: fix ne...
1939
  int __netlink_change_ngroups(struct sock *sk, unsigned int groups)
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
1940
  {
5c398dc8f   Eric Dumazet   netlink: fix netl...
1941
  	struct listeners *new, *old;
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
1942
  	struct netlink_table *tbl = &nl_table[sk->sk_protocol];
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
1943
1944
1945
  
  	if (groups < 32)
  		groups = 32;
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
1946
  	if (NLGRPSZ(tbl->groups) < NLGRPSZ(groups)) {
5c398dc8f   Eric Dumazet   netlink: fix netl...
1947
1948
  		new = kzalloc(sizeof(*new) + NLGRPSZ(groups), GFP_ATOMIC);
  		if (!new)
d136f1bd3   Johannes Berg   genetlink: fix ne...
1949
  			return -ENOMEM;
6d772ac55   Eric Dumazet   netlink: use kfre...
1950
  		old = nl_deref_protected(tbl->listeners);
5c398dc8f   Eric Dumazet   netlink: fix netl...
1951
1952
  		memcpy(new->masks, old->masks, NLGRPSZ(tbl->groups));
  		rcu_assign_pointer(tbl->listeners, new);
37b6b935e   Lai Jiangshan   net,rcu: convert ...
1953
  		kfree_rcu(old, rcu);
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
1954
1955
  	}
  	tbl->groups = groups;
d136f1bd3   Johannes Berg   genetlink: fix ne...
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
  	return 0;
  }
  
  /**
   * netlink_change_ngroups - change number of multicast groups
   *
   * This changes the number of multicast groups that are available
   * on a certain netlink family. Note that it is not possible to
   * change the number of groups to below 32. Also note that it does
   * not implicitly call netlink_clear_multicast_users() when the
   * number of groups is reduced.
   *
   * @sk: The kernel netlink socket, as returned by netlink_kernel_create().
   * @groups: The new number of groups.
   */
  int netlink_change_ngroups(struct sock *sk, unsigned int groups)
  {
  	int err;
  
  	netlink_table_grab();
  	err = __netlink_change_ngroups(sk, groups);
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
1977
  	netlink_table_ungrab();
d136f1bd3   Johannes Berg   genetlink: fix ne...
1978

b4ff4f041   Johannes Berg   [NETLINK]: alloca...
1979
1980
  	return err;
  }
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
1981

b8273570f   Johannes Berg   genetlink: fix ne...
1982
1983
1984
  void __netlink_clear_multicast_users(struct sock *ksk, unsigned int group)
  {
  	struct sock *sk;
b8273570f   Johannes Berg   genetlink: fix ne...
1985
  	struct netlink_table *tbl = &nl_table[ksk->sk_protocol];
b67bfe0d4   Sasha Levin   hlist: drop the n...
1986
  	sk_for_each_bound(sk, &tbl->mc_list)
b8273570f   Johannes Berg   genetlink: fix ne...
1987
1988
  		netlink_update_socket_mc(nlk_sk(sk), group, 0);
  }
a46621a3a   Denys Vlasenko   net: Deinline __n...
1989
  struct nlmsghdr *
15e473046   Eric W. Biederman   netlink: Rename p...
1990
  __nlmsg_put(struct sk_buff *skb, u32 portid, u32 seq, int type, int len, int flags)
a46621a3a   Denys Vlasenko   net: Deinline __n...
1991
1992
  {
  	struct nlmsghdr *nlh;
573ce260b   Hong zhi guo   net-next: replace...
1993
  	int size = nlmsg_msg_size(len);
a46621a3a   Denys Vlasenko   net: Deinline __n...
1994

4df864c1d   Johannes Berg   networking: make ...
1995
  	nlh = skb_put(skb, NLMSG_ALIGN(size));
a46621a3a   Denys Vlasenko   net: Deinline __n...
1996
1997
1998
  	nlh->nlmsg_type = type;
  	nlh->nlmsg_len = size;
  	nlh->nlmsg_flags = flags;
15e473046   Eric W. Biederman   netlink: Rename p...
1999
  	nlh->nlmsg_pid = portid;
a46621a3a   Denys Vlasenko   net: Deinline __n...
2000
2001
  	nlh->nlmsg_seq = seq;
  	if (!__builtin_constant_p(size) || NLMSG_ALIGN(size) - size != 0)
573ce260b   Hong zhi guo   net-next: replace...
2002
  		memset(nlmsg_data(nlh) + len, 0, NLMSG_ALIGN(size) - size);
a46621a3a   Denys Vlasenko   net: Deinline __n...
2003
2004
2005
  	return nlh;
  }
  EXPORT_SYMBOL(__nlmsg_put);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2006
2007
2008
2009
2010
2011
2012
2013
2014
  /*
   * It looks a bit ugly.
   * It would be better to create kernel thread.
   */
  
  static int netlink_dump(struct sock *sk)
  {
  	struct netlink_sock *nlk = nlk_sk(sk);
  	struct netlink_callback *cb;
c7ac8679b   Greg Rose   rtnetlink: Comput...
2015
  	struct sk_buff *skb = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2016
  	struct nlmsghdr *nlh;
92964c79b   Herbert Xu   netlink: Fix dump...
2017
  	struct module *module;
5856c858c   Jason A. Donenfeld   af_netlink: ensur...
2018
  	int err = -ENOBUFS;
db65a3aaf   Arad, Ronen   netlink: Trim skb...
2019
  	int alloc_min_size;
c7ac8679b   Greg Rose   rtnetlink: Comput...
2020
  	int alloc_size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2021

af65bdfce   Patrick McHardy   [NETLINK]: Switch...
2022
  	mutex_lock(nlk->cb_mutex);
16b304f34   Pravin B Shelar   netlink: Eliminat...
2023
  	if (!nlk->cb_running) {
bf8b79e44   Thomas Graf   [NETLINK]: Conver...
2024
2025
  		err = -EINVAL;
  		goto errout_skb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2026
  	}
d1b4c689d   Florian Westphal   netlink: remove m...
2027
  	if (atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf)
f9c228883   Patrick McHardy   netlink: implemen...
2028
  		goto errout_skb;
9063e21fb   Eric Dumazet   netlink: autosize...
2029
2030
2031
2032
2033
2034
  
  	/* NLMSG_GOODSIZE is small to avoid high order allocations being
  	 * required, but it makes sense to _attempt_ a 16K bytes allocation
  	 * to reduce number of system calls on dump operations, if user
  	 * ever provided a big enough buffer.
  	 */
db65a3aaf   Arad, Ronen   netlink: Trim skb...
2035
2036
2037
2038
2039
  	cb = &nlk->cb;
  	alloc_min_size = max_t(int, cb->min_dump_alloc, NLMSG_GOODSIZE);
  
  	if (alloc_min_size < nlk->max_recvmsg_len) {
  		alloc_size = nlk->max_recvmsg_len;
d35c99ff7   Eric Dumazet   netlink: do not e...
2040
2041
2042
  		skb = alloc_skb(alloc_size,
  				(GFP_KERNEL & ~__GFP_DIRECT_RECLAIM) |
  				__GFP_NOWARN | __GFP_NORETRY);
9063e21fb   Eric Dumazet   netlink: autosize...
2043
  	}
db65a3aaf   Arad, Ronen   netlink: Trim skb...
2044
2045
  	if (!skb) {
  		alloc_size = alloc_min_size;
c5b0db326   Florian Westphal   nfnetlink: Revert...
2046
  		skb = alloc_skb(alloc_size, GFP_KERNEL);
db65a3aaf   Arad, Ronen   netlink: Trim skb...
2047
  	}
c7ac8679b   Greg Rose   rtnetlink: Comput...
2048
  	if (!skb)
c63d6ea30   Dan Carpenter   rtnetlink: unlock...
2049
  		goto errout_skb;
db65a3aaf   Arad, Ronen   netlink: Trim skb...
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
  
  	/* Trim skb to allocated size. User is expected to provide buffer as
  	 * large as max(min_dump_alloc, 16KiB (mac_recvmsg_len capped at
  	 * netlink_recvmsg())). dump will pack as many smaller messages as
  	 * could fit within the allocated skb. skb is typically allocated
  	 * with larger space than required (could be as much as near 2x the
  	 * requested size with align to next power of 2 approach). Allowing
  	 * dump to use the excess space makes it difficult for a user to have a
  	 * reasonable static buffer based on the expected largest dump of a
  	 * single netdev. The outcome is MSG_TRUNC error.
  	 */
d1b4c689d   Florian Westphal   netlink: remove m...
2061
  	skb_reserve(skb, skb_tailroom(skb) - alloc_size);
f9c228883   Patrick McHardy   netlink: implemen...
2062
  	netlink_skb_set_owner_r(skb, sk);
c7ac8679b   Greg Rose   rtnetlink: Comput...
2063

5856c858c   Jason A. Donenfeld   af_netlink: ensur...
2064
2065
  	if (nlk->dump_done_errno > 0)
  		nlk->dump_done_errno = cb->dump(skb, cb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2066

5856c858c   Jason A. Donenfeld   af_netlink: ensur...
2067
2068
  	if (nlk->dump_done_errno > 0 ||
  	    skb_tailroom(skb) < nlmsg_total_size(sizeof(nlk->dump_done_errno))) {
af65bdfce   Patrick McHardy   [NETLINK]: Switch...
2069
  		mutex_unlock(nlk->cb_mutex);
b1153f29e   Stephen Hemminger   netlink: make soc...
2070
2071
2072
  
  		if (sk_filter(sk, skb))
  			kfree_skb(skb);
4a7e7c2ad   Eric Dumazet   netlink: fix race...
2073
2074
  		else
  			__netlink_sendskb(sk, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2075
2076
  		return 0;
  	}
5856c858c   Jason A. Donenfeld   af_netlink: ensur...
2077
2078
2079
  	nlh = nlmsg_put_answer(skb, cb, NLMSG_DONE,
  			       sizeof(nlk->dump_done_errno), NLM_F_MULTI);
  	if (WARN_ON(!nlh))
bf8b79e44   Thomas Graf   [NETLINK]: Conver...
2080
  		goto errout_skb;
670dc2833   Johannes Berg   netlink: advertis...
2081
  	nl_dump_check_consistent(cb, nlh);
5856c858c   Jason A. Donenfeld   af_netlink: ensur...
2082
2083
  	memcpy(nlmsg_data(nlh), &nlk->dump_done_errno,
  	       sizeof(nlk->dump_done_errno));
bf8b79e44   Thomas Graf   [NETLINK]: Conver...
2084

b1153f29e   Stephen Hemminger   netlink: make soc...
2085
2086
  	if (sk_filter(sk, skb))
  		kfree_skb(skb);
4a7e7c2ad   Eric Dumazet   netlink: fix race...
2087
2088
  	else
  		__netlink_sendskb(sk, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2089

a8f74b228   Thomas Graf   [NETLINK]: Make n...
2090
2091
  	if (cb->done)
  		cb->done(cb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2092

16b304f34   Pravin B Shelar   netlink: Eliminat...
2093
  	nlk->cb_running = false;
92964c79b   Herbert Xu   netlink: Fix dump...
2094
2095
  	module = cb->module;
  	skb = cb->skb;
16b304f34   Pravin B Shelar   netlink: Eliminat...
2096
  	mutex_unlock(nlk->cb_mutex);
92964c79b   Herbert Xu   netlink: Fix dump...
2097
2098
  	module_put(module);
  	consume_skb(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2099
  	return 0;
1797754ea   Thomas Graf   [NETLINK]: Introd...
2100

bf8b79e44   Thomas Graf   [NETLINK]: Conver...
2101
  errout_skb:
af65bdfce   Patrick McHardy   [NETLINK]: Switch...
2102
  	mutex_unlock(nlk->cb_mutex);
bf8b79e44   Thomas Graf   [NETLINK]: Conver...
2103
  	kfree_skb(skb);
bf8b79e44   Thomas Graf   [NETLINK]: Conver...
2104
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2105
  }
6dc878a8c   Gao feng   netlink: add refe...
2106
2107
2108
  int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
  			 const struct nlmsghdr *nlh,
  			 struct netlink_dump_control *control)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2109
2110
2111
2112
  {
  	struct netlink_callback *cb;
  	struct sock *sk;
  	struct netlink_sock *nlk;
b44d211e1   Andrey Vagin   netlink: handle e...
2113
  	int ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2114

633547973   Reshetova, Elena   net: convert sk_b...
2115
  	refcount_inc(&skb->users);
f9c228883   Patrick McHardy   netlink: implemen...
2116

15e473046   Eric W. Biederman   netlink: Rename p...
2117
  	sk = netlink_lookup(sock_net(ssk), ssk->sk_protocol, NETLINK_CB(skb).portid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2118
  	if (sk == NULL) {
16b304f34   Pravin B Shelar   netlink: Eliminat...
2119
2120
  		ret = -ECONNREFUSED;
  		goto error_free;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2121
  	}
6dc878a8c   Gao feng   netlink: add refe...
2122

16b304f34   Pravin B Shelar   netlink: Eliminat...
2123
  	nlk = nlk_sk(sk);
af65bdfce   Patrick McHardy   [NETLINK]: Switch...
2124
  	mutex_lock(nlk->cb_mutex);
6dc878a8c   Gao feng   netlink: add refe...
2125
  	/* A dump is in progress... */
16b304f34   Pravin B Shelar   netlink: Eliminat...
2126
  	if (nlk->cb_running) {
6dc878a8c   Gao feng   netlink: add refe...
2127
  		ret = -EBUSY;
16b304f34   Pravin B Shelar   netlink: Eliminat...
2128
  		goto error_unlock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2129
  	}
6dc878a8c   Gao feng   netlink: add refe...
2130
  	/* add reference of module which cb->dump belongs to */
16b304f34   Pravin B Shelar   netlink: Eliminat...
2131
  	if (!try_module_get(control->module)) {
6dc878a8c   Gao feng   netlink: add refe...
2132
  		ret = -EPROTONOSUPPORT;
16b304f34   Pravin B Shelar   netlink: Eliminat...
2133
  		goto error_unlock;
6dc878a8c   Gao feng   netlink: add refe...
2134
  	}
16b304f34   Pravin B Shelar   netlink: Eliminat...
2135
2136
  	cb = &nlk->cb;
  	memset(cb, 0, sizeof(*cb));
fc9e50f5a   Tom Herbert   netlink: add a st...
2137
  	cb->start = control->start;
16b304f34   Pravin B Shelar   netlink: Eliminat...
2138
2139
2140
2141
2142
2143
2144
  	cb->dump = control->dump;
  	cb->done = control->done;
  	cb->nlh = nlh;
  	cb->data = control->data;
  	cb->module = control->module;
  	cb->min_dump_alloc = control->min_dump_alloc;
  	cb->skb = skb;
41c87425a   Jason A. Donenfeld   netlink: do not s...
2145
2146
2147
  	if (cb->start) {
  		ret = cb->start(cb);
  		if (ret)
eec434c57   Jason A. Donenfeld   netlink: put modu...
2148
  			goto error_put;
41c87425a   Jason A. Donenfeld   netlink: do not s...
2149
  	}
16b304f34   Pravin B Shelar   netlink: Eliminat...
2150
  	nlk->cb_running = true;
5856c858c   Jason A. Donenfeld   af_netlink: ensur...
2151
  	nlk->dump_done_errno = INT_MAX;
16b304f34   Pravin B Shelar   netlink: Eliminat...
2152

af65bdfce   Patrick McHardy   [NETLINK]: Switch...
2153
  	mutex_unlock(nlk->cb_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2154

41c87425a   Jason A. Donenfeld   netlink: do not s...
2155
  	ret = netlink_dump(sk);
fc9e50f5a   Tom Herbert   netlink: add a st...
2156

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2157
  	sock_put(sk);
5c58298c2   Denis V. Lunev   [NETLINK]: Fix AC...
2158

b44d211e1   Andrey Vagin   netlink: handle e...
2159
2160
  	if (ret)
  		return ret;
5c58298c2   Denis V. Lunev   [NETLINK]: Fix AC...
2161
2162
2163
2164
  	/* We successfully started a dump, by returning -EINTR we
  	 * signal not to send ACK even if it was requested.
  	 */
  	return -EINTR;
16b304f34   Pravin B Shelar   netlink: Eliminat...
2165

eec434c57   Jason A. Donenfeld   netlink: put modu...
2166
2167
  error_put:
  	module_put(control->module);
16b304f34   Pravin B Shelar   netlink: Eliminat...
2168
2169
2170
2171
2172
2173
  error_unlock:
  	sock_put(sk);
  	mutex_unlock(nlk->cb_mutex);
  error_free:
  	kfree_skb(skb);
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2174
  }
6dc878a8c   Gao feng   netlink: add refe...
2175
  EXPORT_SYMBOL(__netlink_dump_start);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2176

2d4bc9336   Johannes Berg   netlink: extended...
2177
2178
  void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err,
  		 const struct netlink_ext_ack *extack)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2179
2180
2181
2182
  {
  	struct sk_buff *skb;
  	struct nlmsghdr *rep;
  	struct nlmsgerr *errmsg;
339bf98ff   Thomas Graf   [NETLINK]: Do pre...
2183
  	size_t payload = sizeof(*errmsg);
2d4bc9336   Johannes Berg   netlink: extended...
2184
  	size_t tlvlen = 0;
0a6a3a23e   Christophe Ricard   netlink: add NETL...
2185
  	struct netlink_sock *nlk = nlk_sk(NETLINK_CB(in_skb).sk);
2d4bc9336   Johannes Berg   netlink: extended...
2186
  	unsigned int flags = 0;
48044eb49   Johannes Berg   netlink: fix netl...
2187
  	bool nlk_has_extack = nlk->flags & NETLINK_F_EXT_ACK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2188

0a6a3a23e   Christophe Ricard   netlink: add NETL...
2189
  	/* Error messages get the original request appened, unless the user
2d4bc9336   Johannes Berg   netlink: extended...
2190
2191
  	 * requests to cap the error message, and get extra error data if
  	 * requested.
0a6a3a23e   Christophe Ricard   netlink: add NETL...
2192
  	 */
2d4bc9336   Johannes Berg   netlink: extended...
2193
2194
2195
2196
2197
  	if (err) {
  		if (!(nlk->flags & NETLINK_F_CAP_ACK))
  			payload += nlmsg_len(nlh);
  		else
  			flags |= NLM_F_CAPPED;
48044eb49   Johannes Berg   netlink: fix netl...
2198
  		if (nlk_has_extack && extack) {
2d4bc9336   Johannes Berg   netlink: extended...
2199
2200
2201
2202
2203
2204
2205
  			if (extack->_msg)
  				tlvlen += nla_total_size(strlen(extack->_msg) + 1);
  			if (extack->bad_attr)
  				tlvlen += nla_total_size(sizeof(u32));
  		}
  	} else {
  		flags |= NLM_F_CAPPED;
ba0dc5f6e   Johannes Berg   netlink: allow se...
2206

48044eb49   Johannes Berg   netlink: fix netl...
2207
  		if (nlk_has_extack && extack && extack->cookie_len)
ba0dc5f6e   Johannes Berg   netlink: allow se...
2208
  			tlvlen += nla_total_size(extack->cookie_len);
2d4bc9336   Johannes Berg   netlink: extended...
2209
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2210

2d4bc9336   Johannes Berg   netlink: extended...
2211
2212
2213
2214
  	if (tlvlen)
  		flags |= NLM_F_ACK_TLVS;
  
  	skb = nlmsg_new(payload + tlvlen, GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2215
2216
  	if (!skb) {
  		struct sock *sk;
3b1e0a655   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
2217
  		sk = netlink_lookup(sock_net(in_skb->sk),
b4b510290   Eric W. Biederman   [NET]: Support mu...
2218
  				    in_skb->sk->sk_protocol,
15e473046   Eric W. Biederman   netlink: Rename p...
2219
  				    NETLINK_CB(in_skb).portid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2220
2221
2222
2223
2224
2225
2226
  		if (sk) {
  			sk->sk_err = ENOBUFS;
  			sk->sk_error_report(sk);
  			sock_put(sk);
  		}
  		return;
  	}
15e473046   Eric W. Biederman   netlink: Rename p...
2227
  	rep = __nlmsg_put(skb, NETLINK_CB(in_skb).portid, nlh->nlmsg_seq,
2d4bc9336   Johannes Berg   netlink: extended...
2228
  			  NLMSG_ERROR, payload, flags);
bf8b79e44   Thomas Graf   [NETLINK]: Conver...
2229
  	errmsg = nlmsg_data(rep);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2230
  	errmsg->error = err;
0a6a3a23e   Christophe Ricard   netlink: add NETL...
2231
  	memcpy(&errmsg->msg, nlh, payload > sizeof(*errmsg) ? nlh->nlmsg_len : sizeof(*nlh));
2d4bc9336   Johannes Berg   netlink: extended...
2232

48044eb49   Johannes Berg   netlink: fix netl...
2233
  	if (nlk_has_extack && extack) {
ba0dc5f6e   Johannes Berg   netlink: allow se...
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
  		if (err) {
  			if (extack->_msg)
  				WARN_ON(nla_put_string(skb, NLMSGERR_ATTR_MSG,
  						       extack->_msg));
  			if (extack->bad_attr &&
  			    !WARN_ON((u8 *)extack->bad_attr < in_skb->data ||
  				     (u8 *)extack->bad_attr >= in_skb->data +
  							       in_skb->len))
  				WARN_ON(nla_put_u32(skb, NLMSGERR_ATTR_OFFS,
  						    (u8 *)extack->bad_attr -
  						    in_skb->data));
  		} else {
  			if (extack->cookie_len)
  				WARN_ON(nla_put(skb, NLMSGERR_ATTR_COOKIE,
  						extack->cookie_len,
  						extack->cookie));
  		}
2d4bc9336   Johannes Berg   netlink: extended...
2251
2252
2253
  	}
  
  	nlmsg_end(skb, rep);
15e473046   Eric W. Biederman   netlink: Rename p...
2254
  	netlink_unicast(in_skb->sk, skb, NETLINK_CB(in_skb).portid, MSG_DONTWAIT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2255
  }
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
2256
  EXPORT_SYMBOL(netlink_ack);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2257

cd40b7d39   Denis V. Lunev   [NET]: make netli...
2258
  int netlink_rcv_skb(struct sk_buff *skb, int (*cb)(struct sk_buff *,
2d4bc9336   Johannes Berg   netlink: extended...
2259
2260
  						   struct nlmsghdr *,
  						   struct netlink_ext_ack *))
82ace47a7   Thomas Graf   [NETLINK]: Generi...
2261
  {
3eae0ba8c   David Ahern   netlink: extack n...
2262
  	struct netlink_ext_ack extack;
82ace47a7   Thomas Graf   [NETLINK]: Generi...
2263
2264
2265
2266
  	struct nlmsghdr *nlh;
  	int err;
  
  	while (skb->len >= nlmsg_total_size(0)) {
cd40b7d39   Denis V. Lunev   [NET]: make netli...
2267
  		int msglen;
48606bb1e   Xin Long   netlink: reset ex...
2268
  		memset(&extack, 0, sizeof(extack));
b529ccf27   Arnaldo Carvalho de Melo   [NETLINK]: Introd...
2269
  		nlh = nlmsg_hdr(skb);
d35b68564   Thomas Graf   [NETLINK]: Ignore...
2270
  		err = 0;
82ace47a7   Thomas Graf   [NETLINK]: Generi...
2271

ad8e4b75c   Martin Murray   [AF_NETLINK]: Fix...
2272
  		if (nlh->nlmsg_len < NLMSG_HDRLEN || skb->len < nlh->nlmsg_len)
82ace47a7   Thomas Graf   [NETLINK]: Generi...
2273
  			return 0;
d35b68564   Thomas Graf   [NETLINK]: Ignore...
2274
2275
  		/* Only requests are handled by the kernel */
  		if (!(nlh->nlmsg_flags & NLM_F_REQUEST))
5c58298c2   Denis V. Lunev   [NETLINK]: Fix AC...
2276
  			goto ack;
45e7ae7f7   Thomas Graf   [NETLINK]: Ignore...
2277
2278
2279
  
  		/* Skip control messages */
  		if (nlh->nlmsg_type < NLMSG_MIN_TYPE)
5c58298c2   Denis V. Lunev   [NETLINK]: Fix AC...
2280
  			goto ack;
d35b68564   Thomas Graf   [NETLINK]: Ignore...
2281

2d4bc9336   Johannes Berg   netlink: extended...
2282
  		err = cb(skb, nlh, &extack);
5c58298c2   Denis V. Lunev   [NETLINK]: Fix AC...
2283
2284
2285
2286
  		if (err == -EINTR)
  			goto skip;
  
  ack:
d35b68564   Thomas Graf   [NETLINK]: Ignore...
2287
  		if (nlh->nlmsg_flags & NLM_F_ACK || err)
2d4bc9336   Johannes Berg   netlink: extended...
2288
  			netlink_ack(skb, nlh, err, &extack);
82ace47a7   Thomas Graf   [NETLINK]: Generi...
2289

5c58298c2   Denis V. Lunev   [NETLINK]: Fix AC...
2290
  skip:
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
2291
  		msglen = NLMSG_ALIGN(nlh->nlmsg_len);
cd40b7d39   Denis V. Lunev   [NET]: make netli...
2292
2293
2294
  		if (msglen > skb->len)
  			msglen = skb->len;
  		skb_pull(skb, msglen);
82ace47a7   Thomas Graf   [NETLINK]: Generi...
2295
2296
2297
2298
  	}
  
  	return 0;
  }
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
2299
  EXPORT_SYMBOL(netlink_rcv_skb);
82ace47a7   Thomas Graf   [NETLINK]: Generi...
2300
2301
  
  /**
d387f6ad1   Thomas Graf   [NETLINK]: Add no...
2302
2303
2304
   * nlmsg_notify - send a notification netlink message
   * @sk: netlink socket to use
   * @skb: notification message
15e473046   Eric W. Biederman   netlink: Rename p...
2305
   * @portid: destination netlink portid for reports or 0
d387f6ad1   Thomas Graf   [NETLINK]: Add no...
2306
2307
2308
2309
   * @group: destination multicast group or 0
   * @report: 1 to report back, 0 to disable
   * @flags: allocation flags
   */
15e473046   Eric W. Biederman   netlink: Rename p...
2310
  int nlmsg_notify(struct sock *sk, struct sk_buff *skb, u32 portid,
d387f6ad1   Thomas Graf   [NETLINK]: Add no...
2311
2312
2313
2314
2315
  		 unsigned int group, int report, gfp_t flags)
  {
  	int err = 0;
  
  	if (group) {
15e473046   Eric W. Biederman   netlink: Rename p...
2316
  		int exclude_portid = 0;
d387f6ad1   Thomas Graf   [NETLINK]: Add no...
2317
2318
  
  		if (report) {
633547973   Reshetova, Elena   net: convert sk_b...
2319
  			refcount_inc(&skb->users);
15e473046   Eric W. Biederman   netlink: Rename p...
2320
  			exclude_portid = portid;
d387f6ad1   Thomas Graf   [NETLINK]: Add no...
2321
  		}
1ce85fe40   Pablo Neira Ayuso   netlink: change n...
2322
2323
  		/* errors reported via destination sk->sk_err, but propagate
  		 * delivery errors if NETLINK_BROADCAST_ERROR flag is set */
15e473046   Eric W. Biederman   netlink: Rename p...
2324
  		err = nlmsg_multicast(sk, skb, exclude_portid, group, flags);
d387f6ad1   Thomas Graf   [NETLINK]: Add no...
2325
  	}
1ce85fe40   Pablo Neira Ayuso   netlink: change n...
2326
2327
  	if (report) {
  		int err2;
15e473046   Eric W. Biederman   netlink: Rename p...
2328
  		err2 = nlmsg_unicast(sk, skb, portid);
1ce85fe40   Pablo Neira Ayuso   netlink: change n...
2329
2330
2331
  		if (!err || err == -ESRCH)
  			err = err2;
  	}
d387f6ad1   Thomas Graf   [NETLINK]: Add no...
2332
2333
2334
  
  	return err;
  }
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
2335
  EXPORT_SYMBOL(nlmsg_notify);
d387f6ad1   Thomas Graf   [NETLINK]: Add no...
2336

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2337
2338
  #ifdef CONFIG_PROC_FS
  struct nl_seq_iter {
e372c4140   Denis V. Lunev   [NET]: Consolidat...
2339
  	struct seq_net_private p;
56d28b1e9   Herbert Xu   netlink: Use rhas...
2340
  	struct rhashtable_iter hti;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2341
  	int link;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2342
  };
56d28b1e9   Herbert Xu   netlink: Use rhas...
2343
  static int netlink_walk_start(struct nl_seq_iter *iter)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2344
  {
56d28b1e9   Herbert Xu   netlink: Use rhas...
2345
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2346

8f6fd83c6   Bob Copeland   rhashtable: accep...
2347
2348
  	err = rhashtable_walk_init(&nl_table[iter->link].hash, &iter->hti,
  				   GFP_KERNEL);
56d28b1e9   Herbert Xu   netlink: Use rhas...
2349
2350
2351
  	if (err) {
  		iter->link = MAX_LINKS;
  		return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2352
  	}
56d28b1e9   Herbert Xu   netlink: Use rhas...
2353
2354
2355
  
  	err = rhashtable_walk_start(&iter->hti);
  	return err == -EAGAIN ? 0 : err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2356
  }
56d28b1e9   Herbert Xu   netlink: Use rhas...
2357
  static void netlink_walk_stop(struct nl_seq_iter *iter)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2358
  {
56d28b1e9   Herbert Xu   netlink: Use rhas...
2359
2360
  	rhashtable_walk_stop(&iter->hti);
  	rhashtable_walk_exit(&iter->hti);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2361
  }
56d28b1e9   Herbert Xu   netlink: Use rhas...
2362
  static void *__netlink_seq_next(struct seq_file *seq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2363
  {
56d28b1e9   Herbert Xu   netlink: Use rhas...
2364
  	struct nl_seq_iter *iter = seq->private;
e341694e3   Thomas Graf   netlink: Convert ...
2365
  	struct netlink_sock *nlk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2366

56d28b1e9   Herbert Xu   netlink: Use rhas...
2367
2368
2369
  	do {
  		for (;;) {
  			int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2370

56d28b1e9   Herbert Xu   netlink: Use rhas...
2371
  			nlk = rhashtable_walk_next(&iter->hti);
746fac4dc   YOSHIFUJI Hideaki   [NET] NETLINK: Fi...
2372

56d28b1e9   Herbert Xu   netlink: Use rhas...
2373
2374
2375
  			if (IS_ERR(nlk)) {
  				if (PTR_ERR(nlk) == -EAGAIN)
  					continue;
e341694e3   Thomas Graf   netlink: Convert ...
2376

56d28b1e9   Herbert Xu   netlink: Use rhas...
2377
2378
  				return nlk;
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2379

56d28b1e9   Herbert Xu   netlink: Use rhas...
2380
2381
  			if (nlk)
  				break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2382

56d28b1e9   Herbert Xu   netlink: Use rhas...
2383
2384
2385
  			netlink_walk_stop(iter);
  			if (++iter->link >= MAX_LINKS)
  				return NULL;
da12c90e0   Gao feng   netlink: Add comp...
2386

56d28b1e9   Herbert Xu   netlink: Use rhas...
2387
2388
2389
  			err = netlink_walk_start(iter);
  			if (err)
  				return ERR_PTR(err);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2390
  		}
56d28b1e9   Herbert Xu   netlink: Use rhas...
2391
  	} while (sock_net(&nlk->sk) != seq_file_net(seq));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2392

56d28b1e9   Herbert Xu   netlink: Use rhas...
2393
2394
  	return nlk;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2395

56d28b1e9   Herbert Xu   netlink: Use rhas...
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
  static void *netlink_seq_start(struct seq_file *seq, loff_t *posp)
  {
  	struct nl_seq_iter *iter = seq->private;
  	void *obj = SEQ_START_TOKEN;
  	loff_t pos;
  	int err;
  
  	iter->link = 0;
  
  	err = netlink_walk_start(iter);
  	if (err)
  		return ERR_PTR(err);
  
  	for (pos = *posp; pos && obj && !IS_ERR(obj); pos--)
  		obj = __netlink_seq_next(seq);
  
  	return obj;
  }
  
  static void *netlink_seq_next(struct seq_file *seq, void *v, loff_t *pos)
  {
  	++*pos;
  	return __netlink_seq_next(seq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2419
2420
2421
2422
  }
  
  static void netlink_seq_stop(struct seq_file *seq, void *v)
  {
56d28b1e9   Herbert Xu   netlink: Use rhas...
2423
2424
2425
2426
2427
2428
  	struct nl_seq_iter *iter = seq->private;
  
  	if (iter->link >= MAX_LINKS)
  		return;
  
  	netlink_walk_stop(iter);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2429
2430
2431
2432
2433
  }
  
  
  static int netlink_seq_show(struct seq_file *seq, void *v)
  {
658cb354e   Eric Dumazet   af_netlink: cleanups
2434
  	if (v == SEQ_START_TOKEN) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2435
2436
  		seq_puts(seq,
  			 "sk       Eth Pid    Groups   "
cf0aa4e07   Masatake YAMATO   netlink: Adding i...
2437
2438
  			 "Rmem     Wmem     Dump     Locks     Drops     Inode
  ");
658cb354e   Eric Dumazet   af_netlink: cleanups
2439
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2440
2441
  		struct sock *s = v;
  		struct netlink_sock *nlk = nlk_sk(s);
16b304f34   Pravin B Shelar   netlink: Eliminat...
2442
2443
  		seq_printf(seq, "%pK %-3d %-6u %08x %-8d %-8d %d %-8d %-8d %-8lu
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2444
2445
  			   s,
  			   s->sk_protocol,
15e473046   Eric W. Biederman   netlink: Rename p...
2446
  			   nlk->portid,
513c25000   Patrick McHardy   [NETLINK]: Don't ...
2447
  			   nlk->groups ? (u32)nlk->groups[0] : 0,
31e6d363a   Eric Dumazet   net: correct off-...
2448
2449
  			   sk_rmem_alloc_get(s),
  			   sk_wmem_alloc_get(s),
16b304f34   Pravin B Shelar   netlink: Eliminat...
2450
  			   nlk->cb_running,
41c6d650f   Reshetova, Elena   net: convert sock...
2451
  			   refcount_read(&s->sk_refcnt),
cf0aa4e07   Masatake YAMATO   netlink: Adding i...
2452
2453
  			   atomic_read(&s->sk_drops),
  			   sock_i_ino(s)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2454
2455
2456
2457
2458
  			);
  
  	}
  	return 0;
  }
56b3d975b   Philippe De Muyter   [NET]: Make all i...
2459
  static const struct seq_operations netlink_seq_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2460
2461
2462
2463
2464
2465
2466
2467
2468
  	.start  = netlink_seq_start,
  	.next   = netlink_seq_next,
  	.stop   = netlink_seq_stop,
  	.show   = netlink_seq_show,
  };
  
  
  static int netlink_seq_open(struct inode *inode, struct file *file)
  {
e372c4140   Denis V. Lunev   [NET]: Consolidat...
2469
2470
  	return seq_open_net(inode, file, &netlink_seq_ops,
  				sizeof(struct nl_seq_iter));
b4b510290   Eric W. Biederman   [NET]: Support mu...
2471
  }
da7071d7e   Arjan van de Ven   [PATCH] mark stru...
2472
  static const struct file_operations netlink_seq_fops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2473
2474
2475
2476
  	.owner		= THIS_MODULE,
  	.open		= netlink_seq_open,
  	.read		= seq_read,
  	.llseek		= seq_lseek,
e372c4140   Denis V. Lunev   [NET]: Consolidat...
2477
  	.release	= seq_release_net,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2478
2479
2480
2481
2482
2483
  };
  
  #endif
  
  int netlink_register_notifier(struct notifier_block *nb)
  {
efa172f42   WANG Cong   netlink: use bloc...
2484
  	return blocking_notifier_chain_register(&netlink_chain, nb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2485
  }
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
2486
  EXPORT_SYMBOL(netlink_register_notifier);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2487
2488
2489
  
  int netlink_unregister_notifier(struct notifier_block *nb)
  {
efa172f42   WANG Cong   netlink: use bloc...
2490
  	return blocking_notifier_chain_unregister(&netlink_chain, nb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2491
  }
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
2492
  EXPORT_SYMBOL(netlink_unregister_notifier);
746fac4dc   YOSHIFUJI Hideaki   [NET] NETLINK: Fi...
2493

90ddc4f04   Eric Dumazet   [NET]: move struc...
2494
  static const struct proto_ops netlink_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2495
2496
2497
2498
2499
2500
2501
2502
  	.family =	PF_NETLINK,
  	.owner =	THIS_MODULE,
  	.release =	netlink_release,
  	.bind =		netlink_bind,
  	.connect =	netlink_connect,
  	.socketpair =	sock_no_socketpair,
  	.accept =	sock_no_accept,
  	.getname =	netlink_getname,
d1b4c689d   Florian Westphal   netlink: remove m...
2503
  	.poll =		datagram_poll,
025c68186   David Decotigny   netlink: add supp...
2504
  	.ioctl =	netlink_ioctl,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2505
2506
  	.listen =	sock_no_listen,
  	.shutdown =	sock_no_shutdown,
9a4595bc7   Patrick McHardy   [NETLINK]: Add se...
2507
2508
  	.setsockopt =	netlink_setsockopt,
  	.getsockopt =	netlink_getsockopt,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2509
2510
  	.sendmsg =	netlink_sendmsg,
  	.recvmsg =	netlink_recvmsg,
d1b4c689d   Florian Westphal   netlink: remove m...
2511
  	.mmap =		sock_no_mmap,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2512
2513
  	.sendpage =	sock_no_sendpage,
  };
ec1b4cf74   Stephen Hemminger   net: mark net_pro...
2514
  static const struct net_proto_family netlink_family_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2515
2516
2517
2518
  	.family = PF_NETLINK,
  	.create = netlink_create,
  	.owner	= THIS_MODULE,	/* for consistency 8) */
  };
4665079cb   Pavel Emelyanov   [NETNS]: Move som...
2519
  static int __net_init netlink_net_init(struct net *net)
b4b510290   Eric W. Biederman   [NET]: Support mu...
2520
2521
  {
  #ifdef CONFIG_PROC_FS
d4beaa66a   Gao feng   net: proc: change...
2522
  	if (!proc_create("netlink", 0, net->proc_net, &netlink_seq_fops))
b4b510290   Eric W. Biederman   [NET]: Support mu...
2523
2524
2525
2526
  		return -ENOMEM;
  #endif
  	return 0;
  }
4665079cb   Pavel Emelyanov   [NETNS]: Move som...
2527
  static void __net_exit netlink_net_exit(struct net *net)
b4b510290   Eric W. Biederman   [NET]: Support mu...
2528
2529
  {
  #ifdef CONFIG_PROC_FS
ece31ffd5   Gao feng   net: proc: change...
2530
  	remove_proc_entry("netlink", net->proc_net);
b4b510290   Eric W. Biederman   [NET]: Support mu...
2531
2532
  #endif
  }
b963ea89f   David S. Miller   netlink: Make NET...
2533
2534
  static void __init netlink_add_usersock_entry(void)
  {
5c398dc8f   Eric Dumazet   netlink: fix netl...
2535
  	struct listeners *listeners;
b963ea89f   David S. Miller   netlink: Make NET...
2536
  	int groups = 32;
5c398dc8f   Eric Dumazet   netlink: fix netl...
2537
  	listeners = kzalloc(sizeof(*listeners) + NLGRPSZ(groups), GFP_KERNEL);
b963ea89f   David S. Miller   netlink: Make NET...
2538
  	if (!listeners)
5c398dc8f   Eric Dumazet   netlink: fix netl...
2539
2540
  		panic("netlink_add_usersock_entry: Cannot allocate listeners
  ");
b963ea89f   David S. Miller   netlink: Make NET...
2541
2542
2543
2544
  
  	netlink_table_grab();
  
  	nl_table[NETLINK_USERSOCK].groups = groups;
5c398dc8f   Eric Dumazet   netlink: fix netl...
2545
  	rcu_assign_pointer(nl_table[NETLINK_USERSOCK].listeners, listeners);
b963ea89f   David S. Miller   netlink: Make NET...
2546
2547
  	nl_table[NETLINK_USERSOCK].module = THIS_MODULE;
  	nl_table[NETLINK_USERSOCK].registered = 1;
9785e10ae   Pablo Neira Ayuso   netlink: kill net...
2548
  	nl_table[NETLINK_USERSOCK].flags = NL_CFG_F_NONROOT_SEND;
b963ea89f   David S. Miller   netlink: Make NET...
2549
2550
2551
  
  	netlink_table_ungrab();
  }
022cbae61   Denis V. Lunev   [NET]: Move unnee...
2552
  static struct pernet_operations __net_initdata netlink_net_ops = {
b4b510290   Eric W. Biederman   [NET]: Support mu...
2553
2554
2555
  	.init = netlink_net_init,
  	.exit = netlink_net_exit,
  };
49f7b33e6   Patrick McHardy   rhashtable: provi...
2556
  static inline u32 netlink_hash(const void *data, u32 len, u32 seed)
c428ecd1a   Herbert Xu   netlink: Move nam...
2557
2558
2559
  {
  	const struct netlink_sock *nlk = data;
  	struct netlink_compare_arg arg;
da314c992   Herbert Xu   netlink: Replace ...
2560
  	netlink_compare_arg_init(&arg, sock_net(&nlk->sk), nlk->portid);
11b58ba14   Herbert Xu   netlink: Use defa...
2561
  	return jhash2((u32 *)&arg, netlink_compare_arg_len / sizeof(u32), seed);
c428ecd1a   Herbert Xu   netlink: Move nam...
2562
2563
2564
2565
2566
  }
  
  static const struct rhashtable_params netlink_rhashtable_params = {
  	.head_offset = offsetof(struct netlink_sock, node),
  	.key_len = netlink_compare_arg_len,
c428ecd1a   Herbert Xu   netlink: Move nam...
2567
2568
  	.obj_hashfn = netlink_hash,
  	.obj_cmpfn = netlink_compare,
b5e2c150a   Thomas Graf   rhashtable: Disab...
2569
  	.automatic_shrinking = true,
c428ecd1a   Herbert Xu   netlink: Move nam...
2570
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2571
2572
  static int __init netlink_proto_init(void)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2573
  	int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2574
2575
2576
2577
  	int err = proto_register(&netlink_proto, 0);
  
  	if (err != 0)
  		goto out;
fab257459   YOSHIFUJI Hideaki / 吉藤英明   netlink: Use FIEL...
2578
  	BUILD_BUG_ON(sizeof(struct netlink_skb_parms) > FIELD_SIZEOF(struct sk_buff, cb));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2579

0da974f4f   Panagiotis Issaris   [NET]: Conversion...
2580
  	nl_table = kcalloc(MAX_LINKS, sizeof(*nl_table), GFP_KERNEL);
fab2caf62   Akinobu Mita   [NETLINK]: Call p...
2581
2582
  	if (!nl_table)
  		goto panic;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2583

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2584
  	for (i = 0; i < MAX_LINKS; i++) {
c428ecd1a   Herbert Xu   netlink: Move nam...
2585
2586
  		if (rhashtable_init(&nl_table[i].hash,
  				    &netlink_rhashtable_params) < 0) {
e341694e3   Thomas Graf   netlink: Convert ...
2587
2588
  			while (--i > 0)
  				rhashtable_destroy(&nl_table[i].hash);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2589
  			kfree(nl_table);
fab2caf62   Akinobu Mita   [NETLINK]: Call p...
2590
  			goto panic;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2591
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2592
  	}
bcbde0d44   Daniel Borkmann   net: netlink: vir...
2593
  	INIT_LIST_HEAD(&netlink_tap_all);
b963ea89f   David S. Miller   netlink: Make NET...
2594
  	netlink_add_usersock_entry();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2595
  	sock_register(&netlink_family_ops);
b4b510290   Eric W. Biederman   [NET]: Support mu...
2596
  	register_pernet_subsys(&netlink_net_ops);
746fac4dc   YOSHIFUJI Hideaki   [NET] NETLINK: Fi...
2597
  	/* The netlink device handler may be needed early. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2598
2599
2600
  	rtnetlink_init();
  out:
  	return err;
fab2caf62   Akinobu Mita   [NETLINK]: Call p...
2601
2602
2603
  panic:
  	panic("netlink_init: Cannot allocate nl_table
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2604
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2605
  core_initcall(netlink_proto_init);