Mercurial > hg > dhcpcd
changeset 982:b8b5d9059bb0 draft
Reboot off the last lease and use the last lease if not expired and user has asked for it. Also, add a reboot timeout toggle (default 10 seconds).
| author | Roy Marples <roy@marples.name> |
|---|---|
| date | Mon, 15 Sep 2008 15:23:46 +0000 |
| parents | 8a655d895e9a |
| children | 1f2ad84ae760 |
| files | dhcp.c dhcpcd.8.in dhcpcd.c dhcpcd.conf.5.in dhcpcd.h if-options.c if-options.h ipv4ll.c |
| diffstat | 8 files changed, 149 insertions(+), 55 deletions(-) [+] |
line wrap: on
line diff
--- a/dhcp.c Mon Sep 15 15:20:37 2008 +0000 +++ b/dhcp.c Mon Sep 15 15:23:46 2008 +0000 @@ -1254,7 +1254,6 @@ { time_t t; - lease->frominfo = 0; lease->addr.s_addr = dhcp->yiaddr; if (get_option_addr(&lease->net.s_addr, dhcp, DHO_SUBNETMASK) == -1) lease->net.s_addr = get_netmask(dhcp->yiaddr);
--- a/dhcpcd.8.in Mon Sep 15 15:20:37 2008 +0000 +++ b/dhcpcd.8.in Mon Sep 15 15:23:46 2008 +0000 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd September 11, 2008 +.Dd September 15, 2008 .Dt DHCPCD 8 SMM .Sh NAME .Nm dhcpcd @@ -42,6 +42,7 @@ .Op Fl t , -timeout Ar seconds .Op Fl u , -userclass Ar class .Op Fl v , -vendor Ar code , Ar value +.Op Fl y , -reboot Ar seconds .Op Fl z , -allowinterfaces Ar pattern .Op Fl C , -nohook Ar hook .Op Fl F , -fqdn Ar FQDN @@ -304,6 +305,14 @@ and exit. .Nm then waits until this process has exited. +.It Fl y , -reboot Ar seconds +Allow +.Ar reboot +seconds before moving to the discover phase if we have an old lease to use. +The default is 10 seconds. +A setting if 0 seconds causes +.Nm +to skip the reboot phase and go straight into discover. .It Fl D , -duid Generate an .Li RFC 4361
--- a/dhcpcd.c Mon Sep 15 15:20:37 2008 +0000 +++ b/dhcpcd.c Mon Sep 15 15:23:46 2008 +0000 @@ -127,7 +127,7 @@ static void usage(void) { - printf("usage: "PACKAGE" [-dknpqxADEGHKLOTV] [-c script] [-f file ] [-h hostname]\n" + printf("usage: "PACKAGE" [-dknpqxyADEGHKLOTV] [-c script] [-f file ] [-h hostname]\n" " [-i classID ] [-l leasetime] [-m metric] [-o option] [-r ipaddr]\n" " [-s ipaddr] [-t timeout] [-u userclass] [-F none|ptr|both]\n" " [-I clientID] [-C hookscript] [-Q option] [-X ipaddr] <interface>\n"); @@ -326,7 +326,7 @@ syslog(LOG_ERR, "%s: failed to renew, attmepting to rebind", iface->name); - iface->state->state = DHS_REBINDING; + iface->state->state = DHS_REBIND; delete_timeout(send_renew, iface); iface->state->lease.server.s_addr = 0; send_rebind(iface); @@ -336,14 +336,20 @@ start_expire(void *arg) { struct interface *iface = arg; - int ll = IN_LINKLOCAL(htonl(iface->state->lease.addr.s_addr)); + + if (iface->addr.s_addr == 0) { + /* We failed to reboot, so enter discovery. */ + iface->state->interval = 0; + start_discover(iface); + return; + } syslog(LOG_ERR, "%s: lease expired", iface->name); delete_timeout(NULL, iface); drop_config(iface, "EXPIRE"); iface->state->interval = 0; if (iface->carrier != LINK_DOWN) { - if (ll) + if (IN_LINKLOCAL(htonl(iface->state->lease.addr.s_addr))) start_interface(iface); else start_ipv4ll(iface); @@ -454,7 +460,8 @@ } } - if (type == DHCP_OFFER && state->state == DHS_DISCOVERING) { + if (type == DHCP_OFFER && state->state == DHS_DISCOVER) { + lease->frominfo = 0; lease->addr.s_addr = dhcp->yiaddr; get_option_addr(&lease->server.s_addr, dhcp, DHO_SERVERID); log_dhcp(LOG_INFO, "offered", iface, dhcp); @@ -477,7 +484,6 @@ * then we can't ARP for duplicate detection. */ addr.s_addr = state->offer->yiaddr; if (!has_address(iface->name, &addr, NULL)) { - state->state = DHS_PROBING; state->claims = 0; state->probes = 0; state->conflicts = 0; @@ -485,7 +491,7 @@ return; } } - state->state = DHS_REQUESTING; + state->state = DHS_REQUEST; send_request(iface); return; } @@ -509,6 +515,7 @@ *dhcpp = NULL; /* Delete all timeouts for this interface. */ delete_timeout(NULL, iface); + lease->frominfo = 0; bind_interface(iface); } @@ -636,7 +643,7 @@ struct interface *iface = arg; struct if_options *ifo = iface->state->options; - iface->state->state = DHS_DISCOVERING; + iface->state->state = DHS_DISCOVER; iface->state->xid = arc4random(); open_sockets(iface); delete_timeout(NULL, iface); @@ -660,12 +667,22 @@ syslog(LOG_INFO, "%s: renewing lease of %s", iface->name, inet_ntoa(iface->state->lease.addr)); - iface->state->state = DHS_RENEWING; + iface->state->state = DHS_RENEW; iface->state->xid = arc4random(); open_sockets(iface); send_renew(iface); } +static void +start_timeout(void *arg) +{ + struct interface *iface = arg; + + bind_interface(iface); + iface->state->interval = 0; + start_discover(iface); +} + void start_reboot(struct interface *iface) { @@ -675,15 +692,33 @@ syslog(LOG_INFO, "%s: waiting for carrier", iface->name); return; } + if (ifo->reboot == 0) { + start_discover(iface); + return; + } + if (IN_LINKLOCAL(htonl(iface->state->lease.addr.s_addr))) { + if (ifo->options & DHCPCD_IPV4LL) { + iface->state->claims = 0; + send_arp_announce(iface); + } else + start_discover(iface); + return; + } syslog(LOG_INFO, "%s: rebinding lease of %s", iface->name, inet_ntoa(iface->state->lease.addr)); - iface->state->state = DHS_REBINDING; + iface->state->state = DHS_REBOOT; iface->state->xid = arc4random(); iface->state->lease.server.s_addr = 0; delete_timeout(NULL, iface); - add_timeout_sec(ifo->timeout, start_expire, iface); + if (ifo->options & DHCPCD_LASTLEASE && iface->state->lease.frominfo) + add_timeout_sec(ifo->reboot, start_timeout, iface); + else + add_timeout_sec(ifo->reboot, start_expire, iface); open_sockets(iface); - send_rebind(iface); + if (ifo->options & DHCPCD_ARP) + send_arp_probe(iface); + else + send_request(iface); } static void @@ -703,6 +738,9 @@ start_interface(void *arg) { struct interface *iface = arg; + struct stat st; + struct timeval now; + uint32_t l; if (iface->carrier == LINK_DOWN) { syslog(LOG_INFO, "%s: waiting for carrier", iface->name); @@ -710,9 +748,36 @@ } iface->start_uptime = uptime(); - if (!iface->state->lease.addr.s_addr) + iface->state->offer = read_lease(iface); +/* if (iface->state->offer) { + if (IN_LINKLOCAL(htonl(iface->state->offer->yiaddr))) { + free(iface->state->offer); + iface->state->offer = NULL; + } + } */ + if (iface->state->offer) { + get_lease(&iface->state->lease, iface->state->offer); + iface->state->lease.frominfo = 1; + /* Offset lease times and check expiry */ + if (stat(iface->leasefile, &st) == 0 && + get_option_uint32(&l, iface->state->offer, DHO_LEASETIME) == 0) + { + gettimeofday(&now, NULL); + if ((time_t)l < now.tv_sec - st.st_mtime) { + free(iface->state->offer); + iface->state->offer = NULL; + } else { + l = now.tv_sec - st.st_mtime; + iface->state->lease.leasetime -= l; + iface->state->lease.renewaltime -= l; + iface->state->lease.rebindtime -= l; + } + } + } + if (!iface->state->offer) start_discover(iface); - else if (IN_LINKLOCAL(htonl(iface->state->lease.addr.s_addr))) + else if (IN_LINKLOCAL(htonl(iface->state->lease.addr.s_addr)) && + iface->state->options->options & DHCPCD_IPV4LL) start_ipv4ll(iface); else start_reboot(iface); @@ -861,7 +926,7 @@ { struct interface *iface, *ifl; int sig = signal_read(); - int do_reboot = 0, do_release = 0; + int do_release = 0; switch (sig) { case SIGINT: @@ -872,15 +937,17 @@ break; case SIGALRM: syslog(LOG_INFO, "received SIGALRM, rebinding lease"); - do_reboot = 1; + for (iface = ifaces; iface; iface = iface->next) + start_reboot(iface); + return; case SIGHUP: syslog(LOG_INFO, "received SIGHUP, releasing lease"); do_release = 1; break; default: - syslog (LOG_ERR, - "received signal %d, but don't know what to do with it", - sig); + syslog(LOG_ERR, + "received signal %d, but don't know what to do with it", + sig); return; } @@ -893,14 +960,10 @@ ifl = iface; if (!ifl) break; - if (do_reboot) - start_reboot(ifl); - else { - if (do_release) - send_release(ifl); - if (!(ifl->state->options->options & DHCPCD_PERSISTENT)) - drop_config(ifl, do_release ? "RELEASE" : "STOP"); - } + if (do_release) + send_release(ifl); + if (!(ifl->state->options->options & DHCPCD_PERSISTENT)) + drop_config(ifl, do_release ? "RELEASE" : "STOP"); } exit(EXIT_FAILURE); } @@ -1102,6 +1165,8 @@ unlink(pidfile); exit(EXIT_FAILURE); } + if (sig == SIGALRM) + exit(EXIT_SUCCESS); /* Spin until it exits */ syslog(LOG_INFO, "waiting for pid %d to exit", pid); ts.tv_sec = 0;
--- a/dhcpcd.conf.5.in Mon Sep 15 15:20:37 2008 +0000 +++ b/dhcpcd.conf.5.in Mon Sep 15 15:23:46 2008 +0000 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd September 11, 2008 +.Dd September 15, 2008 .Dt DHCPCD.CONF 5 SMM .Sh NAME .Nm dhcpcd.conf @@ -124,6 +124,14 @@ .Xr dhcpcd-run-hooks 8 or the numerical value. You can specify more options seperated by commas, spaces or more option lines. +.Ic reboot Ar seconds +Allow +.Ar reboot +seconds before moving to the discover phase if we have an old lease to use. +The default is 10 seconds. +A setting if 0 seconds causes +.Nm dhcpcd +to skip the reboot phase and go straight into discover. .It Ic require Ar option Requires the .Ar option
--- a/dhcpcd.h Mon Sep 15 15:20:37 2008 +0000 +++ b/dhcpcd.h Mon Sep 15 15:23:46 2008 +0000 @@ -39,16 +39,14 @@ enum DHS { DHS_INIT, - DHS_DISCOVERING, - DHS_REQUESTING, + DHS_DISCOVER, + DHS_REQUEST, DHS_BOUND, - DHS_RENEWING, - DHS_REBINDING, + DHS_RENEW, + DHS_REBIND, DHS_REBOOT, DHS_RENEW_REQUESTED, - DHS_INIT_IPV4LL, - DHS_PROBING, - DHS_ANNOUNCING + DHS_INIT_IPV4LL }; #define LINK_UP 1
--- a/if-options.c Mon Sep 15 15:20:37 2008 +0000 +++ b/if-options.c Mon Sep 15 15:23:46 2008 +0000 @@ -48,7 +48,7 @@ /* Don't set any optional arguments here so we retain POSIX * compatibility with getopt */ -#define OPTS "bc:df:h:i:kl:m:no:pqr:s:t:u:v:xABC:DEF:GI:KLO:Q:TVX:" +#define OPTS "bc:df:h:i:kl:m:no:pqr:s:t:u:v:xy:z:ABC:DEF:GI:KLO:Q:TVX:Z:" const struct option cf_options[] = { {"background", no_argument, NULL, 'b'}, @@ -70,6 +70,7 @@ {"userclass", required_argument, NULL, 'u'}, {"vendor", required_argument, NULL, 'v'}, {"exit", no_argument, NULL, 'x'}, + {"reboot", required_argument, NULL, 'y'}, {"allowinterfaces", required_argument, NULL, 'z'}, {"noarp", no_argument, NULL, 'A'}, {"nobackground", no_argument, NULL, 'B'}, @@ -382,7 +383,7 @@ case 't': ifo->timeout = atoint(arg); if (ifo->timeout < 0) { - syslog (LOG_ERR, "timeout must be a positive value"); + syslog(LOG_ERR, "timeout must be a positive value"); return -1; } break; @@ -435,6 +436,13 @@ ifo->vendor[0] += s + 2; } break; + case 'y': + ifo->reboot = atoint(arg); + if (ifo->reboot < 0) { + syslog(LOG_ERR, "reboot must be a positive value"); + return -1; + } + break; case 'z': /* We only set this if we haven't got any interfaces */ if (!ifaces) @@ -587,6 +595,7 @@ ifo->options |= DHCPCD_CLIENTID | DHCPCD_GATEWAY | DHCPCD_DAEMONISE; ifo->options |= DHCPCD_ARP | DHCPCD_IPV4LL | DHCPCD_LINK; ifo->timeout = DEFAULT_TIMEOUT; + ifo->reboot = DEFAULT_REBOOT; ifo->metric = -1; gethostname(ifo->hostname + 1, sizeof(ifo->hostname)); if (strcmp(ifo->hostname + 1, "(none)") == 0 ||
--- a/if-options.h Mon Sep 15 15:20:37 2008 +0000 +++ b/if-options.h Mon Sep 15 15:23:46 2008 +0000 @@ -40,6 +40,7 @@ #define IF_OPTS "bc:df:h:i:kl:m:no:pqr:s:t:u:v:xz:ABC:DEF:GI:KLO:Q:TVX:Z:" #define DEFAULT_TIMEOUT 30 +#define DEFAULT_REBOOT 10 #define DEFAULT_LEASETIME 3600 /* 1 hour */ #define HOSTNAME_MAX_LEN 250 /* 255 - 3 (FQDN) - 2 (DNS enc) */ @@ -76,6 +77,7 @@ uint8_t nomask[256 / 8]; uint32_t leasetime; time_t timeout; + time_t reboot; int options; struct in_addr request_address;
--- a/ipv4ll.c Mon Sep 15 15:20:37 2008 +0000 +++ b/ipv4ll.c Mon Sep 15 15:23:46 2008 +0000 @@ -87,11 +87,16 @@ } } - syslog(LOG_INFO, "%s: probing for an IPv4LL address", iface->name); - delete_timeout(NULL, iface); - iface->state->state = DHS_PROBING; - free(iface->state->offer); - iface->state->offer = make_ipv4ll_lease(0); + /* We maybe rebooting of an IPv4LL address. */ + if (!iface->state->offer || + !IN_LINKLOCAL(htonl(iface->state->offer->yiaddr))) + { + syslog(LOG_INFO, "%s: probing for an IPv4LL address", iface->name); + delete_timeout(NULL, iface); + free(iface->state->offer); + iface->state->offer = make_ipv4ll_lease(0); + iface->state->lease.frominfo = 0; + } send_arp_probe(iface); } @@ -102,26 +107,25 @@ time_t up; if (iface->state->fail.s_addr == iface->state->lease.addr.s_addr) { - if (iface->state->state == DHS_PROBING) + up = uptime(); + if (iface->state->defend + DEFEND_INTERVAL > up) { drop_config(iface, "EXPIRE"); - else { - up = uptime(); - if (iface->state->defend + DEFEND_INTERVAL > up) { - drop_config(iface, "EXPIRE"); - iface->state->conflicts = -1; - } else { - iface->state->defend = up; - return; - } + iface->state->conflicts = -1; + } else { + iface->state->defend = up; + return; } } close_sockets(iface); + free(iface->state->offer); + iface->state->offer = NULL; if (++iface->state->conflicts > MAX_CONFLICTS) { syslog(LOG_ERR, "%s: failed to acquire an IPv4LL address", iface->name); iface->state->interval = RATE_LIMIT_INTERVAL / 2; start_discover(iface); - } else + } else { add_timeout_sec(PROBE_WAIT, start_ipv4ll, iface); + } }
