From 0950b932ca05fd8f8626c006eb3059aa021d5ae7 Mon Sep 17 00:00:00 2001 From: David Venhoek Date: Wed, 7 Jan 2026 10:08:10 +0100 Subject: [PATCH 01/11] dns: Introduce separate type for a DNS name lookup result. This type allows carrying of an additional name that is needed when using the results from an SRV lookup. --- client.c | 34 ++++++++++++++++++---------------- cmdparse.c | 4 +++- conf.c | 6 +++--- nameserv.c | 23 ++++++++++++----------- nameserv.h | 10 ++++++++-- nameserv_async.c | 4 ++-- nameserv_async.h | 2 +- ntp_sources.c | 10 +++++----- nts_ke_client.c | 10 +++++----- privops.c | 4 ++-- privops.h | 4 +++- test/unit/ntp_sources.c | 12 ++++++++---- 12 files changed, 70 insertions(+), 53 deletions(-) diff --git a/client.c b/client.c index 66f23b70..bb1312b4 100644 --- a/client.c +++ b/client.c @@ -157,7 +157,7 @@ get_addresses(const char *hostnames, int port) struct Address *addr; ARR_Instance addrs; char *hostname, *s1, *s2; - IPAddr ip_addrs[DNS_MAX_ADDRESSES]; + DNS_AddressLookupResult looked_up_addrs[DNS_MAX_ADDRESSES]; int i; addrs = ARR_CreateInstance(sizeof (*addr)); @@ -175,17 +175,17 @@ get_addresses(const char *hostnames, int port) addr->type = SCK_ADDR_UNIX; addr->addr.path = Strdup(hostname); } else { - if (DNS_Name2IPAddress(hostname, ip_addrs, DNS_MAX_ADDRESSES) != DNS_Success) { + if (DNS_Name2IPAddress(hostname, looked_up_addrs, DNS_MAX_ADDRESSES) != DNS_Success) { DEBUG_LOG("Could not get IP address for %s", hostname); continue; } - for (i = 0; i < DNS_MAX_ADDRESSES && ip_addrs[i].family != IPADDR_UNSPEC; i++) { + for (i = 0; i < DNS_MAX_ADDRESSES && looked_up_addrs[i].ip.family != IPADDR_UNSPEC; i++) { addr = ARR_GetNewElement(addrs); addr->type = SCK_ADDR_IP; - addr->addr.ip.ip_addr = ip_addrs[i]; + addr->addr.ip.ip_addr = looked_up_addrs[i].ip; addr->addr.ip.port = port; - DEBUG_LOG("Resolved %s to %s", hostname, UTI_IPToString(&ip_addrs[i])); + DEBUG_LOG("Resolved %s to %s", hostname, UTI_IPToString(&looked_up_addrs[i].ip)); } } } @@ -449,11 +449,15 @@ bits_to_mask(int bits, int family, IPAddr *mask) static int parse_source_address(char *word, IPAddr *address) { + DNS_AddressLookupResult lookup; + if (UTI_StringToIdIP(word, address)) return 1; - if (DNS_Name2IPAddress(word, address, 1) == DNS_Success) + if (DNS_Name2IPAddress(word, &lookup, 1) == DNS_Success) { + *address = lookup.ip; return 1; + } return 0; } @@ -944,10 +948,10 @@ process_cmd_allowdeny(CMD_Request *msg, char *line, int cmd, int allcmd) static int process_cmd_accheck(CMD_Request *msg, char *line) { - IPAddr ip; + DNS_AddressLookupResult lookup; msg->command = htons(REQ_ACCHECK); - if (DNS_Name2IPAddress(line, &ip, 1) == DNS_Success) { - UTI_IPHostToNetwork(&ip, &msg->data.ac_check.ip); + if (DNS_Name2IPAddress(line, &lookup, 1) == DNS_Success) { + UTI_IPHostToNetwork(&lookup.ip, &msg->data.ac_check.ip); return 1; } else { LOG(LOGS_ERR, "Could not read address"); @@ -960,10 +964,10 @@ process_cmd_accheck(CMD_Request *msg, char *line) static int process_cmd_cmdaccheck(CMD_Request *msg, char *line) { - IPAddr ip; + DNS_AddressLookupResult lookup; msg->command = htons(REQ_CMDACCHECK); - if (DNS_Name2IPAddress(line, &ip, 1) == DNS_Success) { - UTI_IPHostToNetwork(&ip, &msg->data.ac_check.ip); + if (DNS_Name2IPAddress(line, &lookup, 1) == DNS_Success) { + UTI_IPHostToNetwork(&lookup.ip, &msg->data.ac_check.ip); return 1; } else { LOG(LOGS_ERR, "Could not read address"); @@ -1025,7 +1029,7 @@ process_cmd_add_source(CMD_Request *msg, char *line) { CPS_NTP_Source data; CPS_Status status; - IPAddr ip_addr; + DNS_AddressLookupResult lookup; int result = 0, type; const char *opt_name, *word; @@ -1051,7 +1055,7 @@ process_cmd_add_source(CMD_Request *msg, char *line) /* Verify that the address is resolvable (chronyc and chronyd are assumed to be running on the same host) */ if (strlen(data.name) >= sizeof (msg->data.ntp_source.name) || - DNS_Name2IPAddress(data.name, &ip_addr, 1) != DNS_Success) { + DNS_Name2IPAddress(data.name, &lookup, 1) != DNS_Success) { LOG(LOGS_ERR, "Invalid host/IP address"); break; } @@ -3730,5 +3734,3 @@ main(int argc, char **argv) return !ret; } - - diff --git a/cmdparse.c b/cmdparse.c index 29c65b31..0e24b7b9 100644 --- a/cmdparse.c +++ b/cmdparse.c @@ -231,6 +231,7 @@ CPS_ParseAllowDeny(char *line, int *all, IPAddr *ip, int *subnet_bits) char *p, *net, *slash; uint32_t a, b, c; int bits, len, n; + DNS_AddressLookupResult lookup_result; p = CPS_SplitWord(line); @@ -294,7 +295,8 @@ CPS_ParseAllowDeny(char *line, int *all, IPAddr *ip, int *subnet_bits) } /* The last possibility is a hostname */ - if (bits < 0 && DNS_Name2IPAddress(net, ip, 1) == DNS_Success) { + if (bits < 0 && DNS_Name2IPAddress(net, &lookup_result, 1) == DNS_Success) { + *ip = lookup_result.ip; *subnet_bits = ip->family == IPADDR_INET6 ? 128 : 32; return 1; } diff --git a/conf.c b/conf.c index 1f362d7f..17578587 100644 --- a/conf.c +++ b/conf.c @@ -1164,7 +1164,7 @@ static void parse_initstepslew(char *line) { char *p, *hostname; - IPAddr ip_addr; + DNS_AddressLookupResult addr; /* Ignore the line if chronyd was started with -R. */ if (restarted) { @@ -1183,8 +1183,8 @@ parse_initstepslew(char *line) hostname = p; p = CPS_SplitWord(p); if (*hostname) { - if (DNS_Name2IPAddress(hostname, &ip_addr, 1) == DNS_Success) { - ARR_AppendElement(init_sources, &ip_addr); + if (DNS_Name2IPAddress(hostname, &addr, 1) == DNS_Success) { + ARR_AppendElement(init_sources, &addr.ip); } else { LOG(LOGS_WARN, "Could not resolve address of initstepslew server %s", hostname); } diff --git a/nameserv.c b/nameserv.c index 9f7e648c..99609964 100644 --- a/nameserv.c +++ b/nameserv.c @@ -48,7 +48,7 @@ DNS_SetAddressFamily(int family) } DNS_Status -DNS_Name2IPAddress(const char *name, IPAddr *ip_addrs, int max_addrs) +DNS_Name2IPAddress(const char *name, DNS_AddressLookupResult *addrs, int max_addrs) { struct addrinfo hints, *res, *ai; int i, result; @@ -56,15 +56,17 @@ DNS_Name2IPAddress(const char *name, IPAddr *ip_addrs, int max_addrs) max_addrs = MIN(max_addrs, DNS_MAX_ADDRESSES); - for (i = 0; i < max_addrs; i++) - ip_addrs[i].family = IPADDR_UNSPEC; + for (i = 0; i < max_addrs; i++) { + addrs[i].ip.family = IPADDR_UNSPEC; + addrs[i].service_name[0] = 0; + } /* Avoid calling getaddrinfo() if the name is an IP address */ if (UTI_StringToIP(name, &ip)) { if (address_family != IPADDR_UNSPEC && ip.family != address_family) return DNS_Failure; if (max_addrs >= 1) - ip_addrs[0] = ip; + addrs[0].ip = ip; return DNS_Success; } @@ -99,8 +101,8 @@ DNS_Name2IPAddress(const char *name, IPAddr *ip_addrs, int max_addrs) case AF_INET: if (address_family != IPADDR_UNSPEC && address_family != IPADDR_INET4) continue; - ip_addrs[i].family = IPADDR_INET4; - ip_addrs[i].addr.in4 = ntohl(((struct sockaddr_in *)ai->ai_addr)->sin_addr.s_addr); + addrs[i].ip.family = IPADDR_INET4; + addrs[i].ip.addr.in4 = ntohl(((struct sockaddr_in *)ai->ai_addr)->sin_addr.s_addr); i++; break; #ifdef FEAT_IPV6 @@ -110,9 +112,9 @@ DNS_Name2IPAddress(const char *name, IPAddr *ip_addrs, int max_addrs) /* Don't return an address that would lose a scope ID */ if (((struct sockaddr_in6 *)ai->ai_addr)->sin6_scope_id != 0) continue; - ip_addrs[i].family = IPADDR_INET6; - memcpy(&ip_addrs[i].addr.in6, &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr.s6_addr, - sizeof (ip_addrs->addr.in6)); + addrs[i].ip.family = IPADDR_INET6; + memcpy(&addrs[i].ip.addr.in6, &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr.s6_addr, + sizeof (addrs->ip.addr.in6)); i++; break; #endif @@ -121,7 +123,7 @@ DNS_Name2IPAddress(const char *name, IPAddr *ip_addrs, int max_addrs) freeaddrinfo(res); - return !max_addrs || ip_addrs[0].family != IPADDR_UNSPEC ? DNS_Success : DNS_Failure; + return !max_addrs || addrs[0].ip.family != IPADDR_UNSPEC ? DNS_Success : DNS_Failure; } /* ================================================== */ @@ -163,4 +165,3 @@ DNS_Reload(void) } /* ================================================== */ - diff --git a/nameserv.h b/nameserv.h index dbef61a3..acd698d7 100644 --- a/nameserv.h +++ b/nameserv.h @@ -30,23 +30,29 @@ #include "addressing.h" +#define DNS_SERVICE_NAME_LEN 256 + typedef enum { DNS_Success, DNS_TryAgain, DNS_Failure } DNS_Status; +typedef struct { + IPAddr ip; + char service_name[DNS_SERVICE_NAME_LEN]; +} DNS_AddressLookupResult; + /* Resolve names only to selected address family */ extern void DNS_SetAddressFamily(int family); /* Maximum number of addresses returned by DNS_Name2IPAddress */ #define DNS_MAX_ADDRESSES 16 -extern DNS_Status DNS_Name2IPAddress(const char *name, IPAddr *ip_addrs, int max_addrs); +extern DNS_Status DNS_Name2IPAddress(const char *name, DNS_AddressLookupResult *addrs, int max_addrs); extern int DNS_IPAddress2Name(IPAddr *ip_addr, char *name, int len); extern void DNS_Reload(void); #endif /* GOT_NAMESERV_H */ - diff --git a/nameserv_async.c b/nameserv_async.c index 118443c6..f6aa7dd8 100644 --- a/nameserv_async.c +++ b/nameserv_async.c @@ -43,7 +43,7 @@ struct DNS_Async_Instance { const char *name; DNS_Status status; - IPAddr addresses[DNS_MAX_ADDRESSES]; + DNS_AddressLookupResult addresses[DNS_MAX_ADDRESSES]; DNS_NameResolveHandler handler; void *arg; @@ -88,7 +88,7 @@ end_resolving(int fd, int event, void *anything) close(inst->pipe[1]); for (i = 0; inst->status == DNS_Success && i < DNS_MAX_ADDRESSES && - inst->addresses[i].family != IPADDR_UNSPEC; i++) + inst->addresses[i].ip.family != IPADDR_UNSPEC; i++) ; (inst->handler)(inst->status, i, inst->addresses, inst->arg); diff --git a/nameserv_async.h b/nameserv_async.h index b8479e1d..00bd2451 100644 --- a/nameserv_async.h +++ b/nameserv_async.h @@ -31,7 +31,7 @@ #include "nameserv.h" /* Function type for callback to process the result */ -typedef void (*DNS_NameResolveHandler)(DNS_Status status, int n_addrs, IPAddr *ip_addrs, void *anything); +typedef void (*DNS_NameResolveHandler)(DNS_Status status, int n_addrs, DNS_AddressLookupResult *addrs, void *anything); /* Request resolving of a name to IP address. The handler will be called when the result is available. */ diff --git a/ntp_sources.c b/ntp_sources.c index 7bf08894..4f197589 100644 --- a/ntp_sources.c +++ b/ntp_sources.c @@ -533,7 +533,7 @@ replace_source_connectable(NTP_Remote_Address *old_addr, NTP_Remote_Address *new /* ================================================== */ static void -process_resolved_name(struct UnresolvedSource *us, IPAddr *ip_addrs, int n_addrs) +process_resolved_name(struct UnresolvedSource *us, DNS_AddressLookupResult *addrs, int n_addrs) { NTP_Remote_Address old_addr, new_addr; SourceRecord *record; @@ -547,7 +547,7 @@ process_resolved_name(struct UnresolvedSource *us, IPAddr *ip_addrs, int n_addrs for (i = 0; i < n_addrs; i++) { if (find_slot2(&us->address, &slot) == 2 && - UTI_CompareIPs(&get_record(slot)->resolved_addr, &ip_addrs[i], NULL) == 0) { + UTI_CompareIPs(&get_record(slot)->resolved_addr, &addrs[i].ip, NULL) == 0) { DEBUG_LOG("%s still fresh", UTI_IPToString(&us->address.ip_addr)); return; } @@ -558,7 +558,7 @@ process_resolved_name(struct UnresolvedSource *us, IPAddr *ip_addrs, int n_addrs UTI_GetRandomBytes(&first, sizeof (first)); for (i = 0; i < n_addrs; i++) { - new_addr.ip_addr = ip_addrs[((unsigned int)i + first) % n_addrs]; + new_addr.ip_addr = addrs[((unsigned int)i + first) % n_addrs].ip; DEBUG_LOG("(%d) %s", i + 1, UTI_IPToString(&new_addr.ip_addr)); @@ -616,7 +616,7 @@ resolve_sources_timeout(void *arg) /* ================================================== */ static void -name_resolve_handler(DNS_Status status, int n_addrs, IPAddr *ip_addrs, void *anything) +name_resolve_handler(DNS_Status status, int n_addrs, DNS_AddressLookupResult *addrs, void *anything) { struct UnresolvedSource *us, *next; @@ -631,7 +631,7 @@ name_resolve_handler(DNS_Status status, int n_addrs, IPAddr *ip_addrs, void *any case DNS_TryAgain: break; case DNS_Success: - process_resolved_name(us, ip_addrs, n_addrs); + process_resolved_name(us, addrs, n_addrs); break; case DNS_Failure: LOG(LOGS_WARN, "Invalid host %s", us->name); diff --git a/nts_ke_client.c b/nts_ke_client.c index e68d4dcf..563d2c56 100644 --- a/nts_ke_client.c +++ b/nts_ke_client.c @@ -67,7 +67,7 @@ static int default_credentials_refs = 0; /* ================================================== */ static void -name_resolve_handler(DNS_Status status, int n_addrs, IPAddr *ip_addrs, void *arg) +name_resolve_handler(DNS_Status status, int n_addrs, DNS_AddressLookupResult *addrs, void *arg) { NKC_Instance inst = arg; int i; @@ -86,13 +86,13 @@ name_resolve_handler(DNS_Status status, int n_addrs, IPAddr *ip_addrs, void *arg return; } - inst->ntp_address.ip_addr = ip_addrs[0]; + inst->ntp_address.ip_addr = addrs[0].ip; /* Prefer an address in the same family as the NTS-KE server */ for (i = 0; i < n_addrs; i++) { - DEBUG_LOG("%s resolved to %s", inst->server_name, UTI_IPToString(&ip_addrs[i])); - if (ip_addrs[i].family == inst->address.ip_addr.family) { - inst->ntp_address.ip_addr = ip_addrs[i]; + DEBUG_LOG("%s resolved to %s", inst->server_name, UTI_IPToString(&addrs[i].ip)); + if (addrs[i].ip.family == inst->address.ip_addr.family) { + inst->ntp_address.ip_addr = addrs[i].ip; break; } } diff --git a/privops.c b/privops.c index 3bc76d14..1c2dec88 100644 --- a/privops.c +++ b/privops.c @@ -106,7 +106,7 @@ typedef struct { #endif typedef struct { - IPAddr addresses[DNS_MAX_ADDRESSES]; + DNS_AddressLookupResult addresses[DNS_MAX_ADDRESSES]; } ResName2IPAddress; typedef struct { @@ -573,7 +573,7 @@ PRV_BindSocket(int sock, struct sockaddr *address, socklen_t address_len) #ifdef PRIVOPS_NAME2IPADDRESS int -PRV_Name2IPAddress(const char *name, IPAddr *ip_addrs, int max_addrs) +PRV_Name2IPAddress(const char *name, DNS_AddressLookupResult *ip_addrs, int max_addrs) { PrvRequest req; PrvResponse res; diff --git a/privops.h b/privops.h index 146580b7..48a35cab 100644 --- a/privops.h +++ b/privops.h @@ -28,6 +28,8 @@ #ifndef GOT_PRIVOPS_H #define GOT_PRIVOPS_H +#include "nameserv.h" + #ifdef PRIVOPS_ADJUSTTIME int PRV_AdjustTime(const struct timeval *delta, struct timeval *olddelta); #else @@ -53,7 +55,7 @@ int PRV_BindSocket(int sock, struct sockaddr *address, socklen_t address_len); #endif #ifdef PRIVOPS_NAME2IPADDRESS -int PRV_Name2IPAddress(const char *name, IPAddr *ip_addrs, int max_addrs); +int PRV_Name2IPAddress(const char *name, DNS_AddressLookupResult *ip_addrs, int max_addrs); #else #define PRV_Name2IPAddress DNS_Name2IPAddress #endif diff --git a/test/unit/ntp_sources.c b/test/unit/ntp_sources.c index be5d2ea8..22890154 100644 --- a/test/unit/ntp_sources.c +++ b/test/unit/ntp_sources.c @@ -53,7 +53,7 @@ static double get_mono_time(void); static void resolve_random_address(DNS_Status status, int rand_bits) { - IPAddr ip_addrs[DNS_MAX_ADDRESSES]; + DNS_AddressLookupResult addrs[DNS_MAX_ADDRESSES]; int i, n_addrs; TEST_CHECK(requested_name); @@ -61,13 +61,17 @@ resolve_random_address(DNS_Status status, int rand_bits) if (status == DNS_Success) { n_addrs = random() % DNS_MAX_ADDRESSES + 1; - for (i = 0; i < n_addrs; i++) - TST_GetRandomAddress(&ip_addrs[i], IPADDR_UNSPEC, rand_bits); + for (i = 0; i < n_addrs; i++) { + TST_GetRandomAddress(&addrs[i].ip, IPADDR_UNSPEC, rand_bits); + addrs[i].service_name[0] = 0; + } } else { n_addrs = 0; } - (resolve_handler)(status, n_addrs, ip_addrs, resolve_handler_arg); + DEBUG_LOG("Random resolving to %d addrs", n_addrs); + + (resolve_handler)(status, n_addrs, addrs, resolve_handler_arg); } static int From d8667cdf4bd2e6deb09dc5960b36890a0196cd66 Mon Sep 17 00:00:00 2001 From: David Venhoek Date: Wed, 7 Jan 2026 11:49:55 +0100 Subject: [PATCH 02/11] nts: Update nts server name from DNS lookup results. When using a server through an SRV record, the name used for the TLS certificate should match the service name, not the dns name where the SRV record was found. Therefore the name used for certificate validation needs to be updated when using the result of a DNS resolve that went through an SRV record. --- nameserv.h | 5 ++++ ntp_auth.c | 2 +- ntp_auth.h | 3 ++- ntp_core.c | 11 ++++---- ntp_core.h | 3 ++- ntp_sources.c | 51 ++++++++++++++++++++++---------------- ntp_sources.h | 2 +- nts_ntp_client.c | 29 ++++++++++++++-------- nts_ntp_client.h | 3 ++- test/unit/ntp_auth.c | 8 ++++-- test/unit/ntp_sources.c | 17 ++++++++----- test/unit/nts_ntp_client.c | 7 +++--- util.c | 17 +++++++++++++ util.h | 2 ++ 14 files changed, 108 insertions(+), 52 deletions(-) diff --git a/nameserv.h b/nameserv.h index acd698d7..69ef9262 100644 --- a/nameserv.h +++ b/nameserv.h @@ -43,6 +43,11 @@ typedef struct { char service_name[DNS_SERVICE_NAME_LEN]; } DNS_AddressLookupResult; +typedef struct { + DNS_AddressLookupResult ip; + uint16_t port; +} DNS_SockAddrLookupResult; + /* Resolve names only to selected address family */ extern void DNS_SetAddressFamily(int family); diff --git a/ntp_auth.c b/ntp_auth.c index 58374c57..014c8363 100644 --- a/ntp_auth.c +++ b/ntp_auth.c @@ -332,7 +332,7 @@ NAU_CheckResponseAuth(NAU_Instance instance, NTP_Packet *response, NTP_PacketInf /* ================================================== */ void -NAU_ChangeAddress(NAU_Instance instance, IPAddr *address) +NAU_ChangeAddress(NAU_Instance instance, DNS_AddressLookupResult *address) { switch (instance->mode) { case NTP_AUTH_NONE: diff --git a/ntp_auth.h b/ntp_auth.h index 0b8a8253..31b5ba6c 100644 --- a/ntp_auth.h +++ b/ntp_auth.h @@ -28,6 +28,7 @@ #define GOT_NTP_AUTH_H #include "addressing.h" +#include "nameserv.h" #include "ntp.h" #include "reports.h" @@ -73,7 +74,7 @@ extern int NAU_CheckResponseAuth(NAU_Instance instance, NTP_Packet *response, NTP_PacketInfo *info); /* Change an authentication-specific address (e.g. after replacing a source) */ -extern void NAU_ChangeAddress(NAU_Instance instance, IPAddr *address); +extern void NAU_ChangeAddress(NAU_Instance instance, DNS_AddressLookupResult *address); /* Save authentication-specific data to speed up the next start */ extern void NAU_DumpData(NAU_Instance instance); diff --git a/ntp_core.c b/ntp_core.c index 7395a638..9213a56e 100644 --- a/ntp_core.c +++ b/ntp_core.c @@ -823,14 +823,15 @@ NCR_ResetPoll(NCR_Instance instance) /* ================================================== */ void -NCR_ChangeRemoteAddress(NCR_Instance inst, NTP_Remote_Address *remote_addr, int ntp_only) +NCR_ChangeRemoteAddress(NCR_Instance inst, DNS_SockAddrLookupResult *remote_addr, int ntp_only) { NCR_ResetInstance(inst); if (!ntp_only) - NAU_ChangeAddress(inst->auth, &remote_addr->ip_addr); + NAU_ChangeAddress(inst->auth, &remote_addr->ip); - inst->remote_addr = *remote_addr; + inst->remote_addr.ip_addr = remote_addr->ip.ip; + inst->remote_addr.port = remote_addr->port; if (inst->mode == MODE_CLIENT) close_client_socket(inst); @@ -838,7 +839,7 @@ NCR_ChangeRemoteAddress(NCR_Instance inst, NTP_Remote_Address *remote_addr, int NIO_CloseServerSocket(inst->local_addr.sock_fd); inst->local_addr.ip_addr.family = IPADDR_UNSPEC; inst->local_addr.if_index = INVALID_IF_INDEX; - inst->local_addr.sock_fd = NIO_OpenServerSocket(remote_addr); + inst->local_addr.sock_fd = NIO_OpenServerSocket(&inst->remote_addr); } /* Reset the polling interval only if the source wasn't unreachable to @@ -848,7 +849,7 @@ NCR_ChangeRemoteAddress(NCR_Instance inst, NTP_Remote_Address *remote_addr, int NCR_ResetPoll(inst); /* Update the reference ID and reset the source/sourcestats instances */ - SRC_SetRefid(inst->source, UTI_IPToRefid(&remote_addr->ip_addr), + SRC_SetRefid(inst->source, UTI_IPToRefid(&remote_addr->ip.ip), &inst->remote_addr.ip_addr); SRC_ResetInstance(inst->source); diff --git a/ntp_core.h b/ntp_core.h index 67971ead..8b23f2f1 100644 --- a/ntp_core.h +++ b/ntp_core.h @@ -31,6 +31,7 @@ #include "addressing.h" #include "srcparams.h" +#include "nameserv.h" #include "ntp.h" #include "reports.h" @@ -71,7 +72,7 @@ extern void NCR_ResetInstance(NCR_Instance inst); extern void NCR_ResetPoll(NCR_Instance instance); /* Change the remote address of an instance */ -extern void NCR_ChangeRemoteAddress(NCR_Instance inst, NTP_Remote_Address *remote_addr, +extern void NCR_ChangeRemoteAddress(NCR_Instance inst, DNS_SockAddrLookupResult *remote_addr, int ntp_only); /* This routine is called when a new packet arrives off the network, diff --git a/ntp_sources.c b/ntp_sources.c index 4f197589..15f584a2 100644 --- a/ntp_sources.c +++ b/ntp_sources.c @@ -144,7 +144,7 @@ static ARR_Instance pools; /* Requested update of a source's address */ struct AddressUpdate { NTP_Remote_Address old_address; - NTP_Remote_Address new_address; + DNS_SockAddrLookupResult new_address; }; /* Update saved when record_lock is true */ @@ -431,21 +431,25 @@ add_source(NTP_Remote_Address *remote_addr, char *name, int family, NTP_Source_T /* ================================================== */ static NSR_Status -change_source_address(NTP_Remote_Address *old_addr, NTP_Remote_Address *new_addr, +change_source_address(NTP_Remote_Address *old_addr, DNS_SockAddrLookupResult *new_address, int replacement) { + NTP_Remote_Address new_addr; int slot1, slot2, found; SourceRecord *record; LOG_Severity severity; char *name; + new_addr.ip_addr = new_address->ip.ip; + new_addr.port = new_address->port; + found = find_slot2(old_addr, &slot1); if (found != 2) return NSR_NoSuchSource; /* Make sure there is no other source using the new address (with the same or different port), but allow a source to have its port changed */ - found = find_slot2(new_addr, &slot2); + found = find_slot2(&new_addr, &slot2); if (found == 2 || (found != 0 && slot1 != slot2)) return NSR_AlreadyInUse; @@ -453,14 +457,14 @@ change_source_address(NTP_Remote_Address *old_addr, NTP_Remote_Address *new_addr record_lock = 1; record = get_record(slot1); - NCR_ChangeRemoteAddress(record->data, new_addr, !replacement); + NCR_ChangeRemoteAddress(record->data, new_address, !replacement); if (replacement) - record->resolved_addr = new_addr->ip_addr; + record->resolved_addr = new_addr.ip_addr; BRIEF_ASSERT(record->remote_addr == NCR_GetRemoteAddress(record->data) && - UTI_CompareIPs(&record->remote_addr->ip_addr, &new_addr->ip_addr, NULL) == 0); + UTI_CompareIPs(&record->remote_addr->ip_addr, &new_addr.ip_addr, NULL) == 0); - if (!UTI_IsIPReal(&old_addr->ip_addr) && UTI_IsIPReal(&new_addr->ip_addr)) { + if (!UTI_IsIPReal(&old_addr->ip_addr) && UTI_IsIPReal(&new_addr.ip_addr)) { if (auto_start_sources) NCR_StartInstance(record->data); if (record->pool_id != INVALID_POOL) @@ -485,10 +489,10 @@ change_source_address(NTP_Remote_Address *old_addr, NTP_Remote_Address *new_addr LOG(severity, "Source %s %s %s (%s)", UTI_IPToString(&old_addr->ip_addr), replacement ? "replaced with" : "changed to", - UTI_IPToString(&new_addr->ip_addr), name); + UTI_IPToString(&new_addr.ip_addr), name); } else { LOG(severity, "Source %s (%s) changed port to %d", - UTI_IPToString(&new_addr->ip_addr), name, new_addr->port); + UTI_IPToString(&new_addr.ip_addr), name, new_addr.port); } return NSR_Success; @@ -507,7 +511,7 @@ handle_saved_address_update(void) /* This is expected to happen only if the old address is wrong */ LOG(LOGS_ERR, "Could not change %s to %s", UTI_IPSockAddrToString(&saved_address_update.old_address), - UTI_IPSockAddrToString(&saved_address_update.new_address)); + UTI_DNS_SockAddrLookupResultToString(&saved_address_update.new_address)); saved_address_update.old_address.ip_addr.family = IPADDR_UNSPEC; } @@ -515,10 +519,14 @@ handle_saved_address_update(void) /* ================================================== */ static int -replace_source_connectable(NTP_Remote_Address *old_addr, NTP_Remote_Address *new_addr) +replace_source_connectable(NTP_Remote_Address *old_addr, DNS_SockAddrLookupResult *new_addr) { - if (!NIO_IsServerConnectable(new_addr)) { - DEBUG_LOG("%s not connectable", UTI_IPToString(&new_addr->ip_addr)); + NTP_Remote_Address new_remote; + new_remote.ip_addr = new_addr->ip.ip; + new_remote.port = new_addr->port; + + if (!NIO_IsServerConnectable(&new_remote)) { + DEBUG_LOG("%s not connectable", UTI_IPToString(&new_addr->ip.ip)); return 0; } @@ -535,7 +543,8 @@ replace_source_connectable(NTP_Remote_Address *old_addr, NTP_Remote_Address *new static void process_resolved_name(struct UnresolvedSource *us, DNS_AddressLookupResult *addrs, int n_addrs) { - NTP_Remote_Address old_addr, new_addr; + NTP_Remote_Address old_addr; + DNS_SockAddrLookupResult new_addr; SourceRecord *record; unsigned short first = 0; int i, j, slot; @@ -558,12 +567,12 @@ process_resolved_name(struct UnresolvedSource *us, DNS_AddressLookupResult *addr UTI_GetRandomBytes(&first, sizeof (first)); for (i = 0; i < n_addrs; i++) { - new_addr.ip_addr = addrs[((unsigned int)i + first) % n_addrs].ip; + new_addr.ip = addrs[((unsigned int)i + first) % n_addrs]; - DEBUG_LOG("(%d) %s", i + 1, UTI_IPToString(&new_addr.ip_addr)); + DEBUG_LOG("(%d) %s", i + 1, UTI_IPToString(&new_addr.ip.ip)); /* Skip addresses not from the requested family */ - if (us->family != IPADDR_UNSPEC && us->family != new_addr.ip_addr.family) + if (us->family != IPADDR_UNSPEC && us->family != new_addr.ip.ip.family) continue; if (us->pool_id != INVALID_POOL) { @@ -1174,15 +1183,15 @@ NSR_RefreshAddresses(void) /* ================================================== */ NSR_Status -NSR_UpdateSourceNtpAddress(NTP_Remote_Address *old_addr, NTP_Remote_Address *new_addr) +NSR_UpdateSourceNtpAddress(NTP_Remote_Address *old_addr, DNS_SockAddrLookupResult *new_addr) { int slot; - if (!UTI_IsIPReal(&old_addr->ip_addr) || !UTI_IsIPReal(&new_addr->ip_addr)) + if (!UTI_IsIPReal(&old_addr->ip_addr) || !UTI_IsIPReal(&new_addr->ip.ip)) return NSR_InvalidAF; - if (UTI_CompareIPs(&old_addr->ip_addr, &new_addr->ip_addr, NULL) != 0 && - find_slot(&new_addr->ip_addr, &slot)) + if (UTI_CompareIPs(&old_addr->ip_addr, &new_addr->ip.ip, NULL) != 0 && + find_slot(&new_addr->ip.ip, &slot)) return NSR_AlreadyInUse; /* If a record is being modified (e.g. by change_source_address(), or the diff --git a/ntp_sources.h b/ntp_sources.h index 89a322e9..3a9050d0 100644 --- a/ntp_sources.h +++ b/ntp_sources.h @@ -99,7 +99,7 @@ extern void NSR_RefreshAddresses(void); /* Procedure to update the address of a source. The update may be postponed. */ extern NSR_Status NSR_UpdateSourceNtpAddress(NTP_Remote_Address *old_addr, - NTP_Remote_Address *new_addr); + DNS_SockAddrLookupResult *new_addr); /* Procedure to get local reference ID corresponding to a source */ extern uint32_t NSR_GetLocalRefid(IPAddr *address); diff --git a/nts_ntp_client.c b/nts_ntp_client.c index 2c3464fe..91bd182d 100644 --- a/nts_ntp_client.c +++ b/nts_ntp_client.c @@ -194,28 +194,32 @@ check_cookies(NNC_Instance inst) static int set_ntp_address(NNC_Instance inst, NTP_Remote_Address *negotiated_address) { - NTP_Remote_Address old_address, new_address; + NTP_Remote_Address old_address; + DNS_SockAddrLookupResult new_address; old_address = inst->ntp_address; - new_address = *negotiated_address; + new_address.ip.service_name[0] = 0; + new_address.ip.ip = negotiated_address->ip_addr; + new_address.port = negotiated_address->port; - if (new_address.ip_addr.family == IPADDR_UNSPEC) - new_address.ip_addr = inst->nts_address.ip_addr; + if (new_address.ip.ip.family == IPADDR_UNSPEC) + new_address.ip.ip = inst->nts_address.ip_addr; if (new_address.port == 0) new_address.port = inst->default_ntp_port; - if (UTI_CompareIPs(&old_address.ip_addr, &new_address.ip_addr, NULL) == 0 && + if (UTI_CompareIPs(&old_address.ip_addr, &new_address.ip.ip, NULL) == 0 && old_address.port == new_address.port) /* Nothing to do */ return 1; if (NSR_UpdateSourceNtpAddress(&old_address, &new_address) != NSR_Success) { LOG(LOGS_ERR, "Could not change %s to negotiated address %s", - UTI_IPToString(&old_address.ip_addr), UTI_IPToString(&new_address.ip_addr)); + UTI_IPToString(&old_address.ip_addr), UTI_IPToString(&new_address.ip.ip)); return 0; } - inst->ntp_address = new_address; + inst->ntp_address.ip_addr = new_address.ip.ip; + inst->ntp_address.port = new_address.port; return 1; } @@ -545,12 +549,17 @@ NNC_CheckResponseAuth(NNC_Instance inst, NTP_Packet *packet, /* ================================================== */ void -NNC_ChangeAddress(NNC_Instance inst, IPAddr *address) +NNC_ChangeAddress(NNC_Instance inst, DNS_AddressLookupResult *address) { save_cookies(inst); - inst->nts_address.ip_addr = *address; - inst->ntp_address.ip_addr = *address; + inst->nts_address.ip_addr = address->ip; + inst->ntp_address.ip_addr = address->ip; + + if (address->service_name[0] != '\0') { + free(inst->name); + inst->name = strdup(address->service_name); + } reset_instance(inst); diff --git a/nts_ntp_client.h b/nts_ntp_client.h index 2c314cca..b1928ffb 100644 --- a/nts_ntp_client.h +++ b/nts_ntp_client.h @@ -28,6 +28,7 @@ #define GOT_NTS_NTP_CLIENT_H #include "addressing.h" +#include "nameserv.h" #include "ntp.h" #include "reports.h" @@ -42,7 +43,7 @@ extern int NNC_GenerateRequestAuth(NNC_Instance inst, NTP_Packet *packet, extern int NNC_CheckResponseAuth(NNC_Instance inst, NTP_Packet *packet, NTP_PacketInfo *info); -extern void NNC_ChangeAddress(NNC_Instance inst, IPAddr *address); +extern void NNC_ChangeAddress(NNC_Instance inst, DNS_AddressLookupResult *address); extern void NNC_DumpData(NNC_Instance inst); diff --git a/test/unit/ntp_auth.c b/test/unit/ntp_auth.c index e2924a33..d5adaf32 100644 --- a/test/unit/ntp_auth.c +++ b/test/unit/ntp_auth.c @@ -129,6 +129,7 @@ test_unit(void) RPT_AuthReport report; NTP_AuthMode mode; IPSockAddr nts_addr; + DNS_AddressLookupResult lookup; uint32_t key_id, kod; char conf[][100] = { "keyfile ntp_core.keys" @@ -204,8 +205,11 @@ test_unit(void) NAU_DumpData(inst); NAU_GetReport(inst, &report); - if (random() % 2) - NAU_ChangeAddress(inst, &nts_addr.ip_addr); + if (random() % 2) { + lookup.ip = nts_addr.ip_addr; + lookup.service_name[0] = 0; + NAU_ChangeAddress(inst, &lookup); + } if (inst->mode == NTP_AUTH_NTS) { for (j = random() % 5; j > 0; j--) diff --git a/test/unit/ntp_sources.c b/test/unit/ntp_sources.c index 22890154..5fd57756 100644 --- a/test/unit/ntp_sources.c +++ b/test/unit/ntp_sources.c @@ -42,7 +42,7 @@ static void *resolve_handler_arg = NULL; #define NIO_IsServerConnectable(addr) (random() % 2) #define SCH_GetLastEventMonoTime() get_mono_time() -static void change_remote_address(NCR_Instance inst, NTP_Remote_Address *remote_addr, +static void change_remote_address(NCR_Instance inst, DNS_SockAddrLookupResult *remote_addr, int ntp_only); static double get_mono_time(void); @@ -77,10 +77,11 @@ resolve_random_address(DNS_Status status, int rand_bits) static int update_random_address(NTP_Remote_Address *addr, int rand_bits) { - NTP_Remote_Address new_addr; + DNS_SockAddrLookupResult new_addr; NSR_Status status; - TST_GetRandomAddress(&new_addr.ip_addr, IPADDR_UNSPEC, rand_bits); + TST_GetRandomAddress(&new_addr.ip.ip, IPADDR_UNSPEC, rand_bits); + new_addr.ip.service_name[0] = 0; new_addr.port = random() % 1024; status = NSR_UpdateSourceNtpAddress(addr, &new_addr); @@ -96,19 +97,23 @@ update_random_address(NTP_Remote_Address *addr, int rand_bits) } static void -change_remote_address(NCR_Instance inst, NTP_Remote_Address *remote_addr, int ntp_only) +change_remote_address(NCR_Instance inst, DNS_SockAddrLookupResult *remote_addr, int ntp_only) { + NTP_Remote_Address rem_addr; int update = !ntp_only && random() % 4 == 0, update_pos = random() % 2, r = 0; + rem_addr.ip_addr = remote_addr->ip.ip; + rem_addr.port = remote_addr->port; + TEST_CHECK(record_lock); if (update && update_pos == 0) - r = update_random_address(random() % 2 ? remote_addr : NCR_GetRemoteAddress(inst), 4); + r = update_random_address(random() % 2 ? &rem_addr : NCR_GetRemoteAddress(inst), 4); NCR_ChangeRemoteAddress(inst, remote_addr, ntp_only); if (update && update_pos == 1) - r = update_random_address(random() % 2 ? remote_addr : NCR_GetRemoteAddress(inst), 4); + r = update_random_address(random() % 2 ? &rem_addr : NCR_GetRemoteAddress(inst), 4); if (r) TEST_CHECK(UTI_IsIPReal(&saved_address_update.old_address.ip_addr)); diff --git a/test/unit/nts_ntp_client.c b/test/unit/nts_ntp_client.c index 4b567324..501c92ae 100644 --- a/test/unit/nts_ntp_client.c +++ b/test/unit/nts_ntp_client.c @@ -245,7 +245,7 @@ test_unit(void) NTP_PacketInfo info; NTP_Packet packet; IPSockAddr addr; - IPAddr ip_addr; + DNS_AddressLookupResult ip_addr; int i, j, prev_num_cookies, valid; TEST_CHECK(SIV_GetKeyLength(AEAD_AES_SIV_CMAC_256) > 0); @@ -293,9 +293,10 @@ test_unit(void) TEST_CHECK(inst->ok_response == valid); if (random() % 10 == 0) { - TST_GetRandomAddress(&ip_addr, IPADDR_INET4, 32); + TST_GetRandomAddress(&ip_addr.ip, IPADDR_INET4, 32); + ip_addr.service_name[0] = 0; NNC_ChangeAddress(inst, &ip_addr); - TEST_CHECK(UTI_CompareIPs(&inst->nts_address.ip_addr, &ip_addr, NULL) == 0); + TEST_CHECK(UTI_CompareIPs(&inst->nts_address.ip_addr, &ip_addr.ip, NULL) == 0); } } diff --git a/util.c b/util.c index 404e5b74..2a7e71ea 100644 --- a/util.c +++ b/util.c @@ -559,6 +559,23 @@ UTI_IPSockAddrToString(const IPSockAddr *sa) /* ================================================== */ +char * +UTI_DNS_SockAddrLookupResultToString(const DNS_SockAddrLookupResult *sa) +{ + char buf[BUFFER_LENGTH], *result; + + /* Copy to a separate buffer to avoid a compiler warning */ + snprintf(buf, sizeof (buf), "%s", UTI_IPToString(&sa->ip.ip)); + + result = NEXT_BUFFER; + snprintf(result, BUFFER_LENGTH, + sa->ip.ip.family != IPADDR_INET6 ? "%s:%hu" : "[%s]:%hu", buf, sa->port); + + return result; +} + +/* ================================================== */ + char * UTI_IPSubnetToString(IPAddr *subnet, int bits) { diff --git a/util.h b/util.h index 682c58f5..5147d005 100644 --- a/util.h +++ b/util.h @@ -30,6 +30,7 @@ #include "sysincl.h" #include "addressing.h" +#include "nameserv.h" #include "ntp.h" #include "candm.h" #include "cmac.h" @@ -119,6 +120,7 @@ extern void UTI_IPNetworkToHost(const IPAddr *src, IPAddr *dest); extern int UTI_CompareIPs(const IPAddr *a, const IPAddr *b, const IPAddr *mask); extern char *UTI_IPSockAddrToString(const IPSockAddr *sa); +extern char *UTI_DNS_SockAddrLookupResultToString(const DNS_SockAddrLookupResult *sa); extern char *UTI_IPSubnetToString(IPAddr *subnet, int bits); From b223688916acfee7197480a17ef67e91a5408272 Mon Sep 17 00:00:00 2001 From: David Venhoek Date: Wed, 7 Jan 2026 13:39:13 +0100 Subject: [PATCH 03/11] dns: Add parameter to DNS lookups to indicate whether its for NTS. This will allow the DNS lookup code to do service lookups only when doing name resolving for NTSKE servers. --- client.c | 10 +++++----- cmdparse.c | 2 +- conf.c | 2 +- nameserv.c | 2 +- nameserv.h | 2 +- nameserv_async.c | 6 ++++-- nameserv_async.h | 2 +- ntp_sources.c | 10 ++++++++-- nts_ke_client.c | 2 +- privops.c | 7 ++++--- privops.h | 2 +- test/unit/ntp_sources.c | 2 +- 12 files changed, 29 insertions(+), 20 deletions(-) diff --git a/client.c b/client.c index bb1312b4..2c384f1e 100644 --- a/client.c +++ b/client.c @@ -175,7 +175,7 @@ get_addresses(const char *hostnames, int port) addr->type = SCK_ADDR_UNIX; addr->addr.path = Strdup(hostname); } else { - if (DNS_Name2IPAddress(hostname, looked_up_addrs, DNS_MAX_ADDRESSES) != DNS_Success) { + if (DNS_Name2IPAddress(hostname, looked_up_addrs, DNS_MAX_ADDRESSES, 0) != DNS_Success) { DEBUG_LOG("Could not get IP address for %s", hostname); continue; } @@ -454,7 +454,7 @@ parse_source_address(char *word, IPAddr *address) if (UTI_StringToIdIP(word, address)) return 1; - if (DNS_Name2IPAddress(word, &lookup, 1) == DNS_Success) { + if (DNS_Name2IPAddress(word, &lookup, 1, 0) == DNS_Success) { *address = lookup.ip; return 1; } @@ -950,7 +950,7 @@ process_cmd_accheck(CMD_Request *msg, char *line) { DNS_AddressLookupResult lookup; msg->command = htons(REQ_ACCHECK); - if (DNS_Name2IPAddress(line, &lookup, 1) == DNS_Success) { + if (DNS_Name2IPAddress(line, &lookup, 1, 0) == DNS_Success) { UTI_IPHostToNetwork(&lookup.ip, &msg->data.ac_check.ip); return 1; } else { @@ -966,7 +966,7 @@ process_cmd_cmdaccheck(CMD_Request *msg, char *line) { DNS_AddressLookupResult lookup; msg->command = htons(REQ_CMDACCHECK); - if (DNS_Name2IPAddress(line, &lookup, 1) == DNS_Success) { + if (DNS_Name2IPAddress(line, &lookup, 1, 0) == DNS_Success) { UTI_IPHostToNetwork(&lookup.ip, &msg->data.ac_check.ip); return 1; } else { @@ -1055,7 +1055,7 @@ process_cmd_add_source(CMD_Request *msg, char *line) /* Verify that the address is resolvable (chronyc and chronyd are assumed to be running on the same host) */ if (strlen(data.name) >= sizeof (msg->data.ntp_source.name) || - DNS_Name2IPAddress(data.name, &lookup, 1) != DNS_Success) { + DNS_Name2IPAddress(data.name, &lookup, 1, data.params.nts) != DNS_Success) { LOG(LOGS_ERR, "Invalid host/IP address"); break; } diff --git a/cmdparse.c b/cmdparse.c index 0e24b7b9..6c142055 100644 --- a/cmdparse.c +++ b/cmdparse.c @@ -295,7 +295,7 @@ CPS_ParseAllowDeny(char *line, int *all, IPAddr *ip, int *subnet_bits) } /* The last possibility is a hostname */ - if (bits < 0 && DNS_Name2IPAddress(net, &lookup_result, 1) == DNS_Success) { + if (bits < 0 && DNS_Name2IPAddress(net, &lookup_result, 1, 0) == DNS_Success) { *ip = lookup_result.ip; *subnet_bits = ip->family == IPADDR_INET6 ? 128 : 32; return 1; diff --git a/conf.c b/conf.c index 17578587..c0112190 100644 --- a/conf.c +++ b/conf.c @@ -1183,7 +1183,7 @@ parse_initstepslew(char *line) hostname = p; p = CPS_SplitWord(p); if (*hostname) { - if (DNS_Name2IPAddress(hostname, &addr, 1) == DNS_Success) { + if (DNS_Name2IPAddress(hostname, &addr, 1, 0) == DNS_Success) { ARR_AppendElement(init_sources, &addr.ip); } else { LOG(LOGS_WARN, "Could not resolve address of initstepslew server %s", hostname); diff --git a/nameserv.c b/nameserv.c index 99609964..37a2d032 100644 --- a/nameserv.c +++ b/nameserv.c @@ -48,7 +48,7 @@ DNS_SetAddressFamily(int family) } DNS_Status -DNS_Name2IPAddress(const char *name, DNS_AddressLookupResult *addrs, int max_addrs) +DNS_Name2IPAddress(const char *name, DNS_AddressLookupResult *addrs, int max_addrs, int service_nts) { struct addrinfo hints, *res, *ai; int i, result; diff --git a/nameserv.h b/nameserv.h index 69ef9262..3f32c6bf 100644 --- a/nameserv.h +++ b/nameserv.h @@ -54,7 +54,7 @@ extern void DNS_SetAddressFamily(int family); /* Maximum number of addresses returned by DNS_Name2IPAddress */ #define DNS_MAX_ADDRESSES 16 -extern DNS_Status DNS_Name2IPAddress(const char *name, DNS_AddressLookupResult *addrs, int max_addrs); +extern DNS_Status DNS_Name2IPAddress(const char *name, DNS_AddressLookupResult *addrs, int max_addrs, int service_nts); extern int DNS_IPAddress2Name(IPAddr *ip_addr, char *name, int len); diff --git a/nameserv_async.c b/nameserv_async.c index f6aa7dd8..c23f0b27 100644 --- a/nameserv_async.c +++ b/nameserv_async.c @@ -42,6 +42,7 @@ struct DNS_Async_Instance { const char *name; + int service_nts; DNS_Status status; DNS_AddressLookupResult addresses[DNS_MAX_ADDRESSES]; DNS_NameResolveHandler handler; @@ -61,7 +62,7 @@ start_resolving(void *anything) struct DNS_Async_Instance *inst = (struct DNS_Async_Instance *)anything; pthread_mutex_lock(&privops_lock); - inst->status = PRV_Name2IPAddress(inst->name, inst->addresses, DNS_MAX_ADDRESSES); + inst->status = PRV_Name2IPAddress(inst->name, inst->addresses, DNS_MAX_ADDRESSES, inst->service_nts); pthread_mutex_unlock(&privops_lock); /* Notify the main thread that the result is ready */ @@ -99,12 +100,13 @@ end_resolving(int fd, int event, void *anything) /* ================================================== */ void -DNS_Name2IPAddressAsync(const char *name, DNS_NameResolveHandler handler, void *anything) +DNS_Name2IPAddressAsync(const char *name, DNS_NameResolveHandler handler, int service_nts, void *anything) { struct DNS_Async_Instance *inst; inst = MallocNew(struct DNS_Async_Instance); inst->name = name; + inst->service_nts = service_nts; inst->handler = handler; inst->arg = anything; inst->status = DNS_Failure; diff --git a/nameserv_async.h b/nameserv_async.h index 00bd2451..000fe6b4 100644 --- a/nameserv_async.h +++ b/nameserv_async.h @@ -35,6 +35,6 @@ typedef void (*DNS_NameResolveHandler)(DNS_Status status, int n_addrs, DNS_Addre /* Request resolving of a name to IP address. The handler will be called when the result is available. */ -extern void DNS_Name2IPAddressAsync(const char *name, DNS_NameResolveHandler handler, void *anything); +extern void DNS_Name2IPAddressAsync(const char *name, DNS_NameResolveHandler handler, int service_nts, void *anything); #endif diff --git a/ntp_sources.c b/ntp_sources.c index 15f584a2..c6a145ba 100644 --- a/ntp_sources.c +++ b/ntp_sources.c @@ -59,6 +59,7 @@ typedef struct { NCR_Instance data; /* Data for the protocol engine for this source */ char *name; /* Name of the source as it was specified (may be an IP address) */ + int nts; /* Whether the source is NTS enabled */ IPAddr resolved_addr; /* Address resolved from the name, which can be different from remote_addr (e.g. NTS-KE) */ int family; /* IP family of acceptable resolved addresses @@ -100,6 +101,8 @@ struct UnresolvedSource { int pool_id; /* Name to be resolved */ char *name; + /* Whether it should be resolved for NTS */ + int service_nts; /* Address family to filter resolved addresses */ int family; /* Flag indicating addresses should be used in a random order */ @@ -398,6 +401,7 @@ add_source(NTP_Remote_Address *remote_addr, char *name, int family, NTP_Source_T record = get_record(slot); record->name = Strdup(name ? name : UTI_IPToString(&remote_addr->ip_addr)); + record->nts = params->nts; record->data = NCR_CreateInstance(remote_addr, type, params, record->name); record->remote_addr = NCR_GetRemoteAddress(record->data); record->resolved_addr = remote_addr->ip_addr; @@ -671,7 +675,7 @@ name_resolve_handler(DNS_Status status, int n_addrs, DNS_AddressLookupResult *ad if (next) { /* Continue with the next source in the list */ DEBUG_LOG("resolving %s", next->name); - DNS_Name2IPAddressAsync(next->name, name_resolve_handler, next); + DNS_Name2IPAddressAsync(next->name, name_resolve_handler, next->service_nts, next); } else { /* This was the last source in the list. If some sources couldn't be resolved, try again in exponentially increasing interval. */ @@ -717,7 +721,7 @@ resolve_sources(void) resolving_source = us; DEBUG_LOG("resolving %s", us->name); - DNS_Name2IPAddressAsync(us->name, name_resolve_handler, us); + DNS_Name2IPAddressAsync(us->name, name_resolve_handler, us->service_nts, us); } /* ================================================== */ @@ -842,6 +846,7 @@ NSR_AddSourceByName(char *name, int family, int port, int pool, NTP_Source_Type us = MallocNew(struct UnresolvedSource); us->name = Strdup(name); + us->service_nts = params->nts; us->family = family; us->random_order = 0; us->refreshment = 0; @@ -1070,6 +1075,7 @@ resolve_source_replacement(SourceRecord *record, int refreshment) us = MallocNew(struct UnresolvedSource); us->name = Strdup(record->name); + us->service_nts = record->nts; us->family = record->family; /* Ignore the order of addresses from the resolver to not get stuck with a pair of unreachable or otherwise unusable servers diff --git a/nts_ke_client.c b/nts_ke_client.c index 563d2c56..77f30111 100644 --- a/nts_ke_client.c +++ b/nts_ke_client.c @@ -330,7 +330,7 @@ handle_message(void *arg) inst->server_name[length + 1] = '\0'; } - DNS_Name2IPAddressAsync(inst->server_name, name_resolve_handler, inst); + DNS_Name2IPAddressAsync(inst->server_name, name_resolve_handler, 0, inst); inst->resolving_name = 1; } } diff --git a/privops.c b/privops.c index 1c2dec88..3c47c9df 100644 --- a/privops.c +++ b/privops.c @@ -76,6 +76,7 @@ typedef struct { typedef struct { char name[256]; + int service_nts; } ReqName2IPAddress; typedef struct { @@ -283,7 +284,7 @@ do_name_to_ipaddress(ReqName2IPAddress *req, PrvResponse *res) req->name[sizeof (req->name) - 1] = '\0'; res->rc = DNS_Name2IPAddress(req->name, res->data.name_to_ipaddress.addresses, - DNS_MAX_ADDRESSES); + DNS_MAX_ADDRESSES, req->service_nts); } #endif @@ -573,14 +574,14 @@ PRV_BindSocket(int sock, struct sockaddr *address, socklen_t address_len) #ifdef PRIVOPS_NAME2IPADDRESS int -PRV_Name2IPAddress(const char *name, DNS_AddressLookupResult *ip_addrs, int max_addrs) +PRV_Name2IPAddress(const char *name, DNS_AddressLookupResult *ip_addrs, int service_nts, int max_addrs) { PrvRequest req; PrvResponse res; int i; if (!have_helper()) - return DNS_Name2IPAddress(name, ip_addrs, max_addrs); + return DNS_Name2IPAddress(name, ip_addrs, service_nts, max_addrs); memset(&req, 0, sizeof (req)); req.op = OP_NAME2IPADDRESS; diff --git a/privops.h b/privops.h index 48a35cab..c0f4223a 100644 --- a/privops.h +++ b/privops.h @@ -55,7 +55,7 @@ int PRV_BindSocket(int sock, struct sockaddr *address, socklen_t address_len); #endif #ifdef PRIVOPS_NAME2IPADDRESS -int PRV_Name2IPAddress(const char *name, DNS_AddressLookupResult *ip_addrs, int max_addrs); +int PRV_Name2IPAddress(const char *name, DNS_AddressLookupResult *ip_addrs, int service_nts, int max_addrs); #else #define PRV_Name2IPAddress DNS_Name2IPAddress #endif diff --git a/test/unit/ntp_sources.c b/test/unit/ntp_sources.c index 5fd57756..c904c17f 100644 --- a/test/unit/ntp_sources.c +++ b/test/unit/ntp_sources.c @@ -32,7 +32,7 @@ static char *requested_name = NULL; static DNS_NameResolveHandler resolve_handler = NULL; static void *resolve_handler_arg = NULL; -#define DNS_Name2IPAddressAsync(name, handler, arg) \ +#define DNS_Name2IPAddressAsync(name, handler, service_nts, arg) \ requested_name = (name), \ resolve_handler = (handler), \ resolve_handler_arg = (arg) From 0f0d69a42f681a9de93ce2ae0d7750535ba22b4f Mon Sep 17 00:00:00 2001 From: David Venhoek Date: Thu, 8 Jan 2026 15:29:55 +0100 Subject: [PATCH 04/11] dns: Implement SRV record indirection for NTSKE lookups. This allows the actual address of an NTSKE server to be behind an SRV record, allowing SRV record based pools. Since such records also modify the name expected on the certificate, we require succesfull DNSSEC validation for these records. --- configure | 24 ++++++++- nameserv.c | 152 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 174 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 195b1ed7..ec66e657 100755 --- a/configure +++ b/configure @@ -110,6 +110,7 @@ For better control, use the options below. --disable-readline Disable line editing support --without-editline Don't use editline even if it is available --disable-sechash Disable support for hashes other than MD5 + --without-getdns Don't use getdns --without-nettle Don't use nettle even if it is available --without-gnutls Don't use gnutls even if it is available --without-nss Don't use NSS even if it is available @@ -122,6 +123,7 @@ For better control, use the options below. --disable-ipv6 Disable IPv6 support --disable-rtc Don't include RTC even on Linux --disable-privdrop Disable support for dropping root privileges + --disable-srv Disable support for resolving through SRV records --without-libcap Don't use libcap even if it is available --enable-scfilter Enable support for system call filtering --without-seccomp Don't use seccomp even if it is available @@ -221,6 +223,8 @@ feat_cmdmon=1 feat_refclock=1 feat_readline=1 try_editline=1 +feat_srv=1 +try_getdns=1 feat_sechash=1 try_nettle=1 try_nss=1 @@ -383,9 +387,15 @@ do --without-tomcrypt ) try_tomcrypt=0 ;; + --disable-srv ) + feat_srv=0 + ;; --disable-nts ) feat_nts=0 ;; + --without-getdns ) + try_getdns=0 + ;; --without-gnutls ) try_gnutls=0 ;; @@ -970,6 +980,17 @@ EXTRA_OBJECTS="$EXTRA_OBJECTS $HASH_OBJ" EXTRA_CLI_OBJECTS="$EXTRA_CLI_OBJECTS $HASH_OBJ" LIBS="$LIBS $HASH_LINK" +if [ $feat_srv = "1" ] && [ $try_getdns = "1" ]; then + if test_code 'getdns' 'getdns/getdns.h' '' '-lgetdns' ' + getdns_context *context; + getdns_context_create(&context, 1);' + then + EXTRA_LIBS="$EXTRA_LIBS -lgetdns" + EXTRA_CLI_LIBS="$EXTRA_CLI_LIBS -lgetdns" + add_def FEAT_SRV + fi +fi + if [ $feat_nts = "1" ] && [ $try_gnutls = "1" ]; then if [ "$HASH_OBJ" = "hash_gnutls.o" ]; then test_cflags="" @@ -1096,7 +1117,7 @@ add_def MAIL_PROGRAM "\"$mail_program\"" common_features="`get_features SECHASH IPV6 DEBUG`" chronyc_features="`get_features READLINE`" -chronyd_features="`get_features CMDMON REFCLOCK RTC PRIVDROP SCFILTER SIGND NTS`" +chronyd_features="`get_features CMDMON REFCLOCK RTC PRIVDROP SCFILTER SIGND NTS SRV`" add_def CHRONYC_FEATURES "\"$chronyc_features $common_features\"" add_def CHRONYD_FEATURES "\"$chronyd_features $common_features\"" echo "Features : $chronyd_features $chronyc_features $common_features" @@ -1141,4 +1162,3 @@ done # ======================================================================= # vim:et:sw=2:ht=2:sts=2:fdm=marker:cms=#%s - diff --git a/nameserv.c b/nameserv.c index 37a2d032..97a5e3f6 100644 --- a/nameserv.c +++ b/nameserv.c @@ -32,7 +32,14 @@ #include #include +#ifdef FEAT_SRV +#include +#endif +#ifdef FEAT_SRV +#include "logging.h" +#include "memory.h" +#endif #include "nameserv.h" #include "socket.h" #include "util.h" @@ -41,6 +48,24 @@ static int address_family = IPADDR_UNSPEC; +#ifdef FEAT_SRV +#define NTS_SERVICE_NAME "_ntske._tcp." + +static getdns_context *dns_context = NULL; + +static void +reinit() +{ + if (dns_context != NULL) + { + getdns_context_destroy(dns_context); + dns_context = NULL; + } + if (getdns_context_create(&dns_context, 1)) + LOG_MESSAGE(LOGS_ERR, "Could not initialize DNS resolver."); +} +#endif + void DNS_SetAddressFamily(int family) { @@ -61,6 +86,10 @@ DNS_Name2IPAddress(const char *name, DNS_AddressLookupResult *addrs, int max_add addrs[i].service_name[0] = 0; } + /* Avoid dealing with the max_addrs=0 edgecase below */ + if (max_addrs < 1) + return DNS_Success; + /* Avoid calling getaddrinfo() if the name is an IP address */ if (UTI_StringToIP(name, &ip)) { if (address_family != IPADDR_UNSPEC && ip.family != address_family) @@ -70,6 +99,126 @@ DNS_Name2IPAddress(const char *name, DNS_AddressLookupResult *addrs, int max_add return DNS_Success; } +#ifdef FEAT_SRV + /* First try if we can do a service record based resolution" */ + if (service_nts) + { + int write_idx; + getdns_dict *extensions = NULL, *response = NULL; + getdns_list *service_addresses = NULL; + getdns_dict *service_entry = NULL; + getdns_bindata *raw_data = NULL; + char *service_domain = NULL; + char *last_name = NULL; + getdns_return_t getdns_status; + size_t returned_addresses; + + if (dns_context == NULL) + { + reinit(); + if (dns_context == NULL) + { +#ifdef FORCE_DNSRETRY + return DNS_TryAgain; +#else + return DNS_Failure; +#endif + } + } + + service_domain = Malloc(strlen(NTS_SERVICE_NAME) + strlen(name) + 1); + strcpy(service_domain, NTS_SERVICE_NAME); + strcat(service_domain, name); + + if ((extensions = getdns_dict_create()) == NULL) + LOG_FATAL("Could not allocate memory"); + if (getdns_dict_set_int(extensions, "dnssec_return_only_secure", GETDNS_EXTENSION_TRUE)) + LOG_FATAL("Could not allocate memory"); + getdns_status = getdns_service_sync(dns_context, service_domain, extensions, &response); + free(service_domain); + getdns_dict_destroy(extensions); + if (getdns_status) + { +#ifdef FORCE_DNSRETRY + return DNS_TryAgain; +#else + return DNS_Failure; +#endif + } + + if (getdns_dict_get_list(response, "/srv_addresses", &service_addresses)) + LOG_FATAL("Unrecoverable error calling getdns."); + if (getdns_list_get_length(service_addresses, &returned_addresses)) + LOG_FATAL("Unrecoverable error calling getdns."); + + write_idx = 0; + + for (i = 0; i < returned_addresses; i++) + { + if (getdns_list_get_dict(service_addresses, i, &service_entry)) + LOG_FATAL("Unrecoverable error calling getdns."); + if (getdns_dict_get_bindata(service_entry, "domain_name", &raw_data)) + LOG_FATAL("Unrecoverable error calling getdns."); + if (getdns_convert_dns_name_to_fqdn(raw_data, &service_domain)) + LOG_FATAL("Unrecoverable error calling getnds."); + //*Ignore too-long domain names */ + if (strlen(service_domain) >= DNS_SERVICE_NAME_LEN) + continue; + /* Ignore repeated names. This is needed to deal with multiple + addresses from the same service. */ + if (last_name != NULL && strcmp(last_name, service_domain) == 0) + continue; + if (getdns_dict_get_bindata(service_entry, "address_data", &raw_data)) { + // No pre-populated address, recurse to resolve name + if (DNS_Name2IPAddress(service_domain, &addrs[write_idx], 1, 0) == DNS_Success) { + strncpy(addrs[write_idx].service_name, service_domain, DNS_SERVICE_NAME_LEN-1); + write_idx++; + free(last_name); + last_name = service_domain; + service_domain = NULL; + } + } else { + switch (raw_data->size) { + case sizeof (addrs[write_idx].ip.addr.in4): + if (address_family != IPADDR_UNSPEC && address_family != IPADDR_INET4) + continue; + /* copy first to deal with the fact that alignment of data might not be okay. */ + memcpy(&addrs[write_idx].ip.addr.in4, raw_data->data, + sizeof (addrs[write_idx].ip.addr.in4)); + addrs[write_idx].ip.addr.in4 = htonl(addrs[write_idx].ip.addr.in4); + addrs[write_idx].ip.family = IPADDR_INET4; + strncpy(addrs[write_idx].service_name, service_domain, DNS_SERVICE_NAME_LEN-1); + write_idx++; + free(last_name); + last_name = service_domain; + service_domain = NULL; + break; +#ifdef FEAT_IPV6 + case sizeof (addrs[write_idx].ip.addr.in6): + if (address_family != IPADDR_UNSPEC && address_family != IPADDR_INET6) + continue; + memcpy(addrs[write_idx].ip.addr.in6, raw_data->data, + sizeof(addrs[write_idx].ip.addr.in6)); + addrs[write_idx].ip.family = IPADDR_INET6; + strncpy(addrs[write_idx].service_name, service_domain, DNS_SERVICE_NAME_LEN-1); + write_idx++; + free(last_name); + last_name = service_domain; + service_domain = NULL; + break; +#endif + } + } + free(service_domain); + } + + if (addrs[0].ip.family != IPADDR_UNSPEC) + return DNS_Success; + } + + /* Fall back to regular name resolution */ +#endif + memset(&hints, 0, sizeof (hints)); switch (address_family) { @@ -162,6 +311,9 @@ void DNS_Reload(void) { res_init(); +#ifdef FEAT_SRV + reinit(); +#endif } /* ================================================== */ From a0ea1fd4c7eb06a04db5e3142cd82c0f7595e50e Mon Sep 17 00:00:00 2001 From: David Venhoek Date: Mon, 12 Jan 2026 13:31:34 +0100 Subject: [PATCH 05/11] dns: Trim trailing dot from resolved SRV domain name. This solves issues with certificates not validating for the new domain name. --- nameserv.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/nameserv.c b/nameserv.c index 97a5e3f6..253bcd69 100644 --- a/nameserv.c +++ b/nameserv.c @@ -112,6 +112,7 @@ DNS_Name2IPAddress(const char *name, DNS_AddressLookupResult *addrs, int max_add char *last_name = NULL; getdns_return_t getdns_status; size_t returned_addresses; + size_t domain_name_len; if (dns_context == NULL) { @@ -161,6 +162,10 @@ DNS_Name2IPAddress(const char *name, DNS_AddressLookupResult *addrs, int max_add LOG_FATAL("Unrecoverable error calling getdns."); if (getdns_convert_dns_name_to_fqdn(raw_data, &service_domain)) LOG_FATAL("Unrecoverable error calling getnds."); + /* Remove any potential trailing dot as it would interfere with certificate validation*/ + domain_name_len = strlen(service_domain); + if (service_domain[domain_name_len-1] == '.') + service_domain[domain_name_len-1] = 0; //*Ignore too-long domain names */ if (strlen(service_domain) >= DNS_SERVICE_NAME_LEN) continue; From c24d0c1034370438a3c71f0d4557521ddc668ae6 Mon Sep 17 00:00:00 2001 From: David Venhoek Date: Mon, 12 Jan 2026 13:37:45 +0100 Subject: [PATCH 06/11] dns: Use SRV record port. This allows the SRV record to specify a custom port for an NTSKE server. --- nameserv.c | 1 + nameserv.h | 1 + nts_ntp_client.c | 4 ++++ 3 files changed, 6 insertions(+) diff --git a/nameserv.c b/nameserv.c index 253bcd69..2bb45401 100644 --- a/nameserv.c +++ b/nameserv.c @@ -84,6 +84,7 @@ DNS_Name2IPAddress(const char *name, DNS_AddressLookupResult *addrs, int max_add for (i = 0; i < max_addrs; i++) { addrs[i].ip.family = IPADDR_UNSPEC; addrs[i].service_name[0] = 0; + addrs[i].service_port = 0; } /* Avoid dealing with the max_addrs=0 edgecase below */ diff --git a/nameserv.h b/nameserv.h index 3f32c6bf..627e494e 100644 --- a/nameserv.h +++ b/nameserv.h @@ -41,6 +41,7 @@ typedef enum { typedef struct { IPAddr ip; char service_name[DNS_SERVICE_NAME_LEN]; + uint16_t service_port; } DNS_AddressLookupResult; typedef struct { diff --git a/nts_ntp_client.c b/nts_ntp_client.c index 91bd182d..925563e3 100644 --- a/nts_ntp_client.c +++ b/nts_ntp_client.c @@ -561,6 +561,10 @@ NNC_ChangeAddress(NNC_Instance inst, DNS_AddressLookupResult *address) inst->name = strdup(address->service_name); } + if (address->service_port != 0) { + inst->nts_address.port = address->service_port; + } + reset_instance(inst); DEBUG_LOG("NTS reset"); From 527cfc6e921fc8b9209c0643214ef93f220c2606 Mon Sep 17 00:00:00 2001 From: Marc Schoolderman Date: Mon, 2 Feb 2026 16:34:40 +0100 Subject: [PATCH 07/11] rename ip->ip_addr in DNS_SockAddrLookupResult --- nameserv.h | 2 +- ntp_core.c | 6 +++--- ntp_sources.c | 18 +++++++++--------- nts_ntp_client.c | 14 +++++++------- util.c | 4 ++-- 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/nameserv.h b/nameserv.h index 627e494e..054d83a4 100644 --- a/nameserv.h +++ b/nameserv.h @@ -45,7 +45,7 @@ typedef struct { } DNS_AddressLookupResult; typedef struct { - DNS_AddressLookupResult ip; + DNS_AddressLookupResult ip_addr; uint16_t port; } DNS_SockAddrLookupResult; diff --git a/ntp_core.c b/ntp_core.c index 9213a56e..a274c106 100644 --- a/ntp_core.c +++ b/ntp_core.c @@ -828,9 +828,9 @@ NCR_ChangeRemoteAddress(NCR_Instance inst, DNS_SockAddrLookupResult *remote_addr NCR_ResetInstance(inst); if (!ntp_only) - NAU_ChangeAddress(inst->auth, &remote_addr->ip); + NAU_ChangeAddress(inst->auth, &remote_addr->ip_addr); - inst->remote_addr.ip_addr = remote_addr->ip.ip; + inst->remote_addr.ip_addr = remote_addr->ip_addr.ip; inst->remote_addr.port = remote_addr->port; if (inst->mode == MODE_CLIENT) @@ -849,7 +849,7 @@ NCR_ChangeRemoteAddress(NCR_Instance inst, DNS_SockAddrLookupResult *remote_addr NCR_ResetPoll(inst); /* Update the reference ID and reset the source/sourcestats instances */ - SRC_SetRefid(inst->source, UTI_IPToRefid(&remote_addr->ip.ip), + SRC_SetRefid(inst->source, UTI_IPToRefid(&remote_addr->ip_addr.ip), &inst->remote_addr.ip_addr); SRC_ResetInstance(inst->source); diff --git a/ntp_sources.c b/ntp_sources.c index c6a145ba..b943a490 100644 --- a/ntp_sources.c +++ b/ntp_sources.c @@ -444,7 +444,7 @@ change_source_address(NTP_Remote_Address *old_addr, DNS_SockAddrLookupResult *ne LOG_Severity severity; char *name; - new_addr.ip_addr = new_address->ip.ip; + new_addr.ip_addr = new_address->ip_addr.ip; new_addr.port = new_address->port; found = find_slot2(old_addr, &slot1); @@ -526,11 +526,11 @@ static int replace_source_connectable(NTP_Remote_Address *old_addr, DNS_SockAddrLookupResult *new_addr) { NTP_Remote_Address new_remote; - new_remote.ip_addr = new_addr->ip.ip; + new_remote.ip_addr = new_addr->ip_addr.ip; new_remote.port = new_addr->port; if (!NIO_IsServerConnectable(&new_remote)) { - DEBUG_LOG("%s not connectable", UTI_IPToString(&new_addr->ip.ip)); + DEBUG_LOG("%s not connectable", UTI_IPToString(&new_addr->ip_addr.ip)); return 0; } @@ -571,12 +571,12 @@ process_resolved_name(struct UnresolvedSource *us, DNS_AddressLookupResult *addr UTI_GetRandomBytes(&first, sizeof (first)); for (i = 0; i < n_addrs; i++) { - new_addr.ip = addrs[((unsigned int)i + first) % n_addrs]; + new_addr.ip_addr = addrs[((unsigned int)i + first) % n_addrs]; - DEBUG_LOG("(%d) %s", i + 1, UTI_IPToString(&new_addr.ip.ip)); + DEBUG_LOG("(%d) %s", i + 1, UTI_IPToString(&new_addr.ip_addr.ip)); /* Skip addresses not from the requested family */ - if (us->family != IPADDR_UNSPEC && us->family != new_addr.ip.ip.family) + if (us->family != IPADDR_UNSPEC && us->family != new_addr.ip_addr.ip.family) continue; if (us->pool_id != INVALID_POOL) { @@ -1193,11 +1193,11 @@ NSR_UpdateSourceNtpAddress(NTP_Remote_Address *old_addr, DNS_SockAddrLookupResul { int slot; - if (!UTI_IsIPReal(&old_addr->ip_addr) || !UTI_IsIPReal(&new_addr->ip.ip)) + if (!UTI_IsIPReal(&old_addr->ip_addr) || !UTI_IsIPReal(&new_addr->ip_addr.ip)) return NSR_InvalidAF; - if (UTI_CompareIPs(&old_addr->ip_addr, &new_addr->ip.ip, NULL) != 0 && - find_slot(&new_addr->ip.ip, &slot)) + if (UTI_CompareIPs(&old_addr->ip_addr, &new_addr->ip_addr.ip, NULL) != 0 && + find_slot(&new_addr->ip_addr.ip, &slot)) return NSR_AlreadyInUse; /* If a record is being modified (e.g. by change_source_address(), or the diff --git a/nts_ntp_client.c b/nts_ntp_client.c index 925563e3..5fbcee8d 100644 --- a/nts_ntp_client.c +++ b/nts_ntp_client.c @@ -198,27 +198,27 @@ set_ntp_address(NNC_Instance inst, NTP_Remote_Address *negotiated_address) DNS_SockAddrLookupResult new_address; old_address = inst->ntp_address; - new_address.ip.service_name[0] = 0; - new_address.ip.ip = negotiated_address->ip_addr; + new_address.ip_addr.service_name[0] = 0; + new_address.ip_addr.ip = negotiated_address->ip_addr; new_address.port = negotiated_address->port; - if (new_address.ip.ip.family == IPADDR_UNSPEC) - new_address.ip.ip = inst->nts_address.ip_addr; + if (new_address.ip_addr.ip.family == IPADDR_UNSPEC) + new_address.ip_addr.ip = inst->nts_address.ip_addr; if (new_address.port == 0) new_address.port = inst->default_ntp_port; - if (UTI_CompareIPs(&old_address.ip_addr, &new_address.ip.ip, NULL) == 0 && + if (UTI_CompareIPs(&old_address.ip_addr, &new_address.ip_addr.ip, NULL) == 0 && old_address.port == new_address.port) /* Nothing to do */ return 1; if (NSR_UpdateSourceNtpAddress(&old_address, &new_address) != NSR_Success) { LOG(LOGS_ERR, "Could not change %s to negotiated address %s", - UTI_IPToString(&old_address.ip_addr), UTI_IPToString(&new_address.ip.ip)); + UTI_IPToString(&old_address.ip_addr), UTI_IPToString(&new_address.ip_addr.ip)); return 0; } - inst->ntp_address.ip_addr = new_address.ip.ip; + inst->ntp_address.ip_addr = new_address.ip_addr.ip; inst->ntp_address.port = new_address.port; return 1; diff --git a/util.c b/util.c index 2a7e71ea..7ac4d428 100644 --- a/util.c +++ b/util.c @@ -565,11 +565,11 @@ UTI_DNS_SockAddrLookupResultToString(const DNS_SockAddrLookupResult *sa) char buf[BUFFER_LENGTH], *result; /* Copy to a separate buffer to avoid a compiler warning */ - snprintf(buf, sizeof (buf), "%s", UTI_IPToString(&sa->ip.ip)); + snprintf(buf, sizeof (buf), "%s", UTI_IPToString(&sa->ip_addr.ip)); result = NEXT_BUFFER; snprintf(result, BUFFER_LENGTH, - sa->ip.ip.family != IPADDR_INET6 ? "%s:%hu" : "[%s]:%hu", buf, sa->port); + sa->ip_addr.ip.family != IPADDR_INET6 ? "%s:%hu" : "[%s]:%hu", buf, sa->port); return result; } From d52c0d4fd5c85ea773b776454d0bdadc68538ac5 Mon Sep 17 00:00:00 2001 From: Marc Schoolderman Date: Mon, 2 Feb 2026 16:54:44 +0100 Subject: [PATCH 08/11] formatting style --- nameserv.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/nameserv.c b/nameserv.c index 2bb45401..424c2fc8 100644 --- a/nameserv.c +++ b/nameserv.c @@ -102,8 +102,7 @@ DNS_Name2IPAddress(const char *name, DNS_AddressLookupResult *addrs, int max_add #ifdef FEAT_SRV /* First try if we can do a service record based resolution" */ - if (service_nts) - { + if (service_nts) { int write_idx; getdns_dict *extensions = NULL, *response = NULL; getdns_list *service_addresses = NULL; @@ -115,11 +114,9 @@ DNS_Name2IPAddress(const char *name, DNS_AddressLookupResult *addrs, int max_add size_t returned_addresses; size_t domain_name_len; - if (dns_context == NULL) - { + if (dns_context == NULL) { reinit(); - if (dns_context == NULL) - { + if (dns_context == NULL) { #ifdef FORCE_DNSRETRY return DNS_TryAgain; #else @@ -139,8 +136,7 @@ DNS_Name2IPAddress(const char *name, DNS_AddressLookupResult *addrs, int max_add getdns_status = getdns_service_sync(dns_context, service_domain, extensions, &response); free(service_domain); getdns_dict_destroy(extensions); - if (getdns_status) - { + if (getdns_status) { #ifdef FORCE_DNSRETRY return DNS_TryAgain; #else @@ -155,8 +151,7 @@ DNS_Name2IPAddress(const char *name, DNS_AddressLookupResult *addrs, int max_add write_idx = 0; - for (i = 0; i < returned_addresses; i++) - { + for (i = 0; i < returned_addresses; i++) { if (getdns_list_get_dict(service_addresses, i, &service_entry)) LOG_FATAL("Unrecoverable error calling getdns."); if (getdns_dict_get_bindata(service_entry, "domain_name", &raw_data)) From 39bf9dbac37cbd2eadf60adaecae59478301754b Mon Sep 17 00:00:00 2001 From: Marc Schoolderman Date: Mon, 2 Feb 2026 16:39:27 +0100 Subject: [PATCH 09/11] rename service_nts --- nameserv.c | 4 ++-- nameserv.h | 2 +- nameserv_async.c | 8 ++++---- nameserv_async.h | 2 +- ntp_sources.c | 10 +++++----- privops.c | 8 ++++---- privops.h | 2 +- 7 files changed, 18 insertions(+), 18 deletions(-) diff --git a/nameserv.c b/nameserv.c index 424c2fc8..db6b3360 100644 --- a/nameserv.c +++ b/nameserv.c @@ -73,7 +73,7 @@ DNS_SetAddressFamily(int family) } DNS_Status -DNS_Name2IPAddress(const char *name, DNS_AddressLookupResult *addrs, int max_addrs, int service_nts) +DNS_Name2IPAddress(const char *name, DNS_AddressLookupResult *addrs, int max_addrs, int use_srv_lookup) { struct addrinfo hints, *res, *ai; int i, result; @@ -102,7 +102,7 @@ DNS_Name2IPAddress(const char *name, DNS_AddressLookupResult *addrs, int max_add #ifdef FEAT_SRV /* First try if we can do a service record based resolution" */ - if (service_nts) { + if (use_srv_lookup) { int write_idx; getdns_dict *extensions = NULL, *response = NULL; getdns_list *service_addresses = NULL; diff --git a/nameserv.h b/nameserv.h index 054d83a4..29bb424e 100644 --- a/nameserv.h +++ b/nameserv.h @@ -55,7 +55,7 @@ extern void DNS_SetAddressFamily(int family); /* Maximum number of addresses returned by DNS_Name2IPAddress */ #define DNS_MAX_ADDRESSES 16 -extern DNS_Status DNS_Name2IPAddress(const char *name, DNS_AddressLookupResult *addrs, int max_addrs, int service_nts); +extern DNS_Status DNS_Name2IPAddress(const char *name, DNS_AddressLookupResult *addrs, int max_addrs, int use_srv_lookup); extern int DNS_IPAddress2Name(IPAddr *ip_addr, char *name, int len); diff --git a/nameserv_async.c b/nameserv_async.c index c23f0b27..805d9c68 100644 --- a/nameserv_async.c +++ b/nameserv_async.c @@ -42,7 +42,7 @@ struct DNS_Async_Instance { const char *name; - int service_nts; + int use_srv_lookup; DNS_Status status; DNS_AddressLookupResult addresses[DNS_MAX_ADDRESSES]; DNS_NameResolveHandler handler; @@ -62,7 +62,7 @@ start_resolving(void *anything) struct DNS_Async_Instance *inst = (struct DNS_Async_Instance *)anything; pthread_mutex_lock(&privops_lock); - inst->status = PRV_Name2IPAddress(inst->name, inst->addresses, DNS_MAX_ADDRESSES, inst->service_nts); + inst->status = PRV_Name2IPAddress(inst->name, inst->addresses, DNS_MAX_ADDRESSES, inst->use_srv_lookup); pthread_mutex_unlock(&privops_lock); /* Notify the main thread that the result is ready */ @@ -100,13 +100,13 @@ end_resolving(int fd, int event, void *anything) /* ================================================== */ void -DNS_Name2IPAddressAsync(const char *name, DNS_NameResolveHandler handler, int service_nts, void *anything) +DNS_Name2IPAddressAsync(const char *name, DNS_NameResolveHandler handler, int use_srv_lookup, void *anything) { struct DNS_Async_Instance *inst; inst = MallocNew(struct DNS_Async_Instance); inst->name = name; - inst->service_nts = service_nts; + inst->use_srv_lookup = use_srv_lookup; inst->handler = handler; inst->arg = anything; inst->status = DNS_Failure; diff --git a/nameserv_async.h b/nameserv_async.h index 000fe6b4..e5662907 100644 --- a/nameserv_async.h +++ b/nameserv_async.h @@ -35,6 +35,6 @@ typedef void (*DNS_NameResolveHandler)(DNS_Status status, int n_addrs, DNS_Addre /* Request resolving of a name to IP address. The handler will be called when the result is available. */ -extern void DNS_Name2IPAddressAsync(const char *name, DNS_NameResolveHandler handler, int service_nts, void *anything); +extern void DNS_Name2IPAddressAsync(const char *name, DNS_NameResolveHandler handler, int perform_srv, void *anything); #endif diff --git a/ntp_sources.c b/ntp_sources.c index b943a490..d2294371 100644 --- a/ntp_sources.c +++ b/ntp_sources.c @@ -102,7 +102,7 @@ struct UnresolvedSource { /* Name to be resolved */ char *name; /* Whether it should be resolved for NTS */ - int service_nts; + int perform_srv; /* Address family to filter resolved addresses */ int family; /* Flag indicating addresses should be used in a random order */ @@ -675,7 +675,7 @@ name_resolve_handler(DNS_Status status, int n_addrs, DNS_AddressLookupResult *ad if (next) { /* Continue with the next source in the list */ DEBUG_LOG("resolving %s", next->name); - DNS_Name2IPAddressAsync(next->name, name_resolve_handler, next->service_nts, next); + DNS_Name2IPAddressAsync(next->name, name_resolve_handler, next->perform_srv, next); } else { /* This was the last source in the list. If some sources couldn't be resolved, try again in exponentially increasing interval. */ @@ -721,7 +721,7 @@ resolve_sources(void) resolving_source = us; DEBUG_LOG("resolving %s", us->name); - DNS_Name2IPAddressAsync(us->name, name_resolve_handler, us->service_nts, us); + DNS_Name2IPAddressAsync(us->name, name_resolve_handler, us->perform_srv, us); } /* ================================================== */ @@ -846,7 +846,7 @@ NSR_AddSourceByName(char *name, int family, int port, int pool, NTP_Source_Type us = MallocNew(struct UnresolvedSource); us->name = Strdup(name); - us->service_nts = params->nts; + us->perform_srv = params->nts; us->family = family; us->random_order = 0; us->refreshment = 0; @@ -1075,7 +1075,7 @@ resolve_source_replacement(SourceRecord *record, int refreshment) us = MallocNew(struct UnresolvedSource); us->name = Strdup(record->name); - us->service_nts = record->nts; + us->perform_srv = record->nts; us->family = record->family; /* Ignore the order of addresses from the resolver to not get stuck with a pair of unreachable or otherwise unusable servers diff --git a/privops.c b/privops.c index 3c47c9df..4914dd81 100644 --- a/privops.c +++ b/privops.c @@ -76,7 +76,7 @@ typedef struct { typedef struct { char name[256]; - int service_nts; + int perform_srv; } ReqName2IPAddress; typedef struct { @@ -284,7 +284,7 @@ do_name_to_ipaddress(ReqName2IPAddress *req, PrvResponse *res) req->name[sizeof (req->name) - 1] = '\0'; res->rc = DNS_Name2IPAddress(req->name, res->data.name_to_ipaddress.addresses, - DNS_MAX_ADDRESSES, req->service_nts); + DNS_MAX_ADDRESSES, req->perform_srv); } #endif @@ -574,14 +574,14 @@ PRV_BindSocket(int sock, struct sockaddr *address, socklen_t address_len) #ifdef PRIVOPS_NAME2IPADDRESS int -PRV_Name2IPAddress(const char *name, DNS_AddressLookupResult *ip_addrs, int service_nts, int max_addrs) +PRV_Name2IPAddress(const char *name, DNS_AddressLookupResult *ip_addrs, int perform_srv, int max_addrs) { PrvRequest req; PrvResponse res; int i; if (!have_helper()) - return DNS_Name2IPAddress(name, ip_addrs, service_nts, max_addrs); + return DNS_Name2IPAddress(name, ip_addrs, perform_srv, max_addrs); memset(&req, 0, sizeof (req)); req.op = OP_NAME2IPADDRESS; diff --git a/privops.h b/privops.h index c0f4223a..838e6419 100644 --- a/privops.h +++ b/privops.h @@ -55,7 +55,7 @@ int PRV_BindSocket(int sock, struct sockaddr *address, socklen_t address_len); #endif #ifdef PRIVOPS_NAME2IPADDRESS -int PRV_Name2IPAddress(const char *name, DNS_AddressLookupResult *ip_addrs, int service_nts, int max_addrs); +int PRV_Name2IPAddress(const char *name, DNS_AddressLookupResult *ip_addrs, int perform_srv, int max_addrs); #else #define PRV_Name2IPAddress DNS_Name2IPAddress #endif From d4c791e2675b4700458bd98102eedbd661c31746 Mon Sep 17 00:00:00 2001 From: David Venhoek Date: Thu, 12 Mar 2026 12:25:43 +0100 Subject: [PATCH 10/11] Fixup unit tests for ip->ipaddr rename. --- test/unit/ntp_sources.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/unit/ntp_sources.c b/test/unit/ntp_sources.c index c904c17f..1890986f 100644 --- a/test/unit/ntp_sources.c +++ b/test/unit/ntp_sources.c @@ -80,8 +80,8 @@ update_random_address(NTP_Remote_Address *addr, int rand_bits) DNS_SockAddrLookupResult new_addr; NSR_Status status; - TST_GetRandomAddress(&new_addr.ip.ip, IPADDR_UNSPEC, rand_bits); - new_addr.ip.service_name[0] = 0; + TST_GetRandomAddress(&new_addr.ip_addr.ip, IPADDR_UNSPEC, rand_bits); + new_addr.ip_addr.service_name[0] = 0; new_addr.port = random() % 1024; status = NSR_UpdateSourceNtpAddress(addr, &new_addr); @@ -102,7 +102,7 @@ change_remote_address(NCR_Instance inst, DNS_SockAddrLookupResult *remote_addr, NTP_Remote_Address rem_addr; int update = !ntp_only && random() % 4 == 0, update_pos = random() % 2, r = 0; - rem_addr.ip_addr = remote_addr->ip.ip; + rem_addr.ip_addr = remote_addr->ip_addr.ip; rem_addr.port = remote_addr->port; TEST_CHECK(record_lock); From d22573f74ad2a4058b06ab460df921a3a9a1070f Mon Sep 17 00:00:00 2001 From: David Venhoek Date: Thu, 12 Mar 2026 12:26:07 +0100 Subject: [PATCH 11/11] Split off srv lookups into their own function. This makes code size a bit more manageable. --- nameserv.c | 232 ++++++++++++++++++++++++++++------------------------- 1 file changed, 123 insertions(+), 109 deletions(-) diff --git a/nameserv.c b/nameserv.c index db6b3360..5d26b0f9 100644 --- a/nameserv.c +++ b/nameserv.c @@ -72,6 +72,126 @@ DNS_SetAddressFamily(int family) address_family = family; } +#ifdef FEAT_SRV +static DNS_Status +srv_lookup(const char *name, DNS_AddressLookupResult *addrs, int max_addrs) { + int i, write_idx; + getdns_dict *extensions = NULL, *response = NULL; + getdns_list *service_addresses = NULL; + getdns_dict *service_entry = NULL; + getdns_bindata *raw_data = NULL; + char *service_domain = NULL; + char *last_name = NULL; + getdns_return_t getdns_status; + size_t returned_addresses; + size_t domain_name_len; + + if (dns_context == NULL) { + reinit(); + if (dns_context == NULL) { +#ifdef FORCE_DNSRETRY + return DNS_TryAgain; +#else + return DNS_Failure; +#endif + } + } + + service_domain = Malloc(strlen(NTS_SERVICE_NAME) + strlen(name) + 1); + strcpy(service_domain, NTS_SERVICE_NAME); + strcat(service_domain, name); + + if ((extensions = getdns_dict_create()) == NULL) + LOG_FATAL("Could not allocate memory"); + if (getdns_dict_set_int(extensions, "dnssec_return_only_secure", GETDNS_EXTENSION_TRUE)) + LOG_FATAL("Could not allocate memory"); + getdns_status = getdns_service_sync(dns_context, service_domain, extensions, &response); + free(service_domain); + getdns_dict_destroy(extensions); + if (getdns_status) { +#ifdef FORCE_DNSRETRY + return DNS_TryAgain; +#else + return DNS_Failure; +#endif + } + + if (getdns_dict_get_list(response, "/srv_addresses", &service_addresses)) + LOG_FATAL("Unrecoverable error calling getdns."); + if (getdns_list_get_length(service_addresses, &returned_addresses)) + LOG_FATAL("Unrecoverable error calling getdns."); + + write_idx = 0; + + for (i = 0; i < returned_addresses; i++) { + if (getdns_list_get_dict(service_addresses, i, &service_entry)) + LOG_FATAL("Unrecoverable error calling getdns."); + if (getdns_dict_get_bindata(service_entry, "domain_name", &raw_data)) + LOG_FATAL("Unrecoverable error calling getdns."); + if (getdns_convert_dns_name_to_fqdn(raw_data, &service_domain)) + LOG_FATAL("Unrecoverable error calling getnds."); + + /* Remove any potential trailing dot as it would interfere with certificate validation*/ + domain_name_len = strlen(service_domain); + if (service_domain[domain_name_len-1] == '.') + service_domain[domain_name_len-1] = 0; + + //*Ignore too-long domain names */ + if (strlen(service_domain) >= DNS_SERVICE_NAME_LEN) + continue; + + /* Ignore repeated names. This is needed to deal with multiple + addresses from the same service. */ + if (last_name != NULL && strcmp(last_name, service_domain) == 0) + continue; + + if (getdns_dict_get_bindata(service_entry, "address_data", &raw_data)) { + // No pre-populated address, recurse to resolve name + if (DNS_Name2IPAddress(service_domain, &addrs[write_idx], 1, 0) == DNS_Success) { + strncpy(addrs[write_idx].service_name, service_domain, DNS_SERVICE_NAME_LEN-1); + write_idx++; + free(last_name); + last_name = service_domain; + service_domain = NULL; + } + } else { + switch (raw_data->size) { + case sizeof (addrs[write_idx].ip.addr.in4): + if (address_family != IPADDR_UNSPEC && address_family != IPADDR_INET4) + continue; + /* copy first to deal with the fact that alignment of data might not be okay. */ + memcpy(&addrs[write_idx].ip.addr.in4, raw_data->data, + sizeof (addrs[write_idx].ip.addr.in4)); + addrs[write_idx].ip.addr.in4 = htonl(addrs[write_idx].ip.addr.in4); + addrs[write_idx].ip.family = IPADDR_INET4; + strncpy(addrs[write_idx].service_name, service_domain, DNS_SERVICE_NAME_LEN-1); + write_idx++; + free(last_name); + last_name = service_domain; + service_domain = NULL; + break; + +#ifdef FEAT_IPV6 + case sizeof (addrs[write_idx].ip.addr.in6): + if (address_family != IPADDR_UNSPEC && address_family != IPADDR_INET6) + continue; + memcpy(addrs[write_idx].ip.addr.in6, raw_data->data, + sizeof(addrs[write_idx].ip.addr.in6)); + addrs[write_idx].ip.family = IPADDR_INET6; + strncpy(addrs[write_idx].service_name, service_domain, DNS_SERVICE_NAME_LEN-1); + write_idx++; + free(last_name); + last_name = service_domain; + service_domain = NULL; + break; +#endif + } + } + free(service_domain); + } +} +#endif + DNS_Status DNS_Name2IPAddress(const char *name, DNS_AddressLookupResult *addrs, int max_addrs, int use_srv_lookup) { @@ -103,115 +223,9 @@ DNS_Name2IPAddress(const char *name, DNS_AddressLookupResult *addrs, int max_add #ifdef FEAT_SRV /* First try if we can do a service record based resolution" */ if (use_srv_lookup) { - int write_idx; - getdns_dict *extensions = NULL, *response = NULL; - getdns_list *service_addresses = NULL; - getdns_dict *service_entry = NULL; - getdns_bindata *raw_data = NULL; - char *service_domain = NULL; - char *last_name = NULL; - getdns_return_t getdns_status; - size_t returned_addresses; - size_t domain_name_len; - - if (dns_context == NULL) { - reinit(); - if (dns_context == NULL) { -#ifdef FORCE_DNSRETRY - return DNS_TryAgain; -#else - return DNS_Failure; -#endif - } - } - - service_domain = Malloc(strlen(NTS_SERVICE_NAME) + strlen(name) + 1); - strcpy(service_domain, NTS_SERVICE_NAME); - strcat(service_domain, name); - - if ((extensions = getdns_dict_create()) == NULL) - LOG_FATAL("Could not allocate memory"); - if (getdns_dict_set_int(extensions, "dnssec_return_only_secure", GETDNS_EXTENSION_TRUE)) - LOG_FATAL("Could not allocate memory"); - getdns_status = getdns_service_sync(dns_context, service_domain, extensions, &response); - free(service_domain); - getdns_dict_destroy(extensions); - if (getdns_status) { -#ifdef FORCE_DNSRETRY - return DNS_TryAgain; -#else - return DNS_Failure; -#endif - } - - if (getdns_dict_get_list(response, "/srv_addresses", &service_addresses)) - LOG_FATAL("Unrecoverable error calling getdns."); - if (getdns_list_get_length(service_addresses, &returned_addresses)) - LOG_FATAL("Unrecoverable error calling getdns."); - - write_idx = 0; - - for (i = 0; i < returned_addresses; i++) { - if (getdns_list_get_dict(service_addresses, i, &service_entry)) - LOG_FATAL("Unrecoverable error calling getdns."); - if (getdns_dict_get_bindata(service_entry, "domain_name", &raw_data)) - LOG_FATAL("Unrecoverable error calling getdns."); - if (getdns_convert_dns_name_to_fqdn(raw_data, &service_domain)) - LOG_FATAL("Unrecoverable error calling getnds."); - /* Remove any potential trailing dot as it would interfere with certificate validation*/ - domain_name_len = strlen(service_domain); - if (service_domain[domain_name_len-1] == '.') - service_domain[domain_name_len-1] = 0; - //*Ignore too-long domain names */ - if (strlen(service_domain) >= DNS_SERVICE_NAME_LEN) - continue; - /* Ignore repeated names. This is needed to deal with multiple - addresses from the same service. */ - if (last_name != NULL && strcmp(last_name, service_domain) == 0) - continue; - if (getdns_dict_get_bindata(service_entry, "address_data", &raw_data)) { - // No pre-populated address, recurse to resolve name - if (DNS_Name2IPAddress(service_domain, &addrs[write_idx], 1, 0) == DNS_Success) { - strncpy(addrs[write_idx].service_name, service_domain, DNS_SERVICE_NAME_LEN-1); - write_idx++; - free(last_name); - last_name = service_domain; - service_domain = NULL; - } - } else { - switch (raw_data->size) { - case sizeof (addrs[write_idx].ip.addr.in4): - if (address_family != IPADDR_UNSPEC && address_family != IPADDR_INET4) - continue; - /* copy first to deal with the fact that alignment of data might not be okay. */ - memcpy(&addrs[write_idx].ip.addr.in4, raw_data->data, - sizeof (addrs[write_idx].ip.addr.in4)); - addrs[write_idx].ip.addr.in4 = htonl(addrs[write_idx].ip.addr.in4); - addrs[write_idx].ip.family = IPADDR_INET4; - strncpy(addrs[write_idx].service_name, service_domain, DNS_SERVICE_NAME_LEN-1); - write_idx++; - free(last_name); - last_name = service_domain; - service_domain = NULL; - break; -#ifdef FEAT_IPV6 - case sizeof (addrs[write_idx].ip.addr.in6): - if (address_family != IPADDR_UNSPEC && address_family != IPADDR_INET6) - continue; - memcpy(addrs[write_idx].ip.addr.in6, raw_data->data, - sizeof(addrs[write_idx].ip.addr.in6)); - addrs[write_idx].ip.family = IPADDR_INET6; - strncpy(addrs[write_idx].service_name, service_domain, DNS_SERVICE_NAME_LEN-1); - write_idx++; - free(last_name); - last_name = service_domain; - service_domain = NULL; - break; -#endif - } - } - free(service_domain); - } + result = srv_lookup(name, addrs, max_addrs); + if (result != DNS_Success) + return result; if (addrs[0].ip.family != IPADDR_UNSPEC) return DNS_Success;