]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Rework if_address to just use an ipv4_addr structure, similar to how
authorRoy Marples <roy@marples.name>
Wed, 18 May 2016 16:23:28 +0000 (16:23 +0000)
committerRoy Marples <roy@marples.name>
Wed, 18 May 2016 16:23:28 +0000 (16:23 +0000)
if_address6 works.
Use a pointer to the ipv4_addr for the address we added for dhcp and ipv4ll
states.
This is quite some churn throughout the IPv4 stack, but makes the
binary smaller (at least on Linux/amd64).
It will be needed to support adding addresses on Solaris.

15 files changed:
arp.c
arp.h
dhcp.c
dhcp.h
if-bsd.c
if-linux.c
if-sun.c
if.h
ipv4.c
ipv4.h
ipv4ll.c
ipv4ll.h
ipv6.c
ipv6nd.c
script.c

diff --git a/arp.c b/arp.c
index 64f1237160dbfac0e8935ff92f720e70d6acf45f..ad4eb8f48d4154c3b5191ef427843e7b379c88fa 100644 (file)
--- a/arp.c
+++ b/arp.c
@@ -425,8 +425,7 @@ arp_close(struct interface *ifp)
 }
 
 void
-arp_handleifa(int cmd, struct interface *ifp, const struct in_addr *addr,
-    int flags)
+arp_handleifa(int cmd, struct ipv4_addr *addr)
 {
 #ifdef IN_IFF_DUPLICATED
        struct iarp_state *state;
@@ -436,7 +435,7 @@ arp_handleifa(int cmd, struct interface *ifp, const struct in_addr *addr,
                return;
 
        TAILQ_FOREACH_SAFE(astate, &state->arp_states, next, asn) {
-               if (astate->addr.s_addr == addr->s_addr) {
+               if (astate->addr.s_addr == addr->addr.s_addr) {
                        if (flags & IN_IFF_DUPLICATED) {
                                if (astate->conflicted_cb)
                                        astate->conflicted_cb(astate, NULL);
@@ -448,8 +447,6 @@ arp_handleifa(int cmd, struct interface *ifp, const struct in_addr *addr,
        }
 #else
        UNUSED(cmd);
-       UNUSED(ifp);
        UNUSED(addr);
-       UNUSED(flags);
 #endif
 }
diff --git a/arp.h b/arp.h
index b9636662992d928221ba49fa58d2920a66aafdba..b844e49870bacbddaafae8abf12172d1e94a863e 100644 (file)
--- a/arp.h
+++ b/arp.h
@@ -41,6 +41,7 @@
 #define DEFEND_INTERVAL                10
 
 #include "dhcpcd.h"
+#include "if.h"
 
 struct arp_msg {
        uint16_t op;
@@ -89,7 +90,7 @@ void arp_free_but(struct arp_state *);
 struct arp_state *arp_find(struct interface *, const struct in_addr *);
 void arp_close(struct interface *);
 
-void arp_handleifa(int, struct interface *, const struct in_addr *, int);
+void arp_handleifa(int, struct ipv4_addr *);
 #else
 #define arp_close(a) {}
 #endif
diff --git a/dhcp.c b/dhcp.c
index 833568c96d67c87f48db9163196ae0b31e315079..32d2f9077c36e0c8eed3885acb60f2fcf7a8ccbc 100644 (file)
--- a/dhcp.c
+++ b/dhcp.c
@@ -760,16 +760,12 @@ make_message(struct bootp **bootpm, const struct interface *ifp, uint8_t type)
                return -1;
        *bootpm = bootp;
 
-       if ((type == DHCP_INFORM || type == DHCP_RELEASE ||
-           (type == DHCP_REQUEST && state->mask.s_addr == lease->mask.s_addr &&
+       if (state->addr != NULL &&
+           (type == DHCP_INFORM || type == DHCP_RELEASE ||
+           (type == DHCP_REQUEST &&
+           state->addr->mask.s_addr == lease->mask.s_addr &&
            (state->new == NULL || IS_DHCP(state->new)))))
-       {
-               /* In-case we haven't actually configured the address yet */
-               if (type == DHCP_INFORM && state->addr.s_addr == 0)
-                       bootp->ciaddr = lease->addr.s_addr;
-               else
-                       bootp->ciaddr = state->addr.s_addr;
-       }
+               bootp->ciaddr = state->addr->addr.s_addr;
 
        bootp->op = BOOTREQUEST;
        bootp->htype = (uint8_t)ifp->family;
@@ -835,7 +831,8 @@ make_message(struct bootp **bootpm, const struct interface *ifp, uint8_t type)
        if (lease->addr.s_addr && lease->cookie == htonl(MAGIC_COOKIE)) {
                if (type == DHCP_DECLINE ||
                    (type == DHCP_REQUEST &&
-                       lease->addr.s_addr != state->addr.s_addr))
+                       state->addr != NULL &&
+                       lease->addr.s_addr != state->addr->addr.s_addr))
                {
                        PUT_ADDR(DHO_IPADDRESS, &lease->addr);
                        if (lease->server.s_addr)
@@ -1553,9 +1550,9 @@ dhcp_openudp(struct interface *ifp)
        sin.sin_port = htons(BOOTPC);
        if (ifp) {
                state = D_STATE(ifp);
-               sin.sin_addr.s_addr = state->addr.s_addr;
-       } else
-               state = NULL; /* appease gcc */
+               if (state->addr)
+                       sin.sin_addr.s_addr = state->addr->addr.s_addr;
+       }
        if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) == -1)
                goto eexit;
 
@@ -1646,7 +1643,7 @@ send_message(struct interface *ifp, uint8_t type,
        size_t len;
        ssize_t r;
        struct in_addr from, to;
-       in_addr_t a = INADDR_ANY;
+       struct ipv4_addr *iap;
        struct timespec tv;
        int s;
 #ifdef IN_IFF_NOTUSEABLE
@@ -1689,11 +1686,11 @@ send_message(struct interface *ifp, uint8_t type,
        if (dhcp_open(ifp) == -1)
                return;
 
+       iap = state->addr;
        if (state->added && !(state->added & STATE_FAKE) &&
-           state->addr.s_addr != INADDR_ANY &&
-           state->new != NULL &&
+           state->addr != NULL && state->new != NULL &&
 #ifdef IN_IFF_NOTUSEABLE
-           ((ia = ipv4_iffindaddr(ifp, &state->addr, NULL)) &&
+           ((ia = ipv4_iffindaddr(ifp, &state->addr->addr, NULL)) &&
            !(ia->addr_flags & IN_IFF_NOTUSEABLE)) &&
 #endif
            (state->lease.server.s_addr ||
@@ -1706,14 +1703,12 @@ send_message(struct interface *ifp, uint8_t type,
                                logger(ifp->ctx, LOG_ERR,
                                    "%s: dhcp_openudp: %m", ifp->name);
                        /* We cannot renew */
-                       a = state->addr.s_addr;
-                       state->addr.s_addr = INADDR_ANY;
+                       state->addr = NULL;
                }
        }
 
        r = make_message(&bootp, ifp, type);
-       if (a != INADDR_ANY)
-               state->addr.s_addr = a;
+       state->addr = iap;
        if (r == -1)
                goto fail;
        len = (size_t)r;
@@ -2081,9 +2076,9 @@ dhcp_arp_conflicted(struct arp_state *astate, const struct arp_msg *amsg)
                    !state->lease.frominfo)
                        dhcp_decline(ifp);
 #ifdef IN_IFF_DUPLICATED
-               ia = ipv4_iffindaddr(ifp, &astate->addr, NULL);
+               ia = ipv4_iffindaddr(ifp, &astate->addr->addr, NULL);
                if (ia)
-                       ipv4_deladdr(ifp, &ia->addr, &ia->mask, 1);
+                       ipv4_deladdr(ia->addr, 1);
 #endif
                arp_free(astate);
                eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
@@ -2093,11 +2088,12 @@ dhcp_arp_conflicted(struct arp_state *astate, const struct arp_msg *amsg)
        }
 
        /* Bound address */
-       if (amsg &&
-           (amsg->sip.s_addr == state->addr.s_addr ||
-           (amsg->sip.s_addr == 0 && amsg->tip.s_addr == state->addr.s_addr)))
+       if (amsg && state->addr &&
+           (amsg->sip.s_addr == state->addr->addr.s_addr ||
+           (amsg->sip.s_addr == 0 &&
+           amsg->tip.s_addr == state->addr->addr.s_addr)))
        {
-               astate->failed = state->addr;
+               astate->failed = state->addr->addr;
                arp_report_conflicted(astate, amsg);
                if (state->state == DHS_BOUND) {
                        /* For now, just report the duplicated address */
@@ -2179,7 +2175,8 @@ dhcp_bind(struct interface *ifp)
                                    ifp->name, lease->renewaltime);
                        }
                        logger(ifp->ctx,
-                           lease->addr.s_addr == state->addr.s_addr &&
+                           state->addr &&
+                           lease->addr.s_addr == state->addr->addr.s_addr &&
                            !(state->added & STATE_FAKE) ?
                            LOG_DEBUG : LOG_INFO,
                            "%s: leased %s for %"PRIu32" seconds", ifp->name,
@@ -2409,7 +2406,7 @@ dhcp_inform(struct interface *ifp)
                        ia = ipv4_iffindaddr(ifp, &ifo->req_addr, NULL);
                        if (ia != NULL)
                                /* Netmask must be different, delete it. */
-                               ipv4_deladdr(ifp, &ia->addr, &ia->mask, 1);
+                               ipv4_deladdr(ia, 1);
                        state->offer_len = dhcp_message_new(&state->offer,
                            &ifo->req_addr, &ifo->req_mask);
                        if (dhcp_arp_address(ifp) == 0)
@@ -2420,7 +2417,9 @@ dhcp_inform(struct interface *ifp)
                }
        }
 
-       state->offer_len = dhcp_message_new(&state->offer, &ia->addr, &ia->mask);
+       state->addr = ia;
+       state->offer_len = dhcp_message_new(&state->offer,
+           &ia->addr, &ia->mask);
        if (state->offer_len) {
                state->xid = dhcp_xid(ifp);
                get_lease(ifp, &state->lease, state->offer, state->offer_len);
@@ -2438,7 +2437,8 @@ dhcp_reboot_newopts(struct interface *ifp, unsigned long long oldopts)
                return;
        ifo = ifp->options;
        if ((ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC) &&
-               state->addr.s_addr != ifo->req_addr.s_addr) ||
+               (state->addr == NULL ||
+               state->addr->addr.s_addr != ifo->req_addr.s_addr)) ||
            (oldopts & (DHCPCD_INFORM | DHCPCD_STATIC) &&
                !(ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC))))
        {
@@ -3146,7 +3146,9 @@ dhcp_handlepacket(void *arg)
                    ifp->name, inet_ntoa(from));
                return;
        }
-       if (ifp->flags & IFF_POINTOPOINT && state->brd.s_addr != from.s_addr) {
+       if (ifp->flags & IFF_POINTOPOINT &&
+           (state->addr == NULL || state->addr->brd.s_addr != from.s_addr))
+       {
                logger(ifp->ctx, LOG_WARNING,
                    "%s: server %s is not destination",
                    ifp->name, inet_ntoa(from));
@@ -3460,11 +3462,13 @@ dhcp_start1(void *arg)
                }
        }
        if (state->offer) {
+               struct ipv4_addr *ia;
+
                get_lease(ifp, &state->lease, state->offer, state->offer_len);
                state->lease.frominfo = 1;
                if (state->new == NULL &&
-                   ipv4_iffindaddr(ifp,
-                   &state->lease.addr, &state->lease.mask))
+                   (ia = ipv4_iffindaddr(ifp,
+                   &state->lease.addr, &state->lease.mask)) != NULL)
                {
                        /* We still have the IP address from the last lease.
                         * Fake add the address and routes from it so the lease
@@ -3473,19 +3477,17 @@ dhcp_start1(void *arg)
                        if (state->new) {
                                memcpy(state->new,
                                    state->offer, state->offer_len);
-                               state->addr = state->lease.addr;
-                               state->mask = state->lease.mask;
+                               state->new_len = state->offer_len;
+                               state->addr = ia;
                                state->added |= STATE_ADDED | STATE_FAKE;
                                ipv4_buildroutes(ifp->ctx);
                        } else
                                logger(ifp->ctx, LOG_ERR, "%s: %m", __func__);
                }
                if (!IS_DHCP(state->offer)) {
-                       if (state->offer->yiaddr == state->addr.s_addr) {
-                               free(state->offer);
-                               state->offer = NULL;
-                               state->offer_len = 0;
-                       }
+                       free(state->offer);
+                       state->offer = NULL;
+                       state->offer_len = 0;
                } else if (!(ifo->options & DHCPCD_LASTLEASE_EXTEND) &&
                    state->lease.leasetime != ~0U &&
                    stat(state->leasefile, &st) == 0)
@@ -3599,29 +3601,22 @@ dhcp_abort(struct interface *ifp)
 }
 
 void
-dhcp_handleifa(int cmd, struct interface *ifp,
-       const struct in_addr *addr,
-       const struct in_addr *mask,
-       const struct in_addr *brd,
-       int flags)
+dhcp_handleifa(int cmd, struct ipv4_addr *ia)
 {
+       struct interface *ifp;
        struct dhcp_state *state;
        struct if_options *ifo;
        uint8_t i;
 
+       ifp = ia->iface;
        state = D_STATE(ifp);
        if (state == NULL)
                return;
 
        if (cmd == RTM_DELADDR) {
-               if (state->addr.s_addr == addr->s_addr &&
-                   state->mask.s_addr == mask->s_addr &&
-                   state->brd.s_addr == brd->s_addr)
-               {
+               if (IPV4_BRD_EQ(state->addr, ia)) {
                        logger(ifp->ctx, LOG_INFO,
-                           "%s: removing IP address %s/%d",
-                           ifp->name, inet_ntoa(state->addr),
-                           inet_ntocidr(state->mask));
+                           "%s: removing IP address %s", ifp->name, ia->saddr);
                        dhcp_drop(ifp, "EXPIRE");
                }
                return;
@@ -3631,10 +3626,8 @@ dhcp_handleifa(int cmd, struct interface *ifp,
                return;
 
 #ifdef IN_IFF_NOTUSEABLE
-       if (flags & IN_IFF_NOTUSEABLE)
+       if (ia->flags & IN_IFF_NOTUSEABLE)
                return;
-#else
-       UNUSED(flags);
 #endif
 
        ifo = ifp->options;
@@ -3651,14 +3644,13 @@ dhcp_handleifa(int cmd, struct interface *ifp,
 
        free(state->old);
        state->old = state->new;
-       state->new_len = dhcp_message_new(&state->new, addr, mask);
+       state->new_len = dhcp_message_new(&state->new, &ia->addr, &ia->mask);
        if (state->new == NULL)
                return;
-       state->brd = *brd;
        if (ifp->flags & IFF_POINTOPOINT) {
                for (i = 1; i < 255; i++)
                        if (i != DHO_ROUTER && has_option_mask(ifo->dstmask,i))
-                               dhcp_message_add_addr(state->new, i, *brd);
+                               dhcp_message_add_addr(state->new, i, ia->brd);
        }
        state->reason = "STATIC";
        ipv4_buildroutes(ifp->ctx);
@@ -3666,9 +3658,8 @@ dhcp_handleifa(int cmd, struct interface *ifp,
        if (ifo->options & DHCPCD_INFORM) {
                state->state = DHS_INFORM;
                state->xid = dhcp_xid(ifp);
-               state->lease.server = *brd;
-               state->addr = *addr;
-               state->mask = *mask;
+               state->lease.server.s_addr = INADDR_ANY;
+               state->addr = ia;
                dhcp_inform(ifp);
        }
 }
diff --git a/dhcp.h b/dhcp.h
index dbb7b1c2b3b6bd6fb714db678da63eda0983bbec..f573735f38d84eda4bdd6e7783e4910888168352 100644 (file)
--- a/dhcp.h
+++ b/dhcp.h
@@ -213,9 +213,7 @@ struct dhcp_state {
        int socket;
 
        int raw_fd;
-       struct in_addr addr;
-       struct in_addr mask;
-       struct in_addr brd;
+       struct ipv4_addr *addr;
        uint8_t added;
 
        char leasefile[sizeof(LEASEFILE) + IF_NAMESIZE + (IF_SSIDLEN * 4)];
@@ -251,10 +249,7 @@ struct rt_head *dhcp_get_routes(struct interface *);
 ssize_t dhcp_env(char **, const char *, const struct bootp *, size_t,
     const struct interface *);
 
-void dhcp_handleifa(int, struct interface *,
-    const struct in_addr *, const struct in_addr *, const struct in_addr *,
-    int);
-
+void dhcp_handleifa(int, struct ipv4_addr *);
 void dhcp_drop(struct interface *, const char *);
 void dhcp_start(struct interface *);
 void dhcp_abort(struct interface *);
index ed8f82b013f98ecd9a29954033b802ea1eb336f5..2d8bd9f940064aa376c2835c0b7c257b0be47a4c 100644 (file)
--- a/if-bsd.c
+++ b/if-bsd.c
@@ -531,9 +531,7 @@ next:
 
 
 int
-if_address(const struct interface *ifp, const struct in_addr *address,
-    const struct in_addr *netmask, const struct in_addr *broadcast,
-    int action)
+if_address(unsigned char cmd, struct ipv4_addr *ia)
 {
        int r;
        struct in_aliasreq ifra;
@@ -546,14 +544,14 @@ if_address(const struct interface *ifp, const struct in_addr *address,
                (var)->sin_len = sizeof(*(var));                              \
                (var)->sin_addr = *(addr);                                    \
        } while (/*CONSTCOND*/0)
-       ADDADDR(&ifra.ifra_addr, address);
-       ADDADDR(&ifra.ifra_mask, netmask);
-       if (action >= 0 && broadcast)
-               ADDADDR(&ifra.ifra_broadaddr, broadcast);
+       ADDADDR(&ifra.ifra_addr, &ia->addr);
+       ADDADDR(&ifra.ifra_mask, &ia->mask);
+       if (cmd == RTM_NEWADDR && ia->brd.s_addr != INADDR_ANY)
+               ADDADDR(&ifra.ifra_broadaddr, &ia->brd);
 #undef ADDADDR
 
        r = ioctl(ifp->ctx->pf_inet_fd,
-           action < 0 ? SIOCDIFADDR : SIOCAIFADDR, &ifra);
+           cmd == RTM_DELADDR ? SIOCDIFADDR : SIOCAIFADDR, &ifra);
        return r;
 }
 
@@ -809,10 +807,10 @@ if_initrt(struct dhcpcd_ctx *ctx)
        return 0;
 }
 
-#ifdef SIOCGIFAFLAG_IN
 int
 if_addrflags(const struct in_addr *addr, const struct interface *ifp)
 {
+#ifdef SIOCGIFAFLAG_IN
        struct ifreq ifr;
        struct sockaddr_in *sin;
 
@@ -824,15 +822,9 @@ if_addrflags(const struct in_addr *addr, const struct interface *ifp)
        if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFAFLAG_IN, &ifr) == -1)
                return -1;
        return ifr.ifr_addrflags;
