From f9e1cd6c99200846b324a8b65f7f31ded74013bd Mon Sep 17 00:00:00 2001 From: "Alexander V. Chernikov" Date: Fri, 19 Feb 2021 21:09:17 +0000 Subject: Fix arp/ndp deletion broken by 2fe5a79425c7. Changes in the 2fe5a79425c7 moved dst sockaddr masking from the routing control plane to the rtsock code. It broke arp/ndp deletion. It turns out, arp/ndp perform RTM_GET request first to get an interface index necessary for the deletion. Then they simply stamp the reply with RTF_LLDATA and set the command to RTM_DELETE. As a result, kernel receives request with non-empty RTA_NETMASK and clears RTA_DST host bits before passing the message to the lla code. De facto, the only needed bits are RTA_DST, RTA_GATEWAY and the subset of rtm_flags. With that in mind, fix the interace by clearing RTA_NETMASK for every messages with RTF_LLDATA. While here, cleanup arp/ndp code a bit. MFC after: 1 day Reviewed by: gnn Differential Revision: https://reviews.freebsd.org/D28804 --- sys/net/rtsock.c | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) (limited to 'sys') diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c index 3c1fea497af6..221661585bbf 100644 --- a/sys/net/rtsock.c +++ b/sys/net/rtsock.c @@ -1376,6 +1376,14 @@ cleanup_xaddrs_gateway(struct rt_addrinfo *info) return (0); } +static void +remove_netmask(struct rt_addrinfo *info) +{ + info->rti_info[RTAX_NETMASK] = NULL; + info->rti_flags |= RTF_HOST; + info->rti_addrs &= ~RTA_NETMASK; +} + #ifdef INET static int cleanup_xaddrs_inet(struct rt_addrinfo *info) @@ -1405,11 +1413,8 @@ cleanup_xaddrs_inet(struct rt_addrinfo *info) if (mask.s_addr != INADDR_BROADCAST) fill_sockaddr_inet(mask_sa, mask); - else { - info->rti_info[RTAX_NETMASK] = NULL; - info->rti_flags |= RTF_HOST; - info->rti_addrs &= ~RTA_NETMASK; - } + else + remove_netmask(info); /* Check gateway */ if (info->rti_info[RTAX_GATEWAY] != NULL) @@ -1445,11 +1450,8 @@ cleanup_xaddrs_inet6(struct rt_addrinfo *info) if (!IN6_ARE_ADDR_EQUAL(&mask, &in6mask128)) fill_sockaddr_inet6(mask_sa, &mask, 0); - else { - info->rti_info[RTAX_NETMASK] = NULL; - info->rti_flags |= RTF_HOST; - info->rti_addrs &= ~RTA_NETMASK; - } + else + remove_netmask(info); /* Check gateway */ if (info->rti_info[RTAX_GATEWAY] != NULL) @@ -1467,6 +1469,15 @@ cleanup_xaddrs(struct rt_addrinfo *info) if (info->rti_info[RTAX_DST] == NULL) return (EINVAL); + if (info->rti_flags & RTF_LLDATA) { + /* + * arp(8)/ndp(8) sends RTA_NETMASK for the associated + * prefix along with the actual address in RTA_DST. + * Remove netmask to avoid unnecessary address masking. + */ + remove_netmask(info); + } + switch (info->rti_info[RTAX_DST]->sa_family) { #ifdef INET case AF_INET: -- cgit v1.2.3