aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/ip6_output.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/ip6_output.c')
-rw-r--r--net/ipv6/ip6_output.c35
1 files changed, 35 insertions, 0 deletions
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 0d60fbc59d8f..7e25043d826c 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -863,6 +863,41 @@ static int ip6_dst_lookup_tail(struct sock *sk,
863 goto out_err_release; 863 goto out_err_release;
864 } 864 }
865 865
866#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
867 /*
868 * Here if the dst entry we've looked up
869 * has a neighbour entry that is in the INCOMPLETE
870 * state and the src address from the flow is
871 * marked as OPTIMISTIC, we release the found
872 * dst entry and replace it instead with the
873 * dst entry of the nexthop router
874 */
875 if (!((*dst)->neighbour->nud_state & NUD_VALID)) {
876 struct inet6_ifaddr *ifp;
877 struct flowi fl_gw;
878 int redirect;
879
880 ifp = ipv6_get_ifaddr(&fl->fl6_src, (*dst)->dev, 1);
881
882 redirect = (ifp && ifp->flags & IFA_F_OPTIMISTIC);
883 if (ifp)
884 in6_ifa_put(ifp);
885
886 if (redirect) {
887 /*
888 * We need to get the dst entry for the
889 * default router instead
890 */
891 dst_release(*dst);
892 memcpy(&fl_gw, fl, sizeof(struct flowi));
893 memset(&fl_gw.fl6_dst, 0, sizeof(struct in6_addr));
894 *dst = ip6_route_output(sk, &fl_gw);
895 if ((err = (*dst)->error))
896 goto out_err_release;
897 }
898 }
899#endif
900
866 return 0; 901 return 0;
867 902
868out_err_release: 903out_err_release: