From a44877bed3a5f35d539fad14469d7ebc29ff9ac5 Mon Sep 17 00:00:00 2001 From: Tony Finch Date: Fri, 16 Dec 2022 10:19:16 +0000 Subject: [PATCH] Move bind9_getaddresses() to isc_sockaddr_fromtext() More convivial surroundings for this function. --- bin/dig/dighost.c | 12 +- bin/nsupdate/nsupdate.c | 6 +- bin/rndc/rndc.c | 4 +- bin/tools/mdig.c | 4 +- lib/bind9/Makefile.am | 6 +- lib/bind9/getaddresses.c | 164 ------------------------- lib/bind9/include/bind9/getaddresses.h | 52 -------- lib/isc/include/isc/sockaddr.h | 28 +++++ lib/isc/sockaddr.c | 139 +++++++++++++++++++++ lib/isccfg/parser.c | 2 +- 10 files changed, 179 insertions(+), 238 deletions(-) delete mode 100644 lib/bind9/getaddresses.c delete mode 100644 lib/bind9/include/bind9/getaddresses.h diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c index b85142e6b4..dae443fd02 100644 --- a/bin/dig/dighost.c +++ b/bin/dig/dighost.c @@ -81,8 +81,6 @@ #include -#include - #include "dighost.h" #define systemlocale(l) (void)setlocale(l, "") @@ -538,8 +536,8 @@ set_nameserver(char *opt) { } isc_loopmgr_blocking(loopmgr); - result = bind9_getaddresses(opt, 0, sockaddrs, DIG_MAX_ADDRESSES, - &count); + result = isc_sockaddr_fromtext(opt, 0, sockaddrs, DIG_MAX_ADDRESSES, + &count); isc_loopmgr_nonblocking(loopmgr); if (result != ISC_R_SUCCESS) { fatal("couldn't get address for '%s': %s", opt, @@ -4533,7 +4531,7 @@ get_address(char *host, in_port_t myport, isc_sockaddr_t *sockaddr) { isc_result_t result; isc_loopmgr_blocking(loopmgr); - result = bind9_getaddresses(host, myport, sockaddr, 1, &count); + result = isc_sockaddr_fromtext(host, myport, sockaddr, 1, &count); isc_loopmgr_nonblocking(loopmgr); if (result != ISC_R_SUCCESS) { return (result); @@ -4554,8 +4552,8 @@ getaddresses(dig_lookup_t *lookup, const char *host, isc_result_t *resultp) { char tmp[ISC_NETADDR_FORMATSIZE]; isc_loopmgr_blocking(loopmgr); - result = bind9_getaddresses(host, 0, sockaddrs, DIG_MAX_ADDRESSES, - &count); + result = isc_sockaddr_fromtext(host, 0, sockaddrs, DIG_MAX_ADDRESSES, + &count); isc_loopmgr_nonblocking(loopmgr); if (resultp != NULL) { *resultp = result; diff --git a/bin/nsupdate/nsupdate.c b/bin/nsupdate/nsupdate.c index de98154ef0..b4769d1b86 100644 --- a/bin/nsupdate/nsupdate.c +++ b/bin/nsupdate/nsupdate.c @@ -95,8 +95,6 @@ #endif /* HAVE_GSSAPI */ -#include - #include "../dig/readline.h" #define MAXCMD (128 * 1024) @@ -108,7 +106,7 @@ #define DNSDEFAULTPORT 53 -/* Number of addresses to request from bind9_getaddresses() */ +/* Number of addresses to request from isc_sockaddr_fromtext() */ #define MAX_SERVERADDRS 4 static uint16_t dnsport = DNSDEFAULTPORT; @@ -1017,7 +1015,7 @@ get_addresses(char *host, in_port_t port, isc_sockaddr_t *sockaddr, isc_result_t result; isc_loopmgr_blocking(loopmgr); - result = bind9_getaddresses(host, port, sockaddr, naddrs, &count); + result = isc_sockaddr_fromtext(host, port, sockaddr, naddrs, &count); isc_loopmgr_nonblocking(loopmgr); if (result != ISC_R_SUCCESS) { error("couldn't get address for '%s': %s", host, diff --git a/bin/rndc/rndc.c b/bin/rndc/rndc.c index 5612845753..aabfadb58c 100644 --- a/bin/rndc/rndc.c +++ b/bin/rndc/rndc.c @@ -50,8 +50,6 @@ #include -#include - #include "util.h" #define SERVERADDRS 10 @@ -282,7 +280,7 @@ get_addresses(const char *host, in_port_t port) { } } else { count = SERVERADDRS - nserveraddrs; - result = bind9_getaddresses( + result = isc_sockaddr_fromtext( host, port, &serveraddrs[nserveraddrs], count, &found); nserveraddrs += found; } diff --git a/bin/tools/mdig.c b/bin/tools/mdig.c index b71e009fa5..919b0f0c3f 100644 --- a/bin/tools/mdig.c +++ b/bin/tools/mdig.c @@ -54,8 +54,6 @@ #include #include -#include - #define CHECK(str, x) \ { \ if ((x) != ISC_R_SUCCESS) { \ @@ -2138,7 +2136,7 @@ main(int argc, char *argv[]) { } ns = 0; - result = bind9_getaddresses(server, port, &dstaddr, 1, &ns); + result = isc_sockaddr_fromtext(server, port, &dstaddr, 1, &ns); if (result != ISC_R_SUCCESS) { fatal("couldn't get address for '%s': %s", server, isc_result_totext(result)); diff --git a/lib/bind9/Makefile.am b/lib/bind9/Makefile.am index 7ec5bdd3bc..5f1ea1e658 100644 --- a/lib/bind9/Makefile.am +++ b/lib/bind9/Makefile.am @@ -4,13 +4,11 @@ lib_LTLIBRARIES = libbind9.la libbind9_ladir = $(includedir)/bind9 libbind9_la_HEADERS = \ - include/bind9/check.h \ - include/bind9/getaddresses.h + include/bind9/check.h libbind9_la_SOURCES = \ $(libbind9_la_HEADERS) \ - check.c \ - getaddresses.c + check.c libbind9_la_CPPFLAGS = \ $(AM_CPPFLAGS) \ diff --git a/lib/bind9/getaddresses.c b/lib/bind9/getaddresses.c deleted file mode 100644 index 5fa77704fe..0000000000 --- a/lib/bind9/getaddresses.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (C) Internet Systems Consortium, Inc. ("ISC") - * - * SPDX-License-Identifier: MPL-2.0 - * - * 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 https://mozilla.org/MPL/2.0/. - * - * See the COPYRIGHT file distributed with this work for additional - * information regarding copyright ownership. - */ - -/*! \file */ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -isc_result_t -bind9_getaddresses(const char *hostname, in_port_t port, isc_sockaddr_t *addrs, - int addrsize, int *addrcount) { - struct in_addr in4; - struct in6_addr in6; - bool have_ipv4, have_ipv6; - int i; - - struct addrinfo *ai = NULL, *tmpai, hints; - int result; - - REQUIRE(hostname != NULL); - REQUIRE(addrs != NULL); - REQUIRE(addrcount != NULL); - REQUIRE(addrsize > 0); - - have_ipv4 = (isc_net_probeipv4() == ISC_R_SUCCESS); - have_ipv6 = (isc_net_probeipv6() == ISC_R_SUCCESS); - - /* - * Try IPv4, then IPv6. In order to handle the extended format - * for IPv6 scoped addresses (address%scope_ID), we'll use a local - * working buffer of 128 bytes. The length is an ad-hoc value, but - * should be enough for this purpose; the buffer can contain a string - * of at least 80 bytes for scope_ID in addition to any IPv6 numeric - * addresses (up to 46 bytes), the delimiter character and the - * terminating NULL character. - */ - if (inet_pton(AF_INET, hostname, &in4) == 1) { - if (have_ipv4) { - isc_sockaddr_fromin(&addrs[0], &in4, port); - } else { - isc_sockaddr_v6fromin(&addrs[0], &in4, port); - } - *addrcount = 1; - return (ISC_R_SUCCESS); - } else if (strlen(hostname) <= 127U) { - char tmpbuf[128], *d; - uint32_t zone = 0; - - strlcpy(tmpbuf, hostname, sizeof(tmpbuf)); - d = strchr(tmpbuf, '%'); - if (d != NULL) { - *d = '\0'; - } - - if (inet_pton(AF_INET6, tmpbuf, &in6) == 1) { - isc_netaddr_t na; - - if (!have_ipv6) { - return (ISC_R_FAMILYNOSUPPORT); - } - - if (d != NULL) { - isc_result_t iresult; - - iresult = isc_netscope_pton(AF_INET6, d + 1, - &in6, &zone); - - if (iresult != ISC_R_SUCCESS) { - return (iresult); - } - } - - isc_netaddr_fromin6(&na, &in6); - isc_netaddr_setzone(&na, zone); - isc_sockaddr_fromnetaddr( - &addrs[0], (const isc_netaddr_t *)&na, port); - - *addrcount = 1; - return (ISC_R_SUCCESS); - } - } - memset(&hints, 0, sizeof(hints)); - if (!have_ipv6) { - hints.ai_family = PF_INET; - } else if (!have_ipv4) { - hints.ai_family = PF_INET6; - } else { - hints.ai_family = PF_UNSPEC; -#ifdef AI_ADDRCONFIG - hints.ai_flags = AI_ADDRCONFIG; -#endif /* ifdef AI_ADDRCONFIG */ - } - hints.ai_socktype = SOCK_STREAM; -#ifdef AI_ADDRCONFIG -again: -#endif /* ifdef AI_ADDRCONFIG */ - result = getaddrinfo(hostname, NULL, &hints, &ai); - switch (result) { - case 0: - break; - case EAI_NONAME: -#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME) - case EAI_NODATA: -#endif /* if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME) */ - return (ISC_R_NOTFOUND); -#ifdef AI_ADDRCONFIG - case EAI_BADFLAGS: - if ((hints.ai_flags & AI_ADDRCONFIG) != 0) { - hints.ai_flags &= ~AI_ADDRCONFIG; - goto again; - } -#endif /* ifdef AI_ADDRCONFIG */ - FALLTHROUGH; - default: - return (ISC_R_FAILURE); - } - for (tmpai = ai, i = 0; tmpai != NULL && i < addrsize; - tmpai = tmpai->ai_next) - { - if (tmpai->ai_family != AF_INET && tmpai->ai_family != AF_INET6) - { - continue; - } - if (tmpai->ai_family == AF_INET) { - struct sockaddr_in *sin; - sin = (struct sockaddr_in *)tmpai->ai_addr; - isc_sockaddr_fromin(&addrs[i], &sin->sin_addr, port); - } else { - struct sockaddr_in6 *sin6; - sin6 = (struct sockaddr_in6 *)tmpai->ai_addr; - isc_sockaddr_fromin6(&addrs[i], &sin6->sin6_addr, port); - } - i++; - } - freeaddrinfo(ai); - *addrcount = i; - if (*addrcount == 0) { - return (ISC_R_NOTFOUND); - } else { - return (ISC_R_SUCCESS); - } -} diff --git a/lib/bind9/include/bind9/getaddresses.h b/lib/bind9/include/bind9/getaddresses.h deleted file mode 100644 index b9a431b581..0000000000 --- a/lib/bind9/include/bind9/getaddresses.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) Internet Systems Consortium, Inc. ("ISC") - * - * SPDX-License-Identifier: MPL-2.0 - * - * 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 https://mozilla.org/MPL/2.0/. - * - * See the COPYRIGHT file distributed with this work for additional - * information regarding copyright ownership. - */ - -#pragma once - -/*! \file bind9/getaddresses.h */ - -#include -#include -#include - -ISC_LANG_BEGINDECLS - -isc_result_t -bind9_getaddresses(const char *hostname, in_port_t port, isc_sockaddr_t *addrs, - int addrsize, int *addrcount); -/*%< - * Use the system resolver to get the addresses associated with a hostname. - * If successful, the number of addresses found is returned in 'addrcount'. - * If a hostname lookup is performed and addresses of an unknown family is - * seen, it is ignored. If more than 'addrsize' addresses are seen, the - * first 'addrsize' are returned and the remainder silently truncated. - * - * This routine may block. If called by a program using the isc_loopmgr - * framework, it should be surrounded by isc_loopmgr_blocking() and - * isc_loopmgr_nonblocking(). - * - * Requires: - *\li 'hostname' is not NULL. - *\li 'addrs' is not NULL. - *\li 'addrsize' > 0 - *\li 'addrcount' is not NULL. - * - * - * Returns: - *\li #ISC_R_SUCCESS - *\li #ISC_R_NOTFOUND - *\li #ISC_R_FAMILYNOSUPPORT - 'hostname' is an IPv6 address, and IPv6 is - * not supported. - */ - -ISC_LANG_ENDDECLS diff --git a/lib/isc/include/isc/sockaddr.h b/lib/isc/include/isc/sockaddr.h index 9f3986b01f..8c5227098a 100644 --- a/lib/isc/include/isc/sockaddr.h +++ b/lib/isc/include/isc/sockaddr.h @@ -245,4 +245,32 @@ isc_sockaddr_fromsockaddr(isc_sockaddr_t *isa, const struct sockaddr *sa); * Minimum size of array to pass to isc_sockaddr_format(). */ +isc_result_t +isc_sockaddr_fromtext(const char *hostname, in_port_t port, + isc_sockaddr_t *addrs, int addrsize, int *addrcount); +/*%< + * Use the system resolver to get the addresses associated with a hostname. + * If successful, the number of addresses found is returned in 'addrcount'. + * If a hostname lookup is performed and addresses of an unknown family is + * seen, it is ignored. If more than 'addrsize' addresses are seen, the + * first 'addrsize' are returned and the remainder silently truncated. + * + * This routine may block. If called by a program using the isc_loopmgr + * framework, it should be surrounded by isc_loopmgr_blocking() and + * isc_loopmgr_nonblocking(). + * + * Requires: + *\li 'hostname' is not NULL. + *\li 'addrs' is not NULL. + *\li 'addrsize' > 0 + *\li 'addrcount' is not NULL. + * + * + * Returns: + *\li #ISC_R_SUCCESS + *\li #ISC_R_NOTFOUND + *\li #ISC_R_FAMILYNOSUPPORT - 'hostname' is an IPv6 address, and IPv6 is + * not supported. + */ + ISC_LANG_ENDDECLS diff --git a/lib/isc/sockaddr.c b/lib/isc/sockaddr.c index 038e3ec7c4..ddc76fa15e 100644 --- a/lib/isc/sockaddr.c +++ b/lib/isc/sockaddr.c @@ -18,11 +18,15 @@ #include #include +#include #include +#include +#include #include #include #include #include +#include #include bool @@ -497,3 +501,138 @@ isc_sockaddr_fromsockaddr(isc_sockaddr_t *isa, const struct sockaddr *sa) { return (ISC_R_SUCCESS); } + +isc_result_t +isc_sockaddr_fromtext(const char *hostname, in_port_t port, + isc_sockaddr_t *addrs, int addrsize, int *addrcount) { + struct in_addr in4; + struct in6_addr in6; + bool have_ipv4, have_ipv6; + int i; + + struct addrinfo *ai = NULL, *tmpai, hints; + int result; + + REQUIRE(hostname != NULL); + REQUIRE(addrs != NULL); + REQUIRE(addrcount != NULL); + REQUIRE(addrsize > 0); + + have_ipv4 = (isc_net_probeipv4() == ISC_R_SUCCESS); + have_ipv6 = (isc_net_probeipv6() == ISC_R_SUCCESS); + + /* + * Try IPv4, then IPv6. In order to handle the extended format + * for IPv6 scoped addresses (address%scope_ID), we'll use a local + * working buffer of 128 bytes. The length is an ad-hoc value, but + * should be enough for this purpose; the buffer can contain a string + * of at least 80 bytes for scope_ID in addition to any IPv6 numeric + * addresses (up to 46 bytes), the delimiter character and the + * terminating NULL character. + */ + if (inet_pton(AF_INET, hostname, &in4) == 1) { + if (have_ipv4) { + isc_sockaddr_fromin(&addrs[0], &in4, port); + } else { + isc_sockaddr_v6fromin(&addrs[0], &in4, port); + } + *addrcount = 1; + return (ISC_R_SUCCESS); + } else if (strlen(hostname) <= 127U) { + char tmpbuf[128], *d; + uint32_t zone = 0; + + strlcpy(tmpbuf, hostname, sizeof(tmpbuf)); + d = strchr(tmpbuf, '%'); + if (d != NULL) { + *d = '\0'; + } + + if (inet_pton(AF_INET6, tmpbuf, &in6) == 1) { + isc_netaddr_t na; + + if (!have_ipv6) { + return (ISC_R_FAMILYNOSUPPORT); + } + + if (d != NULL) { + isc_result_t iresult; + + iresult = isc_netscope_pton(AF_INET6, d + 1, + &in6, &zone); + + if (iresult != ISC_R_SUCCESS) { + return (iresult); + } + } + + isc_netaddr_fromin6(&na, &in6); + isc_netaddr_setzone(&na, zone); + isc_sockaddr_fromnetaddr( + &addrs[0], (const isc_netaddr_t *)&na, port); + + *addrcount = 1; + return (ISC_R_SUCCESS); + } + } + memset(&hints, 0, sizeof(hints)); + if (!have_ipv6) { + hints.ai_family = PF_INET; + } else if (!have_ipv4) { + hints.ai_family = PF_INET6; + } else { + hints.ai_family = PF_UNSPEC; +#ifdef AI_ADDRCONFIG + hints.ai_flags = AI_ADDRCONFIG; +#endif /* ifdef AI_ADDRCONFIG */ + } + hints.ai_socktype = SOCK_STREAM; +#ifdef AI_ADDRCONFIG +again: +#endif /* ifdef AI_ADDRCONFIG */ + result = getaddrinfo(hostname, NULL, &hints, &ai); + switch (result) { + case 0: + break; + case EAI_NONAME: +#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME) + case EAI_NODATA: +#endif /* if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME) */ + return (ISC_R_NOTFOUND); +#ifdef AI_ADDRCONFIG + case EAI_BADFLAGS: + if ((hints.ai_flags & AI_ADDRCONFIG) != 0) { + hints.ai_flags &= ~AI_ADDRCONFIG; + goto again; + } +#endif /* ifdef AI_ADDRCONFIG */ + FALLTHROUGH; + default: + return (ISC_R_FAILURE); + } + for (tmpai = ai, i = 0; tmpai != NULL && i < addrsize; + tmpai = tmpai->ai_next) + { + if (tmpai->ai_family != AF_INET && tmpai->ai_family != AF_INET6) + { + continue; + } + if (tmpai->ai_family == AF_INET) { + struct sockaddr_in *sin; + sin = (struct sockaddr_in *)tmpai->ai_addr; + isc_sockaddr_fromin(&addrs[i], &sin->sin_addr, port); + } else { + struct sockaddr_in6 *sin6; + sin6 = (struct sockaddr_in6 *)tmpai->ai_addr; + isc_sockaddr_fromin6(&addrs[i], &sin6->sin6_addr, port); + } + i++; + } + freeaddrinfo(ai); + *addrcount = i; + if (*addrcount == 0) { + return (ISC_R_NOTFOUND); + } else { + return (ISC_R_SUCCESS); + } +} diff --git a/lib/isccfg/parser.c b/lib/isccfg/parser.c index 325396e4de..b04878e0fb 100644 --- a/lib/isccfg/parser.c +++ b/lib/isccfg/parser.c @@ -2894,7 +2894,7 @@ token_addr(cfg_parser_t *pctx, unsigned int flags, isc_netaddr_t *na) { } } if ((flags & CFG_ADDR_V6OK) != 0 && strlen(s) <= 127U) { - char buf[128]; /* see lib/bind9/getaddresses.c */ + char buf[128]; /* see isc_sockaddr_fromtext() */ char *d; /* zone delimiter */ uint32_t zone = 0; /* scope zone ID */