From 7a26cb65c1c2136fe1a2a41636ee95587b91633f Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Mon, 25 Jan 2021 00:30:15 -0500 Subject: [PATCH 01/49] add a function to parse a srv reply with ttl This adds a new private srv record struct with a ttl field. It also adds public accessor functions to set all of the fields. Finally, it replicates the ares_parse_srv_reply function to use the new struct and accessors. --- .gitignore | 1 + include/ares.h | 37 ++++++ src/lib/Makefile.inc | 2 + src/lib/ares_data.c | 7 +- src/lib/ares_data.h | 3 + src/lib/ares_parse_srv_reply_ext.c | 173 +++++++++++++++++++++++++++++ src/lib/ares_private.h | 14 +++ src/lib/ares_reply_ext.c | 80 +++++++++++++ test/ares-test-parse-srv.cc | 29 +++++ 9 files changed, 345 insertions(+), 1 deletion(-) create mode 100644 src/lib/ares_parse_srv_reply_ext.c create mode 100644 src/lib/ares_reply_ext.c diff --git a/.gitignore b/.gitignore index 3908e69f25..59c6a660dc 100644 --- a/.gitignore +++ b/.gitignore @@ -54,3 +54,4 @@ CHANGES.dist c-ares-*.tar.gz.asc ares_parse_mx_reply.pdf /[0-9]*.patch +.dirstamp diff --git a/include/ares.h b/include/ares.h index b341d60934..a1e98662a1 100644 --- a/include/ares.h +++ b/include/ares.h @@ -545,6 +545,10 @@ struct ares_srv_reply { unsigned short port; }; +struct ares_srv_ext; + +typedef struct ares_srv_ext ares_srv_ext; + struct ares_mx_reply { struct ares_mx_reply *next; char *host; @@ -665,6 +669,39 @@ CARES_EXTERN int ares_parse_srv_reply(const unsigned char* abuf, int alen, struct ares_srv_reply** srv_out); +CARES_EXTERN int ares_parse_srv_reply_ext(const unsigned char* abuf, + int alen, + struct ares_srv_ext** srv_out); + +CARES_EXTERN struct ares_srv_ext* ares_srv_ext_get_next(const ares_srv_ext* srv_reply); + +CARES_EXTERN char* ares_srv_ext_get_host(const ares_srv_ext* srv_reply); + +CARES_EXTERN unsigned short ares_srv_ext_get_priority(const ares_srv_ext* srv_reply); + +CARES_EXTERN unsigned short ares_srv_ext_get_weight(const ares_srv_ext* srv_reply); + +CARES_EXTERN unsigned short ares_srv_ext_get_port(const ares_srv_ext* srv_reply); + +CARES_EXTERN int ares_srv_ext_get_ttl(const ares_srv_ext* srv_reply); + +CARES_EXTERN void ares_srv_ext_set_next(ares_srv_ext* srv_reply, + struct ares_srv_ext* next); + +CARES_EXTERN void ares_srv_ext_set_host(ares_srv_ext* srv_reply, char* host); + +CARES_EXTERN void ares_srv_ext_set_priority(ares_srv_ext* srv_reply, + const unsigned short priority); + +CARES_EXTERN void ares_srv_ext_set_weight(ares_srv_ext* srv_reply, + const unsigned short weight); + +CARES_EXTERN void ares_srv_ext_set_port(ares_srv_ext* srv_reply, + const unsigned short port); + +CARES_EXTERN void ares_srv_ext_set_ttl(ares_srv_ext* srv_reply, + const int ttl); + CARES_EXTERN int ares_parse_mx_reply(const unsigned char* abuf, int alen, struct ares_mx_reply** mx_out); diff --git a/src/lib/Makefile.inc b/src/lib/Makefile.inc index 51be62cb2e..792af27150 100644 --- a/src/lib/Makefile.inc +++ b/src/lib/Makefile.inc @@ -38,10 +38,12 @@ CSOURCES = ares__close_sockets.c \ ares_parse_ptr_reply.c \ ares_parse_soa_reply.c \ ares_parse_srv_reply.c \ + ares_parse_srv_reply_ext.c \ ares_parse_txt_reply.c \ ares_platform.c \ ares_process.c \ ares_query.c \ + ares_reply_ext.c \ ares_search.c \ ares_send.c \ ares_strcasecmp.c \ diff --git a/src/lib/ares_data.c b/src/lib/ares_data.c index aa925b8b51..d308b56d53 100644 --- a/src/lib/ares_data.c +++ b/src/lib/ares_data.c @@ -70,6 +70,7 @@ void ares_free_data(void *dataptr) break; case ARES_DATATYPE_SRV_REPLY: + case ARES_DATATYPE_SRV_EXT: if (ptr->data.srv_reply.next) next_data = ptr->data.srv_reply.next; @@ -120,7 +121,7 @@ void ares_free_data(void *dataptr) break; case ARES_DATATYPE_CAA_REPLY: - + if (ptr->data.caa_reply.next) next_data = ptr->data.caa_reply.next; if (ptr->data.caa_reply.property) @@ -166,6 +167,10 @@ void *ares_malloc_data(ares_datatype type) ptr->data.mx_reply.priority = 0; break; + case ARES_DATATYPE_SRV_EXT: + ptr->data.srv_ext.ttl = 0; + /* FALLTHROUGH */ + case ARES_DATATYPE_SRV_REPLY: ptr->data.srv_reply.next = NULL; ptr->data.srv_reply.host = NULL; diff --git a/src/lib/ares_data.h b/src/lib/ares_data.h index b0182fd690..682b2ff884 100644 --- a/src/lib/ares_data.h +++ b/src/lib/ares_data.h @@ -14,9 +14,11 @@ * without express or implied warranty. */ +#include "ares_private.h" typedef enum { ARES_DATATYPE_UNKNOWN = 1, /* unknown data type - introduced in 1.7.0 */ ARES_DATATYPE_SRV_REPLY, /* struct ares_srv_reply - introduced in 1.7.0 */ + ARES_DATATYPE_SRV_EXT, /* struct ares_srv_ext */ ARES_DATATYPE_TXT_REPLY, /* struct ares_txt_reply - introduced in 1.7.0 */ ARES_DATATYPE_TXT_EXT, /* struct ares_txt_ext - introduced in 1.11.0 */ ARES_DATATYPE_ADDR_NODE, /* struct ares_addr_node - introduced in 1.7.1 */ @@ -61,6 +63,7 @@ struct ares_data { struct ares_txt_reply txt_reply; struct ares_txt_ext txt_ext; struct ares_srv_reply srv_reply; + struct ares_srv_ext srv_ext; struct ares_addr_node addr_node; struct ares_addr_port_node addr_port_node; struct ares_mx_reply mx_reply; diff --git a/src/lib/ares_parse_srv_reply_ext.c b/src/lib/ares_parse_srv_reply_ext.c new file mode 100644 index 0000000000..3af8d389dc --- /dev/null +++ b/src/lib/ares_parse_srv_reply_ext.c @@ -0,0 +1,173 @@ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * Copyright (C) 2009 by Jakub Hrozek + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" + +#ifdef HAVE_NETINET_IN_H +# include +#endif +#ifdef HAVE_NETDB_H +# include +#endif +#ifdef HAVE_ARPA_INET_H +# include +#endif + +#include "ares_nameser.h" + +#include "ares.h" +#include "ares_dns.h" +#include "ares_data.h" +#include "ares_private.h" + +int +ares_parse_srv_reply_ext (const unsigned char *abuf, int alen, + struct ares_srv_ext **srv_out) +{ + unsigned int qdcount, ancount, i; + const unsigned char *aptr, *vptr; + int status, rr_type, rr_class, rr_ttl, rr_len; + long len; + char *hostname = NULL, *rr_name = NULL; + struct ares_srv_ext *srv_head = NULL; + struct ares_srv_ext *srv_last = NULL; + struct ares_srv_ext *srv_curr; + + /* Set *srv_out to NULL for all failure cases. */ + *srv_out = NULL; + + /* Give up if abuf doesn't have room for a header. */ + if (alen < HFIXEDSZ) + return ARES_EBADRESP; + + /* Fetch the question and answer count from the header. */ + qdcount = DNS_HEADER_QDCOUNT (abuf); + ancount = DNS_HEADER_ANCOUNT (abuf); + if (qdcount != 1) + return ARES_EBADRESP; + if (ancount == 0) + return ARES_ENODATA; + + /* Expand the name from the question, and skip past the question. */ + aptr = abuf + HFIXEDSZ; + status = ares_expand_name (aptr, abuf, alen, &hostname, &len); + if (status != ARES_SUCCESS) + return status; + + if (aptr + len + QFIXEDSZ > abuf + alen) + { + ares_free (hostname); + return ARES_EBADRESP; + } + aptr += len + QFIXEDSZ; + + /* Examine each answer resource record (RR) in turn. */ + for (i = 0; i < ancount; i++) + { + /* Decode the RR up to the data field. */ + status = ares_expand_name (aptr, abuf, alen, &rr_name, &len); + if (status != ARES_SUCCESS) + { + break; + } + aptr += len; + if (aptr + RRFIXEDSZ > abuf + alen) + { + status = ARES_EBADRESP; + break; + } + rr_type = DNS_RR_TYPE (aptr); + rr_class = DNS_RR_CLASS (aptr); + rr_ttl = DNS_RR_TTL (aptr); + rr_len = DNS_RR_LEN (aptr); + aptr += RRFIXEDSZ; + if (aptr + rr_len > abuf + alen) + { + status = ARES_EBADRESP; + break; + } + + /* Check if we are really looking at a SRV record */ + if (rr_class == C_IN && rr_type == T_SRV) + { + /* parse the SRV record itself */ + if (rr_len < 6) + { + status = ARES_EBADRESP; + break; + } + + /* Allocate storage for this SRV answer appending it to the list */ + srv_curr = ares_malloc_data(ARES_DATATYPE_SRV_EXT); + if (!srv_curr) + { + status = ARES_ENOMEM; + break; + } + if (srv_last) + { + srv_last->next = srv_curr; + } + else + { + srv_head = srv_curr; + } + srv_last = srv_curr; + + vptr = aptr; + ares_srv_ext_set_priority(srv_curr, DNS__16BIT(vptr)); + vptr += sizeof(unsigned short); + ares_srv_ext_set_weight(srv_curr, DNS__16BIT(vptr)); + vptr += sizeof(unsigned short); + ares_srv_ext_set_port(srv_curr, DNS__16BIT(vptr)); + vptr += sizeof(unsigned short); + ares_srv_ext_set_ttl(srv_curr, rr_ttl); + + char* srv_host = NULL; + + status = ares_expand_name (vptr, abuf, alen, &srv_host, &len); + printf("srv host: %s\n", srv_host); + ares_srv_ext_set_host(srv_curr, srv_host); + printf("srv curr host: %s\n", ares_srv_ext_get_host(srv_curr)); + if (status != ARES_SUCCESS) + break; + } + + /* Don't lose memory in the next iteration */ + ares_free (rr_name); + rr_name = NULL; + + /* Move on to the next record */ + aptr += rr_len; + } + if (hostname) + ares_free (hostname); + if (rr_name) + ares_free (rr_name); + + /* clean up on error */ + if (status != ARES_SUCCESS) + { + if (srv_head) + ares_free_data (srv_head); + return status; + } + + /* everything looks fine, return the data */ + *srv_out = srv_head; + return ARES_SUCCESS; +} diff --git a/src/lib/ares_private.h b/src/lib/ares_private.h index 50b2ba06e1..fcbd1a9c0f 100644 --- a/src/lib/ares_private.h +++ b/src/lib/ares_private.h @@ -416,4 +416,18 @@ int ares__connect_socket(ares_channel channel, (c)->sock_state_cb((c)->sock_state_cb_data, (s), (r), (w)); \ } WHILE_FALSE +/* Private definition of extended ares srv reply so that c-ares users + * only have access to the type definition in ares.h and must use + * accessor functions to interact with the struct. This way, + * ares_srv_reply_ext can be modified without breaking ABI. + */ + struct ares_srv_ext { + struct ares_srv_ext *next; + char *host; + unsigned short priority; + unsigned short weight; + unsigned short port; + int ttl; +}; + #endif /* __ARES_PRIVATE_H */ diff --git a/src/lib/ares_reply_ext.c b/src/lib/ares_reply_ext.c new file mode 100644 index 0000000000..29a2ef15f4 --- /dev/null +++ b/src/lib/ares_reply_ext.c @@ -0,0 +1,80 @@ +/* Copyright (C) 2021 by Kyle Evans + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. M.I.T. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" +#include "ares.h" +#include "ares_private.h" + +struct ares_srv_ext* ares_srv_ext_get_next(const struct ares_srv_ext* srv_reply) +{ + return srv_reply->next; +} + +char* ares_srv_ext_get_host(const struct ares_srv_ext* srv_reply) +{ + return srv_reply->host; +} + +unsigned short ares_srv_ext_get_priority(const struct ares_srv_ext* srv_reply) +{ + return srv_reply->priority; +} + +unsigned short ares_srv_ext_get_weight(const struct ares_srv_ext* srv_reply) +{ + return srv_reply->weight; +} + +unsigned short ares_srv_ext_get_port(const struct ares_srv_ext* srv_reply) +{ + return srv_reply->port; +} + +int ares_srv_ext_get_ttl(const struct ares_srv_ext* srv_reply) +{ + return srv_reply->ttl; +} + +void ares_srv_ext_set_next(struct ares_srv_ext* srv_reply, + struct ares_srv_ext* next) +{ + srv_reply->next = next; +} + +void ares_srv_ext_set_host(struct ares_srv_ext* srv_reply, char* host) +{ + srv_reply->host = host; +} + +void ares_srv_ext_set_priority(struct ares_srv_ext* srv_reply, + const unsigned short priority) +{ + srv_reply->priority = priority; +} + +void ares_srv_ext_set_weight(struct ares_srv_ext* srv_reply, + const unsigned short weight) +{ + srv_reply->weight = weight; +} + +void ares_srv_ext_set_port(struct ares_srv_ext* srv_reply, + const unsigned short port) +{ + srv_reply->port = port; +} + +void ares_srv_ext_set_ttl(struct ares_srv_ext* srv_reply, const int ttl) +{ + srv_reply->ttl = ttl; +} diff --git a/test/ares-test-parse-srv.cc b/test/ares-test-parse-srv.cc index b004759801..2775be920a 100644 --- a/test/ares-test-parse-srv.cc +++ b/test/ares-test-parse-srv.cc @@ -35,6 +35,35 @@ TEST_F(LibraryTest, ParseSrvReplyOK) { ares_free_data(srv); } +TEST_F(LibraryTest, ParseSrvExtReplyOK) { + DNSPacket pkt; + pkt.set_qid(0x1234).set_response().set_aa() + .add_question(new DNSQuestion("example.com", T_SRV)) + .add_answer(new DNSSrvRR("example.com", 100, 10, 20, 30, "srv.example.com")) + .add_answer(new DNSSrvRR("example.com", 100, 11, 21, 31, "srv2.example.com")); + std::vector data = pkt.data(); + + struct ares_srv_ext* srv = nullptr; + EXPECT_EQ(ARES_SUCCESS, ares_parse_srv_reply_ext(data.data(), data.size(), &srv)); + ASSERT_NE(nullptr, srv); + + EXPECT_EQ("srv.example.com", std::string(ares_srv_ext_get_host(srv))); + EXPECT_EQ(10, ares_srv_ext_get_priority(srv)); + EXPECT_EQ(20, ares_srv_ext_get_weight(srv)); + EXPECT_EQ(30, ares_srv_ext_get_port(srv)); + EXPECT_EQ(100, ares_srv_ext_get_ttl(srv)); + + struct ares_srv_ext* srv2 = ares_srv_ext_get_next(srv); + ASSERT_NE(nullptr, srv2); + EXPECT_EQ("srv2.example.com", std::string(ares_srv_ext_get_host(srv2))); + EXPECT_EQ(11, ares_srv_ext_get_priority(srv2)); + EXPECT_EQ(21, ares_srv_ext_get_weight(srv2)); + EXPECT_EQ(31, ares_srv_ext_get_port(srv2)); + EXPECT_EQ(100, ares_srv_ext_get_ttl(srv2)); + EXPECT_EQ(nullptr, ares_srv_ext_get_next(srv2)); + ares_free_data(srv); +} + TEST_F(LibraryTest, ParseSrvReplySingle) { DNSPacket pkt; pkt.set_qid(0x1234).set_response().set_aa() From 4c9f2b628e98351c8f16195874b00dd32d668a8b Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Mon, 25 Jan 2021 00:47:06 -0500 Subject: [PATCH 02/49] remove print statements --- src/lib/ares_parse_srv_reply_ext.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/lib/ares_parse_srv_reply_ext.c b/src/lib/ares_parse_srv_reply_ext.c index 3af8d389dc..32541935b4 100644 --- a/src/lib/ares_parse_srv_reply_ext.c +++ b/src/lib/ares_parse_srv_reply_ext.c @@ -140,9 +140,7 @@ ares_parse_srv_reply_ext (const unsigned char *abuf, int alen, char* srv_host = NULL; status = ares_expand_name (vptr, abuf, alen, &srv_host, &len); - printf("srv host: %s\n", srv_host); ares_srv_ext_set_host(srv_curr, srv_host); - printf("srv curr host: %s\n", ares_srv_ext_get_host(srv_curr)); if (status != ARES_SUCCESS) break; } From ab6677827517d3a3032156868643d01ac86ee959 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Sat, 30 Jan 2021 10:46:14 -0500 Subject: [PATCH 03/49] make ares_parse_srv_reply a wrapper for cares_parse_srv_reply --- include/ares.h | 59 ++-- src/lib/Makefile.inc | 4 +- src/lib/ares_data.c | 7 +- src/lib/ares_data.h | 4 +- src/lib/ares_parse_srv_reply.c | 159 ++++------ src/lib/ares_private.h | 18 +- ...rv_reply_ext.c => cares_parse_srv_reply.c} | 22 +- src/lib/{ares_reply_ext.c => cares_reply.c} | 37 ++- test/ares-test-parse-srv.cc | 292 ++++++++++++++++-- 9 files changed, 407 insertions(+), 195 deletions(-) rename src/lib/{ares_parse_srv_reply_ext.c => cares_parse_srv_reply.c} (87%) rename src/lib/{ares_reply_ext.c => cares_reply.c} (53%) diff --git a/include/ares.h b/include/ares.h index a1e98662a1..21101fd7e5 100644 --- a/include/ares.h +++ b/include/ares.h @@ -545,9 +545,9 @@ struct ares_srv_reply { unsigned short port; }; -struct ares_srv_ext; +struct cares_srv_reply; -typedef struct ares_srv_ext ares_srv_ext; +typedef struct cares_srv_reply cares_srv_reply; struct ares_mx_reply { struct ares_mx_reply *next; @@ -651,8 +651,8 @@ CARES_EXTERN int ares_parse_aaaa_reply(const unsigned char *abuf, int *naddrttls); CARES_EXTERN int ares_parse_caa_reply(const unsigned char* abuf, - int alen, - struct ares_caa_reply** caa_out); + int alen, + struct ares_caa_reply** caa_out); CARES_EXTERN int ares_parse_ptr_reply(const unsigned char *abuf, int alen, @@ -669,42 +669,47 @@ CARES_EXTERN int ares_parse_srv_reply(const unsigned char* abuf, int alen, struct ares_srv_reply** srv_out); -CARES_EXTERN int ares_parse_srv_reply_ext(const unsigned char* abuf, +CARES_EXTERN int cares_parse_srv_reply(const unsigned char* abuf, int alen, - struct ares_srv_ext** srv_out); + struct cares_srv_reply** srv_out); -CARES_EXTERN struct ares_srv_ext* ares_srv_ext_get_next(const ares_srv_ext* srv_reply); +CARES_EXTERN struct cares_srv_reply* +cares_srv_reply_get_next(const cares_srv_reply* srv_reply); -CARES_EXTERN char* ares_srv_ext_get_host(const ares_srv_ext* srv_reply); +CARES_EXTERN char* cares_srv_reply_get_host(const cares_srv_reply* srv_reply); -CARES_EXTERN unsigned short ares_srv_ext_get_priority(const ares_srv_ext* srv_reply); +CARES_EXTERN unsigned short +cares_srv_reply_get_priority(const cares_srv_reply* srv_reply); -CARES_EXTERN unsigned short ares_srv_ext_get_weight(const ares_srv_ext* srv_reply); +CARES_EXTERN unsigned short +cares_srv_reply_get_weight(const cares_srv_reply* srv_reply); -CARES_EXTERN unsigned short ares_srv_ext_get_port(const ares_srv_ext* srv_reply); +CARES_EXTERN unsigned short +cares_srv_reply_get_port(const cares_srv_reply* srv_reply); -CARES_EXTERN int ares_srv_ext_get_ttl(const ares_srv_ext* srv_reply); +CARES_EXTERN int cares_srv_reply_get_ttl(const cares_srv_reply* srv_reply); -CARES_EXTERN void ares_srv_ext_set_next(ares_srv_ext* srv_reply, - struct ares_srv_ext* next); +CARES_EXTERN void cares_srv_reply_set_next(cares_srv_reply* srv_reply, + struct cares_srv_reply* next); -CARES_EXTERN void ares_srv_ext_set_host(ares_srv_ext* srv_reply, char* host); +CARES_EXTERN void +cares_srv_reply_set_host(cares_srv_reply* srv_reply, char* host); -CARES_EXTERN void ares_srv_ext_set_priority(ares_srv_ext* srv_reply, - const unsigned short priority); +CARES_EXTERN void cares_srv_reply_set_priority(cares_srv_reply* srv_reply, + const unsigned short priority); -CARES_EXTERN void ares_srv_ext_set_weight(ares_srv_ext* srv_reply, - const unsigned short weight); +CARES_EXTERN void cares_srv_reply_set_weight(cares_srv_reply* srv_reply, + const unsigned short weight); -CARES_EXTERN void ares_srv_ext_set_port(ares_srv_ext* srv_reply, - const unsigned short port); +CARES_EXTERN void cares_srv_reply_set_port(cares_srv_reply* srv_reply, + const unsigned short port); -CARES_EXTERN void ares_srv_ext_set_ttl(ares_srv_ext* srv_reply, - const int ttl); +CARES_EXTERN void cares_srv_reply_set_ttl(cares_srv_reply* srv_reply, + const int ttl); CARES_EXTERN int ares_parse_mx_reply(const unsigned char* abuf, - int alen, - struct ares_mx_reply** mx_out); + int alen, + struct ares_mx_reply** mx_out); CARES_EXTERN int ares_parse_txt_reply(const unsigned char* abuf, int alen, @@ -719,8 +724,8 @@ CARES_EXTERN int ares_parse_naptr_reply(const unsigned char* abuf, struct ares_naptr_reply** naptr_out); CARES_EXTERN int ares_parse_soa_reply(const unsigned char* abuf, - int alen, - struct ares_soa_reply** soa_out); + int alen, + struct ares_soa_reply** soa_out); CARES_EXTERN void ares_free_string(void *str); diff --git a/src/lib/Makefile.inc b/src/lib/Makefile.inc index 792af27150..284e0ab342 100644 --- a/src/lib/Makefile.inc +++ b/src/lib/Makefile.inc @@ -38,12 +38,12 @@ CSOURCES = ares__close_sockets.c \ ares_parse_ptr_reply.c \ ares_parse_soa_reply.c \ ares_parse_srv_reply.c \ - ares_parse_srv_reply_ext.c \ + cares_parse_srv_reply.c \ ares_parse_txt_reply.c \ ares_platform.c \ ares_process.c \ ares_query.c \ - ares_reply_ext.c \ + cares_reply.c \ ares_search.c \ ares_send.c \ ares_strcasecmp.c \ diff --git a/src/lib/ares_data.c b/src/lib/ares_data.c index d308b56d53..3dfb41d459 100644 --- a/src/lib/ares_data.c +++ b/src/lib/ares_data.c @@ -34,6 +34,7 @@ ** function is: ** ** ares_get_servers() +** cares_parse_srv_reply() ** ares_parse_srv_reply() ** ares_parse_txt_reply() */ @@ -70,7 +71,7 @@ void ares_free_data(void *dataptr) break; case ARES_DATATYPE_SRV_REPLY: - case ARES_DATATYPE_SRV_EXT: + case ARES_DATATYPE_CSRV_REPLY: if (ptr->data.srv_reply.next) next_data = ptr->data.srv_reply.next; @@ -167,8 +168,8 @@ void *ares_malloc_data(ares_datatype type) ptr->data.mx_reply.priority = 0; break; - case ARES_DATATYPE_SRV_EXT: - ptr->data.srv_ext.ttl = 0; + case ARES_DATATYPE_CSRV_REPLY: + ptr->data.csrv_reply.ttl = 0; /* FALLTHROUGH */ case ARES_DATATYPE_SRV_REPLY: diff --git a/src/lib/ares_data.h b/src/lib/ares_data.h index 682b2ff884..d3bff954fb 100644 --- a/src/lib/ares_data.h +++ b/src/lib/ares_data.h @@ -18,7 +18,7 @@ typedef enum { ARES_DATATYPE_UNKNOWN = 1, /* unknown data type - introduced in 1.7.0 */ ARES_DATATYPE_SRV_REPLY, /* struct ares_srv_reply - introduced in 1.7.0 */ - ARES_DATATYPE_SRV_EXT, /* struct ares_srv_ext */ + ARES_DATATYPE_CSRV_REPLY, /* struct cares_srv_reply */ ARES_DATATYPE_TXT_REPLY, /* struct ares_txt_reply - introduced in 1.7.0 */ ARES_DATATYPE_TXT_EXT, /* struct ares_txt_ext - introduced in 1.11.0 */ ARES_DATATYPE_ADDR_NODE, /* struct ares_addr_node - introduced in 1.7.1 */ @@ -63,7 +63,7 @@ struct ares_data { struct ares_txt_reply txt_reply; struct ares_txt_ext txt_ext; struct ares_srv_reply srv_reply; - struct ares_srv_ext srv_ext; + struct cares_srv_reply csrv_reply; struct ares_addr_node addr_node; struct ares_addr_port_node addr_port_node; struct ares_mx_reply mx_reply; diff --git a/src/lib/ares_parse_srv_reply.c b/src/lib/ares_parse_srv_reply.c index 0d8f4d2098..95c28249f2 100644 --- a/src/lib/ares_parse_srv_reply.c +++ b/src/lib/ares_parse_srv_reply.c @@ -38,128 +38,73 @@ int ares_parse_srv_reply (const unsigned char *abuf, int alen, struct ares_srv_reply **srv_out) { - unsigned int qdcount, ancount, i; - const unsigned char *aptr, *vptr; - int status, rr_type, rr_class, rr_len; - long len; - char *hostname = NULL, *rr_name = NULL; + + /* call cares_parse_srv_reply, iterate through the result and + * create a linked list of struct ares_srv_reply to return */ + + int status; struct ares_srv_reply *srv_head = NULL; + struct ares_srv_reply *srv_curr = NULL; struct ares_srv_reply *srv_last = NULL; - struct ares_srv_reply *srv_curr; + struct cares_srv_reply *csrv_curr = NULL; + struct cares_srv_reply *csrv_out = NULL; /* Set *srv_out to NULL for all failure cases. */ *srv_out = NULL; - /* Give up if abuf doesn't have room for a header. */ - if (alen < HFIXEDSZ) - return ARES_EBADRESP; - - /* Fetch the question and answer count from the header. */ - qdcount = DNS_HEADER_QDCOUNT (abuf); - ancount = DNS_HEADER_ANCOUNT (abuf); - if (qdcount != 1) - return ARES_EBADRESP; - if (ancount == 0) - return ARES_ENODATA; - - /* Expand the name from the question, and skip past the question. */ - aptr = abuf + HFIXEDSZ; - status = ares_expand_name (aptr, abuf, alen, &hostname, &len); + status = cares_parse_srv_reply(abuf, alen, &csrv_out); + + /* clean up on error */ if (status != ARES_SUCCESS) + { + if (srv_out) + ares_free_data (*srv_out); return status; - - if (aptr + len + QFIXEDSZ > abuf + alen) + } + + /* iterate through the cares_srv_reply list and + * create a new ares_srv_reply */ + for (csrv_curr = csrv_out; csrv_curr; + csrv_curr = cares_srv_reply_get_next(csrv_curr)) + { + srv_curr = ares_malloc_data(ARES_DATATYPE_SRV_REPLY); + if (!srv_curr) { - ares_free (hostname); - return ARES_EBADRESP; + status = ARES_ENOMEM; + break; } - aptr += len + QFIXEDSZ; - - /* Examine each answer resource record (RR) in turn. */ - for (i = 0; i < ancount; i++) + if (srv_last) + { + srv_last->next = srv_curr; + } + else + { + srv_head = srv_curr; + } + srv_last = srv_curr; + srv_curr->host = cares_srv_reply_get_host(csrv_curr); + if (!srv_curr->host) { - /* Decode the RR up to the data field. */ - status = ares_expand_name (aptr, abuf, alen, &rr_name, &len); - if (status != ARES_SUCCESS) - { - break; - } - aptr += len; - if (aptr + RRFIXEDSZ > abuf + alen) - { - status = ARES_EBADRESP; - break; - } - rr_type = DNS_RR_TYPE (aptr); - rr_class = DNS_RR_CLASS (aptr); - rr_len = DNS_RR_LEN (aptr); - aptr += RRFIXEDSZ; - if (aptr + rr_len > abuf + alen) - { - status = ARES_EBADRESP; - break; - } - - /* Check if we are really looking at a SRV record */ - if (rr_class == C_IN && rr_type == T_SRV) - { - /* parse the SRV record itself */ - if (rr_len < 6) - { - status = ARES_EBADRESP; - break; - } - - /* Allocate storage for this SRV answer appending it to the list */ - srv_curr = ares_malloc_data(ARES_DATATYPE_SRV_REPLY); - if (!srv_curr) - { - status = ARES_ENOMEM; - break; - } - if (srv_last) - { - srv_last->next = srv_curr; - } - else - { - srv_head = srv_curr; - } - srv_last = srv_curr; - - vptr = aptr; - srv_curr->priority = DNS__16BIT(vptr); - vptr += sizeof(unsigned short); - srv_curr->weight = DNS__16BIT(vptr); - vptr += sizeof(unsigned short); - srv_curr->port = DNS__16BIT(vptr); - vptr += sizeof(unsigned short); - - status = ares_expand_name (vptr, abuf, alen, &srv_curr->host, &len); - if (status != ARES_SUCCESS) - break; - } - - /* Don't lose memory in the next iteration */ - ares_free (rr_name); - rr_name = NULL; - - /* Move on to the next record */ - aptr += rr_len; + status = ARES_ENOMEM; + break; } + srv_curr->priority = cares_srv_reply_get_priority(csrv_curr); + srv_curr->weight = cares_srv_reply_get_weight(csrv_curr); + srv_curr->port = cares_srv_reply_get_port(csrv_curr); + } - if (hostname) - ares_free (hostname); - if (rr_name) - ares_free (rr_name); + if (csrv_out) + { + ares_free_data (csrv_out); + } - /* clean up on error */ + /* clean up on error */ if (status != ARES_SUCCESS) - { - if (srv_head) - ares_free_data (srv_head); - return status; - } + { + if (srv_head) + ares_free_data (srv_head); + return status; + } /* everything looks fine, return the data */ *srv_out = srv_head; diff --git a/src/lib/ares_private.h b/src/lib/ares_private.h index fcbd1a9c0f..c9544b69b6 100644 --- a/src/lib/ares_private.h +++ b/src/lib/ares_private.h @@ -416,18 +416,18 @@ int ares__connect_socket(ares_channel channel, (c)->sock_state_cb((c)->sock_state_cb_data, (s), (r), (w)); \ } WHILE_FALSE -/* Private definition of extended ares srv reply so that c-ares users +/* Private definition of c-ares srv reply so that c-ares users * only have access to the type definition in ares.h and must use * accessor functions to interact with the struct. This way, - * ares_srv_reply_ext can be modified without breaking ABI. + * cares_srv_reply can be modified without breaking ABI. */ - struct ares_srv_ext { - struct ares_srv_ext *next; - char *host; - unsigned short priority; - unsigned short weight; - unsigned short port; - int ttl; + struct cares_srv_reply { + struct cares_srv_reply *next; + char *host; + unsigned short priority; + unsigned short weight; + unsigned short port; + int ttl; }; #endif /* __ARES_PRIVATE_H */ diff --git a/src/lib/ares_parse_srv_reply_ext.c b/src/lib/cares_parse_srv_reply.c similarity index 87% rename from src/lib/ares_parse_srv_reply_ext.c rename to src/lib/cares_parse_srv_reply.c index 32541935b4..5e11f92c3a 100644 --- a/src/lib/ares_parse_srv_reply_ext.c +++ b/src/lib/cares_parse_srv_reply.c @@ -35,17 +35,17 @@ #include "ares_private.h" int -ares_parse_srv_reply_ext (const unsigned char *abuf, int alen, - struct ares_srv_ext **srv_out) +cares_parse_srv_reply (const unsigned char *abuf, int alen, + struct cares_srv_reply **srv_out) { unsigned int qdcount, ancount, i; const unsigned char *aptr, *vptr; int status, rr_type, rr_class, rr_ttl, rr_len; long len; char *hostname = NULL, *rr_name = NULL; - struct ares_srv_ext *srv_head = NULL; - struct ares_srv_ext *srv_last = NULL; - struct ares_srv_ext *srv_curr; + struct cares_srv_reply *srv_head = NULL; + struct cares_srv_reply *srv_last = NULL; + struct cares_srv_reply *srv_curr; /* Set *srv_out to NULL for all failure cases. */ *srv_out = NULL; @@ -112,7 +112,7 @@ ares_parse_srv_reply_ext (const unsigned char *abuf, int alen, } /* Allocate storage for this SRV answer appending it to the list */ - srv_curr = ares_malloc_data(ARES_DATATYPE_SRV_EXT); + srv_curr = ares_malloc_data(ARES_DATATYPE_CSRV_REPLY); if (!srv_curr) { status = ARES_ENOMEM; @@ -129,20 +129,20 @@ ares_parse_srv_reply_ext (const unsigned char *abuf, int alen, srv_last = srv_curr; vptr = aptr; - ares_srv_ext_set_priority(srv_curr, DNS__16BIT(vptr)); + cares_srv_reply_set_priority(srv_curr, DNS__16BIT(vptr)); vptr += sizeof(unsigned short); - ares_srv_ext_set_weight(srv_curr, DNS__16BIT(vptr)); + cares_srv_reply_set_weight(srv_curr, DNS__16BIT(vptr)); vptr += sizeof(unsigned short); - ares_srv_ext_set_port(srv_curr, DNS__16BIT(vptr)); + cares_srv_reply_set_port(srv_curr, DNS__16BIT(vptr)); vptr += sizeof(unsigned short); - ares_srv_ext_set_ttl(srv_curr, rr_ttl); + cares_srv_reply_set_ttl(srv_curr, rr_ttl); char* srv_host = NULL; status = ares_expand_name (vptr, abuf, alen, &srv_host, &len); - ares_srv_ext_set_host(srv_curr, srv_host); if (status != ARES_SUCCESS) break; + cares_srv_reply_set_host(srv_curr, srv_host); } /* Don't lose memory in the next iteration */ diff --git a/src/lib/ares_reply_ext.c b/src/lib/cares_reply.c similarity index 53% rename from src/lib/ares_reply_ext.c rename to src/lib/cares_reply.c index 29a2ef15f4..5e4c550f81 100644 --- a/src/lib/ares_reply_ext.c +++ b/src/lib/cares_reply.c @@ -14,67 +14,76 @@ #include "ares_setup.h" #include "ares.h" #include "ares_private.h" +#include "string.h" -struct ares_srv_ext* ares_srv_ext_get_next(const struct ares_srv_ext* srv_reply) +struct cares_srv_reply* +cares_srv_reply_get_next(const struct cares_srv_reply* srv_reply) { return srv_reply->next; } -char* ares_srv_ext_get_host(const struct ares_srv_ext* srv_reply) +char* cares_srv_reply_get_host(const struct cares_srv_reply* srv_reply) { - return srv_reply->host; + char *newhost = NULL; + if ((newhost = malloc(strlen(srv_reply->host) + 1)) != NULL) { + strcpy(newhost, srv_reply->host); + } + return newhost; } -unsigned short ares_srv_ext_get_priority(const struct ares_srv_ext* srv_reply) +unsigned short +cares_srv_reply_get_priority(const struct cares_srv_reply* srv_reply) { return srv_reply->priority; } -unsigned short ares_srv_ext_get_weight(const struct ares_srv_ext* srv_reply) +unsigned short +cares_srv_reply_get_weight(const struct cares_srv_reply* srv_reply) { return srv_reply->weight; } -unsigned short ares_srv_ext_get_port(const struct ares_srv_ext* srv_reply) +unsigned short +cares_srv_reply_get_port(const struct cares_srv_reply* srv_reply) { return srv_reply->port; } -int ares_srv_ext_get_ttl(const struct ares_srv_ext* srv_reply) +int cares_srv_reply_get_ttl(const struct cares_srv_reply* srv_reply) { return srv_reply->ttl; } -void ares_srv_ext_set_next(struct ares_srv_ext* srv_reply, - struct ares_srv_ext* next) +void cares_srv_reply_set_next(struct cares_srv_reply* srv_reply, + struct cares_srv_reply* next) { srv_reply->next = next; } -void ares_srv_ext_set_host(struct ares_srv_ext* srv_reply, char* host) +void cares_srv_reply_set_host(struct cares_srv_reply* srv_reply, char* host) { srv_reply->host = host; } -void ares_srv_ext_set_priority(struct ares_srv_ext* srv_reply, +void cares_srv_reply_set_priority(struct cares_srv_reply* srv_reply, const unsigned short priority) { srv_reply->priority = priority; } -void ares_srv_ext_set_weight(struct ares_srv_ext* srv_reply, +void cares_srv_reply_set_weight(struct cares_srv_reply* srv_reply, const unsigned short weight) { srv_reply->weight = weight; } -void ares_srv_ext_set_port(struct ares_srv_ext* srv_reply, +void cares_srv_reply_set_port(struct cares_srv_reply* srv_reply, const unsigned short port) { srv_reply->port = port; } -void ares_srv_ext_set_ttl(struct ares_srv_ext* srv_reply, const int ttl) +void cares_srv_reply_set_ttl(struct cares_srv_reply* srv_reply, const int ttl) { srv_reply->ttl = ttl; } diff --git a/test/ares-test-parse-srv.cc b/test/ares-test-parse-srv.cc index 2775be920a..29bc1b5dec 100644 --- a/test/ares-test-parse-srv.cc +++ b/test/ares-test-parse-srv.cc @@ -35,7 +35,7 @@ TEST_F(LibraryTest, ParseSrvReplyOK) { ares_free_data(srv); } -TEST_F(LibraryTest, ParseSrvExtReplyOK) { +TEST_F(LibraryTest, ParseCSrvReplyOK) { DNSPacket pkt; pkt.set_qid(0x1234).set_response().set_aa() .add_question(new DNSQuestion("example.com", T_SRV)) @@ -43,24 +43,24 @@ TEST_F(LibraryTest, ParseSrvExtReplyOK) { .add_answer(new DNSSrvRR("example.com", 100, 11, 21, 31, "srv2.example.com")); std::vector data = pkt.data(); - struct ares_srv_ext* srv = nullptr; - EXPECT_EQ(ARES_SUCCESS, ares_parse_srv_reply_ext(data.data(), data.size(), &srv)); + struct cares_srv_reply* srv = nullptr; + EXPECT_EQ(ARES_SUCCESS, cares_parse_srv_reply(data.data(), data.size(), &srv)); ASSERT_NE(nullptr, srv); - EXPECT_EQ("srv.example.com", std::string(ares_srv_ext_get_host(srv))); - EXPECT_EQ(10, ares_srv_ext_get_priority(srv)); - EXPECT_EQ(20, ares_srv_ext_get_weight(srv)); - EXPECT_EQ(30, ares_srv_ext_get_port(srv)); - EXPECT_EQ(100, ares_srv_ext_get_ttl(srv)); + EXPECT_EQ("srv.example.com", std::string(std::unique_ptr(cares_srv_reply_get_host(srv)).get())); + EXPECT_EQ(10, cares_srv_reply_get_priority(srv)); + EXPECT_EQ(20, cares_srv_reply_get_weight(srv)); + EXPECT_EQ(30, cares_srv_reply_get_port(srv)); + EXPECT_EQ(100, cares_srv_reply_get_ttl(srv)); - struct ares_srv_ext* srv2 = ares_srv_ext_get_next(srv); + struct cares_srv_reply* srv2 = cares_srv_reply_get_next(srv); ASSERT_NE(nullptr, srv2); - EXPECT_EQ("srv2.example.com", std::string(ares_srv_ext_get_host(srv2))); - EXPECT_EQ(11, ares_srv_ext_get_priority(srv2)); - EXPECT_EQ(21, ares_srv_ext_get_weight(srv2)); - EXPECT_EQ(31, ares_srv_ext_get_port(srv2)); - EXPECT_EQ(100, ares_srv_ext_get_ttl(srv2)); - EXPECT_EQ(nullptr, ares_srv_ext_get_next(srv2)); + EXPECT_EQ("srv2.example.com", std::string(cares_srv_reply_get_host(srv2))); + EXPECT_EQ(11, cares_srv_reply_get_priority(srv2)); + EXPECT_EQ(21, cares_srv_reply_get_weight(srv2)); + EXPECT_EQ(31, cares_srv_reply_get_port(srv2)); + EXPECT_EQ(100, cares_srv_reply_get_ttl(srv2)); + EXPECT_EQ(nullptr, cares_srv_reply_get_next(srv2)); ares_free_data(srv); } @@ -91,6 +91,34 @@ TEST_F(LibraryTest, ParseSrvReplySingle) { ares_free_data(srv); } +TEST_F(LibraryTest, ParseCSrvReplySingle) { + DNSPacket pkt; + pkt.set_qid(0x1234).set_response().set_aa() + .add_question(new DNSQuestion("example.abc.def.com", T_SRV)) + .add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")) + .add_auth(new DNSNsRR("abc.def.com", 44, "else1.where.com")) + .add_auth(new DNSNsRR("abc.def.com", 44, "else2.where.com")) + .add_auth(new DNSNsRR("abc.def.com", 44, "else3.where.com")) + .add_auth(new DNSNsRR("abc.def.com", 44, "else4.where.com")) + .add_auth(new DNSNsRR("abc.def.com", 44, "else5.where.com")) + .add_additional(new DNSARR("else2.where.com", 42, {172,19,0,1})) + .add_additional(new DNSARR("else5.where.com", 42, {172,19,0,2})); + std::vector data = pkt.data(); + + struct cares_srv_reply* srv = nullptr; + EXPECT_EQ(ARES_SUCCESS, cares_parse_srv_reply(data.data(), data.size(), &srv)); + ASSERT_NE(nullptr, srv); + + EXPECT_EQ("example.abc.def.com", std::string(std::unique_ptr(cares_srv_reply_get_host(srv)).get())); + EXPECT_EQ(0, cares_srv_reply_get_priority(srv)); + EXPECT_EQ(10, cares_srv_reply_get_weight(srv)); + EXPECT_EQ(8160, cares_srv_reply_get_port(srv)); + EXPECT_EQ(180, cares_srv_reply_get_ttl(srv)); + EXPECT_EQ(nullptr, cares_srv_reply_get_next(srv)); + + ares_free_data(srv); +} + TEST_F(LibraryTest, ParseSrvReplyMalformed) { std::vector data = { 0x12, 0x34, // qid @@ -122,6 +150,37 @@ TEST_F(LibraryTest, ParseSrvReplyMalformed) { ASSERT_EQ(nullptr, srv); } +TEST_F(LibraryTest, ParseCSrvReplyMalformed) { + std::vector data = { + 0x12, 0x34, // qid + 0x84, // response + query + AA + not-TC + not-RD + 0x00, // not-RA + not-Z + not-AD + not-CD + rc=NoError + 0x00, 0x01, // num questions + 0x00, 0x01, // num answer RRs + 0x00, 0x00, // num authority RRs + 0x00, 0x00, // num additional RRs + // Question + 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', + 0x03, 'c', 'o', 'm', + 0x00, + 0x00, 0x21, // type SRV + 0x00, 0x01, // class IN + // Answer 1 + 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', + 0x03, 'c', 'o', 'm', + 0x00, + 0x00, 0x21, // RR type + 0x00, 0x01, // class IN + 0x01, 0x02, 0x03, 0x04, // TTL + 0x00, 0x04, // rdata length -- too short + 0x02, 0x03, 0x04, 0x05, + }; + + struct cares_srv_reply* srv = nullptr; + EXPECT_EQ(ARES_EBADRESP, cares_parse_srv_reply(data.data(), data.size(), &srv)); + ASSERT_EQ(nullptr, srv); +} + TEST_F(LibraryTest, ParseSrvReplyMultiple) { DNSPacket pkt; pkt.set_qid(0x1234).set_response().set_ra().set_rd() @@ -168,6 +227,55 @@ TEST_F(LibraryTest, ParseSrvReplyMultiple) { ares_free_data(srv0); } +TEST_F(LibraryTest, ParseCSrvReplyMultiple) { + DNSPacket pkt; + pkt.set_qid(0x1234).set_response().set_ra().set_rd() + .add_question(new DNSQuestion("srv.example.com", T_SRV)) + .add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 6789, "a1.srv.example.com")) + .add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 4567, "a2.srv.example.com")) + .add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 5678, "a3.srv.example.com")) + .add_auth(new DNSNsRR("example.com", 300, "ns1.example.com")) + .add_auth(new DNSNsRR("example.com", 300, "ns2.example.com")) + .add_auth(new DNSNsRR("example.com", 300, "ns3.example.com")) + .add_additional(new DNSARR("a1.srv.example.com", 300, {172,19,1,1})) + .add_additional(new DNSARR("a2.srv.example.com", 300, {172,19,1,2})) + .add_additional(new DNSARR("a3.srv.example.com", 300, {172,19,1,3})) + .add_additional(new DNSARR("n1.example.com", 300, {172,19,0,1})) + .add_additional(new DNSARR("n2.example.com", 300, {172,19,0,2})) + .add_additional(new DNSARR("n3.example.com", 300, {172,19,0,3})); + std::vector data = pkt.data(); + + struct cares_srv_reply* srv0 = nullptr; + EXPECT_EQ(ARES_SUCCESS, cares_parse_srv_reply(data.data(), data.size(), &srv0)); + ASSERT_NE(nullptr, srv0); + struct cares_srv_reply* srv = srv0; + + EXPECT_EQ("a1.srv.example.com", std::string(std::unique_ptr(cares_srv_reply_get_host(srv)).get())); + EXPECT_EQ(0, cares_srv_reply_get_priority(srv)); + EXPECT_EQ(5, cares_srv_reply_get_weight(srv)); + EXPECT_EQ(6789, cares_srv_reply_get_port(srv)); + EXPECT_EQ(300, cares_srv_reply_get_ttl(srv)); + EXPECT_NE(nullptr, cares_srv_reply_get_next(srv)); + srv = cares_srv_reply_get_next(srv); + + EXPECT_EQ("a2.srv.example.com", std::string(std::unique_ptr(cares_srv_reply_get_host(srv)).get())); + EXPECT_EQ(0, cares_srv_reply_get_priority(srv)); + EXPECT_EQ(5, cares_srv_reply_get_weight(srv)); + EXPECT_EQ(4567, cares_srv_reply_get_port(srv)); + EXPECT_EQ(300, cares_srv_reply_get_ttl(srv)); + EXPECT_NE(nullptr, cares_srv_reply_get_next(srv)); + srv = cares_srv_reply_get_next(srv); + + EXPECT_EQ("a3.srv.example.com", std::string(std::unique_ptr(cares_srv_reply_get_host(srv)).get())); + EXPECT_EQ(0, cares_srv_reply_get_priority(srv)); + EXPECT_EQ(5, cares_srv_reply_get_weight(srv)); + EXPECT_EQ(5678, cares_srv_reply_get_port(srv)); + EXPECT_EQ(300, cares_srv_reply_get_ttl(srv)); + EXPECT_EQ(nullptr, cares_srv_reply_get_next(srv)); + + ares_free_data(srv0); +} + TEST_F(LibraryTest, ParseSrvReplyCname) { DNSPacket pkt; pkt.set_qid(0x1234).set_response().set_aa() @@ -196,6 +304,35 @@ TEST_F(LibraryTest, ParseSrvReplyCname) { ares_free_data(srv); } +TEST_F(LibraryTest, ParseCSrvReplyCname) { + DNSPacket pkt; + pkt.set_qid(0x1234).set_response().set_aa() + .add_question(new DNSQuestion("example.abc.def.com", T_SRV)) + .add_answer(new DNSCnameRR("example.abc.def.com", 300, "cname.abc.def.com")) + .add_answer(new DNSSrvRR("cname.abc.def.com", 300, 0, 10, 1234, "srv.abc.def.com")) + .add_auth(new DNSNsRR("abc.def.com", 44, "else1.where.com")) + .add_auth(new DNSNsRR("abc.def.com", 44, "else2.where.com")) + .add_auth(new DNSNsRR("abc.def.com", 44, "else3.where.com")) + .add_additional(new DNSARR("example.abc.def.com", 300, {172,19,0,1})) + .add_additional(new DNSARR("else1.where.com", 42, {172,19,0,1})) + .add_additional(new DNSARR("else2.where.com", 42, {172,19,0,2})) + .add_additional(new DNSARR("else3.where.com", 42, {172,19,0,3})); + std::vector data = pkt.data(); + + struct cares_srv_reply* srv = nullptr; + EXPECT_EQ(ARES_SUCCESS, cares_parse_srv_reply(data.data(), data.size(), &srv)); + ASSERT_NE(nullptr, srv); + + EXPECT_EQ("srv.abc.def.com", std::string(std::unique_ptr(cares_srv_reply_get_host(srv)).get())); + EXPECT_EQ(0, cares_srv_reply_get_priority(srv)); + EXPECT_EQ(10, cares_srv_reply_get_weight(srv)); + EXPECT_EQ(1234, cares_srv_reply_get_port(srv)); + EXPECT_EQ(300, cares_srv_reply_get_ttl(srv)); + EXPECT_EQ(nullptr, cares_srv_reply_get_next(srv)); + + ares_free_data(srv); +} + TEST_F(LibraryTest, ParseSrvReplyCnameMultiple) { DNSPacket pkt; pkt.set_qid(0x1234).set_response().set_ra().set_rd() @@ -243,6 +380,56 @@ TEST_F(LibraryTest, ParseSrvReplyCnameMultiple) { ares_free_data(srv0); } +TEST_F(LibraryTest, ParseCSrvReplyCnameMultiple) { + DNSPacket pkt; + pkt.set_qid(0x1234).set_response().set_ra().set_rd() + .add_question(new DNSQuestion("query.example.com", T_SRV)) + .add_answer(new DNSCnameRR("query.example.com", 300, "srv.example.com")) + .add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 6789, "a1.srv.example.com")) + .add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 4567, "a2.srv.example.com")) + .add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 5678, "a3.srv.example.com")) + .add_auth(new DNSNsRR("example.com", 300, "ns1.example.com")) + .add_auth(new DNSNsRR("example.com", 300, "ns2.example.com")) + .add_auth(new DNSNsRR("example.com", 300, "ns3.example.com")) + .add_additional(new DNSARR("a1.srv.example.com", 300, {172,19,1,1})) + .add_additional(new DNSARR("a2.srv.example.com", 300, {172,19,1,2})) + .add_additional(new DNSARR("a3.srv.example.com", 300, {172,19,1,3})) + .add_additional(new DNSARR("n1.example.com", 300, {172,19,0,1})) + .add_additional(new DNSARR("n2.example.com", 300, {172,19,0,2})) + .add_additional(new DNSARR("n3.example.com", 300, {172,19,0,3})); + std::vector data = pkt.data(); + + struct cares_srv_reply* srv0 = nullptr; + EXPECT_EQ(ARES_SUCCESS, cares_parse_srv_reply(data.data(), data.size(), &srv0)); + ASSERT_NE(nullptr, srv0); + struct cares_srv_reply* srv = srv0; + + EXPECT_EQ("a1.srv.example.com", std::string(std::unique_ptr(cares_srv_reply_get_host(srv)).get())); + EXPECT_EQ(0, cares_srv_reply_get_priority(srv)); + EXPECT_EQ(5, cares_srv_reply_get_weight(srv)); + EXPECT_EQ(6789, cares_srv_reply_get_port(srv)); + EXPECT_EQ(300, cares_srv_reply_get_ttl(srv)); + EXPECT_NE(nullptr, cares_srv_reply_get_next(srv)); + srv = cares_srv_reply_get_next(srv); + + EXPECT_EQ("a2.srv.example.com", std::string(std::unique_ptr(cares_srv_reply_get_host(srv)).get())); + EXPECT_EQ(0, cares_srv_reply_get_priority(srv)); + EXPECT_EQ(5, cares_srv_reply_get_weight(srv)); + EXPECT_EQ(4567, cares_srv_reply_get_port(srv)); + EXPECT_EQ(300, cares_srv_reply_get_ttl(srv)); + EXPECT_NE(nullptr, cares_srv_reply_get_next(srv)); + srv = cares_srv_reply_get_next(srv); + + EXPECT_EQ("a3.srv.example.com", std::string(std::unique_ptr(cares_srv_reply_get_host(srv)).get())); + EXPECT_EQ(0, cares_srv_reply_get_priority(srv)); + EXPECT_EQ(5, cares_srv_reply_get_weight(srv)); + EXPECT_EQ(5678, cares_srv_reply_get_port(srv)); + EXPECT_EQ(300, cares_srv_reply_get_ttl(srv)); + EXPECT_EQ(nullptr, cares_srv_reply_get_next(srv)); + + ares_free_data(srv0); +} + TEST_F(LibraryTest, ParseSrvReplyErrors) { DNSPacket pkt; pkt.set_qid(0x1234).set_response().set_aa() @@ -256,7 +443,6 @@ TEST_F(LibraryTest, ParseSrvReplyErrors) { data = pkt.data(); EXPECT_EQ(ARES_EBADRESP, ares_parse_srv_reply(data.data(), data.size(), &srv)); pkt.add_question(new DNSQuestion("example.abc.def.com", T_SRV)); - #ifdef DISABLED // Question != answer pkt.questions_.clear(); @@ -266,14 +452,12 @@ TEST_F(LibraryTest, ParseSrvReplyErrors) { pkt.questions_.clear(); pkt.add_question(new DNSQuestion("example.com", T_SRV)); #endif - // Two questions. pkt.add_question(new DNSQuestion("example.abc.def.com", T_SRV)); data = pkt.data(); EXPECT_EQ(ARES_EBADRESP, ares_parse_srv_reply(data.data(), data.size(), &srv)); pkt.questions_.clear(); pkt.add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR)); - // Wrong sort of answer. pkt.answers_.clear(); pkt.add_answer(new DNSMxRR("example.com", 100, 100, "mx1.example.com")); @@ -282,13 +466,11 @@ TEST_F(LibraryTest, ParseSrvReplyErrors) { EXPECT_EQ(nullptr, srv); pkt.answers_.clear(); pkt.add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")); - // No answer. pkt.answers_.clear(); data = pkt.data(); EXPECT_EQ(ARES_ENODATA, ares_parse_srv_reply(data.data(), data.size(), &srv)); pkt.add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")); - // Truncated packets. data = pkt.data(); for (size_t len = 1; len < data.size(); len++) { @@ -297,6 +479,60 @@ TEST_F(LibraryTest, ParseSrvReplyErrors) { } } +TEST_F(LibraryTest, ParseCSrvReplyErrors) { + DNSPacket pkt; + pkt.set_qid(0x1234).set_response().set_aa() + .add_question(new DNSQuestion("example.abc.def.com", T_SRV)) + .add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")); + std::vector data; + struct cares_srv_reply* srv = nullptr; + + // No question. + pkt.questions_.clear(); + data = pkt.data(); + EXPECT_EQ(ARES_EBADRESP, cares_parse_srv_reply(data.data(), data.size(), &srv)); + pkt.add_question(new DNSQuestion("example.abc.def.com", T_SRV)); + +#ifdef DISABLED + // Question != answer + pkt.questions_.clear(); + pkt.add_question(new DNSQuestion("Axample.com", T_SRV)); + data = pkt.data(); + EXPECT_EQ(ARES_ENODATA, cares_parse_srv_reply(data.data(), data.size(), &srv)); + pkt.questions_.clear(); + pkt.add_question(new DNSQuestion("example.com", T_SRV)); +#endif + + // Two questions. + pkt.add_question(new DNSQuestion("example.abc.def.com", T_SRV)); + data = pkt.data(); + EXPECT_EQ(ARES_EBADRESP, cares_parse_srv_reply(data.data(), data.size(), &srv)); + pkt.questions_.clear(); + pkt.add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR)); + + // Wrong sort of answer. + pkt.answers_.clear(); + pkt.add_answer(new DNSMxRR("example.com", 100, 100, "mx1.example.com")); + data = pkt.data(); + EXPECT_EQ(ARES_SUCCESS, cares_parse_srv_reply(data.data(), data.size(), &srv)); + EXPECT_EQ(nullptr, srv); + pkt.answers_.clear(); + pkt.add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")); + + // No answer. + pkt.answers_.clear(); + data = pkt.data(); + EXPECT_EQ(ARES_ENODATA, cares_parse_srv_reply(data.data(), data.size(), &srv)); + pkt.add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")); + + // Truncated packets. + data = pkt.data(); + for (size_t len = 1; len < data.size(); len++) { + int rc = cares_parse_srv_reply(data.data(), len, &srv); + EXPECT_TRUE(rc == ARES_EBADRESP || rc == ARES_EBADNAME); + } +} + TEST_F(LibraryTest, ParseSrvReplyAllocFail) { DNSPacket pkt; pkt.set_qid(0x1234).set_response().set_aa() @@ -313,5 +549,21 @@ TEST_F(LibraryTest, ParseSrvReplyAllocFail) { } } +TEST_F(LibraryTest, ParseCSrvReplyAllocFail) { + DNSPacket pkt; + pkt.set_qid(0x1234).set_response().set_aa() + .add_question(new DNSQuestion("example.abc.def.com", T_SRV)) + .add_answer(new DNSCnameRR("example.com", 300, "c.example.com")) + .add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")); + std::vector data = pkt.data(); + struct cares_srv_reply* srv = nullptr; + + for (int ii = 1; ii <= 5; ii++) { + ClearFails(); + SetAllocFail(ii); + EXPECT_EQ(ARES_ENOMEM, cares_parse_srv_reply(data.data(), data.size(), &srv)) << ii; + } +} + } // namespace test } // namespace ares From 73d8bf5c1d75d607130d9ac2eb8a9ee95ca826da Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Sat, 30 Jan 2021 12:26:16 -0500 Subject: [PATCH 04/49] return const char* from cares_srv_reply_get_host --- include/ares.h | 3 ++- src/lib/ares_parse_srv_reply.c | 11 +++++++++-- src/lib/cares_reply.c | 8 ++------ test/ares-test-parse-srv.cc | 18 +++++++++--------- 4 files changed, 22 insertions(+), 18 deletions(-) diff --git a/include/ares.h b/include/ares.h index 21101fd7e5..66d04fbf63 100644 --- a/include/ares.h +++ b/include/ares.h @@ -676,7 +676,8 @@ CARES_EXTERN int cares_parse_srv_reply(const unsigned char* abuf, CARES_EXTERN struct cares_srv_reply* cares_srv_reply_get_next(const cares_srv_reply* srv_reply); -CARES_EXTERN char* cares_srv_reply_get_host(const cares_srv_reply* srv_reply); +CARES_EXTERN const char* +cares_srv_reply_get_host(const cares_srv_reply* srv_reply); CARES_EXTERN unsigned short cares_srv_reply_get_priority(const cares_srv_reply* srv_reply); diff --git a/src/lib/ares_parse_srv_reply.c b/src/lib/ares_parse_srv_reply.c index 95c28249f2..100e53e7f1 100644 --- a/src/lib/ares_parse_srv_reply.c +++ b/src/lib/ares_parse_srv_reply.c @@ -82,12 +82,19 @@ ares_parse_srv_reply (const unsigned char *abuf, int alen, srv_head = srv_curr; } srv_last = srv_curr; - srv_curr->host = cares_srv_reply_get_host(csrv_curr); - if (!srv_curr->host) + + /* copy the host to newhost so we can free csrv_out */ + char *newhost = NULL; + const char *tmphost = cares_srv_reply_get_host(csrv_curr); + if (!tmphost) { status = ARES_ENOMEM; break; } + if ((newhost = malloc(strlen(tmphost) + 1)) != NULL) { + strcpy(newhost, tmphost); + } + srv_curr->host = newhost; srv_curr->priority = cares_srv_reply_get_priority(csrv_curr); srv_curr->weight = cares_srv_reply_get_weight(csrv_curr); srv_curr->port = cares_srv_reply_get_port(csrv_curr); diff --git a/src/lib/cares_reply.c b/src/lib/cares_reply.c index 5e4c550f81..b4423b6c88 100644 --- a/src/lib/cares_reply.c +++ b/src/lib/cares_reply.c @@ -22,13 +22,9 @@ cares_srv_reply_get_next(const struct cares_srv_reply* srv_reply) return srv_reply->next; } -char* cares_srv_reply_get_host(const struct cares_srv_reply* srv_reply) +const char* cares_srv_reply_get_host(const struct cares_srv_reply* srv_reply) { - char *newhost = NULL; - if ((newhost = malloc(strlen(srv_reply->host) + 1)) != NULL) { - strcpy(newhost, srv_reply->host); - } - return newhost; + return srv_reply->host; } unsigned short diff --git a/test/ares-test-parse-srv.cc b/test/ares-test-parse-srv.cc index 29bc1b5dec..fb26e26447 100644 --- a/test/ares-test-parse-srv.cc +++ b/test/ares-test-parse-srv.cc @@ -47,7 +47,7 @@ TEST_F(LibraryTest, ParseCSrvReplyOK) { EXPECT_EQ(ARES_SUCCESS, cares_parse_srv_reply(data.data(), data.size(), &srv)); ASSERT_NE(nullptr, srv); - EXPECT_EQ("srv.example.com", std::string(std::unique_ptr(cares_srv_reply_get_host(srv)).get())); + EXPECT_EQ("srv.example.com", std::string(cares_srv_reply_get_host(srv))); EXPECT_EQ(10, cares_srv_reply_get_priority(srv)); EXPECT_EQ(20, cares_srv_reply_get_weight(srv)); EXPECT_EQ(30, cares_srv_reply_get_port(srv)); @@ -109,7 +109,7 @@ TEST_F(LibraryTest, ParseCSrvReplySingle) { EXPECT_EQ(ARES_SUCCESS, cares_parse_srv_reply(data.data(), data.size(), &srv)); ASSERT_NE(nullptr, srv); - EXPECT_EQ("example.abc.def.com", std::string(std::unique_ptr(cares_srv_reply_get_host(srv)).get())); + EXPECT_EQ("example.abc.def.com", std::string(cares_srv_reply_get_host(srv))); EXPECT_EQ(0, cares_srv_reply_get_priority(srv)); EXPECT_EQ(10, cares_srv_reply_get_weight(srv)); EXPECT_EQ(8160, cares_srv_reply_get_port(srv)); @@ -250,7 +250,7 @@ TEST_F(LibraryTest, ParseCSrvReplyMultiple) { ASSERT_NE(nullptr, srv0); struct cares_srv_reply* srv = srv0; - EXPECT_EQ("a1.srv.example.com", std::string(std::unique_ptr(cares_srv_reply_get_host(srv)).get())); + EXPECT_EQ("a1.srv.example.com", std::string(cares_srv_reply_get_host(srv))); EXPECT_EQ(0, cares_srv_reply_get_priority(srv)); EXPECT_EQ(5, cares_srv_reply_get_weight(srv)); EXPECT_EQ(6789, cares_srv_reply_get_port(srv)); @@ -258,7 +258,7 @@ TEST_F(LibraryTest, ParseCSrvReplyMultiple) { EXPECT_NE(nullptr, cares_srv_reply_get_next(srv)); srv = cares_srv_reply_get_next(srv); - EXPECT_EQ("a2.srv.example.com", std::string(std::unique_ptr(cares_srv_reply_get_host(srv)).get())); + EXPECT_EQ("a2.srv.example.com", std::string(cares_srv_reply_get_host(srv))); EXPECT_EQ(0, cares_srv_reply_get_priority(srv)); EXPECT_EQ(5, cares_srv_reply_get_weight(srv)); EXPECT_EQ(4567, cares_srv_reply_get_port(srv)); @@ -266,7 +266,7 @@ TEST_F(LibraryTest, ParseCSrvReplyMultiple) { EXPECT_NE(nullptr, cares_srv_reply_get_next(srv)); srv = cares_srv_reply_get_next(srv); - EXPECT_EQ("a3.srv.example.com", std::string(std::unique_ptr(cares_srv_reply_get_host(srv)).get())); + EXPECT_EQ("a3.srv.example.com", std::string(cares_srv_reply_get_host(srv))); EXPECT_EQ(0, cares_srv_reply_get_priority(srv)); EXPECT_EQ(5, cares_srv_reply_get_weight(srv)); EXPECT_EQ(5678, cares_srv_reply_get_port(srv)); @@ -323,7 +323,7 @@ TEST_F(LibraryTest, ParseCSrvReplyCname) { EXPECT_EQ(ARES_SUCCESS, cares_parse_srv_reply(data.data(), data.size(), &srv)); ASSERT_NE(nullptr, srv); - EXPECT_EQ("srv.abc.def.com", std::string(std::unique_ptr(cares_srv_reply_get_host(srv)).get())); + EXPECT_EQ("srv.abc.def.com", std::string(cares_srv_reply_get_host(srv))); EXPECT_EQ(0, cares_srv_reply_get_priority(srv)); EXPECT_EQ(10, cares_srv_reply_get_weight(srv)); EXPECT_EQ(1234, cares_srv_reply_get_port(srv)); @@ -404,7 +404,7 @@ TEST_F(LibraryTest, ParseCSrvReplyCnameMultiple) { ASSERT_NE(nullptr, srv0); struct cares_srv_reply* srv = srv0; - EXPECT_EQ("a1.srv.example.com", std::string(std::unique_ptr(cares_srv_reply_get_host(srv)).get())); + EXPECT_EQ("a1.srv.example.com", std::string(cares_srv_reply_get_host(srv))); EXPECT_EQ(0, cares_srv_reply_get_priority(srv)); EXPECT_EQ(5, cares_srv_reply_get_weight(srv)); EXPECT_EQ(6789, cares_srv_reply_get_port(srv)); @@ -412,7 +412,7 @@ TEST_F(LibraryTest, ParseCSrvReplyCnameMultiple) { EXPECT_NE(nullptr, cares_srv_reply_get_next(srv)); srv = cares_srv_reply_get_next(srv); - EXPECT_EQ("a2.srv.example.com", std::string(std::unique_ptr(cares_srv_reply_get_host(srv)).get())); + EXPECT_EQ("a2.srv.example.com", std::string(cares_srv_reply_get_host(srv))); EXPECT_EQ(0, cares_srv_reply_get_priority(srv)); EXPECT_EQ(5, cares_srv_reply_get_weight(srv)); EXPECT_EQ(4567, cares_srv_reply_get_port(srv)); @@ -420,7 +420,7 @@ TEST_F(LibraryTest, ParseCSrvReplyCnameMultiple) { EXPECT_NE(nullptr, cares_srv_reply_get_next(srv)); srv = cares_srv_reply_get_next(srv); - EXPECT_EQ("a3.srv.example.com", std::string(std::unique_ptr(cares_srv_reply_get_host(srv)).get())); + EXPECT_EQ("a3.srv.example.com", std::string(cares_srv_reply_get_host(srv))); EXPECT_EQ(0, cares_srv_reply_get_priority(srv)); EXPECT_EQ(5, cares_srv_reply_get_weight(srv)); EXPECT_EQ(5678, cares_srv_reply_get_port(srv)); From eb34dbed2af419fd5a5608dbecb6d27a1594182d Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Sat, 30 Jan 2021 20:32:11 -0500 Subject: [PATCH 05/49] use ares_strdup in ares_parse_srv_reply to copy host string --- src/lib/ares_parse_srv_reply.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/lib/ares_parse_srv_reply.c b/src/lib/ares_parse_srv_reply.c index 100e53e7f1..0f4830a7e3 100644 --- a/src/lib/ares_parse_srv_reply.c +++ b/src/lib/ares_parse_srv_reply.c @@ -16,6 +16,7 @@ */ #include "ares_setup.h" +#include "ares_strdup.h" #ifdef HAVE_NETINET_IN_H # include @@ -57,8 +58,8 @@ ares_parse_srv_reply (const unsigned char *abuf, int alen, /* clean up on error */ if (status != ARES_SUCCESS) { - if (srv_out) - ares_free_data (*srv_out); + if (csrv_out) + ares_free_data (csrv_out); return status; } @@ -84,16 +85,12 @@ ares_parse_srv_reply (const unsigned char *abuf, int alen, srv_last = srv_curr; /* copy the host to newhost so we can free csrv_out */ - char *newhost = NULL; - const char *tmphost = cares_srv_reply_get_host(csrv_curr); - if (!tmphost) - { + char *newhost = ares_strdup(cares_srv_reply_get_host(csrv_curr)); + if (!newhost) { status = ARES_ENOMEM; break; } - if ((newhost = malloc(strlen(tmphost) + 1)) != NULL) { - strcpy(newhost, tmphost); - } + srv_curr->host = newhost; srv_curr->priority = cares_srv_reply_get_priority(csrv_curr); srv_curr->weight = cares_srv_reply_get_weight(csrv_curr); @@ -105,7 +102,7 @@ ares_parse_srv_reply (const unsigned char *abuf, int alen, ares_free_data (csrv_out); } - /* clean up on error */ + /* clean up on error */ if (status != ARES_SUCCESS) { if (srv_head) From a86be7e8580d5ecda12e21669b5f484b7c91fe94 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Tue, 9 Mar 2021 20:18:43 -0500 Subject: [PATCH 06/49] add new structs and parse functions to support TTL for these RRs: CAA MX NAPTR NS PTR SOA TXT --- include/ares.h | 197 ++++++++++-- src/lib/Makefile.inc | 7 + src/lib/ares_data.c | 45 ++- src/lib/ares_data.h | 14 + src/lib/ares_free_hostent.c | 1 + src/lib/ares_parse_caa_reply.c | 195 ++++-------- src/lib/ares_parse_mx_reply.c | 158 ++++------ src/lib/ares_parse_naptr_reply.c | 204 ++++++------- src/lib/ares_parse_ns_reply.c | 199 ++++++------- src/lib/ares_parse_ptr_reply.c | 270 +++++++---------- src/lib/ares_parse_soa_reply.c | 170 +++-------- src/lib/ares_parse_srv_reply.c | 4 +- src/lib/ares_parse_txt_reply.c | 189 ++++-------- src/lib/ares_private.h | 203 ++++++++++++- src/lib/cares_parse_caa_reply.c | 212 +++++++++++++ src/lib/cares_parse_mx_reply.c | 176 +++++++++++ src/lib/cares_parse_naptr_reply.c | 200 +++++++++++++ src/lib/cares_parse_ns_reply.c | 171 +++++++++++ src/lib/cares_parse_ptr_reply.c | 188 ++++++++++++ src/lib/cares_parse_soa_reply.c | 191 ++++++++++++ src/lib/cares_parse_srv_reply.c | 19 +- src/lib/cares_parse_txt_reply.c | 210 +++++++++++++ src/lib/cares_reply.c | 478 +++++++++++++++++++++++++++++- test/ares-test-parse-caa.cc | 149 ++++++++-- test/ares-test-parse-mx.cc | 117 +++++++- test/ares-test-parse-naptr.cc | 141 ++++++++- test/ares-test-parse-ns.cc | 113 +++++++ test/ares-test-parse-ptr.cc | 199 +++++++++++++ test/ares-test-parse-soa-any.cc | 101 +++++++ test/ares-test-parse-soa.cc | 98 ++++++ test/ares-test-parse-srv.cc | 4 +- test/ares-test-parse-txt.cc | 226 ++++++++++++++ 32 files changed, 3886 insertions(+), 963 deletions(-) create mode 100644 src/lib/cares_parse_caa_reply.c create mode 100644 src/lib/cares_parse_mx_reply.c create mode 100644 src/lib/cares_parse_naptr_reply.c create mode 100644 src/lib/cares_parse_ns_reply.c create mode 100644 src/lib/cares_parse_ptr_reply.c create mode 100644 src/lib/cares_parse_soa_reply.c create mode 100644 src/lib/cares_parse_txt_reply.c diff --git a/include/ares.h b/include/ares.h index 66d04fbf63..6c5e0a3be1 100644 --- a/include/ares.h +++ b/include/ares.h @@ -537,6 +537,18 @@ struct ares_caa_reply { size_t length; /* length excludes null termination */ }; +struct cares_caa_reply; + +typedef struct cares_caa_reply cares_caa_reply; + +struct cares_ptr_reply; + +typedef struct cares_ptr_reply cares_ptr_reply; + +struct cares_ns_reply; + +typedef struct cares_ns_reply cares_ns_reply; + struct ares_srv_reply { struct ares_srv_reply *next; char *host; @@ -549,12 +561,20 @@ struct cares_srv_reply; typedef struct cares_srv_reply cares_srv_reply; +struct cares_host_reply; + +typedef struct cares_host_reply cares_host_reply; + struct ares_mx_reply { struct ares_mx_reply *next; char *host; unsigned short priority; }; +struct cares_mx_reply; + +typedef struct cares_mx_reply cares_mx_reply; + struct ares_txt_reply { struct ares_txt_reply *next; unsigned char *txt; @@ -572,6 +592,10 @@ struct ares_txt_ext { unsigned char record_start; }; +struct cares_txt_reply; + +typedef struct cares_txt_reply cares_txt_reply; + struct ares_naptr_reply { struct ares_naptr_reply *next; unsigned char *flags; @@ -582,6 +606,10 @@ struct ares_naptr_reply { unsigned short preference; }; +struct cares_naptr_reply; + +typedef struct cares_naptr_reply cares_naptr_reply; + struct ares_soa_reply { char *nsname; char *hostmaster; @@ -592,6 +620,10 @@ struct ares_soa_reply { unsigned int minttl; }; +struct cares_soa_reply; + +typedef struct cares_soa_reply cares_soa_reply; + /* * Similar to addrinfo, but with extra ttl and missing canonname. */ @@ -654,6 +686,31 @@ CARES_EXTERN int ares_parse_caa_reply(const unsigned char* abuf, int alen, struct ares_caa_reply** caa_out); +CARES_EXTERN int cares_parse_caa_reply(const unsigned char* abuf, + int alen, + struct cares_caa_reply** caa_out); + +CARES_EXTERN struct cares_caa_reply* +cares_caa_reply_get_next(const cares_caa_reply* caa_reply); + +CARES_EXTERN int +cares_caa_reply_get_critical(const cares_caa_reply* caa_reply); + +CARES_EXTERN const unsigned char* +cares_caa_reply_get_property(const cares_caa_reply* caa_reply); + +CARES_EXTERN size_t +cares_caa_reply_get_plength(const cares_caa_reply* caa_reply); + +CARES_EXTERN const unsigned char* +cares_caa_reply_get_value(const cares_caa_reply* caa_reply); + +CARES_EXTERN size_t +cares_caa_reply_get_length(const cares_caa_reply* caa_reply); + +CARES_EXTERN unsigned int cares_caa_reply_get_ttl(const cares_caa_reply* + caa_reply); + CARES_EXTERN int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr, @@ -661,19 +718,45 @@ CARES_EXTERN int ares_parse_ptr_reply(const unsigned char *abuf, int family, struct hostent **host); +CARES_EXTERN int cares_parse_ptr_reply(const unsigned char *abuf, + int alen, + struct cares_ptr_reply **ptr_out); + +CARES_EXTERN struct cares_ptr_reply* +cares_ptr_reply_get_next(const cares_ptr_reply* ptr_reply); + +CARES_EXTERN const char* +cares_ptr_reply_get_host(const cares_ptr_reply* ptr_reply); + +CARES_EXTERN unsigned int cares_ptr_reply_get_ttl(const cares_ptr_reply* + ptr_reply); + CARES_EXTERN int ares_parse_ns_reply(const unsigned char *abuf, int alen, struct hostent **host); +CARES_EXTERN int cares_parse_ns_reply(const unsigned char *abuf, + int alen, + struct cares_ns_reply **ns_out); + +CARES_EXTERN struct cares_ns_reply* +cares_ns_reply_get_next(const cares_ns_reply* ns_reply); + +CARES_EXTERN const char* +cares_ns_reply_get_host(const cares_ns_reply* ns_reply); + +CARES_EXTERN unsigned int cares_ns_reply_get_ttl(const cares_ns_reply* + ns_reply); + CARES_EXTERN int ares_parse_srv_reply(const unsigned char* abuf, int alen, struct ares_srv_reply** srv_out); CARES_EXTERN int cares_parse_srv_reply(const unsigned char* abuf, - int alen, - struct cares_srv_reply** srv_out); + int alen, + struct cares_srv_reply** srv_out); -CARES_EXTERN struct cares_srv_reply* +CARES_EXTERN cares_srv_reply* cares_srv_reply_get_next(const cares_srv_reply* srv_reply); CARES_EXTERN const char* @@ -688,29 +771,28 @@ cares_srv_reply_get_weight(const cares_srv_reply* srv_reply); CARES_EXTERN unsigned short cares_srv_reply_get_port(const cares_srv_reply* srv_reply); -CARES_EXTERN int cares_srv_reply_get_ttl(const cares_srv_reply* srv_reply); - -CARES_EXTERN void cares_srv_reply_set_next(cares_srv_reply* srv_reply, - struct cares_srv_reply* next); +CARES_EXTERN unsigned int cares_srv_reply_get_ttl(const cares_srv_reply* + srv_reply); -CARES_EXTERN void -cares_srv_reply_set_host(cares_srv_reply* srv_reply, char* host); +CARES_EXTERN int ares_parse_mx_reply(const unsigned char* abuf, + int alen, + struct ares_mx_reply** mx_out); -CARES_EXTERN void cares_srv_reply_set_priority(cares_srv_reply* srv_reply, - const unsigned short priority); +CARES_EXTERN int cares_parse_mx_reply(const unsigned char* abuf, + int alen, + struct cares_mx_reply** mx_out); -CARES_EXTERN void cares_srv_reply_set_weight(cares_srv_reply* srv_reply, - const unsigned short weight); +CARES_EXTERN struct cares_mx_reply* +cares_mx_reply_get_next(const cares_mx_reply* mx_reply); -CARES_EXTERN void cares_srv_reply_set_port(cares_srv_reply* srv_reply, - const unsigned short port); +CARES_EXTERN const char* +cares_mx_reply_get_host(const cares_mx_reply* mx_reply); -CARES_EXTERN void cares_srv_reply_set_ttl(cares_srv_reply* srv_reply, - const int ttl); +CARES_EXTERN unsigned short +cares_mx_reply_get_priority(const cares_mx_reply* mx_reply); -CARES_EXTERN int ares_parse_mx_reply(const unsigned char* abuf, - int alen, - struct ares_mx_reply** mx_out); +CARES_EXTERN unsigned int cares_mx_reply_get_ttl(const cares_mx_reply* + mx_reply); CARES_EXTERN int ares_parse_txt_reply(const unsigned char* abuf, int alen, @@ -720,14 +802,89 @@ CARES_EXTERN int ares_parse_txt_reply_ext(const unsigned char* abuf, int alen, struct ares_txt_ext** txt_out); +CARES_EXTERN int cares_parse_txt_reply(const unsigned char* abuf, + int alen, + struct cares_txt_reply** txt_out); + +CARES_EXTERN struct cares_txt_reply* +cares_txt_reply_get_next(const cares_txt_reply* txt_reply); + +CARES_EXTERN const unsigned char* +cares_txt_reply_get_txt(const cares_txt_reply* txt_reply); + +CARES_EXTERN size_t +cares_txt_reply_get_length(const cares_txt_reply* txt_reply); + +CARES_EXTERN unsigned char +cares_txt_reply_get_record_start(const cares_txt_reply* txt_reply); + +CARES_EXTERN unsigned int cares_txt_reply_get_ttl(const cares_txt_reply* + txt_reply); + CARES_EXTERN int ares_parse_naptr_reply(const unsigned char* abuf, int alen, struct ares_naptr_reply** naptr_out); +CARES_EXTERN int cares_parse_naptr_reply(const unsigned char* abuf, + int alen, + struct cares_naptr_reply** naptr_out); + +CARES_EXTERN struct cares_naptr_reply* +cares_naptr_reply_get_next(const cares_naptr_reply* naptr_reply); + +CARES_EXTERN const unsigned char* +cares_naptr_reply_get_flags(const cares_naptr_reply* naptr_reply); + +CARES_EXTERN const unsigned char* +cares_naptr_reply_get_service(const cares_naptr_reply* naptr_reply); + +CARES_EXTERN const unsigned char* +cares_naptr_reply_get_regexp(const cares_naptr_reply* naptr_reply); + +CARES_EXTERN const char* +cares_naptr_reply_get_replacement(const cares_naptr_reply* naptr_reply); + +CARES_EXTERN unsigned short +cares_naptr_reply_get_order(const cares_naptr_reply* naptr_reply); + +CARES_EXTERN unsigned short +cares_naptr_reply_get_preference(const cares_naptr_reply* naptr_reply); + +CARES_EXTERN unsigned int cares_naptr_reply_get_ttl(const cares_naptr_reply* + naptr_reply); + CARES_EXTERN int ares_parse_soa_reply(const unsigned char* abuf, int alen, struct ares_soa_reply** soa_out); +CARES_EXTERN int cares_parse_soa_reply(const unsigned char* abuf, + int alen, + struct cares_soa_reply** soa_out); + +CARES_EXTERN const char* +cares_soa_reply_get_nsname(const cares_soa_reply* soa_reply); + +CARES_EXTERN const char* +cares_soa_reply_get_hostmaster(const cares_soa_reply* soa_reply); + +CARES_EXTERN unsigned int +cares_soa_reply_get_serial(const cares_soa_reply* soa_reply); + +CARES_EXTERN unsigned int +cares_soa_reply_get_refresh(const cares_soa_reply* soa_reply); + +CARES_EXTERN unsigned int +cares_soa_reply_get_retry(const cares_soa_reply* soa_reply); + +CARES_EXTERN unsigned int +cares_soa_reply_get_expire(const cares_soa_reply* soa_reply); + +CARES_EXTERN unsigned int +cares_soa_reply_get_minttl(const cares_soa_reply* soa_reply); + +CARES_EXTERN unsigned int cares_soa_reply_get_ttl(const cares_soa_reply* + soa_reply); + CARES_EXTERN void ares_free_string(void *str); CARES_EXTERN void ares_free_hostent(struct hostent *host); diff --git a/src/lib/Makefile.inc b/src/lib/Makefile.inc index 284e0ab342..69404e7f8d 100644 --- a/src/lib/Makefile.inc +++ b/src/lib/Makefile.inc @@ -32,14 +32,21 @@ CSOURCES = ares__close_sockets.c \ ares_parse_a_reply.c \ ares_parse_aaaa_reply.c \ ares_parse_caa_reply.c \ + cares_parse_caa_reply.c \ ares_parse_mx_reply.c \ + cares_parse_mx_reply.c \ ares_parse_naptr_reply.c \ + cares_parse_naptr_reply.c \ ares_parse_ns_reply.c \ + cares_parse_ns_reply.c \ ares_parse_ptr_reply.c \ + cares_parse_ptr_reply.c \ ares_parse_soa_reply.c \ + cares_parse_soa_reply.c \ ares_parse_srv_reply.c \ cares_parse_srv_reply.c \ ares_parse_txt_reply.c \ + cares_parse_txt_reply.c \ ares_platform.c \ ares_process.c \ ares_query.c \ diff --git a/src/lib/ares_data.c b/src/lib/ares_data.c index 3dfb41d459..82752fa905 100644 --- a/src/lib/ares_data.c +++ b/src/lib/ares_data.c @@ -63,6 +63,7 @@ void ares_free_data(void *dataptr) switch (ptr->type) { case ARES_DATATYPE_MX_REPLY: + case ARES_DATATYPE_CMX_REPLY: if (ptr->data.mx_reply.next) next_data = ptr->data.mx_reply.next; @@ -81,6 +82,7 @@ void ares_free_data(void *dataptr) case ARES_DATATYPE_TXT_REPLY: case ARES_DATATYPE_TXT_EXT: + case ARES_DATATYPE_CTXT_REPLY: if (ptr->data.txt_reply.next) next_data = ptr->data.txt_reply.next; @@ -101,6 +103,7 @@ void ares_free_data(void *dataptr) break; case ARES_DATATYPE_NAPTR_REPLY: + case ARES_DATATYPE_CNAPTR_REPLY: if (ptr->data.naptr_reply.next) next_data = ptr->data.naptr_reply.next; @@ -115,6 +118,7 @@ void ares_free_data(void *dataptr) break; case ARES_DATATYPE_SOA_REPLY: + case ARES_DATATYPE_CSOA_REPLY: if (ptr->data.soa_reply.nsname) ares_free(ptr->data.soa_reply.nsname); if (ptr->data.soa_reply.hostmaster) @@ -122,7 +126,7 @@ void ares_free_data(void *dataptr) break; case ARES_DATATYPE_CAA_REPLY: - + case ARES_DATATYPE_CCAA_REPLY: if (ptr->data.caa_reply.next) next_data = ptr->data.caa_reply.next; if (ptr->data.caa_reply.property) @@ -162,6 +166,10 @@ void *ares_malloc_data(ares_datatype type) switch (type) { + case ARES_DATATYPE_CMX_REPLY: + ptr->data.cmx_reply.ttl = 0; + /* FALLTHROUGH */ + case ARES_DATATYPE_MX_REPLY: ptr->data.mx_reply.next = NULL; ptr->data.mx_reply.host = NULL; @@ -180,6 +188,10 @@ void *ares_malloc_data(ares_datatype type) ptr->data.srv_reply.port = 0; break; + case ARES_DATATYPE_CTXT_REPLY: + ptr->data.ctxt_reply.ttl = 0; + /* FALLTHROUGH */ + case ARES_DATATYPE_TXT_EXT: ptr->data.txt_ext.record_start = 0; /* FALLTHROUGH */ @@ -190,6 +202,10 @@ void *ares_malloc_data(ares_datatype type) ptr->data.txt_reply.length = 0; break; + case ARES_DATATYPE_CCAA_REPLY: + ptr->data.ccaa_reply.ttl = 0; + /* FALLTHROUGH */ + case ARES_DATATYPE_CAA_REPLY: ptr->data.caa_reply.next = NULL; ptr->data.caa_reply.plength = 0; @@ -202,7 +218,7 @@ void *ares_malloc_data(ares_datatype type) ptr->data.addr_node.next = NULL; ptr->data.addr_node.family = 0; memset(&ptr->data.addr_node.addrV6, 0, - sizeof(ptr->data.addr_node.addrV6)); + sizeof(ptr->data.addr_node.addrV6)); break; case ARES_DATATYPE_ADDR_PORT_NODE: @@ -211,9 +227,13 @@ void *ares_malloc_data(ares_datatype type) ptr->data.addr_port_node.udp_port = 0; ptr->data.addr_port_node.tcp_port = 0; memset(&ptr->data.addr_port_node.addrV6, 0, - sizeof(ptr->data.addr_port_node.addrV6)); + sizeof(ptr->data.addr_port_node.addrV6)); break; + case ARES_DATATYPE_CNAPTR_REPLY: + ptr->data.cnaptr_reply.ttl = 0; + /* FALLTHROUGH */ + case ARES_DATATYPE_NAPTR_REPLY: ptr->data.naptr_reply.next = NULL; ptr->data.naptr_reply.flags = NULL; @@ -224,6 +244,10 @@ void *ares_malloc_data(ares_datatype type) ptr->data.naptr_reply.preference = 0; break; + case ARES_DATATYPE_CSOA_REPLY: + ptr->data.csoa_reply.ttl = 0; + /* FALLTHROUGH */ + case ARES_DATATYPE_SOA_REPLY: ptr->data.soa_reply.nsname = NULL; ptr->data.soa_reply.hostmaster = NULL; @@ -232,7 +256,20 @@ void *ares_malloc_data(ares_datatype type) ptr->data.soa_reply.retry = 0; ptr->data.soa_reply.expire = 0; ptr->data.soa_reply.minttl = 0; - break; + break; + + case ARES_DATATYPE_CPTR_REPLY: + ptr->data.cptr_reply.next = NULL; + ptr->data.cptr_reply.host = NULL; + ptr->data.cptr_reply.ttl = 0; + break; + + case ARES_DATATYPE_CNS_REPLY: + ptr->data.cns_reply.next = NULL; + ptr->data.cns_reply.host = NULL; + ptr->data.cns_reply.ttl = 0; + break; + default: ares_free(ptr); diff --git a/src/lib/ares_data.h b/src/lib/ares_data.h index d3bff954fb..75c6e04cb7 100644 --- a/src/lib/ares_data.h +++ b/src/lib/ares_data.h @@ -21,10 +21,14 @@ typedef enum { ARES_DATATYPE_CSRV_REPLY, /* struct cares_srv_reply */ ARES_DATATYPE_TXT_REPLY, /* struct ares_txt_reply - introduced in 1.7.0 */ ARES_DATATYPE_TXT_EXT, /* struct ares_txt_ext - introduced in 1.11.0 */ + ARES_DATATYPE_CTXT_REPLY, ARES_DATATYPE_ADDR_NODE, /* struct ares_addr_node - introduced in 1.7.1 */ ARES_DATATYPE_MX_REPLY, /* struct ares_mx_reply - introduced in 1.7.2 */ + ARES_DATATYPE_CMX_REPLY, ARES_DATATYPE_NAPTR_REPLY,/* struct ares_naptr_reply - introduced in 1.7.6 */ + ARES_DATATYPE_CNAPTR_REPLY, ARES_DATATYPE_SOA_REPLY, /* struct ares_soa_reply - introduced in 1.9.0 */ + ARES_DATATYPE_CSOA_REPLY, #if 0 ARES_DATATYPE_ADDR6TTL, /* struct ares_addrttl */ ARES_DATATYPE_ADDRTTL, /* struct ares_addr6ttl */ @@ -33,6 +37,9 @@ typedef enum { #endif ARES_DATATYPE_ADDR_PORT_NODE, /* struct ares_addr_port_node - introduced in 1.11.0 */ ARES_DATATYPE_CAA_REPLY, /* struct ares_caa_reply - introduced in 1.17 */ + ARES_DATATYPE_CCAA_REPLY, + ARES_DATATYPE_CPTR_REPLY, + ARES_DATATYPE_CNS_REPLY, ARES_DATATYPE_LAST /* not used - introduced in 1.7.0 */ } ares_datatype; @@ -62,14 +69,21 @@ struct ares_data { union { struct ares_txt_reply txt_reply; struct ares_txt_ext txt_ext; + struct cares_txt_reply ctxt_reply; struct ares_srv_reply srv_reply; struct cares_srv_reply csrv_reply; struct ares_addr_node addr_node; struct ares_addr_port_node addr_port_node; struct ares_mx_reply mx_reply; + struct cares_mx_reply cmx_reply; struct ares_naptr_reply naptr_reply; + struct cares_naptr_reply cnaptr_reply; struct ares_soa_reply soa_reply; + struct cares_soa_reply csoa_reply; struct ares_caa_reply caa_reply; + struct cares_caa_reply ccaa_reply; + struct cares_ptr_reply cptr_reply; + struct cares_ns_reply cns_reply; } data; }; diff --git a/src/lib/ares_free_hostent.c b/src/lib/ares_free_hostent.c index ea28ff0e2c..a27669b031 100644 --- a/src/lib/ares_free_hostent.c +++ b/src/lib/ares_free_hostent.c @@ -22,6 +22,7 @@ #include "ares.h" #include "ares_private.h" /* for memdebug */ +#include void ares_free_hostent(struct hostent *host) { diff --git a/src/lib/ares_parse_caa_reply.c b/src/lib/ares_parse_caa_reply.c index f6d4d3c61f..4a8799f824 100644 --- a/src/lib/ares_parse_caa_reply.c +++ b/src/lib/ares_parse_caa_reply.c @@ -36,163 +36,94 @@ #include "ares_dns.h" #include "ares_data.h" #include "ares_private.h" +#include int ares_parse_caa_reply (const unsigned char *abuf, int alen, struct ares_caa_reply **caa_out) { - unsigned int qdcount, ancount, i; - const unsigned char *aptr; - const unsigned char *strptr; - int status, rr_type, rr_class, rr_len; - long len; - char *hostname = NULL, *rr_name = NULL; + int status; struct ares_caa_reply *caa_head = NULL; struct ares_caa_reply *caa_last = NULL; struct ares_caa_reply *caa_curr; + cares_caa_reply *ccaa_curr = NULL; + cares_caa_reply *ccaa_out = NULL; /* Set *caa_out to NULL for all failure cases. */ *caa_out = NULL; - /* Give up if abuf doesn't have room for a header. */ - if (alen < HFIXEDSZ) - return ARES_EBADRESP; - - /* Fetch the question and answer count from the header. */ - qdcount = DNS_HEADER_QDCOUNT (abuf); - ancount = DNS_HEADER_ANCOUNT (abuf); - if (qdcount != 1) - return ARES_EBADRESP; - if (ancount == 0) - return ARES_ENODATA; - - /* Expand the name from the question, and skip past the question. */ - aptr = abuf + HFIXEDSZ; - status = ares_expand_name (aptr, abuf, alen, &hostname, &len); + status = cares_parse_caa_reply(abuf, alen, &ccaa_out); + if (status != ARES_SUCCESS) + { + if (ccaa_out) + ares_free_data(ccaa_out); return status; + } + + /* iterate through the cares_caa_reply list and + * create a new ares_caa_reply */ + for(ccaa_curr = ccaa_out; ccaa_curr; + ccaa_curr = cares_caa_reply_get_next(ccaa_curr)) + { + caa_curr = ares_malloc_data(ARES_DATATYPE_CAA_REPLY); + if (!caa_curr) + { + status = ARES_ENOMEM; + break; + } + if (caa_last) + { + caa_last->next = caa_curr; + } + else { + caa_head = caa_curr; + } + caa_last = caa_curr; - if (aptr + len + QFIXEDSZ > abuf + alen) + /* fill in the ares_caa_reply fields */ + caa_curr->critical = cares_caa_reply_get_critical(ccaa_curr); + + const unsigned char* property = cares_caa_reply_get_property(ccaa_curr); + caa_curr->property = ares_malloc(cares_caa_reply_get_plength(ccaa_curr) + 1); + if (!caa_curr->property) { - ares_free (hostname); - return ARES_EBADRESP; + status = ARES_ENOMEM; + break; } - aptr += len + QFIXEDSZ; + memcpy(caa_curr->property, property, cares_caa_reply_get_plength(ccaa_curr)); + /* Make sure we NULL-terminate */ + caa_curr->property[cares_caa_reply_get_plength(ccaa_curr)] = 0; + + caa_curr->plength = cares_caa_reply_get_plength(ccaa_curr); - /* Examine each answer resource record (RR) in turn. */ - for (i = 0; i < ancount; i++) + const unsigned char* value = cares_caa_reply_get_value(ccaa_curr); + caa_curr->value = ares_malloc(cares_caa_reply_get_length(ccaa_curr) + 1); + if (!caa_curr->value) { - /* Decode the RR up to the data field. */ - status = ares_expand_name (aptr, abuf, alen, &rr_name, &len); - if (status != ARES_SUCCESS) - { - break; - } - aptr += len; - if (aptr + RRFIXEDSZ > abuf + alen) - { - status = ARES_EBADRESP; - break; - } - rr_type = DNS_RR_TYPE (aptr); - rr_class = DNS_RR_CLASS (aptr); - rr_len = DNS_RR_LEN (aptr); - aptr += RRFIXEDSZ; - if (aptr + rr_len > abuf + alen) - { - status = ARES_EBADRESP; - break; - } - - /* Check if we are really looking at a CAA record */ - if ((rr_class == C_IN || rr_class == C_CHAOS) && rr_type == T_CAA) - { - strptr = aptr; - - /* Allocate storage for this CAA answer appending it to the list */ - caa_curr = ares_malloc_data(ARES_DATATYPE_CAA_REPLY); - if (!caa_curr) - { - status = ARES_ENOMEM; - break; - } - if (caa_last) - { - caa_last->next = caa_curr; - } - else - { - caa_head = caa_curr; - } - caa_last = caa_curr; - if (rr_len < 2) - { - status = ARES_EBADRESP; - break; - } - caa_curr->critical = (int)*strptr++; - caa_curr->plength = (int)*strptr++; - if (caa_curr->plength <= 0 || (int)caa_curr->plength >= rr_len - 2) - { - status = ARES_EBADRESP; - break; - } - caa_curr->property = ares_malloc (caa_curr->plength + 1/* Including null byte */); - if (caa_curr->property == NULL) - { - status = ARES_ENOMEM; - break; - } - memcpy ((char *) caa_curr->property, strptr, caa_curr->plength); - /* Make sure we NULL-terminate */ - caa_curr->property[caa_curr->plength] = 0; - strptr += caa_curr->plength; - - caa_curr->length = rr_len - caa_curr->plength - 2; - if (caa_curr->length <= 0) - { - status = ARES_EBADRESP; - break; - } - caa_curr->value = ares_malloc (caa_curr->length + 1/* Including null byte */); - if (caa_curr->value == NULL) - { - status = ARES_ENOMEM; - break; - } - memcpy ((char *) caa_curr->value, strptr, caa_curr->length); - /* Make sure we NULL-terminate */ - caa_curr->value[caa_curr->length] = 0; - } - - /* Propagate any failures */ - if (status != ARES_SUCCESS) - { - break; - } - - /* Don't lose memory in the next iteration */ - ares_free (rr_name); - rr_name = NULL; - - /* Move on to the next record */ - aptr += rr_len; + status = ARES_ENOMEM; + break; } + memcpy(caa_curr->value, value, cares_caa_reply_get_length(ccaa_curr)); + /* Make sure we NULL-terminate */ + caa_curr->value[cares_caa_reply_get_length(ccaa_curr)] = 0; + + caa_curr->length = cares_caa_reply_get_length(ccaa_curr); + } - if (hostname) - ares_free (hostname); - if (rr_name) - ares_free (rr_name); + if (ccaa_out) + { + ares_free_data(ccaa_out); + } /* clean up on error */ if (status != ARES_SUCCESS) - { - if (caa_head) - ares_free_data (caa_head); - return status; - } + { + if (caa_head) + ares_free_data(caa_head); + return status; + } - /* everything looks fine, return the data */ *caa_out = caa_head; return ARES_SUCCESS; diff --git a/src/lib/ares_parse_mx_reply.c b/src/lib/ares_parse_mx_reply.c index a497f55873..172f62f78e 100644 --- a/src/lib/ares_parse_mx_reply.c +++ b/src/lib/ares_parse_mx_reply.c @@ -1,6 +1,5 @@ /* Copyright 1998 by the Massachusetts Institute of Technology. - * Copyright (C) 2010 Jeremy Lal * * Permission to use, copy, modify, and distribute this * software and its documentation for any purpose and without @@ -16,6 +15,7 @@ */ #include "ares_setup.h" +#include "ares_strdup.h" #ifdef HAVE_NETINET_IN_H # include @@ -36,126 +36,76 @@ int ares_parse_mx_reply (const unsigned char *abuf, int alen, - struct ares_mx_reply **mx_out) + struct ares_mx_reply **mx_out) { - unsigned int qdcount, ancount, i; - const unsigned char *aptr, *vptr; - int status, rr_type, rr_class, rr_len; - long len; - char *hostname = NULL, *rr_name = NULL; + + /* call cares_parse_mx_reply, iterate through the result and + * create a linked list of struct ares_mx_reply to return */ + + int status; struct ares_mx_reply *mx_head = NULL; + struct ares_mx_reply *mx_curr = NULL; struct ares_mx_reply *mx_last = NULL; - struct ares_mx_reply *mx_curr; + cares_mx_reply *cmx_curr = NULL; + cares_mx_reply *cmx_out = NULL; /* Set *mx_out to NULL for all failure cases. */ *mx_out = NULL; - /* Give up if abuf doesn't have room for a header. */ - if (alen < HFIXEDSZ) - return ARES_EBADRESP; - - /* Fetch the question and answer count from the header. */ - qdcount = DNS_HEADER_QDCOUNT (abuf); - ancount = DNS_HEADER_ANCOUNT (abuf); - if (qdcount != 1) - return ARES_EBADRESP; - if (ancount == 0) - return ARES_ENODATA; - - /* Expand the name from the question, and skip past the question. */ - aptr = abuf + HFIXEDSZ; - status = ares_expand_name (aptr, abuf, alen, &hostname, &len); + status = cares_parse_mx_reply(abuf, alen, &cmx_out); + + /* clean up on error */ if (status != ARES_SUCCESS) + { + if (cmx_out) + ares_free_data (cmx_out); return status; - - if (aptr + len + QFIXEDSZ > abuf + alen) + } + + /* iterate through the cares_mx_reply list and + * create a new ares_mx_reply */ + for (cmx_curr = cmx_out; cmx_curr; + cmx_curr = cares_mx_reply_get_next(cmx_curr)) + { + mx_curr = ares_malloc_data(ARES_DATATYPE_MX_REPLY); + if (!mx_curr) { - ares_free (hostname); - return ARES_EBADRESP; + status = ARES_ENOMEM; + break; } - aptr += len + QFIXEDSZ; - - /* Examine each answer resource record (RR) in turn. */ - for (i = 0; i < ancount; i++) + if (mx_last) + { + mx_last->next = mx_curr; + } + else { - /* Decode the RR up to the data field. */ - status = ares_expand_name (aptr, abuf, alen, &rr_name, &len); - if (status != ARES_SUCCESS) - { - break; - } - aptr += len; - if (aptr + RRFIXEDSZ > abuf + alen) - { - status = ARES_EBADRESP; - break; - } - rr_type = DNS_RR_TYPE (aptr); - rr_class = DNS_RR_CLASS (aptr); - rr_len = DNS_RR_LEN (aptr); - aptr += RRFIXEDSZ; - if (aptr + rr_len > abuf + alen) - { - status = ARES_EBADRESP; - break; - } - - /* Check if we are really looking at a MX record */ - if (rr_class == C_IN && rr_type == T_MX) - { - /* parse the MX record itself */ - if (rr_len < 2) - { - status = ARES_EBADRESP; - break; - } - - /* Allocate storage for this MX answer appending it to the list */ - mx_curr = ares_malloc_data(ARES_DATATYPE_MX_REPLY); - if (!mx_curr) - { - status = ARES_ENOMEM; - break; - } - if (mx_last) - { - mx_last->next = mx_curr; - } - else - { - mx_head = mx_curr; - } - mx_last = mx_curr; - - vptr = aptr; - mx_curr->priority = DNS__16BIT(vptr); - vptr += sizeof(unsigned short); - - status = ares_expand_name (vptr, abuf, alen, &mx_curr->host, &len); - if (status != ARES_SUCCESS) - break; - } - - /* Don't lose memory in the next iteration */ - ares_free (rr_name); - rr_name = NULL; - - /* Move on to the next record */ - aptr += rr_len; + mx_head = mx_curr; + } + mx_last = mx_curr; + + /* copy the host to newhost so we can free cmx_out */ + char *newhost = ares_strdup(cares_mx_reply_get_host(cmx_curr)); + if (!newhost) { + status = ARES_ENOMEM; + break; } - if (hostname) - ares_free (hostname); - if (rr_name) - ares_free (rr_name); + mx_curr->host = newhost; + mx_curr->priority = cares_mx_reply_get_priority(cmx_curr); + } + + if (cmx_out) + { + ares_free_data (cmx_out); + } /* clean up on error */ if (status != ARES_SUCCESS) - { - if (mx_head) - ares_free_data (mx_head); - return status; - } + { + if (mx_head) + ares_free_data (mx_head); + return status; + } /* everything looks fine, return the data */ *mx_out = mx_head; diff --git a/src/lib/ares_parse_naptr_reply.c b/src/lib/ares_parse_naptr_reply.c index dd984c0fea..fefc83107e 100644 --- a/src/lib/ares_parse_naptr_reply.c +++ b/src/lib/ares_parse_naptr_reply.c @@ -38,145 +38,109 @@ int ares_parse_naptr_reply (const unsigned char *abuf, int alen, struct ares_naptr_reply **naptr_out) { - unsigned int qdcount, ancount, i; - const unsigned char *aptr, *vptr; - int status, rr_type, rr_class, rr_len; - long len; - char *hostname = NULL, *rr_name = NULL; + int status; struct ares_naptr_reply *naptr_head = NULL; struct ares_naptr_reply *naptr_last = NULL; struct ares_naptr_reply *naptr_curr; + cares_naptr_reply *cnaptr_curr = NULL; + cares_naptr_reply *cnaptr_out = NULL; /* Set *naptr_out to NULL for all failure cases. */ *naptr_out = NULL; - /* Give up if abuf doesn't have room for a header. */ - if (alen < HFIXEDSZ) - return ARES_EBADRESP; - - /* Fetch the question and answer count from the header. */ - qdcount = DNS_HEADER_QDCOUNT (abuf); - ancount = DNS_HEADER_ANCOUNT (abuf); - if (qdcount != 1) - return ARES_EBADRESP; - if (ancount == 0) - return ARES_ENODATA; - - /* Expand the name from the question, and skip past the question. */ - aptr = abuf + HFIXEDSZ; - status = ares_expand_name (aptr, abuf, alen, &hostname, &len); + status = cares_parse_naptr_reply(abuf, alen, &cnaptr_out); + if (status != ARES_SUCCESS) + { + if (cnaptr_out) + ares_free_data(cnaptr_out); return status; - - if (aptr + len + QFIXEDSZ > abuf + alen) + } + + /* iterate through the cares_naptr_reply list and + * create a new ares_naptr_reply */ + for(cnaptr_curr = cnaptr_out; cnaptr_curr; + cnaptr_curr = cares_naptr_reply_get_next(cnaptr_curr)) + { + naptr_curr = ares_malloc_data(ARES_DATATYPE_NAPTR_REPLY); + if (!naptr_curr) + { + status = ARES_ENOMEM; + break; + } + if (naptr_last) { - ares_free (hostname); - return ARES_EBADRESP; + naptr_last->next = naptr_curr; } - aptr += len + QFIXEDSZ; + else { + naptr_head = naptr_curr; + } + naptr_last = naptr_curr; + + /* fill in the ares_naptr_reply fields */ + naptr_curr->order = cares_naptr_reply_get_order(cnaptr_curr); + naptr_curr->preference = cares_naptr_reply_get_preference(cnaptr_curr); - /* Examine each answer resource record (RR) in turn. */ - for (i = 0; i < ancount; i++) + const unsigned char* flags = cares_naptr_reply_get_flags(cnaptr_curr); + unsigned long len; + len = strlen((char *)flags); + naptr_curr->flags = ares_malloc(len + 1); + if (!naptr_curr->flags) + { + status = ARES_ENOMEM; + break; + } + memcpy(naptr_curr->flags, flags, len); + /* Make sure we NULL-terminate */ + naptr_curr->flags[len] = 0; + + const unsigned char* service = cares_naptr_reply_get_service(cnaptr_curr); + len = strlen((char *)service); + naptr_curr->service = ares_malloc(len + 1); + if (!naptr_curr->service) { - /* Decode the RR up to the data field. */ - status = ares_expand_name (aptr, abuf, alen, &rr_name, &len); - if (status != ARES_SUCCESS) - { - break; - } - aptr += len; - if (aptr + RRFIXEDSZ > abuf + alen) - { - status = ARES_EBADRESP; - break; - } - rr_type = DNS_RR_TYPE (aptr); - rr_class = DNS_RR_CLASS (aptr); - rr_len = DNS_RR_LEN (aptr); - aptr += RRFIXEDSZ; - if (aptr + rr_len > abuf + alen) - { - status = ARES_EBADRESP; - break; - } - - /* Check if we are really looking at a NAPTR record */ - if (rr_class == C_IN && rr_type == T_NAPTR) - { - /* parse the NAPTR record itself */ - - /* RR must contain at least 7 bytes = 2 x int16 + 3 x name */ - if (rr_len < 7) - { - status = ARES_EBADRESP; - break; - } - - /* Allocate storage for this NAPTR answer appending it to the list */ - naptr_curr = ares_malloc_data(ARES_DATATYPE_NAPTR_REPLY); - if (!naptr_curr) - { - status = ARES_ENOMEM; - break; - } - if (naptr_last) - { - naptr_last->next = naptr_curr; - } - else - { - naptr_head = naptr_curr; - } - naptr_last = naptr_curr; - - vptr = aptr; - naptr_curr->order = DNS__16BIT(vptr); - vptr += sizeof(unsigned short); - naptr_curr->preference = DNS__16BIT(vptr); - vptr += sizeof(unsigned short); - - status = ares_expand_string(vptr, abuf, alen, &naptr_curr->flags, &len); - if (status != ARES_SUCCESS) - break; - vptr += len; - - status = ares_expand_string(vptr, abuf, alen, &naptr_curr->service, &len); - if (status != ARES_SUCCESS) - break; - vptr += len; - - status = ares_expand_string(vptr, abuf, alen, &naptr_curr->regexp, &len); - if (status != ARES_SUCCESS) - break; - vptr += len; - - status = ares_expand_name(vptr, abuf, alen, &naptr_curr->replacement, &len); - if (status != ARES_SUCCESS) - break; - } - - /* Don't lose memory in the next iteration */ - ares_free (rr_name); - rr_name = NULL; - - /* Move on to the next record */ - aptr += rr_len; + status = ARES_ENOMEM; + break; } + memcpy(naptr_curr->service, service, len); + /* Make sure we NULL-terminate */ + naptr_curr->service[len] = 0; + + const unsigned char* regexp = cares_naptr_reply_get_regexp(cnaptr_curr); + len = strlen((char *)regexp); + naptr_curr->regexp = ares_malloc(len + 1); + if (!naptr_curr->regexp) + { + status = ARES_ENOMEM; + break; + } + memcpy(naptr_curr->regexp, regexp, len); + /* Make sure we NULL-terminate */ + naptr_curr->regexp[len] = 0; + + char *replacement = ares_strdup( + cares_naptr_reply_get_replacement(cnaptr_curr)); + if (!replacement) { + status = ARES_ENOMEM; + break; + } + + naptr_curr->replacement = replacement; + } - if (hostname) - ares_free (hostname); - if (rr_name) - ares_free (rr_name); + if (cnaptr_out) + { + ares_free_data(cnaptr_out); + } /* clean up on error */ if (status != ARES_SUCCESS) - { - if (naptr_head) - ares_free_data (naptr_head); - return status; - } + { + if (naptr_head) + ares_free_data(naptr_head); + return status; + } - /* everything looks fine, return the data */ *naptr_out = naptr_head; return ARES_SUCCESS; diff --git a/src/lib/ares_parse_ns_reply.c b/src/lib/ares_parse_ns_reply.c index 8057022c64..baaeb5eadb 100644 --- a/src/lib/ares_parse_ns_reply.c +++ b/src/lib/ares_parse_ns_reply.c @@ -39,139 +39,116 @@ int ares_parse_ns_reply( const unsigned char* abuf, int alen, struct hostent** host ) { - unsigned int qdcount, ancount; - int status, i, rr_type, rr_class, rr_len; - int nameservers_num; - long len; + struct hostent *hostent = NULL; + char *hname = NULL; const unsigned char *aptr; - char* hostname, *rr_name, *rr_data, **nameservers; - struct hostent *hostent; + int status, i; + long len; + int alias_alloc = 2; /* Set *host to NULL for all failure cases. */ *host = NULL; - /* Give up if abuf doesn't have room for a header. */ - if ( alen < HFIXEDSZ ) - return ARES_EBADRESP; - - /* Fetch the question and answer count from the header. */ - qdcount = DNS_HEADER_QDCOUNT( abuf ); - ancount = DNS_HEADER_ANCOUNT( abuf ); - if ( qdcount != 1 ) - return ARES_EBADRESP; - - /* Expand the name from the question, and skip past the question. */ - aptr = abuf + HFIXEDSZ; - status = ares__expand_name_for_response( aptr, abuf, alen, &hostname, &len); - if ( status != ARES_SUCCESS ) - return status; - if ( aptr + len + QFIXEDSZ > abuf + alen ) - { - ares_free( hostname ); - return ARES_EBADRESP; - } - aptr += len + QFIXEDSZ; + cares_ns_reply* ns_out = NULL; + status = cares_parse_ns_reply(abuf, alen, &ns_out); - /* Allocate nameservers array; ancount gives an upper bound */ - nameservers = ares_malloc( ( ancount + 1 ) * sizeof( char * ) ); - if ( !nameservers ) + /* clean up on error */ + if (status != ARES_SUCCESS) { - ares_free( hostname ); - return ARES_ENOMEM; + if (ns_out) + ares_free_data(ns_out); + return status; } - nameservers_num = 0; - /* Examine each answer resource record (RR) in turn. */ - for ( i = 0; i < ( int ) ancount; i++ ) + aptr = abuf + HFIXEDSZ; + status = ares__expand_name_for_response(aptr, abuf, alen, &hname, &len); + if (status != ARES_SUCCESS) { - /* Decode the RR up to the data field. */ - status = ares__expand_name_for_response( aptr, abuf, alen, &rr_name, &len ); - if ( status != ARES_SUCCESS ) - break; - aptr += len; - if ( aptr + RRFIXEDSZ > abuf + alen ) - { - status = ARES_EBADRESP; - ares_free(rr_name); - break; - } - rr_type = DNS_RR_TYPE( aptr ); - rr_class = DNS_RR_CLASS( aptr ); - rr_len = DNS_RR_LEN( aptr ); - aptr += RRFIXEDSZ; - if (aptr + rr_len > abuf + alen) - { - ares_free(rr_name); - status = ARES_EBADRESP; - break; - } - - if ( rr_class == C_IN && rr_type == T_NS ) - { - /* Decode the RR data and add it to the nameservers list */ - status = ares__expand_name_for_response( aptr, abuf, alen, &rr_data, - &len); - if ( status != ARES_SUCCESS ) - { - ares_free(rr_name); - break; - } - - nameservers[nameservers_num] = ares_malloc(strlen(rr_data)+1); - - if (nameservers[nameservers_num]==NULL) - { - ares_free(rr_name); - ares_free(rr_data); - status=ARES_ENOMEM; - break; - } - strcpy(nameservers[nameservers_num],rr_data); - ares_free(rr_data); - - nameservers_num++; - } - - ares_free( rr_name ); - - aptr += rr_len; - if ( aptr > abuf + alen ) - { /* LCOV_EXCL_START: already checked above */ - status = ARES_EBADRESP; - break; - } /* LCOV_EXCL_STOP */ + if (hname) + ares_free(hname); + return status; } - if ( status == ARES_SUCCESS && nameservers_num == 0 ) + /* We got our answer. Allocate memory to build the host entry. */ + hostent = ares_malloc(sizeof(*hostent)); + if (hostent) { - status = ARES_ENODATA; - } - if ( status == ARES_SUCCESS ) - { - /* We got our answer. Allocate memory to build the host entry. */ - nameservers[nameservers_num] = NULL; - hostent = ares_malloc( sizeof( struct hostent ) ); - if ( hostent ) + hostent->h_addr_list = ares_malloc(sizeof(char *)); + if (hostent->h_addr_list) { - hostent->h_addr_list = ares_malloc( 1 * sizeof( char * ) ); - if ( hostent->h_addr_list ) + hostent->h_aliases = ares_malloc(alias_alloc * sizeof (char *)); + if (hostent->h_aliases) { /* Fill in the hostent and return successfully. */ - hostent->h_name = hostname; - hostent->h_aliases = nameservers; + hostent->h_name = hname; + + /* iterate through the linked list of cares_ns_reply + and build the h_aliases array. */ + i = 0; + for (cares_ns_reply* ns_curr=ns_out; ns_curr; + ns_curr = cares_ns_reply_get_next(ns_curr)) + { + if (alias_alloc > 2) + { + char** ptr; + ptr = ares_realloc(hostent->h_aliases, + alias_alloc * sizeof(char *)); + if (!ptr) + { + status = ARES_ENOMEM; + if (ns_out) + ares_free_data(ns_out); + + for (int j = 0; j <= i; ++j) + { + if (hostent->h_aliases[j]) + ares_free(hostent->h_aliases[j]); + } + ares_free(hostent->h_name); + ares_free(hostent->h_aliases); + ares_free(hostent->h_addr_list); + ares_free(hostent); + return status; + } + hostent->h_aliases = ptr; + } + hostent->h_aliases[i] = ares_strdup(cares_ns_reply_get_host(ns_curr)); + if (!hostent->h_aliases[i]) { + status = ARES_ENOMEM; + if (ns_out) + ares_free_data(ns_out); + + for (int j = 0; j <= i; ++j) + { + if (hostent->h_aliases[j]) + ares_free(hostent->h_aliases[j]); + } + ares_free(hostent->h_name); + ares_free(hostent->h_aliases); + ares_free(hostent->h_addr_list); + ares_free(hostent); + return status; + } + i++; + alias_alloc++; + } + hostent->h_aliases[i] = NULL; hostent->h_addrtype = AF_INET; hostent->h_length = sizeof( struct in_addr ); hostent->h_addr_list[0] = NULL; *host = hostent; + if (ns_out) + ares_free_data(ns_out); + return ARES_SUCCESS; } - ares_free( hostent ); + ares_free(hostent->h_aliases); } - status = ARES_ENOMEM; + ares_free(hostent->h_addr_list); } - for ( i = 0; i < nameservers_num; i++ ) - ares_free( nameservers[i] ); - ares_free( nameservers ); - ares_free( hostname ); - return status; + ares_free(hostent); + if (ns_out) + ares_free_data(ns_out); + + return ARES_ENOMEM; } diff --git a/src/lib/ares_parse_ptr_reply.c b/src/lib/ares_parse_ptr_reply.c index abd3ec229a..e389e7e025 100644 --- a/src/lib/ares_parse_ptr_reply.c +++ b/src/lib/ares_parse_ptr_reply.c @@ -15,6 +15,7 @@ */ #include "ares_setup.h" +#include "ares_strdup.h" #ifdef HAVE_NETINET_IN_H # include @@ -37,192 +38,135 @@ int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr, int addrlen, int family, struct hostent **host) { - unsigned int qdcount, ancount; - int status, i, rr_type, rr_class, rr_len; - long len; - const unsigned char *aptr; - char *ptrname, *hostname, *rr_name, *rr_data; struct hostent *hostent = NULL; - int aliascnt = 0; - int alias_alloc = 8; - char ** aliases; - size_t rr_data_len; + int status, i; + int alias_alloc = 2; /* Set *host to NULL for all failure cases. */ *host = NULL; - /* Give up if abuf doesn't have room for a header. */ - if (alen < HFIXEDSZ) - return ARES_EBADRESP; + cares_ptr_reply* ptr_out = NULL; + status = cares_parse_ptr_reply(abuf, alen, &ptr_out); - /* Fetch the question and answer count from the header. */ - qdcount = DNS_HEADER_QDCOUNT(abuf); - ancount = DNS_HEADER_ANCOUNT(abuf); - if (qdcount != 1) - return ARES_EBADRESP; - - /* Expand the name from the question, and skip past the question. */ - aptr = abuf + HFIXEDSZ; - status = ares__expand_name_for_response(aptr, abuf, alen, &ptrname, &len); + /* clean up on error */ if (status != ARES_SUCCESS) + { + if (ptr_out) + ares_free_data(ptr_out); return status; - if (aptr + len + QFIXEDSZ > abuf + alen) + } + + /* We got our answer. Allocate memory to build the host entry. */ + hostent = ares_malloc(sizeof(*hostent)); + if (hostent) + { + hostent->h_addr_list = ares_malloc(2 * sizeof(char *)); + if (hostent->h_addr_list) { - ares_free(ptrname); - return ARES_EBADRESP; - } - aptr += len + QFIXEDSZ; - - /* Examine each answer resource record (RR) in turn. */ - hostname = NULL; - aliases = ares_malloc(alias_alloc * sizeof(char *)); - if (!aliases) - { - ares_free(ptrname); - return ARES_ENOMEM; - } - for (i = 0; i < (int)ancount; i++) - { - /* Decode the RR up to the data field. */ - status = ares__expand_name_for_response(aptr, abuf, alen, &rr_name, &len); - if (status != ARES_SUCCESS) - break; - aptr += len; - if (aptr + RRFIXEDSZ > abuf + alen) + if (addr && addrlen) + { + hostent->h_addr_list[0] = ares_malloc(addrlen); + if (!hostent->h_addr_list[0]) { - ares_free(rr_name); - status = ARES_EBADRESP; - break; + status = ARES_ENOMEM; + if (ptr_out) + ares_free_data(ptr_out); + ares_free(hostent->h_addr_list); + ares_free(hostent); + return status; } - rr_type = DNS_RR_TYPE(aptr); - rr_class = DNS_RR_CLASS(aptr); - rr_len = DNS_RR_LEN(aptr); - aptr += RRFIXEDSZ; - if (aptr + rr_len > abuf + alen) - { - ares_free(rr_name); - status = ARES_EBADRESP; - break; + } else { + hostent->h_addr_list[0] = NULL; + } + hostent->h_aliases = ares_malloc(alias_alloc * sizeof (char *)); + if (hostent->h_aliases) + { + /* Fill in the hostent and return successfully. */ + hostent->h_name = ares_strdup(cares_ptr_reply_get_host(ptr_out)); + if (!hostent->h_name) { + status = ARES_ENOMEM; + if (ptr_out) + ares_free_data(ptr_out); + if (hostent->h_addr_list[0]) + ares_free(hostent->h_addr_list[0]); + ares_free(hostent->h_addr_list); + ares_free(hostent); + return status; } - if (rr_class == C_IN && rr_type == T_PTR - && strcasecmp(rr_name, ptrname) == 0) + /* iterate through the linked list of cares_ptr_reply + and build the h_aliases array. */ + i = 0; + for (cares_ptr_reply* ptr_curr=ptr_out; ptr_curr; + ptr_curr = cares_ptr_reply_get_next(ptr_curr)) { - /* Decode the RR data and set hostname to it. */ - status = ares__expand_name_for_response(aptr, abuf, alen, &rr_data, - &len); - if (status != ARES_SUCCESS) + if (alias_alloc > 2) + { + char** ptr; + ptr = ares_realloc(hostent->h_aliases, + alias_alloc * sizeof(char *)); + if (!ptr) { - ares_free(rr_name); - break; - } - if (hostname) - ares_free(hostname); - hostname = rr_data; - rr_data_len = strlen(rr_data)+1; - aliases[aliascnt] = ares_malloc(rr_data_len * sizeof(char)); - if (!aliases[aliascnt]) - { - ares_free(rr_name); - status = ARES_ENOMEM; - break; - } - strncpy(aliases[aliascnt], rr_data, rr_data_len); - aliascnt++; - if (aliascnt >= alias_alloc) { - char **ptr; - alias_alloc *= 2; - ptr = ares_realloc(aliases, alias_alloc * sizeof(char *)); - if(!ptr) { - ares_free(rr_name); status = ARES_ENOMEM; - break; + if (ptr_out) + ares_free_data(ptr_out); + + for (int j = 0; j <= i; ++j) + { + if (hostent->h_aliases[j]) + { + ares_free(hostent->h_aliases[j]); + } + } + ares_free(hostent->h_name); + ares_free(hostent->h_aliases); + ares_free(hostent->h_addr_list[0]); + ares_free(hostent->h_addr_list); + ares_free(hostent); + return status; } - aliases = ptr; + hostent->h_aliases = ptr; } - } + hostent->h_aliases[i] = ares_strdup(cares_ptr_reply_get_host(ptr_curr)); + if (!hostent->h_aliases[i]) { + status = ARES_ENOMEM; + if (ptr_out) + ares_free_data(ptr_out); - if (rr_class == C_IN && rr_type == T_CNAME) - { - /* Decode the RR data and replace ptrname with it. */ - status = ares__expand_name_for_response(aptr, abuf, alen, &rr_data, - &len); - if (status != ARES_SUCCESS) + for (int j = 0; j <= i; ++j) { - ares_free(rr_name); - break; + if (hostent->h_aliases[j]) + ares_free(hostent->h_aliases[j]); } - ares_free(ptrname); - ptrname = rr_data; + ares_free(hostent->h_name); + ares_free(hostent->h_aliases); + ares_free(hostent->h_addr_list[0]); + ares_free(hostent->h_addr_list); + ares_free(hostent); + return status; + } + i++; + alias_alloc++; } - - ares_free(rr_name); - aptr += rr_len; - if (aptr > abuf + alen) - { /* LCOV_EXCL_START: already checked above */ - status = ARES_EBADRESP; - break; - } /* LCOV_EXCL_STOP */ - } - - if (status == ARES_SUCCESS && !hostname) - status = ARES_ENODATA; - if (status == ARES_SUCCESS) - { - /* If we don't reach the end, we must have failed due to out of memory */ - status = ARES_ENOMEM; - - /* We got our answer. Allocate memory to build the host entry. */ - hostent = ares_malloc(sizeof(*hostent)); - if (!hostent) - goto fail; - - /* If we don't memset here, cleanups may fail */ - memset(hostent, 0, sizeof(*hostent)); - - hostent->h_addr_list = ares_malloc(2 * sizeof(char *)); - if (!hostent->h_addr_list) - goto fail; - - - if (addr && addrlen) { - hostent->h_addr_list[0] = ares_malloc(addrlen); - if (!hostent->h_addr_list[0]) - goto fail; - } else { - hostent->h_addr_list[0] = NULL; + hostent->h_aliases[i] = NULL; + hostent->h_addrtype = aresx_sitoss(family); + hostent->h_length = aresx_sitoss(addrlen); + if (addr && addrlen) + memcpy(hostent->h_addr_list[0], addr, addrlen); + hostent->h_addr_list[1] = NULL; + *host = hostent; + if (ptr_out) + ares_free_data(ptr_out); + + return ARES_SUCCESS; } - - hostent->h_aliases = ares_malloc((aliascnt+1) * sizeof (char *)); - if (!hostent->h_aliases) - goto fail; - - /* Fill in the hostent and return successfully. */ - hostent->h_name = hostname; - for (i=0 ; ih_aliases[i] = aliases[i]; - hostent->h_aliases[aliascnt] = NULL; - hostent->h_addrtype = aresx_sitoss(family); - hostent->h_length = aresx_sitoss(addrlen); - if (addr && addrlen) - memcpy(hostent->h_addr_list[0], addr, addrlen); - hostent->h_addr_list[1] = NULL; - *host = hostent; - ares_free(aliases); - ares_free(ptrname); - - return ARES_SUCCESS; + ares_free(hostent->h_aliases); } + ares_free(hostent->h_addr_list); + } + ares_free(hostent); + if (ptr_out) + ares_free_data(ptr_out); -fail: - ares_free_hostent(hostent); - - for (i=0 ; i abuf + alen) - goto failed; - aptr += QFIXEDSZ; - - /* qclass of SOA with multiple answers */ - if (qclass == T_SOA && ancount > 1) - goto failed; - - /* examine all the records, break and return if found soa */ - for (i = 0; i < ancount; i++) { - rr_name = NULL; - status = ares__expand_name_for_response (aptr, abuf, alen, &rr_name, &len); - if (status != ARES_SUCCESS) - { - ares_free(rr_name); - goto failed_stat; - } + if (csoa_out) + ares_free_data (csoa_out); + return status; + } + soa = ares_malloc_data(ARES_DATATYPE_SOA_REPLY); - aptr += len; - if ( aptr + RRFIXEDSZ > abuf + alen ) + char *nsname = ares_strdup(cares_soa_reply_get_nsname(csoa_out)); + if (!nsname) + { + status = ARES_ENOMEM; + if (soa) { - ares_free(rr_name); - status = ARES_EBADRESP; - goto failed_stat; + ares_free_data (soa); } - rr_type = DNS_RR_TYPE( aptr ); - rr_class = DNS_RR_CLASS( aptr ); - rr_len = DNS_RR_LEN( aptr ); - aptr += RRFIXEDSZ; - if (aptr + rr_len > abuf + alen) - { - ares_free(rr_name); - status = ARES_EBADRESP; - goto failed_stat; - } - if ( rr_class == C_IN && rr_type == T_SOA ) + if (csoa_out) { - /* allocate result struct */ - soa = ares_malloc_data(ARES_DATATYPE_SOA_REPLY); - if (!soa) - { - ares_free(rr_name); - status = ARES_ENOMEM; - goto failed_stat; - } - - /* nsname */ - status = ares__expand_name_for_response(aptr, abuf, alen, &soa->nsname, - &len); - if (status != ARES_SUCCESS) - { - ares_free(rr_name); - goto failed_stat; - } - aptr += len; - - /* hostmaster */ - status = ares__expand_name_for_response(aptr, abuf, alen, - &soa->hostmaster, &len); - if (status != ARES_SUCCESS) - { - ares_free(rr_name); - goto failed_stat; - } - aptr += len; - - /* integer fields */ - if (aptr + 5 * 4 > abuf + alen) - { - ares_free(rr_name); - goto failed; - } - soa->serial = DNS__32BIT(aptr + 0 * 4); - soa->refresh = DNS__32BIT(aptr + 1 * 4); - soa->retry = DNS__32BIT(aptr + 2 * 4); - soa->expire = DNS__32BIT(aptr + 3 * 4); - soa->minttl = DNS__32BIT(aptr + 4 * 4); - - ares_free(qname); - ares_free(rr_name); - - *soa_out = soa; + ares_free_data (csoa_out); + } + return status; + } + soa->nsname = nsname; - return ARES_SUCCESS; + char *hostmaster = ares_strdup(cares_soa_reply_get_hostmaster(csoa_out)); + if (!hostmaster) + { + status = ARES_ENOMEM; + if (soa) + { + ares_free_data (soa); + } + if (csoa_out) + { + ares_free_data (csoa_out); } - aptr += rr_len; + return status; + } + soa->hostmaster = hostmaster; - ares_free(rr_name); + soa->serial = cares_soa_reply_get_serial(csoa_out); + soa->refresh = cares_soa_reply_get_refresh(csoa_out); + soa->retry = cares_soa_reply_get_retry(csoa_out); + soa->expire = cares_soa_reply_get_expire(csoa_out); + soa->minttl = cares_soa_reply_get_minttl(csoa_out); - if (aptr > abuf + alen) - goto failed_stat; + if (csoa_out) + { + ares_free_data (csoa_out); } - /* no SOA record found */ - status = ARES_EBADRESP; - goto failed_stat; -failed: - status = ARES_EBADRESP; + /* everything looks fine, return the data */ + *soa_out = soa; -failed_stat: - if (soa) - ares_free_data(soa); - if (qname) - ares_free(qname); - return status; + return ARES_SUCCESS; } diff --git a/src/lib/ares_parse_srv_reply.c b/src/lib/ares_parse_srv_reply.c index 0f4830a7e3..e3d37bc92b 100644 --- a/src/lib/ares_parse_srv_reply.c +++ b/src/lib/ares_parse_srv_reply.c @@ -47,8 +47,8 @@ ares_parse_srv_reply (const unsigned char *abuf, int alen, struct ares_srv_reply *srv_head = NULL; struct ares_srv_reply *srv_curr = NULL; struct ares_srv_reply *srv_last = NULL; - struct cares_srv_reply *csrv_curr = NULL; - struct cares_srv_reply *csrv_out = NULL; + cares_srv_reply *csrv_curr = NULL; + cares_srv_reply *csrv_out = NULL; /* Set *srv_out to NULL for all failure cases. */ *srv_out = NULL; diff --git a/src/lib/ares_parse_txt_reply.c b/src/lib/ares_parse_txt_reply.c index 6848a092bb..61bef206dd 100644 --- a/src/lib/ares_parse_txt_reply.c +++ b/src/lib/ares_parse_txt_reply.c @@ -42,155 +42,80 @@ static int ares__parse_txt_reply (const unsigned char *abuf, int alen, int ex, void **txt_out) { - size_t substr_len; - unsigned int qdcount, ancount, i; - const unsigned char *aptr; - const unsigned char *strptr; - int status, rr_type, rr_class, rr_len; - long len; - char *hostname = NULL, *rr_name = NULL; + /* call cares_parse_txt_reply, iterate through the result and + * create a linked list of struct ares_txt_reply to return */ + + int status; struct ares_txt_ext *txt_head = NULL; + struct ares_txt_ext *txt_curr = NULL; struct ares_txt_ext *txt_last = NULL; - struct ares_txt_ext *txt_curr; + cares_txt_reply *ctxt_curr = NULL; + cares_txt_reply *ctxt_out = NULL; /* Set *txt_out to NULL for all failure cases. */ *txt_out = NULL; - /* Give up if abuf doesn't have room for a header. */ - if (alen < HFIXEDSZ) - return ARES_EBADRESP; - - /* Fetch the question and answer count from the header. */ - qdcount = DNS_HEADER_QDCOUNT (abuf); - ancount = DNS_HEADER_ANCOUNT (abuf); - if (qdcount != 1) - return ARES_EBADRESP; - if (ancount == 0) - return ARES_ENODATA; - - /* Expand the name from the question, and skip past the question. */ - aptr = abuf + HFIXEDSZ; - status = ares_expand_name (aptr, abuf, alen, &hostname, &len); + status = cares_parse_txt_reply(abuf, alen, &ctxt_out); + + /* clean up on error */ if (status != ARES_SUCCESS) + { + if (ctxt_out) + ares_free_data (ctxt_out); return status; - - if (aptr + len + QFIXEDSZ > abuf + alen) + } + + /* iterate through the cares_txt_reply list and + * create a new ares_txt_reply */ + for (ctxt_curr = ctxt_out; ctxt_curr; + ctxt_curr = cares_txt_reply_get_next(ctxt_curr)) + { + txt_curr = ares_malloc_data(ex ? ARES_DATATYPE_TXT_EXT : + ARES_DATATYPE_TXT_REPLY); + if (!txt_curr) { - ares_free (hostname); - return ARES_EBADRESP; + status = ARES_ENOMEM; + break; } - aptr += len + QFIXEDSZ; + if (txt_last) + { + txt_last->next = txt_curr; + } + else + { + txt_head = txt_curr; + } + txt_last = txt_curr; - /* Examine each answer resource record (RR) in turn. */ - for (i = 0; i < ancount; i++) + const unsigned char* txt = cares_txt_reply_get_txt(ctxt_curr); + txt_curr->txt = ares_malloc(cares_txt_reply_get_length(ctxt_curr) + 1); + if (!txt_curr->txt) { - /* Decode the RR up to the data field. */ - status = ares_expand_name (aptr, abuf, alen, &rr_name, &len); - if (status != ARES_SUCCESS) - { - break; - } - aptr += len; - if (aptr + RRFIXEDSZ > abuf + alen) - { - status = ARES_EBADRESP; - break; - } - rr_type = DNS_RR_TYPE (aptr); - rr_class = DNS_RR_CLASS (aptr); - rr_len = DNS_RR_LEN (aptr); - aptr += RRFIXEDSZ; - if (aptr + rr_len > abuf + alen) - { - status = ARES_EBADRESP; - break; - } - - /* Check if we are really looking at a TXT record */ - if ((rr_class == C_IN || rr_class == C_CHAOS) && rr_type == T_TXT) - { - /* - * There may be multiple substrings in a single TXT record. Each - * substring may be up to 255 characters in length, with a - * "length byte" indicating the size of the substring payload. - * RDATA contains both the length-bytes and payloads of all - * substrings contained therein. - */ - - strptr = aptr; - while (strptr < (aptr + rr_len)) - { - substr_len = (unsigned char)*strptr; - if (strptr + substr_len + 1 > aptr + rr_len) - { - status = ARES_EBADRESP; - break; - } - - /* Allocate storage for this TXT answer appending it to the list */ - txt_curr = ares_malloc_data(ex ? ARES_DATATYPE_TXT_EXT : - ARES_DATATYPE_TXT_REPLY); - if (!txt_curr) - { - status = ARES_ENOMEM; - break; - } - if (txt_last) - { - txt_last->next = txt_curr; - } - else - { - txt_head = txt_curr; - } - txt_last = txt_curr; - - if (ex) - txt_curr->record_start = (strptr == aptr); - txt_curr->length = substr_len; - txt_curr->txt = ares_malloc (substr_len + 1/* Including null byte */); - if (txt_curr->txt == NULL) - { - status = ARES_ENOMEM; - break; - } - - ++strptr; - memcpy ((char *) txt_curr->txt, strptr, substr_len); - - /* Make sure we NULL-terminate */ - txt_curr->txt[substr_len] = 0; - - strptr += substr_len; - } - } - - /* Propagate any failures */ - if (status != ARES_SUCCESS) - { - break; - } - - /* Don't lose memory in the next iteration */ - ares_free (rr_name); - rr_name = NULL; - - /* Move on to the next record */ - aptr += rr_len; + status = ARES_ENOMEM; + break; } + memcpy(txt_curr->txt, txt, cares_txt_reply_get_length(ctxt_curr)); + /* Make sure we NULL-terminate */ + txt_curr->txt[cares_txt_reply_get_length(ctxt_curr)] = 0; + + txt_curr->length = cares_txt_reply_get_length(ctxt_curr); + if (ex) + txt_curr->record_start = cares_txt_reply_get_record_start(ctxt_curr); + + } - if (hostname) - ares_free (hostname); - if (rr_name) - ares_free (rr_name); + if (ctxt_out) + { + ares_free_data (ctxt_out); + } /* clean up on error */ if (status != ARES_SUCCESS) - { - if (txt_head) - ares_free_data (txt_head); - return status; - } + { + if (txt_head) + ares_free_data (txt_head); + return status; + } /* everything looks fine, return the data */ *txt_out = txt_head; diff --git a/src/lib/ares_private.h b/src/lib/ares_private.h index c9544b69b6..ad09b7e4b5 100644 --- a/src/lib/ares_private.h +++ b/src/lib/ares_private.h @@ -416,18 +416,211 @@ int ares__connect_socket(ares_channel channel, (c)->sock_state_cb((c)->sock_state_cb_data, (s), (r), (w)); \ } WHILE_FALSE -/* Private definition of c-ares srv reply so that c-ares users +/* Private definition of c-ares reply structs so that c-ares users * only have access to the type definition in ares.h and must use - * accessor functions to interact with the struct. This way, - * cares_srv_reply can be modified without breaking ABI. + * accessor functions to interact with the structs. This way, + * cares reply structs can be modified without breaking ABI. */ - struct cares_srv_reply { + struct cares_caa_reply { + struct cares_caa_reply *next; + int critical; + unsigned char *property; + size_t plength; /* plength excludes null termination */ + unsigned char *value; + size_t length; /* length excludes null termination */ + unsigned int ttl; +}; + +struct cares_ptr_reply { + struct cares_ptr_reply *next; + char *host; + unsigned int ttl; +}; + +struct cares_ns_reply { + struct cares_ns_reply *next; + char *host; + unsigned int ttl; +}; + +struct cares_srv_reply { struct cares_srv_reply *next; char *host; unsigned short priority; unsigned short weight; unsigned short port; - int ttl; + unsigned int ttl; +}; + +struct cares_mx_reply { + struct cares_mx_reply *next; + char *host; + unsigned short priority; + unsigned int ttl; +}; + +struct cares_txt_reply { + struct cares_txt_reply *next; + unsigned char *txt; + size_t length; + /* 1 - if start of new record + * 0 - if a chunk in the same record */ + unsigned char record_start; + unsigned int ttl; +}; + +struct cares_naptr_reply { + struct cares_naptr_reply *next; + unsigned char *flags; + unsigned char *service; + unsigned char *regexp; + char *replacement; + unsigned short order; + unsigned short preference; + unsigned int ttl; +}; + +struct cares_soa_reply { + char *nsname; + char *hostmaster; + unsigned int serial; + unsigned int refresh; + unsigned int retry; + unsigned int expire; + unsigned int minttl; + unsigned int ttl; }; +/* Private declaration of c-ares reply setters */ +void cares_srv_reply_set_next(cares_srv_reply* srv_reply, + cares_srv_reply* next); + +void cares_srv_reply_set_host(cares_srv_reply* srv_reply, char* host); + +void cares_srv_reply_set_priority(cares_srv_reply* srv_reply, + const unsigned short priority); + +void cares_srv_reply_set_weight(cares_srv_reply* srv_reply, + const unsigned short weight); + +void cares_srv_reply_set_port(cares_srv_reply* srv_reply, + const unsigned short port); + +void cares_srv_reply_set_ttl(cares_srv_reply* srv_reply, + const unsigned int ttl); + + + +void cares_caa_reply_set_next(cares_caa_reply* caa_reply, + cares_caa_reply* next); + +void cares_caa_reply_set_critical(cares_caa_reply* caa_reply, + const int critical); + +void cares_caa_reply_set_property(cares_caa_reply* caa_reply, + unsigned char* property); + +void cares_caa_reply_set_plength(cares_caa_reply* caa_reply, + const size_t plength); + +void cares_caa_reply_set_value(cares_caa_reply* caa_reply, + unsigned char* value); + +void cares_caa_reply_set_length(cares_caa_reply* caa_reply, + const size_t length); + +void cares_caa_reply_set_ttl(cares_caa_reply* caa_reply, + const unsigned int ttl); + +void cares_ptr_reply_set_next(cares_ptr_reply* ptr_reply, + cares_ptr_reply* next); + +void cares_ptr_reply_set_host(cares_ptr_reply* ptr_reply, char* host); + +void cares_ptr_reply_set_ttl(cares_ptr_reply* ptr_reply, + const unsigned int ttl); + +void cares_ns_reply_set_next(cares_ns_reply* ns_reply, + cares_ns_reply* next); + +void cares_ns_reply_set_host(cares_ns_reply* ns_reply, char* host); + +void cares_ns_reply_set_ttl(cares_ns_reply* ns_reply, + const unsigned int ttl); + +void cares_mx_reply_set_next(cares_mx_reply* mx_reply, + cares_mx_reply* next); + +void cares_mx_reply_set_host(cares_mx_reply* mx_reply, char *host); + +void cares_mx_reply_set_priority(cares_mx_reply* mx_reply, + const unsigned short priority); + +void cares_mx_reply_set_ttl(cares_mx_reply* mx_reply, + const unsigned int ttl); + +void cares_txt_reply_set_next(cares_txt_reply* txt_reply, + cares_txt_reply* next); + +void cares_txt_reply_set_txt(cares_txt_reply* txt_reply, + unsigned char* txt); + +void cares_txt_reply_set_length(cares_txt_reply* txt_reply, + const size_t length); + +void cares_txt_reply_set_record_start(cares_txt_reply* txt_reply, + const unsigned char record_start); + +void cares_txt_reply_set_ttl(cares_txt_reply* txt_reply, + const unsigned int ttl); + +void cares_naptr_reply_set_next(cares_naptr_reply* naptr_reply, + cares_naptr_reply* next); + +void cares_naptr_reply_set_flags(cares_naptr_reply* naptr_reply, + unsigned char* flags); + +void cares_naptr_reply_set_service(cares_naptr_reply* naptr_reply, + unsigned char* service); + +void cares_naptr_reply_set_regexp(cares_naptr_reply* naptr_reply, + unsigned char* regexp); + +void cares_naptr_reply_set_replacement(cares_naptr_reply* naptr_reply, + char* replacement); + +void cares_naptr_reply_set_order(cares_naptr_reply* naptr_reply, + const unsigned short order); + +void cares_naptr_reply_set_preference(cares_naptr_reply* naptr_reply, + const unsigned short preference); + +void cares_naptr_reply_set_ttl(cares_naptr_reply* naptr_reply, + const unsigned int ttl); + +void cares_soa_reply_set_nsname(cares_soa_reply* soa_reply, char* nsname); + +void cares_soa_reply_set_hostmaster(cares_soa_reply* soa_reply, + char* hostmaster); + +void cares_soa_reply_set_serial(cares_soa_reply* soa_reply, + const unsigned int serial); + +void cares_soa_reply_set_refresh(cares_soa_reply* soa_reply, + const unsigned int refresh); + +void cares_soa_reply_set_retry(cares_soa_reply* soa_reply, + const unsigned int retry); + +void cares_soa_reply_set_expire(cares_soa_reply* soa_reply, + const unsigned int expire); + +void cares_soa_reply_set_minttl(cares_soa_reply* soa_reply, + const unsigned int minttl); + +void cares_soa_reply_set_ttl(cares_soa_reply* soa_reply, + const unsigned int ttl); + + + #endif /* __ARES_PRIVATE_H */ diff --git a/src/lib/cares_parse_caa_reply.c b/src/lib/cares_parse_caa_reply.c new file mode 100644 index 0000000000..59beea77a3 --- /dev/null +++ b/src/lib/cares_parse_caa_reply.c @@ -0,0 +1,212 @@ + +/* Copyright 2020 by + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" + +#ifdef HAVE_NETINET_IN_H +# include +#endif +#ifdef HAVE_NETDB_H +# include +#endif +#ifdef HAVE_ARPA_INET_H +# include +#endif + +#include "ares_nameser.h" + +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "ares.h" +#include "ares_dns.h" +#include "ares_data.h" +#include "ares_private.h" + +int +cares_parse_caa_reply (const unsigned char *abuf, int alen, + cares_caa_reply **caa_out) +{ + unsigned int qdcount, ancount, i; + const unsigned char *aptr; + const unsigned char *strptr; + int status, rr_type, rr_class, rr_len; + unsigned int rr_ttl; + long len; + char *hostname = NULL, *rr_name = NULL; + cares_caa_reply *caa_head = NULL; + cares_caa_reply *caa_last = NULL; + cares_caa_reply *caa_curr; + + /* Set *caa_out to NULL for all failure cases. */ + *caa_out = NULL; + + /* Give up if abuf doesn't have room for a header. */ + if (alen < HFIXEDSZ) + return ARES_EBADRESP; + + /* Fetch the question and answer count from the header. */ + qdcount = DNS_HEADER_QDCOUNT (abuf); + ancount = DNS_HEADER_ANCOUNT (abuf); + if (qdcount != 1) + return ARES_EBADRESP; + if (ancount == 0) + return ARES_ENODATA; + + /* Expand the name from the question, and skip past the question. */ + aptr = abuf + HFIXEDSZ; + status = ares_expand_name (aptr, abuf, alen, &hostname, &len); + if (status != ARES_SUCCESS) + return status; + + if (aptr + len + QFIXEDSZ > abuf + alen) + { + ares_free (hostname); + return ARES_EBADRESP; + } + aptr += len + QFIXEDSZ; + + /* Examine each answer resource record (RR) in turn. */ + for (i = 0; i < ancount; i++) + { + /* Decode the RR up to the data field. */ + status = ares_expand_name (aptr, abuf, alen, &rr_name, &len); + if (status != ARES_SUCCESS) + { + break; + } + aptr += len; + if (aptr + RRFIXEDSZ > abuf + alen) + { + status = ARES_EBADRESP; + break; + } + rr_type = DNS_RR_TYPE (aptr); + rr_class = DNS_RR_CLASS (aptr); + rr_ttl = DNS_RR_TTL (aptr); + rr_len = DNS_RR_LEN (aptr); + aptr += RRFIXEDSZ; + if (aptr + rr_len > abuf + alen) + { + status = ARES_EBADRESP; + break; + } + + /* Check if we are really looking at a CAA record */ + if ((rr_class == C_IN || rr_class == C_CHAOS) && rr_type == T_CAA) + { + strptr = aptr; + + /* Allocate storage for this CAA answer appending it to the list */ + caa_curr = ares_malloc_data(ARES_DATATYPE_CCAA_REPLY); + if (!caa_curr) + { + status = ARES_ENOMEM; + break; + } + if (caa_last) + { + cares_caa_reply_set_next(caa_last, caa_curr); + } + else + { + caa_head = caa_curr; + } + caa_last = caa_curr; + if (rr_len < 2) + { + status = ARES_EBADRESP; + break; + } + cares_caa_reply_set_critical(caa_curr, (int)*strptr++); + cares_caa_reply_set_plength(caa_curr, (int)*strptr++); + if (cares_caa_reply_get_plength(caa_curr) <= 0 || (int)cares_caa_reply_get_plength(caa_curr) >= rr_len - 2) + { + status = ARES_EBADRESP; + break; + } + unsigned char *property; + property = ares_malloc (cares_caa_reply_get_plength(caa_curr) + 1/* Including null byte */); + if (property == NULL) + { + status = ARES_ENOMEM; + break; + } + memcpy ((char *) property, strptr, cares_caa_reply_get_plength(caa_curr)); + /* Make sure we NULL-terminate */ + property[cares_caa_reply_get_plength(caa_curr)] = 0; + cares_caa_reply_set_property(caa_curr, property); + strptr += cares_caa_reply_get_plength(caa_curr); + + cares_caa_reply_set_length(caa_curr, rr_len - cares_caa_reply_get_plength(caa_curr) - 2); + if (cares_caa_reply_get_length(caa_curr) <= 0) + { + status = ARES_EBADRESP; + break; + } + unsigned char *value; + value = ares_malloc (cares_caa_reply_get_length(caa_curr) + 1/* Including null byte */); + if (value == NULL) + { + status = ARES_ENOMEM; + break; + } + memcpy ((char *) value, strptr, cares_caa_reply_get_length(caa_curr)); + /* Make sure we NULL-terminate */ + value[caa_curr->length] = 0; + cares_caa_reply_set_value(caa_curr, value); + cares_caa_reply_set_ttl(caa_curr, rr_ttl); + } + else if (rr_type != T_CNAME) + { + /* wrong record type */ + status = ARES_ENODATA; + break; + } + + /* Propagate any failures */ + if (status != ARES_SUCCESS) + { + break; + } + + /* Don't lose memory in the next iteration */ + ares_free (rr_name); + rr_name = NULL; + + /* Move on to the next record */ + aptr += rr_len; + } + + if (hostname) + ares_free (hostname); + if (rr_name) + ares_free (rr_name); + + /* clean up on error */ + if (status != ARES_SUCCESS) + { + if (caa_head) + ares_free_data (caa_head); + return status; + } + + /* everything looks fine, return the data */ + *caa_out = caa_head; + + return ARES_SUCCESS; +} diff --git a/src/lib/cares_parse_mx_reply.c b/src/lib/cares_parse_mx_reply.c new file mode 100644 index 0000000000..711e10730d --- /dev/null +++ b/src/lib/cares_parse_mx_reply.c @@ -0,0 +1,176 @@ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * Copyright (C) 2010 Jeremy Lal + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" + +#ifdef HAVE_NETINET_IN_H +# include +#endif +#ifdef HAVE_NETDB_H +# include +#endif +#ifdef HAVE_ARPA_INET_H +# include +#endif + +#include "ares_nameser.h" + +#include "ares.h" +#include "ares_dns.h" +#include "ares_data.h" +#include "ares_private.h" + +int +cares_parse_mx_reply (const unsigned char *abuf, int alen, + cares_mx_reply **mx_out) +{ + unsigned int qdcount, ancount, i; + const unsigned char *aptr, *vptr; + int status, rr_type, rr_class, rr_len; + unsigned int rr_ttl; + long len; + char *hostname = NULL, *rr_name = NULL; + struct cares_mx_reply *mx_head = NULL; + struct cares_mx_reply *mx_last = NULL; + struct cares_mx_reply *mx_curr; + + /* Set *mx_out to NULL for all failure cases. */ + *mx_out = NULL; + + /* Give up if abuf doesn't have room for a header. */ + if (alen < HFIXEDSZ) + return ARES_EBADRESP; + + /* Fetch the question and answer count from the header. */ + qdcount = DNS_HEADER_QDCOUNT (abuf); + ancount = DNS_HEADER_ANCOUNT (abuf); + if (qdcount != 1) + return ARES_EBADRESP; + if (ancount == 0) + return ARES_ENODATA; + + /* Expand the name from the question, and skip past the question. */ + aptr = abuf + HFIXEDSZ; + status = ares_expand_name (aptr, abuf, alen, &hostname, &len); + if (status != ARES_SUCCESS) + return status; + + if (aptr + len + QFIXEDSZ > abuf + alen) + { + ares_free (hostname); + return ARES_EBADRESP; + } + aptr += len + QFIXEDSZ; + + /* Examine each answer resource record (RR) in turn. */ + for (i = 0; i < ancount; i++) + { + /* Decode the RR up to the data field. */ + status = ares_expand_name (aptr, abuf, alen, &rr_name, &len); + if (status != ARES_SUCCESS) + { + break; + } + aptr += len; + if (aptr + RRFIXEDSZ > abuf + alen) + { + status = ARES_EBADRESP; + break; + } + rr_type = DNS_RR_TYPE (aptr); + rr_class = DNS_RR_CLASS (aptr); + rr_ttl = DNS_RR_TTL(aptr); + rr_len = DNS_RR_LEN (aptr); + aptr += RRFIXEDSZ; + if (aptr + rr_len > abuf + alen) + { + status = ARES_EBADRESP; + break; + } + + /* Check if we are really looking at a MX record */ + if (rr_class == C_IN && rr_type == T_MX) + { + /* parse the MX record itself */ + if (rr_len < 2) + { + status = ARES_EBADRESP; + break; + } + + /* Allocate storage for this MX answer appending it to the list */ + mx_curr = ares_malloc_data(ARES_DATATYPE_CMX_REPLY); + if (!mx_curr) + { + status = ARES_ENOMEM; + break; + } + if (mx_last) + { + cares_mx_reply_set_next(mx_last, mx_curr); + } + else + { + mx_head = mx_curr; + } + mx_last = mx_curr; + + vptr = aptr; + cares_mx_reply_set_priority(mx_curr, DNS__16BIT(vptr)); + cares_mx_reply_set_ttl(mx_curr, rr_ttl); + vptr += sizeof(unsigned short); + + char* mx_host = NULL; + status = ares_expand_name (vptr, abuf, alen, &mx_host, &len); + if (status != ARES_SUCCESS) + break; + + cares_mx_reply_set_host(mx_curr, mx_host); + } + else if (rr_type != T_CNAME) + { + /* wrong record type */ + status = ARES_ENODATA; + break; + } + + /* Don't lose memory in the next iteration */ + ares_free (rr_name); + rr_name = NULL; + + /* Move on to the next record */ + aptr += rr_len; + } + + if (hostname) + ares_free (hostname); + if (rr_name) + ares_free (rr_name); + + /* clean up on error */ + if (status != ARES_SUCCESS) + { + if (mx_head) + ares_free_data (mx_head); + return status; + } + + /* everything looks fine, return the data */ + *mx_out = mx_head; + + return ARES_SUCCESS; +} diff --git a/src/lib/cares_parse_naptr_reply.c b/src/lib/cares_parse_naptr_reply.c new file mode 100644 index 0000000000..b2d73831ba --- /dev/null +++ b/src/lib/cares_parse_naptr_reply.c @@ -0,0 +1,200 @@ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * Copyright (C) 2009 by Jakub Hrozek + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" + +#ifdef HAVE_NETINET_IN_H +# include +#endif +#ifdef HAVE_NETDB_H +# include +#endif +#ifdef HAVE_ARPA_INET_H +# include +#endif + +#include "ares_nameser.h" + +#include "ares.h" +#include "ares_dns.h" +#include "ares_data.h" +#include "ares_private.h" + +int +cares_parse_naptr_reply (const unsigned char *abuf, int alen, + struct cares_naptr_reply **naptr_out) +{ + unsigned int qdcount, ancount, i; + const unsigned char *aptr, *vptr; + int status, rr_type, rr_class, rr_len; + unsigned int rr_ttl; + long len; + char *hostname = NULL, *rr_name = NULL; + struct cares_naptr_reply *naptr_head = NULL; + struct cares_naptr_reply *naptr_last = NULL; + struct cares_naptr_reply *naptr_curr; + + /* Set *naptr_out to NULL for all failure cases. */ + *naptr_out = NULL; + + /* Give up if abuf doesn't have room for a header. */ + if (alen < HFIXEDSZ) + return ARES_EBADRESP; + + /* Fetch the question and answer count from the header. */ + qdcount = DNS_HEADER_QDCOUNT (abuf); + ancount = DNS_HEADER_ANCOUNT (abuf); + if (qdcount != 1) + return ARES_EBADRESP; + if (ancount == 0) + return ARES_ENODATA; + + /* Expand the name from the question, and skip past the question. */ + aptr = abuf + HFIXEDSZ; + status = ares_expand_name (aptr, abuf, alen, &hostname, &len); + if (status != ARES_SUCCESS) + return status; + + if (aptr + len + QFIXEDSZ > abuf + alen) + { + ares_free (hostname); + return ARES_EBADRESP; + } + aptr += len + QFIXEDSZ; + + /* Examine each answer resource record (RR) in turn. */ + for (i = 0; i < ancount; i++) + { + /* Decode the RR up to the data field. */ + status = ares_expand_name (aptr, abuf, alen, &rr_name, &len); + if (status != ARES_SUCCESS) + { + break; + } + aptr += len; + if (aptr + RRFIXEDSZ > abuf + alen) + { + status = ARES_EBADRESP; + break; + } + rr_type = DNS_RR_TYPE (aptr); + rr_class = DNS_RR_CLASS (aptr); + rr_ttl = DNS_RR_TTL(aptr); + rr_len = DNS_RR_LEN (aptr); + aptr += RRFIXEDSZ; + if (aptr + rr_len > abuf + alen) + { + status = ARES_EBADRESP; + break; + } + + /* Check if we are really looking at a NAPTR record */ + if (rr_class == C_IN && rr_type == T_NAPTR) + { + /* parse the NAPTR record itself */ + + /* RR must contain at least 7 bytes = 2 x int16 + 3 x name */ + if (rr_len < 7) + { + status = ARES_EBADRESP; + break; + } + + /* Allocate storage for this NAPTR answer appending it to the list */ + naptr_curr = ares_malloc_data(ARES_DATATYPE_CNAPTR_REPLY); + if (!naptr_curr) + { + status = ARES_ENOMEM; + break; + } + if (naptr_last) + { + cares_naptr_reply_set_next(naptr_last, naptr_curr); + } + else + { + naptr_head = naptr_curr; + } + naptr_last = naptr_curr; + + vptr = aptr; + cares_naptr_reply_set_order(naptr_curr, DNS__16BIT(vptr)); + vptr += sizeof(unsigned short); + cares_naptr_reply_set_preference(naptr_curr, DNS__16BIT(vptr)); + vptr += sizeof(unsigned short); + cares_naptr_reply_set_ttl(naptr_curr, rr_ttl); + + unsigned char* flags; + status = ares_expand_string(vptr, abuf, alen, &flags, &len); + if (status != ARES_SUCCESS) + break; + vptr += len; + cares_naptr_reply_set_flags(naptr_curr, flags); + + unsigned char* service; + status = ares_expand_string(vptr, abuf, alen, &service, &len); + if (status != ARES_SUCCESS) + break; + vptr += len; + cares_naptr_reply_set_service(naptr_curr, service); + + unsigned char* regexp; + status = ares_expand_string(vptr, abuf, alen, ®exp, &len); + if (status != ARES_SUCCESS) + break; + vptr += len; + cares_naptr_reply_set_regexp(naptr_curr, regexp); + + char* replacement; + status = ares_expand_name(vptr, abuf, alen, &replacement, &len); + if (status != ARES_SUCCESS) + break; + cares_naptr_reply_set_replacement(naptr_curr, replacement); + } + else if (rr_type != T_CNAME) + { + /* wrong record type */ + status = ARES_ENODATA; + break; + } + + /* Don't lose memory in the next iteration */ + ares_free (rr_name); + rr_name = NULL; + + /* Move on to the next record */ + aptr += rr_len; + } + + if (hostname) + ares_free (hostname); + if (rr_name) + ares_free (rr_name); + + /* clean up on error */ + if (status != ARES_SUCCESS) + { + if (naptr_head) + ares_free_data (naptr_head); + return status; + } + + /* everything looks fine, return the data */ + *naptr_out = naptr_head; + + return ARES_SUCCESS; +} diff --git a/src/lib/cares_parse_ns_reply.c b/src/lib/cares_parse_ns_reply.c new file mode 100644 index 0000000000..bec4a9a563 --- /dev/null +++ b/src/lib/cares_parse_ns_reply.c @@ -0,0 +1,171 @@ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" + +#ifdef HAVE_NETINET_IN_H +# include +#endif +#ifdef HAVE_NETDB_H +# include +#endif + +#include "ares_nameser.h" + +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "ares.h" +#include "ares_dns.h" +#include "ares_nowarn.h" +#include "ares_data.h" +#include "ares_private.h" + +int cares_parse_ns_reply(const unsigned char *abuf, int alen, + cares_ns_reply **ns_out) +{ + unsigned int qdcount, ancount; + int status, i, rr_type, rr_class, rr_len; + unsigned int rr_ttl; + long len; + const unsigned char *aptr; + char *ptrname = NULL, *rr_name = NULL; + cares_ns_reply *ns_head = NULL; + cares_ns_reply *ns_last = NULL; + cares_ns_reply *ns_curr; + + /* Set *ns_out to NULL for all failure cases. */ + *ns_out = NULL; + + /* Give up if abuf doesn't have room for a header. */ + if (alen < HFIXEDSZ) + return ARES_EBADRESP; + + /* Fetch the question and answer count from the header. */ + qdcount = DNS_HEADER_QDCOUNT(abuf); + ancount = DNS_HEADER_ANCOUNT(abuf); + if (qdcount != 1) + return ARES_EBADRESP; + if (ancount == 0) + return ARES_ENODATA; + + /* Expand the name from the question, and skip past the question. */ + aptr = abuf + HFIXEDSZ; + status = ares__expand_name_for_response(aptr, abuf, alen, &ptrname, &len); + if (status != ARES_SUCCESS) + return status; + if (aptr + len + QFIXEDSZ > abuf + alen) + { + ares_free(ptrname); + return ARES_EBADRESP; + } + aptr += len + QFIXEDSZ; + + /* Examine each answer resource record (RR) in turn. */ + for (i = 0; i < (int)ancount; i++) + { + /* Decode the RR up to the data field. */ + status = ares__expand_name_for_response(aptr, abuf, alen, &rr_name, &len); + if (status != ARES_SUCCESS) + break; + aptr += len; + if (aptr + RRFIXEDSZ > abuf + alen) + { + status = ARES_EBADRESP; + break; + } + rr_type = DNS_RR_TYPE(aptr); + rr_class = DNS_RR_CLASS(aptr); + rr_ttl = DNS_RR_TTL(aptr); + rr_len = DNS_RR_LEN(aptr); + aptr += RRFIXEDSZ; + if (aptr + rr_len > abuf + alen) + { + status = ARES_EBADRESP; + break; + } + + if (rr_class == C_IN && rr_type == T_NS) + { + /* Allocate storage for this NS answer appending it to the list */ + ns_curr = ares_malloc_data(ARES_DATATYPE_CNS_REPLY); + if (!ns_curr) + { + status = ARES_ENOMEM; + break; + } + if (ns_last) + { + cares_ns_reply_set_next(ns_last, ns_curr); + } + else + { + ns_head = ns_curr; + } + ns_last = ns_curr; + + char* ns_host = NULL; + /* Decode the RR data and set hostname to it. */ + status = ares__expand_name_for_response(aptr, abuf, alen, &ns_host, + &len); + if (status != ARES_SUCCESS) + { + break; + } + + cares_ns_reply_set_host(ns_curr, ns_host); + cares_ns_reply_set_ttl(ns_curr, rr_ttl); + } + else if (rr_type != T_CNAME) + { + /* wrong record type */ + status = ARES_ENODATA; + break; + } + + /* Don't lose memory in the next iteration */ + ares_free(rr_name); + rr_name = NULL; + + /* Move on to the next record */ + aptr += rr_len; + if (aptr > abuf + alen) + { /* LCOV_EXCL_START: already checked above */ + status = ARES_EBADRESP; + break; + } /* LCOV_EXCL_STOP */ + } + + if (ptrname) + ares_free(ptrname); + if (rr_name) + ares_free(rr_name); + + /* clean up on error */ + if (status != ARES_SUCCESS) + { + if (ns_head) + { + ares_free_data(ns_head); + } + return status; + } + + /* everything looks fine, return the data */ + *ns_out = ns_head; + return ARES_SUCCESS; +} diff --git a/src/lib/cares_parse_ptr_reply.c b/src/lib/cares_parse_ptr_reply.c new file mode 100644 index 0000000000..68b877ac44 --- /dev/null +++ b/src/lib/cares_parse_ptr_reply.c @@ -0,0 +1,188 @@ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" + +#ifdef HAVE_NETINET_IN_H +# include +#endif +#ifdef HAVE_NETDB_H +# include +#endif + +#include "ares_nameser.h" + +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "ares.h" +#include "ares_dns.h" +#include "ares_nowarn.h" +#include "ares_data.h" +#include "ares_private.h" + +int cares_parse_ptr_reply(const unsigned char *abuf, int alen, + cares_ptr_reply **ptr_out) +{ + unsigned int qdcount, ancount; + int status, i, rr_type, rr_class, rr_len; + unsigned int rr_ttl; + long len; + const unsigned char *aptr; + char *ptrname = NULL, *rr_name = NULL; + cares_ptr_reply *ptr_head = NULL; + cares_ptr_reply *ptr_last = NULL; + cares_ptr_reply *ptr_curr; + + /* Set *ptr_out to NULL for all failure cases. */ + *ptr_out = NULL; + + /* Give up if abuf doesn't have room for a header. */ + if (alen < HFIXEDSZ) + return ARES_EBADRESP; + + /* Fetch the question and answer count from the header. */ + qdcount = DNS_HEADER_QDCOUNT(abuf); + ancount = DNS_HEADER_ANCOUNT(abuf); + if (qdcount != 1) + return ARES_EBADRESP; + if (ancount == 0) + return ARES_ENODATA; + + /* Expand the name from the question, and skip past the question. */ + aptr = abuf + HFIXEDSZ; + status = ares__expand_name_for_response(aptr, abuf, alen, &ptrname, &len); + if (status != ARES_SUCCESS) + return status; + if (aptr + len + QFIXEDSZ > abuf + alen) + { + ares_free(ptrname); + return ARES_EBADRESP; + } + aptr += len + QFIXEDSZ; + + /* Examine each answer resource record (RR) in turn. */ + for (i = 0; i < (int)ancount; i++) + { + /* Decode the RR up to the data field. */ + status = ares__expand_name_for_response(aptr, abuf, alen, &rr_name, &len); + if (status != ARES_SUCCESS) + break; + aptr += len; + if (aptr + RRFIXEDSZ > abuf + alen) + { + status = ARES_EBADRESP; + break; + } + rr_type = DNS_RR_TYPE(aptr); + rr_class = DNS_RR_CLASS(aptr); + rr_ttl = DNS_RR_TTL(aptr); + rr_len = DNS_RR_LEN(aptr); + aptr += RRFIXEDSZ; + if (aptr + rr_len > abuf + alen) + { + status = ARES_EBADRESP; + break; + } + + if (rr_class == C_IN && rr_type == T_PTR) + { + if (strcasecmp(rr_name, ptrname) != 0) + { + /* question and answer don't match */ + status = ARES_ENODATA; + break; + } + /* Allocate storage for this PTR answer appending it to the list */ + ptr_curr = ares_malloc_data(ARES_DATATYPE_CPTR_REPLY); + if (!ptr_curr) + { + status = ARES_ENOMEM; + break; + } + if (ptr_last) + { + cares_ptr_reply_set_next(ptr_last, ptr_curr); + } + else + { + ptr_head = ptr_curr; + } + ptr_last = ptr_curr; + + char* ptr_host = NULL; + /* Decode the RR data and set hostname to it. */ + status = ares__expand_name_for_response(aptr, abuf, alen, &ptr_host, + &len); + if (status != ARES_SUCCESS) + { + break; + } + + cares_ptr_reply_set_host(ptr_curr, ptr_host); + cares_ptr_reply_set_ttl(ptr_curr, rr_ttl); + } + else if (rr_class == C_IN && rr_type == T_CNAME) + { + /* Decode the RR data and replace ptrname with it. */ + ares_free(ptrname); + ptrname = NULL; + status = ares__expand_name_for_response(aptr, abuf, alen, &ptrname, + &len); + if (status != ARES_SUCCESS) + { + break; + } + } + else + { + /* wrong record type */ + status = ARES_ENODATA; + break; + } + + /* Don't lose memory in the next iteration */ + ares_free(rr_name); + rr_name = NULL; + + /* Move on to the next record */ + aptr += rr_len; + if (aptr > abuf + alen) + { /* LCOV_EXCL_START: already checked above */ + status = ARES_EBADRESP; + break; + } /* LCOV_EXCL_STOP */ + } + if (ptrname) + ares_free(ptrname); + if (rr_name) + ares_free(rr_name); + + /* clean up on error */ + if (status != ARES_SUCCESS) + { + if (ptr_head) + { + ares_free_data (ptr_head); + } + return status; + } + + /* everything looks fine, return the data */ + *ptr_out = ptr_head; + return ARES_SUCCESS; +} diff --git a/src/lib/cares_parse_soa_reply.c b/src/lib/cares_parse_soa_reply.c new file mode 100644 index 0000000000..2d0a5a4521 --- /dev/null +++ b/src/lib/cares_parse_soa_reply.c @@ -0,0 +1,191 @@ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * Copyright (C) 2012 Marko Kreen + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" + +#ifdef HAVE_NETINET_IN_H +# include +#endif +#ifdef HAVE_NETDB_H +# include +#endif +#ifdef HAVE_ARPA_INET_H +# include +#endif + +#include "ares_nameser.h" + +#include "ares.h" +#include "ares_dns.h" +#include "ares_data.h" +#include "ares_private.h" + +int +cares_parse_soa_reply(const unsigned char *abuf, int alen, + struct cares_soa_reply **soa_out) +{ + const unsigned char *aptr; + long len; + char *qname = NULL, *rr_name = NULL; + struct cares_soa_reply *soa = NULL; + int qdcount, ancount, qclass; + int status, i, rr_type, rr_class, rr_len; + unsigned int rr_ttl; + + if (alen < HFIXEDSZ) + return ARES_EBADRESP; + + /* parse message header */ + qdcount = DNS_HEADER_QDCOUNT(abuf); + ancount = DNS_HEADER_ANCOUNT(abuf); + + if (qdcount != 1) + return ARES_EBADRESP; + if (ancount == 0) + return ARES_EBADRESP; + + aptr = abuf + HFIXEDSZ; + + /* query name */ + status = ares__expand_name_for_response(aptr, abuf, alen, &qname, &len); + if (status != ARES_SUCCESS) + return status; + + if (alen <= len + HFIXEDSZ + 1) + return ARES_EBADRESP; + aptr += len; + + qclass = DNS_QUESTION_TYPE(aptr); + + /* skip qtype & qclass */ + if (aptr + QFIXEDSZ > abuf + alen) + { + ares_free(qname); + return ARES_EBADRESP; + } + aptr += QFIXEDSZ; + + /* qclass of SOA with multiple answers */ + if (qclass == T_SOA && ancount > 1) + { + ares_free(qname); + return ARES_EBADRESP; + } + + /* examine all the records, break and return if found soa */ + for (i = 0; i < ancount; i++) + { + rr_name = NULL; + status = ares__expand_name_for_response (aptr, abuf, alen, &rr_name, &len); + if (status != ARES_SUCCESS) + { + break; + } + + aptr += len; + if ( aptr + RRFIXEDSZ > abuf + alen ) + { + status = ARES_EBADRESP; + break; + } + rr_type = DNS_RR_TYPE( aptr ); + rr_class = DNS_RR_CLASS( aptr ); + rr_ttl = DNS_RR_TTL(aptr); + rr_len = DNS_RR_LEN( aptr ); + aptr += RRFIXEDSZ; + if (aptr + rr_len > abuf + alen) + { + status = ARES_EBADRESP; + break; + } + if ( rr_class == C_IN && rr_type == T_SOA ) + { + /* allocate result struct */ + soa = ares_malloc_data(ARES_DATATYPE_CSOA_REPLY); + if (!soa) + { + status = ARES_ENOMEM; + break; + } + + /* nsname */ + char* nsname; + status = ares__expand_name_for_response(aptr, abuf, alen, &nsname, + &len); + if (status != ARES_SUCCESS) + break; + cares_soa_reply_set_nsname(soa, nsname); + aptr += len; + + /* hostmaster */ + char* hostmaster; + status = ares__expand_name_for_response(aptr, abuf, alen, + &hostmaster, &len); + if (status != ARES_SUCCESS) + break; + cares_soa_reply_set_hostmaster(soa, hostmaster); + aptr += len; + + /* integer fields */ + if (aptr + 5 * 4 > abuf + alen) + { + status = ARES_EBADRESP; + break; + } + cares_soa_reply_set_serial(soa, DNS__32BIT(aptr + 0 * 4)); + cares_soa_reply_set_refresh(soa, DNS__32BIT(aptr + 1 * 4)); + cares_soa_reply_set_retry(soa, DNS__32BIT(aptr + 2 * 4)); + cares_soa_reply_set_expire(soa, DNS__32BIT(aptr + 3 * 4)); + cares_soa_reply_set_minttl(soa, DNS__32BIT(aptr + 4 * 4)); + cares_soa_reply_set_ttl(soa, rr_ttl); + break; + } + aptr += rr_len; + + ares_free(rr_name); + rr_name = NULL; + + if (aptr > abuf + alen) + { + status = ARES_EBADRESP; + break; + } + } + + if (status == ARES_SUCCESS && !soa) + { + /* no SOA record found */ + status = ARES_EBADRESP; + } + + if (qname) + ares_free(qname); + if(rr_name) + ares_free(rr_name); + + if (status != ARES_SUCCESS) + { + /* no SOA record found */ + if (soa) + ares_free_data(soa); + return status; + } + + *soa_out = soa; + + return ARES_SUCCESS; +} diff --git a/src/lib/cares_parse_srv_reply.c b/src/lib/cares_parse_srv_reply.c index 5e11f92c3a..2c75b55fd6 100644 --- a/src/lib/cares_parse_srv_reply.c +++ b/src/lib/cares_parse_srv_reply.c @@ -36,16 +36,17 @@ int cares_parse_srv_reply (const unsigned char *abuf, int alen, - struct cares_srv_reply **srv_out) + cares_srv_reply **srv_out) { unsigned int qdcount, ancount, i; const unsigned char *aptr, *vptr; - int status, rr_type, rr_class, rr_ttl, rr_len; + int status, rr_type, rr_class, rr_len; + unsigned int rr_ttl; long len; char *hostname = NULL, *rr_name = NULL; - struct cares_srv_reply *srv_head = NULL; - struct cares_srv_reply *srv_last = NULL; - struct cares_srv_reply *srv_curr; + cares_srv_reply *srv_head = NULL; + cares_srv_reply *srv_last = NULL; + cares_srv_reply *srv_curr; /* Set *srv_out to NULL for all failure cases. */ *srv_out = NULL; @@ -120,7 +121,7 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, } if (srv_last) { - srv_last->next = srv_curr; + cares_srv_reply_set_next(srv_last, srv_curr); } else { @@ -144,6 +145,12 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, break; cares_srv_reply_set_host(srv_curr, srv_host); } + else if (rr_type != T_CNAME) + { + /* wrong record type */ + status = ARES_ENODATA; + break; + } /* Don't lose memory in the next iteration */ ares_free (rr_name); diff --git a/src/lib/cares_parse_txt_reply.c b/src/lib/cares_parse_txt_reply.c new file mode 100644 index 0000000000..0f4f04258c --- /dev/null +++ b/src/lib/cares_parse_txt_reply.c @@ -0,0 +1,210 @@ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * Copyright (C) 2009 by Jakub Hrozek + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" + +#ifdef HAVE_NETINET_IN_H +# include +#endif +#ifdef HAVE_NETDB_H +# include +#endif +#ifdef HAVE_ARPA_INET_H +# include +#endif + +#include "ares_nameser.h" + +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "ares.h" +#include "ares_dns.h" +#include "ares_data.h" +#include "ares_private.h" + +int cares_parse_txt_reply (const unsigned char *abuf, int alen, + cares_txt_reply **txt_out) +{ + size_t substr_len; + unsigned int qdcount, ancount, i; + const unsigned char *aptr; + const unsigned char *strptr; + int status, rr_type, rr_class, rr_len; + unsigned int rr_ttl; + long len; + char *hostname = NULL, *rr_name = NULL; + struct cares_txt_reply *txt_head = NULL; + struct cares_txt_reply *txt_last = NULL; + struct cares_txt_reply *txt_curr; + + /* Set *txt_out to NULL for all failure cases. */ + *txt_out = NULL; + + /* Give up if abuf doesn't have room for a header. */ + if (alen < HFIXEDSZ) + return ARES_EBADRESP; + + /* Fetch the question and answer count from the header. */ + qdcount = DNS_HEADER_QDCOUNT (abuf); + ancount = DNS_HEADER_ANCOUNT (abuf); + if (qdcount != 1) + return ARES_EBADRESP; + if (ancount == 0) + return ARES_ENODATA; + + /* Expand the name from the question, and skip past the question. */ + aptr = abuf + HFIXEDSZ; + status = ares_expand_name (aptr, abuf, alen, &hostname, &len); + if (status != ARES_SUCCESS) + return status; + + if (aptr + len + QFIXEDSZ > abuf + alen) + { + ares_free (hostname); + return ARES_EBADRESP; + } + aptr += len + QFIXEDSZ; + + /* Examine each answer resource record (RR) in turn. */ + for (i = 0; i < ancount; i++) + { + /* Decode the RR up to the data field. */ + status = ares_expand_name (aptr, abuf, alen, &rr_name, &len); + if (status != ARES_SUCCESS) + { + break; + } + aptr += len; + if (aptr + RRFIXEDSZ > abuf + alen) + { + status = ARES_EBADRESP; + break; + } + rr_type = DNS_RR_TYPE (aptr); + rr_class = DNS_RR_CLASS (aptr); + rr_ttl = DNS_RR_TTL(aptr); + rr_len = DNS_RR_LEN (aptr); + aptr += RRFIXEDSZ; + if (aptr + rr_len > abuf + alen) + { + status = ARES_EBADRESP; + break; + } + + /* Check if we are really looking at a TXT record */ + if ((rr_class == C_IN || rr_class == C_CHAOS) && rr_type == T_TXT) + { + /* + * There may be multiple substrings in a single TXT record. Each + * substring may be up to 255 characters in length, with a + * "length byte" indicating the size of the substring payload. + * RDATA contains both the length-bytes and payloads of all + * substrings contained therein. + */ + + strptr = aptr; + while (strptr < (aptr + rr_len)) + { + substr_len = (unsigned char)*strptr; + if (strptr + substr_len + 1 > aptr + rr_len) + { + status = ARES_EBADRESP; + break; + } + + /* Allocate storage for this TXT answer appending it to the list */ + txt_curr = ares_malloc_data(ARES_DATATYPE_CTXT_REPLY); + if (!txt_curr) + { + status = ARES_ENOMEM; + break; + } + if (txt_last) + { + cares_txt_reply_set_next(txt_last, txt_curr); + } + else + { + txt_head = txt_curr; + } + txt_last = txt_curr; + + + cares_txt_reply_set_record_start(txt_curr, (strptr == aptr)); + cares_txt_reply_set_length(txt_curr, substr_len); + cares_txt_reply_set_ttl(txt_curr, rr_ttl); + + unsigned char* txt = NULL; + txt = ares_malloc (substr_len + 1/* Including null byte */); + if (txt == NULL) + { + status = ARES_ENOMEM; + break; + } + + ++strptr; + memcpy ((char *) txt, strptr, substr_len); + + /* Make sure we NULL-terminate */ + txt[substr_len] = 0; + + cares_txt_reply_set_txt(txt_curr, txt); + + strptr += substr_len; + } + } + else if (rr_type != T_CNAME) + { + /* wrong record type */ + status = ARES_ENODATA; + break; + } + + /* Propagate any failures */ + if (status != ARES_SUCCESS) + { + break; + } + + /* Don't lose memory in the next iteration */ + ares_free (rr_name); + rr_name = NULL; + + /* Move on to the next record */ + aptr += rr_len; + } + + if (hostname) + ares_free (hostname); + if (rr_name) + ares_free (rr_name); + + /* clean up on error */ + if (status != ARES_SUCCESS) + { + if (txt_head) + ares_free_data (txt_head); + return status; + } + + /* everything looks fine, return the data */ + *txt_out = txt_head; + + return ARES_SUCCESS; +} diff --git a/src/lib/cares_reply.c b/src/lib/cares_reply.c index b4423b6c88..374c2ff396 100644 --- a/src/lib/cares_reply.c +++ b/src/lib/cares_reply.c @@ -15,71 +15,521 @@ #include "ares.h" #include "ares_private.h" #include "string.h" +#include -struct cares_srv_reply* -cares_srv_reply_get_next(const struct cares_srv_reply* srv_reply) + +cares_srv_reply* +cares_srv_reply_get_next(const cares_srv_reply* srv_reply) { return srv_reply->next; } -const char* cares_srv_reply_get_host(const struct cares_srv_reply* srv_reply) +const char* cares_srv_reply_get_host(const cares_srv_reply* srv_reply) { return srv_reply->host; } unsigned short -cares_srv_reply_get_priority(const struct cares_srv_reply* srv_reply) +cares_srv_reply_get_priority(const cares_srv_reply* srv_reply) { return srv_reply->priority; } unsigned short -cares_srv_reply_get_weight(const struct cares_srv_reply* srv_reply) +cares_srv_reply_get_weight(const cares_srv_reply* srv_reply) { return srv_reply->weight; } unsigned short -cares_srv_reply_get_port(const struct cares_srv_reply* srv_reply) +cares_srv_reply_get_port(const cares_srv_reply* srv_reply) { return srv_reply->port; } -int cares_srv_reply_get_ttl(const struct cares_srv_reply* srv_reply) +unsigned int cares_srv_reply_get_ttl(const cares_srv_reply* srv_reply) { return srv_reply->ttl; } -void cares_srv_reply_set_next(struct cares_srv_reply* srv_reply, - struct cares_srv_reply* next) +void cares_srv_reply_set_next(cares_srv_reply* srv_reply, + cares_srv_reply* next) { srv_reply->next = next; } -void cares_srv_reply_set_host(struct cares_srv_reply* srv_reply, char* host) +void cares_srv_reply_set_host(cares_srv_reply* srv_reply, char* host) { srv_reply->host = host; } -void cares_srv_reply_set_priority(struct cares_srv_reply* srv_reply, +void cares_srv_reply_set_priority(cares_srv_reply* srv_reply, const unsigned short priority) { srv_reply->priority = priority; } -void cares_srv_reply_set_weight(struct cares_srv_reply* srv_reply, +void cares_srv_reply_set_weight(cares_srv_reply* srv_reply, const unsigned short weight) { srv_reply->weight = weight; } -void cares_srv_reply_set_port(struct cares_srv_reply* srv_reply, +void cares_srv_reply_set_port(cares_srv_reply* srv_reply, const unsigned short port) { srv_reply->port = port; } -void cares_srv_reply_set_ttl(struct cares_srv_reply* srv_reply, const int ttl) +void cares_srv_reply_set_ttl(cares_srv_reply* srv_reply, + const unsigned int ttl) { srv_reply->ttl = ttl; } + + + +cares_caa_reply* +cares_caa_reply_get_next(const cares_caa_reply* caa_reply) +{ + return caa_reply->next; +} + +int +cares_caa_reply_get_critical(const cares_caa_reply* caa_reply) +{ + return caa_reply->critical; +} + +const unsigned char* +cares_caa_reply_get_property(const cares_caa_reply* caa_reply) +{ + return caa_reply->property; +} + +size_t +cares_caa_reply_get_plength(const cares_caa_reply* caa_reply) +{ + return caa_reply->plength; +} + +const unsigned char* +cares_caa_reply_get_value(const cares_caa_reply* caa_reply) +{ + return caa_reply->value; +} + +size_t +cares_caa_reply_get_length(const cares_caa_reply* caa_reply) +{ + return caa_reply->length; +} + +unsigned int cares_caa_reply_get_ttl(const cares_caa_reply* caa_reply) +{ + return caa_reply->ttl; +} + +void cares_caa_reply_set_next(cares_caa_reply* caa_reply, + cares_caa_reply* next) +{ + caa_reply->next = next; +} + +void cares_caa_reply_set_critical(cares_caa_reply* caa_reply, + const int critical) +{ + caa_reply->critical = critical; +} + +void cares_caa_reply_set_property(cares_caa_reply* caa_reply, + unsigned char* property) +{ + caa_reply->property = property; +} + +void cares_caa_reply_set_plength(cares_caa_reply* caa_reply, + const size_t plength) +{ + caa_reply->plength = plength; +} + +void cares_caa_reply_set_value(cares_caa_reply* caa_reply, + unsigned char* value) +{ + caa_reply->value = value; +} + +void cares_caa_reply_set_length(cares_caa_reply* caa_reply, + const size_t length) +{ + caa_reply->length = length; +} + +void cares_caa_reply_set_ttl(cares_caa_reply* caa_reply, + const unsigned int ttl) +{ + caa_reply->ttl = ttl; +} + +cares_ptr_reply* +cares_ptr_reply_get_next(const cares_ptr_reply* ptr_reply) +{ + return ptr_reply->next; +} + +const char* +cares_ptr_reply_get_host(const cares_ptr_reply* ptr_reply) +{ + return ptr_reply->host; +} + +unsigned int cares_ptr_reply_get_ttl(const cares_ptr_reply* ptr_reply) +{ + return ptr_reply->ttl; +} + +void cares_ptr_reply_set_next(cares_ptr_reply* ptr_reply, + cares_ptr_reply* next) +{ + ptr_reply->next = next; +} + +void cares_ptr_reply_set_host(cares_ptr_reply* ptr_reply, char* host) +{ + ptr_reply->host = host; +} + +void cares_ptr_reply_set_ttl(cares_ptr_reply* ptr_reply, + const unsigned int ttl) +{ + ptr_reply->ttl = ttl; +} + +cares_ns_reply* +cares_ns_reply_get_next(const cares_ns_reply* ns_reply) +{ + return ns_reply->next; +} + +const char* +cares_ns_reply_get_host(const cares_ns_reply* ns_reply) +{ + return ns_reply->host; +} + +unsigned int cares_ns_reply_get_ttl(const cares_ns_reply* ns_reply) +{ + return ns_reply->ttl; +} + +void cares_ns_reply_set_next(cares_ns_reply* ns_reply, + cares_ns_reply* next) +{ + ns_reply->next = next; +} + +void cares_ns_reply_set_host(cares_ns_reply* ns_reply, char* host) +{ + ns_reply->host = host; +} + +void cares_ns_reply_set_ttl(cares_ns_reply* ns_reply, + const unsigned int ttl) +{ + ns_reply->ttl = ttl; +} + +cares_mx_reply* +cares_mx_reply_get_next(const cares_mx_reply* mx_reply) +{ + return mx_reply->next; +} + +const char* +cares_mx_reply_get_host(const cares_mx_reply* mx_reply) +{ + return mx_reply->host; +} + +unsigned short +cares_mx_reply_get_priority(const cares_mx_reply* mx_reply) +{ + return mx_reply->priority; +} + +unsigned int cares_mx_reply_get_ttl(const cares_mx_reply* mx_reply) +{ + return mx_reply->ttl; +} + +void cares_mx_reply_set_next(cares_mx_reply* mx_reply, + cares_mx_reply* next) +{ + mx_reply->next = next; +} + +void cares_mx_reply_set_host(cares_mx_reply* mx_reply, char *host) +{ + mx_reply->host = host; +} + +void cares_mx_reply_set_priority(cares_mx_reply* mx_reply, + const unsigned short priority) +{ + mx_reply->priority = priority; +} + +void cares_mx_reply_set_ttl(cares_mx_reply* mx_reply, + const unsigned int ttl) +{ + mx_reply->ttl = ttl; +} + +cares_txt_reply* +cares_txt_reply_get_next(const cares_txt_reply* txt_reply) +{ + return txt_reply->next; +} + +const unsigned char* +cares_txt_reply_get_txt(const cares_txt_reply* txt_reply) +{ + return txt_reply->txt; +} + +size_t +cares_txt_reply_get_length(const cares_txt_reply* txt_reply) +{ + return txt_reply->length; +} + +unsigned char +cares_txt_reply_get_record_start(const cares_txt_reply* txt_reply) +{ + return txt_reply->record_start; +} + +unsigned int cares_txt_reply_get_ttl(const cares_txt_reply* txt_reply) +{ + return txt_reply->ttl; +} + +void cares_txt_reply_set_next(cares_txt_reply* txt_reply, + cares_txt_reply* next) +{ + txt_reply->next = next; +} + +void cares_txt_reply_set_txt(cares_txt_reply* txt_reply, + unsigned char* txt) +{ + txt_reply->txt = txt; +} + +void cares_txt_reply_set_length(cares_txt_reply* txt_reply, + const size_t length) +{ + txt_reply->length = length; +} + +void cares_txt_reply_set_record_start(cares_txt_reply* txt_reply, + const unsigned char record_start) +{ + txt_reply->record_start = record_start; +} + +void cares_txt_reply_set_ttl(cares_txt_reply* txt_reply, + const unsigned int ttl) +{ + txt_reply->ttl = ttl; +} + +cares_naptr_reply* +cares_naptr_reply_get_next(const cares_naptr_reply* naptr_reply) +{ + return naptr_reply->next; +} + +const unsigned char* +cares_naptr_reply_get_flags(const cares_naptr_reply* naptr_reply) +{ + return naptr_reply->flags; +} + +const unsigned char* +cares_naptr_reply_get_service(const cares_naptr_reply* naptr_reply) +{ + return naptr_reply->service; +} + +const unsigned char* +cares_naptr_reply_get_regexp(const cares_naptr_reply* naptr_reply) +{ + return naptr_reply->regexp; +} + +const char* +cares_naptr_reply_get_replacement(const cares_naptr_reply* naptr_reply) +{ + return naptr_reply->replacement; +} + +unsigned short +cares_naptr_reply_get_order(const cares_naptr_reply* naptr_reply) +{ + return naptr_reply->order; +} + +unsigned short +cares_naptr_reply_get_preference(const cares_naptr_reply* naptr_reply) +{ + return naptr_reply->preference; +} + +unsigned int cares_naptr_reply_get_ttl(const cares_naptr_reply* naptr_reply) +{ + return naptr_reply->ttl; +} + +void cares_naptr_reply_set_next(cares_naptr_reply* naptr_reply, + cares_naptr_reply* next) +{ + naptr_reply->next = next; +} + +void cares_naptr_reply_set_flags(cares_naptr_reply* naptr_reply, + unsigned char* flags) +{ + naptr_reply->flags = flags; +} + +void cares_naptr_reply_set_service(cares_naptr_reply* naptr_reply, + unsigned char* service) +{ + naptr_reply->service = service; +} + +void cares_naptr_reply_set_regexp(cares_naptr_reply* naptr_reply, + unsigned char* regexp) +{ + naptr_reply->regexp = regexp; +} + +void cares_naptr_reply_set_replacement(cares_naptr_reply* naptr_reply, + char* replacement) +{ + naptr_reply->replacement = replacement; +} + +void cares_naptr_reply_set_order(cares_naptr_reply* naptr_reply, + const unsigned short order) +{ + naptr_reply->order = order; +} + +void cares_naptr_reply_set_preference(cares_naptr_reply* naptr_reply, + const unsigned short preference) +{ + naptr_reply->preference = preference; +} + +void cares_naptr_reply_set_ttl(cares_naptr_reply* naptr_reply, + const unsigned int ttl) +{ + naptr_reply->ttl = ttl; +} + +const char* +cares_soa_reply_get_nsname(const cares_soa_reply* soa_reply) +{ + return soa_reply->nsname; +} + +const char* +cares_soa_reply_get_hostmaster(const cares_soa_reply* soa_reply) +{ + return soa_reply->hostmaster; +} + +unsigned int +cares_soa_reply_get_serial(const cares_soa_reply* soa_reply) +{ + return soa_reply->serial; +} + +unsigned int +cares_soa_reply_get_refresh(const cares_soa_reply* soa_reply) +{ + return soa_reply->refresh; +} + +unsigned int +cares_soa_reply_get_retry(const cares_soa_reply* soa_reply) +{ + return soa_reply->retry; +} + +unsigned int +cares_soa_reply_get_expire(const cares_soa_reply* soa_reply) +{ + return soa_reply->expire; +} + +unsigned int +cares_soa_reply_get_minttl(const cares_soa_reply* soa_reply) +{ + return soa_reply->minttl; +} + +unsigned int cares_soa_reply_get_ttl(const cares_soa_reply* soa_reply) +{ + return soa_reply->ttl; +} + +void cares_soa_reply_set_nsname(cares_soa_reply* soa_reply, char* nsname) +{ + soa_reply->nsname = nsname; +} + +void cares_soa_reply_set_hostmaster(cares_soa_reply* soa_reply, + char* hostmaster) +{ + soa_reply->hostmaster = hostmaster; +} + +void cares_soa_reply_set_serial(cares_soa_reply* soa_reply, + const unsigned int serial) +{ + soa_reply->serial = serial; +} + +void cares_soa_reply_set_refresh(cares_soa_reply* soa_reply, + const unsigned int refresh) +{ + soa_reply->refresh = refresh; +} + +void cares_soa_reply_set_retry(cares_soa_reply* soa_reply, + const unsigned int retry) +{ + soa_reply->retry = retry; +} + +void cares_soa_reply_set_expire(cares_soa_reply* soa_reply, + const unsigned int expire) +{ + soa_reply->expire = expire; +} + +void cares_soa_reply_set_minttl(cares_soa_reply* soa_reply, + const unsigned int minttl) +{ + soa_reply->minttl = minttl; +} + +void cares_soa_reply_set_ttl(cares_soa_reply* soa_reply, + const unsigned int ttl) +{ + soa_reply->ttl = ttl; +} diff --git a/test/ares-test-parse-caa.cc b/test/ares-test-parse-caa.cc index 99903edf71..9e688e2115 100644 --- a/test/ares-test-parse-caa.cc +++ b/test/ares-test-parse-caa.cc @@ -33,12 +33,38 @@ TEST_F(LibraryTest, ParseCaaReplyMultipleOK) { ares_free_data(caa); } +TEST_F(LibraryTest, ParseCCaaReplyMultipleOK) { + std::vector data = { + 0x27, 0x86, 0x81, 0x80, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x09, 0x77, 0x69, 0x6B, // '............wik + 0x69, 0x70, 0x65, 0x64, 0x69, 0x61, 0x03, 0x6F, 0x72, 0x67, 0x00, 0x01, 0x01, 0x00, 0x01, 0xC0, // ipedia.org...... + 0x0C, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x02, 0x23, 0x00, 0x15, 0x00, 0x05, 0x69, 0x73, 0x73, // ........#....iss + 0x75, 0x65, 0x67, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x73, 0x69, 0x67, 0x6E, 0x2E, 0x63, 0x6F, 0x6D, // ueglobalsign.com + 0xC0, 0x0C, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x02, 0x23, 0x00, 0x13, 0x00, 0x05, 0x69, 0x73, // .........#....is + 0x73, 0x75, 0x65, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0xC0, // suedigicert.com. + 0x0C, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x02, 0x23, 0x00, 0x16, 0x00, 0x05, 0x69, 0x73, 0x73, // ........#....iss + 0x75, 0x65, 0x6C, 0x65, 0x74, 0x73, 0x65, 0x6E, 0x63, 0x72, 0x79, 0x70, 0x74, 0x2E, 0x6F, 0x72, // ueletsencrypt.or + 0x67, 0xC0, 0x0C, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x02, 0x23, 0x00, 0x25, 0x00, 0x05, 0x69, // g.........#.%..i + 0x6F, 0x64, 0x65, 0x66, 0x6D, 0x61, 0x69, 0x6C, 0x74, 0x6F, 0x3A, 0x64, 0x6E, 0x73, 0x2D, 0x61, // odefmailto:dns-a + 0x64, 0x6D, 0x69, 0x6E, 0x40, 0x77, 0x69, 0x6B, 0x69, 0x6D, 0x65, 0x64, 0x69, 0x61, 0x2E, 0x6F, // dmin@wikimedia.o + 0x72, 0x67 // rg + }; + + cares_caa_reply* caa = nullptr; + EXPECT_EQ(ARES_SUCCESS, cares_parse_caa_reply(data.data(), data.size(), &caa)); + ASSERT_NE(nullptr, caa); + ASSERT_NE(nullptr, cares_caa_reply_get_next(caa)); + ASSERT_NE(nullptr, cares_caa_reply_get_next(cares_caa_reply_get_next(caa))); + ASSERT_NE(nullptr, cares_caa_reply_get_next(cares_caa_reply_get_next(cares_caa_reply_get_next(caa)))); + + ares_free_data(caa); +} + TEST_F(LibraryTest, ParseCaaReplySingleOK) { std::vector data = { - 0x27, 0x86, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0x67, 0x6F, 0x6F, // '............goo - 0x67, 0x6C, 0x65, 0x03, 0x63, 0x6F, 0x6D, 0x00, 0x01, 0x01, 0x00, 0x01, 0xC0, 0x0C, 0x01, 0x01, // gle.com......... - 0x00, 0x01, 0x00, 0x01, 0x43, 0xBE, 0x00, 0x0F, 0x00, 0x05, 0x69, 0x73, 0x73, 0x75, 0x65, 0x70, // ....C.....issuep - 0x6B, 0x69, 0x2E, 0x67, 0x6F, 0x6F, 0x67 // ki.goog + 0x27, 0x86, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0x67, 0x6F, 0x6F, // '............goo + 0x67, 0x6C, 0x65, 0x03, 0x63, 0x6F, 0x6D, 0x00, 0x01, 0x01, 0x00, 0x01, 0xC0, 0x0C, 0x01, 0x01, // gle.com......... + 0x00, 0x01, 0x00, 0x01, 0x43, 0xBE, 0x00, 0x0F, 0x00, 0x05, 0x69, 0x73, 0x73, 0x75, 0x65, 0x70, // ....C.....issuep + 0x6B, 0x69, 0x2E, 0x67, 0x6F, 0x6F, 0x67 // ki.goog }; struct ares_caa_reply* caa = nullptr; @@ -54,12 +80,34 @@ TEST_F(LibraryTest, ParseCaaReplySingleOK) { ares_free_data(caa); } +TEST_F(LibraryTest, ParseCCaaReplySingleOK) { + std::vector data = { + 0x27, 0x86, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0x67, 0x6F, 0x6F, // '............goo + 0x67, 0x6C, 0x65, 0x03, 0x63, 0x6F, 0x6D, 0x00, 0x01, 0x01, 0x00, 0x01, 0xC0, 0x0C, 0x01, 0x01, // gle.com......... + 0x00, 0x01, 0x00, 0x01, 0x43, 0xBE, 0x00, 0x0F, 0x00, 0x05, 0x69, 0x73, 0x73, 0x75, 0x65, 0x70, // ....C.....issuep + 0x6B, 0x69, 0x2E, 0x67, 0x6F, 0x6F, 0x67 // ki.goog + }; + + cares_caa_reply* caa = nullptr; + EXPECT_EQ(ARES_SUCCESS, cares_parse_caa_reply(data.data(), data.size(), &caa)); + ASSERT_NE(nullptr, caa); + + EXPECT_EQ(cares_caa_reply_get_critical(caa), 0); + EXPECT_EQ(cares_caa_reply_get_plength(caa), 5); + EXPECT_STREQ((char *)cares_caa_reply_get_property(caa), "issue"); + EXPECT_EQ(cares_caa_reply_get_length(caa), 8); + EXPECT_STREQ((char *)cares_caa_reply_get_value(caa), "pki.goog"); + EXPECT_EQ(cares_caa_reply_get_ttl(caa), 82878); + + ares_free_data(caa); +} + TEST_F(LibraryTest, ParseCaaBogusReply1) { std::vector data = { - 0x27, 0x86, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0x67, 0x6F, 0x6F, // '............goo - 0x67, 0x6C, 0x65, 0x03, 0x63, 0x6F, 0x6D, 0x00, 0x01, 0x01, 0x00, 0x01, 0xC0, 0x0C, 0x01, 0x01, // gle.com......... - 0x00, 0x01, 0x00, 0x01, 0x43, 0xBE, 0x00, 0x0F, 0x00, 0x00, 0x69, 0x73, 0x73, 0x75, 0x65, 0x70, // ....C.....issuep - 0x6B, 0x69, 0x2E, 0x67, 0x6F, 0x6F, 0x67 // ki.goog + 0x27, 0x86, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0x67, 0x6F, 0x6F, // '............goo + 0x67, 0x6C, 0x65, 0x03, 0x63, 0x6F, 0x6D, 0x00, 0x01, 0x01, 0x00, 0x01, 0xC0, 0x0C, 0x01, 0x01, // gle.com......... + 0x00, 0x01, 0x00, 0x01, 0x43, 0xBE, 0x00, 0x0F, 0x00, 0x00, 0x69, 0x73, 0x73, 0x75, 0x65, 0x70, // ....C.....issuep + 0x6B, 0x69, 0x2E, 0x67, 0x6F, 0x6F, 0x67 // ki.goog }; struct ares_caa_reply* caa = nullptr; @@ -67,12 +115,25 @@ TEST_F(LibraryTest, ParseCaaBogusReply1) { ASSERT_EQ(nullptr, caa); } +TEST_F(LibraryTest, ParseCCaaBogusReply1) { + std::vector data = { + 0x27, 0x86, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0x67, 0x6F, 0x6F, // '............goo + 0x67, 0x6C, 0x65, 0x03, 0x63, 0x6F, 0x6D, 0x00, 0x01, 0x01, 0x00, 0x01, 0xC0, 0x0C, 0x01, 0x01, // gle.com......... + 0x00, 0x01, 0x00, 0x01, 0x43, 0xBE, 0x00, 0x0F, 0x00, 0x00, 0x69, 0x73, 0x73, 0x75, 0x65, 0x70, // ....C.....issuep + 0x6B, 0x69, 0x2E, 0x67, 0x6F, 0x6F, 0x67 // ki.goog + }; + + struct cares_caa_reply* caa = nullptr; + EXPECT_EQ(ARES_EBADRESP, cares_parse_caa_reply(data.data(), data.size(), &caa)); + ASSERT_EQ(nullptr, caa); +} + TEST_F(LibraryTest, ParseCaaBogusReply2) { std::vector data = { - 0x27, 0x86, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0x67, 0x6F, 0x6F, // '............goo - 0x67, 0x6C, 0x65, 0x03, 0x63, 0x6F, 0x6D, 0x00, 0x01, 0x01, 0x00, 0x01, 0xC0, 0x0C, 0x01, 0x01, // gle.com......... - 0x00, 0x01, 0x00, 0x01, 0x43, 0xBE, 0x00, 0x0F, 0x00, 0x0e, 0x69, 0x73, 0x73, 0x75, 0x65, 0x70, // ....C.....issuep - 0x6B, 0x69, 0x2E, 0x67, 0x6F, 0x6F, 0x67 // ki.goog + 0x27, 0x86, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0x67, 0x6F, 0x6F, // '............goo + 0x67, 0x6C, 0x65, 0x03, 0x63, 0x6F, 0x6D, 0x00, 0x01, 0x01, 0x00, 0x01, 0xC0, 0x0C, 0x01, 0x01, // gle.com......... + 0x00, 0x01, 0x00, 0x01, 0x43, 0xBE, 0x00, 0x0F, 0x00, 0x0e, 0x69, 0x73, 0x73, 0x75, 0x65, 0x70, // ....C.....issuep + 0x6B, 0x69, 0x2E, 0x67, 0x6F, 0x6F, 0x67 // ki.goog }; struct ares_caa_reply* caa = nullptr; @@ -80,12 +141,25 @@ TEST_F(LibraryTest, ParseCaaBogusReply2) { ASSERT_EQ(nullptr, caa); } +TEST_F(LibraryTest, ParseCCaaBogusReply2) { + std::vector data = { + 0x27, 0x86, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0x67, 0x6F, 0x6F, // '............goo + 0x67, 0x6C, 0x65, 0x03, 0x63, 0x6F, 0x6D, 0x00, 0x01, 0x01, 0x00, 0x01, 0xC0, 0x0C, 0x01, 0x01, // gle.com......... + 0x00, 0x01, 0x00, 0x01, 0x43, 0xBE, 0x00, 0x0F, 0x00, 0x0e, 0x69, 0x73, 0x73, 0x75, 0x65, 0x70, // ....C.....issuep + 0x6B, 0x69, 0x2E, 0x67, 0x6F, 0x6F, 0x67 // ki.goog + }; + + struct cares_caa_reply* caa = nullptr; + EXPECT_EQ(ARES_EBADRESP, cares_parse_caa_reply(data.data(), data.size(), &caa)); + ASSERT_EQ(nullptr, caa); +} + TEST_F(LibraryTest, ParseCaaBogusReply3) { std::vector data = { - 0x27, 0x86, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0x67, 0x6F, 0x6F, // '............goo - 0x67, 0x6C, 0x65, 0x03, 0x63, 0x6F, 0x6D, 0x00, 0x01, 0x01, 0x00, 0x01, 0xC0, 0x0C, 0x01, 0x01, // gle.com......... - 0x00, 0x01, 0x00, 0x01, 0x43, 0xBE, 0x00, 0x10, 0x00, 0x05, 0x69, 0x73, 0x73, 0x75, 0x65, 0x70, // ....C.....issuep - 0x6B, 0x69, 0x2E, 0x67, 0x6F, 0x6F, 0x67 // ki.goog + 0x27, 0x86, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0x67, 0x6F, 0x6F, // '............goo + 0x67, 0x6C, 0x65, 0x03, 0x63, 0x6F, 0x6D, 0x00, 0x01, 0x01, 0x00, 0x01, 0xC0, 0x0C, 0x01, 0x01, // gle.com......... + 0x00, 0x01, 0x00, 0x01, 0x43, 0xBE, 0x00, 0x10, 0x00, 0x05, 0x69, 0x73, 0x73, 0x75, 0x65, 0x70, // ....C.....issuep + 0x6B, 0x69, 0x2E, 0x67, 0x6F, 0x6F, 0x67 // ki.goog }; struct ares_caa_reply* caa = nullptr; @@ -93,15 +167,28 @@ TEST_F(LibraryTest, ParseCaaBogusReply3) { ASSERT_EQ(nullptr, caa); } +TEST_F(LibraryTest, ParseCCaaBogusReply3) { + std::vector data = { + 0x27, 0x86, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0x67, 0x6F, 0x6F, // '............goo + 0x67, 0x6C, 0x65, 0x03, 0x63, 0x6F, 0x6D, 0x00, 0x01, 0x01, 0x00, 0x01, 0xC0, 0x0C, 0x01, 0x01, // gle.com......... + 0x00, 0x01, 0x00, 0x01, 0x43, 0xBE, 0x00, 0x10, 0x00, 0x05, 0x69, 0x73, 0x73, 0x75, 0x65, 0x70, // ....C.....issuep + 0x6B, 0x69, 0x2E, 0x67, 0x6F, 0x6F, 0x67 // ki.goog + }; + + struct cares_caa_reply* caa = nullptr; + EXPECT_EQ(ARES_EBADRESP, cares_parse_caa_reply(data.data(), data.size(), &caa)); + ASSERT_EQ(nullptr, caa); +} + TEST_F(LibraryTest, ParseCaaEmptyReply) { std::vector data = { - 0x27, 0x86, 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x09, 0x77, 0x69, 0x6B, // '............wik - 0x69, 0x70, 0x65, 0x64, 0x69, 0x61, 0x02, 0x64, 0x65, 0x00, 0x01, 0x01, 0x00, 0x01, 0xC0, 0x0C, // ipedia.de....... - 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x02, 0x58, 0x00, 0x3B, 0x04, 0x6E, 0x73, 0x38, 0x31, 0x0D, // .......X.;.ns81. - 0x64, 0x6F, 0x6D, 0x61, 0x69, 0x6E, 0x63, 0x6F, 0x6E, 0x74, 0x72, 0x6F, 0x6C, 0x03, 0x63, 0x6F, // domaincontrol.co - 0x6D, 0x00, 0x03, 0x64, 0x6E, 0x73, 0x05, 0x6A, 0x6F, 0x6D, 0x61, 0x78, 0x03, 0x6E, 0x65, 0x74, // m..dns.jomax.net - 0x00, 0x78, 0x67, 0xFE, 0x34, 0x00, 0x00, 0x70, 0x80, 0x00, 0x00, 0x1C, 0x20, 0x00, 0x09, 0x3A, // .xg.4..p.... ..: - 0x80, 0x00, 0x00, 0x02, 0x58 // ....X + 0x27, 0x86, 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x09, 0x77, 0x69, 0x6B, // '............wik + 0x69, 0x70, 0x65, 0x64, 0x69, 0x61, 0x02, 0x64, 0x65, 0x00, 0x01, 0x01, 0x00, 0x01, 0xC0, 0x0C, // ipedia.de....... + 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x02, 0x58, 0x00, 0x3B, 0x04, 0x6E, 0x73, 0x38, 0x31, 0x0D, // .......X.;.ns81. + 0x64, 0x6F, 0x6D, 0x61, 0x69, 0x6E, 0x63, 0x6F, 0x6E, 0x74, 0x72, 0x6F, 0x6C, 0x03, 0x63, 0x6F, // domaincontrol.co + 0x6D, 0x00, 0x03, 0x64, 0x6E, 0x73, 0x05, 0x6A, 0x6F, 0x6D, 0x61, 0x78, 0x03, 0x6E, 0x65, 0x74, // m..dns.jomax.net + 0x00, 0x78, 0x67, 0xFE, 0x34, 0x00, 0x00, 0x70, 0x80, 0x00, 0x00, 0x1C, 0x20, 0x00, 0x09, 0x3A, // .xg.4..p.... ..: + 0x80, 0x00, 0x00, 0x02, 0x58 // ....X }; struct ares_caa_reply* caa = nullptr; @@ -109,5 +196,21 @@ TEST_F(LibraryTest, ParseCaaEmptyReply) { ASSERT_EQ(nullptr, caa); } +TEST_F(LibraryTest, ParseCCaaEmptyReply) { + std::vector data = { + 0x27, 0x86, 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x09, 0x77, 0x69, 0x6B, // '............wik + 0x69, 0x70, 0x65, 0x64, 0x69, 0x61, 0x02, 0x64, 0x65, 0x00, 0x01, 0x01, 0x00, 0x01, 0xC0, 0x0C, // ipedia.de....... + 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x02, 0x58, 0x00, 0x3B, 0x04, 0x6E, 0x73, 0x38, 0x31, 0x0D, // .......X.;.ns81. + 0x64, 0x6F, 0x6D, 0x61, 0x69, 0x6E, 0x63, 0x6F, 0x6E, 0x74, 0x72, 0x6F, 0x6C, 0x03, 0x63, 0x6F, // domaincontrol.co + 0x6D, 0x00, 0x03, 0x64, 0x6E, 0x73, 0x05, 0x6A, 0x6F, 0x6D, 0x61, 0x78, 0x03, 0x6E, 0x65, 0x74, // m..dns.jomax.net + 0x00, 0x78, 0x67, 0xFE, 0x34, 0x00, 0x00, 0x70, 0x80, 0x00, 0x00, 0x1C, 0x20, 0x00, 0x09, 0x3A, // .xg.4..p.... ..: + 0x80, 0x00, 0x00, 0x02, 0x58 // ....X + }; + + struct cares_caa_reply* caa = nullptr; + EXPECT_EQ(ARES_ENODATA, cares_parse_caa_reply(data.data(), data.size(), &caa)); + ASSERT_EQ(nullptr, caa); +} + } // namespace test } // namespace ares diff --git a/test/ares-test-parse-mx.cc b/test/ares-test-parse-mx.cc index db8fa89404..19cce7a077 100644 --- a/test/ares-test-parse-mx.cc +++ b/test/ares-test-parse-mx.cc @@ -30,6 +30,31 @@ TEST_F(LibraryTest, ParseMxReplyOK) { ares_free_data(mx); } +TEST_F(LibraryTest, ParseCMxReplyOK) { + DNSPacket pkt; + pkt.set_qid(0x1234).set_response().set_aa() + .add_question(new DNSQuestion("example.com", T_MX)) + .add_answer(new DNSMxRR("example.com", 100, 100, "mx1.example.com")) + .add_answer(new DNSMxRR("example.com", 100, 200, "mx2.example.com")); + std::vector data = pkt.data(); + + struct cares_mx_reply* mx = nullptr; + EXPECT_EQ(ARES_SUCCESS, cares_parse_mx_reply(data.data(), data.size(), &mx)); + ASSERT_NE(nullptr, mx); + EXPECT_EQ("mx1.example.com", std::string(cares_mx_reply_get_host(mx))); + EXPECT_EQ(100, cares_mx_reply_get_priority(mx)); + EXPECT_EQ(100, cares_mx_reply_get_ttl(mx)); + + struct cares_mx_reply* mx2 = cares_mx_reply_get_next(mx); + ASSERT_NE(nullptr, mx2); + EXPECT_EQ("mx2.example.com", std::string(cares_mx_reply_get_host(mx2))); + EXPECT_EQ(200, cares_mx_reply_get_priority(mx2)); + EXPECT_EQ(100, cares_mx_reply_get_ttl(mx2)); + EXPECT_EQ(nullptr, cares_mx_reply_get_next(mx2)); + + ares_free_data(mx); +} + TEST_F(LibraryTest, ParseMxReplyMalformed) { std::vector data = { 0x12, 0x34, // qid @@ -61,6 +86,37 @@ TEST_F(LibraryTest, ParseMxReplyMalformed) { ASSERT_EQ(nullptr, mx); } +TEST_F(LibraryTest, ParseCMxReplyMalformed) { + std::vector data = { + 0x12, 0x34, // qid + 0x84, // response + query + AA + not-TC + not-RD + 0x00, // not-RA + not-Z + not-AD + not-CD + rc=NoError + 0x00, 0x01, // num questions + 0x00, 0x01, // num answer RRs + 0x00, 0x00, // num authority RRs + 0x00, 0x00, // num additional RRs + // Question + 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', + 0x03, 'c', 'o', 'm', + 0x00, + 0x00, 0x0F, // type MX + 0x00, 0x01, // class IN + // Answer 1 + 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', + 0x03, 'c', 'o', 'm', + 0x00, + 0x00, 0x0F, // RR type + 0x00, 0x01, // class IN + 0x01, 0x02, 0x03, 0x04, // TTL + 0x00, 0x01, // rdata length -- too short + 0x02, + }; + + struct cares_mx_reply* mx = nullptr; + EXPECT_EQ(ARES_EBADRESP, cares_parse_mx_reply(data.data(), data.size(), &mx)); + ASSERT_EQ(nullptr, mx); +} + TEST_F(LibraryTest, ParseMxReplyErrors) { DNSPacket pkt; @@ -96,11 +152,10 @@ TEST_F(LibraryTest, ParseMxReplyErrors) { pkt.add_question(new DNSQuestion("example.com", T_MX)); // Wrong sort of answer. - // TODO(drysdale): check if this should be ARES_ENODATA? pkt.answers_.clear(); pkt.add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")); data = pkt.data(); - EXPECT_EQ(ARES_SUCCESS, ares_parse_mx_reply(data.data(), data.size(), &mx)); + EXPECT_EQ(ARES_ENODATA, ares_parse_mx_reply(data.data(), data.size(), &mx)); EXPECT_EQ(nullptr, mx); pkt.answers_.clear(); pkt.add_answer(new DNSMxRR("example.com", 100, 100, "mx1.example.com")); @@ -121,6 +176,64 @@ TEST_F(LibraryTest, ParseMxReplyErrors) { } } +TEST_F(LibraryTest, ParseCMxReplyErrors) { + DNSPacket pkt; + pkt.set_qid(0x1234).set_response().set_aa() + .add_question(new DNSQuestion("example.com", T_MX)) + .add_answer(new DNSMxRR("example.com", 100, 100, "mx1.example.com")); + std::vector data; + struct cares_mx_reply* mx = nullptr; + + // No question. + pkt.questions_.clear(); + data = pkt.data(); + EXPECT_EQ(ARES_EBADRESP, cares_parse_mx_reply(data.data(), data.size(), &mx)); + EXPECT_EQ(nullptr, mx); + pkt.add_question(new DNSQuestion("example.com", T_MX)); + +#ifdef DISABLED + // Question != answer + pkt.questions_.clear(); + pkt.add_question(new DNSQuestion("Axample.com", T_MX)); + data = pkt.data(); + EXPECT_EQ(ARES_EBADRESP, cares_parse_mx_reply(data.data(), data.size(), &mx)); + pkt.questions_.clear(); + pkt.add_question(new DNSQuestion("example.com", T_MX)); +#endif + + // Two questions. + pkt.add_question(new DNSQuestion("example.com", T_MX)); + data = pkt.data(); + EXPECT_EQ(ARES_EBADRESP, cares_parse_mx_reply(data.data(), data.size(), &mx)); + EXPECT_EQ(nullptr, mx); + pkt.questions_.clear(); + pkt.add_question(new DNSQuestion("example.com", T_MX)); + + // Wrong sort of answer. + pkt.answers_.clear(); + pkt.add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")); + data = pkt.data(); + EXPECT_EQ(ARES_ENODATA, cares_parse_mx_reply(data.data(), data.size(), &mx)); + EXPECT_EQ(nullptr, mx); + pkt.answers_.clear(); + pkt.add_answer(new DNSMxRR("example.com", 100, 100, "mx1.example.com")); + + // No answer. + pkt.answers_.clear(); + data = pkt.data(); + EXPECT_EQ(ARES_ENODATA, cares_parse_mx_reply(data.data(), data.size(), &mx)); + EXPECT_EQ(nullptr, mx); + pkt.add_answer(new DNSMxRR("example.com", 100, 100, "mx1.example.com")); + + // Truncated packets. + data = pkt.data(); + for (size_t len = 1; len < data.size(); len++) { + int rc = cares_parse_mx_reply(data.data(), len, &mx); + EXPECT_EQ(nullptr, mx); + EXPECT_TRUE(rc == ARES_EBADRESP || rc == ARES_EBADNAME); + } +} + TEST_F(LibraryTest, ParseMxReplyAllocFail) { DNSPacket pkt; pkt.set_qid(0x1234).set_response().set_aa() diff --git a/test/ares-test-parse-naptr.cc b/test/ares-test-parse-naptr.cc index aa1a2a5029..fd772ae698 100644 --- a/test/ares-test-parse-naptr.cc +++ b/test/ares-test-parse-naptr.cc @@ -40,6 +40,41 @@ TEST_F(LibraryTest, ParseNaptrReplyOK) { ares_free_data(naptr); } +TEST_F(LibraryTest, ParseCNaptrReplyOK) { + DNSPacket pkt; + pkt.set_qid(0x1234).set_response().set_aa() + .add_question(new DNSQuestion("example.com", T_NAPTR)) + .add_answer(new DNSNaptrRR("example.com", 100, + 10, 20, "SP", "service", "regexp", "replace")) + .add_answer(new DNSNaptrRR("example.com", 0x0010, + 11, 21, "SP", "service2", "regexp2", "replace2")); + std::vector data = pkt.data(); + + struct cares_naptr_reply* naptr = nullptr; + EXPECT_EQ(ARES_SUCCESS, cares_parse_naptr_reply(data.data(), data.size(), &naptr)); + ASSERT_NE(nullptr, naptr); + EXPECT_EQ("SP", std::string((char*)cares_naptr_reply_get_flags(naptr))); + EXPECT_EQ("service", std::string((char*)cares_naptr_reply_get_service(naptr))); + EXPECT_EQ("regexp", std::string((char*)cares_naptr_reply_get_regexp(naptr))); + EXPECT_EQ("replace", std::string((char*)cares_naptr_reply_get_replacement(naptr))); + EXPECT_EQ(10, cares_naptr_reply_get_order(naptr)); + EXPECT_EQ(20, cares_naptr_reply_get_preference(naptr)); + EXPECT_EQ(100, cares_naptr_reply_get_ttl(naptr)); + + struct cares_naptr_reply* naptr2 = cares_naptr_reply_get_next(naptr); + ASSERT_NE(nullptr, naptr2); + EXPECT_EQ("SP", std::string((char*)cares_naptr_reply_get_flags(naptr2))); + EXPECT_EQ("service2", std::string((char*)cares_naptr_reply_get_service(naptr2))); + EXPECT_EQ("regexp2", std::string((char*)cares_naptr_reply_get_regexp(naptr2))); + EXPECT_EQ("replace2", std::string((char*)cares_naptr_reply_get_replacement(naptr2))); + EXPECT_EQ(11, cares_naptr_reply_get_order(naptr2)); + EXPECT_EQ(21, cares_naptr_reply_get_preference(naptr2)); + EXPECT_EQ(nullptr, cares_naptr_reply_get_next(naptr2)); + EXPECT_EQ(16, cares_naptr_reply_get_ttl(naptr2)); + + ares_free_data(naptr); +} + TEST_F(LibraryTest, ParseNaptrReplyErrors) { DNSPacket pkt; pkt.set_qid(0x1234).set_response().set_aa() @@ -76,7 +111,7 @@ TEST_F(LibraryTest, ParseNaptrReplyErrors) { pkt.answers_.clear(); pkt.add_answer(new DNSMxRR("example.com", 100, 100, "mx1.example.com")); data = pkt.data(); - EXPECT_EQ(ARES_SUCCESS, ares_parse_naptr_reply(data.data(), data.size(), &naptr)); + EXPECT_EQ(ARES_ENODATA, ares_parse_naptr_reply(data.data(), data.size(), &naptr)); EXPECT_EQ(nullptr, naptr); pkt.answers_.clear(); pkt.add_answer(new DNSNaptrRR("example.com", 100, @@ -97,6 +132,63 @@ TEST_F(LibraryTest, ParseNaptrReplyErrors) { } } +TEST_F(LibraryTest, ParseCNaptrReplyErrors) { + DNSPacket pkt; + pkt.set_qid(0x1234).set_response().set_aa() + .add_question(new DNSQuestion("example.com", T_NAPTR)) + .add_answer(new DNSNaptrRR("example.com", 100, + 10, 20, "SP", "service", "regexp", "replace")); + std::vector data; + struct cares_naptr_reply* naptr = nullptr; + + // No question. + pkt.questions_.clear(); + data = pkt.data(); + EXPECT_EQ(ARES_EBADRESP, cares_parse_naptr_reply(data.data(), data.size(), &naptr)); + pkt.add_question(new DNSQuestion("example.com", T_NAPTR)); + +#ifdef DISABLED + // Question != answer + pkt.questions_.clear(); + pkt.add_question(new DNSQuestion("Axample.com", T_NAPTR)); + data = pkt.data(); + EXPECT_EQ(ARES_ENODATA, cares_parse_naptr_reply(data.data(), data.size(), &naptr)); + pkt.questions_.clear(); + pkt.add_question(new DNSQuestion("example.com", T_NAPTR)); +#endif + + // Two questions + pkt.add_question(new DNSQuestion("example.com", T_NAPTR)); + data = pkt.data(); + EXPECT_EQ(ARES_EBADRESP, cares_parse_naptr_reply(data.data(), data.size(), &naptr)); + pkt.questions_.clear(); + pkt.add_question(new DNSQuestion("example.com", T_NAPTR)); + + // Wrong sort of answer. + pkt.answers_.clear(); + pkt.add_answer(new DNSMxRR("example.com", 100, 100, "mx1.example.com")); + data = pkt.data(); + EXPECT_EQ(ARES_ENODATA, cares_parse_naptr_reply(data.data(), data.size(), &naptr)); + EXPECT_EQ(nullptr, naptr); + pkt.answers_.clear(); + pkt.add_answer(new DNSNaptrRR("example.com", 100, + 10, 20, "SP", "service", "regexp", "replace")); + + // No answer. + pkt.answers_.clear(); + data = pkt.data(); + EXPECT_EQ(ARES_ENODATA, cares_parse_naptr_reply(data.data(), data.size(), &naptr)); + pkt.add_answer(new DNSNaptrRR("example.com", 100, + 10, 20, "SP", "service", "regexp", "replace")); + + // Truncated packets. + data = pkt.data(); + for (size_t len = 1; len < data.size(); len++) { + int rc = cares_parse_naptr_reply(data.data(), len, &naptr); + EXPECT_TRUE(rc == ARES_EBADRESP || rc == ARES_EBADNAME); + } +} + TEST_F(LibraryTest, ParseNaptrReplyTooShort) { std::vector data = { 0x12, 0x34, // qid @@ -126,6 +218,35 @@ TEST_F(LibraryTest, ParseNaptrReplyTooShort) { EXPECT_EQ(ARES_EBADRESP, ares_parse_naptr_reply(data.data(), data.size(), &naptr)); } +TEST_F(LibraryTest, ParseCNaptrReplyTooShort) { + std::vector data = { + 0x12, 0x34, // qid + 0x84, // response + query + AA + not-TC + not-RD + 0x00, // not-RA + not-Z + not-AD + not-CD + rc=NoError + 0x00, 0x01, // num questions + 0x00, 0x01, // num answer RRs + 0x00, 0x00, // num authority RRs + 0x00, 0x00, // num additional RRs + // Question + 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', + 0x03, 'c', 'o', 'm', + 0x00, + 0x00, 0x23, // type NAPTR + 0x00, 0x01, // class IN + // Answer 1 + 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', + 0x03, 'c', 'o', 'm', + 0x00, + 0x00, 0x23, // RR type + 0x00, 0x01, // class IN + 0x01, 0x02, 0x03, 0x04, // TTL + 0x00, 0x01, // rdata length + 0x00, // Too short: expect 2 x int16 and 3 x name (min 1 byte each) + }; + struct cares_naptr_reply* naptr = nullptr; + EXPECT_EQ(ARES_EBADRESP, cares_parse_naptr_reply(data.data(), data.size(), &naptr)); +} + TEST_F(LibraryTest, ParseNaptrReplyAllocFail) { DNSPacket pkt; pkt.set_qid(0x1234).set_response().set_aa() @@ -144,5 +265,23 @@ TEST_F(LibraryTest, ParseNaptrReplyAllocFail) { } } +TEST_F(LibraryTest, ParseCNaptrReplyAllocFail) { + DNSPacket pkt; + pkt.set_qid(0x1234).set_response().set_aa() + .add_question(new DNSQuestion("example.com", T_NAPTR)) + .add_answer(new DNSNaptrRR("example.com", 100, + 10, 20, "SP", "service", "regexp", "replace")) + .add_answer(new DNSNaptrRR("example.com", 0x0010, + 11, 21, "SP", "service2", "regexp2", "replace2")); + std::vector data = pkt.data(); + struct cares_naptr_reply* naptr = nullptr; + + for (int ii = 1; ii <= 13; ii++) { + ClearFails(); + SetAllocFail(ii); + EXPECT_EQ(ARES_ENOMEM, cares_parse_naptr_reply(data.data(), data.size(), &naptr)); + } +} + } // namespace test } // namespace ares diff --git a/test/ares-test-parse-ns.cc b/test/ares-test-parse-ns.cc index 316492174c..45aa9dca2d 100644 --- a/test/ares-test-parse-ns.cc +++ b/test/ares-test-parse-ns.cc @@ -23,6 +23,21 @@ TEST_F(LibraryTest, ParseNsReplyOK) { ares_free_hostent(host); } +TEST_F(LibraryTest, ParseCNsReplyOK) { + DNSPacket pkt; + pkt.set_qid(0x1234).set_response().set_aa() + .add_question(new DNSQuestion("example.com", T_NS)) + .add_answer(new DNSNsRR("example.com", 100, "ns.example.com")); + std::vector data = pkt.data(); + + cares_ns_reply* ns = nullptr; + EXPECT_EQ(ARES_SUCCESS, cares_parse_ns_reply(data.data(), data.size(), &ns)); + ASSERT_NE(nullptr, ns); + EXPECT_EQ("ns.example.com", std::string(cares_ns_reply_get_host(ns))); + EXPECT_EQ(100, cares_ns_reply_get_ttl(ns)); + ares_free_data(ns); +} + TEST_F(LibraryTest, ParseNsReplyMultiple) { DNSPacket pkt; pkt.set_qid(10501).set_response().set_rd().set_ra() @@ -46,6 +61,37 @@ TEST_F(LibraryTest, ParseNsReplyMultiple) { ares_free_hostent(host); } +TEST_F(LibraryTest, ParseCNsReplyMultiple) { + DNSPacket pkt; + pkt.set_qid(10501).set_response().set_rd().set_ra() + .add_question(new DNSQuestion("google.com", T_NS)) + .add_answer(new DNSNsRR("google.com", 59, "ns1.google.com")) + .add_answer(new DNSNsRR("google.com", 59, "ns2.google.com")) + .add_answer(new DNSNsRR("google.com", 59, "ns3.google.com")) + .add_answer(new DNSNsRR("google.com", 59, "ns4.google.com")) + .add_additional(new DNSARR("ns4.google.com", 247, {216,239,38,10})) + .add_additional(new DNSARR("ns2.google.com", 247, {216,239,34,10})) + .add_additional(new DNSARR("ns1.google.com", 247, {216,239,32,10})) + .add_additional(new DNSARR("ns3.google.com", 247, {216,239,36,10})); + std::vector data = pkt.data(); + + cares_ns_reply* ns = nullptr; + EXPECT_EQ(ARES_SUCCESS, cares_parse_ns_reply(data.data(), data.size(), &ns)); + ASSERT_NE(nullptr, ns); + EXPECT_EQ("ns1.google.com", std::string(cares_ns_reply_get_host(ns))); + EXPECT_EQ(59, cares_ns_reply_get_ttl(ns)); + ns = cares_ns_reply_get_next(ns); + EXPECT_EQ("ns2.google.com", std::string(cares_ns_reply_get_host(ns))); + EXPECT_EQ(59, cares_ns_reply_get_ttl(ns)); + ns = cares_ns_reply_get_next(ns); + EXPECT_EQ("ns3.google.com", std::string(cares_ns_reply_get_host(ns))); + EXPECT_EQ(59, cares_ns_reply_get_ttl(ns)); + ns = cares_ns_reply_get_next(ns); + EXPECT_EQ("ns4.google.com", std::string(cares_ns_reply_get_host(ns))); + EXPECT_EQ(59, cares_ns_reply_get_ttl(ns)); + ares_free_data(ns); +} + TEST_F(LibraryTest, ParseNsReplyErrors) { DNSPacket pkt; pkt.set_qid(0x1234).set_response().set_aa() @@ -98,6 +144,58 @@ TEST_F(LibraryTest, ParseNsReplyErrors) { } } +TEST_F(LibraryTest, ParseCNsReplyErrors) { + DNSPacket pkt; + pkt.set_qid(0x1234).set_response().set_aa() + .add_question(new DNSQuestion("example.com", T_NS)) + .add_answer(new DNSNsRR("example.com", 100, "ns.example.com")); + std::vector data; + cares_ns_reply* ns = nullptr; + + // No question. + pkt.questions_.clear(); + data = pkt.data(); + EXPECT_EQ(ARES_EBADRESP, cares_parse_ns_reply(data.data(), data.size(), &ns)); + pkt.add_question(new DNSQuestion("example.com", T_NS)); + +#ifdef DISABLED + // Question != answer + pkt.questions_.clear(); + pkt.add_question(new DNSQuestion("Axample.com", T_NS)); + data = pkt.data(); + EXPECT_EQ(ARES_ENODATA, cares_parse_ns_reply(data.data(), data.size(), &ns)); + pkt.questions_.clear(); + pkt.add_question(new DNSQuestion("example.com", T_NS)); +#endif + + // Two questions. + pkt.add_question(new DNSQuestion("example.com", T_NS)); + data = pkt.data(); + EXPECT_EQ(ARES_EBADRESP, cares_parse_ns_reply(data.data(), data.size(), &ns)); + pkt.questions_.clear(); + pkt.add_question(new DNSQuestion("example.com", T_NS)); + + // Wrong sort of answer. + pkt.answers_.clear(); + pkt.add_answer(new DNSMxRR("example.com", 100, 100, "mx1.example.com")); + data = pkt.data(); + EXPECT_EQ(ARES_ENODATA, cares_parse_ns_reply(data.data(), data.size(), &ns)); + pkt.answers_.clear(); + pkt.add_answer(new DNSNsRR("example.com", 100, "ns.example.com")); + + // No answer. + pkt.answers_.clear(); + data = pkt.data(); + EXPECT_EQ(ARES_ENODATA, cares_parse_ns_reply(data.data(), data.size(), &ns)); + pkt.add_answer(new DNSNsRR("example.com", 100, "ns.example.com")); + + // Truncated packets. + data = pkt.data(); + for (size_t len = 1; len < data.size(); len++) { + EXPECT_EQ(ARES_EBADRESP, cares_parse_ns_reply(data.data(), len, &ns)); + } +} + TEST_F(LibraryTest, ParseNsReplyAllocFail) { DNSPacket pkt; pkt.set_qid(0x1234).set_response().set_aa() @@ -114,6 +212,21 @@ TEST_F(LibraryTest, ParseNsReplyAllocFail) { } } +TEST_F(LibraryTest, ParseCNsReplyAllocFail) { + DNSPacket pkt; + pkt.set_qid(0x1234).set_response().set_aa() + .add_question(new DNSQuestion("example.com", T_NS)) + .add_answer(new DNSCnameRR("example.com", 300, "c.example.com")) + .add_answer(new DNSNsRR("c.example.com", 100, "ns.example.com")); + std::vector data = pkt.data(); + cares_ns_reply* ns = nullptr; + + for (int ii = 1; ii <= 5; ii++) { + ClearFails(); + SetAllocFail(ii); + EXPECT_EQ(ARES_ENOMEM, cares_parse_ns_reply(data.data(), data.size(), &ns)) << ii; + } +} } // namespace test } // namespace ares diff --git a/test/ares-test-parse-ptr.cc b/test/ares-test-parse-ptr.cc index 6fdaf3ea5d..fa1b24f4fc 100644 --- a/test/ares-test-parse-ptr.cc +++ b/test/ares-test-parse-ptr.cc @@ -25,6 +25,22 @@ TEST_F(LibraryTest, ParsePtrReplyOK) { ares_free_hostent(host); } +TEST_F(LibraryTest, ParseCPtrReplyOK) { + DNSPacket pkt; + pkt.set_qid(0x1234).set_response().set_aa() + .add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR)) + .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other.com")); + std::vector data = pkt.data(); + + struct cares_ptr_reply *ptr = nullptr; + EXPECT_EQ(ARES_SUCCESS, cares_parse_ptr_reply(data.data(), data.size(), &ptr)); + ASSERT_NE(nullptr, ptr); + + EXPECT_EQ("other.com", std::string(cares_ptr_reply_get_host(ptr))); + EXPECT_EQ(100, cares_ptr_reply_get_ttl(ptr)); + ares_free_data(ptr); +} + TEST_F(LibraryTest, ParsePtrReplyCname) { byte addrv4[4] = {0x10, 0x20, 0x30, 0x40}; DNSPacket pkt; @@ -44,6 +60,23 @@ TEST_F(LibraryTest, ParsePtrReplyCname) { ares_free_hostent(host); } +TEST_F(LibraryTest, ParseCPtrReplyCname) { + DNSPacket pkt; + pkt.set_qid(0x1234).set_response().set_aa() + .add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR)) + .add_answer(new DNSCnameRR("64.48.32.16.in-addr.arpa", 50, "64.48.32.8.in-addr.arpa")) + .add_answer(new DNSPtrRR("64.48.32.8.in-addr.arpa", 100, "other.com")); + std::vector data = pkt.data(); + + struct cares_ptr_reply *ptr = nullptr; + EXPECT_EQ(ARES_SUCCESS, cares_parse_ptr_reply(data.data(), data.size(), &ptr)); + ASSERT_NE(nullptr, ptr); + + EXPECT_EQ("other.com", std::string(cares_ptr_reply_get_host(ptr))); + EXPECT_EQ(100, cares_ptr_reply_get_ttl(ptr)); + ares_free_data(ptr); +} + struct DNSMalformedCnameRR : public DNSCnameRR { DNSMalformedCnameRR(const std::string& name, int ttl, const std::string& other) @@ -74,6 +107,19 @@ TEST_F(LibraryTest, ParsePtrReplyMalformedCname) { ASSERT_EQ(nullptr, host); } +TEST_F(LibraryTest, ParseCPtrReplyMalformedCname) { + DNSPacket pkt; + pkt.set_qid(0x1234).set_response().set_aa() + .add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR)) + .add_answer(new DNSMalformedCnameRR("64.48.32.16.in-addr.arpa", 50, "64.48.32.8.in-addr.arpa")) + .add_answer(new DNSPtrRR("64.48.32.8.in-addr.arpa", 100, "other.com")); + std::vector data = pkt.data(); + + struct cares_ptr_reply *ptr = nullptr; + EXPECT_EQ(ARES_EBADRESP, cares_parse_ptr_reply(data.data(), data.size(), &ptr)); + ASSERT_EQ(nullptr, ptr); +} + TEST_F(LibraryTest, ParseManyPtrReply) { byte addrv4[4] = {0x10, 0x20, 0x30, 0x40}; DNSPacket pkt; @@ -98,6 +144,28 @@ TEST_F(LibraryTest, ParseManyPtrReply) { ares_free_hostent(host); } +TEST_F(LibraryTest, ParseManyCPtrReply) { + DNSPacket pkt; + pkt.set_qid(0x1234).set_response().set_aa() + .add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR)) + .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "main.com")) + .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other1.com")) + .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other2.com")) + .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other3.com")) + .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other4.com")) + .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other5.com")) + .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other6.com")) + .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other7.com")) + .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other8.com")) + .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other9.com")); + std::vector data = pkt.data(); + + struct cares_ptr_reply *ptr = nullptr; + EXPECT_EQ(ARES_SUCCESS, cares_parse_ptr_reply(data.data(), data.size(), &ptr)); + ASSERT_NE(nullptr, ptr); + ares_free_data(ptr); +} + TEST_F(LibraryTest, ParsePtrReplyAdditional) { byte addrv4[4] = {0x10, 0x20, 0x30, 0x40}; DNSPacket pkt; @@ -122,6 +190,27 @@ TEST_F(LibraryTest, ParsePtrReplyAdditional) { ares_free_hostent(host); } +TEST_F(LibraryTest, ParseCPtrReplyAdditional) { + DNSPacket pkt; + pkt.set_qid(0x1234).set_response().set_aa() + .add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR)) + .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 55, "other.com")) + .add_auth(new DNSNsRR("16.in-addr.arpa", 234, "ns1.other.com")) + .add_auth(new DNSNsRR("16.in-addr.arpa", 234, "bb.ns2.other.com")) + .add_auth(new DNSNsRR("16.in-addr.arpa", 234, "ns3.other.com")) + .add_additional(new DNSARR("ns1.other.com", 229, {10,20,30,41})) + .add_additional(new DNSARR("bb.ns2.other.com", 229, {10,20,30,42})) + .add_additional(new DNSARR("ns3.other.com", 229, {10,20,30,43})); + std::vector data = pkt.data(); + + struct cares_ptr_reply *ptr = nullptr; + EXPECT_EQ(ARES_SUCCESS, cares_parse_ptr_reply(data.data(), data.size(), &ptr)); + ASSERT_NE(nullptr, ptr); + EXPECT_EQ("other.com", std::string(cares_ptr_reply_get_host(ptr))); + EXPECT_EQ(55, cares_ptr_reply_get_ttl(ptr)); + ares_free_data(ptr); +} + TEST_F(LibraryTest, ParsePtrReplyErrors) { byte addrv4[4] = {0x10, 0x20, 0x30, 0x40}; DNSPacket pkt; @@ -193,6 +282,69 @@ TEST_F(LibraryTest, ParsePtrReplyErrors) { } } +TEST_F(LibraryTest, ParseCPtrReplyErrors) { + DNSPacket pkt; + pkt.set_qid(0x1234).set_response().set_aa() + .add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR)) + .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other.com")); + std::vector data; + struct cares_ptr_reply *ptr = nullptr; + + // No question. + pkt.questions_.clear(); + data = pkt.data(); + EXPECT_EQ(ARES_EBADRESP, cares_parse_ptr_reply(data.data(), data.size(), &ptr)); + pkt.add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR)); + + // Question != answer + pkt.questions_.clear(); + pkt.add_question(new DNSQuestion("99.48.32.16.in-addr.arpa", T_PTR)); + data = pkt.data(); + EXPECT_EQ(ARES_ENODATA, cares_parse_ptr_reply(data.data(), data.size(), &ptr)); + EXPECT_EQ(nullptr, ptr); + pkt.questions_.clear(); + pkt.add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR)); + + // Two questions. + pkt.add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR)); + data = pkt.data(); + EXPECT_EQ(ARES_EBADRESP, cares_parse_ptr_reply(data.data(), data.size(), &ptr)); + EXPECT_EQ(nullptr, ptr); + pkt.questions_.clear(); + pkt.add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR)); + + // Wrong sort of answer. + pkt.answers_.clear(); + pkt.add_answer(new DNSMxRR("example.com", 100, 100, "mx1.example.com")); + data = pkt.data(); + EXPECT_EQ(ARES_ENODATA, cares_parse_ptr_reply(data.data(), data.size(), &ptr)); + EXPECT_EQ(nullptr, ptr); + pkt.answers_.clear(); + pkt.add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other.com")); + + // No answer. + pkt.answers_.clear(); + data = pkt.data(); + EXPECT_EQ(ARES_ENODATA, cares_parse_ptr_reply(data.data(), data.size(), &ptr)); + EXPECT_EQ(nullptr, ptr); + pkt.add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other.com")); + + // Truncated packets. + data = pkt.data(); + for (size_t len = 1; len < data.size(); len++) { + EXPECT_EQ(ARES_EBADRESP, cares_parse_ptr_reply(data.data(), len, &ptr)); + EXPECT_EQ(nullptr, ptr); + } + + // Truncated packets with CNAME. + pkt.add_answer(new DNSCnameRR("64.48.32.16.in-addr.arpa", 50, "64.48.32.8.in-addr.arpa")); + data = pkt.data(); + for (size_t len = 1; len < data.size(); len++) { + EXPECT_EQ(ARES_EBADRESP, cares_parse_ptr_reply(data.data(), len, &ptr)); + EXPECT_EQ(nullptr, ptr); + } +} + TEST_F(LibraryTest, ParsePtrReplyAllocFailSome) { byte addrv4[4] = {0x10, 0x20, 0x30, 0x40}; DNSPacket pkt; @@ -213,6 +365,24 @@ TEST_F(LibraryTest, ParsePtrReplyAllocFailSome) { } } +TEST_F(LibraryTest, ParseCPtrReplyAllocFailSome) { + DNSPacket pkt; + pkt.set_qid(0x1234).set_response().set_aa() + .add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR)) + .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "main.com")) + .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other1.com")) + .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other2.com")) + .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other3.com")); + std::vector data = pkt.data(); + struct cares_ptr_reply *ptr = nullptr; + + for (int ii = 1; ii <= 13; ii++) { + ClearFails(); + SetAllocFail(ii); + EXPECT_EQ(ARES_ENOMEM, cares_parse_ptr_reply(data.data(), data.size(), &ptr)) << ii; + } +} + TEST_F(LibraryTest, ParsePtrReplyAllocFailMany) { byte addrv4[4] = {0x10, 0x20, 0x30, 0x40}; DNSPacket pkt; @@ -244,6 +414,35 @@ TEST_F(LibraryTest, ParsePtrReplyAllocFailMany) { } } +TEST_F(LibraryTest, ParseCPtrReplyAllocFailMany) { + DNSPacket pkt; + pkt.set_qid(0x1234).set_response().set_aa() + .add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR)) + .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "main.com")) + .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other1.com")) + .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other2.com")) + .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other3.com")) + .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other4.com")) + .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other5.com")) + .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other6.com")) + .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other7.com")) + .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other8.com")) + .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other9.com")); + std::vector data = pkt.data(); + struct cares_ptr_reply *ptr = nullptr; + + for (int ii = 1; ii <= 63; ii++) { + ClearFails(); + SetAllocFail(ii); + int rc = cares_parse_ptr_reply(data.data(), data.size(), &ptr); + if (rc != ARES_ENOMEM) { + EXPECT_EQ(ARES_SUCCESS, rc); + ares_free_data(ptr); + ptr = nullptr; + } + } +} + } // namespace test } // namespace ares diff --git a/test/ares-test-parse-soa-any.cc b/test/ares-test-parse-soa-any.cc index 700073c5c8..a47caf9151 100644 --- a/test/ares-test-parse-soa-any.cc +++ b/test/ares-test-parse-soa-any.cc @@ -32,6 +32,32 @@ TEST_F(LibraryTest, ParseSoaAnyReplyOK) { ares_free_data(soa); } +TEST_F(LibraryTest, ParseCSoaAnyReplyOK) { + DNSPacket pkt; + pkt.set_qid(0x1234).set_response().set_aa() + .add_question(new DNSQuestion("example.com", T_ANY))\ + .add_answer(new DNSARR("example.com", 0x01020304, {2,3,4,5})) + .add_answer(new DNSMxRR("example.com", 100, 100, "mx1.example.com")) + .add_answer(new DNSMxRR("example.com", 100, 200, "mx2.example.com")) + .add_answer(new DNSSoaRR("example.com", 100, + "soa1.example.com", "fred.example.com", + 1, 2, 3, 4, 5)); + std::vector data = pkt.data(); + + struct cares_soa_reply* soa = nullptr; + EXPECT_EQ(ARES_SUCCESS, cares_parse_soa_reply(data.data(), data.size(), &soa)); + ASSERT_NE(nullptr, soa); + EXPECT_EQ("soa1.example.com", std::string(cares_soa_reply_get_nsname(soa))); + EXPECT_EQ("fred.example.com", std::string(cares_soa_reply_get_hostmaster(soa))); + EXPECT_EQ(1, cares_soa_reply_get_serial(soa)); + EXPECT_EQ(2, cares_soa_reply_get_refresh(soa)); + EXPECT_EQ(3, cares_soa_reply_get_retry(soa)); + EXPECT_EQ(4, cares_soa_reply_get_expire(soa)); + EXPECT_EQ(5, cares_soa_reply_get_minttl(soa)); + EXPECT_EQ(100, cares_soa_reply_get_ttl(soa)); + ares_free_data(soa); +} + TEST_F(LibraryTest, ParseSoaAnyReplyErrors) { DNSPacket pkt; pkt.set_qid(0x1234).set_response().set_aa() @@ -90,6 +116,64 @@ TEST_F(LibraryTest, ParseSoaAnyReplyErrors) { } } +TEST_F(LibraryTest, ParseCSoaAnyReplyErrors) { + DNSPacket pkt; + pkt.set_qid(0x1234).set_response().set_aa() + .add_question(new DNSQuestion("example.com", T_ANY)) + .add_answer(new DNSSoaRR("example.com", 100, + "soa1.example.com", "fred.example.com", + 1, 2, 3, 4, 5)); + std::vector data; + struct cares_soa_reply* soa = nullptr; + + // No question. + pkt.questions_.clear(); + data = pkt.data(); + EXPECT_EQ(ARES_EBADRESP, cares_parse_soa_reply(data.data(), data.size(), &soa)); + pkt.add_question(new DNSQuestion("example.com", T_ANY)); + +#ifdef DISABLED + // Question != answer + pkt.questions_.clear(); + pkt.add_question(new DNSQuestion("Axample.com", T_ANY)); + data = pkt.data(); + EXPECT_EQ(ARES_EBADRESP, cares_parse_soa_reply(data.data(), data.size(), &soa)); + pkt.questions_.clear(); + pkt.add_question(new DNSQuestion("example.com", T_ANY)); +#endif + + // Two questions + pkt.add_question(new DNSQuestion("example.com", T_ANY)); + data = pkt.data(); + EXPECT_EQ(ARES_EBADRESP, cares_parse_soa_reply(data.data(), data.size(), &soa)); + pkt.questions_.clear(); + pkt.add_question(new DNSQuestion("example.com", T_ANY)); + + // Wrong sort of answer. + pkt.answers_.clear(); + pkt.add_answer(new DNSMxRR("example.com", 100, 100, "mx1.example.com")); + data = pkt.data(); + EXPECT_EQ(ARES_EBADRESP, cares_parse_soa_reply(data.data(), data.size(), &soa)); + pkt.answers_.clear(); + pkt.add_answer(new DNSSoaRR("example.com", 100, + "soa1.example.com", "fred.example.com", + 1, 2, 3, 4, 5)); + + // No answer. + pkt.answers_.clear(); + data = pkt.data(); + EXPECT_EQ(ARES_EBADRESP, cares_parse_soa_reply(data.data(), data.size(), &soa)); + pkt.add_answer(new DNSSoaRR("example.com", 100, + "soa1.example.com", "fred.example.com", + 1, 2, 3, 4, 5)); + + // Truncated packets. + data = pkt.data(); + for (size_t len = 1; len < data.size(); len++) { + EXPECT_EQ(ARES_EBADRESP, cares_parse_soa_reply(data.data(), len, &soa)); + } +} + TEST_F(LibraryTest, ParseSoaAnyReplyAllocFail) { DNSPacket pkt; pkt.set_qid(0x1234).set_response().set_aa() @@ -107,5 +191,22 @@ TEST_F(LibraryTest, ParseSoaAnyReplyAllocFail) { } } +TEST_F(LibraryTest, ParseCSoaAnyReplyAllocFail) { + DNSPacket pkt; + pkt.set_qid(0x1234).set_response().set_aa() + .add_question(new DNSQuestion("example.com", T_ANY)) + .add_answer(new DNSSoaRR("example.com", 100, + "soa1.example.com", "fred.example.com", + 1, 2, 3, 4, 5)); + std::vector data = pkt.data(); + struct cares_soa_reply* soa = nullptr; + + for (int ii = 1; ii <= 5; ii++) { + ClearFails(); + SetAllocFail(ii); + EXPECT_EQ(ARES_ENOMEM, cares_parse_soa_reply(data.data(), data.size(), &soa)) << ii; + } +} + } // namespace test } // namespace ares diff --git a/test/ares-test-parse-soa.cc b/test/ares-test-parse-soa.cc index 22a78e5f46..b6f2184343 100644 --- a/test/ares-test-parse-soa.cc +++ b/test/ares-test-parse-soa.cc @@ -29,6 +29,29 @@ TEST_F(LibraryTest, ParseSoaReplyOK) { ares_free_data(soa); } +TEST_F(LibraryTest, ParseCSoaReplyOK) { + DNSPacket pkt; + pkt.set_qid(0x1234).set_response().set_aa() + .add_question(new DNSQuestion("example.com", T_SOA)) + .add_answer(new DNSSoaRR("example.com", 100, + "soa1.example.com", "fred.example.com", + 1, 2, 3, 4, 5)); + std::vector data = pkt.data(); + + struct cares_soa_reply* soa = nullptr; + EXPECT_EQ(ARES_SUCCESS, cares_parse_soa_reply(data.data(), data.size(), &soa)); + ASSERT_NE(nullptr, soa); + EXPECT_EQ("soa1.example.com", std::string(cares_soa_reply_get_nsname(soa))); + EXPECT_EQ("fred.example.com", std::string(cares_soa_reply_get_hostmaster(soa))); + EXPECT_EQ(1, cares_soa_reply_get_serial(soa)); + EXPECT_EQ(2, cares_soa_reply_get_refresh(soa)); + EXPECT_EQ(3, cares_soa_reply_get_retry(soa)); + EXPECT_EQ(4, cares_soa_reply_get_expire(soa)); + EXPECT_EQ(5, cares_soa_reply_get_minttl(soa)); + EXPECT_EQ(100, cares_soa_reply_get_ttl(soa)); + ares_free_data(soa); +} + TEST_F(LibraryTest, ParseSoaReplyErrors) { DNSPacket pkt; pkt.set_qid(0x1234).set_response().set_aa() @@ -87,6 +110,64 @@ TEST_F(LibraryTest, ParseSoaReplyErrors) { } } +TEST_F(LibraryTest, ParseCSoaReplyErrors) { + DNSPacket pkt; + pkt.set_qid(0x1234).set_response().set_aa() + .add_question(new DNSQuestion("example.com", T_SOA)) + .add_answer(new DNSSoaRR("example.com", 100, + "soa1.example.com", "fred.example.com", + 1, 2, 3, 4, 5)); + std::vector data; + struct cares_soa_reply* soa = nullptr; + + // No question. + pkt.questions_.clear(); + data = pkt.data(); + EXPECT_EQ(ARES_EBADRESP, cares_parse_soa_reply(data.data(), data.size(), &soa)); + pkt.add_question(new DNSQuestion("example.com", T_SOA)); + +#ifdef DISABLED + // Question != answer + pkt.questions_.clear(); + pkt.add_question(new DNSQuestion("Axample.com", T_SOA)); + data = pkt.data(); + EXPECT_EQ(ARES_EBADRESP, cares_parse_soa_reply(data.data(), data.size(), &soa)); + pkt.questions_.clear(); + pkt.add_question(new DNSQuestion("example.com", T_SOA)); +#endif + + // Two questions + pkt.add_question(new DNSQuestion("example.com", T_SOA)); + data = pkt.data(); + EXPECT_EQ(ARES_EBADRESP, cares_parse_soa_reply(data.data(), data.size(), &soa)); + pkt.questions_.clear(); + pkt.add_question(new DNSQuestion("example.com", T_SOA)); + + // Wrong sort of answer. + pkt.answers_.clear(); + pkt.add_answer(new DNSMxRR("example.com", 100, 100, "mx1.example.com")); + data = pkt.data(); + EXPECT_EQ(ARES_EBADRESP, cares_parse_soa_reply(data.data(), data.size(), &soa)); + pkt.answers_.clear(); + pkt.add_answer(new DNSSoaRR("example.com", 100, + "soa1.example.com", "fred.example.com", + 1, 2, 3, 4, 5)); + + // No answer. + pkt.answers_.clear(); + data = pkt.data(); + EXPECT_EQ(ARES_EBADRESP, cares_parse_soa_reply(data.data(), data.size(), &soa)); + pkt.add_answer(new DNSSoaRR("example.com", 100, + "soa1.example.com", "fred.example.com", + 1, 2, 3, 4, 5)); + + // Truncated packets. + data = pkt.data(); + for (size_t len = 1; len < data.size(); len++) { + EXPECT_EQ(ARES_EBADRESP, cares_parse_soa_reply(data.data(), len, &soa)); + } +} + TEST_F(LibraryTest, ParseSoaReplyAllocFail) { DNSPacket pkt; pkt.set_qid(0x1234).set_response().set_aa() @@ -104,5 +185,22 @@ TEST_F(LibraryTest, ParseSoaReplyAllocFail) { } } +TEST_F(LibraryTest, ParseCSoaReplyAllocFail) { + DNSPacket pkt; + pkt.set_qid(0x1234).set_response().set_aa() + .add_question(new DNSQuestion("example.com", T_SOA)) + .add_answer(new DNSSoaRR("example.com", 100, + "soa1.example.com", "fred.example.com", + 1, 2, 3, 4, 5)); + std::vector data = pkt.data(); + struct cares_soa_reply* soa = nullptr; + + for (int ii = 1; ii <= 5; ii++) { + ClearFails(); + SetAllocFail(ii); + EXPECT_EQ(ARES_ENOMEM, cares_parse_soa_reply(data.data(), data.size(), &soa)) << ii; + } +} + } // namespace test } // namespace ares diff --git a/test/ares-test-parse-srv.cc b/test/ares-test-parse-srv.cc index fb26e26447..4673c67151 100644 --- a/test/ares-test-parse-srv.cc +++ b/test/ares-test-parse-srv.cc @@ -462,7 +462,7 @@ TEST_F(LibraryTest, ParseSrvReplyErrors) { pkt.answers_.clear(); pkt.add_answer(new DNSMxRR("example.com", 100, 100, "mx1.example.com")); data = pkt.data(); - EXPECT_EQ(ARES_SUCCESS, ares_parse_srv_reply(data.data(), data.size(), &srv)); + EXPECT_EQ(ARES_ENODATA, ares_parse_srv_reply(data.data(), data.size(), &srv)); EXPECT_EQ(nullptr, srv); pkt.answers_.clear(); pkt.add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")); @@ -514,7 +514,7 @@ TEST_F(LibraryTest, ParseCSrvReplyErrors) { pkt.answers_.clear(); pkt.add_answer(new DNSMxRR("example.com", 100, 100, "mx1.example.com")); data = pkt.data(); - EXPECT_EQ(ARES_SUCCESS, cares_parse_srv_reply(data.data(), data.size(), &srv)); + EXPECT_EQ(ARES_ENODATA, cares_parse_srv_reply(data.data(), data.size(), &srv)); EXPECT_EQ(nullptr, srv); pkt.answers_.clear(); pkt.add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")); diff --git a/test/ares-test-parse-txt.cc b/test/ares-test-parse-txt.cc index b33fb2de0c..158dfe12e1 100644 --- a/test/ares-test-parse-txt.cc +++ b/test/ares-test-parse-txt.cc @@ -72,6 +72,43 @@ TEST_F(LibraryTest, ParseTxtExtReplyOK) { ares_free_data(txt); } +TEST_F(LibraryTest, ParseCTxtReplyOK) { + DNSPacket pkt; + std::string expected1 = "txt1.example.com"; + 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_answer(new DNSTxtRR("example.com", 100, {expected1})) + .add_answer(new DNSTxtRR("example.com", 100, {expected2a, expected2b})); + std::vector data = pkt.data(); + + struct cares_txt_reply* txt = nullptr; + EXPECT_EQ(ARES_SUCCESS, cares_parse_txt_reply(data.data(), data.size(), &txt)); + ASSERT_NE(nullptr, txt); + EXPECT_EQ(std::vector(expected1.data(), expected1.data() + expected1.size()), + std::vector(cares_txt_reply_get_txt(txt), + cares_txt_reply_get_txt(txt) + cares_txt_reply_get_length(txt))); + EXPECT_EQ(100, cares_txt_reply_get_ttl(txt)); + + struct cares_txt_reply* txt2 = cares_txt_reply_get_next(txt); + ASSERT_NE(nullptr, txt2); + EXPECT_EQ(std::vector(expected2a.data(), expected2a.data() + expected2a.size()), + std::vector(cares_txt_reply_get_txt(txt2), + cares_txt_reply_get_txt(txt2) + cares_txt_reply_get_length(txt2))); + EXPECT_EQ(100, cares_txt_reply_get_ttl(txt2)); + + struct cares_txt_reply* txt3 = cares_txt_reply_get_next(txt2); + ASSERT_NE(nullptr, txt3); + EXPECT_EQ(std::vector(expected2b.data(), expected2b.data() + expected2b.size()), + std::vector(cares_txt_reply_get_txt(txt3), + cares_txt_reply_get_txt(txt3) + cares_txt_reply_get_length(txt3))); + EXPECT_EQ(nullptr, cares_txt_reply_get_next(txt3)); + EXPECT_EQ(100, cares_txt_reply_get_ttl(txt3)); + + ares_free_data(txt); +} + TEST_F(LibraryTest, ParseTxtMalformedReply1) { std::vector data = { 0x12, 0x34, // qid @@ -103,6 +140,37 @@ TEST_F(LibraryTest, ParseTxtMalformedReply1) { ASSERT_EQ(nullptr, txt); } +TEST_F(LibraryTest, ParseCTxtMalformedReply1) { + std::vector data = { + 0x12, 0x34, // qid + 0x84, // response + query + AA + not-TC + not-RD + 0x00, // not-RA + not-Z + not-AD + not-CD + rc=NoError + 0x00, 0x01, // num questions + 0x00, 0x01, // num answer RRs + 0x00, 0x00, // num authority RRs + 0x00, 0x00, // num additional RRs + // Question + 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', + 0x03, 'c', 'o', 'm', + 0x00, + 0x00, 0x10, // type TXT + 0x00, 0x01, // class IN + // Answer 1 + 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', + 0x03, 'c', 'o', 'm', + 0x00, + 0x00, 0x10, // RR type + 0x00, 0x01, // class IN + 0x01, 0x02, 0x03, 0x04, // TTL + 0x00, 0x03, // rdata length + 0x12, 'a', 'b', // invalid length + }; + + struct cares_txt_reply* txt = nullptr; + EXPECT_EQ(ARES_EBADRESP, cares_parse_txt_reply(data.data(), data.size(), &txt)); + ASSERT_EQ(nullptr, txt); +} + TEST_F(LibraryTest, ParseTxtMalformedReply2) { std::vector data = { 0x12, 0x34, // qid @@ -131,6 +199,34 @@ TEST_F(LibraryTest, ParseTxtMalformedReply2) { ASSERT_EQ(nullptr, txt); } +TEST_F(LibraryTest, ParseCTxtMalformedReply2) { + std::vector data = { + 0x12, 0x34, // qid + 0x84, // response + query + AA + not-TC + not-RD + 0x00, // not-RA + not-Z + not-AD + not-CD + rc=NoError + 0x00, 0x01, // num questions + 0x00, 0x01, // num answer RRs + 0x00, 0x00, // num authority RRs + 0x00, 0x00, // num additional RRs + // Question + 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', + 0x03, 'c', 'o', 'm', + 0x00, + 0x00, 0x10, // type TXT + 0x00, 0x01, // class IN + // Answer 1 + 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', + 0x03, 'c', 'o', 'm', + 0x00, + 0x00, 0x10, // RR type + // truncated + }; + + struct cares_txt_reply* txt = nullptr; + EXPECT_EQ(ARES_EBADRESP, cares_parse_txt_reply(data.data(), data.size(), &txt)); + ASSERT_EQ(nullptr, txt); +} + TEST_F(LibraryTest, ParseTxtMalformedReply3) { std::vector data = { 0x12, 0x34, // qid @@ -162,6 +258,37 @@ TEST_F(LibraryTest, ParseTxtMalformedReply3) { ASSERT_EQ(nullptr, txt); } +TEST_F(LibraryTest, ParseCTxtMalformedReply3) { + std::vector data = { + 0x12, 0x34, // qid + 0x84, // response + query + AA + not-TC + not-RD + 0x00, // not-RA + not-Z + not-AD + not-CD + rc=NoError + 0x00, 0x01, // num questions + 0x00, 0x01, // num answer RRs + 0x00, 0x00, // num authority RRs + 0x00, 0x00, // num additional RRs + // Question + 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', + 0x03, 'c', 'o', 'm', + 0x00, + 0x00, 0x10, // type TXT + 0x00, 0x01, // class IN + // Answer 1 + 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', + 0x03, 'c', 'o', 'm', + 0x00, + 0x00, 0x10, // RR type + 0x00, 0x01, // class IN + 0x01, 0x02, 0x03, 0x04, // TTL + 0x00, 0x13, // rdata length INVALID + 0x02, 'a', 'b', + }; + + struct cares_txt_reply* txt = nullptr; + EXPECT_EQ(ARES_EBADRESP, cares_parse_txt_reply(data.data(), data.size(), &txt)); + ASSERT_EQ(nullptr, txt); +} + TEST_F(LibraryTest, ParseTxtMalformedReply4) { std::vector data = { 0x12, 0x34, // qid @@ -184,6 +311,28 @@ TEST_F(LibraryTest, ParseTxtMalformedReply4) { ASSERT_EQ(nullptr, txt); } +TEST_F(LibraryTest, ParseCTxtMalformedReply4) { + std::vector data = { + 0x12, 0x34, // qid + 0x84, // response + query + AA + not-TC + not-RD + 0x00, // not-RA + not-Z + not-AD + not-CD + rc=NoError + 0x00, 0x01, // num questions + 0x00, 0x01, // num answer RRs + 0x00, 0x00, // num authority RRs + 0x00, 0x00, // num additional RRs + // Question + 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', + 0x03, 'c', 'o', 'm', + 0x00, + 0x00, 0x10, // type TXT + 0x00, // TRUNCATED + }; + + struct cares_txt_reply* txt = nullptr; + EXPECT_EQ(ARES_EBADRESP, cares_parse_txt_reply(data.data(), data.size(), &txt)); + ASSERT_EQ(nullptr, txt); +} + TEST_F(LibraryTest, ParseTxtReplyErrors) { DNSPacket pkt; std::string expected1 = "txt1.example.com"; @@ -240,6 +389,62 @@ TEST_F(LibraryTest, ParseTxtReplyErrors) { } } +TEST_F(LibraryTest, ParseCTxtReplyErrors) { + DNSPacket pkt; + std::string expected1 = "txt1.example.com"; + 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_answer(new DNSTxtRR("example.com", 100, {expected1})) + .add_answer(new DNSTxtRR("example.com", 100, {expected1})) + .add_answer(new DNSTxtRR("example.com", 100, {expected2a, expected2b})); + std::vector data = pkt.data(); + struct cares_txt_reply* txt = nullptr; + + // No question. + pkt.questions_.clear(); + data = pkt.data(); + txt = nullptr; + EXPECT_EQ(ARES_EBADRESP, cares_parse_txt_reply(data.data(), data.size(), &txt)); + EXPECT_EQ(nullptr, txt); + pkt.add_question(new DNSQuestion("example.com", T_MX)); + +#ifdef DISABLED + // Question != answer + pkt.questions_.clear(); + pkt.add_question(new DNSQuestion("Axample.com", T_TXT)); + data = pkt.data(); + EXPECT_EQ(ARES_ENODATA, cares_parse_txt_reply(data.data(), data.size(), &txt)); + pkt.questions_.clear(); + pkt.add_question(new DNSQuestion("example.com", T_TXT)); +#endif + + // Two questions. + pkt.add_question(new DNSQuestion("example.com", T_MX)); + data = pkt.data(); + txt = nullptr; + EXPECT_EQ(ARES_EBADRESP, cares_parse_txt_reply(data.data(), data.size(), &txt)); + EXPECT_EQ(nullptr, txt); + pkt.questions_.clear(); + pkt.add_question(new DNSQuestion("example.com", T_MX)); + + // No answer. + pkt.answers_.clear(); + data = pkt.data(); + txt = nullptr; + EXPECT_EQ(ARES_ENODATA, cares_parse_txt_reply(data.data(), data.size(), &txt)); + EXPECT_EQ(nullptr, txt); + pkt.add_answer(new DNSTxtRR("example.com", 100, {expected1})); + + // Truncated packets. + for (size_t len = 1; len < data.size(); len++) { + txt = nullptr; + EXPECT_NE(ARES_SUCCESS, cares_parse_txt_reply(data.data(), len, &txt)); + EXPECT_EQ(nullptr, txt); + } +} + TEST_F(LibraryTest, ParseTxtReplyAllocFail) { DNSPacket pkt; std::string expected1 = "txt1.example.com"; @@ -261,6 +466,27 @@ TEST_F(LibraryTest, ParseTxtReplyAllocFail) { } } +TEST_F(LibraryTest, ParseCTxtReplyAllocFail) { + DNSPacket pkt; + std::string expected1 = "txt1.example.com"; + 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_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})) + .add_answer(new DNSTxtRR("c.example.com", 100, {expected2a, expected2b})); + std::vector data = pkt.data(); + struct cares_txt_reply* txt = nullptr; + + for (int ii = 1; ii <= 13; ii++) { + ClearFails(); + SetAllocFail(ii); + EXPECT_EQ(ARES_ENOMEM, cares_parse_txt_reply(data.data(), data.size(), &txt)) << ii; + } +} + } // namespace test } // namespace ares From ce230f7f3fa4456d4ba7f185bf6ed9b4cbadaca4 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Wed, 10 Mar 2021 13:27:43 -0500 Subject: [PATCH 07/49] check hostent->h_addr_list[0] before free --- src/lib/ares_parse_ptr_reply.c | 3 ++- src/lib/cares_reply.c | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/ares_parse_ptr_reply.c b/src/lib/ares_parse_ptr_reply.c index e389e7e025..f84b02b514 100644 --- a/src/lib/ares_parse_ptr_reply.c +++ b/src/lib/ares_parse_ptr_reply.c @@ -120,7 +120,8 @@ int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr, } ares_free(hostent->h_name); ares_free(hostent->h_aliases); - ares_free(hostent->h_addr_list[0]); + if (hostent->h_addr_list[0]) + ares_free(hostent->h_addr_list[0]); ares_free(hostent->h_addr_list); ares_free(hostent); return status; diff --git a/src/lib/cares_reply.c b/src/lib/cares_reply.c index 374c2ff396..daaf0d7e92 100644 --- a/src/lib/cares_reply.c +++ b/src/lib/cares_reply.c @@ -15,7 +15,6 @@ #include "ares.h" #include "ares_private.h" #include "string.h" -#include cares_srv_reply* From 3d06d0604ea5a1932df833aed6db796956b1eadc Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Wed, 10 Mar 2021 14:34:32 -0500 Subject: [PATCH 08/49] fix loop off by one for freeing h_aliases --- src/lib/ares_parse_ptr_reply.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/lib/ares_parse_ptr_reply.c b/src/lib/ares_parse_ptr_reply.c index f84b02b514..a5b62b12ee 100644 --- a/src/lib/ares_parse_ptr_reply.c +++ b/src/lib/ares_parse_ptr_reply.c @@ -111,7 +111,7 @@ int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr, if (ptr_out) ares_free_data(ptr_out); - for (int j = 0; j <= i; ++j) + for (int j = 0; j < i; ++j) { if (hostent->h_aliases[j]) { @@ -134,14 +134,15 @@ int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr, if (ptr_out) ares_free_data(ptr_out); - for (int j = 0; j <= i; ++j) + for (int j = 0; j < i; ++j) { if (hostent->h_aliases[j]) ares_free(hostent->h_aliases[j]); } ares_free(hostent->h_name); ares_free(hostent->h_aliases); - ares_free(hostent->h_addr_list[0]); + if (hostent->h_addr_list[0]) + ares_free(hostent->h_addr_list[0]); ares_free(hostent->h_addr_list); ares_free(hostent); return status; From a6c585c522baf7ed23b85ceebe21b74fa57a2709 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Wed, 10 Mar 2021 22:44:41 -0500 Subject: [PATCH 09/49] modify ptr parsing to use the last hostname as h_name --- src/lib/ares_parse_caa_reply.c | 6 ++-- src/lib/ares_parse_mx_reply.c | 3 +- src/lib/ares_parse_naptr_reply.c | 14 ++++++--- src/lib/ares_parse_ns_reply.c | 8 ++--- src/lib/ares_parse_ptr_reply.c | 52 ++++++++++++++++++++----------- src/lib/ares_parse_soa_reply.c | 6 ++-- src/lib/ares_parse_srv_reply.c | 3 +- src/lib/ares_parse_txt_reply.c | 3 +- src/lib/cares_parse_caa_reply.c | 4 +-- src/lib/cares_parse_mx_reply.c | 3 +- src/lib/cares_parse_naptr_reply.c | 8 ++--- src/lib/cares_parse_ns_reply.c | 2 +- src/lib/cares_parse_ptr_reply.c | 2 +- src/lib/cares_parse_soa_reply.c | 6 ++-- src/lib/cares_parse_srv_reply.c | 3 +- src/lib/cares_parse_txt_reply.c | 2 +- 16 files changed, 76 insertions(+), 49 deletions(-) diff --git a/src/lib/ares_parse_caa_reply.c b/src/lib/ares_parse_caa_reply.c index 4a8799f824..27c178a906 100644 --- a/src/lib/ares_parse_caa_reply.c +++ b/src/lib/ares_parse_caa_reply.c @@ -66,6 +66,8 @@ ares_parse_caa_reply (const unsigned char *abuf, int alen, for(ccaa_curr = ccaa_out; ccaa_curr; ccaa_curr = cares_caa_reply_get_next(ccaa_curr)) { + const unsigned char* property; + const unsigned char* value; caa_curr = ares_malloc_data(ARES_DATATYPE_CAA_REPLY); if (!caa_curr) { @@ -84,7 +86,7 @@ ares_parse_caa_reply (const unsigned char *abuf, int alen, /* fill in the ares_caa_reply fields */ caa_curr->critical = cares_caa_reply_get_critical(ccaa_curr); - const unsigned char* property = cares_caa_reply_get_property(ccaa_curr); + property = cares_caa_reply_get_property(ccaa_curr); caa_curr->property = ares_malloc(cares_caa_reply_get_plength(ccaa_curr) + 1); if (!caa_curr->property) { @@ -97,7 +99,7 @@ ares_parse_caa_reply (const unsigned char *abuf, int alen, caa_curr->plength = cares_caa_reply_get_plength(ccaa_curr); - const unsigned char* value = cares_caa_reply_get_value(ccaa_curr); + value = cares_caa_reply_get_value(ccaa_curr); caa_curr->value = ares_malloc(cares_caa_reply_get_length(ccaa_curr) + 1); if (!caa_curr->value) { diff --git a/src/lib/ares_parse_mx_reply.c b/src/lib/ares_parse_mx_reply.c index 172f62f78e..acbbd0fcc1 100644 --- a/src/lib/ares_parse_mx_reply.c +++ b/src/lib/ares_parse_mx_reply.c @@ -43,6 +43,7 @@ ares_parse_mx_reply (const unsigned char *abuf, int alen, * create a linked list of struct ares_mx_reply to return */ int status; + char* newhost; struct ares_mx_reply *mx_head = NULL; struct ares_mx_reply *mx_curr = NULL; struct ares_mx_reply *mx_last = NULL; @@ -84,7 +85,7 @@ ares_parse_mx_reply (const unsigned char *abuf, int alen, mx_last = mx_curr; /* copy the host to newhost so we can free cmx_out */ - char *newhost = ares_strdup(cares_mx_reply_get_host(cmx_curr)); + newhost = ares_strdup(cares_mx_reply_get_host(cmx_curr)); if (!newhost) { status = ARES_ENOMEM; break; diff --git a/src/lib/ares_parse_naptr_reply.c b/src/lib/ares_parse_naptr_reply.c index fefc83107e..1ab55a7a7d 100644 --- a/src/lib/ares_parse_naptr_reply.c +++ b/src/lib/ares_parse_naptr_reply.c @@ -39,6 +39,11 @@ ares_parse_naptr_reply (const unsigned char *abuf, int alen, struct ares_naptr_reply **naptr_out) { int status; + const unsigned char* flags = NULL; + const unsigned char* service = NULL; + const unsigned char* regexp = NULL; + char* replacement = NULL; + unsigned long len; struct ares_naptr_reply *naptr_head = NULL; struct ares_naptr_reply *naptr_last = NULL; struct ares_naptr_reply *naptr_curr; @@ -81,8 +86,7 @@ ares_parse_naptr_reply (const unsigned char *abuf, int alen, naptr_curr->order = cares_naptr_reply_get_order(cnaptr_curr); naptr_curr->preference = cares_naptr_reply_get_preference(cnaptr_curr); - const unsigned char* flags = cares_naptr_reply_get_flags(cnaptr_curr); - unsigned long len; + flags = cares_naptr_reply_get_flags(cnaptr_curr); len = strlen((char *)flags); naptr_curr->flags = ares_malloc(len + 1); if (!naptr_curr->flags) @@ -94,7 +98,7 @@ ares_parse_naptr_reply (const unsigned char *abuf, int alen, /* Make sure we NULL-terminate */ naptr_curr->flags[len] = 0; - const unsigned char* service = cares_naptr_reply_get_service(cnaptr_curr); + service = cares_naptr_reply_get_service(cnaptr_curr); len = strlen((char *)service); naptr_curr->service = ares_malloc(len + 1); if (!naptr_curr->service) @@ -106,7 +110,7 @@ ares_parse_naptr_reply (const unsigned char *abuf, int alen, /* Make sure we NULL-terminate */ naptr_curr->service[len] = 0; - const unsigned char* regexp = cares_naptr_reply_get_regexp(cnaptr_curr); + regexp = cares_naptr_reply_get_regexp(cnaptr_curr); len = strlen((char *)regexp); naptr_curr->regexp = ares_malloc(len + 1); if (!naptr_curr->regexp) @@ -118,7 +122,7 @@ ares_parse_naptr_reply (const unsigned char *abuf, int alen, /* Make sure we NULL-terminate */ naptr_curr->regexp[len] = 0; - char *replacement = ares_strdup( + replacement = ares_strdup( cares_naptr_reply_get_replacement(cnaptr_curr)); if (!replacement) { status = ARES_ENOMEM; diff --git a/src/lib/ares_parse_ns_reply.c b/src/lib/ares_parse_ns_reply.c index baaeb5eadb..eb6178b1c4 100644 --- a/src/lib/ares_parse_ns_reply.c +++ b/src/lib/ares_parse_ns_reply.c @@ -45,11 +45,11 @@ int ares_parse_ns_reply( const unsigned char* abuf, int alen, int status, i; long len; int alias_alloc = 2; + cares_ns_reply* ns_out = NULL; /* Set *host to NULL for all failure cases. */ *host = NULL; - cares_ns_reply* ns_out = NULL; status = cares_parse_ns_reply(abuf, alen, &ns_out); /* clean up on error */ @@ -142,11 +142,11 @@ int ares_parse_ns_reply( const unsigned char* abuf, int alen, return ARES_SUCCESS; } - ares_free(hostent->h_aliases); + ares_free(hostent->h_addr_list); } - ares_free(hostent->h_addr_list); + ares_free(hostent); } - ares_free(hostent); + ares_free(hname); if (ns_out) ares_free_data(ns_out); diff --git a/src/lib/ares_parse_ptr_reply.c b/src/lib/ares_parse_ptr_reply.c index a5b62b12ee..f786cb23c2 100644 --- a/src/lib/ares_parse_ptr_reply.c +++ b/src/lib/ares_parse_ptr_reply.c @@ -41,11 +41,11 @@ int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr, struct hostent *hostent = NULL; int status, i; int alias_alloc = 2; + cares_ptr_reply* ptr_out = NULL; /* Set *host to NULL for all failure cases. */ *host = NULL; - cares_ptr_reply* ptr_out = NULL; status = cares_parse_ptr_reply(abuf, alen, &ptr_out); /* clean up on error */ @@ -82,24 +82,37 @@ int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr, if (hostent->h_aliases) { /* Fill in the hostent and return successfully. */ - hostent->h_name = ares_strdup(cares_ptr_reply_get_host(ptr_out)); - if (!hostent->h_name) { - status = ARES_ENOMEM; - if (ptr_out) - ares_free_data(ptr_out); - if (hostent->h_addr_list[0]) - ares_free(hostent->h_addr_list[0]); - ares_free(hostent->h_addr_list); - ares_free(hostent); - return status; - } - + hostent->h_name = NULL; /* iterate through the linked list of cares_ptr_reply and build the h_aliases array. */ i = 0; for (cares_ptr_reply* ptr_curr=ptr_out; ptr_curr; ptr_curr = cares_ptr_reply_get_next(ptr_curr)) { + if (!cares_ptr_reply_get_next(ptr_curr)) + { + hostent->h_name = ares_strdup(cares_ptr_reply_get_host(ptr_out)); + if (!hostent->h_name) + { + status = ARES_ENOMEM; + if (ptr_out) + ares_free_data(ptr_out); + + for (int j = 0; j < i; ++j) + { + if (hostent->h_aliases[j]) + { + ares_free(hostent->h_aliases[j]); + } + } + if (hostent->h_addr_list[0]) + ares_free(hostent->h_addr_list[0]); + ares_free(hostent->h_addr_list); + ares_free(hostent); + return status; + } + } + if (alias_alloc > 2) { char** ptr; @@ -118,7 +131,8 @@ int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr, ares_free(hostent->h_aliases[j]); } } - ares_free(hostent->h_name); + if (hostent->h_name) + ares_free(hostent->h_name); ares_free(hostent->h_aliases); if (hostent->h_addr_list[0]) ares_free(hostent->h_addr_list[0]); @@ -139,7 +153,8 @@ int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr, if (hostent->h_aliases[j]) ares_free(hostent->h_aliases[j]); } - ares_free(hostent->h_name); + if (hostent->h_name) + ares_free(hostent->h_name); ares_free(hostent->h_aliases); if (hostent->h_addr_list[0]) ares_free(hostent->h_addr_list[0]); @@ -162,11 +177,12 @@ int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr, return ARES_SUCCESS; } - ares_free(hostent->h_aliases); + if (hostent->h_addr_list[0]) + ares_free(hostent->h_addr_list[0]); + ares_free(hostent->h_addr_list); } - ares_free(hostent->h_addr_list); + ares_free(hostent); } - ares_free(hostent); if (ptr_out) ares_free_data(ptr_out); diff --git a/src/lib/ares_parse_soa_reply.c b/src/lib/ares_parse_soa_reply.c index 2b2fa48f34..0c66b64b37 100644 --- a/src/lib/ares_parse_soa_reply.c +++ b/src/lib/ares_parse_soa_reply.c @@ -39,6 +39,8 @@ ares_parse_soa_reply(const unsigned char *abuf, int alen, struct ares_soa_reply **soa_out) { int status; + char* nsname = NULL; + char* hostmaster = NULL; cares_soa_reply *csoa_out = NULL; struct ares_soa_reply *soa = NULL; @@ -56,7 +58,7 @@ ares_parse_soa_reply(const unsigned char *abuf, int alen, } soa = ares_malloc_data(ARES_DATATYPE_SOA_REPLY); - char *nsname = ares_strdup(cares_soa_reply_get_nsname(csoa_out)); + nsname = ares_strdup(cares_soa_reply_get_nsname(csoa_out)); if (!nsname) { status = ARES_ENOMEM; @@ -72,7 +74,7 @@ ares_parse_soa_reply(const unsigned char *abuf, int alen, } soa->nsname = nsname; - char *hostmaster = ares_strdup(cares_soa_reply_get_hostmaster(csoa_out)); + hostmaster = ares_strdup(cares_soa_reply_get_hostmaster(csoa_out)); if (!hostmaster) { status = ARES_ENOMEM; diff --git a/src/lib/ares_parse_srv_reply.c b/src/lib/ares_parse_srv_reply.c index e3d37bc92b..335b90f151 100644 --- a/src/lib/ares_parse_srv_reply.c +++ b/src/lib/ares_parse_srv_reply.c @@ -44,6 +44,7 @@ ares_parse_srv_reply (const unsigned char *abuf, int alen, * create a linked list of struct ares_srv_reply to return */ int status; + char* newhost = NULL; struct ares_srv_reply *srv_head = NULL; struct ares_srv_reply *srv_curr = NULL; struct ares_srv_reply *srv_last = NULL; @@ -85,7 +86,7 @@ ares_parse_srv_reply (const unsigned char *abuf, int alen, srv_last = srv_curr; /* copy the host to newhost so we can free csrv_out */ - char *newhost = ares_strdup(cares_srv_reply_get_host(csrv_curr)); + newhost = ares_strdup(cares_srv_reply_get_host(csrv_curr)); if (!newhost) { status = ARES_ENOMEM; break; diff --git a/src/lib/ares_parse_txt_reply.c b/src/lib/ares_parse_txt_reply.c index 61bef206dd..309522dcdb 100644 --- a/src/lib/ares_parse_txt_reply.c +++ b/src/lib/ares_parse_txt_reply.c @@ -46,6 +46,7 @@ ares__parse_txt_reply (const unsigned char *abuf, int alen, * create a linked list of struct ares_txt_reply to return */ int status; + const unsigned char* txt = NULL; struct ares_txt_ext *txt_head = NULL; struct ares_txt_ext *txt_curr = NULL; struct ares_txt_ext *txt_last = NULL; @@ -87,7 +88,7 @@ ares__parse_txt_reply (const unsigned char *abuf, int alen, } txt_last = txt_curr; - const unsigned char* txt = cares_txt_reply_get_txt(ctxt_curr); + txt = cares_txt_reply_get_txt(ctxt_curr); txt_curr->txt = ares_malloc(cares_txt_reply_get_length(ctxt_curr) + 1); if (!txt_curr->txt) { diff --git a/src/lib/cares_parse_caa_reply.c b/src/lib/cares_parse_caa_reply.c index 59beea77a3..1f26f05ce3 100644 --- a/src/lib/cares_parse_caa_reply.c +++ b/src/lib/cares_parse_caa_reply.c @@ -109,6 +109,8 @@ cares_parse_caa_reply (const unsigned char *abuf, int alen, /* Check if we are really looking at a CAA record */ if ((rr_class == C_IN || rr_class == C_CHAOS) && rr_type == T_CAA) { + unsigned char* property; + unsigned char* value; strptr = aptr; /* Allocate storage for this CAA answer appending it to the list */ @@ -139,7 +141,6 @@ cares_parse_caa_reply (const unsigned char *abuf, int alen, status = ARES_EBADRESP; break; } - unsigned char *property; property = ares_malloc (cares_caa_reply_get_plength(caa_curr) + 1/* Including null byte */); if (property == NULL) { @@ -158,7 +159,6 @@ cares_parse_caa_reply (const unsigned char *abuf, int alen, status = ARES_EBADRESP; break; } - unsigned char *value; value = ares_malloc (cares_caa_reply_get_length(caa_curr) + 1/* Including null byte */); if (value == NULL) { diff --git a/src/lib/cares_parse_mx_reply.c b/src/lib/cares_parse_mx_reply.c index 711e10730d..05d531fd2e 100644 --- a/src/lib/cares_parse_mx_reply.c +++ b/src/lib/cares_parse_mx_reply.c @@ -40,6 +40,7 @@ cares_parse_mx_reply (const unsigned char *abuf, int alen, { unsigned int qdcount, ancount, i; const unsigned char *aptr, *vptr; + char* mx_host = NULL; int status, rr_type, rr_class, rr_len; unsigned int rr_ttl; long len; @@ -105,6 +106,7 @@ cares_parse_mx_reply (const unsigned char *abuf, int alen, /* Check if we are really looking at a MX record */ if (rr_class == C_IN && rr_type == T_MX) { + /* parse the MX record itself */ if (rr_len < 2) { @@ -134,7 +136,6 @@ cares_parse_mx_reply (const unsigned char *abuf, int alen, cares_mx_reply_set_ttl(mx_curr, rr_ttl); vptr += sizeof(unsigned short); - char* mx_host = NULL; status = ares_expand_name (vptr, abuf, alen, &mx_host, &len); if (status != ARES_SUCCESS) break; diff --git a/src/lib/cares_parse_naptr_reply.c b/src/lib/cares_parse_naptr_reply.c index b2d73831ba..437b739537 100644 --- a/src/lib/cares_parse_naptr_reply.c +++ b/src/lib/cares_parse_naptr_reply.c @@ -44,6 +44,10 @@ cares_parse_naptr_reply (const unsigned char *abuf, int alen, unsigned int rr_ttl; long len; char *hostname = NULL, *rr_name = NULL; + unsigned char* flags = NULL; + unsigned char* service = NULL; + unsigned char* regexp = NULL; + char* replacement = NULL; struct cares_naptr_reply *naptr_head = NULL; struct cares_naptr_reply *naptr_last = NULL; struct cares_naptr_reply *naptr_curr; @@ -138,28 +142,24 @@ cares_parse_naptr_reply (const unsigned char *abuf, int alen, vptr += sizeof(unsigned short); cares_naptr_reply_set_ttl(naptr_curr, rr_ttl); - unsigned char* flags; status = ares_expand_string(vptr, abuf, alen, &flags, &len); if (status != ARES_SUCCESS) break; vptr += len; cares_naptr_reply_set_flags(naptr_curr, flags); - unsigned char* service; status = ares_expand_string(vptr, abuf, alen, &service, &len); if (status != ARES_SUCCESS) break; vptr += len; cares_naptr_reply_set_service(naptr_curr, service); - unsigned char* regexp; status = ares_expand_string(vptr, abuf, alen, ®exp, &len); if (status != ARES_SUCCESS) break; vptr += len; cares_naptr_reply_set_regexp(naptr_curr, regexp); - char* replacement; status = ares_expand_name(vptr, abuf, alen, &replacement, &len); if (status != ARES_SUCCESS) break; diff --git a/src/lib/cares_parse_ns_reply.c b/src/lib/cares_parse_ns_reply.c index bec4a9a563..b44a25ab8b 100644 --- a/src/lib/cares_parse_ns_reply.c +++ b/src/lib/cares_parse_ns_reply.c @@ -44,6 +44,7 @@ int cares_parse_ns_reply(const unsigned char *abuf, int alen, long len; const unsigned char *aptr; char *ptrname = NULL, *rr_name = NULL; + char* ns_host = NULL; cares_ns_reply *ns_head = NULL; cares_ns_reply *ns_last = NULL; cares_ns_reply *ns_curr; @@ -118,7 +119,6 @@ int cares_parse_ns_reply(const unsigned char *abuf, int alen, } ns_last = ns_curr; - char* ns_host = NULL; /* Decode the RR data and set hostname to it. */ status = ares__expand_name_for_response(aptr, abuf, alen, &ns_host, &len); diff --git a/src/lib/cares_parse_ptr_reply.c b/src/lib/cares_parse_ptr_reply.c index 68b877ac44..358563e407 100644 --- a/src/lib/cares_parse_ptr_reply.c +++ b/src/lib/cares_parse_ptr_reply.c @@ -44,6 +44,7 @@ int cares_parse_ptr_reply(const unsigned char *abuf, int alen, long len; const unsigned char *aptr; char *ptrname = NULL, *rr_name = NULL; + char* ptr_host = NULL; cares_ptr_reply *ptr_head = NULL; cares_ptr_reply *ptr_last = NULL; cares_ptr_reply *ptr_curr; @@ -124,7 +125,6 @@ int cares_parse_ptr_reply(const unsigned char *abuf, int alen, } ptr_last = ptr_curr; - char* ptr_host = NULL; /* Decode the RR data and set hostname to it. */ status = ares__expand_name_for_response(aptr, abuf, alen, &ptr_host, &len); diff --git a/src/lib/cares_parse_soa_reply.c b/src/lib/cares_parse_soa_reply.c index 2d0a5a4521..01969055e4 100644 --- a/src/lib/cares_parse_soa_reply.c +++ b/src/lib/cares_parse_soa_reply.c @@ -36,9 +36,11 @@ int cares_parse_soa_reply(const unsigned char *abuf, int alen, - struct cares_soa_reply **soa_out) + struct cares_soa_reply **soa_out) { const unsigned char *aptr; + char* nsname = NULL; + char* hostmaster = NULL; long len; char *qname = NULL, *rr_name = NULL; struct cares_soa_reply *soa = NULL; @@ -123,7 +125,6 @@ cares_parse_soa_reply(const unsigned char *abuf, int alen, } /* nsname */ - char* nsname; status = ares__expand_name_for_response(aptr, abuf, alen, &nsname, &len); if (status != ARES_SUCCESS) @@ -132,7 +133,6 @@ cares_parse_soa_reply(const unsigned char *abuf, int alen, aptr += len; /* hostmaster */ - char* hostmaster; status = ares__expand_name_for_response(aptr, abuf, alen, &hostmaster, &len); if (status != ARES_SUCCESS) diff --git a/src/lib/cares_parse_srv_reply.c b/src/lib/cares_parse_srv_reply.c index 2c75b55fd6..e0b70afe0b 100644 --- a/src/lib/cares_parse_srv_reply.c +++ b/src/lib/cares_parse_srv_reply.c @@ -44,6 +44,7 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, unsigned int rr_ttl; long len; char *hostname = NULL, *rr_name = NULL; + char* srv_host = NULL; cares_srv_reply *srv_head = NULL; cares_srv_reply *srv_last = NULL; cares_srv_reply *srv_curr; @@ -138,8 +139,6 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, vptr += sizeof(unsigned short); cares_srv_reply_set_ttl(srv_curr, rr_ttl); - char* srv_host = NULL; - status = ares_expand_name (vptr, abuf, alen, &srv_host, &len); if (status != ARES_SUCCESS) break; diff --git a/src/lib/cares_parse_txt_reply.c b/src/lib/cares_parse_txt_reply.c index 0f4f04258c..d5abb650af 100644 --- a/src/lib/cares_parse_txt_reply.c +++ b/src/lib/cares_parse_txt_reply.c @@ -45,6 +45,7 @@ int cares_parse_txt_reply (const unsigned char *abuf, int alen, unsigned int qdcount, ancount, i; const unsigned char *aptr; const unsigned char *strptr; + unsigned char* txt = NULL; int status, rr_type, rr_class, rr_len; unsigned int rr_ttl; long len; @@ -150,7 +151,6 @@ int cares_parse_txt_reply (const unsigned char *abuf, int alen, cares_txt_reply_set_length(txt_curr, substr_len); cares_txt_reply_set_ttl(txt_curr, rr_ttl); - unsigned char* txt = NULL; txt = ares_malloc (substr_len + 1/* Including null byte */); if (txt == NULL) { From b55ccb9af8a06dc9c5a4740ba6b662631f81890e Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Thu, 11 Mar 2021 00:50:50 -0500 Subject: [PATCH 10/49] use ptr_curr instead of ptr_out to get h_name --- src/lib/ares_parse_ptr_reply.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib/ares_parse_ptr_reply.c b/src/lib/ares_parse_ptr_reply.c index f786cb23c2..13b733d434 100644 --- a/src/lib/ares_parse_ptr_reply.c +++ b/src/lib/ares_parse_ptr_reply.c @@ -82,7 +82,7 @@ int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr, if (hostent->h_aliases) { /* Fill in the hostent and return successfully. */ - hostent->h_name = NULL; + hostent->h_name = NULL; /* iterate through the linked list of cares_ptr_reply and build the h_aliases array. */ i = 0; @@ -91,8 +91,8 @@ int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr, { if (!cares_ptr_reply_get_next(ptr_curr)) { - hostent->h_name = ares_strdup(cares_ptr_reply_get_host(ptr_out)); - if (!hostent->h_name) + hostent->h_name = ares_strdup(cares_ptr_reply_get_host(ptr_curr)); + if (!hostent->h_name) { status = ARES_ENOMEM; if (ptr_out) From 08de712a6a68bd8d2f92b2336c995c39366265a8 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Fri, 12 Mar 2021 20:50:54 -0500 Subject: [PATCH 11/49] fix memory leaks --- src/lib/ares_data.c | 22 +++++++++++++++++++++- src/lib/ares_parse_ns_reply.c | 7 +++---- src/lib/ares_parse_ptr_reply.c | 5 ++++- src/lib/cares_parse_ns_reply.c | 12 ++++++------ src/lib/cares_parse_soa_reply.c | 3 +++ test/ares-test-parse-ns.cc | 9 +++++---- 6 files changed, 42 insertions(+), 16 deletions(-) diff --git a/src/lib/ares_data.c b/src/lib/ares_data.c index 82752fa905..3fc43d7d10 100644 --- a/src/lib/ares_data.c +++ b/src/lib/ares_data.c @@ -135,10 +135,30 @@ void ares_free_data(void *dataptr) ares_free(ptr->data.caa_reply.value); break; + case ARES_DATATYPE_CPTR_REPLY: + + if (ptr->data.cptr_reply.next) + next_data = ptr->data.cptr_reply.next; + if (ptr->data.cptr_reply.host) + ares_free(ptr->data.cptr_reply.host); + break; + + case ARES_DATATYPE_CNS_REPLY: + + printf("free ns\n"); + if (ptr->data.cns_reply.next) + next_data = ptr->data.cns_reply.next; + if (ptr->data.cns_reply.host) + { + printf("free host\n"); + ares_free(ptr->data.cns_reply.host); + } + break; + default: return; } - + printf("free ptr\n"); ares_free(ptr); dataptr = next_data; } diff --git a/src/lib/ares_parse_ns_reply.c b/src/lib/ares_parse_ns_reply.c index eb6178b1c4..c9706c6422 100644 --- a/src/lib/ares_parse_ns_reply.c +++ b/src/lib/ares_parse_ns_reply.c @@ -64,8 +64,7 @@ int ares_parse_ns_reply( const unsigned char* abuf, int alen, status = ares__expand_name_for_response(aptr, abuf, alen, &hname, &len); if (status != ARES_SUCCESS) { - if (hname) - ares_free(hname); + ares_free_data(ns_out); return status; } @@ -99,7 +98,7 @@ int ares_parse_ns_reply( const unsigned char* abuf, int alen, if (ns_out) ares_free_data(ns_out); - for (int j = 0; j <= i; ++j) + for (int j = 0; j < i; ++j) { if (hostent->h_aliases[j]) ares_free(hostent->h_aliases[j]); @@ -118,7 +117,7 @@ int ares_parse_ns_reply( const unsigned char* abuf, int alen, if (ns_out) ares_free_data(ns_out); - for (int j = 0; j <= i; ++j) + for (int j = 0; j < i; ++j) { if (hostent->h_aliases[j]) ares_free(hostent->h_aliases[j]); diff --git a/src/lib/ares_parse_ptr_reply.c b/src/lib/ares_parse_ptr_reply.c index 13b733d434..486dff7ed8 100644 --- a/src/lib/ares_parse_ptr_reply.c +++ b/src/lib/ares_parse_ptr_reply.c @@ -83,6 +83,7 @@ int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr, { /* Fill in the hostent and return successfully. */ hostent->h_name = NULL; + /* iterate through the linked list of cares_ptr_reply and build the h_aliases array. */ i = 0; @@ -105,6 +106,8 @@ int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr, ares_free(hostent->h_aliases[j]); } } + if (hostent->h_aliases) + ares_free(hostent->h_aliases); if (hostent->h_addr_list[0]) ares_free(hostent->h_addr_list[0]); ares_free(hostent->h_addr_list); @@ -117,7 +120,7 @@ int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr, { char** ptr; ptr = ares_realloc(hostent->h_aliases, - alias_alloc * sizeof(char *)); + alias_alloc * sizeof(char *)); if (!ptr) { status = ARES_ENOMEM; diff --git a/src/lib/cares_parse_ns_reply.c b/src/lib/cares_parse_ns_reply.c index b44a25ab8b..e87e5e5313 100644 --- a/src/lib/cares_parse_ns_reply.c +++ b/src/lib/cares_parse_ns_reply.c @@ -43,11 +43,11 @@ int cares_parse_ns_reply(const unsigned char *abuf, int alen, unsigned int rr_ttl; long len; const unsigned char *aptr; - char *ptrname = NULL, *rr_name = NULL; + char *nsname = NULL, *rr_name = NULL; char* ns_host = NULL; cares_ns_reply *ns_head = NULL; cares_ns_reply *ns_last = NULL; - cares_ns_reply *ns_curr; + cares_ns_reply *ns_curr = NULL; /* Set *ns_out to NULL for all failure cases. */ *ns_out = NULL; @@ -66,12 +66,12 @@ int cares_parse_ns_reply(const unsigned char *abuf, int alen, /* Expand the name from the question, and skip past the question. */ aptr = abuf + HFIXEDSZ; - status = ares__expand_name_for_response(aptr, abuf, alen, &ptrname, &len); + status = ares__expand_name_for_response(aptr, abuf, alen, &nsname, &len); if (status != ARES_SUCCESS) return status; if (aptr + len + QFIXEDSZ > abuf + alen) { - ares_free(ptrname); + ares_free(nsname); return ARES_EBADRESP; } aptr += len + QFIXEDSZ; @@ -150,8 +150,8 @@ int cares_parse_ns_reply(const unsigned char *abuf, int alen, } /* LCOV_EXCL_STOP */ } - if (ptrname) - ares_free(ptrname); + if (nsname) + ares_free(nsname); if (rr_name) ares_free(rr_name); diff --git a/src/lib/cares_parse_soa_reply.c b/src/lib/cares_parse_soa_reply.c index 01969055e4..3d312af0ac 100644 --- a/src/lib/cares_parse_soa_reply.c +++ b/src/lib/cares_parse_soa_reply.c @@ -68,7 +68,10 @@ cares_parse_soa_reply(const unsigned char *abuf, int alen, return status; if (alen <= len + HFIXEDSZ + 1) + { + ares_free(qname); return ARES_EBADRESP; + } aptr += len; qclass = DNS_QUESTION_TYPE(aptr); diff --git a/test/ares-test-parse-ns.cc b/test/ares-test-parse-ns.cc index 45aa9dca2d..eec385b9c1 100644 --- a/test/ares-test-parse-ns.cc +++ b/test/ares-test-parse-ns.cc @@ -75,9 +75,10 @@ TEST_F(LibraryTest, ParseCNsReplyMultiple) { .add_additional(new DNSARR("ns3.google.com", 247, {216,239,36,10})); std::vector data = pkt.data(); - cares_ns_reply* ns = nullptr; - EXPECT_EQ(ARES_SUCCESS, cares_parse_ns_reply(data.data(), data.size(), &ns)); - ASSERT_NE(nullptr, ns); + cares_ns_reply* ns0 = nullptr; + EXPECT_EQ(ARES_SUCCESS, cares_parse_ns_reply(data.data(), data.size(), &ns0)); + ASSERT_NE(nullptr, ns0); + cares_ns_reply* ns = ns0; EXPECT_EQ("ns1.google.com", std::string(cares_ns_reply_get_host(ns))); EXPECT_EQ(59, cares_ns_reply_get_ttl(ns)); ns = cares_ns_reply_get_next(ns); @@ -89,7 +90,7 @@ TEST_F(LibraryTest, ParseCNsReplyMultiple) { ns = cares_ns_reply_get_next(ns); EXPECT_EQ("ns4.google.com", std::string(cares_ns_reply_get_host(ns))); EXPECT_EQ(59, cares_ns_reply_get_ttl(ns)); - ares_free_data(ns); + ares_free_data(ns0); } TEST_F(LibraryTest, ParseNsReplyErrors) { From 7eae6d83ab7f899c0110a48192bcfd80095254e9 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Sat, 13 Mar 2021 14:23:44 -0500 Subject: [PATCH 12/49] remove debug prints and fix unrelated Container test leak --- src/lib/ares_data.c | 3 --- test/ares-test-init.cc | 1 + 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/lib/ares_data.c b/src/lib/ares_data.c index 3fc43d7d10..39b2f3454d 100644 --- a/src/lib/ares_data.c +++ b/src/lib/ares_data.c @@ -145,12 +145,10 @@ void ares_free_data(void *dataptr) case ARES_DATATYPE_CNS_REPLY: - printf("free ns\n"); if (ptr->data.cns_reply.next) next_data = ptr->data.cns_reply.next; if (ptr->data.cns_reply.host) { - printf("free host\n"); ares_free(ptr->data.cns_reply.host); } break; @@ -158,7 +156,6 @@ void ares_free_data(void *dataptr) default: return; } - printf("free ptr\n"); ares_free(ptr); dataptr = next_data; } diff --git a/test/ares-test-init.cc b/test/ares-test-init.cc index ff6c6c6e02..d519c9f2a9 100644 --- a/test/ares-test-init.cc +++ b/test/ares-test-init.cc @@ -505,6 +505,7 @@ CONTAINED_TEST_F(LibraryTest, ContainerResolvConfNotReadable, MakeUnreadable hide("/etc/resolv.conf"); // Unavailable /etc/resolv.conf falls back to defaults EXPECT_EQ(ARES_SUCCESS, ares_init(&channel)); + ares_destroy(channel); return HasFailure(); } CONTAINED_TEST_F(LibraryTest, ContainerNsswitchConfNotReadable, From 31797320e65819bdc83f0518f67a7b407b47eac9 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Sat, 6 Nov 2021 23:24:25 -0400 Subject: [PATCH 13/49] 406 - Validate hostnames in DNS responses Update the new cares parse ns, ptr, and soa to have the is_hostname parameter passed to ares__expand_name_for_response. This is to make sure the fix for issue #406 is applied. --- src/lib/cares_parse_ns_reply.c | 6 +++--- src/lib/cares_parse_ptr_reply.c | 8 ++++---- src/lib/cares_parse_soa_reply.c | 8 ++++---- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/lib/cares_parse_ns_reply.c b/src/lib/cares_parse_ns_reply.c index e87e5e5313..ad7fc0cd81 100644 --- a/src/lib/cares_parse_ns_reply.c +++ b/src/lib/cares_parse_ns_reply.c @@ -66,7 +66,7 @@ int cares_parse_ns_reply(const unsigned char *abuf, int alen, /* Expand the name from the question, and skip past the question. */ aptr = abuf + HFIXEDSZ; - status = ares__expand_name_for_response(aptr, abuf, alen, &nsname, &len); + status = ares__expand_name_for_response(aptr, abuf, alen, &nsname, &len, 0); if (status != ARES_SUCCESS) return status; if (aptr + len + QFIXEDSZ > abuf + alen) @@ -80,7 +80,7 @@ int cares_parse_ns_reply(const unsigned char *abuf, int alen, for (i = 0; i < (int)ancount; i++) { /* Decode the RR up to the data field. */ - status = ares__expand_name_for_response(aptr, abuf, alen, &rr_name, &len); + status = ares__expand_name_for_response(aptr, abuf, alen, &rr_name, &len, 0); if (status != ARES_SUCCESS) break; aptr += len; @@ -121,7 +121,7 @@ int cares_parse_ns_reply(const unsigned char *abuf, int alen, /* Decode the RR data and set hostname to it. */ status = ares__expand_name_for_response(aptr, abuf, alen, &ns_host, - &len); + &len, 1); if (status != ARES_SUCCESS) { break; diff --git a/src/lib/cares_parse_ptr_reply.c b/src/lib/cares_parse_ptr_reply.c index 358563e407..a52fd0222c 100644 --- a/src/lib/cares_parse_ptr_reply.c +++ b/src/lib/cares_parse_ptr_reply.c @@ -66,7 +66,7 @@ int cares_parse_ptr_reply(const unsigned char *abuf, int alen, /* Expand the name from the question, and skip past the question. */ aptr = abuf + HFIXEDSZ; - status = ares__expand_name_for_response(aptr, abuf, alen, &ptrname, &len); + status = ares__expand_name_for_response(aptr, abuf, alen, &ptrname, &len, 0); if (status != ARES_SUCCESS) return status; if (aptr + len + QFIXEDSZ > abuf + alen) @@ -80,7 +80,7 @@ int cares_parse_ptr_reply(const unsigned char *abuf, int alen, for (i = 0; i < (int)ancount; i++) { /* Decode the RR up to the data field. */ - status = ares__expand_name_for_response(aptr, abuf, alen, &rr_name, &len); + status = ares__expand_name_for_response(aptr, abuf, alen, &rr_name, &len, 0); if (status != ARES_SUCCESS) break; aptr += len; @@ -127,7 +127,7 @@ int cares_parse_ptr_reply(const unsigned char *abuf, int alen, /* Decode the RR data and set hostname to it. */ status = ares__expand_name_for_response(aptr, abuf, alen, &ptr_host, - &len); + &len, 1); if (status != ARES_SUCCESS) { break; @@ -142,7 +142,7 @@ int cares_parse_ptr_reply(const unsigned char *abuf, int alen, ares_free(ptrname); ptrname = NULL; status = ares__expand_name_for_response(aptr, abuf, alen, &ptrname, - &len); + &len, 1); if (status != ARES_SUCCESS) { break; diff --git a/src/lib/cares_parse_soa_reply.c b/src/lib/cares_parse_soa_reply.c index 3d312af0ac..be9fe0f1d7 100644 --- a/src/lib/cares_parse_soa_reply.c +++ b/src/lib/cares_parse_soa_reply.c @@ -63,7 +63,7 @@ cares_parse_soa_reply(const unsigned char *abuf, int alen, aptr = abuf + HFIXEDSZ; /* query name */ - status = ares__expand_name_for_response(aptr, abuf, alen, &qname, &len); + status = ares__expand_name_for_response(aptr, abuf, alen, &qname, &len, 0); if (status != ARES_SUCCESS) return status; @@ -95,7 +95,7 @@ cares_parse_soa_reply(const unsigned char *abuf, int alen, for (i = 0; i < ancount; i++) { rr_name = NULL; - status = ares__expand_name_for_response (aptr, abuf, alen, &rr_name, &len); + status = ares__expand_name_for_response (aptr, abuf, alen, &rr_name, &len, 0); if (status != ARES_SUCCESS) { break; @@ -129,7 +129,7 @@ cares_parse_soa_reply(const unsigned char *abuf, int alen, /* nsname */ status = ares__expand_name_for_response(aptr, abuf, alen, &nsname, - &len); + &len, 0); if (status != ARES_SUCCESS) break; cares_soa_reply_set_nsname(soa, nsname); @@ -137,7 +137,7 @@ cares_parse_soa_reply(const unsigned char *abuf, int alen, /* hostmaster */ status = ares__expand_name_for_response(aptr, abuf, alen, - &hostmaster, &len); + &hostmaster, &len, 0); if (status != ARES_SUCCESS) break; cares_soa_reply_set_hostmaster(soa, hostmaster); From 1e03b8127d591eccf7c875fbb5484df841e1f974 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Sat, 6 Nov 2021 23:39:04 -0400 Subject: [PATCH 14/49] fix a missed a conflict in ares.h --- aminclude_static.am | 126 ++++++++++++++++++++++++++++++++++++++++++++ include/ares.h | 3 -- 2 files changed, 126 insertions(+), 3 deletions(-) create mode 100644 aminclude_static.am diff --git a/aminclude_static.am b/aminclude_static.am new file mode 100644 index 0000000000..fff4199273 --- /dev/null +++ b/aminclude_static.am @@ -0,0 +1,126 @@ + +# aminclude_static.am generated automatically by Autoconf +# from AX_AM_MACROS_STATIC on Sat Nov 6 23:31:46 EDT 2021 + + +# Code coverage +# +# Optional: +# - CODE_COVERAGE_DIRECTORY: Top-level directory for code coverage reporting. +# Multiple directories may be specified, separated by whitespace. +# (Default: $(top_builddir)) +# - CODE_COVERAGE_OUTPUT_FILE: Filename and path for the .info file generated +# by lcov for code coverage. (Default: +# $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info) +# - CODE_COVERAGE_OUTPUT_DIRECTORY: Directory for generated code coverage +# reports to be created. (Default: +# $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage) +# - CODE_COVERAGE_BRANCH_COVERAGE: Set to 1 to enforce branch coverage, +# set to 0 to disable it and leave empty to stay with the default. +# (Default: empty) +# - CODE_COVERAGE_LCOV_SHOPTS_DEFAULT: Extra options shared between both lcov +# instances. (Default: based on ) +# - CODE_COVERAGE_LCOV_SHOPTS: Extra options to shared between both lcov +# instances. (Default: ) +# - CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH: --gcov-tool pathtogcov +# - CODE_COVERAGE_LCOV_OPTIONS_DEFAULT: Extra options to pass to the +# collecting lcov instance. (Default: ) +# - CODE_COVERAGE_LCOV_OPTIONS: Extra options to pass to the collecting lcov +# instance. (Default: ) +# - CODE_COVERAGE_LCOV_RMOPTS_DEFAULT: Extra options to pass to the filtering +# lcov instance. (Default: empty) +# - CODE_COVERAGE_LCOV_RMOPTS: Extra options to pass to the filtering lcov +# instance. (Default: ) +# - CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT: Extra options to pass to the +# genhtml instance. (Default: based on ) +# - CODE_COVERAGE_GENHTML_OPTIONS: Extra options to pass to the genhtml +# instance. (Default: ) +# - CODE_COVERAGE_IGNORE_PATTERN: Extra glob pattern of files to ignore +# +# The generated report will be titled using the $(PACKAGE_NAME) and +# $(PACKAGE_VERSION). In order to add the current git hash to the title, +# use the git-version-gen script, available online. +# Optional variables +# run only on top dir +if CODE_COVERAGE_ENABLED + ifeq ($(abs_builddir), $(abs_top_builddir)) +CODE_COVERAGE_DIRECTORY ?= $(top_builddir) +CODE_COVERAGE_OUTPUT_FILE ?= $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info +CODE_COVERAGE_OUTPUT_DIRECTORY ?= $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage + +CODE_COVERAGE_BRANCH_COVERAGE ?= +CODE_COVERAGE_LCOV_SHOPTS_DEFAULT ?= $(if $(CODE_COVERAGE_BRANCH_COVERAGE),--rc lcov_branch_coverage=$(CODE_COVERAGE_BRANCH_COVERAGE)) +CODE_COVERAGE_LCOV_SHOPTS ?= $(CODE_COVERAGE_LCOV_SHOPTS_DEFAULT) +CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH ?= --gcov-tool "$(GCOV)" +CODE_COVERAGE_LCOV_OPTIONS_DEFAULT ?= $(CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH) +CODE_COVERAGE_LCOV_OPTIONS ?= $(CODE_COVERAGE_LCOV_OPTIONS_DEFAULT) +CODE_COVERAGE_LCOV_RMOPTS_DEFAULT ?= +CODE_COVERAGE_LCOV_RMOPTS ?= $(CODE_COVERAGE_LCOV_RMOPTS_DEFAULT) +CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT ?=$(if $(CODE_COVERAGE_BRANCH_COVERAGE),--rc genhtml_branch_coverage=$(CODE_COVERAGE_BRANCH_COVERAGE)) +CODE_COVERAGE_GENHTML_OPTIONS ?= $(CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT) +CODE_COVERAGE_IGNORE_PATTERN ?= + +GITIGNOREFILES := $(GITIGNOREFILES) $(CODE_COVERAGE_OUTPUT_FILE) $(CODE_COVERAGE_OUTPUT_DIRECTORY) +code_coverage_v_lcov_cap = $(code_coverage_v_lcov_cap_$(V)) +code_coverage_v_lcov_cap_ = $(code_coverage_v_lcov_cap_$(AM_DEFAULT_VERBOSITY)) +code_coverage_v_lcov_cap_0 = @echo " LCOV --capture" $(CODE_COVERAGE_OUTPUT_FILE); +code_coverage_v_lcov_ign = $(code_coverage_v_lcov_ign_$(V)) +code_coverage_v_lcov_ign_ = $(code_coverage_v_lcov_ign_$(AM_DEFAULT_VERBOSITY)) +code_coverage_v_lcov_ign_0 = @echo " LCOV --remove /tmp/*" $(CODE_COVERAGE_IGNORE_PATTERN); +code_coverage_v_genhtml = $(code_coverage_v_genhtml_$(V)) +code_coverage_v_genhtml_ = $(code_coverage_v_genhtml_$(AM_DEFAULT_VERBOSITY)) +code_coverage_v_genhtml_0 = @echo " GEN " "$(CODE_COVERAGE_OUTPUT_DIRECTORY)"; +code_coverage_quiet = $(code_coverage_quiet_$(V)) +code_coverage_quiet_ = $(code_coverage_quiet_$(AM_DEFAULT_VERBOSITY)) +code_coverage_quiet_0 = --quiet + +# sanitizes the test-name: replaces with underscores: dashes and dots +code_coverage_sanitize = $(subst -,_,$(subst .,_,$(1))) + +# Use recursive makes in order to ignore errors during check +check-code-coverage: + -$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -k check + $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) code-coverage-capture + +# Capture code coverage data +code-coverage-capture: code-coverage-capture-hook + $(code_coverage_v_lcov_cap)$(LCOV) $(code_coverage_quiet) $(addprefix --directory ,$(CODE_COVERAGE_DIRECTORY)) --capture --output-file "$(CODE_COVERAGE_OUTPUT_FILE).tmp" --test-name "$(call code_coverage_sanitize,$(PACKAGE_NAME)-$(PACKAGE_VERSION))" --no-checksum --compat-libtool $(CODE_COVERAGE_LCOV_SHOPTS) $(CODE_COVERAGE_LCOV_OPTIONS) + $(code_coverage_v_lcov_ign)$(LCOV) $(code_coverage_quiet) $(addprefix --directory ,$(CODE_COVERAGE_DIRECTORY)) --remove "$(CODE_COVERAGE_OUTPUT_FILE).tmp" "/tmp/*" $(CODE_COVERAGE_IGNORE_PATTERN) --output-file "$(CODE_COVERAGE_OUTPUT_FILE)" $(CODE_COVERAGE_LCOV_SHOPTS) $(CODE_COVERAGE_LCOV_RMOPTS) + -@rm -f "$(CODE_COVERAGE_OUTPUT_FILE).tmp" + $(code_coverage_v_genhtml)LANG=C $(GENHTML) $(code_coverage_quiet) $(addprefix --prefix ,$(CODE_COVERAGE_DIRECTORY)) --output-directory "$(CODE_COVERAGE_OUTPUT_DIRECTORY)" --title "$(PACKAGE_NAME)-$(PACKAGE_VERSION) Code Coverage" --legend --show-details "$(CODE_COVERAGE_OUTPUT_FILE)" $(CODE_COVERAGE_GENHTML_OPTIONS) + @echo "file://$(abs_builddir)/$(CODE_COVERAGE_OUTPUT_DIRECTORY)/index.html" + +code-coverage-clean: + -$(LCOV) --directory $(top_builddir) -z + -rm -rf "$(CODE_COVERAGE_OUTPUT_FILE)" "$(CODE_COVERAGE_OUTPUT_FILE).tmp" "$(CODE_COVERAGE_OUTPUT_DIRECTORY)" + -find . \( -name "*.gcda" -o -name "*.gcno" -o -name "*.gcov" \) -delete + +code-coverage-dist-clean: + +AM_DISTCHECK_CONFIGURE_FLAGS := $(AM_DISTCHECK_CONFIGURE_FLAGS) --disable-code-coverage + else # ifneq ($(abs_builddir), $(abs_top_builddir)) +check-code-coverage: + +code-coverage-capture: code-coverage-capture-hook + +code-coverage-clean: + +code-coverage-dist-clean: + endif # ifeq ($(abs_builddir), $(abs_top_builddir)) +else #! CODE_COVERAGE_ENABLED +# Use recursive makes in order to ignore errors during check +check-code-coverage: + @echo "Need to reconfigure with --enable-code-coverage" +# Capture code coverage data +code-coverage-capture: code-coverage-capture-hook + @echo "Need to reconfigure with --enable-code-coverage" + +code-coverage-clean: + +code-coverage-dist-clean: + +endif #CODE_COVERAGE_ENABLED +# Hook rule executed before code-coverage-capture, overridable by the user +code-coverage-capture-hook: + +.PHONY: check-code-coverage code-coverage-capture code-coverage-dist-clean code-coverage-clean code-coverage-capture-hook diff --git a/include/ares.h b/include/ares.h index 6f50b95588..3d4cddabf1 100644 --- a/include/ares.h +++ b/include/ares.h @@ -620,11 +620,9 @@ struct ares_soa_reply { unsigned int minttl; }; -<<<<<<< HEAD struct cares_soa_reply; typedef struct cares_soa_reply cares_soa_reply; -======= struct ares_uri_reply { struct ares_uri_reply *next; unsigned short priority; @@ -632,7 +630,6 @@ struct ares_uri_reply { char *uri; int ttl; }; ->>>>>>> main /* * Similar to addrinfo, but with extra ttl and missing canonname. From d36bec7f5645c43f5448be5fb7114e9cb452494f Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Sat, 6 Nov 2021 23:51:07 -0400 Subject: [PATCH 15/49] add is_hostname parameter back in one spot --- src/lib/ares_parse_ns_reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/ares_parse_ns_reply.c b/src/lib/ares_parse_ns_reply.c index c9706c6422..29a758b730 100644 --- a/src/lib/ares_parse_ns_reply.c +++ b/src/lib/ares_parse_ns_reply.c @@ -61,7 +61,7 @@ int ares_parse_ns_reply( const unsigned char* abuf, int alen, } aptr = abuf + HFIXEDSZ; - status = ares__expand_name_for_response(aptr, abuf, alen, &hname, &len); + status = ares__expand_name_for_response(aptr, abuf, alen, &hname, &len, 0); if (status != ARES_SUCCESS) { ares_free_data(ns_out); From 281489419f9b61f54e117e6ed369acd6ef2422f0 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Sun, 7 Nov 2021 00:40:11 -0400 Subject: [PATCH 16/49] change struct cares_ to just cares_ for declarations --- include/ares.h | 1 + src/lib/ares_private.h | 14 +++++++------- src/lib/cares_parse_mx_reply.c | 6 +++--- src/lib/cares_parse_naptr_reply.c | 8 ++++---- src/lib/cares_parse_soa_reply.c | 4 ++-- src/lib/cares_parse_txt_reply.c | 6 +++--- test/ares-test-parse-caa.cc | 8 ++++---- test/ares-test-parse-mx.cc | 8 ++++---- test/ares-test-parse-naptr.cc | 10 +++++----- test/ares-test-parse-ptr.cc | 16 ++++++++-------- test/ares-test-parse-soa-any.cc | 6 +++--- test/ares-test-parse-soa.cc | 6 +++--- test/ares-test-parse-srv.cc | 22 +++++++++++----------- test/ares-test-parse-txt.cc | 18 +++++++++--------- 14 files changed, 67 insertions(+), 66 deletions(-) diff --git a/include/ares.h b/include/ares.h index 3d4cddabf1..f98471cdd3 100644 --- a/include/ares.h +++ b/include/ares.h @@ -623,6 +623,7 @@ struct ares_soa_reply { struct cares_soa_reply; typedef struct cares_soa_reply cares_soa_reply; + struct ares_uri_reply { struct ares_uri_reply *next; unsigned short priority; diff --git a/src/lib/ares_private.h b/src/lib/ares_private.h index abb22cb33a..e5d6bc76a2 100644 --- a/src/lib/ares_private.h +++ b/src/lib/ares_private.h @@ -440,7 +440,7 @@ int ares__connect_socket(ares_channel channel, * cares reply structs can be modified without breaking ABI. */ struct cares_caa_reply { - struct cares_caa_reply *next; + cares_caa_reply *next; int critical; unsigned char *property; size_t plength; /* plength excludes null termination */ @@ -450,19 +450,19 @@ int ares__connect_socket(ares_channel channel, }; struct cares_ptr_reply { - struct cares_ptr_reply *next; + cares_ptr_reply *next; char *host; unsigned int ttl; }; struct cares_ns_reply { - struct cares_ns_reply *next; + cares_ns_reply *next; char *host; unsigned int ttl; }; struct cares_srv_reply { - struct cares_srv_reply *next; + cares_srv_reply *next; char *host; unsigned short priority; unsigned short weight; @@ -471,14 +471,14 @@ struct cares_srv_reply { }; struct cares_mx_reply { - struct cares_mx_reply *next; + cares_mx_reply *next; char *host; unsigned short priority; unsigned int ttl; }; struct cares_txt_reply { - struct cares_txt_reply *next; + cares_txt_reply *next; unsigned char *txt; size_t length; /* 1 - if start of new record @@ -488,7 +488,7 @@ struct cares_txt_reply { }; struct cares_naptr_reply { - struct cares_naptr_reply *next; + cares_naptr_reply *next; unsigned char *flags; unsigned char *service; unsigned char *regexp; diff --git a/src/lib/cares_parse_mx_reply.c b/src/lib/cares_parse_mx_reply.c index 05d531fd2e..f6bf9425fc 100644 --- a/src/lib/cares_parse_mx_reply.c +++ b/src/lib/cares_parse_mx_reply.c @@ -45,9 +45,9 @@ cares_parse_mx_reply (const unsigned char *abuf, int alen, unsigned int rr_ttl; long len; char *hostname = NULL, *rr_name = NULL; - struct cares_mx_reply *mx_head = NULL; - struct cares_mx_reply *mx_last = NULL; - struct cares_mx_reply *mx_curr; + cares_mx_reply *mx_head = NULL; + cares_mx_reply *mx_last = NULL; + cares_mx_reply *mx_curr; /* Set *mx_out to NULL for all failure cases. */ *mx_out = NULL; diff --git a/src/lib/cares_parse_naptr_reply.c b/src/lib/cares_parse_naptr_reply.c index 437b739537..735bc2a3dc 100644 --- a/src/lib/cares_parse_naptr_reply.c +++ b/src/lib/cares_parse_naptr_reply.c @@ -36,7 +36,7 @@ int cares_parse_naptr_reply (const unsigned char *abuf, int alen, - struct cares_naptr_reply **naptr_out) + cares_naptr_reply **naptr_out) { unsigned int qdcount, ancount, i; const unsigned char *aptr, *vptr; @@ -48,9 +48,9 @@ cares_parse_naptr_reply (const unsigned char *abuf, int alen, unsigned char* service = NULL; unsigned char* regexp = NULL; char* replacement = NULL; - struct cares_naptr_reply *naptr_head = NULL; - struct cares_naptr_reply *naptr_last = NULL; - struct cares_naptr_reply *naptr_curr; + cares_naptr_reply *naptr_head = NULL; + cares_naptr_reply *naptr_last = NULL; + cares_naptr_reply *naptr_curr; /* Set *naptr_out to NULL for all failure cases. */ *naptr_out = NULL; diff --git a/src/lib/cares_parse_soa_reply.c b/src/lib/cares_parse_soa_reply.c index be9fe0f1d7..87e5aab0e1 100644 --- a/src/lib/cares_parse_soa_reply.c +++ b/src/lib/cares_parse_soa_reply.c @@ -36,14 +36,14 @@ int cares_parse_soa_reply(const unsigned char *abuf, int alen, - struct cares_soa_reply **soa_out) + cares_soa_reply **soa_out) { const unsigned char *aptr; char* nsname = NULL; char* hostmaster = NULL; long len; char *qname = NULL, *rr_name = NULL; - struct cares_soa_reply *soa = NULL; + cares_soa_reply *soa = NULL; int qdcount, ancount, qclass; int status, i, rr_type, rr_class, rr_len; unsigned int rr_ttl; diff --git a/src/lib/cares_parse_txt_reply.c b/src/lib/cares_parse_txt_reply.c index d5abb650af..36166ace4a 100644 --- a/src/lib/cares_parse_txt_reply.c +++ b/src/lib/cares_parse_txt_reply.c @@ -50,9 +50,9 @@ int cares_parse_txt_reply (const unsigned char *abuf, int alen, unsigned int rr_ttl; long len; char *hostname = NULL, *rr_name = NULL; - struct cares_txt_reply *txt_head = NULL; - struct cares_txt_reply *txt_last = NULL; - struct cares_txt_reply *txt_curr; + cares_txt_reply *txt_head = NULL; + cares_txt_reply *txt_last = NULL; + cares_txt_reply *txt_curr; /* Set *txt_out to NULL for all failure cases. */ *txt_out = NULL; diff --git a/test/ares-test-parse-caa.cc b/test/ares-test-parse-caa.cc index 9e688e2115..aab12dcc40 100644 --- a/test/ares-test-parse-caa.cc +++ b/test/ares-test-parse-caa.cc @@ -123,7 +123,7 @@ TEST_F(LibraryTest, ParseCCaaBogusReply1) { 0x6B, 0x69, 0x2E, 0x67, 0x6F, 0x6F, 0x67 // ki.goog }; - struct cares_caa_reply* caa = nullptr; + cares_caa_reply* caa = nullptr; EXPECT_EQ(ARES_EBADRESP, cares_parse_caa_reply(data.data(), data.size(), &caa)); ASSERT_EQ(nullptr, caa); } @@ -149,7 +149,7 @@ TEST_F(LibraryTest, ParseCCaaBogusReply2) { 0x6B, 0x69, 0x2E, 0x67, 0x6F, 0x6F, 0x67 // ki.goog }; - struct cares_caa_reply* caa = nullptr; + cares_caa_reply* caa = nullptr; EXPECT_EQ(ARES_EBADRESP, cares_parse_caa_reply(data.data(), data.size(), &caa)); ASSERT_EQ(nullptr, caa); } @@ -175,7 +175,7 @@ TEST_F(LibraryTest, ParseCCaaBogusReply3) { 0x6B, 0x69, 0x2E, 0x67, 0x6F, 0x6F, 0x67 // ki.goog }; - struct cares_caa_reply* caa = nullptr; + cares_caa_reply* caa = nullptr; EXPECT_EQ(ARES_EBADRESP, cares_parse_caa_reply(data.data(), data.size(), &caa)); ASSERT_EQ(nullptr, caa); } @@ -207,7 +207,7 @@ TEST_F(LibraryTest, ParseCCaaEmptyReply) { 0x80, 0x00, 0x00, 0x02, 0x58 // ....X }; - struct cares_caa_reply* caa = nullptr; + cares_caa_reply* caa = nullptr; EXPECT_EQ(ARES_ENODATA, cares_parse_caa_reply(data.data(), data.size(), &caa)); ASSERT_EQ(nullptr, caa); } diff --git a/test/ares-test-parse-mx.cc b/test/ares-test-parse-mx.cc index 19cce7a077..b6099e66a0 100644 --- a/test/ares-test-parse-mx.cc +++ b/test/ares-test-parse-mx.cc @@ -38,14 +38,14 @@ TEST_F(LibraryTest, ParseCMxReplyOK) { .add_answer(new DNSMxRR("example.com", 100, 200, "mx2.example.com")); std::vector data = pkt.data(); - struct cares_mx_reply* mx = nullptr; + cares_mx_reply* mx = nullptr; EXPECT_EQ(ARES_SUCCESS, cares_parse_mx_reply(data.data(), data.size(), &mx)); ASSERT_NE(nullptr, mx); EXPECT_EQ("mx1.example.com", std::string(cares_mx_reply_get_host(mx))); EXPECT_EQ(100, cares_mx_reply_get_priority(mx)); EXPECT_EQ(100, cares_mx_reply_get_ttl(mx)); - struct cares_mx_reply* mx2 = cares_mx_reply_get_next(mx); + cares_mx_reply* mx2 = cares_mx_reply_get_next(mx); ASSERT_NE(nullptr, mx2); EXPECT_EQ("mx2.example.com", std::string(cares_mx_reply_get_host(mx2))); EXPECT_EQ(200, cares_mx_reply_get_priority(mx2)); @@ -112,7 +112,7 @@ TEST_F(LibraryTest, ParseCMxReplyMalformed) { 0x02, }; - struct cares_mx_reply* mx = nullptr; + cares_mx_reply* mx = nullptr; EXPECT_EQ(ARES_EBADRESP, cares_parse_mx_reply(data.data(), data.size(), &mx)); ASSERT_EQ(nullptr, mx); } @@ -182,7 +182,7 @@ TEST_F(LibraryTest, ParseCMxReplyErrors) { .add_question(new DNSQuestion("example.com", T_MX)) .add_answer(new DNSMxRR("example.com", 100, 100, "mx1.example.com")); std::vector data; - struct cares_mx_reply* mx = nullptr; + cares_mx_reply* mx = nullptr; // No question. pkt.questions_.clear(); diff --git a/test/ares-test-parse-naptr.cc b/test/ares-test-parse-naptr.cc index fd772ae698..46d631ebdc 100644 --- a/test/ares-test-parse-naptr.cc +++ b/test/ares-test-parse-naptr.cc @@ -50,7 +50,7 @@ TEST_F(LibraryTest, ParseCNaptrReplyOK) { 11, 21, "SP", "service2", "regexp2", "replace2")); std::vector data = pkt.data(); - struct cares_naptr_reply* naptr = nullptr; + cares_naptr_reply* naptr = nullptr; EXPECT_EQ(ARES_SUCCESS, cares_parse_naptr_reply(data.data(), data.size(), &naptr)); ASSERT_NE(nullptr, naptr); EXPECT_EQ("SP", std::string((char*)cares_naptr_reply_get_flags(naptr))); @@ -61,7 +61,7 @@ TEST_F(LibraryTest, ParseCNaptrReplyOK) { EXPECT_EQ(20, cares_naptr_reply_get_preference(naptr)); EXPECT_EQ(100, cares_naptr_reply_get_ttl(naptr)); - struct cares_naptr_reply* naptr2 = cares_naptr_reply_get_next(naptr); + cares_naptr_reply* naptr2 = cares_naptr_reply_get_next(naptr); ASSERT_NE(nullptr, naptr2); EXPECT_EQ("SP", std::string((char*)cares_naptr_reply_get_flags(naptr2))); EXPECT_EQ("service2", std::string((char*)cares_naptr_reply_get_service(naptr2))); @@ -139,7 +139,7 @@ TEST_F(LibraryTest, ParseCNaptrReplyErrors) { .add_answer(new DNSNaptrRR("example.com", 100, 10, 20, "SP", "service", "regexp", "replace")); std::vector data; - struct cares_naptr_reply* naptr = nullptr; + cares_naptr_reply* naptr = nullptr; // No question. pkt.questions_.clear(); @@ -243,7 +243,7 @@ TEST_F(LibraryTest, ParseCNaptrReplyTooShort) { 0x00, 0x01, // rdata length 0x00, // Too short: expect 2 x int16 and 3 x name (min 1 byte each) }; - struct cares_naptr_reply* naptr = nullptr; + cares_naptr_reply* naptr = nullptr; EXPECT_EQ(ARES_EBADRESP, cares_parse_naptr_reply(data.data(), data.size(), &naptr)); } @@ -274,7 +274,7 @@ TEST_F(LibraryTest, ParseCNaptrReplyAllocFail) { .add_answer(new DNSNaptrRR("example.com", 0x0010, 11, 21, "SP", "service2", "regexp2", "replace2")); std::vector data = pkt.data(); - struct cares_naptr_reply* naptr = nullptr; + cares_naptr_reply* naptr = nullptr; for (int ii = 1; ii <= 13; ii++) { ClearFails(); diff --git a/test/ares-test-parse-ptr.cc b/test/ares-test-parse-ptr.cc index fa1b24f4fc..afdcc5f3d5 100644 --- a/test/ares-test-parse-ptr.cc +++ b/test/ares-test-parse-ptr.cc @@ -32,7 +32,7 @@ TEST_F(LibraryTest, ParseCPtrReplyOK) { .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other.com")); std::vector data = pkt.data(); - struct cares_ptr_reply *ptr = nullptr; + cares_ptr_reply *ptr = nullptr; EXPECT_EQ(ARES_SUCCESS, cares_parse_ptr_reply(data.data(), data.size(), &ptr)); ASSERT_NE(nullptr, ptr); @@ -68,7 +68,7 @@ TEST_F(LibraryTest, ParseCPtrReplyCname) { .add_answer(new DNSPtrRR("64.48.32.8.in-addr.arpa", 100, "other.com")); std::vector data = pkt.data(); - struct cares_ptr_reply *ptr = nullptr; + cares_ptr_reply *ptr = nullptr; EXPECT_EQ(ARES_SUCCESS, cares_parse_ptr_reply(data.data(), data.size(), &ptr)); ASSERT_NE(nullptr, ptr); @@ -115,7 +115,7 @@ TEST_F(LibraryTest, ParseCPtrReplyMalformedCname) { .add_answer(new DNSPtrRR("64.48.32.8.in-addr.arpa", 100, "other.com")); std::vector data = pkt.data(); - struct cares_ptr_reply *ptr = nullptr; + cares_ptr_reply *ptr = nullptr; EXPECT_EQ(ARES_EBADRESP, cares_parse_ptr_reply(data.data(), data.size(), &ptr)); ASSERT_EQ(nullptr, ptr); } @@ -160,7 +160,7 @@ TEST_F(LibraryTest, ParseManyCPtrReply) { .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other9.com")); std::vector data = pkt.data(); - struct cares_ptr_reply *ptr = nullptr; + cares_ptr_reply *ptr = nullptr; EXPECT_EQ(ARES_SUCCESS, cares_parse_ptr_reply(data.data(), data.size(), &ptr)); ASSERT_NE(nullptr, ptr); ares_free_data(ptr); @@ -203,7 +203,7 @@ TEST_F(LibraryTest, ParseCPtrReplyAdditional) { .add_additional(new DNSARR("ns3.other.com", 229, {10,20,30,43})); std::vector data = pkt.data(); - struct cares_ptr_reply *ptr = nullptr; + cares_ptr_reply *ptr = nullptr; EXPECT_EQ(ARES_SUCCESS, cares_parse_ptr_reply(data.data(), data.size(), &ptr)); ASSERT_NE(nullptr, ptr); EXPECT_EQ("other.com", std::string(cares_ptr_reply_get_host(ptr))); @@ -288,7 +288,7 @@ TEST_F(LibraryTest, ParseCPtrReplyErrors) { .add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR)) .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other.com")); std::vector data; - struct cares_ptr_reply *ptr = nullptr; + cares_ptr_reply *ptr = nullptr; // No question. pkt.questions_.clear(); @@ -374,7 +374,7 @@ TEST_F(LibraryTest, ParseCPtrReplyAllocFailSome) { .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other2.com")) .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other3.com")); std::vector data = pkt.data(); - struct cares_ptr_reply *ptr = nullptr; + cares_ptr_reply *ptr = nullptr; for (int ii = 1; ii <= 13; ii++) { ClearFails(); @@ -429,7 +429,7 @@ TEST_F(LibraryTest, ParseCPtrReplyAllocFailMany) { .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other8.com")) .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other9.com")); std::vector data = pkt.data(); - struct cares_ptr_reply *ptr = nullptr; + cares_ptr_reply *ptr = nullptr; for (int ii = 1; ii <= 63; ii++) { ClearFails(); diff --git a/test/ares-test-parse-soa-any.cc b/test/ares-test-parse-soa-any.cc index a47caf9151..14b5f569a5 100644 --- a/test/ares-test-parse-soa-any.cc +++ b/test/ares-test-parse-soa-any.cc @@ -44,7 +44,7 @@ TEST_F(LibraryTest, ParseCSoaAnyReplyOK) { 1, 2, 3, 4, 5)); std::vector data = pkt.data(); - struct cares_soa_reply* soa = nullptr; + cares_soa_reply* soa = nullptr; EXPECT_EQ(ARES_SUCCESS, cares_parse_soa_reply(data.data(), data.size(), &soa)); ASSERT_NE(nullptr, soa); EXPECT_EQ("soa1.example.com", std::string(cares_soa_reply_get_nsname(soa))); @@ -124,7 +124,7 @@ TEST_F(LibraryTest, ParseCSoaAnyReplyErrors) { "soa1.example.com", "fred.example.com", 1, 2, 3, 4, 5)); std::vector data; - struct cares_soa_reply* soa = nullptr; + cares_soa_reply* soa = nullptr; // No question. pkt.questions_.clear(); @@ -199,7 +199,7 @@ TEST_F(LibraryTest, ParseCSoaAnyReplyAllocFail) { "soa1.example.com", "fred.example.com", 1, 2, 3, 4, 5)); std::vector data = pkt.data(); - struct cares_soa_reply* soa = nullptr; + cares_soa_reply* soa = nullptr; for (int ii = 1; ii <= 5; ii++) { ClearFails(); diff --git a/test/ares-test-parse-soa.cc b/test/ares-test-parse-soa.cc index b6f2184343..00a947bf52 100644 --- a/test/ares-test-parse-soa.cc +++ b/test/ares-test-parse-soa.cc @@ -38,7 +38,7 @@ TEST_F(LibraryTest, ParseCSoaReplyOK) { 1, 2, 3, 4, 5)); std::vector data = pkt.data(); - struct cares_soa_reply* soa = nullptr; + cares_soa_reply* soa = nullptr; EXPECT_EQ(ARES_SUCCESS, cares_parse_soa_reply(data.data(), data.size(), &soa)); ASSERT_NE(nullptr, soa); EXPECT_EQ("soa1.example.com", std::string(cares_soa_reply_get_nsname(soa))); @@ -118,7 +118,7 @@ TEST_F(LibraryTest, ParseCSoaReplyErrors) { "soa1.example.com", "fred.example.com", 1, 2, 3, 4, 5)); std::vector data; - struct cares_soa_reply* soa = nullptr; + cares_soa_reply* soa = nullptr; // No question. pkt.questions_.clear(); @@ -193,7 +193,7 @@ TEST_F(LibraryTest, ParseCSoaReplyAllocFail) { "soa1.example.com", "fred.example.com", 1, 2, 3, 4, 5)); std::vector data = pkt.data(); - struct cares_soa_reply* soa = nullptr; + cares_soa_reply* soa = nullptr; for (int ii = 1; ii <= 5; ii++) { ClearFails(); diff --git a/test/ares-test-parse-srv.cc b/test/ares-test-parse-srv.cc index 4673c67151..0327635a2a 100644 --- a/test/ares-test-parse-srv.cc +++ b/test/ares-test-parse-srv.cc @@ -43,7 +43,7 @@ TEST_F(LibraryTest, ParseCSrvReplyOK) { .add_answer(new DNSSrvRR("example.com", 100, 11, 21, 31, "srv2.example.com")); std::vector data = pkt.data(); - struct cares_srv_reply* srv = nullptr; + cares_srv_reply* srv = nullptr; EXPECT_EQ(ARES_SUCCESS, cares_parse_srv_reply(data.data(), data.size(), &srv)); ASSERT_NE(nullptr, srv); @@ -53,7 +53,7 @@ TEST_F(LibraryTest, ParseCSrvReplyOK) { EXPECT_EQ(30, cares_srv_reply_get_port(srv)); EXPECT_EQ(100, cares_srv_reply_get_ttl(srv)); - struct cares_srv_reply* srv2 = cares_srv_reply_get_next(srv); + cares_srv_reply* srv2 = cares_srv_reply_get_next(srv); ASSERT_NE(nullptr, srv2); EXPECT_EQ("srv2.example.com", std::string(cares_srv_reply_get_host(srv2))); EXPECT_EQ(11, cares_srv_reply_get_priority(srv2)); @@ -105,7 +105,7 @@ TEST_F(LibraryTest, ParseCSrvReplySingle) { .add_additional(new DNSARR("else5.where.com", 42, {172,19,0,2})); std::vector data = pkt.data(); - struct cares_srv_reply* srv = nullptr; + cares_srv_reply* srv = nullptr; EXPECT_EQ(ARES_SUCCESS, cares_parse_srv_reply(data.data(), data.size(), &srv)); ASSERT_NE(nullptr, srv); @@ -176,7 +176,7 @@ TEST_F(LibraryTest, ParseCSrvReplyMalformed) { 0x02, 0x03, 0x04, 0x05, }; - struct cares_srv_reply* srv = nullptr; + cares_srv_reply* srv = nullptr; EXPECT_EQ(ARES_EBADRESP, cares_parse_srv_reply(data.data(), data.size(), &srv)); ASSERT_EQ(nullptr, srv); } @@ -245,10 +245,10 @@ TEST_F(LibraryTest, ParseCSrvReplyMultiple) { .add_additional(new DNSARR("n3.example.com", 300, {172,19,0,3})); std::vector data = pkt.data(); - struct cares_srv_reply* srv0 = nullptr; + cares_srv_reply* srv0 = nullptr; EXPECT_EQ(ARES_SUCCESS, cares_parse_srv_reply(data.data(), data.size(), &srv0)); ASSERT_NE(nullptr, srv0); - struct cares_srv_reply* srv = srv0; + cares_srv_reply* srv = srv0; EXPECT_EQ("a1.srv.example.com", std::string(cares_srv_reply_get_host(srv))); EXPECT_EQ(0, cares_srv_reply_get_priority(srv)); @@ -319,7 +319,7 @@ TEST_F(LibraryTest, ParseCSrvReplyCname) { .add_additional(new DNSARR("else3.where.com", 42, {172,19,0,3})); std::vector data = pkt.data(); - struct cares_srv_reply* srv = nullptr; + cares_srv_reply* srv = nullptr; EXPECT_EQ(ARES_SUCCESS, cares_parse_srv_reply(data.data(), data.size(), &srv)); ASSERT_NE(nullptr, srv); @@ -399,10 +399,10 @@ TEST_F(LibraryTest, ParseCSrvReplyCnameMultiple) { .add_additional(new DNSARR("n3.example.com", 300, {172,19,0,3})); std::vector data = pkt.data(); - struct cares_srv_reply* srv0 = nullptr; + cares_srv_reply* srv0 = nullptr; EXPECT_EQ(ARES_SUCCESS, cares_parse_srv_reply(data.data(), data.size(), &srv0)); ASSERT_NE(nullptr, srv0); - struct cares_srv_reply* srv = srv0; + cares_srv_reply* srv = srv0; EXPECT_EQ("a1.srv.example.com", std::string(cares_srv_reply_get_host(srv))); EXPECT_EQ(0, cares_srv_reply_get_priority(srv)); @@ -485,7 +485,7 @@ TEST_F(LibraryTest, ParseCSrvReplyErrors) { .add_question(new DNSQuestion("example.abc.def.com", T_SRV)) .add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")); std::vector data; - struct cares_srv_reply* srv = nullptr; + cares_srv_reply* srv = nullptr; // No question. pkt.questions_.clear(); @@ -556,7 +556,7 @@ TEST_F(LibraryTest, ParseCSrvReplyAllocFail) { .add_answer(new DNSCnameRR("example.com", 300, "c.example.com")) .add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")); std::vector data = pkt.data(); - struct cares_srv_reply* srv = nullptr; + cares_srv_reply* srv = nullptr; for (int ii = 1; ii <= 5; ii++) { ClearFails(); diff --git a/test/ares-test-parse-txt.cc b/test/ares-test-parse-txt.cc index 158dfe12e1..1b1e05d125 100644 --- a/test/ares-test-parse-txt.cc +++ b/test/ares-test-parse-txt.cc @@ -83,7 +83,7 @@ TEST_F(LibraryTest, ParseCTxtReplyOK) { .add_answer(new DNSTxtRR("example.com", 100, {expected2a, expected2b})); std::vector data = pkt.data(); - struct cares_txt_reply* txt = nullptr; + cares_txt_reply* txt = nullptr; EXPECT_EQ(ARES_SUCCESS, cares_parse_txt_reply(data.data(), data.size(), &txt)); ASSERT_NE(nullptr, txt); EXPECT_EQ(std::vector(expected1.data(), expected1.data() + expected1.size()), @@ -91,14 +91,14 @@ TEST_F(LibraryTest, ParseCTxtReplyOK) { cares_txt_reply_get_txt(txt) + cares_txt_reply_get_length(txt))); EXPECT_EQ(100, cares_txt_reply_get_ttl(txt)); - struct cares_txt_reply* txt2 = cares_txt_reply_get_next(txt); + cares_txt_reply* txt2 = cares_txt_reply_get_next(txt); ASSERT_NE(nullptr, txt2); EXPECT_EQ(std::vector(expected2a.data(), expected2a.data() + expected2a.size()), std::vector(cares_txt_reply_get_txt(txt2), cares_txt_reply_get_txt(txt2) + cares_txt_reply_get_length(txt2))); EXPECT_EQ(100, cares_txt_reply_get_ttl(txt2)); - struct cares_txt_reply* txt3 = cares_txt_reply_get_next(txt2); + cares_txt_reply* txt3 = cares_txt_reply_get_next(txt2); ASSERT_NE(nullptr, txt3); EXPECT_EQ(std::vector(expected2b.data(), expected2b.data() + expected2b.size()), std::vector(cares_txt_reply_get_txt(txt3), @@ -166,7 +166,7 @@ TEST_F(LibraryTest, ParseCTxtMalformedReply1) { 0x12, 'a', 'b', // invalid length }; - struct cares_txt_reply* txt = nullptr; + cares_txt_reply* txt = nullptr; EXPECT_EQ(ARES_EBADRESP, cares_parse_txt_reply(data.data(), data.size(), &txt)); ASSERT_EQ(nullptr, txt); } @@ -222,7 +222,7 @@ TEST_F(LibraryTest, ParseCTxtMalformedReply2) { // truncated }; - struct cares_txt_reply* txt = nullptr; + cares_txt_reply* txt = nullptr; EXPECT_EQ(ARES_EBADRESP, cares_parse_txt_reply(data.data(), data.size(), &txt)); ASSERT_EQ(nullptr, txt); } @@ -284,7 +284,7 @@ TEST_F(LibraryTest, ParseCTxtMalformedReply3) { 0x02, 'a', 'b', }; - struct cares_txt_reply* txt = nullptr; + cares_txt_reply* txt = nullptr; EXPECT_EQ(ARES_EBADRESP, cares_parse_txt_reply(data.data(), data.size(), &txt)); ASSERT_EQ(nullptr, txt); } @@ -328,7 +328,7 @@ TEST_F(LibraryTest, ParseCTxtMalformedReply4) { 0x00, // TRUNCATED }; - struct cares_txt_reply* txt = nullptr; + cares_txt_reply* txt = nullptr; EXPECT_EQ(ARES_EBADRESP, cares_parse_txt_reply(data.data(), data.size(), &txt)); ASSERT_EQ(nullptr, txt); } @@ -400,7 +400,7 @@ TEST_F(LibraryTest, ParseCTxtReplyErrors) { .add_answer(new DNSTxtRR("example.com", 100, {expected1})) .add_answer(new DNSTxtRR("example.com", 100, {expected2a, expected2b})); std::vector data = pkt.data(); - struct cares_txt_reply* txt = nullptr; + cares_txt_reply* txt = nullptr; // No question. pkt.questions_.clear(); @@ -478,7 +478,7 @@ TEST_F(LibraryTest, ParseCTxtReplyAllocFail) { .add_answer(new DNSTxtRR("c.example.com", 100, {expected1})) .add_answer(new DNSTxtRR("c.example.com", 100, {expected2a, expected2b})); std::vector data = pkt.data(); - struct cares_txt_reply* txt = nullptr; + cares_txt_reply* txt = nullptr; for (int ii = 1; ii <= 13; ii++) { ClearFails(); From 7fcb191f4bc7310a36608ed5b032734e26636575 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Sun, 7 Nov 2021 00:54:40 -0400 Subject: [PATCH 17/49] change ttl in ares_uri_reply to be unsigned int --- include/ares.h | 2 +- src/lib/ares_parse_uri_reply.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/ares.h b/include/ares.h index f98471cdd3..9d2942e77e 100644 --- a/include/ares.h +++ b/include/ares.h @@ -629,7 +629,7 @@ struct ares_uri_reply { unsigned short priority; unsigned short weight; char *uri; - int ttl; + unsigned int ttl; }; /* diff --git a/src/lib/ares_parse_uri_reply.c b/src/lib/ares_parse_uri_reply.c index d79b5c4d85..199f500cd2 100644 --- a/src/lib/ares_parse_uri_reply.c +++ b/src/lib/ares_parse_uri_reply.c @@ -45,7 +45,8 @@ ares_parse_uri_reply (const unsigned char *abuf, int alen, { unsigned int qdcount, ancount, i; const unsigned char *aptr, *vptr; - int status, rr_type, rr_class, rr_len, rr_ttl; + int status, rr_type, rr_class, rr_len; + unsigned int rr_ttl; long len; char *uri_str = NULL, *rr_name = NULL; struct ares_uri_reply *uri_head = NULL; From 487d072874e1c994a1e77ca5bd923287f11b9496 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Sun, 7 Nov 2021 09:34:16 -0500 Subject: [PATCH 18/49] change ARES_DATATYPE_C prefix to CARES_DATATYPE_ prefix --- src/lib/ares_data.c | 32 +++++++++++++++---------------- src/lib/ares_data.h | 16 ++++++++-------- src/lib/cares_parse_caa_reply.c | 2 +- src/lib/cares_parse_mx_reply.c | 2 +- src/lib/cares_parse_naptr_reply.c | 2 +- src/lib/cares_parse_ns_reply.c | 2 +- src/lib/cares_parse_ptr_reply.c | 2 +- src/lib/cares_parse_soa_reply.c | 2 +- src/lib/cares_parse_srv_reply.c | 2 +- src/lib/cares_parse_txt_reply.c | 2 +- 10 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/lib/ares_data.c b/src/lib/ares_data.c index 5b64410eb8..74cc7ee492 100644 --- a/src/lib/ares_data.c +++ b/src/lib/ares_data.c @@ -63,7 +63,7 @@ void ares_free_data(void *dataptr) switch (ptr->type) { case ARES_DATATYPE_MX_REPLY: - case ARES_DATATYPE_CMX_REPLY: + case CARES_DATATYPE_MX_REPLY: if (ptr->data.mx_reply.next) next_data = ptr->data.mx_reply.next; @@ -72,7 +72,7 @@ void ares_free_data(void *dataptr) break; case ARES_DATATYPE_SRV_REPLY: - case ARES_DATATYPE_CSRV_REPLY: + case CARES_DATATYPE_SRV_REPLY: if (ptr->data.srv_reply.next) next_data = ptr->data.srv_reply.next; @@ -90,7 +90,7 @@ void ares_free_data(void *dataptr) case ARES_DATATYPE_TXT_REPLY: case ARES_DATATYPE_TXT_EXT: - case ARES_DATATYPE_CTXT_REPLY: + case CARES_DATATYPE_TXT_REPLY: if (ptr->data.txt_reply.next) next_data = ptr->data.txt_reply.next; @@ -111,7 +111,7 @@ void ares_free_data(void *dataptr) break; case ARES_DATATYPE_NAPTR_REPLY: - case ARES_DATATYPE_CNAPTR_REPLY: + case CARES_DATATYPE_NAPTR_REPLY: if (ptr->data.naptr_reply.next) next_data = ptr->data.naptr_reply.next; @@ -126,7 +126,7 @@ void ares_free_data(void *dataptr) break; case ARES_DATATYPE_SOA_REPLY: - case ARES_DATATYPE_CSOA_REPLY: + case CARES_DATATYPE_SOA_REPLY: if (ptr->data.soa_reply.nsname) ares_free(ptr->data.soa_reply.nsname); if (ptr->data.soa_reply.hostmaster) @@ -134,7 +134,7 @@ void ares_free_data(void *dataptr) break; case ARES_DATATYPE_CAA_REPLY: - case ARES_DATATYPE_CCAA_REPLY: + case CARES_DATATYPE_CAA_REPLY: if (ptr->data.caa_reply.next) next_data = ptr->data.caa_reply.next; if (ptr->data.caa_reply.property) @@ -143,7 +143,7 @@ void ares_free_data(void *dataptr) ares_free(ptr->data.caa_reply.value); break; - case ARES_DATATYPE_CPTR_REPLY: + case CARES_DATATYPE_PTR_REPLY: if (ptr->data.cptr_reply.next) next_data = ptr->data.cptr_reply.next; @@ -151,7 +151,7 @@ void ares_free_data(void *dataptr) ares_free(ptr->data.cptr_reply.host); break; - case ARES_DATATYPE_CNS_REPLY: + case CARES_DATATYPE_NS_REPLY: if (ptr->data.cns_reply.next) next_data = ptr->data.cns_reply.next; @@ -191,7 +191,7 @@ void *ares_malloc_data(ares_datatype type) switch (type) { - case ARES_DATATYPE_CMX_REPLY: + case CARES_DATATYPE_MX_REPLY: ptr->data.cmx_reply.ttl = 0; /* FALLTHROUGH */ @@ -201,7 +201,7 @@ void *ares_malloc_data(ares_datatype type) ptr->data.mx_reply.priority = 0; break; - case ARES_DATATYPE_CSRV_REPLY: + case CARES_DATATYPE_SRV_REPLY: ptr->data.csrv_reply.ttl = 0; /* FALLTHROUGH */ @@ -221,7 +221,7 @@ void *ares_malloc_data(ares_datatype type) ptr->data.uri_reply.ttl = 0; break; - case ARES_DATATYPE_CTXT_REPLY: + case CARES_DATATYPE_TXT_REPLY: ptr->data.ctxt_reply.ttl = 0; /* FALLTHROUGH */ @@ -235,7 +235,7 @@ void *ares_malloc_data(ares_datatype type) ptr->data.txt_reply.length = 0; break; - case ARES_DATATYPE_CCAA_REPLY: + case CARES_DATATYPE_CAA_REPLY: ptr->data.ccaa_reply.ttl = 0; /* FALLTHROUGH */ @@ -263,7 +263,7 @@ void *ares_malloc_data(ares_datatype type) sizeof(ptr->data.addr_port_node.addrV6)); break; - case ARES_DATATYPE_CNAPTR_REPLY: + case CARES_DATATYPE_NAPTR_REPLY: ptr->data.cnaptr_reply.ttl = 0; /* FALLTHROUGH */ @@ -277,7 +277,7 @@ void *ares_malloc_data(ares_datatype type) ptr->data.naptr_reply.preference = 0; break; - case ARES_DATATYPE_CSOA_REPLY: + case CARES_DATATYPE_SOA_REPLY: ptr->data.csoa_reply.ttl = 0; /* FALLTHROUGH */ @@ -291,13 +291,13 @@ void *ares_malloc_data(ares_datatype type) ptr->data.soa_reply.minttl = 0; break; - case ARES_DATATYPE_CPTR_REPLY: + case CARES_DATATYPE_PTR_REPLY: ptr->data.cptr_reply.next = NULL; ptr->data.cptr_reply.host = NULL; ptr->data.cptr_reply.ttl = 0; break; - case ARES_DATATYPE_CNS_REPLY: + case CARES_DATATYPE_NS_REPLY: ptr->data.cns_reply.next = NULL; ptr->data.cns_reply.host = NULL; ptr->data.cns_reply.ttl = 0; diff --git a/src/lib/ares_data.h b/src/lib/ares_data.h index c708baa738..ba225e5ed9 100644 --- a/src/lib/ares_data.h +++ b/src/lib/ares_data.h @@ -18,17 +18,17 @@ typedef enum { ARES_DATATYPE_UNKNOWN = 1, /* unknown data type - introduced in 1.7.0 */ ARES_DATATYPE_SRV_REPLY, /* struct ares_srv_reply - introduced in 1.7.0 */ - ARES_DATATYPE_CSRV_REPLY, /* struct cares_srv_reply */ + CARES_DATATYPE_SRV_REPLY, /* struct cares_srv_reply */ ARES_DATATYPE_TXT_REPLY, /* struct ares_txt_reply - introduced in 1.7.0 */ ARES_DATATYPE_TXT_EXT, /* struct ares_txt_ext - introduced in 1.11.0 */ - ARES_DATATYPE_CTXT_REPLY, + CARES_DATATYPE_TXT_REPLY, ARES_DATATYPE_ADDR_NODE, /* struct ares_addr_node - introduced in 1.7.1 */ ARES_DATATYPE_MX_REPLY, /* struct ares_mx_reply - introduced in 1.7.2 */ - ARES_DATATYPE_CMX_REPLY, + CARES_DATATYPE_MX_REPLY, ARES_DATATYPE_NAPTR_REPLY,/* struct ares_naptr_reply - introduced in 1.7.6 */ - ARES_DATATYPE_CNAPTR_REPLY, + CARES_DATATYPE_NAPTR_REPLY, ARES_DATATYPE_SOA_REPLY, /* struct ares_soa_reply - introduced in 1.9.0 */ - ARES_DATATYPE_CSOA_REPLY, + CARES_DATATYPE_SOA_REPLY, ARES_DATATYPE_URI_REPLY, /* struct ares_uri_reply */ #if 0 ARES_DATATYPE_ADDR6TTL, /* struct ares_addrttl */ @@ -38,9 +38,9 @@ typedef enum { #endif ARES_DATATYPE_ADDR_PORT_NODE, /* struct ares_addr_port_node - introduced in 1.11.0 */ ARES_DATATYPE_CAA_REPLY, /* struct ares_caa_reply - introduced in 1.17 */ - ARES_DATATYPE_CCAA_REPLY, - ARES_DATATYPE_CPTR_REPLY, - ARES_DATATYPE_CNS_REPLY, + CARES_DATATYPE_CAA_REPLY, + CARES_DATATYPE_PTR_REPLY, + CARES_DATATYPE_NS_REPLY, ARES_DATATYPE_LAST /* not used - introduced in 1.7.0 */ } ares_datatype; diff --git a/src/lib/cares_parse_caa_reply.c b/src/lib/cares_parse_caa_reply.c index 1f26f05ce3..3b24fd5872 100644 --- a/src/lib/cares_parse_caa_reply.c +++ b/src/lib/cares_parse_caa_reply.c @@ -114,7 +114,7 @@ cares_parse_caa_reply (const unsigned char *abuf, int alen, strptr = aptr; /* Allocate storage for this CAA answer appending it to the list */ - caa_curr = ares_malloc_data(ARES_DATATYPE_CCAA_REPLY); + caa_curr = ares_malloc_data(CARES_DATATYPE_CAA_REPLY); if (!caa_curr) { status = ARES_ENOMEM; diff --git a/src/lib/cares_parse_mx_reply.c b/src/lib/cares_parse_mx_reply.c index f6bf9425fc..640e44e0cc 100644 --- a/src/lib/cares_parse_mx_reply.c +++ b/src/lib/cares_parse_mx_reply.c @@ -115,7 +115,7 @@ cares_parse_mx_reply (const unsigned char *abuf, int alen, } /* Allocate storage for this MX answer appending it to the list */ - mx_curr = ares_malloc_data(ARES_DATATYPE_CMX_REPLY); + mx_curr = ares_malloc_data(CARES_DATATYPE_MX_REPLY); if (!mx_curr) { status = ARES_ENOMEM; diff --git a/src/lib/cares_parse_naptr_reply.c b/src/lib/cares_parse_naptr_reply.c index 735bc2a3dc..ff3f301ffa 100644 --- a/src/lib/cares_parse_naptr_reply.c +++ b/src/lib/cares_parse_naptr_reply.c @@ -119,7 +119,7 @@ cares_parse_naptr_reply (const unsigned char *abuf, int alen, } /* Allocate storage for this NAPTR answer appending it to the list */ - naptr_curr = ares_malloc_data(ARES_DATATYPE_CNAPTR_REPLY); + naptr_curr = ares_malloc_data(CARES_DATATYPE_NAPTR_REPLY); if (!naptr_curr) { status = ARES_ENOMEM; diff --git a/src/lib/cares_parse_ns_reply.c b/src/lib/cares_parse_ns_reply.c index ad7fc0cd81..87280fdbe6 100644 --- a/src/lib/cares_parse_ns_reply.c +++ b/src/lib/cares_parse_ns_reply.c @@ -103,7 +103,7 @@ int cares_parse_ns_reply(const unsigned char *abuf, int alen, if (rr_class == C_IN && rr_type == T_NS) { /* Allocate storage for this NS answer appending it to the list */ - ns_curr = ares_malloc_data(ARES_DATATYPE_CNS_REPLY); + ns_curr = ares_malloc_data(CARES_DATATYPE_NS_REPLY); if (!ns_curr) { status = ARES_ENOMEM; diff --git a/src/lib/cares_parse_ptr_reply.c b/src/lib/cares_parse_ptr_reply.c index a52fd0222c..2a05338e61 100644 --- a/src/lib/cares_parse_ptr_reply.c +++ b/src/lib/cares_parse_ptr_reply.c @@ -109,7 +109,7 @@ int cares_parse_ptr_reply(const unsigned char *abuf, int alen, break; } /* Allocate storage for this PTR answer appending it to the list */ - ptr_curr = ares_malloc_data(ARES_DATATYPE_CPTR_REPLY); + ptr_curr = ares_malloc_data(CARES_DATATYPE_PTR_REPLY); if (!ptr_curr) { status = ARES_ENOMEM; diff --git a/src/lib/cares_parse_soa_reply.c b/src/lib/cares_parse_soa_reply.c index 87e5aab0e1..d38becfca2 100644 --- a/src/lib/cares_parse_soa_reply.c +++ b/src/lib/cares_parse_soa_reply.c @@ -120,7 +120,7 @@ cares_parse_soa_reply(const unsigned char *abuf, int alen, if ( rr_class == C_IN && rr_type == T_SOA ) { /* allocate result struct */ - soa = ares_malloc_data(ARES_DATATYPE_CSOA_REPLY); + soa = ares_malloc_data(CARES_DATATYPE_SOA_REPLY); if (!soa) { status = ARES_ENOMEM; diff --git a/src/lib/cares_parse_srv_reply.c b/src/lib/cares_parse_srv_reply.c index e0b70afe0b..d4f61a00df 100644 --- a/src/lib/cares_parse_srv_reply.c +++ b/src/lib/cares_parse_srv_reply.c @@ -114,7 +114,7 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, } /* Allocate storage for this SRV answer appending it to the list */ - srv_curr = ares_malloc_data(ARES_DATATYPE_CSRV_REPLY); + srv_curr = ares_malloc_data(CARES_DATATYPE_SRV_REPLY); if (!srv_curr) { status = ARES_ENOMEM; diff --git a/src/lib/cares_parse_txt_reply.c b/src/lib/cares_parse_txt_reply.c index 36166ace4a..8dabb8567f 100644 --- a/src/lib/cares_parse_txt_reply.c +++ b/src/lib/cares_parse_txt_reply.c @@ -130,7 +130,7 @@ int cares_parse_txt_reply (const unsigned char *abuf, int alen, } /* Allocate storage for this TXT answer appending it to the list */ - txt_curr = ares_malloc_data(ARES_DATATYPE_CTXT_REPLY); + txt_curr = ares_malloc_data(CARES_DATATYPE_TXT_REPLY); if (!txt_curr) { status = ARES_ENOMEM; From 97143ccf78e9565a1cc8ac655351caad0022b4f9 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Thu, 11 Nov 2021 19:16:28 -0500 Subject: [PATCH 19/49] return const from cares_get_next functions --- include/ares.h | 14 +++++++------- src/lib/ares_parse_caa_reply.c | 2 +- src/lib/ares_parse_mx_reply.c | 2 +- src/lib/ares_parse_naptr_reply.c | 2 +- src/lib/ares_parse_ns_reply.c | 2 +- src/lib/ares_parse_ptr_reply.c | 2 +- src/lib/ares_parse_srv_reply.c | 2 +- src/lib/ares_parse_txt_reply.c | 2 +- src/lib/cares_reply.c | 14 +++++++------- test/ares-test-parse-mx.cc | 2 +- test/ares-test-parse-naptr.cc | 2 +- test/ares-test-parse-ns.cc | 2 +- test/ares-test-parse-srv.cc | 6 +++--- test/ares-test-parse-txt.cc | 4 ++-- 14 files changed, 29 insertions(+), 29 deletions(-) diff --git a/include/ares.h b/include/ares.h index 9d2942e77e..f8cb3d15fc 100644 --- a/include/ares.h +++ b/include/ares.h @@ -699,7 +699,7 @@ CARES_EXTERN int cares_parse_caa_reply(const unsigned char* abuf, int alen, struct cares_caa_reply** caa_out); -CARES_EXTERN struct cares_caa_reply* +CARES_EXTERN const cares_caa_reply* cares_caa_reply_get_next(const cares_caa_reply* caa_reply); CARES_EXTERN int @@ -731,7 +731,7 @@ CARES_EXTERN int cares_parse_ptr_reply(const unsigned char *abuf, int alen, struct cares_ptr_reply **ptr_out); -CARES_EXTERN struct cares_ptr_reply* +CARES_EXTERN const cares_ptr_reply* cares_ptr_reply_get_next(const cares_ptr_reply* ptr_reply); CARES_EXTERN const char* @@ -748,7 +748,7 @@ CARES_EXTERN int cares_parse_ns_reply(const unsigned char *abuf, int alen, struct cares_ns_reply **ns_out); -CARES_EXTERN struct cares_ns_reply* +CARES_EXTERN const cares_ns_reply* cares_ns_reply_get_next(const cares_ns_reply* ns_reply); CARES_EXTERN const char* @@ -765,7 +765,7 @@ CARES_EXTERN int cares_parse_srv_reply(const unsigned char* abuf, int alen, struct cares_srv_reply** srv_out); -CARES_EXTERN cares_srv_reply* +CARES_EXTERN const cares_srv_reply* cares_srv_reply_get_next(const cares_srv_reply* srv_reply); CARES_EXTERN const char* @@ -791,7 +791,7 @@ CARES_EXTERN int cares_parse_mx_reply(const unsigned char* abuf, int alen, struct cares_mx_reply** mx_out); -CARES_EXTERN struct cares_mx_reply* +CARES_EXTERN const cares_mx_reply* cares_mx_reply_get_next(const cares_mx_reply* mx_reply); CARES_EXTERN const char* @@ -815,7 +815,7 @@ CARES_EXTERN int cares_parse_txt_reply(const unsigned char* abuf, int alen, struct cares_txt_reply** txt_out); -CARES_EXTERN struct cares_txt_reply* +CARES_EXTERN const cares_txt_reply* cares_txt_reply_get_next(const cares_txt_reply* txt_reply); CARES_EXTERN const unsigned char* @@ -838,7 +838,7 @@ CARES_EXTERN int cares_parse_naptr_reply(const unsigned char* abuf, int alen, struct cares_naptr_reply** naptr_out); -CARES_EXTERN struct cares_naptr_reply* +CARES_EXTERN const cares_naptr_reply* cares_naptr_reply_get_next(const cares_naptr_reply* naptr_reply); CARES_EXTERN const unsigned char* diff --git a/src/lib/ares_parse_caa_reply.c b/src/lib/ares_parse_caa_reply.c index 27c178a906..73b6595085 100644 --- a/src/lib/ares_parse_caa_reply.c +++ b/src/lib/ares_parse_caa_reply.c @@ -46,7 +46,7 @@ ares_parse_caa_reply (const unsigned char *abuf, int alen, struct ares_caa_reply *caa_head = NULL; struct ares_caa_reply *caa_last = NULL; struct ares_caa_reply *caa_curr; - cares_caa_reply *ccaa_curr = NULL; + const cares_caa_reply *ccaa_curr = NULL; cares_caa_reply *ccaa_out = NULL; /* Set *caa_out to NULL for all failure cases. */ diff --git a/src/lib/ares_parse_mx_reply.c b/src/lib/ares_parse_mx_reply.c index acbbd0fcc1..0c088f2469 100644 --- a/src/lib/ares_parse_mx_reply.c +++ b/src/lib/ares_parse_mx_reply.c @@ -47,7 +47,7 @@ ares_parse_mx_reply (const unsigned char *abuf, int alen, struct ares_mx_reply *mx_head = NULL; struct ares_mx_reply *mx_curr = NULL; struct ares_mx_reply *mx_last = NULL; - cares_mx_reply *cmx_curr = NULL; + const cares_mx_reply *cmx_curr = NULL; cares_mx_reply *cmx_out = NULL; /* Set *mx_out to NULL for all failure cases. */ diff --git a/src/lib/ares_parse_naptr_reply.c b/src/lib/ares_parse_naptr_reply.c index 1ab55a7a7d..671996bcd7 100644 --- a/src/lib/ares_parse_naptr_reply.c +++ b/src/lib/ares_parse_naptr_reply.c @@ -47,7 +47,7 @@ ares_parse_naptr_reply (const unsigned char *abuf, int alen, struct ares_naptr_reply *naptr_head = NULL; struct ares_naptr_reply *naptr_last = NULL; struct ares_naptr_reply *naptr_curr; - cares_naptr_reply *cnaptr_curr = NULL; + const cares_naptr_reply *cnaptr_curr = NULL; cares_naptr_reply *cnaptr_out = NULL; /* Set *naptr_out to NULL for all failure cases. */ diff --git a/src/lib/ares_parse_ns_reply.c b/src/lib/ares_parse_ns_reply.c index 29a758b730..720487f8f1 100644 --- a/src/lib/ares_parse_ns_reply.c +++ b/src/lib/ares_parse_ns_reply.c @@ -84,7 +84,7 @@ int ares_parse_ns_reply( const unsigned char* abuf, int alen, /* iterate through the linked list of cares_ns_reply and build the h_aliases array. */ i = 0; - for (cares_ns_reply* ns_curr=ns_out; ns_curr; + for (const cares_ns_reply* ns_curr=ns_out; ns_curr; ns_curr = cares_ns_reply_get_next(ns_curr)) { if (alias_alloc > 2) diff --git a/src/lib/ares_parse_ptr_reply.c b/src/lib/ares_parse_ptr_reply.c index 486dff7ed8..5f1ed2f820 100644 --- a/src/lib/ares_parse_ptr_reply.c +++ b/src/lib/ares_parse_ptr_reply.c @@ -87,7 +87,7 @@ int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr, /* iterate through the linked list of cares_ptr_reply and build the h_aliases array. */ i = 0; - for (cares_ptr_reply* ptr_curr=ptr_out; ptr_curr; + for (const cares_ptr_reply* ptr_curr=ptr_out; ptr_curr; ptr_curr = cares_ptr_reply_get_next(ptr_curr)) { if (!cares_ptr_reply_get_next(ptr_curr)) diff --git a/src/lib/ares_parse_srv_reply.c b/src/lib/ares_parse_srv_reply.c index 335b90f151..d2934b6a4b 100644 --- a/src/lib/ares_parse_srv_reply.c +++ b/src/lib/ares_parse_srv_reply.c @@ -48,7 +48,7 @@ ares_parse_srv_reply (const unsigned char *abuf, int alen, struct ares_srv_reply *srv_head = NULL; struct ares_srv_reply *srv_curr = NULL; struct ares_srv_reply *srv_last = NULL; - cares_srv_reply *csrv_curr = NULL; + const cares_srv_reply *csrv_curr = NULL; cares_srv_reply *csrv_out = NULL; /* Set *srv_out to NULL for all failure cases. */ diff --git a/src/lib/ares_parse_txt_reply.c b/src/lib/ares_parse_txt_reply.c index 309522dcdb..8ce3daf9cc 100644 --- a/src/lib/ares_parse_txt_reply.c +++ b/src/lib/ares_parse_txt_reply.c @@ -50,7 +50,7 @@ ares__parse_txt_reply (const unsigned char *abuf, int alen, struct ares_txt_ext *txt_head = NULL; struct ares_txt_ext *txt_curr = NULL; struct ares_txt_ext *txt_last = NULL; - cares_txt_reply *ctxt_curr = NULL; + const cares_txt_reply *ctxt_curr = NULL; cares_txt_reply *ctxt_out = NULL; /* Set *txt_out to NULL for all failure cases. */ diff --git a/src/lib/cares_reply.c b/src/lib/cares_reply.c index daaf0d7e92..98e975f21b 100644 --- a/src/lib/cares_reply.c +++ b/src/lib/cares_reply.c @@ -17,7 +17,7 @@ #include "string.h" -cares_srv_reply* +const cares_srv_reply* cares_srv_reply_get_next(const cares_srv_reply* srv_reply) { return srv_reply->next; @@ -88,7 +88,7 @@ void cares_srv_reply_set_ttl(cares_srv_reply* srv_reply, -cares_caa_reply* +const cares_caa_reply* cares_caa_reply_get_next(const cares_caa_reply* caa_reply) { return caa_reply->next; @@ -171,7 +171,7 @@ void cares_caa_reply_set_ttl(cares_caa_reply* caa_reply, caa_reply->ttl = ttl; } -cares_ptr_reply* +const cares_ptr_reply* cares_ptr_reply_get_next(const cares_ptr_reply* ptr_reply) { return ptr_reply->next; @@ -205,7 +205,7 @@ void cares_ptr_reply_set_ttl(cares_ptr_reply* ptr_reply, ptr_reply->ttl = ttl; } -cares_ns_reply* +const cares_ns_reply* cares_ns_reply_get_next(const cares_ns_reply* ns_reply) { return ns_reply->next; @@ -239,7 +239,7 @@ void cares_ns_reply_set_ttl(cares_ns_reply* ns_reply, ns_reply->ttl = ttl; } -cares_mx_reply* +const cares_mx_reply* cares_mx_reply_get_next(const cares_mx_reply* mx_reply) { return mx_reply->next; @@ -285,7 +285,7 @@ void cares_mx_reply_set_ttl(cares_mx_reply* mx_reply, mx_reply->ttl = ttl; } -cares_txt_reply* +const cares_txt_reply* cares_txt_reply_get_next(const cares_txt_reply* txt_reply) { return txt_reply->next; @@ -344,7 +344,7 @@ void cares_txt_reply_set_ttl(cares_txt_reply* txt_reply, txt_reply->ttl = ttl; } -cares_naptr_reply* +const cares_naptr_reply* cares_naptr_reply_get_next(const cares_naptr_reply* naptr_reply) { return naptr_reply->next; diff --git a/test/ares-test-parse-mx.cc b/test/ares-test-parse-mx.cc index b6099e66a0..cc8998e35f 100644 --- a/test/ares-test-parse-mx.cc +++ b/test/ares-test-parse-mx.cc @@ -45,7 +45,7 @@ TEST_F(LibraryTest, ParseCMxReplyOK) { EXPECT_EQ(100, cares_mx_reply_get_priority(mx)); EXPECT_EQ(100, cares_mx_reply_get_ttl(mx)); - cares_mx_reply* mx2 = cares_mx_reply_get_next(mx); + const cares_mx_reply* mx2 = cares_mx_reply_get_next(mx); ASSERT_NE(nullptr, mx2); EXPECT_EQ("mx2.example.com", std::string(cares_mx_reply_get_host(mx2))); EXPECT_EQ(200, cares_mx_reply_get_priority(mx2)); diff --git a/test/ares-test-parse-naptr.cc b/test/ares-test-parse-naptr.cc index 46d631ebdc..40d3f980ee 100644 --- a/test/ares-test-parse-naptr.cc +++ b/test/ares-test-parse-naptr.cc @@ -61,7 +61,7 @@ TEST_F(LibraryTest, ParseCNaptrReplyOK) { EXPECT_EQ(20, cares_naptr_reply_get_preference(naptr)); EXPECT_EQ(100, cares_naptr_reply_get_ttl(naptr)); - cares_naptr_reply* naptr2 = cares_naptr_reply_get_next(naptr); + const cares_naptr_reply* naptr2 = cares_naptr_reply_get_next(naptr); ASSERT_NE(nullptr, naptr2); EXPECT_EQ("SP", std::string((char*)cares_naptr_reply_get_flags(naptr2))); EXPECT_EQ("service2", std::string((char*)cares_naptr_reply_get_service(naptr2))); diff --git a/test/ares-test-parse-ns.cc b/test/ares-test-parse-ns.cc index eec385b9c1..8ef284d701 100644 --- a/test/ares-test-parse-ns.cc +++ b/test/ares-test-parse-ns.cc @@ -78,7 +78,7 @@ TEST_F(LibraryTest, ParseCNsReplyMultiple) { cares_ns_reply* ns0 = nullptr; EXPECT_EQ(ARES_SUCCESS, cares_parse_ns_reply(data.data(), data.size(), &ns0)); ASSERT_NE(nullptr, ns0); - cares_ns_reply* ns = ns0; + const cares_ns_reply* ns = ns0; EXPECT_EQ("ns1.google.com", std::string(cares_ns_reply_get_host(ns))); EXPECT_EQ(59, cares_ns_reply_get_ttl(ns)); ns = cares_ns_reply_get_next(ns); diff --git a/test/ares-test-parse-srv.cc b/test/ares-test-parse-srv.cc index 0327635a2a..c4b484cc75 100644 --- a/test/ares-test-parse-srv.cc +++ b/test/ares-test-parse-srv.cc @@ -53,7 +53,7 @@ TEST_F(LibraryTest, ParseCSrvReplyOK) { EXPECT_EQ(30, cares_srv_reply_get_port(srv)); EXPECT_EQ(100, cares_srv_reply_get_ttl(srv)); - cares_srv_reply* srv2 = cares_srv_reply_get_next(srv); + const cares_srv_reply* srv2 = cares_srv_reply_get_next(srv); ASSERT_NE(nullptr, srv2); EXPECT_EQ("srv2.example.com", std::string(cares_srv_reply_get_host(srv2))); EXPECT_EQ(11, cares_srv_reply_get_priority(srv2)); @@ -248,7 +248,7 @@ TEST_F(LibraryTest, ParseCSrvReplyMultiple) { cares_srv_reply* srv0 = nullptr; EXPECT_EQ(ARES_SUCCESS, cares_parse_srv_reply(data.data(), data.size(), &srv0)); ASSERT_NE(nullptr, srv0); - cares_srv_reply* srv = srv0; + const cares_srv_reply* srv = srv0; EXPECT_EQ("a1.srv.example.com", std::string(cares_srv_reply_get_host(srv))); EXPECT_EQ(0, cares_srv_reply_get_priority(srv)); @@ -402,7 +402,7 @@ TEST_F(LibraryTest, ParseCSrvReplyCnameMultiple) { cares_srv_reply* srv0 = nullptr; EXPECT_EQ(ARES_SUCCESS, cares_parse_srv_reply(data.data(), data.size(), &srv0)); ASSERT_NE(nullptr, srv0); - cares_srv_reply* srv = srv0; + const cares_srv_reply* srv = srv0; EXPECT_EQ("a1.srv.example.com", std::string(cares_srv_reply_get_host(srv))); EXPECT_EQ(0, cares_srv_reply_get_priority(srv)); diff --git a/test/ares-test-parse-txt.cc b/test/ares-test-parse-txt.cc index 1b1e05d125..2008792760 100644 --- a/test/ares-test-parse-txt.cc +++ b/test/ares-test-parse-txt.cc @@ -91,14 +91,14 @@ TEST_F(LibraryTest, ParseCTxtReplyOK) { cares_txt_reply_get_txt(txt) + cares_txt_reply_get_length(txt))); EXPECT_EQ(100, cares_txt_reply_get_ttl(txt)); - cares_txt_reply* txt2 = cares_txt_reply_get_next(txt); + const cares_txt_reply* txt2 = cares_txt_reply_get_next(txt); ASSERT_NE(nullptr, txt2); EXPECT_EQ(std::vector(expected2a.data(), expected2a.data() + expected2a.size()), std::vector(cares_txt_reply_get_txt(txt2), cares_txt_reply_get_txt(txt2) + cares_txt_reply_get_length(txt2))); EXPECT_EQ(100, cares_txt_reply_get_ttl(txt2)); - cares_txt_reply* txt3 = cares_txt_reply_get_next(txt2); + const cares_txt_reply* txt3 = cares_txt_reply_get_next(txt2); ASSERT_NE(nullptr, txt3); EXPECT_EQ(std::vector(expected2b.data(), expected2b.data() + expected2b.size()), std::vector(cares_txt_reply_get_txt(txt3), From 699a9cd524f0a5ab981d6f991e8e2d2d6a9a4660 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Thu, 11 Nov 2021 22:56:51 -0500 Subject: [PATCH 20/49] create cares_memdup function as sugar for malloc/memcpy pattern --- aminclude_static.am | 126 ------------------------------- src/lib/Makefile.inc | 2 + src/lib/ares_parse_caa_reply.c | 18 ++--- src/lib/ares_parse_naptr_reply.c | 25 ++---- src/lib/ares_parse_txt_reply.c | 9 +-- src/lib/cares_memdup.c | 33 ++++++++ src/lib/cares_memdup.h | 19 +++++ src/lib/cares_parse_caa_reply.c | 29 +++---- src/lib/cares_parse_txt_reply.c | 17 ++--- 9 files changed, 86 insertions(+), 192 deletions(-) delete mode 100644 aminclude_static.am create mode 100644 src/lib/cares_memdup.c create mode 100644 src/lib/cares_memdup.h diff --git a/aminclude_static.am b/aminclude_static.am deleted file mode 100644 index fff4199273..0000000000 --- a/aminclude_static.am +++ /dev/null @@ -1,126 +0,0 @@ - -# aminclude_static.am generated automatically by Autoconf -# from AX_AM_MACROS_STATIC on Sat Nov 6 23:31:46 EDT 2021 - - -# Code coverage -# -# Optional: -# - CODE_COVERAGE_DIRECTORY: Top-level directory for code coverage reporting. -# Multiple directories may be specified, separated by whitespace. -# (Default: $(top_builddir)) -# - CODE_COVERAGE_OUTPUT_FILE: Filename and path for the .info file generated -# by lcov for code coverage. (Default: -# $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info) -# - CODE_COVERAGE_OUTPUT_DIRECTORY: Directory for generated code coverage -# reports to be created. (Default: -# $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage) -# - CODE_COVERAGE_BRANCH_COVERAGE: Set to 1 to enforce branch coverage, -# set to 0 to disable it and leave empty to stay with the default. -# (Default: empty) -# - CODE_COVERAGE_LCOV_SHOPTS_DEFAULT: Extra options shared between both lcov -# instances. (Default: based on ) -# - CODE_COVERAGE_LCOV_SHOPTS: Extra options to shared between both lcov -# instances. (Default: ) -# - CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH: --gcov-tool pathtogcov -# - CODE_COVERAGE_LCOV_OPTIONS_DEFAULT: Extra options to pass to the -# collecting lcov instance. (Default: ) -# - CODE_COVERAGE_LCOV_OPTIONS: Extra options to pass to the collecting lcov -# instance. (Default: ) -# - CODE_COVERAGE_LCOV_RMOPTS_DEFAULT: Extra options to pass to the filtering -# lcov instance. (Default: empty) -# - CODE_COVERAGE_LCOV_RMOPTS: Extra options to pass to the filtering lcov -# instance. (Default: ) -# - CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT: Extra options to pass to the -# genhtml instance. (Default: based on ) -# - CODE_COVERAGE_GENHTML_OPTIONS: Extra options to pass to the genhtml -# instance. (Default: ) -# - CODE_COVERAGE_IGNORE_PATTERN: Extra glob pattern of files to ignore -# -# The generated report will be titled using the $(PACKAGE_NAME) and -# $(PACKAGE_VERSION). In order to add the current git hash to the title, -# use the git-version-gen script, available online. -# Optional variables -# run only on top dir -if CODE_COVERAGE_ENABLED - ifeq ($(abs_builddir), $(abs_top_builddir)) -CODE_COVERAGE_DIRECTORY ?= $(top_builddir) -CODE_COVERAGE_OUTPUT_FILE ?= $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info -CODE_COVERAGE_OUTPUT_DIRECTORY ?= $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage - -CODE_COVERAGE_BRANCH_COVERAGE ?= -CODE_COVERAGE_LCOV_SHOPTS_DEFAULT ?= $(if $(CODE_COVERAGE_BRANCH_COVERAGE),--rc lcov_branch_coverage=$(CODE_COVERAGE_BRANCH_COVERAGE)) -CODE_COVERAGE_LCOV_SHOPTS ?= $(CODE_COVERAGE_LCOV_SHOPTS_DEFAULT) -CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH ?= --gcov-tool "$(GCOV)" -CODE_COVERAGE_LCOV_OPTIONS_DEFAULT ?= $(CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH) -CODE_COVERAGE_LCOV_OPTIONS ?= $(CODE_COVERAGE_LCOV_OPTIONS_DEFAULT) -CODE_COVERAGE_LCOV_RMOPTS_DEFAULT ?= -CODE_COVERAGE_LCOV_RMOPTS ?= $(CODE_COVERAGE_LCOV_RMOPTS_DEFAULT) -CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT ?=$(if $(CODE_COVERAGE_BRANCH_COVERAGE),--rc genhtml_branch_coverage=$(CODE_COVERAGE_BRANCH_COVERAGE)) -CODE_COVERAGE_GENHTML_OPTIONS ?= $(CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT) -CODE_COVERAGE_IGNORE_PATTERN ?= - -GITIGNOREFILES := $(GITIGNOREFILES) $(CODE_COVERAGE_OUTPUT_FILE) $(CODE_COVERAGE_OUTPUT_DIRECTORY) -code_coverage_v_lcov_cap = $(code_coverage_v_lcov_cap_$(V)) -code_coverage_v_lcov_cap_ = $(code_coverage_v_lcov_cap_$(AM_DEFAULT_VERBOSITY)) -code_coverage_v_lcov_cap_0 = @echo " LCOV --capture" $(CODE_COVERAGE_OUTPUT_FILE); -code_coverage_v_lcov_ign = $(code_coverage_v_lcov_ign_$(V)) -code_coverage_v_lcov_ign_ = $(code_coverage_v_lcov_ign_$(AM_DEFAULT_VERBOSITY)) -code_coverage_v_lcov_ign_0 = @echo " LCOV --remove /tmp/*" $(CODE_COVERAGE_IGNORE_PATTERN); -code_coverage_v_genhtml = $(code_coverage_v_genhtml_$(V)) -code_coverage_v_genhtml_ = $(code_coverage_v_genhtml_$(AM_DEFAULT_VERBOSITY)) -code_coverage_v_genhtml_0 = @echo " GEN " "$(CODE_COVERAGE_OUTPUT_DIRECTORY)"; -code_coverage_quiet = $(code_coverage_quiet_$(V)) -code_coverage_quiet_ = $(code_coverage_quiet_$(AM_DEFAULT_VERBOSITY)) -code_coverage_quiet_0 = --quiet - -# sanitizes the test-name: replaces with underscores: dashes and dots -code_coverage_sanitize = $(subst -,_,$(subst .,_,$(1))) - -# Use recursive makes in order to ignore errors during check -check-code-coverage: - -$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -k check - $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) code-coverage-capture - -# Capture code coverage data -code-coverage-capture: code-coverage-capture-hook - $(code_coverage_v_lcov_cap)$(LCOV) $(code_coverage_quiet) $(addprefix --directory ,$(CODE_COVERAGE_DIRECTORY)) --capture --output-file "$(CODE_COVERAGE_OUTPUT_FILE).tmp" --test-name "$(call code_coverage_sanitize,$(PACKAGE_NAME)-$(PACKAGE_VERSION))" --no-checksum --compat-libtool $(CODE_COVERAGE_LCOV_SHOPTS) $(CODE_COVERAGE_LCOV_OPTIONS) - $(code_coverage_v_lcov_ign)$(LCOV) $(code_coverage_quiet) $(addprefix --directory ,$(CODE_COVERAGE_DIRECTORY)) --remove "$(CODE_COVERAGE_OUTPUT_FILE).tmp" "/tmp/*" $(CODE_COVERAGE_IGNORE_PATTERN) --output-file "$(CODE_COVERAGE_OUTPUT_FILE)" $(CODE_COVERAGE_LCOV_SHOPTS) $(CODE_COVERAGE_LCOV_RMOPTS) - -@rm -f "$(CODE_COVERAGE_OUTPUT_FILE).tmp" - $(code_coverage_v_genhtml)LANG=C $(GENHTML) $(code_coverage_quiet) $(addprefix --prefix ,$(CODE_COVERAGE_DIRECTORY)) --output-directory "$(CODE_COVERAGE_OUTPUT_DIRECTORY)" --title "$(PACKAGE_NAME)-$(PACKAGE_VERSION) Code Coverage" --legend --show-details "$(CODE_COVERAGE_OUTPUT_FILE)" $(CODE_COVERAGE_GENHTML_OPTIONS) - @echo "file://$(abs_builddir)/$(CODE_COVERAGE_OUTPUT_DIRECTORY)/index.html" - -code-coverage-clean: - -$(LCOV) --directory $(top_builddir) -z - -rm -rf "$(CODE_COVERAGE_OUTPUT_FILE)" "$(CODE_COVERAGE_OUTPUT_FILE).tmp" "$(CODE_COVERAGE_OUTPUT_DIRECTORY)" - -find . \( -name "*.gcda" -o -name "*.gcno" -o -name "*.gcov" \) -delete - -code-coverage-dist-clean: - -AM_DISTCHECK_CONFIGURE_FLAGS := $(AM_DISTCHECK_CONFIGURE_FLAGS) --disable-code-coverage - else # ifneq ($(abs_builddir), $(abs_top_builddir)) -check-code-coverage: - -code-coverage-capture: code-coverage-capture-hook - -code-coverage-clean: - -code-coverage-dist-clean: - endif # ifeq ($(abs_builddir), $(abs_top_builddir)) -else #! CODE_COVERAGE_ENABLED -# Use recursive makes in order to ignore errors during check -check-code-coverage: - @echo "Need to reconfigure with --enable-code-coverage" -# Capture code coverage data -code-coverage-capture: code-coverage-capture-hook - @echo "Need to reconfigure with --enable-code-coverage" - -code-coverage-clean: - -code-coverage-dist-clean: - -endif #CODE_COVERAGE_ENABLED -# Hook rule executed before code-coverage-capture, overridable by the user -code-coverage-capture-hook: - -.PHONY: check-code-coverage code-coverage-capture code-coverage-dist-clean code-coverage-clean code-coverage-capture-hook diff --git a/src/lib/Makefile.inc b/src/lib/Makefile.inc index c68a3dfd2f..69494570b6 100644 --- a/src/lib/Makefile.inc +++ b/src/lib/Makefile.inc @@ -58,6 +58,7 @@ CSOURCES = ares__addrinfo2hostent.c \ ares_send.c \ ares_strcasecmp.c \ ares_strdup.c \ + cares_memdup.c \ ares_strerror.c \ ares_strsplit.c \ ares_timeout.c \ @@ -81,6 +82,7 @@ HHEADERS = ares_android.h \ ares_private.h \ ares_strcasecmp.h \ ares_strdup.h \ + cares_memdup.h \ ares_strsplit.h \ ares_writev.h \ bitncmp.h \ diff --git a/src/lib/ares_parse_caa_reply.c b/src/lib/ares_parse_caa_reply.c index 73b6595085..ec5e5bb83d 100644 --- a/src/lib/ares_parse_caa_reply.c +++ b/src/lib/ares_parse_caa_reply.c @@ -36,7 +36,7 @@ #include "ares_dns.h" #include "ares_data.h" #include "ares_private.h" -#include +#include "cares_memdup.h" int ares_parse_caa_reply (const unsigned char *abuf, int alen, @@ -87,28 +87,20 @@ ares_parse_caa_reply (const unsigned char *abuf, int alen, caa_curr->critical = cares_caa_reply_get_critical(ccaa_curr); property = cares_caa_reply_get_property(ccaa_curr); - caa_curr->property = ares_malloc(cares_caa_reply_get_plength(ccaa_curr) + 1); - if (!caa_curr->property) - { + caa_curr->property = cares_memdup(property, cares_caa_reply_get_plength(ccaa_curr)); + if (!caa_curr->property) { status = ARES_ENOMEM; break; } - memcpy(caa_curr->property, property, cares_caa_reply_get_plength(ccaa_curr)); - /* Make sure we NULL-terminate */ - caa_curr->property[cares_caa_reply_get_plength(ccaa_curr)] = 0; caa_curr->plength = cares_caa_reply_get_plength(ccaa_curr); value = cares_caa_reply_get_value(ccaa_curr); - caa_curr->value = ares_malloc(cares_caa_reply_get_length(ccaa_curr) + 1); - if (!caa_curr->value) - { + caa_curr->value = cares_memdup(value, cares_caa_reply_get_length(ccaa_curr)); + if (!caa_curr->value) { status = ARES_ENOMEM; break; } - memcpy(caa_curr->value, value, cares_caa_reply_get_length(ccaa_curr)); - /* Make sure we NULL-terminate */ - caa_curr->value[cares_caa_reply_get_length(ccaa_curr)] = 0; caa_curr->length = cares_caa_reply_get_length(ccaa_curr); } diff --git a/src/lib/ares_parse_naptr_reply.c b/src/lib/ares_parse_naptr_reply.c index 671996bcd7..0bc027be39 100644 --- a/src/lib/ares_parse_naptr_reply.c +++ b/src/lib/ares_parse_naptr_reply.c @@ -33,6 +33,7 @@ #include "ares_dns.h" #include "ares_data.h" #include "ares_private.h" +#include "cares_memdup.h" int ares_parse_naptr_reply (const unsigned char *abuf, int alen, @@ -88,39 +89,27 @@ ares_parse_naptr_reply (const unsigned char *abuf, int alen, flags = cares_naptr_reply_get_flags(cnaptr_curr); len = strlen((char *)flags); - naptr_curr->flags = ares_malloc(len + 1); - if (!naptr_curr->flags) - { + naptr_curr->flags = cares_memdup(flags, len); + if (!naptr_curr->flags) { status = ARES_ENOMEM; break; } - memcpy(naptr_curr->flags, flags, len); - /* Make sure we NULL-terminate */ - naptr_curr->flags[len] = 0; service = cares_naptr_reply_get_service(cnaptr_curr); len = strlen((char *)service); - naptr_curr->service = ares_malloc(len + 1); - if (!naptr_curr->service) - { + naptr_curr->service = cares_memdup(service, len); + if (!naptr_curr->service) { status = ARES_ENOMEM; break; } - memcpy(naptr_curr->service, service, len); - /* Make sure we NULL-terminate */ - naptr_curr->service[len] = 0; regexp = cares_naptr_reply_get_regexp(cnaptr_curr); len = strlen((char *)regexp); - naptr_curr->regexp = ares_malloc(len + 1); - if (!naptr_curr->regexp) - { + naptr_curr->regexp = cares_memdup(regexp, len); + if (!naptr_curr->regexp) { status = ARES_ENOMEM; break; } - memcpy(naptr_curr->regexp, regexp, len); - /* Make sure we NULL-terminate */ - naptr_curr->regexp[len] = 0; replacement = ares_strdup( cares_naptr_reply_get_replacement(cnaptr_curr)); diff --git a/src/lib/ares_parse_txt_reply.c b/src/lib/ares_parse_txt_reply.c index 8ce3daf9cc..7ac5059ad5 100644 --- a/src/lib/ares_parse_txt_reply.c +++ b/src/lib/ares_parse_txt_reply.c @@ -37,6 +37,7 @@ #include "ares_dns.h" #include "ares_data.h" #include "ares_private.h" +#include "cares_memdup.h" static int ares__parse_txt_reply (const unsigned char *abuf, int alen, @@ -89,15 +90,11 @@ ares__parse_txt_reply (const unsigned char *abuf, int alen, txt_last = txt_curr; txt = cares_txt_reply_get_txt(ctxt_curr); - txt_curr->txt = ares_malloc(cares_txt_reply_get_length(ctxt_curr) + 1); - if (!txt_curr->txt) - { + txt_curr->txt = cares_memdup(txt, cares_txt_reply_get_length(ctxt_curr)); + if (!txt_curr->txt) { status = ARES_ENOMEM; break; } - memcpy(txt_curr->txt, txt, cares_txt_reply_get_length(ctxt_curr)); - /* Make sure we NULL-terminate */ - txt_curr->txt[cares_txt_reply_get_length(ctxt_curr)] = 0; txt_curr->length = cares_txt_reply_get_length(ctxt_curr); if (ex) diff --git a/src/lib/cares_memdup.c b/src/lib/cares_memdup.c new file mode 100644 index 0000000000..2aceea21e8 --- /dev/null +++ b/src/lib/cares_memdup.c @@ -0,0 +1,33 @@ +/* Copyright (C) 2021 by Kyle Evans + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. M.I.T. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" +#include "ares.h" +#include "cares_memdup.h" +#include "ares_private.h" +#include "string.h" + +unsigned char* cares_memdup(const unsigned char* data, size_t sz) +{ + unsigned char* data2; + data2 = ares_malloc(sz + 1); + if (!data2) + { + return (unsigned char*)NULL; + } + memcpy(data2, data, sz); + /* Make sure we NULL-terminate */ + data2[sz] = 0; + + return data2; +} diff --git a/src/lib/cares_memdup.h b/src/lib/cares_memdup.h new file mode 100644 index 0000000000..03e6e7b65b --- /dev/null +++ b/src/lib/cares_memdup.h @@ -0,0 +1,19 @@ +#ifndef HEADER_CARES_MEMDUP_H +#define HEADER_CARES_MEMDUP_H + +/* Copyright (C) 2021 by Kyle Evans + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. M.I.T. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + */ + +unsigned char* cares_memdup(const unsigned char* data, size_t sz); + +#endif /* HEADER_CARES_MEMDUP_H */ diff --git a/src/lib/cares_parse_caa_reply.c b/src/lib/cares_parse_caa_reply.c index 3b24fd5872..febf10b3ff 100644 --- a/src/lib/cares_parse_caa_reply.c +++ b/src/lib/cares_parse_caa_reply.c @@ -36,6 +36,7 @@ #include "ares_dns.h" #include "ares_data.h" #include "ares_private.h" +#include "cares_memdup.h" int cares_parse_caa_reply (const unsigned char *abuf, int alen, @@ -141,15 +142,11 @@ cares_parse_caa_reply (const unsigned char *abuf, int alen, status = ARES_EBADRESP; break; } - property = ares_malloc (cares_caa_reply_get_plength(caa_curr) + 1/* Including null byte */); - if (property == NULL) - { - status = ARES_ENOMEM; - break; - } - memcpy ((char *) property, strptr, cares_caa_reply_get_plength(caa_curr)); - /* Make sure we NULL-terminate */ - property[cares_caa_reply_get_plength(caa_curr)] = 0; + property = cares_memdup((unsigned char*) strptr, cares_caa_reply_get_plength(caa_curr)); + if (!property) { + status = ARES_ENOMEM; + break; + } cares_caa_reply_set_property(caa_curr, property); strptr += cares_caa_reply_get_plength(caa_curr); @@ -159,15 +156,11 @@ cares_parse_caa_reply (const unsigned char *abuf, int alen, status = ARES_EBADRESP; break; } - value = ares_malloc (cares_caa_reply_get_length(caa_curr) + 1/* Including null byte */); - if (value == NULL) - { - status = ARES_ENOMEM; - break; - } - memcpy ((char *) value, strptr, cares_caa_reply_get_length(caa_curr)); - /* Make sure we NULL-terminate */ - value[caa_curr->length] = 0; + value = cares_memdup((unsigned char*) strptr, cares_caa_reply_get_length(caa_curr)); + if (!value) { + status = ARES_ENOMEM; + break; + } cares_caa_reply_set_value(caa_curr, value); cares_caa_reply_set_ttl(caa_curr, rr_ttl); } diff --git a/src/lib/cares_parse_txt_reply.c b/src/lib/cares_parse_txt_reply.c index 8dabb8567f..6fd81e1c8f 100644 --- a/src/lib/cares_parse_txt_reply.c +++ b/src/lib/cares_parse_txt_reply.c @@ -37,6 +37,7 @@ #include "ares_dns.h" #include "ares_data.h" #include "ares_private.h" +#include "cares_memdup.h" int cares_parse_txt_reply (const unsigned char *abuf, int alen, cares_txt_reply **txt_out) @@ -151,18 +152,12 @@ int cares_parse_txt_reply (const unsigned char *abuf, int alen, cares_txt_reply_set_length(txt_curr, substr_len); cares_txt_reply_set_ttl(txt_curr, rr_ttl); - txt = ares_malloc (substr_len + 1/* Including null byte */); - if (txt == NULL) - { - status = ARES_ENOMEM; - break; - } - ++strptr; - memcpy ((char *) txt, strptr, substr_len); - - /* Make sure we NULL-terminate */ - txt[substr_len] = 0; + txt = cares_memdup((unsigned char*) strptr, cares_txt_reply_get_length(txt_curr)); + if (!txt) { + status = ARES_ENOMEM; + break; + } cares_txt_reply_set_txt(txt_curr, txt); From 3286a5d5a0e500e1c2abbcf4de13338ec80ff176 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Wed, 29 Dec 2021 17:03:29 -0500 Subject: [PATCH 21/49] save progress --- aminclude_static.am | 126 +++++++++++++++++++++++++++++++++ include/ares.h | 15 +++- src/lib/Makefile.inc | 3 + src/lib/ares_free_hostent.c | 1 - src/lib/ares_private.h | 19 ++++- src/lib/cares_container.c | 75 ++++++++++++++++++++ src/lib/cares_free_container.c | 18 +++++ src/lib/cares_free_container.h | 31 ++++++++ test/aminclude_static.am | 126 +++++++++++++++++++++++++++++++++ 9 files changed, 409 insertions(+), 5 deletions(-) create mode 100644 aminclude_static.am create mode 100644 src/lib/cares_container.c create mode 100644 src/lib/cares_free_container.c create mode 100644 src/lib/cares_free_container.h create mode 100644 test/aminclude_static.am diff --git a/aminclude_static.am b/aminclude_static.am new file mode 100644 index 0000000000..fff4199273 --- /dev/null +++ b/aminclude_static.am @@ -0,0 +1,126 @@ + +# aminclude_static.am generated automatically by Autoconf +# from AX_AM_MACROS_STATIC on Sat Nov 6 23:31:46 EDT 2021 + + +# Code coverage +# +# Optional: +# - CODE_COVERAGE_DIRECTORY: Top-level directory for code coverage reporting. +# Multiple directories may be specified, separated by whitespace. +# (Default: $(top_builddir)) +# - CODE_COVERAGE_OUTPUT_FILE: Filename and path for the .info file generated +# by lcov for code coverage. (Default: +# $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info) +# - CODE_COVERAGE_OUTPUT_DIRECTORY: Directory for generated code coverage +# reports to be created. (Default: +# $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage) +# - CODE_COVERAGE_BRANCH_COVERAGE: Set to 1 to enforce branch coverage, +# set to 0 to disable it and leave empty to stay with the default. +# (Default: empty) +# - CODE_COVERAGE_LCOV_SHOPTS_DEFAULT: Extra options shared between both lcov +# instances. (Default: based on ) +# - CODE_COVERAGE_LCOV_SHOPTS: Extra options to shared between both lcov +# instances. (Default: ) +# - CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH: --gcov-tool pathtogcov +# - CODE_COVERAGE_LCOV_OPTIONS_DEFAULT: Extra options to pass to the +# collecting lcov instance. (Default: ) +# - CODE_COVERAGE_LCOV_OPTIONS: Extra options to pass to the collecting lcov +# instance. (Default: ) +# - CODE_COVERAGE_LCOV_RMOPTS_DEFAULT: Extra options to pass to the filtering +# lcov instance. (Default: empty) +# - CODE_COVERAGE_LCOV_RMOPTS: Extra options to pass to the filtering lcov +# instance. (Default: ) +# - CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT: Extra options to pass to the +# genhtml instance. (Default: based on ) +# - CODE_COVERAGE_GENHTML_OPTIONS: Extra options to pass to the genhtml +# instance. (Default: ) +# - CODE_COVERAGE_IGNORE_PATTERN: Extra glob pattern of files to ignore +# +# The generated report will be titled using the $(PACKAGE_NAME) and +# $(PACKAGE_VERSION). In order to add the current git hash to the title, +# use the git-version-gen script, available online. +# Optional variables +# run only on top dir +if CODE_COVERAGE_ENABLED + ifeq ($(abs_builddir), $(abs_top_builddir)) +CODE_COVERAGE_DIRECTORY ?= $(top_builddir) +CODE_COVERAGE_OUTPUT_FILE ?= $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info +CODE_COVERAGE_OUTPUT_DIRECTORY ?= $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage + +CODE_COVERAGE_BRANCH_COVERAGE ?= +CODE_COVERAGE_LCOV_SHOPTS_DEFAULT ?= $(if $(CODE_COVERAGE_BRANCH_COVERAGE),--rc lcov_branch_coverage=$(CODE_COVERAGE_BRANCH_COVERAGE)) +CODE_COVERAGE_LCOV_SHOPTS ?= $(CODE_COVERAGE_LCOV_SHOPTS_DEFAULT) +CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH ?= --gcov-tool "$(GCOV)" +CODE_COVERAGE_LCOV_OPTIONS_DEFAULT ?= $(CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH) +CODE_COVERAGE_LCOV_OPTIONS ?= $(CODE_COVERAGE_LCOV_OPTIONS_DEFAULT) +CODE_COVERAGE_LCOV_RMOPTS_DEFAULT ?= +CODE_COVERAGE_LCOV_RMOPTS ?= $(CODE_COVERAGE_LCOV_RMOPTS_DEFAULT) +CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT ?=$(if $(CODE_COVERAGE_BRANCH_COVERAGE),--rc genhtml_branch_coverage=$(CODE_COVERAGE_BRANCH_COVERAGE)) +CODE_COVERAGE_GENHTML_OPTIONS ?= $(CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT) +CODE_COVERAGE_IGNORE_PATTERN ?= + +GITIGNOREFILES := $(GITIGNOREFILES) $(CODE_COVERAGE_OUTPUT_FILE) $(CODE_COVERAGE_OUTPUT_DIRECTORY) +code_coverage_v_lcov_cap = $(code_coverage_v_lcov_cap_$(V)) +code_coverage_v_lcov_cap_ = $(code_coverage_v_lcov_cap_$(AM_DEFAULT_VERBOSITY)) +code_coverage_v_lcov_cap_0 = @echo " LCOV --capture" $(CODE_COVERAGE_OUTPUT_FILE); +code_coverage_v_lcov_ign = $(code_coverage_v_lcov_ign_$(V)) +code_coverage_v_lcov_ign_ = $(code_coverage_v_lcov_ign_$(AM_DEFAULT_VERBOSITY)) +code_coverage_v_lcov_ign_0 = @echo " LCOV --remove /tmp/*" $(CODE_COVERAGE_IGNORE_PATTERN); +code_coverage_v_genhtml = $(code_coverage_v_genhtml_$(V)) +code_coverage_v_genhtml_ = $(code_coverage_v_genhtml_$(AM_DEFAULT_VERBOSITY)) +code_coverage_v_genhtml_0 = @echo " GEN " "$(CODE_COVERAGE_OUTPUT_DIRECTORY)"; +code_coverage_quiet = $(code_coverage_quiet_$(V)) +code_coverage_quiet_ = $(code_coverage_quiet_$(AM_DEFAULT_VERBOSITY)) +code_coverage_quiet_0 = --quiet + +# sanitizes the test-name: replaces with underscores: dashes and dots +code_coverage_sanitize = $(subst -,_,$(subst .,_,$(1))) + +# Use recursive makes in order to ignore errors during check +check-code-coverage: + -$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -k check + $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) code-coverage-capture + +# Capture code coverage data +code-coverage-capture: code-coverage-capture-hook + $(code_coverage_v_lcov_cap)$(LCOV) $(code_coverage_quiet) $(addprefix --directory ,$(CODE_COVERAGE_DIRECTORY)) --capture --output-file "$(CODE_COVERAGE_OUTPUT_FILE).tmp" --test-name "$(call code_coverage_sanitize,$(PACKAGE_NAME)-$(PACKAGE_VERSION))" --no-checksum --compat-libtool $(CODE_COVERAGE_LCOV_SHOPTS) $(CODE_COVERAGE_LCOV_OPTIONS) + $(code_coverage_v_lcov_ign)$(LCOV) $(code_coverage_quiet) $(addprefix --directory ,$(CODE_COVERAGE_DIRECTORY)) --remove "$(CODE_COVERAGE_OUTPUT_FILE).tmp" "/tmp/*" $(CODE_COVERAGE_IGNORE_PATTERN) --output-file "$(CODE_COVERAGE_OUTPUT_FILE)" $(CODE_COVERAGE_LCOV_SHOPTS) $(CODE_COVERAGE_LCOV_RMOPTS) + -@rm -f "$(CODE_COVERAGE_OUTPUT_FILE).tmp" + $(code_coverage_v_genhtml)LANG=C $(GENHTML) $(code_coverage_quiet) $(addprefix --prefix ,$(CODE_COVERAGE_DIRECTORY)) --output-directory "$(CODE_COVERAGE_OUTPUT_DIRECTORY)" --title "$(PACKAGE_NAME)-$(PACKAGE_VERSION) Code Coverage" --legend --show-details "$(CODE_COVERAGE_OUTPUT_FILE)" $(CODE_COVERAGE_GENHTML_OPTIONS) + @echo "file://$(abs_builddir)/$(CODE_COVERAGE_OUTPUT_DIRECTORY)/index.html" + +code-coverage-clean: + -$(LCOV) --directory $(top_builddir) -z + -rm -rf "$(CODE_COVERAGE_OUTPUT_FILE)" "$(CODE_COVERAGE_OUTPUT_FILE).tmp" "$(CODE_COVERAGE_OUTPUT_DIRECTORY)" + -find . \( -name "*.gcda" -o -name "*.gcno" -o -name "*.gcov" \) -delete + +code-coverage-dist-clean: + +AM_DISTCHECK_CONFIGURE_FLAGS := $(AM_DISTCHECK_CONFIGURE_FLAGS) --disable-code-coverage + else # ifneq ($(abs_builddir), $(abs_top_builddir)) +check-code-coverage: + +code-coverage-capture: code-coverage-capture-hook + +code-coverage-clean: + +code-coverage-dist-clean: + endif # ifeq ($(abs_builddir), $(abs_top_builddir)) +else #! CODE_COVERAGE_ENABLED +# Use recursive makes in order to ignore errors during check +check-code-coverage: + @echo "Need to reconfigure with --enable-code-coverage" +# Capture code coverage data +code-coverage-capture: code-coverage-capture-hook + @echo "Need to reconfigure with --enable-code-coverage" + +code-coverage-clean: + +code-coverage-dist-clean: + +endif #CODE_COVERAGE_ENABLED +# Hook rule executed before code-coverage-capture, overridable by the user +code-coverage-capture-hook: + +.PHONY: check-code-coverage code-coverage-capture code-coverage-dist-clean code-coverage-clean code-coverage-capture-hook diff --git a/include/ares.h b/include/ares.h index f8cb3d15fc..e32133eb7b 100644 --- a/include/ares.h +++ b/include/ares.h @@ -561,6 +561,10 @@ struct cares_srv_reply; typedef struct cares_srv_reply cares_srv_reply; +struct cares_srv_reply_container + +typedef struct cares_srv_reply_container cares_srv_reply_container; + struct cares_host_reply; typedef struct cares_host_reply cares_host_reply; @@ -766,7 +770,16 @@ CARES_EXTERN int cares_parse_srv_reply(const unsigned char* abuf, struct cares_srv_reply** srv_out); CARES_EXTERN const cares_srv_reply* -cares_srv_reply_get_next(const cares_srv_reply* srv_reply); +cares_srv_reply_container_get_first(const cares_srv_reply_container* container); + +CARES_EXTERN const cares_srv_reply* +cares_srv_reply_container_get_next(const cares_srv_reply_container* container); + +CARES_EXTERN const cares_srv_reply* +cares_srv_reply_container_get_last(const cares_srv_reply_container* container); + +CARES_EXTERN const unsigned int +cares_srv_reply_container_get_count(const cares_srv_reply_container* container); CARES_EXTERN const char* cares_srv_reply_get_host(const cares_srv_reply* srv_reply); diff --git a/src/lib/Makefile.inc b/src/lib/Makefile.inc index 69494570b6..86b1521a99 100644 --- a/src/lib/Makefile.inc +++ b/src/lib/Makefile.inc @@ -67,6 +67,8 @@ CSOURCES = ares__addrinfo2hostent.c \ bitncmp.c \ inet_net_pton.c \ inet_ntop.c \ + cares_container.c \ + cares_free_container.c \ windows_port.c HHEADERS = ares_android.h \ @@ -87,6 +89,7 @@ HHEADERS = ares_android.h \ ares_writev.h \ bitncmp.h \ ares_setup.h \ + ares_free_container.h \ setup_once.h diff --git a/src/lib/ares_free_hostent.c b/src/lib/ares_free_hostent.c index a27669b031..ea28ff0e2c 100644 --- a/src/lib/ares_free_hostent.c +++ b/src/lib/ares_free_hostent.c @@ -22,7 +22,6 @@ #include "ares.h" #include "ares_private.h" /* for memdebug */ -#include void ares_free_hostent(struct hostent *host) { diff --git a/src/lib/ares_private.h b/src/lib/ares_private.h index e5d6bc76a2..f9c624b3b7 100644 --- a/src/lib/ares_private.h +++ b/src/lib/ares_private.h @@ -462,7 +462,7 @@ struct cares_ns_reply { }; struct cares_srv_reply { - cares_srv_reply *next; +// cares_srv_reply *next; char *host; unsigned short priority; unsigned short weight; @@ -470,6 +470,12 @@ struct cares_srv_reply { unsigned int ttl; }; +struct cares_srv_reply_container { + cares_srv_reply *replies; + int curr; + int count; +} + struct cares_mx_reply { cares_mx_reply *next; char *host; @@ -510,8 +516,8 @@ struct cares_soa_reply { }; /* Private declaration of c-ares reply setters */ -void cares_srv_reply_set_next(cares_srv_reply* srv_reply, - cares_srv_reply* next); +// void cares_srv_reply_set_next(cares_srv_reply* srv_reply, +// cares_srv_reply* next); void cares_srv_reply_set_host(cares_srv_reply* srv_reply, char* host); @@ -527,7 +533,14 @@ void cares_srv_reply_set_port(cares_srv_reply* srv_reply, void cares_srv_reply_set_ttl(cares_srv_reply* srv_reply, const unsigned int ttl); +void cares_srv_reply_container_set_replies(cares_srv_reply_container* container, + cares_srv_reply* replies); + +void cares_srv_reply_container_set_curr(cares_srv_reply_container* container, + const unsigned int index); +void cares_srv_reply_container_set_count(cares_srv_reply_container* container, + const unsigned int count); void cares_caa_reply_set_next(cares_caa_reply* caa_reply, cares_caa_reply* next); diff --git a/src/lib/cares_container.c b/src/lib/cares_container.c new file mode 100644 index 0000000000..f3e267b179 --- /dev/null +++ b/src/lib/cares_container.c @@ -0,0 +1,75 @@ +/* Copyright (C) 2021 by Kyle Evans + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. M.I.T. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" +#include "ares.h" +#include "ares_private.h" + + +const cares_srv_reply* +cares_srv_reply_container_get_first(const cares_srv_reply_container* container) +{ + return &container[0]; +} + +const cares_srv_reply* +cares_srv_reply_container_get_next(const cares_srv_reply_container* container) +{ + if (cares_srv_reply_container_get_count(container) == 0) + { + return container->replies; + } + + if (container->curr == cares_srv_reply_container_get_count(container) - 1) + { + return &container->replies[cares_srv_reply_container_get_count(container) - 1]; + } + + container->curr = container->curr + 1; + return &container->replies[container->curr]; +} + +const cares_srv_reply* +cares_srv_reply_container_get_last(const cares_srv_reply_container* container) +{ + if (cares_srv_reply_container_get_count(container) == 0) + { + return container->replies; + } + + return &container->replies[cares_srv_reply_container_get_count(container) - 1]; +} + +const int +cares_srv_reply_container_get_count(const cares_srv_reply_container* container) +{ + return container->count; +} + +void cares_srv_reply_container_set_replies(cares_srv_reply_container* container, + cares_srv_reply* replies) +{ + container->replies = replies; +} + +void cares_srv_reply_container_set_curr(cares_srv_reply_container* container, + const unsigned int index) +{ + container->curr = index; +} + +void cares_srv_reply_container_set_count(cares_srv_reply_container* container, + const unsigned int count) +{ + container->count = count; +} \ No newline at end of file diff --git a/src/lib/cares_free_container.c b/src/lib/cares_free_container.c new file mode 100644 index 0000000000..64eac11af8 --- /dev/null +++ b/src/lib/cares_free_container.c @@ -0,0 +1,18 @@ +/* Copyright (C) 2021 by Kyle Evans + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. M.I.T. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" +#include "ares.h" +#include "ares_private.h" + +for () \ No newline at end of file diff --git a/src/lib/cares_free_container.h b/src/lib/cares_free_container.h new file mode 100644 index 0000000000..6754f54b7b --- /dev/null +++ b/src/lib/cares_free_container.h @@ -0,0 +1,31 @@ +/* Copyright (C) 2021 by Kyle Evans + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. M.I.T. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_private.h" +#include "ares_data.h" + +typedef enum { + CARES_CONTAINER_SRV_REPLY_CONTAINER, + CARES_CONTAINER_LAST /* not used */ +} cares_datatype; + + +struct cares_data_container { + cares_datatype type; /* Actual data type identifier. */ + unsigned int mark; /* Private ares_data signature. */ + union { + struct cares_srv_reply_container srv_container; + } container; +}; + +void *ares_malloc_container(cares_datatype type); \ No newline at end of file diff --git a/test/aminclude_static.am b/test/aminclude_static.am new file mode 100644 index 0000000000..fff4199273 --- /dev/null +++ b/test/aminclude_static.am @@ -0,0 +1,126 @@ + +# aminclude_static.am generated automatically by Autoconf +# from AX_AM_MACROS_STATIC on Sat Nov 6 23:31:46 EDT 2021 + + +# Code coverage +# +# Optional: +# - CODE_COVERAGE_DIRECTORY: Top-level directory for code coverage reporting. +# Multiple directories may be specified, separated by whitespace. +# (Default: $(top_builddir)) +# - CODE_COVERAGE_OUTPUT_FILE: Filename and path for the .info file generated +# by lcov for code coverage. (Default: +# $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info) +# - CODE_COVERAGE_OUTPUT_DIRECTORY: Directory for generated code coverage +# reports to be created. (Default: +# $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage) +# - CODE_COVERAGE_BRANCH_COVERAGE: Set to 1 to enforce branch coverage, +# set to 0 to disable it and leave empty to stay with the default. +# (Default: empty) +# - CODE_COVERAGE_LCOV_SHOPTS_DEFAULT: Extra options shared between both lcov +# instances. (Default: based on ) +# - CODE_COVERAGE_LCOV_SHOPTS: Extra options to shared between both lcov +# instances. (Default: ) +# - CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH: --gcov-tool pathtogcov +# - CODE_COVERAGE_LCOV_OPTIONS_DEFAULT: Extra options to pass to the +# collecting lcov instance. (Default: ) +# - CODE_COVERAGE_LCOV_OPTIONS: Extra options to pass to the collecting lcov +# instance. (Default: ) +# - CODE_COVERAGE_LCOV_RMOPTS_DEFAULT: Extra options to pass to the filtering +# lcov instance. (Default: empty) +# - CODE_COVERAGE_LCOV_RMOPTS: Extra options to pass to the filtering lcov +# instance. (Default: ) +# - CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT: Extra options to pass to the +# genhtml instance. (Default: based on ) +# - CODE_COVERAGE_GENHTML_OPTIONS: Extra options to pass to the genhtml +# instance. (Default: ) +# - CODE_COVERAGE_IGNORE_PATTERN: Extra glob pattern of files to ignore +# +# The generated report will be titled using the $(PACKAGE_NAME) and +# $(PACKAGE_VERSION). In order to add the current git hash to the title, +# use the git-version-gen script, available online. +# Optional variables +# run only on top dir +if CODE_COVERAGE_ENABLED + ifeq ($(abs_builddir), $(abs_top_builddir)) +CODE_COVERAGE_DIRECTORY ?= $(top_builddir) +CODE_COVERAGE_OUTPUT_FILE ?= $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info +CODE_COVERAGE_OUTPUT_DIRECTORY ?= $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage + +CODE_COVERAGE_BRANCH_COVERAGE ?= +CODE_COVERAGE_LCOV_SHOPTS_DEFAULT ?= $(if $(CODE_COVERAGE_BRANCH_COVERAGE),--rc lcov_branch_coverage=$(CODE_COVERAGE_BRANCH_COVERAGE)) +CODE_COVERAGE_LCOV_SHOPTS ?= $(CODE_COVERAGE_LCOV_SHOPTS_DEFAULT) +CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH ?= --gcov-tool "$(GCOV)" +CODE_COVERAGE_LCOV_OPTIONS_DEFAULT ?= $(CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH) +CODE_COVERAGE_LCOV_OPTIONS ?= $(CODE_COVERAGE_LCOV_OPTIONS_DEFAULT) +CODE_COVERAGE_LCOV_RMOPTS_DEFAULT ?= +CODE_COVERAGE_LCOV_RMOPTS ?= $(CODE_COVERAGE_LCOV_RMOPTS_DEFAULT) +CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT ?=$(if $(CODE_COVERAGE_BRANCH_COVERAGE),--rc genhtml_branch_coverage=$(CODE_COVERAGE_BRANCH_COVERAGE)) +CODE_COVERAGE_GENHTML_OPTIONS ?= $(CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT) +CODE_COVERAGE_IGNORE_PATTERN ?= + +GITIGNOREFILES := $(GITIGNOREFILES) $(CODE_COVERAGE_OUTPUT_FILE) $(CODE_COVERAGE_OUTPUT_DIRECTORY) +code_coverage_v_lcov_cap = $(code_coverage_v_lcov_cap_$(V)) +code_coverage_v_lcov_cap_ = $(code_coverage_v_lcov_cap_$(AM_DEFAULT_VERBOSITY)) +code_coverage_v_lcov_cap_0 = @echo " LCOV --capture" $(CODE_COVERAGE_OUTPUT_FILE); +code_coverage_v_lcov_ign = $(code_coverage_v_lcov_ign_$(V)) +code_coverage_v_lcov_ign_ = $(code_coverage_v_lcov_ign_$(AM_DEFAULT_VERBOSITY)) +code_coverage_v_lcov_ign_0 = @echo " LCOV --remove /tmp/*" $(CODE_COVERAGE_IGNORE_PATTERN); +code_coverage_v_genhtml = $(code_coverage_v_genhtml_$(V)) +code_coverage_v_genhtml_ = $(code_coverage_v_genhtml_$(AM_DEFAULT_VERBOSITY)) +code_coverage_v_genhtml_0 = @echo " GEN " "$(CODE_COVERAGE_OUTPUT_DIRECTORY)"; +code_coverage_quiet = $(code_coverage_quiet_$(V)) +code_coverage_quiet_ = $(code_coverage_quiet_$(AM_DEFAULT_VERBOSITY)) +code_coverage_quiet_0 = --quiet + +# sanitizes the test-name: replaces with underscores: dashes and dots +code_coverage_sanitize = $(subst -,_,$(subst .,_,$(1))) + +# Use recursive makes in order to ignore errors during check +check-code-coverage: + -$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -k check + $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) code-coverage-capture + +# Capture code coverage data +code-coverage-capture: code-coverage-capture-hook + $(code_coverage_v_lcov_cap)$(LCOV) $(code_coverage_quiet) $(addprefix --directory ,$(CODE_COVERAGE_DIRECTORY)) --capture --output-file "$(CODE_COVERAGE_OUTPUT_FILE).tmp" --test-name "$(call code_coverage_sanitize,$(PACKAGE_NAME)-$(PACKAGE_VERSION))" --no-checksum --compat-libtool $(CODE_COVERAGE_LCOV_SHOPTS) $(CODE_COVERAGE_LCOV_OPTIONS) + $(code_coverage_v_lcov_ign)$(LCOV) $(code_coverage_quiet) $(addprefix --directory ,$(CODE_COVERAGE_DIRECTORY)) --remove "$(CODE_COVERAGE_OUTPUT_FILE).tmp" "/tmp/*" $(CODE_COVERAGE_IGNORE_PATTERN) --output-file "$(CODE_COVERAGE_OUTPUT_FILE)" $(CODE_COVERAGE_LCOV_SHOPTS) $(CODE_COVERAGE_LCOV_RMOPTS) + -@rm -f "$(CODE_COVERAGE_OUTPUT_FILE).tmp" + $(code_coverage_v_genhtml)LANG=C $(GENHTML) $(code_coverage_quiet) $(addprefix --prefix ,$(CODE_COVERAGE_DIRECTORY)) --output-directory "$(CODE_COVERAGE_OUTPUT_DIRECTORY)" --title "$(PACKAGE_NAME)-$(PACKAGE_VERSION) Code Coverage" --legend --show-details "$(CODE_COVERAGE_OUTPUT_FILE)" $(CODE_COVERAGE_GENHTML_OPTIONS) + @echo "file://$(abs_builddir)/$(CODE_COVERAGE_OUTPUT_DIRECTORY)/index.html" + +code-coverage-clean: + -$(LCOV) --directory $(top_builddir) -z + -rm -rf "$(CODE_COVERAGE_OUTPUT_FILE)" "$(CODE_COVERAGE_OUTPUT_FILE).tmp" "$(CODE_COVERAGE_OUTPUT_DIRECTORY)" + -find . \( -name "*.gcda" -o -name "*.gcno" -o -name "*.gcov" \) -delete + +code-coverage-dist-clean: + +AM_DISTCHECK_CONFIGURE_FLAGS := $(AM_DISTCHECK_CONFIGURE_FLAGS) --disable-code-coverage + else # ifneq ($(abs_builddir), $(abs_top_builddir)) +check-code-coverage: + +code-coverage-capture: code-coverage-capture-hook + +code-coverage-clean: + +code-coverage-dist-clean: + endif # ifeq ($(abs_builddir), $(abs_top_builddir)) +else #! CODE_COVERAGE_ENABLED +# Use recursive makes in order to ignore errors during check +check-code-coverage: + @echo "Need to reconfigure with --enable-code-coverage" +# Capture code coverage data +code-coverage-capture: code-coverage-capture-hook + @echo "Need to reconfigure with --enable-code-coverage" + +code-coverage-clean: + +code-coverage-dist-clean: + +endif #CODE_COVERAGE_ENABLED +# Hook rule executed before code-coverage-capture, overridable by the user +code-coverage-capture-hook: + +.PHONY: check-code-coverage code-coverage-capture code-coverage-dist-clean code-coverage-clean code-coverage-capture-hook From aed6a71ea6be214824158027cfcb577211f01e30 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Wed, 29 Dec 2021 17:04:45 -0500 Subject: [PATCH 22/49] save progress --- src/lib/cares_parse_srv_reply.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/lib/cares_parse_srv_reply.c b/src/lib/cares_parse_srv_reply.c index d4f61a00df..6b8849fd94 100644 --- a/src/lib/cares_parse_srv_reply.c +++ b/src/lib/cares_parse_srv_reply.c @@ -36,7 +36,7 @@ int cares_parse_srv_reply (const unsigned char *abuf, int alen, - cares_srv_reply **srv_out) + cares_srv_reply_container **srv_out) { unsigned int qdcount, ancount, i; const unsigned char *aptr, *vptr; @@ -45,8 +45,8 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, long len; char *hostname = NULL, *rr_name = NULL; char* srv_host = NULL; - cares_srv_reply *srv_head = NULL; - cares_srv_reply *srv_last = NULL; + // cares_srv_reply *srv_head = NULL; + // cares_srv_reply *srv_last = NULL; cares_srv_reply *srv_curr; /* Set *srv_out to NULL for all failure cases. */ @@ -77,6 +77,8 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, } aptr += len + QFIXEDSZ; + cares_srv_reply* + /* Examine each answer resource record (RR) in turn. */ for (i = 0; i < ancount; i++) { From baf30b85f8a26cec84282ca9b8351c599a739784 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Thu, 30 Dec 2021 01:37:48 -0500 Subject: [PATCH 23/49] save progress --- include/ares.h | 2 ++ src/lib/cares_free_container.c | 9 +++++++++ src/lib/cares_free_container.h | 8 ++++---- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/include/ares.h b/include/ares.h index e32133eb7b..660afb7f80 100644 --- a/include/ares.h +++ b/include/ares.h @@ -960,6 +960,8 @@ CARES_EXTERN const char *ares_inet_ntop(int af, const void *src, char *dst, CARES_EXTERN int ares_inet_pton(int af, const char *src, void *dst); +CARES_EXTERN void ares_free_container(void *containerptr); + #ifdef __cplusplus } diff --git a/src/lib/cares_free_container.c b/src/lib/cares_free_container.c index 64eac11af8..9564c994f5 100644 --- a/src/lib/cares_free_container.c +++ b/src/lib/cares_free_container.c @@ -15,4 +15,13 @@ #include "ares.h" #include "ares_private.h" +void cares_free_container(void *containerptr) +{ + if (containerptr == NULL) { + return; + } + + ptr = (void *)((char *)containerptr - offsetof(struct cares_container, container)); +} + for () \ No newline at end of file diff --git a/src/lib/cares_free_container.h b/src/lib/cares_free_container.h index 6754f54b7b..b4a870c3e0 100644 --- a/src/lib/cares_free_container.h +++ b/src/lib/cares_free_container.h @@ -17,15 +17,15 @@ typedef enum { CARES_CONTAINER_SRV_REPLY_CONTAINER, CARES_CONTAINER_LAST /* not used */ -} cares_datatype; +} cares_container_type; -struct cares_data_container { - cares_datatype type; /* Actual data type identifier. */ +struct cares_container { + cares_container_type type; /* Actual data type identifier. */ unsigned int mark; /* Private ares_data signature. */ union { struct cares_srv_reply_container srv_container; } container; }; -void *ares_malloc_container(cares_datatype type); \ No newline at end of file +void *ares_malloc_container(cares_container_type type); \ No newline at end of file From 6983bc335fc29ac3ba8baa32578f5495dc78a871 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Thu, 30 Dec 2021 13:35:59 -0500 Subject: [PATCH 24/49] add free routine for container --- include/ares.h | 2 +- src/lib/cares_free_container.c | 26 +++++++++++++++++++++++++- src/lib/cares_free_container.h | 2 +- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/include/ares.h b/include/ares.h index 660afb7f80..472a6c7da3 100644 --- a/include/ares.h +++ b/include/ares.h @@ -960,7 +960,7 @@ CARES_EXTERN const char *ares_inet_ntop(int af, const void *src, char *dst, CARES_EXTERN int ares_inet_pton(int af, const char *src, void *dst); -CARES_EXTERN void ares_free_container(void *containerptr); +CARES_EXTERN void cares_free_container(void *containerptr); #ifdef __cplusplus diff --git a/src/lib/cares_free_container.c b/src/lib/cares_free_container.c index 9564c994f5..fec9689d13 100644 --- a/src/lib/cares_free_container.c +++ b/src/lib/cares_free_container.c @@ -22,6 +22,30 @@ void cares_free_container(void *containerptr) } ptr = (void *)((char *)containerptr - offsetof(struct cares_container, container)); + + if (ptr->mark != ARES_DATATYPE_MARK) + return; + + for (int i = 0; i < ptr->count; ++i) + { + curr = ptr->container->replies; + switch (ptr->type) + { + case CARES_CONTAINER_SRV_REPLY_CONTAINER: + ares_free_data((cares_srv_reply *)curr[i]); + break; + + default: + return; + } + } + + ares_free(ptr->container->replies); + ares_free(ptr->container); + ares_free(ptr); } -for () \ No newline at end of file +void *cares_malloc_container(cares_container_type type) +{ + +} \ No newline at end of file diff --git a/src/lib/cares_free_container.h b/src/lib/cares_free_container.h index b4a870c3e0..712d4e15c8 100644 --- a/src/lib/cares_free_container.h +++ b/src/lib/cares_free_container.h @@ -28,4 +28,4 @@ struct cares_container { } container; }; -void *ares_malloc_container(cares_container_type type); \ No newline at end of file +void *cares_malloc_container(cares_container_type type); \ No newline at end of file From 39c8e5594aa9a2ee03a217109d841213764abde4 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Thu, 30 Dec 2021 22:04:14 -0500 Subject: [PATCH 25/49] add malloc routine for container --- src/lib/cares_free_container.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/lib/cares_free_container.c b/src/lib/cares_free_container.c index fec9689d13..28a15ca3e5 100644 --- a/src/lib/cares_free_container.c +++ b/src/lib/cares_free_container.c @@ -47,5 +47,27 @@ void cares_free_container(void *containerptr) void *cares_malloc_container(cares_container_type type) { - + struct cares_container *ptr; + + ptr = ares_malloc(sizeof(struct cares_container)); + if (!ptr) + return NULL; + + switch (type) + { + case CARES_CONTAINER_SRV_REPLY_CONTAINER: + ptr->container.srv_container.replies = NULL; + ptr->container.srv_container.curr = 0; + ptr->container.srv_container.count = 0; + break; + + default: + ares_free(ptr); + return NULL; + } + + ptr->mark = ARES_DATATYPE_MARK; + ptr->type = type; + + return &ptr->container; } \ No newline at end of file From 385a3fe683bbb7c6440818e0b13803dbc83003c8 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Thu, 30 Dec 2021 23:34:44 -0500 Subject: [PATCH 26/49] change cares_parse_srv_reply to use container --- src/lib/cares_parse_srv_reply.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/lib/cares_parse_srv_reply.c b/src/lib/cares_parse_srv_reply.c index 6b8849fd94..e5c0fdc8c8 100644 --- a/src/lib/cares_parse_srv_reply.c +++ b/src/lib/cares_parse_srv_reply.c @@ -48,10 +48,15 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, // cares_srv_reply *srv_head = NULL; // cares_srv_reply *srv_last = NULL; cares_srv_reply *srv_curr; + cares_srv_reply *srv_replies = NULL; /* Set *srv_out to NULL for all failure cases. */ *srv_out = NULL; + *srv_out = ares_malloc_container(CARES_CONTAINER_SRV_REPLY_CONTAINER); + if (*srv_out == NULL) + return ARES_ENOMEM; + /* Give up if abuf doesn't have room for a header. */ if (alen < HFIXEDSZ) return ARES_EBADRESP; @@ -64,6 +69,9 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, if (ancount == 0) return ARES_ENODATA; + *srv_out->count = ancount; + srv_replies = ares_malloc(ancount * sizeof(*srv_replies)); + /* Expand the name from the question, and skip past the question. */ aptr = abuf + HFIXEDSZ; status = ares_expand_name (aptr, abuf, alen, &hostname, &len); @@ -77,8 +85,6 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, } aptr += len + QFIXEDSZ; - cares_srv_reply* - /* Examine each answer resource record (RR) in turn. */ for (i = 0; i < ancount; i++) { @@ -122,15 +128,6 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, status = ARES_ENOMEM; break; } - if (srv_last) - { - cares_srv_reply_set_next(srv_last, srv_curr); - } - else - { - srv_head = srv_curr; - } - srv_last = srv_curr; vptr = aptr; cares_srv_reply_set_priority(srv_curr, DNS__16BIT(vptr)); @@ -145,6 +142,7 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, if (status != ARES_SUCCESS) break; cares_srv_reply_set_host(srv_curr, srv_host); + srv_replies[i] = srv_curr; } else if (rr_type != T_CNAME) { @@ -174,6 +172,6 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, } /* everything looks fine, return the data */ - *srv_out = srv_head; + *srv_out->replies = srv_replies; return ARES_SUCCESS; } From 697b9fdda14bb2b9a08df73965c04a65a02e7c07 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Fri, 31 Dec 2021 01:04:01 -0500 Subject: [PATCH 27/49] change ares_parse_srv_reply to use container --- src/lib/ares_parse_srv_reply.c | 11 +- src/lib/cares_container.c | 16 +- src/lib/cares_parse_srv_reply.c | 12 +- test/ares-test-parse-srv.cc | 1058 +++++++++++++++---------------- 4 files changed, 560 insertions(+), 537 deletions(-) diff --git a/src/lib/ares_parse_srv_reply.c b/src/lib/ares_parse_srv_reply.c index d2934b6a4b..52f23f58ed 100644 --- a/src/lib/ares_parse_srv_reply.c +++ b/src/lib/ares_parse_srv_reply.c @@ -49,7 +49,7 @@ ares_parse_srv_reply (const unsigned char *abuf, int alen, struct ares_srv_reply *srv_curr = NULL; struct ares_srv_reply *srv_last = NULL; const cares_srv_reply *csrv_curr = NULL; - cares_srv_reply *csrv_out = NULL; + cares_srv_reply_container *csrv_out = NULL; /* Set *srv_out to NULL for all failure cases. */ *srv_out = NULL; @@ -60,13 +60,14 @@ ares_parse_srv_reply (const unsigned char *abuf, int alen, if (status != ARES_SUCCESS) { if (csrv_out) - ares_free_data (csrv_out); + ares_free_container(csrv_out); return status; } - /* iterate through the cares_srv_reply list and + /* iterate through the cares_srv_reply_container and * create a new ares_srv_reply */ - for (csrv_curr = csrv_out; csrv_curr; + for (csrv_curr = cares_srv_reply_container_get_first(csrv_out); + !cares_srv_reply_container_at_end(csrv_out); csrv_curr = cares_srv_reply_get_next(csrv_curr)) { srv_curr = ares_malloc_data(ARES_DATATYPE_SRV_REPLY); @@ -100,7 +101,7 @@ ares_parse_srv_reply (const unsigned char *abuf, int alen, if (csrv_out) { - ares_free_data (csrv_out); + ares_free_container(csrv_out); } /* clean up on error */ diff --git a/src/lib/cares_container.c b/src/lib/cares_container.c index f3e267b179..527630cf17 100644 --- a/src/lib/cares_container.c +++ b/src/lib/cares_container.c @@ -35,7 +35,9 @@ cares_srv_reply_container_get_next(const cares_srv_reply_container* container) return &container->replies[cares_srv_reply_container_get_count(container) - 1]; } - container->curr = container->curr + 1; + cares_srv_reply_container_set_curr(container, + cares_srv_reply_container_get_curr(container) + 1); + return &container->replies[container->curr]; } @@ -56,6 +58,18 @@ cares_srv_reply_container_get_count(const cares_srv_reply_container* container) return container->count; } +const int +cares_srv_reply_container_get_curr(const cares_srv_reply_container* container) +{ + return container->curr; +} + +const bool +cares_srv_reply_container_at_end(const cares_srv_reply_container* container) +{ + return cares_srv_reply_get_curr(container) == cares_srv_reply_get_count(container); +} + void cares_srv_reply_container_set_replies(cares_srv_reply_container* container, cares_srv_reply* replies) { diff --git a/src/lib/cares_parse_srv_reply.c b/src/lib/cares_parse_srv_reply.c index e5c0fdc8c8..af3ee56ff1 100644 --- a/src/lib/cares_parse_srv_reply.c +++ b/src/lib/cares_parse_srv_reply.c @@ -49,6 +49,7 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, // cares_srv_reply *srv_last = NULL; cares_srv_reply *srv_curr; cares_srv_reply *srv_replies = NULL; + int count; /* Set *srv_out to NULL for all failure cases. */ *srv_out = NULL; @@ -88,6 +89,7 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, /* Examine each answer resource record (RR) in turn. */ for (i = 0; i < ancount; i++) { + count = i; /* Decode the RR up to the data field. */ status = ares_expand_name (aptr, abuf, alen, &rr_name, &len); if (status != ARES_SUCCESS) @@ -166,8 +168,14 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, /* clean up on error */ if (status != ARES_SUCCESS) { - if (srv_head) - ares_free_data (srv_head); + if (srv_replies) + { + for(i = 0; i <= count; ++i) { + if (srv_replies[i]) + ares_free_data(srv_replies[i]); + } + ares_free(srv_replies); + } return status; } diff --git a/test/ares-test-parse-srv.cc b/test/ares-test-parse-srv.cc index c4b484cc75..a76a5f801a 100644 --- a/test/ares-test-parse-srv.cc +++ b/test/ares-test-parse-srv.cc @@ -35,535 +35,535 @@ TEST_F(LibraryTest, ParseSrvReplyOK) { ares_free_data(srv); } -TEST_F(LibraryTest, ParseCSrvReplyOK) { - DNSPacket pkt; - pkt.set_qid(0x1234).set_response().set_aa() - .add_question(new DNSQuestion("example.com", T_SRV)) - .add_answer(new DNSSrvRR("example.com", 100, 10, 20, 30, "srv.example.com")) - .add_answer(new DNSSrvRR("example.com", 100, 11, 21, 31, "srv2.example.com")); - std::vector data = pkt.data(); - - cares_srv_reply* srv = nullptr; - EXPECT_EQ(ARES_SUCCESS, cares_parse_srv_reply(data.data(), data.size(), &srv)); - ASSERT_NE(nullptr, srv); - - EXPECT_EQ("srv.example.com", std::string(cares_srv_reply_get_host(srv))); - EXPECT_EQ(10, cares_srv_reply_get_priority(srv)); - EXPECT_EQ(20, cares_srv_reply_get_weight(srv)); - EXPECT_EQ(30, cares_srv_reply_get_port(srv)); - EXPECT_EQ(100, cares_srv_reply_get_ttl(srv)); - - const cares_srv_reply* srv2 = cares_srv_reply_get_next(srv); - ASSERT_NE(nullptr, srv2); - EXPECT_EQ("srv2.example.com", std::string(cares_srv_reply_get_host(srv2))); - EXPECT_EQ(11, cares_srv_reply_get_priority(srv2)); - EXPECT_EQ(21, cares_srv_reply_get_weight(srv2)); - EXPECT_EQ(31, cares_srv_reply_get_port(srv2)); - EXPECT_EQ(100, cares_srv_reply_get_ttl(srv2)); - EXPECT_EQ(nullptr, cares_srv_reply_get_next(srv2)); - ares_free_data(srv); -} - -TEST_F(LibraryTest, ParseSrvReplySingle) { - DNSPacket pkt; - pkt.set_qid(0x1234).set_response().set_aa() - .add_question(new DNSQuestion("example.abc.def.com", T_SRV)) - .add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")) - .add_auth(new DNSNsRR("abc.def.com", 44, "else1.where.com")) - .add_auth(new DNSNsRR("abc.def.com", 44, "else2.where.com")) - .add_auth(new DNSNsRR("abc.def.com", 44, "else3.where.com")) - .add_auth(new DNSNsRR("abc.def.com", 44, "else4.where.com")) - .add_auth(new DNSNsRR("abc.def.com", 44, "else5.where.com")) - .add_additional(new DNSARR("else2.where.com", 42, {172,19,0,1})) - .add_additional(new DNSARR("else5.where.com", 42, {172,19,0,2})); - std::vector data = pkt.data(); - - struct ares_srv_reply* srv = nullptr; - EXPECT_EQ(ARES_SUCCESS, ares_parse_srv_reply(data.data(), data.size(), &srv)); - ASSERT_NE(nullptr, srv); - - EXPECT_EQ("example.abc.def.com", std::string(srv->host)); - EXPECT_EQ(0, srv->priority); - EXPECT_EQ(10, srv->weight); - EXPECT_EQ(8160, srv->port); - EXPECT_EQ(nullptr, srv->next); - - ares_free_data(srv); -} - -TEST_F(LibraryTest, ParseCSrvReplySingle) { - DNSPacket pkt; - pkt.set_qid(0x1234).set_response().set_aa() - .add_question(new DNSQuestion("example.abc.def.com", T_SRV)) - .add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")) - .add_auth(new DNSNsRR("abc.def.com", 44, "else1.where.com")) - .add_auth(new DNSNsRR("abc.def.com", 44, "else2.where.com")) - .add_auth(new DNSNsRR("abc.def.com", 44, "else3.where.com")) - .add_auth(new DNSNsRR("abc.def.com", 44, "else4.where.com")) - .add_auth(new DNSNsRR("abc.def.com", 44, "else5.where.com")) - .add_additional(new DNSARR("else2.where.com", 42, {172,19,0,1})) - .add_additional(new DNSARR("else5.where.com", 42, {172,19,0,2})); - std::vector data = pkt.data(); - - cares_srv_reply* srv = nullptr; - EXPECT_EQ(ARES_SUCCESS, cares_parse_srv_reply(data.data(), data.size(), &srv)); - ASSERT_NE(nullptr, srv); - - EXPECT_EQ("example.abc.def.com", std::string(cares_srv_reply_get_host(srv))); - EXPECT_EQ(0, cares_srv_reply_get_priority(srv)); - EXPECT_EQ(10, cares_srv_reply_get_weight(srv)); - EXPECT_EQ(8160, cares_srv_reply_get_port(srv)); - EXPECT_EQ(180, cares_srv_reply_get_ttl(srv)); - EXPECT_EQ(nullptr, cares_srv_reply_get_next(srv)); - - ares_free_data(srv); -} - -TEST_F(LibraryTest, ParseSrvReplyMalformed) { - std::vector data = { - 0x12, 0x34, // qid - 0x84, // response + query + AA + not-TC + not-RD - 0x00, // not-RA + not-Z + not-AD + not-CD + rc=NoError - 0x00, 0x01, // num questions - 0x00, 0x01, // num answer RRs - 0x00, 0x00, // num authority RRs - 0x00, 0x00, // num additional RRs - // Question - 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', - 0x03, 'c', 'o', 'm', - 0x00, - 0x00, 0x21, // type SRV - 0x00, 0x01, // class IN - // Answer 1 - 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', - 0x03, 'c', 'o', 'm', - 0x00, - 0x00, 0x21, // RR type - 0x00, 0x01, // class IN - 0x01, 0x02, 0x03, 0x04, // TTL - 0x00, 0x04, // rdata length -- too short - 0x02, 0x03, 0x04, 0x05, - }; - - struct ares_srv_reply* srv = nullptr; - EXPECT_EQ(ARES_EBADRESP, ares_parse_srv_reply(data.data(), data.size(), &srv)); - ASSERT_EQ(nullptr, srv); -} - -TEST_F(LibraryTest, ParseCSrvReplyMalformed) { - std::vector data = { - 0x12, 0x34, // qid - 0x84, // response + query + AA + not-TC + not-RD - 0x00, // not-RA + not-Z + not-AD + not-CD + rc=NoError - 0x00, 0x01, // num questions - 0x00, 0x01, // num answer RRs - 0x00, 0x00, // num authority RRs - 0x00, 0x00, // num additional RRs - // Question - 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', - 0x03, 'c', 'o', 'm', - 0x00, - 0x00, 0x21, // type SRV - 0x00, 0x01, // class IN - // Answer 1 - 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', - 0x03, 'c', 'o', 'm', - 0x00, - 0x00, 0x21, // RR type - 0x00, 0x01, // class IN - 0x01, 0x02, 0x03, 0x04, // TTL - 0x00, 0x04, // rdata length -- too short - 0x02, 0x03, 0x04, 0x05, - }; - - cares_srv_reply* srv = nullptr; - EXPECT_EQ(ARES_EBADRESP, cares_parse_srv_reply(data.data(), data.size(), &srv)); - ASSERT_EQ(nullptr, srv); -} - -TEST_F(LibraryTest, ParseSrvReplyMultiple) { - DNSPacket pkt; - pkt.set_qid(0x1234).set_response().set_ra().set_rd() - .add_question(new DNSQuestion("srv.example.com", T_SRV)) - .add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 6789, "a1.srv.example.com")) - .add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 4567, "a2.srv.example.com")) - .add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 5678, "a3.srv.example.com")) - .add_auth(new DNSNsRR("example.com", 300, "ns1.example.com")) - .add_auth(new DNSNsRR("example.com", 300, "ns2.example.com")) - .add_auth(new DNSNsRR("example.com", 300, "ns3.example.com")) - .add_additional(new DNSARR("a1.srv.example.com", 300, {172,19,1,1})) - .add_additional(new DNSARR("a2.srv.example.com", 300, {172,19,1,2})) - .add_additional(new DNSARR("a3.srv.example.com", 300, {172,19,1,3})) - .add_additional(new DNSARR("n1.example.com", 300, {172,19,0,1})) - .add_additional(new DNSARR("n2.example.com", 300, {172,19,0,2})) - .add_additional(new DNSARR("n3.example.com", 300, {172,19,0,3})); - std::vector data = pkt.data(); - - struct ares_srv_reply* srv0 = nullptr; - EXPECT_EQ(ARES_SUCCESS, ares_parse_srv_reply(data.data(), data.size(), &srv0)); - ASSERT_NE(nullptr, srv0); - struct ares_srv_reply* srv = srv0; - - EXPECT_EQ("a1.srv.example.com", std::string(srv->host)); - EXPECT_EQ(0, srv->priority); - EXPECT_EQ(5, srv->weight); - EXPECT_EQ(6789, srv->port); - EXPECT_NE(nullptr, srv->next); - srv = srv->next; - - EXPECT_EQ("a2.srv.example.com", std::string(srv->host)); - EXPECT_EQ(0, srv->priority); - EXPECT_EQ(5, srv->weight); - EXPECT_EQ(4567, srv->port); - EXPECT_NE(nullptr, srv->next); - srv = srv->next; - - EXPECT_EQ("a3.srv.example.com", std::string(srv->host)); - EXPECT_EQ(0, srv->priority); - EXPECT_EQ(5, srv->weight); - EXPECT_EQ(5678, srv->port); - EXPECT_EQ(nullptr, srv->next); - - ares_free_data(srv0); -} - -TEST_F(LibraryTest, ParseCSrvReplyMultiple) { - DNSPacket pkt; - pkt.set_qid(0x1234).set_response().set_ra().set_rd() - .add_question(new DNSQuestion("srv.example.com", T_SRV)) - .add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 6789, "a1.srv.example.com")) - .add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 4567, "a2.srv.example.com")) - .add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 5678, "a3.srv.example.com")) - .add_auth(new DNSNsRR("example.com", 300, "ns1.example.com")) - .add_auth(new DNSNsRR("example.com", 300, "ns2.example.com")) - .add_auth(new DNSNsRR("example.com", 300, "ns3.example.com")) - .add_additional(new DNSARR("a1.srv.example.com", 300, {172,19,1,1})) - .add_additional(new DNSARR("a2.srv.example.com", 300, {172,19,1,2})) - .add_additional(new DNSARR("a3.srv.example.com", 300, {172,19,1,3})) - .add_additional(new DNSARR("n1.example.com", 300, {172,19,0,1})) - .add_additional(new DNSARR("n2.example.com", 300, {172,19,0,2})) - .add_additional(new DNSARR("n3.example.com", 300, {172,19,0,3})); - std::vector data = pkt.data(); - - cares_srv_reply* srv0 = nullptr; - EXPECT_EQ(ARES_SUCCESS, cares_parse_srv_reply(data.data(), data.size(), &srv0)); - ASSERT_NE(nullptr, srv0); - const cares_srv_reply* srv = srv0; - - EXPECT_EQ("a1.srv.example.com", std::string(cares_srv_reply_get_host(srv))); - EXPECT_EQ(0, cares_srv_reply_get_priority(srv)); - EXPECT_EQ(5, cares_srv_reply_get_weight(srv)); - EXPECT_EQ(6789, cares_srv_reply_get_port(srv)); - EXPECT_EQ(300, cares_srv_reply_get_ttl(srv)); - EXPECT_NE(nullptr, cares_srv_reply_get_next(srv)); - srv = cares_srv_reply_get_next(srv); - - EXPECT_EQ("a2.srv.example.com", std::string(cares_srv_reply_get_host(srv))); - EXPECT_EQ(0, cares_srv_reply_get_priority(srv)); - EXPECT_EQ(5, cares_srv_reply_get_weight(srv)); - EXPECT_EQ(4567, cares_srv_reply_get_port(srv)); - EXPECT_EQ(300, cares_srv_reply_get_ttl(srv)); - EXPECT_NE(nullptr, cares_srv_reply_get_next(srv)); - srv = cares_srv_reply_get_next(srv); - - EXPECT_EQ("a3.srv.example.com", std::string(cares_srv_reply_get_host(srv))); - EXPECT_EQ(0, cares_srv_reply_get_priority(srv)); - EXPECT_EQ(5, cares_srv_reply_get_weight(srv)); - EXPECT_EQ(5678, cares_srv_reply_get_port(srv)); - EXPECT_EQ(300, cares_srv_reply_get_ttl(srv)); - EXPECT_EQ(nullptr, cares_srv_reply_get_next(srv)); - - ares_free_data(srv0); -} - -TEST_F(LibraryTest, ParseSrvReplyCname) { - DNSPacket pkt; - pkt.set_qid(0x1234).set_response().set_aa() - .add_question(new DNSQuestion("example.abc.def.com", T_SRV)) - .add_answer(new DNSCnameRR("example.abc.def.com", 300, "cname.abc.def.com")) - .add_answer(new DNSSrvRR("cname.abc.def.com", 300, 0, 10, 1234, "srv.abc.def.com")) - .add_auth(new DNSNsRR("abc.def.com", 44, "else1.where.com")) - .add_auth(new DNSNsRR("abc.def.com", 44, "else2.where.com")) - .add_auth(new DNSNsRR("abc.def.com", 44, "else3.where.com")) - .add_additional(new DNSARR("example.abc.def.com", 300, {172,19,0,1})) - .add_additional(new DNSARR("else1.where.com", 42, {172,19,0,1})) - .add_additional(new DNSARR("else2.where.com", 42, {172,19,0,2})) - .add_additional(new DNSARR("else3.where.com", 42, {172,19,0,3})); - std::vector data = pkt.data(); - - struct ares_srv_reply* srv = nullptr; - EXPECT_EQ(ARES_SUCCESS, ares_parse_srv_reply(data.data(), data.size(), &srv)); - ASSERT_NE(nullptr, srv); - - EXPECT_EQ("srv.abc.def.com", std::string(srv->host)); - EXPECT_EQ(0, srv->priority); - EXPECT_EQ(10, srv->weight); - EXPECT_EQ(1234, srv->port); - EXPECT_EQ(nullptr, srv->next); - - ares_free_data(srv); -} - -TEST_F(LibraryTest, ParseCSrvReplyCname) { - DNSPacket pkt; - pkt.set_qid(0x1234).set_response().set_aa() - .add_question(new DNSQuestion("example.abc.def.com", T_SRV)) - .add_answer(new DNSCnameRR("example.abc.def.com", 300, "cname.abc.def.com")) - .add_answer(new DNSSrvRR("cname.abc.def.com", 300, 0, 10, 1234, "srv.abc.def.com")) - .add_auth(new DNSNsRR("abc.def.com", 44, "else1.where.com")) - .add_auth(new DNSNsRR("abc.def.com", 44, "else2.where.com")) - .add_auth(new DNSNsRR("abc.def.com", 44, "else3.where.com")) - .add_additional(new DNSARR("example.abc.def.com", 300, {172,19,0,1})) - .add_additional(new DNSARR("else1.where.com", 42, {172,19,0,1})) - .add_additional(new DNSARR("else2.where.com", 42, {172,19,0,2})) - .add_additional(new DNSARR("else3.where.com", 42, {172,19,0,3})); - std::vector data = pkt.data(); - - cares_srv_reply* srv = nullptr; - EXPECT_EQ(ARES_SUCCESS, cares_parse_srv_reply(data.data(), data.size(), &srv)); - ASSERT_NE(nullptr, srv); - - EXPECT_EQ("srv.abc.def.com", std::string(cares_srv_reply_get_host(srv))); - EXPECT_EQ(0, cares_srv_reply_get_priority(srv)); - EXPECT_EQ(10, cares_srv_reply_get_weight(srv)); - EXPECT_EQ(1234, cares_srv_reply_get_port(srv)); - EXPECT_EQ(300, cares_srv_reply_get_ttl(srv)); - EXPECT_EQ(nullptr, cares_srv_reply_get_next(srv)); - - ares_free_data(srv); -} - -TEST_F(LibraryTest, ParseSrvReplyCnameMultiple) { - DNSPacket pkt; - pkt.set_qid(0x1234).set_response().set_ra().set_rd() - .add_question(new DNSQuestion("query.example.com", T_SRV)) - .add_answer(new DNSCnameRR("query.example.com", 300, "srv.example.com")) - .add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 6789, "a1.srv.example.com")) - .add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 4567, "a2.srv.example.com")) - .add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 5678, "a3.srv.example.com")) - .add_auth(new DNSNsRR("example.com", 300, "ns1.example.com")) - .add_auth(new DNSNsRR("example.com", 300, "ns2.example.com")) - .add_auth(new DNSNsRR("example.com", 300, "ns3.example.com")) - .add_additional(new DNSARR("a1.srv.example.com", 300, {172,19,1,1})) - .add_additional(new DNSARR("a2.srv.example.com", 300, {172,19,1,2})) - .add_additional(new DNSARR("a3.srv.example.com", 300, {172,19,1,3})) - .add_additional(new DNSARR("n1.example.com", 300, {172,19,0,1})) - .add_additional(new DNSARR("n2.example.com", 300, {172,19,0,2})) - .add_additional(new DNSARR("n3.example.com", 300, {172,19,0,3})); - std::vector data = pkt.data(); - - struct ares_srv_reply* srv0 = nullptr; - EXPECT_EQ(ARES_SUCCESS, ares_parse_srv_reply(data.data(), data.size(), &srv0)); - ASSERT_NE(nullptr, srv0); - struct ares_srv_reply* srv = srv0; - - EXPECT_EQ("a1.srv.example.com", std::string(srv->host)); - EXPECT_EQ(0, srv->priority); - EXPECT_EQ(5, srv->weight); - EXPECT_EQ(6789, srv->port); - EXPECT_NE(nullptr, srv->next); - srv = srv->next; - - EXPECT_EQ("a2.srv.example.com", std::string(srv->host)); - EXPECT_EQ(0, srv->priority); - EXPECT_EQ(5, srv->weight); - EXPECT_EQ(4567, srv->port); - EXPECT_NE(nullptr, srv->next); - srv = srv->next; - - EXPECT_EQ("a3.srv.example.com", std::string(srv->host)); - EXPECT_EQ(0, srv->priority); - EXPECT_EQ(5, srv->weight); - EXPECT_EQ(5678, srv->port); - EXPECT_EQ(nullptr, srv->next); - - ares_free_data(srv0); -} - -TEST_F(LibraryTest, ParseCSrvReplyCnameMultiple) { - DNSPacket pkt; - pkt.set_qid(0x1234).set_response().set_ra().set_rd() - .add_question(new DNSQuestion("query.example.com", T_SRV)) - .add_answer(new DNSCnameRR("query.example.com", 300, "srv.example.com")) - .add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 6789, "a1.srv.example.com")) - .add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 4567, "a2.srv.example.com")) - .add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 5678, "a3.srv.example.com")) - .add_auth(new DNSNsRR("example.com", 300, "ns1.example.com")) - .add_auth(new DNSNsRR("example.com", 300, "ns2.example.com")) - .add_auth(new DNSNsRR("example.com", 300, "ns3.example.com")) - .add_additional(new DNSARR("a1.srv.example.com", 300, {172,19,1,1})) - .add_additional(new DNSARR("a2.srv.example.com", 300, {172,19,1,2})) - .add_additional(new DNSARR("a3.srv.example.com", 300, {172,19,1,3})) - .add_additional(new DNSARR("n1.example.com", 300, {172,19,0,1})) - .add_additional(new DNSARR("n2.example.com", 300, {172,19,0,2})) - .add_additional(new DNSARR("n3.example.com", 300, {172,19,0,3})); - std::vector data = pkt.data(); - - cares_srv_reply* srv0 = nullptr; - EXPECT_EQ(ARES_SUCCESS, cares_parse_srv_reply(data.data(), data.size(), &srv0)); - ASSERT_NE(nullptr, srv0); - const cares_srv_reply* srv = srv0; - - EXPECT_EQ("a1.srv.example.com", std::string(cares_srv_reply_get_host(srv))); - EXPECT_EQ(0, cares_srv_reply_get_priority(srv)); - EXPECT_EQ(5, cares_srv_reply_get_weight(srv)); - EXPECT_EQ(6789, cares_srv_reply_get_port(srv)); - EXPECT_EQ(300, cares_srv_reply_get_ttl(srv)); - EXPECT_NE(nullptr, cares_srv_reply_get_next(srv)); - srv = cares_srv_reply_get_next(srv); - - EXPECT_EQ("a2.srv.example.com", std::string(cares_srv_reply_get_host(srv))); - EXPECT_EQ(0, cares_srv_reply_get_priority(srv)); - EXPECT_EQ(5, cares_srv_reply_get_weight(srv)); - EXPECT_EQ(4567, cares_srv_reply_get_port(srv)); - EXPECT_EQ(300, cares_srv_reply_get_ttl(srv)); - EXPECT_NE(nullptr, cares_srv_reply_get_next(srv)); - srv = cares_srv_reply_get_next(srv); - - EXPECT_EQ("a3.srv.example.com", std::string(cares_srv_reply_get_host(srv))); - EXPECT_EQ(0, cares_srv_reply_get_priority(srv)); - EXPECT_EQ(5, cares_srv_reply_get_weight(srv)); - EXPECT_EQ(5678, cares_srv_reply_get_port(srv)); - EXPECT_EQ(300, cares_srv_reply_get_ttl(srv)); - EXPECT_EQ(nullptr, cares_srv_reply_get_next(srv)); - - ares_free_data(srv0); -} - -TEST_F(LibraryTest, ParseSrvReplyErrors) { - DNSPacket pkt; - pkt.set_qid(0x1234).set_response().set_aa() - .add_question(new DNSQuestion("example.abc.def.com", T_SRV)) - .add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")); - std::vector data; - struct ares_srv_reply* srv = nullptr; - - // No question. - pkt.questions_.clear(); - data = pkt.data(); - EXPECT_EQ(ARES_EBADRESP, ares_parse_srv_reply(data.data(), data.size(), &srv)); - pkt.add_question(new DNSQuestion("example.abc.def.com", T_SRV)); -#ifdef DISABLED - // Question != answer - pkt.questions_.clear(); - pkt.add_question(new DNSQuestion("Axample.com", T_SRV)); - data = pkt.data(); - EXPECT_EQ(ARES_ENODATA, ares_parse_srv_reply(data.data(), data.size(), &srv)); - pkt.questions_.clear(); - pkt.add_question(new DNSQuestion("example.com", T_SRV)); -#endif - // Two questions. - pkt.add_question(new DNSQuestion("example.abc.def.com", T_SRV)); - data = pkt.data(); - EXPECT_EQ(ARES_EBADRESP, ares_parse_srv_reply(data.data(), data.size(), &srv)); - pkt.questions_.clear(); - pkt.add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR)); - // Wrong sort of answer. - pkt.answers_.clear(); - pkt.add_answer(new DNSMxRR("example.com", 100, 100, "mx1.example.com")); - data = pkt.data(); - EXPECT_EQ(ARES_ENODATA, ares_parse_srv_reply(data.data(), data.size(), &srv)); - EXPECT_EQ(nullptr, srv); - pkt.answers_.clear(); - pkt.add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")); - // No answer. - pkt.answers_.clear(); - data = pkt.data(); - EXPECT_EQ(ARES_ENODATA, ares_parse_srv_reply(data.data(), data.size(), &srv)); - pkt.add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")); - // Truncated packets. - data = pkt.data(); - for (size_t len = 1; len < data.size(); len++) { - int rc = ares_parse_srv_reply(data.data(), len, &srv); - EXPECT_TRUE(rc == ARES_EBADRESP || rc == ARES_EBADNAME); - } -} - -TEST_F(LibraryTest, ParseCSrvReplyErrors) { - DNSPacket pkt; - pkt.set_qid(0x1234).set_response().set_aa() - .add_question(new DNSQuestion("example.abc.def.com", T_SRV)) - .add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")); - std::vector data; - cares_srv_reply* srv = nullptr; - - // No question. - pkt.questions_.clear(); - data = pkt.data(); - EXPECT_EQ(ARES_EBADRESP, cares_parse_srv_reply(data.data(), data.size(), &srv)); - pkt.add_question(new DNSQuestion("example.abc.def.com", T_SRV)); - -#ifdef DISABLED - // Question != answer - pkt.questions_.clear(); - pkt.add_question(new DNSQuestion("Axample.com", T_SRV)); - data = pkt.data(); - EXPECT_EQ(ARES_ENODATA, cares_parse_srv_reply(data.data(), data.size(), &srv)); - pkt.questions_.clear(); - pkt.add_question(new DNSQuestion("example.com", T_SRV)); -#endif - - // Two questions. - pkt.add_question(new DNSQuestion("example.abc.def.com", T_SRV)); - data = pkt.data(); - EXPECT_EQ(ARES_EBADRESP, cares_parse_srv_reply(data.data(), data.size(), &srv)); - pkt.questions_.clear(); - pkt.add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR)); - - // Wrong sort of answer. - pkt.answers_.clear(); - pkt.add_answer(new DNSMxRR("example.com", 100, 100, "mx1.example.com")); - data = pkt.data(); - EXPECT_EQ(ARES_ENODATA, cares_parse_srv_reply(data.data(), data.size(), &srv)); - EXPECT_EQ(nullptr, srv); - pkt.answers_.clear(); - pkt.add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")); - - // No answer. - pkt.answers_.clear(); - data = pkt.data(); - EXPECT_EQ(ARES_ENODATA, cares_parse_srv_reply(data.data(), data.size(), &srv)); - pkt.add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")); - - // Truncated packets. - data = pkt.data(); - for (size_t len = 1; len < data.size(); len++) { - int rc = cares_parse_srv_reply(data.data(), len, &srv); - EXPECT_TRUE(rc == ARES_EBADRESP || rc == ARES_EBADNAME); - } -} - -TEST_F(LibraryTest, ParseSrvReplyAllocFail) { - DNSPacket pkt; - pkt.set_qid(0x1234).set_response().set_aa() - .add_question(new DNSQuestion("example.abc.def.com", T_SRV)) - .add_answer(new DNSCnameRR("example.com", 300, "c.example.com")) - .add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")); - std::vector data = pkt.data(); - struct ares_srv_reply* srv = nullptr; - - for (int ii = 1; ii <= 5; ii++) { - ClearFails(); - SetAllocFail(ii); - EXPECT_EQ(ARES_ENOMEM, ares_parse_srv_reply(data.data(), data.size(), &srv)) << ii; - } -} - -TEST_F(LibraryTest, ParseCSrvReplyAllocFail) { - DNSPacket pkt; - pkt.set_qid(0x1234).set_response().set_aa() - .add_question(new DNSQuestion("example.abc.def.com", T_SRV)) - .add_answer(new DNSCnameRR("example.com", 300, "c.example.com")) - .add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")); - std::vector data = pkt.data(); - cares_srv_reply* srv = nullptr; - - for (int ii = 1; ii <= 5; ii++) { - ClearFails(); - SetAllocFail(ii); - EXPECT_EQ(ARES_ENOMEM, cares_parse_srv_reply(data.data(), data.size(), &srv)) << ii; - } -} +// TEST_F(LibraryTest, ParseCSrvReplyOK) { +// DNSPacket pkt; +// pkt.set_qid(0x1234).set_response().set_aa() +// .add_question(new DNSQuestion("example.com", T_SRV)) +// .add_answer(new DNSSrvRR("example.com", 100, 10, 20, 30, "srv.example.com")) +// .add_answer(new DNSSrvRR("example.com", 100, 11, 21, 31, "srv2.example.com")); +// std::vector data = pkt.data(); + +// cares_srv_reply* srv = nullptr; +// EXPECT_EQ(ARES_SUCCESS, cares_parse_srv_reply(data.data(), data.size(), &srv)); +// ASSERT_NE(nullptr, srv); + +// EXPECT_EQ("srv.example.com", std::string(cares_srv_reply_get_host(srv))); +// EXPECT_EQ(10, cares_srv_reply_get_priority(srv)); +// EXPECT_EQ(20, cares_srv_reply_get_weight(srv)); +// EXPECT_EQ(30, cares_srv_reply_get_port(srv)); +// EXPECT_EQ(100, cares_srv_reply_get_ttl(srv)); + +// const cares_srv_reply* srv2 = cares_srv_reply_get_next(srv); +// ASSERT_NE(nullptr, srv2); +// EXPECT_EQ("srv2.example.com", std::string(cares_srv_reply_get_host(srv2))); +// EXPECT_EQ(11, cares_srv_reply_get_priority(srv2)); +// EXPECT_EQ(21, cares_srv_reply_get_weight(srv2)); +// EXPECT_EQ(31, cares_srv_reply_get_port(srv2)); +// EXPECT_EQ(100, cares_srv_reply_get_ttl(srv2)); +// EXPECT_EQ(nullptr, cares_srv_reply_get_next(srv2)); +// ares_free_data(srv); +// } + +// TEST_F(LibraryTest, ParseSrvReplySingle) { +// DNSPacket pkt; +// pkt.set_qid(0x1234).set_response().set_aa() +// .add_question(new DNSQuestion("example.abc.def.com", T_SRV)) +// .add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")) +// .add_auth(new DNSNsRR("abc.def.com", 44, "else1.where.com")) +// .add_auth(new DNSNsRR("abc.def.com", 44, "else2.where.com")) +// .add_auth(new DNSNsRR("abc.def.com", 44, "else3.where.com")) +// .add_auth(new DNSNsRR("abc.def.com", 44, "else4.where.com")) +// .add_auth(new DNSNsRR("abc.def.com", 44, "else5.where.com")) +// .add_additional(new DNSARR("else2.where.com", 42, {172,19,0,1})) +// .add_additional(new DNSARR("else5.where.com", 42, {172,19,0,2})); +// std::vector data = pkt.data(); + +// struct ares_srv_reply* srv = nullptr; +// EXPECT_EQ(ARES_SUCCESS, ares_parse_srv_reply(data.data(), data.size(), &srv)); +// ASSERT_NE(nullptr, srv); + +// EXPECT_EQ("example.abc.def.com", std::string(srv->host)); +// EXPECT_EQ(0, srv->priority); +// EXPECT_EQ(10, srv->weight); +// EXPECT_EQ(8160, srv->port); +// EXPECT_EQ(nullptr, srv->next); + +// ares_free_data(srv); +// } + +// TEST_F(LibraryTest, ParseCSrvReplySingle) { +// DNSPacket pkt; +// pkt.set_qid(0x1234).set_response().set_aa() +// .add_question(new DNSQuestion("example.abc.def.com", T_SRV)) +// .add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")) +// .add_auth(new DNSNsRR("abc.def.com", 44, "else1.where.com")) +// .add_auth(new DNSNsRR("abc.def.com", 44, "else2.where.com")) +// .add_auth(new DNSNsRR("abc.def.com", 44, "else3.where.com")) +// .add_auth(new DNSNsRR("abc.def.com", 44, "else4.where.com")) +// .add_auth(new DNSNsRR("abc.def.com", 44, "else5.where.com")) +// .add_additional(new DNSARR("else2.where.com", 42, {172,19,0,1})) +// .add_additional(new DNSARR("else5.where.com", 42, {172,19,0,2})); +// std::vector data = pkt.data(); + +// cares_srv_reply* srv = nullptr; +// EXPECT_EQ(ARES_SUCCESS, cares_parse_srv_reply(data.data(), data.size(), &srv)); +// ASSERT_NE(nullptr, srv); + +// EXPECT_EQ("example.abc.def.com", std::string(cares_srv_reply_get_host(srv))); +// EXPECT_EQ(0, cares_srv_reply_get_priority(srv)); +// EXPECT_EQ(10, cares_srv_reply_get_weight(srv)); +// EXPECT_EQ(8160, cares_srv_reply_get_port(srv)); +// EXPECT_EQ(180, cares_srv_reply_get_ttl(srv)); +// EXPECT_EQ(nullptr, cares_srv_reply_get_next(srv)); + +// ares_free_data(srv); +// } + +// TEST_F(LibraryTest, ParseSrvReplyMalformed) { +// std::vector data = { +// 0x12, 0x34, // qid +// 0x84, // response + query + AA + not-TC + not-RD +// 0x00, // not-RA + not-Z + not-AD + not-CD + rc=NoError +// 0x00, 0x01, // num questions +// 0x00, 0x01, // num answer RRs +// 0x00, 0x00, // num authority RRs +// 0x00, 0x00, // num additional RRs +// // Question +// 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', +// 0x03, 'c', 'o', 'm', +// 0x00, +// 0x00, 0x21, // type SRV +// 0x00, 0x01, // class IN +// // Answer 1 +// 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', +// 0x03, 'c', 'o', 'm', +// 0x00, +// 0x00, 0x21, // RR type +// 0x00, 0x01, // class IN +// 0x01, 0x02, 0x03, 0x04, // TTL +// 0x00, 0x04, // rdata length -- too short +// 0x02, 0x03, 0x04, 0x05, +// }; + +// struct ares_srv_reply* srv = nullptr; +// EXPECT_EQ(ARES_EBADRESP, ares_parse_srv_reply(data.data(), data.size(), &srv)); +// ASSERT_EQ(nullptr, srv); +// } + +// TEST_F(LibraryTest, ParseCSrvReplyMalformed) { +// std::vector data = { +// 0x12, 0x34, // qid +// 0x84, // response + query + AA + not-TC + not-RD +// 0x00, // not-RA + not-Z + not-AD + not-CD + rc=NoError +// 0x00, 0x01, // num questions +// 0x00, 0x01, // num answer RRs +// 0x00, 0x00, // num authority RRs +// 0x00, 0x00, // num additional RRs +// // Question +// 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', +// 0x03, 'c', 'o', 'm', +// 0x00, +// 0x00, 0x21, // type SRV +// 0x00, 0x01, // class IN +// // Answer 1 +// 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', +// 0x03, 'c', 'o', 'm', +// 0x00, +// 0x00, 0x21, // RR type +// 0x00, 0x01, // class IN +// 0x01, 0x02, 0x03, 0x04, // TTL +// 0x00, 0x04, // rdata length -- too short +// 0x02, 0x03, 0x04, 0x05, +// }; + +// cares_srv_reply* srv = nullptr; +// EXPECT_EQ(ARES_EBADRESP, cares_parse_srv_reply(data.data(), data.size(), &srv)); +// ASSERT_EQ(nullptr, srv); +// } + +// TEST_F(LibraryTest, ParseSrvReplyMultiple) { +// DNSPacket pkt; +// pkt.set_qid(0x1234).set_response().set_ra().set_rd() +// .add_question(new DNSQuestion("srv.example.com", T_SRV)) +// .add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 6789, "a1.srv.example.com")) +// .add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 4567, "a2.srv.example.com")) +// .add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 5678, "a3.srv.example.com")) +// .add_auth(new DNSNsRR("example.com", 300, "ns1.example.com")) +// .add_auth(new DNSNsRR("example.com", 300, "ns2.example.com")) +// .add_auth(new DNSNsRR("example.com", 300, "ns3.example.com")) +// .add_additional(new DNSARR("a1.srv.example.com", 300, {172,19,1,1})) +// .add_additional(new DNSARR("a2.srv.example.com", 300, {172,19,1,2})) +// .add_additional(new DNSARR("a3.srv.example.com", 300, {172,19,1,3})) +// .add_additional(new DNSARR("n1.example.com", 300, {172,19,0,1})) +// .add_additional(new DNSARR("n2.example.com", 300, {172,19,0,2})) +// .add_additional(new DNSARR("n3.example.com", 300, {172,19,0,3})); +// std::vector data = pkt.data(); + +// struct ares_srv_reply* srv0 = nullptr; +// EXPECT_EQ(ARES_SUCCESS, ares_parse_srv_reply(data.data(), data.size(), &srv0)); +// ASSERT_NE(nullptr, srv0); +// struct ares_srv_reply* srv = srv0; + +// EXPECT_EQ("a1.srv.example.com", std::string(srv->host)); +// EXPECT_EQ(0, srv->priority); +// EXPECT_EQ(5, srv->weight); +// EXPECT_EQ(6789, srv->port); +// EXPECT_NE(nullptr, srv->next); +// srv = srv->next; + +// EXPECT_EQ("a2.srv.example.com", std::string(srv->host)); +// EXPECT_EQ(0, srv->priority); +// EXPECT_EQ(5, srv->weight); +// EXPECT_EQ(4567, srv->port); +// EXPECT_NE(nullptr, srv->next); +// srv = srv->next; + +// EXPECT_EQ("a3.srv.example.com", std::string(srv->host)); +// EXPECT_EQ(0, srv->priority); +// EXPECT_EQ(5, srv->weight); +// EXPECT_EQ(5678, srv->port); +// EXPECT_EQ(nullptr, srv->next); + +// ares_free_data(srv0); +// } + +// TEST_F(LibraryTest, ParseCSrvReplyMultiple) { +// DNSPacket pkt; +// pkt.set_qid(0x1234).set_response().set_ra().set_rd() +// .add_question(new DNSQuestion("srv.example.com", T_SRV)) +// .add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 6789, "a1.srv.example.com")) +// .add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 4567, "a2.srv.example.com")) +// .add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 5678, "a3.srv.example.com")) +// .add_auth(new DNSNsRR("example.com", 300, "ns1.example.com")) +// .add_auth(new DNSNsRR("example.com", 300, "ns2.example.com")) +// .add_auth(new DNSNsRR("example.com", 300, "ns3.example.com")) +// .add_additional(new DNSARR("a1.srv.example.com", 300, {172,19,1,1})) +// .add_additional(new DNSARR("a2.srv.example.com", 300, {172,19,1,2})) +// .add_additional(new DNSARR("a3.srv.example.com", 300, {172,19,1,3})) +// .add_additional(new DNSARR("n1.example.com", 300, {172,19,0,1})) +// .add_additional(new DNSARR("n2.example.com", 300, {172,19,0,2})) +// .add_additional(new DNSARR("n3.example.com", 300, {172,19,0,3})); +// std::vector data = pkt.data(); + +// cares_srv_reply* srv0 = nullptr; +// EXPECT_EQ(ARES_SUCCESS, cares_parse_srv_reply(data.data(), data.size(), &srv0)); +// ASSERT_NE(nullptr, srv0); +// const cares_srv_reply* srv = srv0; + +// EXPECT_EQ("a1.srv.example.com", std::string(cares_srv_reply_get_host(srv))); +// EXPECT_EQ(0, cares_srv_reply_get_priority(srv)); +// EXPECT_EQ(5, cares_srv_reply_get_weight(srv)); +// EXPECT_EQ(6789, cares_srv_reply_get_port(srv)); +// EXPECT_EQ(300, cares_srv_reply_get_ttl(srv)); +// EXPECT_NE(nullptr, cares_srv_reply_get_next(srv)); +// srv = cares_srv_reply_get_next(srv); + +// EXPECT_EQ("a2.srv.example.com", std::string(cares_srv_reply_get_host(srv))); +// EXPECT_EQ(0, cares_srv_reply_get_priority(srv)); +// EXPECT_EQ(5, cares_srv_reply_get_weight(srv)); +// EXPECT_EQ(4567, cares_srv_reply_get_port(srv)); +// EXPECT_EQ(300, cares_srv_reply_get_ttl(srv)); +// EXPECT_NE(nullptr, cares_srv_reply_get_next(srv)); +// srv = cares_srv_reply_get_next(srv); + +// EXPECT_EQ("a3.srv.example.com", std::string(cares_srv_reply_get_host(srv))); +// EXPECT_EQ(0, cares_srv_reply_get_priority(srv)); +// EXPECT_EQ(5, cares_srv_reply_get_weight(srv)); +// EXPECT_EQ(5678, cares_srv_reply_get_port(srv)); +// EXPECT_EQ(300, cares_srv_reply_get_ttl(srv)); +// EXPECT_EQ(nullptr, cares_srv_reply_get_next(srv)); + +// ares_free_data(srv0); +// } + +// TEST_F(LibraryTest, ParseSrvReplyCname) { +// DNSPacket pkt; +// pkt.set_qid(0x1234).set_response().set_aa() +// .add_question(new DNSQuestion("example.abc.def.com", T_SRV)) +// .add_answer(new DNSCnameRR("example.abc.def.com", 300, "cname.abc.def.com")) +// .add_answer(new DNSSrvRR("cname.abc.def.com", 300, 0, 10, 1234, "srv.abc.def.com")) +// .add_auth(new DNSNsRR("abc.def.com", 44, "else1.where.com")) +// .add_auth(new DNSNsRR("abc.def.com", 44, "else2.where.com")) +// .add_auth(new DNSNsRR("abc.def.com", 44, "else3.where.com")) +// .add_additional(new DNSARR("example.abc.def.com", 300, {172,19,0,1})) +// .add_additional(new DNSARR("else1.where.com", 42, {172,19,0,1})) +// .add_additional(new DNSARR("else2.where.com", 42, {172,19,0,2})) +// .add_additional(new DNSARR("else3.where.com", 42, {172,19,0,3})); +// std::vector data = pkt.data(); + +// struct ares_srv_reply* srv = nullptr; +// EXPECT_EQ(ARES_SUCCESS, ares_parse_srv_reply(data.data(), data.size(), &srv)); +// ASSERT_NE(nullptr, srv); + +// EXPECT_EQ("srv.abc.def.com", std::string(srv->host)); +// EXPECT_EQ(0, srv->priority); +// EXPECT_EQ(10, srv->weight); +// EXPECT_EQ(1234, srv->port); +// EXPECT_EQ(nullptr, srv->next); + +// ares_free_data(srv); +// } + +// TEST_F(LibraryTest, ParseCSrvReplyCname) { +// DNSPacket pkt; +// pkt.set_qid(0x1234).set_response().set_aa() +// .add_question(new DNSQuestion("example.abc.def.com", T_SRV)) +// .add_answer(new DNSCnameRR("example.abc.def.com", 300, "cname.abc.def.com")) +// .add_answer(new DNSSrvRR("cname.abc.def.com", 300, 0, 10, 1234, "srv.abc.def.com")) +// .add_auth(new DNSNsRR("abc.def.com", 44, "else1.where.com")) +// .add_auth(new DNSNsRR("abc.def.com", 44, "else2.where.com")) +// .add_auth(new DNSNsRR("abc.def.com", 44, "else3.where.com")) +// .add_additional(new DNSARR("example.abc.def.com", 300, {172,19,0,1})) +// .add_additional(new DNSARR("else1.where.com", 42, {172,19,0,1})) +// .add_additional(new DNSARR("else2.where.com", 42, {172,19,0,2})) +// .add_additional(new DNSARR("else3.where.com", 42, {172,19,0,3})); +// std::vector data = pkt.data(); + +// cares_srv_reply* srv = nullptr; +// EXPECT_EQ(ARES_SUCCESS, cares_parse_srv_reply(data.data(), data.size(), &srv)); +// ASSERT_NE(nullptr, srv); + +// EXPECT_EQ("srv.abc.def.com", std::string(cares_srv_reply_get_host(srv))); +// EXPECT_EQ(0, cares_srv_reply_get_priority(srv)); +// EXPECT_EQ(10, cares_srv_reply_get_weight(srv)); +// EXPECT_EQ(1234, cares_srv_reply_get_port(srv)); +// EXPECT_EQ(300, cares_srv_reply_get_ttl(srv)); +// EXPECT_EQ(nullptr, cares_srv_reply_get_next(srv)); + +// ares_free_data(srv); +// } + +// TEST_F(LibraryTest, ParseSrvReplyCnameMultiple) { +// DNSPacket pkt; +// pkt.set_qid(0x1234).set_response().set_ra().set_rd() +// .add_question(new DNSQuestion("query.example.com", T_SRV)) +// .add_answer(new DNSCnameRR("query.example.com", 300, "srv.example.com")) +// .add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 6789, "a1.srv.example.com")) +// .add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 4567, "a2.srv.example.com")) +// .add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 5678, "a3.srv.example.com")) +// .add_auth(new DNSNsRR("example.com", 300, "ns1.example.com")) +// .add_auth(new DNSNsRR("example.com", 300, "ns2.example.com")) +// .add_auth(new DNSNsRR("example.com", 300, "ns3.example.com")) +// .add_additional(new DNSARR("a1.srv.example.com", 300, {172,19,1,1})) +// .add_additional(new DNSARR("a2.srv.example.com", 300, {172,19,1,2})) +// .add_additional(new DNSARR("a3.srv.example.com", 300, {172,19,1,3})) +// .add_additional(new DNSARR("n1.example.com", 300, {172,19,0,1})) +// .add_additional(new DNSARR("n2.example.com", 300, {172,19,0,2})) +// .add_additional(new DNSARR("n3.example.com", 300, {172,19,0,3})); +// std::vector data = pkt.data(); + +// struct ares_srv_reply* srv0 = nullptr; +// EXPECT_EQ(ARES_SUCCESS, ares_parse_srv_reply(data.data(), data.size(), &srv0)); +// ASSERT_NE(nullptr, srv0); +// struct ares_srv_reply* srv = srv0; + +// EXPECT_EQ("a1.srv.example.com", std::string(srv->host)); +// EXPECT_EQ(0, srv->priority); +// EXPECT_EQ(5, srv->weight); +// EXPECT_EQ(6789, srv->port); +// EXPECT_NE(nullptr, srv->next); +// srv = srv->next; + +// EXPECT_EQ("a2.srv.example.com", std::string(srv->host)); +// EXPECT_EQ(0, srv->priority); +// EXPECT_EQ(5, srv->weight); +// EXPECT_EQ(4567, srv->port); +// EXPECT_NE(nullptr, srv->next); +// srv = srv->next; + +// EXPECT_EQ("a3.srv.example.com", std::string(srv->host)); +// EXPECT_EQ(0, srv->priority); +// EXPECT_EQ(5, srv->weight); +// EXPECT_EQ(5678, srv->port); +// EXPECT_EQ(nullptr, srv->next); + +// ares_free_data(srv0); +// } + +// TEST_F(LibraryTest, ParseCSrvReplyCnameMultiple) { +// DNSPacket pkt; +// pkt.set_qid(0x1234).set_response().set_ra().set_rd() +// .add_question(new DNSQuestion("query.example.com", T_SRV)) +// .add_answer(new DNSCnameRR("query.example.com", 300, "srv.example.com")) +// .add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 6789, "a1.srv.example.com")) +// .add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 4567, "a2.srv.example.com")) +// .add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 5678, "a3.srv.example.com")) +// .add_auth(new DNSNsRR("example.com", 300, "ns1.example.com")) +// .add_auth(new DNSNsRR("example.com", 300, "ns2.example.com")) +// .add_auth(new DNSNsRR("example.com", 300, "ns3.example.com")) +// .add_additional(new DNSARR("a1.srv.example.com", 300, {172,19,1,1})) +// .add_additional(new DNSARR("a2.srv.example.com", 300, {172,19,1,2})) +// .add_additional(new DNSARR("a3.srv.example.com", 300, {172,19,1,3})) +// .add_additional(new DNSARR("n1.example.com", 300, {172,19,0,1})) +// .add_additional(new DNSARR("n2.example.com", 300, {172,19,0,2})) +// .add_additional(new DNSARR("n3.example.com", 300, {172,19,0,3})); +// std::vector data = pkt.data(); + +// cares_srv_reply* srv0 = nullptr; +// EXPECT_EQ(ARES_SUCCESS, cares_parse_srv_reply(data.data(), data.size(), &srv0)); +// ASSERT_NE(nullptr, srv0); +// const cares_srv_reply* srv = srv0; + +// EXPECT_EQ("a1.srv.example.com", std::string(cares_srv_reply_get_host(srv))); +// EXPECT_EQ(0, cares_srv_reply_get_priority(srv)); +// EXPECT_EQ(5, cares_srv_reply_get_weight(srv)); +// EXPECT_EQ(6789, cares_srv_reply_get_port(srv)); +// EXPECT_EQ(300, cares_srv_reply_get_ttl(srv)); +// EXPECT_NE(nullptr, cares_srv_reply_get_next(srv)); +// srv = cares_srv_reply_get_next(srv); + +// EXPECT_EQ("a2.srv.example.com", std::string(cares_srv_reply_get_host(srv))); +// EXPECT_EQ(0, cares_srv_reply_get_priority(srv)); +// EXPECT_EQ(5, cares_srv_reply_get_weight(srv)); +// EXPECT_EQ(4567, cares_srv_reply_get_port(srv)); +// EXPECT_EQ(300, cares_srv_reply_get_ttl(srv)); +// EXPECT_NE(nullptr, cares_srv_reply_get_next(srv)); +// srv = cares_srv_reply_get_next(srv); + +// EXPECT_EQ("a3.srv.example.com", std::string(cares_srv_reply_get_host(srv))); +// EXPECT_EQ(0, cares_srv_reply_get_priority(srv)); +// EXPECT_EQ(5, cares_srv_reply_get_weight(srv)); +// EXPECT_EQ(5678, cares_srv_reply_get_port(srv)); +// EXPECT_EQ(300, cares_srv_reply_get_ttl(srv)); +// EXPECT_EQ(nullptr, cares_srv_reply_get_next(srv)); + +// ares_free_data(srv0); +// } + +// TEST_F(LibraryTest, ParseSrvReplyErrors) { +// DNSPacket pkt; +// pkt.set_qid(0x1234).set_response().set_aa() +// .add_question(new DNSQuestion("example.abc.def.com", T_SRV)) +// .add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")); +// std::vector data; +// struct ares_srv_reply* srv = nullptr; + +// // No question. +// pkt.questions_.clear(); +// data = pkt.data(); +// EXPECT_EQ(ARES_EBADRESP, ares_parse_srv_reply(data.data(), data.size(), &srv)); +// pkt.add_question(new DNSQuestion("example.abc.def.com", T_SRV)); +// #ifdef DISABLED +// // Question != answer +// pkt.questions_.clear(); +// pkt.add_question(new DNSQuestion("Axample.com", T_SRV)); +// data = pkt.data(); +// EXPECT_EQ(ARES_ENODATA, ares_parse_srv_reply(data.data(), data.size(), &srv)); +// pkt.questions_.clear(); +// pkt.add_question(new DNSQuestion("example.com", T_SRV)); +// #endif +// // Two questions. +// pkt.add_question(new DNSQuestion("example.abc.def.com", T_SRV)); +// data = pkt.data(); +// EXPECT_EQ(ARES_EBADRESP, ares_parse_srv_reply(data.data(), data.size(), &srv)); +// pkt.questions_.clear(); +// pkt.add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR)); +// // Wrong sort of answer. +// pkt.answers_.clear(); +// pkt.add_answer(new DNSMxRR("example.com", 100, 100, "mx1.example.com")); +// data = pkt.data(); +// EXPECT_EQ(ARES_ENODATA, ares_parse_srv_reply(data.data(), data.size(), &srv)); +// EXPECT_EQ(nullptr, srv); +// pkt.answers_.clear(); +// pkt.add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")); +// // No answer. +// pkt.answers_.clear(); +// data = pkt.data(); +// EXPECT_EQ(ARES_ENODATA, ares_parse_srv_reply(data.data(), data.size(), &srv)); +// pkt.add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")); +// // Truncated packets. +// data = pkt.data(); +// for (size_t len = 1; len < data.size(); len++) { +// int rc = ares_parse_srv_reply(data.data(), len, &srv); +// EXPECT_TRUE(rc == ARES_EBADRESP || rc == ARES_EBADNAME); +// } +// } + +// TEST_F(LibraryTest, ParseCSrvReplyErrors) { +// DNSPacket pkt; +// pkt.set_qid(0x1234).set_response().set_aa() +// .add_question(new DNSQuestion("example.abc.def.com", T_SRV)) +// .add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")); +// std::vector data; +// cares_srv_reply* srv = nullptr; + +// // No question. +// pkt.questions_.clear(); +// data = pkt.data(); +// EXPECT_EQ(ARES_EBADRESP, cares_parse_srv_reply(data.data(), data.size(), &srv)); +// pkt.add_question(new DNSQuestion("example.abc.def.com", T_SRV)); + +// #ifdef DISABLED +// // Question != answer +// pkt.questions_.clear(); +// pkt.add_question(new DNSQuestion("Axample.com", T_SRV)); +// data = pkt.data(); +// EXPECT_EQ(ARES_ENODATA, cares_parse_srv_reply(data.data(), data.size(), &srv)); +// pkt.questions_.clear(); +// pkt.add_question(new DNSQuestion("example.com", T_SRV)); +// #endif + +// // Two questions. +// pkt.add_question(new DNSQuestion("example.abc.def.com", T_SRV)); +// data = pkt.data(); +// EXPECT_EQ(ARES_EBADRESP, cares_parse_srv_reply(data.data(), data.size(), &srv)); +// pkt.questions_.clear(); +// pkt.add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR)); + +// // Wrong sort of answer. +// pkt.answers_.clear(); +// pkt.add_answer(new DNSMxRR("example.com", 100, 100, "mx1.example.com")); +// data = pkt.data(); +// EXPECT_EQ(ARES_ENODATA, cares_parse_srv_reply(data.data(), data.size(), &srv)); +// EXPECT_EQ(nullptr, srv); +// pkt.answers_.clear(); +// pkt.add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")); + +// // No answer. +// pkt.answers_.clear(); +// data = pkt.data(); +// EXPECT_EQ(ARES_ENODATA, cares_parse_srv_reply(data.data(), data.size(), &srv)); +// pkt.add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")); + +// // Truncated packets. +// data = pkt.data(); +// for (size_t len = 1; len < data.size(); len++) { +// int rc = cares_parse_srv_reply(data.data(), len, &srv); +// EXPECT_TRUE(rc == ARES_EBADRESP || rc == ARES_EBADNAME); +// } +// } + +// TEST_F(LibraryTest, ParseSrvReplyAllocFail) { +// DNSPacket pkt; +// pkt.set_qid(0x1234).set_response().set_aa() +// .add_question(new DNSQuestion("example.abc.def.com", T_SRV)) +// .add_answer(new DNSCnameRR("example.com", 300, "c.example.com")) +// .add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")); +// std::vector data = pkt.data(); +// struct ares_srv_reply* srv = nullptr; + +// for (int ii = 1; ii <= 5; ii++) { +// ClearFails(); +// SetAllocFail(ii); +// EXPECT_EQ(ARES_ENOMEM, ares_parse_srv_reply(data.data(), data.size(), &srv)) << ii; +// } +// } + +// TEST_F(LibraryTest, ParseCSrvReplyAllocFail) { +// DNSPacket pkt; +// pkt.set_qid(0x1234).set_response().set_aa() +// .add_question(new DNSQuestion("example.abc.def.com", T_SRV)) +// .add_answer(new DNSCnameRR("example.com", 300, "c.example.com")) +// .add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")); +// std::vector data = pkt.data(); +// cares_srv_reply* srv = nullptr; + +// for (int ii = 1; ii <= 5; ii++) { +// ClearFails(); +// SetAllocFail(ii); +// EXPECT_EQ(ARES_ENOMEM, cares_parse_srv_reply(data.data(), data.size(), &srv)) << ii; +// } +// } } // namespace test } // namespace ares From de092f36f13974872fe953294c27688cca9e018a Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Fri, 31 Dec 2021 01:41:03 -0500 Subject: [PATCH 28/49] fix errors and warnings --- include/ares.h | 12 +++++++++--- src/lib/ares_parse_srv_reply.c | 6 +++--- src/lib/ares_private.h | 6 +++--- src/lib/cares_container.c | 8 ++++---- src/lib/cares_parse_srv_reply.c | 7 ++++--- 5 files changed, 23 insertions(+), 16 deletions(-) diff --git a/include/ares.h b/include/ares.h index 472a6c7da3..baf295b50a 100644 --- a/include/ares.h +++ b/include/ares.h @@ -561,7 +561,7 @@ struct cares_srv_reply; typedef struct cares_srv_reply cares_srv_reply; -struct cares_srv_reply_container +struct cares_srv_reply_container; typedef struct cares_srv_reply_container cares_srv_reply_container; @@ -767,7 +767,7 @@ CARES_EXTERN int ares_parse_srv_reply(const unsigned char* abuf, CARES_EXTERN int cares_parse_srv_reply(const unsigned char* abuf, int alen, - struct cares_srv_reply** srv_out); + struct cares_srv_reply_container** srv_out); CARES_EXTERN const cares_srv_reply* cares_srv_reply_container_get_first(const cares_srv_reply_container* container); @@ -778,9 +778,15 @@ cares_srv_reply_container_get_next(const cares_srv_reply_container* container); CARES_EXTERN const cares_srv_reply* cares_srv_reply_container_get_last(const cares_srv_reply_container* container); -CARES_EXTERN const unsigned int +CARES_EXTERN unsigned int cares_srv_reply_container_get_count(const cares_srv_reply_container* container); +CARES_EXTERN unsigned int +cares_srv_reply_container_get_curr(const cares_srv_reply_container* container); + +CARES_EXTERN bool +cares_srv_reply_container_at_end(const cares_srv_reply_container* container); + CARES_EXTERN const char* cares_srv_reply_get_host(const cares_srv_reply* srv_reply); diff --git a/src/lib/ares_parse_srv_reply.c b/src/lib/ares_parse_srv_reply.c index 52f23f58ed..76c7f0ae35 100644 --- a/src/lib/ares_parse_srv_reply.c +++ b/src/lib/ares_parse_srv_reply.c @@ -60,7 +60,7 @@ ares_parse_srv_reply (const unsigned char *abuf, int alen, if (status != ARES_SUCCESS) { if (csrv_out) - ares_free_container(csrv_out); + cares_free_container(csrv_out); return status; } @@ -68,7 +68,7 @@ ares_parse_srv_reply (const unsigned char *abuf, int alen, * create a new ares_srv_reply */ for (csrv_curr = cares_srv_reply_container_get_first(csrv_out); !cares_srv_reply_container_at_end(csrv_out); - csrv_curr = cares_srv_reply_get_next(csrv_curr)) + csrv_curr = cares_srv_reply_container_get_next(csrv_out)) { srv_curr = ares_malloc_data(ARES_DATATYPE_SRV_REPLY); if (!srv_curr) @@ -101,7 +101,7 @@ ares_parse_srv_reply (const unsigned char *abuf, int alen, if (csrv_out) { - ares_free_container(csrv_out); + cares_free_container(csrv_out); } /* clean up on error */ diff --git a/src/lib/ares_private.h b/src/lib/ares_private.h index f9c624b3b7..f8557c8f08 100644 --- a/src/lib/ares_private.h +++ b/src/lib/ares_private.h @@ -472,9 +472,9 @@ struct cares_srv_reply { struct cares_srv_reply_container { cares_srv_reply *replies; - int curr; - int count; -} + unsigned int curr; + unsigned int count; +}; struct cares_mx_reply { cares_mx_reply *next; diff --git a/src/lib/cares_container.c b/src/lib/cares_container.c index 527630cf17..be0653ce36 100644 --- a/src/lib/cares_container.c +++ b/src/lib/cares_container.c @@ -37,7 +37,7 @@ cares_srv_reply_container_get_next(const cares_srv_reply_container* container) cares_srv_reply_container_set_curr(container, cares_srv_reply_container_get_curr(container) + 1); - + return &container->replies[container->curr]; } @@ -52,19 +52,19 @@ cares_srv_reply_container_get_last(const cares_srv_reply_container* container) return &container->replies[cares_srv_reply_container_get_count(container) - 1]; } -const int +unsigned int cares_srv_reply_container_get_count(const cares_srv_reply_container* container) { return container->count; } -const int +unsigned int cares_srv_reply_container_get_curr(const cares_srv_reply_container* container) { return container->curr; } -const bool +bool cares_srv_reply_container_at_end(const cares_srv_reply_container* container) { return cares_srv_reply_get_curr(container) == cares_srv_reply_get_count(container); diff --git a/src/lib/cares_parse_srv_reply.c b/src/lib/cares_parse_srv_reply.c index af3ee56ff1..eb060a205e 100644 --- a/src/lib/cares_parse_srv_reply.c +++ b/src/lib/cares_parse_srv_reply.c @@ -33,6 +33,7 @@ #include "ares_dns.h" #include "ares_data.h" #include "ares_private.h" +#include "cares_free_container.h" int cares_parse_srv_reply (const unsigned char *abuf, int alen, @@ -54,7 +55,7 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, /* Set *srv_out to NULL for all failure cases. */ *srv_out = NULL; - *srv_out = ares_malloc_container(CARES_CONTAINER_SRV_REPLY_CONTAINER); + *srv_out = cares_malloc_container(CARES_CONTAINER_SRV_REPLY_CONTAINER); if (*srv_out == NULL) return ARES_ENOMEM; @@ -70,7 +71,7 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, if (ancount == 0) return ARES_ENODATA; - *srv_out->count = ancount; + cares_srv_reply_container_set_count(*srv_out, ancount); srv_replies = ares_malloc(ancount * sizeof(*srv_replies)); /* Expand the name from the question, and skip past the question. */ @@ -144,7 +145,7 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, if (status != ARES_SUCCESS) break; cares_srv_reply_set_host(srv_curr, srv_host); - srv_replies[i] = srv_curr; + srv_replies[i] = *srv_curr; } else if (rr_type != T_CNAME) { From 9583762c4e4b0619f28ea0cdbf7f8b40f3e284e2 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Fri, 31 Dec 2021 15:55:16 -0500 Subject: [PATCH 29/49] fix errors and warnings --- include/ares.h | 4 ++-- src/lib/ares_private.h | 4 ++-- src/lib/cares_container.c | 23 ++++++++++++----------- src/lib/cares_free_container.c | 27 +++++++++++++++++++++------ src/lib/cares_free_container.h | 5 ++--- src/lib/cares_parse_srv_reply.c | 11 +++++------ src/lib/cares_reply.c | 20 ++++++++++---------- 7 files changed, 54 insertions(+), 40 deletions(-) diff --git a/include/ares.h b/include/ares.h index baf295b50a..48f3117659 100644 --- a/include/ares.h +++ b/include/ares.h @@ -773,7 +773,7 @@ CARES_EXTERN const cares_srv_reply* cares_srv_reply_container_get_first(const cares_srv_reply_container* container); CARES_EXTERN const cares_srv_reply* -cares_srv_reply_container_get_next(const cares_srv_reply_container* container); +cares_srv_reply_container_get_next(cares_srv_reply_container* container); CARES_EXTERN const cares_srv_reply* cares_srv_reply_container_get_last(const cares_srv_reply_container* container); @@ -784,7 +784,7 @@ cares_srv_reply_container_get_count(const cares_srv_reply_container* container); CARES_EXTERN unsigned int cares_srv_reply_container_get_curr(const cares_srv_reply_container* container); -CARES_EXTERN bool +CARES_EXTERN int cares_srv_reply_container_at_end(const cares_srv_reply_container* container); CARES_EXTERN const char* diff --git a/src/lib/ares_private.h b/src/lib/ares_private.h index f8557c8f08..be5a297e75 100644 --- a/src/lib/ares_private.h +++ b/src/lib/ares_private.h @@ -471,7 +471,7 @@ struct cares_srv_reply { }; struct cares_srv_reply_container { - cares_srv_reply *replies; + cares_srv_reply **replies; unsigned int curr; unsigned int count; }; @@ -534,7 +534,7 @@ void cares_srv_reply_set_ttl(cares_srv_reply* srv_reply, const unsigned int ttl); void cares_srv_reply_container_set_replies(cares_srv_reply_container* container, - cares_srv_reply* replies); + cares_srv_reply** replies); void cares_srv_reply_container_set_curr(cares_srv_reply_container* container, const unsigned int index); diff --git a/src/lib/cares_container.c b/src/lib/cares_container.c index be0653ce36..facbee886a 100644 --- a/src/lib/cares_container.c +++ b/src/lib/cares_container.c @@ -19,26 +19,26 @@ const cares_srv_reply* cares_srv_reply_container_get_first(const cares_srv_reply_container* container) { - return &container[0]; + return container->replies[0]; } const cares_srv_reply* -cares_srv_reply_container_get_next(const cares_srv_reply_container* container) +cares_srv_reply_container_get_next(cares_srv_reply_container* container) { if (cares_srv_reply_container_get_count(container) == 0) { - return container->replies; + return container->replies[0]; } if (container->curr == cares_srv_reply_container_get_count(container) - 1) { - return &container->replies[cares_srv_reply_container_get_count(container) - 1]; + return container->replies[cares_srv_reply_container_get_count(container) - 1]; } cares_srv_reply_container_set_curr(container, cares_srv_reply_container_get_curr(container) + 1); - return &container->replies[container->curr]; + return container->replies[container->curr]; } const cares_srv_reply* @@ -46,10 +46,10 @@ cares_srv_reply_container_get_last(const cares_srv_reply_container* container) { if (cares_srv_reply_container_get_count(container) == 0) { - return container->replies; + return container->replies[0]; } - return &container->replies[cares_srv_reply_container_get_count(container) - 1]; + return container->replies[cares_srv_reply_container_get_count(container) - 1]; } unsigned int @@ -64,14 +64,15 @@ cares_srv_reply_container_get_curr(const cares_srv_reply_container* container) return container->curr; } -bool +int cares_srv_reply_container_at_end(const cares_srv_reply_container* container) { - return cares_srv_reply_get_curr(container) == cares_srv_reply_get_count(container); + return cares_srv_reply_container_get_curr(container) == + cares_srv_reply_container_get_count(container); } void cares_srv_reply_container_set_replies(cares_srv_reply_container* container, - cares_srv_reply* replies) + cares_srv_reply** replies) { container->replies = replies; } @@ -86,4 +87,4 @@ void cares_srv_reply_container_set_count(cares_srv_reply_container* container, const unsigned int count) { container->count = count; -} \ No newline at end of file +} diff --git a/src/lib/cares_free_container.c b/src/lib/cares_free_container.c index 28a15ca3e5..f67524ad22 100644 --- a/src/lib/cares_free_container.c +++ b/src/lib/cares_free_container.c @@ -11,9 +11,12 @@ * without express or implied warranty. */ +#include #include "ares_setup.h" #include "ares.h" #include "ares_private.h" +#include "cares_free_container.h" +#include "ares_data.h" void cares_free_container(void *containerptr) { @@ -21,18 +24,32 @@ void cares_free_container(void *containerptr) return; } + struct cares_container *ptr; + unsigned int count; + ptr = (void *)((char *)containerptr - offsetof(struct cares_container, container)); if (ptr->mark != ARES_DATATYPE_MARK) return; - for (int i = 0; i < ptr->count; ++i) + switch (ptr->type) + { + case CARES_CONTAINER_SRV_REPLY_CONTAINER: + count = ptr->container.srv_container.count; + break; + + default: + return; + } + + for (unsigned int i = 0; i < count; ++i) { - curr = ptr->container->replies; switch (ptr->type) { case CARES_CONTAINER_SRV_REPLY_CONTAINER: - ares_free_data((cares_srv_reply *)curr[i]); + ares_free_data(ptr->container.srv_container.replies[i]); + if (i == count - 1) + ares_free(ptr->container.srv_container.replies); break; default: @@ -40,8 +57,6 @@ void cares_free_container(void *containerptr) } } - ares_free(ptr->container->replies); - ares_free(ptr->container); ares_free(ptr); } @@ -70,4 +85,4 @@ void *cares_malloc_container(cares_container_type type) ptr->type = type; return &ptr->container; -} \ No newline at end of file +} diff --git a/src/lib/cares_free_container.h b/src/lib/cares_free_container.h index 712d4e15c8..fd158232f5 100644 --- a/src/lib/cares_free_container.h +++ b/src/lib/cares_free_container.h @@ -12,7 +12,6 @@ */ #include "ares_private.h" -#include "ares_data.h" typedef enum { CARES_CONTAINER_SRV_REPLY_CONTAINER, @@ -22,10 +21,10 @@ typedef enum { struct cares_container { cares_container_type type; /* Actual data type identifier. */ - unsigned int mark; /* Private ares_data signature. */ + unsigned int mark; /* Private ares_data signature. */ union { struct cares_srv_reply_container srv_container; } container; }; -void *cares_malloc_container(cares_container_type type); \ No newline at end of file +void *cares_malloc_container(cares_container_type type); diff --git a/src/lib/cares_parse_srv_reply.c b/src/lib/cares_parse_srv_reply.c index eb060a205e..d23d114ba2 100644 --- a/src/lib/cares_parse_srv_reply.c +++ b/src/lib/cares_parse_srv_reply.c @@ -39,7 +39,7 @@ int cares_parse_srv_reply (const unsigned char *abuf, int alen, cares_srv_reply_container **srv_out) { - unsigned int qdcount, ancount, i; + unsigned int qdcount, ancount, i, count; const unsigned char *aptr, *vptr; int status, rr_type, rr_class, rr_len; unsigned int rr_ttl; @@ -49,8 +49,7 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, // cares_srv_reply *srv_head = NULL; // cares_srv_reply *srv_last = NULL; cares_srv_reply *srv_curr; - cares_srv_reply *srv_replies = NULL; - int count; + cares_srv_reply **srv_replies = NULL; /* Set *srv_out to NULL for all failure cases. */ *srv_out = NULL; @@ -72,7 +71,7 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, return ARES_ENODATA; cares_srv_reply_container_set_count(*srv_out, ancount); - srv_replies = ares_malloc(ancount * sizeof(*srv_replies)); + *srv_replies = ares_malloc(ancount * sizeof(**srv_replies)); /* Expand the name from the question, and skip past the question. */ aptr = abuf + HFIXEDSZ; @@ -145,7 +144,7 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, if (status != ARES_SUCCESS) break; cares_srv_reply_set_host(srv_curr, srv_host); - srv_replies[i] = *srv_curr; + srv_replies[i] = srv_curr; } else if (rr_type != T_CNAME) { @@ -181,6 +180,6 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, } /* everything looks fine, return the data */ - *srv_out->replies = srv_replies; + (*srv_out)->replies = srv_replies; return ARES_SUCCESS; } diff --git a/src/lib/cares_reply.c b/src/lib/cares_reply.c index 98e975f21b..7ee41727a0 100644 --- a/src/lib/cares_reply.c +++ b/src/lib/cares_reply.c @@ -17,11 +17,11 @@ #include "string.h" -const cares_srv_reply* -cares_srv_reply_get_next(const cares_srv_reply* srv_reply) -{ - return srv_reply->next; -} +// const cares_srv_reply* +// cares_srv_reply_get_next(const cares_srv_reply* srv_reply) +// { +// return srv_reply->next; +// } const char* cares_srv_reply_get_host(const cares_srv_reply* srv_reply) { @@ -51,11 +51,11 @@ unsigned int cares_srv_reply_get_ttl(const cares_srv_reply* srv_reply) return srv_reply->ttl; } -void cares_srv_reply_set_next(cares_srv_reply* srv_reply, - cares_srv_reply* next) -{ - srv_reply->next = next; -} +// void cares_srv_reply_set_next(cares_srv_reply* srv_reply, +// cares_srv_reply* next) +// { +// srv_reply->next = next; +// } void cares_srv_reply_set_host(cares_srv_reply* srv_reply, char* host) { From e22efd5177aa09a7571c160771cefd97216a751f Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Sat, 1 Jan 2022 15:02:46 -0500 Subject: [PATCH 30/49] add debugging --- include/ares.h | 3 +++ src/lib/ares_data.c | 8 ++++++++ src/lib/ares_parse_srv_reply.c | 9 +++++++++ src/lib/cares_container.c | 9 +++++++-- src/lib/cares_free_container.c | 20 ++++++++++++++++++-- src/lib/cares_parse_srv_reply.c | 16 ++++++++++++++-- test/ares-test-parse-srv.cc | 2 ++ 7 files changed, 61 insertions(+), 6 deletions(-) diff --git a/include/ares.h b/include/ares.h index 48f3117659..42e8377317 100644 --- a/include/ares.h +++ b/include/ares.h @@ -787,6 +787,9 @@ cares_srv_reply_container_get_curr(const cares_srv_reply_container* container); CARES_EXTERN int cares_srv_reply_container_at_end(const cares_srv_reply_container* container); +CARES_EXTERN void +cares_srv_reply_container_reset(cares_srv_reply_container* container); + CARES_EXTERN const char* cares_srv_reply_get_host(const cares_srv_reply* srv_reply); diff --git a/src/lib/ares_data.c b/src/lib/ares_data.c index 74cc7ee492..e6e8b67fe5 100644 --- a/src/lib/ares_data.c +++ b/src/lib/ares_data.c @@ -22,6 +22,7 @@ #include "ares.h" #include "ares_data.h" #include "ares_private.h" +#include "stdio.h" /* @@ -41,6 +42,8 @@ void ares_free_data(void *dataptr) { + printf("dataptr: %p\n", (void *)dataptr); + printf("dataptr->host: %p; host: %s\n", (void *)((cares_srv_reply *)dataptr)->host, ((cares_srv_reply *)dataptr)->host); while (dataptr != NULL) { struct ares_data *ptr; void *next_data = NULL; @@ -52,6 +55,7 @@ void ares_free_data(void *dataptr) #endif ptr = (void *)((char *)dataptr - offsetof(struct ares_data, data)); + printf("ptr in ares_data: %p\n", (void *)ptr); #ifdef __INTEL_COMPILER # pragma warning(pop) @@ -77,7 +81,11 @@ void ares_free_data(void *dataptr) if (ptr->data.srv_reply.next) next_data = ptr->data.srv_reply.next; if (ptr->data.srv_reply.host) + { + printf("before ares_free in ares_data; srv_reply.host: %p, dataptr: %p; host:%s\n", (void *)ptr->data.srv_reply.host, (void *)&ptr->data, ptr->data.csrv_reply.host); ares_free(ptr->data.srv_reply.host); + printf("after ares_free in ares_data\n"); + } break; case ARES_DATATYPE_URI_REPLY: diff --git a/src/lib/ares_parse_srv_reply.c b/src/lib/ares_parse_srv_reply.c index 76c7f0ae35..27151953db 100644 --- a/src/lib/ares_parse_srv_reply.c +++ b/src/lib/ares_parse_srv_reply.c @@ -34,6 +34,7 @@ #include "ares_dns.h" #include "ares_data.h" #include "ares_private.h" +#include "stdio.h" int ares_parse_srv_reply (const unsigned char *abuf, int alen, @@ -55,6 +56,7 @@ ares_parse_srv_reply (const unsigned char *abuf, int alen, *srv_out = NULL; status = cares_parse_srv_reply(abuf, alen, &csrv_out); + printf("After cares_parse_srv_reply in ares_parse_srv_reply\n"); /* clean up on error */ if (status != ARES_SUCCESS) @@ -70,7 +72,10 @@ ares_parse_srv_reply (const unsigned char *abuf, int alen, !cares_srv_reply_container_at_end(csrv_out); csrv_curr = cares_srv_reply_container_get_next(csrv_out)) { + printf("csrv_out curr: %u\n", cares_srv_reply_container_get_curr(csrv_out)); + printf("csrv_out count: %u\n", cares_srv_reply_container_get_count(csrv_out)); srv_curr = ares_malloc_data(ARES_DATATYPE_SRV_REPLY); + printf("after srv_curr malloc\n"); if (!srv_curr) { status = ARES_ENOMEM; @@ -86,12 +91,14 @@ ares_parse_srv_reply (const unsigned char *abuf, int alen, } srv_last = srv_curr; + printf("csrv_curr host: %p\n", (void *)cares_srv_reply_get_host(csrv_curr)); /* copy the host to newhost so we can free csrv_out */ newhost = ares_strdup(cares_srv_reply_get_host(csrv_curr)); if (!newhost) { status = ARES_ENOMEM; break; } + printf("newhost: %p\n", (void *)newhost); srv_curr->host = newhost; srv_curr->priority = cares_srv_reply_get_priority(csrv_curr); @@ -101,7 +108,9 @@ ares_parse_srv_reply (const unsigned char *abuf, int alen, if (csrv_out) { + printf("before cares_free_container\n"); cares_free_container(csrv_out); + printf("after cares_free_container\n"); } /* clean up on error */ diff --git a/src/lib/cares_container.c b/src/lib/cares_container.c index facbee886a..245546917f 100644 --- a/src/lib/cares_container.c +++ b/src/lib/cares_container.c @@ -30,7 +30,7 @@ cares_srv_reply_container_get_next(cares_srv_reply_container* container) return container->replies[0]; } - if (container->curr == cares_srv_reply_container_get_count(container) - 1) + if (container->curr == cares_srv_reply_container_get_count(container)) { return container->replies[cares_srv_reply_container_get_count(container) - 1]; } @@ -67,7 +67,7 @@ cares_srv_reply_container_get_curr(const cares_srv_reply_container* container) int cares_srv_reply_container_at_end(const cares_srv_reply_container* container) { - return cares_srv_reply_container_get_curr(container) == + return cares_srv_reply_container_get_curr(container) >= cares_srv_reply_container_get_count(container); } @@ -88,3 +88,8 @@ void cares_srv_reply_container_set_count(cares_srv_reply_container* container, { container->count = count; } + +void cares_srv_reply_container_reset(cares_srv_reply_container* container) +{ + cares_srv_reply_container_set_curr(container, 0); +} diff --git a/src/lib/cares_free_container.c b/src/lib/cares_free_container.c index f67524ad22..0eb6e10097 100644 --- a/src/lib/cares_free_container.c +++ b/src/lib/cares_free_container.c @@ -17,18 +17,22 @@ #include "ares_private.h" #include "cares_free_container.h" #include "ares_data.h" +#include "stdio.h" void cares_free_container(void *containerptr) { if (containerptr == NULL) { return; } + printf("containerptr: %p\n", (void *)containerptr); struct cares_container *ptr; unsigned int count; ptr = (void *)((char *)containerptr - offsetof(struct cares_container, container)); + printf("ptr: %p\n", (void *)ptr); + if (ptr->mark != ARES_DATATYPE_MARK) return; @@ -47,17 +51,29 @@ void cares_free_container(void *containerptr) switch (ptr->type) { case CARES_CONTAINER_SRV_REPLY_CONTAINER: - ares_free_data(ptr->container.srv_container.replies[i]); + if (ptr->container.srv_container.replies[i]) + { + printf("before free data; replies[i]: %p\n", (void *)ptr->container.srv_container.replies[i]); + ares_free_data(ptr->container.srv_container.replies[i]); + printf("after free data\n"); + } + if (i == count - 1) + { + printf("before free replies\n"); ares_free(ptr->container.srv_container.replies); - break; + printf("after free replies\n"); + break; + } default: return; } } + printf("before free ptr\n"); ares_free(ptr); + printf("after free ptr\n"); } void *cares_malloc_container(cares_container_type type) diff --git a/src/lib/cares_parse_srv_reply.c b/src/lib/cares_parse_srv_reply.c index d23d114ba2..87221c085c 100644 --- a/src/lib/cares_parse_srv_reply.c +++ b/src/lib/cares_parse_srv_reply.c @@ -34,6 +34,7 @@ #include "ares_data.h" #include "ares_private.h" #include "cares_free_container.h" +#include "stdio.h" int cares_parse_srv_reply (const unsigned char *abuf, int alen, @@ -54,7 +55,9 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, /* Set *srv_out to NULL for all failure cases. */ *srv_out = NULL; + printf("before cares_malloc_container\n"); *srv_out = cares_malloc_container(CARES_CONTAINER_SRV_REPLY_CONTAINER); + printf("after cares_malloc_container\n"); if (*srv_out == NULL) return ARES_ENOMEM; @@ -69,9 +72,14 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, return ARES_EBADRESP; if (ancount == 0) return ARES_ENODATA; - + + printf("before set count\n"); cares_srv_reply_container_set_count(*srv_out, ancount); - *srv_replies = ares_malloc(ancount * sizeof(**srv_replies)); + printf("after set count\n"); + printf("before srv_replies malloc, ancount: %d\n", ancount); + printf("ancount * sizeof(**srv_replies): %lu\n", ancount * sizeof(**srv_replies)); + srv_replies = ares_malloc(ancount * sizeof(**srv_replies)); + printf("after srv_replies malloc\n"); /* Expand the name from the question, and skip past the question. */ aptr = abuf + HFIXEDSZ; @@ -89,6 +97,7 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, /* Examine each answer resource record (RR) in turn. */ for (i = 0; i < ancount; i++) { + printf("start loop\n"); count = i; /* Decode the RR up to the data field. */ status = ares_expand_name (aptr, abuf, alen, &rr_name, &len); @@ -144,7 +153,10 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, if (status != ARES_SUCCESS) break; cares_srv_reply_set_host(srv_curr, srv_host); + printf("srv_curr->host: %p; host: %s\n", (void *)srv_curr->host, srv_curr->host); + printf("before assign to srv_replies[i]; srv_curr: %p\n", (void *)srv_curr); srv_replies[i] = srv_curr; + printf("after assign to srv_replies[i]: %p; srv_replies[i]->host: %p\n", (void *)srv_replies[i], (void *)srv_replies[i]->host); } else if (rr_type != T_CNAME) { diff --git a/test/ares-test-parse-srv.cc b/test/ares-test-parse-srv.cc index a76a5f801a..a207185d25 100644 --- a/test/ares-test-parse-srv.cc +++ b/test/ares-test-parse-srv.cc @@ -3,6 +3,7 @@ #include #include +#include "stdio.h" namespace ares { namespace test { @@ -17,6 +18,7 @@ TEST_F(LibraryTest, ParseSrvReplyOK) { struct ares_srv_reply* srv = nullptr; EXPECT_EQ(ARES_SUCCESS, ares_parse_srv_reply(data.data(), data.size(), &srv)); + printf("After ares_parse_srv_reply\n"); ASSERT_NE(nullptr, srv); EXPECT_EQ("srv.example.com", std::string(srv->host)); From f34910594534ebea6ab6f214e1f58f18a5089828 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Sun, 2 Jan 2022 01:39:02 -0500 Subject: [PATCH 31/49] fix crashes and add debugging --- src/lib/ares_data.c | 34 ++- src/lib/ares_parse_srv_reply.c | 9 +- src/lib/cares_free_container.c | 6 + src/lib/cares_parse_srv_reply.c | 19 +- test/ares-test-parse-srv.cc | 452 ++++++++++++++++---------------- 5 files changed, 282 insertions(+), 238 deletions(-) diff --git a/src/lib/ares_data.c b/src/lib/ares_data.c index e6e8b67fe5..7e794389d1 100644 --- a/src/lib/ares_data.c +++ b/src/lib/ares_data.c @@ -42,8 +42,10 @@ void ares_free_data(void *dataptr) { - printf("dataptr: %p\n", (void *)dataptr); - printf("dataptr->host: %p; host: %s\n", (void *)((cares_srv_reply *)dataptr)->host, ((cares_srv_reply *)dataptr)->host); + printf("start ares_free_data\n"); + if (dataptr) { + printf("dataptr is good: %p\n", (void *)dataptr); + } while (dataptr != NULL) { struct ares_data *ptr; void *next_data = NULL; @@ -56,13 +58,20 @@ void ares_free_data(void *dataptr) ptr = (void *)((char *)dataptr - offsetof(struct ares_data, data)); printf("ptr in ares_data: %p\n", (void *)ptr); + if (ptr) { + printf("ptr in ares_data is good\n"); + } #ifdef __INTEL_COMPILER # pragma warning(pop) #endif - - if (ptr->mark != ARES_DATATYPE_MARK) + printf("before ptr mark check\n"); + if (ptr->mark != ARES_DATATYPE_MARK) { + printf("inside ptr mark\n"); return; + } + + printf("after ptr mark check\n"); switch (ptr->type) { @@ -76,15 +85,26 @@ void ares_free_data(void *dataptr) break; case ARES_DATATYPE_SRV_REPLY: - case CARES_DATATYPE_SRV_REPLY: + printf("inside ARES_DATATYPE case in ares_free_data\n"); if (ptr->data.srv_reply.next) next_data = ptr->data.srv_reply.next; if (ptr->data.srv_reply.host) { - printf("before ares_free in ares_data; srv_reply.host: %p, dataptr: %p; host:%s\n", (void *)ptr->data.srv_reply.host, (void *)&ptr->data, ptr->data.csrv_reply.host); + printf("before ares_free in ares_data srv\n"); ares_free(ptr->data.srv_reply.host); - printf("after ares_free in ares_data\n"); + printf("after ares_free in ares_data srv\n"); + } + break; + + case CARES_DATATYPE_SRV_REPLY: + + printf("inside CARES_DATATYPE case in ares_free_data\n"); + if (ptr->data.srv_reply.host) + { + printf("before ares_free in ares_data csrv\n"); + ares_free(ptr->data.csrv_reply.host); + printf("after ares_free in ares_data csrv\n"); } break; diff --git a/src/lib/ares_parse_srv_reply.c b/src/lib/ares_parse_srv_reply.c index 27151953db..395a4792da 100644 --- a/src/lib/ares_parse_srv_reply.c +++ b/src/lib/ares_parse_srv_reply.c @@ -55,14 +55,19 @@ ares_parse_srv_reply (const unsigned char *abuf, int alen, /* Set *srv_out to NULL for all failure cases. */ *srv_out = NULL; + printf("Before cares_parse_srv_reply in ares_parse_srv_reply; csrv_out: %p\n", (void *)csrv_out); status = cares_parse_srv_reply(abuf, alen, &csrv_out); - printf("After cares_parse_srv_reply in ares_parse_srv_reply\n"); + printf("After cares_parse_srv_reply in ares_parse_srv_reply; csrv_out: %p\n", (void *)csrv_out); /* clean up on error */ if (status != ARES_SUCCESS) { if (csrv_out) + { + printf("before cares_free_container in ares_parse\n"); cares_free_container(csrv_out); + printf("after cares_free_container in ares_parse\n"); + } return status; } @@ -79,6 +84,7 @@ ares_parse_srv_reply (const unsigned char *abuf, int alen, if (!srv_curr) { status = ARES_ENOMEM; + printf("ares_parse ENOMEM after srv_curr malloc\n"); break; } if (srv_last) @@ -90,6 +96,7 @@ ares_parse_srv_reply (const unsigned char *abuf, int alen, srv_head = srv_curr; } srv_last = srv_curr; + printf("before printing csrv_curr host in ares_parse\n"); printf("csrv_curr host: %p\n", (void *)cares_srv_reply_get_host(csrv_curr)); /* copy the host to newhost so we can free csrv_out */ diff --git a/src/lib/cares_free_container.c b/src/lib/cares_free_container.c index 0eb6e10097..c52ce20ea7 100644 --- a/src/lib/cares_free_container.c +++ b/src/lib/cares_free_container.c @@ -36,9 +36,12 @@ void cares_free_container(void *containerptr) if (ptr->mark != ARES_DATATYPE_MARK) return; + printf("after mark in free container\n"); + switch (ptr->type) { case CARES_CONTAINER_SRV_REPLY_CONTAINER: + printf("inside switch 1\n"); count = ptr->container.srv_container.count; break; @@ -46,11 +49,14 @@ void cares_free_container(void *containerptr) return; } + printf("before for loop in free container; count: %u\n", count); for (unsigned int i = 0; i < count; ++i) { + printf("outside switch 2\n"); switch (ptr->type) { case CARES_CONTAINER_SRV_REPLY_CONTAINER: + printf("inside switch 2\n"); if (ptr->container.srv_container.replies[i]) { printf("before free data; replies[i]: %p\n", (void *)ptr->container.srv_container.replies[i]); diff --git a/src/lib/cares_parse_srv_reply.c b/src/lib/cares_parse_srv_reply.c index 87221c085c..823ca5da2d 100644 --- a/src/lib/cares_parse_srv_reply.c +++ b/src/lib/cares_parse_srv_reply.c @@ -73,13 +73,14 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, if (ancount == 0) return ARES_ENODATA; - printf("before set count\n"); - cares_srv_reply_container_set_count(*srv_out, ancount); - printf("after set count\n"); printf("before srv_replies malloc, ancount: %d\n", ancount); printf("ancount * sizeof(**srv_replies): %lu\n", ancount * sizeof(**srv_replies)); srv_replies = ares_malloc(ancount * sizeof(**srv_replies)); printf("after srv_replies malloc\n"); + for (i = 0; i < ancount; ++i) + { + srv_replies[i] = NULL; + } /* Expand the name from the question, and skip past the question. */ aptr = abuf + HFIXEDSZ; @@ -97,7 +98,7 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, /* Examine each answer resource record (RR) in turn. */ for (i = 0; i < ancount; i++) { - printf("start loop\n"); + printf("start loop cares_parse_srv_reply\n"); count = i; /* Decode the RR up to the data field. */ status = ares_expand_name (aptr, abuf, alen, &rr_name, &len); @@ -184,14 +185,24 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, { for(i = 0; i <= count; ++i) { if (srv_replies[i]) + { + printf("before ares_free_data srv_replies[i] in cares_parse_srv: %p\n", (void *)srv_replies[i]); ares_free_data(srv_replies[i]); + printf("after ares_free_data srv_replies[i] in cares_parse_srv\n"); + } + } + printf("before ares_free srv_replies in cares_parse_srv\n"); ares_free(srv_replies); + printf("after ares_free srv_replies in cares_parse_srv\n"); } return status; } /* everything looks fine, return the data */ (*srv_out)->replies = srv_replies; + printf("before set count\n"); + cares_srv_reply_container_set_count(*srv_out, ancount); + printf("after set count\n"); return ARES_SUCCESS; } diff --git a/test/ares-test-parse-srv.cc b/test/ares-test-parse-srv.cc index a207185d25..0036b2f088 100644 --- a/test/ares-test-parse-srv.cc +++ b/test/ares-test-parse-srv.cc @@ -66,32 +66,32 @@ TEST_F(LibraryTest, ParseSrvReplyOK) { // ares_free_data(srv); // } -// TEST_F(LibraryTest, ParseSrvReplySingle) { -// DNSPacket pkt; -// pkt.set_qid(0x1234).set_response().set_aa() -// .add_question(new DNSQuestion("example.abc.def.com", T_SRV)) -// .add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")) -// .add_auth(new DNSNsRR("abc.def.com", 44, "else1.where.com")) -// .add_auth(new DNSNsRR("abc.def.com", 44, "else2.where.com")) -// .add_auth(new DNSNsRR("abc.def.com", 44, "else3.where.com")) -// .add_auth(new DNSNsRR("abc.def.com", 44, "else4.where.com")) -// .add_auth(new DNSNsRR("abc.def.com", 44, "else5.where.com")) -// .add_additional(new DNSARR("else2.where.com", 42, {172,19,0,1})) -// .add_additional(new DNSARR("else5.where.com", 42, {172,19,0,2})); -// std::vector data = pkt.data(); +TEST_F(LibraryTest, ParseSrvReplySingle) { + DNSPacket pkt; + pkt.set_qid(0x1234).set_response().set_aa() + .add_question(new DNSQuestion("example.abc.def.com", T_SRV)) + .add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")) + .add_auth(new DNSNsRR("abc.def.com", 44, "else1.where.com")) + .add_auth(new DNSNsRR("abc.def.com", 44, "else2.where.com")) + .add_auth(new DNSNsRR("abc.def.com", 44, "else3.where.com")) + .add_auth(new DNSNsRR("abc.def.com", 44, "else4.where.com")) + .add_auth(new DNSNsRR("abc.def.com", 44, "else5.where.com")) + .add_additional(new DNSARR("else2.where.com", 42, {172,19,0,1})) + .add_additional(new DNSARR("else5.where.com", 42, {172,19,0,2})); + std::vector data = pkt.data(); -// struct ares_srv_reply* srv = nullptr; -// EXPECT_EQ(ARES_SUCCESS, ares_parse_srv_reply(data.data(), data.size(), &srv)); -// ASSERT_NE(nullptr, srv); + struct ares_srv_reply* srv = nullptr; + EXPECT_EQ(ARES_SUCCESS, ares_parse_srv_reply(data.data(), data.size(), &srv)); + ASSERT_NE(nullptr, srv); -// EXPECT_EQ("example.abc.def.com", std::string(srv->host)); -// EXPECT_EQ(0, srv->priority); -// EXPECT_EQ(10, srv->weight); -// EXPECT_EQ(8160, srv->port); -// EXPECT_EQ(nullptr, srv->next); + EXPECT_EQ("example.abc.def.com", std::string(srv->host)); + EXPECT_EQ(0, srv->priority); + EXPECT_EQ(10, srv->weight); + EXPECT_EQ(8160, srv->port); + EXPECT_EQ(nullptr, srv->next); -// ares_free_data(srv); -// } + ares_free_data(srv); +} // TEST_F(LibraryTest, ParseCSrvReplySingle) { // DNSPacket pkt; @@ -121,36 +121,36 @@ TEST_F(LibraryTest, ParseSrvReplyOK) { // ares_free_data(srv); // } -// TEST_F(LibraryTest, ParseSrvReplyMalformed) { -// std::vector data = { -// 0x12, 0x34, // qid -// 0x84, // response + query + AA + not-TC + not-RD -// 0x00, // not-RA + not-Z + not-AD + not-CD + rc=NoError -// 0x00, 0x01, // num questions -// 0x00, 0x01, // num answer RRs -// 0x00, 0x00, // num authority RRs -// 0x00, 0x00, // num additional RRs -// // Question -// 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', -// 0x03, 'c', 'o', 'm', -// 0x00, -// 0x00, 0x21, // type SRV -// 0x00, 0x01, // class IN -// // Answer 1 -// 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', -// 0x03, 'c', 'o', 'm', -// 0x00, -// 0x00, 0x21, // RR type -// 0x00, 0x01, // class IN -// 0x01, 0x02, 0x03, 0x04, // TTL -// 0x00, 0x04, // rdata length -- too short -// 0x02, 0x03, 0x04, 0x05, -// }; +TEST_F(LibraryTest, ParseSrvReplyMalformed) { + std::vector data = { + 0x12, 0x34, // qid + 0x84, // response + query + AA + not-TC + not-RD + 0x00, // not-RA + not-Z + not-AD + not-CD + rc=NoError + 0x00, 0x01, // num questions + 0x00, 0x01, // num answer RRs + 0x00, 0x00, // num authority RRs + 0x00, 0x00, // num additional RRs + // Question + 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', + 0x03, 'c', 'o', 'm', + 0x00, + 0x00, 0x21, // type SRV + 0x00, 0x01, // class IN + // Answer 1 + 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', + 0x03, 'c', 'o', 'm', + 0x00, + 0x00, 0x21, // RR type + 0x00, 0x01, // class IN + 0x01, 0x02, 0x03, 0x04, // TTL + 0x00, 0x04, // rdata length -- too short + 0x02, 0x03, 0x04, 0x05, + }; -// struct ares_srv_reply* srv = nullptr; -// EXPECT_EQ(ARES_EBADRESP, ares_parse_srv_reply(data.data(), data.size(), &srv)); -// ASSERT_EQ(nullptr, srv); -// } + struct ares_srv_reply* srv = nullptr; + EXPECT_EQ(ARES_EBADRESP, ares_parse_srv_reply(data.data(), data.size(), &srv)); + ASSERT_EQ(nullptr, srv); +} // TEST_F(LibraryTest, ParseCSrvReplyMalformed) { // std::vector data = { @@ -183,51 +183,51 @@ TEST_F(LibraryTest, ParseSrvReplyOK) { // ASSERT_EQ(nullptr, srv); // } -// TEST_F(LibraryTest, ParseSrvReplyMultiple) { -// DNSPacket pkt; -// pkt.set_qid(0x1234).set_response().set_ra().set_rd() -// .add_question(new DNSQuestion("srv.example.com", T_SRV)) -// .add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 6789, "a1.srv.example.com")) -// .add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 4567, "a2.srv.example.com")) -// .add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 5678, "a3.srv.example.com")) -// .add_auth(new DNSNsRR("example.com", 300, "ns1.example.com")) -// .add_auth(new DNSNsRR("example.com", 300, "ns2.example.com")) -// .add_auth(new DNSNsRR("example.com", 300, "ns3.example.com")) -// .add_additional(new DNSARR("a1.srv.example.com", 300, {172,19,1,1})) -// .add_additional(new DNSARR("a2.srv.example.com", 300, {172,19,1,2})) -// .add_additional(new DNSARR("a3.srv.example.com", 300, {172,19,1,3})) -// .add_additional(new DNSARR("n1.example.com", 300, {172,19,0,1})) -// .add_additional(new DNSARR("n2.example.com", 300, {172,19,0,2})) -// .add_additional(new DNSARR("n3.example.com", 300, {172,19,0,3})); -// std::vector data = pkt.data(); - -// struct ares_srv_reply* srv0 = nullptr; -// EXPECT_EQ(ARES_SUCCESS, ares_parse_srv_reply(data.data(), data.size(), &srv0)); -// ASSERT_NE(nullptr, srv0); -// struct ares_srv_reply* srv = srv0; - -// EXPECT_EQ("a1.srv.example.com", std::string(srv->host)); -// EXPECT_EQ(0, srv->priority); -// EXPECT_EQ(5, srv->weight); -// EXPECT_EQ(6789, srv->port); -// EXPECT_NE(nullptr, srv->next); -// srv = srv->next; - -// EXPECT_EQ("a2.srv.example.com", std::string(srv->host)); -// EXPECT_EQ(0, srv->priority); -// EXPECT_EQ(5, srv->weight); -// EXPECT_EQ(4567, srv->port); -// EXPECT_NE(nullptr, srv->next); -// srv = srv->next; - -// EXPECT_EQ("a3.srv.example.com", std::string(srv->host)); -// EXPECT_EQ(0, srv->priority); -// EXPECT_EQ(5, srv->weight); -// EXPECT_EQ(5678, srv->port); -// EXPECT_EQ(nullptr, srv->next); +TEST_F(LibraryTest, ParseSrvReplyMultiple) { + DNSPacket pkt; + pkt.set_qid(0x1234).set_response().set_ra().set_rd() + .add_question(new DNSQuestion("srv.example.com", T_SRV)) + .add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 6789, "a1.srv.example.com")) + .add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 4567, "a2.srv.example.com")) + .add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 5678, "a3.srv.example.com")) + .add_auth(new DNSNsRR("example.com", 300, "ns1.example.com")) + .add_auth(new DNSNsRR("example.com", 300, "ns2.example.com")) + .add_auth(new DNSNsRR("example.com", 300, "ns3.example.com")) + .add_additional(new DNSARR("a1.srv.example.com", 300, {172,19,1,1})) + .add_additional(new DNSARR("a2.srv.example.com", 300, {172,19,1,2})) + .add_additional(new DNSARR("a3.srv.example.com", 300, {172,19,1,3})) + .add_additional(new DNSARR("n1.example.com", 300, {172,19,0,1})) + .add_additional(new DNSARR("n2.example.com", 300, {172,19,0,2})) + .add_additional(new DNSARR("n3.example.com", 300, {172,19,0,3})); + std::vector data = pkt.data(); -// ares_free_data(srv0); -// } + struct ares_srv_reply* srv0 = nullptr; + EXPECT_EQ(ARES_SUCCESS, ares_parse_srv_reply(data.data(), data.size(), &srv0)); + ASSERT_NE(nullptr, srv0); + struct ares_srv_reply* srv = srv0; + + EXPECT_EQ("a1.srv.example.com", std::string(srv->host)); + EXPECT_EQ(0, srv->priority); + EXPECT_EQ(5, srv->weight); + EXPECT_EQ(6789, srv->port); + EXPECT_NE(nullptr, srv->next); + srv = srv->next; + + EXPECT_EQ("a2.srv.example.com", std::string(srv->host)); + EXPECT_EQ(0, srv->priority); + EXPECT_EQ(5, srv->weight); + EXPECT_EQ(4567, srv->port); + EXPECT_NE(nullptr, srv->next); + srv = srv->next; + + EXPECT_EQ("a3.srv.example.com", std::string(srv->host)); + EXPECT_EQ(0, srv->priority); + EXPECT_EQ(5, srv->weight); + EXPECT_EQ(5678, srv->port); + EXPECT_EQ(nullptr, srv->next); + + ares_free_data(srv0); +} // TEST_F(LibraryTest, ParseCSrvReplyMultiple) { // DNSPacket pkt; @@ -278,33 +278,33 @@ TEST_F(LibraryTest, ParseSrvReplyOK) { // ares_free_data(srv0); // } -// TEST_F(LibraryTest, ParseSrvReplyCname) { -// DNSPacket pkt; -// pkt.set_qid(0x1234).set_response().set_aa() -// .add_question(new DNSQuestion("example.abc.def.com", T_SRV)) -// .add_answer(new DNSCnameRR("example.abc.def.com", 300, "cname.abc.def.com")) -// .add_answer(new DNSSrvRR("cname.abc.def.com", 300, 0, 10, 1234, "srv.abc.def.com")) -// .add_auth(new DNSNsRR("abc.def.com", 44, "else1.where.com")) -// .add_auth(new DNSNsRR("abc.def.com", 44, "else2.where.com")) -// .add_auth(new DNSNsRR("abc.def.com", 44, "else3.where.com")) -// .add_additional(new DNSARR("example.abc.def.com", 300, {172,19,0,1})) -// .add_additional(new DNSARR("else1.where.com", 42, {172,19,0,1})) -// .add_additional(new DNSARR("else2.where.com", 42, {172,19,0,2})) -// .add_additional(new DNSARR("else3.where.com", 42, {172,19,0,3})); -// std::vector data = pkt.data(); +TEST_F(LibraryTest, ParseSrvReplyCname) { + DNSPacket pkt; + pkt.set_qid(0x1234).set_response().set_aa() + .add_question(new DNSQuestion("example.abc.def.com", T_SRV)) + .add_answer(new DNSCnameRR("example.abc.def.com", 300, "cname.abc.def.com")) + .add_answer(new DNSSrvRR("cname.abc.def.com", 300, 0, 10, 1234, "srv.abc.def.com")) + .add_auth(new DNSNsRR("abc.def.com", 44, "else1.where.com")) + .add_auth(new DNSNsRR("abc.def.com", 44, "else2.where.com")) + .add_auth(new DNSNsRR("abc.def.com", 44, "else3.where.com")) + .add_additional(new DNSARR("example.abc.def.com", 300, {172,19,0,1})) + .add_additional(new DNSARR("else1.where.com", 42, {172,19,0,1})) + .add_additional(new DNSARR("else2.where.com", 42, {172,19,0,2})) + .add_additional(new DNSARR("else3.where.com", 42, {172,19,0,3})); + std::vector data = pkt.data(); -// struct ares_srv_reply* srv = nullptr; -// EXPECT_EQ(ARES_SUCCESS, ares_parse_srv_reply(data.data(), data.size(), &srv)); -// ASSERT_NE(nullptr, srv); + struct ares_srv_reply* srv = nullptr; + EXPECT_EQ(ARES_SUCCESS, ares_parse_srv_reply(data.data(), data.size(), &srv)); + ASSERT_NE(nullptr, srv); -// EXPECT_EQ("srv.abc.def.com", std::string(srv->host)); -// EXPECT_EQ(0, srv->priority); -// EXPECT_EQ(10, srv->weight); -// EXPECT_EQ(1234, srv->port); -// EXPECT_EQ(nullptr, srv->next); + EXPECT_EQ("srv.abc.def.com", std::string(srv->host)); + EXPECT_EQ(0, srv->priority); + EXPECT_EQ(10, srv->weight); + EXPECT_EQ(1234, srv->port); + EXPECT_EQ(nullptr, srv->next); -// ares_free_data(srv); -// } + ares_free_data(srv); +} // TEST_F(LibraryTest, ParseCSrvReplyCname) { // DNSPacket pkt; @@ -335,52 +335,52 @@ TEST_F(LibraryTest, ParseSrvReplyOK) { // ares_free_data(srv); // } -// TEST_F(LibraryTest, ParseSrvReplyCnameMultiple) { -// DNSPacket pkt; -// pkt.set_qid(0x1234).set_response().set_ra().set_rd() -// .add_question(new DNSQuestion("query.example.com", T_SRV)) -// .add_answer(new DNSCnameRR("query.example.com", 300, "srv.example.com")) -// .add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 6789, "a1.srv.example.com")) -// .add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 4567, "a2.srv.example.com")) -// .add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 5678, "a3.srv.example.com")) -// .add_auth(new DNSNsRR("example.com", 300, "ns1.example.com")) -// .add_auth(new DNSNsRR("example.com", 300, "ns2.example.com")) -// .add_auth(new DNSNsRR("example.com", 300, "ns3.example.com")) -// .add_additional(new DNSARR("a1.srv.example.com", 300, {172,19,1,1})) -// .add_additional(new DNSARR("a2.srv.example.com", 300, {172,19,1,2})) -// .add_additional(new DNSARR("a3.srv.example.com", 300, {172,19,1,3})) -// .add_additional(new DNSARR("n1.example.com", 300, {172,19,0,1})) -// .add_additional(new DNSARR("n2.example.com", 300, {172,19,0,2})) -// .add_additional(new DNSARR("n3.example.com", 300, {172,19,0,3})); -// std::vector data = pkt.data(); - -// struct ares_srv_reply* srv0 = nullptr; -// EXPECT_EQ(ARES_SUCCESS, ares_parse_srv_reply(data.data(), data.size(), &srv0)); -// ASSERT_NE(nullptr, srv0); -// struct ares_srv_reply* srv = srv0; - -// EXPECT_EQ("a1.srv.example.com", std::string(srv->host)); -// EXPECT_EQ(0, srv->priority); -// EXPECT_EQ(5, srv->weight); -// EXPECT_EQ(6789, srv->port); -// EXPECT_NE(nullptr, srv->next); -// srv = srv->next; - -// EXPECT_EQ("a2.srv.example.com", std::string(srv->host)); -// EXPECT_EQ(0, srv->priority); -// EXPECT_EQ(5, srv->weight); -// EXPECT_EQ(4567, srv->port); -// EXPECT_NE(nullptr, srv->next); -// srv = srv->next; - -// EXPECT_EQ("a3.srv.example.com", std::string(srv->host)); -// EXPECT_EQ(0, srv->priority); -// EXPECT_EQ(5, srv->weight); -// EXPECT_EQ(5678, srv->port); -// EXPECT_EQ(nullptr, srv->next); +TEST_F(LibraryTest, ParseSrvReplyCnameMultiple) { + DNSPacket pkt; + pkt.set_qid(0x1234).set_response().set_ra().set_rd() + .add_question(new DNSQuestion("query.example.com", T_SRV)) + .add_answer(new DNSCnameRR("query.example.com", 300, "srv.example.com")) + .add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 6789, "a1.srv.example.com")) + .add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 4567, "a2.srv.example.com")) + .add_answer(new DNSSrvRR("srv.example.com", 300, 0, 5, 5678, "a3.srv.example.com")) + .add_auth(new DNSNsRR("example.com", 300, "ns1.example.com")) + .add_auth(new DNSNsRR("example.com", 300, "ns2.example.com")) + .add_auth(new DNSNsRR("example.com", 300, "ns3.example.com")) + .add_additional(new DNSARR("a1.srv.example.com", 300, {172,19,1,1})) + .add_additional(new DNSARR("a2.srv.example.com", 300, {172,19,1,2})) + .add_additional(new DNSARR("a3.srv.example.com", 300, {172,19,1,3})) + .add_additional(new DNSARR("n1.example.com", 300, {172,19,0,1})) + .add_additional(new DNSARR("n2.example.com", 300, {172,19,0,2})) + .add_additional(new DNSARR("n3.example.com", 300, {172,19,0,3})); + std::vector data = pkt.data(); -// ares_free_data(srv0); -// } + struct ares_srv_reply* srv0 = nullptr; + EXPECT_EQ(ARES_SUCCESS, ares_parse_srv_reply(data.data(), data.size(), &srv0)); + ASSERT_NE(nullptr, srv0); + struct ares_srv_reply* srv = srv0; + + EXPECT_EQ("a1.srv.example.com", std::string(srv->host)); + EXPECT_EQ(0, srv->priority); + EXPECT_EQ(5, srv->weight); + EXPECT_EQ(6789, srv->port); + EXPECT_NE(nullptr, srv->next); + srv = srv->next; + + EXPECT_EQ("a2.srv.example.com", std::string(srv->host)); + EXPECT_EQ(0, srv->priority); + EXPECT_EQ(5, srv->weight); + EXPECT_EQ(4567, srv->port); + EXPECT_NE(nullptr, srv->next); + srv = srv->next; + + EXPECT_EQ("a3.srv.example.com", std::string(srv->host)); + EXPECT_EQ(0, srv->priority); + EXPECT_EQ(5, srv->weight); + EXPECT_EQ(5678, srv->port); + EXPECT_EQ(nullptr, srv->next); + + ares_free_data(srv0); +} // TEST_F(LibraryTest, ParseCSrvReplyCnameMultiple) { // DNSPacket pkt; @@ -432,54 +432,54 @@ TEST_F(LibraryTest, ParseSrvReplyOK) { // ares_free_data(srv0); // } -// TEST_F(LibraryTest, ParseSrvReplyErrors) { -// DNSPacket pkt; -// pkt.set_qid(0x1234).set_response().set_aa() -// .add_question(new DNSQuestion("example.abc.def.com", T_SRV)) -// .add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")); -// std::vector data; -// struct ares_srv_reply* srv = nullptr; +TEST_F(LibraryTest, ParseSrvReplyErrors) { + DNSPacket pkt; + pkt.set_qid(0x1234).set_response().set_aa() + .add_question(new DNSQuestion("example.abc.def.com", T_SRV)) + .add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")); + std::vector data; + struct ares_srv_reply* srv = nullptr; -// // No question. -// pkt.questions_.clear(); -// data = pkt.data(); -// EXPECT_EQ(ARES_EBADRESP, ares_parse_srv_reply(data.data(), data.size(), &srv)); -// pkt.add_question(new DNSQuestion("example.abc.def.com", T_SRV)); -// #ifdef DISABLED -// // Question != answer -// pkt.questions_.clear(); -// pkt.add_question(new DNSQuestion("Axample.com", T_SRV)); -// data = pkt.data(); -// EXPECT_EQ(ARES_ENODATA, ares_parse_srv_reply(data.data(), data.size(), &srv)); -// pkt.questions_.clear(); -// pkt.add_question(new DNSQuestion("example.com", T_SRV)); -// #endif -// // Two questions. -// pkt.add_question(new DNSQuestion("example.abc.def.com", T_SRV)); -// data = pkt.data(); -// EXPECT_EQ(ARES_EBADRESP, ares_parse_srv_reply(data.data(), data.size(), &srv)); -// pkt.questions_.clear(); -// pkt.add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR)); -// // Wrong sort of answer. -// pkt.answers_.clear(); -// pkt.add_answer(new DNSMxRR("example.com", 100, 100, "mx1.example.com")); -// data = pkt.data(); -// EXPECT_EQ(ARES_ENODATA, ares_parse_srv_reply(data.data(), data.size(), &srv)); -// EXPECT_EQ(nullptr, srv); -// pkt.answers_.clear(); -// pkt.add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")); -// // No answer. -// pkt.answers_.clear(); -// data = pkt.data(); -// EXPECT_EQ(ARES_ENODATA, ares_parse_srv_reply(data.data(), data.size(), &srv)); -// pkt.add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")); -// // Truncated packets. -// data = pkt.data(); -// for (size_t len = 1; len < data.size(); len++) { -// int rc = ares_parse_srv_reply(data.data(), len, &srv); -// EXPECT_TRUE(rc == ARES_EBADRESP || rc == ARES_EBADNAME); -// } -// } + // No question. + pkt.questions_.clear(); + data = pkt.data(); + EXPECT_EQ(ARES_EBADRESP, ares_parse_srv_reply(data.data(), data.size(), &srv)); + pkt.add_question(new DNSQuestion("example.abc.def.com", T_SRV)); +#ifdef DISABLED + // Question != answer + pkt.questions_.clear(); + pkt.add_question(new DNSQuestion("Axample.com", T_SRV)); + data = pkt.data(); + EXPECT_EQ(ARES_ENODATA, ares_parse_srv_reply(data.data(), data.size(), &srv)); + pkt.questions_.clear(); + pkt.add_question(new DNSQuestion("example.com", T_SRV)); +#endif + // Two questions. + pkt.add_question(new DNSQuestion("example.abc.def.com", T_SRV)); + data = pkt.data(); + EXPECT_EQ(ARES_EBADRESP, ares_parse_srv_reply(data.data(), data.size(), &srv)); + pkt.questions_.clear(); + pkt.add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR)); + // Wrong sort of answer. + pkt.answers_.clear(); + pkt.add_answer(new DNSMxRR("example.com", 100, 100, "mx1.example.com")); + data = pkt.data(); + EXPECT_EQ(ARES_ENODATA, ares_parse_srv_reply(data.data(), data.size(), &srv)); + EXPECT_EQ(nullptr, srv); + pkt.answers_.clear(); + pkt.add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")); + // No answer. + pkt.answers_.clear(); + data = pkt.data(); + EXPECT_EQ(ARES_ENODATA, ares_parse_srv_reply(data.data(), data.size(), &srv)); + pkt.add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")); + // Truncated packets. + data = pkt.data(); + for (size_t len = 1; len < data.size(); len++) { + int rc = ares_parse_srv_reply(data.data(), len, &srv); + EXPECT_TRUE(rc == ARES_EBADRESP || rc == ARES_EBADNAME); + } +} // TEST_F(LibraryTest, ParseCSrvReplyErrors) { // DNSPacket pkt; @@ -535,21 +535,21 @@ TEST_F(LibraryTest, ParseSrvReplyOK) { // } // } -// TEST_F(LibraryTest, ParseSrvReplyAllocFail) { -// DNSPacket pkt; -// pkt.set_qid(0x1234).set_response().set_aa() -// .add_question(new DNSQuestion("example.abc.def.com", T_SRV)) -// .add_answer(new DNSCnameRR("example.com", 300, "c.example.com")) -// .add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")); -// std::vector data = pkt.data(); -// struct ares_srv_reply* srv = nullptr; +TEST_F(LibraryTest, ParseSrvReplyAllocFail) { + DNSPacket pkt; + pkt.set_qid(0x1234).set_response().set_aa() + .add_question(new DNSQuestion("example.abc.def.com", T_SRV)) + .add_answer(new DNSCnameRR("example.com", 300, "c.example.com")) + .add_answer(new DNSSrvRR("example.abc.def.com", 180, 0, 10, 8160, "example.abc.def.com")); + std::vector data = pkt.data(); + struct ares_srv_reply* srv = nullptr; -// for (int ii = 1; ii <= 5; ii++) { -// ClearFails(); -// SetAllocFail(ii); -// EXPECT_EQ(ARES_ENOMEM, ares_parse_srv_reply(data.data(), data.size(), &srv)) << ii; -// } -// } + for (int ii = 1; ii <= 5; ii++) { + ClearFails(); + SetAllocFail(ii); + EXPECT_EQ(ARES_ENOMEM, ares_parse_srv_reply(data.data(), data.size(), &srv)) << ii; + } +} // TEST_F(LibraryTest, ParseCSrvReplyAllocFail) { // DNSPacket pkt; From 867e3f7458920f0c900f23d17539685fb4eda4d8 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Sun, 2 Jan 2022 11:04:04 -0500 Subject: [PATCH 32/49] fix crashes --- src/lib/cares_parse_srv_reply.c | 50 ++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/src/lib/cares_parse_srv_reply.c b/src/lib/cares_parse_srv_reply.c index 823ca5da2d..83619a79e4 100644 --- a/src/lib/cares_parse_srv_reply.c +++ b/src/lib/cares_parse_srv_reply.c @@ -40,7 +40,7 @@ int cares_parse_srv_reply (const unsigned char *abuf, int alen, cares_srv_reply_container **srv_out) { - unsigned int qdcount, ancount, i, count; + unsigned int qdcount, ancount, i, count = 0; const unsigned char *aptr, *vptr; int status, rr_type, rr_class, rr_len; unsigned int rr_ttl; @@ -55,12 +55,6 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, /* Set *srv_out to NULL for all failure cases. */ *srv_out = NULL; - printf("before cares_malloc_container\n"); - *srv_out = cares_malloc_container(CARES_CONTAINER_SRV_REPLY_CONTAINER); - printf("after cares_malloc_container\n"); - if (*srv_out == NULL) - return ARES_ENOMEM; - /* Give up if abuf doesn't have room for a header. */ if (alen < HFIXEDSZ) return ARES_EBADRESP; @@ -72,15 +66,6 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, return ARES_EBADRESP; if (ancount == 0) return ARES_ENODATA; - - printf("before srv_replies malloc, ancount: %d\n", ancount); - printf("ancount * sizeof(**srv_replies): %lu\n", ancount * sizeof(**srv_replies)); - srv_replies = ares_malloc(ancount * sizeof(**srv_replies)); - printf("after srv_replies malloc\n"); - for (i = 0; i < ancount; ++i) - { - srv_replies[i] = NULL; - } /* Expand the name from the question, and skip past the question. */ aptr = abuf + HFIXEDSZ; @@ -95,11 +80,25 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, } aptr += len + QFIXEDSZ; + printf("before srv_replies malloc, ancount: %d\n", ancount); + printf("ancount * sizeof(**srv_replies): %lu\n", ancount * sizeof(**srv_replies)); + srv_replies = ares_malloc(ancount * sizeof(**srv_replies)); + printf("after srv_replies malloc\n"); + if (srv_replies == NULL) + { + ares_free (hostname); + return ARES_ENOMEM; + } + + for (i = 0; i < ancount; ++i) + { + srv_replies[i] = NULL; + } + /* Examine each answer resource record (RR) in turn. */ for (i = 0; i < ancount; i++) { printf("start loop cares_parse_srv_reply\n"); - count = i; /* Decode the RR up to the data field. */ status = ares_expand_name (aptr, abuf, alen, &rr_name, &len); if (status != ARES_SUCCESS) @@ -155,9 +154,10 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, break; cares_srv_reply_set_host(srv_curr, srv_host); printf("srv_curr->host: %p; host: %s\n", (void *)srv_curr->host, srv_curr->host); - printf("before assign to srv_replies[i]; srv_curr: %p\n", (void *)srv_curr); - srv_replies[i] = srv_curr; - printf("after assign to srv_replies[i]: %p; srv_replies[i]->host: %p\n", (void *)srv_replies[i], (void *)srv_replies[i]->host); + printf("before assign to srv_replies[count]; count: %u; srv_curr: %p\n", count, (void *)srv_curr); + srv_replies[count] = srv_curr; + printf("after assign to srv_replies[count]: %p; srv_replies[count]->host: %p\n", (void *)srv_replies[count], (void *)srv_replies[count]->host); + count++; } else if (rr_type != T_CNAME) { @@ -183,7 +183,7 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, { if (srv_replies) { - for(i = 0; i <= count; ++i) { + for(i = 0; i < count; ++i) { if (srv_replies[i]) { printf("before ares_free_data srv_replies[i] in cares_parse_srv: %p\n", (void *)srv_replies[i]); @@ -199,10 +199,16 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, return status; } + printf("before cares_malloc_container\n"); + *srv_out = cares_malloc_container(CARES_CONTAINER_SRV_REPLY_CONTAINER); + printf("after cares_malloc_container\n"); + if (*srv_out == NULL) + return ARES_ENOMEM; + /* everything looks fine, return the data */ (*srv_out)->replies = srv_replies; printf("before set count\n"); - cares_srv_reply_container_set_count(*srv_out, ancount); + cares_srv_reply_container_set_count(*srv_out, count); printf("after set count\n"); return ARES_SUCCESS; } From 0f5ba50526d1017d70d4de35ddb24e5ddd9f57a9 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Sun, 2 Jan 2022 12:27:21 -0500 Subject: [PATCH 33/49] remove print statements --- src/lib/ares_data.c | 20 ++------------------ src/lib/ares_parse_srv_reply.c | 14 -------------- src/lib/cares_free_container.c | 16 ---------------- src/lib/cares_parse_srv_reply.c | 16 ---------------- 4 files changed, 2 insertions(+), 64 deletions(-) diff --git a/src/lib/ares_data.c b/src/lib/ares_data.c index 7e794389d1..cf46c8dfcb 100644 --- a/src/lib/ares_data.c +++ b/src/lib/ares_data.c @@ -22,7 +22,6 @@ #include "ares.h" #include "ares_data.h" #include "ares_private.h" -#include "stdio.h" /* @@ -42,10 +41,7 @@ void ares_free_data(void *dataptr) { - printf("start ares_free_data\n"); - if (dataptr) { - printf("dataptr is good: %p\n", (void *)dataptr); - } + while (dataptr != NULL) { struct ares_data *ptr; void *next_data = NULL; @@ -57,21 +53,15 @@ void ares_free_data(void *dataptr) #endif ptr = (void *)((char *)dataptr - offsetof(struct ares_data, data)); - printf("ptr in ares_data: %p\n", (void *)ptr); - if (ptr) { - printf("ptr in ares_data is good\n"); - } #ifdef __INTEL_COMPILER # pragma warning(pop) #endif - printf("before ptr mark check\n"); + if (ptr->mark != ARES_DATATYPE_MARK) { - printf("inside ptr mark\n"); return; } - printf("after ptr mark check\n"); switch (ptr->type) { @@ -86,25 +76,19 @@ void ares_free_data(void *dataptr) case ARES_DATATYPE_SRV_REPLY: - printf("inside ARES_DATATYPE case in ares_free_data\n"); if (ptr->data.srv_reply.next) next_data = ptr->data.srv_reply.next; if (ptr->data.srv_reply.host) { - printf("before ares_free in ares_data srv\n"); ares_free(ptr->data.srv_reply.host); - printf("after ares_free in ares_data srv\n"); } break; case CARES_DATATYPE_SRV_REPLY: - printf("inside CARES_DATATYPE case in ares_free_data\n"); if (ptr->data.srv_reply.host) { - printf("before ares_free in ares_data csrv\n"); ares_free(ptr->data.csrv_reply.host); - printf("after ares_free in ares_data csrv\n"); } break; diff --git a/src/lib/ares_parse_srv_reply.c b/src/lib/ares_parse_srv_reply.c index 395a4792da..bb819e7f62 100644 --- a/src/lib/ares_parse_srv_reply.c +++ b/src/lib/ares_parse_srv_reply.c @@ -34,7 +34,6 @@ #include "ares_dns.h" #include "ares_data.h" #include "ares_private.h" -#include "stdio.h" int ares_parse_srv_reply (const unsigned char *abuf, int alen, @@ -55,18 +54,14 @@ ares_parse_srv_reply (const unsigned char *abuf, int alen, /* Set *srv_out to NULL for all failure cases. */ *srv_out = NULL; - printf("Before cares_parse_srv_reply in ares_parse_srv_reply; csrv_out: %p\n", (void *)csrv_out); status = cares_parse_srv_reply(abuf, alen, &csrv_out); - printf("After cares_parse_srv_reply in ares_parse_srv_reply; csrv_out: %p\n", (void *)csrv_out); /* clean up on error */ if (status != ARES_SUCCESS) { if (csrv_out) { - printf("before cares_free_container in ares_parse\n"); cares_free_container(csrv_out); - printf("after cares_free_container in ares_parse\n"); } return status; } @@ -77,14 +72,10 @@ ares_parse_srv_reply (const unsigned char *abuf, int alen, !cares_srv_reply_container_at_end(csrv_out); csrv_curr = cares_srv_reply_container_get_next(csrv_out)) { - printf("csrv_out curr: %u\n", cares_srv_reply_container_get_curr(csrv_out)); - printf("csrv_out count: %u\n", cares_srv_reply_container_get_count(csrv_out)); srv_curr = ares_malloc_data(ARES_DATATYPE_SRV_REPLY); - printf("after srv_curr malloc\n"); if (!srv_curr) { status = ARES_ENOMEM; - printf("ares_parse ENOMEM after srv_curr malloc\n"); break; } if (srv_last) @@ -96,16 +87,13 @@ ares_parse_srv_reply (const unsigned char *abuf, int alen, srv_head = srv_curr; } srv_last = srv_curr; - printf("before printing csrv_curr host in ares_parse\n"); - printf("csrv_curr host: %p\n", (void *)cares_srv_reply_get_host(csrv_curr)); /* copy the host to newhost so we can free csrv_out */ newhost = ares_strdup(cares_srv_reply_get_host(csrv_curr)); if (!newhost) { status = ARES_ENOMEM; break; } - printf("newhost: %p\n", (void *)newhost); srv_curr->host = newhost; srv_curr->priority = cares_srv_reply_get_priority(csrv_curr); @@ -115,9 +103,7 @@ ares_parse_srv_reply (const unsigned char *abuf, int alen, if (csrv_out) { - printf("before cares_free_container\n"); cares_free_container(csrv_out); - printf("after cares_free_container\n"); } /* clean up on error */ diff --git a/src/lib/cares_free_container.c b/src/lib/cares_free_container.c index c52ce20ea7..3a3750f11e 100644 --- a/src/lib/cares_free_container.c +++ b/src/lib/cares_free_container.c @@ -17,31 +17,24 @@ #include "ares_private.h" #include "cares_free_container.h" #include "ares_data.h" -#include "stdio.h" void cares_free_container(void *containerptr) { if (containerptr == NULL) { return; } - printf("containerptr: %p\n", (void *)containerptr); struct cares_container *ptr; unsigned int count; ptr = (void *)((char *)containerptr - offsetof(struct cares_container, container)); - printf("ptr: %p\n", (void *)ptr); - if (ptr->mark != ARES_DATATYPE_MARK) return; - printf("after mark in free container\n"); - switch (ptr->type) { case CARES_CONTAINER_SRV_REPLY_CONTAINER: - printf("inside switch 1\n"); count = ptr->container.srv_container.count; break; @@ -49,26 +42,19 @@ void cares_free_container(void *containerptr) return; } - printf("before for loop in free container; count: %u\n", count); for (unsigned int i = 0; i < count; ++i) { - printf("outside switch 2\n"); switch (ptr->type) { case CARES_CONTAINER_SRV_REPLY_CONTAINER: - printf("inside switch 2\n"); if (ptr->container.srv_container.replies[i]) { - printf("before free data; replies[i]: %p\n", (void *)ptr->container.srv_container.replies[i]); ares_free_data(ptr->container.srv_container.replies[i]); - printf("after free data\n"); } if (i == count - 1) { - printf("before free replies\n"); ares_free(ptr->container.srv_container.replies); - printf("after free replies\n"); break; } @@ -77,9 +63,7 @@ void cares_free_container(void *containerptr) } } - printf("before free ptr\n"); ares_free(ptr); - printf("after free ptr\n"); } void *cares_malloc_container(cares_container_type type) diff --git a/src/lib/cares_parse_srv_reply.c b/src/lib/cares_parse_srv_reply.c index 83619a79e4..1339a358fa 100644 --- a/src/lib/cares_parse_srv_reply.c +++ b/src/lib/cares_parse_srv_reply.c @@ -34,7 +34,6 @@ #include "ares_data.h" #include "ares_private.h" #include "cares_free_container.h" -#include "stdio.h" int cares_parse_srv_reply (const unsigned char *abuf, int alen, @@ -80,10 +79,7 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, } aptr += len + QFIXEDSZ; - printf("before srv_replies malloc, ancount: %d\n", ancount); - printf("ancount * sizeof(**srv_replies): %lu\n", ancount * sizeof(**srv_replies)); srv_replies = ares_malloc(ancount * sizeof(**srv_replies)); - printf("after srv_replies malloc\n"); if (srv_replies == NULL) { ares_free (hostname); @@ -98,7 +94,6 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, /* Examine each answer resource record (RR) in turn. */ for (i = 0; i < ancount; i++) { - printf("start loop cares_parse_srv_reply\n"); /* Decode the RR up to the data field. */ status = ares_expand_name (aptr, abuf, alen, &rr_name, &len); if (status != ARES_SUCCESS) @@ -153,10 +148,7 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, if (status != ARES_SUCCESS) break; cares_srv_reply_set_host(srv_curr, srv_host); - printf("srv_curr->host: %p; host: %s\n", (void *)srv_curr->host, srv_curr->host); - printf("before assign to srv_replies[count]; count: %u; srv_curr: %p\n", count, (void *)srv_curr); srv_replies[count] = srv_curr; - printf("after assign to srv_replies[count]: %p; srv_replies[count]->host: %p\n", (void *)srv_replies[count], (void *)srv_replies[count]->host); count++; } else if (rr_type != T_CNAME) @@ -186,29 +178,21 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, for(i = 0; i < count; ++i) { if (srv_replies[i]) { - printf("before ares_free_data srv_replies[i] in cares_parse_srv: %p\n", (void *)srv_replies[i]); ares_free_data(srv_replies[i]); - printf("after ares_free_data srv_replies[i] in cares_parse_srv\n"); } } - printf("before ares_free srv_replies in cares_parse_srv\n"); ares_free(srv_replies); - printf("after ares_free srv_replies in cares_parse_srv\n"); } return status; } - printf("before cares_malloc_container\n"); *srv_out = cares_malloc_container(CARES_CONTAINER_SRV_REPLY_CONTAINER); - printf("after cares_malloc_container\n"); if (*srv_out == NULL) return ARES_ENOMEM; /* everything looks fine, return the data */ (*srv_out)->replies = srv_replies; - printf("before set count\n"); cares_srv_reply_container_set_count(*srv_out, count); - printf("after set count\n"); return ARES_SUCCESS; } From 9268be0f345f5c3cab57cc2b3a2d0a87b3ff9648 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Sun, 2 Jan 2022 13:31:28 -0500 Subject: [PATCH 34/49] Add build/test instructions for asan --- CONTRIBUTING.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a3b5194c78..75c70adb3f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -13,3 +13,13 @@ To improve the chances of the c-ares maintainers responding to your request: - Also send an email to the mailing list at `c-ares@lists.haxx.se` describing your change. - To follow any associated discussion, please subscribe to the [mailing list](http://lists.haxx.se/listinfo/c-ares). + +To build locally with asan, ubsan, and lsan: +``` +export BUILD_TYPE=asan +export CFLAGS=-fsanitize=address +export CXXFLAGS=-fsanitize=address +export LDFLAGS=-fsanitize=address +./configure --disable-symbol-hiding --enable-expose-statics --enable-maintainer-mode --enable-debug +ASAN_OPTIONS=detect_leaks=1 test/arestest --gtest_filter='-*.Live*' +``` From 13aec44460e4212ae4a33694cb5ea116fb8a43d8 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Sun, 2 Jan 2022 13:35:47 -0500 Subject: [PATCH 35/49] update build/test instructions for asan --- CONTRIBUTING.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 75c70adb3f..c0cab67b3f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -21,5 +21,6 @@ export CFLAGS=-fsanitize=address export CXXFLAGS=-fsanitize=address export LDFLAGS=-fsanitize=address ./configure --disable-symbol-hiding --enable-expose-statics --enable-maintainer-mode --enable-debug +make ASAN_OPTIONS=detect_leaks=1 test/arestest --gtest_filter='-*.Live*' ``` From 86daca35a4bdf4f9d40bd2cfc39a291fa609df4d Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Sun, 2 Jan 2022 13:42:16 -0500 Subject: [PATCH 36/49] update build/test instructions for asan --- CONTRIBUTING.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c0cab67b3f..312082de08 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -20,6 +20,7 @@ export BUILD_TYPE=asan export CFLAGS=-fsanitize=address export CXXFLAGS=-fsanitize=address export LDFLAGS=-fsanitize=address +autoreconf -fi ./configure --disable-symbol-hiding --enable-expose-statics --enable-maintainer-mode --enable-debug make ASAN_OPTIONS=detect_leaks=1 test/arestest --gtest_filter='-*.Live*' From 9f7b8b9bd417a74a14ee78d59b8523420892efad Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Sun, 2 Jan 2022 13:49:16 -0500 Subject: [PATCH 37/49] update build/test instructions for asan --- CONTRIBUTING.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 312082de08..86a6903bbe 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -14,7 +14,7 @@ To improve the chances of the c-ares maintainers responding to your request: - Also send an email to the mailing list at `c-ares@lists.haxx.se` describing your change. - To follow any associated discussion, please subscribe to the [mailing list](http://lists.haxx.se/listinfo/c-ares). -To build locally with asan, ubsan, and lsan: +To build locally with asan and lsan: ``` export BUILD_TYPE=asan export CFLAGS=-fsanitize=address @@ -25,3 +25,10 @@ autoreconf -fi make ASAN_OPTIONS=detect_leaks=1 test/arestest --gtest_filter='-*.Live*' ``` + +To build locally with ubsan, same instructions as asan but switch out CFLAGS, CXXFLAGS, and LDFLAGS: +``` +export CFLAGS=-fsanitize=undefined -fno-sanitize-recover +export CXXFLAGS=-fsanitize=undefined -fno-sanitize-recover +export LDFLAGS=CFLAGS=-fsanitize=undefined +``` From 487cb0c2ce065c51aad58ffc89d5ac9e94c009ab Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Sun, 2 Jan 2022 13:57:10 -0500 Subject: [PATCH 38/49] attempt to fix leak --- src/lib/ares_parse_srv_reply.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib/ares_parse_srv_reply.c b/src/lib/ares_parse_srv_reply.c index bb819e7f62..db10ae6910 100644 --- a/src/lib/ares_parse_srv_reply.c +++ b/src/lib/ares_parse_srv_reply.c @@ -59,9 +59,9 @@ ares_parse_srv_reply (const unsigned char *abuf, int alen, /* clean up on error */ if (status != ARES_SUCCESS) { - if (csrv_out) + if (*csrv_out) { - cares_free_container(csrv_out); + cares_free_container(*csrv_out); } return status; } @@ -101,9 +101,9 @@ ares_parse_srv_reply (const unsigned char *abuf, int alen, srv_curr->port = cares_srv_reply_get_port(csrv_curr); } - if (csrv_out) + if (*csrv_out) { - cares_free_container(csrv_out); + cares_free_container(*csrv_out); } /* clean up on error */ From 84d87cbaa0d0257ab5d0cbdef4210da0be1d28d7 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Sun, 2 Jan 2022 14:11:42 -0500 Subject: [PATCH 39/49] attempt to fix leak --- src/lib/ares_parse_srv_reply.c | 8 ++++---- src/lib/cares_free_container.c | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/lib/ares_parse_srv_reply.c b/src/lib/ares_parse_srv_reply.c index db10ae6910..bb819e7f62 100644 --- a/src/lib/ares_parse_srv_reply.c +++ b/src/lib/ares_parse_srv_reply.c @@ -59,9 +59,9 @@ ares_parse_srv_reply (const unsigned char *abuf, int alen, /* clean up on error */ if (status != ARES_SUCCESS) { - if (*csrv_out) + if (csrv_out) { - cares_free_container(*csrv_out); + cares_free_container(csrv_out); } return status; } @@ -101,9 +101,9 @@ ares_parse_srv_reply (const unsigned char *abuf, int alen, srv_curr->port = cares_srv_reply_get_port(csrv_curr); } - if (*csrv_out) + if (csrv_out) { - cares_free_container(*csrv_out); + cares_free_container(csrv_out); } /* clean up on error */ diff --git a/src/lib/cares_free_container.c b/src/lib/cares_free_container.c index 3a3750f11e..77f49d7717 100644 --- a/src/lib/cares_free_container.c +++ b/src/lib/cares_free_container.c @@ -25,7 +25,7 @@ void cares_free_container(void *containerptr) } struct cares_container *ptr; - unsigned int count; + unsigned int count = 0; ptr = (void *)((char *)containerptr - offsetof(struct cares_container, container)); @@ -39,7 +39,7 @@ void cares_free_container(void *containerptr) break; default: - return; + break; } for (unsigned int i = 0; i < count; ++i) @@ -59,7 +59,7 @@ void cares_free_container(void *containerptr) } default: - return; + break; } } From f131cf2c69990d41f7eb8f9617924f04e03fc61a Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Sun, 2 Jan 2022 16:32:50 -0500 Subject: [PATCH 40/49] add missing break statement --- src/lib/cares_free_container.c | 2 +- test/ares-test-parse-srv.cc | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/lib/cares_free_container.c b/src/lib/cares_free_container.c index 77f49d7717..312f2b6b5a 100644 --- a/src/lib/cares_free_container.c +++ b/src/lib/cares_free_container.c @@ -55,8 +55,8 @@ void cares_free_container(void *containerptr) if (i == count - 1) { ares_free(ptr->container.srv_container.replies); - break; } + break; default: break; diff --git a/test/ares-test-parse-srv.cc b/test/ares-test-parse-srv.cc index 0036b2f088..aafa5423e9 100644 --- a/test/ares-test-parse-srv.cc +++ b/test/ares-test-parse-srv.cc @@ -3,7 +3,6 @@ #include #include -#include "stdio.h" namespace ares { namespace test { @@ -18,7 +17,6 @@ TEST_F(LibraryTest, ParseSrvReplyOK) { struct ares_srv_reply* srv = nullptr; EXPECT_EQ(ARES_SUCCESS, ares_parse_srv_reply(data.data(), data.size(), &srv)); - printf("After ares_parse_srv_reply\n"); ASSERT_NE(nullptr, srv); EXPECT_EQ("srv.example.com", std::string(srv->host)); From 8bca0fa81a629ef2a0c9f778896ddc8e7731be20 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Sun, 2 Jan 2022 16:50:43 -0500 Subject: [PATCH 41/49] free srv_host on error --- src/lib/cares_parse_srv_reply.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/lib/cares_parse_srv_reply.c b/src/lib/cares_parse_srv_reply.c index 1339a358fa..ec73a8b708 100644 --- a/src/lib/cares_parse_srv_reply.c +++ b/src/lib/cares_parse_srv_reply.c @@ -184,6 +184,10 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, } ares_free(srv_replies); } + if (srv_host) + { + ares_free(srv_host); + } return status; } From 979f715cddc40fd3bff7764c75c7357b1e15e02b Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Sun, 2 Jan 2022 18:10:30 -0500 Subject: [PATCH 42/49] add debugging --- src/lib/ares_parse_srv_reply.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib/ares_parse_srv_reply.c b/src/lib/ares_parse_srv_reply.c index bb819e7f62..d4b8f04746 100644 --- a/src/lib/ares_parse_srv_reply.c +++ b/src/lib/ares_parse_srv_reply.c @@ -34,6 +34,7 @@ #include "ares_dns.h" #include "ares_data.h" #include "ares_private.h" +#include "stdio.h" int ares_parse_srv_reply (const unsigned char *abuf, int alen, @@ -55,6 +56,7 @@ ares_parse_srv_reply (const unsigned char *abuf, int alen, *srv_out = NULL; status = cares_parse_srv_reply(abuf, alen, &csrv_out); + printf("status after cares_parse_srv_reply: %d\n", status); /* clean up on error */ if (status != ARES_SUCCESS) From 183a9997f02a344c9c58e6336b33425dfb24a5d1 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Mon, 3 Jan 2022 01:45:39 -0500 Subject: [PATCH 43/49] fix leak if no srv rr type --- aminclude_static.am | 2 +- src/lib/ares_data.c | 10 +++++++-- src/lib/ares_parse_srv_reply.c | 2 ++ src/lib/cares_free_container.c | 2 ++ src/lib/cares_parse_srv_reply.c | 36 +++++++++++++++++++++++++++++---- test/aminclude_static.am | 2 +- 6 files changed, 46 insertions(+), 8 deletions(-) diff --git a/aminclude_static.am b/aminclude_static.am index fff4199273..6ee9c15b43 100644 --- a/aminclude_static.am +++ b/aminclude_static.am @@ -1,6 +1,6 @@ # aminclude_static.am generated automatically by Autoconf -# from AX_AM_MACROS_STATIC on Sat Nov 6 23:31:46 EDT 2021 +# from AX_AM_MACROS_STATIC on Sun Jan 2 13:41:56 EST 2022 # Code coverage diff --git a/src/lib/ares_data.c b/src/lib/ares_data.c index cf46c8dfcb..3ae082cfa7 100644 --- a/src/lib/ares_data.c +++ b/src/lib/ares_data.c @@ -22,7 +22,7 @@ #include "ares.h" #include "ares_data.h" #include "ares_private.h" - +#include "stdio.h" /* ** ares_free_data() - c-ares external API function. @@ -80,6 +80,7 @@ void ares_free_data(void *dataptr) next_data = ptr->data.srv_reply.next; if (ptr->data.srv_reply.host) { + printf("free host srv\n"); ares_free(ptr->data.srv_reply.host); } break; @@ -88,6 +89,7 @@ void ares_free_data(void *dataptr) if (ptr->data.srv_reply.host) { + printf("free host csrv\n"); ares_free(ptr->data.csrv_reply.host); } break; @@ -214,8 +216,12 @@ void *ares_malloc_data(ares_datatype type) break; case CARES_DATATYPE_SRV_REPLY: + ptr->data.csrv_reply.host = NULL; + ptr->data.csrv_reply.priority = 0; + ptr->data.csrv_reply.weight = 0; + ptr->data.csrv_reply.port = 0; ptr->data.csrv_reply.ttl = 0; - /* FALLTHROUGH */ + break; case ARES_DATATYPE_SRV_REPLY: ptr->data.srv_reply.next = NULL; diff --git a/src/lib/ares_parse_srv_reply.c b/src/lib/ares_parse_srv_reply.c index d4b8f04746..bd26939e8b 100644 --- a/src/lib/ares_parse_srv_reply.c +++ b/src/lib/ares_parse_srv_reply.c @@ -105,12 +105,14 @@ ares_parse_srv_reply (const unsigned char *abuf, int alen, if (csrv_out) { + printf("free container in ares_parse\n"); cares_free_container(csrv_out); } /* clean up on error */ if (status != ARES_SUCCESS) { + printf("free srv_head in ares_parse\n"); if (srv_head) ares_free_data (srv_head); return status; diff --git a/src/lib/cares_free_container.c b/src/lib/cares_free_container.c index 312f2b6b5a..feac5ef0bf 100644 --- a/src/lib/cares_free_container.c +++ b/src/lib/cares_free_container.c @@ -49,11 +49,13 @@ void cares_free_container(void *containerptr) case CARES_CONTAINER_SRV_REPLY_CONTAINER: if (ptr->container.srv_container.replies[i]) { + printf("before ares_free_data in free container; count: %u\n", count); ares_free_data(ptr->container.srv_container.replies[i]); } if (i == count - 1) { + printf("before free replies in free container\n"); ares_free(ptr->container.srv_container.replies); } break; diff --git a/src/lib/cares_parse_srv_reply.c b/src/lib/cares_parse_srv_reply.c index ec73a8b708..8ef267d8b0 100644 --- a/src/lib/cares_parse_srv_reply.c +++ b/src/lib/cares_parse_srv_reply.c @@ -56,25 +56,42 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, /* Give up if abuf doesn't have room for a header. */ if (alen < HFIXEDSZ) + { + printf("alen return\n"); return ARES_EBADRESP; + } /* Fetch the question and answer count from the header. */ qdcount = DNS_HEADER_QDCOUNT (abuf); ancount = DNS_HEADER_ANCOUNT (abuf); if (qdcount != 1) + { + printf("qdcount return\n"); return ARES_EBADRESP; + } if (ancount == 0) + { + printf("ancount return\n"); return ARES_ENODATA; + } /* Expand the name from the question, and skip past the question. */ aptr = abuf + HFIXEDSZ; status = ares_expand_name (aptr, abuf, alen, &hostname, &len); if (status != ARES_SUCCESS) + { + if (hostname) + { + ares_free(hostname); + } + printf("expand_name return\n"); return status; + } if (aptr + len + QFIXEDSZ > abuf + alen) { ares_free (hostname); + printf("aptr + len + QFIXED return\n"); return ARES_EBADRESP; } aptr += len + QFIXEDSZ; @@ -83,6 +100,7 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, if (srv_replies == NULL) { ares_free (hostname); + printf("srv_replies null return\n"); return ARES_ENOMEM; } @@ -91,6 +109,8 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, srv_replies[i] = NULL; } + printf("ancount: %u\n", ancount); + /* Examine each answer resource record (RR) in turn. */ for (i = 0; i < ancount; i++) { @@ -120,6 +140,7 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, /* Check if we are really looking at a SRV record */ if (rr_class == C_IN && rr_type == T_SRV) { + printf("rr is srv\n"); /* parse the SRV record itself */ if (rr_len < 6) { @@ -147,6 +168,7 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, status = ares_expand_name (vptr, abuf, alen, &srv_host, &len); if (status != ARES_SUCCESS) break; + printf("expand name succeeded; srv_host: %p\n", (void *)srv_host); cares_srv_reply_set_host(srv_curr, srv_host); srv_replies[count] = srv_curr; count++; @@ -170,9 +192,17 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, if (rr_name) ares_free (rr_name); + *srv_out = cares_malloc_container(CARES_CONTAINER_SRV_REPLY_CONTAINER); + if (*srv_out == NULL) + status = ARES_ENOMEM; + + if (count == 0 && status == ARES_SUCCESS) + status = ARES_ENODATA; + /* clean up on error */ if (status != ARES_SUCCESS) { + printf("status not success in cares_parse_srv\n"); if (srv_replies) { for(i = 0; i < count; ++i) { @@ -188,15 +218,13 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, { ares_free(srv_host); } + printf("should have been freed return\n"); return status; } - *srv_out = cares_malloc_container(CARES_CONTAINER_SRV_REPLY_CONTAINER); - if (*srv_out == NULL) - return ARES_ENOMEM; - /* everything looks fine, return the data */ (*srv_out)->replies = srv_replies; cares_srv_reply_container_set_count(*srv_out, count); + printf("should have been success return\n"); return ARES_SUCCESS; } diff --git a/test/aminclude_static.am b/test/aminclude_static.am index fff4199273..0a943e225b 100644 --- a/test/aminclude_static.am +++ b/test/aminclude_static.am @@ -1,6 +1,6 @@ # aminclude_static.am generated automatically by Autoconf -# from AX_AM_MACROS_STATIC on Sat Nov 6 23:31:46 EDT 2021 +# from AX_AM_MACROS_STATIC on Sun Jan 2 13:43:16 EST 2022 # Code coverage From e247b6e534a2455271f4d382f0efd17393f768b6 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Mon, 3 Jan 2022 01:46:44 -0500 Subject: [PATCH 44/49] add fuzzing loop instrution --- CONTRIBUTING.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 86a6903bbe..a6cccb176c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -24,6 +24,7 @@ autoreconf -fi ./configure --disable-symbol-hiding --enable-expose-statics --enable-maintainer-mode --enable-debug make ASAN_OPTIONS=detect_leaks=1 test/arestest --gtest_filter='-*.Live*' +for file in $(ls test/fuzzinput); do echo "$file"; test/aresfuzz "test/fuzzinput/$file"; done ``` To build locally with ubsan, same instructions as asan but switch out CFLAGS, CXXFLAGS, and LDFLAGS: From e1bb47d53d865b7890e0ced52d461ea5ea237d42 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Mon, 3 Jan 2022 01:52:17 -0500 Subject: [PATCH 45/49] fix typo for cares_free_container.h --- src/lib/Makefile.inc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/Makefile.inc b/src/lib/Makefile.inc index 86b1521a99..eddeaa63e7 100644 --- a/src/lib/Makefile.inc +++ b/src/lib/Makefile.inc @@ -67,7 +67,7 @@ CSOURCES = ares__addrinfo2hostent.c \ bitncmp.c \ inet_net_pton.c \ inet_ntop.c \ - cares_container.c \ + cares_container.c \ cares_free_container.c \ windows_port.c @@ -89,7 +89,7 @@ HHEADERS = ares_android.h \ ares_writev.h \ bitncmp.h \ ares_setup.h \ - ares_free_container.h \ + cares_free_container.h \ setup_once.h From 73248f72daba1ec6880e6627740c28506515c21b Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Mon, 3 Jan 2022 01:56:18 -0500 Subject: [PATCH 46/49] remove debugging print statements --- src/lib/ares_data.c | 3 --- src/lib/ares_parse_srv_reply.c | 4 ---- src/lib/cares_free_container.c | 2 -- src/lib/cares_parse_srv_reply.c | 13 ------------- 4 files changed, 22 deletions(-) diff --git a/src/lib/ares_data.c b/src/lib/ares_data.c index 3ae082cfa7..a3531f1897 100644 --- a/src/lib/ares_data.c +++ b/src/lib/ares_data.c @@ -22,7 +22,6 @@ #include "ares.h" #include "ares_data.h" #include "ares_private.h" -#include "stdio.h" /* ** ares_free_data() - c-ares external API function. @@ -80,7 +79,6 @@ void ares_free_data(void *dataptr) next_data = ptr->data.srv_reply.next; if (ptr->data.srv_reply.host) { - printf("free host srv\n"); ares_free(ptr->data.srv_reply.host); } break; @@ -89,7 +87,6 @@ void ares_free_data(void *dataptr) if (ptr->data.srv_reply.host) { - printf("free host csrv\n"); ares_free(ptr->data.csrv_reply.host); } break; diff --git a/src/lib/ares_parse_srv_reply.c b/src/lib/ares_parse_srv_reply.c index bd26939e8b..bb819e7f62 100644 --- a/src/lib/ares_parse_srv_reply.c +++ b/src/lib/ares_parse_srv_reply.c @@ -34,7 +34,6 @@ #include "ares_dns.h" #include "ares_data.h" #include "ares_private.h" -#include "stdio.h" int ares_parse_srv_reply (const unsigned char *abuf, int alen, @@ -56,7 +55,6 @@ ares_parse_srv_reply (const unsigned char *abuf, int alen, *srv_out = NULL; status = cares_parse_srv_reply(abuf, alen, &csrv_out); - printf("status after cares_parse_srv_reply: %d\n", status); /* clean up on error */ if (status != ARES_SUCCESS) @@ -105,14 +103,12 @@ ares_parse_srv_reply (const unsigned char *abuf, int alen, if (csrv_out) { - printf("free container in ares_parse\n"); cares_free_container(csrv_out); } /* clean up on error */ if (status != ARES_SUCCESS) { - printf("free srv_head in ares_parse\n"); if (srv_head) ares_free_data (srv_head); return status; diff --git a/src/lib/cares_free_container.c b/src/lib/cares_free_container.c index feac5ef0bf..312f2b6b5a 100644 --- a/src/lib/cares_free_container.c +++ b/src/lib/cares_free_container.c @@ -49,13 +49,11 @@ void cares_free_container(void *containerptr) case CARES_CONTAINER_SRV_REPLY_CONTAINER: if (ptr->container.srv_container.replies[i]) { - printf("before ares_free_data in free container; count: %u\n", count); ares_free_data(ptr->container.srv_container.replies[i]); } if (i == count - 1) { - printf("before free replies in free container\n"); ares_free(ptr->container.srv_container.replies); } break; diff --git a/src/lib/cares_parse_srv_reply.c b/src/lib/cares_parse_srv_reply.c index 8ef267d8b0..5948f16b97 100644 --- a/src/lib/cares_parse_srv_reply.c +++ b/src/lib/cares_parse_srv_reply.c @@ -57,7 +57,6 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, /* Give up if abuf doesn't have room for a header. */ if (alen < HFIXEDSZ) { - printf("alen return\n"); return ARES_EBADRESP; } @@ -66,12 +65,10 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, ancount = DNS_HEADER_ANCOUNT (abuf); if (qdcount != 1) { - printf("qdcount return\n"); return ARES_EBADRESP; } if (ancount == 0) { - printf("ancount return\n"); return ARES_ENODATA; } @@ -84,14 +81,12 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, { ares_free(hostname); } - printf("expand_name return\n"); return status; } if (aptr + len + QFIXEDSZ > abuf + alen) { ares_free (hostname); - printf("aptr + len + QFIXED return\n"); return ARES_EBADRESP; } aptr += len + QFIXEDSZ; @@ -100,7 +95,6 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, if (srv_replies == NULL) { ares_free (hostname); - printf("srv_replies null return\n"); return ARES_ENOMEM; } @@ -109,8 +103,6 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, srv_replies[i] = NULL; } - printf("ancount: %u\n", ancount); - /* Examine each answer resource record (RR) in turn. */ for (i = 0; i < ancount; i++) { @@ -140,7 +132,6 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, /* Check if we are really looking at a SRV record */ if (rr_class == C_IN && rr_type == T_SRV) { - printf("rr is srv\n"); /* parse the SRV record itself */ if (rr_len < 6) { @@ -168,7 +159,6 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, status = ares_expand_name (vptr, abuf, alen, &srv_host, &len); if (status != ARES_SUCCESS) break; - printf("expand name succeeded; srv_host: %p\n", (void *)srv_host); cares_srv_reply_set_host(srv_curr, srv_host); srv_replies[count] = srv_curr; count++; @@ -202,7 +192,6 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, /* clean up on error */ if (status != ARES_SUCCESS) { - printf("status not success in cares_parse_srv\n"); if (srv_replies) { for(i = 0; i < count; ++i) { @@ -218,13 +207,11 @@ cares_parse_srv_reply (const unsigned char *abuf, int alen, { ares_free(srv_host); } - printf("should have been freed return\n"); return status; } /* everything looks fine, return the data */ (*srv_out)->replies = srv_replies; cares_srv_reply_container_set_count(*srv_out, count); - printf("should have been success return\n"); return ARES_SUCCESS; } From 337db1d9d75371722bdeaae41b337356c8444659 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Mon, 3 Jan 2022 20:14:38 -0500 Subject: [PATCH 47/49] Update instructions for lsan --- CONTRIBUTING.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a6cccb176c..5529605e9b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -14,7 +14,7 @@ To improve the chances of the c-ares maintainers responding to your request: - Also send an email to the mailing list at `c-ares@lists.haxx.se` describing your change. - To follow any associated discussion, please subscribe to the [mailing list](http://lists.haxx.se/listinfo/c-ares). -To build locally with asan and lsan: +To build locally with asan: ``` export BUILD_TYPE=asan export CFLAGS=-fsanitize=address @@ -27,9 +27,18 @@ ASAN_OPTIONS=detect_leaks=1 test/arestest --gtest_filter='-*.Live*' for file in $(ls test/fuzzinput); do echo "$file"; test/aresfuzz "test/fuzzinput/$file"; done ``` -To build locally with ubsan, same instructions as asan but switch out CFLAGS, CXXFLAGS, and LDFLAGS: +To build locally with ubsan, same instructions as asan but switch out BUILD_TYPE, CFLAGS, CXXFLAGS, and LDFLAGS: ``` +export BUILD_TYPE=ubsan export CFLAGS=-fsanitize=undefined -fno-sanitize-recover export CXXFLAGS=-fsanitize=undefined -fno-sanitize-recover export LDFLAGS=CFLAGS=-fsanitize=undefined ``` + +To build locally with lsan, same instructions as asan but switch out BUILD_TYPE, CFLAGS, CXXFLAGS, and LDFLAGS: +``` +export BUILD_TYPE=lsan +export CFLAGS=-fsanitize=leak +export CXXFLAGS=-fsanitize=leak +export LDFLAGS=CFLAGS=-fsanitize=leak +``` From be37e6a4f6d955a2feee0abc42b4c2c58aaf7d4c Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Mon, 3 Jan 2022 20:23:49 -0500 Subject: [PATCH 48/49] Update instructions for lsan --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5529605e9b..18cf2d02ac 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -40,5 +40,5 @@ To build locally with lsan, same instructions as asan but switch out BUILD_TYPE, export BUILD_TYPE=lsan export CFLAGS=-fsanitize=leak export CXXFLAGS=-fsanitize=leak -export LDFLAGS=CFLAGS=-fsanitize=leak +export LDFLAGS=-fsanitize=leak ``` From e82ff03c32a1cb08308842e15dca13ee81333ef2 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Mon, 3 Jan 2022 21:05:49 -0500 Subject: [PATCH 49/49] change srv to csrv --- src/lib/ares_data.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/ares_data.c b/src/lib/ares_data.c index a3531f1897..b41e215442 100644 --- a/src/lib/ares_data.c +++ b/src/lib/ares_data.c @@ -85,7 +85,7 @@ void ares_free_data(void *dataptr) case CARES_DATATYPE_SRV_REPLY: - if (ptr->data.srv_reply.host) + if (ptr->data.csrv_reply.host) { ares_free(ptr->data.csrv_reply.host); }