Bug 32452

Summary: IP_PKTINFO cmsg lacks if index
Product: Networking Reporter: Andreas Schwab (schwab)
Component: IPV4Assignee: Stephen Hemminger (stephen)
Status: CLOSED CODE_FIX    
Severity: normal CC: florian, maciej.rutecki, rjw
Priority: P1    
Hardware: All   
OS: Linux   
Kernel Version: 2.6.39-rc1 Subsystem:
Regression: Yes Bisected commit-id:
Bug Depends on:    
Bug Blocks: 32012    

Description Andreas Schwab 2011-04-01 18:59:13 UTC
The IP_PKTINFO cmsg is missing the if index, ie. ipi_ifindex == 0 (but the address is non-zero).  This causes avahi-daemon to abort.
Comment 1 Andreas Schwab 2011-04-06 08:54:53 UTC
Still broken in 2.6.39-rc2.
Comment 2 Andrew Morton 2011-04-19 21:46:58 UTC
(switched to email.  Please respond via emailed reply-to-all, not via the
bugzilla web interface).

On Fri, 1 Apr 2011 18:59:14 GMT
bugzilla-daemon@bugzilla.kernel.org wrote:

> https://bugzilla.kernel.org/show_bug.cgi?id=32452
> 
>            Summary: IP_PKTINFO cmsg lacks if index
>            Product: Networking
>            Version: 2.5
>     Kernel Version: 2.6.39-rc1
>           Platform: All
>         OS/Version: Linux
>               Tree: Mainline
>             Status: NEW
>           Severity: normal
>           Priority: P1
>          Component: IPV4
>         AssignedTo: shemminger@linux-foundation.org
>         ReportedBy: schwab@linux-m68k.org
>         Regression: Yes
> 
> 
> The IP_PKTINFO cmsg is missing the if index, ie. ipi_ifindex == 0 (but the
> address is non-zero).  This causes avahi-daemon to abort.
> 

Might be a post-2.6.38 regression (the report doesn't say).
Comment 3 David S. Miller 2011-04-19 21:53:37 UTC
From: Andrew Morton <akpm@linux-foundation.org>
Date: Tue, 19 Apr 2011 14:45:56 -0700

> On Fri, 1 Apr 2011 18:59:14 GMT
> bugzilla-daemon@bugzilla.kernel.org wrote:
> 
>> https://bugzilla.kernel.org/show_bug.cgi?id=32452
>> 
>>            Summary: IP_PKTINFO cmsg lacks if index
>>            Product: Networking
>>            Version: 2.5
>>     Kernel Version: 2.6.39-rc1
>>           Platform: All
>>         OS/Version: Linux
>>               Tree: Mainline
>>             Status: NEW
>>           Severity: normal
>>           Priority: P1
>>          Component: IPV4
>>         AssignedTo: shemminger@linux-foundation.org
>>         ReportedBy: schwab@linux-m68k.org
>>         Regression: Yes
>> 
>> 
>> The IP_PKTINFO cmsg is missing the if index, ie. ipi_ifindex == 0 (but the
>> address is non-zero).  This causes avahi-daemon to abort.
>> 
> Might be a post-2.6.38 regression (the report doesn't say).

Fixed by:

commit 1b86a58f9d7ce4fe2377687f378fbfb53bdc9b6c
Author: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Date:   Thu Apr 7 14:04:08 2011 -0700

    ipv4: Fix "Set rt->rt_iif more sanely on output routes."
    
    Commit 1018b5c01636c7c6bda31a719bda34fc631db29a ("Set rt->rt_iif more
    sanely on output routes.")  breaks rt_is_{output,input}_route.
    
    This became the cause to return "IP_PKTINFO's ->ipi_ifindex == 0".
    
    To fix it, this does:
    
    1) Add "int rt_route_iif;" to struct rtable
    
    2) For input routes, always set rt_route_iif to same value as rt_iif
    
    3) For output routes, always set rt_route_iif to zero.  Set rt_iif
       as it is done currently.
    
    4) Change rt_is_{output,input}_route() to test rt_route_iif
    
    Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
    Signed-off-by: David S. Miller <davem@davemloft.net>

