1
2
3
4
5
6
7
8
9
10
11
12
13
14#include <linux/netdevice.h>
15#include <linux/rtnetlink.h>
16#include <linux/export.h>
17#include <linux/list.h>
18#include <linux/proc_fs.h>
19
20
21
22
23
24static int __hw_addr_create_ex(struct netdev_hw_addr_list *list,
25 unsigned char *addr, int addr_len,
26 unsigned char addr_type, bool global)
27{
28 struct netdev_hw_addr *ha;
29 int alloc_size;
30
31 alloc_size = sizeof(*ha);
32 if (alloc_size < L1_CACHE_BYTES)
33 alloc_size = L1_CACHE_BYTES;
34 ha = kmalloc(alloc_size, GFP_ATOMIC);
35 if (!ha)
36 return -ENOMEM;
37 memcpy(ha->addr, addr, addr_len);
38 ha->type = addr_type;
39 ha->refcount = 1;
40 ha->global_use = global;
41 ha->synced = false;
42 list_add_tail_rcu(&ha->list, &list->list);
43 list->count++;
44
45 return 0;
46}
47
48static int __hw_addr_add_ex(struct netdev_hw_addr_list *list,
49 unsigned char *addr, int addr_len,
50 unsigned char addr_type, bool global)
51{
52 struct netdev_hw_addr *ha;
53
54 if (addr_len > MAX_ADDR_LEN)
55 return -EINVAL;
56
57 list_for_each_entry(ha, &list->list, list) {
58 if (!memcmp(ha->addr, addr, addr_len) &&
59 ha->type == addr_type) {
60 if (global) {
61
62 if (ha->global_use)
63 return 0;
64 else
65 ha->global_use = true;
66 }
67 ha->refcount++;
68 return 0;
69 }
70 }
71
72 return __hw_addr_create_ex(list, addr, addr_len, addr_type, global);
73}
74
75static int __hw_addr_add(struct netdev_hw_addr_list *list, unsigned char *addr,
76 int addr_len, unsigned char addr_type)
77{
78 return __hw_addr_add_ex(list, addr, addr_len, addr_type, false);
79}
80
81static int __hw_addr_del_ex(struct netdev_hw_addr_list *list,
82 unsigned char *addr, int addr_len,
83 unsigned char addr_type, bool global)
84{
85 struct netdev_hw_addr *ha;
86
87 list_for_each_entry(ha, &list->list, list) {
88 if (!memcmp(ha->addr, addr, addr_len) &&
89 (ha->type == addr_type || !addr_type)) {
90 if (global) {
91 if (!ha->global_use)
92 break;
93 else
94 ha->global_use = false;
95 }
96 if (--ha->refcount)
97 return 0;
98 list_del_rcu(&ha->list);
99 kfree_rcu(ha, rcu_head);
100 list->count--;
101 return 0;
102 }
103 }
104 return -ENOENT;
105}
106
107static int __hw_addr_del(struct netdev_hw_addr_list *list, unsigned char *addr,
108 int addr_len, unsigned char addr_type)
109{
110 return __hw_addr_del_ex(list, addr, addr_len, addr_type, false);
111}
112
113int __hw_addr_add_multiple(struct netdev_hw_addr_list *to_list,
114 struct netdev_hw_addr_list *from_list,
115 int addr_len, unsigned char addr_type)
116{
117 int err;
118 struct netdev_hw_addr *ha, *ha2;
119 unsigned char type;
120
121 list_for_each_entry(ha, &from_list->list, list) {
122 type = addr_type ? addr_type : ha->type;
123 err = __hw_addr_add(to_list, ha->addr, addr_len, type);
124 if (err)
125 goto unroll;
126 }
127 return 0;
128
129unroll:
130 list_for_each_entry(ha2, &from_list->list, list) {
131 if (ha2 == ha)
132 break;
133 type = addr_type ? addr_type : ha2->type;
134 __hw_addr_del(to_list, ha2->addr, addr_len, type);
135 }
136 return err;
137}
138EXPORT_SYMBOL(__hw_addr_add_multiple);
139
140void __hw_addr_del_multiple(struct netdev_hw_addr_list *to_list,
141 struct netdev_hw_addr_list *from_list,
142 int addr_len, unsigned char addr_type)
143{
144 struct netdev_hw_addr *ha;
145 unsigned char type;
146
147 list_for_each_entry(ha, &from_list->list, list) {
148 type = addr_type ? addr_type : ha->type;
149 __hw_addr_del(to_list, ha->addr, addr_len, type);
150 }
151}
152EXPORT_SYMBOL(__hw_addr_del_multiple);
153
154int __hw_addr_sync(struct netdev_hw_addr_list *to_list,
155 struct netdev_hw_addr_list *from_list,
156 int addr_len)
157{
158 int err = 0;
159 struct netdev_hw_addr *ha, *tmp;
160
161 list_for_each_entry_safe(ha, tmp, &from_list->list, list) {
162 if (!ha->synced) {
163 err = __hw_addr_add(to_list, ha->addr,
164 addr_len, ha->type);
165 if (err)
166 break;
167 ha->synced = true;
168 ha->refcount++;
169 } else if (ha->refcount == 1) {
170 __hw_addr_del(to_list, ha->addr, addr_len, ha->type);
171 __hw_addr_del(from_list, ha->addr, addr_len, ha->type);
172 }
173 }
174 return err;
175}
176EXPORT_SYMBOL(__hw_addr_sync);
177
178void __hw_addr_unsync(struct netdev_hw_addr_list *to_list,
179 struct netdev_hw_addr_list *from_list,
180 int addr_len)
181{
182 struct netdev_hw_addr *ha, *tmp;
183
184 list_for_each_entry_safe(ha, tmp, &from_list->list, list) {
185 if (ha->synced) {
186 __hw_addr_del(to_list, ha->addr,
187 addr_len, ha->type);
188 ha->synced = false;
189 __hw_addr_del(from_list, ha->addr,
190 addr_len, ha->type);
191 }
192 }
193}
194EXPORT_SYMBOL(__hw_addr_unsync);
195
196void __hw_addr_flush(struct netdev_hw_addr_list *list)
197{
198 struct netdev_hw_addr *ha, *tmp;
199
200 list_for_each_entry_safe(ha, tmp, &list->list, list) {
201 list_del_rcu(&ha->list);
202 kfree_rcu(ha, rcu_head);
203 }
204 list->count = 0;
205}
206EXPORT_SYMBOL(__hw_addr_flush);
207
208void __hw_addr_init(struct netdev_hw_addr_list *list)
209{
210 INIT_LIST_HEAD(&list->list);
211 list->count = 0;
212}
213EXPORT_SYMBOL(__hw_addr_init);
214
215
216
217
218
219
220
221
222
223
224
225
226
227void dev_addr_flush(struct net_device *dev)
228{
229
230
231 __hw_addr_flush(&dev->dev_addrs);
232 dev->dev_addr = NULL;
233}
234EXPORT_SYMBOL(dev_addr_flush);
235
236
237
238
239
240
241
242
243
244
245int dev_addr_init(struct net_device *dev)
246{
247 unsigned char addr[MAX_ADDR_LEN];
248 struct netdev_hw_addr *ha;
249 int err;
250
251
252
253 __hw_addr_init(&dev->dev_addrs);
254 memset(addr, 0, sizeof(addr));
255 err = __hw_addr_add(&dev->dev_addrs, addr, sizeof(addr),
256 NETDEV_HW_ADDR_T_LAN);
257 if (!err) {
258
259
260
261
262 ha = list_first_entry(&dev->dev_addrs.list,
263 struct netdev_hw_addr, list);
264 dev->dev_addr = ha->addr;
265 }
266 return err;
267}
268EXPORT_SYMBOL(dev_addr_init);
269
270
271
272
273
274
275
276
277
278
279
280
281int dev_addr_add(struct net_device *dev, unsigned char *addr,
282 unsigned char addr_type)
283{
284 int err;
285
286 ASSERT_RTNL();
287
288 err = __hw_addr_add(&dev->dev_addrs, addr, dev->addr_len, addr_type);
289 if (!err)
290 call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
291 return err;
292}
293EXPORT_SYMBOL(dev_addr_add);
294
295
296
297
298
299
300
301
302
303
304
305
306int dev_addr_del(struct net_device *dev, unsigned char *addr,
307 unsigned char addr_type)
308{
309 int err;
310 struct netdev_hw_addr *ha;
311
312 ASSERT_RTNL();
313
314
315
316
317
318 ha = list_first_entry(&dev->dev_addrs.list,
319 struct netdev_hw_addr, list);
320 if (!memcmp(ha->addr, addr, dev->addr_len) &&
321 ha->type == addr_type && ha->refcount == 1)
322 return -ENOENT;
323
324 err = __hw_addr_del(&dev->dev_addrs, addr, dev->addr_len,
325 addr_type);
326 if (!err)
327 call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
328 return err;
329}
330EXPORT_SYMBOL(dev_addr_del);
331
332
333
334
335
336
337
338
339
340
341
342int dev_addr_add_multiple(struct net_device *to_dev,
343 struct net_device *from_dev,
344 unsigned char addr_type)
345{
346 int err;
347
348 ASSERT_RTNL();
349
350 if (from_dev->addr_len != to_dev->addr_len)
351 return -EINVAL;
352 err = __hw_addr_add_multiple(&to_dev->dev_addrs, &from_dev->dev_addrs,
353 to_dev->addr_len, addr_type);
354 if (!err)
355 call_netdevice_notifiers(NETDEV_CHANGEADDR, to_dev);
356 return err;
357}
358EXPORT_SYMBOL(dev_addr_add_multiple);
359
360
361
362
363
364
365
366
367
368
369
370int dev_addr_del_multiple(struct net_device *to_dev,
371 struct net_device *from_dev,
372 unsigned char addr_type)
373{
374 ASSERT_RTNL();
375
376 if (from_dev->addr_len != to_dev->addr_len)
377 return -EINVAL;
378 __hw_addr_del_multiple(&to_dev->dev_addrs, &from_dev->dev_addrs,
379 to_dev->addr_len, addr_type);
380 call_netdevice_notifiers(NETDEV_CHANGEADDR, to_dev);
381 return 0;
382}
383EXPORT_SYMBOL(dev_addr_del_multiple);
384
385
386
387
388
389
390
391
392
393
394int dev_uc_add_excl(struct net_device *dev, unsigned char *addr)
395{
396 struct netdev_hw_addr *ha;
397 int err;
398
399 netif_addr_lock_bh(dev);
400 list_for_each_entry(ha, &dev->uc.list, list) {
401 if (!memcmp(ha->addr, addr, dev->addr_len) &&
402 ha->type == NETDEV_HW_ADDR_T_UNICAST) {
403 err = -EEXIST;
404 goto out;
405 }
406 }
407 err = __hw_addr_create_ex(&dev->uc, addr, dev->addr_len,
408 NETDEV_HW_ADDR_T_UNICAST, true);
409 if (!err)
410 __dev_set_rx_mode(dev);
411out:
412 netif_addr_unlock_bh(dev);
413 return err;
414}
415EXPORT_SYMBOL(dev_uc_add_excl);
416
417
418
419
420
421
422
423
424
425int dev_uc_add(struct net_device *dev, unsigned char *addr)
426{
427 int err;
428
429 netif_addr_lock_bh(dev);
430 err = __hw_addr_add(&dev->uc, addr, dev->addr_len,
431 NETDEV_HW_ADDR_T_UNICAST);
432 if (!err)
433 __dev_set_rx_mode(dev);
434 netif_addr_unlock_bh(dev);
435 return err;
436}
437EXPORT_SYMBOL(dev_uc_add);
438
439
440
441
442
443
444
445
446
447int dev_uc_del(struct net_device *dev, unsigned char *addr)
448{
449 int err;
450
451 netif_addr_lock_bh(dev);
452 err = __hw_addr_del(&dev->uc, addr, dev->addr_len,
453 NETDEV_HW_ADDR_T_UNICAST);
454 if (!err)
455 __dev_set_rx_mode(dev);
456 netif_addr_unlock_bh(dev);
457 return err;
458}
459EXPORT_SYMBOL(dev_uc_del);
460
461
462
463
464
465
466
467
468
469
470
471
472
473int dev_uc_sync(struct net_device *to, struct net_device *from)
474{
475 int err = 0;
476
477 if (to->addr_len != from->addr_len)
478 return -EINVAL;
479
480 netif_addr_lock_nested(to);
481 err = __hw_addr_sync(&to->uc, &from->uc, to->addr_len);
482 if (!err)
483 __dev_set_rx_mode(to);
484 netif_addr_unlock(to);
485 return err;
486}
487EXPORT_SYMBOL(dev_uc_sync);
488
489
490
491
492
493
494
495
496
497
498void dev_uc_unsync(struct net_device *to, struct net_device *from)
499{
500 if (to->addr_len != from->addr_len)
501 return;
502
503 netif_addr_lock_bh(from);
504 netif_addr_lock_nested(to);
505 __hw_addr_unsync(&to->uc, &from->uc, to->addr_len);
506 __dev_set_rx_mode(to);
507 netif_addr_unlock(to);
508 netif_addr_unlock_bh(from);
509}
510EXPORT_SYMBOL(dev_uc_unsync);
511
512
513
514
515
516
517
518void dev_uc_flush(struct net_device *dev)
519{
520 netif_addr_lock_bh(dev);
521 __hw_addr_flush(&dev->uc);
522 netif_addr_unlock_bh(dev);
523}
524EXPORT_SYMBOL(dev_uc_flush);
525
526
527
528
529
530
531
532void dev_uc_init(struct net_device *dev)
533{
534 __hw_addr_init(&dev->uc);
535}
536EXPORT_SYMBOL(dev_uc_init);
537
538
539
540
541
542
543
544
545
546
547int dev_mc_add_excl(struct net_device *dev, unsigned char *addr)
548{
549 struct netdev_hw_addr *ha;
550 int err;
551
552 netif_addr_lock_bh(dev);
553 list_for_each_entry(ha, &dev->mc.list, list) {
554 if (!memcmp(ha->addr, addr, dev->addr_len) &&
555 ha->type == NETDEV_HW_ADDR_T_MULTICAST) {
556 err = -EEXIST;
557 goto out;
558 }
559 }
560 err = __hw_addr_create_ex(&dev->mc, addr, dev->addr_len,
561 NETDEV_HW_ADDR_T_MULTICAST, true);
562 if (!err)
563 __dev_set_rx_mode(dev);
564out:
565 netif_addr_unlock_bh(dev);
566 return err;
567}
568EXPORT_SYMBOL(dev_mc_add_excl);
569
570static int __dev_mc_add(struct net_device *dev, unsigned char *addr,
571 bool global)
572{
573 int err;
574
575 netif_addr_lock_bh(dev);
576 err = __hw_addr_add_ex(&dev->mc, addr, dev->addr_len,
577 NETDEV_HW_ADDR_T_MULTICAST, global);
578 if (!err)
579 __dev_set_rx_mode(dev);
580 netif_addr_unlock_bh(dev);
581 return err;
582}
583
584
585
586
587
588
589
590
591int dev_mc_add(struct net_device *dev, unsigned char *addr)
592{
593 return __dev_mc_add(dev, addr, false);
594}
595EXPORT_SYMBOL(dev_mc_add);
596
597
598
599
600
601
602
603
604int dev_mc_add_global(struct net_device *dev, unsigned char *addr)
605{
606 return __dev_mc_add(dev, addr, true);
607}
608EXPORT_SYMBOL(dev_mc_add_global);
609
610static int __dev_mc_del(struct net_device *dev, unsigned char *addr,
611 bool global)
612{
613 int err;
614
615 netif_addr_lock_bh(dev);
616 err = __hw_addr_del_ex(&dev->mc, addr, dev->addr_len,
617 NETDEV_HW_ADDR_T_MULTICAST, global);
618 if (!err)
619 __dev_set_rx_mode(dev);
620 netif_addr_unlock_bh(dev);
621 return err;
622}
623
624
625
626
627
628
629
630
631
632int dev_mc_del(struct net_device *dev, unsigned char *addr)
633{
634 return __dev_mc_del(dev, addr, false);
635}
636EXPORT_SYMBOL(dev_mc_del);
637
638
639
640
641
642
643
644
645
646int dev_mc_del_global(struct net_device *dev, unsigned char *addr)
647{
648 return __dev_mc_del(dev, addr, true);
649}
650EXPORT_SYMBOL(dev_mc_del_global);
651
652
653
654
655
656
657
658
659
660
661
662
663
664int dev_mc_sync(struct net_device *to, struct net_device *from)
665{
666 int err = 0;
667
668 if (to->addr_len != from->addr_len)
669 return -EINVAL;
670
671 netif_addr_lock_nested(to);
672 err = __hw_addr_sync(&to->mc, &from->mc, to->addr_len);
673 if (!err)
674 __dev_set_rx_mode(to);
675 netif_addr_unlock(to);
676 return err;
677}
678EXPORT_SYMBOL(dev_mc_sync);
679
680
681
682
683
684
685
686
687
688
689void dev_mc_unsync(struct net_device *to, struct net_device *from)
690{
691 if (to->addr_len != from->addr_len)
692 return;
693
694 netif_addr_lock_bh(from);
695 netif_addr_lock_nested(to);
696 __hw_addr_unsync(&to->mc, &from->mc, to->addr_len);
697 __dev_set_rx_mode(to);
698 netif_addr_unlock(to);
699 netif_addr_unlock_bh(from);
700}
701EXPORT_SYMBOL(dev_mc_unsync);
702
703
704
705
706
707
708
709void dev_mc_flush(struct net_device *dev)
710{
711 netif_addr_lock_bh(dev);
712 __hw_addr_flush(&dev->mc);
713 netif_addr_unlock_bh(dev);
714}
715EXPORT_SYMBOL(dev_mc_flush);
716
717
718
719
720
721
722
723void dev_mc_init(struct net_device *dev)
724{
725 __hw_addr_init(&dev->mc);
726}
727EXPORT_SYMBOL(dev_mc_init);
728
729#ifdef CONFIG_PROC_FS
730#include <linux/seq_file.h>
731
732static int dev_mc_seq_show(struct seq_file *seq, void *v)
733{
734 struct netdev_hw_addr *ha;
735 struct net_device *dev = v;
736
737 if (v == SEQ_START_TOKEN)
738 return 0;
739
740 netif_addr_lock_bh(dev);
741 netdev_for_each_mc_addr(ha, dev) {
742 int i;
743
744 seq_printf(seq, "%-4d %-15s %-5d %-5d ", dev->ifindex,
745 dev->name, ha->refcount, ha->global_use);
746
747 for (i = 0; i < dev->addr_len; i++)
748 seq_printf(seq, "%02x", ha->addr[i]);
749
750 seq_putc(seq, '\n');
751 }
752 netif_addr_unlock_bh(dev);
753 return 0;
754}
755
756static const struct seq_operations dev_mc_seq_ops = {
757 .start = dev_seq_start,
758 .next = dev_seq_next,
759 .stop = dev_seq_stop,
760 .show = dev_mc_seq_show,
761};
762
763static int dev_mc_seq_open(struct inode *inode, struct file *file)
764{
765 return seq_open_net(inode, file, &dev_mc_seq_ops,
766 sizeof(struct seq_net_private));
767}
768
769static const struct file_operations dev_mc_seq_fops = {
770 .owner = THIS_MODULE,
771 .open = dev_mc_seq_open,
772 .read = seq_read,
773 .llseek = seq_lseek,
774 .release = seq_release_net,
775};
776
777#endif
778
779static int __net_init dev_mc_net_init(struct net *net)
780{
781 if (!proc_net_fops_create(net, "dev_mcast", 0, &dev_mc_seq_fops))
782 return -ENOMEM;
783 return 0;
784}
785
786static void __net_exit dev_mc_net_exit(struct net *net)
787{
788 proc_net_remove(net, "dev_mcast");
789}
790
791static struct pernet_operations __net_initdata dev_mc_net_ops = {
792 .init = dev_mc_net_init,
793 .exit = dev_mc_net_exit,
794};
795
796void __init dev_mcast_init(void)
797{
798 register_pernet_subsys(&dev_mc_net_ops);
799}
800
801