-}
 #else
-int
-if_addrflags(__unused const struct in_addr *addr,
-    __unused const struct interface *ifp)
-{
-
-       errno = ENOTSUP;
-       return 0;
+       UNUSED(ia);
+#endif
 }
 #endif
 #endif /* INET */
@@ -869,7 +861,7 @@ ifa_scope(struct sockaddr_in6 *sin, unsigned int ifindex)
 #endif
 
 int
-if_address6(const struct ipv6_addr *ia, int action)
+if_address6(unsigned char cmd, const struct ipv6_addr *ia)
 {
        struct in6_aliasreq ifa;
        struct in6_addr mask;
@@ -910,7 +902,7 @@ if_address6(const struct ipv6_addr *ia, int action)
 
        priv = (struct priv *)ia->iface->ctx->priv;
        return ioctl(priv->pf_inet6_fd,
-           action < 0 ? SIOCDIFADDR_IN6 : SIOCAIFADDR_IN6, &ifa);
+           cmd == RTM_DELADDR ? SIOCDIFADDR_IN6 : SIOCAIFADDR_IN6, &ifa);
 }
 
 
index 21a2c31759910809c53f27fd67466ed54cf77f20..4085b9f0da94007d028e5779739db37a005b5d12 100644 (file)
@@ -1354,9 +1354,7 @@ if_readraw(__unused struct interface *ifp, int fd,
 }
 
 int
