Commit dd357348 authored by David S. Miller's avatar David S. Miller

Merge branch 'ipv4-invalidate-broadcast-neigh-upon-address-addition'

Ido Schimmel says:

====================
ipv4: Invalidate neighbour for broadcast address upon address addition

Patch #1 solves a recently reported issue [1]. See detailed description
in the changelog.

Patch #2 adds a matching test case.

Targeting at net-next since as far as I can tell this use case never
worked.

There are no regressions in fib_tests.sh with this change:

 # ./fib_tests.sh
 ...
 Tests passed: 186
 Tests failed:   0

[1] https://lore.kernel.org/netdev/55a04a8f-56f3-f73c-2aea-2195923f09d1@huawei.com/
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 0f6938eb 25bd462f
...@@ -65,6 +65,7 @@ void arp_send(int type, int ptype, __be32 dest_ip, ...@@ -65,6 +65,7 @@ void arp_send(int type, int ptype, __be32 dest_ip,
const unsigned char *src_hw, const unsigned char *th); const unsigned char *src_hw, const unsigned char *th);
int arp_mc_map(__be32 addr, u8 *haddr, struct net_device *dev, int dir); int arp_mc_map(__be32 addr, u8 *haddr, struct net_device *dev, int dir);
void arp_ifdown(struct net_device *dev); void arp_ifdown(struct net_device *dev);
int arp_invalidate(struct net_device *dev, __be32 ip, bool force);
struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip, struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip,
struct net_device *dev, __be32 src_ip, struct net_device *dev, __be32 src_ip,
......
...@@ -1116,13 +1116,18 @@ static int arp_req_get(struct arpreq *r, struct net_device *dev) ...@@ -1116,13 +1116,18 @@ static int arp_req_get(struct arpreq *r, struct net_device *dev)
return err; return err;
} }
static int arp_invalidate(struct net_device *dev, __be32 ip) int arp_invalidate(struct net_device *dev, __be32 ip, bool force)
{ {
struct neighbour *neigh = neigh_lookup(&arp_tbl, &ip, dev); struct neighbour *neigh = neigh_lookup(&arp_tbl, &ip, dev);
int err = -ENXIO; int err = -ENXIO;
struct neigh_table *tbl = &arp_tbl; struct neigh_table *tbl = &arp_tbl;
if (neigh) { if (neigh) {
if ((neigh->nud_state & NUD_VALID) && !force) {
neigh_release(neigh);
return 0;
}
if (neigh->nud_state & ~NUD_NOARP) if (neigh->nud_state & ~NUD_NOARP)
err = neigh_update(neigh, NULL, NUD_FAILED, err = neigh_update(neigh, NULL, NUD_FAILED,
NEIGH_UPDATE_F_OVERRIDE| NEIGH_UPDATE_F_OVERRIDE|
...@@ -1169,7 +1174,7 @@ static int arp_req_delete(struct net *net, struct arpreq *r, ...@@ -1169,7 +1174,7 @@ static int arp_req_delete(struct net *net, struct arpreq *r,
if (!dev) if (!dev)
return -EINVAL; return -EINVAL;
} }
return arp_invalidate(dev, ip); return arp_invalidate(dev, ip, true);
} }
/* /*
......
...@@ -1124,9 +1124,11 @@ void fib_add_ifaddr(struct in_ifaddr *ifa) ...@@ -1124,9 +1124,11 @@ void fib_add_ifaddr(struct in_ifaddr *ifa)
return; return;
/* Add broadcast address, if it is explicitly assigned. */ /* Add broadcast address, if it is explicitly assigned. */
if (ifa->ifa_broadcast && ifa->ifa_broadcast != htonl(0xFFFFFFFF)) if (ifa->ifa_broadcast && ifa->ifa_broadcast != htonl(0xFFFFFFFF)) {
fib_magic(RTM_NEWROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32, fib_magic(RTM_NEWROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32,
prim, 0); prim, 0);
arp_invalidate(dev, ifa->ifa_broadcast, false);
}
if (!ipv4_is_zeronet(prefix) && !(ifa->ifa_flags & IFA_F_SECONDARY) && if (!ipv4_is_zeronet(prefix) && !(ifa->ifa_flags & IFA_F_SECONDARY) &&
(prefix != addr || ifa->ifa_prefixlen < 32)) { (prefix != addr || ifa->ifa_prefixlen < 32)) {
...@@ -1140,6 +1142,7 @@ void fib_add_ifaddr(struct in_ifaddr *ifa) ...@@ -1140,6 +1142,7 @@ void fib_add_ifaddr(struct in_ifaddr *ifa)
if (ifa->ifa_prefixlen < 31) { if (ifa->ifa_prefixlen < 31) {
fib_magic(RTM_NEWROUTE, RTN_BROADCAST, prefix | ~mask, fib_magic(RTM_NEWROUTE, RTN_BROADCAST, prefix | ~mask,
32, prim, 0); 32, prim, 0);
arp_invalidate(dev, prefix | ~mask, false);
} }
} }
} }
......
...@@ -9,7 +9,7 @@ ret=0 ...@@ -9,7 +9,7 @@ ret=0
ksft_skip=4 ksft_skip=4
# all tests in this script. Can be overridden with -t option # all tests in this script. Can be overridden with -t option
TESTS="unregister down carrier nexthop suppress ipv6_rt ipv4_rt ipv6_addr_metric ipv4_addr_metric ipv6_route_metrics ipv4_route_metrics ipv4_route_v6_gw rp_filter ipv4_del_addr ipv4_mangle ipv6_mangle" TESTS="unregister down carrier nexthop suppress ipv6_rt ipv4_rt ipv6_addr_metric ipv4_addr_metric ipv6_route_metrics ipv4_route_metrics ipv4_route_v6_gw rp_filter ipv4_del_addr ipv4_mangle ipv6_mangle ipv4_bcast_neigh"
VERBOSE=0 VERBOSE=0
PAUSE_ON_FAIL=no PAUSE_ON_FAIL=no
...@@ -1954,6 +1954,61 @@ ipv6_mangle_test() ...@@ -1954,6 +1954,61 @@ ipv6_mangle_test()
route_cleanup route_cleanup
} }
ip_neigh_get_check()
{
ip neigh help 2>&1 | grep -q 'ip neigh get'
if [ $? -ne 0 ]; then
echo "iproute2 command does not support neigh get. Skipping test"
return 1
fi
return 0
}
ipv4_bcast_neigh_test()
{
local rc
echo
echo "IPv4 broadcast neighbour tests"
ip_neigh_get_check || return 1
setup
set -e
run_cmd "$IP neigh add 192.0.2.111 lladdr 00:11:22:33:44:55 nud perm dev dummy0"
run_cmd "$IP neigh add 192.0.2.255 lladdr 00:11:22:33:44:55 nud perm dev dummy0"
run_cmd "$IP neigh get 192.0.2.111 dev dummy0"
run_cmd "$IP neigh get 192.0.2.255 dev dummy0"
run_cmd "$IP address add 192.0.2.1/24 broadcast 192.0.2.111 dev dummy0"
run_cmd "$IP neigh add 203.0.113.111 nud failed dev dummy0"
run_cmd "$IP neigh add 203.0.113.255 nud failed dev dummy0"
run_cmd "$IP neigh get 203.0.113.111 dev dummy0"
run_cmd "$IP neigh get 203.0.113.255 dev dummy0"
run_cmd "$IP address add 203.0.113.1/24 broadcast 203.0.113.111 dev dummy0"
set +e
run_cmd "$IP neigh get 192.0.2.111 dev dummy0"
log_test $? 0 "Resolved neighbour for broadcast address"
run_cmd "$IP neigh get 192.0.2.255 dev dummy0"
log_test $? 0 "Resolved neighbour for network broadcast address"
run_cmd "$IP neigh get 203.0.113.111 dev dummy0"
log_test $? 2 "Unresolved neighbour for broadcast address"
run_cmd "$IP neigh get 203.0.113.255 dev dummy0"
log_test $? 2 "Unresolved neighbour for network broadcast address"
cleanup
}
################################################################################ ################################################################################
# usage # usage
...@@ -2028,6 +2083,7 @@ do ...@@ -2028,6 +2083,7 @@ do
ipv4_route_v6_gw) ipv4_route_v6_gw_test;; ipv4_route_v6_gw) ipv4_route_v6_gw_test;;
ipv4_mangle) ipv4_mangle_test;; ipv4_mangle) ipv4_mangle_test;;
ipv6_mangle) ipv6_mangle_test;; ipv6_mangle) ipv6_mangle_test;;
ipv4_bcast_neigh) ipv4_bcast_neigh_test;;
help) echo "Test names: $TESTS"; exit 0;; help) echo "Test names: $TESTS"; exit 0;;
esac esac
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment