]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Delete duplicated addresses.
authorRoy Marples <roy@marples.name>
Fri, 1 May 2015 14:02:36 +0000 (14:02 +0000)
committerRoy Marples <roy@marples.name>
Fri, 1 May 2015 14:02:36 +0000 (14:02 +0000)
dhcp.c
dhcpcd.c
ipv4.c
ipv4.h

diff --git a/dhcp.c b/dhcp.c
index 4fa3eb04c3ee96fa778d8b3ff1977a7f4f1ee817..abdfc7874b50939ef94447a268ec00b54d68ee0c 100644 (file)
--- a/dhcp.c
+++ b/dhcp.c
@@ -2415,6 +2415,10 @@ dhcp_arp_conflicted(struct arp_state *astate, const struct arp_msg *amsg)
            (amsg->sip.s_addr == 0 &&
            amsg->tip.s_addr == state->offer->yiaddr))))
        {
+#ifdef IN_IFF_DUPLICATED
+               struct ipv4_addr *ia;
+#endif
+
                if (amsg)
                        astate->failed.s_addr = state->offer->yiaddr;
                else
@@ -2423,6 +2427,11 @@ dhcp_arp_conflicted(struct arp_state *astate, const struct arp_msg *amsg)
                unlink(state->leasefile);
                if (!state->lease.frominfo)
                        dhcp_decline(astate->iface);
+#ifdef IN_IFF_DUPLICATED
+               ia = ipv4_iffindaddr(astate->iface, &astate->addr, NULL);
+               if (ia)
+                       ipv4_deladdr(astate->iface, &ia->addr, &ia->net);
+#endif
                eloop_timeout_delete(astate->iface->ctx->eloop, NULL,
                    astate->iface);
                eloop_timeout_add_sec(astate->iface->ctx->eloop,
@@ -2663,6 +2672,7 @@ dhcp_handledhcp(struct interface *ifp, struct dhcp_message **dhcpp,
                    ifp, dhcp, from);
                if (type)
                        dhcp_decline(ifp);
+               ipv4_deladdr(ifp, &ia->addr, &ia->net);
                eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
                eloop_timeout_add_sec(ifp->ctx->eloop,
                    DHCP_RAND_MAX, dhcp_discover, ifp);
@@ -3347,15 +3357,13 @@ dhcp_handleifa(int cmd, struct interface *ifp,
                return;
 
        if (cmd == RTM_DELADDR) {
-               if (state->new &&
-                   (state->new->yiaddr == addr->s_addr ||
-                   (state->new->yiaddr == INADDR_ANY &&
-                    state->new->ciaddr == addr->s_addr)))
+               if (state->addr.s_addr == addr->s_addr &&
+                   state->net.s_addr == net->s_addr)
                {
                        logger(ifp->ctx, LOG_INFO,
                            "%s: removing IP address %s/%d",
-                           ifp->name, inet_ntoa(state->lease.addr),
-                           inet_ntocidr(state->lease.net));
+                           ifp->name, inet_ntoa(state->addr),
+                           inet_ntocidr(state->net));
                        dhcp_drop(ifp, "EXPIRE");
                }
                return;
index a9fbc601f56749d562b915883fa5caefc52d7b45..76205e201e35be372efbd7109e3bb8c9b649663e 100644 (file)
--- a/dhcpcd.c
+++ b/dhcpcd.c
@@ -638,7 +638,9 @@ dhcpcd_handlecarrier(struct dhcpcd_ctx *ctx, int carrier, unsigned int flags,
                                    ifp->name);
                        ifp->carrier = LINK_DOWN;
                        script_runreason(ifp, "NOCARRIER");
-#ifndef NOCARRIER_PRESERVE_IP
+#ifdef NOCARRIER_PRESERVE_IP
+                       arp_close(ifp);
+#else
                        dhcpcd_drop(ifp, 0);
 #endif
                }
@@ -1716,7 +1718,6 @@ main(int argc, char **argv)
                }
        }
 
-
        if (ctx.options & DHCPCD_MASTER) {
                if (control_start(&ctx, NULL) == -1)
                        logger(&ctx, LOG_ERR, "control_start: %m");
diff --git a/ipv4.c b/ipv4.c
index 5f4acaa54b037b2f7ea6a0a63dfed5466fb4099e..e517bcbbf43ffb63597512840b150544325e44ea 100644 (file)
--- a/ipv4.c
+++ b/ipv4.c
@@ -731,21 +731,32 @@ ipv4_buildroutes(struct dhcpcd_ctx *ctx)
        ctx->ipv4_routes = nrs;
 }
 
