changeset 60:76274880aa25 draft

Test to see if the pid in the pidfile is actually running before claiming that we are. Fix the error since 3.0.6. We now ensure that our renewal and rebind times are sane. Fix flushing interfaces for systems without getifaddrs and >1 interface. All netlink error messages are now prefixed with netlink.
author Roy Marples <roy@marples.name>
date Tue, 20 Feb 2007 22:57:10 +0000
parents 047729b6641a
children 835ca00adaa9
files ChangeLog Makefile client.c configure.c dhcp.c dhcpcd.c interface.c interface.h
diffstat 8 files changed, 135 insertions(+), 74 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Mon Feb 12 17:08:44 2007 +0000
+++ b/ChangeLog	Tue Feb 20 22:57:10 2007 +0000
@@ -1,3 +1,9 @@
+Test to see if the pid in the pidfile is actually running before claiming
+that we are.
+Fix the `netlink message truncated` error since 3.0.6.
+We now ensure that our renewal and rebind times are sane.
+Fix flushing interfaces for systems without getifaddrs and >1 interface.
+All netlink error messages are now prefixed with netlink.
 Add DHCP over FireWire 1394 (RFC 2855) and InfiniBand (RFC 4390) support.
 We should add support for DUIDs (RFC4361) as well.
 
--- a/Makefile	Mon Feb 12 17:08:44 2007 +0000
+++ b/Makefile	Tue Feb 20 22:57:10 2007 +0000
@@ -1,6 +1,6 @@
 # Should work for both GNU make and BSD make
 
-VERSION = 3.0.12_pre1
+VERSION = 3.0.12_pre2
 
 CFLAGS ?= -O2 -pipe
 
