| From 52752b65dc62ae78762eef153bd911f9a068440c Mon Sep 17 00:00:00 2001 |
| From: Paolo Abeni <pabeni@redhat.com> |
| Date: Sat, 26 Oct 2019 11:53:39 +0200 |
| Subject: [PATCH] ipv4: fix route update on metric change. |
| |
| commit 0b834ba00ab5337e938c727e216e1f5249794717 upstream. |
| |
| Since commit af4d768ad28c ("net/ipv4: Add support for specifying metric |
| of connected routes"), when updating an IP address with a different metric, |
| the associated connected route is updated, too. |
| |
| Still, the mentioned commit doesn't handle properly some corner cases: |
| |
| $ ip addr add dev eth0 192.168.1.0/24 |
| $ ip addr add dev eth0 192.168.2.1/32 peer 192.168.2.2 |
| $ ip addr add dev eth0 192.168.3.1/24 |
| $ ip addr change dev eth0 192.168.1.0/24 metric 10 |
| $ ip addr change dev eth0 192.168.2.1/32 peer 192.168.2.2 metric 10 |
| $ ip addr change dev eth0 192.168.3.1/24 metric 10 |
| $ ip -4 route |
| 192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.0 |
| 192.168.2.2 dev eth0 proto kernel scope link src 192.168.2.1 |
| 192.168.3.0/24 dev eth0 proto kernel scope link src 192.168.2.1 metric 10 |
| |
| Only the last route is correctly updated. |
| |
| The problem is the current test in fib_modify_prefix_metric(): |
| |
| if (!(dev->flags & IFF_UP) || |
| ifa->ifa_flags & (IFA_F_SECONDARY | IFA_F_NOPREFIXROUTE) || |
| ipv4_is_zeronet(prefix) || |
| prefix == ifa->ifa_local || ifa->ifa_prefixlen == 32) |
| |
| Which should be the logical 'not' of the pre-existing test in |
| fib_add_ifaddr(): |
| |
| if (!ipv4_is_zeronet(prefix) && !(ifa->ifa_flags & IFA_F_SECONDARY) && |
| (prefix != addr || ifa->ifa_prefixlen < 32)) |
| |
| To properly negate the original expression, we need to change the last |
| logical 'or' to a logical 'and'. |
| |
| Fixes: af4d768ad28c ("net/ipv4: Add support for specifying metric of connected routes") |
| Reported-and-suggested-by: Beniamino Galvani <bgalvani@redhat.com> |
| Signed-off-by: Paolo Abeni <pabeni@redhat.com> |
| Reviewed-by: David Ahern <dsahern@gmail.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c |
| index e54c2bcbb465..48137d37695e 100644 |
| --- a/net/ipv4/fib_frontend.c |
| +++ b/net/ipv4/fib_frontend.c |
| @@ -1105,7 +1105,7 @@ void fib_modify_prefix_metric(struct in_ifaddr *ifa, u32 new_metric) |
| if (!(dev->flags & IFF_UP) || |
| ifa->ifa_flags & (IFA_F_SECONDARY | IFA_F_NOPREFIXROUTE) || |
| ipv4_is_zeronet(prefix) || |
| - prefix == ifa->ifa_local || ifa->ifa_prefixlen == 32) |
| + (prefix == ifa->ifa_local && ifa->ifa_prefixlen == 32)) |
| return; |
| |
| /* add the new */ |
| -- |
| 2.7.4 |
| |