diff --git a/client.c b/client.c index 66f23b70..2c384f1e 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, 0) != 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, 0) == 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, 0) == 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, 0) == 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, data.params.nts) != 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..6c142055 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, 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 1f362d7f..c0112190 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, 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/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 9f7e648c..5d26b0f9 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,14 +48,152 @@ 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) { 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, IPAddr *ip_addrs, int max_addrs) +DNS_Name2IPAddress(const char *name, DNS_AddressLookupResult *addrs, int max_addrs, int use_srv_lookup) { struct addrinfo hints, *res, *ai; int i, result; @@ -56,18 +201,39 @@ 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; + addrs[i].service_port = 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) return DNS_Failure; if (max_addrs >= 1) - ip_addrs[0] = ip; + addrs[0].ip = ip; return DNS_Success; } +#ifdef FEAT_SRV + /* First try if we can do a service record based resolution" */ + if (use_srv_lookup) { + result = srv_lookup(name, addrs, max_addrs); + if (result != DNS_Success) + return result; + + 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) { @@ -99,8 +265,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 +276,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 +287,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; } /* ================================================== */ @@ -160,7 +326,9 @@ void DNS_Reload(void) { res_init(); +#ifdef FEAT_SRV + reinit(); +#endif } /* ================================================== */ - diff --git a/nameserv.h b/nameserv.h index dbef61a3..29bb424e 100644 --- a/nameserv.h +++ b/nameserv.h @@ -30,23 +30,35 @@ #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]; + uint16_t service_port; +} DNS_AddressLookupResult; + +typedef struct { + DNS_AddressLookupResult ip_addr; + uint16_t port; +} DNS_SockAddrLookupResult; + /* 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, int use_srv_lookup); 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..805d9c68 100644 --- a/nameserv_async.c +++ b/nameserv_async.c @@ -42,8 +42,9 @@ struct DNS_Async_Instance { const char *name; + int use_srv_lookup; DNS_Status status; - IPAddr addresses[DNS_MAX_ADDRESSES]; + DNS_AddressLookupResult addresses[DNS_MAX_ADDRESSES]; DNS_NameResolveHandler handler; void *arg; @@ -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->use_srv_lookup); pthread_mutex_unlock(&privops_lock); /* Notify the main thread that the result is ready */ @@ -88,7 +89,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); @@ -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 use_srv_lookup, void *anything) { struct DNS_Async_Instance *inst; inst = MallocNew(struct DNS_Async_Instance); inst->name = name; + 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 b8479e1d..e5662907 100644 --- a/nameserv_async.h +++ b/nameserv_async.h @@ -31,10 +31,10 @@ #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. */ -extern void DNS_Name2IPAddressAsync(const char *name, DNS_NameResolveHandler handler, void *anything); +extern void DNS_Name2IPAddressAsync(const char *name, DNS_NameResolveHandler handler, int perform_srv, void *anything); #endif 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..a274c106 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); - inst->remote_addr = *remote_addr; + inst->remote_addr.ip_addr = remote_addr->ip_addr.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_addr.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 7bf08894..d2294371 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 perform_srv; /* Address family to filter resolved addresses */ int family; /* Flag indicating addresses should be used in a random order */ @@ -144,7 +147,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 */ @@ -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; @@ -431,21 +435,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_addr.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 +461,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 +493,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 +515,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 +523,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_addr.ip; + new_remote.port = new_addr->port; + + if (!NIO_IsServerConnectable(&new_remote)) { + DEBUG_LOG("%s not connectable", UTI_IPToString(&new_addr->ip_addr.ip)); return 0; } @@ -533,9 +545,10 @@ 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; + NTP_Remote_Address old_addr; + DNS_SockAddrLookupResult new_addr; SourceRecord *record; unsigned short first = 0; int i, j, slot; @@ -547,7 +560,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,12 +571,12 @@ 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]; - DEBUG_LOG("(%d) %s", i + 1, UTI_IPToString(&new_addr.ip_addr)); + 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_addr.family) + if (us->family != IPADDR_UNSPEC && us->family != new_addr.ip_addr.ip.family) continue; if (us->pool_id != INVALID_POOL) { @@ -616,7 +629,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 +644,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); @@ -662,7 +675,7 @@ name_resolve_handler(DNS_Status status, int n_addrs, IPAddr *ip_addrs, void *any 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->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. */ @@ -708,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->perform_srv, us); } /* ================================================== */ @@ -833,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->perform_srv = params->nts; us->family = family; us->random_order = 0; us->refreshment = 0; @@ -1061,6 +1075,7 @@ resolve_source_replacement(SourceRecord *record, int refreshment) us = MallocNew(struct UnresolvedSource); us->name = Strdup(record->name); + 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 @@ -1174,15 +1189,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_addr.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_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/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_ke_client.c b/nts_ke_client.c index e68d4dcf..77f30111 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; } } @@ -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/nts_ntp_client.c b/nts_ntp_client.c index 2c3464fe..5fbcee8d 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_addr.service_name[0] = 0; + new_address.ip_addr.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_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_addr, 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_addr)); + UTI_IPToString(&old_address.ip_addr), UTI_IPToString(&new_address.ip_addr.ip)); return 0; } - inst->ntp_address = new_address; + inst->ntp_address.ip_addr = new_address.ip_addr.ip; + inst->ntp_address.port = new_address.port; return 1; } @@ -545,12 +549,21 @@ 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); + } + + if (address->service_port != 0) { + inst->nts_address.port = address->service_port; + } 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/privops.c b/privops.c index 3bc76d14..4914dd81 100644 --- a/privops.c +++ b/privops.c @@ -76,6 +76,7 @@ typedef struct { typedef struct { char name[256]; + int perform_srv; } ReqName2IPAddress; typedef struct { @@ -106,7 +107,7 @@ typedef struct { #endif typedef struct { - IPAddr addresses[DNS_MAX_ADDRESSES]; + DNS_AddressLookupResult addresses[DNS_MAX_ADDRESSES]; } ResName2IPAddress; 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->perform_srv); } #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, IPAddr *ip_addrs, 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, 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 146580b7..838e6419 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 perform_srv, int max_addrs); #else #define PRV_Name2IPAddress DNS_Name2IPAddress #endif 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 be5d2ea8..1890986f 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) @@ -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); @@ -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,22 +61,27 @@ 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 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_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); @@ -92,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_addr.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..7ac4d428 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_addr.ip)); + + result = NEXT_BUFFER; + snprintf(result, BUFFER_LENGTH, + sa->ip_addr.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);