diff --git a/cmdmon.c b/cmdmon.c index 9adc9d6..d2199a7 100644 --- a/cmdmon.c +++ b/cmdmon.c @@ -789,7 +789,7 @@ handle_add_source(CMD_Request *rx_message, CMD_Reply *tx_message) NTP_EF_FLAG_EXP_NET_CORRECTION : 0); params.sel_options = convert_addsrc_select_options(ntohl(rx_message->data.ntp_source.flags)); - status = NSR_AddSourceByName(name, port, pool, type, ¶ms, NULL); + status = NSR_AddSourceByName(name, IPADDR_UNSPEC, port, pool, type, ¶ms, NULL); switch (status) { case NSR_Success: break; diff --git a/conf.c b/conf.c index fa74459..9bae265 100644 --- a/conf.c +++ b/conf.c @@ -1728,8 +1728,9 @@ reload_source_dirs(void) /* Add new sources */ if (pass == 1 && d > 0) { source = &new_sources[j]; - s = NSR_AddSourceByName(source->params.name, source->params.port, source->pool, - source->type, &source->params.params, &new_ids[j]); + s = NSR_AddSourceByName(source->params.name, IPADDR_UNSPEC, source->params.port, + source->pool, source->type, &source->params.params, + &new_ids[j]); if (s == NSR_UnresolvedName) { unresolved++; @@ -1842,8 +1843,8 @@ CNF_AddSources(void) for (i = 0; i < ARR_GetSize(ntp_sources); i++) { source = (NTP_Source *)ARR_GetElement(ntp_sources, i); - s = NSR_AddSourceByName(source->params.name, source->params.port, source->pool, - source->type, &source->params.params, NULL); + s = NSR_AddSourceByName(source->params.name, IPADDR_UNSPEC, source->params.port, + source->pool, source->type, &source->params.params, NULL); if (s != NSR_Success && s != NSR_UnresolvedName) LOG(LOGS_ERR, "Could not add source %s", source->params.name); diff --git a/ntp_sources.c b/ntp_sources.c index d8bd2d8..590e5e0 100644 --- a/ntp_sources.c +++ b/ntp_sources.c @@ -61,6 +61,8 @@ typedef struct { (may be an IP address) */ 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 + (IPADDR_UNSPEC if any) */ int pool_id; /* ID of the pool from which was this source added or INVALID_POOL */ int tentative; /* Flag indicating there was no valid response @@ -98,6 +100,8 @@ struct UnresolvedSource { int pool_id; /* Name to be resolved */ char *name; + /* Address family to filter resolved addresses */ + int family; /* Flag indicating addresses should be used in a random order */ int random_order; /* Flag indicating current address should be replaced only if it is @@ -353,7 +357,7 @@ log_source(SourceRecord *record, int addition, int once_per_pool) /* Procedure to add a new source */ static NSR_Status -add_source(NTP_Remote_Address *remote_addr, char *name, NTP_Source_Type type, +add_source(NTP_Remote_Address *remote_addr, char *name, int family, NTP_Source_Type type, SourceParameters *params, int pool_id, uint32_t conf_id) { SourceRecord *record; @@ -391,6 +395,7 @@ add_source(NTP_Remote_Address *remote_addr, char *name, NTP_Source_Type type, record->data = NCR_CreateInstance(remote_addr, type, params, record->name); record->remote_addr = NCR_GetRemoteAddress(record->data); record->resolved_addr = remote_addr->ip_addr; + record->family = family; record->pool_id = pool_id; record->tentative = 1; record->conf_id = conf_id; @@ -552,6 +557,10 @@ process_resolved_name(struct UnresolvedSource *us, IPAddr *ip_addrs, int n_addrs DEBUG_LOG("(%d) %s", i + 1, UTI_IPToString(&new_addr.ip_addr)); + /* Skip addresses not from the requested family */ + if (us->family != IPADDR_UNSPEC && us->family != new_addr.ip_addr.family) + continue; + if (us->pool_id != INVALID_POOL) { /* In the pool resolving mode, try to replace a source from the pool which does not have a real address yet */ @@ -768,14 +777,14 @@ NSR_Status NSR_AddSource(NTP_Remote_Address *remote_addr, NTP_Source_Type type, SourceParameters *params, uint32_t *conf_id) { - return add_source(remote_addr, NULL, type, params, INVALID_POOL, + return add_source(remote_addr, NULL, IPADDR_UNSPEC, type, params, INVALID_POOL, get_next_conf_id(conf_id)); } /* ================================================== */ NSR_Status -NSR_AddSourceByName(char *name, int port, int pool, NTP_Source_Type type, +NSR_AddSourceByName(char *name, int family, int port, int pool, NTP_Source_Type type, SourceParameters *params, uint32_t *conf_id) { struct UnresolvedSource *us; @@ -787,7 +796,9 @@ NSR_AddSourceByName(char *name, int port, int pool, NTP_Source_Type type, /* If the name is an IP address, add the source with the address directly */ if (UTI_StringToIP(name, &remote_addr.ip_addr)) { remote_addr.port = port; - return add_source(&remote_addr, name, type, params, INVALID_POOL, + if (family != IPADDR_UNSPEC && family != remote_addr.ip_addr.family) + return NSR_InvalidAF; + return add_source(&remote_addr, name, IPADDR_UNSPEC, type, params, INVALID_POOL, get_next_conf_id(conf_id)); } @@ -799,6 +810,7 @@ NSR_AddSourceByName(char *name, int port, int pool, NTP_Source_Type type, us = MallocNew(struct UnresolvedSource); us->name = Strdup(name); + us->family = family; us->random_order = 0; us->refreshment = 0; @@ -835,7 +847,7 @@ NSR_AddSourceByName(char *name, int port, int pool, NTP_Source_Type type, for (i = 0; i < new_sources; i++) { if (i > 0) remote_addr.ip_addr.addr.id = ++last_address_id; - if (add_source(&remote_addr, name, type, params, us->pool_id, cid) != NSR_Success) + if (add_source(&remote_addr, name, family, type, params, us->pool_id, cid) != NSR_Success) return NSR_TooManySources; } @@ -1026,6 +1038,7 @@ resolve_source_replacement(SourceRecord *record, int refreshment) us = MallocNew(struct UnresolvedSource); us->name = Strdup(record->name); + 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 (e.g. falsetickers) in case the order doesn't change, or a group diff --git a/ntp_sources.h b/ntp_sources.h index 5aeb1a3..79daf1d 100644 --- a/ntp_sources.h +++ b/ntp_sources.h @@ -55,9 +55,12 @@ extern NSR_Status NSR_AddSource(NTP_Remote_Address *remote_addr, NTP_Source_Type /* Procedure to add a new server, peer source, or pool of servers specified by name instead of address. The name is resolved in exponentially increasing - intervals until it succeeds or fails with a non-temporary error. If the - name is an address, it is equivalent to NSR_AddSource(). */ -extern NSR_Status NSR_AddSourceByName(char *name, int port, int pool, NTP_Source_Type type, + intervals until it succeeds or fails with a non-temporary error. The + specified family filters resolved addresses. If the name is an address + and its family does not conflict with the specified family, it is equivalent + to NSR_AddSource(). */ +extern NSR_Status NSR_AddSourceByName(char *name, int family, int port, int pool, + NTP_Source_Type type, SourceParameters *params, uint32_t *conf_id); extern const char *NSR_StatusToString(NSR_Status status); diff --git a/stubs.c b/stubs.c index b729c2f..044d17e 100644 --- a/stubs.c +++ b/stubs.c @@ -201,7 +201,7 @@ NSR_AddSource(NTP_Remote_Address *remote_addr, NTP_Source_Type type, } NSR_Status -NSR_AddSourceByName(char *name, int port, int pool, NTP_Source_Type type, +NSR_AddSourceByName(char *name, int family, int port, int pool, NTP_Source_Type type, SourceParameters *params, uint32_t *conf_id) { return NSR_TooManySources; diff --git a/test/unit/ntp_sources.c b/test/unit/ntp_sources.c index e3d7c4d..a9bdbad 100644 --- a/test/unit/ntp_sources.c +++ b/test/unit/ntp_sources.c @@ -125,7 +125,7 @@ void test_unit(void) { char source_line[] = "127.0.0.1 offline", conf[] = "port 0", name[64]; - int i, j, k, slot, found, pool, prev_n; + int i, j, k, family, slot, found, pool, prev_n; uint32_t hash = 0, conf_id; NTP_Remote_Address addrs[256], addr; NTP_Local_Address local_addr; @@ -216,7 +216,7 @@ test_unit(void) TEST_CHECK(n_sources == 0); - status = NSR_AddSourceByName("a b", 0, 0, 0, &source.params, &conf_id); + status = NSR_AddSourceByName("a b", IPADDR_UNSPEC, 0, 0, 0, &source.params, &conf_id); TEST_CHECK(status == NSR_InvalidName); local_addr.ip_addr.family = IPADDR_INET4; @@ -228,11 +228,13 @@ test_unit(void) for (i = 0; i < 500; i++) { for (j = 0; j < 20; j++) { snprintf(name, sizeof (name), "ntp%d.example.net", (int)(random() % 10)); + family = random() % 2 ? IPADDR_UNSPEC : random() % 2 ? IPADDR_INET4 : IPADDR_INET6; pool = random() % 2; prev_n = n_sources; DEBUG_LOG("%d/%d adding source %s pool=%d", i, j, name, pool); - status = NSR_AddSourceByName(name, 0, pool, random() % 2 ? NTP_SERVER : NTP_PEER, + status = NSR_AddSourceByName(name, family, 0, pool, + random() % 2 ? NTP_SERVER : NTP_PEER, &source.params, &conf_id); TEST_CHECK(status == NSR_UnresolvedName); @@ -242,11 +244,13 @@ test_unit(void) for (us = unresolved_sources; us->next; us = us->next) ; TEST_CHECK(strcmp(us->name, name) == 0); + TEST_CHECK(us->family == family); if (pool) { TEST_CHECK(us->address.ip_addr.family == IPADDR_UNSPEC && us->pool_id >= 0); } else { TEST_CHECK(strcmp(NSR_GetName(&us->address.ip_addr), name) == 0); TEST_CHECK(find_slot2(&us->address, &slot) == 2); + TEST_CHECK(get_record(slot)->family == family); } if (random() % 2) {