-if_address(const struct interface *iface,
-    const struct in_addr *address, const struct in_addr *netmask,
-    const struct in_addr *broadcast, int action)
+if_address(unsigned char cmd, const struct ipv4_addr *addr)
 {
        struct nlma nlm;
        int retval = 0;
@@ -1364,24 +1362,24 @@ if_address(const struct interface *iface,
        memset(&nlm, 0, sizeof(nlm));
        nlm.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
        nlm.hdr.nlmsg_flags = NLM_F_REQUEST;
-       if (action >= 0) {
+       nlm.hdr.nlmsg_type = cmd;
+       if (cmd == RTM_NEWADDR)
                nlm.hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE;
-               nlm.hdr.nlmsg_type = RTM_NEWADDR;
-       } else
-               nlm.hdr.nlmsg_type = RTM_DELADDR;
-       nlm.ifa.ifa_index = iface->index;
+       nlm.ifa.ifa_index = addr->iface->index;
        nlm.ifa.ifa_family = AF_INET;
-       nlm.ifa.ifa_prefixlen = inet_ntocidr(*netmask);
+       nlm.ifa.ifa_prefixlen = inet_ntocidr(addr->mask);
        /* This creates the aliased interface */
        add_attr_l(&nlm.hdr, sizeof(nlm), IFA_LABEL,
-           iface->alias, (unsigned short)(strlen(iface->alias) + 1));
+           addr->iface->alias,
+           (unsigned short)(strlen(addr->iface->alias) + 1));
        add_attr_l(&nlm.hdr, sizeof(nlm), IFA_LOCAL,
-           &address->s_addr, sizeof(address->s_addr));
-       if (action >= 0 && broadcast)
+           &addr->addr.s_addr, sizeof(addr->addr.s_addr));
+       if (cmd == RTM_NEWADDR)
                add_attr_l(&nlm.hdr, sizeof(nlm), IFA_BROADCAST,
-                   &broadcast->s_addr, sizeof(broadcast->s_addr));
+                   &addr->brd.s_addr, sizeof(addr->brd.s_addr));
 
-       if (send_netlink(iface->ctx, NULL, NETLINK_ROUTE, &nlm.hdr, NULL) == -1)
+       if (send_netlink(addr->iface->ctx, NULL,
+           NETLINK_ROUTE, &nlm.hdr, NULL) == -1)
                retval = -1;
        return retval;
 }
