]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Quote all vars in the info file.
authorRoy Marples <roy@marples.name>
Thu, 30 Nov 2006 13:04:23 +0000 (13:04 +0000)
committerRoy Marples <roy@marples.name>
Thu, 30 Nov 2006 13:04:23 +0000 (13:04 +0000)
-n and -G options now work as stated in the man page.
Handle select loops with large timeouts and infinite lease times.
Correctly set the broadcast flag.
make_dhcp_packet already has byte ordered addresses, thanks to TGL
for the fix.
If we get a NAK then always re-enter the INIT state.

ChangeLog
Makefile
client.c
configure.c
dhcp.c
dhcp.h
dhcpcd.8
dhcpcd.c
dhcpcd.h
interface.c
socket.c

index 3acca3d3b94ee5378f4ae74f46db14b0d5efe029..514b3f9d16a751f775709cc76a98f4c632e89665 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+dhcpcd-3.0.1
+Quote all vars in the info file.
+-n and -G options now work as stated in the man page.
+Handle select loops with large timeouts and infinite lease times.
+Correctly set the broadcast flag.
+make_dhcp_packet already has byte ordered addresses, thanks to TGL
+for the fix.
+If we get a NAK then always re-enter the INIT state.
+
 dhcpcd-3.0.0
 A complete rewrite by Roy Marples <uberlord@gentoo.org>
 
index c632972863420f6c4b8f8b9eda9c6e4b55f0e968..bf03a21bf6590972c571da8ef5cd5846ed29d710 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 # Should work for both GNU make and BSD mke
 
-VERSION = 3.0.0
+VERSION = 3.0.1
 
 INSTALL ?= install
 CFLAGS ?= -Wall -O2 -pedantic -std=gnu99
index 0ed7fb5c41d65e45c7c8d7581e36e3c1ce0a0f00..46a07ba2b07976e004079c62dd3b4e2e4a967a35 100644 (file)
--- a/client.c
+++ b/client.c
 #include "signals.h"
 #include "socket.h"
 
+/* We need this for our maximum timeout as FreeBSD's select cannot handle
+   any higher than this. Is there a better way of working this out? */
+#define SELECT_MAX 100000000 
+
 /* This is out mini timeout.
    Basically we resend the last request every TIMEOUT_MINI seconds. */
 #define TIMEOUT_MINI           3
@@ -73,22 +77,13 @@ send_message (iface, &dhcp, xid, _type, options);
 
 static int daemonise (char *pidfile)
 {
-  FILE *fp;
-
   if (daemon (0, 0) < 0)
     {
       logger (LOG_ERR, "unable to daemonise: %s", strerror (errno));
       return -1;
     }
 
-  if ((fp = fopen (pidfile, "w")) == NULL)
-    {
-      logger (LOG_ERR, "fopen `%s': %m", pidfile);
-      return -1;
-    }
-
-  fprintf (fp, "%u\n", getpid ());
-  fclose (fp);
+  make_pid (pidfile);
 
   return 0;
 }
@@ -127,7 +122,7 @@ int dhcp_run (options_t *options)
   int state = STATE_INIT;
   struct timeval tv;
   int xid = 0;
-  unsigned long timeout = 0;
+  long timeout = 0;
   fd_set rset;
   int maxfd;
   int retval;
@@ -150,14 +145,12 @@ int dhcp_run (options_t *options)
   /* Remove all existing addresses.
      After all, we ARE a DHCP client whose job it is to configure the
      interface. We only do this on start, so persistent addresses can be added
-     afterwards by the user if needed.
-     */
+     afterwards by the user if needed. */
   flush_addresses (iface->name);
 
   memset (&dhcp, 0, sizeof (dhcp_t));
   memset (&last_dhcp, 0, sizeof (dhcp_t));
 
-  dhcp.leasetime = options->leasetime;
   strcpy (dhcp.classid, options->classid);
   if (options->clientid[0])
     strcpy (dhcp.clientid, options->clientid);
@@ -165,22 +158,18 @@ int dhcp_run (options_t *options)
     sprintf (dhcp.clientid, "%s", ether_ntoa (&iface->ethernet_address));
 
   if (options->requestaddress.s_addr != 0)
