From: Roy Marples Date: Fri, 13 Nov 2015 10:37:27 +0000 (+0000) Subject: Add a -N --renew option to renew any existing address early, similar to the X-Git-Tag: v6.9.4~15 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=56a660173fc6e510007dfaee5ea36e46f554b4b8;p=thirdparty%2Fdhcpcd.git Add a -N --renew option to renew any existing address early, similar to the -n --rebind option. However, configuration is not reloaded. Fixes [6cf818eeab]. --- diff --git a/dhcp.c b/dhcp.c index 24317838..cdfae5b9 100644 --- a/dhcp.c +++ b/dhcp.c @@ -1829,23 +1829,39 @@ dhcp_decline(struct interface *ifp) } static void -dhcp_renew(void *arg) +dhcp_startrenew(void *arg) { struct interface *ifp = arg; - struct dhcp_state *state = D_STATE(ifp); - struct dhcp_lease *lease = &state->lease; + struct dhcp_state *state; + struct dhcp_lease *lease; + + if ((state = D_STATE(ifp)) == NULL) + return; + /* Only renew in the bound or renew states */ + if (state->state != DHS_BOUND && + state->state != DHS_RENEW) + return; + + /* Remove the timeout as the renew may have been forced. */ + eloop_timeout_delete(ifp->ctx->eloop, dhcp_startrenew, ifp); + + lease = &state->lease; logger(ifp->ctx, LOG_DEBUG, "%s: renewing lease of %s", ifp->name, inet_ntoa(lease->addr)); - logger(ifp->ctx, LOG_DEBUG, "%s: rebind in %"PRIu32" seconds," - " expire in %"PRIu32" seconds", - ifp->name, lease->rebindtime - lease->renewaltime, - lease->leasetime - lease->renewaltime); state->state = DHS_RENEW; state->xid = dhcp_xid(ifp); + state->interval = 0; send_renew(ifp); } +void +dhcp_renew(struct interface *ifp) +{ + + dhcp_startrenew(ifp); +} + static void dhcp_arp_announced(struct arp_state *astate) { @@ -1867,6 +1883,7 @@ dhcp_rebind(void *arg) state->state = DHS_REBIND; eloop_timeout_delete(ifp->ctx->eloop, send_renew, ifp); state->lease.server.s_addr = 0; + state->interval = 0; ifp->options->options &= ~(DHCPCD_CSR_WARNED | DHCPCD_ROUTER_HOST_ROUTE_WARNED); send_rebind(ifp); @@ -2085,7 +2102,7 @@ dhcp_bind(struct interface *ifp) lease->renewaltime = lease->rebindtime = lease->leasetime; else { eloop_timeout_add_sec(ifp->ctx->eloop, - (time_t)lease->renewaltime, dhcp_renew, ifp); + (time_t)lease->renewaltime, dhcp_startrenew, ifp); eloop_timeout_add_sec(ifp->ctx->eloop, (time_t)lease->rebindtime, dhcp_rebind, ifp); eloop_timeout_add_sec(ifp->ctx->eloop, @@ -2598,11 +2615,9 @@ dhcp_handledhcp(struct interface *ifp, struct dhcp_message **dhcpp, log_dhcp(LOG_ERR, "Force Renew from", ifp, dhcp, from); /* The rebind and expire timings are still the same, we just * enter the renew state early */ - if (state->state == DHS_BOUND) { - eloop_timeout_delete(ifp->ctx->eloop, - dhcp_renew, ifp); + if (state->state == DHS_BOUND) dhcp_renew(ifp); - } else { + else { eloop_timeout_delete(ifp->ctx->eloop, send_inform, ifp); dhcp_inform(ifp); diff --git a/dhcp.h b/dhcp.h index 6bbca2a3..2bbf3db3 100644 --- a/dhcp.h +++ b/dhcp.h @@ -266,6 +266,7 @@ void dhcp_start(struct interface *); void dhcp_abort(struct interface *); void dhcp_discover(void *); void dhcp_inform(struct interface *); +void dhcp_renew(struct interface *); void dhcp_bind(struct interface *); void dhcp_reboot_newopts(struct interface *, unsigned long long); void dhcp_close(struct interface *); @@ -275,6 +276,7 @@ int dhcp_dump(struct interface *); #define dhcp_drop(a, b) {} #define dhcp_start(a) {} #define dhcp_abort(a) {} +#define dhcp_renew(a) {} #define dhcp_reboot(a, b) (b = b) #define dhcp_reboot_newopts(a, b) (b = b) #define dhcp_close(a) {} diff --git a/dhcp6.c b/dhcp6.c index 48883f8f..283563d3 100644 --- a/dhcp6.c +++ b/dhcp6.c @@ -1251,7 +1251,17 @@ dhcp6_startrenew(void *arg) struct dhcp6_state *state; ifp = arg; - state = D6_STATE(ifp); + if ((state = D6_STATE(ifp)) == NULL) + return; + + /* Only renew in the bound or renew states */ + if (state->state != DH6S_BOUND && + state->state != DH6S_RENEW) + return; + + /* Remove the timeout as the renew may have been forced. */ + eloop_timeout_delete(ifp->ctx->eloop, dhcp6_startrenew, ifp); + state->state = DH6S_RENEW; state->RTC = 0; state->IRT = REN_TIMEOUT; @@ -1265,6 +1275,12 @@ dhcp6_startrenew(void *arg) dhcp6_sendrenew(ifp); } +void dhcp6_renew(struct interface *ifp) +{ + + dhcp6_startrenew(ifp); +} + int dhcp6_dadcompleted(const struct interface *ifp) { @@ -2894,8 +2910,6 @@ dhcp6_handledata(void *arg) ifp->name, op); return; } - eloop_timeout_delete(ifp->ctx->eloop, - dhcp6_startrenew, ifp); dhcp6_startrenew(ifp); break; case DHCP6_INFORMATION_REQ: diff --git a/dhcp6.h b/dhcp6.h index d1a43723..60719e6f 100644 --- a/dhcp6.h +++ b/dhcp6.h @@ -241,6 +241,7 @@ size_t dhcp6_find_delegates(struct interface *); int dhcp6_has_public_addr(const struct interface *); int dhcp6_start(struct interface *, enum DH6S); void dhcp6_reboot(struct interface *); +void dhcp6_renew(struct interface *); ssize_t dhcp6_env(char **, const char *, const struct interface *, const struct dhcp6_message *, size_t); void dhcp6_free(struct interface *); diff --git a/dhcpcd.8.in b/dhcpcd.8.in index 862d5a20..6927693d 100644 --- a/dhcpcd.8.in +++ b/dhcpcd.8.in @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd September 30, 2015 +.Dd November 13, 2015 .Dt DHCPCD 8 .Os .Sh NAME @@ -30,7 +30,7 @@ .Nd a DHCP client .Sh SYNOPSIS .Nm -.Op Fl 46ABbDdEGgHJKLMpqTV +.Op Fl 46ABbDdEGgHJKLMNpqTV .Op Fl C , Fl Fl nohook Ar hook .Op Fl c , Fl Fl script Ar script .Op Fl e , Fl Fl env Ar value @@ -378,6 +378,22 @@ is not running, then it starts up as normal. This may also cause .Xr wpa_supplicant 8 to reload its configuration for each interface as well. +.It Fl N , Fl Fl renew Op Ar interface +Notifies +.Nm +to renew existing addresses on the specified +.Ar interface . +If no interface is specified then this applies to all interfaces. +If +.Nm +is not running, then it starts up as normal. +Unlike the +.Fl n , Fl Fl rebind +option above, the configuration for +.Nm +and +.Xr wpa_supplicant 8 +is not reloaded. .It Fl o , Fl Fl option Ar option Request the DHCP .Ar option diff --git a/dhcpcd.c b/dhcpcd.c index d33fcfd3..9b6da58d 100644 --- a/dhcpcd.c +++ b/dhcpcd.c @@ -1165,13 +1165,37 @@ stop_all_interfaces(struct dhcpcd_ctx *ctx, unsigned long long opts) } } +static void +dhcpcd_ifrenew(struct interface *ifp) +{ + +#define DHCPCD_RARENEW (DHCPCD_IPV6 | DHCPCD_IPV6RS) + if (ifp->options->options & DHCPCD_LINK && + ifp->carrier != LINK_DOWN) + { + dhcp_renew(ifp); + if ((ifp->options->options & DHCPCD_RARENEW) == DHCPCD_RARENEW) + ipv6nd_startrs(ifp); + dhcp6_renew(ifp); + } +} + +static void +dhcpcd_renew(struct dhcpcd_ctx *ctx) +{ + struct interface *ifp; + + TAILQ_FOREACH(ifp, ctx->ifaces, next) { + dhcpcd_ifrenew(ifp); + } +} + #ifdef USE_SIGNALS #define sigmsg "received %s, %s" static void signal_cb(int sig, void *arg) { struct dhcpcd_ctx *ctx = arg; - struct interface *ifp; unsigned long long opts; int exit_code; @@ -1199,10 +1223,8 @@ signal_cb(int sig, void *arg) ctx->argc - ctx->ifc); return; case SIGUSR1: - logger(ctx, LOG_INFO, sigmsg, "SIGUSR1", "reconfiguring"); - TAILQ_FOREACH(ifp, ctx->ifaces, next) { - ipv4_applyaddr(ifp); - } + logger(ctx, LOG_INFO, sigmsg, "SIGUSR1", "renewing"); + dhcpcd_renew(ctx); return; case SIGUSR2: logger_close(ctx); @@ -1261,7 +1283,7 @@ dhcpcd_handleargs(struct dhcpcd_ctx *ctx, struct fd_list *fd, { struct interface *ifp; unsigned long long opts; - int opt, oi, do_reboot; + int opt, oi, do_reboot, do_renew; size_t len, l; char *tmp, *p; @@ -1312,7 +1334,7 @@ dhcpcd_handleargs(struct dhcpcd_ctx *ctx, struct fd_list *fd, optind = 0; oi = 0; opts = 0; - do_reboot = 0; + do_reboot = do_renew = 0; while ((opt = getopt_long(argc, argv, IF_OPTS, cf_options, &oi)) != -1) { switch (opt) { @@ -1331,6 +1353,9 @@ dhcpcd_handleargs(struct dhcpcd_ctx *ctx, struct fd_list *fd, case 'x': opts |= DHCPCD_EXITING; break; + case 'N': + do_renew = 1; + break; } } @@ -1351,6 +1376,19 @@ dhcpcd_handleargs(struct dhcpcd_ctx *ctx, struct fd_list *fd, return 0; } + if (do_renew) { + if (optind == argc) { + dhcpcd_renew(ctx); + return 0; + } + for (oi = optind; oi < argc; oi++) { + if ((ifp = if_find(ctx->ifaces, argv[oi])) == NULL) + continue; + dhcpcd_ifrenew(ifp); + } + return 0; + } + reload_config(ctx); /* XXX: Respect initial commandline options? */ reconf_reboot(ctx, do_reboot, argc, argv, optind - 1); @@ -1451,6 +1489,10 @@ main(int argc, char **argv) sig = SIGTERM; siga = "TERM"; break; + case 'N': + sig = SIGUSR1; + siga = "USR1"; + break; #endif case 'T': i = 1; @@ -1669,14 +1711,14 @@ main(int argc, char **argv) logger(&ctx, LOG_INFO, "sending signal %s to pid %d", siga, pid); if (pid == 0 || kill(pid, sig) != 0) { - if (sig != SIGHUP && errno != EPERM) + if (sig != SIGHUP && sig != SIGUSR1 && errno != EPERM) logger(&ctx, LOG_ERR, ""PACKAGE" not running"); if (pid != 0 && errno != ESRCH) { logger(&ctx, LOG_ERR, "kill: %m"); goto exit_failure; } unlink(ctx.pidfile); - if (sig != SIGHUP) + if (sig != SIGHUP && sig != SIGUSR1) goto exit_failure; } else { struct timespec ts; diff --git a/if-options.c b/if-options.c index 71d2cb47..1a6d981f 100644 --- a/if-options.c +++ b/if-options.c @@ -144,6 +144,7 @@ const struct option cf_options[] = { {"nolink", no_argument, NULL, 'K'}, {"noipv4ll", no_argument, NULL, 'L'}, {"master", no_argument, NULL, 'M'}, + {"renew", no_argument, NULL, 'N'}, {"nooption", optional_argument, NULL, 'O'}, {"require", required_argument, NULL, 'Q'}, {"static", required_argument, NULL, 'S'}, @@ -684,6 +685,7 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo, case 'g': /* FALLTHROUGH */ case 'n': /* FALLTHROUGH */ case 'x': /* FALLTHROUGH */ + case 'N': /* FALLTHROUGH */ case 'T': /* FALLTHROUGH */ case 'U': /* FALLTHROUGH */ case 'V': /* We need to handle non interface options */ diff --git a/if-options.h b/if-options.h index cf1d4a35..429e8b5e 100644 --- a/if-options.h +++ b/if-options.h @@ -42,7 +42,7 @@ /* Don't set any optional arguments here so we retain POSIX * compatibility with getopt */ #define IF_OPTS "46bc:de:f:gh:i:j:kl:m:no:pqr:s:t:u:v:wxy:z:" \ - "ABC:DEF:GHI:JKLMO:Q:S:TUVW:X:Z:" + "ABC:DEF:GHI:JKLMNO:Q:S:TUVW:X:Z:" #define DEFAULT_TIMEOUT 30 #define DEFAULT_REBOOT 5