changeset 78:3e35e39a5fa3 draft

You can now build dhcpcd without support for writing ntp, nis and info files which makes the binary a few k smaller. Support OpenNTP as well as NTP. Re-work the state engine a little, so we renew and rebind correctly. Subsequent debug options stop dhcpcd from daemonising.
author Roy Marples <roy@marples.name>
date Tue, 03 Apr 2007 07:03:04 +0000
parents 0d143e90c3cb
children ee2c527a6b84
files ChangeLog Makefile client.c configure.c configure.h dhcp.c dhcpcd.8 dhcpcd.c dhcpcd.h pathnames.h signals.c
diffstat 11 files changed, 193 insertions(+), 95 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Fri Mar 23 10:32:11 2007 +0000
+++ b/ChangeLog	Tue Apr 03 07:03:04 2007 +0000
@@ -1,3 +1,8 @@
+You can now build dhcpcd without support for writing ntp, nis and info files
+which makes the binary a few k smaller.
+Support OpenNTP as well as NTP.
+Re-work the state engine a little, so we renew and rebind correctly.
+Subsequent debug options stop dhcpcd from daemonising.
 When we get an invalid length for a DHCP option, try and continue anyway.
 When MTU is less than 576 we now ignore it instead of setting the MTU to 576.
 Build correctly on dietlibc, thanks to d00mer.
--- a/Makefile	Fri Mar 23 10:32:11 2007 +0000
+++ b/Makefile	Tue Apr 03 07:03:04 2007 +0000
@@ -1,6 +1,6 @@
 # Should work for both GNU make and BSD make
 
-VERSION = 3.0.16
+VERSION = 3.0.17_pre2
 
 CFLAGS ?= -O2 -pipe
 
@@ -8,7 +8,7 @@
 # IMPORTANT: We should be using c99 instead of gnu99 but for some reason
 # generic linux headers as of 2.6.19 don't allow this in asm/types.h
 CFLAGS += -pedantic -std=gnu99 \
-    -Wall -Wunused -Wimplicit -Wshadow -Wformat=2 \
+    -Wall -Wextra -Wunused -Wimplicit -Wshadow -Wformat=2 \
     -Wmissing-declarations -Wno-missing-prototypes -Wwrite-strings \
     -Wbad-function-cast -Wnested-externs -Wcomment -Winline \
     -Wchar-subscripts -Wcast-align -Wno-format-nonliteral
--- a/client.c	Fri Mar 23 10:32:11 2007 +0000
+++ b/client.c	Tue Apr 03 07:03:04 2007 +0000
@@ -21,7 +21,6 @@
 
 #include <sys/types.h>
 #include <sys/select.h>
-#include <sys/wait.h>
 #include <arpa/inet.h>
 #ifdef __linux__
 #include <netinet/ether.h>
@@ -86,6 +85,15 @@
   send_message (iface, dhcp, xid, _type, options); \
 }
 
