diff options
-rw-r--r-- | include/net/neighbour.h | 25 | ||||
-rw-r--r-- | net/core/neighbour.c | 26 |
2 files changed, 41 insertions, 10 deletions
diff --git a/include/net/neighbour.h b/include/net/neighbour.h index 062281872064..8bec0d69b270 100644 --- a/include/net/neighbour.h +++ b/include/net/neighbour.h | |||
@@ -38,7 +38,9 @@ struct neighbour; | |||
38 | 38 | ||
39 | struct neigh_parms | 39 | struct neigh_parms |
40 | { | 40 | { |
41 | #ifdef CONFIG_NET_NS | ||
41 | struct net *net; | 42 | struct net *net; |
43 | #endif | ||
42 | struct net_device *dev; | 44 | struct net_device *dev; |
43 | struct neigh_parms *next; | 45 | struct neigh_parms *next; |
44 | int (*neigh_setup)(struct neighbour *); | 46 | int (*neigh_setup)(struct neighbour *); |
@@ -131,7 +133,9 @@ struct neigh_ops | |||
131 | struct pneigh_entry | 133 | struct pneigh_entry |
132 | { | 134 | { |
133 | struct pneigh_entry *next; | 135 | struct pneigh_entry *next; |
136 | #ifdef CONFIG_NET_NS | ||
134 | struct net *net; | 137 | struct net *net; |
138 | #endif | ||
135 | struct net_device *dev; | 139 | struct net_device *dev; |
136 | u8 flags; | 140 | u8 flags; |
137 | u8 key[0]; | 141 | u8 key[0]; |
@@ -213,6 +217,17 @@ extern struct neighbour *neigh_event_ns(struct neigh_table *tbl, | |||
213 | 217 | ||
214 | extern struct neigh_parms *neigh_parms_alloc(struct net_device *dev, struct neigh_table *tbl); | 218 | extern struct neigh_parms *neigh_parms_alloc(struct net_device *dev, struct neigh_table *tbl); |
215 | extern void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms); | 219 | extern void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms); |
220 | |||
221 | static inline | ||
222 | struct net *neigh_parms_net(const struct neigh_parms *parms) | ||
223 | { | ||
224 | #ifdef CONFIG_NET_NS | ||
225 | return parms->net; | ||
226 | #else | ||
227 | return &init_net; | ||
228 | #endif | ||
229 | } | ||
230 | |||
216 | extern unsigned long neigh_rand_reach_time(unsigned long base); | 231 | extern unsigned long neigh_rand_reach_time(unsigned long base); |
217 | 232 | ||
218 | extern void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p, | 233 | extern void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p, |
@@ -220,6 +235,16 @@ extern void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p, | |||
220 | extern struct pneigh_entry *pneigh_lookup(struct neigh_table *tbl, struct net *net, const void *key, struct net_device *dev, int creat); | 235 | extern struct pneigh_entry *pneigh_lookup(struct neigh_table *tbl, struct net *net, const void *key, struct net_device *dev, int creat); |
221 | extern int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *key, struct net_device *dev); | 236 | extern int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *key, struct net_device *dev); |
222 | 237 | ||
238 | static inline | ||
239 | struct net *pneigh_net(const struct pneigh_entry *pneigh) | ||
240 | { | ||
241 | #ifdef CONFIG_NET_NS | ||
242 | return pneigh->net; | ||
243 | #else | ||
244 | return &init_net; | ||
245 | #endif | ||
246 | } | ||
247 | |||
223 | extern void neigh_app_ns(struct neighbour *n); | 248 | extern void neigh_app_ns(struct neighbour *n); |
224 | extern void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie); | 249 | extern void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie); |
225 | extern void __neigh_for_each_release(struct neigh_table *tbl, int (*cb)(struct neighbour *)); | 250 | extern void __neigh_for_each_release(struct neigh_table *tbl, int (*cb)(struct neighbour *)); |
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index b8d491fb4b42..de654ea8a944 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c | |||
@@ -483,7 +483,7 @@ struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl, | |||
483 | 483 | ||
484 | for (n = tbl->phash_buckets[hash_val]; n; n = n->next) { | 484 | for (n = tbl->phash_buckets[hash_val]; n; n = n->next) { |
485 | if (!memcmp(n->key, pkey, key_len) && | 485 | if (!memcmp(n->key, pkey, key_len) && |
486 | (n->net == net) && | 486 | (pneigh_net(n) == net) && |
487 | (n->dev == dev || !n->dev)) { | 487 | (n->dev == dev || !n->dev)) { |
488 | read_unlock_bh(&tbl->lock); | 488 | read_unlock_bh(&tbl->lock); |
489 | goto out; | 489 | goto out; |
@@ -500,7 +500,9 @@ struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl, | |||
500 | if (!n) | 500 | if (!n) |
501 | goto out; | 501 | goto out; |
502 | 502 | ||
503 | #ifdef CONFIG_NET_NS | ||
503 | n->net = hold_net(net); | 504 | n->net = hold_net(net); |
505 | #endif | ||
504 | memcpy(n->key, pkey, key_len); | 506 | memcpy(n->key, pkey, key_len); |
505 | n->dev = dev; | 507 | n->dev = dev; |
506 | if (dev) | 508 | if (dev) |
@@ -540,14 +542,14 @@ int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *pkey, | |||
540 | for (np = &tbl->phash_buckets[hash_val]; (n = *np) != NULL; | 542 | for (np = &tbl->phash_buckets[hash_val]; (n = *np) != NULL; |
541 | np = &n->next) { | 543 | np = &n->next) { |
542 | if (!memcmp(n->key, pkey, key_len) && n->dev == dev && | 544 | if (!memcmp(n->key, pkey, key_len) && n->dev == dev && |
543 | (n->net == net)) { | 545 | (pneigh_net(n) == net)) { |
544 | *np = n->next; | 546 | *np = n->next; |
545 | write_unlock_bh(&tbl->lock); | 547 | write_unlock_bh(&tbl->lock); |
546 | if (tbl->pdestructor) | 548 | if (tbl->pdestructor) |
547 | tbl->pdestructor(n); | 549 | tbl->pdestructor(n); |
548 | if (n->dev) | 550 | if (n->dev) |
549 | dev_put(n->dev); | 551 | dev_put(n->dev); |
550 | release_net(n->net); | 552 | release_net(pneigh_net(n)); |
551 | kfree(n); | 553 | kfree(n); |
552 | return 0; | 554 | return 0; |
553 | } | 555 | } |
@@ -570,7 +572,7 @@ static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev) | |||
570 | tbl->pdestructor(n); | 572 | tbl->pdestructor(n); |
571 | if (n->dev) | 573 | if (n->dev) |
572 | dev_put(n->dev); | 574 | dev_put(n->dev); |
573 | release_net(n->net); | 575 | release_net(pneigh_net(n)); |
574 | kfree(n); | 576 | kfree(n); |
575 | continue; | 577 | continue; |
576 | } | 578 | } |
@@ -1284,7 +1286,7 @@ static inline struct neigh_parms *lookup_neigh_params(struct neigh_table *tbl, | |||
1284 | struct neigh_parms *p; | 1286 | struct neigh_parms *p; |
1285 | 1287 | ||
1286 | for (p = &tbl->parms; p; p = p->next) { | 1288 | for (p = &tbl->parms; p; p = p->next) { |
1287 | if ((p->dev && p->dev->ifindex == ifindex && p->net == net) || | 1289 | if ((p->dev && p->dev->ifindex == ifindex && neigh_parms_net(p) == net) || |
1288 | (!p->dev && !ifindex)) | 1290 | (!p->dev && !ifindex)) |
1289 | return p; | 1291 | return p; |
1290 | } | 1292 | } |
@@ -1318,7 +1320,9 @@ struct neigh_parms *neigh_parms_alloc(struct net_device *dev, | |||
1318 | 1320 | ||
1319 | dev_hold(dev); | 1321 | dev_hold(dev); |
1320 | p->dev = dev; | 1322 | p->dev = dev; |
1323 | #ifdef CONFIG_NET_NS | ||
1321 | p->net = hold_net(net); | 1324 | p->net = hold_net(net); |
1325 | #endif | ||
1322 | p->sysctl_table = NULL; | 1326 | p->sysctl_table = NULL; |
1323 | write_lock_bh(&tbl->lock); | 1327 | write_lock_bh(&tbl->lock); |
1324 | p->next = tbl->parms.next; | 1328 | p->next = tbl->parms.next; |
@@ -1360,7 +1364,7 @@ void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms) | |||
1360 | 1364 | ||
1361 | static void neigh_parms_destroy(struct neigh_parms *parms) | 1365 | static void neigh_parms_destroy(struct neigh_parms *parms) |
1362 | { | 1366 | { |
1363 | release_net(parms->net); | 1367 | release_net(neigh_parms_net(parms)); |
1364 | kfree(parms); | 1368 | kfree(parms); |
1365 | } | 1369 | } |
1366 | 1370 | ||
@@ -1371,7 +1375,9 @@ void neigh_table_init_no_netlink(struct neigh_table *tbl) | |||
1371 | unsigned long now = jiffies; | 1375 | unsigned long now = jiffies; |
1372 | unsigned long phsize; | 1376 | unsigned long phsize; |
1373 | 1377 | ||
1378 | #ifdef CONFIG_NET_NS | ||
1374 | tbl->parms.net = &init_net; | 1379 | tbl->parms.net = &init_net; |
1380 | #endif | ||
1375 | atomic_set(&tbl->parms.refcnt, 1); | 1381 | atomic_set(&tbl->parms.refcnt, 1); |
1376 | INIT_RCU_HEAD(&tbl->parms.rcu_head); | 1382 | INIT_RCU_HEAD(&tbl->parms.rcu_head); |
1377 | tbl->parms.reachable_time = | 1383 | tbl->parms.reachable_time = |
@@ -1958,7 +1964,7 @@ static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb) | |||
1958 | break; | 1964 | break; |
1959 | 1965 | ||
1960 | for (nidx = 0, p = tbl->parms.next; p; p = p->next) { | 1966 | for (nidx = 0, p = tbl->parms.next; p; p = p->next) { |
1961 | if (net != p->net) | 1967 | if (net != neigh_parms_net(p)) |
1962 | continue; | 1968 | continue; |
1963 | 1969 | ||
1964 | if (nidx++ < neigh_skip) | 1970 | if (nidx++ < neigh_skip) |
@@ -2254,7 +2260,7 @@ static struct pneigh_entry *pneigh_get_first(struct seq_file *seq) | |||
2254 | state->flags |= NEIGH_SEQ_IS_PNEIGH; | 2260 | state->flags |= NEIGH_SEQ_IS_PNEIGH; |
2255 | for (bucket = 0; bucket <= PNEIGH_HASHMASK; bucket++) { | 2261 | for (bucket = 0; bucket <= PNEIGH_HASHMASK; bucket++) { |
2256 | pn = tbl->phash_buckets[bucket]; | 2262 | pn = tbl->phash_buckets[bucket]; |
2257 | while (pn && (pn->net != net)) | 2263 | while (pn && (pneigh_net(pn) != net)) |
2258 | pn = pn->next; | 2264 | pn = pn->next; |
2259 | if (pn) | 2265 | if (pn) |
2260 | break; | 2266 | break; |
@@ -2277,7 +2283,7 @@ static struct pneigh_entry *pneigh_get_next(struct seq_file *seq, | |||
2277 | if (++state->bucket > PNEIGH_HASHMASK) | 2283 | if (++state->bucket > PNEIGH_HASHMASK) |
2278 | break; | 2284 | break; |
2279 | pn = tbl->phash_buckets[state->bucket]; | 2285 | pn = tbl->phash_buckets[state->bucket]; |
2280 | while (pn && (pn->net != net)) | 2286 | while (pn && (pneigh_net(pn) != net)) |
2281 | pn = pn->next; | 2287 | pn = pn->next; |
2282 | if (pn) | 2288 | if (pn) |
2283 | break; | 2289 | break; |
@@ -2740,7 +2746,7 @@ int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p, | |||
2740 | neigh_path[NEIGH_CTL_PATH_PROTO].ctl_name = p_id; | 2746 | neigh_path[NEIGH_CTL_PATH_PROTO].ctl_name = p_id; |
2741 | 2747 | ||
2742 | t->sysctl_header = | 2748 | t->sysctl_header = |
2743 | register_net_sysctl_table(p->net, neigh_path, t->neigh_vars); | 2749 | register_net_sysctl_table(neigh_parms_net(p), neigh_path, t->neigh_vars); |
2744 | if (!t->sysctl_header) | 2750 | if (!t->sysctl_header) |
2745 | goto free_procname; | 2751 | goto free_procname; |
2746 | 2752 | ||