Implement DoT support for nsupdate
Implement DNS-over-TLS support for nsupdate. Use DiG's DoT implementation as a model for the newly added features.
This commit is contained in:
@@ -46,6 +46,7 @@
|
||||
#include <isc/stdio.h>
|
||||
#include <isc/string.h>
|
||||
#include <isc/task.h>
|
||||
#include <isc/tls.h>
|
||||
#include <isc/types.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
@@ -68,6 +69,7 @@
|
||||
#include <dns/rdatatype.h>
|
||||
#include <dns/request.h>
|
||||
#include <dns/tkey.h>
|
||||
#include <dns/transport.h>
|
||||
#include <dns/tsig.h>
|
||||
|
||||
#include <dst/dst.h>
|
||||
@@ -120,6 +122,7 @@ static bool memdebugging = false;
|
||||
static bool have_ipv4 = false;
|
||||
static bool have_ipv6 = false;
|
||||
static bool is_dst_up = false;
|
||||
static bool use_tls = false;
|
||||
static bool usevc = false;
|
||||
static bool usegsstsig = false;
|
||||
static bool use_win2k_gsstsig = false;
|
||||
@@ -147,6 +150,14 @@ static dns_tsigkey_t *tsigkey = NULL;
|
||||
static dst_key_t *sig0key = NULL;
|
||||
static isc_sockaddr_t *servers = NULL;
|
||||
static isc_sockaddr_t *primary_servers = NULL;
|
||||
static dns_transport_list_t *transport_list = NULL;
|
||||
static dns_transport_t *transport = NULL;
|
||||
static isc_tlsctx_cache_t *tls_ctx_cache = NULL;
|
||||
static char *tls_hostname = NULL;
|
||||
static char *tls_client_key_file = NULL;
|
||||
static char *tls_client_cert_file = NULL;
|
||||
static char *tls_ca_file = NULL;
|
||||
static bool tls_always_verify_remote = true;
|
||||
static bool default_servers = true;
|
||||
static int ns_inuse = 0;
|
||||
static int primary_inuse = 0;
|
||||
@@ -793,6 +804,19 @@ set_source_ports(dns_dispatchmgr_t *manager) {
|
||||
isc_portset_destroy(gmctx, &v6portset);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
create_name(const char *str, char *namedata, size_t len, dns_name_t *name) {
|
||||
isc_buffer_t namesrc, namebuf;
|
||||
|
||||
dns_name_init(name, NULL);
|
||||
isc_buffer_constinit(&namesrc, str, strlen(str));
|
||||
isc_buffer_add(&namesrc, strlen(str));
|
||||
isc_buffer_init(&namebuf, namedata, len);
|
||||
|
||||
return (dns_name_fromtext(name, &namesrc, dns_rootname,
|
||||
DNS_NAME_DOWNCASE, &namebuf));
|
||||
}
|
||||
|
||||
static void
|
||||
setup_system(void) {
|
||||
isc_result_t result;
|
||||
@@ -800,6 +824,8 @@ setup_system(void) {
|
||||
isc_sockaddrlist_t *nslist;
|
||||
isc_logconfig_t *logconfig = NULL;
|
||||
irs_resconf_t *resconf = NULL;
|
||||
dns_name_t tlsname;
|
||||
char namedata[DNS_NAME_FORMATSIZE + 1];
|
||||
|
||||
ddebug("setup_system()");
|
||||
|
||||
@@ -936,6 +962,31 @@ setup_system(void) {
|
||||
&dispatchv4);
|
||||
check_result(result, "dns_dispatch_createudp (v4)");
|
||||
}
|
||||
transport_list = dns_transport_list_new(gmctx);
|
||||
|
||||
tls_ctx_cache = isc_tlsctx_cache_new(gmctx);
|
||||
|
||||
if (tls_client_key_file == NULL) {
|
||||
result = create_name("tls-non-auth-client", namedata,
|
||||
sizeof(namedata), &tlsname);
|
||||
check_result(result, "create_name (tls-non-auth-client)");
|
||||
transport = dns_transport_new(&tlsname, DNS_TRANSPORT_TLS,
|
||||
transport_list);
|
||||
dns_transport_set_tlsname(transport, "tls-non-auth-client");
|
||||
} else {
|
||||
result = create_name("tls-auth-client", namedata,
|
||||
sizeof(namedata), &tlsname);
|
||||
check_result(result, "create_name (tls-auth-client)");
|
||||
transport = dns_transport_new(&tlsname, DNS_TRANSPORT_TLS,
|
||||
transport_list);
|
||||
dns_transport_set_tlsname(transport, "tls-auth-client");
|
||||
dns_transport_set_keyfile(transport, tls_client_key_file);
|
||||
dns_transport_set_certfile(transport, tls_client_cert_file);
|
||||
}
|
||||
dns_transport_set_cafile(transport, tls_ca_file);
|
||||
dns_transport_set_remote_hostname(transport, tls_hostname);
|
||||
dns_transport_set_always_verify_remote(transport,
|
||||
tls_always_verify_remote);
|
||||
|
||||
result = dns_requestmgr_create(gmctx, taskmgr, dispatchmgr, dispatchv4,
|
||||
dispatchv6, &requestmgr);
|
||||
@@ -972,7 +1023,7 @@ get_addresses(char *host, in_port_t port, isc_sockaddr_t *sockaddr,
|
||||
return (count);
|
||||
}
|
||||
|
||||
#define PARSE_ARGS_FMT "46C:dDghilL:Mok:p:Pr:R:t:Tu:vVy:"
|
||||
#define PARSE_ARGS_FMT "46A:C:dDE:ghH:iK:lL:MoOk:p:Pr:R:St:Tu:vVy:"
|
||||
|
||||
static void
|
||||
pre_parse_args(int argc, char **argv) {
|
||||
@@ -1015,7 +1066,9 @@ pre_parse_args(int argc, char **argv) {
|
||||
fprintf(stderr, "usage: nsupdate [-CdDi] [-L level] "
|
||||
"[-l] [-g | -o | -y keyname:secret "
|
||||
"| -k keyfile] [-p port] "
|
||||
"[-v] [-V] [-P] [-T] [-4 | -6] "
|
||||
"[ -S [-K tlskeyfile] [-E tlscertfile] "
|
||||
"[-A tlscafile] [-H tlshostname] "
|
||||
"[-O] ] [-v] [-V] [-P] [-T] [-4 | -6] "
|
||||
"[filename]\n");
|
||||
exit(1);
|
||||
|
||||
@@ -1087,6 +1140,11 @@ parse_args(int argc, char **argv) {
|
||||
fatal("can't find IPv6 networking");
|
||||
}
|
||||
break;
|
||||
case 'A':
|
||||
use_tls = true;
|
||||
usevc = true;
|
||||
tls_ca_file = isc_commandline_argument;
|
||||
break;
|
||||
case 'C':
|
||||
resolvconf = isc_commandline_argument;
|
||||
break;
|
||||
@@ -1097,12 +1155,27 @@ parse_args(int argc, char **argv) {
|
||||
debugging = true;
|
||||
ddebugging = true;
|
||||
break;
|
||||
case 'E':
|
||||
use_tls = true;
|
||||
usevc = true;
|
||||
tls_client_cert_file = isc_commandline_argument;
|
||||
break;
|
||||
case 'H':
|
||||
use_tls = true;
|
||||
usevc = true;
|
||||
tls_hostname = isc_commandline_argument;
|
||||
break;
|
||||
case 'M':
|
||||
break;
|
||||
case 'i':
|
||||
force_interactive = true;
|
||||
interactive = true;
|
||||
break;
|
||||
case 'K':
|
||||
use_tls = true;
|
||||
usevc = true;
|
||||
tls_client_key_file = isc_commandline_argument;
|
||||
break;
|
||||
case 'l':
|
||||
local_only = true;
|
||||
break;
|
||||
@@ -1135,6 +1208,11 @@ parse_args(int argc, char **argv) {
|
||||
usegsstsig = true;
|
||||
use_win2k_gsstsig = true;
|
||||
break;
|
||||
case 'O':
|
||||
use_tls = true;
|
||||
usevc = true;
|
||||
tls_always_verify_remote = false;
|
||||
break;
|
||||
case 'p':
|
||||
result = isc_parse_uint16(&dnsport,
|
||||
isc_commandline_argument, 10);
|
||||
@@ -1146,6 +1224,10 @@ parse_args(int argc, char **argv) {
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'S':
|
||||
use_tls = true;
|
||||
usevc = true;
|
||||
break;
|
||||
case 't':
|
||||
result = isc_parse_uint32(&timeout,
|
||||
isc_commandline_argument, 10);
|
||||
@@ -1211,6 +1293,24 @@ parse_args(int argc, char **argv) {
|
||||
}
|
||||
#endif /* HAVE_GSSAPI */
|
||||
|
||||
if (use_tls) {
|
||||
if ((tls_client_key_file == NULL) !=
|
||||
(tls_client_cert_file == NULL)) {
|
||||
fprintf(stderr,
|
||||
"%s: cannot specify the -K option without"
|
||||
"the -E option, and vice versa.\n",
|
||||
argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
if (tls_ca_file != NULL && tls_always_verify_remote == false) {
|
||||
fprintf(stderr,
|
||||
"%s: cannot specify the -A option in "
|
||||
"conjuction with the -O option.\n",
|
||||
argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (argv[isc_commandline_index] != NULL) {
|
||||
if (strcmp(argv[isc_commandline_index], "-") == 0) {
|
||||
input = stdin;
|
||||
@@ -2448,8 +2548,10 @@ static void
|
||||
send_update(dns_name_t *zone, isc_sockaddr_t *primary) {
|
||||
isc_result_t result;
|
||||
dns_request_t *request = NULL;
|
||||
unsigned int options = DNS_REQUESTOPT_CASE;
|
||||
isc_sockaddr_t *srcaddr;
|
||||
unsigned int options = DNS_REQUESTOPT_CASE;
|
||||
dns_transport_t *req_transport = NULL;
|
||||
isc_tlsctx_cache_t *req_tls_ctx_cache = NULL;
|
||||
|
||||
ddebug("send_update()");
|
||||
|
||||
@@ -2457,7 +2559,12 @@ send_update(dns_name_t *zone, isc_sockaddr_t *primary) {
|
||||
|
||||
if (usevc) {
|
||||
options |= DNS_REQUESTOPT_TCP;
|
||||
if (use_tls) {
|
||||
req_transport = transport;
|
||||
req_tls_ctx_cache = tls_ctx_cache;
|
||||
}
|
||||
}
|
||||
|
||||
if (tsigkey == NULL && sig0key != NULL) {
|
||||
result = dns_message_setsig0key(updatemsg, sig0key);
|
||||
check_result(result, "dns_message_setsig0key");
|
||||
@@ -2480,10 +2587,10 @@ send_update(dns_name_t *zone, isc_sockaddr_t *primary) {
|
||||
updatemsg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
|
||||
}
|
||||
|
||||
result = dns_request_create(requestmgr, updatemsg, srcaddr, primary,
|
||||
NULL, NULL, -1, options, tsigkey, timeout,
|
||||
udp_timeout, udp_retries, global_task,
|
||||
update_completed, NULL, &request);
|
||||
result = dns_request_create(
|
||||
requestmgr, updatemsg, srcaddr, primary, req_transport,
|
||||
req_tls_ctx_cache, -1, options, tsigkey, timeout, udp_timeout,
|
||||
udp_retries, global_task, update_completed, NULL, &request);
|
||||
check_result(result, "dns_request_create");
|
||||
|
||||
if (debugging) {
|
||||
@@ -2574,6 +2681,10 @@ recvsoa(isc_task_t *task, isc_event_t *event) {
|
||||
result = dns_request_getresponse(request, rcvmsg,
|
||||
DNS_MESSAGEPARSE_PRESERVEORDER);
|
||||
if (result == DNS_R_TSIGERRORSET && servers != NULL) {
|
||||
unsigned int options = DNS_REQUESTOPT_CASE;
|
||||
dns_transport_t *req_transport = NULL;
|
||||
isc_tlsctx_cache_t *req_tls_ctx_cache = NULL;
|
||||
|
||||
dns_message_detach(&rcvmsg);
|
||||
ddebug("Destroying request [%p]", request);
|
||||
dns_request_destroy(&request);
|
||||
@@ -2583,6 +2694,14 @@ recvsoa(isc_task_t *task, isc_event_t *event) {
|
||||
dns_message_renderreset(soaquery);
|
||||
ddebug("retrying soa request without TSIG");
|
||||
|
||||
if (usevc) {
|
||||
options |= DNS_REQUESTOPT_TCP;
|
||||
if (!default_servers && use_tls) {
|
||||
req_transport = transport;
|
||||
req_tls_ctx_cache = tls_ctx_cache;
|
||||
}
|
||||
}
|
||||
|
||||
if (isc_sockaddr_pf(addr) == AF_INET6) {
|
||||
srcaddr = localaddr6;
|
||||
} else {
|
||||
@@ -2590,9 +2709,10 @@ recvsoa(isc_task_t *task, isc_event_t *event) {
|
||||
}
|
||||
|
||||
result = dns_request_create(
|
||||
requestmgr, soaquery, srcaddr, addr, NULL, NULL, -1, 0,
|
||||
NULL, FIND_TIMEOUT * 20, FIND_TIMEOUT, 3, global_task,
|
||||
recvsoa, reqinfo, &request);
|
||||
requestmgr, soaquery, srcaddr, addr, req_transport,
|
||||
req_tls_ctx_cache, -1, options, NULL, FIND_TIMEOUT * 20,
|
||||
FIND_TIMEOUT, 3, global_task, recvsoa, reqinfo,
|
||||
&request);
|
||||
check_result(result, "dns_request_create");
|
||||
requests++;
|
||||
return;
|
||||
@@ -2797,6 +2917,17 @@ sendrequest(isc_sockaddr_t *destaddr, dns_message_t *msg,
|
||||
isc_result_t result;
|
||||
nsu_requestinfo_t *reqinfo;
|
||||
isc_sockaddr_t *srcaddr;
|
||||
unsigned int options = DNS_REQUESTOPT_CASE;
|
||||
dns_transport_t *req_transport = NULL;
|
||||
isc_tlsctx_cache_t *req_tls_ctx_cache = NULL;
|
||||
|
||||
if (usevc) {
|
||||
options |= DNS_REQUESTOPT_TCP;
|
||||
if (!default_servers && use_tls) {
|
||||
req_transport = transport;
|
||||
req_tls_ctx_cache = tls_ctx_cache;
|
||||
}
|
||||
}
|
||||
|
||||
reqinfo = isc_mem_get(gmctx, sizeof(nsu_requestinfo_t));
|
||||
reqinfo->msg = msg;
|
||||
@@ -2808,10 +2939,11 @@ sendrequest(isc_sockaddr_t *destaddr, dns_message_t *msg,
|
||||
srcaddr = localaddr4;
|
||||
}
|
||||
|
||||
result = dns_request_create(
|
||||
requestmgr, msg, srcaddr, destaddr, NULL, NULL, -1, 0,
|
||||
default_servers ? NULL : tsigkey, FIND_TIMEOUT * 20,
|
||||
FIND_TIMEOUT, 3, global_task, recvsoa, reqinfo, request);
|
||||
result = dns_request_create(requestmgr, msg, srcaddr, destaddr,
|
||||
req_transport, req_tls_ctx_cache, -1,
|
||||
options, default_servers ? NULL : tsigkey,
|
||||
FIND_TIMEOUT * 20, FIND_TIMEOUT, 3,
|
||||
global_task, recvsoa, reqinfo, request);
|
||||
check_result(result, "dns_request_create");
|
||||
requests++;
|
||||
}
|
||||
@@ -2991,8 +3123,15 @@ send_gssrequest(isc_sockaddr_t *destaddr, dns_message_t *msg,
|
||||
dns_request_t **request, gss_ctx_id_t context) {
|
||||
isc_result_t result;
|
||||
nsu_gssinfo_t *reqinfo;
|
||||
unsigned int options = 0;
|
||||
isc_sockaddr_t *srcaddr;
|
||||
unsigned int options = DNS_REQUESTOPT_CASE | DNS_REQUESTOPT_TCP;
|
||||
dns_transport_t *req_transport = NULL;
|
||||
isc_tlsctx_cache_t *req_tls_ctx_cache = NULL;
|
||||
|
||||
if (!default_servers && use_tls) {
|
||||
req_transport = transport;
|
||||
req_tls_ctx_cache = tls_ctx_cache;
|
||||
}
|
||||
|
||||
debug("send_gssrequest");
|
||||
REQUIRE(destaddr != NULL);
|
||||
@@ -3002,18 +3141,16 @@ send_gssrequest(isc_sockaddr_t *destaddr, dns_message_t *msg,
|
||||
reqinfo->addr = destaddr;
|
||||
reqinfo->context = context;
|
||||
|
||||
options |= DNS_REQUESTOPT_TCP;
|
||||
|
||||
if (isc_sockaddr_pf(destaddr) == AF_INET6) {
|
||||
srcaddr = localaddr6;
|
||||
} else {
|
||||
srcaddr = localaddr4;
|
||||
}
|
||||
|
||||
result = dns_request_create(requestmgr, msg, srcaddr, destaddr, NULL,
|
||||
NULL, -1, options, tsigkey,
|
||||
FIND_TIMEOUT * 20, FIND_TIMEOUT, 3,
|
||||
global_task, recvgss, reqinfo, request);
|
||||
result = dns_request_create(
|
||||
requestmgr, msg, srcaddr, destaddr, req_transport,
|
||||
req_tls_ctx_cache, -1, options, tsigkey, FIND_TIMEOUT * 20,
|
||||
FIND_TIMEOUT, 3, global_task, recvgss, reqinfo, request);
|
||||
check_result(result, "dns_request_create");
|
||||
if (debugging) {
|
||||
show_message(stdout, msg, "Outgoing update query:");
|
||||
@@ -3271,6 +3408,14 @@ static void
|
||||
cleanup(void) {
|
||||
ddebug("cleanup()");
|
||||
|
||||
if (tls_ctx_cache != NULL) {
|
||||
isc_tlsctx_cache_detach(&tls_ctx_cache);
|
||||
}
|
||||
|
||||
if (transport_list != NULL) {
|
||||
dns_transport_list_detach(&transport_list);
|
||||
}
|
||||
|
||||
LOCK(&answer_lock);
|
||||
if (answer != NULL) {
|
||||
dns_message_detach(&answer);
|
||||
|
||||
@@ -62,9 +62,13 @@ dns_transport_get_tls_versions(const dns_transport_t *transport);
|
||||
bool
|
||||
dns_transport_get_prefer_server_ciphers(const dns_transport_t *transport,
|
||||
bool *preferp);
|
||||
bool
|
||||
dns_transport_get_always_verify_remote(dns_transport_t *transport);
|
||||
/*%<
|
||||
* Getter functions: return the type, cert file, key file, CA file,
|
||||
* hostname, HTTP endpoint, or HTTP mode (GET or POST) for 'transport'.
|
||||
* hostname, HTTP endpoint, HTTP mode (GET or POST), ciphers, TLS name,
|
||||
* TLS version, server ciphers preference mode, and always enabling
|
||||
* authentication mode for 'transport'.
|
||||
*
|
||||
* dns_transport_get_prefer_server_ciphers() returns 'true' is value
|
||||
* was set, 'false' otherwise. The actual value is returned via
|
||||
@@ -80,6 +84,13 @@ dns_transport_get_tlsctx(dns_transport_t *transport, const isc_sockaddr_t *peer,
|
||||
* Get the transport's TLS Context and the TLS Client Session Cache associated
|
||||
* with it.
|
||||
*
|
||||
* When neither the TLS hostname, nor the TLS certificates authorities (CA)
|
||||
* file are set for the 'transport', then Opportunistic TLS (no authentication
|
||||
* of the remote peer) will be used, unless the 'always_verify_remote' mode is
|
||||
* enabled on the 'transport', in which case the remote peer will be
|
||||
* authenticated by its IP address using the system's default certificates
|
||||
* authorities store.
|
||||
*
|
||||
* Requires:
|
||||
*\li 'transport' is a valid, 'DNS_TRANSPORT_TLS' type transport.
|
||||
*\li 'peer' is not NULL.
|
||||
@@ -113,9 +124,14 @@ dns_transport_set_tls_versions(dns_transport_t *transport,
|
||||
void
|
||||
dns_transport_set_prefer_server_ciphers(dns_transport_t *transport,
|
||||
const bool prefer);
|
||||
void
|
||||
dns_transport_set_always_verify_remote(dns_transport_t *transport,
|
||||
const bool always_verify_remote);
|
||||
/*%<
|
||||
* Setter functions: set the type, cert file, key file, CA file,
|
||||
* hostname, HTTP endpoint, or HTTP mode (GET or POST) for 'transport'.
|
||||
* hostname, HTTP endpoint, HTTP mode (GET or POST), ciphers, TLS name,
|
||||
* TLS version, server ciphers preference mode, and always enabling
|
||||
* authentication mode for 'transport'.
|
||||
*
|
||||
* Requires:
|
||||
*\li 'transport' is valid.
|
||||
|
||||
@@ -56,6 +56,7 @@ struct dns_transport {
|
||||
char *ciphers;
|
||||
uint32_t protocol_versions;
|
||||
ternary_t prefer_server_ciphers;
|
||||
bool always_verify_remote;
|
||||
} tls;
|
||||
struct {
|
||||
char *endpoint;
|
||||
@@ -334,6 +335,25 @@ dns_transport_get_prefer_server_ciphers(const dns_transport_t *transport,
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
dns_transport_set_always_verify_remote(dns_transport_t *transport,
|
||||
const bool always_verify_remote) {
|
||||
REQUIRE(VALID_TRANSPORT(transport));
|
||||
REQUIRE(transport->type == DNS_TRANSPORT_TLS ||
|
||||
transport->type == DNS_TRANSPORT_HTTP);
|
||||
|
||||
transport->tls.always_verify_remote = always_verify_remote;
|
||||
}
|
||||
|
||||
bool
|
||||
dns_transport_get_always_verify_remote(dns_transport_t *transport) {
|
||||
REQUIRE(VALID_TRANSPORT(transport));
|
||||
REQUIRE(transport->type == DNS_TRANSPORT_TLS ||
|
||||
transport->type == DNS_TRANSPORT_HTTP);
|
||||
|
||||
return transport->tls.always_verify_remote;
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_transport_get_tlsctx(dns_transport_t *transport, const isc_sockaddr_t *peer,
|
||||
isc_tlsctx_cache_t *tlsctx_cache, isc_mem_t *mctx,
|
||||
@@ -378,6 +398,8 @@ dns_transport_get_tlsctx(dns_transport_t *transport, const isc_sockaddr_t *peer,
|
||||
const char *ca_file = dns_transport_get_cafile(transport);
|
||||
const char *cert_file = dns_transport_get_certfile(transport);
|
||||
const char *key_file = dns_transport_get_keyfile(transport);
|
||||
const bool always_verify_remote =
|
||||
dns_transport_get_always_verify_remote(transport);
|
||||
char peer_addr_str[INET6_ADDRSTRLEN] = { 0 };
|
||||
isc_netaddr_t peer_netaddr = { 0 };
|
||||
bool hostname_ignore_subject;
|
||||
@@ -406,7 +428,8 @@ dns_transport_get_tlsctx(dns_transport_t *transport, const isc_sockaddr_t *peer,
|
||||
prefer_server_ciphers);
|
||||
}
|
||||
|
||||
if (hostname != NULL || ca_file != NULL) {
|
||||
if (always_verify_remote || hostname != NULL || ca_file != NULL)
|
||||
{
|
||||
/*
|
||||
* The situation when 'found_store != NULL' while
|
||||
* 'found == NULL' may occur as there is a one-to-many
|
||||
@@ -433,12 +456,9 @@ dns_transport_get_tlsctx(dns_transport_t *transport, const isc_sockaddr_t *peer,
|
||||
INSIST(store != NULL);
|
||||
if (hostname == NULL) {
|
||||
/*
|
||||
* If CA bundle file is specified, but
|
||||
* hostname is not, then use the peer
|
||||
* IP address for validation, just like
|
||||
* dig does.
|
||||
* If hostname is not specified, then use the
|
||||
* peer IP address for validation.
|
||||
*/
|
||||
INSIST(ca_file != NULL);
|
||||
isc_netaddr_fromsockaddr(&peer_netaddr, peer);
|
||||
isc_netaddr_format(&peer_netaddr, peer_addr_str,
|
||||
sizeof(peer_addr_str));
|
||||
|
||||
Reference in New Issue
Block a user