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')