Blame view

net/netlink/af_netlink.c 47.9 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
6
7
8
9
10
   * 				Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
   *
   *		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...
11
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
13
14
15
   * 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...
16
17
18
19
20
21
   * 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
22
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23
  #include <linux/module.h>
4fc268d24   Randy Dunlap   [PATCH] capable/c...
24
  #include <linux/capability.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25
26
  #include <linux/kernel.h>
  #include <linux/init.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
  #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>
  #include <asm/uaccess.h>
  #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
46
47
48
49
50
51
52
53
  #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...
54
  #include <linux/audit.h>
af65bdfce   Patrick McHardy   [NETLINK]: Switch...
55
  #include <linux/mutex.h>
54e0f520e   Andrew Morton   netlink audit war...
56

457c4cbc5   Eric W. Biederman   [NET]: Make /proc...
57
  #include <net/net_namespace.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
59
  #include <net/sock.h>
  #include <net/scm.h>
82ace47a7   Thomas Graf   [NETLINK]: Generi...
60
  #include <net/netlink.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
61

f7fa9b10e   Patrick McHardy   [NETLINK]: Suppor...
62
  #define NLGRPSZ(x)	(ALIGN(x, sizeof(unsigned long) * 8) / 8)
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
63
  #define NLGRPLONGS(x)	(NLGRPSZ(x)/sizeof(unsigned long))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
65
66
67
68
  
  struct netlink_sock {
  	/* struct sock has to be the first member of netlink_sock */
  	struct sock		sk;
  	u32			pid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69
  	u32			dst_pid;
d629b836d   Patrick McHardy   [NETLINK]: Use gr...
70
  	u32			dst_group;
f7fa9b10e   Patrick McHardy   [NETLINK]: Suppor...
71
72
73
74
  	u32			flags;
  	u32			subscriptions;
  	u32			ngroups;
  	unsigned long		*groups;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
75
76
77
  	unsigned long		state;
  	wait_queue_head_t	wait;
  	struct netlink_callback	*cb;
af65bdfce   Patrick McHardy   [NETLINK]: Switch...
78
79
  	struct mutex		*cb_mutex;
  	struct mutex		cb_def_mutex;
cd40b7d39   Denis V. Lunev   [NET]: make netli...
80
  	void			(*netlink_rcv)(struct sk_buff *skb);
77247bbb3   Patrick McHardy   [NETLINK]: Fix mo...
81
  	struct module		*module;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
82
  };
5c398dc8f   Eric Dumazet   netlink: fix netl...
83
84
85
  struct listeners {
  	struct rcu_head		rcu;
  	unsigned long		masks[0];
6c04bb18d   Johannes Berg   netlink: use call...
86
  };
77247bbb3   Patrick McHardy   [NETLINK]: Fix mo...
87
  #define NETLINK_KERNEL_SOCKET	0x1
9a4595bc7   Patrick McHardy   [NETLINK]: Add se...
88
  #define NETLINK_RECV_PKTINFO	0x2
be0c22a46   Pablo Neira Ayuso   netlink: add NETL...
89
  #define NETLINK_BROADCAST_SEND_ERROR	0x4
38938bfe3   Pablo Neira Ayuso   netlink: add NETL...
90
  #define NETLINK_RECV_NO_ENOBUFS	0x8
