From: Roy Marples Date: Fri, 1 May 2015 09:53:45 +0000 (+0000) Subject: Add initial support for keeping addresses at carrier down for supported platforms. X-Git-Tag: v6.8.2~11 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bee534494cdd5891de0aee4e62500437cc3e3af2;p=thirdparty%2Fdhcpcd.git Add initial support for keeping addresses at carrier down for supported platforms. --- diff --git a/dhcp.c b/dhcp.c index 08b75eaa..8d2d946f 100644 --- 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) { diff --git a/dhcpcd.c b/dhcpcd.c index c91fce84..c5389d5c 100644 --- 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 */ diff --git a/if-options.h b/if-options.h index 8a8f23da..5544e23c 100644 --- a/if-options.h +++ b/if-options.h @@ -112,6 +112,10 @@ #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 8330ad75..e4f31eb6 100644 --- a/if.h +++ b/if.h @@ -43,6 +43,14 @@ # 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"