Enhance --synth-domain to allow names with sequential integers.
diff --git a/CHANGELOG b/CHANGELOG
index 87dcfef..4cc1858 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -49,7 +49,17 @@
 	Fix failure to delete dynamically created dhcp options
 	from files in -dhcp-optsdir directories. Thanks to
 	Lindgren Fredrik for the bug report.
-	
+
+	Add to --synth-domain the ability to create names using
+	sequential numbers, as well as encodings of IP addresses.
+	For instance,
+	--synth-domain=thekelleys.org.uk,192.168.0.50,192.168.0.70,internal-*
+	creates 21 domain names of the form
+	internal-4.thekelleys.org.uk over the address range given, with
+	internal-0.thekelleys.org.uk being 192.168.0.50 and
+	internal-20.thekelleys.org.uk being 192.168.0.70
+	Thanks to Andy Hawkins for the suggestion.
+
 
 version 2.78
         Fix logic of appending ".<layer>" to PXE basename. Thanks to Chris
diff --git a/man/dnsmasq.8 b/man/dnsmasq.8
index 68e602e..bd99b48 100644
--- a/man/dnsmasq.8
+++ b/man/dnsmasq.8
@@ -626,13 +626,16 @@
 for the reverse address-to-name mapping. Note that a name used in 
 --interface-name may not appear in /etc/hosts.
 .TP
-.B --synth-domain=<domain>,<address range>[,<prefix>]
+.B --synth-domain=<domain>,<address range>[,<prefix>[*]]
 Create artificial A/AAAA and PTR records for an address range. The
-records use the address, with periods (or colons for IPv6) replaced
-with dashes.
+records either seqential numbers or the address, with periods (or colons for IPv6) replaced with dashes.
 
-An example should make this clearer.
-.B --synth-domain=thekelleys.org.uk,192.168.0.0/24,internal-
+An examples should make this clearer. First sequential numbers.
+.B --synth-domain=thekelleys.org.uk,192.168.0.50,192.168.0.70,internal-*
+results in the name internal-0.thekelleys.org.uk. returning 192.168.0.50, internal-1.thekelleys.org.uk returning 192.168.0.51 and so on. (note the *) The same principle applies to IPv6 addresses (where the numbers may be very large). Reverse lookups from address to name behave as expected.
+
+Second, 
+.B --synth-domain=thekelleys.org.uk,192.168.0.0/24,internal- (no *)
 will result in a query for internal-192-168-0-56.thekelleys.org.uk returning
 192.168.0.56 and a reverse query vice versa. The same applies to IPv6,
 but IPv6 addresses may start with '::'
@@ -642,7 +645,7 @@
 V4 mapped IPv6 addresses, which have a representation like ::ffff:1.2.3.4 are handled specially, and become like 0--ffff-1-2-3-4
 
 The address range can be of the form
-<ip address>,<ip address> or <ip address>/<netmask>
+<ip address>,<ip address> or <ip address>/<netmask> in both forms of the option.
 .TP
 .B --add-mac[=base64|text]
 Add the MAC address of the requestor to DNS queries which are
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index f4d330a..6773b69 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -839,7 +839,7 @@
 #ifdef HAVE_IPV6
   struct in6_addr start6, end6;
 #endif
-  int is6;
+  int is6, indexed;
   struct cond_domain *next;
 }; 
 
diff --git a/src/domain.c b/src/domain.c
index 853dc17..04d7cf8 100644
--- a/src/domain.c
+++ b/src/domain.c
@@ -55,83 +55,133 @@
       
       if (pref && *pref != 0)
 	continue; /* prefix match fail */
