aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2008-01-24 03:13:18 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 18:00:03 -0500
commit426b5303eb435d98b9bee37a807be386bc2b3320 (patch)
tree86f7bd945101d9ac51afb22a210d22b8ff956a4e
parente1af9f270b69a3ad1dcbabb404dd1f40a96f43f5 (diff)
[NETNS]: Modify the neighbour table code so it handles multiple network namespaces
I'm actually surprised at how much was involved. At first glance it appears that the neighbour table data structures are already split by network device so all that should be needed is to modify the user interface commands to filter the set of neighbours by the network namespace of their devices. However a couple things turned up while I was reading through the code. The proxy neighbour table allows entries with no network device, and the neighbour parms are per network device (except for the defaults) so they now need a per network namespace default. So I updated the two structures (which surprised me) with their very own network namespace parameter. Updated the relevant lookup and destroy routines with a network namespace parameter and modified the code that interacts with users to filter out neighbour table entries for devices of other namespaces. I'm a little concerned that we can modify and display the global table configuration and from all network namespaces. But this appears good enough for now. I keep thinking modifying the neighbour table to have per network namespace instances of each table type would should be cleaner. The hash table is already dynamically sized so there are it is not a limiter. The default parameter would be straight forward to take care of. However when I look at the how the network table is built and used I still find some assumptions that there is only a single neighbour table for each type of table in the kernel. The netlink operations, neigh_seq_start, the non-core network users that call neigh_lookup. So while it might be doable it would require more refactoring than my current approach of just doing a little extra filtering in the code. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/neighbour.h10
-rw-r--r--net/atm/clip.c15
-rw-r--r--net/core/neighbour.c116
-rw-r--r--net/decnet/dn_neigh.c6
-rw-r--r--net/decnet/dn_route.c2
-rw-r--r--net/ipv4/arp.c12
-rw-r--r--net/ipv6/ip6_output.c2
-rw-r--r--net/ipv6/ndisc.c4
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
35struct neigh_parms 35struct 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
126struct pneigh_entry 127struct 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);
189extern struct neighbour * neigh_lookup_nodev(struct neigh_table *tbl, 191extern struct neighbour * neigh_lookup_nodev(struct neigh_table *tbl,
192 struct net *net,
190 const void *pkey); 193 const void *pkey);
191extern struct neighbour * neigh_create(struct neigh_table *tbl, 194extern 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
212extern void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p, 215extern void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
213 struct sk_buff *skb); 216 struct sk_buff *skb);
214extern struct pneigh_entry *pneigh_lookup(struct neigh_table *tbl, const void *key, struct net_device *dev, int creat); 217extern struct pneigh_entry *pneigh_lookup(struct neigh_table *tbl, struct net *net, const void *key, struct net_device *dev, int creat);
215extern int pneigh_delete(struct neigh_table *tbl, const void *key, struct net_device *dev); 218extern int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *key, struct net_device *dev);
216 219
217extern void neigh_app_ns(struct neighbour *n); 220extern void neigh_app_ns(struct neighbour *n);
218extern void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie); 221extern 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
220extern void pneigh_for_each(struct neigh_table *tbl, void (*cb)(struct pneigh_entry *)); 223extern void pneigh_for_each(struct neigh_table *tbl, void (*cb)(struct pneigh_entry *));
221 224
222struct neigh_seq_state { 225struct 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 }
952out: 957out:
953 return rc; 958 return rc;
954 959
@@ -957,11 +962,19 @@ out_kfree:
957 goto out; 962 goto out;
958} 963}
959 964
965static 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
960static const struct file_operations arp_seq_fops = { 973static 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
378struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, const void *pkey) 378struct 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
466struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl, const void *pkey, 468struct 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
520int pneigh_delete(struct neigh_table *tbl, const void *pkey, 525int 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
1272static 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
1265struct neigh_parms *neigh_parms_alloc(struct net_device *dev, 1288struct 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
1324void neigh_parms_destroy(struct neigh_parms *parms) 1358void 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
1755static 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
1768static const struct nla_policy nl_neightbl_policy[NDTA_MAX+1] = { 1785static 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)
2020static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, 2034static 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
2054static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb) 2073static 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);
2127static struct neighbour *neigh_get_first(struct seq_file *seq) 2142static 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)
2222static struct pneigh_entry *pneigh_get_first(struct seq_file *seq) 2243static 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
2451static void __neigh_notify(struct neighbour *n, int type, int flags) 2478static 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);
2468errout: 2496errout:
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
581static int dn_neigh_seq_open(struct inode *inode, struct file *file) 581static 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
587static const struct file_operations dn_neigh_seq_fops = { 587static 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
1376static int arp_seq_open(struct inode *inode, struct file *file) 1376static 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
1382static const struct file_operations arp_seq_fops = { 1382static 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
1390static int __init arp_proc_init(void) 1390static 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 }