]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
config.h now has the compile time options, instead of being dotted around.
authorRoy Marples <roy@marples.name>
Thu, 10 May 2007 09:39:26 +0000 (09:39 +0000)
committerRoy Marples <roy@marples.name>
Thu, 10 May 2007 09:39:26 +0000 (09:39 +0000)
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.

13 files changed:
ChangeLog
Makefile
arp.c
arp.h
client.c
common.c
configure.c
configure.h
dhcp.c
dhcp.h
dhcpcd.8
dhcpcd.c
dhcpcd.h

index 071df3d434398b0ef082aead0df81935e967e75e..6334ed4c15163e8562b7fd1181f90669a44229d3 100644 (file)
--- 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.
index ebbe1942f27d9964097fb75799ed12f8dc0a6182..4c3bbe3158b1d3a1ed1a4356ec9032c5d08b31c5 100644 (file)
--- 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 0828ec1c7c5c3405e686a70fabecbe453efb255f..be340484e40778995c013a5e9c556a17fb39cf4a 100644 (file)
--- a/arp.c
+++ b/arp.c
@@ -34,6 +34,7 @@
 #include <string.h>
 #include <unistd.h>
 
+#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 25563c60d4b115c4d86ee4a66de058bcf1710c15..bb424748cc7fe134a2693c00ca7611a3a9e4b8fd 100644 (file)
--- a/arp.h
+++ b/arp.h
 #ifndef ARP_H
 #define ARP_H
 
+#ifdef ENABLE_ARP
 #include <netinet/in.h>
 
 #include "interface.h"
 
 int arp_check (interface_t *iface, struct in_addr address);
+#endif
 
 #endif
index 9d603c91a6b45101e3d2200c5bc8825b3d6258b4..693790f3bb8e420a647a38090200b8de79decde5 100644 (file)
--- a/client.c
+++ b/client.c
@@ -21,6 +21,7 @@
 
 #include <sys/types.h>
 #include <sys/select.h>
+#include <sys/time.h>
 #include <arpa/inet.h>
 #ifdef __linux__
 #include <netinet/ether.h>
 #include <time.h>
 #include <unistd.h>
 
+#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;
index c609abaa0dd42a20e367fa5c379349db69832840..7362d7933811727f531ec52dddf138b690854c57 100644 (file)
--- 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;
        }
index 1904a2423841e417e305d11030d2a1b5e0fea527..27567ce0fee17fdeb61ed53672526ab1a3e9bb87 100644 (file)
 #include <stdlib.h>
 #include <unistd.h>
 
+#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 ||
index ac4eb2e3dc62241dd6f99bd496049c09af08a7c3..ddc709f9820242893fa0542d07f029dd040b406b 100644 (file)
 #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 4b9bc0d0fe2f15ddf8785c04feb2073c7711eeff..642e1d9895e85c100677b6876d655da6d060ed11 100644 (file)
--- a/dhcp.c
+++ b/dhcp.c
 
 #include <sys/types.h>
 #include <sys/socket.h>
+#include <sys/time.h>
 
 #include <netinet/in.h>
 #include <net/if_arp.h>
 
+#include <errno.h>
 #include <limits.h>
 #include <math.h>
 #include <stdint.h>
@@ -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 e86197af8a5ffa4f13fe3beeb428fd27f8d9ff5b..9b88dc340d0310e5139514cc5fae87b23a887720 100644 (file)
--- 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;
 
 
index eec47653b72b0ae9ce7ada7047d898042cc49b24..576da490252e93e0a2e10d384277dd155d968525 100644 (file)
--- 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-<interface>.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
index 2a952e6b41817e006af227c65d17ba45ac64b21d..0ce089d73a87bd8af85e04557efb1bbaaa156f1f 100644 (file)
--- 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;
index 82066e0037ecf40e92185be32bc8274df0846583..ff1086f2891068e65e9840f646e5916ee43457f0 100644 (file)
--- 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;