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
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
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,
.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 '::'
but DNS labels may not start with '-' so in this case if no prefix is
configured a zero is added in front of the label. ::1 becomes 0--1.
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
192.168.0.56 and a reverse query vice versa. The same applies to IPv6;
the representation doesn't use the :: compression feature or
the special representation of V4 mapped IPv6 addresses as these
can generate illegal domain names, so all domains are of the form
internal-1000-0000-0000-0000-0000-0000-0000-0008.example.com
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

View File

@@ -115,26 +115,15 @@ int is_name_synthetic(int flags, char *name, union all_addr *addrp)
*p = 0;
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 == '-')
/* swap . or : for - */
for (p = tail; *p; p++)
if (*p == '-')
{
if (prot == AF_INET)
*p = '.';
}
else
{
/* swap . or : for - */
for (p = tail; *p; p++)
if (*p == '-')
{
if (prot == AF_INET)
*p = '.';
else
*p = ':';
}
}
else
*p = ':';
}
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);
@@ -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)))
{
char *p;
*name = 0;
if (c->indexed)
{
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
{
if (c->prefix)
strncpy(name, c->prefix, MAXDNAME - ADDRSTRLEN);
inet_ntop(AF_INET6, &addr->addr6, name + strlen(name), ADDRSTRLEN);
int i;
char frag[6];
/* 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->prefix)
strncpy(name, c->prefix, MAXDNAME);
for (i = 0; i < 16; i += 2)
{
*name = '0';
inet_ntop(AF_INET6, &addr->addr6, name+1, ADDRSTRLEN);
sprintf(frag, "%s%02x%02x", i == 0 ? "" : "-", addr->addr6.s6_addr[i], addr->addr6.s6_addr[i+1]);
strncat(name, frag, MAXDNAME);
}
/* V4-mapped have periods.... */
for (p = name; *p; p++)
if (*p == ':' || *p == '.')
*p = '-';
}
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')
{
/* 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)) ||
strlen(new->prefix) > MAXLABEL - INET_ADDRSTRLEN)
strlen(new->prefix) > (MAXLABEL - 39))
ret_err_free(_("bad prefix"), new);
}
else if (strcmp(arg, "local") != 0)