Going forward skb_dst_set will assert that skb dst_entry is empty during skb_dst_set. skb_dst_reset is added to reset existing entry without doing refcnt. skb_dst_restore should be used to restore the previous entry. Convert icmp_route_lookup and ip_options_rcv_srr to these helpers. Add extra call to skb_dst_drop to icmp_route_lookup to clear the ip_route_input entry. Signed-off-by: Stanislav Fomichev --- net/ipv4/icmp.c | 7 ++++--- net/ipv4/ip_options.c | 5 ++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 2ffe73ea644f..93a166a7ec8d 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -544,14 +544,15 @@ static struct rtable *icmp_route_lookup(struct net *net, struct flowi4 *fl4, goto relookup_failed; } /* Ugh! */ - orefdst = skb_in->_skb_refdst; /* save old refdst */ - skb_dst_set(skb_in, NULL); + orefdst = skb_dst_reset(skb_in); err = ip_route_input(skb_in, fl4_dec.daddr, fl4_dec.saddr, dscp, rt2->dst.dev) ? -EINVAL : 0; dst_release(&rt2->dst); rt2 = skb_rtable(skb_in); - skb_in->_skb_refdst = orefdst; /* restore old refdst */ + /* steal dst entry from skb_in, don't drop refcnt */ + skb_dst_reset(skb_in); + skb_dst_restore(skb_in, orefdst); } if (err) diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c index e3321932bec0..95f113dc37d8 100644 --- a/net/ipv4/ip_options.c +++ b/net/ipv4/ip_options.c @@ -615,14 +615,13 @@ int ip_options_rcv_srr(struct sk_buff *skb, struct net_device *dev) } memcpy(&nexthop, &optptr[srrptr-1], 4); - orefdst = skb->_skb_refdst; - skb_dst_set(skb, NULL); + orefdst = skb_dst_reset(skb); err = ip_route_input(skb, nexthop, iph->saddr, ip4h_dscp(iph), dev) ? -EINVAL : 0; rt2 = skb_rtable(skb); if (err || (rt2->rt_type != RTN_UNICAST && rt2->rt_type != RTN_LOCAL)) { skb_dst_drop(skb); - skb->_skb_refdst = orefdst; + skb_dst_restore(skb, orefdst); return -EINVAL; } refdst_drop(orefdst); -- 2.50.1