-      
-      /* NB, must not alter name if we return zero */
-      for (p = tail; *p; p++)
+
+      if (c->indexed)
 	{
-	  char c = *p;
+	  for (p = tail; *p; p++)
+	    {
+	      char c = *p;
+	      
+	      if (c < '0' || c > '9')
+		break;
+	    }
 	  
-	  if ((c >='0' && c <= '9') || c == '-')
+	  if (*p != '.')
 	    continue;
 	  
-#ifdef HAVE_IPV6
-	  if (prot == AF_INET6 && ((c >='A' && c <= 'F') || (c >='a' && c <= 'f'))) 
-	    continue;
+	  *p = 0;
+	  
+	  if (hostname_isequal(c->domain, p+1))
+	    {
+	      if (prot == AF_INET)
+		{
+		  unsigned int index = atoi(tail);
+
+		   if (!c->is6 &&
+		      index <= ntohl(c->end.s_addr) - ntohl(c->start.s_addr))
+		    {
+		      addr->addr.addr4.s_addr = htonl(ntohl(c->start.s_addr) + index);
+		      found = 1;
+		    }
+		}
+#ifdef HAVE_IPV6 
+	      else
+		{
+		  u64 index = atoll(tail);
+		  
+		  if (c->is6 &&
+		      index <= addr6part(&c->end6) - addr6part(&c->start6))
+		    {
+		      u64 start = addr6part(&c->start6);
+		      addr->addr.addr6 = c->start6;
+		      setaddr6part(&addr->addr.addr6, start + index);
+		      found = 1;
+		    }
+		}
 #endif
-	  
-	  break;
-	}
-      
-      if (*p != '.')
-	continue;
-      
-      *p = 0;	
-      
- #ifdef HAVE_IPV6
-      if (prot == AF_INET6 && strstr(tail, "--ffff-") == tail)
-	{
-	  /* special hack for v4-mapped. */
-	  memcpy(tail, "::ffff:", 7);
-	  for (p = tail + 7; *p; p++)
-	    if (*p == '-')
-	      *p = '.';
+	    }
 	}
       else
-#endif
 	{
-	  /* swap . or : for - */
+	  /* NB, must not alter name if we return zero */
 	  for (p = tail; *p; p++)
-	    if (*p == '-')
-	      {
-		if (prot == AF_INET)
-		  *p = '.';
+	    {
+	      char c = *p;
+	      
+	      if ((c >='0' && c <= '9') || c == '-')
+		continue;
+	      
 #ifdef HAVE_IPV6
-		else
-		  *p = ':';
+	      if (prot == AF_INET6 && ((c >='A' && c <= 'F') || (c >='a' && c <= 'f'))) 
+		continue;
 #endif
-	      }
+	      
+	      break;
+	    }
+	  
+	  if (*p != '.')
+	    continue;
+	  
+	  *p = 0;	
+	  
+#ifdef HAVE_IPV6
+	  if (prot == AF_INET6 && strstr(tail, "--ffff-") == tail)
+	    {
+	      /* special hack for v4-mapped. */
+	      memcpy(tail, "::ffff:", 7);
+	      for (p = tail + 7; *p; p++)
+		if (*p == '-')
+		  *p = '.';
+	    }
+	  else
+#endif
+	    {
+	      /* swap . or : for - */
+	      for (p = tail; *p; p++)
+		if (*p == '-')
+		  {
+		    if (prot == AF_INET)
+		      *p = '.';
+#ifdef HAVE_IPV6
+		    else
+		      *p = ':';
+#endif
+		  }
+	    }
+	  
+	  if (hostname_isequal(c->domain, p+1) && inet_pton(prot, tail, addr))
+	    {
+	      if (prot == AF_INET)
+		{
+		  if (!c->is6 &&
+		      ntohl(addr->addr.addr4.s_addr) >= ntohl(c->start.s_addr) &&
+		      ntohl(addr->addr.addr4.s_addr) <= ntohl(c->end.s_addr))
+		    found = 1;
+		}
+#ifdef HAVE_IPV6
+	      else
+		{
+		  u64 addrpart = addr6part(&addr->addr.addr6);
+		  
+		  if (c->is6 &&
+		      is_same_net6(&addr->addr.addr6, &c->start6, 64) &&
+		      addrpart >= addr6part(&c->start6) &&
+		      addrpart <= addr6part(&c->end6))
+		    found = 1;
+		}
+#endif
+	    }
+
 	}
 
-      if (hostname_isequal(c->domain, p+1) && inet_pton(prot, tail, addr))
-	{
-	  if (prot == AF_INET)
-	    {
-	      if (!c->is6 &&
-		  ntohl(addr->addr.addr4.s_addr) >= ntohl(c->start.s_addr) &&
-		  ntohl(addr->addr.addr4.s_addr) <= ntohl(c->end.s_addr))
-		found = 1;
-	    }
-#ifdef HAVE_IPV6
-	  else
-	    {
-	      u64 addrpart = addr6part(&addr->addr.addr6);
-	      
-	      if (c->is6 &&
-		  is_same_net6(&addr->addr.addr6, &c->start6, 64) &&
-		  addrpart >= addr6part(&c->start6) &&
-		  addrpart <= addr6part(&c->end6))
-		found = 1;
-	    }
-#endif
-	}
-      
       /* restore name */
       for (p = tail; *p; p++)
 	if (*p == '.' || *p == ':')
 	  *p = '-';
       
       *p = '.';