@@ -1508,7 +1506,7 @@ if_addrflags(__unused const struct in_addr *addr,
 
 #ifdef INET6
 int
-if_address6(const struct ipv6_addr *ia, int action)
+if_address6(unsigned char cmd, const struct ipv6_addr *ia)
 {
        struct nlma nlm;
        struct ifa_cacheinfo cinfo;
@@ -1521,11 +1519,9 @@ if_address6(const struct ipv6_addr *ia, int action)
        memset(&nlm, 0, sizeof(nlm));
        nlm.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
        nlm.hdr.nlmsg_flags = NLM_F_REQUEST;
-       if (action >= 0) {
+       nlm.hdr.nlmsg_type = cmd;
+       if (cmd == RTM_NEWADDR)
                nlm.hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE;
-               nlm.hdr.nlmsg_type = RTM_NEWADDR;
-       } else
-               nlm.hdr.nlmsg_type = RTM_DELADDR;
        nlm.ifa.ifa_index = ia->iface->index;
        nlm.ifa.ifa_family = AF_INET6;
 #ifdef IPV6_MANAGETEMPADDR
@@ -1550,7 +1546,7 @@ if_address6(const struct ipv6_addr *ia, int action)
        add_attr_l(&nlm.hdr, sizeof(nlm), IFA_LOCAL,
            &ia->addr.s6_addr, sizeof(ia->addr.s6_addr));
 
-       if (action >= 0) {
+       if (cmd == RTM_NEWADDR) {
                memset(&cinfo, 0, sizeof(cinfo));
                cinfo.ifa_prefered = ia->prefix_pltime;
                cinfo.ifa_valid = ia->prefix_vltime;
index 55bee0c4191ce88d4fd526f4589c70e6d4779f36..7db7f3df49f2c0bbaf30d506e112d0a3e7d2d19a 100644 (file)
--- a/if-sun.c
+++ b/if-sun.c
@@ -546,26 +546,20 @@ if_readraw(struct interface *ifp, int fd,
 }
 
 int
-if_address(const struct interface *ifp, const struct in_addr *addr,
-    const struct in_addr *mask, const struct in_addr *bcast,
-    int action)
+if_address(unsigned char cmd, struct ipv4_addr *ia)
 {
 
-       UNUSED(ifp);
-       UNUSED(addr);
-       UNUSED(mask);
-       UNUSED(bcast);
-       UNUSED(action);
+       UNUSED(cmd);
+       UNUSED(ia);
        errno = ENOTSUP;
        return -1;
 }
 
 int
-if_addrflags(const struct in_addr *addr, const struct interface *ifp)
+if_addrflags(const struct ipv4_addr *ia)
 {
 
-       UNUSED(addr);
-       UNUSED(ifp);
+       UNUSED(ia);
        errno = ENOTSUP;
        return -1;
 }
@@ -646,21 +640,20 @@ if_initrt(struct dhcpcd_ctx *ctx)
 
 #ifdef INET6
 int
-if_address6(const struct ipv6_addr *addr, int action)
+if_address6(unsigned char cmd, const struct ipv6_addr *ia)
 {
 
-       UNUSED(addr);
+       UNUSED(cmd);
        UNUSED(action);
        errno = ENOTSUP;
        return -1;
 }
 
 int
-if_addrflags6(const struct in6_addr *addr, const struct interface *ifp)
+if_addrflags6(const struct ipv6_addr *ia)
 {
 
-       UNUSED(addr);
-       UNUSED(ifp);
+       UNUSED(ia);
        errno = ENOTSUP;
        return -1;
 }
diff --git a/if.h b/if.h
index b4a9f983e9e491fb1c83fc4b4cd6676a9cae49a4..0aaa47bde7df27ca76b3e48b57a1cfc7f6be8ad6 100644 (file)
--- a/if.h
+++ b/if.h
@@ -144,14 +144,7 @@ ssize_t if_sendraw(const struct interface *, int, uint16_t,
 ssize_t if_readraw(struct interface *, int, void *, size_t, int *);
 void if_closeraw(struct interface *, int);
 
-int if_address(const struct interface *,
-    const struct in_addr *, const struct in_addr *,
-    const struct in_addr *, int);
-#define if_addaddress(ifp, addr, net, brd)     \
-       if_address(ifp, addr, net, brd, 1)
-#define if_deladdress(ifp, addr, net)          \
-       if_address(ifp, addr, net, NULL, -1)
-
+int if_address(unsigned char, const struct ipv4_addr *);
 int if_addrflags(const struct in_addr *, const struct interface *);
 
 int if_route(unsigned char, const struct rt *rt);
@@ -168,10 +161,7 @@ int ip6_temp_valid_lifetime(const char *ifname);
 #define ip6_use_tempaddr(a) (0)
 #endif
 
-int if_address6(const struct ipv6_addr *, int);
-#define if_addaddress6(a) if_address6(a, 1)
-#define if_deladdress6(a) if_address6(a, -1)
-
+int if_address6(unsigned char, const struct ipv6_addr *);
 int if_addrflags6(const struct in6_addr *, const struct interface *);
 int if_getlifetime6(struct ipv6_addr *);
 
diff --git a/ipv4.c b/ipv4.c
index 4003438285e662524d7c8a593fd6f3990f944dfe..2e71278c563206f714c51695fd943aa6e7e820f1 100644 (file)
--- a/ipv4.c
+++ b/ipv4.c
@@ -203,31 +203,33 @@ ipv4_srcaddr(const struct rt *rt, struct in_addr *addr)
 
        /* Prefer DHCP source address if matching */
        dstate = D_CSTATE(rt->iface);
-       if (dstate &&
-           rt->mask.s_addr == dstate->mask.s_addr &&
-           rt->dest.s_addr == (dstate->addr.s_addr & dstate->mask.s_addr))
+       if (dstate && dstate->addr &&
+           rt->mask.s_addr == dstate->addr->mask.s_addr &&
+           rt->dest.s_addr ==
+           (dstate->addr->addr.s_addr & dstate->addr->mask.s_addr))
        {
-               *addr = dstate->addr;
+               *addr = dstate->addr->addr;
                return 1;
        }
 
        /* Then IPv4LL source address if matching */
        istate = IPV4LL_CSTATE(rt->iface);
-       if (istate &&
-           rt->mask.s_addr == inaddr_llmask.s_addr &&
-           rt->dest.s_addr == (istate->addr.s_addr & inaddr_llmask.s_addr))
+       if (istate && istate->addr &&
+           rt->mask.s_addr == istate->addr->mask.s_addr &&
+           rt->dest.s_addr ==
+           (istate->addr->addr.s_addr & istate->addr->mask.s_addr))
        {
-               *addr = istate->addr;
+               *addr = istate->addr->addr;
                return 1;
        }
 
        /* If neither match, return DHCP then IPv4LL */
-       if (dstate) {
-               *addr = dstate->addr;
+       if (dstate && dstate->addr) {
+               *addr = dstate->addr->addr;
                return 0;
        }
-       if (istate) {
-               *addr = istate->addr;
+       if (istate && istate->addr) {
+               *addr = istate->addr->addr;
                return 0;
        }
 
@@ -245,8 +247,8 @@ ipv4_hasaddr(const struct interface *ifp)
        istate = IPV4LL_CSTATE(ifp);
        return ((dstate &&
            dstate->added == STATE_ADDED &&
-           dstate->addr.s_addr != INADDR_ANY) ||
-           (istate && istate->addr.s_addr != INADDR_ANY));
+           dstate->addr != NULL) ||
+           (istate && istate->addr));
 }
 
 void
@@ -540,19 +542,19 @@ d_route(struct rt *rt)
 static struct rt_head *
 add_subnet_route(struct rt_head *rt, const struct interface *ifp)
 {
-       const struct dhcp_state *s;
+       const struct dhcp_state *state;
        struct rt *r;
 
        if (rt == NULL) /* earlier malloc failed */
                return NULL;
 
-       s = D_CSTATE(ifp);
+       state = D_CSTATE(ifp);
        /* Don't create a subnet route for these addresses */
-       if (s->mask.s_addr == INADDR_ANY)
+       if (state->addr->mask.s_addr == INADDR_ANY)
                return rt;
 #ifndef BSD
        /* BSD adds a route in this instance */
-       if (s->mask.s_addr == INADDR_BROADCAST)
+       if (state->addr->mask.s_addr == INADDR_BROADCAST)
                return rt;
 #endif
 
@@ -561,11 +563,11 @@ add_subnet_route(struct rt_head *rt, const struct interface *ifp)
                ipv4_freeroutes(rt);
                return NULL;
        }
-       r->dest.s_addr = s->addr.s_addr & s->mask.s_addr;
-       r->mask.s_addr = s->mask.s_addr;
+       r->dest.s_addr = state->addr->addr.s_addr & state->addr->mask.s_addr;
+       r->mask.s_addr = state->addr->mask.s_addr;
        r->gate.s_addr = INADDR_ANY;
        r->mtu = dhcp_get_mtu(ifp);
-       r->src = s->addr;
+       r->src = state->addr->addr;
 
        TAILQ_INSERT_HEAD(rt, r, next);
        return rt;
@@ -629,7 +631,7 @@ get_routes(struct interface *ifp)
        if (nrt) {
                state = D_CSTATE(ifp);
                TAILQ_FOREACH(rt, nrt, next) {
-                       rt->src = state->addr;
+                       rt->src = state->addr->addr;
                }
        }
 
@@ -655,9 +657,9 @@ add_destination_route(struct rt_head *rt, const struct interface *ifp)
        }
        r->dest.s_addr = INADDR_ANY;
        r->mask.s_addr = INADDR_ANY;
-       r->gate.s_addr = state->brd.s_addr;
+       r->gate = state->addr->brd;
        r->mtu = dhcp_get_mtu(ifp);
-       r->src = state->addr;
+       r->src = state->addr->addr;
        TAILQ_INSERT_HEAD(rt, r, next);
        return rt;
 }
@@ -731,7 +733,7 @@ add_router_host_route(struct rt_head *rt, const struct interface *ifp)
                rtn->mask.s_addr = htonl(INADDR_BROADCAST);
                rtn->gate.s_addr = htonl(INADDR_ANY);
                rtn->mtu = dhcp_get_mtu(ifp);
-               rtn->src = state->addr;
+               rtn->src = state->addr->addr;
                TAILQ_INSERT_BEFORE(rtp, rtn, next);
        }
        return rt;
@@ -884,49 +886,43 @@ ipv4_buildroutes(struct dhcpcd_ctx *ctx)
 }
 
 int
