]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Add initial support for keeping addresses at carrier down for supported platforms.
authorRoy Marples <roy@marples.name>
Fri, 1 May 2015 09:53:45 +0000 (09:53 +0000)
committerRoy Marples <roy@marples.name>
Fri, 1 May 2015 09:53:45 +0000 (09:53 +0000)
dhcp.c
dhcpcd.c
if-options.h
if.h

diff --git a/dhcp.c b/dhcp.c
index 08b75eaac6aeba4fa27fa3e87ae99ab3ed05d32c..8d2d946f7e8351019185f0bd8d59f5167148e6f6 100644 (file)
--- a/dhcp.c
+++ b/dhcp.c
@@ -1986,6 +1986,8 @@ applyaddr:
 #ifdef IN_IFF_TENTATIVE
                if (astate)
                        arp_free_but(astate);
+               else if (!ipv4ll)
+                       arp_close(ifp);
 #else
                if (state->added) {
                        if (astate == NULL) {
index c91fce84a024878276fd1cbba5d89b2e20d35c6d..c5389d5cfa7028f6ca1ad50e9792d5c875c048f3 100644 (file)
--- a/dhcpcd.c
+++ b/dhcpcd.c
@@ -350,7 +350,7 @@ stop_interface(struct interface *ifp)
 }
 
 static void
-configure_interface1(struct interface *ifp)
+configure_interface1(struct interface *ifp, struct if_options *old)
 {
        struct if_options *ifo = ifp->options;
        int ra_global, ra_iface;
@@ -516,6 +516,16 @@ configure_interface1(struct interface *ifp)
        /* If we are not sending an authentication option, don't require it */
        if (!(ifo->auth.options & DHCPCD_AUTH_SEND))
                ifo->auth.options &= ~DHCPCD_AUTH_REQUIRE;
+
+       /* If we ARPing something or options have changed,
+        * drop leases and restart */
+       if (old) {
+               /* Remove warning options for a fair comparison */
+               old->options &= ~(DHCPCD_WARNINGS | DHCPCD_CONF);
+               if (ifo->arping_len || memcmp(ifo, old, sizeof(*old)))
+                       dhcpcd_drop(ifp, 0);
+               free(old);
+       }
 }
 
 int
@@ -548,10 +558,17 @@ dhcpcd_selectprofile(struct interface *ifp, const char *profile)
                    ifp->name, profile);
        } else
                *ifp->profile = '\0';
-       free_options(ifp->options);
-       ifp->options = ifo;
-       if (profile)
-               configure_interface1(ifp);
+
+       if (profile) {
+               struct if_options *old;
+
+               old = ifp->options;
+               ifp->options = ifo;
+               configure_interface1(ifp, old);
+       } else {
+               free_options(ifp->options);
+               ifp->options = ifo;
+       }
        return 1;
 }
 
@@ -559,11 +576,13 @@ static void
 configure_interface(struct interface *ifp, int argc, char **argv,
     unsigned long long options)
 {
+       struct if_options *old;
 
+       old = ifp->options;
        dhcpcd_selectprofile(ifp, NULL);
        add_options(ifp->ctx, ifp->name, ifp->options, argc, argv);
        ifp->options->options |= options;
-       configure_interface1(ifp);
+       configure_interface1(ifp, old);
 }
 
 static void
@@ -624,14 +643,18 @@ dhcpcd_handlecarrier(struct dhcpcd_ctx *ctx, int carrier, unsigned int flags,
        } else if (carrier == LINK_DOWN || (ifp->flags & IFF_UP) == 0) {
                if (ifp->carrier != LINK_DOWN) {
                        if (ifp->carrier == LINK_UP)
-                               logger(ctx, LOG_INFO, "%s: carrier lost", ifp->name);
+                               logger(ctx, LOG_INFO, "%s: carrier lost",
+                                   ifp->name);
                        ifp->carrier = LINK_DOWN;
                        script_runreason(ifp, "NOCARRIER");
+#ifndef NOCARRIER_PRESERVE_IP
                        dhcpcd_drop(ifp, 0);
+#endif
                }
        } else if (carrier == LINK_UP && ifp->flags & IFF_UP) {
                if (ifp->carrier != LINK_UP) {
-                       logger(ctx, LOG_INFO, "%s: carrier acquired", ifp->name);
+                       logger(ctx, LOG_INFO, "%s: carrier acquired",
+                           ifp->name);
                        ifp->carrier = LINK_UP;
 #if !defined(__linux__) && !defined(__NetBSD__)
                        /* BSD does not emit RTM_NEWADDR or RTM_CHGADDR when the
@@ -639,8 +662,20 @@ dhcpcd_handlecarrier(struct dhcpcd_ctx *ctx, int carrier, unsigned int flags,
                         * through the disovery process to work it out. */
                        dhcpcd_handleinterface(ctx, 0, ifp->name);
 #endif
-                       if (ifp->wireless)
+                       if (ifp->wireless) {
+                               size_t olen;
+                               uint8_t ossid[IF_SSIDSIZE];
+
+                               olen = ifp->ssid_len;
+                               memcpy(ossid, ifp->ssid, ifp->ssid_len);
                                if_getssid(ifp);
+#ifdef NOCARRIER_PRESERVE_IP
+                               /* If we changed SSID network, drop leases */
+                               if (ifp->ssid_len != olen ||
+                                   memcmp(ifp->ssid, ossid, ifp->ssid_len))
+                                       dhcpcd_drop(ifp, 0);
+#endif
+                       }
                        dhcpcd_initstate(ifp, 0);
                        script_runreason(ifp, "CARRIER");
                        /* RFC4941 Section 3.5 */
index 8a8f23da97894d3e39fb37c60179392019a636d8..5544e23cdb9502596d1bad5e1aad59bb59469939 100644 (file)
 #define DHCPCD_IPV6RA_ACCEPT_NOPUBLIC  (1ULL << 56)
 #define DHCPCD_BOOTP                   (1ULL << 57)
 
+#define DHCPCD_WARNINGS (DHCPCD_CSR_WARNED | \
+               DHCPCD_ROUTER_HOST_ROUTE_WARNED)
+#define DHCPCD_CONF (DHCPCD_NOPFXDLG | DHCPCD_PFXDLGONLY)
+
 extern const struct option cf_options[];
 
 struct if_sla {
diff --git a/if.h b/if.h
index 8330ad7528014dd85904b66fa4712f25c09d44b5..e4f31eb6abae6bf2323412dc3c9e4ac7ced58d66 100644 (file)
--- a/if.h
+++ b/if.h
 # endif
 #endif
 
+/* Some systems have in-built IPv4 DAD.
+ * However, we need them to do DAD at carrier up as well. */
+#ifdef IN_IFF_TENTATIVE
+#  ifdef __NetBSD__
+#    define NOCARRIER_PRESERVE_IP
+#  endif
+#endif
+
 #include "config.h"
 #include "dhcpcd.h"
 #include "ipv4.h"