-    memcpy (&dhcp.address, &options->requestaddress, sizeof (struct in_addr));
+    dhcp.address.s_addr = options->requestaddress.s_addr;
 
   signal_setup ();
 
   while (1)
     {
-      int timeout_secs = timeout - uptime();
-      tv.tv_sec = timeout - uptime ();
-      tv.tv_usec = 0;
-
       maxfd = signal_fd_set (&rset, iface->fd);
 
-      if (timeout_secs > 0 || (options->timeout == 0 &&
-                              (state != STATE_INIT || xid)))
+      if (timeout > 0 || (options->timeout == 0 &&
+                         (state != STATE_INIT || xid)))
        {
-         if (options->timeout == 0)
+         if (options->timeout == 0 || dhcp.leasetime == -1)
            {
              logger (LOG_DEBUG, "waiting on select for infinity");
              retval = select (maxfd + 1, &rset, NULL, NULL, NULL);
@@ -188,27 +177,24 @@ int dhcp_run (options_t *options)
          else
            {
              logger (LOG_DEBUG, "waiting on select for %d seconds",
-                     timeout_secs);
+                     timeout);
              /* If we're waiting for a reply, then we re-send the last
                 DHCP request periodically in-case of a bad line */
-             if (iface->fd == -1)
+             retval = 0;
+             while (timeout > 0 && retval == 0)
                {
-                 tv.tv_sec = timeout_secs;
+                 if (iface->fd == -1)
+                   tv.tv_sec = SELECT_MAX;
+                 else
+                   tv.tv_sec = TIMEOUT_MINI;
+                 if (timeout < tv.tv_sec)
+                   tv.tv_sec = timeout;
                  tv.tv_usec = 0;
+                 start = uptime ();
                  retval = select (maxfd + 1, &rset, NULL, NULL, &tv);
-               }
-             else
-               {
-                 while (timeout_secs > 0)
-                   {
-                     tv.tv_sec = TIMEOUT_MINI;
-                     tv.tv_usec = 0;
-                     retval = select (maxfd + 1, &rset, NULL, NULL, &tv);
-                     if (retval != 0)
-                       break;
-                     send_message (iface, &last_dhcp, xid, last_type, options);
-                     timeout_secs -= TIMEOUT_MINI;
-                   }
+                 if (retval == 0 && iface->fd != -1)
+                   send_message (iface, &last_dhcp, xid, last_type, options);
+                 timeout -= uptime () - start;
                }
            }
        }
@@ -236,7 +222,6 @@ int dhcp_run (options_t *options)
              switch (state)
                {
                case STATE_BOUND:
-                 SOCKET_MODE (SOCKET_OPEN);
                case STATE_RENEWING:
                case STATE_REBINDING:
                  state = STATE_RENEW_REQUESTED;
@@ -313,51 +298,54 @@ int dhcp_run (options_t *options)
                    }
                }
 
-             timeout = uptime () + options->timeout;
+             SOCKET_MODE (SOCKET_OPEN);
+             timeout = options->timeout;
              if (dhcp.address.s_addr == 0)
-               logger (LOG_INFO, "broadcasting for lease");
+               {
+                 logger (LOG_INFO, "broadcasting for a lease");
+                 SEND_MESSAGE (DHCP_DISCOVER);
+               }
              else
-               logger (LOG_INFO, "broadcasting for lease of %s",
-                       inet_ntoa (dhcp.address));
+               {
+                 logger (LOG_INFO, "broadcasting for a lease of %s",
+                         inet_ntoa (dhcp.address));
+                 SEND_MESSAGE (DHCP_REQUEST);
+                 state = STATE_REQUESTING;
+               }
 
-             SOCKET_MODE (SOCKET_OPEN);
-             SEND_MESSAGE (DHCP_DISCOVER);
              break;
            case STATE_BOUND:
+           case STATE_RENEW_REQUESTED:
              state = STATE_RENEWING;
+             xid = random_xid ();
            case STATE_RENEWING:
              logger (LOG_INFO, "renewing lease of %s", inet_ntoa
                      (dhcp.address));
              SOCKET_MODE (SOCKET_OPEN);
-             xid = random_xid ();
              SEND_MESSAGE (DHCP_REQUEST);
-             timeout = uptime() + (dhcp.rebindtime - dhcp.renewaltime);
+             timeout = dhcp.rebindtime - dhcp.renewaltime;
              state = STATE_REBINDING;
              break;
            case STATE_REBINDING:
              logger (LOG_ERR, "lost lease, attemping to rebind");
-             xid = random_xid ();
+             SOCKET_MODE (SOCKET_OPEN);
              SEND_MESSAGE (DHCP_DISCOVER);
-             timeout = uptime() + (dhcp.leasetime - dhcp.rebindtime);
+             timeout = dhcp.leasetime - dhcp.rebindtime;
              state = STATE_INIT;
              break;
            case STATE_REQUESTING:
-           case STATE_RENEW_REQUESTED:
              logger (LOG_ERR, "timed out");
-             if (! daemonised)
-               {
-                 retval = -1;
-                 goto eexit;
-               }
-
              state = STATE_INIT;
-             timeout = uptime();
+             SOCKET_MODE (SOCKET_CLOSED);
+             timeout = 0;
              xid = 0;
-             SOCKET_MODE (SOCKET_OPEN);
+             free_dhcp (&dhcp);
+             memset (&dhcp, 0, sizeof (dhcp_t));
+             memset (&last_dhcp, 0, sizeof (dhcp_t));
              break;
 
            case STATE_RELEASED:
-             timeout = 0x7fffffff;
+             dhcp.leasetime = -1;
              break;
            }
        }
