Modify the behaviour of --synth-domain for IPv6.

When deriving a domain name from an IPv6 address, an address
such as 1234:: would become 1234--.example.com, which is
not legal in IDNA2008. Stop using the :: compression method,
so 1234:: becomes
1234-0000-0000-0000-0000-0000-0000-0000.example.com
This commit is contained in:
Simon Kelley
2024-11-27 23:12:41 +00:00
parent 41d2ae3203
commit a8088e331a
4 changed files with 33 additions and 43 deletions

View File

@@ -44,6 +44,13 @@ version 2.91
returns truncated, do likewise. If upstream is OK, but the returns truncated, do likewise. If upstream is OK, but the
answer is too big for downstream, truncate the answer. answer is too big for downstream, truncate the answer.
Modify the behaviour of --synth-domain for IPv6.
When deriving a domain name from an IPv6 address, an address
such as 1234:: would become 1234--.example.com, which is
not legal in IDNA2008. Stop using the :: compression method,
so 1234:: becomes
1234-0000-0000-0000-0000-0000-0000-0000.example.com
version 2.90 version 2.90
Fix reversion in --rev-server introduced in 2.88 which Fix reversion in --rev-server introduced in 2.88 which

View File

@@ -769,12 +769,11 @@ results in the name internal-0.thekelleys.org.uk. returning 192.168.0.50, intern
Second, Second,
.B --synth-domain=thekelleys.org.uk,192.168.0.0/24,internal- (no *) .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 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, 192.168.0.56 and a reverse query vice versa. The same applies to IPv6;
but IPv6 addresses may start with '::' the representation doesn't use the :: compression feature or
but DNS labels may not start with '-' so in this case if no prefix is the special representation of V4 mapped IPv6 addresses as these
configured a zero is added in front of the label. ::1 becomes 0--1. can generate illegal domain names, so all domains are of the form
internal-1000-0000-0000-0000-0000-0000-0000-0008.example.com
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 The address range can be of the form
<start address>,<end address> or <ip address>/<prefix-length> in both forms of the option. For IPv6 the start and end addresses <start address>,<end address> or <ip address>/<prefix-length> in both forms of the option. For IPv6 the start and end addresses

View File

@@ -115,26 +115,15 @@ int is_name_synthetic(int flags, char *name, union all_addr *addrp)
*p = 0; *p = 0;
if (prot == AF_INET6 && strstr(tail, "--ffff-") == tail) /* swap . or : for - */
{ for (p = tail; *p; p++)
/* special hack for v4-mapped. */ if (*p == '-')
memcpy(tail, "::ffff:", 7); {
for (p = tail + 7; *p; p++) if (prot == AF_INET)
if (*p == '-')
*p = '.'; *p = '.';
} else
else *p = ':';
{ }
/* swap . or : for - */
for (p = tail; *p; p++)
if (*p == '-')
{
if (prot == AF_INET)
*p = '.';
else
*p = ':';
}
}
if (hostname_isequal(c->domain, p+1) && inet_pton(prot, tail, &addr)) if (hostname_isequal(c->domain, p+1) && inet_pton(prot, tail, &addr))
found = (prot == AF_INET) ? match_domain(addr.addr4, c) : match_domain6(&addr.addr6, c); found = (prot == AF_INET) ? match_domain(addr.addr4, c) : match_domain6(&addr.addr6, c);
@@ -194,9 +183,8 @@ int is_rev_synth(int flag, union all_addr *addr, char *name)
if ((flag & F_IPV6) && (c = search_domain6(&addr->addr6, daemon->synth_domains))) if ((flag & F_IPV6) && (c = search_domain6(&addr->addr6, daemon->synth_domains)))
{ {
char *p;
*name = 0; *name = 0;
if (c->indexed) if (c->indexed)
{ {
u64 index = addr6part(&addr->addr6) - addr6part(&c->start6); u64 index = addr6part(&addr->addr6) - addr6part(&c->start6);
@@ -204,24 +192,17 @@ int is_rev_synth(int flag, union all_addr *addr, char *name)
} }
else else
{ {
int i;
char frag[6];
if (c->prefix) if (c->prefix)
strncpy(name, c->prefix, MAXDNAME - ADDRSTRLEN); strncpy(name, c->prefix, MAXDNAME);
inet_ntop(AF_INET6, &addr->addr6, name + strlen(name), ADDRSTRLEN); for (i = 0; i < 16; i += 2)
/* 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'; sprintf(frag, "%s%02x%02x", i == 0 ? "" : "-", addr->addr6.s6_addr[i], addr->addr6.s6_addr[i+1]);
inet_ntop(AF_INET6, &addr->addr6, name+1, ADDRSTRLEN); strncat(name, frag, MAXDNAME);
} }
/* V4-mapped have periods.... */
for (p = name; *p; p++)
if (*p == ':' || *p == '.')
*p = '-';
} }
strncat(name, ".", MAXDNAME); strncat(name, ".", MAXDNAME);

View File

@@ -2636,8 +2636,11 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
{ {
if (option != 's') if (option != 's')
{ {
/* IPv6 address is longest and represented as
xxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxx
which is 39 chars */
if (!(new->prefix = canonicalise_opt(arg)) || if (!(new->prefix = canonicalise_opt(arg)) ||
strlen(new->prefix) > MAXLABEL - INET_ADDRSTRLEN) strlen(new->prefix) > (MAXLABEL - 39))
ret_err_free(_("bad prefix"), new); ret_err_free(_("bad prefix"), new);
} }
else if (strcmp(arg, "local") != 0) else if (strcmp(arg, "local") != 0)