* [PATCH net-next v3 0/4] ipv4: restrict on-link fallback to lookup misses
@ 2026-11-12 23:59 liamsmith827
2026-11-12 23:59 ` [PATCH net-next v3 1/4] ipv4: add FIB_LOOKUP_REPORT_MISS liamsmith827
` (4 more replies)
0 siblings, 5 replies; 8+ messages in thread
From: liamsmith827 @ 2026-11-12 23:59 UTC (permalink / raw)
To: netdev
Cc: David Ahern, Ido Schimmel, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Shuah Khan,
linux-kselftest, linux-kernel, Liam Smith
From: Liam Smith <liamsmith827@proton.me>
When an output interface is specified (e.g., using SO_BINDTODEVICE,
IP_UNICAST_IF or IP_PKTINFO) and the FIB lookup fails, the IPv4 output
path ignores the error and constructs an on-link route via the
specified interface. According to the comment above the code, the
intent was to allow sending packets via an interface that does not have
any routes.
However, the error code is not checked, so the fallback is also taken
when the lookup hits an unreachable, blackhole or prohibit route/rule.
In other words, these routes and rules are ignored when an output
interface is specified [1].
This is a problem for Android, which implements its VPN "kill switch"
using prohibit rules, with the expectation that packets hitting such
rules are never transmitted. Unprivileged applications can bind a
socket to an interface and trivially bypass the VPN. This is especially
bad on cellular interfaces where neighbor resolution is not needed, so
packets can reach any destination and not only on-link ones.
Solve this by only taking the fallback when the lookup did not match
any route (i.e., a miss) and returning the error to the caller
otherwise [2].
It is currently impossible to distinguish between a miss and an
unreachable rule since they both return the same error (-ENETUNREACH).
Therefore, patch #1 adds a lookup flag that makes the lookup return a
different error upon a miss and patch #2 uses it to restrict the
fallback. Patch #3 adjusts the selftests and patch #4 updates the
comment above the fallback.
After the change, a packet that was previously transmitted on-link
despite hitting one of these routes/rules is no longer transmitted and
an error is returned to user space instead. It is unlikely that anyone
is relying on the current behavior:
1. It is a side effect of not checking the error code and it contradicts
ip-route(8) and ip-rule(8), which document these routes and rules as
dropping packets or generating an error.
2. These routes and rules are already honored when the output interface
is a VRF device or enslaved to one.
3. These rules are already honored by IPv6, which does not have such a
fallback.
The following is unchanged:
1. Packets can still be sent via the specified interface when the
lookup does not match any route, which is the original use case.
2. The fallback is still always taken for multicast packets. The
precedent in ip_route_output_key_hash_rcu() is to not enforce
restriction rule/routes on oif-bound multicast, so that precedent should
be followed here too.
[1]
# ip link add name dummy1 up type dummy
# ip address add 192.0.2.1/24 dev dummy1
# ip rule add to 198.51.100.1 prohibit
# ip route get 198.51.100.1
RTNETLINK answers: Permission denied
# ip route get 198.51.100.1 oif dummy1
198.51.100.1 dev dummy1 src 192.0.2.1 uid 0
cache
[2]
# ip route get 198.51.100.1 oif dummy1
RTNETLINK answers: Permission denied
v3:
- Remove comment on flag.
- Improve flag commit message.
- Improve cover letter.
- Target net-next instead of net, remove Fixes and stable Ccs.
- Change author to legal name.
v2: https://lore.kernel.org/netdev/20261110061536.10811-1-liamsmith827@grapheneos.org/
- Restrict the fallback to routing lookup misses, instead of only
honoring prohibit (-EACCES).
- Add FIB_LOOKUP_REPORT_MISS to differentiate a routing miss from an
unreachable rule.
- Split the comment update out into its own patch and remove the
signature.
- Enable all of the commented out device bind tests in
ipv4_ping_novrf(), add a route miss test and update the UDP test
expectations.
- Target net instead of net-next, add Fixes and Cc stable.
- Drop RFC.
v1: https://lore.kernel.org/netdev/20261019032406.88874-1-liamsmith827@grapheneos.org/
Liam Smith (4):
ipv4: add FIB_LOOKUP_REPORT_MISS
ipv4: restrict on-link fallback to lookup misses
selftests: net: test restricted on-link fallback
ipv4: replace obsolete routing comment
include/net/fib_rules.h | 1 +
include/net/ip_fib.h | 6 +--
net/ipv4/fib_rules.c | 2 +-
net/ipv4/route.c | 34 ++++++++--------
tools/testing/selftests/net/fcnal-test.sh | 47 +++++++++++++----------
5 files changed, 47 insertions(+), 43 deletions(-)
--
2.47.3
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH net-next v3 1/4] ipv4: add FIB_LOOKUP_REPORT_MISS
2026-11-12 23:59 [PATCH net-next v3 0/4] ipv4: restrict on-link fallback to lookup misses liamsmith827
@ 2026-11-12 23:59 ` liamsmith827
2026-11-12 23:59 ` [PATCH net-next v3 2/4] ipv4: restrict on-link fallback to lookup misses liamsmith827
` (3 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: liamsmith827 @ 2026-11-12 23:59 UTC (permalink / raw)
To: netdev
Cc: David Ahern, Ido Schimmel, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Shuah Khan,
linux-kselftest, linux-kernel, Liam Smith
From: Liam Smith <liamsmith827@proton.me>
Currently, fib_lookup() returns -ENETUNREACH for both a routing lookup
miss and an unreachable rule. These two cases must be distinguishable to
facilitate a fallback that only occurs when there's a miss.
Add a new FIB_LOOKUP flag that instructs lookups to return -ESRCH when
there's a miss.
Signed-off-by: Liam Smith <liamsmith827@proton.me>
---
include/net/fib_rules.h | 1 +
include/net/ip_fib.h | 6 +++---
net/ipv4/fib_rules.c | 2 +-
3 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h
index c6b94790fa81..df1cb39ddf92 100644
--- a/include/net/fib_rules.h
+++ b/include/net/fib_rules.h
@@ -59,6 +59,7 @@ struct fib_lookup_arg {
int flags;
#define FIB_LOOKUP_NOREF 1
#define FIB_LOOKUP_IGNORE_LINKSTATE 2
+#define FIB_LOOKUP_REPORT_MISS 4
};
struct fib_rules_ops {
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index 92f4eb8b86d7..d0b4f261585a 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -318,7 +318,7 @@ static inline int fib_lookup(struct net *net, const struct flowi4 *flp,
struct fib_result *res, unsigned int flags)
{
struct fib_table *tb;
- int err = -ENETUNREACH;
+ int err = -EAGAIN;
rcu_read_lock();
@@ -327,7 +327,7 @@ static inline int fib_lookup(struct net *net, const struct flowi4 *flp,
err = fib_table_lookup(tb, flp, res, flags | FIB_LOOKUP_NOREF);
if (err == -EAGAIN)
- err = -ENETUNREACH;
+ err = (flags & FIB_LOOKUP_REPORT_MISS) ? -ESRCH : -ENETUNREACH;
rcu_read_unlock();
@@ -398,7 +398,7 @@ static inline int fib_lookup(struct net *net, struct flowi4 *flp,
err = fib_table_lookup(tb, flp, res, flags);
if (err == -EAGAIN)
- err = -ENETUNREACH;
+ err = (flags & FIB_LOOKUP_REPORT_MISS) ? -ESRCH : -ENETUNREACH;
out:
rcu_read_unlock();
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index 060501b376a8..3d7dcb8d0865 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -101,7 +101,7 @@ int __fib_lookup(struct net *net, struct flowi4 *flp,
res->tclassid = 0;
#endif
- if (err == -ESRCH)
+ if (err == -ESRCH && !(flags & FIB_LOOKUP_REPORT_MISS))
err = -ENETUNREACH;
return err;
--
2.47.3
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH net-next v3 2/4] ipv4: restrict on-link fallback to lookup misses
2026-11-12 23:59 [PATCH net-next v3 0/4] ipv4: restrict on-link fallback to lookup misses liamsmith827
2026-11-12 23:59 ` [PATCH net-next v3 1/4] ipv4: add FIB_LOOKUP_REPORT_MISS liamsmith827
@ 2026-11-12 23:59 ` liamsmith827
2026-11-12 23:59 ` [PATCH net-next v3 3/4] selftests: net: test restricted on-link fallback liamsmith827
` (2 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: liamsmith827 @ 2026-11-12 23:59 UTC (permalink / raw)
To: netdev
Cc: David Ahern, Ido Schimmel, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Shuah Khan,
linux-kselftest, linux-kernel, Liam Smith
From: Liam Smith <liamsmith827@proton.me>
For non-vrf unicast, the on-link fallback currently occurs regardless of
the particular error returned by fib_lookup(). As a result, routes and
rules that are supposed to restrict traffic (blackhole, prohibit,
unreachable) are unable to do so comprehensively.
A specific example of this being a problem is within Android, where the
VPN "kill switch" is implemented with prohibit rules. Any process that
can set flowi4_oif (SO_BINDTODEVICE, IP_UNICAST_IF, IP_PKTINFO, etc.) is
able to utilize this fallback, meaning unprivileged Android apps can
trivially bypass the VPN. This is particularly bad on cellular networks,
where ARP is often not needed.
Restrict the fallback to routing lookup misses.
This was originally observed on an Android device, by way of packet
capture.
Tested fcnal-test.sh in UML with CONFIG_IP_MULTIPLE_TABLES both enabled
and disabled.
Signed-off-by: Liam Smith <liamsmith827@proton.me>
---
net/ipv4/route.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 595a3b7f1783..03db105303b4 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -2849,12 +2849,13 @@ struct rtable *ip_route_output_key_hash_rcu(struct net *net, struct flowi4 *fl4,
goto make_route;
}
- err = fib_lookup(net, fl4, res, 0);
+ err = fib_lookup(net, fl4, res, FIB_LOOKUP_REPORT_MISS);
if (err) {
res->fi = NULL;
res->table = NULL;
if (fl4->flowi4_oif &&
- (ipv4_is_multicast(fl4->daddr) || !fl4->flowi4_l3mdev)) {
+ (ipv4_is_multicast(fl4->daddr) ||
+ (!fl4->flowi4_l3mdev && err == -ESRCH))) {
/* Apparently, routing tables are wrong. Assume,
* that the destination is on link.
*
@@ -2879,6 +2880,8 @@ struct rtable *ip_route_output_key_hash_rcu(struct net *net, struct flowi4 *fl4,
res->type = RTN_UNICAST;
goto make_route;
}
+ /* Reverse the mapping induced by FIB_LOOKUP_REPORT_MISS. */
+ err = err == -ESRCH ? -ENETUNREACH : err;
rth = ERR_PTR(err);
goto out;
}
--
2.47.3
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH net-next v3 3/4] selftests: net: test restricted on-link fallback
2026-11-12 23:59 [PATCH net-next v3 0/4] ipv4: restrict on-link fallback to lookup misses liamsmith827
2026-11-12 23:59 ` [PATCH net-next v3 1/4] ipv4: add FIB_LOOKUP_REPORT_MISS liamsmith827
2026-11-12 23:59 ` [PATCH net-next v3 2/4] ipv4: restrict on-link fallback to lookup misses liamsmith827
@ 2026-11-12 23:59 ` liamsmith827
2026-11-15 8:30 ` Ido Schimmel
2026-11-12 23:59 ` [PATCH net-next v3 4/4] ipv4: replace obsolete routing comment liamsmith827
2026-11-15 8:30 ` [PATCH net-next v3 0/4] ipv4: restrict on-link fallback to lookup misses Ido Schimmel
4 siblings, 1 reply; 8+ messages in thread
From: liamsmith827 @ 2026-11-12 23:59 UTC (permalink / raw)
To: netdev
Cc: David Ahern, Ido Schimmel, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Shuah Khan,
linux-kselftest, linux-kernel, Liam Smith
From: Liam Smith <liamsmith827@proton.me>
Update tests now that the on-link fallback has been restricted to
routing lookup misses for non-vrf unicast.
Signed-off-by: Liam Smith <liamsmith827@proton.me>
---
tools/testing/selftests/net/fcnal-test.sh | 47 +++++++++++++----------
1 file changed, 26 insertions(+), 21 deletions(-)
diff --git a/tools/testing/selftests/net/fcnal-test.sh b/tools/testing/selftests/net/fcnal-test.sh
index a50609535fed..c048d5be139d 100755
--- a/tools/testing/selftests/net/fcnal-test.sh
+++ b/tools/testing/selftests/net/fcnal-test.sh
@@ -619,17 +619,29 @@ ipv4_ping_novrf()
run_cmd ping -c1 -w1 -I ${NSA_DEV} ${a}
log_test_addr ${a} $? 0 "ping local, device bind"
- # loopback addresses not reachable from device bind
- # fails in a really weird way though because ipv4 special cases
- # route lookups with oif set.
+ # loopback addresses not reachable from device bind, unreachable default route
for a in ${NSA_LO_IP} 127.0.0.1
do
log_start
show_hint "Fails since address on loopback device is out of device scope"
run_cmd ping -c1 -w1 -I ${NSA_DEV} ${a}
- log_test_addr ${a} $? 1 "ping local, device bind"
+ log_test_addr ${a} $? 2 "ping local, device bind, unreachable default route"
done
+ # loopback addresses not reachable from device bind, route miss
+ log_start
+ setup_cmd ip route del unreachable default metric 8192
+
+ for a in ${NSA_LO_IP} 127.0.0.1
+ do
+ log_start
+ show_hint "Fails since address on loopback device is out of device scope"
+ run_cmd ping -c1 -w1 -I ${NSA_DEV} ${a}
+ log_test_addr ${a} $? 1 "ping local, device bind, route miss"
+ done
+
+ setup_cmd ip route add unreachable default metric 8192
+
#
# ip rule blocks reachability to remote address
#
@@ -643,10 +655,9 @@ ipv4_ping_novrf()
run_cmd ping -c1 -w1 ${a}
log_test_addr ${a} $? 2 "ping out, blocked by rule"
- # NOTE: ipv4 actually allows the lookup to fail and yet still create
- # a viable rtable if the oif (e.g., bind to device) is set, so this
- # case succeeds despite the rule
- # run_cmd ping -c1 -w1 -I ${NSA_DEV} ${a}
+ log_start
+ run_cmd ping -c1 -w1 -I ${NSA_DEV} ${a}
+ log_test_addr ${a} $? 2 "ping out, device bind, blocked by rule"
a=${NSA_LO_IP}
log_start
@@ -671,10 +682,9 @@ ipv4_ping_novrf()
run_cmd ping -c1 -w1 ${a}
log_test_addr ${a} $? 2 "ping out, blocked by route"
- # NOTE: ipv4 actually allows the lookup to fail and yet still create
- # a viable rtable if the oif (e.g., bind to device) is set, so this
- # case succeeds despite not having a route for the address
- # run_cmd ping -c1 -w1 -I ${NSA_DEV} ${a}
+ log_start
+ run_cmd ping -c1 -w1 -I ${NSA_DEV} ${a}
+ log_test_addr ${a} $? 2 "ping out, device bind, blocked by route"
a=${NSA_LO_IP}
log_start
@@ -692,10 +702,9 @@ ipv4_ping_novrf()
run_cmd ping -c1 -w1 ${a}
log_test_addr ${a} $? 2 "ping out, unreachable default route"
- # NOTE: ipv4 actually allows the lookup to fail and yet still create
- # a viable rtable if the oif (e.g., bind to device) is set, so this
- # case succeeds despite not having a route for the address
- # run_cmd ping -c1 -w1 -I ${NSA_DEV} ${a}
+ log_start
+ run_cmd ping -c1 -w1 -I ${NSA_DEV} ${a}
+ log_test_addr ${a} $? 2 "ping out, device bind, unreachable default route"
}
ipv4_ping_vrf()
@@ -1602,10 +1611,6 @@ ipv4_udp_novrf()
run_cmd nettest -D -d ${NSA_DEV} -S -r ${a} -U
log_test_addr ${a} $? 0 "Global server, device client via IP_UNICAST_IF, local connection, with connect()"
-
- # IPv4 with device bind has really weird behavior - it overrides the
- # fib lookup, generates an rtable and tries to send the packet. This
- # causes failures for local traffic at different places
for a in ${NSA_LO_IP} 127.0.0.1
do
log_start
@@ -1613,7 +1618,7 @@ ipv4_udp_novrf()
run_cmd nettest -D -s &
wait_local_port_listen ${NSA} 12345 udp
run_cmd nettest -D -r ${a} -d ${NSA_DEV}
- log_test_addr ${a} $? 2 "Global server, device client, local connection"
+ log_test_addr ${a} $? 1 "Global server, device client, local connection"
log_start
show_hint "Should fail since addresses on loopback are out of device scope"
--
2.47.3
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH net-next v3 4/4] ipv4: replace obsolete routing comment
2026-11-12 23:59 [PATCH net-next v3 0/4] ipv4: restrict on-link fallback to lookup misses liamsmith827
` (2 preceding siblings ...)
2026-11-12 23:59 ` [PATCH net-next v3 3/4] selftests: net: test restricted on-link fallback liamsmith827
@ 2026-11-12 23:59 ` liamsmith827
2026-11-15 8:31 ` Ido Schimmel
2026-11-15 8:30 ` [PATCH net-next v3 0/4] ipv4: restrict on-link fallback to lookup misses Ido Schimmel
4 siblings, 1 reply; 8+ messages in thread
From: liamsmith827 @ 2026-11-12 23:59 UTC (permalink / raw)
To: netdev
Cc: David Ahern, Ido Schimmel, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Shuah Khan,
linux-kselftest, linux-kernel, Liam Smith
From: Liam Smith <liamsmith827@proton.me>
Replace an existing comment which describes obsolete fib_lookup(),
MSG_DONTROUTE and IPv6 behavior.
Signed-off-by: Liam Smith <liamsmith827@proton.me>
---
net/ipv4/route.c | 27 +++++++++++----------------
1 file changed, 11 insertions(+), 16 deletions(-)
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 03db105303b4..d862b5ecad71 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -2856,24 +2856,19 @@ struct rtable *ip_route_output_key_hash_rcu(struct net *net, struct flowi4 *fl4,
if (fl4->flowi4_oif &&
(ipv4_is_multicast(fl4->daddr) ||
(!fl4->flowi4_l3mdev && err == -ESRCH))) {
- /* Apparently, routing tables are wrong. Assume,
- * that the destination is on link.
+ /* When oif is specified, fib_lookup() is called
+ * primarily to determine if the destination is
+ * accessible directly or through a gateway. It also
+ * checks whether there are any traffic restrictions
+ * (blackhole, prohibit, unreachable), or if there's a
+ * routing lookup miss.
*
- * WHY? DW.
- * Because we are allowed to send to iface
- * even if it has NO routes and NO assigned
- * addresses. When oif is specified, routing
- * tables are looked up with only one purpose:
- * to catch if destination is gatewayed, rather than
- * direct. Moreover, if MSG_DONTROUTE is set,
- * we send packet, ignoring both routing tables
- * and ifaddr state. --ANK
- *
- *
- * We could make it even if oif is unknown,
- * likely IPv6, but we do not.
+ * This fallback path is always taken for multicast,
+ * regardless of any restrictions or misses. Non-vrf
+ * unicast does honor restrictions, but falls back if
+ * there's a miss. The destination is assumed on-link
+ * for both.
*/
-
if (fl4->saddr == 0)
fl4->saddr = inet_select_addr(dev_out, 0,
RT_SCOPE_LINK);
--
2.47.3
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH net-next v3 0/4] ipv4: restrict on-link fallback to lookup misses
2026-11-12 23:59 [PATCH net-next v3 0/4] ipv4: restrict on-link fallback to lookup misses liamsmith827
` (3 preceding siblings ...)
2026-11-12 23:59 ` [PATCH net-next v3 4/4] ipv4: replace obsolete routing comment liamsmith827
@ 2026-11-15 8:30 ` Ido Schimmel
4 siblings, 0 replies; 8+ messages in thread
From: Ido Schimmel @ 2026-11-15 8:30 UTC (permalink / raw)
To: liamsmith827
Cc: netdev, David Ahern, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Shuah Khan,
linux-kselftest, linux-kernel, Liam Smith
On Thu, Nov 12, 2026 at 11:59:28PM +0000, liamsmith827 wrote:
> The following is unchanged:
>
> 1. Packets can still be sent via the specified interface when the
> lookup does not match any route, which is the original use case.
>
> 2. The fallback is still always taken for multicast packets. The
> precedent in ip_route_output_key_hash_rcu() is to not enforce
> restriction rule/routes on oif-bound multicast, so that precedent should
> be followed here too.
Please also mention that omitting the fallback for multicast packets
will break multicast traffic in a VRF, which hits the default
unreachable route by design.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH net-next v3 3/4] selftests: net: test restricted on-link fallback
2026-11-12 23:59 ` [PATCH net-next v3 3/4] selftests: net: test restricted on-link fallback liamsmith827
@ 2026-11-15 8:30 ` Ido Schimmel
0 siblings, 0 replies; 8+ messages in thread
From: Ido Schimmel @ 2026-11-15 8:30 UTC (permalink / raw)
To: liamsmith827
Cc: netdev, David Ahern, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Shuah Khan,
linux-kselftest, linux-kernel, Liam Smith
On Thu, Nov 12, 2026 at 11:59:31PM +0000, liamsmith827 wrote:
> From: Liam Smith <liamsmith827@proton.me>
>
> Update tests now that the on-link fallback has been restricted to
> routing lookup misses for non-vrf unicast.
The commit message is too terse. Which "tests"? Are they aligned with
IPv6 now? Try:
"
Following the previous patch, the on-link fallback is no longer taken
when the FIB lookup hits an unreachable, blackhole or prohibit route /
rule. Adjust the IPv4 tests accordingly:
1. ipv4_ping_novrf(): Pinging a loopback address while bound to a
device now fails with an error instead of timing out, since the lookup
hits the unreachable default route. Adjust the expected return code.
2. ipv4_ping_novrf(): Add a variant of the above without the
unreachable default route, to make sure that the fallback is still
taken upon a route miss.
3. ipv4_ping_novrf(): Enable the device bind test cases that were
commented out because of the fallback (prohibit rule, unreachable route
and unreachable default route).
4. ipv4_udp_novrf(): Connecting to a loopback address while bound to a
device now fails with an error instead of timing out. Adjust the
expected return code.
With the exception of the route miss test case, which is specific to
IPv4, the IPv4 test cases are now aligned with their IPv6 counterparts.
"
>
> Signed-off-by: Liam Smith <liamsmith827@proton.me>
> ---
> tools/testing/selftests/net/fcnal-test.sh | 47 +++++++++++++----------
> 1 file changed, 26 insertions(+), 21 deletions(-)
>
> diff --git a/tools/testing/selftests/net/fcnal-test.sh b/tools/testing/selftests/net/fcnal-test.sh
> index a50609535fed..c048d5be139d 100755
> --- a/tools/testing/selftests/net/fcnal-test.sh
> +++ b/tools/testing/selftests/net/fcnal-test.sh
> @@ -619,17 +619,29 @@ ipv4_ping_novrf()
> run_cmd ping -c1 -w1 -I ${NSA_DEV} ${a}
> log_test_addr ${a} $? 0 "ping local, device bind"
>
> - # loopback addresses not reachable from device bind
> - # fails in a really weird way though because ipv4 special cases
> - # route lookups with oif set.
> + # loopback addresses not reachable from device bind, unreachable default route
Avoid going over 80 chars when easily avoided.
> for a in ${NSA_LO_IP} 127.0.0.1
> do
> log_start
> show_hint "Fails since address on loopback device is out of device scope"
> run_cmd ping -c1 -w1 -I ${NSA_DEV} ${a}
> - log_test_addr ${a} $? 1 "ping local, device bind"
> + log_test_addr ${a} $? 2 "ping local, device bind, unreachable default route"
> done
>
> + # loopback addresses not reachable from device bind, route miss
> + log_start
> + setup_cmd ip route del unreachable default metric 8192
> +
> + for a in ${NSA_LO_IP} 127.0.0.1
> + do
> + log_start
> + show_hint "Fails since address on loopback device is out of device scope"
> + run_cmd ping -c1 -w1 -I ${NSA_DEV} ${a}
> + log_test_addr ${a} $? 1 "ping local, device bind, route miss"
> + done
Add an unreachable rule here and test that ping exits with 2. This
verifies that the new FIB_LOOKUP_REPORT_MISS flag works as intended.
Adjust the commit message accordingly.
> +
> + setup_cmd ip route add unreachable default metric 8192
> +
> #
> # ip rule blocks reachability to remote address
> #
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH net-next v3 4/4] ipv4: replace obsolete routing comment
2026-11-12 23:59 ` [PATCH net-next v3 4/4] ipv4: replace obsolete routing comment liamsmith827
@ 2026-11-15 8:31 ` Ido Schimmel
0 siblings, 0 replies; 8+ messages in thread
From: Ido Schimmel @ 2026-11-15 8:31 UTC (permalink / raw)
To: liamsmith827
Cc: netdev, David Ahern, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Shuah Khan,
linux-kselftest, linux-kernel, Liam Smith
On Thu, Nov 12, 2026 at 11:59:32PM +0000, liamsmith827 wrote:
> From: Liam Smith <liamsmith827@proton.me>
>
> Replace an existing comment which describes obsolete fib_lookup(),
> MSG_DONTROUTE and IPv6 behavior.
>
> Signed-off-by: Liam Smith <liamsmith827@proton.me>
> ---
> net/ipv4/route.c | 27 +++++++++++----------------
> 1 file changed, 11 insertions(+), 16 deletions(-)
>
> diff --git a/net/ipv4/route.c b/net/ipv4/route.c
> index 03db105303b4..d862b5ecad71 100644
> --- a/net/ipv4/route.c
> +++ b/net/ipv4/route.c
> @@ -2856,24 +2856,19 @@ struct rtable *ip_route_output_key_hash_rcu(struct net *net, struct flowi4 *fl4,
> if (fl4->flowi4_oif &&
> (ipv4_is_multicast(fl4->daddr) ||
> (!fl4->flowi4_l3mdev && err == -ESRCH))) {
> - /* Apparently, routing tables are wrong. Assume,
> - * that the destination is on link.
> + /* When oif is specified, fib_lookup() is called
> + * primarily to determine if the destination is
> + * accessible directly or through a gateway. It also
> + * checks whether there are any traffic restrictions
> + * (blackhole, prohibit, unreachable), or if there's a
> + * routing lookup miss.
> *
> - * WHY? DW.
> - * Because we are allowed to send to iface
> - * even if it has NO routes and NO assigned
> - * addresses. When oif is specified, routing
The new comment should include the motivation for the fallback.
Something like [1].
> - * tables are looked up with only one purpose:
> - * to catch if destination is gatewayed, rather than
> - * direct. Moreover, if MSG_DONTROUTE is set,
> - * we send packet, ignoring both routing tables
> - * and ifaddr state. --ANK
> - *
> - *
> - * We could make it even if oif is unknown,
> - * likely IPv6, but we do not.
> + * This fallback path is always taken for multicast,
> + * regardless of any restrictions or misses. Non-vrf
> + * unicast does honor restrictions, but falls back if
> + * there's a miss. The destination is assumed on-link
> + * for both.
> */
> -
> if (fl4->saddr == 0)
> fl4->saddr = inet_select_addr(dev_out, 0,
> RT_SCOPE_LINK);
[1]
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 18cb8bfc5bfc..0b5f6e9cc437 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -2859,24 +2859,18 @@ struct rtable *ip_route_output_key_hash_rcu(struct net *net, struct flowi4 *fl4,
if (fl4->flowi4_oif &&
(ipv4_is_multicast(fl4->daddr) ||
(!fl4->flowi4_l3mdev && err == -ESRCH))) {
- /* Apparently, routing tables are wrong. Assume,
- * that the destination is on link.
+ /* We are allowed to send packets via the specified
+ * interface even if it does not have any routes.
+ * Upon a lookup miss, assume that the destination is
+ * on-link, unless the interface is a VRF device or
+ * enslaved to one.
*
- * WHY? DW.
- * Because we are allowed to send to iface
- * even if it has NO routes and NO assigned
- * addresses. When oif is specified, routing
- * tables are looked up with only one purpose:
- * to catch if destination is gatewayed, rather than
- * direct. Moreover, if MSG_DONTROUTE is set,
- * we send packet, ignoring both routing tables
- * and ifaddr state. --ANK
- *
- *
- * We could make it even if oif is unknown,
- * likely IPv6, but we do not.
+ * Unreachable, blackhole and prohibit routes / rules
+ * are honored, but not for multicast packets.
+ * Multicast in a VRF relies on this fallback since
+ * the lookup hits the unreachable default route in
+ * the VRF table.
*/
-
if (fl4->saddr == 0)
fl4->saddr = inet_select_addr(dev_out, 0,
RT_SCOPE_LINK);
^ permalink raw reply related [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-11-15 8:33 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-12 23:59 [PATCH net-next v3 0/4] ipv4: restrict on-link fallback to lookup misses liamsmith827
2026-11-12 23:59 ` [PATCH net-next v3 1/4] ipv4: add FIB_LOOKUP_REPORT_MISS liamsmith827
2026-11-12 23:59 ` [PATCH net-next v3 2/4] ipv4: restrict on-link fallback to lookup misses liamsmith827
2026-11-12 23:59 ` [PATCH net-next v3 3/4] selftests: net: test restricted on-link fallback liamsmith827
2026-11-15 8:30 ` Ido Schimmel
2026-11-12 23:59 ` [PATCH net-next v3 4/4] ipv4: replace obsolete routing comment liamsmith827
2026-11-15 8:31 ` Ido Schimmel
2026-11-15 8:30 ` [PATCH net-next v3 0/4] ipv4: restrict on-link fallback to lookup misses Ido Schimmel
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox