diff options
-rw-r--r-- | include/net/neighbour.h | 10 | ||||
-rw-r--r-- | net/atm/clip.c | 15 | ||||
-rw-r--r-- | net/core/neighbour.c | 116 | ||||
-rw-r--r-- | net/decnet/dn_neigh.c | 6 | ||||
-rw-r--r-- | net/decnet/dn_route.c | 2 | ||||
-rw-r--r-- | net/ipv4/arp.c | 12 | ||||
-rw-r--r-- | net/ipv6/ip6_output.c | 2 | ||||
-rw-r--r-- | net/ipv6/ndisc.c | 4 |
8 files changed, 106 insertions, 61 deletions
diff --git a/include/net/neighbour.h b/include/net/neighbour.h index a4f26187fc1a..11590f23d99d 100644 --- a/include/net/neighbour.h +++ b/include/net/neighbour.h | |||
@@ -34,6 +34,7 @@ struct neighbour; | |||
34 | 34 | ||
35 | struct neigh_parms | 35 | struct neigh_parms |
36 | { | 36 | { |
37 | struct net *net; | ||
37 | struct net_device *dev; | 38 | struct net_device *dev; |
38 | struct neigh_parms *next; | 39 | struct neigh_parms *next; |
39 | int (*neigh_setup)(struct neighbour *); | 40 | int (*neigh_setup)(struct neighbour *); |
@@ -126,7 +127,8 @@ struct neigh_ops | |||
126 | struct pneigh_entry | 127 | struct pneigh_entry |
127 | { | 128 | { |
128 | struct pneigh_entry *next; | 129 | struct pneigh_entry *next; |
129 | struct net_device *dev; | 130 | struct net *net; |
131 | struct net_device *dev; | ||
130 | u8 flags; | 132 | u8 flags; |
131 | u8 key[0]; | 133 | u8 key[0]; |
132 | }; | 134 | }; |
@@ -187,6 +189,7 @@ extern struct neighbour * neigh_lookup(struct neigh_table *tbl, | |||
187 | const void *pkey, | 189 | const void *pkey, |
188 | struct net_device *dev); | 190 | struct net_device *dev); |
189 | extern struct neighbour * neigh_lookup_nodev(struct neigh_table *tbl, | 191 | extern struct neighbour * neigh_lookup_nodev(struct neigh_table *tbl, |
192 | struct net *net, | ||
190 | const void *pkey); | 193 | const void *pkey); |
191 | extern struct neighbour * neigh_create(struct neigh_table *tbl, | 194 | extern struct neighbour * neigh_create(struct neigh_table *tbl, |
192 | const void *pkey, | 195 | const void *pkey, |
@@ -211,8 +214,8 @@ extern unsigned long neigh_rand_reach_time(unsigned long base); | |||
211 | 214 | ||
212 | extern void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p, | 215 | extern void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p, |
213 | struct sk_buff *skb); | 216 | struct sk_buff *skb); |
214 | extern struct pneigh_entry *pneigh_lookup(struct neigh_table *tbl, const void *key, struct net_device *dev, int creat); | 217 | extern struct pneigh_entry *pneigh_lookup(struct neigh_table *tbl, struct net *net, const void *key, struct net_device *dev, int creat); |
215 | extern int pneigh_delete(struct neigh_table *tbl, const void *key, struct net_device *dev); | 218 | extern int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *key, struct net_device *dev); |
216 | 219 | ||
217 | extern void neigh_app_ns(struct neighbour *n); | 220 | extern void neigh_app_ns(struct neighbour *n); |
218 | extern void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie); | 221 | extern void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie); |
@@ -220,6 +223,7 @@ extern void __neigh_for_each_release(struct neigh_table *tbl, int (*cb)(struct n | |||
220 | extern void pneigh_for_each(struct neigh_table *tbl, void (*cb)(struct pneigh_entry *)); | 223 | extern void pneigh_for_each(struct neigh_table *tbl, void (*cb)(struct pneigh_entry *)); |
221 | 224 | ||
222 | struct neigh_seq_state { | 225 | struct neigh_seq_state { |
226 | struct net *net; | ||
223 | struct neigh_table *tbl; | 227 | struct neigh_table *tbl; |
224 | void *(*neigh_sub_iter)(struct neigh_seq_state *state, | 228 | void *(*neigh_sub_iter)(struct neigh_seq_state *state, |
225 | struct neighbour *n, loff_t *pos); | 229 | struct neighbour *n, loff_t *pos); |
diff --git a/net/atm/clip.c b/net/atm/clip.c index 741742f00797..47fbdc0c5f72 100644 --- a/net/atm/clip.c +++ b/net/atm/clip.c | |||
@@ -949,6 +949,11 @@ static int arp_seq_open(struct inode *inode, struct file *file) | |||
949 | 949 | ||
950 | seq = file->private_data; | 950 | seq = file->private_data; |
951 | seq->private = state; | 951 | seq->private = state; |
952 | state->ns.net = get_proc_net(inode); | ||
953 | if (!state->ns.net) { | ||
954 | seq_release_private(inode, file); | ||
955 | rc = -ENXIO; | ||
956 | } | ||
952 | out: | 957 | out: |
953 | return rc; | 958 | return rc; |
954 | 959 | ||
@@ -957,11 +962,19 @@ out_kfree: | |||
957 | goto out; | 962 | goto out; |
958 | } | 963 | } |
959 | 964 | ||
965 | static int arp_seq_release(struct inode *inode, struct file *file) | ||
966 | { | ||
967 | struct seq_file *seq = file->private_data; | ||
968 | struct clip_seq_state *state = seq->private; | ||
969 | put_net(state->ns.net); | ||
970 | return seq_release_private(inode, file); | ||
971 | } | ||
972 | |||
960 | static const struct file_operations arp_seq_fops = { | 973 | static const struct file_operations arp_seq_fops = { |
961 | .open = arp_seq_open, | 974 | .open = arp_seq_open, |
962 | .read = seq_read, | 975 | .read = seq_read, |
963 | .llseek = seq_lseek, | 976 | .llseek = seq_lseek, |
964 | .release = seq_release_private, | 977 | .release = arp_seq_release, |
965 | .owner = THIS_MODULE | 978 | .owner = THIS_MODULE |
966 | }; | 979 | }; |
967 | #endif | 980 | #endif |
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 9a283fcde9a6..bd899d557737 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c | |||
@@ -375,7 +375,8 @@ struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey, | |||
375 | return n; | 375 | return n; |
376 | } | 376 | } |
377 | 377 | ||
378 | struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, const void *pkey) | 378 | struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net, |
379 | const void *pkey) | ||
379 | { | 380 | { |
380 | struct neighbour *n; | 381 | struct neighbour *n; |
381 | int key_len = tbl->key_len; | 382 | int key_len = tbl->key_len; |
@@ -385,7 +386,8 @@ struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, const void *pkey) | |||
385 | 386 | ||
386 | read_lock_bh(&tbl->lock); | 387 | read_lock_bh(&tbl->lock); |
387 | for (n = tbl->hash_buckets[hash_val & tbl->hash_mask]; n; n = n->next) { | 388 | for (n = tbl->hash_buckets[hash_val & tbl->hash_mask]; n; n = n->next) { |
388 | if (!memcmp(n->primary_key, pkey, key_len)) { | 389 | if (!memcmp(n->primary_key, pkey, key_len) && |
390 | (net == n->dev->nd_net)) { | ||
389 | neigh_hold(n); | 391 | neigh_hold(n); |
390 | NEIGH_CACHE_STAT_INC(tbl, hits); | 392 | NEIGH_CACHE_STAT_INC(tbl, hits); |
391 | break; | 393 | break; |
@@ -463,7 +465,8 @@ out_neigh_release: | |||
463 | goto out; | 465 | goto out; |
464 | } | 466 | } |
465 | 467 | ||
466 | struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl, const void *pkey, | 468 | struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl, |
469 | struct net *net, const void *pkey, | ||
467 | struct net_device *dev, int creat) | 470 | struct net_device *dev, int creat) |
468 | { | 471 | { |
469 | struct pneigh_entry *n; | 472 | struct pneigh_entry *n; |
@@ -479,6 +482,7 @@ struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl, const void *pkey, | |||
479 | 482 | ||
480 | for (n = tbl->phash_buckets[hash_val]; n; n = n->next) { | 483 | for (n = tbl->phash_buckets[hash_val]; n; n = n->next) { |
481 | if (!memcmp(n->key, pkey, key_len) && | 484 | if (!memcmp(n->key, pkey, key_len) && |
485 | (n->net == net) && | ||
482 | (n->dev == dev || !n->dev)) { | 486 | (n->dev == dev || !n->dev)) { |
483 | read_unlock_bh(&tbl->lock); | 487 | read_unlock_bh(&tbl->lock); |
484 | goto out; | 488 | goto out; |
@@ -495,6 +499,7 @@ struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl, const void *pkey, | |||
495 | if (!n) | 499 | if (!n) |
496 | goto out; | 500 | goto out; |
497 | 501 | ||
502 | n->net = hold_net(net); | ||
498 | memcpy(n->key, pkey, key_len); | 503 | memcpy(n->key, pkey, key_len); |
499 | n->dev = dev; | 504 | n->dev = dev; |
500 | if (dev) | 505 | if (dev) |
@@ -517,7 +522,7 @@ out: | |||
517 | } | 522 | } |
518 | 523 | ||
519 | 524 | ||
520 | int pneigh_delete(struct neigh_table *tbl, const void *pkey, | 525 | int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *pkey, |
521 | struct net_device *dev) | 526 | struct net_device *dev) |
522 | { | 527 | { |
523 | struct pneigh_entry *n, **np; | 528 | struct pneigh_entry *n, **np; |
@@ -532,13 +537,15 @@ int pneigh_delete(struct neigh_table *tbl, const void *pkey, | |||
532 | write_lock_bh(&tbl->lock); | 537 | write_lock_bh(&tbl->lock); |
533 | for (np = &tbl->phash_buckets[hash_val]; (n = *np) != NULL; | 538 | for (np = &tbl->phash_buckets[hash_val]; (n = *np) != NULL; |
534 | np = &n->next) { | 539 | np = &n->next) { |
535 | if (!memcmp(n->key, pkey, key_len) && n->dev == dev) { | 540 | if (!memcmp(n->key, pkey, key_len) && n->dev == dev && |
541 | (n->net == net)) { | ||
536 | *np = n->next; | 542 | *np = n->next; |
537 | write_unlock_bh(&tbl->lock); | 543 | write_unlock_bh(&tbl->lock); |
538 | if (tbl->pdestructor) | 544 | if (tbl->pdestructor) |
539 | tbl->pdestructor(n); | 545 | tbl->pdestructor(n); |
540 | if (n->dev) | 546 | if (n->dev) |
541 | dev_put(n->dev); | 547 | dev_put(n->dev); |
548 | release_net(n->net); | ||
542 | kfree(n); | 549 | kfree(n); |
543 | return 0; | 550 | return 0; |
544 | } | 551 | } |
@@ -561,6 +568,7 @@ static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev) | |||
561 | tbl->pdestructor(n); | 568 | tbl->pdestructor(n); |
562 | if (n->dev) | 569 | if (n->dev) |
563 | dev_put(n->dev); | 570 | dev_put(n->dev); |
571 | release_net(n->net); | ||
564 | kfree(n); | 572 | kfree(n); |
565 | continue; | 573 | continue; |
566 | } | 574 | } |
@@ -1261,12 +1269,37 @@ void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p, | |||
1261 | spin_unlock(&tbl->proxy_queue.lock); | 1269 | spin_unlock(&tbl->proxy_queue.lock); |
1262 | } | 1270 | } |
1263 | 1271 | ||
1272 | static inline struct neigh_parms *lookup_neigh_params(struct neigh_table *tbl, | ||
1273 | struct net *net, int ifindex) | ||
1274 | { | ||
1275 | struct neigh_parms *p; | ||
1276 | |||
1277 | for (p = &tbl->parms; p; p = p->next) { | ||
1278 | if (p->net != net) | ||
1279 | continue; | ||
1280 | if ((p->dev && p->dev->ifindex == ifindex) || | ||
1281 | (!p->dev && !ifindex)) | ||
1282 | return p; | ||
1283 | } | ||
1284 | |||
1285 | return NULL; | ||
1286 | } | ||
1264 | 1287 | ||
1265 | struct neigh_parms *neigh_parms_alloc(struct net_device *dev, | 1288 | struct neigh_parms *neigh_parms_alloc(struct net_device *dev, |
1266 | struct neigh_table *tbl) | 1289 | struct neigh_table *tbl) |
1267 | { | 1290 | { |
1268 | struct neigh_parms *p = kmemdup(&tbl->parms, sizeof(*p), GFP_KERNEL); | 1291 | struct neigh_parms *p, *ref; |
1292 | struct net *net; | ||
1293 | |||
1294 | net = &init_net; | ||
1295 | if (dev) | ||
1296 | net = dev->nd_net; | ||
1297 | |||
1298 | ref = lookup_neigh_params(tbl, net, 0); | ||
1299 | if (!ref) | ||
1300 | return NULL; | ||
1269 | 1301 | ||
1302 | p = kmemdup(ref, sizeof(*p), GFP_KERNEL); | ||
1270 | if (p) { | 1303 | if (p) { |
1271 | p->tbl = tbl; | 1304 | p->tbl = tbl; |
1272 | atomic_set(&p->refcnt, 1); | 1305 | atomic_set(&p->refcnt, 1); |
@@ -1282,6 +1315,7 @@ struct neigh_parms *neigh_parms_alloc(struct net_device *dev, | |||
1282 | dev_hold(dev); | 1315 | dev_hold(dev); |
1283 | p->dev = dev; | 1316 | p->dev = dev; |
1284 | } | 1317 | } |
1318 | p->net = hold_net(net); | ||
1285 | p->sysctl_table = NULL; | 1319 | p->sysctl_table = NULL; |
1286 | write_lock_bh(&tbl->lock); | 1320 | write_lock_bh(&tbl->lock); |
1287 | p->next = tbl->parms.next; | 1321 | p->next = tbl->parms.next; |
@@ -1323,6 +1357,7 @@ void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms) | |||
1323 | 1357 | ||
1324 | void neigh_parms_destroy(struct neigh_parms *parms) | 1358 | void neigh_parms_destroy(struct neigh_parms *parms) |
1325 | { | 1359 | { |
1360 | release_net(parms->net); | ||
1326 | kfree(parms); | 1361 | kfree(parms); |
1327 | } | 1362 | } |
1328 | 1363 | ||
@@ -1333,6 +1368,7 @@ void neigh_table_init_no_netlink(struct neigh_table *tbl) | |||
1333 | unsigned long now = jiffies; | 1368 | unsigned long now = jiffies; |
1334 | unsigned long phsize; | 1369 | unsigned long phsize; |
1335 | 1370 | ||
1371 | tbl->parms.net = &init_net; | ||
1336 | atomic_set(&tbl->parms.refcnt, 1); | 1372 | atomic_set(&tbl->parms.refcnt, 1); |
1337 | INIT_RCU_HEAD(&tbl->parms.rcu_head); | 1373 | INIT_RCU_HEAD(&tbl->parms.rcu_head); |
1338 | tbl->parms.reachable_time = | 1374 | tbl->parms.reachable_time = |
@@ -1446,9 +1482,6 @@ static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
1446 | struct net_device *dev = NULL; | 1482 | struct net_device *dev = NULL; |
1447 | int err = -EINVAL; | 1483 | int err = -EINVAL; |
1448 | 1484 | ||
1449 | if (net != &init_net) | ||
1450 | return -EINVAL; | ||
1451 | |||
1452 | if (nlmsg_len(nlh) < sizeof(*ndm)) | 1485 | if (nlmsg_len(nlh) < sizeof(*ndm)) |
1453 | goto out; | 1486 | goto out; |
1454 | 1487 | ||
@@ -1477,7 +1510,7 @@ static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
1477 | goto out_dev_put; | 1510 | goto out_dev_put; |
1478 | 1511 | ||
1479 | if (ndm->ndm_flags & NTF_PROXY) { | 1512 | if (ndm->ndm_flags & NTF_PROXY) { |
1480 | err = pneigh_delete(tbl, nla_data(dst_attr), dev); | 1513 | err = pneigh_delete(tbl, net, nla_data(dst_attr), dev); |
1481 | goto out_dev_put; | 1514 | goto out_dev_put; |
1482 | } | 1515 | } |
1483 | 1516 | ||
@@ -1515,9 +1548,6 @@ static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
1515 | struct net_device *dev = NULL; | 1548 | struct net_device *dev = NULL; |
1516 | int err; | 1549 | int err; |
1517 | 1550 | ||
1518 | if (net != &init_net) | ||
1519 | return -EINVAL; | ||
1520 | |||
1521 | err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL); | 1551 | err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL); |
1522 | if (err < 0) | 1552 | if (err < 0) |
1523 | goto out; | 1553 | goto out; |
@@ -1557,7 +1587,7 @@ static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
1557 | struct pneigh_entry *pn; | 1587 | struct pneigh_entry *pn; |
1558 | 1588 | ||
1559 | err = -ENOBUFS; | 1589 | err = -ENOBUFS; |
1560 | pn = pneigh_lookup(tbl, dst, dev, 1); | 1590 | pn = pneigh_lookup(tbl, net, dst, dev, 1); |
1561 | if (pn) { | 1591 | if (pn) { |
1562 | pn->flags = ndm->ndm_flags; | 1592 | pn->flags = ndm->ndm_flags; |
1563 | err = 0; | 1593 | err = 0; |
@@ -1752,19 +1782,6 @@ errout: | |||
1752 | return -EMSGSIZE; | 1782 | return -EMSGSIZE; |
1753 | } | 1783 | } |
1754 | 1784 | ||
1755 | static inline struct neigh_parms *lookup_neigh_params(struct neigh_table *tbl, | ||
1756 | int ifindex) | ||
1757 | { | ||
1758 | struct neigh_parms *p; | ||
1759 | |||
1760 | for (p = &tbl->parms; p; p = p->next) | ||
1761 | if ((p->dev && p->dev->ifindex == ifindex) || | ||
1762 | (!p->dev && !ifindex)) | ||
1763 | return p; | ||
1764 | |||
1765 | return NULL; | ||
1766 | } | ||
1767 | |||
1768 | static const struct nla_policy nl_neightbl_policy[NDTA_MAX+1] = { | 1785 | static const struct nla_policy nl_neightbl_policy[NDTA_MAX+1] = { |
1769 | [NDTA_NAME] = { .type = NLA_STRING }, | 1786 | [NDTA_NAME] = { .type = NLA_STRING }, |
1770 | [NDTA_THRESH1] = { .type = NLA_U32 }, | 1787 | [NDTA_THRESH1] = { .type = NLA_U32 }, |
@@ -1798,9 +1815,6 @@ static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
1798 | struct nlattr *tb[NDTA_MAX+1]; | 1815 | struct nlattr *tb[NDTA_MAX+1]; |
1799 | int err; | 1816 | int err; |
1800 | 1817 | ||
1801 | if (net != &init_net) | ||
1802 | return -EINVAL; | ||
1803 | |||
1804 | err = nlmsg_parse(nlh, sizeof(*ndtmsg), tb, NDTA_MAX, | 1818 | err = nlmsg_parse(nlh, sizeof(*ndtmsg), tb, NDTA_MAX, |
1805 | nl_neightbl_policy); | 1819 | nl_neightbl_policy); |
1806 | if (err < 0) | 1820 | if (err < 0) |
@@ -1845,7 +1859,7 @@ static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
1845 | if (tbp[NDTPA_IFINDEX]) | 1859 | if (tbp[NDTPA_IFINDEX]) |
1846 | ifindex = nla_get_u32(tbp[NDTPA_IFINDEX]); | 1860 | ifindex = nla_get_u32(tbp[NDTPA_IFINDEX]); |
1847 | 1861 | ||
1848 | p = lookup_neigh_params(tbl, ifindex); | 1862 | p = lookup_neigh_params(tbl, net, ifindex); |
1849 | if (p == NULL) { | 1863 | if (p == NULL) { |
1850 | err = -ENOENT; | 1864 | err = -ENOENT; |
1851 | goto errout_tbl_lock; | 1865 | goto errout_tbl_lock; |
@@ -1926,9 +1940,6 @@ static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb) | |||
1926 | int neigh_skip = cb->args[1]; | 1940 | int neigh_skip = cb->args[1]; |
1927 | struct neigh_table *tbl; | 1941 | struct neigh_table *tbl; |
1928 | 1942 | ||
1929 | if (net != &init_net) | ||
1930 | return 0; | ||
1931 | |||
1932 | family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family; | 1943 | family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family; |
1933 | 1944 | ||
1934 | read_lock(&neigh_tbl_lock); | 1945 | read_lock(&neigh_tbl_lock); |
@@ -1943,8 +1954,11 @@ static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb) | |||
1943 | NLM_F_MULTI) <= 0) | 1954 | NLM_F_MULTI) <= 0) |
1944 | break; | 1955 | break; |
1945 | 1956 | ||
1946 | for (nidx = 0, p = tbl->parms.next; p; p = p->next, nidx++) { | 1957 | for (nidx = 0, p = tbl->parms.next; p; p = p->next) { |
1947 | if (nidx < neigh_skip) | 1958 | if (net != p->net) |
1959 | continue; | ||
1960 | |||
1961 | if (nidx++ < neigh_skip) | ||
1948 | continue; | 1962 | continue; |
1949 | 1963 | ||
1950 | if (neightbl_fill_param_info(skb, tbl, p, | 1964 | if (neightbl_fill_param_info(skb, tbl, p, |
@@ -2020,6 +2034,7 @@ static void neigh_update_notify(struct neighbour *neigh) | |||
2020 | static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, | 2034 | static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, |
2021 | struct netlink_callback *cb) | 2035 | struct netlink_callback *cb) |
2022 | { | 2036 | { |
2037 | struct net * net = skb->sk->sk_net; | ||
2023 | struct neighbour *n; | 2038 | struct neighbour *n; |
2024 | int rc, h, s_h = cb->args[1]; | 2039 | int rc, h, s_h = cb->args[1]; |
2025 | int idx, s_idx = idx = cb->args[2]; | 2040 | int idx, s_idx = idx = cb->args[2]; |
@@ -2030,8 +2045,12 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, | |||
2030 | continue; | 2045 | continue; |
2031 | if (h > s_h) | 2046 | if (h > s_h) |
2032 | s_idx = 0; | 2047 | s_idx = 0; |
2033 | for (n = tbl->hash_buckets[h], idx = 0; n; n = n->next, idx++) { | 2048 | for (n = tbl->hash_buckets[h], idx = 0; n; n = n->next) { |
2034 | if (idx < s_idx) | 2049 | int lidx; |
2050 | if (n->dev->nd_net != net) | ||
2051 | continue; | ||
2052 | lidx = idx++; | ||
2053 | if (lidx < s_idx) | ||
2035 | continue; | 2054 | continue; |
2036 | if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).pid, | 2055 | if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).pid, |
2037 | cb->nlh->nlmsg_seq, | 2056 | cb->nlh->nlmsg_seq, |
@@ -2053,13 +2072,9 @@ out: | |||
2053 | 2072 | ||
2054 | static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb) | 2073 | static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb) |
2055 | { | 2074 | { |
2056 | struct net *net = skb->sk->sk_net; | ||
2057 | struct neigh_table *tbl; | 2075 | struct neigh_table *tbl; |
2058 | int t, family, s_t; | 2076 | int t, family, s_t; |
2059 | 2077 | ||
2060 | if (net != &init_net) | ||
2061 | return 0; | ||
2062 | |||
2063 | read_lock(&neigh_tbl_lock); | 2078 | read_lock(&neigh_tbl_lock); |
2064 | family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family; | 2079 | family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family; |
2065 | s_t = cb->args[0]; | 2080 | s_t = cb->args[0]; |
@@ -2127,6 +2142,7 @@ EXPORT_SYMBOL(__neigh_for_each_release); | |||
2127 | static struct neighbour *neigh_get_first(struct seq_file *seq) | 2142 | static struct neighbour *neigh_get_first(struct seq_file *seq) |
2128 | { | 2143 | { |
2129 | struct neigh_seq_state *state = seq->private; | 2144 | struct neigh_seq_state *state = seq->private; |
2145 | struct net *net = state->net; | ||
2130 | struct neigh_table *tbl = state->tbl; | 2146 | struct neigh_table *tbl = state->tbl; |
2131 | struct neighbour *n = NULL; | 2147 | struct neighbour *n = NULL; |
2132 | int bucket = state->bucket; | 2148 | int bucket = state->bucket; |
@@ -2136,6 +2152,8 @@ static struct neighbour *neigh_get_first(struct seq_file *seq) | |||
2136 | n = tbl->hash_buckets[bucket]; | 2152 | n = tbl->hash_buckets[bucket]; |
2137 | 2153 | ||
2138 | while (n) { | 2154 | while (n) { |
2155 | if (n->dev->nd_net != net) | ||
2156 | goto next; | ||
2139 | if (state->neigh_sub_iter) { | 2157 | if (state->neigh_sub_iter) { |
2140 | loff_t fakep = 0; | 2158 | loff_t fakep = 0; |
2141 | void *v; | 2159 | void *v; |
@@ -2165,6 +2183,7 @@ static struct neighbour *neigh_get_next(struct seq_file *seq, | |||
2165 | loff_t *pos) | 2183 | loff_t *pos) |
2166 | { | 2184 | { |
2167 | struct neigh_seq_state *state = seq->private; | 2185 | struct neigh_seq_state *state = seq->private; |
2186 | struct net *net = state->net; | ||
2168 | struct neigh_table *tbl = state->tbl; | 2187 | struct neigh_table *tbl = state->tbl; |
2169 | 2188 | ||
2170 | if (state->neigh_sub_iter) { | 2189 | if (state->neigh_sub_iter) { |
@@ -2176,6 +2195,8 @@ static struct neighbour *neigh_get_next(struct seq_file *seq, | |||
2176 | 2195 | ||
2177 | while (1) { | 2196 | while (1) { |
2178 | while (n) { | 2197 | while (n) { |
2198 | if (n->dev->nd_net != net) | ||
2199 | goto next; | ||
2179 | if (state->neigh_sub_iter) { | 2200 | if (state->neigh_sub_iter) { |
2180 | void *v = state->neigh_sub_iter(state, n, pos); | 2201 | void *v = state->neigh_sub_iter(state, n, pos); |
2181 | if (v) | 2202 | if (v) |
@@ -2222,6 +2243,7 @@ static struct neighbour *neigh_get_idx(struct seq_file *seq, loff_t *pos) | |||
2222 | static struct pneigh_entry *pneigh_get_first(struct seq_file *seq) | 2243 | static struct pneigh_entry *pneigh_get_first(struct seq_file *seq) |
2223 | { | 2244 | { |
2224 | struct neigh_seq_state *state = seq->private; | 2245 | struct neigh_seq_state *state = seq->private; |
2246 | struct net * net = state->net; | ||
2225 | struct neigh_table *tbl = state->tbl; | 2247 | struct neigh_table *tbl = state->tbl; |
2226 | struct pneigh_entry *pn = NULL; | 2248 | struct pneigh_entry *pn = NULL; |
2227 | int bucket = state->bucket; | 2249 | int bucket = state->bucket; |
@@ -2229,6 +2251,8 @@ static struct pneigh_entry *pneigh_get_first(struct seq_file *seq) | |||
2229 | state->flags |= NEIGH_SEQ_IS_PNEIGH; | 2251 | state->flags |= NEIGH_SEQ_IS_PNEIGH; |
2230 | for (bucket = 0; bucket <= PNEIGH_HASHMASK; bucket++) { | 2252 | for (bucket = 0; bucket <= PNEIGH_HASHMASK; bucket++) { |
2231 | pn = tbl->phash_buckets[bucket]; | 2253 | pn = tbl->phash_buckets[bucket]; |
2254 | while (pn && (pn->net != net)) | ||
2255 | pn = pn->next; | ||
2232 | if (pn) | 2256 | if (pn) |
2233 | break; | 2257 | break; |
2234 | } | 2258 | } |
@@ -2242,6 +2266,7 @@ static struct pneigh_entry *pneigh_get_next(struct seq_file *seq, | |||
2242 | loff_t *pos) | 2266 | loff_t *pos) |
2243 | { | 2267 | { |
2244 | struct neigh_seq_state *state = seq->private; | 2268 | struct neigh_seq_state *state = seq->private; |
2269 | struct net * net = state->net; | ||
2245 | struct neigh_table *tbl = state->tbl; | 2270 | struct neigh_table *tbl = state->tbl; |
2246 | 2271 | ||
2247 | pn = pn->next; | 2272 | pn = pn->next; |
@@ -2249,6 +2274,8 @@ static struct pneigh_entry *pneigh_get_next(struct seq_file *seq, | |||
2249 | if (++state->bucket > PNEIGH_HASHMASK) | 2274 | if (++state->bucket > PNEIGH_HASHMASK) |
2250 | break; | 2275 | break; |
2251 | pn = tbl->phash_buckets[state->bucket]; | 2276 | pn = tbl->phash_buckets[state->bucket]; |
2277 | while (pn && (pn->net != net)) | ||
2278 | pn = pn->next; | ||
2252 | if (pn) | 2279 | if (pn) |
2253 | break; | 2280 | break; |
2254 | } | 2281 | } |
@@ -2450,6 +2477,7 @@ static inline size_t neigh_nlmsg_size(void) | |||
2450 | 2477 | ||
2451 | static void __neigh_notify(struct neighbour *n, int type, int flags) | 2478 | static void __neigh_notify(struct neighbour *n, int type, int flags) |
2452 | { | 2479 | { |
2480 | struct net *net = n->dev->nd_net; | ||
2453 | struct sk_buff *skb; | 2481 | struct sk_buff *skb; |
2454 | int err = -ENOBUFS; | 2482 | int err = -ENOBUFS; |
2455 | 2483 | ||
@@ -2464,10 +2492,10 @@ static void __neigh_notify(struct neighbour *n, int type, int flags) | |||
2464 | kfree_skb(skb); | 2492 | kfree_skb(skb); |
2465 | goto errout; | 2493 | goto errout; |
2466 | } | 2494 | } |
2467 | err = rtnl_notify(skb, &init_net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC); | 2495 | err = rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC); |
2468 | errout: | 2496 | errout: |
2469 | if (err < 0) | 2497 | if (err < 0) |
2470 | rtnl_set_sk_err(&init_net, RTNLGRP_NEIGH, err); | 2498 | rtnl_set_sk_err(net, RTNLGRP_NEIGH, err); |
2471 | } | 2499 | } |
2472 | 2500 | ||
2473 | #ifdef CONFIG_ARPD | 2501 | #ifdef CONFIG_ARPD |
diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c index e851b143cca3..1ca13b17974d 100644 --- a/net/decnet/dn_neigh.c +++ b/net/decnet/dn_neigh.c | |||
@@ -580,8 +580,8 @@ static const struct seq_operations dn_neigh_seq_ops = { | |||
580 | 580 | ||
581 | static int dn_neigh_seq_open(struct inode *inode, struct file *file) | 581 | static int dn_neigh_seq_open(struct inode *inode, struct file *file) |
582 | { | 582 | { |
583 | return seq_open_private(file, &dn_neigh_seq_ops, | 583 | return seq_open_net(inode, file, &dn_neigh_seq_ops, |
584 | sizeof(struct neigh_seq_state)); | 584 | sizeof(struct neigh_seq_state)); |
585 | } | 585 | } |
586 | 586 | ||
587 | static const struct file_operations dn_neigh_seq_fops = { | 587 | static const struct file_operations dn_neigh_seq_fops = { |
@@ -589,7 +589,7 @@ static const struct file_operations dn_neigh_seq_fops = { | |||
589 | .open = dn_neigh_seq_open, | 589 | .open = dn_neigh_seq_open, |
590 | .read = seq_read, | 590 | .read = seq_read, |
591 | .llseek = seq_lseek, | 591 | .llseek = seq_lseek, |
592 | .release = seq_release_private, | 592 | .release = seq_release_net, |
593 | }; | 593 | }; |
594 | 594 | ||
595 | #endif | 595 | #endif |
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index 1ae5efcdbd5f..938ba7da217c 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c | |||
@@ -984,7 +984,7 @@ source_ok: | |||
984 | * here | 984 | * here |
985 | */ | 985 | */ |
986 | if (!try_hard) { | 986 | if (!try_hard) { |
987 | neigh = neigh_lookup_nodev(&dn_neigh_table, &fl.fld_dst); | 987 | neigh = neigh_lookup_nodev(&dn_neigh_table, &init_net, &fl.fld_dst); |
988 | if (neigh) { | 988 | if (neigh) { |
989 | if ((oldflp->oif && | 989 | if ((oldflp->oif && |
990 | (neigh->dev->ifindex != oldflp->oif)) || | 990 | (neigh->dev->ifindex != oldflp->oif)) || |
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index fdf12d1c350e..9eb6d3ab2977 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c | |||
@@ -837,7 +837,7 @@ static int arp_process(struct sk_buff *skb) | |||
837 | } else if (IN_DEV_FORWARD(in_dev)) { | 837 | } else if (IN_DEV_FORWARD(in_dev)) { |
838 | if ((rt->rt_flags&RTCF_DNAT) || | 838 | if ((rt->rt_flags&RTCF_DNAT) || |
839 | (addr_type == RTN_UNICAST && rt->u.dst.dev != dev && | 839 | (addr_type == RTN_UNICAST && rt->u.dst.dev != dev && |
840 | (arp_fwd_proxy(in_dev, rt) || pneigh_lookup(&arp_tbl, &tip, dev, 0)))) { | 840 | (arp_fwd_proxy(in_dev, rt) || pneigh_lookup(&arp_tbl, &init_net, &tip, dev, 0)))) { |
841 | n = neigh_event_ns(&arp_tbl, sha, &sip, dev); | 841 | n = neigh_event_ns(&arp_tbl, sha, &sip, dev); |
842 | if (n) | 842 | if (n) |
843 | neigh_release(n); | 843 | neigh_release(n); |
@@ -980,7 +980,7 @@ static int arp_req_set_public(struct net *net, struct arpreq *r, | |||
980 | return -ENODEV; | 980 | return -ENODEV; |
981 | } | 981 | } |
982 | if (mask) { | 982 | if (mask) { |
983 | if (pneigh_lookup(&arp_tbl, &ip, dev, 1) == NULL) | 983 | if (pneigh_lookup(&arp_tbl, &init_net, &ip, dev, 1) == NULL) |
984 | return -ENOBUFS; | 984 | return -ENOBUFS; |
985 | return 0; | 985 | return 0; |
986 | } | 986 | } |
@@ -1089,7 +1089,7 @@ static int arp_req_delete_public(struct net *net, struct arpreq *r, | |||
1089 | __be32 mask = ((struct sockaddr_in *)&r->arp_netmask)->sin_addr.s_addr; | 1089 | __be32 mask = ((struct sockaddr_in *)&r->arp_netmask)->sin_addr.s_addr; |
1090 | 1090 | ||
1091 | if (mask == htonl(0xFFFFFFFF)) | 1091 | if (mask == htonl(0xFFFFFFFF)) |
1092 | return pneigh_delete(&arp_tbl, &ip, dev); | 1092 | return pneigh_delete(&arp_tbl, &init_net, &ip, dev); |
1093 | 1093 | ||
1094 | if (mask) | 1094 | if (mask) |
1095 | return -EINVAL; | 1095 | return -EINVAL; |
@@ -1375,8 +1375,8 @@ static const struct seq_operations arp_seq_ops = { | |||
1375 | 1375 | ||
1376 | static int arp_seq_open(struct inode *inode, struct file *file) | 1376 | static int arp_seq_open(struct inode *inode, struct file *file) |
1377 | { | 1377 | { |
1378 | return seq_open_private(file, &arp_seq_ops, | 1378 | return seq_open_net(inode, file, &arp_seq_ops, |
1379 | sizeof(struct neigh_seq_state)); | 1379 | sizeof(struct neigh_seq_state)); |
1380 | } | 1380 | } |
1381 | 1381 | ||
1382 | static const struct file_operations arp_seq_fops = { | 1382 | static const struct file_operations arp_seq_fops = { |
@@ -1384,7 +1384,7 @@ static const struct file_operations arp_seq_fops = { | |||
1384 | .open = arp_seq_open, | 1384 | .open = arp_seq_open, |
1385 | .read = seq_read, | 1385 | .read = seq_read, |
1386 | .llseek = seq_lseek, | 1386 | .llseek = seq_lseek, |
1387 | .release = seq_release_private, | 1387 | .release = seq_release_net, |
1388 | }; | 1388 | }; |
1389 | 1389 | ||
1390 | static int __init arp_proc_init(void) | 1390 | static int __init arp_proc_init(void) |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 4686646058d3..ba7c8aaf2782 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -449,7 +449,7 @@ int ip6_forward(struct sk_buff *skb) | |||
449 | 449 | ||
450 | /* XXX: idev->cnf.proxy_ndp? */ | 450 | /* XXX: idev->cnf.proxy_ndp? */ |
451 | if (ipv6_devconf.proxy_ndp && | 451 | if (ipv6_devconf.proxy_ndp && |
452 | pneigh_lookup(&nd_tbl, &hdr->daddr, skb->dev, 0)) { | 452 | pneigh_lookup(&nd_tbl, &init_net, &hdr->daddr, skb->dev, 0)) { |
453 | int proxied = ip6_forward_proxy_check(skb); | 453 | int proxied = ip6_forward_proxy_check(skb); |
454 | if (proxied > 0) | 454 | if (proxied > 0) |
455 | return ip6_input(skb); | 455 | return ip6_input(skb); |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index b87f9d245e2e..b66a1f81bd83 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -789,7 +789,7 @@ static void ndisc_recv_ns(struct sk_buff *skb) | |||
789 | if (ipv6_chk_acast_addr(dev, &msg->target) || | 789 | if (ipv6_chk_acast_addr(dev, &msg->target) || |
790 | (idev->cnf.forwarding && | 790 | (idev->cnf.forwarding && |
791 | (ipv6_devconf.proxy_ndp || idev->cnf.proxy_ndp) && | 791 | (ipv6_devconf.proxy_ndp || idev->cnf.proxy_ndp) && |
792 | (pneigh = pneigh_lookup(&nd_tbl, | 792 | (pneigh = pneigh_lookup(&nd_tbl, &init_net, |
793 | &msg->target, dev, 0)) != NULL)) { | 793 | &msg->target, dev, 0)) != NULL)) { |
794 | if (!(NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED) && | 794 | if (!(NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED) && |
795 | skb->pkt_type != PACKET_HOST && | 795 | skb->pkt_type != PACKET_HOST && |
@@ -930,7 +930,7 @@ static void ndisc_recv_na(struct sk_buff *skb) | |||
930 | */ | 930 | */ |
931 | if (lladdr && !memcmp(lladdr, dev->dev_addr, dev->addr_len) && | 931 | if (lladdr && !memcmp(lladdr, dev->dev_addr, dev->addr_len) && |
932 | ipv6_devconf.forwarding && ipv6_devconf.proxy_ndp && | 932 | ipv6_devconf.forwarding && ipv6_devconf.proxy_ndp && |
933 | pneigh_lookup(&nd_tbl, &msg->target, dev, 0)) { | 933 | pneigh_lookup(&nd_tbl, &init_net, &msg->target, dev, 0)) { |
934 | /* XXX: idev->cnf.prixy_ndp */ | 934 | /* XXX: idev->cnf.prixy_ndp */ |
935 | goto out; | 935 | goto out; |
936 | } | 936 | } |