import of dnsmasq-2.6.tar.gz
diff --git a/src/dhcp.c b/src/dhcp.c
index f4f71a6..02e42b9 100644
--- a/src/dhcp.c
+++ b/src/dhcp.c
@@ -362,6 +362,10 @@
   start = ntohl(context->start.s_addr);
   end = ntohl(context->end.s_addr);
 
+  /* static leases only. */
+  if (start == end)
+    return 0;
+
   if (addr < start)
     return 0;
 
@@ -382,7 +386,11 @@
 
   struct dhcp_config *config;
   struct in_addr start = context->last;
-  
+
+  /* start == end means no dynamic leases. */
+  if (context->end.s_addr == context->start.s_addr)
+    return 0;
+
   do {
     if (context->last.s_addr == context->end.s_addr)
       context->last = context->start;
@@ -393,7 +401,7 @@
     if (!lease_find_by_addr(context->last))
       {
 	for (config = configs; config; config = config->next)
-	  if (config->addr.s_addr == context->last.s_addr)
+	  if ((config->flags & CONFIG_ADDR) && config->addr.s_addr == context->last.s_addr)
 	    break;
 	
 	if (!config)
@@ -411,7 +419,7 @@
 {
   if (!context)
     return 1;
-  if (config->addr.s_addr == 0)
+  if (!(config->flags & CONFIG_ADDR))
     return 1;
   if ((config->addr.s_addr & context->netmask.s_addr) == (context->start.s_addr & context->netmask.s_addr))
     return 1;
@@ -428,28 +436,31 @@
   
   if (clid_len)
     for (config = configs; config; config = config->next)
-      {
-	if (config->clid_len == clid_len && 
-	    memcmp(config->clid, clid, clid_len) == 0 &&
-	    is_addr_in_context(context, config))
-	  return config;
-	
-	/* dhcpcd prefixes ASCII client IDs by zero which is wrong, but we try and
-	   cope with that here */
-	if (*clid == 0 && config->clid_len == clid_len-1  &&
-	    memcmp(config->clid, clid+1, clid_len-1) == 0 &&
-	    is_addr_in_context(context, config))
-	  return config;
-      }
-    
+      if (config->flags & CONFIG_CLID)
+	{
+	  if (config->clid_len == clid_len && 
+	      memcmp(config->clid, clid, clid_len) == 0 &&
+	      is_addr_in_context(context, config))
+	    return config;
+	  
+	  /* dhcpcd prefixes ASCII client IDs by zero which is wrong, but we try and
+	     cope with that here */
+	  if (*clid == 0 && config->clid_len == clid_len-1  &&
+	      memcmp(config->clid, clid+1, clid_len-1) == 0 &&
+	      is_addr_in_context(context, config))
+	    return config;
+	}
+  
   for (config = configs; config; config = config->next)
-    if (memcmp(config->hwaddr, hwaddr, ETHER_ADDR_LEN) == 0 &&
+    if ((config->flags & CONFIG_HWADDR) &&
+	memcmp(config->hwaddr, hwaddr, ETHER_ADDR_LEN) == 0 &&
 	is_addr_in_context(context, config))
       return config;
   
   if (hostname)
     for (config = configs; config; config = config->next)
-      if (config->hostname && hostname_isequal(config->hostname, hostname) &&
+      if ((config->flags & CONFIG_NAME) && 
+	  hostname_isequal(config->hostname, hostname) &&
 	  is_addr_in_context(context, config))
 	return config;
   
@@ -459,28 +470,29 @@
 struct dhcp_config *dhcp_read_ethers(struct dhcp_config *configs, char *buff)
 {
   FILE *f = fopen(ETHERSFILE, "r");
-  unsigned int e0, e1, e2, e3, e4, e5;
-  char *ip, *cp, *name;
+  unsigned int flags, e0, e1, e2, e3, e4, e5;
+  char *ip, *cp;
   struct in_addr addr;
+  unsigned char hwaddr[ETHER_ADDR_LEN];
   struct dhcp_config *config;
+  int count = 0;
   
   if (!f)
-    die("failed to open " ETHERSFILE ":%s", NULL);
-  
+    {
+      syslog(LOG_ERR, "failed to read " ETHERSFILE ":%m");
+      return configs;
+    }
+
   while (fgets(buff, MAXDNAME, f))
     {
-      while (strlen(buff) > 0 && 
-	     (buff[strlen(buff)-1] == '\n' || 
-	      buff[strlen(buff)-1] == ' ' || 
-	      buff[strlen(buff)-1] == '\r' || 
-	      buff[strlen(buff)-1] == '\t'))
+      while (strlen(buff) > 0 && isspace(buff[strlen(buff)-1]))
 	buff[strlen(buff)-1] = 0;
       
       if ((*buff == '#') || (*buff == '+'))
 	continue;
       
-      for (ip = buff; *ip && *ip != ' ' && *ip != '\t'; ip++);
-      for(; *ip && (*ip == ' ' || *ip == '\t'); ip++)
+      for (ip = buff; *ip && !isspace(*ip); ip++);
+      for(; *ip && isspace(*ip); ip++)
 	*ip = 0;
       if (!*ip)
 	continue;
@@ -488,6 +500,13 @@
       if (!sscanf(buff, "%x:%x:%x:%x:%x:%x", &e0, &e1, &e2, &e3, &e4, &e5))
 	continue;
       
+      hwaddr[0] = e0;
+      hwaddr[1] = e1;
+      hwaddr[2] = e2;
+      hwaddr[3] = e3;
+      hwaddr[4] = e4;
+      hwaddr[5] = e5;
+
       /* check for name or dotted-quad */
       for (cp = ip; *cp; cp++)
 	if (!(*cp == '.' || (*cp >='0' && *cp <= '9')))
@@ -495,47 +514,64 @@
       
       if (!*cp)
 	{
-	  name = NULL;
 	  if ((addr.s_addr = inet_addr(ip)) == (in_addr_t)-1)
 	    continue;
+	  flags = CONFIG_ADDR;
 	  
 	  for (config = configs; config; config = config->next)
-	    if (config->addr.s_addr == addr.s_addr)
+	    if ((config->flags & CONFIG_ADDR) && config->addr.s_addr == addr.s_addr)
 	      break;
 	}
       else 
 	{
 	  if (!canonicalise(ip))
 	    continue;
-	  name = ip;
-	  addr.s_addr = 0;
+	  flags = CONFIG_NAME;
 
 	  for (config = configs; config; config = config->next)
-	    if (config->hostname && hostname_isequal(config->hostname, name))
+	    if ((config->flags & CONFIG_NAME) && hostname_isequal(config->hostname, ip))
 	      break;
 	}
       
       if (!config)
 	{ 
-	  config = safe_malloc(sizeof(struct dhcp_config));
-	  config->clid_len = 0;
-	  config->clid = NULL; 
-	  config->lease_time = 0;
-	  config->hostname = safe_string_alloc(name);
-	  config->addr = addr;
-	  config->next = configs;
-	  configs = config;
+	  for (config = configs; config; config = config->next)
+	    if ((config->flags & CONFIG_HWADDR) && 
+		memcmp(config->hwaddr, hwaddr, ETHER_ADDR_LEN) == 0)
+	      break;
+	  
+	  if (!config)
+	    {
+	      if (!(config = malloc(sizeof(struct dhcp_config))))
+		continue;
+	      config->flags = 0;
+	      config->next = configs;
+	      configs = config;
+	    }
+	  
+	  config->flags |= flags;
+	  
+	  if (flags & CONFIG_NAME)
+	    {
+	      if ((config->hostname = malloc(strlen(ip)+1)))
+		strcpy(config->hostname, ip);
+	      else
+		config->flags &= ~CONFIG_NAME;
+	    }
+	  
+	  if (flags & CONFIG_ADDR)
+	    config->addr = addr;
 	}
+      
+      config->flags |= CONFIG_HWADDR;
+      memcpy(config->hwaddr, hwaddr, ETHER_ADDR_LEN);
 
-      config->hwaddr[0] = e0;
-      config->hwaddr[1] = e1;
-      config->hwaddr[2] = e2;
-      config->hwaddr[3] = e3;
-      config->hwaddr[4] = e4;
-      config->hwaddr[5] = e5;
+      count++;
     }
   
   fclose(f);
+
+  syslog(LOG_INFO, "read " ETHERSFILE " - %d addresses", count);
   return configs;
 }
 
@@ -549,10 +585,13 @@
   struct crec *crec;
   
   for (config = configs; config; config = config->next)
-    if (config->addr.s_addr == 0 && config->hostname && 
+    if (!(config->flags & CONFIG_ADDR) &&
+	(config->flags & CONFIG_NAME) && 
 	(crec = cache_find_by_name(NULL, config->hostname, 0, F_IPV4)) &&
 	(crec->flags & F_HOSTS))
-      config->addr = crec->addr.addr.addr4;
-  
+      {
+	config->addr = crec->addr.addr.addr4;
+	config->flags |= CONFIG_ADDR;
+      }
 }