77247bbb3   Patrick McHardy   [NETLINK]: Fix mo...
91

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92
93
  static inline struct netlink_sock *nlk_sk(struct sock *sk)
  {
32b21e034   Denis Cheng   [NETLINK]: use co...
94
  	return container_of(sk, struct netlink_sock, sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
95
  }
035c4c16b   David S. Miller   netlink: Undo con...
96
  static inline int netlink_is_kernel(struct sock *sk)
aed815601   Denis V. Lunev   [NET]: unify netl...
97
98
99
  {
  	return nlk_sk(sk)->flags & NETLINK_KERNEL_SOCKET;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
  struct nl_pid_hash {
  	struct hlist_head *table;
  	unsigned long rehash_time;
  
  	unsigned int mask;
  	unsigned int shift;
  
  	unsigned int entries;
  	unsigned int max_shift;
  
  	u32 rnd;
  };
  
  struct netlink_table {
  	struct nl_pid_hash hash;
  	struct hlist_head mc_list;
5c398dc8f   Eric Dumazet   netlink: fix netl...
116
  	struct listeners __rcu *listeners;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
117
  	unsigned int nl_nonroot;
f7fa9b10e   Patrick McHardy   [NETLINK]: Suppor...
118
  	unsigned int groups;
af65bdfce   Patrick McHardy   [NETLINK]: Switch...
119
  	struct mutex *cb_mutex;
77247bbb3   Patrick McHardy   [NETLINK]: Fix mo...
120
  	struct module *module;
ab33a1711   Patrick McHardy   [NETLINK]: Return...
121
  	int registered;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
122
123
124
125
126
127
128
129
130
131
132
  };
  
  static struct netlink_table *nl_table;
  
  static DECLARE_WAIT_QUEUE_HEAD(nl_table_wait);
  
  static int netlink_dump(struct sock *sk);
  static void netlink_destroy_callback(struct netlink_callback *cb);
  
  static DEFINE_RWLOCK(nl_table_lock);
  static atomic_t nl_table_users = ATOMIC_INIT(0);
e041c6834   Alan Stern   [PATCH] Notifier ...
133
  static ATOMIC_NOTIFIER_HEAD(netlink_chain);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134

b57ef81ff   stephen hemminger   netlink: af_netli...
135
  static inline u32 netlink_group_mask(u32 group)
d629b836d   Patrick McHardy   [NETLINK]: Use gr...
136
137
138
  {
  	return group ? 1 << (group - 1) : 0;
  }
b57ef81ff   stephen hemminger   netlink: af_netli...
139
  static inline struct hlist_head *nl_pid_hashfn(struct nl_pid_hash *hash, u32 pid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
140
141
142
143
144
145
  {
  	return &hash->table[jhash_1word(pid, hash->rnd) & hash->mask];
  }
  
  static void netlink_sock_destruct(struct sock *sk)
  {
3f660d66d   Herbert Xu   [NETLINK]: Kill C...
146
  	struct netlink_sock *nlk = nlk_sk(sk);
3f660d66d   Herbert Xu   [NETLINK]: Kill C...
147
148
149
150
151
  	if (nlk->cb) {
  		if (nlk->cb->done)
  			nlk->cb->done(nlk->cb);
  		netlink_destroy_callback(nlk->cb);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
152
153
154
  	skb_queue_purge(&sk->sk_receive_queue);
  
  	if (!sock_flag(sk, SOCK_DEAD)) {
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
155
156
  		printk(KERN_ERR "Freeing alive netlink socket %p
  ", sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
157
158
  		return;
  	}
547b792ca   Ilpo Järvinen   net: convert BUG_...
159
160
161
162
  
  	WARN_ON(atomic_read(&sk->sk_rmem_alloc));
  	WARN_ON(atomic_read(&sk->sk_wmem_alloc));
  	WARN_ON(nlk_sk(sk)->groups);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
163
  }
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
164
165
  /* 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
166
167
168
   * 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...
169
  void netlink_table_grab(void)
9a429c498   Eric Dumazet   [NET]: Add some a...
170
  	__acquires(nl_table_lock)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
171
  {
d136f1bd3   Johannes Berg   genetlink: fix ne...
172
  	might_sleep();
6abd219c6   Arjan van de Ven   [PATCH] bcm43xx: ...
173
  	write_lock_irq(&nl_table_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
174
175
176
177
178
  
  	if (atomic_read(&nl_table_users)) {
  		DECLARE_WAITQUEUE(wait, current);
  
  		add_wait_queue_exclusive(&nl_table_wait, &wait);
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
179
  		for (;;) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
180
181
182
  			set_current_state(TASK_UNINTERRUPTIBLE);
  			if (atomic_read(&nl_table_users) == 0)
  				break;
6abd219c6   Arjan van de Ven   [PATCH] bcm43xx: ...
183
  			write_unlock_irq(&nl_table_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
184
  			schedule();
6abd219c6   Arjan van de Ven   [PATCH] bcm43xx: ...
185
  			write_lock_irq(&nl_table_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
186
187
188
189
190
191
  		}
  
  		__set_current_state(TASK_RUNNING);
  		remove_wait_queue(&nl_table_wait, &wait);
  	}
  }
d136f1bd3   Johannes Berg   genetlink: fix ne...
192
  void netlink_table_ungrab(void)
9a429c498   Eric Dumazet   [NET]: Add some a...
193
  	__releases(nl_table_lock)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
194
  {
6abd219c6   Arjan van de Ven   [PATCH] bcm43xx: ...
195
  	write_unlock_irq(&nl_table_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
196
197
  	wake_up(&nl_table_wait);
  }
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
198
  static inline void
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
199
200
201
202
203
204
205
206
  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...
207
  static inline void
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
208
209
210
211
212
  netlink_unlock_table(void)
  {
  	if (atomic_dec_and_test(&nl_table_users))
  		wake_up(&nl_table_wait);
  }
b57ef81ff   stephen hemminger   netlink: af_netli...
213
  static struct sock *netlink_lookup(struct net *net, int protocol, u32 pid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214
215
216
217
218
219
220
221
222
  {
  	struct nl_pid_hash *hash = &nl_table[protocol].hash;
  	struct hlist_head *head;
  	struct sock *sk;
  	struct hlist_node *node;
  
  	read_lock(&nl_table_lock);
  	head = nl_pid_hashfn(hash, pid);
  	sk_for_each(sk, node, head) {
878628fbf   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
223
  		if (net_eq(sock_net(sk), net) && (nlk_sk(sk)->pid == pid)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
224
225
226
227
228
229
230
231
232
  			sock_hold(sk);
  			goto found;
  		}
  	}
  	sk = NULL;
  found:
  	read_unlock(&nl_table_lock);
  	return sk;
  }
b57ef81ff   stephen hemminger   netlink: af_netli...
233
  static struct hlist_head *nl_pid_hash_zalloc(size_t size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
234
235
  {
  	if (size <= PAGE_SIZE)
ea72912c8   Eric Dumazet   [NETLINK]: kzallo...
236
  		return kzalloc(size, GFP_ATOMIC);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
237
238
  	else
  		return (struct hlist_head *)
ea72912c8   Eric Dumazet   [NETLINK]: kzallo...
239
240
  			__get_free_pages(GFP_ATOMIC | __GFP_ZERO,
  					 get_order(size));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
241
  }
b57ef81ff   stephen hemminger   netlink: af_netli...
242
  static void nl_pid_hash_free(struct hlist_head *table, size_t size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
  {
  	if (size <= PAGE_SIZE)
  		kfree(table);
  	else
  		free_pages((unsigned long)table, get_order(size));
  }
  
  static int nl_pid_hash_rehash(struct nl_pid_hash *hash, int grow)
  {
  	unsigned int omask, mask, shift;
  	size_t osize, size;
  	struct hlist_head *otable, *table;
  	int i;
  
  	omask = mask = hash->mask;
  	osize = size = (mask + 1) * sizeof(*table);
  	shift = hash->shift;
  
  	if (grow) {
  		if (++shift > hash->max_shift)
  			return 0;
  		mask = mask * 2 + 1;
  		size *= 2;
  	}
ea72912c8   Eric Dumazet   [NETLINK]: kzallo...
267
  	table = nl_pid_hash_zalloc(size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
268
269
  	if (!table)
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
  	otable = hash->table;
  	hash->table = table;
  	hash->mask = mask;
  	hash->shift = shift;
  	get_random_bytes(&hash->rnd, sizeof(hash->rnd));
  
  	for (i = 0; i <= omask; i++) {
  		struct sock *sk;
  		struct hlist_node *node, *tmp;
  
  		sk_for_each_safe(sk, node, tmp, &otable[i])
  			__sk_add_node(sk, nl_pid_hashfn(hash, nlk_sk(sk)->pid));
  	}
  
  	nl_pid_hash_free(otable, osize);
  	hash->rehash_time = jiffies + 10 * 60 * HZ;
  	return 1;
  }
  
  static inline int nl_pid_hash_dilute(struct nl_pid_hash *hash, int len)
  {
  	int avg = hash->entries >> hash->shift;
  
  	if (unlikely(avg > 1) && nl_pid_hash_rehash(hash, 1))
  		return 1;
  
  	if (unlikely(len > avg) && time_after(jiffies, hash->rehash_time)) {
  		nl_pid_hash_rehash(hash, 0);
  		return 1;
  	}
  
  	return 0;
  }
90ddc4f04   Eric Dumazet   [NET]: move struc...
303
  static const struct proto_ops netlink_ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
304

4277a083e   Patrick McHardy   [NETLINK]: Add ne...
305
306
307
308
309
310
311
  static void
  netlink_update_listeners(struct sock *sk)
  {
  	struct netlink_table *tbl = &nl_table[sk->sk_protocol];
  	struct hlist_node *node;
  	unsigned long mask;
  	unsigned int i;
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
312
  	for (i = 0; i < NLGRPLONGS(tbl->groups); i++) {
4277a083e   Patrick McHardy   [NETLINK]: Add ne...
313
  		mask = 0;
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
314
315
316
317
  		sk_for_each_bound(sk, node, &tbl->mc_list) {
  			if (i < NLGRPLONGS(nlk_sk(sk)->ngroups))
  				mask |= nlk_sk(sk)->groups[i];
  		}
5c398dc8f   Eric Dumazet   netlink: fix netl...
318
  		tbl->listeners->masks[i] = mask;
4277a083e   Patrick McHardy   [NETLINK]: Add ne...
319
320
321
322
  	}
  	/* this function is only called with the netlink table "grabbed", which
  	 * makes sure updates are visible before bind or setsockopt return. */
  }
b4b510290   Eric W. Biederman   [NET]: Support mu...
323
  static int netlink_insert(struct sock *sk, struct net *net, u32 pid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
324
325
326
327
328
329
330
331
332
333
334
335
  {
  	struct nl_pid_hash *hash = &nl_table[sk->sk_protocol].hash;
  	struct hlist_head *head;
  	int err = -EADDRINUSE;
  	struct sock *osk;
  	struct hlist_node *node;
  	int len;
  
  	netlink_table_grab();
  	head = nl_pid_hashfn(hash, pid);
  	len = 0;
  	sk_for_each(osk, node, head) {
878628fbf   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
336
  		if (net_eq(sock_net(osk), net) && (nlk_sk(osk)->pid == pid))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
  			break;
  		len++;
  	}
  	if (node)
  		goto err;
  
  	err = -EBUSY;
  	if (nlk_sk(sk)->pid)
  		goto err;
  
  	err = -ENOMEM;
  	if (BITS_PER_LONG > 32 && unlikely(hash->entries >= UINT_MAX))
  		goto err;
  
  	if (len && nl_pid_hash_dilute(hash, len))
  		head = nl_pid_hashfn(hash, pid);
  	hash->entries++;
  	nlk_sk(sk)->pid = pid;
  	sk_add_node(sk, head);
  	err = 0;
  
  err:
  	netlink_table_ungrab();
  	return err;
  }
  
  static void netlink_remove(struct sock *sk)
  {
  	netlink_table_grab();
d470e3b48   David S. Miller   [NETLINK]: Fix tw...
366
367
  	if (sk_del_node_init(sk))
  		nl_table[sk->sk_protocol].hash.entries--;
f7fa9b10e   Patrick McHardy   [NETLINK]: Suppor...
368
  	if (nlk_sk(sk)->subscriptions)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
369
370
371
372
373
374
375
376
377
  		__sk_del_bind_node(sk);
  	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...
378
379
  static int __netlink_create(struct net *net, struct socket *sock,
  			    struct mutex *cb_mutex, int protocol)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
380
381
382
  {
  	struct sock *sk;
  	struct netlink_sock *nlk;
ab33a1711   Patrick McHardy   [NETLINK]: Return...
383
384
  
  	sock->ops = &netlink_ops;
6257ff217   Pavel Emelyanov   [NET]: Forget the...
385
  	sk = sk_alloc(net, PF_NETLINK, GFP_KERNEL, &netlink_proto);
ab33a1711   Patrick McHardy   [NETLINK]: Return...
386
387
388
389
390
391
  	if (!sk)
  		return -ENOMEM;
  
  	sock_init_data(sock, sk);
  
  	nlk = nlk_sk(sk);
ffa4d7216   Patrick McHardy   [NETLINK]: don't ...
392
393
394
395
396
397
  	if (cb_mutex)
  		nlk->cb_mutex = cb_mutex;
  	else {
  		nlk->cb_mutex = &nlk->cb_def_mutex;
  		mutex_init(nlk->cb_mutex);
  	}
ab33a1711   Patrick McHardy   [NETLINK]: Return...
398
399
400
401
402
403
  	init_waitqueue_head(&nlk->wait);
  
  	sk->sk_destruct = netlink_sock_destruct;
  	sk->sk_protocol = protocol;
  	return 0;
  }
3f378b684   Eric Paris   net: pass kern to...
404
405
  static int netlink_create(struct net *net, struct socket *sock, int protocol,
  			  int kern)
ab33a1711   Patrick McHardy   [NETLINK]: Return...
406
407
  {
  	struct module *module = NULL;
af65bdfce   Patrick McHardy   [NETLINK]: Switch...
408
  	struct mutex *cb_mutex;
f7fa9b10e   Patrick McHardy   [NETLINK]: Suppor...
409
  	struct netlink_sock *nlk;
ab33a1711   Patrick McHardy   [NETLINK]: Return...
410
  	int err = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
411
412
413
414
415
  
  	sock->state = SS_UNCONNECTED;
  
  	if (sock->type != SOCK_RAW && sock->type != SOCK_DGRAM)
  		return -ESOCKTNOSUPPORT;
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
416
  	if (protocol < 0 || protocol >= MAX_LINKS)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
417
  		return -EPROTONOSUPPORT;
77247bbb3   Patrick McHardy   [NETLINK]: Fix mo...
418
  	netlink_lock_table();
95a5afca4   Johannes Berg   net: Remove CONFI...
419
  #ifdef CONFIG_MODULES
ab33a1711   Patrick McHardy   [NETLINK]: Return...
420
  	if (!nl_table[protocol].registered) {
77247bbb3   Patrick McHardy   [NETLINK]: Fix mo...
421
  		netlink_unlock_table();
4fdb3bb72   Harald Welte   [NETLINK]: Add pr...
422
  		request_module("net-pf-%d-proto-%d", PF_NETLINK, protocol);
77247bbb3   Patrick McHardy   [NETLINK]: Fix mo...
423
  		netlink_lock_table();
4fdb3bb72   Harald Welte   [NETLINK]: Add pr...
424
  	}
ab33a1711   Patrick McHardy   [NETLINK]: Return...
425
426
427
428
  #endif
  	if (nl_table[protocol].registered &&
  	    try_module_get(nl_table[protocol].module))
  		module = nl_table[protocol].module;
974c37e9d   Alexey Dobriyan   netlink: fix for ...
429
430
  	else
  		err = -EPROTONOSUPPORT;
af65bdfce   Patrick McHardy   [NETLINK]: Switch...
431
  	cb_mutex = nl_table[protocol].cb_mutex;
77247bbb3   Patrick McHardy   [NETLINK]: Fix mo...
432
  	netlink_unlock_table();
4fdb3bb72   Harald Welte   [NETLINK]: Add pr...
433

974c37e9d   Alexey Dobriyan   netlink: fix for ...
434
435
  	if (err < 0)
  		goto out;
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
436
437
  	err = __netlink_create(net, sock, cb_mutex, protocol);
  	if (err < 0)
f7fa9b10e   Patrick McHardy   [NETLINK]: Suppor...
438
  		goto out_module;
6f756a8c3   David S. Miller   net: Make sure BH...
439
  	local_bh_disable();
c1fd3b945   Eric Dumazet   net: af_netlink s...
440
  	sock_prot_inuse_add(net, &netlink_proto, 1);
6f756a8c3   David S. Miller   net: Make sure BH...
441
  	local_bh_enable();
f7fa9b10e   Patrick McHardy   [NETLINK]: Suppor...
442
  	nlk = nlk_sk(sock->sk);
f7fa9b10e   Patrick McHardy   [NETLINK]: Suppor...
443
  	nlk->module = module;
ab33a1711   Patrick McHardy   [NETLINK]: Return...
444
445
  out:
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
446

ab33a1711   Patrick McHardy   [NETLINK]: Return...
447
448
449
  out_module:
  	module_put(module);
  	goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
450
451
452
453
454
455
456
457
458
459
460
  }
  
  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 ...
461
  	sock_orphan(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
462
  	nlk = nlk_sk(sk);
3f660d66d   Herbert Xu   [NETLINK]: Kill C...
463
464
465
466
  	/*
  	 * OK. Socket is unlinked, any packets that arrive now
  	 * will be purged.
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
467

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
468
469
470
471
  	sock->sk = NULL;
  	wake_up_interruptible_all(&nlk->wait);
  
  	skb_queue_purge(&sk->sk_write_queue);
649300b92   Johannes Berg   netlink: remove s...
472
  	if (nlk->pid) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
473
  		struct netlink_notify n = {
3b1e0a655   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
474
  						.net = sock_net(sk),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
475
476
477
  						.protocol = sk->sk_protocol,
  						.pid = nlk->pid,
  					  };
e041c6834   Alan Stern   [PATCH] Notifier ...
478
479
  		atomic_notifier_call_chain(&netlink_chain,
  				NETLINK_URELEASE, &n);
746fac4dc   YOSHIFUJI Hideaki   [NET] NETLINK: Fi...
480
  	}
4fdb3bb72   Harald Welte   [NETLINK]: Add pr...
481

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

4277a083e   Patrick McHardy   [NETLINK]: Add ne...
484
  	netlink_table_grab();
aed815601   Denis V. Lunev   [NET]: unify netl...
485
  	if (netlink_is_kernel(sk)) {
869e58f87   Denis V. Lunev   [NETNS]: Double f...
486
487
488
489
490
491
  		BUG_ON(nl_table[sk->sk_protocol].registered == 0);
  		if (--nl_table[sk->sk_protocol].registered == 0) {
  			kfree(nl_table[sk->sk_protocol].listeners);
  			nl_table[sk->sk_protocol].module = NULL;
  			nl_table[sk->sk_protocol].registered = 0;
  		}
4277a083e   Patrick McHardy   [NETLINK]: Add ne...
492
493
494
  	} else if (nlk->subscriptions)
  		netlink_update_listeners(sk);
  	netlink_table_ungrab();
77247bbb3   Patrick McHardy   [NETLINK]: Fix mo...
495

f7fa9b10e   Patrick McHardy   [NETLINK]: Suppor...
496
497
  	kfree(nlk->groups);
  	nlk->groups = NULL;
3755810ce   Eric Dumazet   net: Make sure BH...
498
  	local_bh_disable();
c1fd3b945   Eric Dumazet   net: af_netlink s...
499
  	sock_prot_inuse_add(sock_net(sk), &netlink_proto, -1);
3755810ce   Eric Dumazet   net: Make sure BH...
500
  	local_bh_enable();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
501
502
503
504
505
506
507
  	sock_put(sk);
  	return 0;
  }
  
  static int netlink_autobind(struct socket *sock)
  {
  	struct sock *sk = sock->sk;
3b1e0a655   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
508
  	struct net *net = sock_net(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
509
510
511
512
  	struct nl_pid_hash *hash = &nl_table[sk->sk_protocol].hash;
  	struct hlist_head *head;
  	struct sock *osk;
  	struct hlist_node *node;
66aa4a55f   Tom Goff   netlink: use the ...
513
  	s32 pid = task_tgid_vnr(current);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
514
515
516
517
518
519
520
521
  	int err;
  	static s32 rover = -4097;
  
  retry:
  	cond_resched();
  	netlink_table_grab();
  	head = nl_pid_hashfn(hash, pid);
  	sk_for_each(osk, node, head) {
878628fbf   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
522
  		if (!net_eq(sock_net(osk), net))
b4b510290   Eric W. Biederman   [NET]: Support mu...
523
  			continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
524
525
526
527
528
529
530
531
532
533
  		if (nlk_sk(osk)->pid == pid) {
  			/* Bind collision, search negative pid values. */
  			pid = rover--;
  			if (rover > -4097)
  				rover = -4097;
  			netlink_table_ungrab();
  			goto retry;
  		}
  	}
  	netlink_table_ungrab();
b4b510290   Eric W. Biederman   [NET]: Support mu...
534
  	err = netlink_insert(sk, net, pid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
535
536
  	if (err == -EADDRINUSE)
  		goto retry;
d470e3b48   David S. Miller   [NETLINK]: Fix tw...
537
538
539
540
541
542
  
  	/* If 2 threads race to autobind, that is fine.  */
  	if (err == -EBUSY)
  		err = 0;
  
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
543
  }
b57ef81ff   stephen hemminger   netlink: af_netli...
544
  static inline int netlink_capable(const struct socket *sock, unsigned int flag)
746fac4dc   YOSHIFUJI Hideaki   [NET] NETLINK: Fi...
545
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
546
547
  	return (nl_table[sock->sk->sk_protocol].nl_nonroot & flag) ||
  	       capable(CAP_NET_ADMIN);
746fac4dc   YOSHIFUJI Hideaki   [NET] NETLINK: Fi...
548
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
549

f7fa9b10e   Patrick McHardy   [NETLINK]: Suppor...
550
551
552
553
554
555
556
557
558
559
560
  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...
561
  static int netlink_realloc_groups(struct sock *sk)
513c25000   Patrick McHardy   [NETLINK]: Don't ...
562
563
564
  {
  	struct netlink_sock *nlk = nlk_sk(sk);
  	unsigned int groups;
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
565
  	unsigned long *new_groups;
513c25000   Patrick McHardy   [NETLINK]: Don't ...
566
  	int err = 0;
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
567
  	netlink_table_grab();
513c25000   Patrick McHardy   [NETLINK]: Don't ...
568
  	groups = nl_table[sk->sk_protocol].groups;
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
569
  	if (!nl_table[sk->sk_protocol].registered) {
513c25000   Patrick McHardy   [NETLINK]: Don't ...
570
  		err = -ENOENT;
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
571
572
  		goto out_unlock;
  	}
513c25000   Patrick McHardy   [NETLINK]: Don't ...
573

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

b4ff4f041   Johannes Berg   [NETLINK]: alloca...
577
578
579
580
581
  	new_groups = krealloc(nlk->groups, NLGRPSZ(groups), GFP_ATOMIC);
  	if (new_groups == NULL) {
  		err = -ENOMEM;
  		goto out_unlock;
  	}
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
582
  	memset((char *)new_groups + NLGRPSZ(nlk->ngroups), 0,
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
583
584
585
  	       NLGRPSZ(groups) - NLGRPSZ(nlk->ngroups));
  
  	nlk->groups = new_groups;
513c25000   Patrick McHardy   [NETLINK]: Don't ...
586
  	nlk->ngroups = groups;
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
587
588
589
   out_unlock:
  	netlink_table_ungrab();
  	return err;
513c25000   Patrick McHardy   [NETLINK]: Don't ...
590
  }
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
591
592
  static int netlink_bind(struct socket *sock, struct sockaddr *addr,
  			int addr_len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
593
594
  {
  	struct sock *sk = sock->sk;
3b1e0a655   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
595
  	struct net *net = sock_net(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
596
597
598
  	struct netlink_sock *nlk = nlk_sk(sk);
  	struct sockaddr_nl *nladdr = (struct sockaddr_nl *)addr;
  	int err;
746fac4dc   YOSHIFUJI Hideaki   [NET] NETLINK: Fi...
599

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
600
601
602
603
  	if (nladdr->nl_family != AF_NETLINK)
  		return -EINVAL;
  
  	/* Only superuser is allowed to listen multicasts */
513c25000   Patrick McHardy   [NETLINK]: Don't ...
604
605
606
  	if (nladdr->nl_groups) {
  		if (!netlink_capable(sock, NL_NONROOT_RECV))
  			return -EPERM;
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
607
608
609
  		err = netlink_realloc_groups(sk);
  		if (err)
  			return err;
513c25000   Patrick McHardy   [NETLINK]: Don't ...
610
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
611
612
613
614
615
616
  
  	if (nlk->pid) {
  		if (nladdr->nl_pid != nlk->pid)
  			return -EINVAL;
  	} else {
  		err = nladdr->nl_pid ?
b4b510290   Eric W. Biederman   [NET]: Support mu...
617
  			netlink_insert(sk, net, nladdr->nl_pid) :
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
618
619
620
621
  			netlink_autobind(sock);
  		if (err)
  			return err;
  	}
513c25000   Patrick McHardy   [NETLINK]: Don't ...
622
  	if (!nladdr->nl_groups && (nlk->groups == NULL || !(u32)nlk->groups[0]))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
623
624
625
  		return 0;
  
  	netlink_table_grab();
f7fa9b10e   Patrick McHardy   [NETLINK]: Suppor...
626
  	netlink_update_subscriptions(sk, nlk->subscriptions +
746fac4dc   YOSHIFUJI Hideaki   [NET] NETLINK: Fi...
627
628
629
  					 hweight32(nladdr->nl_groups) -
  					 hweight32(nlk->groups[0]));
  	nlk->groups[0] = (nlk->groups[0] & ~0xffffffffUL) | nladdr->nl_groups;
4277a083e   Patrick McHardy   [NETLINK]: Add ne...
630
  	netlink_update_listeners(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
631
632
633
634
635
636
637
638
639
640
641
  	netlink_table_ungrab();
  
  	return 0;
  }
  
  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...
642
  	struct sockaddr_nl *nladdr = (struct sockaddr_nl *)addr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
643

6503d9616   Changli Gao   net: check the le...
644
645
  	if (alen < sizeof(addr->sa_family))
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
646
647
648
  	if (addr->sa_family == AF_UNSPEC) {
  		sk->sk_state	= NETLINK_UNCONNECTED;
  		nlk->dst_pid	= 0;
d629b836d   Patrick McHardy   [NETLINK]: Use gr...
649
  		nlk->dst_group  = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
  		return 0;
  	}
  	if (addr->sa_family != AF_NETLINK)
  		return -EINVAL;
  
  	/* Only superuser is allowed to send multicasts */
  	if (nladdr->nl_groups && !netlink_capable(sock, NL_NONROOT_SEND))
  		return -EPERM;
  
  	if (!nlk->pid)
  		err = netlink_autobind(sock);
  
  	if (err == 0) {
  		sk->sk_state	= NETLINK_CONNECTED;
  		nlk->dst_pid 	= nladdr->nl_pid;
d629b836d   Patrick McHardy   [NETLINK]: Use gr...
665
  		nlk->dst_group  = ffs(nladdr->nl_groups);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
666
667
668
669
  	}
  
  	return err;
  }
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
670
671
  static int netlink_getname(struct socket *sock, struct sockaddr *addr,
  			   int *addr_len, int peer)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
672
673
674
  {
  	struct sock *sk = sock->sk;
  	struct netlink_sock *nlk = nlk_sk(sk);
13cfa97be   Cyrill Gorcunov   net: netlink_getn...
675
  	DECLARE_SOCKADDR(struct sockaddr_nl *, nladdr, addr);
746fac4dc   YOSHIFUJI Hideaki   [NET] NETLINK: Fi...
676

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
677
678
679
680
681
682
  	nladdr->nl_family = AF_NETLINK;
  	nladdr->nl_pad = 0;
  	*addr_len = sizeof(*nladdr);
  
  	if (peer) {
  		nladdr->nl_pid = nlk->dst_pid;
d629b836d   Patrick McHardy   [NETLINK]: Use gr...
683
  		nladdr->nl_groups = netlink_group_mask(nlk->dst_group);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
684
685
  	} else {
  		nladdr->nl_pid = nlk->pid;
513c25000   Patrick McHardy   [NETLINK]: Don't ...
686
  		nladdr->nl_groups = nlk->groups ? nlk->groups[0] : 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
687
688
689
690
691
692
  	}
  	return 0;
  }
  
  static void netlink_overrun(struct sock *sk)
  {
38938bfe3   Pablo Neira Ayuso   netlink: add NETL...
693
694
695
696
697
698
699
  	struct netlink_sock *nlk = nlk_sk(sk);
  
  	if (!(nlk->flags & NETLINK_RECV_NO_ENOBUFS)) {
  		if (!test_and_set_bit(0, &nlk_sk(sk)->state)) {
  			sk->sk_err = ENOBUFS;
  			sk->sk_error_report(sk);
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
700
  	}
38938bfe3   Pablo Neira Ayuso   netlink: add NETL...
701
  	atomic_inc(&sk->sk_drops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
702
703
704
705
  }
  
  static struct sock *netlink_getsockbypid(struct sock *ssk, u32 pid)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
706
707
  	struct sock *sock;
  	struct netlink_sock *nlk;
3b1e0a655   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
708
  	sock = netlink_lookup(sock_net(ssk), ssk->sk_protocol, pid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
709
710
711
712
713
  	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...
714
715
  	if (sock->sk_state == NETLINK_CONNECTED &&
  	    nlk->dst_pid != nlk_sk(ssk)->pid) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
716
717
718
719
720
721
722
723
  		sock_put(sock);
  		return ERR_PTR(-ECONNREFUSED);
  	}
  	return sock;
  }
  
  struct sock *netlink_getsockbyfilp(struct file *filp)
  {
6db5fc5d5   Josef Sipek   [PATCH] struct pa...
724
  	struct inode *inode = filp->f_path.dentry->d_inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
  	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;
  }
  
  /*
   * 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...
748
  int netlink_attachskb(struct sock *sk, struct sk_buff *skb,
c3d8d1e30   Patrick McHardy   [NETLINK]: Fix un...
749
  		      long *timeo, struct sock *ssk)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
750
751
752
753
754
755
756
757
  {
  	struct netlink_sock *nlk;
  
  	nlk = nlk_sk(sk);
  
  	if (atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf ||
  	    test_bit(0, &nlk->state)) {
  		DECLARE_WAITQUEUE(wait, current);
c3d8d1e30   Patrick McHardy   [NETLINK]: Fix un...
758
  		if (!*timeo) {
aed815601   Denis V. Lunev   [NET]: unify netl...
759
  			if (!ssk || netlink_is_kernel(ssk))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
760
761
762
763
764
765
766
767
768
769
770
771
  				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 ||
  		     test_bit(0, &nlk->state)) &&
  		    !sock_flag(sk, SOCK_DEAD))
c3d8d1e30   Patrick McHardy   [NETLINK]: Fix un...
772
  			*timeo = schedule_timeout(*timeo);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
773
774
775
776
777
778
779
  
  		__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...
780
  			return sock_intr_errno(*timeo);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
781
782
783
784
785
786
  		}
  		return 1;
  	}
  	skb_set_owner_r(skb, sk);
  	return 0;
  }
7ee015e0f   Denis V. Lunev   [NET]: cleanup 3r...
787
  int netlink_sendskb(struct sock *sk, struct sk_buff *skb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
788
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
789
  	int len = skb->len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
790
791
792
793
794
795
796
797
798
799
800
  	skb_queue_tail(&sk->sk_receive_queue, skb);
  	sk->sk_data_ready(sk, len);
  	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...
801
  static struct sk_buff *netlink_trim(struct sk_buff *skb, gfp_t allocation)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
802
803
804
805
  {
  	int delta;
  
  	skb_orphan(skb);
4305b5413   Arnaldo Carvalho de Melo   [SK_BUFF]: Conver...
806
  	delta = skb->end - skb->tail;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
  	if (delta * 2 < skb->truesize)
  		return skb;
  
  	if (skb_shared(skb)) {
  		struct sk_buff *nskb = skb_clone(skb, allocation);
  		if (!nskb)
  			return skb;
  		kfree_skb(skb);
  		skb = nskb;
  	}
  
  	if (!pskb_expand_head(skb, 0, -delta, allocation))
  		skb->truesize -= delta;
  
  	return skb;
  }
b57ef81ff   stephen hemminger   netlink: af_netli...
823
  static void netlink_rcv_wake(struct sock *sk)
cd40b7d39   Denis V. Lunev   [NET]: make netli...
824
825
826
827
828
829
830
831
  {
  	struct netlink_sock *nlk = nlk_sk(sk);
  
  	if (skb_queue_empty(&sk->sk_receive_queue))
  		clear_bit(0, &nlk->state);
  	if (!test_bit(0, &nlk->state))
  		wake_up_interruptible(&nlk->wait);
  }
b57ef81ff   stephen hemminger   netlink: af_netli...
832
  static int netlink_unicast_kernel(struct sock *sk, struct sk_buff *skb)
cd40b7d39   Denis V. Lunev   [NET]: make netli...
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
  {
  	int ret;
  	struct netlink_sock *nlk = nlk_sk(sk);
  
  	ret = -ECONNREFUSED;
  	if (nlk->netlink_rcv != NULL) {
  		ret = skb->len;
  		skb_set_owner_r(skb, sk);
  		nlk->netlink_rcv(skb);
  	}
  	kfree_skb(skb);
  	sock_put(sk);
  	return ret;
  }
  
  int netlink_unicast(struct sock *ssk, struct sk_buff *skb,
  		    u32 pid, int nonblock)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
850
851
852
853
854
855
856
857
858
859
860
861
862
863
  {
  	struct sock *sk;
  	int err;
  	long timeo;
  
  	skb = netlink_trim(skb, gfp_any());
  
  	timeo = sock_sndtimeo(ssk, nonblock);
  retry:
  	sk = netlink_getsockbypid(ssk, pid);
  	if (IS_ERR(sk)) {
  		kfree_skb(skb);
  		return PTR_ERR(sk);
  	}
cd40b7d39   Denis V. Lunev   [NET]: make netli...
864
865
  	if (netlink_is_kernel(sk))
  		return netlink_unicast_kernel(sk, skb);
b1153f29e   Stephen Hemminger   netlink: make soc...
866
  	if (sk_filter(sk, skb)) {
848746072   Wang Chen   netlink: Unneeded...
867
  		err = skb->len;
b1153f29e   Stephen Hemminger   netlink: make soc...
868
869
870
871
  		kfree_skb(skb);
  		sock_put(sk);
  		return err;
  	}
9457afee8   Denis V. Lunev   netlink: Remove n...
872
  	err = netlink_attachskb(sk, skb, &timeo, ssk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
873
874
875
876
  	if (err == 1)
  		goto retry;
  	if (err)
  		return err;
7ee015e0f   Denis V. Lunev   [NET]: cleanup 3r...
877
  	return netlink_sendskb(sk, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
878
  }
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
879
  EXPORT_SYMBOL(netlink_unicast);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
880

4277a083e   Patrick McHardy   [NETLINK]: Add ne...
881
882
883
  int netlink_has_listeners(struct sock *sk, unsigned int group)
  {
  	int res = 0;
5c398dc8f   Eric Dumazet   netlink: fix netl...
884
  	struct listeners *listeners;
4277a083e   Patrick McHardy   [NETLINK]: Add ne...
885

aed815601   Denis V. Lunev   [NET]: unify netl...
886
  	BUG_ON(!netlink_is_kernel(sk));
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
887
888
889
  
  	rcu_read_lock();
  	listeners = rcu_dereference(nl_table[sk->sk_protocol].listeners);
4277a083e   Patrick McHardy   [NETLINK]: Add ne...
890
  	if (group - 1 < nl_table[sk->sk_protocol].groups)
5c398dc8f   Eric Dumazet   netlink: fix netl...
891
  		res = test_bit(group - 1, listeners->masks);
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
892
893
  
  	rcu_read_unlock();
4277a083e   Patrick McHardy   [NETLINK]: Add ne...
894
895
896
  	return res;
  }
  EXPORT_SYMBOL_GPL(netlink_has_listeners);
b57ef81ff   stephen hemminger   netlink: af_netli...
897
  static int netlink_broadcast_deliver(struct sock *sk, struct sk_buff *skb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
898
899
900
901
902
903
904
905
  {
  	struct netlink_sock *nlk = nlk_sk(sk);
  
  	if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf &&
  	    !test_bit(0, &nlk->state)) {
  		skb_set_owner_r(skb, sk);
  		skb_queue_tail(&sk->sk_receive_queue, skb);
  		sk->sk_data_ready(sk, skb->len);
2c6458004   stephen hemminger   netlink: wake up ...
906
  		return atomic_read(&sk->sk_rmem_alloc) > (sk->sk_rcvbuf >> 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
907
908
909
910
911
912
  	}
  	return -1;
  }
  
  struct netlink_broadcast_data {
  	struct sock *exclude_sk;
b4b510290   Eric W. Biederman   [NET]: Support mu...
913
  	struct net *net;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
914
915
916
  	u32 pid;
  	u32 group;
  	int failure;
ff491a733   Pablo Neira Ayuso   netlink: change r...
917
  	int delivery_failure;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
918
919
  	int congested;
  	int delivered;
7d877f3bd   Al Viro   [PATCH] gfp_t: net/*
920
  	gfp_t allocation;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
921
  	struct sk_buff *skb, *skb2;
910a7e905   Eric W. Biederman   netlink: Implment...
922
923
  	int (*tx_filter)(struct sock *dsk, struct sk_buff *skb, void *data);
  	void *tx_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
924
  };
b57ef81ff   stephen hemminger   netlink: af_netli...
925
  static int do_one_broadcast(struct sock *sk,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
926
927
928
929
930
931
932
  				   struct netlink_broadcast_data *p)
  {
  	struct netlink_sock *nlk = nlk_sk(sk);
  	int val;
  
  	if (p->exclude_sk == sk)
  		goto out;
f7fa9b10e   Patrick McHardy   [NETLINK]: Suppor...
933
934
  	if (nlk->pid == p->pid || p->group - 1 >= nlk->ngroups ||
  	    !test_bit(p->group - 1, nlk->groups))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
935
  		goto out;
878628fbf   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
936
  	if (!net_eq(sock_net(sk), p->net))
b4b510290   Eric W. Biederman   [NET]: Support mu...
937
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
938
939
940
941
942
943
944
  	if (p->failure) {
  		netlink_overrun(sk);
  		goto out;
  	}
  
  	sock_hold(sk);
  	if (p->skb2 == NULL) {
68acc024e   Tommy S. Christensen   [NETLINK]: Move b...
945
  		if (skb_shared(p->skb)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
946
947
  			p->skb2 = skb_clone(p->skb, p->allocation);
  		} else {
68acc024e   Tommy S. Christensen   [NETLINK]: Move b...
948
949
950
951
952
953
  			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
954
955
956
957
958
959
  		}
  	}
  	if (p->skb2 == NULL) {
  		netlink_overrun(sk);
  		/* Clone failed. Notify ALL listeners. */
  		p->failure = 1;
be0c22a46   Pablo Neira Ayuso   netlink: add NETL...
960
961
  		if (nlk->flags & NETLINK_BROADCAST_SEND_ERROR)
  			p->delivery_failure = 1;
910a7e905   Eric W. Biederman   netlink: Implment...
962
963
964
  	} else if (p->tx_filter && p->tx_filter(sk, p->skb2, p->tx_data)) {
  		kfree_skb(p->skb2);
  		p->skb2 = NULL;
b1153f29e   Stephen Hemminger   netlink: make soc...
965
966
967
  	} else if (sk_filter(sk, p->skb2)) {
  		kfree_skb(p->skb2);
  		p->skb2 = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
968
969
  	} else if ((val = netlink_broadcast_deliver(sk, p->skb2)) < 0) {
  		netlink_overrun(sk);
be0c22a46   Pablo Neira Ayuso   netlink: add NETL...
970
971
  		if (nlk->flags & NETLINK_BROADCAST_SEND_ERROR)
  			p->delivery_failure = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
972
973
974
975
976
977
978
979
980
981
  	} else {
  		p->congested |= val;
  		p->delivered = 1;
  		p->skb2 = NULL;
  	}
  	sock_put(sk);
  
  out:
  	return 0;
  }
910a7e905   Eric W. Biederman   netlink: Implment...
982
983
984
985
  int netlink_broadcast_filtered(struct sock *ssk, struct sk_buff *skb, u32 pid,
  	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
986
  {
3b1e0a655   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
987
  	struct net *net = sock_net(ssk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
988
989
990
991
992
993
994
  	struct netlink_broadcast_data info;
  	struct hlist_node *node;
  	struct sock *sk;
  
  	skb = netlink_trim(skb, allocation);
  
  	info.exclude_sk = ssk;
b4b510290   Eric W. Biederman   [NET]: Support mu...
995
  	info.net = net;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
996
997
998
  	info.pid = pid;
  	info.group = group;
  	info.failure = 0;
ff491a733   Pablo Neira Ayuso   netlink: change r...
999
  	info.delivery_failure = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1000
1001
1002
1003
1004
  	info.congested = 0;
  	info.delivered = 0;
  	info.allocation = allocation;
  	info.skb = skb;
  	info.skb2 = NULL;
910a7e905   Eric W. Biederman   netlink: Implment...
1005
1006
  	info.tx_filter = filter;
  	info.tx_data = filter_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1007
1008
1009
1010
1011
1012
1013
  
  	/* While we sleep in clone, do not allow to change socket list */
  
  	netlink_lock_table();
  
  	sk_for_each_bound(sk, node, &nl_table[ssk->sk_protocol].mc_list)
  		do_one_broadcast(sk, &info);
70d4bf6d4   Neil Horman   drop_monitor: con...
1014
  	consume_skb(skb);
aa1c6a6f7   Tommy S. Christensen   [NETLINK]: Defer ...
1015

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1016
  	netlink_unlock_table();
70d4bf6d4   Neil Horman   drop_monitor: con...
1017
1018
  	if (info.delivery_failure) {
  		kfree_skb(info.skb2);
ff491a733   Pablo Neira Ayuso   netlink: change r...
1019
  		return -ENOBUFS;
70d4bf6d4   Neil Horman   drop_monitor: con...
1020
1021
  	} else
  		consume_skb(info.skb2);
ff491a733   Pablo Neira Ayuso   netlink: change r...
1022

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1023
1024
1025
1026
1027
  	if (info.delivered) {
  		if (info.congested && (allocation & __GFP_WAIT))
  			yield();
  		return 0;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1028
1029
  	return -ESRCH;
  }
910a7e905   Eric W. Biederman   netlink: Implment...
1030
1031
1032
1033
1034
1035
1036
1037
  EXPORT_SYMBOL(netlink_broadcast_filtered);
  
  int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid,
  		      u32 group, gfp_t allocation)
  {
  	return netlink_broadcast_filtered(ssk, skb, pid, group, allocation,
  		NULL, NULL);
  }
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
1038
  EXPORT_SYMBOL(netlink_broadcast);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1039
1040
1041
1042
1043
1044
1045
  
  struct netlink_set_err_data {
  	struct sock *exclude_sk;
  	u32 pid;
  	u32 group;
  	int code;
  };
b57ef81ff   stephen hemminger   netlink: af_netli...
1046
  static int do_one_set_err(struct sock *sk, struct netlink_set_err_data *p)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1047
1048
  {
  	struct netlink_sock *nlk = nlk_sk(sk);
1a50307ba   Pablo Neira Ayuso   netlink: fix NETL...
1049
  	int ret = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1050
1051
1052
  
  	if (sk == p->exclude_sk)
  		goto out;
09ad9bc75   Octavian Purdila   net: use net_eq t...
1053
  	if (!net_eq(sock_net(sk), sock_net(p->exclude_sk)))
b4b510290   Eric W. Biederman   [NET]: Support mu...
1054
  		goto out;
f7fa9b10e   Patrick McHardy   [NETLINK]: Suppor...
1055
1056
  	if (nlk->pid == p->pid || p->group - 1 >= nlk->ngroups ||
  	    !test_bit(p->group - 1, nlk->groups))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1057
  		goto out;
1a50307ba   Pablo Neira Ayuso   netlink: fix NETL...
1058
1059
1060
1061
  	if (p->code == ENOBUFS && nlk->flags & NETLINK_RECV_NO_ENOBUFS) {
  		ret = 1;
  		goto out;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1062
1063
1064
  	sk->sk_err = p->code;
  	sk->sk_error_report(sk);
  out:
1a50307ba   Pablo Neira Ayuso   netlink: fix NETL...
1065
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1066
  }
4843b93c9   Pablo Neira Ayuso   netlink: invert e...
1067
1068
1069
1070
1071
1072
  /**
   * netlink_set_err - report error to broadcast listeners
   * @ssk: the kernel netlink socket, as returned by netlink_kernel_create()
   * @pid: the PID of a process that we want to skip (if any)
   * @groups: the broadcast group that will notice the error
   * @code: error code, must be negative (as usual in kernelspace)
1a50307ba   Pablo Neira Ayuso   netlink: fix NETL...
1073
1074
1075
   *
   * This function returns the number of broadcast listeners that have set the
   * NETLINK_RECV_NO_ENOBUFS socket option.
4843b93c9   Pablo Neira Ayuso   netlink: invert e...
1076
   */
1a50307ba   Pablo Neira Ayuso   netlink: fix NETL...
1077
  int netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1078
1079
1080
1081
  {
  	struct netlink_set_err_data info;
  	struct hlist_node *node;
  	struct sock *sk;
1a50307ba   Pablo Neira Ayuso   netlink: fix NETL...
1082
  	int ret = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1083
1084
1085
1086
  
  	info.exclude_sk = ssk;
  	info.pid = pid;
  	info.group = group;
4843b93c9   Pablo Neira Ayuso   netlink: invert e...
1087
1088
  	/* sk->sk_err wants a positive error value */
  	info.code = -code;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1089
1090
1091
1092
  
  	read_lock(&nl_table_lock);
  
  	sk_for_each_bound(sk, node, &nl_table[ssk->sk_protocol].mc_list)
1a50307ba   Pablo Neira Ayuso   netlink: fix NETL...
1093
  		ret += do_one_set_err(sk, &info);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1094
1095
  
  	read_unlock(&nl_table_lock);
1a50307ba   Pablo Neira Ayuso   netlink: fix NETL...
1096
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1097
  }
dd5b6ce6f   Pablo Neira Ayuso   nefilter: nfnetli...
1098
  EXPORT_SYMBOL(netlink_set_err);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1099

84659eb52   Johannes Berg   [NETLIKN]: Allow ...
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
  /* 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...
1116
  static int netlink_setsockopt(struct socket *sock, int level, int optname,
b7058842c   David S. Miller   net: Make setsock...
1117
  			      char __user *optval, unsigned int optlen)
9a4595bc7   Patrick McHardy   [NETLINK]: Add se...
1118
1119
1120
  {
  	struct sock *sk = sock->sk;
  	struct netlink_sock *nlk = nlk_sk(sk);
eb4965344   Johannes Berg   [NETLINK]: negati...
1121
1122
  	unsigned int val = 0;
  	int err;
9a4595bc7   Patrick McHardy   [NETLINK]: Add se...
1123
1124
1125
1126
1127
  
  	if (level != SOL_NETLINK)
  		return -ENOPROTOOPT;
  
  	if (optlen >= sizeof(int) &&
eb4965344   Johannes Berg   [NETLINK]: negati...
1128
  	    get_user(val, (unsigned int __user *)optval))
9a4595bc7   Patrick McHardy   [NETLINK]: Add se...
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
  		return -EFAULT;
  
  	switch (optname) {
  	case NETLINK_PKTINFO:
  		if (val)
  			nlk->flags |= NETLINK_RECV_PKTINFO;
  		else
  			nlk->flags &= ~NETLINK_RECV_PKTINFO;
  		err = 0;
  		break;
  	case NETLINK_ADD_MEMBERSHIP:
  	case NETLINK_DROP_MEMBERSHIP: {
9a4595bc7   Patrick McHardy   [NETLINK]: Add se...
1141
1142
  		if (!netlink_capable(sock, NL_NONROOT_RECV))
  			return -EPERM;
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
1143
1144
1145
  		err = netlink_realloc_groups(sk);
  		if (err)
  			return err;
9a4595bc7   Patrick McHardy   [NETLINK]: Add se...
1146
1147
1148
  		if (!val || val - 1 >= nlk->ngroups)
  			return -EINVAL;
  		netlink_table_grab();
84659eb52   Johannes Berg   [NETLIKN]: Allow ...
1149
1150
  		netlink_update_socket_mc(nlk, val,
  					 optname == NETLINK_ADD_MEMBERSHIP);
9a4595bc7   Patrick McHardy   [NETLINK]: Add se...
1151
1152
1153
1154
  		netlink_table_ungrab();
  		err = 0;
  		break;
  	}
be0c22a46   Pablo Neira Ayuso   netlink: add NETL...
1155
1156
1157
1158
1159
1160
1161
  	case NETLINK_BROADCAST_ERROR:
  		if (val)
  			nlk->flags |= NETLINK_BROADCAST_SEND_ERROR;
  		else
  			nlk->flags &= ~NETLINK_BROADCAST_SEND_ERROR;
  		err = 0;
  		break;
38938bfe3   Pablo Neira Ayuso   netlink: add NETL...
1162
1163
1164
1165
1166
1167
1168
1169
1170
  	case NETLINK_NO_ENOBUFS:
  		if (val) {
  			nlk->flags |= NETLINK_RECV_NO_ENOBUFS;
  			clear_bit(0, &nlk->state);
  			wake_up_interruptible(&nlk->wait);
  		} else
  			nlk->flags &= ~NETLINK_RECV_NO_ENOBUFS;
  		err = 0;
  		break;
9a4595bc7   Patrick McHardy   [NETLINK]: Add se...
1171
1172
1173
1174
1175
1176
1177
  	default:
  		err = -ENOPROTOOPT;
  	}
  	return err;
  }
  
  static int netlink_getsockopt(struct socket *sock, int level, int optname,
746fac4dc   YOSHIFUJI Hideaki   [NET] NETLINK: Fi...
1178
  			      char __user *optval, int __user *optlen)
9a4595bc7   Patrick McHardy   [NETLINK]: Add se...
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
  {
  	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);
  		val = nlk->flags & NETLINK_RECV_PKTINFO ? 1 : 0;
a27b58fed   Heiko Carstens   [NET]: fix uacces...
1198
1199
1200
  		if (put_user(len, optlen) ||
  		    put_user(val, optval))
  			return -EFAULT;
9a4595bc7   Patrick McHardy   [NETLINK]: Add se...
1201
1202
  		err = 0;
  		break;
be0c22a46   Pablo Neira Ayuso   netlink: add NETL...
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
  	case NETLINK_BROADCAST_ERROR:
  		if (len < sizeof(int))
  			return -EINVAL;
  		len = sizeof(int);
  		val = nlk->flags & NETLINK_BROADCAST_SEND_ERROR ? 1 : 0;
  		if (put_user(len, optlen) ||
  		    put_user(val, optval))
  			return -EFAULT;
  		err = 0;
  		break;
38938bfe3   Pablo Neira Ayuso   netlink: add NETL...
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
  	case NETLINK_NO_ENOBUFS:
  		if (len < sizeof(int))
  			return -EINVAL;
  		len = sizeof(int);
  		val = nlk->flags & NETLINK_RECV_NO_ENOBUFS ? 1 : 0;
  		if (put_user(len, optlen) ||
  		    put_user(val, optval))
  			return -EFAULT;
  		err = 0;
  		break;
9a4595bc7   Patrick McHardy   [NETLINK]: Add se...
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
  	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);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1236
1237
1238
1239
1240
1241
  static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
  			   struct msghdr *msg, size_t len)
  {
  	struct sock_iocb *siocb = kiocb_to_siocb(kiocb);
  	struct sock *sk = sock->sk;
  	struct netlink_sock *nlk = nlk_sk(sk);
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
1242
  	struct sockaddr_nl *addr = msg->msg_name;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1243
  	u32 dst_pid;
d629b836d   Patrick McHardy   [NETLINK]: Use gr...
1244
  	u32 dst_group;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1245
1246
1247
1248
1249
1250
  	struct sk_buff *skb;
  	int err;
  	struct scm_cookie scm;
  
  	if (msg->msg_flags&MSG_OOB)
  		return -EOPNOTSUPP;
16e572626   Eric Dumazet   af_unix: dont sen...
1251
  	if (NULL == siocb->scm)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1252
  		siocb->scm = &scm;
16e572626   Eric Dumazet   af_unix: dont sen...
1253

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1254
1255
1256
1257
1258
  	err = scm_send(sock, msg, siocb->scm);
  	if (err < 0)
  		return err;
  
  	if (msg->msg_namelen) {
b47030c71   Eric W. Biederman   af_netlink: Add n...
1259
  		err = -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1260
  		if (addr->nl_family != AF_NETLINK)
b47030c71   Eric W. Biederman   af_netlink: Add n...
1261
  			goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1262
  		dst_pid = addr->nl_pid;
d629b836d   Patrick McHardy   [NETLINK]: Use gr...
1263
  		dst_group = ffs(addr->nl_groups);
b47030c71   Eric W. Biederman   af_netlink: Add n...
1264
  		err =  -EPERM;
d629b836d   Patrick McHardy   [NETLINK]: Use gr...
1265
  		if (dst_group && !netlink_capable(sock, NL_NONROOT_SEND))
b47030c71   Eric W. Biederman   af_netlink: Add n...
1266
  			goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1267
1268
  	} else {
  		dst_pid = nlk->dst_pid;
d629b836d   Patrick McHardy   [NETLINK]: Use gr...
1269
  		dst_group = nlk->dst_group;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
  	}
  
  	if (!nlk->pid) {
  		err = netlink_autobind(sock);
  		if (err)
  			goto out;
  	}
  
  	err = -EMSGSIZE;
  	if (len > sk->sk_sndbuf - 32)
  		goto out;
  	err = -ENOBUFS;
339bf98ff   Thomas Graf   [NETLINK]: Do pre...
1282
  	skb = alloc_skb(len, GFP_KERNEL);
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
1283
  	if (skb == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1284
1285
1286
  		goto out;
  
  	NETLINK_CB(skb).pid	= nlk->pid;
d629b836d   Patrick McHardy   [NETLINK]: Use gr...
1287
  	NETLINK_CB(skb).dst_group = dst_group;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1288
  	memcpy(NETLINK_CREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1289
  	err = -EFAULT;
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
1290
  	if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1291
1292
1293
1294
1295
1296
1297
1298
1299
  		kfree_skb(skb);
  		goto out;
  	}
  
  	err = security_netlink_send(sk, skb);
  	if (err) {
  		kfree_skb(skb);
  		goto out;
  	}
d629b836d   Patrick McHardy   [NETLINK]: Use gr...
1300
  	if (dst_group) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1301
  		atomic_inc(&skb->users);
d629b836d   Patrick McHardy   [NETLINK]: Use gr...
1302
  		netlink_broadcast(sk, skb, dst_pid, dst_group, GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1303
1304
1305
1306
  	}
  	err = netlink_unicast(sk, skb, dst_pid, msg->msg_flags&MSG_DONTWAIT);
  
  out:
b47030c71   Eric W. Biederman   af_netlink: Add n...
1307
  	scm_destroy(siocb->scm);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
  	return err;
  }
  
  static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock,
  			   struct msghdr *msg, size_t len,
  			   int flags)
  {
  	struct sock_iocb *siocb = kiocb_to_siocb(kiocb);
  	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...
1321
  	struct sk_buff *skb, *data_skb;
b44d211e1   Andrey Vagin   netlink: handle e...
1322
  	int err, ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1323
1324
1325
1326
1327
  
  	if (flags&MSG_OOB)
  		return -EOPNOTSUPP;
  
  	copied = 0;
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
1328
1329
  	skb = skb_recv_datagram(sk, flags, noblock, &err);
  	if (skb == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1330
  		goto out;
68d6ac6d2   Johannes Berg   netlink: fix comp...
1331
  	data_skb = skb;
1dacc76d0   Johannes Berg   net/compat/wext: ...
1332
1333
  #ifdef CONFIG_COMPAT_NETLINK_MESSAGES
  	if (unlikely(skb_shinfo(skb)->frag_list)) {
1dacc76d0   Johannes Berg   net/compat/wext: ...
1334
  		/*
68d6ac6d2   Johannes Berg   netlink: fix comp...
1335
1336
1337
  		 * 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: ...
1338
  		 *
68d6ac6d2   Johannes Berg   netlink: fix comp...
1339
1340
1341
1342
  		 * 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: ...
1343
  		 */
68d6ac6d2   Johannes Berg   netlink: fix comp...
1344
1345
  		if (flags & MSG_CMSG_COMPAT)
  			data_skb = skb_shinfo(skb)->frag_list;
1dacc76d0   Johannes Berg   net/compat/wext: ...
1346
1347
  	}
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1348
  	msg->msg_namelen = 0;
68d6ac6d2   Johannes Berg   netlink: fix comp...
1349
  	copied = data_skb->len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1350
1351
1352
1353
  	if (len < copied) {
  		msg->msg_flags |= MSG_TRUNC;
  		copied = len;
  	}
68d6ac6d2   Johannes Berg   netlink: fix comp...
1354
1355
  	skb_reset_transport_header(data_skb);
  	err = skb_copy_datagram_iovec(data_skb, 0, msg->msg_iov, copied);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1356
1357
  
  	if (msg->msg_name) {
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
1358
  		struct sockaddr_nl *addr = (struct sockaddr_nl *)msg->msg_name;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1359
1360
1361
  		addr->nl_family = AF_NETLINK;
  		addr->nl_pad    = 0;
  		addr->nl_pid	= NETLINK_CB(skb).pid;
d629b836d   Patrick McHardy   [NETLINK]: Use gr...
1362
  		addr->nl_groups	= netlink_group_mask(NETLINK_CB(skb).dst_group);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1363
1364
  		msg->msg_namelen = sizeof(*addr);
  	}
cc9a06cd8   Patrick McHardy   [NETLINK]: Fix us...
1365
1366
  	if (nlk->flags & NETLINK_RECV_PKTINFO)
  		netlink_cmsg_recv_pktinfo(msg, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1367
1368
1369
1370
1371
  	if (NULL == siocb->scm) {
  		memset(&scm, 0, sizeof(scm));
  		siocb->scm = &scm;
  	}
  	siocb->scm->creds = *NETLINK_CREDS(skb);
188ccb558   Patrick McHardy   [NETLINK]: Fix us...
1372
  	if (flags & MSG_TRUNC)
68d6ac6d2   Johannes Berg   netlink: fix comp...
1373
  		copied = data_skb->len;
daa3766e7   David S. Miller   Revert "netlink: ...
1374

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1375
  	skb_free_datagram(sk, skb);
b44d211e1   Andrey Vagin   netlink: handle e...
1376
1377
1378
1379
1380
1381
1382
  	if (nlk->cb && atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf / 2) {
  		ret = netlink_dump(sk);
  		if (ret) {
  			sk->sk_err = ret;
  			sk->sk_error_report(sk);
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1383
1384
  
  	scm_recv(sock, msg, siocb->scm, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1385
1386
1387
1388
1389
1390
1391
  out:
  	netlink_rcv_wake(sk);
  	return err ? : copied;
  }
  
  static void netlink_data_ready(struct sock *sk, int len)
  {
cd40b7d39   Denis V. Lunev   [NET]: make netli...
1392
  	BUG();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1393
1394
1395
  }
  
  /*
746fac4dc   YOSHIFUJI Hideaki   [NET] NETLINK: Fi...
1396
   *	We export these functions to other modules. They provide a
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1397
1398
1399
1400
1401
   *	complete set of kernel non-blocking support for message
   *	queueing.
   */
  
  struct sock *
b4b510290   Eric W. Biederman   [NET]: Support mu...
1402
  netlink_kernel_create(struct net *net, int unit, unsigned int groups,
cd40b7d39   Denis V. Lunev   [NET]: make netli...
1403
  		      void (*input)(struct sk_buff *skb),
af65bdfce   Patrick McHardy   [NETLINK]: Switch...
1404
  		      struct mutex *cb_mutex, struct module *module)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1405
1406
1407
  {
  	struct socket *sock;
  	struct sock *sk;
77247bbb3   Patrick McHardy   [NETLINK]: Fix mo...
1408
  	struct netlink_sock *nlk;
5c398dc8f   Eric Dumazet   netlink: fix netl...
1409
  	struct listeners *listeners = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1410

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

6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
1413
  	if (unit < 0 || unit >= MAX_LINKS)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1414
1415
1416
1417
  		return NULL;
  
  	if (sock_create_lite(PF_NETLINK, SOCK_DGRAM, unit, &sock))
  		return NULL;
23fe18669   Pavel Emelyanov   [NETNS]: Fix race...
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
  	/*
  	 * We have to just have a reference on the net from sk, but don't
  	 * get_net it. Besides, we cannot get and then put the net here.
  	 * So we create one inside init_net and the move it to net.
  	 */
  
  	if (__netlink_create(&init_net, sock, cb_mutex, unit) < 0)
  		goto out_sock_release_nosk;
  
  	sk = sock->sk;
edf020870   Denis V. Lunev   [NET]: Make netli...
1428
  	sk_change_net(sk, net);
4fdb3bb72   Harald Welte   [NETLINK]: Add pr...
1429

4277a083e   Patrick McHardy   [NETLINK]: Add ne...
1430
1431
  	if (groups < 32)
  		groups = 32;
5c398dc8f   Eric Dumazet   netlink: fix netl...
1432
  	listeners = kzalloc(sizeof(*listeners) + NLGRPSZ(groups), GFP_KERNEL);
4277a083e   Patrick McHardy   [NETLINK]: Add ne...
1433
1434
  	if (!listeners)
  		goto out_sock_release;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1435
1436
  	sk->sk_data_ready = netlink_data_ready;
  	if (input)
cd40b7d39   Denis V. Lunev   [NET]: make netli...
1437
  		nlk_sk(sk)->netlink_rcv = input;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1438

b4b510290   Eric W. Biederman   [NET]: Support mu...
1439
  	if (netlink_insert(sk, net, 0))
77247bbb3   Patrick McHardy   [NETLINK]: Fix mo...
1440
  		goto out_sock_release;
4fdb3bb72   Harald Welte   [NETLINK]: Add pr...
1441

77247bbb3   Patrick McHardy   [NETLINK]: Fix mo...
1442
1443
  	nlk = nlk_sk(sk);
  	nlk->flags |= NETLINK_KERNEL_SOCKET;
4fdb3bb72   Harald Welte   [NETLINK]: Add pr...
1444

4fdb3bb72   Harald Welte   [NETLINK]: Add pr...
1445
  	netlink_table_grab();
b4b510290   Eric W. Biederman   [NET]: Support mu...
1446
1447
  	if (!nl_table[unit].registered) {
  		nl_table[unit].groups = groups;
5c398dc8f   Eric Dumazet   netlink: fix netl...
1448
  		rcu_assign_pointer(nl_table[unit].listeners, listeners);
b4b510290   Eric W. Biederman   [NET]: Support mu...
1449
1450
1451
  		nl_table[unit].cb_mutex = cb_mutex;
  		nl_table[unit].module = module;
  		nl_table[unit].registered = 1;
f937f1f46   Jesper Juhl   [NETLINK]: Don't ...
1452
1453
  	} else {
  		kfree(listeners);
869e58f87   Denis V. Lunev   [NETNS]: Double f...
1454
  		nl_table[unit].registered++;
b4b510290   Eric W. Biederman   [NET]: Support mu...
1455
  	}
4fdb3bb72   Harald Welte   [NETLINK]: Add pr...
1456
  	netlink_table_ungrab();
77247bbb3   Patrick McHardy   [NETLINK]: Fix mo...
1457
  	return sk;
4fdb3bb72   Harald Welte   [NETLINK]: Add pr...
1458
  out_sock_release:
4277a083e   Patrick McHardy   [NETLINK]: Add ne...
1459
  	kfree(listeners);
9dfbec1fb   Denis V. Lunev   [NETLINK]: No nee...
1460
  	netlink_kernel_release(sk);
23fe18669   Pavel Emelyanov   [NETNS]: Fix race...
1461
1462
1463
  	return NULL;
  
  out_sock_release_nosk:
4fdb3bb72   Harald Welte   [NETLINK]: Add pr...
1464
  	sock_release(sock);
77247bbb3   Patrick McHardy   [NETLINK]: Fix mo...
1465
  	return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1466
  }
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
1467
  EXPORT_SYMBOL(netlink_kernel_create);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1468

b7c6ba6eb   Denis V. Lunev   [NETNS]: Consolid...
1469
1470
1471
1472
  
  void
  netlink_kernel_release(struct sock *sk)
  {
edf020870   Denis V. Lunev   [NET]: Make netli...
1473
  	sk_release_kernel(sk);
b7c6ba6eb   Denis V. Lunev   [NETNS]: Consolid...
1474
1475
  }
  EXPORT_SYMBOL(netlink_kernel_release);
d136f1bd3   Johannes Berg   genetlink: fix ne...
1476
  int __netlink_change_ngroups(struct sock *sk, unsigned int groups)
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
1477
  {
5c398dc8f   Eric Dumazet   netlink: fix netl...
1478
  	struct listeners *new, *old;
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
1479
  	struct netlink_table *tbl = &nl_table[sk->sk_protocol];
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
1480
1481
1482
  
  	if (groups < 32)
  		groups = 32;
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
1483
  	if (NLGRPSZ(tbl->groups) < NLGRPSZ(groups)) {
5c398dc8f   Eric Dumazet   netlink: fix netl...
1484
1485
  		new = kzalloc(sizeof(*new) + NLGRPSZ(groups), GFP_ATOMIC);
  		if (!new)
d136f1bd3   Johannes Berg   genetlink: fix ne...
1486
  			return -ENOMEM;
33d480ce6   Eric Dumazet   net: cleanup some...
1487
  		old = rcu_dereference_protected(tbl->listeners, 1);
5c398dc8f   Eric Dumazet   netlink: fix netl...
1488
1489
  		memcpy(new->masks, old->masks, NLGRPSZ(tbl->groups));
  		rcu_assign_pointer(tbl->listeners, new);
37b6b935e   Lai Jiangshan   net,rcu: convert ...
1490
  		kfree_rcu(old, rcu);
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
1491
1492
  	}
  	tbl->groups = groups;
d136f1bd3   Johannes Berg   genetlink: fix ne...
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
  	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...
1514
  	netlink_table_ungrab();
d136f1bd3   Johannes Berg   genetlink: fix ne...
1515

b4ff4f041   Johannes Berg   [NETLINK]: alloca...
1516
1517
  	return err;
  }
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
1518

b8273570f   Johannes Berg   genetlink: fix ne...
1519
1520
1521
1522
1523
1524
1525
1526
1527
  void __netlink_clear_multicast_users(struct sock *ksk, unsigned int group)
  {
  	struct sock *sk;
  	struct hlist_node *node;
  	struct netlink_table *tbl = &nl_table[ksk->sk_protocol];
  
  	sk_for_each_bound(sk, node, &tbl->mc_list)
  		netlink_update_socket_mc(nlk_sk(sk), group, 0);
  }
84659eb52   Johannes Berg   [NETLIKN]: Allow ...
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
  /**
   * netlink_clear_multicast_users - kick off multicast listeners
   *
   * This function removes all listeners from the given group.
   * @ksk: The kernel netlink socket, as returned by
   *	netlink_kernel_create().
   * @group: The multicast group to clear.
   */
  void netlink_clear_multicast_users(struct sock *ksk, unsigned int group)
  {
84659eb52   Johannes Berg   [NETLIKN]: Allow ...
1538
  	netlink_table_grab();
b8273570f   Johannes Berg   genetlink: fix ne...
1539
  	__netlink_clear_multicast_users(ksk, group);
84659eb52   Johannes Berg   [NETLIKN]: Allow ...
1540
1541
  	netlink_table_ungrab();
  }
84659eb52   Johannes Berg   [NETLIKN]: Allow ...
1542

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1543
  void netlink_set_nonroot(int protocol, unsigned int flags)
746fac4dc   YOSHIFUJI Hideaki   [NET] NETLINK: Fi...
1544
1545
  {
  	if ((unsigned int)protocol < MAX_LINKS)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1546
  		nl_table[protocol].nl_nonroot = flags;
746fac4dc   YOSHIFUJI Hideaki   [NET] NETLINK: Fi...
1547
  }
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
1548
  EXPORT_SYMBOL(netlink_set_nonroot);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1549
1550
1551
  
  static void netlink_destroy_callback(struct netlink_callback *cb)
  {
91744f655   Wei Yongjun   netlink: remove s...
1552
  	kfree_skb(cb->skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
  	kfree(cb);
  }
  
  /*
   * 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...
1565
  	struct sk_buff *skb = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1566
  	struct nlmsghdr *nlh;
bf8b79e44   Thomas Graf   [NETLINK]: Conver...
1567
  	int len, err = -ENOBUFS;
c7ac8679b   Greg Rose   rtnetlink: Comput...
1568
  	int alloc_size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1569

af65bdfce   Patrick McHardy   [NETLINK]: Switch...
1570
  	mutex_lock(nlk->cb_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1571
1572
1573
  
  	cb = nlk->cb;
  	if (cb == NULL) {
bf8b79e44   Thomas Graf   [NETLINK]: Conver...
1574
1575
  		err = -EINVAL;
  		goto errout_skb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1576
  	}
c7ac8679b   Greg Rose   rtnetlink: Comput...
1577
1578
1579
1580
  	alloc_size = max_t(int, cb->min_dump_alloc, NLMSG_GOODSIZE);
  
  	skb = sock_rmalloc(sk, alloc_size, 0, GFP_KERNEL);
  	if (!skb)
c63d6ea30   Dan Carpenter   rtnetlink: unlock...
1581
  		goto errout_skb;
c7ac8679b   Greg Rose   rtnetlink: Comput...
1582

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1583
1584
1585
  	len = cb->dump(skb, cb);
  
  	if (len > 0) {
af65bdfce   Patrick McHardy   [NETLINK]: Switch...
1586
  		mutex_unlock(nlk->cb_mutex);
b1153f29e   Stephen Hemminger   netlink: make soc...
1587
1588
1589
1590
1591
1592
1593
  
  		if (sk_filter(sk, skb))
  			kfree_skb(skb);
  		else {
  			skb_queue_tail(&sk->sk_receive_queue, skb);
  			sk->sk_data_ready(sk, skb->len);
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1594
1595
  		return 0;
  	}
bf8b79e44   Thomas Graf   [NETLINK]: Conver...
1596
1597
1598
  	nlh = nlmsg_put_answer(skb, cb, NLMSG_DONE, sizeof(len), NLM_F_MULTI);
  	if (!nlh)
  		goto errout_skb;
670dc2833   Johannes Berg   netlink: advertis...
1599
  	nl_dump_check_consistent(cb, nlh);
bf8b79e44   Thomas Graf   [NETLINK]: Conver...
1600
  	memcpy(nlmsg_data(nlh), &len, sizeof(len));
b1153f29e   Stephen Hemminger   netlink: make soc...
1601
1602
1603
1604
1605
1606
  	if (sk_filter(sk, skb))
  		kfree_skb(skb);
  	else {
  		skb_queue_tail(&sk->sk_receive_queue, skb);
  		sk->sk_data_ready(sk, skb->len);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1607

a8f74b228   Thomas Graf   [NETLINK]: Make n...
1608
1609
  	if (cb->done)
  		cb->done(cb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1610
  	nlk->cb = NULL;
af65bdfce   Patrick McHardy   [NETLINK]: Switch...
1611
  	mutex_unlock(nlk->cb_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1612
1613
  
  	netlink_destroy_callback(cb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1614
  	return 0;
1797754ea   Thomas Graf   [NETLINK]: Introd...
1615

bf8b79e44   Thomas Graf   [NETLINK]: Conver...
1616
  errout_skb:
af65bdfce   Patrick McHardy   [NETLINK]: Switch...
1617
  	mutex_unlock(nlk->cb_mutex);
bf8b79e44   Thomas Graf   [NETLINK]: Conver...
1618
  	kfree_skb(skb);
bf8b79e44   Thomas Graf   [NETLINK]: Conver...
1619
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1620
1621
1622
  }
  
  int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
3a6c2b419   Patrick McHardy   netlink: constify...
1623
  		       const struct nlmsghdr *nlh,
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
1624
1625
  		       int (*dump)(struct sk_buff *skb,
  				   struct netlink_callback *),
c7ac8679b   Greg Rose   rtnetlink: Comput...
1626
1627
  		       int (*done)(struct netlink_callback *),
  		       u16 min_dump_alloc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1628
1629
1630
1631
  {
  	struct netlink_callback *cb;
  	struct sock *sk;
  	struct netlink_sock *nlk;
b44d211e1   Andrey Vagin   netlink: handle e...
1632
  	int ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1633

0da974f4f   Panagiotis Issaris   [NET]: Conversion...
1634
  	cb = kzalloc(sizeof(*cb), GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1635
1636
  	if (cb == NULL)
  		return -ENOBUFS;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1637
1638
1639
  	cb->dump = dump;
  	cb->done = done;
  	cb->nlh = nlh;
c7ac8679b   Greg Rose   rtnetlink: Comput...
1640
  	cb->min_dump_alloc = min_dump_alloc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1641
1642
  	atomic_inc(&skb->users);
  	cb->skb = skb;
3b1e0a655   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
1643
  	sk = netlink_lookup(sock_net(ssk), ssk->sk_protocol, NETLINK_CB(skb).pid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1644
1645
1646
1647
1648
  	if (sk == NULL) {
  		netlink_destroy_callback(cb);
  		return -ECONNREFUSED;
  	}
  	nlk = nlk_sk(sk);
3f660d66d   Herbert Xu   [NETLINK]: Kill C...
1649
  	/* A dump is in progress... */
af65bdfce   Patrick McHardy   [NETLINK]: Switch...
1650
  	mutex_lock(nlk->cb_mutex);
3f660d66d   Herbert Xu   [NETLINK]: Kill C...
1651
  	if (nlk->cb) {
af65bdfce   Patrick McHardy   [NETLINK]: Switch...
1652
  		mutex_unlock(nlk->cb_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1653
1654
1655
1656
1657
  		netlink_destroy_callback(cb);
  		sock_put(sk);
  		return -EBUSY;
  	}
  	nlk->cb = cb;
af65bdfce   Patrick McHardy   [NETLINK]: Switch...
1658
  	mutex_unlock(nlk->cb_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1659

b44d211e1   Andrey Vagin   netlink: handle e...
1660
  	ret = netlink_dump(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1661
  	sock_put(sk);
5c58298c2   Denis V. Lunev   [NETLINK]: Fix AC...
1662

b44d211e1   Andrey Vagin   netlink: handle e...
1663
1664
  	if (ret)
  		return ret;
5c58298c2   Denis V. Lunev   [NETLINK]: Fix AC...
1665
1666
1667
1668
  	/* We successfully started a dump, by returning -EINTR we
  	 * signal not to send ACK even if it was requested.
  	 */
  	return -EINTR;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1669
  }
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
1670
  EXPORT_SYMBOL(netlink_dump_start);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1671
1672
1673
1674
1675
1676
  
  void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err)
  {
  	struct sk_buff *skb;
  	struct nlmsghdr *rep;
  	struct nlmsgerr *errmsg;
339bf98ff   Thomas Graf   [NETLINK]: Do pre...
1677
  	size_t payload = sizeof(*errmsg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1678

339bf98ff   Thomas Graf   [NETLINK]: Do pre...
1679
1680
1681
  	/* error messages get the original request appened */
  	if (err)
  		payload += nlmsg_len(nlh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1682

339bf98ff   Thomas Graf   [NETLINK]: Do pre...
1683
  	skb = nlmsg_new(payload, GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1684
1685
  	if (!skb) {
  		struct sock *sk;
3b1e0a655   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
1686
  		sk = netlink_lookup(sock_net(in_skb->sk),
b4b510290   Eric W. Biederman   [NET]: Support mu...
1687
  				    in_skb->sk->sk_protocol,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
  				    NETLINK_CB(in_skb).pid);
  		if (sk) {
  			sk->sk_err = ENOBUFS;
  			sk->sk_error_report(sk);
  			sock_put(sk);
  		}
  		return;
  	}
  
  	rep = __nlmsg_put(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq,
5dba93aed   John Fastabend   net: fix nlmsg le...
1698
  			  NLMSG_ERROR, payload, 0);
bf8b79e44   Thomas Graf   [NETLINK]: Conver...
1699
  	errmsg = nlmsg_data(rep);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1700
  	errmsg->error = err;
bf8b79e44   Thomas Graf   [NETLINK]: Conver...
1701
  	memcpy(&errmsg->msg, nlh, err ? nlh->nlmsg_len : sizeof(*nlh));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1702
1703
  	netlink_unicast(in_skb->sk, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT);
  }
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
1704
  EXPORT_SYMBOL(netlink_ack);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1705

cd40b7d39   Denis V. Lunev   [NET]: make netli...
1706
  int netlink_rcv_skb(struct sk_buff *skb, int (*cb)(struct sk_buff *,
1d00a4eb4   Thomas Graf   [NETLINK]: Remove...
1707
  						     struct nlmsghdr *))
82ace47a7   Thomas Graf   [NETLINK]: Generi...
1708
  {
82ace47a7   Thomas Graf   [NETLINK]: Generi...
1709
1710
1711
1712
  	struct nlmsghdr *nlh;
  	int err;
  
  	while (skb->len >= nlmsg_total_size(0)) {
cd40b7d39   Denis V. Lunev   [NET]: make netli...
1713
  		int msglen;
b529ccf27   Arnaldo Carvalho de Melo   [NETLINK]: Introd...
1714
  		nlh = nlmsg_hdr(skb);
d35b68564   Thomas Graf   [NETLINK]: Ignore...
1715
  		err = 0;
82ace47a7   Thomas Graf   [NETLINK]: Generi...
1716

ad8e4b75c   Martin Murray   [AF_NETLINK]: Fix...
1717
  		if (nlh->nlmsg_len < NLMSG_HDRLEN || skb->len < nlh->nlmsg_len)
82ace47a7   Thomas Graf   [NETLINK]: Generi...
1718
  			return 0;
d35b68564   Thomas Graf   [NETLINK]: Ignore...
1719
1720
  		/* Only requests are handled by the kernel */
  		if (!(nlh->nlmsg_flags & NLM_F_REQUEST))
5c58298c2   Denis V. Lunev   [NETLINK]: Fix AC...
1721
  			goto ack;
45e7ae7f7   Thomas Graf   [NETLINK]: Ignore...
1722
1723
1724
  
  		/* Skip control messages */
  		if (nlh->nlmsg_type < NLMSG_MIN_TYPE)
5c58298c2   Denis V. Lunev   [NETLINK]: Fix AC...
1725
  			goto ack;
d35b68564   Thomas Graf   [NETLINK]: Ignore...
1726

1d00a4eb4   Thomas Graf   [NETLINK]: Remove...
1727
  		err = cb(skb, nlh);
5c58298c2   Denis V. Lunev   [NETLINK]: Fix AC...
1728
1729
1730
1731
  		if (err == -EINTR)
  			goto skip;
  
  ack:
d35b68564   Thomas Graf   [NETLINK]: Ignore...
1732
  		if (nlh->nlmsg_flags & NLM_F_ACK || err)
82ace47a7   Thomas Graf   [NETLINK]: Generi...
1733
  			netlink_ack(skb, nlh, err);
82ace47a7   Thomas Graf   [NETLINK]: Generi...
1734

5c58298c2   Denis V. Lunev   [NETLINK]: Fix AC...
1735
  skip:
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
1736
  		msglen = NLMSG_ALIGN(nlh->nlmsg_len);
cd40b7d39   Denis V. Lunev   [NET]: make netli...
1737
1738
1739
  		if (msglen > skb->len)
  			msglen = skb->len;
  		skb_pull(skb, msglen);
82ace47a7   Thomas Graf   [NETLINK]: Generi...
1740
1741
1742
1743
  	}
  
  	return 0;
  }
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
1744
  EXPORT_SYMBOL(netlink_rcv_skb);
82ace47a7   Thomas Graf   [NETLINK]: Generi...
1745
1746
  
  /**
d387f6ad1   Thomas Graf   [NETLINK]: Add no...
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
   * nlmsg_notify - send a notification netlink message
   * @sk: netlink socket to use
   * @skb: notification message
   * @pid: destination netlink pid for reports or 0
   * @group: destination multicast group or 0
   * @report: 1 to report back, 0 to disable
   * @flags: allocation flags
   */
  int nlmsg_notify(struct sock *sk, struct sk_buff *skb, u32 pid,
  		 unsigned int group, int report, gfp_t flags)
  {
  	int err = 0;
  
  	if (group) {
  		int exclude_pid = 0;
  
  		if (report) {
  			atomic_inc(&skb->users);
  			exclude_pid = pid;
  		}
1ce85fe40   Pablo Neira Ayuso   netlink: change n...
1767
1768
1769
  		/* errors reported via destination sk->sk_err, but propagate
  		 * delivery errors if NETLINK_BROADCAST_ERROR flag is set */
  		err = nlmsg_multicast(sk, skb, exclude_pid, group, flags);
d387f6ad1   Thomas Graf   [NETLINK]: Add no...
1770
  	}
1ce85fe40   Pablo Neira Ayuso   netlink: change n...
1771
1772
1773
1774
1775
1776
1777
  	if (report) {
  		int err2;
  
  		err2 = nlmsg_unicast(sk, skb, pid);
  		if (!err || err == -ESRCH)
  			err = err2;
  	}
d387f6ad1   Thomas Graf   [NETLINK]: Add no...
1778
1779
1780
  
  	return err;
  }
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
1781
  EXPORT_SYMBOL(nlmsg_notify);
d387f6ad1   Thomas Graf   [NETLINK]: Add no...
1782

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1783
1784
  #ifdef CONFIG_PROC_FS
  struct nl_seq_iter {
e372c4140   Denis V. Lunev   [NET]: Consolidat...
1785
  	struct seq_net_private p;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
  	int link;
  	int hash_idx;
  };
  
  static struct sock *netlink_seq_socket_idx(struct seq_file *seq, loff_t pos)
  {
  	struct nl_seq_iter *iter = seq->private;
  	int i, j;
  	struct sock *s;
  	struct hlist_node *node;
  	loff_t off = 0;
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
1797
  	for (i = 0; i < MAX_LINKS; i++) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1798
1799
1800
1801
  		struct nl_pid_hash *hash = &nl_table[i].hash;
  
  		for (j = 0; j <= hash->mask; j++) {
  			sk_for_each(s, node, &hash->table[j]) {
1218854af   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
1802
  				if (sock_net(s) != seq_file_net(seq))
b4b510290   Eric W. Biederman   [NET]: Support mu...
1803
  					continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
  				if (off == pos) {
  					iter->link = i;
  					iter->hash_idx = j;
  					return s;
  				}
  				++off;
  			}
  		}
  	}
  	return NULL;
  }
  
  static void *netlink_seq_start(struct seq_file *seq, loff_t *pos)
9a429c498   Eric Dumazet   [NET]: Add some a...
1817
  	__acquires(nl_table_lock)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
  {
  	read_lock(&nl_table_lock);
  	return *pos ? netlink_seq_socket_idx(seq, *pos - 1) : SEQ_START_TOKEN;
  }
  
  static void *netlink_seq_next(struct seq_file *seq, void *v, loff_t *pos)
  {
  	struct sock *s;
  	struct nl_seq_iter *iter;
  	int i, j;
  
  	++*pos;
  
  	if (v == SEQ_START_TOKEN)
  		return netlink_seq_socket_idx(seq, 0);
746fac4dc   YOSHIFUJI Hideaki   [NET] NETLINK: Fi...
1833

b4b510290   Eric W. Biederman   [NET]: Support mu...
1834
1835
1836
1837
  	iter = seq->private;
  	s = v;
  	do {
  		s = sk_next(s);
1218854af   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
1838
  	} while (s && sock_net(s) != seq_file_net(seq));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1839
1840
  	if (s)
  		return s;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1841
1842
1843
1844
1845
1846
1847
1848
  	i = iter->link;
  	j = iter->hash_idx + 1;
  
  	do {
  		struct nl_pid_hash *hash = &nl_table[i].hash;
  
  		for (; j <= hash->mask; j++) {
  			s = sk_head(&hash->table[j]);
1218854af   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
1849
  			while (s && sock_net(s) != seq_file_net(seq))
b4b510290   Eric W. Biederman   [NET]: Support mu...
1850
  				s = sk_next(s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
  			if (s) {
  				iter->link = i;
  				iter->hash_idx = j;
  				return s;
  			}
  		}
  
  		j = 0;
  	} while (++i < MAX_LINKS);
  
  	return NULL;
  }
  
  static void netlink_seq_stop(struct seq_file *seq, void *v)
9a429c498   Eric Dumazet   [NET]: Add some a...
1865
  	__releases(nl_table_lock)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
  {
  	read_unlock(&nl_table_lock);
  }
  
  
  static int netlink_seq_show(struct seq_file *seq, void *v)
  {
  	if (v == SEQ_START_TOKEN)
  		seq_puts(seq,
  			 "sk       Eth Pid    Groups   "
cf0aa4e07   Masatake YAMATO   netlink: Adding i...
1876
1877
  			 "Rmem     Wmem     Dump     Locks     Drops     Inode
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1878
1879
1880
  	else {
  		struct sock *s = v;
  		struct netlink_sock *nlk = nlk_sk(s);
71338aa7d   Dan Rosenberg   net: convert %p u...
1881
1882
  		seq_printf(seq, "%pK %-3d %-6d %08x %-8d %-8d %pK %-8d %-8d %-8lu
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1883
1884
1885
  			   s,
  			   s->sk_protocol,
  			   nlk->pid,
513c25000   Patrick McHardy   [NETLINK]: Don't ...
1886
  			   nlk->groups ? (u32)nlk->groups[0] : 0,
31e6d363a   Eric Dumazet   net: correct off-...
1887
1888
  			   sk_rmem_alloc_get(s),
  			   sk_wmem_alloc_get(s),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1889
  			   nlk->cb,
38938bfe3   Pablo Neira Ayuso   netlink: add NETL...
1890
  			   atomic_read(&s->sk_refcnt),
cf0aa4e07   Masatake YAMATO   netlink: Adding i...
1891
1892
  			   atomic_read(&s->sk_drops),
  			   sock_i_ino(s)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1893
1894
1895
1896
1897
  			);
  
  	}
  	return 0;
  }
56b3d975b   Philippe De Muyter   [NET]: Make all i...
1898
  static const struct seq_operations netlink_seq_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1899
1900
1901
1902
1903
1904
1905
1906
1907
  	.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...
1908
1909
  	return seq_open_net(inode, file, &netlink_seq_ops,
  				sizeof(struct nl_seq_iter));
b4b510290   Eric W. Biederman   [NET]: Support mu...
1910
  }
da7071d7e   Arjan van de Ven   [PATCH] mark stru...
1911
  static const struct file_operations netlink_seq_fops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1912
1913
1914
1915
  	.owner		= THIS_MODULE,
  	.open		= netlink_seq_open,
  	.read		= seq_read,
  	.llseek		= seq_lseek,
e372c4140   Denis V. Lunev   [NET]: Consolidat...
1916
  	.release	= seq_release_net,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1917
1918
1919
1920
1921
1922
  };
  
  #endif
  
  int netlink_register_notifier(struct notifier_block *nb)
  {
e041c6834   Alan Stern   [PATCH] Notifier ...
1923
  	return atomic_notifier_chain_register(&netlink_chain, nb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1924
  }
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
1925
  EXPORT_SYMBOL(netlink_register_notifier);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1926
1927
1928
  
  int netlink_unregister_notifier(struct notifier_block *nb)
  {
e041c6834   Alan Stern   [PATCH] Notifier ...
1929
  	return atomic_notifier_chain_unregister(&netlink_chain, nb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1930
  }
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
1931
  EXPORT_SYMBOL(netlink_unregister_notifier);
746fac4dc   YOSHIFUJI Hideaki   [NET] NETLINK: Fi...
1932

90ddc4f04   Eric Dumazet   [NET]: move struc...
1933
  static const struct proto_ops netlink_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
  	.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,
  	.poll =		datagram_poll,
  	.ioctl =	sock_no_ioctl,
  	.listen =	sock_no_listen,
  	.shutdown =	sock_no_shutdown,
9a4595bc7   Patrick McHardy   [NETLINK]: Add se...
1946
1947
  	.setsockopt =	netlink_setsockopt,
  	.getsockopt =	netlink_getsockopt,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1948
1949
1950
1951
1952
  	.sendmsg =	netlink_sendmsg,
  	.recvmsg =	netlink_recvmsg,
  	.mmap =		sock_no_mmap,
  	.sendpage =	sock_no_sendpage,
  };
ec1b4cf74   Stephen Hemminger   net: mark net_pro...
1953
  static const struct net_proto_family netlink_family_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1954
1955
1956
1957
  	.family = PF_NETLINK,
  	.create = netlink_create,
  	.owner	= THIS_MODULE,	/* for consistency 8) */
  };
4665079cb   Pavel Emelyanov   [NETNS]: Move som...
1958
  static int __net_init netlink_net_init(struct net *net)
b4b510290   Eric W. Biederman   [NET]: Support mu...
1959
1960
1961
1962
1963
1964
1965
  {
  #ifdef CONFIG_PROC_FS
  	if (!proc_net_fops_create(net, "netlink", 0, &netlink_seq_fops))
  		return -ENOMEM;
  #endif
  	return 0;
  }
4665079cb   Pavel Emelyanov   [NETNS]: Move som...
1966
  static void __net_exit netlink_net_exit(struct net *net)
b4b510290   Eric W. Biederman   [NET]: Support mu...
1967
1968
1969
1970
1971
  {
  #ifdef CONFIG_PROC_FS
  	proc_net_remove(net, "netlink");
  #endif
  }
b963ea89f   David S. Miller   netlink: Make NET...
1972
1973
  static void __init netlink_add_usersock_entry(void)
  {
5c398dc8f   Eric Dumazet   netlink: fix netl...
1974
  	struct listeners *listeners;
b963ea89f   David S. Miller   netlink: Make NET...
1975
  	int groups = 32;
5c398dc8f   Eric Dumazet   netlink: fix netl...
1976
  	listeners = kzalloc(sizeof(*listeners) + NLGRPSZ(groups), GFP_KERNEL);
b963ea89f   David S. Miller   netlink: Make NET...
1977
  	if (!listeners)
5c398dc8f   Eric Dumazet   netlink: fix netl...
1978
1979
  		panic("netlink_add_usersock_entry: Cannot allocate listeners
  ");
b963ea89f   David S. Miller   netlink: Make NET...
1980
1981
1982
1983
  
  	netlink_table_grab();
  
  	nl_table[NETLINK_USERSOCK].groups = groups;
5c398dc8f   Eric Dumazet   netlink: fix netl...
1984
  	rcu_assign_pointer(nl_table[NETLINK_USERSOCK].listeners, listeners);
b963ea89f   David S. Miller   netlink: Make NET...
1985
1986
1987
1988
1989
  	nl_table[NETLINK_USERSOCK].module = THIS_MODULE;
  	nl_table[NETLINK_USERSOCK].registered = 1;
  
  	netlink_table_ungrab();
  }
022cbae61   Denis V. Lunev   [NET]: Move unnee...
1990
  static struct pernet_operations __net_initdata netlink_net_ops = {
b4b510290   Eric W. Biederman   [NET]: Support mu...
1991
1992
1993
  	.init = netlink_net_init,
  	.exit = netlink_net_exit,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1994
1995
1996
1997
  static int __init netlink_proto_init(void)
  {
  	struct sk_buff *dummy_skb;
  	int i;
26ff5ddc5   Denis Cheng   [NETLINK]: the te...
1998
  	unsigned long limit;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1999
2000
2001
2002
2003
  	unsigned int order;
  	int err = proto_register(&netlink_proto, 0);
  
  	if (err != 0)
  		goto out;
ef047f5e1   YOSHIFUJI Hideaki   [NET]: Use BUILD_...
2004
  	BUILD_BUG_ON(sizeof(struct netlink_skb_parms) > sizeof(dummy_skb->cb));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2005

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

4481374ce   Jan Beulich   mm: replace vario...
2010
2011
  	if (totalram_pages >= (128 * 1024))
  		limit = totalram_pages >> (21 - PAGE_SHIFT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2012
  	else
4481374ce   Jan Beulich   mm: replace vario...
2013
  		limit = totalram_pages >> (23 - PAGE_SHIFT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2014

26ff5ddc5   Denis Cheng   [NETLINK]: the te...
2015
2016
2017
  	order = get_bitmask_order(limit) - 1 + PAGE_SHIFT;
  	limit = (1UL << order) / sizeof(struct hlist_head);
  	order = get_bitmask_order(min(limit, (unsigned long)UINT_MAX)) - 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2018
2019
2020
  
  	for (i = 0; i < MAX_LINKS; i++) {
  		struct nl_pid_hash *hash = &nl_table[i].hash;
ea72912c8   Eric Dumazet   [NETLINK]: kzallo...
2021
  		hash->table = nl_pid_hash_zalloc(1 * sizeof(*hash->table));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2022
2023
2024
2025
2026
  		if (!hash->table) {
  			while (i-- > 0)
  				nl_pid_hash_free(nl_table[i].hash.table,
  						 1 * sizeof(*hash->table));
  			kfree(nl_table);
fab2caf62   Akinobu Mita   [NETLINK]: Call p...
2027
  			goto panic;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2028
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2029
2030
2031
2032
2033
  		hash->max_shift = order;
  		hash->shift = 0;
  		hash->mask = 0;
  		hash->rehash_time = jiffies;
  	}
b963ea89f   David S. Miller   netlink: Make NET...
2034
  	netlink_add_usersock_entry();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2035
  	sock_register(&netlink_family_ops);
b4b510290   Eric W. Biederman   [NET]: Support mu...
2036
  	register_pernet_subsys(&netlink_net_ops);
746fac4dc   YOSHIFUJI Hideaki   [NET] NETLINK: Fi...
2037
  	/* The netlink device handler may be needed early. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2038
2039
2040
  	rtnetlink_init();
  out:
  	return err;
fab2caf62   Akinobu Mita   [NETLINK]: Call p...
2041
2042
2043
  panic:
  	panic("netlink_init: Cannot allocate nl_table
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2044
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2045
  core_initcall(netlink_proto_init);