Skip to content

Commit f8ea4a1

Browse files
committed
Merge branch 'l3mdev-icmp-error-route-lookup-fixes'
Mathieu Desnoyers says: ==================== l3mdev icmp error route lookup fixes Here is a series of fixes for ipv4 and ipv6 which ensure the route lookup is performed on the right routing table in VRF configurations when sending TTL expired icmp errors (useful for traceroute). It includes tests for both ipv4 and ipv6. These fixes address specifically address the code paths involved in sending TTL expired icmp errors. As detailed in the individual commit messages, those fixes do not address similar icmp errors related to network namespaces and unreachable / fragmentation needed messages, which appear to use different code paths. ==================== Link: https://lore.kernel.org/r/20201012145016.2023-1-mathieu.desnoyers@efficios.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2 parents 1e40d75 + 1a01727 commit f8ea4a1

5 files changed

Lines changed: 653 additions & 6 deletions

File tree

net/ipv4/icmp.c

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,23 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
457457
local_bh_enable();
458458
}
459459

460+
/*
461+
* The device used for looking up which routing table to use for sending an ICMP
462+
* error is preferably the source whenever it is set, which should ensure the
463+
* icmp error can be sent to the source host, else lookup using the routing
464+
* table of the destination device, else use the main routing table (index 0).
465+
*/
466+
static struct net_device *icmp_get_route_lookup_dev(struct sk_buff *skb)
467+
{
468+
struct net_device *route_lookup_dev = NULL;
469+
470+
if (skb->dev)
471+
route_lookup_dev = skb->dev;
472+
else if (skb_dst(skb))
473+
route_lookup_dev = skb_dst(skb)->dev;
474+
return route_lookup_dev;
475+
}
476+
460477
static struct rtable *icmp_route_lookup(struct net *net,
461478
struct flowi4 *fl4,
462479
struct sk_buff *skb_in,
@@ -465,6 +482,7 @@ static struct rtable *icmp_route_lookup(struct net *net,
465482
int type, int code,
466483
struct icmp_bxm *param)
467484
{
485+
struct net_device *route_lookup_dev;
468486
struct rtable *rt, *rt2;
469487
struct flowi4 fl4_dec;
470488
int err;
@@ -479,7 +497,8 @@ static struct rtable *icmp_route_lookup(struct net *net,
479497
fl4->flowi4_proto = IPPROTO_ICMP;
480498
fl4->fl4_icmp_type = type;
481499
fl4->fl4_icmp_code = code;
482-
fl4->flowi4_oif = l3mdev_master_ifindex(skb_dst(skb_in)->dev);
500+
route_lookup_dev = icmp_get_route_lookup_dev(skb_in);
501+
fl4->flowi4_oif = l3mdev_master_ifindex(route_lookup_dev);
483502

484503
security_skb_classify_flow(skb_in, flowi4_to_flowi(fl4));
485504
rt = ip_route_output_key_hash(net, fl4, skb_in);
@@ -503,7 +522,7 @@ static struct rtable *icmp_route_lookup(struct net *net,
503522
if (err)
504523
goto relookup_failed;
505524

506-
if (inet_addr_type_dev_table(net, skb_dst(skb_in)->dev,
525+
if (inet_addr_type_dev_table(net, route_lookup_dev,
507526
fl4_dec.saddr) == RTN_LOCAL) {
508527
rt2 = __ip_route_output_key(net, &fl4_dec);
509528
if (IS_ERR(rt2))

net/ipv6/icmp.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -501,8 +501,11 @@ void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info,
501501
if (__ipv6_addr_needs_scope_id(addr_type)) {
502502
iif = icmp6_iif(skb);
503503
} else {
504-
dst = skb_dst(skb);
505-
iif = l3mdev_master_ifindex(dst ? dst->dev : skb->dev);
504+
/*
505+
* The source device is used for looking up which routing table
506+
* to use for sending an ICMP error.
507+
*/
508+
iif = l3mdev_master_ifindex(skb->dev);
506509
}
507510

508511
/*

net/ipv6/ip6_output.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -468,8 +468,6 @@ int ip6_forward(struct sk_buff *skb)
468468
* check and decrement ttl
469469
*/
470470
if (hdr->hop_limit <= 1) {
471-
/* Force OUTPUT device used as source address */
472-
skb->dev = dst->dev;
473471
icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, 0);
474472
__IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
475473

tools/testing/selftests/net/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ TEST_PROGS += txtimestamp.sh
1919
TEST_PROGS += vrf-xfrm-tests.sh
2020
TEST_PROGS += rxtimestamp.sh
2121
TEST_PROGS += devlink_port_split.py
22+
TEST_PROGS += vrf_route_leaking.sh
2223
TEST_PROGS_EXTENDED := in_netns.sh
2324
TEST_GEN_FILES = socket nettest
2425
TEST_GEN_FILES += psock_fanout psock_tpacket msg_zerocopy reuseport_addr_any

0 commit comments

Comments
 (0)