e20e41
From 87444dc6977b61096127dcdfe87dc6cf2c0167d6 Mon Sep 17 00:00:00 2001
e20e41
From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= <pemensik@redhat.com>
e20e41
Date: Sun, 16 Apr 2017 20:20:08 +0100
e20e41
Subject: [PATCH] Capture and log  STDOUT and STDERR output from dhcp-script.
e20e41
e20e41
(cherry picked from commit c77fb9d8f09d136fa71bde2469c4fd11cefa6f4a)
e20e41
e20e41
Compile-time check on buffer sizes for leasefile parsing code.
e20e41
e20e41
(cherry picked from commit bf4e62c19e619f7edf8d03d58d33a5752f190bfd)
e20e41
e20e41
Improve error handling with shcp-script "init" mode.
e20e41
e20e41
(cherry picked from commit 3a8b0f6fccf464b1ec6d24c0e00e540ab2b17705)
e20e41
e20e41
Tweak logging introduced in 3a8b0f6fccf464b1ec6d24c0e00e540ab2b17705
e20e41
e20e41
(cherry picked from commit efff74c1aea14757ce074db28e02671c7f7bb5f5)
e20e41
e20e41
Don't die() on failing to parse lease-script output.
e20e41
e20e41
(cherry picked from commit 05f76dab89d5b879519a4f45b0cccaa1fc3d162d)
e20e41
---
e20e41
 man/dnsmasq.8       |   4 +-
e20e41
 src/dhcp-common.c   |  16 +++---
e20e41
 src/dhcp-protocol.h |   4 ++
e20e41
 src/dnsmasq.c       |   8 +++
e20e41
 src/dnsmasq.h       |  54 +++++++++---------
e20e41
 src/helper.c        |  56 +++++++++++++++++-
e20e41
 src/lease.c         | 159 +++++++++++++++++++++++++++++++---------------------
e20e41
 src/log.c           |   4 +-
e20e41
 src/rfc3315.c       |   2 +-
e20e41
 9 files changed, 202 insertions(+), 105 deletions(-)
e20e41
e20e41
diff --git a/man/dnsmasq.8 b/man/dnsmasq.8
e20e41
index 0521534..97d0a4f 100644
e20e41
--- a/man/dnsmasq.8
e20e41
+++ b/man/dnsmasq.8
e20e41
@@ -1551,8 +1551,8 @@ database.
e20e41
 
e20e41
 
e20e41
 All file descriptors are
e20e41
-closed except stdin, stdout and stderr which are open to /dev/null
e20e41
-(except in debug mode).
e20e41
+closed except stdin, which is open to /dev/null, and stdout and stderr which capture output for logging by dnsmasq. 
e20e41
+(In debug mode, stdio, stdout and stderr file are left as those inherited from the invoker of dnsmasq).
e20e41
 
e20e41
 The script is not invoked concurrently: at most one instance