diff --git a/include/net/route.h b/include/net/route.h
index f88429c..8fce062 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -64,6 +64,7 @@ struct rtable {
 
 	__be32			rt_dst;	/* Path destination	*/
 	__be32			rt_src;	/* Path source		*/
+	int			rt_route_iif;
 	int			rt_iif;
 	int			rt_oif;
 	__u32			rt_mark;
@@ -80,12 +81,12 @@ struct rtable {
 
 static inline bool rt_is_input_route(struct rtable *rt)
 {
-	return rt->rt_iif != 0;
+	return rt->rt_route_iif != 0;
 }
 
 static inline bool rt_is_output_route(struct rtable *rt)
 {
-	return rt->rt_iif == 0;
+	return rt->rt_route_iif == 0;
 }
 
 struct ip_rt_acct {
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 4b0c811..1628be5 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1891,6 +1891,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 #ifdef CONFIG_IP_ROUTE_CLASSID
 	rth->dst.tclassid = itag;
 #endif
+	rth->rt_route_iif = dev->ifindex;
 	rth->rt_iif	= dev->ifindex;
 	rth->dst.dev	= init_net.loopback_dev;
 	dev_hold(rth->dst.dev);
@@ -2026,6 +2027,7 @@ static int __mkroute_input(struct sk_buff *skb,
 	rth->rt_key_src	= saddr;
 	rth->rt_src	= saddr;
 	rth->rt_gateway	= daddr;
+	rth->rt_route_iif = in_dev->dev->ifindex;
 	rth->rt_iif 	= in_dev->dev->ifindex;
 	rth->dst.dev	= (out_dev)->dev;
 	dev_hold(rth->dst.dev);
@@ -2202,6 +2204,7 @@ local_input:
 #ifdef CONFIG_IP_ROUTE_CLASSID
 	rth->dst.tclassid = itag;
 #endif
+	rth->rt_route_iif = dev->ifindex;
 	rth->rt_iif	= dev->ifindex;
 	rth->dst.dev	= net->loopback_dev;
 	dev_hold(rth->dst.dev);
@@ -2401,7 +2404,8 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
 	rth->rt_mark    = oldflp4->flowi4_mark;
 	rth->rt_dst	= fl4->daddr;
 	rth->rt_src	= fl4->saddr;
-	rth->rt_iif	= 0;
+	rth->rt_route_iif = 0;
+	rth->rt_iif	= oldflp4->flowi4_oif ? : dev_out->ifindex;
 	/* get references to the devices that are to be hold by the routing
 	   cache entry */
 	rth->dst.dev	= dev_out;
@@ -2716,6 +2720,7 @@ struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_or
 		rt->rt_key_dst = ort->rt_key_dst;
 		rt->rt_key_src = ort->rt_key_src;
 		rt->rt_tos = ort->rt_tos;
+		rt->rt_route_iif = ort->rt_route_iif;
 		rt->rt_iif = ort->rt_iif;
 		rt->rt_oif = ort->rt_oif;
 		rt->rt_mark = ort->rt_mark;
@@ -2725,7 +2730,6 @@ struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_or
 		rt->rt_type = ort->rt_type;
 		rt->rt_dst = ort->rt_dst;
 		rt->rt_src = ort->rt_src;
-		rt->rt_iif = ort->rt_iif;
 		rt->rt_gateway = ort->rt_gateway;
 		rt->rt_spec_dst = ort->rt_spec_dst;
 		rt->peer = ort->peer;
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index 13e0e7f..d20a05e 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -74,6 +74,7 @@ static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev,
 	rt->rt_key_dst = fl4->daddr;
 	rt->rt_key_src = fl4->saddr;
 	rt->rt_tos = fl4->flowi4_tos;
+	rt->rt_route_iif = fl4->flowi4_iif;
 	rt->rt_iif = fl4->flowi4_iif;
 	rt->rt_oif = fl4->flowi4_oif;
 	rt->rt_mark = fl4->flowi4_mark;