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
  };
6c04bb18d   Johannes Berg   netlink: use call...
83
84
85
86
  struct listeners_rcu_head {
  	struct rcu_head rcu_head;
  	void *ptr;
  };
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
  }
aed815601   Denis V. Lunev   [NET]: unify netl...
96
97
98
99
  static inline int netlink_is_kernel(struct sock *sk)
  {
  	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;
4277a083e   Patrick McHardy   [NETLINK]: Add ne...
116
  	unsigned long *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

d629b836d   Patrick McHardy   [NETLINK]: Use gr...
135
136
137
138
  static u32 netlink_group_mask(u32 group)
  {
  	return group ? 1 << (group - 1) : 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139
140
141
142
143
144
145
  static struct hlist_head *nl_pid_hashfn(struct nl_pid_hash *hash, u32 pid)
  {
  	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);
  }
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
213
214
  static inline struct sock *netlink_lookup(struct net *net, int protocol,
  					  u32 pid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
215
216
217
218
219
220
221
222
223
  {
  	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...
224
  		if (net_eq(sock_net(sk), net) && (nlk_sk(sk)->pid == pid)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
225
226
227
228
229
230
231
232
233
  			sock_hold(sk);
  			goto found;
  		}
  	}
  	sk = NULL;
  found:
  	read_unlock(&nl_table_lock);
  	return sk;
  }
ea72912c8   Eric Dumazet   [NETLINK]: kzallo...
234
  static inline struct hlist_head *nl_pid_hash_zalloc(size_t size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
235
236
  {
  	if (size <= PAGE_SIZE)
ea72912c8   Eric Dumazet   [NETLINK]: kzallo...
237
  		return kzalloc(size, GFP_ATOMIC);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
238
239
  	else
  		return (struct hlist_head *)
ea72912c8   Eric Dumazet   [NETLINK]: kzallo...
240
241
  			__get_free_pages(GFP_ATOMIC | __GFP_ZERO,
  					 get_order(size));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
  }
  
  static inline void nl_pid_hash_free(struct hlist_head *table, size_t size)
  {
  	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...
269
  	table = nl_pid_hash_zalloc(size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
270
271
  	if (!table)
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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
303
304
  	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...
305
  static const struct proto_ops netlink_ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
306

4277a083e   Patrick McHardy   [NETLINK]: Add ne...
307
308
309
310
311
312
313
  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...
314
  	for (i = 0; i < NLGRPLONGS(tbl->groups); i++) {
4277a083e   Patrick McHardy   [NETLINK]: Add ne...
315
  		mask = 0;
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
316
317
318
319
  		sk_for_each_bound(sk, node, &tbl->mc_list) {
  			if (i < NLGRPLONGS(nlk_sk(sk)->ngroups))
  				mask |= nlk_sk(sk)->groups[i];
  		}
4277a083e   Patrick McHardy   [NETLINK]: Add ne...
320
321
322
323
324
  		tbl->listeners[i] = mask;
  	}
  	/* 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...
325
  static int netlink_insert(struct sock *sk, struct net *net, u32 pid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
326
327
328
329
330
331
332
333
334
335
336
337
  {
  	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...
338
  		if (net_eq(sock_net(osk), net) && (nlk_sk(osk)->pid == pid))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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
366
367
  			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...
368
369
  	if (sk_del_node_init(sk))
  		nl_table[sk->sk_protocol].hash.entries--;
f7fa9b10e   Patrick McHardy   [NETLINK]: Suppor...
370
  	if (nlk_sk(sk)->subscriptions)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
371
372
373
374
375
376
377
378
379
  		__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...
380
381
  static int __netlink_create(struct net *net, struct socket *sock,
  			    struct mutex *cb_mutex, int protocol)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
382
383
384
  {
  	struct sock *sk;
  	struct netlink_sock *nlk;
ab33a1711   Patrick McHardy   [NETLINK]: Return...
385
386
  
  	sock->ops = &netlink_ops;
6257ff217   Pavel Emelyanov   [NET]: Forget the...
387
  	sk = sk_alloc(net, PF_NETLINK, GFP_KERNEL, &netlink_proto);
ab33a1711   Patrick McHardy   [NETLINK]: Return...
388
389
390
391
392
393
  	if (!sk)
  		return -ENOMEM;
  
  	sock_init_data(sock, sk);
  
  	nlk = nlk_sk(sk);
ffa4d7216   Patrick McHardy   [NETLINK]: don't ...
394
395
396
397
398
399
  	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...
400
401
402
403
404
405
  	init_waitqueue_head(&nlk->wait);
  
  	sk->sk_destruct = netlink_sock_destruct;
  	sk->sk_protocol = protocol;
  	return 0;
  }
3f378b684   Eric Paris   net: pass kern to...
406
407
  static int netlink_create(struct net *net, struct socket *sock, int protocol,
  			  int kern)
ab33a1711   Patrick McHardy   [NETLINK]: Return...
408
409
  {
  	struct module *module = NULL;
af65bdfce   Patrick McHardy   [NETLINK]: Switch...
410
  	struct mutex *cb_mutex;
f7fa9b10e   Patrick McHardy   [NETLINK]: Suppor...
411
  	struct netlink_sock *nlk;
ab33a1711   Patrick McHardy   [NETLINK]: Return...
412
  	int err = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
413
414
415
416
417
  
  	sock->state = SS_UNCONNECTED;
  
  	if (sock->type != SOCK_RAW && sock->type != SOCK_DGRAM)
  		return -ESOCKTNOSUPPORT;
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
418
  	if (protocol < 0 || protocol >= MAX_LINKS)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
419
  		return -EPROTONOSUPPORT;
77247bbb3   Patrick McHardy   [NETLINK]: Fix mo...
420
  	netlink_lock_table();
95a5afca4   Johannes Berg   net: Remove CONFI...
421
  #ifdef CONFIG_MODULES
ab33a1711   Patrick McHardy   [NETLINK]: Return...
422
  	if (!nl_table[protocol].registered) {
77247bbb3   Patrick McHardy   [NETLINK]: Fix mo...
423
  		netlink_unlock_table();
4fdb3bb72   Harald Welte   [NETLINK]: Add pr...
424
  		request_module("net-pf-%d-proto-%d", PF_NETLINK, protocol);
77247bbb3   Patrick McHardy   [NETLINK]: Fix mo...
425
  		netlink_lock_table();
4fdb3bb72   Harald Welte   [NETLINK]: Add pr...
426
  	}
ab33a1711   Patrick McHardy   [NETLINK]: Return...
427
428
429
430
  #endif
  	if (nl_table[protocol].registered &&
  	    try_module_get(nl_table[protocol].module))
  		module = nl_table[protocol].module;
974c37e9d   Alexey Dobriyan   netlink: fix for ...
431
432
  	else
  		err = -EPROTONOSUPPORT;
af65bdfce   Patrick McHardy   [NETLINK]: Switch...
433
  	cb_mutex = nl_table[protocol].cb_mutex;
77247bbb3   Patrick McHardy   [NETLINK]: Fix mo...
434
  	netlink_unlock_table();
4fdb3bb72   Harald Welte   [NETLINK]: Add pr...
435

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

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

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

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

4277a083e   Patrick McHardy   [NETLINK]: Add ne...
486
  	netlink_table_grab();
aed815601   Denis V. Lunev   [NET]: unify netl...
487
  	if (netlink_is_kernel(sk)) {
869e58f87   Denis V. Lunev   [NETNS]: Double f...
488
489
490
491
492
493
  		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...
494
495
496
  	} else if (nlk->subscriptions)
  		netlink_update_listeners(sk);
  	netlink_table_ungrab();
77247bbb3   Patrick McHardy   [NETLINK]: Fix mo...
497

f7fa9b10e   Patrick McHardy   [NETLINK]: Suppor...
498
499
  	kfree(nlk->groups);
  	nlk->groups = NULL;
3755810ce   Eric Dumazet   net: Make sure BH...
500
  	local_bh_disable();
c1fd3b945   Eric Dumazet   net: af_netlink s...
501
  	sock_prot_inuse_add(sock_net(sk), &netlink_proto, -1);
3755810ce   Eric Dumazet   net: Make sure BH...
502
  	local_bh_enable();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
503
504
505
506
507
508
509
  	sock_put(sk);
  	return 0;
  }
  
  static int netlink_autobind(struct socket *sock)
  {
  	struct sock *sk = sock->sk;
3b1e0a655   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
510
  	struct net *net = sock_net(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
511
512
513
514
  	struct nl_pid_hash *hash = &nl_table[sk->sk_protocol].hash;
  	struct hlist_head *head;
  	struct sock *osk;
  	struct hlist_node *node;
c27bd492f   Herbert Xu   [NETLINK]: Use tg...
515
  	s32 pid = current->tgid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
516
517
518
519
520
521
522
523
  	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...
524
  		if (!net_eq(sock_net(osk), net))
b4b510290   Eric W. Biederman   [NET]: Support mu...
525
  			continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
526
527
528
529
530
531
532
533
534
535
  		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...
536
  	err = netlink_insert(sk, net, pid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
537
538
  	if (err == -EADDRINUSE)
  		goto retry;
d470e3b48   David S. Miller   [NETLINK]: Fix tw...
539
540
541
542
543
544
  
  	/* If 2 threads race to autobind, that is fine.  */
  	if (err == -EBUSY)
  		err = 0;
  
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
545
  }
746fac4dc   YOSHIFUJI Hideaki   [NET] NETLINK: Fi...
546
547
  static inline int netlink_capable(struct socket *sock, unsigned int flag)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
548
549
  	return (nl_table[sock->sk->sk_protocol].nl_nonroot & flag) ||
  	       capable(CAP_NET_ADMIN);
746fac4dc   YOSHIFUJI Hideaki   [NET] NETLINK: Fi...
550
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
551

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

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

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

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

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

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

4277a083e   Patrick McHardy   [NETLINK]: Add ne...
885
886
887
  int netlink_has_listeners(struct sock *sk, unsigned int group)
  {
  	int res = 0;
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
888
  	unsigned long *listeners;
4277a083e   Patrick McHardy   [NETLINK]: Add ne...
889

aed815601   Denis V. Lunev   [NET]: unify netl...
890
  	BUG_ON(!netlink_is_kernel(sk));
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
891
892
893
  
  	rcu_read_lock();
  	listeners = rcu_dereference(nl_table[sk->sk_protocol].listeners);
4277a083e   Patrick McHardy   [NETLINK]: Add ne...
894
  	if (group - 1 < nl_table[sk->sk_protocol].groups)
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
895
896
897
  		res = test_bit(group - 1, listeners);
  
  	rcu_read_unlock();
4277a083e   Patrick McHardy   [NETLINK]: Add ne...
898
899
900
  	return res;
  }
  EXPORT_SYMBOL_GPL(netlink_has_listeners);
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
901
902
  static inline int netlink_broadcast_deliver(struct sock *sk,
  					    struct sk_buff *skb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
  {
  	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);
  		return atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf;
  	}
  	return -1;
  }
  
  struct netlink_broadcast_data {
  	struct sock *exclude_sk;
b4b510290   Eric W. Biederman   [NET]: Support mu...
918
  	struct net *net;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
919
920
921
  	u32 pid;
  	u32 group;
  	int failure;
ff491a733   Pablo Neira Ayuso   netlink: change r...
922
  	int delivery_failure;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
923
924
  	int congested;
  	int delivered;
7d877f3bd   Al Viro   [PATCH] gfp_t: net/*
925
  	gfp_t allocation;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
926
927
928
929
930
931
932
933
934
935
936
  	struct sk_buff *skb, *skb2;
  };
  
  static inline int do_one_broadcast(struct sock *sk,
  				   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...
937
938
  	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
939
  		goto out;
878628fbf   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
940
  	if (!net_eq(sock_net(sk), p->net))
b4b510290   Eric W. Biederman   [NET]: Support mu...
941
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
942
943
944
945
946
947
948
  	if (p->failure) {
  		netlink_overrun(sk);
  		goto out;
  	}
  
  	sock_hold(sk);
  	if (p->skb2 == NULL) {
68acc024e   Tommy S. Christensen   [NETLINK]: Move b...
949
  		if (skb_shared(p->skb)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
950
951
  			p->skb2 = skb_clone(p->skb, p->allocation);
  		} else {
68acc024e   Tommy S. Christensen   [NETLINK]: Move b...
952
953
954
955
956
957
  			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
958
959
960
961
962
963
  		}
  	}
  	if (p->skb2 == NULL) {
  		netlink_overrun(sk);
  		/* Clone failed. Notify ALL listeners. */
  		p->failure = 1;
be0c22a46   Pablo Neira Ayuso   netlink: add NETL...
964
965
  		if (nlk->flags & NETLINK_BROADCAST_SEND_ERROR)
  			p->delivery_failure = 1;
b1153f29e   Stephen Hemminger   netlink: make soc...
966
967
968
  	} else if (sk_filter(sk, p->skb2)) {
  		kfree_skb(p->skb2);
  		p->skb2 = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
969
970
  	} else if ((val = netlink_broadcast_deliver(sk, p->skb2)) < 0) {
  		netlink_overrun(sk);
be0c22a46   Pablo Neira Ayuso   netlink: add NETL...
971
972
  		if (nlk->flags & NETLINK_BROADCAST_SEND_ERROR)
  			p->delivery_failure = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
973
974
975
976
977
978
979
980
981
982
983
984
  	} else {
  		p->congested |= val;
  		p->delivered = 1;
  		p->skb2 = NULL;
  	}
  	sock_put(sk);
  
  out:
  	return 0;
  }
  
  int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid,
dd0fc66fb   Al Viro   [PATCH] gfp flags...
985
  		      u32 group, gfp_t allocation)
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
1005
1006
1007
1008
1009
1010
1011
  	info.congested = 0;
  	info.delivered = 0;
  	info.allocation = allocation;
  	info.skb = skb;
  	info.skb2 = NULL;
  
  	/* 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);
aa1c6a6f7   Tommy S. Christensen   [NETLINK]: Defer ...
1012
  	kfree_skb(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1013
  	netlink_unlock_table();
91744f655   Wei Yongjun   netlink: remove s...
1014
  	kfree_skb(info.skb2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1015

be0c22a46   Pablo Neira Ayuso   netlink: add NETL...
1016
  	if (info.delivery_failure)
ff491a733   Pablo Neira Ayuso   netlink: change r...
1017
  		return -ENOBUFS;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1018
1019
1020
1021
1022
  	if (info.delivered) {
  		if (info.congested && (allocation & __GFP_WAIT))
  			yield();
  		return 0;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1023
1024
  	return -ESRCH;
  }
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
1025
  EXPORT_SYMBOL(netlink_broadcast);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
  
  struct netlink_set_err_data {
  	struct sock *exclude_sk;
  	u32 pid;
  	u32 group;
  	int code;
  };
  
  static inline int do_one_set_err(struct sock *sk,
  				 struct netlink_set_err_data *p)
  {
  	struct netlink_sock *nlk = nlk_sk(sk);
1a50307ba   Pablo Neira Ayuso   netlink: fix NETL...
1038
  	int ret = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1039
1040
1041
  
  	if (sk == p->exclude_sk)
  		goto out;
09ad9bc75   Octavian Purdila   net: use net_eq t...
1042
  	if (!net_eq(sock_net(sk), sock_net(p->exclude_sk)))
b4b510290   Eric W. Biederman   [NET]: Support mu...
1043
  		goto out;
f7fa9b10e   Patrick McHardy   [NETLINK]: Suppor...
1044
1045
  	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
1046
  		goto out;
1a50307ba   Pablo Neira Ayuso   netlink: fix NETL...
1047
1048
1049
1050
  	if (p->code == ENOBUFS && nlk->flags & NETLINK_RECV_NO_ENOBUFS) {
  		ret = 1;
  		goto out;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1051
1052
1053
  	sk->sk_err = p->code;
  	sk->sk_error_report(sk);
  out:
1a50307ba   Pablo Neira Ayuso   netlink: fix NETL...
1054
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1055
  }
4843b93c9   Pablo Neira Ayuso   netlink: invert e...
1056
1057
1058
1059
1060
1061
  /**
   * 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...
1062
1063
1064
   *
   * 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...
1065
   */
