aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander V. Chernikov <melifaro@FreeBSD.org>2021-02-19 21:09:17 +0000
committerAlexander V. Chernikov <melifaro@FreeBSD.org>2021-02-19 21:17:17 +0000
commitf9e1cd6c99200846b324a8b65f7f31ded74013bd (patch)
treee1de91c2b590f2e9c4a7b0a6bceda69a8d23240e
parenta78bb831a17f9ba4b3d833ae6a9c2ce4f5cb5d1e (diff)
downloadsrc-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.c31
-rw-r--r--usr.sbin/arp/arp.c9
-rw-r--r--usr.sbin/ndp/ndp.c10
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: