From: Roy Marples Date: Fri, 16 Sep 2016 15:49:01 +0000 (+0000) Subject: One BSD in the future will include address flags in ifa_msghdr. X-Git-Tag: v6.11.4~27 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b0601fe4165e342848c344faf2e08720db5fa271;p=thirdparty%2Fdhcpcd.git One BSD in the future will include address flags in ifa_msghdr. A libc in the future will include address flags in ifaddrs. Although this does make the code a bit more #ifdef messy, the end result is a smaller binary, and less ioctls to make. --- diff --git a/configure b/configure index 0f2e2341..c5b8a218 100755 --- a/configure +++ b/configure @@ -533,6 +533,22 @@ EOF echo "no" fi rm -f _ifam_pid.c _ifam_pid + + printf "Testing for ifam_addrflags ... " + cat <_ifam_addrflags.c +#include +int main(void) { + struct ifa_msghdr ifam = { }; + return (int)ifam.ifam_addrflags; +} +EOF + if $XCC _ifam_addrflags.c -o _ifam_addrflags 2>&3; then + echo "yes" + echo "#define HAVE_IFAM_ADDRFLAGS" >>$CONFIG_H + else + echo "no" + fi + rm -f _ifam_addrflags.c _ifam_addrflags fi abort=false @@ -546,9 +562,11 @@ int main(void) { return getifaddrs(&ifap); } EOF +LIBSOCKET= if $XCC _getifaddrs.c -o _getifaddrs 2>&3; then echo "yes" elif $XCC _getifaddrs.c -o _getifaddrs -lsocket 2>&3; then + LIBSOCKET=-lsocket echo "yes (-lsocket)" echo "LDADD+= -lsocket" >>$CONFIG_MK else @@ -559,6 +577,24 @@ fi rm -f _getifaddrs.c _getifaddrs $abort && exit 1 +printf "Testing for ifaddrs.ifa_addrflags ... " +cat <_getifaddrs_addrflags.c +#include +#include +int main(void) { + struct ifaddrs *ifap; + getifaddrs(&ifap); + return (int)ifap->ifa_addrflags; +} +EOF +if $XCC _getifaddrs_addrflags.c -o _getifaddrs_addrflags $LIBSOCKET 2>&3; then + echo "yes" + echo "#define HAVE_IFADDRS_ADDRFLAGS" >>$CONFIG_H +else + echo "no" +fi +rm -f _getifaddrs_addrflags.c _getifaddrs_addrflags + printf "Testing for clock_gettime ... " cat <_clock_gettime.c #include diff --git a/if-bsd.c b/if-bsd.c index 8f072968..d197db53 100644 --- a/if-bsd.c +++ b/if-bsd.c @@ -849,26 +849,30 @@ if_initrt(struct dhcpcd_ctx *ctx) return 0; } +#if !(defined(HAVE_IFADDRS_ADDRFLAGS) && defined(HAVE_IFAM_ADDRFLAGS)) int -if_addrflags(const struct ipv4_addr *ia) +if_addrflags(const struct interface *ifp, const struct in_addr *addr, + __unused const char *alias) { #ifdef SIOCGIFAFLAG_IN struct ifreq ifr; struct sockaddr_in *sin; memset(&ifr, 0, sizeof(ifr)); - strlcpy(ifr.ifr_name, ia->iface->name, sizeof(ifr.ifr_name)); + strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); sin = (void *)&ifr.ifr_addr; sin->sin_family = AF_INET; - sin->sin_addr = ia->addr; - if (ioctl(ia->iface->ctx->pf_inet_fd, SIOCGIFAFLAG_IN, &ifr) == -1) + sin->sin_addr = *addr; + if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFAFLAG_IN, &ifr) == -1) return -1; return ifr.ifr_addrflags; #else - UNUSED(ia); + UNUSED(ifp); + UNUSED(addr); return 0; #endif } +#endif #endif /* INET */ #ifdef INET6 @@ -1213,25 +1217,28 @@ if_initrt6(struct dhcpcd_ctx *ctx) return 0; } +#if !(defined(HAVE_IFADDRS_ADDRFLAGS) && defined(HAVE_IFAM_ADDRFLAGS)) int -if_addrflags6(const struct ipv6_addr *ia) +if_addrflags6(const struct interface *ifp, const struct in6_addr *addr, + __unused const char *alias) { int flags; struct in6_ifreq ifr6; struct priv *priv; memset(&ifr6, 0, sizeof(ifr6)); - strlcpy(ifr6.ifr_name, ia->iface->name, sizeof(ifr6.ifr_name)); + strlcpy(ifr6.ifr_name, ifp->name, sizeof(ifr6.ifr_name)); ifr6.ifr_addr.sin6_family = AF_INET6; - ifr6.ifr_addr.sin6_addr = ia->addr; - ifa_scope(&ifr6.ifr_addr, ia->iface->index); - priv = (struct priv *)ia->iface->ctx->priv; + ifr6.ifr_addr.sin6_addr = *addr; + ifa_scope(&ifr6.ifr_addr, ifp->index); + priv = (struct priv *)ifp->ctx->priv; if (ioctl(priv->pf_inet6_fd, SIOCGIFAFLAG_IN6, &ifr6) != -1) flags = ifr6.ifr_ifru.ifru_flags6; else flags = -1; return flags; } +#endif int if_getlifetime6(struct ipv6_addr *ia) @@ -1405,6 +1412,7 @@ if_ifa(struct dhcpcd_ctx *ctx, const struct ifa_msghdr *ifam) { struct interface *ifp; const struct sockaddr *rti_info[RTAX_MAX]; + int addrflags; #ifdef HAVE_IFAM_PID if (if_ownmsgpid(ctx, ifam->ifam_pid, 0)) @@ -1416,6 +1424,9 @@ if_ifa(struct dhcpcd_ctx *ctx, const struct ifa_msghdr *ifam) get_addrs(ifam->ifam_addrs, ifam + 1, rti_info); if (rti_info[RTAX_IFA] == NULL) return; +#ifdef HAVE_IFAM_ADDRFLAGS + addrflags = ifam->ifam_addrflags; +#endif switch (rti_info[RTAX_IFA]->sa_family) { case AF_LINK: { @@ -1473,8 +1484,20 @@ if_ifa(struct dhcpcd_ctx *ctx, const struct ifa_msghdr *ifam) } #endif +#ifndef HAVE_IFAM_ADDRFLAGS + if (ifam->ifam_type == RTM_DELADDR || + (addrflags = if_addrflags(ifp, &addr, NULL)) == -1) + { + if (ifam->ifam_type != RTM_DELADDR || errno != EEXIST) + logger(ctx, LOG_ERR, + "%s: if_addrflags1: %s: %m", + ifp->name, inet_ntoa(addr)); + addrflags = 0; + } +#endif + ipv4_handleifa(ctx, ifam->ifam_type, NULL, ifp->name, - &addr, &mask, &bcast); + &addr, &mask, &bcast, addrflags); break; } #endif @@ -1490,8 +1513,21 @@ if_ifa(struct dhcpcd_ctx *ctx, const struct ifa_msghdr *ifam) sin6 = (const void *)rti_info[RTAX_NETMASK]; mask6 = sin6->sin6_addr; DESCOPE(&mask6); + +#ifndef HAVE_IFAM_ADDRFLAGS + if (ifam->ifam_type == RTM_DELADDR || + (addrflags = if_addrflags6(ifp, &addr6, NULL)) == -1) + { + if (ifam->ifam_type != RTM_DELADDR || errno != EEXIST) + logger(ctx, LOG_ERR, + "%s: if_addrflags1: %s: %m", + ifp->name, inet_ntoa(addr)); + addrflags = 0; + } +#endif + ipv6_handleifa(ctx, ifam->ifam_type, NULL, - ifp->name, &addr6, ipv6_prefixlen(&mask6)); + ifp->name, &addr6, ipv6_prefixlen(&mask6), addrflags); break; } #endif diff --git a/if-linux.c b/if-linux.c index f46509d4..488d689a 100644 --- a/if-linux.c +++ b/if-linux.c @@ -1476,7 +1476,8 @@ if_initrt(struct dhcpcd_ctx *ctx) } int -if_addrflags(__unused const struct ipv4_addr *addr) +if_addrflags(__unused const struct interface *ifp, +__unused const struct in_addr *addr, __unused const char *alias) { /* Linux has no support for IPv4 address flags */ @@ -1658,7 +1659,8 @@ if_initrt6(struct dhcpcd_ctx *ctx) } int -if_addrflags6(const struct ipv6_addr *ia) +if_addrflags6(const struct interface *ifp, const struct in6_addr *addr, + _unused const char *alias) { FILE *fp; char *p, ifaddress[33], address[33], name[IF_NAMESIZE + 1]; @@ -1670,8 +1672,8 @@ if_addrflags6(const struct ipv6_addr *ia) return -1; p = ifaddress; - for (i = 0; i < (int)sizeof(ia->addr.s6_addr); i++) { - p += snprintf(p, 3, "%.2x", ia->addr.s6_addr[i]); + for (i = 0; i < (int)sizeof(addr->s6_addr); i++) { + p += snprintf(p, 3, "%.2x", addr->s6_addr[i]); } *p = '\0'; @@ -1683,7 +1685,7 @@ if_addrflags6(const struct ipv6_addr *ia) errno = EINVAL; return -1; } - if (strcmp(name, ia->iface->name) == 0 && + if (strcmp(name, ifp->name) == 0 && strcmp(ifaddress, address) == 0) { fclose(fp); diff --git a/if-sun.c b/if-sun.c index 39285e92..66db0c32 100644 --- a/if-sun.c +++ b/if-sun.c @@ -1340,11 +1340,12 @@ if_address(unsigned char cmd, const struct ipv4_addr *ia) } int -if_addrflags(const struct ipv4_addr *ia) +if_addrflags(const struct interface *ifp, __unused const struct in_addr *addr, + const char *alias) { int flags, aflags; - aflags = if_addrflags0(ia->iface->ctx->pf_inet_fd, ia->alias); + aflags = if_addrflags0(ifp->ctx->pf_inet_fd, alias); if (aflags == -1) return -1; flags = 0; @@ -1517,13 +1518,14 @@ if_address6(unsigned char cmd, const struct ipv6_addr *ia) } int -if_addrflags6(const struct ipv6_addr *ia) +if_addrflags6(const struct interface *ifp, __unused const struct in6_addr *addr, + const char *alias) { struct priv *priv; int aflags, flags; - priv = (struct priv *)ia->iface->ctx->priv; - aflags = if_addrflags0(priv->pf_inet6_fd, ia->alias); + priv = (struct priv *)ifp->ctx->priv; + aflags = if_addrflags0(priv->pf_inet6_fd, alias); flags = 0; if (aflags & IFF_DUPLICATE) flags |= IN6_IFF_DUPLICATED; diff --git a/if.c b/if.c index 6a311ef8..fcfdf3da 100644 --- a/if.c +++ b/if.c @@ -198,12 +198,16 @@ static void if_learnaddrs(struct dhcpcd_ctx *ctx, struct if_head *ifs, #ifdef INET6 struct sockaddr_in6 *sin6, *net6; #endif + int addrflags; for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) { if (ifa->ifa_addr == NULL) continue; if ((ifp = if_find(ifs, ifa->ifa_name)) == NULL) continue; +#ifdef HAVE_IFADDRS_ADDRFLAGS + addrflags = (int)ifa->ifa_addrflags; +#endif switch(ifa->ifa_addr->sa_family) { #ifdef INET case AF_INET: @@ -213,9 +217,21 @@ static void if_learnaddrs(struct dhcpcd_ctx *ctx, struct if_head *ifs, brd = (void *)ifa->ifa_dstaddr; else brd = (void *)ifa->ifa_broadaddr; +#ifndef HAVE_IFADDRS_ADDRFLAGS + addrflags = if_addrflags(ifp, &addr->sin_addr, + ifa->ifa_name); + if (addrflags == -1) { + if (errno != EEXIST) + logger(ctx, LOG_ERR, + "%s: if_addrflags: %s: %m", + __func__, + inet_ntoa(addr->sin_addr)); + continue; + } +#endif ipv4_handleifa(ctx, RTM_NEWADDR, ifs, ifa->ifa_name, &addr->sin_addr, &net->sin_addr, - brd ? &brd->sin_addr : NULL); + brd ? &brd->sin_addr : NULL, addrflags); break; #endif #ifdef INET6 @@ -227,10 +243,20 @@ static void if_learnaddrs(struct dhcpcd_ctx *ctx, struct if_head *ifs, /* Remove the scope from the address */ sin6->sin6_addr.s6_addr[2] = sin6->sin6_addr.s6_addr[3] = '\0'; +#endif +#ifndef HAVE_IFADDRS_ADDRFLAGS + addrflags = if_addrflags6(ifp, &sin6->sin6_addr, + ifa->ifa_name); + if (addrflags == -1) { + if (errno != EEXIST) + logger(ctx, LOG_ERR, + "%s: if_addrflags6: %m", __func__); + continue; + } #endif ipv6_handleifa(ctx, RTM_NEWADDR, ifs, ifa->ifa_name, &sin6->sin6_addr, - ipv6_prefixlen(&net6->sin6_addr)); + ipv6_prefixlen(&net6->sin6_addr), addrflags); break; #endif } diff --git a/if.h b/if.h index 670c8b8a..fb83f0cd 100644 --- a/if.h +++ b/if.h @@ -185,7 +185,8 @@ ssize_t if_readraw(struct interface *, int, void *, size_t, int *); void if_closeraw(struct interface *, int); int if_address(unsigned char, const struct ipv4_addr *); -int if_addrflags(const struct ipv4_addr *); +int if_addrflags(const struct interface *, const struct in_addr *, + const char *); int if_route(unsigned char, const struct rt *rt); int if_initrt(struct dhcpcd_ctx *); @@ -202,7 +203,8 @@ int ip6_temp_valid_lifetime(const char *ifname); #endif int if_address6(unsigned char, const struct ipv6_addr *); -int if_addrflags6(const struct ipv6_addr *); +int if_addrflags6(const struct interface *, const struct in6_addr *, + const char *); int if_getlifetime6(struct ipv6_addr *); int if_route6(unsigned char, const struct rt6 *rt); diff --git a/ipv4.c b/ipv4.c index cc80b532..1da40ad0 100644 --- a/ipv4.c +++ b/ipv4.c @@ -1273,12 +1273,11 @@ void ipv4_handleifa(struct dhcpcd_ctx *ctx, int cmd, struct if_head *ifs, const char *ifname, const struct in_addr *addr, const struct in_addr *mask, - const struct in_addr *brd) + const struct in_addr *brd, const int addrflags) { struct interface *ifp; struct ipv4_state *state; struct ipv4_addr *ia; - int flags; bool ia_is_new; if (ifs == NULL) @@ -1325,16 +1324,7 @@ ipv4_handleifa(struct dhcpcd_ctx *ctx, ia->brd = *brd; else ia->brd.s_addr = INADDR_ANY; - - flags = if_addrflags(ia); - if (flags == -1) { - if (errno != EADDRNOTAVAIL) - logger(ia->iface->ctx, LOG_ERR, - "%s: %s: if_addrflags: %m", - ia->iface->name, ia->saddr); - return; - } - ia->addr_flags = flags; + ia->addr_flags = addrflags; break; case RTM_DELADDR: if (ia == NULL) diff --git a/ipv4.h b/ipv4.h index a8a6efb1..c24a38ef 100644 --- a/ipv4.h +++ b/ipv4.h @@ -152,7 +152,8 @@ struct ipv4_addr *ipv4_findaddr(struct dhcpcd_ctx *, const struct in_addr *); struct ipv4_addr *ipv4_findmaskaddr(struct dhcpcd_ctx *, const struct in_addr *); void ipv4_handleifa(struct dhcpcd_ctx *, int, struct if_head *, const char *, - const struct in_addr *, const struct in_addr *, const struct in_addr *); + const struct in_addr *, const struct in_addr *, const struct in_addr *, + int); void ipv4_freeroutes(struct rt_head *); diff --git a/ipv6.c b/ipv6.c index 61bc3c63..a49cffd0 100644 --- a/ipv6.c +++ b/ipv6.c @@ -1060,13 +1060,12 @@ ipv6_getstate(struct interface *ifp) void ipv6_handleifa(struct dhcpcd_ctx *ctx, int cmd, struct if_head *ifs, const char *ifname, - const struct in6_addr *addr, uint8_t prefix_len) + const struct in6_addr *addr, uint8_t prefix_len, int addrflags) { struct interface *ifp; struct ipv6_state *state; struct ipv6_addr *ia; struct ll_callback *cb; - int flags; #if 0 char dbuf[INET6_ADDRSTRLEN]; @@ -1148,15 +1147,7 @@ ipv6_handleifa(struct dhcpcd_ctx *ctx, ia->acquired = ia->created; TAILQ_INSERT_TAIL(&state->addrs, ia, next); } - flags = if_addrflags6(ia); - if (flags == -1) { - if (errno != EADDRNOTAVAIL) - logger(ia->iface->ctx, LOG_ERR, - "%s: %s: if_addrflags6: %m", - ia->iface->name, ia->saddr); - return; - } - ia->addr_flags = flags; + ia->addr_flags = addrflags; #ifdef IPV6_MANAGETEMPADDR if (ia->addr_flags & IN6_IFF_TEMPORARY) ia->flags |= IPV6_AF_TEMPORARY; diff --git a/ipv6.h b/ipv6.h index 4c77e335..8182d34a 100644 --- a/ipv6.h +++ b/ipv6.h @@ -297,7 +297,7 @@ ssize_t ipv6_addaddrs(struct ipv6_addrhead *addrs); void ipv6_freedrop_addrs(struct ipv6_addrhead *, int, const struct interface *); void ipv6_handleifa(struct dhcpcd_ctx *ctx, int, struct if_head *, - const char *, const struct in6_addr *, uint8_t); + const char *, const struct in6_addr *, uint8_t, int); int ipv6_handleifa_addrs(int, struct ipv6_addrhead *, const struct ipv6_addr *); struct ipv6_addr *ipv6_iffindaddr(struct interface *, const struct in6_addr *, int);