+#define DROP_CONFIG \
+{ \
+  memset (&dhcp->address, 0, sizeof (struct in_addr)); \
+  if (iface->previous_address.s_addr != 0 && ! options->persistent) \
+    configure (options, iface, dhcp); \
+  free_dhcp (dhcp); \
+  memset (dhcp, 0, sizeof (dhcp_t)); \
+}
+
 static int daemonise (const char *pidfile)
 {
   logger (LOG_DEBUG, "forking to background");
@@ -240,10 +248,6 @@
 	{
 	  switch (sig)
 	    {
-	    case SIGCHLD:
-	      /* Silently ignore this signal and wait for it
-		 This stops zombies */
-	      wait (0);
 	      break;
 	    case SIGINT:
 	      logger (LOG_INFO, "received SIGINT, stopping");
@@ -311,17 +315,7 @@
 		  xid = 0;
 		  SOCKET_MODE (SOCKET_CLOSED);
 		  if (! options->persistent)
-		    {
-		      free_dhcp (dhcp);
-		      memset (dhcp, 0, sizeof (dhcp_t));
-		      configure (options, iface, dhcp);
-		    }
-		  if (! daemonised)
-		    {
-		      retval = -1;
-		      goto eexit;
-		    }
-		  break;
+		    DROP_CONFIG;
 		}
 
 	      if (xid == 0)
@@ -368,22 +362,25 @@
 	      break;
 	    case STATE_REBINDING:
 	      logger (LOG_ERR, "lost lease, attemping to rebind");
+	      memset (&dhcp->address, 0, sizeof (struct in_addr));
 	      SOCKET_MODE (SOCKET_OPEN);
-	      SEND_MESSAGE (DHCP_DISCOVER);
+	      SEND_MESSAGE (DHCP_REQUEST);
 	      timeout = dhcp->leasetime - dhcp->rebindtime;
-	      state = STATE_INIT;
+	      state = STATE_REQUESTING;
 	      break;
 	    case STATE_REQUESTING:
-	      logger (LOG_ERR, "timed out");
-	      if (! daemonised)
+	      if (iface->previous_address.s_addr != 0)
+		logger (LOG_ERR, "lost lease");
+	      else
+		logger (LOG_ERR, "timed out");
+	      if (! daemonised && options->daemonise)
 		goto eexit;
 
 	      state = STATE_INIT;
 	      SOCKET_MODE (SOCKET_CLOSED);
 	      timeout = 0;
 	      xid = 0;
-	      free_dhcp (dhcp);
-	      memset (dhcp, 0, sizeof (dhcp_t));
+	      DROP_CONFIG;
 	      break;
 
 	    case STATE_RELEASED:
@@ -420,12 +417,12 @@
 	      if (xid != message.xid)
 		{
 		  logger (LOG_ERR,
-			  "ignoring packet with xid %d as it's not ours (%d)",
+			  "ignoring packet with xid 0x%x as it's not ours (0x%x)",
 			  message.xid, xid);
 		  continue;
 		}
 
-	      logger (LOG_DEBUG, "got a packet with xid %d", message.xid);
+	      logger (LOG_DEBUG, "got a packet with xid 0x%x", message.xid);
 	      memset (new_dhcp, 0, sizeof (dhcp_t));
 	      if ((type = parse_dhcpmessage (new_dhcp, &message)) < 0)
 		{
@@ -461,9 +458,7 @@
 	      state = STATE_INIT;
 	      timeout = 0;
 	      xid = 0;
-	      free_dhcp (dhcp);
-	      memset (dhcp, 0, sizeof (dhcp_t));
-	      configure (options, iface, dhcp);
+	      DROP_CONFIG;
 	      continue;
 	    }
 
@@ -502,12 +497,7 @@
 			  SOCKET_MODE (SOCKET_OPEN);
 			  SEND_MESSAGE (DHCP_DECLINE);
 			  SOCKET_MODE (SOCKET_CLOSED);
-
-			  free_dhcp (dhcp);
-			  memset (dhcp, 0, sizeof (dhcp_t));
- 
-			  if (daemonised)
-			    configure (options, iface, dhcp);
+			  DROP_CONFIG;
 
 			  xid = 0;
 			  timeout = 0;
@@ -592,7 +582,7 @@
 		      goto eexit;
 		    }
 
-		  if (! daemonised)
+		  if (! daemonised && options->daemonise)
 		    {
 		      if ((daemonise (options->pidfile)) < 0 )
 			{
@@ -627,12 +617,7 @@
 
 eexit:
   SOCKET_MODE (SOCKET_CLOSED);
-
-  /* Remove our config if we need to */
-  free_dhcp (dhcp);
-  memset (dhcp, 0, sizeof (dhcp_t));
-  if (iface->previous_address.s_addr != 0 && ! options->persistent && daemonised)
-    configure (options, iface, dhcp);
+  DROP_CONFIG;
   free (dhcp);
 
   if (iface)
--- a/configure.c	Fri Mar 23 10:32:11 2007 +0000
+++ b/configure.c	Tue Apr 03 07:03:04 2007 +0000
@@ -47,34 +47,6 @@
 #include "logger.h"
 #include "socket.h"
 
-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;
-}
 
 /* IMPORTANT: Ensure that the last parameter is NULL when calling */
 static int exec_cmd (const char *cmd, const char *args, ...)
@@ -105,7 +77,7 @@
 
   if ((pid = fork ()) == 0)
     {
-      if (execve (cmd, argv, NULL) && errno != ENOENT)
+      if (execv (cmd, argv) && errno != ENOENT)
 	logger (LOG_ERR, "error executing \"%s\": %s",
 		cmd, strerror (errno));
       exit (0);
@@ -121,8 +93,13 @@
 {
   struct stat buf;
 
+#ifdef ENABLE_INFO
   if (! script || ! infofile || ! arg)
     return;
+#else
+  if (! script || ! arg)
+    return ;
+#endif
 
   if (stat (script, &buf) < 0)
     {
@@ -131,8 +108,13 @@
       return;
     }
 
+#ifdef ENABLE_INFO
   logger (LOG_DEBUG, "exec \"%s %s %s\"", script, infofile, arg);
   exec_cmd (script, infofile, arg, NULL);
+#else
+  logger (LOG_DEBUG, "exec \"%s \"\" %s\"", script, infofile, arg);
+  exec_cmd (script, infofile, "", arg, NULL);
+#endif
 }
 
 static int make_resolv (const char *ifname, const dhcp_t *dhcp)
@@ -142,6 +124,7 @@
   char resolvconf[PATH_MAX] = {0};
   address_t *address;
 
+#ifdef RESOLVCONF
   if (stat (RESOLVCONF, &buf) == 0)
     {
       logger (LOG_DEBUG, "sending DNS information to resolvconf");
@@ -152,6 +135,7 @@
 	logger (LOG_ERR, "popen: %s", strerror (errno));
     }
   else
+#endif
     {
       logger (LOG_DEBUG, "writing "RESOLVFILE);
       if (! (f = fopen(RESOLVFILE, "w")))
@@ -185,6 +169,7 @@
 
 static void restore_resolv(const char *ifname)
 {
+#ifdef RESOLVCONF
   struct stat buf;
 
   if (stat (RESOLVCONF, &buf) < 0)
@@ -192,9 +177,11 @@
 
   logger (LOG_DEBUG, "removing information from resolvconf");
   exec_cmd (RESOLVCONF, "-d", ifname, NULL);
+#endif
 }
 
-static int make_ntp (const char *ifname, const dhcp_t *dhcp)
+#ifdef ENABLE_NTP
+static int _make_ntp (const char *file, const char *ifname, const dhcp_t *dhcp)
 {
   FILE *f;
   address_t *address;
@@ -202,17 +189,18 @@
   char buffer[1024];
   int tomatch = 0;
   char *token;
+  bool ntp = false;
 
   for (address = dhcp->ntpservers; address; address = address->next)
     tomatch++;
 
   /* Check that we really need to update the servers
      We do this because ntp has to be restarted to work with a changed config */
-  if (! (f = fopen(NTPFILE, "r")))
+  if (! (f = fopen (file, "r")))
     {
       if (errno != ENOENT)
 	{
-	  logger (LOG_ERR, "fopen `%s': %s", NTPFILE, strerror (errno));
+	  logger (LOG_ERR, "fopen `%s': %s", file, strerror (errno));
 	  return -1;
 	}
     }
@@ -244,36 +232,85 @@
       /* File has the same name servers that we do, so no need to restart ntp */
       if (tomatch == 0)
 	{
-	  logger (LOG_DEBUG, "ntp already configured, skipping");
+	  logger (LOG_DEBUG, "%s already configured, skipping", file);
 	  return 0;
 	}
     }
 
-  logger (LOG_DEBUG, "writing "NTPFILE);
-  if (! (f = fopen(NTPFILE, "w")))
+  logger (LOG_DEBUG, "writing %s", file);
+  if (! (f = fopen (file, "w")))
     {
-      logger (LOG_ERR, "fopen `%s': %s", NTPFILE, strerror (errno));
+      logger (LOG_ERR, "fopen `%s': %s", file, strerror (errno));
       return -1;
     }
 
   fprintf (f, "# Generated by dhcpcd for interface %s\n", ifname);
-  fprintf (f, "restrict default noquery notrust nomodify\n");
-  fprintf (f, "restrict 127.0.0.1\n");
+#ifdef NTPFILE
+  if (strcmp (file, NTPFILE) == 0)
+    {
+      ntp = true;
+      fprintf (f, "restrict default noquery notrust nomodify\n");
+      fprintf (f, "restrict 127.0.0.1\n");
+    }
+#endif
 
   for (address = dhcp->ntpservers; address; address = address->next)
     {
       a = inet_ntoa (address->address);
-      fprintf (f, "restrict %s nomodify notrap noquery\nserver %s\n", a, a);
+      if (ntp)
+	fprintf (f, "restrict %s nomodify notrap noquery\n", a);
+      fprintf (f, "server %s\n", a);
     }
 
-  fprintf (f, "driftfile " NTPDRIFTFILE "\n");
-  fprintf (f, "logfile " NTPLOGFILE "\n");
+  if (ntp)
+    {
+      fprintf (f, "driftfile " NTPDRIFTFILE "\n");
+      fprintf (f, "logfile " NTPLOGFILE "\n");
+    }
   fclose (f);
 
-  exec_cmd (NTPSERVICE, NTPRESTARTARGS, NULL);
-  return 0;
+  return 1;
 }
 
+static int make_ntp (const char *ifname, const dhcp_t *dhcp)
+{
+  /* On some systems we have only have one ntp service, but we don't know
+     which configuration file we're using. So we need to write to both and
+     restart accordingly. */
+
+  bool restart_ntp = false;
+  bool restart_openntp = false;
+  int retval = 0;
+
+#ifdef NTPFILE
+  if (_make_ntp (NTPFILE, ifname, dhcp) > 0)
+    restart_ntp = true;
+#endif
+
+#ifdef OPENNTPFILE
+  if (_make_ntp (OPENNTPFILE, ifname, dhcp) > 0)
+    restart_openntp = true;
+#endif
+
+#ifdef NTPSERVICE
+  if (restart_ntp)
+    retval += exec_cmd (NTPSERVICE, NTPRESTARTARGS, NULL);
+#endif
+
+#if defined (NTPSERVICE) && defined (OPENNTPSERVICE)
+  if (restart_openntp &&
+      (strcmp (NTPSERVICE, OPENNTPSERVICE) != 0 || ! restart_ntp))
+    retval += exec_cmd (OPENNTPSERVICE, OPENNTPRESTARTARGS, NULL);
+#elif defined (OPENNTPSERVICE) && ! defined (NTPSERVICE)
+  if (restart_openntp) 
+    retval += exec_cmd (OPENNTPSERVICE, OPENNTPRESTARTARGS, NULL);
+#endif
+
+  return retval;
+}
+#endif
+
+#ifdef ENABLE_NIS
 static int make_nis (const char *ifname, const dhcp_t *dhcp)
 {
   FILE *f;
@@ -308,6 +345,37 @@
   exec_cmd (NISSERVICE, NISRESTARTARGS, NULL);
   return 0;
 }
+#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)
@@ -417,6 +485,7 @@
   fclose (f);
   return 0;
 }
+#endif
 
 int configure (const options_t *options, interface_t *iface,
 	       const dhcp_t *dhcp)
@@ -567,11 +636,15 @@
   else
     logger (LOG_DEBUG, "no dns information to write");
 
+#ifdef ENABLE_NTP
   if (options->dontp && dhcp->ntpservers)
     make_ntp(iface->name, dhcp);
+#endif
 
+#ifdef ENABLE_NIS
   if (options->donis && (dhcp->nisservers || dhcp->nisdomain))
     make_nis(iface->name, dhcp);
+#endif
 
   /* Now we have made a resolv.conf we can obtain a hostname if we need one */
   if (options->dohostname && ! dhcp->hostname)
@@ -606,7 +679,9 @@
 	}
     }
 
