]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
One BSD in the future will include address flags in ifa_msghdr.
authorRoy Marples <roy@marples.name>
Fri, 16 Sep 2016 15:49:01 +0000 (15:49 +0000)
committerRoy Marples <roy@marples.name>
Fri, 16 Sep 2016 15:49:01 +0000 (15:49 +0000)
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.

configure
if-bsd.c
if-linux.c
if-sun.c
if.c
if.h
ipv4.c
ipv4.h
ipv6.c
ipv6.h

index 0f2e2341f1ac7c7fd15bd313ab8f6d8b733eccb1..c5b8a218daaf38e8a97d79eab1f2d3b8b3a79fbc 100755 (executable)
--- 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 <<EOF >_ifam_addrflags.c
+#include <net/if.h>
+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 <<EOF >_getifaddrs_addrflags.c
+#include <sys/types.h>
+#include <ifaddrs.h>
+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 <<EOF >_clock_gettime.c
 #include <time.h>
index 8f072968ae786bccfe928018ea7bdb2b8416c8c4..d197db53d064c7cdd79b87c757f36557128b617e 100644 (file)
--- 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
index f46509d46edfbbb93141d6b044c23fcfa5a8bcc0..488d689af7a8c0b8d5c1fcbe3ff3298a01bc05f0 100644 (file)
@@ -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);
index 39285e926f836072365b92e63445ee2e732af5f7..66db0c32d1a0e024c64d225e2f0a1ae027fb733c 100644 (file)
--- 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 6a311ef8dcc4b73cbe07ad84190b5c70c996cf07..fcfdf3da04abe5829752962839a609a373ffa435 100644 (file)
--- 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 670c8b8a98c5fbc799e5ae8bfdee5f11d06f783d..fb83f0cd8f9c4f2007e30d2be84c516ed164264e 100644 (file)
--- 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 cc80b532cf16e0ba617ca3c6cb71dce945d1af00..1da40ad0f89bf2d7f387d1f3bc3f6e01633258ef 100644 (file)
--- 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 a8a6efb1d3dbad514f9b11d4c48cddfcb266d0e2..c24a38eff02d8fa69e289b6733719af7f4bf47ab 100644 (file)
--- 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 61bc3c63284518a1a8941df3edd6b42ed05db21b..a49cffd05498f677c34ee5adaee70264a6bc8e69 100644 (file)
--- 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 4c77e3350a56c6b60dd98ac9e2b27c751af03ef5..8182d34a9898b9d72ac72762a284ced92a604ab3 100644 (file)
--- 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);