]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
[IPV6] NDISC: Set per-entry is_router flag in Proxy NA.
authorVille Nuorvala <vnuorval@tcs.hut.fi>
Fri, 22 Sep 2006 21:43:19 +0000 (14:43 -0700)
committerDavid S. Miller <davem@sunset.davemloft.net>
Fri, 22 Sep 2006 22:20:24 +0000 (15:20 -0700)
We have sent NA with router flag from the node-wide forwarding
configuration.  This is not appropriate for proxy NA, and it should be
set according to each proxy entry's configuration.

This is used by Mobile IPv6 home agent to support physical home link
in acting as a proxy router for mobile node which is not a router,
for example.

Based on MIPL2 kernel patch.

Signed-off-by: Ville Nuorvala <vnuorval@tcs.hut.fi>
Signed-off-by: Masahide NAKAMURA <nakam@linux-ipv6.org>
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
include/net/neighbour.h
net/core/neighbour.c
net/ipv6/ndisc.c

index bd187daffdb9f51decc99b6ac90b7de778db267c..c8aacbd2e3331198fbde8125b1829e61f779a043 100644 (file)
@@ -126,6 +126,7 @@ struct pneigh_entry
 {
        struct pneigh_entry     *next;
        struct net_device               *dev;
+       u8                      flags;
        u8                      key[0];
 };
 
index a45bd2124d6b21a3c93c1aa846a780e759c20f40..b6c69e1463e87f0dc756022ade88e52e4062dea0 100644 (file)
@@ -1544,9 +1544,14 @@ int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
                lladdr = tb[NDA_LLADDR] ? nla_data(tb[NDA_LLADDR]) : NULL;
 
                if (ndm->ndm_flags & NTF_PROXY) {
-                       err = 0;
-                       if (pneigh_lookup(tbl, dst, dev, 1) == NULL)
-                               err = -ENOBUFS;
+                       struct pneigh_entry *pn;
+
+                       err = -ENOBUFS;
+                       pn = pneigh_lookup(tbl, dst, dev, 1);
+                       if (pn) {
+                               pn->flags = ndm->ndm_flags;
+                               err = 0;
+                       }
                        goto out_dev_put;
                }
 
index 0e0d6ce6902134617bb360e980c75ad9eb8cec28..ddf038636f01d21de60a7fd100a220ef21280eeb 100644 (file)
@@ -736,8 +736,10 @@ static void ndisc_recv_ns(struct sk_buff *skb)
        struct inet6_ifaddr *ifp;
        struct inet6_dev *idev = NULL;
        struct neighbour *neigh;
+       struct pneigh_entry *pneigh = NULL;
        int dad = ipv6_addr_any(saddr);
        int inc;
+       int is_router;
 
        if (ipv6_addr_is_multicast(&msg->target)) {
                ND_PRINTK2(KERN_WARNING 
@@ -822,7 +824,8 @@ static void ndisc_recv_ns(struct sk_buff *skb)
 
                if (ipv6_chk_acast_addr(dev, &msg->target) ||
                    (idev->cnf.forwarding && 
-                    pneigh_lookup(&nd_tbl, &msg->target, dev, 0))) {
+                    (pneigh = pneigh_lookup(&nd_tbl,
+                                            &msg->target, dev, 0)) != NULL)) {
                        if (!(NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED) &&
                            skb->pkt_type != PACKET_HOST &&
                            inc != 0 &&
@@ -843,12 +846,17 @@ static void ndisc_recv_ns(struct sk_buff *skb)
                        goto out;
        }
 
+       if (pneigh)
+               is_router = pneigh->flags & NTF_ROUTER;
+       else
+               is_router = idev->cnf.forwarding;
+
        if (dad) {
                struct in6_addr maddr;
 
                ipv6_addr_all_nodes(&maddr);
                ndisc_send_na(dev, NULL, &maddr, &msg->target,
-                             idev->cnf.forwarding, 0, (ifp != NULL), 1);
+                             is_router, 0, (ifp != NULL), 1);
                goto out;
        }
 
@@ -869,7 +877,7 @@ static void ndisc_recv_ns(struct sk_buff *skb)
                             NEIGH_UPDATE_F_OVERRIDE);
        if (neigh || !dev->hard_header) {
                ndisc_send_na(dev, neigh, saddr, &msg->target,
-                             idev->cnf.forwarding, 
+                             is_router,
                              1, (ifp != NULL && inc), inc);
                if (neigh)
                        neigh_release(neigh);