-ipv4_deladdr(struct interface *ifp,
-    const struct in_addr *addr, const struct in_addr *mask, int keeparp)
+ipv4_deladdr(struct ipv4_addr *addr, int keeparp)
 {
-       struct dhcp_state *dstate;
+       struct interface *ifp;
        int r;
        struct ipv4_state *state;
        struct ipv4_addr *ap;
        struct arp_state *astate;
-       uint32_t a, n;
 
-       logger(ifp->ctx, LOG_DEBUG,
-           "%s: deleting IP address %s/%d",
-           ifp->name, inet_ntoa(*addr), inet_ntocidr(*mask));
+       logger(addr->iface->ctx, LOG_DEBUG,
+           "%s: deleting IP address %s", addr->iface->name, addr->saddr);
 
-       r = if_deladdress(ifp, addr, mask);
+       r = if_address(RTM_DELADDR, addr);
        if (r == -1 && errno != EADDRNOTAVAIL && errno != ENXIO &&
            errno != ENODEV)
-               logger(ifp->ctx, LOG_ERR, "%s: %s: %m", ifp->name, __func__);
+               logger(addr->iface->ctx, LOG_ERR, "%s: %s: %m",
+                   addr->iface->name, __func__);
 
-       if (!keeparp && (astate = arp_find(ifp, addr)) != NULL)
+       if (!keeparp && (astate = arp_find(addr->iface, &addr->addr)) != NULL)
                arp_free(astate);
 
-       a = addr->s_addr;
-       n = mask->s_addr;
-       state = IPV4_STATE(ifp);
+       state = IPV4_STATE(addr->iface);
        TAILQ_FOREACH(ap, &state->addrs, next) {
-               if (ap->addr.s_addr == addr->s_addr &&
-                   ap->mask.s_addr == mask->s_addr)
-               {
+               if (IPV4_MASK_EQ(ap, addr)) {
+                       struct dhcp_state *dstate;
+
                        TAILQ_REMOVE(&state->addrs, ap, next);
                        free(ap);
+
+                       dstate = D_STATE(ifp);
+                       if (dstate && dstate->addr == ap) {
+                               dstate->added = 0;
+                               dstate->addr = NULL;
+                       }
                        break;
                }
        }
 
-       /* Have to do this last incase the function arguments
-        * were these very pointers. */
-       dstate = D_STATE(ifp);
-       if (dstate && dstate->addr.s_addr == a && dstate->mask.s_addr == n) {
-               dstate->added = 0;
-               dstate->addr.s_addr = 0;
-               dstate->mask.s_addr = 0;
-       }
        return r;
 }
 
@@ -942,7 +938,7 @@ delete_address(struct interface *ifp)
        if (ifo->options & DHCPCD_INFORM ||
            (ifo->options & DHCPCD_STATIC && ifo->req_addr.s_addr == 0))
                return 0;
-       r = ipv4_deladdr(ifp, &state->addr, &state->mask, 0);
+       r = ipv4_deladdr(state->addr, 0);
        return r;
 }
 
@@ -975,7 +971,6 @@ ipv4_addaddr(struct interface *ifp, const struct in_addr *addr,
 {
        struct ipv4_state *state;
        struct ipv4_addr *ia;
-       char bcast_str[INET_ADDRSTRLEN];
 
        if ((state = ipv4_getstate(ifp)) == NULL) {
                logger(ifp->ctx, LOG_ERR, "%s: ipv4_getstate: %m", __func__);
@@ -986,7 +981,7 @@ ipv4_addaddr(struct interface *ifp, const struct in_addr *addr,
 
                TAILQ_FOREACH_SAFE(ia, &state->addrs, next, ian) {
                        if (ia->addr.s_addr != addr->s_addr)
-                               ipv4_deladdr(ifp, &ia->addr, &ia->mask, 0);
+                               ipv4_deladdr(ia, 0);
                }
        }
 
@@ -995,17 +990,6 @@ ipv4_addaddr(struct interface *ifp, const struct in_addr *addr,
                return NULL;
        }
 
-       strlcpy(bcast_str, inet_ntoa(*bcast), sizeof(bcast_str));
-       logger(ifp->ctx, LOG_DEBUG, "%s: adding IP address %s/%d broadcast %s",
-           ifp->name, inet_ntoa(*addr), inet_ntocidr(*mask), bcast_str);
-       if (if_addaddress(ifp, addr, mask, bcast) == -1) {
-               if (errno != EEXIST)
-                       logger(ifp->ctx, LOG_ERR, "%s: if_addaddress: %m",
-                           __func__);
-               free(ia);
-               return NULL;
-       }
-
        ia->iface = ifp;
        ia->addr = *addr;
        ia->mask = *mask;
@@ -1013,6 +997,18 @@ ipv4_addaddr(struct interface *ifp, const struct in_addr *addr,
 #ifdef IN_IFF_TENTATIVE
        ia->addr_flags = IN_IFF_TENTATIVE;
 #endif
+       snprintf(ia->saddr, sizeof(ia->saddr), "%s/%d",
+           inet_ntoa(*addr), inet_ntocidr(*mask));
+       logger(ifp->ctx, LOG_DEBUG, "%s: adding IP address %s broadcast %s",
+           ifp->name, ia->saddr, inet_ntoa(*bcast));
+       if (if_address(RTM_NEWADDR, ia) == -1) {
+               if (errno != EEXIST)
+                       logger(ifp->ctx, LOG_ERR, "%s: if_addaddress: %m",
+                           __func__);
+               free(ia);
+               return NULL;
+       }
+
        TAILQ_INSERT_TAIL(&state->addrs, ia, next);
        return ia;
 }
@@ -1021,16 +1017,15 @@ static int
 ipv4_daddaddr(struct interface *ifp, const struct dhcp_lease *lease)
 {
        struct dhcp_state *state;
+       struct ipv4_addr *ia;
 
-       if (ipv4_addaddr(ifp, &lease->addr, &lease->mask, &lease->brd) == NULL)
+       ia = ipv4_addaddr(ifp, &lease->addr, &lease->mask, &lease->brd);
+       if (ia == NULL)
                return -1;
 
        state = D_STATE(ifp);
        state->added = STATE_ADDED;
-
-       state->addr.s_addr = lease->addr.s_addr;
-       state->mask.s_addr = lease->mask.s_addr;
-
+       state->addr = ia;
        return 0;
 }
 
@@ -1053,7 +1048,8 @@ ipv4_preferanother(struct interface *ifp)
                        break; /* We are already the most preferred */
                nstate = D_STATE(ifn);
                if (nstate && !nstate->added &&
-                   nstate->lease.addr.s_addr == state->addr.s_addr)
+                   state->addr != NULL &&
+                   nstate->lease.addr.s_addr == state->addr->addr.s_addr)
                {
                        preferred = 1;
                        delete_address(ifp);
@@ -1079,7 +1075,7 @@ ipv4_applyaddr(void *arg)
        struct dhcp_state *state = D_STATE(ifp), *nstate;
        struct dhcp_lease *lease;
        struct if_options *ifo = ifp->options;
-       struct ipv4_addr *ap;
+       struct ipv4_addr *ia;
        int r;
 
        if (state == NULL)
@@ -1111,7 +1107,8 @@ ipv4_applyaddr(void *arg)
                }
                nstate = D_STATE(ifn);
                if (nstate && nstate->added &&
-                   nstate->addr.s_addr == lease->addr.s_addr)
+                   nstate->addr &&
+                   nstate->addr->addr.s_addr == lease->addr.s_addr)
                {
                        if (r == 0) {
                                logger(ifp->ctx, LOG_INFO,
@@ -1125,7 +1122,7 @@ ipv4_applyaddr(void *arg)
                            ifn->name,
                            inet_ntoa(lease->addr),
                            ifp->name);
-                       ipv4_deladdr(ifn, &nstate->addr, &nstate->mask, 0);
+                       ipv4_deladdr(nstate->addr, 0);
                        break;
                }
        }
@@ -1135,53 +1132,52 @@ ipv4_applyaddr(void *arg)
                TAILQ_FOREACH(ifn, ifp->ctx->ifaces, next) {
                        if (ifn == ifp)
                                continue;
-                       ap = ipv4_iffindaddr(ifn, &lease->addr, NULL);
-                       if (ap)
-                               ipv4_deladdr(ifn, &ap->addr, &ap->mask, 0);
+                       ia = ipv4_iffindaddr(ifn, &lease->addr, NULL);
+                       if (ia != NULL)
+                               ipv4_deladdr(ia, 0);
                }
        }
 
        /* If the netmask or broadcast is different, re-add the addresss */
