diff options
Diffstat (limited to 'net/core/neighbour.c')
-rw-r--r-- | net/core/neighbour.c | 24 |
1 files changed, 15 insertions, 9 deletions
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index b4b478353b27..ba509a4a8e92 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c | |||
@@ -1266,10 +1266,9 @@ void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p, | |||
1266 | struct neigh_parms *neigh_parms_alloc(struct net_device *dev, | 1266 | struct neigh_parms *neigh_parms_alloc(struct net_device *dev, |
1267 | struct neigh_table *tbl) | 1267 | struct neigh_table *tbl) |
1268 | { | 1268 | { |
1269 | struct neigh_parms *p = kmalloc(sizeof(*p), GFP_KERNEL); | 1269 | struct neigh_parms *p = kmemdup(&tbl->parms, sizeof(*p), GFP_KERNEL); |
1270 | 1270 | ||
1271 | if (p) { | 1271 | if (p) { |
1272 | memcpy(p, &tbl->parms, sizeof(*p)); | ||
1273 | p->tbl = tbl; | 1272 | p->tbl = tbl; |
1274 | atomic_set(&p->refcnt, 1); | 1273 | atomic_set(&p->refcnt, 1); |
1275 | INIT_RCU_HEAD(&p->rcu_head); | 1274 | INIT_RCU_HEAD(&p->rcu_head); |
@@ -2410,20 +2409,27 @@ static struct file_operations neigh_stat_seq_fops = { | |||
2410 | #endif /* CONFIG_PROC_FS */ | 2409 | #endif /* CONFIG_PROC_FS */ |
2411 | 2410 | ||
2412 | #ifdef CONFIG_ARPD | 2411 | #ifdef CONFIG_ARPD |
2412 | static inline size_t neigh_nlmsg_size(void) | ||
2413 | { | ||
2414 | return NLMSG_ALIGN(sizeof(struct ndmsg)) | ||
2415 | + nla_total_size(MAX_ADDR_LEN) /* NDA_DST */ | ||
2416 | + nla_total_size(MAX_ADDR_LEN) /* NDA_LLADDR */ | ||
2417 | + nla_total_size(sizeof(struct nda_cacheinfo)) | ||
2418 | + nla_total_size(4); /* NDA_PROBES */ | ||
2419 | } | ||
2420 | |||
2413 | static void __neigh_notify(struct neighbour *n, int type, int flags) | 2421 | static void __neigh_notify(struct neighbour *n, int type, int flags) |
2414 | { | 2422 | { |
2415 | struct sk_buff *skb; | 2423 | struct sk_buff *skb; |
2416 | int err = -ENOBUFS; | 2424 | int err = -ENOBUFS; |
2417 | 2425 | ||
2418 | skb = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC); | 2426 | skb = nlmsg_new(neigh_nlmsg_size(), GFP_ATOMIC); |
2419 | if (skb == NULL) | 2427 | if (skb == NULL) |
2420 | goto errout; | 2428 | goto errout; |
2421 | 2429 | ||
2422 | err = neigh_fill_info(skb, n, 0, 0, type, flags); | 2430 | err = neigh_fill_info(skb, n, 0, 0, type, flags); |
2423 | if (err < 0) { | 2431 | /* failure implies BUG in neigh_nlmsg_size() */ |
2424 | kfree_skb(skb); | 2432 | BUG_ON(err < 0); |
2425 | goto errout; | ||
2426 | } | ||
2427 | 2433 | ||
2428 | err = rtnl_notify(skb, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC); | 2434 | err = rtnl_notify(skb, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC); |
2429 | errout: | 2435 | errout: |
@@ -2618,14 +2624,14 @@ int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p, | |||
2618 | int p_id, int pdev_id, char *p_name, | 2624 | int p_id, int pdev_id, char *p_name, |
2619 | proc_handler *handler, ctl_handler *strategy) | 2625 | proc_handler *handler, ctl_handler *strategy) |
2620 | { | 2626 | { |
2621 | struct neigh_sysctl_table *t = kmalloc(sizeof(*t), GFP_KERNEL); | 2627 | struct neigh_sysctl_table *t = kmemdup(&neigh_sysctl_template, |
2628 | sizeof(*t), GFP_KERNEL); | ||
2622 | const char *dev_name_source = NULL; | 2629 | const char *dev_name_source = NULL; |
2623 | char *dev_name = NULL; | 2630 | char *dev_name = NULL; |
2624 | int err = 0; | 2631 | int err = 0; |
2625 | 2632 | ||
2626 | if (!t) | 2633 | if (!t) |
2627 | return -ENOBUFS; | 2634 | return -ENOBUFS; |
2628 | memcpy(t, &neigh_sysctl_template, sizeof(*t)); | ||
2629 | t->neigh_vars[0].data = &p->mcast_probes; | 2635 | t->neigh_vars[0].data = &p->mcast_probes; |
2630 | t->neigh_vars[1].data = &p->ucast_probes; | 2636 | t->neigh_vars[1].data = &p->ucast_probes; |
2631 | t->neigh_vars[2].data = &p->app_probes; | 2637 | t->neigh_vars[2].data = &p->app_probes; |