[SK_BUFF]: Introduce skb_reset_mac_header(skb)
[deliverable/linux.git] / net / ipv6 / ip6_output.c
index 305516921aa8e96583422cdce873777d22f8ee29..a5f4562b5d29c19697bc4407914d7797cc61162d 100644 (file)
@@ -88,7 +88,7 @@ static inline int ip6_output_finish(struct sk_buff *skb)
 /* dev_loopback_xmit for use with netfilter. */
 static int ip6_dev_loopback_xmit(struct sk_buff *newskb)
 {
-       newskb->mac.raw = newskb->data;
+       skb_reset_mac_header(newskb);
        __skb_pull(newskb, newskb->nh.raw - newskb->data);
        newskb->pkt_type = PACKET_LOOPBACK;
        newskb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -239,6 +239,8 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
        return -EMSGSIZE;
 }
 
+EXPORT_SYMBOL(ip6_xmit);
+
 /*
  *     To avoid extra problems ND packets are send through this
  *     routine. It's code duplication but I really want to avoid
@@ -861,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:
This page took 0.024092 seconds and 5 git commands to generate.