From: Roy Marples Date: Fri, 1 May 2015 12:39:06 +0000 (+0000) Subject: If config file changed, drop leases and re-disover. X-Git-Tag: v6.8.2~9 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=727d8459220f711b9c74753933ed4f47bb658a42;p=thirdparty%2Fdhcpcd.git If config file changed, drop leases and re-disover. Fix minor issues with IN_IFF_TENTATIVE. --- diff --git a/arp.c b/arp.c index 614a7b66..01a8ba44 100644 --- a/arp.c +++ b/arp.c @@ -41,6 +41,7 @@ #define ELOOP_QUEUE 5 #include "config.h" #include "arp.h" +#include "if.h" #include "ipv4.h" #include "common.h" #include "dhcp.h" @@ -406,7 +407,7 @@ arp_handleifa(int cmd, struct interface *ifp, const struct in_addr *addr, if (flags & IN_IFF_DUPLICATED) { if (astate->conflicted_cb) astate->conflicted_cb(astate, NULL); - } else if (!(flags & IN_IFF_TENTATIVE)) { + } else if (!(flags & IN_IFF_NOTUSEABLE)) { if (astate->probed_cb) astate->probed_cb(astate); } diff --git a/dhcp.c b/dhcp.c index 8d2d946f..67e0b505 100644 --- a/dhcp.c +++ b/dhcp.c @@ -1589,6 +1589,9 @@ send_message(struct interface *ifp, uint8_t type, in_addr_t a = INADDR_ANY; struct timespec tv; int s; +#ifdef IN_IFF_NOTUSEABLE + struct ipv4_addr *ia; +#endif if (!callback) logger(ifp->ctx, LOG_DEBUG, "%s: sending %s with xid 0x%x", @@ -1621,6 +1624,10 @@ send_message(struct interface *ifp, uint8_t type, if (state->added && !(state->added & STATE_FAKE) && state->addr.s_addr != INADDR_ANY && state->new != NULL && +#ifdef IN_IFF_NOTUSEABLE + ((ia = ipv4_iffindaddr(ifp, &state->addr, NULL)) && + !(ia->addr_flags & IN_IFF_NOTUSEABLE)) && +#endif (state->new->cookie == htonl(MAGIC_COOKIE) || ifp->options->options & DHCPCD_INFORM)) { @@ -2438,6 +2445,9 @@ dhcp_handledhcp(struct interface *ifp, struct dhcp_message **dhcpp, size_t auth_len; char *msg; struct arp_state *astate; +#ifdef IN_IFF_DUPLICATED + struct ipv4_addr *ia; +#endif /* We may have found a BOOTP server */ if (get_option_uint8(ifp->ctx, &type, dhcp, DHO_MESSAGETYPE) == -1) @@ -2648,13 +2658,23 @@ dhcp_handledhcp(struct interface *ifp, struct dhcp_message **dhcpp, return; } - if ((type == 0 || type == DHCP_OFFER) && - (state->state == DHS_DISCOVER || state->state == DHS_IPV4LL_BOUND)) - { #ifdef IN_IFF_DUPLICATED - struct ipv4_addr *ia; + ia = ipv4_iffindaddr(ifp, &lease->addr, NULL); + if (ia && ia->addr_flags & IN_IFF_DUPLICATED) { + log_dhcp(LOG_WARNING, "declined duplicate address", + ifp, dhcp, from); + if (type) + dhcp_decline(ifp); + eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp); + eloop_timeout_add_sec(ifp->ctx->eloop, + DHCP_RAND_MAX, dhcp_discover, ifp); + return; + } #endif + if ((type == 0 || type == DHCP_OFFER) && + (state->state == DHS_DISCOVER || state->state == DHS_IPV4LL_BOUND)) + { lease->frominfo = 0; lease->addr.s_addr = dhcp->yiaddr; lease->cookie = dhcp->cookie; @@ -2663,18 +2683,6 @@ dhcp_handledhcp(struct interface *ifp, struct dhcp_message **dhcpp, &lease->server, dhcp, DHO_SERVERID) != 0) lease->server.s_addr = INADDR_ANY; log_dhcp(LOG_INFO, "offered", ifp, dhcp, from); -#ifdef IN_IFF_DUPLICATED - ia = ipv4_iffindaddr(ifp, &lease->addr, NULL); - if (ia && ia->addr_flags & IN_IFF_DUPLICATED) { - log_dhcp(LOG_WARNING, "declined duplicate address", - ifp, dhcp, from); - dhcp_decline(ifp); - eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp); - eloop_timeout_add_sec(ifp->ctx->eloop, - DHCP_RAND_MAX, dhcp_discover, ifp); - return; - } -#endif free(state->offer); state->offer = dhcp; *dhcpp = NULL; @@ -2739,13 +2747,19 @@ dhcp_handledhcp(struct interface *ifp, struct dhcp_message **dhcpp, lease->frominfo = 0; eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp); astate = NULL; - if (ifo->options & DHCPCD_ARP && - state->addr.s_addr != state->offer->yiaddr) + +#ifndef IN_IFF_TENTATIVE + if (ifo->options & DHCPCD_ARP + && state->addr.s_addr != state->offer->yiaddr) +#endif { + addr.s_addr = state->offer->yiaddr; +#ifndef IN_IFF_TENTATIVE /* If the interface already has the address configured * then we can't ARP for duplicate detection. */ - addr.s_addr = state->offer->yiaddr; - if (!ipv4_iffindaddr(ifp, &addr, NULL)) { + ia = ipv4_findaddr(ifp->ctx, &addr); + if (ia) { +#endif astate = arp_new(ifp, &addr); if (astate) { astate->probed_cb = dhcp_arp_probed; @@ -2756,8 +2770,8 @@ dhcp_handledhcp(struct interface *ifp, struct dhcp_message **dhcpp, } #ifndef IN_IFF_TENTATIVE return; -#endif } +#endif } dhcp_bind(ifp, astate); @@ -3141,7 +3155,8 @@ dhcp_start1(void *arg) /* Don't log an error if some other process * is handling this. */ if (errno != EADDRINUSE) - logger(ifp->ctx, LOG_ERR, "dhcp_openudp: %m"); + logger(ifp->ctx, LOG_ERR, + "%s: dhcp_openudp: %m", __func__); } else eloop_event_add(ifp->ctx->eloop, ifp->ctx->udp_fd, dhcp_handleudp, diff --git a/dhcpcd.c b/dhcpcd.c index c5389d5c..a9fbc601 100644 --- a/dhcpcd.c +++ b/dhcpcd.c @@ -350,7 +350,7 @@ stop_interface(struct interface *ifp) } static void -configure_interface1(struct interface *ifp, struct if_options *old) +configure_interface1(struct interface *ifp) { struct if_options *ifo = ifp->options; int ra_global, ra_iface; @@ -516,16 +516,6 @@ configure_interface1(struct interface *ifp, struct if_options *old) /* 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 @@ -559,16 +549,10 @@ dhcpcd_selectprofile(struct interface *ifp, const char *profile) } else *ifp->profile = '\0'; - if (profile) { - struct if_options *old; - - old = ifp->options; - ifp->options = ifo; - configure_interface1(ifp, old); - } else { - free_options(ifp->options); - ifp->options = ifo; - } + free_options(ifp->options); + ifp->options = ifo; + if (profile) + configure_interface1(ifp); return 1; } @@ -576,13 +560,20 @@ static void configure_interface(struct interface *ifp, int argc, char **argv, unsigned long long options) { - struct if_options *old; + time_t old; - old = ifp->options; + old = ifp->options ? ifp->options->mtime : 0; dhcpcd_selectprofile(ifp, NULL); add_options(ifp->ctx, ifp->name, ifp->options, argc, argv); ifp->options->options |= options; - configure_interface1(ifp, old); + configure_interface1(ifp); + + /* If the mtime has changed drop any old lease */ + if (ifp->options && old != 0 && ifp->options->mtime != old) { + logger(ifp->ctx, LOG_WARNING, + "%s: confile file changed, expiring leases", ifp->name); + dhcpcd_drop(ifp, 0); + } } static void diff --git a/if-options.c b/if-options.c index 4a4c6507..85b6e8e5 100644 --- a/if-options.c +++ b/if-options.c @@ -28,6 +28,7 @@ #define _WITH_GETLINE /* Stop FreeBSD bitching */ #include +#include #include #include @@ -2040,6 +2041,7 @@ read_config(struct dhcpcd_ctx *ctx, { struct if_options *ifo; FILE *fp; + struct stat sb; char *line, *buf, *option, *p; size_t buflen; ssize_t vlen; @@ -2196,6 +2198,8 @@ read_config(struct dhcpcd_ctx *ctx, free(buf); return ifo; } + if (stat(ctx->cffile, &sb) == 0) + ifo->mtime = sb.st_mtime; ldop = edop = NULL; while ((line = get_line(&buf, &buflen, fp))) { diff --git a/if-options.h b/if-options.h index 5544e23c..4d1de15d 100644 --- a/if-options.h +++ b/if-options.h @@ -144,6 +144,7 @@ struct vivco { }; struct if_options { + time_t mtime; uint8_t iaid[4]; int metric; uint8_t requestmask[256 / NBBY]; diff --git a/ipv4.c b/ipv4.c index d49984a0..5f4acaa5 100644 --- a/ipv4.c +++ b/ipv4.c @@ -987,13 +987,13 @@ ipv4_applyaddr(void *arg) return; } -#ifdef IN_IFF_TENTATIVE +#ifdef IN_IFF_NOTUSEABLE ap = ipv4_iffindaddr(ifp, &lease->addr, NULL); if (ap == NULL) { logger(ifp->ctx, LOG_ERR, "%s: added address vanished", ifp->name); return; - } else if (ap->addr_flags & IN_IFF_TENTATIVE) + } else if (ap->addr_flags & IN_IFF_NOTUSEABLE) return; #endif diff --git a/ipv4.h b/ipv4.h index a33e6737..ed694c92 100644 --- a/ipv4.h +++ b/ipv4.h @@ -30,6 +30,11 @@ #include "dhcpcd.h" +#ifdef IN_IFF_TENTATIVE +#define IN_IFF_NOTUSEABLE \ + (IN_IFF_TENTATIVE | IN_IFF_DUPLICATED | IN_IFF_DETACHED) +#endif + struct rt { TAILQ_ENTRY(rt) next; struct in_addr dest;