diff options
-rw-r--r-- | include/linux/netdevice.h | 11 | ||||
-rw-r--r-- | net/core/dev.c | 69 |
2 files changed, 80 insertions, 0 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 7a8f22fb4eee..aa389c77aa3e 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
@@ -177,6 +177,14 @@ struct netif_rx_stats | |||
177 | 177 | ||
178 | DECLARE_PER_CPU(struct netif_rx_stats, netdev_rx_stat); | 178 | DECLARE_PER_CPU(struct netif_rx_stats, netdev_rx_stat); |
179 | 179 | ||
180 | struct dev_addr_list | ||
181 | { | ||
182 | struct dev_addr_list *next; | ||
183 | u8 da_addr[MAX_ADDR_LEN]; | ||
184 | u8 da_addrlen; | ||
185 | int da_users; | ||
186 | int da_gusers; | ||
187 | }; | ||
180 | 188 | ||
181 | /* | 189 | /* |
182 | * We tag multicasts with these structures. | 190 | * We tag multicasts with these structures. |
@@ -1008,6 +1016,9 @@ extern void dev_mc_upload(struct net_device *dev); | |||
1008 | extern int dev_mc_delete(struct net_device *dev, void *addr, int alen, int all); | 1016 | extern int dev_mc_delete(struct net_device *dev, void *addr, int alen, int all); |
1009 | extern int dev_mc_add(struct net_device *dev, void *addr, int alen, int newonly); | 1017 | extern int dev_mc_add(struct net_device *dev, void *addr, int alen, int newonly); |
1010 | extern void dev_mc_discard(struct net_device *dev); | 1018 | extern void dev_mc_discard(struct net_device *dev); |
1019 | extern int __dev_addr_delete(struct dev_addr_list **list, void *addr, int alen, int all); | ||
1020 | extern int __dev_addr_add(struct dev_addr_list **list, void *addr, int alen, int newonly); | ||
1021 | extern void __dev_addr_discard(struct dev_addr_list **list); | ||
1011 | extern void dev_set_promiscuity(struct net_device *dev, int inc); | 1022 | extern void dev_set_promiscuity(struct net_device *dev, int inc); |
1012 | extern void dev_set_allmulti(struct net_device *dev, int inc); | 1023 | extern void dev_set_allmulti(struct net_device *dev, int inc); |
1013 | extern void netdev_state_change(struct net_device *dev); | 1024 | extern void netdev_state_change(struct net_device *dev); |
diff --git a/net/core/dev.c b/net/core/dev.c index a0a46e7ed137..18759ccdf219 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -2553,6 +2553,75 @@ void dev_set_allmulti(struct net_device *dev, int inc) | |||
2553 | dev_mc_upload(dev); | 2553 | dev_mc_upload(dev); |
2554 | } | 2554 | } |
2555 | 2555 | ||
2556 | int __dev_addr_delete(struct dev_addr_list **list, void *addr, int alen, | ||
2557 | int glbl) | ||
2558 | { | ||
2559 | struct dev_addr_list *da; | ||
2560 | |||
2561 | for (; (da = *list) != NULL; list = &da->next) { | ||
2562 | if (memcmp(da->da_addr, addr, da->da_addrlen) == 0 && | ||
2563 | alen == da->da_addrlen) { | ||
2564 | if (glbl) { | ||
2565 | int old_glbl = da->da_gusers; | ||
2566 | da->da_gusers = 0; | ||
2567 | if (old_glbl == 0) | ||
2568 | break; | ||
2569 | } | ||
2570 | if (--da->da_users) | ||
2571 | return 0; | ||
2572 | |||
2573 | *list = da->next; | ||
2574 | kfree(da); | ||
2575 | return 0; | ||
2576 | } | ||
2577 | } | ||
2578 | return -ENOENT; | ||
2579 | } | ||
2580 | |||
2581 | int __dev_addr_add(struct dev_addr_list **list, void *addr, int alen, int glbl) | ||
2582 | { | ||
2583 | struct dev_addr_list *da; | ||
2584 | |||
2585 | for (da = *list; da != NULL; da = da->next) { | ||
2586 | if (memcmp(da->da_addr, addr, da->da_addrlen) == 0 && | ||
2587 | da->da_addrlen == alen) { | ||
2588 | if (glbl) { | ||
2589 | int old_glbl = da->da_gusers; | ||
2590 | da->da_gusers = 1; | ||
2591 | if (old_glbl) | ||
2592 | return 0; | ||
2593 | } | ||
2594 | da->da_users++; | ||
2595 | return 0; | ||
2596 | } | ||
2597 | } | ||
2598 | |||
2599 | da = kmalloc(sizeof(*da), GFP_ATOMIC); | ||
2600 | if (da == NULL) | ||
2601 | return -ENOMEM; | ||
2602 | memcpy(da->da_addr, addr, alen); | ||
2603 | da->da_addrlen = alen; | ||
2604 | da->da_users = 1; | ||
2605 | da->da_gusers = glbl ? 1 : 0; | ||
2606 | da->next = *list; | ||
2607 | *list = da; | ||
2608 | return 0; | ||
2609 | } | ||
2610 | |||
2611 | void __dev_addr_discard(struct dev_addr_list **list) | ||
2612 | { | ||
2613 | struct dev_addr_list *tmp; | ||
2614 | |||
2615 | while (*list != NULL) { | ||
2616 | tmp = *list; | ||
2617 | *list = tmp->next; | ||
2618 | if (tmp->da_users > tmp->da_gusers) | ||
2619 | printk("__dev_addr_discard: address leakage! " | ||
2620 | "da_users=%d\n", tmp->da_users); | ||
2621 | kfree(tmp); | ||
2622 | } | ||
2623 | } | ||
2624 | |||
2556 | unsigned dev_get_flags(const struct net_device *dev) | 2625 | unsigned dev_get_flags(const struct net_device *dev) |
2557 | { | 2626 | { |
2558 | unsigned flags; | 2627 | unsigned flags; |