@@ -386,15 +374,16 @@ int dhcp_run (options_t *options)
 
              if (xid != message.xid)
                {
-                 logger (LOG_ERR, "ignoring transaction %d as it's not ours (%d)",
+                 logger (LOG_ERR,
+                         "ignoring packet with xid %d as it's not ours (%d)",
                          message.xid, xid);
                  continue;
                }
 
-             logger (LOG_DEBUG, "got packet with transaction %d", message.xid);
+             logger (LOG_DEBUG, "got a packet with xid %d", message.xid);
              if ((type = parse_dhcpmessage (&dhcp, &message)) < 0)
                {
-                 logger (LOG_ERR, "failed to parse message");
+                 logger (LOG_ERR, "failed to parse packet");
                  continue;
                }
 
@@ -409,6 +398,20 @@ int dhcp_run (options_t *options)
          if (! valid)
            continue;
 
+         /* We should restart on a NAK */
+         if (type == DHCP_NAK)
+           {
+             logger (LOG_INFO, "received NAK: %s", dhcp.message);
+             state = STATE_INIT;
+             timeout = 0;
+             xid = 0;
+             free_dhcp (&dhcp);
+             memset (&dhcp, 0, sizeof (dhcp_t));
+             memset (&last_dhcp, 0, sizeof (dhcp_t));
+             configure (options, iface, &dhcp);
+             continue;
+           }
+
          switch (state)
            {
            case STATE_INIT:
@@ -474,11 +477,16 @@ int dhcp_run (options_t *options)
                              dhcp.rebindtime);
                    }
 
-                 logger (LOG_INFO, "leased %s for %d seconds",
-                         inet_ntoa (dhcp.address), dhcp.leasetime);
+                 if (dhcp.leasetime == -1)
+                   logger (LOG_INFO, "leased %s for infinity",
+                           inet_ntoa (dhcp.address));
+                 else
+                   logger (LOG_INFO, "leased %s for %u seconds",
+                           inet_ntoa (dhcp.address),
+                           dhcp.leasetime, dhcp.renewaltime);
+
                  state = STATE_BOUND;
-                 start = uptime ();
-                 timeout = start + dhcp.renewaltime;
+                 timeout = dhcp.renewaltime;
                  xid = 0;
 
                  if (configure (options, iface, &dhcp) < 0 && ! daemonised)
@@ -497,8 +505,6 @@ int dhcp_run (options_t *options)
                      daemonised = true;
                    }
                }
-             else if (type == DHCP_NAK)
-               logger (LOG_INFO, "received NAK: %s", dhcp.message);
              else if (type == DHCP_OFFER)
                logger (LOG_INFO, "got subsequent offer of %s, ignoring ",
                        inet_ntoa (dhcp.address));
@@ -511,12 +517,14 @@ int dhcp_run (options_t *options)
        }
       else if (retval == -1 && errno == EINTR)
        {
-         /* Signal interupt will be handled above */
+         /* The interupt will be handled above */
        }
       else 
        {
-         /* An error occured */
+         /* An error occured. As we heavily depend on select, we abort. */
          logger (LOG_ERR, "error on select: %s", strerror (errno));
+         retval = -1;
+         goto eexit;
        }
     }
 
@@ -524,15 +532,10 @@ eexit:
   SOCKET_MODE (SOCKET_CLOSED);
 
   /* Remove our config if we need to */
-  if (dhcp.address.s_addr != 0 && ! options->persistent && daemonised)
-    {
-      dhcp.address.s_addr = 0;
-      dhcp.netmask.s_addr = 0;
-      dhcp.broadcast.s_addr = 0;
-      configure (options, iface, &dhcp);
-    }
-
   free_dhcp (&dhcp);
+  memset (&dhcp, 0, sizeof (dhcp_t));
+  if (iface->previous_address.s_addr != 0 && ! options->persistent && daemonised)
+      configure (options, iface, &dhcp);
 
   if (iface)
     {
index ff6cecf4e558577b61381371ab21912dcb237ceb..a70859a52dc998accd68154c19e1f07a61491dcd 100644 (file)
@@ -252,11 +252,11 @@ static int write_info(interface_t *iface, dhcp_t *dhcp)
       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));
+  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);
+    fprintf (f, "MTU='%d'\n", dhcp->mtu);
   
   if (dhcp->routes)
     {
@@ -295,9 +295,9 @@ static int write_info(interface_t *iface, dhcp_t *dhcp)
 
   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, "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);
     }
 
@@ -331,12 +331,12 @@ static int write_info(interface_t *iface, dhcp_t *dhcp)
   if (dhcp->rootpath)
     fprintf (f, "ROOTPATH='%s'\n", cleanmetas (dhcp->rootpath));
 
-  fprintf (f, "DHCPSID=%s\n", inet_ntoa (dhcp->serveraddress));
-  fprintf (f, "DHCPCHADDR=%s\n", ether_ntoa (&iface->ethernet_address));
+  fprintf (f, "DHCPSID='%s'\n", inet_ntoa (dhcp->serveraddress));
+  fprintf (f, "DHCPCHADDR='%s'\n", ether_ntoa (&iface->ethernet_address));
   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, "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 (dhcp->classid));
   fprintf (f, "CLIENTID='%s'\n", cleanmetas (dhcp->clientid));
@@ -392,14 +392,17 @@ int configure (options_t *options, interface_t *iface, dhcp_t *dhcp)
          iface->previous_routes = NULL;
        }
 
+      /* Only reset things if we had set them before */
       if (iface->previous_address.s_addr != 0)
-       del_address (iface->name, iface->previous_address);
-      memset (&iface->previous_address, 0, sizeof (struct in_addr));
+       {
+         del_address (iface->name, iface->previous_address);
+         memset (&iface->previous_address, 0, sizeof (struct in_addr));
 
-      restore_resolv (iface->name);
-      
-      /* We currently don't have a resolvconf style programs for ntp/nis */
-      exec_script (options->script, iface->infofile, "down");
+         restore_resolv (iface->name);
+
+         /* we currently don't have a resolvconf style programs for ntp/nis */
+         exec_script (options->script, iface->infofile, "down");
+       }
       return 0;
     }
 
