diff options
| author | Roy Marples <roy@marples.name> | 2016-09-01 13:17:07 +0000 |
|---|---|---|
| committer | Roy Marples <roy@marples.name> | 2016-09-01 13:17:07 +0000 |
| commit | 8d31ed9d3cc3415518c311914d3c7ab113566df1 (patch) | |
| tree | bc2248cb55e6d6f8877b6457e465acfaea7e7aa5 /if-bsd.c | |
| parent | 4793785b7f24474266d6a5ccd0a253bf54ca09db (diff) | |
| download | dhcpcd-8d31ed9d3cc3415518c311914d3c7ab113566df1.tar.xz | |
FreeBSD emits RTM_DELADDR for INET addresses that still exit,
for example when dowing the interface.
This is totally bogus, so we ignore it.
While here, only set LINK_UP for RTM_IFINFO messges when IFF_UP is also set.
This should fix dhcpcd working on FreeBSD when downing interfaces and
link is lost.
Diffstat (limited to 'if-bsd.c')
| -rw-r--r-- | if-bsd.c | 28 |
1 files changed, 27 insertions, 1 deletions
@@ -1297,7 +1297,8 @@ if_ifinfo(struct dhcpcd_ctx *ctx, const struct if_msghdr *ifm) state = LINK_DOWN; break; case LINK_STATE_UP: - state = LINK_UP; + /* Some BSD's don't take the link down on downed interface. */ + state = ifm->ifm_flags & IFF_UP ? LINK_UP : LINK_DOWN; break; default: /* handle_carrier will re-load the interface flags and check for @@ -1434,6 +1435,31 @@ if_ifa(struct dhcpcd_ctx *ctx, const struct ifa_msghdr *ifam) sin = (const void *)rti_info[RTAX_BRD]; bcast.s_addr = sin != NULL && sin->sin_family == AF_INET ? sin->sin_addr.s_addr : INADDR_ANY; + +#ifdef __FreeBSD__ + /* FreeBSD sends RTM_DELADDR for each assigned address + * to an interface just brought down. + * This is wrong, because the address still exists. + * So we need to ignore it. + * Oddly enough this only happens for INET addresses. */ + if (ifam->ifam_type == RTM_DELADDR) { + struct ifreq ifr; + struct sockaddr_in *ifr_sin; + + memset(&ifr, 0, sizeof(ifr)); + strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); + ifr_sin = (void *)&ifr.ifr_addr; + ifr_sin->sin_family = AF_INET; + ifr_sin->sin_addr = addr; + if (ioctl(ctx->pf_inet_fd, SIOCGIFADDR, &ifr) == 0) { + logger(ctx, LOG_WARNING, + "%s: ignored false RTM_DELADDR for %s", + ifp->name, inet_ntoa(addr)); + break; + } + } +#endif + ipv4_handleifa(ctx, ifam->ifam_type, NULL, ifp->name, &addr, &mask, &bcast); break; |