-static int
-delete_address1(struct interface *ifp,
+int
+ipv4_deladdr(struct interface *ifp,
     const struct in_addr *addr, const struct in_addr *net)
 {
+       struct dhcp_state *dstate;
        int r;
        struct ipv4_state *state;
        struct ipv4_addr *ap;
 
        logger(ifp->ctx, LOG_DEBUG, "%s: deleting IP address %s/%d",
            ifp->name, inet_ntoa(*addr), inet_ntocidr(*net));
+
        r = if_deladdress(ifp, addr, net);
        if (r == -1 && errno != EADDRNOTAVAIL && errno != ENXIO &&
            errno != ENODEV)
                logger(ifp->ctx, LOG_ERR, "%s: %s: %m", ifp->name, __func__);
 
+       dstate = D_STATE(ifp);
+       if (dstate->addr.s_addr == addr->s_addr &&
+           dstate->net.s_addr == net->s_addr)
+       {
+               dstate->added = 0;
+               dstate->addr.s_addr = 0;
+               dstate->net.s_addr = 0;
+       }
+
        state = IPV4_STATE(ifp);
        TAILQ_FOREACH(ap, &state->addrs, next) {
                if (ap->addr.s_addr == addr->s_addr &&
@@ -771,10 +782,7 @@ delete_address(struct interface *ifp)
        if (ifo->options & DHCPCD_INFORM ||
            (ifo->options & DHCPCD_STATIC && ifo->req_addr.s_addr == 0))
                return 0;
-       r = delete_address1(ifp, &state->addr, &state->net);
-       state->added = 0;
-       state->addr.s_addr = 0;
-       state->net.s_addr = 0;
+       r = ipv4_deladdr(ifp, &state->addr, &state->net);
        return r;
 }
 
@@ -812,7 +820,7 @@ ipv4_addaddr(struct interface *ifp, const struct dhcp_lease *lease)
 
                TAILQ_FOREACH_SAFE(ia, &state->addrs, next, ian) {
                        if (ia->addr.s_addr != lease->addr.s_addr)
-                               delete_address1(ifp, &ia->addr, &ia->net);
+                               ipv4_deladdr(ifp, &ia->addr, &ia->net);
                }
        }
 
@@ -954,7 +962,7 @@ ipv4_applyaddr(void *arg)
                            ifn->name,
                            inet_ntoa(lease->addr),
                            ifp->name);
-                       delete_address1(ifn, &nstate->addr, &nstate->net);
+                       ipv4_deladdr(ifn, &nstate->addr, &nstate->net);
                        nstate->added = 0;
                        break;
                }
@@ -967,14 +975,14 @@ ipv4_applyaddr(void *arg)
                                continue;
                        ap = ipv4_iffindaddr(ifn, &lease->addr, NULL);
                        if (ap)
-                               delete_address1(ifn, &ap->addr, &ap->net);
+                               ipv4_deladdr(ifn, &ap->addr, &ap->net);
                }
        }
 
        /* If the netmask is different, delete the addresss */
        ap = ipv4_iffindaddr(ifp, &lease->addr, NULL);
        if (ap && ap->net.s_addr != lease->net.s_addr)
-               delete_address1(ifp, &ap->addr, &ap->net);
+               ipv4_deladdr(ifp, &ap->addr, &ap->net);
 
        if (ipv4_iffindaddr(ifp, &lease->addr, &lease->net))
                logger(ifp->ctx, LOG_DEBUG,
diff --git a/ipv4.h b/ipv4.h
index ed694c9278447b5291c498cf927c5c1bad327ac3..cd52c41b81ecfe92d4b5152304abfc5577e44520 100644 (file)
--- a/ipv4.h
+++ b/ipv4.h
@@ -82,6 +82,8 @@ int ipv4_addrexists(struct dhcpcd_ctx *, const struct in_addr *);
 
 void ipv4_buildroutes(struct dhcpcd_ctx *);
 void ipv4_finaliseaddr(struct interface *);
+int ipv4_deladdr(struct interface *ifp, const struct in_addr *,
+    const struct in_addr *);
 void ipv4_applyaddr(void *);
 int ipv4_handlert(struct dhcpcd_ctx *, int, struct rt *);
 void ipv4_freerts(struct rt_head *);