1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#include <linux/capability.h>
17#include <linux/module.h>
18#include <linux/errno.h>
19#include <linux/types.h>
20#include <linux/random.h>
21#include <linux/string.h>
22#include <linux/socket.h>
23#include <linux/sockios.h>
24#include <linux/net.h>
25#include <linux/in6.h>
26#include <linux/netdevice.h>
27#include <linux/if_arp.h>
28#include <linux/route.h>
29#include <linux/init.h>
30#include <linux/proc_fs.h>
31#include <linux/seq_file.h>
32
33#include <net/net_namespace.h>
34#include <net/sock.h>
35#include <net/snmp.h>
36
37#include <net/ipv6.h>
38#include <net/protocol.h>
39#include <net/if_inet6.h>
40#include <net/ndisc.h>
41#include <net/addrconf.h>
42#include <net/ip6_route.h>
43
44#include <net/checksum.h>
45
46static int ipv6_dev_ac_dec(struct net_device *dev, struct in6_addr *addr);
47
48
49static DEFINE_RWLOCK(ipv6_sk_ac_lock);
50
51
52
53
54
55
56int ipv6_sock_ac_join(struct sock *sk, int ifindex, struct in6_addr *addr)
57{
58 struct ipv6_pinfo *np = inet6_sk(sk);
59 struct net_device *dev = NULL;
60 struct inet6_dev *idev;
61 struct ipv6_ac_socklist *pac;
62 struct net *net = sock_net(sk);
63 int ishost = !net->ipv6.devconf_all->forwarding;
64 int err = 0;
65
66 if (!capable(CAP_NET_ADMIN))
67 return -EPERM;
68 if (ipv6_addr_is_multicast(addr))
69 return -EINVAL;
70 if (ipv6_chk_addr(net, addr, NULL, 0))
71 return -EINVAL;
72
73 pac = sock_kmalloc(sk, sizeof(struct ipv6_ac_socklist), GFP_KERNEL);
74 if (pac == NULL)
75 return -ENOMEM;
76 pac->acl_next = NULL;
77 ipv6_addr_copy(&pac->acl_addr, addr);
78
79 if (ifindex == 0) {
80 struct rt6_info *rt;
81
82 rt = rt6_lookup(net, addr, NULL, 0, 0);
83 if (rt) {
84 dev = rt->rt6i_dev;
85 dev_hold(dev);
86 dst_release(&rt->u.dst);
87 } else if (ishost) {
88 err = -EADDRNOTAVAIL;
89 goto out_free_pac;
90 } else {
91
92
93 dev = dev_get_by_flags(net, IFF_UP, IFF_UP|IFF_LOOPBACK);
94 }
95 } else
96 dev = dev_get_by_index(net, ifindex);
97
98 if (dev == NULL) {
99 err = -ENODEV;
100 goto out_free_pac;
101 }
102
103 idev = in6_dev_get(dev);
104 if (!idev) {
105 if (ifindex)
106 err = -ENODEV;
107 else
108 err = -EADDRNOTAVAIL;
109 goto out_dev_put;
110 }
111
112 ishost = !idev->cnf.forwarding;
113 in6_dev_put(idev);
114
115 pac->acl_ifindex = dev->ifindex;
116
117
118
119
120
121
122 if (!ipv6_chk_prefix(addr, dev)) {
123 if (ishost)
124 err = -EADDRNOTAVAIL;
125 if (err)
126 goto out_dev_put;
127 }
128
129 err = ipv6_dev_ac_inc(dev, addr);
130 if (err)
131 goto out_dev_put;
132
133 write_lock_bh(&ipv6_sk_ac_lock);
134 pac->acl_next = np->ipv6_ac_list;
135 np->ipv6_ac_list = pac;
136 write_unlock_bh(&ipv6_sk_ac_lock);
137
138 dev_put(dev);
139
140 return 0;
141
142out_dev_put:
143 dev_put(dev);
144out_free_pac:
145 sock_kfree_s(sk, pac, sizeof(*pac));
146 return err;
147}
148
149
150
151
152int ipv6_sock_ac_drop(struct sock *sk, int ifindex, struct in6_addr *addr)
153{
154 struct ipv6_pinfo *np = inet6_sk(sk);
155 struct net_device *dev;
156 struct ipv6_ac_socklist *pac, *prev_pac;
157 struct net *net = sock_net(sk);
158
159 write_lock_bh(&ipv6_sk_ac_lock);
160 prev_pac = NULL;
161 for (pac = np->ipv6_ac_list; pac; pac = pac->acl_next) {
162 if ((ifindex == 0 || pac->acl_ifindex == ifindex) &&
163 ipv6_addr_equal(&pac->acl_addr, addr))
164 break;
165 prev_pac = pac;
166 }
167 if (!pac) {
168 write_unlock_bh(&ipv6_sk_ac_lock);
169 return -ENOENT;
170 }
171 if (prev_pac)
172 prev_pac->acl_next = pac->acl_next;
173 else
174 np->ipv6_ac_list = pac->acl_next;
175
176 write_unlock_bh(&ipv6_sk_ac_lock);
177
178 dev = dev_get_by_index(net, pac->acl_ifindex);
179 if (dev) {
180 ipv6_dev_ac_dec(dev, &pac->acl_addr);
181 dev_put(dev);
182 }
183 sock_kfree_s(sk, pac, sizeof(*pac));
184 return 0;
185}
186
187void ipv6_sock_ac_close(struct sock *sk)
188{
189 struct ipv6_pinfo *np = inet6_sk(sk);
190 struct net_device *dev = NULL;
191 struct ipv6_ac_socklist *pac;
192 struct net *net = sock_net(sk);
193 int prev_index;
194
195 write_lock_bh(&ipv6_sk_ac_lock);
196 pac = np->ipv6_ac_list;
197 np->ipv6_ac_list = NULL;
198 write_unlock_bh(&ipv6_sk_ac_lock);
199
200 prev_index = 0;
201 while (pac) {
202 struct ipv6_ac_socklist *next = pac->acl_next;
203
204 if (pac->acl_ifindex != prev_index) {
205 if (dev)
206 dev_put(dev);
207 dev = dev_get_by_index(net, pac->acl_ifindex);
208 prev_index = pac->acl_ifindex;
209 }
210 if (dev)
211 ipv6_dev_ac_dec(dev, &pac->acl_addr);
212 sock_kfree_s(sk, pac, sizeof(*pac));
213 pac = next;
214 }
215 if (dev)
216 dev_put(dev);
217}
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248static void aca_put(struct ifacaddr6 *ac)
249{
250 if (atomic_dec_and_test(&ac->aca_refcnt)) {
251 in6_dev_put(ac->aca_idev);
252 dst_release(&ac->aca_rt->u.dst);
253 kfree(ac);
254 }
255}
256
257
258
259
260int ipv6_dev_ac_inc(struct net_device *dev, struct in6_addr *addr)
261{
262 struct ifacaddr6 *aca;
263 struct inet6_dev *idev;
264 struct rt6_info *rt;
265 int err;
266
267 idev = in6_dev_get(dev);
268
269 if (idev == NULL)
270 return -EINVAL;
271
272 write_lock_bh(&idev->lock);
273 if (idev->dead) {
274 err = -ENODEV;
275 goto out;
276 }
277
278 for (aca = idev->ac_list; aca; aca = aca->aca_next) {
279 if (ipv6_addr_equal(&aca->aca_addr, addr)) {
280 aca->aca_users++;
281 err = 0;
282 goto out;
283 }
284 }
285
286
287
288
289
290 aca = kzalloc(sizeof(struct ifacaddr6), GFP_ATOMIC);
291
292 if (aca == NULL) {
293 err = -ENOMEM;
294 goto out;
295 }
296
297 rt = addrconf_dst_alloc(idev, addr, 1);
298 if (IS_ERR(rt)) {
299 kfree(aca);
300 err = PTR_ERR(rt);
301 goto out;
302 }
303
304 ipv6_addr_copy(&aca->aca_addr, addr);
305 aca->aca_idev = idev;
306 aca->aca_rt = rt;
307 aca->aca_users = 1;
308
309 aca->aca_cstamp = aca->aca_tstamp = jiffies;
310 atomic_set(&aca->aca_refcnt, 2);
311 spin_lock_init(&aca->aca_lock);
312
313 aca->aca_next = idev->ac_list;
314 idev->ac_list = aca;
315 write_unlock_bh(&idev->lock);
316
317 ip6_ins_rt(rt);
318
319 addrconf_join_solict(dev, &aca->aca_addr);
320
321 aca_put(aca);
322 return 0;
323out:
324 write_unlock_bh(&idev->lock);
325 in6_dev_put(idev);
326 return err;
327}
328
329
330
331
332int __ipv6_dev_ac_dec(struct inet6_dev *idev, struct in6_addr *addr)
333{
334 struct ifacaddr6 *aca, *prev_aca;
335
336 write_lock_bh(&idev->lock);
337 prev_aca = NULL;
338 for (aca = idev->ac_list; aca; aca = aca->aca_next) {
339 if (ipv6_addr_equal(&aca->aca_addr, addr))
340 break;
341 prev_aca = aca;
342 }
343 if (!aca) {
344 write_unlock_bh(&idev->lock);
345 return -ENOENT;
346 }
347 if (--aca->aca_users > 0) {
348 write_unlock_bh(&idev->lock);
349 return 0;
350 }
351 if (prev_aca)
352 prev_aca->aca_next = aca->aca_next;
353 else
354 idev->ac_list = aca->aca_next;
355 write_unlock_bh(&idev->lock);
356 addrconf_leave_solict(idev, &aca->aca_addr);
357
358 dst_hold(&aca->aca_rt->u.dst);
359 ip6_del_rt(aca->aca_rt);
360
361 aca_put(aca);
362 return 0;
363}
364
365static int ipv6_dev_ac_dec(struct net_device *dev, struct in6_addr *addr)
366{
367 int ret;
368 struct inet6_dev *idev = in6_dev_get(dev);
369 if (idev == NULL)
370 return -ENODEV;
371 ret = __ipv6_dev_ac_dec(idev, addr);
372 in6_dev_put(idev);
373 return ret;
374}
375
376
377
378
379static int ipv6_chk_acast_dev(struct net_device *dev, struct in6_addr *addr)
380{
381 struct inet6_dev *idev;
382 struct ifacaddr6 *aca;
383
384 idev = in6_dev_get(dev);
385 if (idev) {
386 read_lock_bh(&idev->lock);
387 for (aca = idev->ac_list; aca; aca = aca->aca_next)
388 if (ipv6_addr_equal(&aca->aca_addr, addr))
389 break;
390 read_unlock_bh(&idev->lock);
391 in6_dev_put(idev);
392 return aca != NULL;
393 }
394 return 0;
395}
396
397
398
399
400int ipv6_chk_acast_addr(struct net *net, struct net_device *dev,
401 struct in6_addr *addr)
402{
403 int found = 0;
404
405 if (dev)
406 return ipv6_chk_acast_dev(dev, addr);
407 read_lock(&dev_base_lock);
408 for_each_netdev(net, dev)
409 if (ipv6_chk_acast_dev(dev, addr)) {
410 found = 1;
411 break;
412 }
413 read_unlock(&dev_base_lock);
414 return found;
415}
416
417
418#ifdef CONFIG_PROC_FS
419struct ac6_iter_state {
420 struct seq_net_private p;
421 struct net_device *dev;
422 struct inet6_dev *idev;
423};
424
425#define ac6_seq_private(seq) ((struct ac6_iter_state *)(seq)->private)
426
427static inline struct ifacaddr6 *ac6_get_first(struct seq_file *seq)
428{
429 struct ifacaddr6 *im = NULL;
430 struct ac6_iter_state *state = ac6_seq_private(seq);
431 struct net *net = seq_file_net(seq);
432
433 state->idev = NULL;
434 for_each_netdev(net, state->dev) {
435 struct inet6_dev *idev;
436 idev = in6_dev_get(state->dev);
437 if (!idev)
438 continue;
439 read_lock_bh(&idev->lock);
440 im = idev->ac_list;
441 if (im) {
442 state->idev = idev;
443 break;
444 }
445 read_unlock_bh(&idev->lock);
446 in6_dev_put(idev);
447 }
448 return im;
449}
450
451static struct ifacaddr6 *ac6_get_next(struct seq_file *seq, struct ifacaddr6 *im)
452{
453 struct ac6_iter_state *state = ac6_seq_private(seq);
454
455 im = im->aca_next;
456 while (!im) {
457 if (likely(state->idev != NULL)) {
458 read_unlock_bh(&state->idev->lock);
459 in6_dev_put(state->idev);
460 }
461 state->dev = next_net_device(state->dev);
462 if (!state->dev) {
463 state->idev = NULL;
464 break;
465 }
466 state->idev = in6_dev_get(state->dev);
467 if (!state->idev)
468 continue;
469 read_lock_bh(&state->idev->lock);
470 im = state->idev->ac_list;
471 }
472 return im;
473}
474
475static struct ifacaddr6 *ac6_get_idx(struct seq_file *seq, loff_t pos)
476{
477 struct ifacaddr6 *im = ac6_get_first(seq);
478 if (im)
479 while (pos && (im = ac6_get_next(seq, im)) != NULL)
480 --pos;
481 return pos ? NULL : im;
482}
483
484static void *ac6_seq_start(struct seq_file *seq, loff_t *pos)
485 __acquires(dev_base_lock)
486{
487 read_lock(&dev_base_lock);
488 return ac6_get_idx(seq, *pos);
489}
490
491static void *ac6_seq_next(struct seq_file *seq, void *v, loff_t *pos)
492{
493 struct ifacaddr6 *im;
494 im = ac6_get_next(seq, v);
495 ++*pos;
496 return im;
497}
498
499static void ac6_seq_stop(struct seq_file *seq, void *v)
500 __releases(dev_base_lock)
501{
502 struct ac6_iter_state *state = ac6_seq_private(seq);
503 if (likely(state->idev != NULL)) {
504 read_unlock_bh(&state->idev->lock);
505 in6_dev_put(state->idev);
506 }
507 read_unlock(&dev_base_lock);
508}
509
510static int ac6_seq_show(struct seq_file *seq, void *v)
511{
512 struct ifacaddr6 *im = (struct ifacaddr6 *)v;
513 struct ac6_iter_state *state = ac6_seq_private(seq);
514
515 seq_printf(seq,
516 "%-4d %-15s " NIP6_SEQFMT " %5d\n",
517 state->dev->ifindex, state->dev->name,
518 NIP6(im->aca_addr),
519 im->aca_users);
520 return 0;
521}
522
523static const struct seq_operations ac6_seq_ops = {
524 .start = ac6_seq_start,
525 .next = ac6_seq_next,
526 .stop = ac6_seq_stop,
527 .show = ac6_seq_show,
528};
529
530static int ac6_seq_open(struct inode *inode, struct file *file)
531{
532 return seq_open_net(inode, file, &ac6_seq_ops,
533 sizeof(struct ac6_iter_state));
534}
535
536static const struct file_operations ac6_seq_fops = {
537 .owner = THIS_MODULE,
538 .open = ac6_seq_open,
539 .read = seq_read,
540 .llseek = seq_lseek,
541 .release = seq_release_net,
542};
543
544int ac6_proc_init(struct net *net)
545{
546 if (!proc_net_fops_create(net, "anycast6", S_IRUGO, &ac6_seq_fops))
547 return -ENOMEM;
548
549 return 0;
550}
551
552void ac6_proc_exit(struct net *net)
553{
554 proc_net_remove(net, "anycast6");
555}
556#endif
557