Move bind9_getaddresses() to isc_sockaddr_fromtext()

More convivial surroundings for this function.
This commit is contained in:
Tony Finch
2022-12-16 13:46:04 +00:00
committed by Tony Finch
parent 94f2da42e0
commit a44877bed3
10 changed files with 179 additions and 238 deletions
+5 -7
View File
@@ -81,8 +81,6 @@
#include <irs/resconf.h>
#include <bind9/getaddresses.h>
#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;
+2 -4
View File
@@ -95,8 +95,6 @@
#endif /* HAVE_GSSAPI */
#include <bind9/getaddresses.h>
#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,
+1 -3
View File
@@ -50,8 +50,6 @@
#include <isccfg/namedconf.h>
#include <bind9/getaddresses.h>
#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;
}
+1 -3
View File
@@ -54,8 +54,6 @@
#include <dns/types.h>
#include <dns/view.h>
#include <bind9/getaddresses.h>
#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));
+2 -4
View File
@@ -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) \
-164
View File
@@ -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 <inttypes.h>
#include <stdbool.h>
#include <string.h>
#include <isc/net.h>
#include <isc/netaddr.h>
#include <isc/netdb.h>
#include <isc/netscope.h>
#include <isc/result.h>
#include <isc/sockaddr.h>
#include <isc/string.h>
#include <isc/util.h>
#include <bind9/getaddresses.h>
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);
}
}
-52
View File
@@ -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 <isc/lang.h>
#include <isc/net.h>
#include <isc/types.h>
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
+28
View File
@@ -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
+139
View File
@@ -18,11 +18,15 @@
#include <isc/buffer.h>
#include <isc/hash.h>
#include <isc/net.h>
#include <isc/netaddr.h>
#include <isc/netdb.h>
#include <isc/netscope.h>
#include <isc/print.h>
#include <isc/region.h>
#include <isc/sockaddr.h>
#include <isc/string.h>
#include <isc/types.h>
#include <isc/util.h>
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);
}
}
+1 -1
View File
@@ -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 */