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: David S. Miller <davem@davemloft.net>
This commit is contained in:
Родитель
58050fce35
Коммит
a207a4b2e8
|
@ -185,28 +185,36 @@ __be32 fib_compute_spec_dst(struct sk_buff *skb)
|
|||
struct net_device *dev = skb->dev;
|
||||
struct in_device *in_dev;
|
||||
struct fib_result res;
|
||||
struct rtable *rt;
|
||||
struct flowi4 fl4;
|
||||
struct net *net;
|
||||
int scope;
|
||||
|
||||
if (skb->pkt_type != PACKET_BROADCAST &&
|
||||
skb->pkt_type != PACKET_MULTICAST)
|
||||
rt = skb_rtable(skb);
|
||||
if (!(rt->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)))
|
||||
return ip_hdr(skb)->daddr;
|
||||
|
||||
in_dev = __in_dev_get_rcu(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);
|
||||
if (!fib_lookup(net, &fl4, &res))
|
||||
return FIB_RES_PREFSRC(net, res);
|
||||
else
|
||||
return inet_select_addr(dev, 0, RT_SCOPE_UNIVERSE);
|
||||
|
||||
scope = RT_SCOPE_UNIVERSE;
|
||||
if (!ipv4_is_zeronet(ip_hdr(skb)->saddr)) {
|
||||
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):
|
||||
|
|
Загрузка…
Ссылка в новой задаче