]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/ipv6/ip6_output.c
[IPV6] ADDRCONF: Optimistic Duplicate Address Detection (RFC 4429) Support.
[linux-2.6-omap-h63xx.git] / net / ipv6 / ip6_output.c
index 0d60fbc59d8f080c1d92f7c88d52132aa6ee4403..7e25043d826c0b772007fbc5cdd86d396dbe2088 100644 (file)
@@ -863,6 +863,41 @@ static int ip6_dst_lookup_tail(struct sock *sk,
                        goto out_err_release;
        }
 
+#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
+               /*
+                * Here if the dst entry we've looked up
+                * has a neighbour entry that is in the INCOMPLETE
+                * state and the src address from the flow is
+                * marked as OPTIMISTIC, we release the found
+                * dst entry and replace it instead with the
+                * dst entry of the nexthop router
+                */
+               if (!((*dst)->neighbour->nud_state & NUD_VALID)) {
+                       struct inet6_ifaddr *ifp;
+                       struct flowi fl_gw;
+                       int redirect;
+
+                       ifp = ipv6_get_ifaddr(&fl->fl6_src, (*dst)->dev, 1);
+
+                       redirect = (ifp && ifp->flags & IFA_F_OPTIMISTIC);
+                       if (ifp)
+                               in6_ifa_put(ifp);
+
+                       if (redirect) {
+                               /*
+                                * We need to get the dst entry for the
+                                * default router instead
+                                */
+                               dst_release(*dst);
+                               memcpy(&fl_gw, fl, sizeof(struct flowi));
+                               memset(&fl_gw.fl6_dst, 0, sizeof(struct in6_addr));
+                               *dst = ip6_route_output(sk, &fl_gw);
+                               if ((err = (*dst)->error))
+                                       goto out_err_release;
+                       }
+               }
+#endif
+
        return 0;
 
 out_err_release: