1 /* MIT License
2 *
3 * Copyright (c) The c-ares project and its contributors
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 *
24 * SPDX-License-Identifier: MIT
25 */
26 #include "ares-test-ai.h"
27 #include "dns-proto.h"
28
29 #ifdef HAVE_NETINET_IN_H
30 #include <netinet/in.h>
31 #endif
32
33 #include <sstream>
34 #include <vector>
35
36 using testing::InvokeWithoutArgs;
37 using testing::DoAll;
38
39 namespace ares {
40 namespace test {
41
42 MATCHER_P(IncludesNumAddresses, n, "") {
43 (void)result_listener;
44 if(!arg)
45 return false;
46 int cnt = 0;
47 for (const ares_addrinfo_node* ai = arg->nodes; ai != NULL; ai = ai->ai_next)
48 cnt++;
49 return n == cnt;
50 }
51
52 MATCHER_P(IncludesV4Address, address, "") {
53 (void)result_listener;
54 if(!arg)
55 return false;
56 in_addr addressnum = {};
57 if (!ares_inet_pton(AF_INET, address, &addressnum))
58 return false; // wrong number format?
59 for (const ares_addrinfo_node* ai = arg->nodes; ai != NULL; ai = ai->ai_next) {
60 if (ai->ai_family != AF_INET)
61 continue;
62 if (ai->ai_addrlen != sizeof(struct sockaddr_in))
63 continue;
64 if (reinterpret_cast<sockaddr_in*>(ai->ai_addr)->sin_addr.s_addr ==
65 addressnum.s_addr)
66 return true; // found
67 }
68 return false;
69 }
70
71 MATCHER_P(IncludesV6Address, address, "") {
72 (void)result_listener;
73 if(!arg)
74 return false;
75 in6_addr addressnum = {};
76 if (!ares_inet_pton(AF_INET6, address, &addressnum)) {
77 return false; // wrong number format?
78 }
79 for (const ares_addrinfo_node* ai = arg->nodes; ai != NULL; ai = ai->ai_next) {
80 if (ai->ai_family != AF_INET6)
81 continue;
82 if (ai->ai_addrlen != sizeof(struct sockaddr_in6))
83 continue;
84 if (!memcmp(
85 reinterpret_cast<sockaddr_in6*>(ai->ai_addr)->sin6_addr.s6_addr,
86 addressnum.s6_addr, sizeof(addressnum.s6_addr)))
87 return true; // found
88 }
89 return false;
90 }
91
92 // UDP only so mock server doesn't get confused by concatenated requests
TEST_P(MockUDPChannelTestAI,GetAddrInfoParallelLookups)93 TEST_P(MockUDPChannelTestAI, GetAddrInfoParallelLookups) {
94 DNSPacket rsp1;
95 rsp1.set_response().set_aa()
96 .add_question(new DNSQuestion("www.google.com", T_A))
97 .add_answer(new DNSARR("www.google.com", 100, {2, 3, 4, 5}));
98 ON_CALL(server_, OnRequest("www.google.com", T_A))
99 .WillByDefault(SetReply(&server_, &rsp1));
100 DNSPacket rsp2;
101 rsp2.set_response().set_aa()
102 .add_question(new DNSQuestion("www.example.com", T_A))
103 .add_answer(new DNSARR("www.example.com", 100, {1, 2, 3, 4}));
104 ON_CALL(server_, OnRequest("www.example.com", T_A))
105 .WillByDefault(SetReply(&server_, &rsp2));
106
107 struct ares_addrinfo_hints hints = {0, 0, 0, 0};
108 hints.ai_family = AF_INET;
109 hints.ai_flags = ARES_AI_NOSORT;
110 AddrInfoResult result1;
111 ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result1);
112 AddrInfoResult result2;
113 ares_getaddrinfo(channel_, "www.example.com.", NULL, &hints, AddrInfoCallback, &result2);
114 AddrInfoResult result3;
115 ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result3);
116 Process();
117
118 EXPECT_TRUE(result1.done_);
119 EXPECT_EQ(result1.status_, ARES_SUCCESS);
120 EXPECT_THAT(result1.ai_, IncludesNumAddresses(1));
121 EXPECT_THAT(result1.ai_, IncludesV4Address("2.3.4.5"));
122
123 EXPECT_TRUE(result2.done_);
124 EXPECT_EQ(result2.status_, ARES_SUCCESS);
125 EXPECT_THAT(result2.ai_, IncludesNumAddresses(1));
126 EXPECT_THAT(result2.ai_, IncludesV4Address("1.2.3.4"));
127
128 EXPECT_TRUE(result3.done_);
129 EXPECT_EQ(result3.status_, ARES_SUCCESS);
130 EXPECT_THAT(result3.ai_, IncludesNumAddresses(1));
131 EXPECT_THAT(result3.ai_, IncludesV4Address("2.3.4.5"));
132 }
133
134 // UDP to TCP specific test
TEST_P(MockUDPChannelTestAI,TruncationRetry)135 TEST_P(MockUDPChannelTestAI, TruncationRetry) {
136 DNSPacket rsptruncated;
137 rsptruncated.set_response().set_aa().set_tc()
138 .add_question(new DNSQuestion("www.google.com", T_A));
139 DNSPacket rspok;
140 rspok.set_response()
141 .add_question(new DNSQuestion("www.google.com", T_A))
142 .add_answer(new DNSARR("www.google.com", 100, {1, 2, 3, 4}));
143 EXPECT_CALL(server_, OnRequest("www.google.com", T_A))
144 .WillOnce(SetReply(&server_, &rsptruncated))
145 .WillOnce(SetReply(&server_, &rspok));
146
147 AddrInfoResult result;
148 struct ares_addrinfo_hints hints = {0, 0, 0, 0};
149 hints.ai_family = AF_INET;
150 hints.ai_flags = ARES_AI_NOSORT;
151 ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result);
152 Process();
153 EXPECT_TRUE(result.done_);
154 EXPECT_EQ(result.status_, ARES_SUCCESS);
155 EXPECT_THAT(result.ai_, IncludesNumAddresses(1));
156 EXPECT_THAT(result.ai_, IncludesV4Address("1.2.3.4"));
157 }
158
TEST_P(MockTCPChannelTestAI,MalformedResponse)159 TEST_P(MockTCPChannelTestAI, MalformedResponse) {
160 std::vector<byte> one = {0x01};
161 ON_CALL(server_, OnRequest("www.google.com", T_A))
162 .WillByDefault(SetReplyData(&server_, one));
163
164 AddrInfoResult result;
165 struct ares_addrinfo_hints hints = {0, 0, 0, 0};
166 hints.ai_family = AF_INET;
167 hints.ai_flags = ARES_AI_NOSORT;
168 ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result);
169 Process();
170 EXPECT_TRUE(result.done_);
171 EXPECT_EQ(ARES_EBADRESP, result.status_);
172 }
173
TEST_P(MockTCPChannelTestAI,FormErrResponse)174 TEST_P(MockTCPChannelTestAI, FormErrResponse) {
175 DNSPacket rsp;
176 rsp.set_response().set_aa()
177 .add_question(new DNSQuestion("www.google.com", T_A));
178 rsp.set_rcode(FORMERR);
179 EXPECT_CALL(server_, OnRequest("www.google.com", T_A))
180 .WillOnce(SetReply(&server_, &rsp));
181
182 AddrInfoResult result;
183 struct ares_addrinfo_hints hints = {0, 0, 0, 0};
184 hints.ai_family = AF_INET;
185 hints.ai_flags = ARES_AI_NOSORT;
186 ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result);
187 Process();
188 EXPECT_TRUE(result.done_);
189 EXPECT_EQ(ARES_EFORMERR, result.status_);
190 }
191
TEST_P(MockTCPChannelTestAI,ServFailResponse)192 TEST_P(MockTCPChannelTestAI, ServFailResponse) {
193 DNSPacket rsp;
194 rsp.set_response().set_aa()
195 .add_question(new DNSQuestion("www.google.com", T_A));
196 rsp.set_rcode(SERVFAIL);
197 ON_CALL(server_, OnRequest("www.google.com", T_A))
198 .WillByDefault(SetReply(&server_, &rsp));
199
200 AddrInfoResult result;
201 struct ares_addrinfo_hints hints = {0, 0, 0, 0};
202 hints.ai_family = AF_INET;
203 hints.ai_flags = ARES_AI_NOSORT;
204 ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result);
205 Process();
206 EXPECT_TRUE(result.done_);
207 EXPECT_EQ(ARES_ESERVFAIL, result.status_);
208 }
209
TEST_P(MockTCPChannelTestAI,NotImplResponse)210 TEST_P(MockTCPChannelTestAI, NotImplResponse) {
211 DNSPacket rsp;
212 rsp.set_response().set_aa()
213 .add_question(new DNSQuestion("www.google.com", T_A));
214 rsp.set_rcode(NOTIMP);
215 ON_CALL(server_, OnRequest("www.google.com", T_A))
216 .WillByDefault(SetReply(&server_, &rsp));
217
218 AddrInfoResult result;
219 struct ares_addrinfo_hints hints = {0, 0, 0, 0};
220 hints.ai_family = AF_INET;
221 hints.ai_flags = ARES_AI_NOSORT;
222 ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result);
223 Process();
224 EXPECT_TRUE(result.done_);
225 EXPECT_EQ(ARES_ENOTIMP, result.status_);
226 }
227
TEST_P(MockTCPChannelTestAI,RefusedResponse)228 TEST_P(MockTCPChannelTestAI, RefusedResponse) {
229 DNSPacket rsp;
230 rsp.set_response().set_aa()
231 .add_question(new DNSQuestion("www.google.com", T_A));
232 rsp.set_rcode(REFUSED);
233 ON_CALL(server_, OnRequest("www.google.com", T_A))
234 .WillByDefault(SetReply(&server_, &rsp));
235
236 AddrInfoResult result;
237 struct ares_addrinfo_hints hints = {0, 0, 0, 0};
238 hints.ai_family = AF_INET;
239 hints.ai_flags = ARES_AI_NOSORT;
240 ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result);
241 Process();
242 EXPECT_TRUE(result.done_);
243 EXPECT_EQ(ARES_EREFUSED, result.status_);
244 }
245
TEST_P(MockTCPChannelTestAI,YXDomainResponse)246 TEST_P(MockTCPChannelTestAI, YXDomainResponse) {
247 DNSPacket rsp;
248 rsp.set_response().set_aa()
249 .add_question(new DNSQuestion("www.google.com", T_A));
250 rsp.set_rcode(YXDOMAIN);
251 EXPECT_CALL(server_, OnRequest("www.google.com", T_A))
252 .WillOnce(SetReply(&server_, &rsp));
253
254 AddrInfoResult result;
255 struct ares_addrinfo_hints hints = {0, 0, 0, 0};
256 hints.ai_family = AF_INET;
257 hints.ai_flags = ARES_AI_NOSORT;
258 ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result);
259 Process();
260 EXPECT_TRUE(result.done_);
261 EXPECT_EQ(ARES_ENODATA, result.status_);
262 }
263
264 class MockExtraOptsTestAI
265 : public MockChannelOptsTest,
266 public ::testing::WithParamInterface< std::pair<int, bool> > {
267 public:
MockExtraOptsTestAI()268 MockExtraOptsTestAI()
269 : MockChannelOptsTest(1, GetParam().first, GetParam().second, false,
270 FillOptions(&opts_),
271 ARES_OPT_SOCK_SNDBUF|ARES_OPT_SOCK_RCVBUF) {}
FillOptions(struct ares_options * opts)272 static struct ares_options* FillOptions(struct ares_options * opts) {
273 memset(opts, 0, sizeof(struct ares_options));
274 // Set a few options that affect socket communications
275 opts->socket_send_buffer_size = 514;
276 opts->socket_receive_buffer_size = 514;
277 return opts;
278 }
279 private:
280 struct ares_options opts_;
281 };
282
TEST_P(MockExtraOptsTestAI,SimpleQuery)283 TEST_P(MockExtraOptsTestAI, SimpleQuery) {
284 ares_set_local_ip4(channel_, 0x7F000001);
285 byte addr6[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
286 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
287 ares_set_local_ip6(channel_, addr6);
288 ares_set_local_dev(channel_, "dummy");
289
290 DNSPacket rsp;
291 rsp.set_response().set_aa()
292 .add_question(new DNSQuestion("www.google.com", T_A))
293 .add_answer(new DNSARR("www.google.com", 100, {2, 3, 4, 5}));
294 ON_CALL(server_, OnRequest("www.google.com", T_A))
295 .WillByDefault(SetReply(&server_, &rsp));
296
297 AddrInfoResult result;
298 struct ares_addrinfo_hints hints = {0, 0, 0, 0};
299 hints.ai_family = AF_INET;
300 hints.ai_flags = ARES_AI_NOSORT;
301 ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result);
302 Process();
303 EXPECT_TRUE(result.done_);
304 EXPECT_EQ(ARES_SUCCESS, result.status_);
305 EXPECT_THAT(result.ai_, IncludesNumAddresses(1));
306 EXPECT_THAT(result.ai_, IncludesV4Address("2.3.4.5"));
307 }
308
309 class MockExtraOptsNDotsTestAI
310 : public MockChannelOptsTest,
311 public ::testing::WithParamInterface< std::pair<int, bool> > {
312 public:
MockExtraOptsNDotsTestAI(int ndots)313 MockExtraOptsNDotsTestAI(int ndots)
314 : MockChannelOptsTest(1, GetParam().first, GetParam().second, false,
315 FillOptions(&opts_, ndots),
316 ARES_OPT_SOCK_SNDBUF|ARES_OPT_SOCK_RCVBUF|ARES_OPT_NDOTS) {}
FillOptions(struct ares_options * opts,int ndots)317 static struct ares_options* FillOptions(struct ares_options * opts, int ndots) {
318 memset(opts, 0, sizeof(struct ares_options));
319 // Set a few options that affect socket communications
320 opts->socket_send_buffer_size = 514;
321 opts->socket_receive_buffer_size = 514;
322 opts->ndots = ndots;
323 return opts;
324 }
325 private:
326 struct ares_options opts_;
327 };
328
329 class MockExtraOptsNDots5TestAI : public MockExtraOptsNDotsTestAI {
330 public:
MockExtraOptsNDots5TestAI()331 MockExtraOptsNDots5TestAI() : MockExtraOptsNDotsTestAI(5) {}
332 };
333
TEST_P(MockExtraOptsNDots5TestAI,SimpleQuery)334 TEST_P(MockExtraOptsNDots5TestAI, SimpleQuery) {
335 ares_set_local_ip4(channel_, 0x7F000001);
336 byte addr6[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
337 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
338 ares_set_local_ip6(channel_, addr6);
339 ares_set_local_dev(channel_, "dummy");
340
341 DNSPacket rsp;
342 rsp.set_response().set_aa()
343 .add_question(new DNSQuestion("dynamodb.us-east-1.amazonaws.com", T_A))
344 .add_answer(new DNSARR("dynamodb.us-east-1.amazonaws.com", 100, {123, 45, 67, 8}));
345 ON_CALL(server_, OnRequest("dynamodb.us-east-1.amazonaws.com", T_A))
346 .WillByDefault(SetReply(&server_, &rsp));
347
348 AddrInfoResult result;
349 struct ares_addrinfo_hints hints = {0, 0, 0, 0};
350 hints.ai_family = AF_INET;
351 hints.ai_flags = ARES_AI_NOSORT;
352 ares_getaddrinfo(channel_, "dynamodb.us-east-1.amazonaws.com.", NULL, &hints, AddrInfoCallback, &result);
353 Process();
354 EXPECT_TRUE(result.done_);
355 EXPECT_EQ(ARES_SUCCESS, result.status_);
356 EXPECT_THAT(result.ai_, IncludesNumAddresses(1));
357 EXPECT_THAT(result.ai_, IncludesV4Address("123.45.67.8"));
358 }
359
360 class MockExtraOptsNDots0TestAI : public MockExtraOptsNDotsTestAI {
361 public:
MockExtraOptsNDots0TestAI()362 MockExtraOptsNDots0TestAI() : MockExtraOptsNDotsTestAI(0) {}
363 };
364
TEST_P(MockExtraOptsNDots0TestAI,SimpleQuery)365 TEST_P(MockExtraOptsNDots0TestAI, SimpleQuery) {
366 DNSPacket rsp_ndots0;
367 rsp_ndots0.set_response().set_aa()
368 .add_question(new DNSQuestion("ndots0", T_A))
369 .add_answer(new DNSARR("ndots0", 100, {1, 2, 3, 4}));
370 ON_CALL(server_, OnRequest("ndots0", T_A))
371 .WillByDefault(SetReply(&server_, &rsp_ndots0));
372
373 DNSPacket rsp_ndots0_first;
374 rsp_ndots0_first.set_response().set_aa()
375 .add_question(new DNSQuestion("ndots0.first.com", T_A))
376 .add_answer(new DNSARR("ndots0.first.com", 100, {99, 99, 99, 99}));
377 ON_CALL(server_, OnRequest("ndots0.first.com", T_A))
378 .WillByDefault(SetReply(&server_, &rsp_ndots0_first));
379
380 DNSPacket rsp_ndots0_second;
381 rsp_ndots0_second.set_response().set_aa()
382 .add_question(new DNSQuestion("ndots0.second.org", T_A))
383 .add_answer(new DNSARR("ndots0.second.org", 100, {98, 98, 98, 98}));
384 ON_CALL(server_, OnRequest("ndots0.second.org", T_A))
385 .WillByDefault(SetReply(&server_, &rsp_ndots0_second));
386
387 DNSPacket rsp_ndots0_third;
388 rsp_ndots0_third.set_response().set_aa()
389 .add_question(new DNSQuestion("ndots0.third.gov", T_A))
390 .add_answer(new DNSARR("ndots0.third.gov", 100, {97, 97, 97, 97}));
391 ON_CALL(server_, OnRequest("ndots0.third.gov", T_A))
392 .WillByDefault(SetReply(&server_, &rsp_ndots0_third));
393
394 AddrInfoResult result;
395 struct ares_addrinfo_hints hints = {0, 0, 0, 0};
396 hints.ai_family = AF_INET;
397 hints.ai_flags = ARES_AI_NOSORT;
398 ares_getaddrinfo(channel_, "ndots0", NULL, &hints, AddrInfoCallback, &result);
399 Process();
400 EXPECT_TRUE(result.done_);
401 EXPECT_EQ(ARES_SUCCESS, result.status_);
402 std::stringstream ss;
403 ss << result.ai_;
404 EXPECT_EQ("{addr=[1.2.3.4]}", ss.str());
405 }
406
407
408 // Issue #852, systemd-resolved returns SERVFAIL (and possibly REFUSED) on
409 // single label domains. We need to work around this by continuing to go
410 // to the next in the search list. See also
411 // https://github.com/systemd/systemd/issues/34101
TEST_P(MockExtraOptsNDots0TestAI,SystemdServFail)412 TEST_P(MockExtraOptsNDots0TestAI, SystemdServFail) {
413 DNSPacket rsp_ndots0;
414 rsp_ndots0.set_response().set_rcode(SERVFAIL)
415 .add_question(new DNSQuestion("ndots0", T_A));
416 EXPECT_CALL(server_, OnRequest("ndots0", T_A))
417 // Will call until it hits max retries
418 .WillRepeatedly(SetReply(&server_, &rsp_ndots0));
419
420 DNSPacket rsp_ndots0_first;
421 rsp_ndots0_first.set_response().set_aa()
422 .add_question(new DNSQuestion("ndots0.first.com", T_A))
423 .add_answer(new DNSARR("ndots0.first.com", 100, {1, 2, 3, 4}));
424 EXPECT_CALL(server_, OnRequest("ndots0.first.com", T_A))
425 .WillOnce(SetReply(&server_, &rsp_ndots0_first));
426
427 AddrInfoResult result;
428 struct ares_addrinfo_hints hints = {0, 0, 0, 0};
429 hints.ai_family = AF_INET;
430 hints.ai_flags = ARES_AI_NOSORT;
431 ares_getaddrinfo(channel_, "ndots0", NULL, &hints, AddrInfoCallback, &result);
432 Process();
433 EXPECT_TRUE(result.done_);
434 EXPECT_EQ(ARES_SUCCESS, result.status_);
435 std::stringstream ss;
436 ss << result.ai_;
437 EXPECT_EQ("{addr=[1.2.3.4]}", ss.str());
438 }
TEST_P(MockExtraOptsNDots0TestAI,SystemdServFailSearch)439 TEST_P(MockExtraOptsNDots0TestAI, SystemdServFailSearch) {
440 DNSPacket rsp_ndots0;
441 rsp_ndots0.set_response().set_rcode(SERVFAIL)
442 .add_question(new DNSQuestion("ndots0", T_A));
443 EXPECT_CALL(server_, OnRequest("ndots0", T_A))
444 // Will call until it hits max retries
445 .WillRepeatedly(SetReply(&server_, &rsp_ndots0));
446
447 DNSPacket rsp_ndots0_first;
448 rsp_ndots0_first.set_response().set_aa()
449 .add_question(new DNSQuestion("ndots0.first.com", T_A))
450 .add_answer(new DNSARR("ndots0.first.com", 100, {1, 2, 3, 4}));
451 EXPECT_CALL(server_, OnRequest("ndots0.first.com", T_A))
452 .WillOnce(SetReply(&server_, &rsp_ndots0_first));
453
454 QueryResult result;
455 ares_dns_record_t *dnsrec = NULL;
456 ares_dns_record_create(&dnsrec, 0, ARES_FLAG_RD, ARES_OPCODE_QUERY, ARES_RCODE_NOERROR);
457 ares_dns_record_query_add(dnsrec, "ndots0", ARES_REC_TYPE_A, ARES_CLASS_IN);
458 ares_search_dnsrec(channel_, dnsrec, QueryCallback, &result);
459 ares_dns_record_destroy(dnsrec);
460 Process();
461 EXPECT_TRUE(result.done_);
462 EXPECT_EQ(ARES_SUCCESS, result.status_);
463
464 // QueryResult doesn't provide an easy way to retrieve the address, just ignore,
465 // success is probably good enough
466 }
TEST_P(MockExtraOptsNDots0TestAI,SystemdRefused)467 TEST_P(MockExtraOptsNDots0TestAI, SystemdRefused) {
468 DNSPacket rsp_ndots0;
469 rsp_ndots0.set_response().set_rcode(REFUSED)
470 .add_question(new DNSQuestion("ndots0", T_A));
471 EXPECT_CALL(server_, OnRequest("ndots0", T_A))
472 // Will call until it hits max retries
473 .WillRepeatedly(SetReply(&server_, &rsp_ndots0));
474
475 DNSPacket rsp_ndots0_first;
476 rsp_ndots0_first.set_response().set_aa()
477 .add_question(new DNSQuestion("ndots0.first.com", T_A))
478 .add_answer(new DNSARR("ndots0.first.com", 100, {1, 2, 3, 4}));
479 EXPECT_CALL(server_, OnRequest("ndots0.first.com", T_A))
480 .WillOnce(SetReply(&server_, &rsp_ndots0_first));
481
482 AddrInfoResult result;
483 struct ares_addrinfo_hints hints = {0, 0, 0, 0};
484 hints.ai_family = AF_INET;
485 hints.ai_flags = ARES_AI_NOSORT;
486 ares_getaddrinfo(channel_, "ndots0", NULL, &hints, AddrInfoCallback, &result);
487 Process();
488 EXPECT_TRUE(result.done_);
489 EXPECT_EQ(ARES_SUCCESS, result.status_);
490 std::stringstream ss;
491 ss << result.ai_;
492 EXPECT_EQ("{addr=[1.2.3.4]}", ss.str());
493 }
TEST_P(MockExtraOptsNDots0TestAI,SystemdRefusedSearch)494 TEST_P(MockExtraOptsNDots0TestAI, SystemdRefusedSearch) {
495 DNSPacket rsp_ndots0;
496 rsp_ndots0.set_response().set_rcode(REFUSED)
497 .add_question(new DNSQuestion("ndots0", T_A));
498 EXPECT_CALL(server_, OnRequest("ndots0", T_A))
499 // Will call until it hits max retries
500 .WillRepeatedly(SetReply(&server_, &rsp_ndots0));
501
502 DNSPacket rsp_ndots0_first;
503 rsp_ndots0_first.set_response().set_aa()
504 .add_question(new DNSQuestion("ndots0.first.com", T_A))
505 .add_answer(new DNSARR("ndots0.first.com", 100, {1, 2, 3, 4}));
506 EXPECT_CALL(server_, OnRequest("ndots0.first.com", T_A))
507 .WillOnce(SetReply(&server_, &rsp_ndots0_first));
508
509 QueryResult result;
510 ares_dns_record_t *dnsrec = NULL;
511 ares_dns_record_create(&dnsrec, 0, ARES_FLAG_RD, ARES_OPCODE_QUERY, ARES_RCODE_NOERROR);
512 ares_dns_record_query_add(dnsrec, "ndots0", ARES_REC_TYPE_A, ARES_CLASS_IN);
513 ares_search_dnsrec(channel_, dnsrec, QueryCallback, &result);
514 ares_dns_record_destroy(dnsrec);
515 Process();
516 EXPECT_TRUE(result.done_);
517 EXPECT_EQ(ARES_SUCCESS, result.status_);
518
519 // QueryResult doesn't provide an easy way to retrieve the address, just ignore,
520 // success is probably good enough
521 }
522
523
524 class MockFlagsChannelOptsTestAI
525 : public MockChannelOptsTest,
526 public ::testing::WithParamInterface< std::pair<int, bool> > {
527 public:
MockFlagsChannelOptsTestAI(int flags)528 MockFlagsChannelOptsTestAI(int flags)
529 : MockChannelOptsTest(1, GetParam().first, GetParam().second, false,
530 FillOptions(&opts_, flags), ARES_OPT_FLAGS) {}
FillOptions(struct ares_options * opts,int flags)531 static struct ares_options* FillOptions(struct ares_options * opts, int flags) {
532 memset(opts, 0, sizeof(struct ares_options));
533 opts->flags = flags;
534 return opts;
535 }
536 private:
537 struct ares_options opts_;
538 };
539
540 class MockNoCheckRespChannelTestAI : public MockFlagsChannelOptsTestAI {
541 public:
MockNoCheckRespChannelTestAI()542 MockNoCheckRespChannelTestAI() : MockFlagsChannelOptsTestAI(ARES_FLAG_NOCHECKRESP) {}
543 };
544
TEST_P(MockNoCheckRespChannelTestAI,ServFailResponse)545 TEST_P(MockNoCheckRespChannelTestAI, ServFailResponse) {
546 DNSPacket rsp;
547 rsp.set_response().set_aa()
548 .add_question(new DNSQuestion("www.google.com", T_A));
549 rsp.set_rcode(SERVFAIL);
550 ON_CALL(server_, OnRequest("www.google.com", T_A))
551 .WillByDefault(SetReply(&server_, &rsp));
552
553 AddrInfoResult result;
554 struct ares_addrinfo_hints hints = {0, 0, 0, 0};
555 hints.ai_family = AF_INET;
556 hints.ai_flags = ARES_AI_NOSORT;
557 ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result);
558 Process();
559 EXPECT_TRUE(result.done_);
560 EXPECT_EQ(ARES_ESERVFAIL, result.status_);
561 }
562
TEST_P(MockNoCheckRespChannelTestAI,NotImplResponse)563 TEST_P(MockNoCheckRespChannelTestAI, NotImplResponse) {
564 DNSPacket rsp;
565 rsp.set_response().set_aa()
566 .add_question(new DNSQuestion("www.google.com", T_A));
567 rsp.set_rcode(NOTIMP);
568 ON_CALL(server_, OnRequest("www.google.com", T_A))
569 .WillByDefault(SetReply(&server_, &rsp));
570
571 AddrInfoResult result;
572 struct ares_addrinfo_hints hints = {0, 0, 0, 0};
573 hints.ai_family = AF_INET;
574 hints.ai_flags = ARES_AI_NOSORT;
575 ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result);
576 Process();
577 EXPECT_TRUE(result.done_);
578 EXPECT_EQ(ARES_ENOTIMP, result.status_);
579 }
580
TEST_P(MockNoCheckRespChannelTestAI,RefusedResponse)581 TEST_P(MockNoCheckRespChannelTestAI, RefusedResponse) {
582 DNSPacket rsp;
583 rsp.set_response().set_aa()
584 .add_question(new DNSQuestion("www.google.com", T_A));
585 rsp.set_rcode(REFUSED);
586 ON_CALL(server_, OnRequest("www.google.com", T_A))
587 .WillByDefault(SetReply(&server_, &rsp));
588
589 AddrInfoResult result;
590 struct ares_addrinfo_hints hints = {0, 0, 0, 0};
591 hints.ai_family = AF_INET;
592 hints.ai_flags = ARES_AI_NOSORT;
593 ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result);
594 Process();
595 EXPECT_TRUE(result.done_);
596 EXPECT_EQ(ARES_EREFUSED, result.status_);
597 }
598
TEST_P(MockChannelTestAI,FamilyV6)599 TEST_P(MockChannelTestAI, FamilyV6) {
600 DNSPacket rsp6;
601 rsp6.set_response().set_aa()
602 .add_question(new DNSQuestion("example.com", T_AAAA))
603 .add_answer(new DNSAaaaRR("example.com", 100,
604 {0x21, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
605 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03}));
606 ON_CALL(server_, OnRequest("example.com", T_AAAA))
607 .WillByDefault(SetReply(&server_, &rsp6));
608 AddrInfoResult result;
609 struct ares_addrinfo_hints hints = {0, 0, 0, 0};
610 hints.ai_family = AF_INET6;
611 hints.ai_flags = ARES_AI_NOSORT;
612 ares_getaddrinfo(channel_, "example.com.", NULL, &hints,
613 AddrInfoCallback, &result);
614 Process();
615 EXPECT_TRUE(result.done_);
616 EXPECT_THAT(result.ai_, IncludesNumAddresses(1));
617 EXPECT_THAT(result.ai_, IncludesV6Address("2121:0000:0000:0000:0000:0000:0000:0303"));
618 }
619
620 // Test case for Issue #662
TEST_P(MockChannelTestAI,PartialQueryCancel)621 TEST_P(MockChannelTestAI, PartialQueryCancel) {
622 std::vector<byte> nothing;
623 DNSPacket reply;
624 reply.set_response().set_aa()
625 .add_question(new DNSQuestion("example.com", T_A))
626 .add_answer(new DNSARR("example.com", 0x0100, {0x01, 0x02, 0x03, 0x04}));
627
628 ON_CALL(server_, OnRequest("example.com", T_A))
629 .WillByDefault(SetReply(&server_, &reply));
630
631 ON_CALL(server_, OnRequest("example.com", T_AAAA))
632 .WillByDefault(SetReplyData(&server_, nothing));
633
634
635 AddrInfoResult result;
636 struct ares_addrinfo_hints hints = {0, 0, 0, 0};
637 hints.ai_family = AF_UNSPEC;
638 ares_getaddrinfo(channel_, "example.com.", NULL, &hints,
639 AddrInfoCallback, &result);
640
641 // After 100ms, issues ares_cancel(), this should be enough time for the A
642 // record reply, but before the timeout on the AAAA record.
643 Process(100);
644 EXPECT_TRUE(result.done_);
645 EXPECT_EQ(ARES_ECANCELLED, result.status_);
646 }
647
TEST_P(MockChannelTestAI,FamilyV4)648 TEST_P(MockChannelTestAI, FamilyV4) {
649 DNSPacket rsp4;
650 rsp4.set_response().set_aa()
651 .add_question(new DNSQuestion("example.com", T_A))
652 .add_answer(new DNSARR("example.com", 100, {2, 3, 4, 5}));
653 ON_CALL(server_, OnRequest("example.com", T_A))
654 .WillByDefault(SetReply(&server_, &rsp4));
655 AddrInfoResult result = {};
656 struct ares_addrinfo_hints hints = {0, 0, 0, 0};
657 hints.ai_family = AF_INET;
658 hints.ai_flags = ARES_AI_NOSORT;
659 ares_getaddrinfo(channel_, "example.com.", NULL, &hints,
660 AddrInfoCallback, &result);
661 Process();
662 EXPECT_TRUE(result.done_);
663 EXPECT_THAT(result.ai_, IncludesNumAddresses(1));
664 EXPECT_THAT(result.ai_, IncludesV4Address("2.3.4.5"));
665 }
666
TEST_P(MockChannelTestAI,FamilyV4_MultipleAddresses)667 TEST_P(MockChannelTestAI, FamilyV4_MultipleAddresses) {
668 DNSPacket rsp4;
669 rsp4.set_response().set_aa()
670 .add_question(new DNSQuestion("example.com", T_A))
671 .add_answer(new DNSARR("example.com", 100, {2, 3, 4, 5}))
672 .add_answer(new DNSARR("example.com", 100, {7, 8, 9, 0}));
673 ON_CALL(server_, OnRequest("example.com", T_A))
674 .WillByDefault(SetReply(&server_, &rsp4));
675 AddrInfoResult result = {};
676 struct ares_addrinfo_hints hints = {0, 0, 0, 0};
677 hints.ai_family = AF_INET;
678 hints.ai_flags = ARES_AI_NOSORT;
679 ares_getaddrinfo(channel_, "example.com.", NULL, &hints,
680 AddrInfoCallback, &result);
681 Process();
682 EXPECT_TRUE(result.done_);
683 std::stringstream ss;
684 ss << result.ai_;
685 EXPECT_EQ("{addr=[2.3.4.5], addr=[7.8.9.0]}", ss.str());
686 }
687
TEST_P(MockChannelTestAI,FamilyUnspecified)688 TEST_P(MockChannelTestAI, FamilyUnspecified) {
689 DNSPacket rsp6;
690 rsp6.set_response().set_aa()
691 .add_question(new DNSQuestion("example.com", T_AAAA))
692 .add_answer(new DNSAaaaRR("example.com", 100,
693 {0x21, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
694 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03}));
695 ON_CALL(server_, OnRequest("example.com", T_AAAA))
696 .WillByDefault(SetReply(&server_, &rsp6));
697 DNSPacket rsp4;
698 rsp4.set_response().set_aa()
699 .add_question(new DNSQuestion("example.com", T_A))
700 .add_answer(new DNSARR("example.com", 100, {2, 3, 4, 5}));
701 ON_CALL(server_, OnRequest("example.com", T_A))
702 .WillByDefault(SetReply(&server_, &rsp4));
703 AddrInfoResult result;
704 struct ares_addrinfo_hints hints = {0, 0, 0, 0};
705 hints.ai_family = AF_UNSPEC;
706 hints.ai_flags = ARES_AI_NOSORT;
707 ares_getaddrinfo(channel_, "example.com.", NULL, &hints,
708 AddrInfoCallback, &result);
709 Process();
710 EXPECT_TRUE(result.done_);
711 EXPECT_THAT(result.ai_, IncludesNumAddresses(2));
712 EXPECT_THAT(result.ai_, IncludesV4Address("2.3.4.5"));
713 EXPECT_THAT(result.ai_, IncludesV6Address("2121:0000:0000:0000:0000:0000:0000:0303"));
714 }
715
716
TEST_P(MockChannelTestAI,TriggerResendThenConnFailSERVFAIL)717 TEST_P(MockChannelTestAI, TriggerResendThenConnFailSERVFAIL) {
718 // Set up the server response. The server always returns SERVFAIL.
719 DNSPacket badrsp4;
720 badrsp4.set_response().set_aa().set_rcode(SERVFAIL)
721 .add_question(new DNSQuestion("www.google.com", T_A));
722 DNSPacket goodrsp4;
723 goodrsp4.set_response().set_aa()
724 .add_question(new DNSQuestion("www.google.com", T_A))
725 .add_answer(new DNSARR("www.google.com", 0x0100, {0x01, 0x02, 0x03, 0x04}));
726
727 DNSPacket goodrsp6;
728 goodrsp6.set_response().set_aa()
729 .add_question(new DNSQuestion("www.google.com", T_AAAA))
730 .add_answer(new DNSAaaaRR("www.google.com", 100,
731 {0x21, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
732 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03}));
733
734 EXPECT_CALL(server_, OnRequest("www.google.com", T_A))
735 .WillOnce(SetReplyAndFailSend(&server_, &badrsp4))
736 .WillOnce(SetReply(&server_, &goodrsp4));
737
738 EXPECT_CALL(server_, OnRequest("www.google.com", T_AAAA))
739 .WillRepeatedly(SetReply(&server_, &goodrsp6));
740
741 ares_socket_functions sock_funcs;
742 memset(&sock_funcs, 0, sizeof(sock_funcs));
743
744 sock_funcs.asendv = ares_sendv_fail;
745
746 ares_set_socket_functions(channel_, &sock_funcs, NULL);
747
748 AddrInfoResult result;
749 struct ares_addrinfo_hints hints = {0, 0, 0, 0};
750 hints.ai_family = AF_UNSPEC;
751 hints.ai_flags = ARES_AI_NOSORT;
752 ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints,
753 AddrInfoCallback, &result);
754
755 Process();
756 EXPECT_TRUE(result.done_);
757 EXPECT_TRUE(result.done_);
758 EXPECT_THAT(result.ai_, IncludesNumAddresses(2));
759 EXPECT_THAT(result.ai_, IncludesV4Address("1.2.3.4"));
760 EXPECT_THAT(result.ai_, IncludesV6Address("2121:0000:0000:0000:0000:0000:0000:0303"));
761 }
762
TEST_P(MockUDPChannelTestAI,TriggerResendThenConnFailEDNS)763 TEST_P(MockUDPChannelTestAI, TriggerResendThenConnFailEDNS) {
764 // Set up the server response to simulate an EDNS failure
765 DNSPacket badrsp4;
766 badrsp4.set_response().set_aa().set_rcode(FORMERR)
767 .add_question(new DNSQuestion("www.google.com", T_A));
768 DNSPacket goodrsp4;
769 goodrsp4.set_response().set_aa()
770 .add_question(new DNSQuestion("www.google.com", T_A))
771 .add_answer(new DNSARR("www.google.com", 0x0100, {0x01, 0x02, 0x03, 0x04}));
772 DNSPacket goodrsp6;
773 goodrsp6.set_response().set_aa()
774 .add_question(new DNSQuestion("www.google.com", T_AAAA))
775 .add_answer(new DNSAaaaRR("www.google.com", 100,
776 {0x21, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
777 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03}));
778
779 EXPECT_CALL(server_, OnRequest("www.google.com", T_A))
780 .WillOnce(SetReplyAndFailSend(&server_, &badrsp4))
781 .WillOnce(SetReply(&server_, &goodrsp4));
782
783 EXPECT_CALL(server_, OnRequest("www.google.com", T_AAAA))
784 .WillRepeatedly(SetReply(&server_, &goodrsp6));
785
786 ares_socket_functions sock_funcs;
787 memset(&sock_funcs, 0, sizeof(sock_funcs));
788
789 sock_funcs.asendv = ares_sendv_fail;
790
791 ares_set_socket_functions(channel_, &sock_funcs, NULL);
792
793 AddrInfoResult result;
794 struct ares_addrinfo_hints hints = {0, 0, 0, 0};
795 hints.ai_family = AF_UNSPEC;
796 hints.ai_flags = ARES_AI_NOSORT;
797 ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints,
798 AddrInfoCallback, &result);
799
800 Process();
801 EXPECT_TRUE(result.done_);
802 EXPECT_TRUE(result.done_);
803 EXPECT_THAT(result.ai_, IncludesNumAddresses(2));
804 EXPECT_THAT(result.ai_, IncludesV4Address("1.2.3.4"));
805 EXPECT_THAT(result.ai_, IncludesV6Address("2121:0000:0000:0000:0000:0000:0000:0303"));
806 }
807
808
809
810 class MockEDNSChannelTestAI : public MockFlagsChannelOptsTestAI {
811 public:
MockEDNSChannelTestAI()812 MockEDNSChannelTestAI() : MockFlagsChannelOptsTestAI(ARES_FLAG_EDNS) {}
813 };
814
TEST_P(MockEDNSChannelTestAI,RetryWithoutEDNS)815 TEST_P(MockEDNSChannelTestAI, RetryWithoutEDNS) {
816 DNSPacket rspfail;
817 rspfail.set_response().set_aa().set_rcode(FORMERR)
818 .add_question(new DNSQuestion("www.google.com", T_A));
819 DNSPacket rspok;
820 rspok.set_response()
821 .add_question(new DNSQuestion("www.google.com", T_A))
822 .add_answer(new DNSARR("www.google.com", 100, {1, 2, 3, 4}));
823 EXPECT_CALL(server_, OnRequest("www.google.com", T_A))
824 .WillOnce(SetReply(&server_, &rspfail))
825 .WillOnce(SetReply(&server_, &rspok));
826
827 AddrInfoResult result;
828 struct ares_addrinfo_hints hints = {0, 0, 0, 0};
829 hints.ai_family = AF_INET;
830 hints.ai_flags = ARES_AI_NOSORT;
831 ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result);
832 Process();
833 EXPECT_TRUE(result.done_);
834 EXPECT_THAT(result.ai_, IncludesNumAddresses(1));
835 EXPECT_THAT(result.ai_, IncludesV4Address("1.2.3.4"));
836 }
837
TEST_P(MockChannelTestAI,SearchDomains)838 TEST_P(MockChannelTestAI, SearchDomains) {
839 DNSPacket nofirst;
840 nofirst.set_response().set_aa().set_rcode(NXDOMAIN)
841 .add_question(new DNSQuestion("www.first.com", T_A));
842 ON_CALL(server_, OnRequest("www.first.com", T_A))
843 .WillByDefault(SetReply(&server_, &nofirst));
844 DNSPacket nosecond;
845 nosecond.set_response().set_aa().set_rcode(NXDOMAIN)
846 .add_question(new DNSQuestion("www.second.org", T_A));
847 ON_CALL(server_, OnRequest("www.second.org", T_A))
848 .WillByDefault(SetReply(&server_, &nosecond));
849 DNSPacket yesthird;
850 yesthird.set_response().set_aa()
851 .add_question(new DNSQuestion("www.third.gov", T_A))
852 .add_answer(new DNSARR("www.third.gov", 0x0200, {2, 3, 4, 5}));
853 ON_CALL(server_, OnRequest("www.third.gov", T_A))
854 .WillByDefault(SetReply(&server_, &yesthird));
855
856 AddrInfoResult result;
857 struct ares_addrinfo_hints hints = {0, 0, 0, 0};
858 hints.ai_family = AF_INET;
859 hints.ai_flags = ARES_AI_NOSORT;
860 ares_getaddrinfo(channel_, "www", NULL, &hints, AddrInfoCallback, &result);
861 Process();
862 EXPECT_TRUE(result.done_);
863 EXPECT_THAT(result.ai_, IncludesNumAddresses(1));
864 EXPECT_THAT(result.ai_, IncludesV4Address("2.3.4.5"));
865 }
866
TEST_P(MockChannelTestAI,SearchDomainsServFailOnAAAA)867 TEST_P(MockChannelTestAI, SearchDomainsServFailOnAAAA) {
868 DNSPacket nofirst;
869 nofirst.set_response().set_aa().set_rcode(NXDOMAIN)
870 .add_question(new DNSQuestion("www.first.com", T_AAAA));
871 ON_CALL(server_, OnRequest("www.first.com", T_AAAA))
872 .WillByDefault(SetReply(&server_, &nofirst));
873 DNSPacket nofirst4;
874 nofirst4.set_response().set_aa().set_rcode(NXDOMAIN)
875 .add_question(new DNSQuestion("www.first.com", T_A));
876 ON_CALL(server_, OnRequest("www.first.com", T_A))
877 .WillByDefault(SetReply(&server_, &nofirst4));
878
879 DNSPacket nosecond;
880 nosecond.set_response().set_aa().set_rcode(NXDOMAIN)
881 .add_question(new DNSQuestion("www.second.org", T_AAAA));
882 ON_CALL(server_, OnRequest("www.second.org", T_AAAA))
883 .WillByDefault(SetReply(&server_, &nosecond));
884 DNSPacket yessecond4;
885 yessecond4.set_response().set_aa()
886 .add_question(new DNSQuestion("www.second.org", T_A))
887 .add_answer(new DNSARR("www.second.org", 0x0200, {2, 3, 4, 5}));
888 ON_CALL(server_, OnRequest("www.second.org", T_A))
889 .WillByDefault(SetReply(&server_, &yessecond4));
890
891 DNSPacket failthird;
892 failthird.set_response().set_aa().set_rcode(SERVFAIL)
893 .add_question(new DNSQuestion("www.third.gov", T_AAAA));
894 ON_CALL(server_, OnRequest("www.third.gov", T_AAAA))
895 .WillByDefault(SetReply(&server_, &failthird));
896 DNSPacket failthird4;
897 failthird4.set_response().set_aa().set_rcode(SERVFAIL)
898 .add_question(new DNSQuestion("www.third.gov", T_A));
899 ON_CALL(server_, OnRequest("www.third.gov", T_A))
900 .WillByDefault(SetReply(&server_, &failthird4));
901
902 AddrInfoResult result;
903 struct ares_addrinfo_hints hints = {0, 0, 0, 0};
904 hints.ai_family = AF_UNSPEC;
905 hints.ai_flags = ARES_AI_NOSORT;
906 ares_getaddrinfo(channel_, "www", NULL, &hints, AddrInfoCallback, &result);
907 Process();
908 EXPECT_TRUE(result.done_);
909 EXPECT_THAT(result.ai_, IncludesNumAddresses(1));
910 EXPECT_THAT(result.ai_, IncludesV4Address("2.3.4.5"));
911 }
912
913 class MockMultiServerChannelTestAI
914 : public MockChannelOptsTest,
915 public ::testing::WithParamInterface< std::pair<int, bool> > {
916 public:
MockMultiServerChannelTestAI(ares_options * opts,int optmask)917 MockMultiServerChannelTestAI(ares_options *opts, int optmask)
918 : MockChannelOptsTest(3, GetParam().first, GetParam().second, false, opts, optmask) {}
CheckExample()919 void CheckExample() {
920 AddrInfoResult result;
921 struct ares_addrinfo_hints hints = {0, 0, 0, 0};
922 hints.ai_family = AF_INET;
923 hints.ai_flags = ARES_AI_NOSORT;
924 ares_getaddrinfo(channel_, "www.example.com.", NULL, &hints, AddrInfoCallback, &result);
925 Process();
926 EXPECT_TRUE(result.done_);
927 EXPECT_EQ(result.status_, ARES_SUCCESS);
928 EXPECT_THAT(result.ai_, IncludesNumAddresses(1));
929 EXPECT_THAT(result.ai_, IncludesV4Address("2.3.4.5"));
930 }
931 };
932
933 class NoRotateMultiMockTestAI : public MockMultiServerChannelTestAI {
934 public:
NoRotateMultiMockTestAI()935 NoRotateMultiMockTestAI() : MockMultiServerChannelTestAI(nullptr, ARES_OPT_NOROTATE) {}
936 };
937
938 /* We want to terminate retries of other address classes on getaddrinfo if one
939 * address class is returned already to return replies faster.
940 * UPDATE: actually we want to do this only if the address class we received
941 * was ipv4. We've seen issues if ipv6 was returned but the host was
942 * really only capable of ipv4.
943 */
TEST_P(NoRotateMultiMockTestAI,v4Worksv6Timesout)944 TEST_P(NoRotateMultiMockTestAI, v4Worksv6Timesout) {
945 std::vector<byte> nothing;
946
947 DNSPacket rsp4;
948 rsp4.set_response().set_aa()
949 .add_question(new DNSQuestion("www.example.com", T_A))
950 .add_answer(new DNSARR("www.example.com", 0x0100, {0x01, 0x02, 0x03, 0x04}));
951
952 EXPECT_CALL(*servers_[0], OnRequest("www.example.com", T_A))
953 .WillOnce(SetReply(servers_[0].get(), &rsp4));
954 EXPECT_CALL(*servers_[0], OnRequest("www.example.com", T_AAAA))
955 .WillOnce(SetReplyData(servers_[0].get(), nothing));
956
957 AddrInfoResult result;
958 struct ares_addrinfo_hints hints = {0, 0, 0, 0};
959 hints.ai_family = AF_UNSPEC;
960 hints.ai_flags = ARES_AI_NOSORT;
961 ares_getaddrinfo(channel_, "www.example.com.", NULL, &hints, AddrInfoCallback, &result);
962 Process();
963 EXPECT_TRUE(result.done_);
964 EXPECT_EQ(result.status_, ARES_SUCCESS);
965 EXPECT_THAT(result.ai_, IncludesNumAddresses(1));
966 EXPECT_THAT(result.ai_, IncludesV4Address("1.2.3.4"));
967 }
968
TEST_P(NoRotateMultiMockTestAI,v6Worksv4TimesoutFirst)969 TEST_P(NoRotateMultiMockTestAI, v6Worksv4TimesoutFirst) {
970 std::vector<byte> nothing;
971
972 DNSPacket rsp4;
973 rsp4.set_response().set_aa()
974 .add_question(new DNSQuestion("www.example.com", T_A))
975 .add_answer(new DNSARR("www.example.com", 0x0100, {0x01, 0x02, 0x03, 0x04}));
976
977 DNSPacket rsp6;
978 rsp6.set_response().set_aa()
979 .add_question(new DNSQuestion("www.example.com", T_AAAA))
980 .add_answer(new DNSAaaaRR("www.example.com", 100,
981 {0x21, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
982 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03}));
983
984 EXPECT_CALL(*servers_[0], OnRequest("www.example.com", T_A))
985 .WillOnce(SetReplyData(servers_[0].get(), nothing));
986 EXPECT_CALL(*servers_[0], OnRequest("www.example.com", T_AAAA))
987 .WillOnce(SetReply(servers_[0].get(), &rsp6));
988 EXPECT_CALL(*servers_[1], OnRequest("www.example.com", T_A))
989 .WillOnce(SetReply(servers_[1].get(), &rsp4));
990
991 AddrInfoResult result;
992 struct ares_addrinfo_hints hints = {0, 0, 0, 0};
993 hints.ai_family = AF_UNSPEC;
994 hints.ai_flags = ARES_AI_NOSORT;
995 ares_getaddrinfo(channel_, "www.example.com.", NULL, &hints, AddrInfoCallback, &result);
996 Process();
997 EXPECT_TRUE(result.done_);
998 EXPECT_EQ(result.status_, ARES_SUCCESS);
999 EXPECT_THAT(result.ai_, IncludesNumAddresses(2));
1000 EXPECT_THAT(result.ai_, IncludesV4Address("1.2.3.4"));
1001 EXPECT_THAT(result.ai_, IncludesV6Address("2121:0000:0000:0000:0000:0000:0000:0303"));
1002
1003 }
1004
TEST_P(NoRotateMultiMockTestAI,ThirdServer)1005 TEST_P(NoRotateMultiMockTestAI, ThirdServer) {
1006 struct ares_options opts;
1007 int optmask = 0;
1008 memset(&opts, 0, sizeof(opts));
1009 EXPECT_EQ(ARES_SUCCESS, ares_save_options(channel_, &opts, &optmask));
1010 EXPECT_EQ(ARES_OPT_NOROTATE, (optmask & ARES_OPT_NOROTATE));
1011 ares_destroy_options(&opts);
1012
1013 DNSPacket servfailrsp;
1014 servfailrsp.set_response().set_aa().set_rcode(SERVFAIL)
1015 .add_question(new DNSQuestion("www.example.com", T_A));
1016 DNSPacket notimplrsp;
1017 notimplrsp.set_response().set_aa().set_rcode(NOTIMP)
1018 .add_question(new DNSQuestion("www.example.com", T_A));
1019 DNSPacket okrsp;
1020 okrsp.set_response().set_aa()
1021 .add_question(new DNSQuestion("www.example.com", T_A))
1022 .add_answer(new DNSARR("www.example.com", 100, {2,3,4,5}));
1023
1024 EXPECT_CALL(*servers_[0], OnRequest("www.example.com", T_A))
1025 .WillOnce(SetReply(servers_[0].get(), &servfailrsp));
1026 EXPECT_CALL(*servers_[1], OnRequest("www.example.com", T_A))
1027 .WillOnce(SetReply(servers_[1].get(), ¬implrsp));
1028 EXPECT_CALL(*servers_[2], OnRequest("www.example.com", T_A))
1029 .WillOnce(SetReply(servers_[2].get(), &okrsp));
1030 CheckExample();
1031
1032 // Second time around, still starts from server [2], as [0] and [1] both
1033 // recorded failures
1034 EXPECT_CALL(*servers_[2], OnRequest("www.example.com", T_A))
1035 .WillOnce(SetReply(servers_[2].get(), &servfailrsp));
1036 EXPECT_CALL(*servers_[0], OnRequest("www.example.com", T_A))
1037 .WillOnce(SetReply(servers_[0].get(), ¬implrsp));
1038 EXPECT_CALL(*servers_[1], OnRequest("www.example.com", T_A))
1039 .WillOnce(SetReply(servers_[1].get(), &okrsp));
1040 CheckExample();
1041
1042 // Third time around, server order is [1] (f0), [2] (f1), [0] (f2), which
1043 // means [1] will get called twice in a row as after the first call
1044 // order will be [1] (f1), [2] (f1), [0] (f2) since sort order is
1045 // (failure count, index)
1046 EXPECT_CALL(*servers_[1], OnRequest("www.example.com", T_A))
1047 .WillOnce(SetReply(servers_[1].get(), &servfailrsp))
1048 .WillOnce(SetReply(servers_[1].get(), ¬implrsp));
1049 EXPECT_CALL(*servers_[2], OnRequest("www.example.com", T_A))
1050 .WillOnce(SetReply(servers_[2].get(), ¬implrsp));
1051 EXPECT_CALL(*servers_[0], OnRequest("www.example.com", T_A))
1052 .WillOnce(SetReply(servers_[0].get(), &okrsp));
1053 CheckExample();
1054 }
1055
TEST_P(MockChannelTestAI,FamilyV4ServiceName)1056 TEST_P(MockChannelTestAI, FamilyV4ServiceName) {
1057 DNSPacket rsp4;
1058 rsp4.set_response().set_aa()
1059 .add_question(new DNSQuestion("example.com", T_A))
1060 .add_answer(new DNSARR("example.com", 100, {1, 1, 1, 1}))
1061 .add_answer(new DNSARR("example.com", 100, {2, 2, 2, 2}));
1062 ON_CALL(server_, OnRequest("example.com", T_A))
1063 .WillByDefault(SetReply(&server_, &rsp4));
1064 AddrInfoResult result = {};
1065 struct ares_addrinfo_hints hints = {0, 0, 0, 0};
1066 hints.ai_family = AF_INET;
1067 hints.ai_flags = ARES_AI_NOSORT;
1068 ares_getaddrinfo(channel_, "example.com", "http", &hints, AddrInfoCallback, &result);
1069 Process();
1070 EXPECT_TRUE(result.done_);
1071 std::stringstream ss;
1072 ss << result.ai_;
1073 EXPECT_EQ("{addr=[1.1.1.1:80], addr=[2.2.2.2:80]}", ss.str());
1074 }
1075
1076 #ifdef HAVE_CONTAINER
1077
1078 class ContainedMockChannelAISysConfig
1079 : public MockChannelOptsTest,
1080 public ::testing::WithParamInterface<std::pair<int, bool>> {
1081 public:
ContainedMockChannelAISysConfig()1082 ContainedMockChannelAISysConfig()
1083 : MockChannelOptsTest(1, GetParam().first, GetParam().second, true, nullptr, 0) {}
1084 };
1085
1086 static NameContentList files_no_ndots = {
1087 {"/etc/resolv.conf", "nameserver 1.2.3.4\n" // Will be replaced
1088 "search example.com example.org\n"
1089 "options edns0 trust-ad\n"}, // ndots:1 is default
1090 {"/etc/hosts", "3.4.5.6 ahostname.com\n"},
1091 {"/etc/nsswitch.conf", "hosts: files dns\n"}};
1092
1093 /* These tests should still work even with /etc/hosts not having any localhost
1094 * entries */
1095 CONTAINED_TEST_P(ContainedMockChannelAISysConfig, NoHostsLocalHostv4,
1096 "myhostname", "mydomainname.org", files_no_ndots) {
1097 AddrInfoResult result = {};
1098 struct ares_addrinfo_hints hints = {0, 0, 0, 0};
1099 hints.ai_family = AF_INET;
1100 hints.ai_flags = ARES_AI_NOSORT;
1101 ares_getaddrinfo(channel_, "localhost", NULL, &hints, AddrInfoCallback, &result);
1102 Process();
1103 EXPECT_TRUE(result.done_);
1104 EXPECT_EQ(result.status_, ARES_SUCCESS);
1105 EXPECT_THAT(result.ai_, IncludesNumAddresses(1));
1106 EXPECT_THAT(result.ai_, IncludesV4Address("127.0.0.1"));
1107 return HasFailure();
1108 }
1109
1110 CONTAINED_TEST_P(ContainedMockChannelAISysConfig, NoHostsLocalHostv6,
1111 "myhostname", "mydomainname.org", files_no_ndots) {
1112 AddrInfoResult result = {};
1113 struct ares_addrinfo_hints hints = {0, 0, 0, 0};
1114 hints.ai_family = AF_INET6;
1115 hints.ai_flags = ARES_AI_NOSORT;
1116 ares_getaddrinfo(channel_, "localhost", NULL, &hints, AddrInfoCallback, &result);
1117 Process();
1118 EXPECT_TRUE(result.done_);
1119 EXPECT_EQ(result.status_, ARES_SUCCESS);
1120 EXPECT_THAT(result.ai_, IncludesNumAddresses(1));
1121 EXPECT_THAT(result.ai_, IncludesV6Address("0000:0000:0000:0000:0000:0000:0000:0001"));
1122 return HasFailure();
1123 }
1124
1125 CONTAINED_TEST_P(ContainedMockChannelAISysConfig, NoHostsLocalHostUnspec,
1126 "myhostname", "mydomainname.org", files_no_ndots) {
1127 AddrInfoResult result = {};
1128 struct ares_addrinfo_hints hints = {0, 0, 0, 0};
1129 hints.ai_family = AF_UNSPEC;
1130 hints.ai_flags = ARES_AI_NOSORT;
1131 ares_getaddrinfo(channel_, "localhost", NULL, &hints, AddrInfoCallback, &result);
1132 Process();
1133 EXPECT_TRUE(result.done_);
1134 EXPECT_EQ(result.status_, ARES_SUCCESS);
1135 EXPECT_THAT(result.ai_, IncludesNumAddresses(2));
1136 EXPECT_THAT(result.ai_, IncludesV4Address("127.0.0.1"));
1137 EXPECT_THAT(result.ai_, IncludesV6Address("0000:0000:0000:0000:0000:0000:0000:0001"));
1138 return HasFailure();
1139 }
1140
1141
1142 /* Issue #946 says if a v4 localhost entry exists, but not a v6 entry, v6
1143 * isn't output correctly. */
1144 static NameContentList files_localhost_v4localhostonly = {
1145 {"/etc/resolv.conf", "nameserver 1.2.3.4\n" // Will be replaced
1146 "search example.com example.org\n"
1147 "options edns0 trust-ad\n"}, // ndots:1 is default
1148 {"/etc/hosts", "127.0.0.1 localhost\n"},
1149 {"/etc/nsswitch.conf", "hosts: files dns\n"}};
1150 CONTAINED_TEST_P(ContainedMockChannelAISysConfig, v4OnlyLocalHostv4,
1151 "myhostname", "mydomainname.org", files_localhost_v4localhostonly) {
1152 AddrInfoResult result = {};
1153 struct ares_addrinfo_hints hints = {0, 0, 0, 0};
1154 hints.ai_family = AF_INET;
1155 hints.ai_flags = ARES_AI_NOSORT;
1156 ares_getaddrinfo(channel_, "localhost", NULL, &hints, AddrInfoCallback, &result);
1157 Process();
1158 EXPECT_TRUE(result.done_);
1159 EXPECT_EQ(result.status_, ARES_SUCCESS);
1160 EXPECT_THAT(result.ai_, IncludesNumAddresses(1));
1161 EXPECT_THAT(result.ai_, IncludesV4Address("127.0.0.1"));
1162 return HasFailure();
1163 }
1164
1165 CONTAINED_TEST_P(ContainedMockChannelAISysConfig, v4OnlyLocalHostv6,
1166 "myhostname", "mydomainname.org", files_localhost_v4localhostonly) {
1167 AddrInfoResult result = {};
1168 struct ares_addrinfo_hints hints = {0, 0, 0, 0};
1169 hints.ai_family = AF_INET6;
1170 hints.ai_flags = ARES_AI_NOSORT;
1171 ares_getaddrinfo(channel_, "localhost", NULL, &hints, AddrInfoCallback, &result);
1172 Process();
1173 EXPECT_TRUE(result.done_);
1174 EXPECT_EQ(result.status_, ARES_SUCCESS);
1175 EXPECT_THAT(result.ai_, IncludesNumAddresses(1));
1176 EXPECT_THAT(result.ai_, IncludesV6Address("0000:0000:0000:0000:0000:0000:0000:0001"));
1177 return HasFailure();
1178 }
1179
1180 CONTAINED_TEST_P(ContainedMockChannelAISysConfig, v4OnlyLocalHostUnspec,
1181 "myhostname", "mydomainname.org", files_localhost_v4localhostonly) {
1182 AddrInfoResult result = {};
1183 struct ares_addrinfo_hints hints = {0, 0, 0, 0};
1184 hints.ai_family = AF_UNSPEC;
1185 hints.ai_flags = ARES_AI_NOSORT;
1186 ares_getaddrinfo(channel_, "localhost", NULL, &hints, AddrInfoCallback, &result);
1187 Process();
1188 EXPECT_TRUE(result.done_);
1189 EXPECT_EQ(result.status_, ARES_SUCCESS);
1190 EXPECT_THAT(result.ai_, IncludesNumAddresses(2));
1191 EXPECT_THAT(result.ai_, IncludesV4Address("127.0.0.1"));
1192 EXPECT_THAT(result.ai_, IncludesV6Address("0000:0000:0000:0000:0000:0000:0000:0001"));
1193 return HasFailure();
1194 }
1195
1196
1197 static NameContentList files_localhost_v6localhostonly = {
1198 {"/etc/resolv.conf", "nameserver 1.2.3.4\n" // Will be replaced
1199 "search example.com example.org\n"
1200 "options edns0 trust-ad\n"}, // ndots:1 is default
1201 {"/etc/hosts", "::1 localhost\n"},
1202 {"/etc/nsswitch.conf", "hosts: files dns\n"}};
1203 CONTAINED_TEST_P(ContainedMockChannelAISysConfig, v6OnlyLocalHostv4,
1204 "myhostname", "mydomainname.org", files_localhost_v6localhostonly) {
1205 AddrInfoResult result = {};
1206 struct ares_addrinfo_hints hints = {0, 0, 0, 0};
1207 hints.ai_family = AF_INET;
1208 hints.ai_flags = ARES_AI_NOSORT;
1209 ares_getaddrinfo(channel_, "localhost", NULL, &hints, AddrInfoCallback, &result);
1210 Process();
1211 EXPECT_TRUE(result.done_);
1212 EXPECT_EQ(result.status_, ARES_SUCCESS);
1213 EXPECT_THAT(result.ai_, IncludesNumAddresses(1));
1214 EXPECT_THAT(result.ai_, IncludesV4Address("127.0.0.1"));
1215 return HasFailure();
1216 }
1217
1218 CONTAINED_TEST_P(ContainedMockChannelAISysConfig, v6OnlyLocalHostv6,
1219 "myhostname", "mydomainname.org", files_localhost_v6localhostonly) {
1220 AddrInfoResult result = {};
1221 struct ares_addrinfo_hints hints = {0, 0, 0, 0};
1222 hints.ai_family = AF_INET6;
1223 hints.ai_flags = ARES_AI_NOSORT;
1224 ares_getaddrinfo(channel_, "localhost", NULL, &hints, AddrInfoCallback, &result);
1225 Process();
1226 EXPECT_TRUE(result.done_);
1227 EXPECT_EQ(result.status_, ARES_SUCCESS);
1228 EXPECT_THAT(result.ai_, IncludesNumAddresses(1));
1229 EXPECT_THAT(result.ai_, IncludesV6Address("0000:0000:0000:0000:0000:0000:0000:0001"));
1230 return HasFailure();
1231 }
1232
1233 CONTAINED_TEST_P(ContainedMockChannelAISysConfig, v6OnlyLocalHostUnspec,
1234 "myhostname", "mydomainname.org", files_localhost_v6localhostonly) {
1235 AddrInfoResult result = {};
1236 struct ares_addrinfo_hints hints = {0, 0, 0, 0};
1237 hints.ai_family = AF_UNSPEC;
1238 hints.ai_flags = ARES_AI_NOSORT;
1239 ares_getaddrinfo(channel_, "localhost", NULL, &hints, AddrInfoCallback, &result);
1240 Process();
1241 EXPECT_TRUE(result.done_);
1242 EXPECT_EQ(result.status_, ARES_SUCCESS);
1243 EXPECT_THAT(result.ai_, IncludesNumAddresses(2));
1244 EXPECT_THAT(result.ai_, IncludesV4Address("127.0.0.1"));
1245 EXPECT_THAT(result.ai_, IncludesV6Address("0000:0000:0000:0000:0000:0000:0000:0001"));
1246 return HasFailure();
1247 }
1248
1249 INSTANTIATE_TEST_SUITE_P(AddressFamiliesAI, ContainedMockChannelAISysConfig, ::testing::ValuesIn(ares::test::families_modes), PrintFamilyMode);
1250 #endif
1251
1252 INSTANTIATE_TEST_SUITE_P(AddressFamiliesAI, MockChannelTestAI,
1253 ::testing::ValuesIn(ares::test::families_modes), PrintFamilyMode);
1254
1255 INSTANTIATE_TEST_SUITE_P(AddressFamiliesAI, MockUDPChannelTestAI,
1256 ::testing::ValuesIn(ares::test::families), PrintFamily);
1257
1258 INSTANTIATE_TEST_SUITE_P(AddressFamiliesAI, MockTCPChannelTestAI,
1259 ::testing::ValuesIn(ares::test::families), PrintFamily);
1260
1261 INSTANTIATE_TEST_SUITE_P(AddressFamiliesAI, MockExtraOptsTestAI,
1262 ::testing::ValuesIn(ares::test::families_modes), PrintFamilyMode);
1263
1264 INSTANTIATE_TEST_SUITE_P(AddressFamiliesAI, MockExtraOptsNDots5TestAI,
1265 ::testing::ValuesIn(ares::test::families_modes), PrintFamilyMode);
1266
1267 INSTANTIATE_TEST_SUITE_P(AddressFamiliesAI, MockExtraOptsNDots0TestAI,
1268 ::testing::ValuesIn(ares::test::families_modes), PrintFamilyMode);
1269
1270 INSTANTIATE_TEST_SUITE_P(AddressFamiliesAI, MockNoCheckRespChannelTestAI,
1271 ::testing::ValuesIn(ares::test::families_modes), PrintFamilyMode);
1272
1273 INSTANTIATE_TEST_SUITE_P(AddressFamiliesAI, MockEDNSChannelTestAI,
1274 ::testing::ValuesIn(ares::test::families_modes), PrintFamilyMode);
1275
1276 INSTANTIATE_TEST_SUITE_P(TransportModesAI, NoRotateMultiMockTestAI,
1277 ::testing::ValuesIn(ares::test::families_modes), PrintFamilyMode);
1278
1279 } // namespace test
1280 } // namespace ares
1281