Allow configuration value for NDots to be zero (#735)

As per Issue #734 some people use `ndots:0` in their configuration which
is allowed by the system resolver but not by c-ares. Add support for
`ndots:0` and add a test case to validate this behavior.

Fixes Issue: #734
Fix By: Brad House (@bradh352)
pull/739/head cares-1_28_0
Brad House 11 months ago committed by GitHub
parent 4cf16268bb
commit 458c937213
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 1
      RELEASE-NOTES.md
  2. 2
      docs/ares_init_options.3
  3. 7
      src/lib/ares_init.c
  4. 2
      src/lib/ares_options.c
  5. 2
      src/lib/ares_private.h
  6. 2
      src/lib/ares_sysconfig.c
  7. 3
      src/lib/ares_sysconfig_files.c
  8. 50
      test/ares-test-mock-ai.cc

@ -28,6 +28,7 @@ Bugfixes:
* Fix a potential memory leak in `ares_init()`. [Issue #724](https://github.com/c-ares/c-ares/issues/724) * Fix a potential memory leak in `ares_init()`. [Issue #724](https://github.com/c-ares/c-ares/issues/724)
* Some platforms don't have the `isascii()` function. Implement as a macro. [PR #721](https://github.com/c-ares/c-ares/pull/721) * Some platforms don't have the `isascii()` function. Implement as a macro. [PR #721](https://github.com/c-ares/c-ares/pull/721)
* CMake: Fix Chain building if CMAKE runtime paths not set * CMake: Fix Chain building if CMAKE runtime paths not set
* NDots configuration should allow a value of zero. [PR #735](https://github.com/c-ares/c-ares/pull/735)
Thanks go to these friendly people for their efforts and contributions for this release: Thanks go to these friendly people for their efforts and contributions for this release:

@ -158,7 +158,7 @@ before giving up. The default is three tries.
The number of dots which must be present in a domain name for it to be The number of dots which must be present in a domain name for it to be
queried for "as is" prior to querying for it with the default domain queried for "as is" prior to querying for it with the default domain
extensions appended. The default value is 1 unless set otherwise by extensions appended. The default value is 1 unless set otherwise by
resolv.conf or the RES_OPTIONS environment variable. resolv.conf or the RES_OPTIONS environment variable. Valid range is 0-15.
.TP 18 .TP 18
.B ARES_OPT_MAXTIMEOUTMS .B ARES_OPT_MAXTIMEOUTMS
.B int \fImaxtimeout\fP; .B int \fImaxtimeout\fP;

@ -152,10 +152,6 @@ static ares_status_t init_by_defaults(ares_channel_t *channel)
channel->tries = DEFAULT_TRIES; channel->tries = DEFAULT_TRIES;
} }
if (channel->ndots == 0) {
channel->ndots = 1;
}
if (ares__slist_len(channel->servers) == 0) { if (ares__slist_len(channel->servers) == 0) {
/* Add a default local named server to the channel unless configured not /* Add a default local named server to the channel unless configured not
* to (in which case return an error). * to (in which case return an error).
@ -284,6 +280,9 @@ int ares_init_options(ares_channel_t **channelptr,
return ARES_ENOMEM; return ARES_ENOMEM;
} }
/* One option where zero is valid, so set default value here */
channel->ndots = 1;
status = ares__channel_threading_init(channel); status = ares__channel_threading_init(channel);
if (status != ARES_SUCCESS) { if (status != ARES_SUCCESS) {
goto done; goto done;

@ -316,7 +316,7 @@ ares_status_t ares__init_by_options(ares_channel_t *channel,
} }
if (optmask & ARES_OPT_NDOTS) { if (optmask & ARES_OPT_NDOTS) {
if (options->ndots <= 0) { if (options->ndots < 0) {
optmask &= ~(ARES_OPT_NDOTS); optmask &= ~(ARES_OPT_NDOTS);
} else { } else {
channel->ndots = (size_t)options->ndots; channel->ndots = (size_t)options->ndots;

@ -581,7 +581,7 @@ void ares_queue_notify_empty(ares_channel_t *channel);
} while (0) } while (0)
#define ARES_CONFIG_CHECK(x) \ #define ARES_CONFIG_CHECK(x) \
(x && x->lookups && ares__slist_len(x->servers) > 0 && x->ndots > 0 && \ (x && x->lookups && ares__slist_len(x->servers) > 0 && \
x->timeout > 0 && x->tries > 0) x->timeout > 0 && x->tries > 0)
ares_bool_t ares__subnet_match(const struct ares_addr *addr, ares_bool_t ares__subnet_match(const struct ares_addr *addr,

@ -954,7 +954,7 @@ static ares_status_t ares__init_sysconfig_libresolv(ares_sysconfig_t *sysconfig)
} }
} }
if (res.ndots > 0) { if (res.ndots >= 0) {
sysconfig->ndots = (size_t)res.ndots; sysconfig->ndots = (size_t)res.ndots;
} }
if (res.retry > 0) { if (res.retry > 0) {

@ -414,9 +414,6 @@ static ares_status_t process_option(ares_sysconfig_t *sysconfig,
} }
if (strcmp(key, "ndots") == 0) { if (strcmp(key, "ndots") == 0) {
if (valint == 0) {
return ARES_EFORMERR;
}
sysconfig->ndots = valint; sysconfig->ndots = valint;
} else if (strcmp(key, "retrans") == 0 || strcmp(key, "timeout") == 0) { } else if (strcmp(key, "retrans") == 0 || strcmp(key, "timeout") == 0) {
if (valint == 0) { if (valint == 0) {

@ -354,6 +354,53 @@ TEST_P(MockExtraOptsNDots5TestAI, SimpleQuery) {
EXPECT_THAT(result.ai_, IncludesV4Address("123.45.67.8")); EXPECT_THAT(result.ai_, IncludesV4Address("123.45.67.8"));
} }
class MockExtraOptsNDots0TestAI : public MockExtraOptsNDotsTestAI {
public:
MockExtraOptsNDots0TestAI() : MockExtraOptsNDotsTestAI(0) {}
};
TEST_P(MockExtraOptsNDots0TestAI, SimpleQuery) {
DNSPacket rsp_ndots0;
rsp_ndots0.set_response().set_aa()
.add_question(new DNSQuestion("ndots0", T_A))
.add_answer(new DNSARR("ndots0", 100, {1, 2, 3, 4}));
ON_CALL(server_, OnRequest("ndots0", T_A))
.WillByDefault(SetReply(&server_, &rsp_ndots0));
DNSPacket rsp_ndots0_first;
rsp_ndots0_first.set_response().set_aa()
.add_question(new DNSQuestion("ndots0.first.com", T_A))
.add_answer(new DNSARR("ndots0.first.com", 100, {99, 99, 99, 99}));
ON_CALL(server_, OnRequest("ndots0.first.com", T_A))
.WillByDefault(SetReply(&server_, &rsp_ndots0_first));
DNSPacket rsp_ndots0_second;
rsp_ndots0_second.set_response().set_aa()
.add_question(new DNSQuestion("ndots0.second.org", T_A))
.add_answer(new DNSARR("ndots0.second.org", 100, {98, 98, 98, 98}));
ON_CALL(server_, OnRequest("ndots0.second.org", T_A))
.WillByDefault(SetReply(&server_, &rsp_ndots0_second));
DNSPacket rsp_ndots0_third;
rsp_ndots0_third.set_response().set_aa()
.add_question(new DNSQuestion("ndots0.third.gov", T_A))
.add_answer(new DNSARR("ndots0.third.gov", 100, {97, 97, 97, 97}));
ON_CALL(server_, OnRequest("ndots0.third.gov", T_A))
.WillByDefault(SetReply(&server_, &rsp_ndots0_third));
AddrInfoResult result;
struct ares_addrinfo_hints hints = {};
hints.ai_family = AF_INET;
hints.ai_flags = ARES_AI_NOSORT;
ares_getaddrinfo(channel_, "ndots0", NULL, &hints, AddrInfoCallback, &result);
Process();
EXPECT_TRUE(result.done_);
EXPECT_EQ(ARES_SUCCESS, result.status_);
std::stringstream ss;
ss << result.ai_;
EXPECT_EQ("{addr=[1.2.3.4]}", ss.str());
}
class MockFlagsChannelOptsTestAI class MockFlagsChannelOptsTestAI
: public MockChannelOptsTest, : public MockChannelOptsTest,
public ::testing::WithParamInterface< std::pair<int, bool> > { public ::testing::WithParamInterface< std::pair<int, bool> > {
@ -762,6 +809,9 @@ INSTANTIATE_TEST_SUITE_P(AddressFamiliesAI, MockExtraOptsTestAI,
INSTANTIATE_TEST_SUITE_P(AddressFamiliesAI, MockExtraOptsNDots5TestAI, INSTANTIATE_TEST_SUITE_P(AddressFamiliesAI, MockExtraOptsNDots5TestAI,
::testing::ValuesIn(ares::test::families_modes), PrintFamilyMode); ::testing::ValuesIn(ares::test::families_modes), PrintFamilyMode);
INSTANTIATE_TEST_SUITE_P(AddressFamiliesAI, MockExtraOptsNDots0TestAI,
::testing::ValuesIn(ares::test::families_modes), PrintFamilyMode);
INSTANTIATE_TEST_SUITE_P(AddressFamiliesAI, MockNoCheckRespChannelTestAI, INSTANTIATE_TEST_SUITE_P(AddressFamiliesAI, MockNoCheckRespChannelTestAI,
::testing::ValuesIn(ares::test::families_modes), PrintFamilyMode); ::testing::ValuesIn(ares::test::families_modes), PrintFamilyMode);

Loading…
Cancel
Save