+#ifdef ENABLE_INFO
   write_info (iface, dhcp, options);
+#endif
 
   if (iface->previous_address.s_addr != dhcp->address.s_addr ||
       iface->previous_netmask.s_addr != dhcp->netmask.s_addr)
--- a/configure.h	Fri Mar 23 10:32:11 2007 +0000
+++ b/configure.h	Tue Apr 03 07:03:04 2007 +0000
@@ -22,6 +22,13 @@
 #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
+
 #include "dhcpcd.h"
 #include "interface.h"
 #include "dhcp.h"
--- a/dhcp.c	Fri Mar 23 10:32:11 2007 +0000
+++ b/dhcp.c	Tue Apr 03 07:03:04 2007 +0000
@@ -80,10 +80,9 @@
 
   memset (&message, 0, sizeof (dhcpmessage_t));
 
-  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)))
+  if (type == DHCP_INFORM ||
+      type == DHCP_RELEASE ||
+      type == DHCP_REQUEST)
     {
       message.ciaddr = iface->previous_address.s_addr;
       from.s_addr = iface->previous_address.s_addr;
@@ -272,7 +271,7 @@
   make_dhcp_packet (&packet, (unsigned char *) &message, message_length,
 		    from, to);
 
-  logger (LOG_DEBUG, "sending %s with xid %d", dhcp_message[(int) type], xid);
+  logger (LOG_DEBUG, "sending %s with xid 0x%x", dhcp_message[(int) type], xid);
   return send_packet (iface, ETHERTYPE_IP, (unsigned char *) &packet,
 		      message_length + sizeof (struct ip) +
 		      sizeof (struct udphdr));
--- a/dhcpcd.8	Fri Mar 23 10:32:11 2007 +0000
+++ b/dhcpcd.8	Tue Apr 03 07:03:04 2007 +0000
@@ -61,6 +61,7 @@
 .TP
 .BI \-d
 Echos debugging and information messages to the console.
+Subsequent debug options stop \fBdhcpcd\fR from daemonising.
 .TP
 .BI \-h \ hostname
 specifies a string used for the hostname option field when
--- a/dhcpcd.c	Fri Mar 23 10:32:11 2007 +0000
+++ b/dhcpcd.c	Tue Apr 03 07:03:04 2007 +0000
@@ -110,6 +110,7 @@
   int option_index = 0;
   char prefix[IF_NAMESIZE + 3];
   pid_t pid;
+  int debug = 0;
 
   const struct option longopts[] =
     {
@@ -158,6 +159,7 @@
   options.donis = true;
   options.dontp = true;
   options.dogateway = true;
+  options.daemonise = true;
   gethostname (options.hostname, sizeof (options.hostname));
   if (strcmp (options.hostname, "(none)") == 0 ||
       strcmp (options.hostname, "localhost") == 0)
@@ -183,12 +185,21 @@
 	options.script = optarg;
 	break;
       case 'd':
-	setloglevel(LOG_DEBUG);
+	debug++;
+	switch (debug)
+	  {
+	    case 1:
+		setloglevel(LOG_DEBUG);
+		break;
+	    case 2:
+		options.daemonise = false;
+		break;
+	  }
 	break;
       case 'h':
 	if (strlen (optarg) > HOSTNAME_MAX_LEN)
 	  {
-	    logger(LOG_ERR, "`%s' too long for HostName string, max is %d",
+	    logger (LOG_ERR, "`%s' too long for HostName string, max is %d",
 		   optarg, HOSTNAME_MAX_LEN);
 	    exit (EXIT_FAILURE);
 	  }
@@ -196,14 +207,14 @@
 	  strcpy (options.hostname, optarg);
 	break;
       case 'i':
-	if (strlen(optarg) > CLASS_ID_MAX_LEN)
+	if (strlen (optarg) > CLASS_ID_MAX_LEN)
 	  {
 	    logger (LOG_ERR, "`%s' too long for ClassID string, max is %d",
 		    optarg, CLASS_ID_MAX_LEN);
 	    exit (EXIT_FAILURE);
 	  }
 	else
-	  sprintf(options.classid, "%s", optarg);
+	  sprintf (options.classid, "%s", optarg);
 	break;
       case 'k':
 	options.signal = SIGHUP;
@@ -217,7 +228,7 @@
 	  }
 	break;
       case 'm':
-	STRINGINT(optarg, options.metric);
+	STRINGINT (optarg, options.metric);
 	break;
       case 'n':
 	options.signal = SIGALRM;
--- a/dhcpcd.h	Fri Mar 23 10:32:11 2007 +0000
+++ b/dhcpcd.h	Tue Apr 03 07:03:04 2007 +0000
@@ -59,6 +59,7 @@
   bool dodomainname;
   int signal;
   bool persistent;
+  bool daemonise;
 
   char *script;
   char pidfile[PATH_MAX];
--- a/pathnames.h	Fri Mar 23 10:32:11 2007 +0000
+++ b/pathnames.h	Tue Apr 03 07:03:04 2007 +0000
@@ -39,6 +39,10 @@
 #define NTPSERVICE		ETCDIR "/init.d/ntpd"
 #define NTPRESTARTARGS		"--quiet", "conditionalrestart"
 
+#define OPENNTPFILE		ETCDIR "/ntpd.conf"
+#define OPENNTPSERVICE		ETCDIR "/init.d/ntpd"
+#define OPENNTPRESTARTARGS	"--quiet", "conditionalrestart"
+
 #define DEFAULT_SCRIPT		ETCDIR "/" PACKAGE ".sh"
 
 #define STATEDIR		"/var"
--- a/signals.c	Fri Mar 23 10:32:11 2007 +0000
+++ b/signals.c	Tue Apr 03 07:03:04 2007 +0000
@@ -21,6 +21,7 @@
 
 #include <sys/socket.h>
 #include <sys/select.h>
+#include <sys/wait.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <signal.h>
@@ -34,6 +35,15 @@
 
 static void signal_handler (int sig)
 {
+  /* Silently ignore this signal and wait for it. This stops zombies.
+     We do this here instead of client.c so that we don't spam the log file
+     with "waiting on select messages" */
+  if (sig == SIGCHLD)
+    {
+      wait (0);
+      return;
+    }
+  
   if (send (signal_pipe[1], &sig, sizeof (sig), MSG_DONTWAIT) < 0)
     logger (LOG_ERR, "Could not send signal: %s", strerror (errno));
 }