mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-31 06:25:31 +00:00
libirs: handle scoped IPv6 addresses in /etc/resolv.conf
Commonly used network configuration tools write scoped IPv6 nameserver addresses to /etc/resolv.conf. libirs only handles these when it is compiled with -DIRS_HAVE_SIN6_SCOPE_ID, which is not the default, and only handles numeric scopes, which is not what network configuration tools typically use. This causes dig to be practically unable to handle scoped IPv6 nameserver addresses in /etc/resolv.conf. Fix the problem by: - not requiring a custom compile-time flag to be set in order for scoped IPv6 addresses to be processed by getaddrinfo(), - parsing non-numeric scope identifiers using if_nametoindex(), - setting the sin6_scope_id field in struct sockaddr_in6 structures returned by getaddrinfo() even if the AI_CANONNAME flag is not set.
This commit is contained in:
@@ -181,6 +181,47 @@ static void _freeaddrinfo(struct addrinfo *ai);
|
||||
#define FOUND_IPV6 0x2
|
||||
#define FOUND_MAX 2
|
||||
|
||||
/*%
|
||||
* Try converting the scope identifier in 'src' to a network interface index.
|
||||
* Upon success, return true and store the resulting index in 'dst'. Upon
|
||||
* failure, return false.
|
||||
*/
|
||||
static bool
|
||||
parse_scopeid(const char *src, uint32_t *dst) {
|
||||
uint32_t scopeid = 0;
|
||||
|
||||
REQUIRE(src != NULL);
|
||||
REQUIRE(dst != NULL);
|
||||
|
||||
#ifdef HAVE_IF_NAMETOINDEX
|
||||
/*
|
||||
* Try using if_nametoindex() first if it is available. As it does not
|
||||
* handle numeric scopes, we do not simply return if it fails.
|
||||
*/
|
||||
scopeid = (uint32_t)if_nametoindex(src);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Fall back to numeric scope processing if if_nametoindex() either
|
||||
* fails or is unavailable.
|
||||
*/
|
||||
if (scopeid == 0) {
|
||||
char *endptr = NULL;
|
||||
scopeid = (uint32_t)strtoul(src, &endptr, 10);
|
||||
/*
|
||||
* The scope identifier must not be empty and no trailing
|
||||
* characters are allowed after it.
|
||||
*/
|
||||
if (src == endptr || endptr == NULL || *endptr != '\0') {
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
|
||||
*dst = scopeid;
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
#define ISC_AI_MASK (AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST)
|
||||
/*%
|
||||
* Get a list of IP addresses and port numbers for host hostname and
|
||||
@@ -365,39 +406,24 @@ getaddrinfo(const char *hostname, const char *servname,
|
||||
char abuf[sizeof(struct in6_addr)];
|
||||
char nbuf[NI_MAXHOST];
|
||||
int addrsize, addroff;
|
||||
#ifdef IRS_HAVE_SIN6_SCOPE_ID
|
||||
char *p, *ep;
|
||||
char ntmp[NI_MAXHOST];
|
||||
uint32_t scopeid;
|
||||
#endif
|
||||
uint32_t scopeid = 0;
|
||||
|
||||
#ifdef IRS_HAVE_SIN6_SCOPE_ID
|
||||
/*
|
||||
* Scope identifier portion.
|
||||
*/
|
||||
ntmp[0] = '\0';
|
||||
if (strchr(hostname, '%') != NULL) {
|
||||
char *p;
|
||||
strlcpy(ntmp, hostname, sizeof(ntmp));
|
||||
p = strchr(ntmp, '%');
|
||||
ep = NULL;
|
||||
|
||||
/*
|
||||
* Vendors may want to support non-numeric
|
||||
* scopeid around here.
|
||||
*/
|
||||
|
||||
if (p != NULL)
|
||||
scopeid = (uint32_t)strtoul(p + 1,
|
||||
&ep, 10);
|
||||
if (p != NULL && ep != NULL && ep[0] == '\0')
|
||||
if (p != NULL && parse_scopeid(p + 1, &scopeid)) {
|
||||
*p = '\0';
|
||||
else {
|
||||
} else {
|
||||
ntmp[0] = '\0';
|
||||
scopeid = 0;
|
||||
}
|
||||
} else
|
||||
scopeid = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (inet_pton(AF_INET, hostname, (struct in_addr *)abuf)
|
||||
== 1) {
|
||||
@@ -415,7 +441,6 @@ getaddrinfo(const char *hostname, const char *servname,
|
||||
addroff = offsetof(struct sockaddr_in, sin_addr);
|
||||
family = AF_INET;
|
||||
goto common;
|
||||
#ifdef IRS_HAVE_SIN6_SCOPE_ID
|
||||
} else if (ntmp[0] != '\0' &&
|
||||
inet_pton(AF_INET6, ntmp, abuf) == 1) {
|
||||
if (family && family != AF_INET6)
|
||||
@@ -424,7 +449,6 @@ getaddrinfo(const char *hostname, const char *servname,
|
||||
addroff = offsetof(struct sockaddr_in6, sin6_addr);
|
||||
family = AF_INET6;
|
||||
goto common;
|
||||
#endif
|
||||
} else if (inet_pton(AF_INET6, hostname, abuf) == 1) {
|
||||
if (family != 0 && family != AF_INET6)
|
||||
return (EAI_NONAME);
|
||||
@@ -444,12 +468,10 @@ getaddrinfo(const char *hostname, const char *servname,
|
||||
ai->ai_socktype = socktype;
|
||||
SIN(ai->ai_addr)->sin_port = port;
|
||||
memmove((char *)ai->ai_addr + addroff, abuf, addrsize);
|
||||
if (ai->ai_family == AF_INET6) {
|
||||
SIN6(ai->ai_addr)->sin6_scope_id = scopeid;
|
||||
}
|
||||
if ((flags & AI_CANONNAME) != 0) {
|
||||
#ifdef IRS_HAVE_SIN6_SCOPE_ID
|
||||
if (ai->ai_family == AF_INET6)
|
||||
SIN6(ai->ai_addr)->sin6_scope_id =
|
||||
scopeid;
|
||||
#endif
|
||||
if (getnameinfo(ai->ai_addr,
|
||||
(socklen_t)ai->ai_addrlen,
|
||||
nbuf, sizeof(nbuf), NULL, 0,
|
||||
|
@@ -64,6 +64,9 @@ ATF_TC_BODY(irs_resconf_load, tc) {
|
||||
}, {
|
||||
"testdata/nameserver-v6.conf", ISC_R_SUCCESS,
|
||||
NULL, ISC_R_SUCCESS
|
||||
}, {
|
||||
"testdata/nameserver-v6-scoped.conf", ISC_R_SUCCESS,
|
||||
NULL, ISC_R_SUCCESS
|
||||
}, {
|
||||
"testdata/options-debug.conf", ISC_R_SUCCESS,
|
||||
NULL, ISC_R_SUCCESS
|
||||
|
10
lib/irs/tests/testdata/nameserver-v6-scoped.conf
vendored
Normal file
10
lib/irs/tests/testdata/nameserver-v6-scoped.conf
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#
|
||||
# See the COPYRIGHT file distributed with this work for additional
|
||||
# information regarding copyright ownership.
|
||||
|
||||
nameserver fe80::1%1
|
@@ -3298,6 +3298,7 @@
|
||||
./lib/irs/tests/resconf_test.c C 2016,2018
|
||||
./lib/irs/tests/testdata/domain.conf CONF-SH 2016,2018
|
||||
./lib/irs/tests/testdata/nameserver-v4.conf CONF-SH 2016,2018
|
||||
./lib/irs/tests/testdata/nameserver-v6-scoped.conf CONF-SH 2018
|
||||
./lib/irs/tests/testdata/nameserver-v6.conf CONF-SH 2016,2018
|
||||
./lib/irs/tests/testdata/options-bad-ndots.conf CONF-SH 2018
|
||||
./lib/irs/tests/testdata/options-debug.conf CONF-SH 2016,2018
|
||||
|
Reference in New Issue
Block a user