1a50307ba   Pablo Neira Ayuso   netlink: fix NETL...
1066
  int netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1067
1068
1069
1070
  {
  	struct netlink_set_err_data info;
  	struct hlist_node *node;
  	struct sock *sk;
1a50307ba   Pablo Neira Ayuso   netlink: fix NETL...
1071
  	int ret = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1072
1073
1074
1075
  
  	info.exclude_sk = ssk;
  	info.pid = pid;
  	info.group = group;
4843b93c9   Pablo Neira Ayuso   netlink: invert e...
1076
1077
  	/* sk->sk_err wants a positive error value */
  	info.code = -code;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1078
1079
1080
1081
  
  	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...
1082
  		ret += do_one_set_err(sk, &info);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1083
1084
  
  	read_unlock(&nl_table_lock);
1a50307ba   Pablo Neira Ayuso   netlink: fix NETL...
1085
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1086
  }
dd5b6ce6f   Pablo Neira Ayuso   nefilter: nfnetli...
1087
  EXPORT_SYMBOL(netlink_set_err);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1088

84659eb52   Johannes Berg   [NETLIKN]: Allow ...
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
  /* 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...
1105
  static int netlink_setsockopt(struct socket *sock, int level, int optname,
b7058842c   David S. Miller   net: Make setsock...
1106
  			      char __user *optval, unsigned int optlen)
9a4595bc7   Patrick McHardy   [NETLINK]: Add se...
1107
1108
1109
  {
  	struct sock *sk = sock->sk;
  	struct netlink_sock *nlk = nlk_sk(sk);
eb4965344   Johannes Berg   [NETLINK]: negati...
1110
1111
  	unsigned int val = 0;
  	int err;
9a4595bc7   Patrick McHardy   [NETLINK]: Add se...
1112
1113
1114
1115
1116
  
  	if (level != SOL_NETLINK)
  		return -ENOPROTOOPT;
  
  	if (optlen >= sizeof(int) &&
eb4965344   Johannes Berg   [NETLINK]: negati...
1117
  	    get_user(val, (unsigned int __user *)optval))
9a4595bc7   Patrick McHardy   [NETLINK]: Add se...
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
  		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...
1130
1131
  		if (!netlink_capable(sock, NL_NONROOT_RECV))
  			return -EPERM;
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
1132
1133
1134
  		err = netlink_realloc_groups(sk);
  		if (err)
  			return err;
9a4595bc7   Patrick McHardy   [NETLINK]: Add se...
1135
1136
1137
  		if (!val || val - 1 >= nlk->ngroups)
  			return -EINVAL;
  		netlink_table_grab();
84659eb52   Johannes Berg   [NETLIKN]: Allow ...
1138
1139
  		netlink_update_socket_mc(nlk, val,
  					 optname == NETLINK_ADD_MEMBERSHIP);
9a4595bc7   Patrick McHardy   [NETLINK]: Add se...
1140
1141
1142
1143
  		netlink_table_ungrab();
  		err = 0;
  		break;
  	}
be0c22a46   Pablo Neira Ayuso   netlink: add NETL...
1144
1145
1146
1147
1148
1149
1150
  	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...
1151
1152
1153
1154
1155
1156
1157
1158
1159
  	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...
1160
1161
1162
1163
1164
1165
1166
  	default:
  		err = -ENOPROTOOPT;
  	}
  	return err;
  }
  
  static int netlink_getsockopt(struct socket *sock, int level, int optname,
746fac4dc   YOSHIFUJI Hideaki   [NET] NETLINK: Fi...
1167
  			      char __user *optval, int __user *optlen)
9a4595bc7   Patrick McHardy   [NETLINK]: Add se...
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
  {
  	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...
1187
1188
1189
  		if (put_user(len, optlen) ||
  		    put_user(val, optval))
  			return -EFAULT;
9a4595bc7   Patrick McHardy   [NETLINK]: Add se...
1190
1191
  		err = 0;
  		break;
be0c22a46   Pablo Neira Ayuso   netlink: add NETL...
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
  	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...
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
  	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...
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
  	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
1225
1226
1227
1228
1229
1230
  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...
1231
  	struct sockaddr_nl *addr = msg->msg_name;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1232
  	u32 dst_pid;
d629b836d   Patrick McHardy   [NETLINK]: Use gr...
1233
  	u32 dst_group;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
  	struct sk_buff *skb;
  	int err;
  	struct scm_cookie scm;
  
  	if (msg->msg_flags&MSG_OOB)
  		return -EOPNOTSUPP;
  
  	if (NULL == siocb->scm)
  		siocb->scm = &scm;
  	err = scm_send(sock, msg, siocb->scm);
  	if (err < 0)
  		return err;
  
  	if (msg->msg_namelen) {
  		if (addr->nl_family != AF_NETLINK)
  			return -EINVAL;
  		dst_pid = addr->nl_pid;
d629b836d   Patrick McHardy   [NETLINK]: Use gr...
1251
1252
  		dst_group = ffs(addr->nl_groups);
  		if (dst_group && !netlink_capable(sock, NL_NONROOT_SEND))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1253
1254
1255
  			return -EPERM;
  	} else {
  		dst_pid = nlk->dst_pid;
d629b836d   Patrick McHardy   [NETLINK]: Use gr...
1256
  		dst_group = nlk->dst_group;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
  	}
  
  	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...
1269
  	skb = alloc_skb(len, GFP_KERNEL);
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
1270
  	if (skb == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1271
1272
1273
  		goto out;
  
  	NETLINK_CB(skb).pid	= nlk->pid;
d629b836d   Patrick McHardy   [NETLINK]: Use gr...
1274
  	NETLINK_CB(skb).dst_group = dst_group;
0c11b9428   Al Viro   [PATCH] switch au...
1275
  	NETLINK_CB(skb).loginuid = audit_get_loginuid(current);
2532386f4   Eric Paris   Audit: collect se...
1276
  	NETLINK_CB(skb).sessionid = audit_get_sessionid(current);
0ce784ca7   Ahmed S. Darwish   Netlink: Use gene...
1277
  	security_task_getsecid(current, &(NETLINK_CB(skb).sid));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1278
1279
1280
1281
1282
1283
1284
1285
1286
  	memcpy(NETLINK_CREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
  
  	/* What can I do? Netlink is asynchronous, so that
  	   we will have to save current capabilities to
  	   check them, when this message will be delivered
  	   to corresponding kernel module.   --ANK (980802)
  	 */
  
  	err = -EFAULT;
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
1287
  	if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1288
