]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
The noalias directive will now remove any IPv4 addresses existing on
authorRoy Marples <roy@marples.name>
Sat, 13 Dec 2014 13:35:18 +0000 (13:35 +0000)
committerRoy Marples <roy@marples.name>
Sat, 13 Dec 2014 13:35:18 +0000 (13:35 +0000)
the interface when we want to add our own.

dhcpcd.conf.5.in
if-bsd.c
if.h
ipv4.c

index 93e74e2b75c6972817e091bd9571f15fc0f1727b..d721fc41fb279846a8d9c9637b34409f5a6e62cf 100644 (file)
@@ -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.
index 728228c36da3bf7783751d657dc46e501d4de4a0..6a9ddc1ed7024f5b83eaaa841a095a1a2d49c37d 100644 (file)
--- a/if-bsd.c
+++ b/if-bsd.c
@@ -46,6 +46,7 @@
 #include <net/route.h>
 #include <netinet/if_ether.h>
 #include <netinet/in.h>
+#include <netinet/in_var.h>
 #include <netinet6/in6_var.h>
 #include <netinet6/nd6.h>
 #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 4f874cb41baad492f3dcc35d4773c5c3adb4f815..6df696749e646bb5813061cad88787de668add91 100644 (file)
--- 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 0d3c74f3a33a5ddd63bf73f5a3c3165ff06b0bdc..d22e77ac8e4fa39a7fd602cef0ba917469e411e3 100644 (file)
--- 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;