-       ap = ipv4_iffindaddr(ifp, &lease->addr, NULL);
-       if (ap &&
-           ap->mask.s_addr == lease->mask.s_addr &&
-           ap->brd.s_addr == lease->brd.s_addr)
+       ia = ipv4_iffindaddr(ifp, &lease->addr, NULL);
+       if (ia &&
+           ia->mask.s_addr == lease->mask.s_addr &&
+           ia->brd.s_addr == lease->brd.s_addr)
                logger(ifp->ctx, LOG_DEBUG,
-                   "%s: IP address %s/%d already exists",
-                   ifp->name, inet_ntoa(lease->addr),
-                   inet_ntocidr(lease->mask));
+                   "%s: IP address %s already exists",
+                   ifp->name, ia->saddr);
        else {
 #if __linux__
                /* Linux does not change netmask/broadcast address
                 * for re-added addresses, so we need to delete the old one
                 * first. */
-               if (ap != NULL)
-                       ipv4_deladdr(ifp, &ap->addr, &ap->mask, 0);
+               if (ia != NULL)
+                       ipv4_deladdr(ia, 0);
 #endif
                r = ipv4_daddaddr(ifp, lease);
                if (r == -1 && errno != EEXIST)
                        return;
        }
 
-#ifdef IN_IFF_NOTUSEABLE
-       ap = ipv4_iffindaddr(ifp, &lease->addr, NULL);
-       if (ap == NULL) {
+       ia = ipv4_iffindaddr(ifp, &lease->addr, NULL);
+       if (ia == NULL) {
                logger(ifp->ctx, LOG_ERR, "%s: added address vanished",
                    ifp->name);
                return;
-       } else if (ap->addr_flags & IN_IFF_NOTUSEABLE)
+       }
+#ifdef IN_IFF_NOTUSEABLE
+       if (ia->addr_flags & IN_IFF_NOTUSEABLE)
                return;
 #endif
 
        /* Delete the old address if different */
-       if (state->addr.s_addr != lease->addr.s_addr &&
-           state->addr.s_addr != 0 &&
+       if (state->addr &&
+           state->addr->addr.s_addr != lease->addr.s_addr &&
            ipv4_iffindaddr(ifp, &lease->addr, NULL))
                delete_address(ifp);
 
+       state->addr = ia;
        state->added = STATE_ADDED;
-       state->addr.s_addr = lease->addr.s_addr;
-       state->mask.s_addr = lease->mask.s_addr;
 
        /* Find any freshly added routes, such as the subnet route.
         * We do this because we cannot rely on recieving the kernel
@@ -1192,7 +1188,7 @@ ipv4_applyaddr(void *arg)
        if (ifo->options & DHCPCD_ARP) {
                struct arp_state *astate;
 
-               if ((astate = arp_new(ifp, &state->addr)) != NULL)
+               if ((astate = arp_new(ifp, &state->addr->addr)) != NULL)
                        arp_announce(astate);
        }
        if (state->state == DHS_BOUND) {
@@ -1209,7 +1205,7 @@ ipv4_handleifa(struct dhcpcd_ctx *ctx,
 {
        struct interface *ifp;
        struct ipv4_state *state;
-       struct ipv4_addr *ap;
+       struct ipv4_addr *ia;
 
        if (ifs == NULL)
                ifs = ctx->ifaces;
@@ -1228,46 +1224,56 @@ ipv4_handleifa(struct dhcpcd_ctx *ctx,
                return;
        }
 
-       ap = ipv4_iffindaddr(ifp, addr, NULL);
-       if (cmd == RTM_NEWADDR) {
-               if (ap == NULL) {
-                       if ((ap = malloc(sizeof(*ap))) == NULL) {
+       ia = ipv4_iffindaddr(ifp, addr, NULL);
+       switch (cmd) {
+       case RTM_NEWADDR:
+               if (ia == NULL) {
+                       if ((ia = malloc(sizeof(*ia))) == NULL) {
                                logger(ifp->ctx, LOG_ERR, "%s: %m", __func__);
                                return;
                        }
-                       ap->iface = ifp;
-                       ap->addr = *addr;
-                       TAILQ_INSERT_TAIL(&state->addrs, ap, next);
+                       ia->iface = ifp;
+                       ia->addr = *addr;
+                       TAILQ_INSERT_TAIL(&state->addrs, ia, next);
                }
-               ap->mask = *mask;
+               /* Mask could have changed */
+               ia->mask = *mask;
+               snprintf(ia->saddr, sizeof(ia->saddr), "%s/%d",
+                   inet_ntoa(*addr), inet_ntocidr(*mask));
                if (brd != NULL)
-                       ap->brd = *brd;
+                       ia->brd = *brd;
                else
-                       ap->brd.s_addr = INADDR_ANY;
-               ap->addr_flags = flags;
-       } else if (cmd == RTM_DELADDR) {
-               if (ap) {
-                       TAILQ_REMOVE(&state->addrs, ap, next);
-                       free(ap);
-               }
+                       ia->brd.s_addr = INADDR_ANY;
+               ia->addr_flags = flags;
+               break;
+       case RTM_DELADDR:
+               if (ia == NULL)
+                       return;
+               TAILQ_REMOVE(&state->addrs, ia, next);
+               break;
+       default:
+               return;
        }
 
