Merge rsync://rsync.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[deliverable/linux.git] / net / ipv6 / ndisc.c
index ddf038636f01d21de60a7fd100a220ef21280eeb..56ea92837307cef89e2f844b1a8a1945401a7676 100644 (file)
@@ -472,7 +472,9 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
                        inc_opt = 0;
        }
 
-       skb = sock_alloc_send_skb(sk, MAX_HEADER + len + LL_RESERVED_SPACE(dev),
+       skb = sock_alloc_send_skb(sk,
+                                 (MAX_HEADER + sizeof(struct ipv6hdr) +
+                                  len + LL_RESERVED_SPACE(dev)),
                                  1, &err);
 
        if (skb == NULL) {
@@ -496,7 +498,7 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
         msg->icmph.icmp6_unused = 0;
         msg->icmph.icmp6_router    = router;
         msg->icmph.icmp6_solicited = solicited;
-        msg->icmph.icmp6_override  = !!override;
+        msg->icmph.icmp6_override  = override;
 
         /* Set the target address. */
        ipv6_addr_copy(&msg->target, solicited_addr);
@@ -513,7 +515,7 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
 
        skb->dst = dst;
        idev = in6_dev_get(dst->dev);
-       IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
+       IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS);
        err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output);
        if (!err) {
                ICMP6_INC_STATS(idev, ICMP6_MIB_OUTNEIGHBORADVERTISEMENTS);
@@ -561,7 +563,9 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
        if (send_llinfo)
                len += ndisc_opt_addr_space(dev);
 
-       skb = sock_alloc_send_skb(sk, MAX_HEADER + len + LL_RESERVED_SPACE(dev),
+       skb = sock_alloc_send_skb(sk,
+                                 (MAX_HEADER + sizeof(struct ipv6hdr) +
+                                  len + LL_RESERVED_SPACE(dev)),
                                  1, &err);
        if (skb == NULL) {
                ND_PRINTK0(KERN_ERR
@@ -597,7 +601,7 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
        /* send it! */
        skb->dst = dst;
        idev = in6_dev_get(dst->dev);
-       IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
+       IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS);
        err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output);
        if (!err) {
                ICMP6_INC_STATS(idev, ICMP6_MIB_OUTNEIGHBORSOLICITS);
@@ -636,7 +640,9 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr,
        if (dev->addr_len)
                len += ndisc_opt_addr_space(dev);
 
-        skb = sock_alloc_send_skb(sk, MAX_HEADER + len + LL_RESERVED_SPACE(dev),
+        skb = sock_alloc_send_skb(sk,
+                                 (MAX_HEADER + sizeof(struct ipv6hdr) +
+                                  len + LL_RESERVED_SPACE(dev)),
                                  1, &err);
        if (skb == NULL) {
                ND_PRINTK0(KERN_ERR
@@ -670,7 +676,7 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr,
        /* send it! */
        skb->dst = dst;
        idev = in6_dev_get(dst->dev);
-       IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); 
+       IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS);
        err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output);
        if (!err) {
                ICMP6_INC_STATS(idev, ICMP6_MIB_OUTROUTERSOLICITS);
@@ -824,6 +830,7 @@ static void ndisc_recv_ns(struct sk_buff *skb)
 
                if (ipv6_chk_acast_addr(dev, &msg->target) ||
                    (idev->cnf.forwarding && 
+                    (ipv6_devconf.proxy_ndp || idev->cnf.proxy_ndp) &&
                     (pneigh = pneigh_lookup(&nd_tbl,
                                             &msg->target, dev, 0)) != NULL)) {
                        if (!(NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED) &&
@@ -846,10 +853,7 @@ 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;
+       is_router = !!(pneigh ? pneigh->flags & NTF_ROUTER : idev->cnf.forwarding);
 
        if (dad) {
                struct in6_addr maddr;
@@ -966,8 +970,11 @@ static void ndisc_recv_na(struct sk_buff *skb)
                 * has already sent a NA to us.
                 */
                if (lladdr && !memcmp(lladdr, dev->dev_addr, dev->addr_len) &&
-                   pneigh_lookup(&nd_tbl, &msg->target, dev, 0))
+                   ipv6_devconf.forwarding && ipv6_devconf.proxy_ndp &&
+                   pneigh_lookup(&nd_tbl, &msg->target, dev, 0)) {
+                       /* XXX: idev->cnf.prixy_ndp */
                        goto out;
+               }
 
                neigh_update(neigh, lladdr,
                             msg->icmph.icmp6_solicited ? NUD_REACHABLE : NUD_STALE,
@@ -1260,10 +1267,11 @@ skip_defrtr:
        }
 
        if (ndopts.nd_opts_mtu) {
+               __be32 n;
                u32 mtu;
 
-               memcpy(&mtu, ((u8*)(ndopts.nd_opts_mtu+1))+2, sizeof(mtu));
-               mtu = ntohl(mtu);
+               memcpy(&n, ((u8*)(ndopts.nd_opts_mtu+1))+2, sizeof(mtu));
+               mtu = ntohl(n);
 
                if (mtu < IPV6_MIN_MTU || mtu > skb->dev->mtu) {
                        ND_PRINTK2(KERN_WARNING
@@ -1445,7 +1453,9 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
        rd_len &= ~0x7;
        len += rd_len;
 
-       buff = sock_alloc_send_skb(sk, MAX_HEADER + len + LL_RESERVED_SPACE(dev),
+       buff = sock_alloc_send_skb(sk,
+                                  (MAX_HEADER + sizeof(struct ipv6hdr) +
+                                   len + LL_RESERVED_SPACE(dev)),
                                   1, &err);
        if (buff == NULL) {
                ND_PRINTK0(KERN_ERR
@@ -1503,7 +1513,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
 
        buff->dst = dst;
        idev = in6_dev_get(dst->dev);
-       IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
+       IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS);
        err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, buff, NULL, dst->dev, dst_output);
        if (!err) {
                ICMP6_INC_STATS(idev, ICMP6_MIB_OUTREDIRECTS);
@@ -1741,6 +1751,7 @@ int __init ndisc_init(struct net_proto_family *ops)
 
 void ndisc_cleanup(void)
 {
+       unregister_netdevice_notifier(&ndisc_netdev_notifier);
 #ifdef CONFIG_SYSCTL
        neigh_sysctl_unregister(&nd_tbl.parms);
 #endif
This page took 0.029854 seconds and 5 git commands to generate.