diff options
Diffstat (limited to 'net/core/neighbour.c')
-rw-r--r-- | net/core/neighbour.c | 87 |
1 files changed, 47 insertions, 40 deletions
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index e7300b6b4079..512eed91785d 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c | |||
@@ -63,7 +63,7 @@ void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev); | |||
63 | 63 | ||
64 | static struct neigh_table *neigh_tables; | 64 | static struct neigh_table *neigh_tables; |
65 | #ifdef CONFIG_PROC_FS | 65 | #ifdef CONFIG_PROC_FS |
66 | static struct file_operations neigh_stat_seq_fops; | 66 | static const struct file_operations neigh_stat_seq_fops; |
67 | #endif | 67 | #endif |
68 | 68 | ||
69 | /* | 69 | /* |
@@ -251,12 +251,10 @@ static struct neighbour *neigh_alloc(struct neigh_table *tbl) | |||
251 | goto out_entries; | 251 | goto out_entries; |
252 | } | 252 | } |
253 | 253 | ||
254 | n = kmem_cache_alloc(tbl->kmem_cachep, GFP_ATOMIC); | 254 | n = kmem_cache_zalloc(tbl->kmem_cachep, GFP_ATOMIC); |
255 | if (!n) | 255 | if (!n) |
256 | goto out_entries; | 256 | goto out_entries; |
257 | 257 | ||
258 | memset(n, 0, tbl->entry_size); | ||
259 | |||
260 | skb_queue_head_init(&n->arp_queue); | 258 | skb_queue_head_init(&n->arp_queue); |
261 | rwlock_init(&n->lock); | 259 | rwlock_init(&n->lock); |
262 | n->updated = n->used = now; | 260 | n->updated = n->used = now; |
@@ -345,7 +343,7 @@ struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey, | |||
345 | struct neighbour *n; | 343 | struct neighbour *n; |
346 | int key_len = tbl->key_len; | 344 | int key_len = tbl->key_len; |
347 | u32 hash_val = tbl->hash(pkey, dev); | 345 | u32 hash_val = tbl->hash(pkey, dev); |
348 | 346 | ||
349 | NEIGH_CACHE_STAT_INC(tbl, lookups); | 347 | NEIGH_CACHE_STAT_INC(tbl, lookups); |
350 | 348 | ||
351 | read_lock_bh(&tbl->lock); | 349 | read_lock_bh(&tbl->lock); |
@@ -687,16 +685,19 @@ next_elt: | |||
687 | np = &n->next; | 685 | np = &n->next; |
688 | } | 686 | } |
689 | 687 | ||
690 | /* Cycle through all hash buckets every base_reachable_time/2 ticks. | 688 | /* Cycle through all hash buckets every base_reachable_time/2 ticks. |
691 | * ARP entry timeouts range from 1/2 base_reachable_time to 3/2 | 689 | * ARP entry timeouts range from 1/2 base_reachable_time to 3/2 |
692 | * base_reachable_time. | 690 | * base_reachable_time. |
693 | */ | 691 | */ |
694 | expire = tbl->parms.base_reachable_time >> 1; | 692 | expire = tbl->parms.base_reachable_time >> 1; |
695 | expire /= (tbl->hash_mask + 1); | 693 | expire /= (tbl->hash_mask + 1); |
696 | if (!expire) | 694 | if (!expire) |
697 | expire = 1; | 695 | expire = 1; |
698 | 696 | ||
699 | mod_timer(&tbl->gc_timer, now + expire); | 697 | if (expire>HZ) |
698 | mod_timer(&tbl->gc_timer, round_jiffies(now + expire)); | ||
699 | else | ||
700 | mod_timer(&tbl->gc_timer, now + expire); | ||
700 | 701 | ||
701 | write_unlock(&tbl->lock); | 702 | write_unlock(&tbl->lock); |
702 | } | 703 | } |
@@ -741,7 +742,7 @@ static void neigh_timer_handler(unsigned long arg) | |||
741 | } | 742 | } |
742 | 743 | ||
743 | if (state & NUD_REACHABLE) { | 744 | if (state & NUD_REACHABLE) { |
744 | if (time_before_eq(now, | 745 | if (time_before_eq(now, |
745 | neigh->confirmed + neigh->parms->reachable_time)) { | 746 | neigh->confirmed + neigh->parms->reachable_time)) { |
746 | NEIGH_PRINTK2("neigh %p is still alive.\n", neigh); | 747 | NEIGH_PRINTK2("neigh %p is still alive.\n", neigh); |
747 | next = neigh->confirmed + neigh->parms->reachable_time; | 748 | next = neigh->confirmed + neigh->parms->reachable_time; |
@@ -760,7 +761,7 @@ static void neigh_timer_handler(unsigned long arg) | |||
760 | notify = 1; | 761 | notify = 1; |
761 | } | 762 | } |
762 | } else if (state & NUD_DELAY) { | 763 | } else if (state & NUD_DELAY) { |
763 | if (time_before_eq(now, | 764 | if (time_before_eq(now, |
764 | neigh->confirmed + neigh->parms->delay_probe_time)) { | 765 | neigh->confirmed + neigh->parms->delay_probe_time)) { |
765 | NEIGH_PRINTK2("neigh %p is now reachable.\n", neigh); | 766 | NEIGH_PRINTK2("neigh %p is now reachable.\n", neigh); |
766 | neigh->nud_state = NUD_REACHABLE; | 767 | neigh->nud_state = NUD_REACHABLE; |
@@ -846,7 +847,7 @@ int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb) | |||
846 | goto out_unlock_bh; | 847 | goto out_unlock_bh; |
847 | 848 | ||
848 | now = jiffies; | 849 | now = jiffies; |
849 | 850 | ||
850 | if (!(neigh->nud_state & (NUD_STALE | NUD_INCOMPLETE))) { | 851 | if (!(neigh->nud_state & (NUD_STALE | NUD_INCOMPLETE))) { |
851 | if (neigh->parms->mcast_probes + neigh->parms->app_probes) { | 852 | if (neigh->parms->mcast_probes + neigh->parms->app_probes) { |
852 | atomic_set(&neigh->probes, neigh->parms->ucast_probes); | 853 | atomic_set(&neigh->probes, neigh->parms->ucast_probes); |
@@ -914,13 +915,13 @@ static void neigh_update_hhs(struct neighbour *neigh) | |||
914 | NEIGH_UPDATE_F_OVERRIDE allows to override existing lladdr, | 915 | NEIGH_UPDATE_F_OVERRIDE allows to override existing lladdr, |
915 | if it is different. | 916 | if it is different. |
916 | NEIGH_UPDATE_F_WEAK_OVERRIDE will suspect existing "connected" | 917 | NEIGH_UPDATE_F_WEAK_OVERRIDE will suspect existing "connected" |
917 | lladdr instead of overriding it | 918 | lladdr instead of overriding it |
918 | if it is different. | 919 | if it is different. |
919 | It also allows to retain current state | 920 | It also allows to retain current state |
920 | if lladdr is unchanged. | 921 | if lladdr is unchanged. |
921 | NEIGH_UPDATE_F_ADMIN means that the change is administrative. | 922 | NEIGH_UPDATE_F_ADMIN means that the change is administrative. |
922 | 923 | ||
923 | NEIGH_UPDATE_F_OVERRIDE_ISROUTER allows to override existing | 924 | NEIGH_UPDATE_F_OVERRIDE_ISROUTER allows to override existing |
924 | NTF_ROUTER flag. | 925 | NTF_ROUTER flag. |
925 | NEIGH_UPDATE_F_ISROUTER indicates if the neighbour is known as | 926 | NEIGH_UPDATE_F_ISROUTER indicates if the neighbour is known as |
926 | a router. | 927 | a router. |
@@ -943,7 +944,7 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, | |||
943 | old = neigh->nud_state; | 944 | old = neigh->nud_state; |
944 | err = -EPERM; | 945 | err = -EPERM; |
945 | 946 | ||
946 | if (!(flags & NEIGH_UPDATE_F_ADMIN) && | 947 | if (!(flags & NEIGH_UPDATE_F_ADMIN) && |
947 | (old & (NUD_NOARP | NUD_PERMANENT))) | 948 | (old & (NUD_NOARP | NUD_PERMANENT))) |
948 | goto out; | 949 | goto out; |
949 | 950 | ||
@@ -967,7 +968,7 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, | |||
967 | - compare new & old | 968 | - compare new & old |
968 | - if they are different, check override flag | 969 | - if they are different, check override flag |
969 | */ | 970 | */ |
970 | if ((old & NUD_VALID) && | 971 | if ((old & NUD_VALID) && |
971 | !memcmp(lladdr, neigh->ha, dev->addr_len)) | 972 | !memcmp(lladdr, neigh->ha, dev->addr_len)) |
972 | lladdr = neigh->ha; | 973 | lladdr = neigh->ha; |
973 | } else { | 974 | } else { |
@@ -1011,8 +1012,8 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, | |||
1011 | neigh_del_timer(neigh); | 1012 | neigh_del_timer(neigh); |
1012 | if (new & NUD_IN_TIMER) { | 1013 | if (new & NUD_IN_TIMER) { |
1013 | neigh_hold(neigh); | 1014 | neigh_hold(neigh); |
1014 | neigh_add_timer(neigh, (jiffies + | 1015 | neigh_add_timer(neigh, (jiffies + |
1015 | ((new & NUD_REACHABLE) ? | 1016 | ((new & NUD_REACHABLE) ? |
1016 | neigh->parms->reachable_time : | 1017 | neigh->parms->reachable_time : |
1017 | 0))); | 1018 | 0))); |
1018 | } | 1019 | } |
@@ -1074,7 +1075,7 @@ struct neighbour *neigh_event_ns(struct neigh_table *tbl, | |||
1074 | struct neighbour *neigh = __neigh_lookup(tbl, saddr, dev, | 1075 | struct neighbour *neigh = __neigh_lookup(tbl, saddr, dev, |
1075 | lladdr || !dev->addr_len); | 1076 | lladdr || !dev->addr_len); |
1076 | if (neigh) | 1077 | if (neigh) |
1077 | neigh_update(neigh, lladdr, NUD_STALE, | 1078 | neigh_update(neigh, lladdr, NUD_STALE, |
1078 | NEIGH_UPDATE_F_OVERRIDE); | 1079 | NEIGH_UPDATE_F_OVERRIDE); |
1079 | return neigh; | 1080 | return neigh; |
1080 | } | 1081 | } |
@@ -1126,7 +1127,7 @@ int neigh_compat_output(struct sk_buff *skb) | |||
1126 | 1127 | ||
1127 | if (dev->hard_header && | 1128 | if (dev->hard_header && |
1128 | dev->hard_header(skb, dev, ntohs(skb->protocol), NULL, NULL, | 1129 | dev->hard_header(skb, dev, ntohs(skb->protocol), NULL, NULL, |
1129 | skb->len) < 0 && | 1130 | skb->len) < 0 && |
1130 | dev->rebuild_header(skb)) | 1131 | dev->rebuild_header(skb)) |
1131 | return 0; | 1132 | return 0; |
1132 | 1133 | ||
@@ -1346,10 +1347,10 @@ void neigh_table_init_no_netlink(struct neigh_table *tbl) | |||
1346 | tbl->stats = alloc_percpu(struct neigh_statistics); | 1347 | tbl->stats = alloc_percpu(struct neigh_statistics); |
1347 | if (!tbl->stats) | 1348 | if (!tbl->stats) |
1348 | panic("cannot create neighbour cache statistics"); | 1349 | panic("cannot create neighbour cache statistics"); |
1349 | 1350 | ||
1350 | #ifdef CONFIG_PROC_FS | 1351 | #ifdef CONFIG_PROC_FS |
1351 | tbl->pde = create_proc_entry(tbl->id, 0, proc_net_stat); | 1352 | tbl->pde = create_proc_entry(tbl->id, 0, proc_net_stat); |
1352 | if (!tbl->pde) | 1353 | if (!tbl->pde) |
1353 | panic("cannot create neighbour proc dir entry"); | 1354 | panic("cannot create neighbour proc dir entry"); |
1354 | tbl->pde->proc_fops = &neigh_stat_seq_fops; | 1355 | tbl->pde->proc_fops = &neigh_stat_seq_fops; |
1355 | tbl->pde->data = tbl; | 1356 | tbl->pde->data = tbl; |
@@ -1564,7 +1565,7 @@ int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
1564 | err = -ENOENT; | 1565 | err = -ENOENT; |
1565 | goto out_dev_put; | 1566 | goto out_dev_put; |
1566 | } | 1567 | } |
1567 | 1568 | ||
1568 | neigh = __neigh_lookup_errno(tbl, dst, dev); | 1569 | neigh = __neigh_lookup_errno(tbl, dst, dev); |
1569 | if (IS_ERR(neigh)) { | 1570 | if (IS_ERR(neigh)) { |
1570 | err = PTR_ERR(neigh); | 1571 | err = PTR_ERR(neigh); |
@@ -1637,7 +1638,7 @@ static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl, | |||
1637 | 1638 | ||
1638 | nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags); | 1639 | nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags); |
1639 | if (nlh == NULL) | 1640 | if (nlh == NULL) |
1640 | return -ENOBUFS; | 1641 | return -EMSGSIZE; |
1641 | 1642 | ||
1642 | ndtmsg = nlmsg_data(nlh); | 1643 | ndtmsg = nlmsg_data(nlh); |
1643 | 1644 | ||
@@ -1706,7 +1707,8 @@ static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl, | |||
1706 | 1707 | ||
1707 | nla_put_failure: | 1708 | nla_put_failure: |
1708 | read_unlock_bh(&tbl->lock); | 1709 | read_unlock_bh(&tbl->lock); |
1709 | return nlmsg_cancel(skb, nlh); | 1710 | nlmsg_cancel(skb, nlh); |
1711 | return -EMSGSIZE; | ||
1710 | } | 1712 | } |
1711 | 1713 | ||
1712 | static int neightbl_fill_param_info(struct sk_buff *skb, | 1714 | static int neightbl_fill_param_info(struct sk_buff *skb, |
@@ -1720,7 +1722,7 @@ static int neightbl_fill_param_info(struct sk_buff *skb, | |||
1720 | 1722 | ||
1721 | nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags); | 1723 | nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags); |
1722 | if (nlh == NULL) | 1724 | if (nlh == NULL) |
1723 | return -ENOBUFS; | 1725 | return -EMSGSIZE; |
1724 | 1726 | ||
1725 | ndtmsg = nlmsg_data(nlh); | 1727 | ndtmsg = nlmsg_data(nlh); |
1726 | 1728 | ||
@@ -1737,14 +1739,15 @@ static int neightbl_fill_param_info(struct sk_buff *skb, | |||
1737 | return nlmsg_end(skb, nlh); | 1739 | return nlmsg_end(skb, nlh); |
1738 | errout: | 1740 | errout: |
1739 | read_unlock_bh(&tbl->lock); | 1741 | read_unlock_bh(&tbl->lock); |
1740 | return nlmsg_cancel(skb, nlh); | 1742 | nlmsg_cancel(skb, nlh); |
1743 | return -EMSGSIZE; | ||
1741 | } | 1744 | } |
1742 | 1745 | ||
1743 | static inline struct neigh_parms *lookup_neigh_params(struct neigh_table *tbl, | 1746 | static inline struct neigh_parms *lookup_neigh_params(struct neigh_table *tbl, |
1744 | int ifindex) | 1747 | int ifindex) |
1745 | { | 1748 | { |
1746 | struct neigh_parms *p; | 1749 | struct neigh_parms *p; |
1747 | 1750 | ||
1748 | for (p = &tbl->parms; p; p = p->next) | 1751 | for (p = &tbl->parms; p; p = p->next) |
1749 | if ((p->dev && p->dev->ifindex == ifindex) || | 1752 | if ((p->dev && p->dev->ifindex == ifindex) || |
1750 | (!p->dev && !ifindex)) | 1753 | (!p->dev && !ifindex)) |
@@ -1810,7 +1813,7 @@ int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
1810 | goto errout_locked; | 1813 | goto errout_locked; |
1811 | } | 1814 | } |
1812 | 1815 | ||
1813 | /* | 1816 | /* |
1814 | * We acquire tbl->lock to be nice to the periodic timers and | 1817 | * We acquire tbl->lock to be nice to the periodic timers and |
1815 | * make sure they always see a consistent set of values. | 1818 | * make sure they always see a consistent set of values. |
1816 | */ | 1819 | */ |
@@ -1955,7 +1958,7 @@ static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh, | |||
1955 | 1958 | ||
1956 | nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags); | 1959 | nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags); |
1957 | if (nlh == NULL) | 1960 | if (nlh == NULL) |
1958 | return -ENOBUFS; | 1961 | return -EMSGSIZE; |
1959 | 1962 | ||
1960 | ndm = nlmsg_data(nlh); | 1963 | ndm = nlmsg_data(nlh); |
1961 | ndm->ndm_family = neigh->ops->family; | 1964 | ndm->ndm_family = neigh->ops->family; |
@@ -1987,7 +1990,8 @@ static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh, | |||
1987 | return nlmsg_end(skb, nlh); | 1990 | return nlmsg_end(skb, nlh); |
1988 | 1991 | ||
1989 | nla_put_failure: | 1992 | nla_put_failure: |
1990 | return nlmsg_cancel(skb, nlh); | 1993 | nlmsg_cancel(skb, nlh); |
1994 | return -EMSGSIZE; | ||
1991 | } | 1995 | } |
1992 | 1996 | ||
1993 | 1997 | ||
@@ -2317,7 +2321,7 @@ static void *neigh_stat_seq_start(struct seq_file *seq, loff_t *pos) | |||
2317 | 2321 | ||
2318 | if (*pos == 0) | 2322 | if (*pos == 0) |
2319 | return SEQ_START_TOKEN; | 2323 | return SEQ_START_TOKEN; |
2320 | 2324 | ||
2321 | for (cpu = *pos-1; cpu < NR_CPUS; ++cpu) { | 2325 | for (cpu = *pos-1; cpu < NR_CPUS; ++cpu) { |
2322 | if (!cpu_possible(cpu)) | 2326 | if (!cpu_possible(cpu)) |
2323 | continue; | 2327 | continue; |
@@ -2399,7 +2403,7 @@ static int neigh_stat_seq_open(struct inode *inode, struct file *file) | |||
2399 | return ret; | 2403 | return ret; |
2400 | }; | 2404 | }; |
2401 | 2405 | ||
2402 | static struct file_operations neigh_stat_seq_fops = { | 2406 | static const struct file_operations neigh_stat_seq_fops = { |
2403 | .owner = THIS_MODULE, | 2407 | .owner = THIS_MODULE, |
2404 | .open = neigh_stat_seq_open, | 2408 | .open = neigh_stat_seq_open, |
2405 | .read = seq_read, | 2409 | .read = seq_read, |
@@ -2429,9 +2433,12 @@ static void __neigh_notify(struct neighbour *n, int type, int flags) | |||
2429 | goto errout; | 2433 | goto errout; |
2430 | 2434 | ||
2431 | err = neigh_fill_info(skb, n, 0, 0, type, flags); | 2435 | err = neigh_fill_info(skb, n, 0, 0, type, flags); |
2432 | /* failure implies BUG in neigh_nlmsg_size() */ | 2436 | if (err < 0) { |
2433 | BUG_ON(err < 0); | 2437 | /* -EMSGSIZE implies BUG in neigh_nlmsg_size() */ |
2434 | 2438 | WARN_ON(err == -EMSGSIZE); | |
2439 | kfree_skb(skb); | ||
2440 | goto errout; | ||
2441 | } | ||
2435 | err = rtnl_notify(skb, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC); | 2442 | err = rtnl_notify(skb, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC); |
2436 | errout: | 2443 | errout: |
2437 | if (err < 0) | 2444 | if (err < 0) |
@@ -2622,7 +2629,7 @@ static struct neigh_sysctl_table { | |||
2622 | }; | 2629 | }; |
2623 | 2630 | ||
2624 | int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p, | 2631 | int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p, |
2625 | int p_id, int pdev_id, char *p_name, | 2632 | int p_id, int pdev_id, char *p_name, |
2626 | proc_handler *handler, ctl_handler *strategy) | 2633 | proc_handler *handler, ctl_handler *strategy) |
2627 | { | 2634 | { |
2628 | struct neigh_sysctl_table *t = kmemdup(&neigh_sysctl_template, | 2635 | struct neigh_sysctl_table *t = kmemdup(&neigh_sysctl_template, |
@@ -2654,7 +2661,7 @@ int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p, | |||
2654 | t->neigh_vars[14].procname = NULL; | 2661 | t->neigh_vars[14].procname = NULL; |
2655 | t->neigh_vars[15].procname = NULL; | 2662 | t->neigh_vars[15].procname = NULL; |
2656 | } else { | 2663 | } else { |
2657 | dev_name_source = t->neigh_dev[0].procname; | 2664 | dev_name_source = t->neigh_dev[0].procname; |
2658 | t->neigh_vars[12].data = (int *)(p + 1); | 2665 | t->neigh_vars[12].data = (int *)(p + 1); |
2659 | t->neigh_vars[13].data = (int *)(p + 1) + 1; | 2666 | t->neigh_vars[13].data = (int *)(p + 1) + 1; |
2660 | t->neigh_vars[14].data = (int *)(p + 1) + 2; | 2667 | t->neigh_vars[14].data = (int *)(p + 1) + 2; |
@@ -2689,7 +2696,7 @@ int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p, | |||
2689 | goto free; | 2696 | goto free; |
2690 | } | 2697 | } |
2691 | 2698 | ||
2692 | t->neigh_dev[0].procname = dev_name; | 2699 | t->neigh_dev[0].procname = dev_name; |
2693 | 2700 | ||
2694 | t->neigh_neigh_dir[0].ctl_name = pdev_id; | 2701 | t->neigh_neigh_dir[0].ctl_name = pdev_id; |
2695 | 2702 | ||