瀏覽代碼

ipv6: ndisc: inherit metadata dst when creating ndisc requests

If output device wants to see the dst, inherit the dst of the original skb
in the ndisc request.

This is an IPv6 counterpart of commit 0accfc268f4d ("arp: Inherit metadata
dst when creating ARP requests").

Signed-off-by: Jiri Benc <jbenc@redhat.com>
Acked-by: Thomas Graf <tgraf@suug.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
Jiri Benc 10 年之前
父節點
當前提交
ab450605b3
共有 4 個文件被更改,包括 11 次插入6 次删除
  1. 2 1
      include/net/ndisc.h
  2. 1 1
      net/ipv6/addrconf.c
  3. 7 3
      net/ipv6/ndisc.c
  4. 1 1
      net/ipv6/route.c

+ 2 - 1
include/net/ndisc.h

@@ -182,7 +182,8 @@ int ndisc_rcv(struct sk_buff *skb);
 
 
 void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
 void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
 		   const struct in6_addr *solicit,
 		   const struct in6_addr *solicit,
-		   const struct in6_addr *daddr, const struct in6_addr *saddr);
+		   const struct in6_addr *daddr, const struct in6_addr *saddr,
+		   struct sk_buff *oskb);
 
 
 void ndisc_send_rs(struct net_device *dev,
 void ndisc_send_rs(struct net_device *dev,
 		   const struct in6_addr *saddr, const struct in6_addr *daddr);
 		   const struct in6_addr *saddr, const struct in6_addr *daddr);

+ 1 - 1
net/ipv6/addrconf.c

@@ -3656,7 +3656,7 @@ static void addrconf_dad_work(struct work_struct *w)
 
 
 	/* send a neighbour solicitation for our addr */
 	/* send a neighbour solicitation for our addr */
 	addrconf_addr_solict_mult(&ifp->addr, &mcaddr);
 	addrconf_addr_solict_mult(&ifp->addr, &mcaddr);
-	ndisc_send_ns(ifp->idev->dev, NULL, &ifp->addr, &mcaddr, &in6addr_any);
+	ndisc_send_ns(ifp->idev->dev, NULL, &ifp->addr, &mcaddr, &in6addr_any, NULL);
 out:
 out:
 	in6_ifa_put(ifp);
 	in6_ifa_put(ifp);
 	rtnl_unlock();
 	rtnl_unlock();

+ 7 - 3
net/ipv6/ndisc.c

@@ -553,7 +553,8 @@ static void ndisc_send_unsol_na(struct net_device *dev)
 
 
 void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
 void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
 		   const struct in6_addr *solicit,
 		   const struct in6_addr *solicit,
-		   const struct in6_addr *daddr, const struct in6_addr *saddr)
+		   const struct in6_addr *daddr, const struct in6_addr *saddr,
+		   struct sk_buff *oskb)
 {
 {
 	struct sk_buff *skb;
 	struct sk_buff *skb;
 	struct in6_addr addr_buf;
 	struct in6_addr addr_buf;
@@ -589,6 +590,9 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
 		ndisc_fill_addr_option(skb, ND_OPT_SOURCE_LL_ADDR,
 		ndisc_fill_addr_option(skb, ND_OPT_SOURCE_LL_ADDR,
 				       dev->dev_addr);
 				       dev->dev_addr);
 
 
+	if (!(dev->priv_flags & IFF_XMIT_DST_RELEASE) && oskb)
+		skb_dst_copy(skb, oskb);
+
 	ndisc_send_skb(skb, daddr, saddr);
 	ndisc_send_skb(skb, daddr, saddr);
 }
 }
 
 
@@ -675,12 +679,12 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb)
 				  "%s: trying to ucast probe in NUD_INVALID: %pI6\n",
 				  "%s: trying to ucast probe in NUD_INVALID: %pI6\n",
 				  __func__, target);
 				  __func__, target);
 		}
 		}
-		ndisc_send_ns(dev, neigh, target, target, saddr);
+		ndisc_send_ns(dev, neigh, target, target, saddr, skb);
 	} else if ((probes -= NEIGH_VAR(neigh->parms, APP_PROBES)) < 0) {
 	} else if ((probes -= NEIGH_VAR(neigh->parms, APP_PROBES)) < 0) {
 		neigh_app_ns(neigh);
 		neigh_app_ns(neigh);
 	} else {
 	} else {
 		addrconf_addr_solict_mult(target, &mcaddr);
 		addrconf_addr_solict_mult(target, &mcaddr);
-		ndisc_send_ns(dev, NULL, target, &mcaddr, saddr);
+		ndisc_send_ns(dev, NULL, target, &mcaddr, saddr, skb);
 	}
 	}
 }
 }
 
 

+ 1 - 1
net/ipv6/route.c

@@ -538,7 +538,7 @@ static void rt6_probe_deferred(struct work_struct *w)
 		container_of(w, struct __rt6_probe_work, work);
 		container_of(w, struct __rt6_probe_work, work);
 
 
 	addrconf_addr_solict_mult(&work->target, &mcaddr);
 	addrconf_addr_solict_mult(&work->target, &mcaddr);
-	ndisc_send_ns(work->dev, NULL, &work->target, &mcaddr, NULL);
+	ndisc_send_ns(work->dev, NULL, &work->target, &mcaddr, NULL, NULL);
 	dev_put(work->dev);
 	dev_put(work->dev);
 	kfree(work);
 	kfree(work);
 }
 }