From: Roy Marples Date: Sat, 13 Dec 2014 13:35:18 +0000 (+0000) Subject: The noalias directive will now remove any IPv4 addresses existing on X-Git-Tag: v6.6.6~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=dffe72f6a66611bfd280efaa10465b91bd0d41a4;p=thirdparty%2Fdhcpcd.git The noalias directive will now remove any IPv4 addresses existing on the interface when we want to add our own. --- diff --git a/dhcpcd.conf.5.in b/dhcpcd.conf.5.in index 93e74e2b..d721fc41 100644 --- a/dhcpcd.conf.5.in +++ b/dhcpcd.conf.5.in @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd October 3, 2014 +.Dd December 13, 2014 .Dt DHCPCD.CONF 5 .Os .Sh NAME @@ -376,8 +376,8 @@ will supply a default metric of 200 + .Xr if_nametoindex 3 . An extra 100 will be added for wireless interfaces. .It Ic noalias -IPv4 addresses added will overwrite a pre-existing address instead of working -alongside. +Any pre-existing IPv4 addresses existing address will be removed from the +interface when adding a new IPv4 address. .It Ic noarp Don't send any ARP requests. This also disables IPv4LL. diff --git a/if-bsd.c b/if-bsd.c index 728228c3..6a9ddc1e 100644 --- a/if-bsd.c +++ b/if-bsd.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #ifdef __DragonFly__ @@ -418,40 +419,32 @@ next: } int -if_address(const struct interface *iface, const struct in_addr *address, +if_address(const struct interface *ifp, const struct in_addr *address, const struct in_addr *netmask, const struct in_addr *broadcast, int action) { int s, r; - struct ifaliasreq ifa; - union { - struct sockaddr *sa; - struct sockaddr_in *sin; - } _s; + struct in_aliasreq ifra; if ((s = socket(PF_INET, SOCK_DGRAM, 0)) == -1) return -1; - memset(&ifa, 0, sizeof(ifa)); - strlcpy(ifa.ifra_name, iface->name, sizeof(ifa.ifra_name)); - -#define ADDADDR(_var, _addr) { \ - _s.sa = &_var; \ - _s.sin->sin_family = AF_INET; \ - _s.sin->sin_len = sizeof(*_s.sin); \ - memcpy(&_s.sin->sin_addr, _addr, sizeof(_s.sin->sin_addr)); \ - } - - ADDADDR(ifa.ifra_addr, address); - ADDADDR(ifa.ifra_mask, netmask); - if (action >= 0 && broadcast) { - ADDADDR(ifa.ifra_broadaddr, broadcast); - } + memset(&ifra, 0, sizeof(ifra)); + strlcpy(ifra.ifra_name, ifp->name, sizeof(ifra.ifra_name)); + +#define ADDADDR(var, addr) do { \ + (var)->sin_family = AF_INET; \ + (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); #undef ADDADDR r = ioctl(s, - action < 0 ? SIOCDIFADDR : - action == 2 ? SIOCSIFADDR : SIOCAIFADDR, &ifa); + action < 0 ? SIOCDIFADDR : SIOCAIFADDR, &ifra); close(s); return r; } diff --git a/if.h b/if.h index 4f874cb4..6df69674 100644 --- a/if.h +++ b/if.h @@ -111,12 +111,10 @@ ssize_t if_readrawpacket(struct interface *, int, void *, size_t, int *); int if_address(const struct interface *, const struct in_addr *, const struct in_addr *, const struct in_addr *, int); -#define if_addaddress(iface, addr, net, brd) \ - if_address(iface, addr, net, brd, 1) -#define if_setaddress(iface, addr, net, brd) \ - if_address(iface, addr, net, brd, 2) -#define if_deladdress(iface, addr, net) \ - if_address(iface, addr, net, NULL, -1) +#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_route(const struct rt *rt, int); #define if_addroute(rt) if_route(rt, 1) diff --git a/ipv4.c b/ipv4.c index 0d3c74f3..d22e77ac 100644 --- a/ipv4.c +++ b/ipv4.c @@ -729,19 +729,25 @@ ipv4_getstate(struct interface *ifp) } static int -ipv4_addaddr(const struct interface *ifp, const struct dhcp_lease *lease) +ipv4_addaddr(struct interface *ifp, const struct dhcp_lease *lease) { int r; + if (ifp->options->options & DHCPCD_NOALIAS) { + struct ipv4_state *state; + struct ipv4_addr *ap, *apn; + + state = IPV4_STATE(ifp); + TAILQ_FOREACH_SAFE(ap, &state->addrs, next, apn) { + if (ap->addr.s_addr != lease->addr.s_addr) + delete_address1(ifp, &ap->addr, &ap->net); + } + } + syslog(LOG_DEBUG, "%s: adding IP address %s/%d", ifp->name, inet_ntoa(lease->addr), inet_ntocidr(lease->net)); - if (ifp->options->options & DHCPCD_NOALIAS) - r = if_setaddress(ifp, - &lease->addr, &lease->net, &lease->brd); - else - r = if_addaddress(ifp, - &lease->addr, &lease->net, &lease->brd); + r = if_addaddress(ifp, &lease->addr, &lease->net, &lease->brd); if (r == -1 && errno != EEXIST) syslog(LOG_ERR, "%s: if_addaddress: %m", __func__); return r; @@ -868,7 +874,8 @@ ipv4_applyaddr(void *arg) /* Now delete the old address if different */ if (state->addr.s_addr != lease->addr.s_addr && - state->addr.s_addr != 0) + state->addr.s_addr != 0 && + ipv4_iffindaddr(ifp, &lease->addr, NULL)) delete_address(ifp); state->added = STATE_ADDED;