ares-test-parse-a.cc
Go to the documentation of this file.
1 #include "ares-test.h"
2 #include "dns-proto.h"
3 
4 #include <sstream>
5 #include <vector>
6 
7 namespace ares {
8 namespace test {
9 
10 TEST_F(LibraryTest, ParseAReplyOK) {
11  DNSPacket pkt;
12  pkt.set_qid(0x1234).set_response().set_aa()
13  .add_question(new DNSQuestion("example.com", T_A))
14  .add_answer(new DNSARR("example.com", 0x01020304, {2,3,4,5}))
15  .add_answer(new DNSAaaaRR("example.com", 0x01020304, {0,0,0,0,0,0,0,0,0,0,0,0,2,3,4,5}));
16  std::vector<byte> data = {
17  0x12, 0x34, // qid
18  0x84, // response + query + AA + not-TC + not-RD
19  0x00, // not-RA + not-Z + not-AD + not-CD + rc=NoError
20  0x00, 0x01, // num questions
21  0x00, 0x02, // num answer RRs
22  0x00, 0x00, // num authority RRs
23  0x00, 0x00, // num additional RRs
24  // Question
25  0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e',
26  0x03, 'c', 'o', 'm',
27  0x00,
28  0x00, 0x01, // type A
29  0x00, 0x01, // class IN
30  // Answer 1
31  0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e',
32  0x03, 'c', 'o', 'm',
33  0x00,
34  0x00, 0x01, // RR type
35  0x00, 0x01, // class IN
36  0x01, 0x02, 0x03, 0x04, // TTL
37  0x00, 0x04, // rdata length
38  0x02, 0x03, 0x04, 0x05,
39  // Answer 2
40  0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e',
41  0x03, 'c', 'o', 'm',
42  0x00,
43  0x00, 0x1c, // RR type
44  0x00, 0x01, // class IN
45  0x01, 0x02, 0x03, 0x04, // TTL
46  0x00, 0x10, // rdata length
47  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x04, 0x05,
48  };
49  EXPECT_EQ(data, pkt.data());
50  struct hostent *host = nullptr;
51  struct ares_addrttl info[5];
52  int count = 5;
54  &host, info, &count));
55  EXPECT_EQ(1, count);
56  EXPECT_EQ(0x01020304, info[0].ttl);
57  unsigned long expected_addr = htonl(0x02030405);
58  EXPECT_EQ(expected_addr, info[0].ipaddr.s_addr);
59  EXPECT_EQ("2.3.4.5", AddressToString(&(info[0].ipaddr), 4));
60  ASSERT_NE(nullptr, host);
61  std::stringstream ss;
62  ss << HostEnt(host);
63  EXPECT_EQ("{'example.com' aliases=[] addrs=[2.3.4.5]}", ss.str());
64  ares_free_hostent(host);
65 
66  // Repeat without providing a hostent
68  nullptr, info, &count));
69  EXPECT_EQ(1, count);
70  EXPECT_EQ(0x01020304, info[0].ttl);
71  EXPECT_EQ(expected_addr, info[0].ipaddr.s_addr);
72  EXPECT_EQ("2.3.4.5", AddressToString(&(info[0].ipaddr), 4));
73 }
74 
75 TEST_F(LibraryTest, ParseMalformedAReply) {
76  std::vector<byte> data = {
77  0x12, 0x34, // [0:2) qid
78  0x84, // [2] response + query + AA + not-TC + not-RD
79  0x00, // [3] not-RA + not-Z + not-AD + not-CD + rc=NoError
80  0x00, 0x01, // [4:6) num questions
81  0x00, 0x02, // [6:8) num answer RRs
82  0x00, 0x00, // [8:10) num authority RRs
83  0x00, 0x00, // [10:12) num additional RRs
84  // Question
85  0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', // [12:20)
86  0x03, 'c', 'o', 'm', // [20,24)
87  0x00, // [24]
88  0x00, 0x01, // [25:26) type A
89  0x00, 0x01, // [27:29) class IN
90  // Answer 1
91  0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', // [29:37)
92  0x03, 'c', 'o', 'm', // [37:41)
93  0x00, // [41]
94  0x00, 0x01, // [42:44) RR type
95  0x00, 0x01, // [44:46) class IN
96  0x01, 0x02, 0x03, 0x04, // [46:50) TTL
97  0x00, 0x04, // [50:52) rdata length
98  0x02, 0x03, 0x04, 0x05, // [52,56)
99  };
100  struct hostent *host = nullptr;
101  struct ares_addrttl info[2];
102  int count = 2;
103 
104  // Invalid RR-len.
105  std::vector<byte> invalid_rrlen(data);
106  invalid_rrlen[51] = 180;
107  EXPECT_EQ(ARES_EBADRESP, ares_parse_a_reply(invalid_rrlen.data(), invalid_rrlen.size(),
108  &host, info, &count));
109 
110  // Truncate mid-question.
112  &host, info, &count));
113 
114  // Truncate mid-answer.
116  &host, info, &count));
117 }
118 
119 TEST_F(LibraryTest, ParseAReplyNoData) {
120  DNSPacket pkt;
121  pkt.set_qid(0x1234).set_response().set_aa()
122  .add_question(new DNSQuestion("example.com", T_A));
123  std::vector<byte> data = pkt.data();
124  struct hostent *host = nullptr;
125  struct ares_addrttl info[2];
126  int count = 2;
128  &host, info, &count));
129  EXPECT_EQ(0, count);
130  EXPECT_EQ(nullptr, host);
131 
132  // Again but with a CNAME.
133  pkt.add_answer(new DNSCnameRR("example.com", 200, "c.example.com"));
134  data = pkt.data();
135  // Expect success as per https://github.com/c-ares/c-ares/commit/2c63440127feed70ccefb148b8f938a2df6c15f8
137  &host, info, &count));
138  EXPECT_EQ(0, count);
139  EXPECT_NE(nullptr, host);
140  std::stringstream ss;
141  ss << HostEnt(host);
142  EXPECT_EQ("{'c.example.com' aliases=[example.com] addrs=[]}", ss.str());
143  ares_free_hostent(host);
144 }
145 
146 TEST_F(LibraryTest, ParseAReplyVariantA) {
147  DNSPacket pkt;
148  pkt.set_qid(6366).set_rd().set_ra()
149  .add_question(new DNSQuestion("mit.edu", T_A))
150  .add_answer(new DNSARR("mit.edu", 52, {18,7,22,69}))
151  .add_auth(new DNSNsRR("mit.edu", 292, "W20NS.mit.edu"))
152  .add_auth(new DNSNsRR("mit.edu", 292, "BITSY.mit.edu"))
153  .add_auth(new DNSNsRR("mit.edu", 292, "STRAWB.mit.edu"))
154  .add_additional(new DNSARR("STRAWB.mit.edu", 292, {18,71,0,151}));
155  struct hostent *host = nullptr;
156  struct ares_addrttl info[2];
157  int count = 2;
158  std::vector<byte> data = pkt.data();
160  &host, info, &count));
161  EXPECT_EQ(1, count);
162  EXPECT_EQ("18.7.22.69", AddressToString(&(info[0].ipaddr), 4));
163  EXPECT_EQ(52, info[0].ttl);
164  ares_free_hostent(host);
165 }
166 
167 TEST_F(LibraryTest, ParseAReplyJustCname) {
168  DNSPacket pkt;
169  pkt.set_qid(6366).set_rd().set_ra()
170  .add_question(new DNSQuestion("mit.edu", T_A))
171  .add_answer(new DNSCnameRR("mit.edu", 52, "other.mit.edu"));
172  struct hostent *host = nullptr;
173  struct ares_addrttl info[2];
174  int count = 2;
175  std::vector<byte> data = pkt.data();
177  &host, info, &count));
178  EXPECT_EQ(0, count);
179  ASSERT_NE(nullptr, host);
180  std::stringstream ss;
181  ss << HostEnt(host);
182  EXPECT_EQ("{'other.mit.edu' aliases=[mit.edu] addrs=[]}", ss.str());
183  ares_free_hostent(host);
184 }
185 
186 TEST_F(LibraryTest, ParseAReplyVariantCname) {
187  DNSPacket pkt;
188  pkt.set_qid(6366).set_rd().set_ra()
189  .add_question(new DNSQuestion("query.example.com", T_A))
190  .add_answer(new DNSCnameRR("query.example.com", 200, "redirect.query.example.com"))
191  .add_answer(new DNSARR("redirect.query.example.com", 300, {129,97,123,22}))
192  .add_auth(new DNSNsRR("example.com", 218, "aa.ns1.example.com"))
193  .add_auth(new DNSNsRR("example.com", 218, "ns2.example.com"))
194  .add_auth(new DNSNsRR("example.com", 218, "ns3.example.com"))
195  .add_auth(new DNSNsRR("example.com", 218, "ns4.example.com"))
196  .add_additional(new DNSARR("aa.ns1.example.com", 218, {129,97,1,1}))
197  .add_additional(new DNSARR("ns2.example.com", 218, {129,97,1,2}))
198  .add_additional(new DNSARR("ns3.example.com", 218, {129,97,1,3}))
199  .add_additional(new DNSARR("ns4.example.com", 218, {129,97,1,4}));
200  struct hostent *host = nullptr;
201  struct ares_addrttl info[2];
202  int count = 2;
203  std::vector<byte> data = pkt.data();
205  &host, info, &count));
206  EXPECT_EQ(1, count);
207  EXPECT_EQ("129.97.123.22", AddressToString(&(info[0].ipaddr), 4));
208  // TTL is reduced to match CNAME's.
209  EXPECT_EQ(200, info[0].ttl);
210  ares_free_hostent(host);
211 
212  // Repeat parsing without places to put the results.
213  count = 0;
215  nullptr, info, &count));
216 }
217 
218 TEST_F(LibraryTest, ParseAReplyVariantCnameChain) {
219  DNSPacket pkt;
220  pkt.set_qid(6366).set_rd().set_ra()
221  .add_question(new DNSQuestion("c1.localhost", T_A))
222  .add_answer(new DNSCnameRR("c1.localhost", 604800, "c2.localhost"))
223  .add_answer(new DNSCnameRR("c2.localhost", 604800, "c3.localhost"))
224  .add_answer(new DNSCnameRR("c3.localhost", 604800, "c4.localhost"))
225  .add_answer(new DNSARR("c4.localhost", 604800, {8,8,8,8}))
226  .add_auth(new DNSNsRR("localhost", 604800, "localhost"))
227  .add_additional(new DNSARR("localhost", 604800, {127,0,0,1}))
228  .add_additional(new DNSAaaaRR("localhost", 604800,
229  {0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
230  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}));
231  struct hostent *host = nullptr;
232  struct ares_addrttl info[2];
233  int count = 2;
234  std::vector<byte> data = pkt.data();
236  &host, info, &count));
237  EXPECT_EQ(1, count);
238  EXPECT_EQ("8.8.8.8", AddressToString(&(info[0].ipaddr), 4));
239  EXPECT_EQ(604800, info[0].ttl);
240  ares_free_hostent(host);
241 }
242 
243 TEST_F(LibraryTest, DISABLED_ParseAReplyVariantCnameLast) {
244  DNSPacket pkt;
245  pkt.set_qid(6366).set_rd().set_ra()
246  .add_question(new DNSQuestion("query.example.com", T_A))
247  .add_answer(new DNSARR("redirect.query.example.com", 300, {129,97,123,221}))
248  .add_answer(new DNSARR("redirect.query.example.com", 300, {129,97,123,222}))
249  .add_answer(new DNSARR("redirect.query.example.com", 300, {129,97,123,223}))
250  .add_answer(new DNSARR("redirect.query.example.com", 300, {129,97,123,224}))
251  .add_answer(new DNSCnameRR("query.example.com", 60, "redirect.query.example.com"))
252  .add_additional(new DNSTxtRR("query.example.com", 60, {"text record"}));
253  struct hostent *host = nullptr;
254  struct ares_addrttl info[8];
255  int count = 8;
256  std::vector<byte> data = pkt.data();
258  &host, info, &count));
259  EXPECT_EQ(4, count);
260  EXPECT_EQ("129.97.123.221", AddressToString(&(info[0].ipaddr), 4));
261  EXPECT_EQ("129.97.123.222", AddressToString(&(info[1].ipaddr), 4));
262  EXPECT_EQ("129.97.123.223", AddressToString(&(info[2].ipaddr), 4));
263  EXPECT_EQ("129.97.123.224", AddressToString(&(info[3].ipaddr), 4));
264  EXPECT_EQ(300, info[0].ttl);
265  EXPECT_EQ(300, info[1].ttl);
266  EXPECT_EQ(300, info[2].ttl);
267  EXPECT_EQ(300, info[3].ttl);
268  ares_free_hostent(host);
269 }
270 
271 TEST_F(LibraryTest, ParseAReplyErrors) {
272  DNSPacket pkt;
273  pkt.set_qid(0x1234).set_response().set_aa()
274  .add_question(new DNSQuestion("example.com", T_A))
275  .add_answer(new DNSARR("example.com", 100, {0x02, 0x03, 0x04, 0x05}));
276  std::vector<byte> data;
277 
278  struct hostent *host = nullptr;
279  struct ares_addrttl info[2];
280  int count = 2;
281 
282  // No question.
283  pkt.questions_.clear();
284  data = pkt.data();
286  &host, info, &count));
287  EXPECT_EQ(nullptr, host);
288  pkt.add_question(new DNSQuestion("example.com", T_A));
289 
290  // Question != answer
291  pkt.questions_.clear();
292  pkt.add_question(new DNSQuestion("Axample.com", T_A));
293  data = pkt.data();
295  &host, info, &count));
296  EXPECT_EQ(nullptr, host);
297  pkt.questions_.clear();
298  pkt.add_question(new DNSQuestion("example.com", T_A));
299 
300 #ifdef DISABLED
301  // Not a response.
302  pkt.set_response(false);
303  data = pkt.data();
305  &host, info, &count));
306  EXPECT_EQ(nullptr, host);
307  pkt.set_response(true);
308 
309  // Bad return code.
310  pkt.set_rcode(FORMERR);
311  data = pkt.data();
313  &host, info, &count));
314  EXPECT_EQ(nullptr, host);
315  pkt.set_rcode(NOERROR);
316 #endif
317 
318  // Two questions
319  pkt.add_question(new DNSQuestion("example.com", T_A));
320  data = pkt.data();
322  &host, info, &count));
323  EXPECT_EQ(nullptr, host);
324  pkt.questions_.clear();
325  pkt.add_question(new DNSQuestion("example.com", T_A));
326 
327  // Wrong sort of answer.
328  pkt.answers_.clear();
329  pkt.add_answer(new DNSMxRR("example.com", 100, 100, "mx1.example.com"));
330  data = pkt.data();
332  &host, info, &count));
333  EXPECT_EQ(nullptr, host);
334  pkt.answers_.clear();
335  pkt.add_answer(new DNSARR("example.com", 100, {0x02, 0x03, 0x04, 0x05}));
336 
337  // No answer.
338  pkt.answers_.clear();
339  data = pkt.data();
341  &host, info, &count));
342  EXPECT_EQ(nullptr, host);
343  pkt.add_answer(new DNSARR("example.com", 100, {0x02, 0x03, 0x04, 0x05}));
344 
345  // Truncated packets.
346  data = pkt.data();
347  for (size_t len = 1; len < data.size(); len++) {
349  &host, info, &count));
350  EXPECT_EQ(nullptr, host);
352  nullptr, info, &count));
353  }
354 }
355 
356 TEST_F(LibraryTest, ParseAReplyAllocFail) {
357  DNSPacket pkt;
358  pkt.set_qid(0x1234).set_response().set_aa()
359  .add_question(new DNSQuestion("example.com", T_A))
360  .add_answer(new DNSCnameRR("example.com", 300, "c.example.com"))
361  .add_answer(new DNSARR("c.example.com", 500, {0x02, 0x03, 0x04, 0x05}));
362  std::vector<byte> data = pkt.data();
363 
364  struct hostent *host = nullptr;
365  struct ares_addrttl info[2];
366  int count = 2;
367 
368  for (int ii = 1; ii <= 8; ii++) {
369  ClearFails();
370  SetAllocFail(ii);
372  &host, info, &count)) << ii;
373  EXPECT_EQ(nullptr, host);
374  }
375 }
376 
377 } // namespace test
378 } // namespace ares
ASSERT_NE
#define ASSERT_NE(val1, val2)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:2060
ARES_ENOMEM
#define ARES_ENOMEM
Definition: ares.h:117
ares::DNSPacket
Definition: dns-proto.h:188
T_A
#define T_A
Definition: ares_nameser.h:310
ares::DNSPacket::set_aa
DNSPacket & set_aa(bool v=true)
Definition: dns-proto.h:213
test
Definition: spinlock_test.cc:36
ares::DNSPacket::set_qid
DNSPacket & set_qid(int qid)
Definition: dns-proto.h:211
NOERROR
#define NOERROR
Definition: ares_nameser.h:255
ares::DNSPacket::add_auth
DNSPacket & add_auth(DNSRR *q)
Definition: dns-proto.h:202
ares::DNSAaaaRR
Definition: dns-proto.h:85
ares::DNSPacket::answers_
std::vector< std::unique_ptr< DNSRR > > answers_
Definition: dns-proto.h:237
FORMERR
#define FORMERR
Definition: ares_nameser.h:258
ares_addrttl::ttl
int ttl
Definition: ares.h:522
EXPECT_EQ
#define EXPECT_EQ(a, b)
Definition: iomgr/time_averaged_stats_test.cc:27
ares::DNSPacket::add_question
DNSPacket & add_question(DNSQuestion *q)
Definition: dns-proto.h:194
ares::DNSPacket::set_rd
DNSPacket & set_rd(bool v=true)
Definition: dns-proto.h:215
ARES_EBADRESP
#define ARES_EBADRESP
Definition: ares.h:112
ares_free_hostent
CARES_EXTERN void ares_free_hostent(struct hostent *host)
Definition: ares_free_hostent.c:26
ares::AddressToString
std::string AddressToString(const void *vaddr, int len)
Definition: dns-proto.cc:157
ares::DNSCnameRR
Definition: dns-proto.h:100
EXPECT_NE
#define EXPECT_NE(val1, val2)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:2028
ARES_ENODATA
#define ARES_ENODATA
Definition: ares.h:101
ares::DNSPacket::set_ra
DNSPacket & set_ra(bool v=true)
Definition: dns-proto.h:216
ares::DNSPacket::add_additional
DNSPacket & add_additional(DNSRR *q)
Definition: dns-proto.h:206
ares::DNSPacket::data
std::vector< byte > data() const
Definition: dns-proto.cc:592
data
char data[kBufferLength]
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1006
ares-test.h
ARES_SUCCESS
#define ARES_SUCCESS
Definition: ares.h:98
ares::test::HostEnt
Definition: ares-test.h:237
ares::DNSPacket::add_answer
DNSPacket & add_answer(DNSRR *q)
Definition: dns-proto.h:198
ares::DNSPacket::questions_
std::vector< std::unique_ptr< DNSQuestion > > questions_
Definition: dns-proto.h:236
ares::DNSPacket::set_rcode
DNSPacket & set_rcode(int rcode)
Definition: dns-proto.h:220
ares_addrttl::ipaddr
struct in_addr ipaddr
Definition: ares.h:521
count
int * count
Definition: bloaty/third_party/googletest/googlemock/test/gmock_stress_test.cc:96
ares_parse_a_reply
CARES_EXTERN int ares_parse_a_reply(const unsigned char *abuf, int alen, struct hostent **host, struct ares_addrttl *addrttls, int *naddrttls)
Definition: ares_parse_a_reply.c:44
ares::DNSPacket::set_response
DNSPacket & set_response(bool v=true)
Definition: dns-proto.h:212
ares_addrttl
Definition: ares.h:520
ares::DNSARR
Definition: dns-proto.h:78
ares::DNSNsRR
Definition: dns-proto.h:105
ares::DNSMxRR
Definition: dns-proto.h:122
len
int len
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:46
ares::test::TEST_F
TEST_F(LibraryTest, OptionsChannelInit)
Definition: ares-test-init.cc:55
ares::DNSTxtRR
Definition: dns-proto.h:115
ares::DNSQuestion
Definition: dns-proto.h:45
ares
Definition: ares-test-ai.h:9
ares::test::LibraryTest
Definition: ares-test.h:60
dns-proto.h


grpc
Author(s):
autogenerated on Fri May 16 2025 02:57:42