]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Add a -N --renew option to renew any existing address early, similar to the
authorRoy Marples <roy@marples.name>
Fri, 13 Nov 2015 10:37:27 +0000 (10:37 +0000)
committerRoy Marples <roy@marples.name>
Fri, 13 Nov 2015 10:37:27 +0000 (10:37 +0000)
-n --rebind option. However, configuration is not reloaded.

Fixes [6cf818eeab].

dhcp.c
dhcp.h
dhcp6.c
dhcp6.h
dhcpcd.8.in
dhcpcd.c
if-options.c
if-options.h

diff --git a/dhcp.c b/dhcp.c
index 24317838f1a63d11d6cbe71de6f07eedde1ddc71..cdfae5b9e88f2d410e81203f4ab279ac3615d80e 100644 (file)
--- 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 6bbca2a3ad59a0a9022743aa73768dac42382fad..2bbf3db3d40048bc42644bb0c5e3331cc5904fd4 100644 (file)
--- 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 48883f8f6d064ee73a89623f43ae160fccced9fe..283563d370a5ea74d8ebe651e447521fc51eed51 100644 (file)
--- 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 d1a4372329fe620cbb6e2a0d5740fc463ab535a5..60719e6fd0d151ceae2c23e7c8ac483fbce1d81c 100644 (file)
--- 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 *);
index 862d5a207b86ace24fed1e437f6dbcd6fca2e453..6927693dd5f6ce8355ae894b03c73bbdabb58ffa 100644 (file)
@@ -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
index d33fcfd3c250ebb4f5411df32af2c25e51491ae6..9b6da58dc35122b0610504826a5bb1ddeff09b1d 100644 (file)
--- 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;
index 71d2cb478059446d47416f39f1e90610e749e8cd..1a6d981fcc16f38dcbcfd986000b8f721212e912 100644 (file)
@@ -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 */
index cf1d4a352e3e426400585cac6c6aa0aa96b7426c..429e8b5e2684d2e4894b5a7d47b44bc0a1520e0c 100644 (file)
@@ -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