Compare commits

...

10 Commits

Author SHA1 Message Date
Brad House 6508d6ad27 Empty TXT records were not being preserved (#922) 2 weeks ago
Brad House d0c02eed26 upload provenance separately 2 weeks ago
Brad House c29e75d54c fix SLSA release upload 2 weeks ago
Brad House a69445ef08 release-1.34.3 (#917) 2 weeks ago
Brad House 9114bc8fea Android: <= 7 might require sys/system_properties.h 2 weeks ago
Brad House efd3272543 Some upstream DNS servers are non-compliant with EDNS options 2 weeks ago
Jiwoo Park f89f3cabe4 Silence TSAN, lock before checking `ares_event_thread::isup` (#915) 2 weeks ago
Jiwoo Park 07827dcabe Use `_GNU_SOURCE` macro on Android (#914) 2 weeks ago
Brad House 24793e2e6c ares_getaddrinfo() for AF_UNSPEC should retry if ipv6 received 2 weeks ago
Brad House e0409fb01f rewrite EBADRESP to EBADQUERY on ares_send 2 weeks ago
  1. 28
      .github/workflows/package.yml
  2. 6
      CMakeLists.txt
  3. 31
      RELEASE-NOTES.md
  4. 9
      configure.ac
  5. 4
      include/ares_version.h
  6. 34
      src/lib/ares_getaddrinfo.c
  7. 55
      src/lib/ares_process.c
  8. 5
      src/lib/ares_send.c
  9. 8
      src/lib/event/ares_event_thread.c
  10. 20
      src/lib/record/ares_dns_multistring.c
  11. 66
      test/ares-test-mock-ai.cc
  12. 23
      test/ares-test-mock.cc
  13. 47
      test/ares-test-parse-txt.cc

@ -77,5 +77,31 @@ jobs:
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.0.0
with:
base64-subjects: "${{ needs.build.outputs.hashes }}"
upload-assets: ${{ startsWith(github.ref, 'refs/tags/') }}
upload-tag-name: "${{ needs.build.outputs.version }}"
draft-release: true
# NOTE: Due to issue with duplicating a draft, we need to download the provenance and
# upload it ourselves via the "upload-provenance" step.
# upload-assets: ${{ startsWith(github.ref, 'refs/tags/') }}
upload-assets: false
provenance-name: "c-ares-${{ needs.build.outputs.version }}.intoto.jsonl"
upload-provenance:
needs: [provenance]
runs-on: ubuntu-latest
permissions:
actions: read # To read the workflow path.
contents: write # To add assets to a release.
steps:
- name: Download the provenance
uses: actions/download-artifact@v4
with:
name: ${{needs.provenance.outputs.provenance-name}}
- name: Upload Provenance to Release
uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/')
id: upload-provenance
with:
name: ${{ needs.build.outputs.version }}
draft: true
files: ${{needs.provenance.outputs.provenance-name}}
fail_on_unmatched_files: true

@ -12,7 +12,7 @@ INCLUDE (CheckCSourceCompiles)
INCLUDE (CheckStructHasMember)
INCLUDE (CheckLibraryExists)
PROJECT (c-ares LANGUAGES C VERSION "1.34.2" )
PROJECT (c-ares LANGUAGES C VERSION "1.34.3" )
# Set this version before release
SET (CARES_VERSION "${PROJECT_VERSION}")
@ -30,7 +30,7 @@ INCLUDE (GNUInstallDirs) # include this *AFTER* PROJECT(), otherwise paths are w
# For example, a version of 4:0:2 would generate output such as:
# libname.so -> libname.so.2
# libname.so.2 -> libname.so.2.2.0
SET (CARES_LIB_VERSIONINFO "21:1:19")
SET (CARES_LIB_VERSIONINFO "21:2:19")
OPTION (CARES_STATIC "Build as a static library" OFF)
@ -263,7 +263,7 @@ ENDIF ()
# Set system-specific compiler flags
IF (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
LIST (APPEND SYSFLAGS -D_DARWIN_C_SOURCE)
ELSEIF (CMAKE_SYSTEM_NAME STREQUAL "Linux")
ELSEIF (CMAKE_SYSTEM_NAME STREQUAL "Linux" OR CMAKE_SYSTEM_NAME STREQUAL "Android")
LIST (APPEND SYSFLAGS -D_GNU_SOURCE -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700)
ELSEIF (CMAKE_SYSTEM_NAME STREQUAL "SunOS")
LIST (APPEND SYSFLAGS -D__EXTENSIONS__ -D_REENTRANT -D_XOPEN_SOURCE=600)

@ -1,3 +1,34 @@
## c-ares version 1.34.3 - November 9 2024
This is a bugfix release.
Changes:
* Build the release package in an automated way so we can provide
provenance as per [SLSA3](https://slsa.dev/).
[PR #906](https://github.com/c-ares/c-ares/pull/906)
Bugfixes:
* Some upstream servers are non-compliant with EDNS options, resend queries
without EDNS. [Issue #911](https://github.com/c-ares/c-ares/issues/911)
* Android: <=7 needs sys/system_properties.h
[a70637c](https://github.com/c-ares/c-ares/commit/a70637c)
* Android: CMake needs `-D_GNU_SOURCE` and others.
[PR #915](https://github.com/c-ares/c-ares/pull/914)
* TSAN warns on missing lock, but lock isn't actually necessary.
[PR #915](https://github.com/c-ares/c-ares/pull/915)
* `ares_getaddrinfo()` for `AF_UNSPEC` should retry IPv4 if only IPv6 is
received. [765d558](https://github.com/c-ares/c-ares/commit/765d558)
* `ares_send()` shouldn't return `ARES_EBADRESP`, its `ARES_EBADQUERY`.
[91519e7](https://github.com/c-ares/c-ares/commit/91519e7)
* Fix typos in man pages. [PR #905](https://github.com/c-ares/c-ares/pull/905)
Thanks go to these friendly people for their efforts and contributions for this
release:
* Brad House (@bradh352)
* Jiwoo Park (@jimmy-park)
## c-ares version 1.34.2 - October 15 2024
This release contains a fix for downstream packages detecting the c-ares

@ -2,10 +2,10 @@ dnl Copyright (C) The c-ares project and its contributors
dnl SPDX-License-Identifier: MIT
AC_PREREQ([2.69])
AC_INIT([c-ares], [1.34.2],
AC_INIT([c-ares], [1.34.3],
[c-ares mailing list: http://lists.haxx.se/listinfo/c-ares])
CARES_VERSION_INFO="21:1:19"
CARES_VERSION_INFO="21:2:19"
dnl This flag accepts an argument of the form current[:revision[:age]]. So,
dnl passing -version-info 3:12:1 sets current to 3, revision to 12, and age to
dnl 1.
@ -373,7 +373,7 @@ AS_HELP_STRING([--enable-libgcc],[use libgcc when linking]),
dnl check for a few basic system headers we need. It would be nice if we could
dnl split these on separate lines, but for some reason autotools on Windows doesn't
dnl allow this, even tried ending lines with a backslash.
AC_CHECK_HEADERS([malloc.h memory.h AvailabilityMacros.h sys/types.h sys/time.h sys/select.h sys/socket.h sys/filio.h sys/ioctl.h sys/param.h sys/uio.h sys/random.h sys/event.h sys/epoll.h assert.h iphlpapi.h netioapi.h netdb.h netinet/in.h netinet6/in6.h netinet/tcp.h net/if.h ifaddrs.h fcntl.h errno.h socket.h strings.h stdbool.h time.h poll.h limits.h arpa/nameser.h arpa/nameser_compat.h arpa/inet.h ],
AC_CHECK_HEADERS([malloc.h memory.h AvailabilityMacros.h sys/types.h sys/time.h sys/select.h sys/socket.h sys/filio.h sys/ioctl.h sys/param.h sys/uio.h sys/random.h sys/event.h sys/epoll.h assert.h iphlpapi.h netioapi.h netdb.h netinet/in.h netinet6/in6.h netinet/tcp.h net/if.h ifaddrs.h fcntl.h errno.h socket.h strings.h stdbool.h time.h poll.h limits.h arpa/nameser.h arpa/nameser_compat.h arpa/inet.h sys/system_properties.h ],
dnl to do if not found
[],
dnl to do if found
@ -488,6 +488,9 @@ cares_all_includes="
#ifdef HAVE_RESOLV_H
# include <resolv.h>
#endif
#ifdef HAVE_SYS_SYSTEM_PROPERTIES_H
# include <sys/system_properties.h>
#endif
#ifdef HAVE_IPHLPAPI_H
# include <iphlpapi.h>
#endif

@ -32,8 +32,8 @@
#define ARES_VERSION_MAJOR 1
#define ARES_VERSION_MINOR 34
#define ARES_VERSION_PATCH 2
#define ARES_VERSION_STR "1.34.2"
#define ARES_VERSION_PATCH 3
#define ARES_VERSION_STR "1.34.3"
/* NOTE: We cannot make the version string a C preprocessor stringify operation
* due to assumptions made by integrators that aren't properly using

@ -481,6 +481,18 @@ static void terminate_retries(const struct host_query *hquery,
query->no_retries = ARES_TRUE;
}
static ares_bool_t ai_has_ipv4(struct ares_addrinfo *ai)
{
struct ares_addrinfo_node *node;
for (node = ai->nodes; node != NULL; node = node->ai_next) {
if (node->ai_family == AF_INET) {
return ARES_TRUE;
}
}
return ARES_FALSE;
}
static void host_callback(void *arg, ares_status_t status, size_t timeouts,
const ares_dns_record_t *dnsrec)
{
@ -496,7 +508,27 @@ static void host_callback(void *arg, ares_status_t status, size_t timeouts,
addinfostatus =
ares_parse_into_addrinfo(dnsrec, ARES_TRUE, hquery->port, hquery->ai);
}
if (addinfostatus == ARES_SUCCESS) {
/* We sent out ipv4 and ipv6 requests simultaneously. If we got a
* successful ipv4 response, we want to go ahead and tell the ipv6 request
* that if it fails or times out to not try again since we have the data
* we need.
*
* Our initial implementation of this would terminate retries if we got any
* successful response (ipv4 _or_ ipv6). But we did get some user-reported
* issues with this that had bad system configs and odd behavior:
* https://github.com/alpinelinux/docker-alpine/issues/366
*
* Essentially the ipv6 query succeeded but the ipv4 query failed or timed
* out, and so we only returned the ipv6 address, but the host couldn't
* use ipv6. If we continued to allow ipv4 retries it would have found a
* server that worked and returned both address classes (this is clearly
* unexpected behavior).
*
* At some point down the road if ipv6 actually becomes required and
* reliable we can drop this ipv4 check.
*/
if (addinfostatus == ARES_SUCCESS && ai_has_ipv4(hquery->ai)) {
terminate_retries(hquery, ares_dns_record_get_id(dnsrec));
}
}

@ -650,6 +650,51 @@ done:
return status;
}
static ares_bool_t issue_might_be_edns(const ares_dns_record_t *req,
const ares_dns_record_t *rsp)
{
const ares_dns_rr_t *rr;
/* If we use EDNS and server answers with FORMERR without an OPT RR, the
* protocol extension is not understood by the responder. We must retry the
* query without EDNS enabled. */
if (ares_dns_record_get_rcode(rsp) != ARES_RCODE_FORMERR) {
return ARES_FALSE;
}
rr = ares_dns_get_opt_rr_const(req);
if (rr == NULL) {
/* We didn't send EDNS */
return ARES_FALSE;
}
if (ares_dns_get_opt_rr_const(rsp) == NULL) {
/* Spec says EDNS won't be echo'd back on non-supporting servers, so
* retry without EDNS */
return ARES_TRUE;
}
/* As per issue #911 some non-compliant servers that do indeed support EDNS
* but don't support unrecognized option codes exist. At this point we
* expect them to have also returned an EDNS opt record, but we may remove
* that check in the future. Lets detect this situation if we're sending
* option codes */
if (ares_dns_rr_get_opt_cnt(rr, ARES_RR_OPT_OPTIONS) == 0) {
/* We didn't send any option codes */
return ARES_FALSE;
}
if (ares_dns_get_opt_rr_const(rsp) != NULL) {
/* At this time we're requiring the server to respond with EDNS opt
* records since that's what has been observed in the field. We might
* find in the future we have to remove this, who knows. Lets go
* ahead and force a retry without EDNS*/
return ARES_TRUE;
}
return ARES_FALSE;
}
/* Handle an answer from a server. This must NEVER cleanup the
* server connection! Return something other than ARES_SUCCESS to cause
* the connection to be terminated after this call. */
@ -713,12 +758,10 @@ static ares_status_t process_answer(ares_channel_t *channel,
ares_llist_node_destroy(query->node_queries_to_conn);
query->node_queries_to_conn = NULL;
/* If we use EDNS and server answers with FORMERR without an OPT RR, the
* protocol extension is not understood by the responder. We must retry the
* query without EDNS enabled. */
if (ares_dns_record_get_rcode(rdnsrec) == ARES_RCODE_FORMERR &&
ares_dns_get_opt_rr_const(query->query) != NULL &&
ares_dns_get_opt_rr_const(rdnsrec) == NULL) {
/* There are old servers that don't understand EDNS at all, then some servers
* that have non-compliant implementations. Lets try to detect this sort
* of thing. */
if (issue_might_be_edns(query->query, rdnsrec)) {
status = rewrite_without_edns(query);
if (status != ARES_SUCCESS) {
end_query(channel, server, query, status, NULL);

@ -153,6 +153,11 @@ ares_status_t ares_send_nolock(ares_channel_t *channel, ares_server_t *server,
/* Duplicate Query */
status = ares_dns_record_duplicate_ex(&query->query, dnsrec);
if (status != ARES_SUCCESS) {
/* Sometimes we might get a EBADRESP response from duplicate due to
* the way it works (write and parse), rewrite it to EBADQUERY. */
if (status == ARES_EBADRESP) {
status = ARES_EBADQUERY;
}
ares_free(query);
callback(arg, status, 0, NULL);
return status;

@ -354,15 +354,17 @@ static void *ares_event_thread(void *arg)
ares_process_pending_write(e->channel);
}
/* Relock before we loop again */
ares_thread_mutex_lock(e->mutex);
/* Each iteration should do timeout processing and any other cleanup
* that may not have been performed */
if (e->isup) {
ares_thread_mutex_unlock(e->mutex);
ares_process_fds(e->channel, NULL, 0, ARES_PROCESS_FLAG_NONE);
}
/* Relock before we loop again */
ares_thread_mutex_lock(e->mutex);
}
}
/* Lets cleanup while we're in the thread itself */
ares_event_thread_cleanup(e);

@ -146,6 +146,18 @@ ares_status_t ares_dns_multistring_add_own(ares_dns_multistring_t *strs,
return status;
}
/* Issue #921, ares_dns_multistring_get() doesn't have a way to indicate
* success or fail on a zero-length string which is actually valid. So we
* are going to allocate a 1-byte buffer to use as a placeholder in this
* case */
if (str == NULL) {
str = ares_malloc_zero(1);
if (str == NULL) {
ares_array_remove_last(strs->strs);
return ARES_ENOMEM;
}
}
data->data = str;
data->len = len;
@ -252,10 +264,10 @@ ares_status_t ares_dns_multistring_parse_buf(ares_buf_t *buf,
break; /* LCOV_EXCL_LINE: DefensiveCoding */
}
if (len) {
/* When used by the _str() parser, it really needs to be validated to
* be a valid printable ascii string. Do that here */
if (validate_printable && ares_buf_len(buf) >= len) {
if (len && validate_printable && ares_buf_len(buf) >= len) {
size_t mylen;
const char *data = (const char *)ares_buf_peek(buf, &mylen);
if (!ares_str_isprint(data, len)) {
@ -266,10 +278,12 @@ ares_status_t ares_dns_multistring_parse_buf(ares_buf_t *buf,
if (strs != NULL) {
unsigned char *data = NULL;
if (len) {
status = ares_buf_fetch_bytes_dup(buf, len, ARES_TRUE, &data);
if (status != ARES_SUCCESS) {
break;
}
}
status = ares_dns_multistring_add_own(*strs, data, len);
if (status != ARES_SUCCESS) {
ares_free(data);
@ -281,7 +295,7 @@ ares_status_t ares_dns_multistring_parse_buf(ares_buf_t *buf,
break;
}
}
}
}
if (status != ARES_SUCCESS && strs != NULL) {

@ -841,6 +841,72 @@ class NoRotateMultiMockTestAI : public MockMultiServerChannelTestAI {
NoRotateMultiMockTestAI() : MockMultiServerChannelTestAI(nullptr, ARES_OPT_NOROTATE) {}
};
/* We want to terminate retries of other address classes on getaddrinfo if one
* address class is returned already to return replies faster.
* UPDATE: actually we want to do this only if the address class we received
* was ipv4. We've seen issues if ipv6 was returned but the host was
* really only capable of ipv4.
*/
TEST_P(NoRotateMultiMockTestAI, v4Worksv6Timesout) {
std::vector<byte> nothing;
DNSPacket rsp4;
rsp4.set_response().set_aa()
.add_question(new DNSQuestion("www.example.com", T_A))
.add_answer(new DNSARR("www.example.com", 0x0100, {0x01, 0x02, 0x03, 0x04}));
EXPECT_CALL(*servers_[0], OnRequest("www.example.com", T_A))
.WillOnce(SetReply(servers_[0].get(), &rsp4));
EXPECT_CALL(*servers_[0], OnRequest("www.example.com", T_AAAA))
.WillOnce(SetReplyData(servers_[0].get(), nothing));
AddrInfoResult result;
struct ares_addrinfo_hints hints = {0, 0, 0, 0};
hints.ai_family = AF_UNSPEC;
hints.ai_flags = ARES_AI_NOSORT;
ares_getaddrinfo(channel_, "www.example.com.", NULL, &hints, AddrInfoCallback, &result);
Process();
EXPECT_TRUE(result.done_);
EXPECT_EQ(result.status_, ARES_SUCCESS);
EXPECT_THAT(result.ai_, IncludesNumAddresses(1));
EXPECT_THAT(result.ai_, IncludesV4Address("1.2.3.4"));
}
TEST_P(NoRotateMultiMockTestAI, v6Worksv4TimesoutFirst) {
std::vector<byte> nothing;
DNSPacket rsp4;
rsp4.set_response().set_aa()
.add_question(new DNSQuestion("www.example.com", T_A))
.add_answer(new DNSARR("www.example.com", 0x0100, {0x01, 0x02, 0x03, 0x04}));
DNSPacket rsp6;
rsp6.set_response().set_aa()
.add_question(new DNSQuestion("www.example.com", T_AAAA))
.add_answer(new DNSAaaaRR("www.example.com", 100,
{0x21, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03}));
EXPECT_CALL(*servers_[0], OnRequest("www.example.com", T_A))
.WillOnce(SetReplyData(servers_[0].get(), nothing));
EXPECT_CALL(*servers_[0], OnRequest("www.example.com", T_AAAA))
.WillOnce(SetReply(servers_[0].get(), &rsp6));
EXPECT_CALL(*servers_[1], OnRequest("www.example.com", T_A))
.WillOnce(SetReply(servers_[1].get(), &rsp4));
AddrInfoResult result;
struct ares_addrinfo_hints hints = {0, 0, 0, 0};
hints.ai_family = AF_UNSPEC;
hints.ai_flags = ARES_AI_NOSORT;
ares_getaddrinfo(channel_, "www.example.com.", NULL, &hints, AddrInfoCallback, &result);
Process();
EXPECT_TRUE(result.done_);
EXPECT_EQ(result.status_, ARES_SUCCESS);
EXPECT_THAT(result.ai_, IncludesNumAddresses(2));
EXPECT_THAT(result.ai_, IncludesV4Address("1.2.3.4"));
EXPECT_THAT(result.ai_, IncludesV6Address("2121:0000:0000:0000:0000:0000:0000:0303"));
}
TEST_P(NoRotateMultiMockTestAI, ThirdServer) {
struct ares_options opts;

@ -790,6 +790,29 @@ TEST_P(MockEDNSChannelTest, RetryWithoutEDNS) {
EXPECT_EQ("{'www.google.com' aliases=[] addrs=[1.2.3.4]}", ss.str());
}
// Issue #911
TEST_P(MockUDPChannelTest, RetryWithoutEDNSNonCompliant) {
DNSPacket rspfail;
rspfail.set_response().set_aa().set_rcode(FORMERR)
.add_question(new DNSQuestion("www.google.com", T_A))
.add_additional(new DNSOptRR(0, 0, 0, 1280, { }, { }, false));
DNSPacket rspok;
rspok.set_response()
.add_question(new DNSQuestion("www.google.com", T_A))
.add_answer(new DNSARR("www.google.com", 100, {1, 2, 3, 4}));
EXPECT_CALL(server_, OnRequest("www.google.com", T_A))
.WillOnce(SetReply(&server_, &rspfail))
.WillOnce(SetReply(&server_, &rspok));
HostResult result;
ares_gethostbyname(channel_, "www.google.com.", AF_INET, HostCallback, &result);
Process();
EXPECT_TRUE(result.done_);
std::stringstream ss;
ss << result.host_;
EXPECT_EQ("{'www.google.com' aliases=[] addrs=[1.2.3.4]}", ss.str());
}
TEST_P(MockChannelTest, SearchDomains) {
DNSPacket nofirst;
nofirst.set_response().set_aa().set_rcode(NXDOMAIN)

@ -38,7 +38,7 @@ TEST_F(LibraryTest, ParseTxtReplyOK) {
std::string expected2a = "txt2a";
std::string expected2b("ABC\0ABC", 7);
pkt.set_qid(0x1234).set_response().set_aa()
.add_question(new DNSQuestion("example.com", T_MX))
.add_question(new DNSQuestion("example.com", T_TXT))
.add_answer(new DNSTxtRR("example.com", 100, {expected1}))
.add_answer(new DNSTxtRR("example.com", 100, {expected2a, expected2b}));
std::vector<byte> data = pkt.data();
@ -68,7 +68,7 @@ TEST_F(LibraryTest, ParseTxtExtReplyOK) {
std::string expected2a = "txt2a";
std::string expected2b("ABC\0ABC", 7);
pkt.set_qid(0x1234).set_response().set_aa()
.add_question(new DNSQuestion("example.com", T_MX))
.add_question(new DNSQuestion("example.com", T_TXT))
.add_answer(new DNSTxtRR("example.com", 100, {expected1}))
.add_answer(new DNSTxtRR("example.com", 100, {expected2a, expected2b}));
std::vector<byte> data = pkt.data();
@ -95,6 +95,39 @@ TEST_F(LibraryTest, ParseTxtExtReplyOK) {
ares_free_data(txt);
}
TEST_F(LibraryTest, ParseTxtEmpty) {
DNSPacket pkt;
std::string expected1 = "";
pkt.set_qid(0x1234).set_response().set_aa()
.add_question(new DNSQuestion("example.com", T_TXT))
.add_answer(new DNSTxtRR("example.com", 100, {expected1}));
std::vector<byte> data = pkt.data();
ares_dns_record_t *dnsrec = NULL;
ares_dns_rr_t *rr = NULL;
EXPECT_EQ(ARES_SUCCESS, ares_dns_parse(data.data(), data.size(), 0, &dnsrec));
EXPECT_EQ(1, ares_dns_record_rr_cnt(dnsrec, ARES_SECTION_ANSWER));
rr = ares_dns_record_rr_get(dnsrec, ARES_SECTION_ANSWER, 0);
ASSERT_NE(nullptr, rr);
EXPECT_EQ(ARES_REC_TYPE_TXT, ares_dns_rr_get_type(rr));
size_t txtdata_len;
const unsigned char *txtdata;
/* Using array methodology */
EXPECT_EQ(1, ares_dns_rr_get_abin_cnt(rr, ARES_RR_TXT_DATA));
txtdata = ares_dns_rr_get_abin(rr, ARES_RR_TXT_DATA, 0, &txtdata_len);
EXPECT_EQ(txtdata_len, 0);
EXPECT_NE(nullptr, txtdata);
/* Using combined methodology */
txtdata = ares_dns_rr_get_bin(rr, ARES_RR_TXT_DATA, &txtdata_len);
EXPECT_EQ(txtdata_len, 0);
EXPECT_NE(nullptr, txtdata);
ares_dns_record_destroy(dnsrec); dnsrec = NULL;
}
TEST_F(LibraryTest, ParseTxtMalformedReply1) {
std::vector<byte> data = {
0x12, 0x34, // qid
@ -213,7 +246,7 @@ TEST_F(LibraryTest, ParseTxtReplyErrors) {
std::string expected2a = "txt2a";
std::string expected2b = "txt2b";
pkt.set_qid(0x1234).set_response().set_aa()
.add_question(new DNSQuestion("example.com", T_MX))
.add_question(new DNSQuestion("example.com", T_TXT))
.add_answer(new DNSTxtRR("example.com", 100, {expected1}))
.add_answer(new DNSTxtRR("example.com", 100, {expected1}))
.add_answer(new DNSTxtRR("example.com", 100, {expected2a, expected2b}));
@ -227,7 +260,7 @@ TEST_F(LibraryTest, ParseTxtReplyErrors) {
txt = nullptr;
EXPECT_EQ(ARES_EBADRESP, ares_parse_txt_reply(data.data(), (int)data.size(), &txt));
EXPECT_EQ(nullptr, txt);
pkt.add_question(new DNSQuestion("example.com", T_MX));
pkt.add_question(new DNSQuestion("example.com", T_TXT));
#ifdef DISABLED
// Question != answer
@ -240,13 +273,13 @@ TEST_F(LibraryTest, ParseTxtReplyErrors) {
#endif
// Two questions.
pkt.add_question(new DNSQuestion("example.com", T_MX));
pkt.add_question(new DNSQuestion("example.com", T_TXT));
data = pkt.data();
txt = nullptr;
EXPECT_EQ(ARES_EBADRESP, ares_parse_txt_reply(data.data(), (int)data.size(), &txt));
EXPECT_EQ(nullptr, txt);
pkt.questions_.clear();
pkt.add_question(new DNSQuestion("example.com", T_MX));
pkt.add_question(new DNSQuestion("example.com", T_TXT));
// No answer.
pkt.answers_.clear();
@ -274,7 +307,7 @@ TEST_F(LibraryTest, ParseTxtReplyAllocFail) {
std::string expected2a = "txt2a";
std::string expected2b = "txt2b";
pkt.set_qid(0x1234).set_response().set_aa()
.add_question(new DNSQuestion("example.com", T_MX))
.add_question(new DNSQuestion("example.com", T_TXT))
.add_answer(new DNSCnameRR("example.com", 300, "c.example.com"))
.add_answer(new DNSTxtRR("c.example.com", 100, {expected1}))
.add_answer(new DNSTxtRR("c.example.com", 100, {expected1}))

Loading…
Cancel
Save