[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

(usagi-users 03557) Possible bug in net/ipv6/ndisc.c




Hello USAGI folks,

 In the following code of net/ipv6/ndisc.c (2.6.14),

 ---
  void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
                         struct in6_addr *target)
  {

...
ndisc_flow_init(&fl, NDISC_REDIRECT, &saddr_buf, &skb->nh.ipv6h->saddr);


       dst = ip6_route_output(NULL, &fl);
       if (dst == NULL)
            return;
  ...
 ---

 The code would use rt6_lookup() in place of ip6_route_output()
 earlier in 2.6.11 with a dev->ifindex parameter.

---
... (2.6.11)
...
ndisc_flow_init(&fl, NDISC_REDIRECT, &saddr_buf, &skb->nh.ipv6h->saddr);


       rt = rt6_lookup(&skb->nh.ipv6h->saddr, NULL, dev->ifindex, 1);
       if (rt == NULL)
            return;
  ...
 ---

 In 2.6.14 version, how does the dev->ifindex value get into oif
 field of the flow? ip6_route_output() seems to use fl->oif.

 A possible solution is to pass dev->ifindex to ndisc_flow_init().
 Attached is the corresponding patch.

 Thanks,
 - Tushar
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -401,7 +401,9 @@ static void pndisc_destructor(struct pne
  */
 
 static inline void ndisc_flow_init(struct flowi *fl, u8 type,
-			    struct in6_addr *saddr, struct in6_addr *daddr)
+				   struct in6_addr *saddr, 
+				   struct in6_addr *daddr,
+				   int oif)
 {
 	memset(fl, 0, sizeof(*fl));
 	ipv6_addr_copy(&fl->fl6_src, saddr);
@@ -409,6 +411,7 @@ static inline void ndisc_flow_init(struc
 	fl->proto	 	= IPPROTO_ICMPV6;
 	fl->fl_icmp_type	= type;
 	fl->fl_icmp_code	= 0;
+	fl->oif			= oif;
 }
 
 static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
@@ -440,7 +443,8 @@ static void ndisc_send_na(struct net_dev
 		src_addr = &tmpaddr;
 	}
 
-	ndisc_flow_init(&fl, NDISC_NEIGHBOUR_ADVERTISEMENT, src_addr, daddr);
+	ndisc_flow_init(&fl, NDISC_NEIGHBOUR_ADVERTISEMENT, 
+			src_addr, daddr, dev->ifindex);
 
 	dst = ndisc_dst_alloc(dev, neigh, daddr, ip6_output);
 	if (!dst)
@@ -530,7 +534,8 @@ void ndisc_send_ns(struct net_device *de
 		saddr = &addr_buf;
 	}
 
-	ndisc_flow_init(&fl, NDISC_NEIGHBOUR_SOLICITATION, saddr, daddr);
+	ndisc_flow_init(&fl, NDISC_NEIGHBOUR_SOLICITATION, 
+			saddr, daddr, dev->ifindex);
 
 	dst = ndisc_dst_alloc(dev, neigh, daddr, ip6_output);
 	if (!dst)
@@ -605,7 +610,8 @@ void ndisc_send_rs(struct net_device *de
         int len;
 	int err;
 
-	ndisc_flow_init(&fl, NDISC_ROUTER_SOLICITATION, saddr, daddr);
+	ndisc_flow_init(&fl, NDISC_ROUTER_SOLICITATION, 
+			saddr, daddr, dev->ifindex);
 
 	dst = ndisc_dst_alloc(dev, NULL, daddr, ip6_output);
 	if (!dst)
@@ -1340,7 +1346,8 @@ void ndisc_send_redirect(struct sk_buff 
  		return;
  	}
 
-	ndisc_flow_init(&fl, NDISC_REDIRECT, &saddr_buf, &skb->nh.ipv6h->saddr);
+	ndisc_flow_init(&fl, NDISC_REDIRECT, &saddr_buf, 
+			&skb->nh.ipv6h->saddr, dev->ifindex);
 
 	dst = ip6_route_output(NULL, &fl);
 	if (dst == NULL)