1289
1290
1291
1292
1293
1294
1295
1296
  		kfree_skb(skb);
  		goto out;
  	}
  
  	err = security_netlink_send(sk, skb);
  	if (err) {
  		kfree_skb(skb);
  		goto out;
  	}
d629b836d   Patrick McHardy   [NETLINK]: Use gr...
1297
  	if (dst_group) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1298
  		atomic_inc(&skb->users);
d629b836d   Patrick McHardy   [NETLINK]: Use gr...
1299
  		netlink_broadcast(sk, skb, dst_pid, dst_group, GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
  	}
  	err = netlink_unicast(sk, skb, dst_pid, msg->msg_flags&MSG_DONTWAIT);
  
  out:
  	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;
1dacc76d0   Johannes Berg   net/compat/wext: ...
1317
  	struct sk_buff *skb, *frag __maybe_unused = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1318
1319
1320
1321
1322
1323
  	int err;
  
  	if (flags&MSG_OOB)
  		return -EOPNOTSUPP;
  
  	copied = 0;
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
1324
1325
  	skb = skb_recv_datagram(sk, flags, noblock, &err);
  	if (skb == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1326
  		goto out;
1dacc76d0   Johannes Berg   net/compat/wext: ...
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
  #ifdef CONFIG_COMPAT_NETLINK_MESSAGES
  	if (unlikely(skb_shinfo(skb)->frag_list)) {
  		bool need_compat = !!(flags & MSG_CMSG_COMPAT);
  
  		/*
  		 * If this skb has a frag_list, then here that means that
  		 * we will have to use the frag_list skb for compat tasks
  		 * and the regular skb for non-compat tasks.
  		 *
  		 * The skb might (and likely will) be cloned, so we can't
  		 * just reset frag_list and go on with things -- we need to
  		 * keep that. For the compat case that's easy -- simply get
  		 * a reference to the compat skb and free the regular one
  		 * including the frag. For the non-compat case, we need to
  		 * avoid sending the frag to the user -- so assign NULL but
  		 * restore it below before freeing the skb.
  		 */
  		if (need_compat) {
  			struct sk_buff *compskb = skb_shinfo(skb)->frag_list;
  			skb_get(compskb);
  			kfree_skb(skb);
  			skb = compskb;
  		} else {
  			frag = skb_shinfo(skb)->frag_list;
  			skb_shinfo(skb)->frag_list = NULL;
  		}
  	}
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1355
1356
1357
1358
1359
1360
1361
  	msg->msg_namelen = 0;
  
  	copied = skb->len;
  	if (len < copied) {
  		msg->msg_flags |= MSG_TRUNC;
  		copied = len;
  	}
badff6d01   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1362
  	skb_reset_transport_header(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1363
1364
1365
  	err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
  
  	if (msg->msg_name) {
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
1366
  		struct sockaddr_nl *addr = (struct sockaddr_nl *)msg->msg_name;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1367
1368
1369
  		addr->nl_family = AF_NETLINK;
  		addr->nl_pad    = 0;
  		addr->nl_pid	= NETLINK_CB(skb).pid;
d629b836d   Patrick McHardy   [NETLINK]: Use gr...
1370
  		addr->nl_groups	= netlink_group_mask(NETLINK_CB(skb).dst_group);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1371
1372
  		msg->msg_namelen = sizeof(*addr);
  	}
cc9a06cd8   Patrick McHardy   [NETLINK]: Fix us...
1373
1374
  	if (nlk->flags & NETLINK_RECV_PKTINFO)
  		netlink_cmsg_recv_pktinfo(msg, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1375
1376
1377
1378
1379
  	if (NULL == siocb->scm) {
  		memset(&scm, 0, sizeof(scm));
  		siocb->scm = &scm;
  	}
  	siocb->scm->creds = *NETLINK_CREDS(skb);
188ccb558   Patrick McHardy   [NETLINK]: Fix us...
1380
1381
  	if (flags & MSG_TRUNC)
  		copied = skb->len;
1dacc76d0   Johannes Berg   net/compat/wext: ...
1382
1383
1384
1385
  
  #ifdef CONFIG_COMPAT_NETLINK_MESSAGES
  	skb_shinfo(skb)->frag_list = frag;
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1386
1387
1388
1389
1390
1391
  	skb_free_datagram(sk, skb);
  
  	if (nlk->cb && atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf / 2)
  		netlink_dump(sk);
  
  	scm_recv(sock, msg, siocb->scm, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1392
1393
1394
1395
1396
1397
1398
  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...
1399
  	BUG();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1400
1401
1402
  }
  
  /*
746fac4dc   YOSHIFUJI Hideaki   [NET] NETLINK: Fi...
1403
   *	We export these functions to other modules. They provide a
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1404
1405
1406
1407
1408
   *	complete set of kernel non-blocking support for message
   *	queueing.
   */
  
  struct sock *
b4b510290   Eric W. Biederman   [NET]: Support mu...
1409
  netlink_kernel_create(struct net *net, int unit, unsigned int groups,
cd40b7d39   Denis V. Lunev   [NET]: make netli...
1410
  		      void (*input)(struct sk_buff *skb),
af65bdfce   Patrick McHardy   [NETLINK]: Switch...
1411
  		      struct mutex *cb_mutex, struct module *module)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1412
1413
1414
  {
  	struct socket *sock;
  	struct sock *sk;
77247bbb3   Patrick McHardy   [NETLINK]: Fix mo...
1415
  	struct netlink_sock *nlk;
4277a083e   Patrick McHardy   [NETLINK]: Add ne...
1416
  	unsigned long *listeners = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1417

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

6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
1420
  	if (unit < 0 || unit >= MAX_LINKS)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1421
1422
1423
1424
  		return NULL;
  
  	if (sock_create_lite(PF_NETLINK, SOCK_DGRAM, unit, &sock))
  		return NULL;
23fe18669   Pavel Emelyanov   [NETNS]: Fix race...
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
  	/*
  	 * 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...
1435
  	sk_change_net(sk, net);
4fdb3bb72   Harald Welte   [NETLINK]: Add pr...
1436

4277a083e   Patrick McHardy   [NETLINK]: Add ne...
1437
1438
  	if (groups < 32)
  		groups = 32;
6c04bb18d   Johannes Berg   netlink: use call...
1439
1440
  	listeners = kzalloc(NLGRPSZ(groups) + sizeof(struct listeners_rcu_head),
  			    GFP_KERNEL);
4277a083e   Patrick McHardy   [NETLINK]: Add ne...
1441
1442
  	if (!listeners)
  		goto out_sock_release;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1443
1444
  	sk->sk_data_ready = netlink_data_ready;
  	if (input)
cd40b7d39   Denis V. Lunev   [NET]: make netli...
1445
  		nlk_sk(sk)->netlink_rcv = input;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1446

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

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

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

b7c6ba6eb   Denis V. Lunev   [NETNS]: Consolid...
1477
1478
1479
1480
  
  void
  netlink_kernel_release(struct sock *sk)
  {
edf020870   Denis V. Lunev   [NET]: Make netli...
1481
  	sk_release_kernel(sk);
b7c6ba6eb   Denis V. Lunev   [NETNS]: Consolid...
1482
1483
  }
  EXPORT_SYMBOL(netlink_kernel_release);
6c04bb18d   Johannes Berg   netlink: use call...
1484
1485
1486
1487
1488
1489
1490
  static void netlink_free_old_listeners(struct rcu_head *rcu_head)
  {
  	struct listeners_rcu_head *lrh;
  
  	lrh = container_of(rcu_head, struct listeners_rcu_head, rcu_head);
  	kfree(lrh->ptr);
  }
d136f1bd3   Johannes Berg   genetlink: fix ne...
1491
  int __netlink_change_ngroups(struct sock *sk, unsigned int groups)
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
1492
1493
  {
  	unsigned long *listeners, *old = NULL;
6c04bb18d   Johannes Berg   netlink: use call...
1494
  	struct listeners_rcu_head *old_rcu_head;
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
1495
  	struct netlink_table *tbl = &nl_table[sk->sk_protocol];
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
1496
1497
1498
  
  	if (groups < 32)
  		groups = 32;
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
1499
  	if (NLGRPSZ(tbl->groups) < NLGRPSZ(groups)) {
6c04bb18d   Johannes Berg   netlink: use call...
1500
1501
1502
  		listeners = kzalloc(NLGRPSZ(groups) +
  				    sizeof(struct listeners_rcu_head),
  				    GFP_ATOMIC);
d136f1bd3   Johannes Berg   genetlink: fix ne...
1503
1504
  		if (!listeners)
  			return -ENOMEM;
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
1505
1506
1507
  		old = tbl->listeners;
  		memcpy(listeners, old, NLGRPSZ(tbl->groups));
  		rcu_assign_pointer(tbl->listeners, listeners);
6c04bb18d   Johannes Berg   netlink: use call...
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
  		/*
  		 * Free the old memory after an RCU grace period so we
  		 * don't leak it. We use call_rcu() here in order to be
  		 * able to call this function from atomic contexts. The
  		 * allocation of this memory will have reserved enough
  		 * space for struct listeners_rcu_head at the end.
  		 */
  		old_rcu_head = (void *)(tbl->listeners +
  					NLGRPLONGS(tbl->groups));
  		old_rcu_head->ptr = old;
  		call_rcu(&old_rcu_head->rcu_head, netlink_free_old_listeners);
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
1519
1520
  	}
  	tbl->groups = groups;
d136f1bd3   Johannes Berg   genetlink: fix ne...
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
  	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...
1542
  	netlink_table_ungrab();
d136f1bd3   Johannes Berg   genetlink: fix ne...
1543

b4ff4f041   Johannes Berg   [NETLINK]: alloca...
1544
1545
  	return err;
  }
b4ff4f041   Johannes Berg   [NETLINK]: alloca...
1546

b8273570f   Johannes Berg   genetlink: fix ne...
1547
1548
1549
1550
1551
1552
1553
1554
1555
  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 ...
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
  /**
   * 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 ...
1566
  	netlink_table_grab();
b8273570f   Johannes Berg   genetlink: fix ne...
1567
  	__netlink_clear_multicast_users(ksk, group);
84659eb52   Johannes Berg   [NETLIKN]: Allow ...
1568
1569
  	netlink_table_ungrab();
  }
84659eb52   Johannes Berg   [NETLIKN]: Allow ...
1570

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1571
  void netlink_set_nonroot(int protocol, unsigned int flags)
746fac4dc   YOSHIFUJI Hideaki   [NET] NETLINK: Fi...
1572
1573
  {
  	if ((unsigned int)protocol < MAX_LINKS)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1574
  		nl_table[protocol].nl_nonroot = flags;
746fac4dc   YOSHIFUJI Hideaki   [NET] NETLINK: Fi...
1575
  }
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
1576
  EXPORT_SYMBOL(netlink_set_nonroot);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1577
1578
1579
  
  static void netlink_destroy_callback(struct netlink_callback *cb)
  {
91744f655   Wei Yongjun   netlink: remove s...
1580
  	kfree_skb(cb->skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
  	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;
  	struct sk_buff *skb;
  	struct nlmsghdr *nlh;
bf8b79e44   Thomas Graf   [NETLINK]: Conver...
1595
  	int len, err = -ENOBUFS;
746fac4dc   YOSHIFUJI Hideaki   [NET] NETLINK: Fi...
1596

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1597
1598
  	skb = sock_rmalloc(sk, NLMSG_GOODSIZE, 0, GFP_KERNEL);
  	if (!skb)
bf8b79e44   Thomas Graf   [NETLINK]: Conver...
1599
  		goto errout;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1600

af65bdfce   Patrick McHardy   [NETLINK]: Switch...
1601
  	mutex_lock(nlk->cb_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1602
1603
1604
  
  	cb = nlk->cb;
  	if (cb == NULL) {
bf8b79e44   Thomas Graf   [NETLINK]: Conver...
1605
1606
  		err = -EINVAL;
  		goto errout_skb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1607
1608
1609
1610
1611
  	}
  
  	len = cb->dump(skb, cb);
  
  	if (len > 0) {
af65bdfce   Patrick McHardy   [NETLINK]: Switch...
1612
  		mutex_unlock(nlk->cb_mutex);
b1153f29e   Stephen Hemminger   netlink: make soc...
1613
1614
1615
1616
1617
1618
1619
  
  		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
1620
1621
  		return 0;
  	}
bf8b79e44   Thomas Graf   [NETLINK]: Conver...
1622
1623
1624
1625
1626
  	nlh = nlmsg_put_answer(skb, cb, NLMSG_DONE, sizeof(len), NLM_F_MULTI);
  	if (!nlh)
  		goto errout_skb;
  
  	memcpy(nlmsg_data(nlh), &len, sizeof(len));
b1153f29e   Stephen Hemminger   netlink: make soc...
1627
1628
1629
1630
1631
1632
  	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
1633

a8f74b228   Thomas Graf   [NETLINK]: Make n...
1634
1635
  	if (cb->done)
  		cb->done(cb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1636
  	nlk->cb = NULL;
af65bdfce   Patrick McHardy   [NETLINK]: Switch...
1637
  	mutex_unlock(nlk->cb_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1638
1639
  
  	netlink_destroy_callback(cb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1640
  	return 0;
1797754ea   Thomas Graf   [NETLINK]: Introd...
1641

bf8b79e44   Thomas Graf   [NETLINK]: Conver...
1642
  errout_skb:
af65bdfce   Patrick McHardy   [NETLINK]: Switch...
1643
  	mutex_unlock(nlk->cb_mutex);
bf8b79e44   Thomas Graf   [NETLINK]: Conver...
1644
1645
1646
  	kfree_skb(skb);
  errout:
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1647
1648
1649
  }
  
  int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
3a6c2b419   Patrick McHardy   netlink: constify...
1650
  		       const struct nlmsghdr *nlh,
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
1651
1652
1653
  		       int (*dump)(struct sk_buff *skb,
  				   struct netlink_callback *),
  		       int (*done)(struct netlink_callback *))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1654
1655
1656
1657
  {
  	struct netlink_callback *cb;
  	struct sock *sk;
  	struct netlink_sock *nlk;
0da974f4f   Panagiotis Issaris   [NET]: Conversion...
1658
  	cb = kzalloc(sizeof(*cb), GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1659
1660
  	if (cb == NULL)
  		return -ENOBUFS;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1661
1662
1663
1664
1665
  	cb->dump = dump;
  	cb->done = done;
  	cb->nlh = nlh;
  	atomic_inc(&skb->users);
  	cb->skb = skb;
3b1e0a655   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
1666
  	sk = netlink_lookup(sock_net(ssk), ssk->sk_protocol, NETLINK_CB(skb).pid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1667
1668
1669
1670
1671
  	if (sk == NULL) {
  		netlink_destroy_callback(cb);
  		return -ECONNREFUSED;
  	}
  	nlk = nlk_sk(sk);
3f660d66d   Herbert Xu   [NETLINK]: Kill C...
1672
  	/* A dump is in progress... */
af65bdfce   Patrick McHardy   [NETLINK]: Switch...
1673
  	mutex_lock(nlk->cb_mutex);
3f660d66d   Herbert Xu   [NETLINK]: Kill C...
1674
  	if (nlk->cb) {
af65bdfce   Patrick McHardy   [NETLINK]: Switch...
1675
  		mutex_unlock(nlk->cb_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1676
1677
1678
1679
1680
  		netlink_destroy_callback(cb);
  		sock_put(sk);
  		return -EBUSY;
  	}
  	nlk->cb = cb;
af65bdfce   Patrick McHardy   [NETLINK]: Switch...
1681
  	mutex_unlock(nlk->cb_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1682
1683
1684
  
  	netlink_dump(sk);
  	sock_put(sk);
5c58298c2   Denis V. Lunev   [NETLINK]: Fix AC...
1685
1686
1687
1688
1689
  
  	/* 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
1690
  }
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
1691
  EXPORT_SYMBOL(netlink_dump_start);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1692
1693
1694
1695
1696
1697
  
  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...
1698
  	size_t payload = sizeof(*errmsg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1699

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

339bf98ff   Thomas Graf   [NETLINK]: Do pre...
1704
  	skb = nlmsg_new(payload, GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1705
1706
  	if (!skb) {
  		struct sock *sk;
3b1e0a655   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
1707
  		sk = netlink_lookup(sock_net(in_skb->sk),
b4b510290   Eric W. Biederman   [NET]: Support mu...
1708
  				    in_skb->sk->sk_protocol,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
  				    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...
1719
  			  NLMSG_ERROR, payload, 0);
bf8b79e44   Thomas Graf   [NETLINK]: Conver...
1720
  	errmsg = nlmsg_data(rep);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1721
  	errmsg->error = err;
bf8b79e44   Thomas Graf   [NETLINK]: Conver...
1722
  	memcpy(&errmsg->msg, nlh, err ? nlh->nlmsg_len : sizeof(*nlh));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1723
1724
  	netlink_unicast(in_skb->sk, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT);
  }
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
1725
  EXPORT_SYMBOL(netlink_ack);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1726

cd40b7d39   Denis V. Lunev   [NET]: make netli...
1727
  int netlink_rcv_skb(struct sk_buff *skb, int (*cb)(struct sk_buff *,
1d00a4eb4   Thomas Graf   [NETLINK]: Remove...
1728
  						     struct nlmsghdr *))
82ace47a7   Thomas Graf   [NETLINK]: Generi...
1729
  {
82ace47a7   Thomas Graf   [NETLINK]: Generi...
1730
1731
1732
1733
  	struct nlmsghdr *nlh;
  	int err;
  
  	while (skb->len >= nlmsg_total_size(0)) {
cd40b7d39   Denis V. Lunev   [NET]: make netli...
1734
  		int msglen;
b529ccf27   Arnaldo Carvalho de Melo   [NETLINK]: Introd...
1735
  		nlh = nlmsg_hdr(skb);
d35b68564   Thomas Graf   [NETLINK]: Ignore...
1736
  		err = 0;
82ace47a7   Thomas Graf   [NETLINK]: Generi...
1737

ad8e4b75c   Martin Murray   [AF_NETLINK]: Fix...
1738
  		if (nlh->nlmsg_len < NLMSG_HDRLEN || skb->len < nlh->nlmsg_len)
82ace47a7   Thomas Graf   [NETLINK]: Generi...
1739
  			return 0;
d35b68564   Thomas Graf   [NETLINK]: Ignore...
1740
1741
  		/* Only requests are handled by the kernel */
  		if (!(nlh->nlmsg_flags & NLM_F_REQUEST))
5c58298c2   Denis V. Lunev   [NETLINK]: Fix AC...
1742
  			goto ack;
45e7ae7f7   Thomas Graf   [NETLINK]: Ignore...
1743
1744
1745
  
  		/* Skip control messages */
  		if (nlh->nlmsg_type < NLMSG_MIN_TYPE)
5c58298c2   Denis V. Lunev   [NETLINK]: Fix AC...
1746
  			goto ack;
d35b68564   Thomas Graf   [NETLINK]: Ignore...
1747

1d00a4eb4   Thomas Graf   [NETLINK]: Remove...
1748
  		err = cb(skb, nlh);
5c58298c2   Denis V. Lunev   [NETLINK]: Fix AC...
1749
1750
1751
1752
  		if (err == -EINTR)
  			goto skip;
  
  ack:
d35b68564   Thomas Graf   [NETLINK]: Ignore...
1753
  		if (nlh->nlmsg_flags & NLM_F_ACK || err)
82ace47a7   Thomas Graf   [NETLINK]: Generi...
1754
  			netlink_ack(skb, nlh, err);
82ace47a7   Thomas Graf   [NETLINK]: Generi...
1755

5c58298c2   Denis V. Lunev   [NETLINK]: Fix AC...
1756
  skip:
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
1757
  		msglen = NLMSG_ALIGN(nlh->nlmsg_len);
cd40b7d39   Denis V. Lunev   [NET]: make netli...
1758
1759
1760
  		if (msglen > skb->len)
  			msglen = skb->len;
  		skb_pull(skb, msglen);
82ace47a7   Thomas Graf   [NETLINK]: Generi...
1761
1762
1763
1764
  	}
  
  	return 0;
  }
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
1765
  EXPORT_SYMBOL(netlink_rcv_skb);
82ace47a7   Thomas Graf   [NETLINK]: Generi...
1766
1767
  
  /**
d387f6ad1   Thomas Graf   [NETLINK]: Add no...
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
   * 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...
1788
1789
1790
  		/* 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...
1791
  	}
1ce85fe40   Pablo Neira Ayuso   netlink: change n...
1792
1793
1794
1795
1796
1797
1798
  	if (report) {
  		int err2;
  
  		err2 = nlmsg_unicast(sk, skb, pid);
  		if (!err || err == -ESRCH)
  			err = err2;
  	}
d387f6ad1   Thomas Graf   [NETLINK]: Add no...
1799
1800
1801
  
  	return err;
  }
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
1802
  EXPORT_SYMBOL(nlmsg_notify);
d387f6ad1   Thomas Graf   [NETLINK]: Add no...
1803

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1804
1805
  #ifdef CONFIG_PROC_FS
  struct nl_seq_iter {
e372c4140   Denis V. Lunev   [NET]: Consolidat...
1806
  	struct seq_net_private p;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
  	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...
1818
  	for (i = 0; i < MAX_LINKS; i++) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1819
1820
1821
1822
  		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...
1823
  				if (sock_net(s) != seq_file_net(seq))
b4b510290   Eric W. Biederman   [NET]: Support mu...
1824
  					continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
  				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...
1838
  	__acquires(nl_table_lock)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
  {
  	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...
1854

b4b510290   Eric W. Biederman   [NET]: Support mu...
1855
1856
1857
1858
  	iter = seq->private;
  	s = v;
  	do {
  		s = sk_next(s);
1218854af   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
1859
  	} while (s && sock_net(s) != seq_file_net(seq));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1860
1861
  	if (s)
  		return s;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1862
1863
1864
1865
1866
1867
1868
1869
  	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...
1870
  			while (s && sock_net(s) != seq_file_net(seq))
b4b510290   Eric W. Biederman   [NET]: Support mu...
1871
  				s = sk_next(s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
  			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...
1886
  	__releases(nl_table_lock)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
  {
  	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...
1897
1898
  			 "Rmem     Wmem     Dump     Locks     Drops     Inode
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1899
1900
1901
  	else {
  		struct sock *s = v;
  		struct netlink_sock *nlk = nlk_sk(s);
cf0aa4e07   Masatake YAMATO   netlink: Adding i...
1902
1903
  		seq_printf(seq, "%p %-3d %-6d %08x %-8d %-8d %p %-8d %-8d %-8lu
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1904
1905
1906
  			   s,
  			   s->sk_protocol,
  			   nlk->pid,
513c25000   Patrick McHardy   [NETLINK]: Don't ...
1907
  			   nlk->groups ? (u32)nlk->groups[0] : 0,
31e6d363a   Eric Dumazet   net: correct off-...
1908
1909
  			   sk_rmem_alloc_get(s),
  			   sk_wmem_alloc_get(s),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1910
  			   nlk->cb,
38938bfe3   Pablo Neira Ayuso   netlink: add NETL...
1911
  			   atomic_read(&s->sk_refcnt),
cf0aa4e07   Masatake YAMATO   netlink: Adding i...
1912
1913
  			   atomic_read(&s->sk_drops),
  			   sock_i_ino(s)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1914
1915
1916
1917
1918
  			);
  
  	}
  	return 0;
  }
56b3d975b   Philippe De Muyter   [NET]: Make all i...
1919
  static const struct seq_operations netlink_seq_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1920
1921
1922
1923
1924
1925
1926
1927
1928
  	.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...
1929
1930
  	return seq_open_net(inode, file, &netlink_seq_ops,
  				sizeof(struct nl_seq_iter));
b4b510290   Eric W. Biederman   [NET]: Support mu...
1931
  }
da7071d7e   Arjan van de Ven   [PATCH] mark stru...
1932
  static const struct file_operations netlink_seq_fops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1933
1934
1935
1936
  	.owner		= THIS_MODULE,
  	.open		= netlink_seq_open,
  	.read		= seq_read,
  	.llseek		= seq_lseek,
e372c4140   Denis V. Lunev   [NET]: Consolidat...
1937
  	.release	= seq_release_net,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1938
1939
1940
1941
1942
1943
  };
  
  #endif
  
  int netlink_register_notifier(struct notifier_block *nb)
  {
e041c6834   Alan Stern   [PATCH] Notifier ...
1944
  	return atomic_notifier_chain_register(&netlink_chain, nb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1945
  }
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
1946
  EXPORT_SYMBOL(netlink_register_notifier);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1947
1948
1949
  
  int netlink_unregister_notifier(struct notifier_block *nb)
  {
e041c6834   Alan Stern   [PATCH] Notifier ...
1950
  	return atomic_notifier_chain_unregister(&netlink_chain, nb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1951
  }
6ac552fdc   Patrick McHardy   [NETLINK]: af_net...
1952
  EXPORT_SYMBOL(netlink_unregister_notifier);
746fac4dc   YOSHIFUJI Hideaki   [NET] NETLINK: Fi...
1953

90ddc4f04   Eric Dumazet   [NET]: move struc...
1954
  static const struct proto_ops netlink_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
  	.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...
1967
1968
  	.setsockopt =	netlink_setsockopt,
  	.getsockopt =	netlink_getsockopt,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1969
1970
1971
1972
1973
  	.sendmsg =	netlink_sendmsg,
  	.recvmsg =	netlink_recvmsg,
  	.mmap =		sock_no_mmap,
  	.sendpage =	sock_no_sendpage,
  };
ec1b4cf74   Stephen Hemminger   net: mark net_pro...
1974
  static const struct net_proto_family netlink_family_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1975
1976
1977
1978
  	.family = PF_NETLINK,
  	.create = netlink_create,
  	.owner	= THIS_MODULE,	/* for consistency 8) */
  };
4665079cb   Pavel Emelyanov   [NETNS]: Move som...
1979
  static int __net_init netlink_net_init(struct net *net)
b4b510290   Eric W. Biederman   [NET]: Support mu...
1980
1981
1982
1983
1984
1985
1986
  {
  #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...
1987
  static void __net_exit netlink_net_exit(struct net *net)
b4b510290   Eric W. Biederman   [NET]: Support mu...
1988
1989
1990
1991
1992
  {
  #ifdef CONFIG_PROC_FS
  	proc_net_remove(net, "netlink");
  #endif
  }
022cbae61   Denis V. Lunev   [NET]: Move unnee...
1993
  static struct pernet_operations __net_initdata netlink_net_ops = {
b4b510290   Eric W. Biederman   [NET]: Support mu...
1994
1995
1996
  	.init = netlink_net_init,
  	.exit = netlink_net_exit,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1997
1998
1999
2000
  static int __init netlink_proto_init(void)
  {
  	struct sk_buff *dummy_skb;
  	int i;
26ff5ddc5   Denis Cheng   [NETLINK]: the te...
2001
  	unsigned long limit;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2002
2003
2004
2005
2006
  	unsigned int order;
  	int err = proto_register(&netlink_proto, 0);
  
  	if (err != 0)
  		goto out;
ef047f5e1   YOSHIFUJI Hideaki   [NET]: Use BUILD_...
2007
  	BUILD_BUG_ON(sizeof(struct netlink_skb_parms) > sizeof(dummy_skb->cb));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2008

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

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

26ff5ddc5   Denis Cheng   [NETLINK]: the te...
2018
2019
2020
  	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
2021
2022
2023
  
  	for (i = 0; i < MAX_LINKS; i++) {
  		struct nl_pid_hash *hash = &nl_table[i].hash;
ea72912c8   Eric Dumazet   [NETLINK]: kzallo...
2024
  		hash->table = nl_pid_hash_zalloc(1 * sizeof(*hash->table));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2025
2026
2027
2028
2029
  		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...
2030
  			goto panic;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2031
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2032
2033
2034
2035
2036
2037
2038
  		hash->max_shift = order;
  		hash->shift = 0;
  		hash->mask = 0;
  		hash->rehash_time = jiffies;
  	}
  
  	sock_register(&netlink_family_ops);
b4b510290   Eric W. Biederman   [NET]: Support mu...
2039
  	register_pernet_subsys(&netlink_net_ops);
746fac4dc   YOSHIFUJI Hideaki   [NET] NETLINK: Fi...
2040
  	/* The netlink device handler may be needed early. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2041
2042
2043
  	rtnetlink_init();
  out:
  	return err;
fab2caf62   Akinobu Mita   [NETLINK]: Call p...
2044
2045
2046
  panic:
  	panic("netlink_init: Cannot allocate nl_table
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2047
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2048
  core_initcall(netlink_proto_init);