From: Roy Marples Date: Wed, 18 May 2016 16:23:28 +0000 (+0000) Subject: Rework if_address to just use an ipv4_addr structure, similar to how X-Git-Tag: v6.11.1~41 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=109146e29e2eadcff467d273018d789359fa11e1;p=thirdparty%2Fdhcpcd.git Rework if_address to just use an ipv4_addr structure, similar to how 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. --- diff --git a/arp.c b/arp.c index 64f12371..ad4eb8f4 100644 --- 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 b9636662..b844e498 100644 --- 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 833568c9..32d2f907 100644 --- 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 dbb7b1c2..f573735f 100644 --- 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 *); diff --git a/if-bsd.c b/if-bsd.c index ed8f82b0..2d8bd9f9 100644 --- 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); } diff --git a/if-linux.c b/if-linux.c index 21a2c317..4085b9f0 100644 --- a/if-linux.c +++ b/if-linux.c @@ -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; diff --git a/if-sun.c b/if-sun.c index 55bee0c4..7db7f3df 100644 --- 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 b4a9f983..0aaa47bd 100644 --- 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 40034382..2e71278c 100644 --- 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 3da7d46e..9b1b89f7 100644 --- 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 *); diff --git a/ipv4ll.c b/ipv4ll.c index 6c165546..287fb66b 100644 --- a/ipv4ll.c +++ b/ipv4ll.c @@ -1,6 +1,6 @@ /* * dhcpcd - DHCP client daemon - * Copyright (c) 2006-2015 Roy Marples + * Copyright (c) 2006-2016 Roy Marples * All rights reserved * Redistribution and use in source and binary forms, with or without @@ -45,11 +45,11 @@ #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; } } diff --git a/ipv4ll.h b/ipv4ll.h index 8350f534..5f7cee88 100644 --- a/ipv4ll.h +++ b/ipv4ll.h @@ -1,6 +1,6 @@ /* * dhcpcd - DHCP client daemon - * Copyright (c) 2006-2015 Roy Marples + * Copyright (c) 2006-2016 Roy Marples * All rights reserved * Redistribution and use in source and binary forms, with or without @@ -31,19 +31,16 @@ #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 1e0f234a..05c9c3b5 100644 --- 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) diff --git a/ipv6nd.c b/ipv6nd.c index 35da0136..597be951 100644 --- 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, diff --git a/script.c b/script.c index 81d95cbc..5b60d307 100644 --- 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;