--- a/client.c	Mon Feb 12 17:08:44 2007 +0000
+++ b/client.c	Tue Feb 20 22:57:10 2007 +0000
@@ -174,7 +174,8 @@
       if (timeout > 0 || (options->timeout == 0 &&
 			  (state != STATE_INIT || xid)))
 	{
-	  if (options->timeout == 0 || dhcp->leasetime == (unsigned) -1)
+	  if (options->timeout == 0 ||
+	      (dhcp->leasetime == (unsigned) -1 && state == STATE_BOUND))
 	    {
 	      int retry = 0;
 	      logger (LOG_DEBUG, "waiting on select for infinity");
@@ -471,8 +472,15 @@
 	    case STATE_INIT:
 	      if (type == DHCP_OFFER)
 		{
-		  logger (LOG_INFO, "offered lease of %s",
-			  inet_ntoa (dhcp->address));
+		  char *addr = strdup (inet_ntoa (dhcp->address));
+		  if (dhcp->servername)
+		    logger (LOG_INFO, "offered %s from %s `%s'",
+			    addr, inet_ntoa (dhcp->serveraddress),
+			    dhcp->servername);
+		  else
+		    logger (LOG_INFO, "offered %s from %s",
+			    addr, inet_ntoa (dhcp->serveraddress));
+		  free (addr);
 
 		  SEND_MESSAGE (DHCP_REQUEST);
 		  state = STATE_REQUESTING;
@@ -512,40 +520,69 @@
 			}
 		    }
 
-		  if (! dhcp->leasetime)
+		  if (dhcp->leasetime == (unsigned) -1)
 		    {
-		      dhcp->leasetime = DEFAULT_TIMEOUT;
-		      logger(LOG_INFO,
-			     "no lease time supplied, assuming %d seconds",
-			     dhcp->leasetime);
+		      dhcp->renewaltime = dhcp->rebindtime = dhcp->leasetime;
+		      timeout = 1; /* So we select on infinity */
+		      logger (LOG_INFO, "leased %s for infinity",
+			      inet_ntoa (dhcp->address));
 		    }
-
-		  if (! dhcp->renewaltime) 
+		  else
 		    {
-		      dhcp->renewaltime = dhcp->leasetime / 2;
-		      logger (LOG_INFO,
-			      "no renewal time supplied, assuming %d seconds",
-			      dhcp->renewaltime);
+		      if (! dhcp->leasetime)
+			{
+			  dhcp->leasetime = DEFAULT_TIMEOUT;
+			  logger(LOG_INFO,
+				 "no lease time supplied, assuming %d seconds",
+				 dhcp->leasetime);
+			}
+		      else
+			logger (LOG_INFO, "leased %s for %u seconds",
+				inet_ntoa (dhcp->address), dhcp->leasetime);
+
+		      if (dhcp->rebindtime >= dhcp->leasetime)
+			{
+			  dhcp->rebindtime = (dhcp->leasetime * 0.875);
+			  logger (LOG_ERR, "rebind time greater than lease "
+				  "time, forcing to %u seconds",
+				  dhcp->rebindtime);
+			}
+
+		      if (dhcp->renewaltime > dhcp->rebindtime)
+			{
+			
+			  dhcp->renewaltime = (dhcp->leasetime * 0.5);
+			  logger (LOG_ERR, "renewal time greater than rebind time, "
+				  "forcing to %u seconds",
+				  dhcp->renewaltime);
+			}
+
+		      if (! dhcp->renewaltime) 
+			{
+			  dhcp->renewaltime = (dhcp->leasetime * 0.5);
+			  logger (LOG_INFO,
+				  "no renewal time supplied, assuming %d seconds",
+				  dhcp->renewaltime);
+			}
+		      else
+			logger (LOG_DEBUG, "renew in %u seconds",
+				dhcp->renewaltime);
+
+		      if (! dhcp->rebindtime)
+			{
+			  dhcp->rebindtime = (dhcp->leasetime * 0.875);
+			  logger (LOG_INFO,
+				  "no rebind time supplied, assuming %d seconds",
+				  dhcp->rebindtime);
+			}
+		      else
+			logger (LOG_DEBUG, "rebind in %u seconds",
+				dhcp->rebindtime);
+
+		      timeout = dhcp->renewaltime;
 		    }
 
-		  if (! dhcp->rebindtime)
-		    {
-		      dhcp->rebindtime = (dhcp->leasetime * 0x7) >> 3;
-		      logger (LOG_INFO,
-			      "no rebind time supplied, assuming %d seconds",
-			      dhcp->rebindtime);
-		    }
-
-		  if (dhcp->leasetime == (unsigned) -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;
-		  timeout = dhcp->renewaltime;
 		  xid = 0;
 
 		  if (configure (options, iface, dhcp) < 0 && ! daemonised)
--- a/configure.c	Mon Feb 12 17:08:44 2007 +0000
+++ b/configure.c	Tue Feb 20 22:57:10 2007 +0000
@@ -468,8 +468,10 @@
       /* Only reset things if we had set them before */
       if (iface->previous_address.s_addr != 0)
 	{
-	  del_address (iface->name, iface->previous_address);
+	  del_address (iface->name, iface->previous_address,
+		       iface->previous_netmask);
 	  memset (&iface->previous_address, 0, sizeof (struct in_addr));
+	  memset (&iface->previous_netmask, 0, sizeof (struct in_addr));
 
 	  restore_resolv (iface->name);
 
@@ -486,7 +488,7 @@
   /* Now delete the old address if different */
   if (iface->previous_address.s_addr != dhcp->address.s_addr
       && iface->previous_address.s_addr != 0)
-    del_address (iface->name, iface->previous_address);
+    del_address (iface->name, iface->previous_address, iface->previous_netmask);
 
 #ifdef __linux__
   /* On linux, we need to change the subnet route to have our metric. */
@@ -602,10 +604,13 @@
 
   write_info (iface, dhcp, options);
 
-  if (iface->previous_address.s_addr != dhcp->address.s_addr)
+  if (iface->previous_address.s_addr != dhcp->address.s_addr ||
+      iface->previous_netmask.s_addr != dhcp->netmask.s_addr)
     {
       memcpy (&iface->previous_address,
 	      &dhcp->address, sizeof (struct in_addr));
+      memcpy (&iface->previous_netmask,
+	      &dhcp->netmask, sizeof (struct in_addr));
       exec_script (options->script, iface->infofile, "new");
     }
   else
--- a/dhcp.c	Mon Feb 12 17:08:44 2007 +0000
+++ b/dhcp.c	Tue Feb 20 22:57:10 2007 +0000
@@ -296,9 +296,9 @@
    seperated string. Returns length of string (including 
    terminating zero) or zero on error. out may be NULL
    to just determine output length. */
-static unsigned int decode_search (u_char *p, int len, char *out)
+static unsigned int decode_search (const unsigned char *p, int len, char *out)
 {
-  u_char *r, *q = p;
+  const unsigned char *r, *q = p;
   unsigned int count = 0, l, hops;
 
   while (q - p < len)
@@ -358,9 +358,9 @@
 
 /* Add our classless static routes to the routes variable
  * and return the last route set */
-static route_t *decodeCSR(unsigned char *p, int len)
+static route_t *decodeCSR(const unsigned char *p, int len)
 {
-  unsigned char *q = p;
+  const unsigned char *q = p;
   int cidr;
   int ocets;
   route_t *first;
@@ -455,7 +455,7 @@
     }
 }
 
-static void dhcp_add_address(address_t *address, unsigned char *data, int length)
+static void dhcp_add_address(address_t *address, const unsigned char *data, int length)
 {
   int i;
   address_t *p = address;
@@ -474,8 +474,8 @@
 
 int parse_dhcpmessage (dhcp_t *dhcp, const dhcpmessage_t *message)
 {
-  unsigned char *p = message->options;
-  unsigned char *end = message->options; /* Add size later for gcc-3 issue */
+  const unsigned char *p = message->options;
+  const unsigned char *end = p; /* Add size later for gcc-3 issue */
   unsigned char option;
   unsigned char length;
   unsigned int len = 0;
--- a/dhcpcd.c	Mon Feb 12 17:08:44 2007 +0000
+++ b/dhcpcd.c	Tue Feb 20 22:57:10 2007 +0000
@@ -100,7 +100,6 @@
 	  "              [-u userclass] [-F [none | ptr | both]] [-I clientID]\n");
 }
 
-
 int main(int argc, char **argv)
 {
   options_t options;
@@ -110,6 +109,7 @@
   int ch;
   int option_index = 0;
   char prefix[IF_NAMESIZE + 3];
+  pid_t pid;
 
   const struct option longopts[] =
     {
@@ -344,7 +344,7 @@
   if (options.signal != 0)
     {
       int killed = -1;
-      pid_t pid = read_pid (options.pidfile);
+      pid = read_pid (options.pidfile);
       if (pid != 0)
         logger (LOG_INFO, "sending signal %d to pid %d", options.signal, pid);
 
@@ -377,7 +377,7 @@
       exit (EXIT_FAILURE);
     }
 
-  if (read_pid (options.pidfile))
+  if ((pid = read_pid (options.pidfile)) > 0 && kill (pid, 0) == 0)
     {
       logger (LOG_ERR, ""PACKAGE" already running (%s)", options.pidfile);
       exit (EXIT_FAILURE);
--- a/interface.c	Mon Feb 12 17:08:44 2007 +0000
+++ b/interface.c	Tue Feb 20 22:57:10 2007 +0000
@@ -181,6 +181,7 @@
 #ifdef __linux__
   /* Do something with the metric parameter to satisfy the compiler warning */
   metric = 0;
+  strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
   if (ioctl (s, SIOCGIFHWADDR, &ifr) <0)
     {
       logger (LOG_ERR, "ioctl SIOCGIFHWADDR: %s", strerror (errno));
@@ -207,6 +208,7 @@
   family = ifr.ifr_hwaddr.sa_family;
 #else
   ifr.ifr_metric = metric;
+  strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
   if (ioctl (s, SIOCSIFMETRIC, &ifr) < 0)
     {
       logger (LOG_ERR, "ioctl SIOCSIFMETRIC: %s", strerror (errno));
@@ -215,6 +217,7 @@
     }
 #endif
 
+  strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
   if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0)
     {
       logger (LOG_ERR, "ioctl SIOCGIFFLAGS: %s", strerror (errno));
@@ -223,6 +226,7 @@
     }
 
   ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
+  strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
   if (ioctl(s, SIOCSIFFLAGS, &ifr) < 0)
     {
       logger (LOG_ERR, "ioctl SIOCSIFFLAGS: %s", strerror (errno));
@@ -281,9 +285,9 @@
     }
 
   ADDADDR (ifa.ifra_addr, address);
+  ADDADDR (ifa.ifra_mask, netmask);
   if (! del)
     {
-      ADDADDR (ifa.ifra_mask, netmask);
       ADDADDR (ifa.ifra_broadaddr, broadcast);
     }
 
@@ -448,7 +452,8 @@
   struct iovec iov;
   struct msghdr msg;
   static unsigned int seq;
-  char buffer[16384];
+  char buffer[256];
+  int bytes;
   union
     {
       char *buffer;
@@ -496,25 +501,25 @@
 
   while (1) 
     {
-      int bytes = recvmsg(s, &msg, 0);
       iov.iov_len = sizeof (buffer);
+      bytes = recvmsg(s, &msg, 0);
 
       if (bytes < 0)
 	{
 	  if (errno != EINTR)
-	    logger (LOG_ERR, "overrun");
+	    logger (LOG_ERR, "netlink: overrun");
 	  continue;
 	}
 
       if (bytes == 0)
 	{
-	  logger (LOG_ERR, "EOF on netlink");
+	  logger (LOG_ERR, "netlink: EOF");
 	  goto eexit;
 	}
 
       if (msg.msg_namelen != sizeof (nl))
 	{
-	  logger (LOG_ERR, "sender address length == %d", msg.msg_namelen);
+	  logger (LOG_ERR, "netlink: sender address length mismatch");
 	  goto eexit;
 	}
 
@@ -526,9 +531,9 @@
 	  if (l < 0 || len > bytes)
 	    {
 	      if (msg.msg_flags & MSG_TRUNC)
-		logger (LOG_ERR, "truncated message");
+		logger (LOG_ERR, "netlink: truncated message");
 	      else
-		logger (LOG_ERR, "malformed message");
+		logger (LOG_ERR, "netlink: malformed message");
 	      goto eexit;
 	    }
 
@@ -543,7 +548,7 @@
 	    {
 	      struct nlmsgerr *err = (struct nlmsgerr *) NLMSG_DATA (h.nlm);
 	      if ((unsigned) l < sizeof (struct nlmsgerr))
-		logger (LOG_ERR, "truncated error message");
+		logger (LOG_ERR, "netlink: truncated error message");
 	      else
 		{
 		  errno = -err->error;
@@ -555,12 +560,12 @@
 
 		  /* Don't report on something already existing */
 		  if (errno != EEXIST)
-		    logger (LOG_ERR, "RTNETLINK answers: %s", strerror (errno));
+		    logger (LOG_ERR, "netlink: %s", strerror (errno));
 		}
 	      goto eexit;
 	    }
 
-	  logger (LOG_ERR, "unexpected reply");
+	  logger (LOG_ERR, "netlink: unexpected reply");
 next:
 	  bytes -= NLMSG_ALIGN (len);
 	  h.buffer += NLMSG_ALIGN (len);
@@ -568,13 +573,13 @@
 
       if (msg.msg_flags & MSG_TRUNC)
 	{
-	  logger (LOG_ERR, "message truncated");
+	  logger (LOG_ERR, "netlink: truncated message");
 	  continue;
 	}
 
       if (bytes)
 	{
-	  logger (LOG_ERR, "remnant of size %d", bytes);
+	  logger (LOG_ERR, "netlink: remnant of size %d", bytes);
 	  goto eexit;
 	}
     }
@@ -637,7 +642,7 @@
     {
       struct nlmsghdr hdr;
       struct ifaddrmsg ifa;
-      char buffer[256];
+      char buffer[64];
     }
   nlm;
   uint32_t mask = htonl (netmask.s_addr);
@@ -649,6 +654,8 @@
 
   nlm.hdr.nlmsg_len = NLMSG_LENGTH (sizeof (struct ifaddrmsg));
   nlm.hdr.nlmsg_flags = NLM_F_REQUEST;
+  if (! del)
+    nlm.hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE;
   nlm.hdr.nlmsg_type = del ? RTM_DELADDR : RTM_NEWADDR;
   nlm.ifa.ifa_index = if_nametoindex (ifname);
   nlm.ifa.ifa_family = AF_INET;
@@ -772,14 +779,18 @@
   return (do_address (ifname, address, netmask, broadcast, 0));
 }
 
-int del_address (const char *ifname, struct in_addr address)
+int del_address (const char *ifname,
+		 struct in_addr address, struct in_addr netmask)
 {
   struct in_addr t;
+  char *addr = strdup (inet_ntoa (address));
 
-  logger (LOG_INFO, "deleting IP address %s", inet_ntoa (address));
+  logger (LOG_INFO, "deleting IP address %s netmask %s", addr,
+	  inet_ntoa (netmask));
+  free (addr);
 
   memset (&t, 0, sizeof (t));
-  return (do_address (ifname, address, t, t, 1));
+  return (do_address (ifname, address, netmask, t, 1));
 }
 
 int add_route (const char *ifname, struct in_addr destination,
@@ -818,15 +829,16 @@
 	{
 	  struct sockaddr *sa;
 	  struct sockaddr_in *sin;
-	} us;
+	} us_a, us_m;
 
       if (strcmp (p->ifa_name, ifname) != 0)
 	continue;
 
-      us.sa = p->ifa_addr;
+      us_a.sa = p->ifa_addr;
+      us_m.sa = p->ifa_netmask;
 
-      if (us.sin->sin_family == AF_INET)
-	if (del_address (ifname, us.sin->sin_addr) < 0)
+      if (us_a.sin->sin_family == AF_INET)
+	if (del_address (ifname, us_a.sin->sin_addr, us_m.sin->sin_addr) < 0)
 	  retval = -1;
     }
   freeifaddrs (ifap);
@@ -874,14 +886,13 @@
   ifr = ifrs;
   for (i = 0; i < nifs; i++)
     {
-      struct sockaddr_in *in = (struct sockaddr_in *) &ifr->ifr_addr;
+      struct sockaddr_in *addr = (struct sockaddr_in *) &ifr->ifr_addr;
+      struct sockaddr_in *netm = (struct sockaddr_in *) &ifr->ifr_netmask;
 
-      if (ifr->ifr_addr.sa_family != AF_INET
-	  || strcmp (ifname, ifr->ifr_name) != 0)
-	continue;
-
-      if (del_address (ifname, in->sin_addr) < 0)
-	retval = -1;
+      if (ifr->ifr_addr.sa_family == AF_INET
+	  && strcmp (ifname, ifr->ifr_name) == 0)
+	if (del_address (ifname, addr->sin_addr, netm->sin_addr) < 0)
+	  retval = -1;
       ifr++;
     }
 
--- a/interface.h	Mon Feb 12 17:08:44 2007 +0000
+++ b/interface.h	Tue Feb 20 22:57:10 2007 +0000
@@ -71,6 +71,7 @@
   char infofile[PATH_MAX];
 
   struct in_addr previous_address;
+  struct in_addr previous_netmask;
   route_t *previous_routes;
 
   long start_uptime;
@@ -82,7 +83,8 @@
 
 int add_address (const char *ifname, struct in_addr address,
 		 struct in_addr netmask, struct in_addr broadcast);
-int del_address (const char *ifname, struct in_addr address);
+int del_address (const char *ifname, struct in_addr address,
+		 struct in_addr netmask);
 int flush_addresses (const char *ifname);
 
 int add_route (const char *ifname, struct in_addr destination,