From: Roy Marples Date: Thu, 10 May 2007 09:39:26 +0000 (+0000) Subject: config.h now has the compile time options, instead of being dotted around. X-Git-Tag: v3.2.3~266 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4549f7a4ddb698e3023816909f4899b6dc771904;p=thirdparty%2Fdhcpcd.git config.h now has the compile time options, instead of being dotted around. Added -E option, which reads the last info file and uses the information there if we timeout and the lease is still valid, thanks to Roberto Angelino. --- diff --git a/ChangeLog b/ChangeLog index 071df3d4..6334ed4c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +config.h now has the compile time options, instead of being dotted around. +Added -E option, which reads the last info file and uses the information there +if we timeout and the lease is still valid, thanks to Roberto Angelino. Compiles ok on NetBSD, but doesn't add routes yet - thanks to Gabor Z. Papp. If the current hostname contains dots then send it as a FQDN. Ensure that static routes are always added before routers. diff --git a/Makefile b/Makefile index ebbe1942..4c3bbe31 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -VERSION = 3.0.18_pre3 +VERSION = 3.1.0_pre1 CFLAGS ?= -O2 -pipe # Should work for both GNU make and BSD make @@ -46,7 +46,7 @@ TARGET = $(SBIN_TARGETS) dhcpcd_H = version.h dhcpcd_OBJS = arp.o client.o common.o configure.o dhcp.o dhcpcd.o \ - interface.o logger.o signals.o socket.o + info.o interface.o logger.o signals.o socket.o # By default we don't need to link to anything # Except on Darwin where we need -lresolv, so they need to uncomment this diff --git a/arp.c b/arp.c index 0828ec1c..be340484 100644 --- a/arp.c +++ b/arp.c @@ -34,6 +34,7 @@ #include #include +#include "config.h" #include "common.h" #include "arp.h" #include "interface.h" @@ -59,6 +60,7 @@ #define arphdr_len(ap) (arphdr_len2 ((ap)->ar_hln, (ap)->ar_pln)) #endif +#ifdef ENABLE_ARP int arp_check (interface_t *iface, struct in_addr address) { union { @@ -165,4 +167,4 @@ int arp_check (interface_t *iface, struct in_addr address) iface->fd = -1; return 0; } - +#endif diff --git a/arp.h b/arp.h index 25563c60..bb424748 100644 --- a/arp.h +++ b/arp.h @@ -20,10 +20,12 @@ #ifndef ARP_H #define ARP_H +#ifdef ENABLE_ARP #include #include "interface.h" int arp_check (interface_t *iface, struct in_addr address); +#endif #endif diff --git a/client.c b/client.c index 9d603c91..693790f3 100644 --- a/client.c +++ b/client.c @@ -21,6 +21,7 @@ #include #include +#include #include #ifdef __linux__ #include @@ -35,12 +36,18 @@ #include #include +#include "config.h" #include "common.h" +#ifdef ENABLE_ARP #include "arp.h" +#endif #include "client.h" #include "configure.h" #include "dhcp.h" #include "dhcpcd.h" +#ifdef ENABLE_INFO +#include "info.h" +#endif #include "interface.h" #include "logger.h" #include "signals.h" @@ -176,7 +183,7 @@ int dhcp_run (const options_t *options) if (timeout > 0 || (options->timeout == 0 && (state != STATE_INIT || xid))) { - if (options->timeout == 0 || + if ((options->timeout == 0 && xid) || (dhcp->leasetime == (unsigned) -1 && state == STATE_BOUND)) { int retry = 0; @@ -302,7 +309,65 @@ int dhcp_run (const options_t *options) if (xid == 0) xid = random_xid (); else { + SOCKET_MODE (SOCKET_CLOSED); logger (LOG_ERR, "timed out"); +#ifdef ENABLE_INFO + if (options->dolastlease) { + unsigned int offset = 0; + + logger (LOG_INFO, "trying to use old lease in `%s'", + iface->infofile); + if (! read_info (iface, dhcp)) { + if (! daemonised) { + retval = EXIT_FAILURE; + goto eexit; + } + } + + /* Ensure that we can still use the lease */ + if (gettimeofday (&tv, NULL) == -1) { + logger (LOG_ERR, "gettimeofday: %s", strerror (errno)); + retval = EXIT_FAILURE; + goto eexit; + } + + offset = tv.tv_sec - dhcp->leasedfrom; + if (dhcp->leasedfrom && + tv.tv_sec - dhcp->leasedfrom > dhcp->leasetime) + { + logger (LOG_ERR, "lease expired %u seconds ago", + offset + dhcp->leasetime); + if (! daemonised) { + retval = EXIT_FAILURE; + goto eexit; + } + } else { + logger (LOG_INFO, "using last known IP address %s", + inet_ntoa (dhcp->address)); + if (configure (options, iface, dhcp)) { + retval = EXIT_FAILURE; + goto eexit; + } + + state = STATE_BOUND; + /* We'll timeout above if timeout is negative, + * so no need for special handling */ + if (dhcp->leasedfrom == 0) + offset = 0; + timeout = dhcp->renewaltime - offset; + iface->start_uptime = uptime (); + + if (! daemonised && options->daemonise) { + if ((daemonise (options->pidfile)) < 0) { + retval = -1; + goto eexit; + } + daemonised = true; + } + continue; + } + } +#endif if (! daemonised) { retval = EXIT_FAILURE; goto eexit; @@ -340,6 +405,8 @@ int dhcp_run (const options_t *options) logger (LOG_ERR, "lost lease, attemping to rebind"); memset (&dhcp->address, 0, sizeof (struct in_addr)); SOCKET_MODE (SOCKET_OPEN); + if (xid == 0) + xid = random_xid (); SEND_MESSAGE (DHCP_REQUEST); timeout = dhcp->leasetime - dhcp->rebindtime; state = STATE_REQUESTING; @@ -458,6 +525,7 @@ int dhcp_run (const options_t *options) case STATE_REBINDING: if (type == DHCP_ACK) { SOCKET_MODE (SOCKET_CLOSED); +#ifdef ENABLE_ARP if (options->doarp && iface->previous_address.s_addr != dhcp->address.s_addr) { @@ -479,6 +547,7 @@ int dhcp_run (const options_t *options) continue; } } +#endif if (dhcp->leasetime == (unsigned) -1) { dhcp->renewaltime = dhcp->rebindtime = dhcp->leasetime; diff --git a/common.c b/common.c index c609abaa..7362d793 100644 --- a/common.c +++ b/common.c @@ -87,7 +87,7 @@ long uptime (void) { struct timespec tp; - if (clock_gettime(CLOCK_MONOTONIC, &tp) == -1) { + if (clock_gettime (CLOCK_MONOTONIC, &tp) == -1) { logger (LOG_ERR, "clock_gettime: %s", strerror (errno)); return -1; } diff --git a/configure.c b/configure.c index 1904a242..27567ce0 100644 --- a/configure.c +++ b/configure.c @@ -38,9 +38,13 @@ #include #include +#include "config.h" #include "common.h" #include "configure.h" #include "dhcp.h" +#ifdef ENABLE_INFO +#include "info.h" +#endif #include "interface.h" #include "dhcpcd.h" #include "pathnames.h" @@ -107,8 +111,9 @@ static void exec_script (const char *script, const char *infofile, logger (LOG_DEBUG, "exec \"%s %s %s\"", script, infofile, arg); exec_cmd (script, infofile, arg, (char *) NULL); #else - logger (LOG_DEBUG, "exec \"%s \"\" %s\"", script, infofile, arg); - exec_cmd (script, infofile, "", arg, (char *) NULL); + infofile = NULL; /* appease gcc */ + logger (LOG_DEBUG, "exec \"%s \"\" %s\"", script, arg); + exec_cmd (script, "", arg, (char *) NULL); #endif } @@ -325,180 +330,6 @@ static int make_nis (const char *ifname, const dhcp_t *dhcp) } #endif -#ifdef ENABLE_INFO -static char *cleanmetas (const char *cstr) -{ - /* The largest single element we can have is 256 bytes according to the RFC, - so this buffer size should be safe even if it's all ' */ - static char buffer[1024]; - char *b = buffer; - - memset (buffer, 0, sizeof (buffer)); - if (cstr == NULL || strlen (cstr) == 0) - return b; - - do - if (*cstr == 39) { - *b++ = '\''; - *b++ = '\\'; - *b++ = '\''; - *b++ = '\''; - } else - *b++ = *cstr; - while (*cstr++); - - *b++ = 0; - b = buffer; - - return b; -} - -static int write_info(const interface_t *iface, const dhcp_t *dhcp, - const options_t *options) -{ - FILE *f; - route_t *route; - address_t *address; - - logger (LOG_DEBUG, "writing %s", iface->infofile); - if ((f = fopen (iface->infofile, "w")) == NULL) { - logger (LOG_ERR, "fopen `%s': %s", iface->infofile, strerror (errno)); - return -1; - } - - fprintf (f, "IPADDR='%s'\n", inet_ntoa (dhcp->address)); - fprintf (f, "NETMASK='%s'\n", inet_ntoa (dhcp->netmask)); - fprintf (f, "BROADCAST='%s'\n", inet_ntoa (dhcp->broadcast)); - if (dhcp->mtu > 0) - fprintf (f, "MTU='%d'\n", dhcp->mtu); - - if (dhcp->routes) { - bool doneone = false; - fprintf (f, "ROUTES='"); - for (route = dhcp->routes; route; route = route->next) { - if (route->destination.s_addr != 0) { - if (doneone) - fprintf (f, " "); - fprintf (f, "%s", inet_ntoa (route->destination)); - fprintf (f, ",%s", inet_ntoa (route->netmask)); - fprintf (f, ",%s", inet_ntoa (route->gateway)); - doneone = true; - } - } - fprintf (f, "'\n"); - - doneone = false; - fprintf (f, "GATEWAYS='"); - for (route = dhcp->routes; route; route = route->next) { - if (route->destination.s_addr == 0) { - if (doneone) - fprintf (f, " "); - fprintf (f, "%s", inet_ntoa (route->gateway)); - doneone = true; - } - } - fprintf (f, "'\n"); - } - - if (dhcp->hostname) - fprintf (f, "HOSTNAME='%s'\n", cleanmetas (dhcp->hostname)); - - if (dhcp->dnsdomain) - fprintf (f, "DNSDOMAIN='%s'\n", cleanmetas (dhcp->dnsdomain)); - - if (dhcp->dnssearch) - fprintf (f, "DNSSEARCH='%s'\n", cleanmetas (dhcp->dnssearch)); - - if (dhcp->dnsservers) { - fprintf (f, "DNSSERVERS='"); - for (address = dhcp->dnsservers; address; address = address->next) { - fprintf (f, "%s", inet_ntoa (address->address)); - if (address->next) - fprintf (f, " "); - } - fprintf (f, "'\n"); - } - - if (dhcp->fqdn) { - fprintf (f, "FQDNFLAGS='%u'\n", dhcp->fqdn->flags); - fprintf (f, "FQDNRCODE1='%u'\n", dhcp->fqdn->r1); - fprintf (f, "FQDNRCODE2='%u'\n", dhcp->fqdn->r2); - fprintf (f, "FQDNHOSTNAME='%s'\n", dhcp->fqdn->name); - } - - if (dhcp->ntpservers) { - fprintf (f, "NTPSERVERS='"); - for (address = dhcp->ntpservers; address; address = address->next) { - fprintf (f, "%s", inet_ntoa (address->address)); - if (address->next) - fprintf (f, " "); - } - fprintf (f, "'\n"); - } - - if (dhcp->nisdomain) - fprintf (f, "NISDOMAIN='%s'\n", cleanmetas (dhcp->nisdomain)); - - if (dhcp->nisservers) { - fprintf (f, "NISSERVERS='"); - for (address = dhcp->nisservers; address; address = address->next) { - fprintf (f, "%s", inet_ntoa (address->address)); - if (address->next) - fprintf (f, " "); - } - fprintf (f, "'\n"); - } - - if (dhcp->rootpath) - fprintf (f, "ROOTPATH='%s'\n", cleanmetas (dhcp->rootpath)); - - fprintf (f, "DHCPSID='%s'\n", inet_ntoa (dhcp->serveraddress)); - fprintf (f, "DHCPSNAME='%s'\n", cleanmetas (dhcp->servername)); - fprintf (f, "LEASETIME='%u'\n", dhcp->leasetime); - fprintf (f, "RENEWALTIME='%u'\n", dhcp->renewaltime); - fprintf (f, "REBINDTIME='%u'\n", dhcp->rebindtime); - fprintf (f, "INTERFACE='%s'\n", iface->name); - fprintf (f, "CLASSID='%s'\n", cleanmetas (options->classid)); - if (options->clientid[0]) - fprintf (f, "CLIENTID='%s'\n", cleanmetas (options->clientid)); - else - fprintf (f, "CLIENTID='%s'\n", hwaddr_ntoa (iface->hwaddr, iface->hwlen)); - fprintf (f, "DHCPCHADDR='%s'\n", hwaddr_ntoa (iface->hwaddr, iface->hwlen)); - -#ifdef ENABLE_INFO_COMPAT - /* Support the old .info settings if we need to */ - fprintf (f, "\n# dhcpcd-1.x and 2.x compatible variables\n"); - if (dhcp->dnsservers) { - fprintf (f, "DNS='"); - for (address = dhcp->dnsservers; address; address = address->next) { - fprintf (f, "%s", inet_ntoa (address->address)); - if (address->next) - fprintf (f, ","); - } - fprintf (f, "'\n"); - } - - if (dhcp->routes) { - bool doneone = false; - fprintf (f, "GATEWAY='"); - for (route = dhcp->routes; route; route = route->next) { - if (route->destination.s_addr == 0) { - if (doneone) - fprintf (f, ","); - fprintf (f, "%s", inet_ntoa (route->gateway)); - doneone = true; - } - } - fprintf (f, "'\n"); - } -#endif - - fprintf (f, "\n"); - fclose (f); - return 0; -} -#endif - int configure (const options_t *options, interface_t *iface, const dhcp_t *dhcp) { @@ -738,7 +569,8 @@ int configure (const options_t *options, interface_t *iface, } #ifdef ENABLE_INFO - write_info (iface, dhcp, options); + if (! dhcp->frominfo) + write_info (iface, dhcp, options); #endif if (iface->previous_address.s_addr != dhcp->address.s_addr || diff --git a/configure.h b/configure.h index ac4eb2e3..ddc709f9 100644 --- a/configure.h +++ b/configure.h @@ -22,16 +22,6 @@ #ifndef DHCPCONFIG_H #define DHCPCONFIG_H -/* If you disable all 3 options you can shrink the binary by around 5-10k - unstripped depending on platform and CFLAGS - */ -#define ENABLE_NTP -#define ENABLE_NIS -#define ENABLE_INFO - -/* Define this to enable some compatability with 1.x and 2.x info files */ -// #define ENABLE_INFO_COMPAT - #include "dhcpcd.h" #include "interface.h" #include "dhcp.h" diff --git a/dhcp.c b/dhcp.c index 4b9bc0d0..642e1d98 100644 --- a/dhcp.c +++ b/dhcp.c @@ -21,10 +21,12 @@ #include #include +#include #include #include +#include #include #include #include @@ -457,6 +459,7 @@ int parse_dhcpmessage (dhcp_t *dhcp, const dhcpmessage_t *message) unsigned int len = 0; int i; int retval = -1; + struct timeval tv; route_t *routers = NULL; route_t *routersp = NULL; route_t *static_routes = NULL; @@ -465,6 +468,13 @@ int parse_dhcpmessage (dhcp_t *dhcp, const dhcpmessage_t *message) end += sizeof (message->options); + if (gettimeofday (&tv, NULL) == -1) { + logger (LOG_ERR, "gettimeofday: %s", strerror (errno)); + return (-1); + } + dhcp->leasedfrom = tv.tv_sec; + dhcp->frominfo = false; + dhcp->address.s_addr = message->yiaddr; strlcpy (dhcp->servername, message->servername, sizeof (dhcp->servername)); diff --git a/dhcp.h b/dhcp.h index e86197af..9b88dc34 100644 --- a/dhcp.h +++ b/dhcp.h @@ -131,6 +131,7 @@ typedef struct dhcp_t struct in_addr broadcast; unsigned short mtu; + unsigned int leasedfrom; unsigned int leasetime; unsigned int renewaltime; unsigned int rebindtime; @@ -151,6 +152,8 @@ typedef struct dhcp_t char *message; char *rootpath; + + bool frominfo; } dhcp_t; diff --git a/dhcpcd.8 b/dhcpcd.8 index eec47653..576da490 100644 --- a/dhcpcd.8 +++ b/dhcpcd.8 @@ -9,7 +9,7 @@ dhcpcd \- DHCP client daemon .in +.5i .ti -.5i dhcpcd -\%[\-adknpGHNRY] +\%[\-adknpGHMNRTY] \%[\-c\ script] \%[\-h\ hostname] \%[\-i\ vendorClassID] @@ -235,6 +235,15 @@ from replacing .I /etc/resolv.conf or using resolvconf. .TP +.BI \-T +Will read +.I /var/lib/dhcpcd/dhcpcd-.info +file and use last known good lease if +.B dhcpcd +is unable to reach the DHCP server and the lease has not expired. +This puts \fBdhcpcd\fR into the BOUND or REBINDING state depending on +how long the lease has until expiry. +.TP .BI \-Y Prevents .B dhcpcd diff --git a/dhcpcd.c b/dhcpcd.c index 2a952e6b..0ce089d7 100644 --- a/dhcpcd.c +++ b/dhcpcd.c @@ -93,7 +93,7 @@ void make_pid (const char *pidfile) static void usage () { - printf ("usage: "PACKAGE" [-adknpGHMNRY] [-c script] [-h hostame] [-i classID]\n" + printf ("usage: "PACKAGE" [-adknpGHLMNRY] [-c script] [-h hostame] [-i classID]\n" " [-l leasetime] [-m metric] [-s ipaddress] [-t timeout]\n" " [-u userclass] [-F [none | ptr | both]] [-I clientID]\n"); } @@ -125,14 +125,15 @@ int main(int argc, char **argv) {"request", required_argument, NULL, 's'}, {"timeout", required_argument, NULL, 't'}, {"userclass", required_argument, NULL, 'u'}, - {"fqdn", optional_argument, NULL, 'F'}, + {"lastlease", no_argument, NULL, 'E'}, + {"fqdn", optional_argument, NULL, 'F'}, {"nogateway", no_argument, NULL, 'G'}, {"sethostname", no_argument, NULL, 'H'}, {"clientid", required_argument, NULL, 'I'}, {"nomtu", no_argument, NULL, 'M'}, {"nontp", no_argument, NULL, 'N'}, {"nodns", no_argument, NULL, 'R'}, - {"nonis", no_argument, NULL, 'Y'}, + {"nonis", no_argument, NULL, 'Y'}, {"help", no_argument, &dohelp, 1}, {"version", no_argument, &doversion, 1}, {NULL, 0, NULL, 0} @@ -157,7 +158,7 @@ int main(int argc, char **argv) options.daemonise = true; options.timeout = DEFAULT_TIMEOUT; - while ((ch = getopt_long(argc, argv, "ac:dh:i:kl:m:nps:t:u:F:GHI:MNRY", longopts, + while ((ch = getopt_long(argc, argv, "ac:dh:i:kl:m:nps:t:u:EF:GHI:MNRY", longopts, &option_index)) != -1) switch (ch) { case 0: @@ -249,6 +250,9 @@ int main(int argc, char **argv) options.userclass_len += (strlen (optarg)) + 1; } break; + case 'E': + options.dolastlease = true; + break; case 'F': if (strncmp (optarg, "none", strlen (optarg)) == 0) options.fqdn = FQDN_NONE; diff --git a/dhcpcd.h b/dhcpcd.h index 82066e00..ff1086f2 100644 --- a/dhcpcd.h +++ b/dhcpcd.h @@ -57,6 +57,7 @@ typedef struct options_t { bool domtu; bool donis; bool dontp; + bool dolastlease; int signal; bool persistent;