e20e41
 of the script is ever running (dnsmasq waits for an instance of script to exit
e20e41
diff --git a/src/dhcp-common.c b/src/dhcp-common.c
e20e41
index 08528e8..ecc752b 100644
e20e41
--- a/src/dhcp-common.c
e20e41
+++ b/src/dhcp-common.c
e20e41
@@ -20,11 +20,11 @@
e20e41
 
e20e41
 void dhcp_common_init(void)
e20e41
 {
e20e41
-    /* These each hold a DHCP option max size 255
e20e41
-       and get a terminating zero added */
e20e41
-  daemon->dhcp_buff = safe_malloc(256);
e20e41
-  daemon->dhcp_buff2 = safe_malloc(256); 
e20e41
-  daemon->dhcp_buff3 = safe_malloc(256);
e20e41
+  /* These each hold a DHCP option max size 255
e20e41
+     and get a terminating zero added */
e20e41
+  daemon->dhcp_buff = safe_malloc(DHCP_BUFF_SZ);
e20e41
+  daemon->dhcp_buff2 = safe_malloc(DHCP_BUFF_SZ); 
e20e41
+  daemon->dhcp_buff3 = safe_malloc(DHCP_BUFF_SZ);
e20e41
   
e20e41
   /* dhcp_packet is used by v4 and v6, outpacket only by v6 
e20e41
      sizeof(struct dhcp_packet) is as good an initial size as any,
e20e41
@@ -855,14 +855,14 @@ void log_context(int family, struct dhcp_context *context)
e20e41
       if (context->flags & CONTEXT_RA_STATELESS)
e20e41
 	{
e20e41
 	  if (context->flags & CONTEXT_TEMPLATE)
e20e41
-	    strncpy(daemon->dhcp_buff, context->template_interface, 256);
e20e41
+	    strncpy(daemon->dhcp_buff, context->template_interface, DHCP_BUFF_SZ);
e20e41
 	  else
e20e41
 	    strcpy(daemon->dhcp_buff, daemon->addrbuff);
e20e41
 	}
e20e41
       else 
e20e41
 #endif
e20e41
-	inet_ntop(family, start, daemon->dhcp_buff, 256);
e20e41
-      inet_ntop(family, end, daemon->dhcp_buff3, 256);
e20e41
+	inet_ntop(family, start, daemon->dhcp_buff, DHCP_BUFF_SZ);
e20e41
+      inet_ntop(family, end, daemon->dhcp_buff3, DHCP_BUFF_SZ);
e20e41
       my_syslog(MS_DHCP | LOG_INFO, 
e20e41
 		(context->flags & CONTEXT_RA_STATELESS) ? 
e20e41
 		_("%s stateless on %s%.0s%.0s%s") :
e20e41
diff --git a/src/dhcp-protocol.h b/src/dhcp-protocol.h
e20e41
index a31d829..0ea449b 100644
e20e41
--- a/src/dhcp-protocol.h
e20e41
+++ b/src/dhcp-protocol.h
e20e41
@@ -19,6 +19,10 @@
e20e41
 #define DHCP_CLIENT_ALTPORT 1068
e20e41
 #define PXE_PORT 4011
e20e41
 
e20e41
+/* These each hold a DHCP option max size 255
e20e41
+   and get a terminating zero added */
e20e41
+#define DHCP_BUFF_SZ 256
e20e41
+
e20e41
 #define BOOTREQUEST              1
e20e41
 #define BOOTREPLY                2
e20e41
 #define DHCP_COOKIE              0x63825363
e20e41
diff --git a/src/dnsmasq.c b/src/dnsmasq.c
e20e41
index 045ec53..9cd4052 100644
e20e41
--- a/src/dnsmasq.c
e20e41
+++ b/src/dnsmasq.c
e20e41
@@ -1294,6 +1294,7 @@ static void async_event(int pipe, time_t now)
e20e41
 		daemon->tcp_pids[i] = 0;
e20e41
 	break;
e20e41
 	
e20e41
+#if defined(HAVE_SCRIPT)	
e20e41
       case EVENT_KILLED:
e20e41
 	my_syslog(LOG_WARNING, _("script process killed by signal %d"), ev.data);
e20e41
 	break;
e20e41
@@ -1307,12 +1308,19 @@ static void async_event(int pipe, time_t now)
e20e41
 		  daemon->lease_change_command, strerror(ev.data));
e20e41
 	break;
e20e41
 
e20e41
+      case EVENT_SCRIPT_LOG:
e20e41
+	my_syslog(MS_SCRIPT | LOG_DEBUG, "%s", msg ? msg : "");
e20e41
+        free(msg);
e20e41
+	msg = NULL;
e20e41
+	break;
e20e41
+
e20e41
 	/* necessary for fatal errors in helper */
e20e41
       case EVENT_USER_ERR:
e20e41
       case EVENT_DIE:
e20e41
       case EVENT_LUA_ERR:
e20e41
 	fatal_event(&ev, msg);
e20e41
 	break;
e20e41
+#endif
e20e41
 
e20e41
       case EVENT_REOPEN:
e20e41
 	/* Note: this may leave TCP-handling processes with the old file still open.
e20e41
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
e20e41
index 1896a64..0cfd3c6 100644
e20e41
--- a/src/dnsmasq.h
e20e41
+++ b/src/dnsmasq.h
e20e41
@@ -145,30 +145,31 @@ struct event_desc {
e20e41
   int event, data, msg_sz;
e20e41
 };
e20e41
 
e20e41
-#define EVENT_RELOAD    1
e20e41
-#define EVENT_DUMP      2
e20e41
-#define EVENT_ALARM     3
e20e41
-#define EVENT_TERM      4
e20e41
-#define EVENT_CHILD     5
e20e41
-#define EVENT_REOPEN    6
e20e41
-#define EVENT_EXITED    7
e20e41
-#define EVENT_KILLED    8
e20e41
-#define EVENT_EXEC_ERR  9
e20e41
-#define EVENT_PIPE_ERR  10
e20e41
-#define EVENT_USER_ERR  11
e20e41
-#define EVENT_CAP_ERR   12
e20e41
-#define EVENT_PIDFILE   13
e20e41
-#define EVENT_HUSER_ERR 14
e20e41
-#define EVENT_GROUP_ERR 15
e20e41
-#define EVENT_DIE       16
e20e41
-#define EVENT_LOG_ERR   17
e20e41
-#define EVENT_FORK_ERR  18
e20e41
-#define EVENT_LUA_ERR   19
e20e41
-#define EVENT_TFTP_ERR  20
e20e41
-#define EVENT_INIT      21
e20e41
-#define EVENT_NEWADDR   22
e20e41
-#define EVENT_NEWROUTE  23
e20e41
-#define EVENT_TIME_ERR  24
e20e41
+#define EVENT_RELOAD     1
e20e41
+#define EVENT_DUMP       2
e20e41
+#define EVENT_ALARM      3
e20e41
+#define EVENT_TERM       4
e20e41
+#define EVENT_CHILD      5
e20e41
+#define EVENT_REOPEN     6
e20e41
+#define EVENT_EXITED     7
e20e41
+#define EVENT_KILLED     8
e20e41
+#define EVENT_EXEC_ERR   9
e20e41
+#define EVENT_PIPE_ERR   10
e20e41
+#define EVENT_USER_ERR   11
e20e41
+#define EVENT_CAP_ERR    12
e20e41
+#define EVENT_PIDFILE    13
e20e41
+#define EVENT_HUSER_ERR  14
e20e41
+#define EVENT_GROUP_ERR  15
e20e41
+#define EVENT_DIE        16
e20e41
+#define EVENT_LOG_ERR    17
e20e41
+#define EVENT_FORK_ERR   18
e20e41
+#define EVENT_LUA_ERR    19
e20e41
+#define EVENT_TFTP_ERR   20
e20e41
+#define EVENT_INIT       21
e20e41
+#define EVENT_NEWADDR    22
e20e41
+#define EVENT_NEWROUTE   23
e20e41
+#define EVENT_TIME_ERR   24
e20e41
+#define EVENT_SCRIPT_LOG 25
e20e41
 
e20e41
 /* Exit codes. */
e20e41
 #define EC_GOOD        0
e20e41
@@ -242,8 +243,9 @@ struct event_desc {
e20e41
 
e20e41
 /* extra flags for my_syslog, we use a couple of facilities since they are known 
e20e41
    not to occupy the same bits as priorities, no matter how syslog.h is set up. */
e20e41
-#define MS_TFTP LOG_USER
e20e41
-#define MS_DHCP LOG_DAEMON 
e20e41
+#define MS_TFTP   LOG_USER
e20e41
+#define MS_DHCP   LOG_DAEMON
e20e41
+#define MS_SCRIPT LOG_MAIL
e20e41
 
e20e41
 struct all_addr {
e20e41
   union {
e20e41
diff --git a/src/helper.c b/src/helper.c
e20e41
index 9c37e37..de31383 100644
e20e41
--- a/src/helper.c
e20e41
+++ b/src/helper.c
e20e41
@@ -14,6 +14,7 @@
e20e41
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
e20e41
 */
e20e41
 
e20e41
+#include <stdio.h>
e20e41
 #include "dnsmasq.h"
e20e41
 
e20e41
 #ifdef HAVE_SCRIPT
e20e41
@@ -135,7 +136,7 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
e20e41
 	max_fd != STDIN_FILENO && max_fd != pipefd[0] && 
e20e41
 	max_fd != event_fd && max_fd != err_fd)
e20e41
       close(max_fd);
e20e41
-  
e20e41
+
e20e41
 #ifdef HAVE_LUASCRIPT
e20e41
   if (daemon->luascript)
e20e41
     {
e20e41
@@ -189,6 +190,7 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
e20e41
       unsigned char *buf = (unsigned char *)daemon->namebuff;
e20e41
       unsigned char *end, *extradata, *alloc_buff = NULL;
e20e41
       int is6, err = 0;
e20e41
+      int pipeout[2];
e20e41
 
e20e41
       free(alloc_buff);
e20e41
       
e20e41
@@ -472,16 +474,54 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
e20e41
       if (!daemon->lease_change_command)
e20e41
 	continue;
e20e41
 
e20e41
+      /* Pipe to capture stdout and stderr from script */
e20e41
+      if (!option_bool(OPT_DEBUG) && pipe(pipeout) == -1)
e20e41
+	continue;
e20e41
+      
e20e41
       /* possible fork errors are all temporary resource problems */
e20e41
       while ((pid = fork()) == -1 && (errno == EAGAIN || errno == ENOMEM))
e20e41
 	sleep(2);
e20e41
 
e20e41
       if (pid == -1)
e20e41
-	continue;
e20e41
+        {
e20e41
+	  if (!option_bool(OPT_DEBUG))
e20e41
+	    {
e20e41
+	      close(pipeout[0]);
e20e41
+	      close(pipeout[1]);
e20e41
+	    }
e20e41
+	  continue;
e20e41
+        }
e20e41
       
e20e41
       /* wait for child to complete */
e20e41
       if (pid != 0)
e20e41
 	{
e20e41
+	  if (!option_bool(OPT_DEBUG))
e20e41
+	    {
e20e41
+	      FILE *fp;
e20e41
+	  
e20e41
+	      close(pipeout[1]);
e20e41
+	      
e20e41
+	      /* Read lines sent to stdout/err by the script and pass them back to be logged */
e20e41
+	      if (!(fp = fdopen(pipeout[0], "r")))
e20e41
+		close(pipeout[0]);
e20e41
+	      else
e20e41
+		{
e20e41
+		  while (fgets(daemon->packet, daemon->packet_buff_sz, fp))
e20e41
+		    {
e20e41
+		      /* do not include new lines, log will append them */
e20e41
+		      size_t len = strlen(daemon->packet);
e20e41
+		      if (len > 0)
e20e41
+			{
e20e41
+			  --len;
e20e41
+			  if (daemon->packet[len] == '\n')
e20e41
+			    daemon->packet[len] = 0;
e20e41
+			}
e20e41
+		      send_event(event_fd, EVENT_SCRIPT_LOG, 0, daemon->packet);
e20e41
+		    }
e20e41
+		  fclose(fp);
e20e41
+		}
e20e41
+	    }
e20e41
+	  
e20e41
 	  /* reap our children's children, if necessary */
e20e41
 	  while (1)
e20e41
 	    {
e20e41
@@ -504,6 +544,15 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
e20e41
 	  
e20e41
 	  continue;
e20e41
 	}
e20e41
+
e20e41
+      if (!option_bool(OPT_DEBUG))
e20e41
+	{
e20e41
+	  /* map stdout/stderr of script to pipeout */
e20e41
+	  close(pipeout[0]);
e20e41
+	  dup2(pipeout[1], STDOUT_FILENO);
e20e41
+	  dup2(pipeout[1], STDERR_FILENO);
e20e41
+	  close(pipeout[1]);
e20e41
+	}
e20e41
       
e20e41
       if (data.action != ACTION_TFTP && data.action != ACTION_ARP)
e20e41
 	{
e20e41
@@ -579,7 +628,8 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
e20e41
 	    hostname = NULL;
e20e41
 	  
e20e41
 	  my_setenv("DNSMASQ_LOG_DHCP", option_bool(OPT_LOG_OPTS) ? "1" : NULL, &err;;
e20e41
-    }
e20e41
+	}
e20e41
+      
e20e41
       /* we need to have the event_fd around if exec fails */
e20e41
       if ((i = fcntl(event_fd, F_GETFD)) != -1)
e20e41
 	fcntl(event_fd, F_SETFD, i | FD_CLOEXEC);
e20e41
diff --git a/src/lease.c b/src/lease.c
e20e41
index 20cac90..64047f9 100644
e20e41
--- a/src/lease.c
e20e41
+++ b/src/lease.c
e20e41
@@ -21,94 +21,62 @@
e20e41
 static struct dhcp_lease *leases = NULL, *old_leases = NULL;
e20e41
 static int dns_dirty, file_dirty, leases_left;
e20e41
 
e20e41
-void lease_init(time_t now)
e20e41
+static int read_leases(time_t now, FILE *leasestream)
e20e41
 {
e20e41
   unsigned long ei;
e20e41
   struct all_addr addr;
e20e41
   struct dhcp_lease *lease;
e20e41
   int clid_len, hw_len, hw_type;
e20e41
-  FILE *leasestream;
e20e41
-  
e20e41
-  leases_left = daemon->dhcp_max;
e20e41
-  
e20e41
-  if (option_bool(OPT_LEASE_RO))
e20e41
-    {
e20e41
-      /* run "<lease_change_script> init" once to get the
e20e41
-	 initial state of the database. If leasefile-ro is
e20e41
-	 set without a script, we just do without any 
e20e41
-	 lease database. */
e20e41
-#ifdef HAVE_SCRIPT
e20e41
-      if (daemon->lease_change_command)
e20e41
-	{
e20e41
-	  strcpy(daemon->dhcp_buff, daemon->lease_change_command);
e20e41
-	  strcat(daemon->dhcp_buff, " init");
e20e41
-	  leasestream = popen(daemon->dhcp_buff, "r");
e20e41
-	}
e20e41
-      else
e20e41
+  int items;
e20e41
+  char *domain = NULL;
e20e41
+
e20e41
+  *daemon->dhcp_buff3 = *daemon->dhcp_buff2 = '\0';
e20e41
+
e20e41
+  /* client-id max length is 255 which is 255*2 digits + 254 colons
e20e41
+     borrow DNS packet buffer which is always larger than 1000 bytes
e20e41
+
e20e41
+     Check various buffers are big enough for the code below */
e20e41
+
e20e41
+#if (DHCP_BUFF_SZ < 255) || (MAXDNAME < 64) || (PACKETSZ+MAXDNAME+RRFIXEDSZ  < 764)
e20e41
+# error Buffer size breakage in leasefile parsing.
e20e41
 #endif
e20e41
-	{
e20e41
-          file_dirty = dns_dirty = 0;
e20e41
-          return;
e20e41
-        }
e20e41
 
e20e41
-    }
e20e41
-  else
e20e41
-    {
e20e41
-      /* NOTE: need a+ mode to create file if it doesn't exist */
e20e41
-      leasestream = daemon->lease_stream = fopen(daemon->lease_file, "a+");
e20e41
-      
e20e41
-      if (!leasestream)
e20e41
-	die(_("cannot open or create lease file %s: %s"), daemon->lease_file, EC_FILE);
e20e41
-      
e20e41
-      /* a+ mode leaves pointer at end. */
e20e41
-      rewind(leasestream);
e20e41
-    }
e20e41
-  
e20e41
-  /* client-id max length is 255 which is 255*2 digits + 254 colons 
e20e41
-     borrow DNS packet buffer which is always larger than 1000 bytes */
e20e41
-  if (leasestream)
e20e41
-    while (fscanf(leasestream, "%255s %255s", daemon->dhcp_buff3, daemon->dhcp_buff2) == 2)
e20e41
+    while ((items=fscanf(leasestream, "%255s %255s", daemon->dhcp_buff3, daemon->dhcp_buff2)) == 2)
e20e41
       {
e20e41
+	*daemon->namebuff = *daemon->dhcp_buff = *daemon->packet = '\0';
e20e41
+	hw_len = hw_type = clid_len = 0;
e20e41
+	
e20e41
 #ifdef HAVE_DHCP6
e20e41
 	if (strcmp(daemon->dhcp_buff3, "duid") == 0)
e20e41
 	  {
e20e41
 	    daemon->duid_len = parse_hex(daemon->dhcp_buff2, (unsigned char *)daemon->dhcp_buff2, 130, NULL, NULL);
e20e41
+	    if (daemon->duid_len < 0)
e20e41
+	      return 0;
e20e41
 	    daemon->duid = safe_malloc(daemon->duid_len);
e20e41
 	    memcpy(daemon->duid, daemon->dhcp_buff2, daemon->duid_len);
e20e41
 	    continue;
e20e41
 	  }
e20e41
 #endif
e20e41
-
e20e41
-	ei = atol(daemon->dhcp_buff3);
e20e41
 	
e20e41
 	if (fscanf(leasestream, " %64s %255s %764s",
e20e41
 		   daemon->namebuff, daemon->dhcp_buff, daemon->packet) != 3)
e20e41
-	  break;
e20e41
+	  return 0;
e20e41
 	
e20e41
-	clid_len = 0;
e20e41
-	if (strcmp(daemon->packet, "*") != 0)
e20e41
-	  clid_len = parse_hex(daemon->packet, (unsigned char *)daemon->packet, 255, NULL, NULL);
e20e41
-	
e20e41
-	if (inet_pton(AF_INET, daemon->namebuff, &addr.addr.addr4) &&
e20e41
-	    (lease = lease4_allocate(addr.addr.addr4)))
e20e41
+	if (inet_pton(AF_INET, daemon->namebuff, &addr.addr.addr4))
e20e41
 	  {
e20e41
+	    if ((lease = lease4_allocate(addr.addr.addr4)))
e20e41
+	      domain = get_domain(lease->addr);
e20e41
+	    
e20e41
 	    hw_len = parse_hex(daemon->dhcp_buff2, (unsigned char *)daemon->dhcp_buff2, DHCP_CHADDR_MAX, NULL, &hw_type);
e20e41
 	    /* For backwards compatibility, no explict MAC address type means ether. */
e20e41
 	    if (hw_type == 0 && hw_len != 0)
e20e41
 	      hw_type = ARPHRD_ETHER; 
e20e41
-
e20e41
-	    lease_set_hwaddr(lease, (unsigned char *)daemon->dhcp_buff2, (unsigned char *)daemon->packet, 
e20e41
-			     hw_len, hw_type, clid_len, now, 0);
e20e41
-	    
e20e41
-	    if (strcmp(daemon->dhcp_buff, "*") !=  0)
e20e41
-	      lease_set_hostname(lease, daemon->dhcp_buff, 0, get_domain(lease->addr), NULL);
e20e41
 	  }
e20e41
 #ifdef HAVE_DHCP6
e20e41
 	else if (inet_pton(AF_INET6, daemon->namebuff, &addr.addr.addr6))
e20e41
 	  {
e20e41
 	    char *s = daemon->dhcp_buff2;
e20e41
 	    int lease_type = LEASE_NA;
e20e41
-	    int iaid;
e20e41
 
e20e41
 	    if (s[0] == 'T')
e20e41
 	      {
e20e41
@@ -116,23 +84,30 @@ void lease_init(time_t now)
e20e41
 		s++;
e20e41
 	      }
e20e41
 	    
e20e41
-	    iaid = strtoul(s, NULL, 10);
e20e41
-	    
e20e41
 	    if ((lease = lease6_allocate(&addr.addr.addr6, lease_type)))
e20e41
 	      {
e20e41
-		lease_set_hwaddr(lease, NULL, (unsigned char *)daemon->packet, 0, 0, clid_len, now, 0);
e20e41
-		lease_set_iaid(lease, iaid);
e20e41
-		if (strcmp(daemon->dhcp_buff, "*") !=  0)
e20e41
-		  lease_set_hostname(lease, daemon->dhcp_buff, 0, get_domain6((struct in6_addr *)lease->hwaddr), NULL);
e20e41
+		lease_set_iaid(lease, strtoul(s, NULL, 10));
e20e41
+		domain = get_domain6((struct in6_addr *)lease->hwaddr);
e20e41
 	      }
e20e41
 	  }
e20e41
 #endif
e20e41
 	else
e20e41
-	  break;
e20e41
+	  return 0;
e20e41
 
e20e41
 	if (!lease)
e20e41
 	  die (_("too many stored leases"), NULL, EC_MISC);
e20e41
-       	
e20e41
+
e20e41
+	if (strcmp(daemon->packet, "*") != 0)
e20e41
+	  clid_len = parse_hex(daemon->packet, (unsigned char *)daemon->packet, 255, NULL, NULL);
e20e41
+	
e20e41
+	lease_set_hwaddr(lease, (unsigned char *)daemon->dhcp_buff2, (unsigned char *)daemon->packet, 
e20e41
+			 hw_len, hw_type, clid_len, now, 0);
e20e41
+	
e20e41
+	if (strcmp(daemon->dhcp_buff, "*") !=  0)
e20e41
+	  lease_set_hostname(lease, daemon->dhcp_buff, 0, domain, NULL);
e20e41
+
e20e41
+	ei = atol(daemon->dhcp_buff3);
e20e41
+
e20e41
 #ifdef HAVE_BROKEN_RTC
e20e41
 	if (ei != 0)
e20e41
 	  lease->expires = (time_t)ei + now;
e20e41
@@ -148,7 +123,62 @@ void lease_init(time_t now)
e20e41
 	/* set these correctly: the "old" events are generated later from
e20e41
 	   the startup synthesised SIGHUP. */
e20e41
 	lease->flags &= ~(LEASE_NEW | LEASE_CHANGED);
e20e41
+	
e20e41
+	*daemon->dhcp_buff3 = *daemon->dhcp_buff2 = '\0';
e20e41
       }
e20e41
+    
e20e41
+    return (items == 0 || items == EOF);
e20e41
+}
e20e41
+
e20e41
+void lease_init(time_t now)
e20e41
+{
e20e41
+  FILE *leasestream;
e20e41
+
e20e41
+  leases_left = daemon->dhcp_max;
e20e41
+
e20e41
+  if (option_bool(OPT_LEASE_RO))
e20e41
+    {
e20e41
+      /* run "<lease_change_script> init" once to get the
e20e41
+	 initial state of the database. If leasefile-ro is
e20e41
+	 set without a script, we just do without any
e20e41
+	 lease database. */
e20e41
+#ifdef HAVE_SCRIPT
e20e41
+      if (daemon->lease_change_command)
e20e41
+	{
e20e41
+	  strcpy(daemon->dhcp_buff, daemon->lease_change_command);
e20e41
+	  strcat(daemon->dhcp_buff, " init");
e20e41
+	  leasestream = popen(daemon->dhcp_buff, "r");
e20e41
+	}
e20e41
+      else
e20e41
+#endif
e20e41
+	{
e20e41
+          file_dirty = dns_dirty = 0;
e20e41
+          return;
e20e41
+        }
e20e41
+
e20e41
+    }
e20e41
+  else
e20e41
+    {
e20e41
+      /* NOTE: need a+ mode to create file if it doesn't exist */
e20e41
+      leasestream = daemon->lease_stream = fopen(daemon->lease_file, "a+");
e20e41
+
e20e41
+      if (!leasestream)
e20e41
+	die(_("cannot open or create lease file %s: %s"), daemon->lease_file, EC_FILE);
e20e41
+
e20e41
+      /* a+ mode leaves pointer at end. */
e20e41
+      rewind(leasestream);
e20e41
+    }
e20e41
+
e20e41
+  if (leasestream)
e20e41
+    {
e20e41
+      if (!read_leases(now, leasestream))
e20e41
+	my_syslog(MS_DHCP | LOG_ERR, _("failed to parse lease database, invalid line: %s %s %s %s ..."),
e20e41
+		  daemon->dhcp_buff3, daemon->dhcp_buff2,
e20e41
+		  daemon->namebuff, daemon->dhcp_buff);
e20e41
+
e20e41
+      if (ferror(leasestream))
e20e41
+	die(_("failed to read lease file %s: %s"), daemon->lease_file, EC_FILE);
e20e41
+    }
e20e41
   
e20e41
 #ifdef HAVE_SCRIPT
e20e41
   if (!daemon->lease_stream)
e20e41
@@ -162,6 +192,7 @@ void lease_init(time_t now)
e20e41
 	    errno = ENOENT;
e20e41
 	  else if (WEXITSTATUS(rc) == 126)
e20e41
 	    errno = EACCES;
e20e41
+
e20e41
 	  die(_("cannot run lease-init script %s: %s"), daemon->lease_change_command, EC_FILE);
e20e41
 	}
e20e41
       
e20e41
diff --git a/src/log.c b/src/log.c
e20e41
index 8e66629..5fc860b 100644
e20e41
--- a/src/log.c
e20e41
+++ b/src/log.c
e20e41
@@ -288,7 +288,9 @@ void my_syslog(int priority, const char *format, ...)
e20e41
     func = "-tftp";
e20e41
   else if ((LOG_FACMASK & priority) == MS_DHCP)
e20e41
     func = "-dhcp";
e20e41
-      
e20e41
+  else if ((LOG_FACMASK & priority) == MS_SCRIPT)
e20e41
+    func = "-script";
e20e41
+	    
e20e41
 #ifdef LOG_PRI
e20e41
   priority = LOG_PRI(priority);
e20e41
 #else
e20e41
diff --git a/src/rfc3315.c b/src/rfc3315.c
e20e41
index 3f4d69c..a3715cd 100644
e20e41
--- a/src/rfc3315.c
e20e41
+++ b/src/rfc3315.c
e20e41
@@ -1975,7 +1975,7 @@ static void log6_packet(struct state *state, char *type, struct in6_addr *addr,
e20e41
 
e20e41
   if (addr)
e20e41
     {
e20e41
-      inet_ntop(AF_INET6, addr, daemon->dhcp_buff2, 255);
e20e41
+      inet_ntop(AF_INET6, addr, daemon->dhcp_buff2, DHCP_BUFF_SZ - 1);
e20e41
       strcat(daemon->dhcp_buff2, " ");
e20e41
     }
e20e41
   else
e20e41
-- 
e20e41
2.9.3
e20e41