|
@@ -380,6 +380,7 @@ static struct rtable *icmp_route_lookup(struct net *net,
|
|
|
struct icmp_bxm *param)
|
|
|
{
|
|
|
struct rtable *rt, *rt2;
|
|
|
+ struct flowi4 fl4_dec;
|
|
|
int err;
|
|
|
|
|
|
memset(fl4, 0, sizeof(*fl4));
|
|
@@ -408,19 +409,19 @@ static struct rtable *icmp_route_lookup(struct net *net,
|
|
|
} else
|
|
|
return rt;
|
|
|
|
|
|
- err = xfrm_decode_session_reverse(skb_in, flowi4_to_flowi(fl4), AF_INET);
|
|
|
+ err = xfrm_decode_session_reverse(skb_in, flowi4_to_flowi(&fl4_dec), AF_INET);
|
|
|
if (err)
|
|
|
goto relookup_failed;
|
|
|
|
|
|
- if (inet_addr_type(net, fl4->saddr) == RTN_LOCAL) {
|
|
|
- rt2 = __ip_route_output_key(net, fl4);
|
|
|
+ if (inet_addr_type(net, fl4_dec.saddr) == RTN_LOCAL) {
|
|
|
+ rt2 = __ip_route_output_key(net, &fl4_dec);
|
|
|
if (IS_ERR(rt2))
|
|
|
err = PTR_ERR(rt2);
|
|
|
} else {
|
|
|
struct flowi4 fl4_2 = {};
|
|
|
unsigned long orefdst;
|
|
|
|
|
|
- fl4_2.daddr = fl4->saddr;
|
|
|
+ fl4_2.daddr = fl4_dec.saddr;
|
|
|
rt2 = ip_route_output_key(net, &fl4_2);
|
|
|
if (IS_ERR(rt2)) {
|
|
|
err = PTR_ERR(rt2);
|
|
@@ -428,7 +429,7 @@ static struct rtable *icmp_route_lookup(struct net *net,
|
|
|
}
|
|
|
/* Ugh! */
|
|
|
orefdst = skb_in->_skb_refdst; /* save old refdst */
|
|
|
- err = ip_route_input(skb_in, fl4->daddr, fl4->saddr,
|
|
|
+ err = ip_route_input(skb_in, fl4_dec.daddr, fl4_dec.saddr,
|
|
|
RT_TOS(tos), rt2->dst.dev);
|
|
|
|
|
|
dst_release(&rt2->dst);
|
|
@@ -440,10 +441,11 @@ static struct rtable *icmp_route_lookup(struct net *net,
|
|
|
goto relookup_failed;
|
|
|
|
|
|
rt2 = (struct rtable *) xfrm_lookup(net, &rt2->dst,
|
|
|
- flowi4_to_flowi(fl4), NULL,
|
|
|
+ flowi4_to_flowi(&fl4_dec), NULL,
|
|
|
XFRM_LOOKUP_ICMP);
|
|
|
if (!IS_ERR(rt2)) {
|
|
|
dst_release(&rt->dst);
|
|
|
+ memcpy(fl4, &fl4_dec, sizeof(*fl4));
|
|
|
rt = rt2;
|
|
|
} else if (PTR_ERR(rt2) == -EPERM) {
|
|
|
if (rt)
|