Add a -N --renew option to renew any existing address early, similar to the

-n --rebind option. However, configuration is not reloaded.

Fixes [6cf818eeab].
This commit is contained in:
Roy Marples 2015-11-13 10:37:27 +00:00
parent 9a42ed94b4
commit 56a660173f
8 changed files with 119 additions and 27 deletions

39
dhcp.c
View File

@ -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);

2
dhcp.h
View File

@ -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) {}

20
dhcp6.c
View File

@ -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:

View File

@ -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 *);

View 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

View File

@ -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;

View 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 */

View 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