-
+      
+      
       if (found)
 	return 1;
     }
@@ -149,14 +199,22 @@
        char *p;
        
        *name = 0;
-       if (c->prefix)
-	 strncpy(name, c->prefix, MAXDNAME - ADDRSTRLEN);
+       if (c->indexed)
+	 {
+	   unsigned int index = ntohl(addr->addr.addr4.s_addr) - ntohl(c->start.s_addr);
+	   snprintf(name, MAXDNAME, "%s%u", c->prefix ? c->prefix : "", index);
+	 }
+       else
+	 {
+	   if (c->prefix)
+	     strncpy(name, c->prefix, MAXDNAME - ADDRSTRLEN);
        
-       inet_ntop(AF_INET, &addr->addr.addr4, name + strlen(name), ADDRSTRLEN);
-       for (p = name; *p; p++)
-	 if (*p == '.')
-	   *p = '-';
-
+       	   inet_ntop(AF_INET, &addr->addr.addr4, name + strlen(name), ADDRSTRLEN);
+	   for (p = name; *p; p++)
+	     if (*p == '.')
+	       *p = '-';
+	 }
+       
        strncat(name, ".", MAXDNAME);
        strncat(name, c->domain, MAXDNAME);
 
@@ -169,23 +227,32 @@
        char *p;
        
        *name = 0;
-       if (c->prefix)
-	 strncpy(name, c->prefix, MAXDNAME - ADDRSTRLEN);
-       
-       inet_ntop(AF_INET6, &addr->addr.addr6, name + strlen(name), ADDRSTRLEN);
-
-       /* IPv6 presentation address can start with ":", but valid domain names
-	  cannot start with "-" so prepend a zero in that case. */
-       if (!c->prefix && *name == ':')
+       if (c->indexed)
 	 {
-	   *name = '0';
-	   inet_ntop(AF_INET6, &addr->addr.addr6, name+1, ADDRSTRLEN);
+	   u64 index = addr6part(&addr->addr.addr6) - addr6part(&c->start6);
+	   snprintf(name, MAXDNAME, "%s%llu", c->prefix ? c->prefix : "", index);
 	 }
+       else
+	 {
+	   if (c->prefix)
+	     strncpy(name, c->prefix, MAXDNAME - ADDRSTRLEN);
+       
+	   inet_ntop(AF_INET6, &addr->addr.addr6, name + strlen(name), ADDRSTRLEN);
 
-       /* V4-mapped have periods.... */
-       for (p = name; *p; p++)
-	 if (*p == ':' || *p == '.')
-	   *p = '-';
+	   /* IPv6 presentation address can start with ":", but valid domain names
+	      cannot start with "-" so prepend a zero in that case. */
+	   if (!c->prefix && *name == ':')
+	     {
+	       *name = '0';
+	       inet_ntop(AF_INET6, &addr->addr.addr6, name+1, ADDRSTRLEN);
+	     }
+	   
+	   /* V4-mapped have periods.... */
+	   for (p = name; *p; p++)
+	     if (*p == ':' || *p == '.')
+	       *p = '-';
+	   
+	 }
 
        strncat(name, ".", MAXDNAME);
        strncat(name, c->domain, MAXDNAME);
diff --git a/src/option.c b/src/option.c
index 6b26576..d358d99 100644
--- a/src/option.c
+++ b/src/option.c
@@ -2071,7 +2071,8 @@
 		  char *netpart;
 		  
 		  new->prefix = NULL;
-
+		  new->indexed = 0;
+		  
 		  unhide_metas(comma);
 		  if ((netpart = split_chr(comma, '/')))
 		    {
@@ -2208,8 +2209,14 @@
 		    }
 		  else
 		    {
+		      char *star;
 		      new->next = daemon->synth_domains;
 		      daemon->synth_domains = new;
+		      if ((star = strrchr(new->prefix, '*')) && *(star+1) == 0)
+			{
+			  *star = 0;
+			  new->indexed = 1;
+			}
 		    }
 		}
 	      else if (option == 's')