-       arp_handleifa(cmd, ifp, addr, flags);
-       dhcp_handleifa(cmd, ifp, addr, mask, brd, flags);
+       arp_handleifa(cmd, ia);
+       dhcp_handleifa(cmd, ia);
+       
+       if (cmd == RTM_DELADDR)
+               free(ia);
 }
 
 void
 ipv4_free(struct interface *ifp)
 {
        struct ipv4_state *state;
-       struct ipv4_addr *addr;
+       struct ipv4_addr *ia;
 
        if (ifp) {
                state = IPV4_STATE(ifp);
                if (state) {
-                       while ((addr = TAILQ_FIRST(&state->addrs))) {
-                               TAILQ_REMOVE(&state->addrs, addr, next);
-                               free(addr);
+                       while ((ia = TAILQ_FIRST(&state->addrs))) {
+                               TAILQ_REMOVE(&state->addrs, ia, next);
+                               free(ia);
                        }
                        ipv4_freerts(&state->routes);
 #ifdef BSD
diff --git a/ipv4.h b/ipv4.h
index 3da7d46ef3c25c0ce74f0f8e9fe537d5d64ac980..9b1b89f75d57b36ad5fde524c96b30d0d9beda9b 100644 (file)
--- a/ipv4.h
+++ b/ipv4.h
@@ -75,9 +75,16 @@ struct ipv4_addr {
        struct in_addr brd;
        struct interface *iface;
        int addr_flags;
+       char saddr[INET_ADDRSTRLEN + 3];
 };
 TAILQ_HEAD(ipv4_addrhead, ipv4_addr);
 
+#define        IPV4_ADDR_EQ(a1, a2)    ((a1) && (a1)->addr.s_addr == (a2)->addr.s_addr)
+#define        IPV4_MASK1_EQ(a1, a2)   ((a1) && (a1)->mask.s_addr == (a2)->mask.s_addr)
+#define        IPV4_MASK_EQ(a1, a2)    (IPV4_ADDR_EQ(a1, a2) && IPV4_MASK1_EQ(a1, a2))
+#define        IPV4_BRD1_EQ(a1, a2)    ((a1) && (a1)->brd.s_addr == (a2)->brd.s_addr)
+#define        IPV4_BRD_EQ(a1, a2)     (IPV4_MASK_EQ(a1, a2) && IPV4_BRD1_EQ(a1, a2))
+
 struct ipv4_state {
        struct ipv4_addrhead addrs;
        struct rt_head routes;
@@ -107,8 +114,7 @@ int ipv4_hasaddr(const struct interface *);
 #define STATE_FAKE             0x02
 
 void ipv4_buildroutes(struct dhcpcd_ctx *);
-int ipv4_deladdr(struct interface *, const struct in_addr *,
-    const struct in_addr *, int);
+int ipv4_deladdr(struct ipv4_addr *, int);
 int ipv4_preferanother(struct interface *);
 struct ipv4_addr *ipv4_addaddr(struct interface *,
     const struct in_addr *, const struct in_addr *, const struct in_addr *);
index 6c165546a43fdb0b4bdcf98bff06235ee5608b04..287fb66b1e52c3d02777d645acf92cb5e7ffd738 100644 (file)
--- a/ipv4ll.c
+++ b/ipv4ll.c
@@ -1,6 +1,6 @@
 /*
  * dhcpcd - DHCP client daemon
- * Copyright (c) 2006-2015 Roy Marples <roy@marples.name>
+ * Copyright (c) 2006-2016 Roy Marples <roy@marples.name>
  * All rights reserved
 
  * Redistribution and use in source and binary forms, with or without
 #include "ipv4ll.h"
 #include "script.h"
 
-const struct in_addr inaddr_llmask = { HTONL(LINKLOCAL_MASK) };
-const struct in_addr inaddr_llbcast = { HTONL(LINKLOCAL_BRDC) };
+static const struct in_addr inaddr_llmask = { HTONL(LINKLOCAL_MASK) };
+static const struct in_addr inaddr_llbcast = { HTONL(LINKLOCAL_BCAST) };
 
 static in_addr_t
-ipv4ll_pick_addr(const struct arp_state *astate)
+ipv4ll_pickaddr(struct arp_state *astate)
 {
        struct in_addr addr;
        struct ipv4ll_state *istate;
@@ -75,8 +75,7 @@ ipv4ll_pick_addr(const struct arp_state *astate)
        } while (ipv4_findaddr(astate->iface->ctx, &addr) != NULL);
 
        /* Restore the original random state */
-       setstate(astate->iface->ctx->randomstate);
-
+       setstate(istate->arp->iface->ctx->randomstate);
        return addr.s_addr;
 }
 
@@ -88,7 +87,7 @@ ipv4ll_subnet_route(const struct interface *ifp)
 
        assert(ifp != NULL);
        if ((state = IPV4LL_CSTATE(ifp)) == NULL ||
-           state->addr.s_addr == INADDR_ANY)
+           state->addr == NULL)
                return NULL;
 
        if ((rt = calloc(1, sizeof(*rt))) == NULL) {
@@ -96,10 +95,10 @@ ipv4ll_subnet_route(const struct interface *ifp)
                return NULL;
        }
        rt->iface = ifp;
-       rt->dest.s_addr = state->addr.s_addr & inaddr_llmask.s_addr;
-       rt->mask = inaddr_llmask;
+       rt->dest.s_addr = state->addr->addr.s_addr & state->addr->mask.s_addr;
+       rt->mask.s_addr = state->addr->mask.s_addr;
        rt->gate.s_addr = INADDR_ANY;
-       rt->src = state->addr;
+       rt->src = state->addr->addr;
        return rt;
 }
 
@@ -111,7 +110,7 @@ ipv4ll_default_route(const struct interface *ifp)
 
        assert(ifp != NULL);
        if ((state = IPV4LL_CSTATE(ifp)) == NULL ||
-           state->addr.s_addr == INADDR_ANY)
+           state->addr == NULL)
                return NULL;
 
        if ((rt = calloc(1, sizeof(*rt))) == NULL) {
@@ -122,7 +121,7 @@ ipv4ll_default_route(const struct interface *ifp)
        rt->dest.s_addr = INADDR_ANY;
        rt->mask.s_addr = INADDR_ANY;
        rt->gate.s_addr = INADDR_ANY;
-       rt->src = state->addr;
+       rt->src = state->addr->addr;
        return rt;
 }
 
@@ -142,18 +141,18 @@ ipv4ll_env(char **env, const char *prefix, const struct interface *ifp)
 
        /* Emulate a DHCP environment */
        if (asprintf(&env[0], "%s%sip_address=%s",
-           prefix, pf, inet_ntoa(state->addr)) == -1)
+           prefix, pf, inet_ntoa(state->addr->addr)) == -1)
                return -1;
        if (asprintf(&env[1], "%s%ssubnet_mask=%s",
-           prefix, pf, inet_ntoa(inaddr_llmask)) == -1)
+           prefix, pf, inet_ntoa(state->addr->mask)) == -1)
                return -1;
        if (asprintf(&env[2], "%s%ssubnet_cidr=%d",
-           prefix, pf, inet_ntocidr(inaddr_llmask)) == -1)
+           prefix, pf, inet_ntocidr(state->addr->mask)) == -1)
                return -1;
        if (asprintf(&env[3], "%s%sbroadcast_address=%s",
-           prefix, pf, inet_ntoa(inaddr_llbcast)) == -1)
+           prefix, pf, inet_ntoa(state->addr->brd)) == -1)
                return -1;
-       netnum.s_addr = state->addr.s_addr & inaddr_llmask.s_addr;
+       netnum.s_addr = state->addr->addr.s_addr & state->addr->mask.s_addr;
        if (asprintf(&env[4], "%s%snetwork_number=%s",
            prefix, pf, inet_ntoa(netnum)) == -1)
                return -1;
@@ -195,7 +194,7 @@ ipv4ll_probed(struct arp_state *astate)
            ifp->name, inet_ntoa(astate->addr));
 #endif
 test:
-       state->addr = astate->addr;
+       state->addr = ia;
        if (ifp->ctx->options & DHCPCD_TEST) {
                script_runreason(ifp, "TEST");
                eloop_exit(ifp->ctx->eloop, EXIT_SUCCESS);
@@ -241,6 +240,7 @@ ipv4ll_conflicted(struct arp_state *astate, const struct arp_msg *amsg)
        ifp = astate->iface;
        state = IPV4LL_STATE(ifp);
        assert(state != NULL);
+       assert(state->addr != NULL);
 
        fail = 0;
        /* RFC 3927 2.2.1, Probe Conflict Detection */
@@ -250,9 +250,9 @@ ipv4ll_conflicted(struct arp_state *astate, const struct arp_msg *amsg)
                fail = astate->addr.s_addr;
 
        /* RFC 3927 2.5, Conflict Defense */
-       if (IN_LINKLOCAL(ntohl(state->addr.s_addr)) &&
-           amsg && amsg->sip.s_addr == state->addr.s_addr)
-               fail = state->addr.s_addr;
+       if (IN_LINKLOCAL(ntohl(state->addr->addr.s_addr)) &&
+           amsg && amsg->sip.s_addr == state->addr->addr.s_addr)
+               fail = state->addr->addr.s_addr;
 
        if (fail == 0)
                return;
@@ -260,7 +260,7 @@ ipv4ll_conflicted(struct arp_state *astate, const struct arp_msg *amsg)
        astate->failed.s_addr = fail;
        arp_report_conflicted(astate, amsg);
 
-       if (astate->failed.s_addr == state->addr.s_addr) {
+       if (astate->failed.s_addr == state->addr->addr.s_addr) {
                struct timespec now, defend;
 
                /* RFC 3927 Section 2.5 says a defence should
@@ -277,24 +277,23 @@ ipv4ll_conflicted(struct arp_state *astate, const struct arp_msg *amsg)
                if (timespeccmp(&defend, &now, >))
                        logger(ifp->ctx, LOG_WARNING,
                            "%s: IPv4LL %d second defence failed for %s",
-                           ifp->name, DEFEND_INTERVAL,
-                           inet_ntoa(state->addr));
+                           ifp->name, DEFEND_INTERVAL, state->addr->saddr);
                else if (arp_request(ifp,
-                   state->addr.s_addr, state->addr.s_addr) == -1)
+                   state->addr->addr.s_addr, state->addr->addr.s_addr) == -1)
                        logger(ifp->ctx, LOG_ERR,
                            "%s: arp_request: %m", __func__);
                else {
                        logger(ifp->ctx, LOG_DEBUG,
                            "%s: defended IPv4LL address %s",
-                           ifp->name, inet_ntoa(state->addr));
+                           ifp->name, state->addr->saddr);
                        state->defend = now;
                        return;
                }
 
-               ipv4_deladdr(ifp, &state->addr, &inaddr_llmask, 1);
+               ipv4_deladdr(state->addr, 1);
                state->down = 1;
+               state->addr = NULL;
                script_runreason(ifp, "IPV4LL");
-               state->addr.s_addr = INADDR_ANY;
        }
 
        arp_cancel(astate);
@@ -302,7 +301,7 @@ ipv4ll_conflicted(struct arp_state *astate, const struct arp_msg *amsg)
                logger(ifp->ctx, LOG_ERR,
                    "%s: failed to acquire an IPv4LL address",
                    ifp->name);
-       astate->addr.s_addr = ipv4ll_pick_addr(astate);
+       astate->addr.s_addr = ipv4ll_pickaddr(astate);
        eloop_timeout_add_sec(ifp->ctx->eloop,
                state->conflicts >= MAX_CONFLICTS ?
                RATE_LIMIT_INTERVAL : PROBE_WAIT,
@@ -335,8 +334,6 @@ ipv4ll_start(void *arg)
                        syslog(LOG_ERR, "%s: calloc %m", __func__);
                        return;
                }
-
-               state->addr.s_addr = INADDR_ANY;
        }
 
        if (state->arp != NULL)
@@ -395,7 +392,7 @@ ipv4ll_start(void *arg)
                        return;
                }
                logger(ifp->ctx, LOG_INFO, "%s: using IPv4LL address %s",
-                 ifp->name, inet_ntoa(astate->addr));
+                 ifp->name, ia->saddr);
 #endif
                ipv4ll_probed(astate);
                return;
@@ -403,7 +400,7 @@ ipv4ll_start(void *arg)
 
        logger(ifp->ctx, LOG_INFO, "%s: probing for an IPv4LL address",
            ifp->name);
-       astate->addr.s_addr = ipv4ll_pick_addr(astate);
+       astate->addr.s_addr = ipv4ll_pickaddr(astate);
 #ifdef IN_IFF_TENTATIVE
        ipv4ll_probed(astate);
 #else
@@ -431,9 +428,9 @@ ipv4ll_freedrop(struct interface *ifp, int drop)
        if (drop && (ifp->options->options & DHCPCD_NODROP) != DHCPCD_NODROP) {
                struct ipv4_state *istate;
 
-               if (state && state->addr.s_addr != INADDR_ANY) {
-                       ipv4_deladdr(ifp, &state->addr, &inaddr_llmask, 1);
-                       state->addr.s_addr = INADDR_ANY;
+               if (state && state->addr != NULL) {
+                       ipv4_deladdr(state->addr, 1);
+                       state->addr = NULL;
                        dropped = 1;
                }
 
@@ -443,8 +440,7 @@ ipv4ll_freedrop(struct interface *ifp, int drop)
 
                        TAILQ_FOREACH_SAFE(ia, &istate->addrs, next, ian) {
                                if (IN_LINKLOCAL(ntohl(ia->addr.s_addr))) {
-                                       ipv4_deladdr(ifp, &ia->addr,
-                                           &ia->mask, 0);
+                                       ipv4_deladdr(ia, 0);
                                        dropped = 1;
                                }
                        }
index 8350f534a398e8b70c6cc5a9b77c63ce44b919a9..5f7cee88650ba4a1f31f01b1b1483f77cf260c4b 100644 (file)
--- a/ipv4ll.h
+++ b/ipv4ll.h
@@ -1,6 +1,6 @@
 /*
  * dhcpcd - DHCP client daemon
- * Copyright (c) 2006-2015 Roy Marples <roy@marples.name>
+ * Copyright (c) 2006-2016 Roy Marples <roy@marples.name>
  * All rights reserved
 
  * Redistribution and use in source and binary forms, with or without
 #ifdef INET
 #include "arp.h"
 
-extern const struct in_addr inaddr_llmask;
-extern const struct in_addr inaddr_llbcast;
-
 #define LINKLOCAL_ADDR 0xa9fe0000
 #define LINKLOCAL_MASK IN_CLASSB_NET
-#define LINKLOCAL_BRDC (LINKLOCAL_ADDR | ~LINKLOCAL_MASK)
+#define LINKLOCAL_BCAST        (LINKLOCAL_ADDR | ~LINKLOCAL_MASK)
 
 #ifndef IN_LINKLOCAL
 # define IN_LINKLOCAL(addr) ((addr & IN_CLASSB_NET) == LINKLOCAL_ADDR)
 #endif
 
 struct ipv4ll_state {
-       struct in_addr addr;
+       struct ipv4_addr *addr;
        struct arp_state *arp;
        unsigned int conflicts;
        struct timespec defend;
@@ -56,8 +53,8 @@ struct ipv4ll_state {
 #define IPV4LL_CSTATE(ifp)                                                    \
        ((const struct ipv4ll_state *)(ifp)->if_data[IF_DATA_IPV4LL])
 #define IPV4LL_STATE_RUNNING(ifp)                                             \
-       (IPV4LL_CSTATE((ifp)) && !IPV4LL_CSTATE((ifp))->down &&        \
-       IN_LINKLOCAL(ntohl(IPV4LL_CSTATE((ifp))->addr.s_addr)))
+       (IPV4LL_CSTATE((ifp)) && !IPV4LL_CSTATE((ifp))->down &&                \
+       (IPV4LL_CSTATE((ifp))->addr != NULL))
 
 struct rt* ipv4ll_subnet_route(const struct interface *);
 struct rt* ipv4ll_default_route(const struct interface *);
diff --git a/ipv6.c b/ipv6.c
index 1e0f234a4ddd55d49b9df7a8f3e7c09aab476b25..05c9c3b5f953e421cd4cbfad4e89ad5a0e36428c 100644 (file)
--- a/ipv6.c
+++ b/ipv6.c
@@ -589,9 +589,9 @@ ipv6_deleteaddr(struct ipv6_addr *ia)
 
        logger(ia->iface->ctx, LOG_INFO, "%s: deleting address %s",
            ia->iface->name, ia->saddr);
-       if (if_deladdress6(ia) == -1 &&
+       if (if_address6(RTM_DELADDR, ia) == -1 &&
            errno != EADDRNOTAVAIL && errno != ENXIO && errno != ENODEV)
-               logger(ia->iface->ctx, LOG_ERR, "if_deladdress6: :%m");
+               logger(ia->iface->ctx, LOG_ERR, "if_address6: :%m");
 
        /* NOREJECT is set if we delegated exactly the prefix to another
         * address.
@@ -701,7 +701,7 @@ ipv6_addaddr(struct ipv6_addr *ap, const struct timespec *now)
 #endif
        }
 
-       if (if_addaddress6(ap) == -1) {
+       if (if_address6(RTM_NEWADDR, ap) == -1) {
                logger(ap->iface->ctx, LOG_ERR, "if_addaddress6: %m");
                /* Restore real pltime and vltime */
                ap->prefix_pltime = pltime;
@@ -824,10 +824,10 @@ ipv6_addaddrs(struct ipv6_addrhead *addrs)
                                    apf->iface->name,
                                    ap->saddr,
                                    ap->iface->name);
-                               if (if_deladdress6(apf) == -1 &&
+                               if (if_address6(RTM_DELADDR, apf) == -1 &&
                                    errno != EADDRNOTAVAIL && errno != ENXIO)
                                        logger(apf->iface->ctx, LOG_ERR,
-                                           "if_deladdress6: %m");
+                                           "if_address6: %m");
                                apf->flags &=
                                    ~(IPV6_AF_ADDED | IPV6_AF_DADCOMPLETED);
                        } else if (apf)
index 35da0136ec33138f06688a2fc91dfac96cea8d72..597be951efeba824123871f08ce71c9efa71d3f6 100644 (file)
--- a/ipv6nd.c
+++ b/ipv6nd.c
@@ -657,9 +657,9 @@ ipv6nd_dadcallback(void *arg)
                        }
                        logger(ifp->ctx, LOG_INFO, "%s: deleting address %s",
                                ifp->name, ap->saddr);
-                       if (if_deladdress6(ap) == -1 &&
+                       if (if_address6(RTM_DELADDR, ap) == -1 &&
                            errno != EADDRNOTAVAIL && errno != ENXIO)
-                               logger(ifp->ctx, LOG_ERR, "if_deladdress6: %m");
+                               logger(ifp->ctx, LOG_ERR, "if_address6: %m");
                        dadcounter = ap->dadcounter;
                        if (ipv6_makestableprivate(&ap->addr,
                            &ap->prefix, ap->prefix_len,
index 81d95cbce27bf866331cda1938c1fe23f55f325e..5b60d3077347161ecae99bec7498a8babb19998f 100644 (file)
--- a/script.c
+++ b/script.c
@@ -261,7 +261,7 @@ make_env(const struct interface *ifp, const char *reason, char ***argv)
                        ra = 1;
 #endif
 #ifdef INET
-               else if (istate && istate->addr.s_addr != INADDR_ANY)
+               else if (istate && istate->addr != NULL)
                        ipv4ll = 1;
                else
                        dhcp = 1;