Blame SOURCES/dnsmasq-2.76-dhcp-script-log.patch

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