Fix arp/ndp deletion broken by 2fe5a79425
.
Changes in the 2fe5a79425
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
This commit is contained in:
parent
a78bb831a1
commit
f9e1cd6c99
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user