diff options
author | Alexander V. Chernikov <melifaro@FreeBSD.org> | 2021-02-19 21:09:17 +0000 |
---|---|---|
committer | Alexander V. Chernikov <melifaro@FreeBSD.org> | 2021-02-19 21:17:17 +0000 |
commit | f9e1cd6c99200846b324a8b65f7f31ded74013bd (patch) | |
tree | e1de91c2b590f2e9c4a7b0a6bceda69a8d23240e | |
parent | a78bb831a17f9ba4b3d833ae6a9c2ce4f5cb5d1e (diff) | |
download | src-f9e1cd6c99200846b324a8b65f7f31ded74013bd.tar.gz src-f9e1cd6c99200846b324a8b65f7f31ded74013bd.zip |
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
-rw-r--r-- | sys/net/rtsock.c | 31 | ||||
-rw-r--r-- | usr.sbin/arp/arp.c | 9 | ||||
-rw-r--r-- | usr.sbin/ndp/ndp.c | 10 |
3 files changed, 21 insertions, 29 deletions
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: diff --git a/usr.sbin/arp/arp.c b/usr.sbin/arp/arp.c index 07e07f1f2da9..08698c7bc299 100644 --- a/usr.sbin/arp/arp.c +++ b/usr.sbin/arp/arp.c @@ -717,7 +717,6 @@ rtmsg(int cmd, struct sockaddr_in *dst, struct sockaddr_dl *sdl) static int seq; int rlen; int l; - struct sockaddr_in so_mask, *som = &so_mask; static int s = -1; static pid_t pid; @@ -735,9 +734,6 @@ rtmsg(int cmd, struct sockaddr_in *dst, struct sockaddr_dl *sdl) xo_err(1, "socket"); pid = getpid(); } - bzero(&so_mask, sizeof(so_mask)); - so_mask.sin_len = 8; - so_mask.sin_addr.s_addr = 0xffffffff; errno = 0; /* @@ -758,10 +754,6 @@ rtmsg(int cmd, struct sockaddr_in *dst, struct sockaddr_dl *sdl) rtm->rtm_rmx.rmx_expire = expire_time; rtm->rtm_inits = RTV_EXPIRE; rtm->rtm_flags |= (RTF_HOST | RTF_STATIC | RTF_LLDATA); - if (doing_proxy) { - rtm->rtm_addrs |= RTA_NETMASK; - rtm->rtm_flags &= ~RTF_HOST; - } /* FALLTHROUGH */ case RTM_GET: rtm->rtm_addrs |= RTA_DST; @@ -776,7 +768,6 @@ rtmsg(int cmd, struct sockaddr_in *dst, struct sockaddr_dl *sdl) NEXTADDR(RTA_DST, dst); NEXTADDR(RTA_GATEWAY, sdl); - NEXTADDR(RTA_NETMASK, som); rtm->rtm_msglen = cp - (char *)&m_rtmsg; doit: diff --git a/usr.sbin/ndp/ndp.c b/usr.sbin/ndp/ndp.c index aa40e2775a59..ce21e34417c3 100644 --- a/usr.sbin/ndp/ndp.c +++ b/usr.sbin/ndp/ndp.c @@ -860,12 +860,6 @@ rtmsg(int cmd) rtm->rtm_inits = RTV_EXPIRE; } rtm->rtm_flags |= (RTF_HOST | RTF_STATIC | RTF_LLDATA); -#if 0 /* we don't support ipv6addr/128 type proxying */ - if (rtm->rtm_flags & RTF_ANNOUNCE) { - rtm->rtm_flags &= ~RTF_HOST; - rtm->rtm_addrs |= RTA_NETMASK; - } -#endif /* FALLTHROUGH */ case RTM_GET: rtm->rtm_addrs |= RTA_DST; @@ -873,10 +867,6 @@ rtmsg(int cmd) NEXTADDR(RTA_DST, sin_m); NEXTADDR(RTA_GATEWAY, sdl_m); -#if 0 /* we don't support ipv6addr/128 type proxying */ - memset(&so_mask.sin6_addr, 0xff, sizeof(so_mask.sin6_addr)); - NEXTADDR(RTA_NETMASK, so_mask); -#endif rtm->rtm_msglen = cp - (char *)&m_rtmsg; doit: |