@@ -434,6 +437,11 @@ int configure (options_t *options, interface_t *iface, dhcp_t *dhcp)
       
       for (route = dhcp->routes; route; route = route->next)
        {
+         /* Don't set default routes if not asked to */
+         if (route->destination.s_addr == 0 && route->netmask.s_addr == 0
+             && ! options->dogateway)
+           continue;
+
          int remember = add_route (iface->name, route->destination,
                                    route->netmask,  route->gateway,
                                    options->metric);
diff --git a/dhcp.c b/dhcp.c
index 486b964d01e5a9d87e455007e3692844ef7cea15..dc9f6539327a32679a94f184d75a0e5d2bae92b5 100644 (file)
--- a/dhcp.c
+++ b/dhcp.c
@@ -36,6 +36,8 @@
 #include "logger.h"
 #include "socket.h"
 
+#define BROADCAST_FLAG 0x8000
+
 static char *dhcp_message[] = {
   [DHCP_DISCOVER]      = "DHCP_DISCOVER",
   [DHCP_OFFER]         = "DHCP_OFFER",
@@ -55,10 +57,24 @@ size_t send_message (interface_t *iface, dhcp_t *dhcp,
   unsigned char *p = (unsigned char *) &message.options;
   unsigned char *n_params = NULL;
   unsigned long l;
+  struct in_addr from;
+  struct in_addr to;
 
   if (!iface || !options || !dhcp)
     return -1;
 
+  if (type == DHCP_RELEASE || type == DHCP_INFORM ||
+      (type == DHCP_REQUEST &&
+       iface->previous_address.s_addr == dhcp->address.s_addr))
+    from.s_addr = dhcp->address.s_addr;
+  else
+    from.s_addr = 0;
+
+  if (type == DHCP_RELEASE)
+    to.s_addr = dhcp->serveraddress.s_addr;
+  else
+    to.s_addr = 0;
+
   memset (&message, 0, sizeof (dhcpmessage_t));
 
   message.op = DHCP_BOOTREQUEST;
@@ -67,11 +83,22 @@ size_t send_message (interface_t *iface, dhcp_t *dhcp,
   message.secs = htons (10);
   message.xid = xid;
   memcpy (&message.hwaddr, &iface->ethernet_address, ETHER_ADDR_LEN);
-  message.cookie = htonl(MAGIC_COOKIE);
+  message.cookie = htonl (MAGIC_COOKIE);
+
+  /* This logic should be improved so that we don't need to set the 0
+     flag as it's done in the above memset statement */
+  if (type == DHCP_REQUEST
+      && dhcp->address.s_addr == iface->previous_address.s_addr
+      && iface->previous_address.s_addr != 0)
+    message.flags = 0;
+  else
+    message.flags = htons (BROADCAST_FLAG);
 
-  if (iface->previous_address.s_addr != 0 &&
-      iface->previous_address.s_addr == dhcp->address.s_addr)
-    message.ciaddr = iface->previous_address.s_addr; 
+  if (iface->previous_address.s_addr != 0
+      && (type == DHCP_INFORM || type == DHCP_RELEASE
+         || (type == DHCP_REQUEST
+             && iface->previous_address.s_addr == dhcp->address.s_addr)))
+    message.ciaddr = iface->previous_address.s_addr;
 
   *p++ = DHCP_MESSAGETYPE; 
   *p++ = 1;
@@ -86,72 +113,73 @@ size_t send_message (interface_t *iface, dhcp_t *dhcp,
       p += 2;
     }
 
-  if (dhcp->address.s_addr != 0 && iface->previous_address.s_addr == 0)
-    {
-      *p++ = DHCP_ADDRESS;
-      *p++ = 4;
-      memcpy (p, &dhcp->address.s_addr, 4);
-      p += 4;
+#define PUTADDR(_type, _val) \
+    { \
+      *p++ = _type; \
+      *p++ = 4; \
+      memcpy (p, &_val.s_addr, 4); \
+      p += 4; \
     }
+  if (dhcp->address.s_addr != 0 && iface->previous_address.s_addr == 0
+      && type != DHCP_RELEASE)
+    PUTADDR (DHCP_ADDRESS, dhcp->address);
 
   if (dhcp->serveraddress.s_addr != 0 && dhcp->address.s_addr !=0 &&
-      iface->previous_address.s_addr == 0)
-    {
-      *p++ = DHCP_SERVERIDENTIFIER;
-      *p++ = 4;
-      memcpy (p, &dhcp->serveraddress.s_addr, 4);
-      p += 4;
-
-      /* Blank out the server address so we broadcast */
-      if (type == DHCP_REQUEST) dhcp->serveraddress.s_addr = 0;
-    }
+      (iface->previous_address.s_addr == 0 || type == DHCP_RELEASE))
+    PUTADDR (DHCP_SERVERIDENTIFIER, dhcp->serveraddress);
+#undef PUTADDR
 
   if (type == DHCP_REQUEST || type == DHCP_DISCOVER)
     {
-      if (dhcp->leasetime > 0)
+      if (options->leasetime != 0)
        {
          *p++ = DHCP_LEASETIME;
          *p++ = 4;
-         uint32_t ul = htonl (dhcp->leasetime);
+         uint32_t ul = htonl (options->leasetime);
          memcpy (p, &ul, 4);
          p += 4;
        }
     }
 
-  *p++ = DHCP_PARAMETERREQUESTLIST;
-  n_params = p;
-  *p++ = 0;
-
-  if (type == DHCP_REQUEST)
+  if (type == DHCP_DISCOVER || type == DHCP_INFORM || type == DHCP_REQUEST)
     {
-      *p++ = DHCP_RENEWALTIME;
-      *p++ = DHCP_REBINDTIME;
-      *p++ = DHCP_NETMASK;
-      *p++ = DHCP_BROADCAST;
-      *p++ = DHCP_CSR;
-      /* RFC 3442 states classless static routes should be before routers
-       * and static routes as classless static routes override them both */
-      *p++ = DHCP_ROUTERS;
-      *p++ = DHCP_STATICROUTE;
-      *p++ = DHCP_HOSTNAME;
-      *p++ = DHCP_DNSSEARCH;
-      *p++ = DHCP_DNSDOMAIN;
-      *p++ = DHCP_DNSSERVER;
-      *p++ = DHCP_NISDOMAIN;
-      *p++ = DHCP_NISSERVER;
-      *p++ = DHCP_NTPSERVER;
-      /* These parameters were requested by dhcpcd-2.0 and earlier
-        but we never did anything with them */
-      /*    *p++ = DHCP_DEFAULTIPTTL;
-       *p++ = DHCP_MASKDISCOVERY;
-       *p++ = DHCP_ROUTERDISCOVERY; */
-    }
-  else
-    /* Always request one parameter so we don't get the server default
-       when we don't actally need any at this time */
-    *p++ = DHCP_DNSSERVER;
+      *p++ = DHCP_PARAMETERREQUESTLIST;
+      n_params = p;
+      *p++ = 0;
 
-  *n_params = p - n_params - 1;
+      /* If we don't request one item, then we get defaults back which
+        we don't want */
+      if (type == DHCP_DISCOVER)
+       {
+         *p++ = DHCP_DNSSERVER;
+       }
+      else
+       {
+         *p++ = DHCP_RENEWALTIME;
+         *p++ = DHCP_REBINDTIME;
+         *p++ = DHCP_NETMASK;
+         *p++ = DHCP_BROADCAST;
+         *p++ = DHCP_CSR;
+         /* RFC 3442 states classless static routes should be before routers
+          * and static routes as classless static routes override them both */
+         *p++ = DHCP_ROUTERS;
+         *p++ = DHCP_STATICROUTE;
+         *p++ = DHCP_HOSTNAME;
+         *p++ = DHCP_DNSSEARCH;
+         *p++ = DHCP_DNSDOMAIN;
+         *p++ = DHCP_DNSSERVER;
+         *p++ = DHCP_NISDOMAIN;
+         *p++ = DHCP_NISSERVER;
+         *p++ = DHCP_NTPSERVER;
+         /* These parameters were requested by dhcpcd-2.0 and earlier
+            but we never did anything with them */
+         /*    *p++ = DHCP_DEFAULTIPTTL;
+          *p++ = DHCP_MASKDISCOVERY;
+          *p++ = DHCP_ROUTERDISCOVERY; */
+       }
+
+      *n_params = p - n_params - 1;
+    }
 
   if (type == DHCP_REQUEST)
     {
@@ -184,19 +212,22 @@ size_t send_message (interface_t *iface, dhcp_t *dhcp,
        }
     }
 
-  if (options->userclass)
+  if (type != DHCP_DECLINE && type != DHCP_RELEASE)
     {
-      *p++ = DHCP_USERCLASS;
-      *p++ = l = strlen (options->userclass);
-      memcpy (p, options->userclass, l);
+      if (options->userclass)
+       {
+         *p++ = DHCP_USERCLASS;
+         *p++ = l = strlen (options->userclass);
+         memcpy (p, options->userclass, l);
+         p += l;
+       }
+      
+      *p++ = DHCP_CLASSID;
+      *p++ = l = strlen (options->classid);
+      memcpy (p, options->classid, l);
       p += l;
     }
 
-  *p++ = DHCP_CLASSID;
-  *p++ = l = strlen (options->classid);
-  memcpy (p, options->classid, l);
-  p += l;
-
   *p++ = DHCP_CLIENTID;
   if (options->clientid[0])
     {
@@ -218,8 +249,7 @@ size_t send_message (interface_t *iface, dhcp_t *dhcp,
 
   struct udp_dhcp_packet packet;
   memset (&packet, 0, sizeof (struct udp_dhcp_packet));
-  make_dhcp_packet (&packet, (unsigned char *) &message,
-                   dhcp->address, dhcp->serveraddress);
+  make_dhcp_packet (&packet, (unsigned char *) &message, from, to);
 
   logger (LOG_DEBUG, "Sending %s with xid %d", dhcp_message[(int) type], xid);
   return send_packet (iface, ETHERTYPE_IP, (unsigned char *) &packet,
@@ -330,7 +360,7 @@ static route_t *decodeCSR(unsigned char *p, int len)
     {
       memset (route, 0, sizeof (route_t));
 
-      cidr = (int) *q++;
+      cidr = *q++;
       if (cidr == 0)
        ocets = 0;
       else if (cidr < 9)
@@ -475,94 +505,77 @@ int parse_dhcpmessage (dhcp_t *dhcp, dhcpmessage_t *message)
        case DHCP_MESSAGETYPE:
          retval = (int) *p;
          break;
-
+#define GET_UINT32(_val) \
+         memcpy (&_val, p, sizeof (uint32_t));
+#define GET_UINT32_H(_val) \
+         GET_UINT32 (_val); \
+         _val = ntohl (_val);
        case DHCP_ADDRESS:
-         memcpy (&dhcp->address.s_addr, p, 4);
+         GET_UINT32 (dhcp->address.s_addr);
          break;
        case DHCP_NETMASK:
-         memcpy (&dhcp->netmask.s_addr, p, 4);
+         GET_UINT32 (dhcp->netmask.s_addr);
          break;
        case DHCP_BROADCAST:
-         memcpy (&dhcp->broadcast.s_addr, p, 4);
+         GET_UINT32 (dhcp->broadcast.s_addr);
          break;
        case DHCP_SERVERIDENTIFIER:
-         memcpy (&dhcp->serveraddress.s_addr, p, 4);
+         GET_UINT32 (dhcp->serveraddress.s_addr);
          break;
-
        case DHCP_LEASETIME:
-         dhcp->leasetime = ntohl (* (uint32_t *) p);
+         GET_UINT32_H (dhcp->leasetime);
          break;
        case DHCP_RENEWALTIME:
-         dhcp->renewaltime = ntohl (* (uint32_t *) p);
+         GET_UINT32_H (dhcp->renewaltime);
          break;
        case DHCP_REBINDTIME:
-         dhcp->rebindtime = ntohl (* (uint32_t *) p);
+         GET_UINT32_H (dhcp->rebindtime);
          break;
        case DHCP_MTU:
-         dhcp->mtu = ntohs (* (uint16_t *) p);
+         GET_UINT32_H (dhcp->mtu);
          /* Minimum legal mtu is 68 */
          if (dhcp->mtu > 0 && dhcp->mtu < 68)
            dhcp->mtu = 68;
          break;
-
+#undef GET_UINT32_H
+#undef GET_UINT32
+
+#define GETSTR(_var) \
+         if (_var) free (_var); \
+         _var = xmalloc (length + 1); \
+         memcpy (_var, p, length); \
+         memset (_var + length, 0, 1);
        case DHCP_HOSTNAME:
-         if (dhcp->hostname)
-           free (dhcp->hostname);
-         dhcp->hostname = xmalloc (length + 1);
-         memcpy (dhcp->hostname, p, length);
-         dhcp->hostname[length] = '\0';
+         GETSTR (dhcp->hostname);
          break;
-
        case DHCP_DNSDOMAIN:
-         if (dhcp->dnsdomain)
-           free (dhcp->dnsdomain);
-         dhcp->dnsdomain = xmalloc (length + 1);
-         memcpy (dhcp->dnsdomain, p, length);
-         dhcp->dnsdomain[length] = '\0';
+         GETSTR (dhcp->dnsdomain);
          break;
-
        case DHCP_MESSAGE:
-         if (dhcp->message)
-           free (dhcp->message);
-         dhcp->message = xmalloc (length + 1);
-         memcpy (dhcp->message, p, length);
-         dhcp->message[length] = '\0';
+         GETSTR (dhcp->message);
          break;
-
        case DHCP_ROOTPATH:
-         if (dhcp->rootpath)
-           free (dhcp->rootpath);
-         dhcp->rootpath = xmalloc (length + 1);
-         memcpy (dhcp->rootpath, p, length);
-         dhcp->rootpath[length] = '\0';
+         GETSTR (dhcp->rootpath);
          break;
-
        case DHCP_NISDOMAIN:
-         if (dhcp->nisdomain)
-           free (dhcp->nisdomain);
-         dhcp->nisdomain = xmalloc (length + 1);
-         memcpy (dhcp->nisdomain, p, length);
-         dhcp->nisdomain[length] = '\0';
+         GETSTR (dhcp->nisdomain);
          break;
+#undef GETSTR
 
+#define GETADDR(_var) \
+         if (_var) free (_var); \
+         _var = xmalloc (sizeof (address_t)); \
+         dhcp_add_address (_var, p, length);
        case DHCP_DNSSERVER:
-         if (dhcp->dnsservers)
-           free_address (dhcp->dnsservers);
-         dhcp->dnsservers = xmalloc (sizeof (address_t));
-         dhcp_add_address (dhcp->dnsservers, p, length);
+         GETADDR (dhcp->dnsservers);
          break;
        case DHCP_NTPSERVER:
-         if (dhcp->ntpservers)
-           free_address (dhcp->ntpservers);
-         dhcp->ntpservers = xmalloc (sizeof (address_t));
-         dhcp_add_address (dhcp->ntpservers, p, length);
+         GETADDR (dhcp->ntpservers);
          break;
        case DHCP_NISSERVER:
-         if (dhcp->nisservers)
-           free_address (dhcp->nisservers);
-         dhcp->nisservers = xmalloc (sizeof (address_t));
-         dhcp_add_address (dhcp->nisservers, p, length);
+         GETADDR (dhcp->nisservers);
          break;
+#undef GETADDR
 
        case DHCP_DNSSEARCH:
          if (dhcp->dnssearch)
@@ -612,9 +625,9 @@ int parse_dhcpmessage (dhcp_t *dhcp, dhcpmessage_t *message)
 
 eexit:
   /* Fill in any missing fields */
-  if (!dhcp->netmask.s_addr)
+  if (! dhcp->netmask.s_addr)
     dhcp->netmask.s_addr = getnetmask (dhcp->address.s_addr);
-  if (!dhcp->broadcast.s_addr)
+  if (! dhcp->broadcast.s_addr)
     dhcp->broadcast.s_addr = dhcp->address.s_addr | ~dhcp->netmask.s_addr;
 
   /* If we have classess static routes then we discard
diff --git a/dhcp.h b/dhcp.h
index 93af9cfc41d6ac7960a9cef9735a3777b8b40283..b5076b388eb4d15f69c897a060a70403f06face2 100644 (file)
--- a/dhcp.h
+++ b/dhcp.h
@@ -128,9 +128,9 @@ typedef struct dhcp_t
   struct in_addr broadcast;
   unsigned short mtu;
 
-  unsigned leasetime;
-  unsigned renewaltime;
-  unsigned rebindtime;
+  unsigned int leasetime;
+  unsigned int renewaltime;
+  unsigned int rebindtime;
   
   route_t *routes;
 
index 936d27a40b9d2fc2c73e1b4feedb066150a1f7df..7bdf97539b3939b124117efdeeb196e9fd5a8bde 100644 (file)
--- a/dhcpcd.8
+++ b/dhcpcd.8
@@ -1,6 +1,6 @@
 .\" $Id$
 .\"
-.TH dhcpcd 8 "15 August 2006" "dhcpcd 3.0"
+.TH dhcpcd 8 "30 November 2006" "dhcpcd 3.0"
 
 .SH NAME
 dhcpcd \- DHCP client daemon
@@ -144,9 +144,11 @@ is stopped it can no longer down an interface at the end of its
 lease period when the lease is not renewed.
 .TP
 .BI \-s \ ipaddr
-Sends DHCP_DISCOVER message to DHCP server requesting to lease ip address
-ipaddr.
+Sends DHCP_REQUEST message requesting to lease IP address ipaddr.
 The ipaddr parameter must be in the form xxx.xxx.xxx.xxx.
+This effectively doubles the timeout period, as if we fail to get
+this IP address then we enter the INIT state and try to get any
+IP address.
 .TP
 .BI \-t \ timeout
 Specifies (in seconds ) for how long
index 9b03fb033c559d457d763c052eec015a57c5b168..0e5a5b20f76619a703e02c744ef6f09315c1cbce 100644 (file)
--- a/dhcpcd.c
+++ b/dhcpcd.c
@@ -56,7 +56,7 @@
   _int = (int) _number; \
 }
 
-static pid_t readpid(char *pidfile)
+static pid_t read_pid(const char *pidfile)
 {
   FILE *fp;
   pid_t pid;
@@ -73,18 +73,18 @@ static pid_t readpid(char *pidfile)
   return pid;
 }
 
-static int kill_pid (char *pidfile, int sig)
+void make_pid (const char *pidfile)
 {
-  pid_t pid = readpid (pidfile);
-  int r = 0;
+  FILE *fp;
 
-  if (!pid || (r = kill (pid, sig)))
+  if ((fp = fopen (pidfile, "w")) == NULL)
     {
-      logger (LOG_ERR, ""PACKAGE" not running");
-      unlink (pidfile);
+      logger (LOG_ERR, "fopen `%s': %s", pidfile, strerror (errno));
+      return;
     }
 
-  return r;
+  fprintf (fp, "%u\n", getpid ());
+  fclose (fp);
 }
 
 static void usage ()
@@ -330,20 +330,31 @@ int main(int argc, char **argv)
            options.interface);
 
   if (options.signal != 0)
-    exit (kill_pid (options.pidfile, options.signal));
-
-  umask (022);
-
-  if (readpid (options.pidfile))
     {
-      logger (LOG_ERR, ""PACKAGE" already running (%s)", options.pidfile);
-      exit (EXIT_FAILURE);
+      pid_t pid = read_pid (options.pidfile);
+      if (pid != 0)
+        logger (LOG_INFO, "sending signal %d to pid %d", options.signal, pid);
+     
+      int killed = -1;
+      if (! pid || (killed = kill (pid, options.signal)))
+       logger (options.signal == SIGALRM ? LOG_INFO : LOG_ERR, ""PACKAGE" not running");
+
+      if (pid != 0 && (options.signal != SIGALRM || killed != 0))
+       unlink (options.pidfile);
+
+      if (killed == 0)
+       exit (EXIT_SUCCESS);
+
+      if (options.signal != SIGALRM)
+       exit (EXIT_FAILURE);
     }
 
+  umask (022);
+
   if (mkdir (CONFIGDIR, S_IRUSR |S_IWUSR |S_IXUSR | S_IRGRP | S_IXGRP
             | S_IROTH | S_IXOTH) && errno != EEXIST )
     {
-      loggerLOG_ERR, "mkdir(\"%s\",0): %m\n", CONFIGDIR);
+      logger (LOG_ERR, "mkdir(\"%s\",0): %m\n", CONFIGDIR);
       exit (EXIT_FAILURE);
     }
 
@@ -354,6 +365,14 @@ int main(int argc, char **argv)
       exit (EXIT_FAILURE);
     }
 
+  if (read_pid (options.pidfile))
+    {
+      logger (LOG_ERR, ""PACKAGE" already running (%s)", options.pidfile);
+      exit (EXIT_FAILURE);
+    }
+
+  make_pid (options.pidfile);
+
   logger (LOG_INFO, PACKAGE " " VERSION " starting");
   if (dhcp_run (&options))
     exit (EXIT_FAILURE);
index f0ffb5a54a1f7c02bea17c6071d86791c2831696..820ab86cbdbc3eef4cfb9a82543874b72abc44a8 100644 (file)
--- a/dhcpcd.h
+++ b/dhcpcd.h
@@ -64,4 +64,6 @@ typedef struct options_t {
   char pidfile[PATH_MAX];
 } options_t;
 
+void make_pid (const char *pidfile);
+
 #endif
index c55a662c16b35855e00ba81b6c15dd81a73f7a9b..abdfbfc14a7b82082c1eecd8f46616e1ddbddc39 100644 (file)
 #include "logger.h"
 #include "pathnames.h"
 
-#ifndef IFF_NOTRAILERS
-#define        IFF_NOTRAILERS 0
-#endif
-
 void free_address (address_t *addresses)
 {
   if (!addresses)
@@ -99,7 +95,6 @@ interface_t *read_interface (const char *ifname, int metric)
 
   struct ifaddrs *ifap;
   struct ifaddrs *p;
-  unsigned int flags;
 
   if (getifaddrs (&ifap) != 0)
     return NULL;
@@ -122,7 +117,6 @@ interface_t *read_interface (const char *ifname, int metric)
          return NULL;
        }
 
-      flags = p->ifa_flags;
 #ifdef __linux__
       memcpy (hwaddr, sll->sll_addr, ETHER_ADDR_LEN);
 #else
@@ -146,30 +140,34 @@ interface_t *read_interface (const char *ifname, int metric)
       return NULL;
     }
 
-  if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0)
+#ifndef __linux__
+  ifr.ifr_metric = metric;
+  if (ioctl(s, SIOCSIFMETRIC, &ifr) < 0)
     {
-      logger (LOG_ERR, "ioctl SIOCGIFFLAGS: %s", strerror (errno));
+      logger (LOG_ERR, "ioctl SIOCSIFMETRIC: %s", strerror (errno));
       close (s);
       return NULL;
     }
+#endif
 
-  ifr.ifr_flags |= IFF_UP | IFF_BROADCAST | IFF_NOTRAILERS | IFF_RUNNING;
-  if (ioctl(s, SIOCSIFFLAGS, &ifr) < 0)
+  if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0)
     {
-      logger (LOG_ERR, "ioctl SIOCSIFFLAGS: %s", strerror (errno));
+      logger (LOG_ERR, "ioctl SIOCGIFFLAGS: %s", strerror (errno));
       close (s);
       return NULL;
     }
 
-#ifndef __linux__
-  ifr.ifr_metric = metric;
-  if (ioctl(s, SIOCSIFMETRIC, &ifr) < 0)
+  /* Bring the interface up if we need to */
+  if (! (ifr.ifr_flags & IFF_UP))
     {
-      logger (LOG_ERR, "ioctl SIOCSIFMETRIC: %s", strerror (errno));
-      close (s);
-      return NULL;
+      ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
+      if (ioctl(s, SIOCSIFFLAGS, &ifr) < 0)
+       {
+         logger (LOG_ERR, "ioctl SIOCSIFFLAGS: %s", strerror (errno));
+         close (s);
+         return NULL;
+       }
     }
-#endif
 
   close (s);
 
index 3996d3b2cd25fa642f0c6e055a19069682f9f646..5c33ba601bab8befec7fe3c3a29583a9fca46199 100644 (file)
--- a/socket.c
+++ b/socket.c
@@ -94,11 +94,11 @@ void make_dhcp_packet(struct udp_dhcp_packet *packet,
   memcpy (&packet->dhcp, data, sizeof (dhcpmessage_t));
 
   ip->ip_p = IPPROTO_UDP;
-  ip->ip_src.s_addr = htonl (source.s_addr);
+  ip->ip_src.s_addr = source.s_addr;
   if (dest.s_addr == 0)
-    ip->ip_dst.s_addr = htonl (INADDR_BROADCAST);
+    ip->ip_dst.s_addr = INADDR_BROADCAST;
   else
-    ip->ip_dst.s_addr = htonl (dest.s_addr);
+    ip->ip_dst.s_addr = dest.s_addr;
 
   udp->uh_sport = htons (DHCP_CLIENT_PORT);
   udp->uh_dport = htons (DHCP_SERVER_PORT);