Commit a207a4b2 authored by David S. Miller's avatar David S. Miller

ipv4: Fix bugs in fib_compute_spec_dst().

Based upon feedback from Julian Anastasov.

1) Use route flags to determine multicast/broadcast, not the
   packet flags.

2) Leave saddr unspecified in flow key.

3) Adjust how we invoke inet_select_addr().  Pass ip_hdr(skb)->saddr as
   second arg, and if it was zeronet use link scope.

4) Use loopback as input interface in flow key.
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 58050fce
...@@ -185,28 +185,36 @@ __be32 fib_compute_spec_dst(struct sk_buff *skb) ...@@ -185,28 +185,36 @@ __be32 fib_compute_spec_dst(struct sk_buff *skb)
struct net_device *dev = skb->dev; struct net_device *dev = skb->dev;
struct in_device *in_dev; struct in_device *in_dev;
struct fib_result res; struct fib_result res;
struct rtable *rt;
struct flowi4 fl4; struct flowi4 fl4;
struct net *net; struct net *net;
int scope;
if (skb->pkt_type != PACKET_BROADCAST && rt = skb_rtable(skb);
skb->pkt_type != PACKET_MULTICAST) if (!(rt->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)))
return ip_hdr(skb)->daddr; return ip_hdr(skb)->daddr;
in_dev = __in_dev_get_rcu(dev); in_dev = __in_dev_get_rcu(dev);
BUG_ON(!in_dev); BUG_ON(!in_dev);
fl4.flowi4_oif = 0;
fl4.flowi4_iif = 0;
fl4.daddr = ip_hdr(skb)->saddr;
fl4.saddr = ip_hdr(skb)->daddr;
fl4.flowi4_tos = RT_TOS(ip_hdr(skb)->tos);
fl4.flowi4_scope = RT_SCOPE_UNIVERSE;
fl4.flowi4_mark = IN_DEV_SRC_VMARK(in_dev) ? skb->mark : 0;
net = dev_net(dev); net = dev_net(dev);
if (!fib_lookup(net, &fl4, &res))
return FIB_RES_PREFSRC(net, res); scope = RT_SCOPE_UNIVERSE;
else if (!ipv4_is_zeronet(ip_hdr(skb)->saddr)) {
return inet_select_addr(dev, 0, RT_SCOPE_UNIVERSE); fl4.flowi4_oif = 0;
fl4.flowi4_iif = net->loopback_dev->ifindex;
fl4.daddr = ip_hdr(skb)->saddr;
fl4.saddr = 0;
fl4.flowi4_tos = RT_TOS(ip_hdr(skb)->tos);
fl4.flowi4_scope = scope;
fl4.flowi4_mark = IN_DEV_SRC_VMARK(in_dev) ? skb->mark : 0;
if (!fib_lookup(net, &fl4, &res))
return FIB_RES_PREFSRC(net, res);
} else {
scope = RT_SCOPE_LINK;
}
return inet_select_addr(dev, ip_hdr(skb)->saddr, scope);
} }
/* Given (packet source, input interface) and optional (dst, oif, tos): /* Given (packet source, input interface) and optional (dst, oif, tos):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment