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

Tushar Gohad <[email protected]>
Newsgroups gmane.linux.ipv6.usagi.users
Message-ID <[email protected]>
  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
ipv6-fix-ndisc-flow_init.patch (text/x-patch, 1.9 KB)
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)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.