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
TEST_F(LibraryTest,ParseAReplyOK)10 TEST_F(LibraryTest, ParseAReplyOK) {
11 DNSPacket pkt;
12 pkt.set_qid(0x1234).set_response().set_aa()
13 .add_question(new DNSQuestion("example.com", ns_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;
53 EXPECT_EQ(ARES_SUCCESS, ares_parse_a_reply(data.data(), data.size(),
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
67 EXPECT_EQ(ARES_SUCCESS, ares_parse_a_reply(data.data(), data.size(),
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
TEST_F(LibraryTest,ParseMalformedAReply)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.
111 EXPECT_EQ(ARES_EBADRESP, ares_parse_a_reply(data.data(), 26,
112 &host, info, &count));
113
114 // Truncate mid-answer.
115 EXPECT_EQ(ARES_EBADRESP, ares_parse_a_reply(data.data(), 42,
116 &host, info, &count));
117 }
118
TEST_F(LibraryTest,ParseAReplyNoData)119 TEST_F(LibraryTest, ParseAReplyNoData) {
120 DNSPacket pkt;
121 pkt.set_qid(0x1234).set_response().set_aa()
122 .add_question(new DNSQuestion("example.com", ns_t_a));
123 std::vector<byte> data = pkt.data();
124 struct hostent *host = nullptr;
125 struct ares_addrttl info[2];
126 int count = 2;
127 EXPECT_EQ(ARES_ENODATA, ares_parse_a_reply(data.data(), data.size(),
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
136 EXPECT_EQ(ARES_SUCCESS, ares_parse_a_reply(data.data(), data.size(),
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
TEST_F(LibraryTest,ParseAReplyVariantA)146 TEST_F(LibraryTest, ParseAReplyVariantA) {
147 DNSPacket pkt;
148 pkt.set_qid(6366).set_rd().set_ra()
149 .add_question(new DNSQuestion("mit.edu", ns_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();
159 EXPECT_EQ(ARES_SUCCESS, ares_parse_a_reply(data.data(), data.size(),
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
TEST_F(LibraryTest,ParseAReplyJustCname)167 TEST_F(LibraryTest, ParseAReplyJustCname) {
168 DNSPacket pkt;
169 pkt.set_qid(6366).set_rd().set_ra()
170 .add_question(new DNSQuestion("mit.edu", ns_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();
176 EXPECT_EQ(ARES_SUCCESS, ares_parse_a_reply(data.data(), data.size(),
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
TEST_F(LibraryTest,ParseAReplyVariantCname)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", ns_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();
204 EXPECT_EQ(ARES_SUCCESS, ares_parse_a_reply(data.data(), data.size(),
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;
214 EXPECT_EQ(ARES_SUCCESS, ares_parse_a_reply(data.data(), data.size(),
215 nullptr, info, &count));
216 }
217
TEST_F(LibraryTest,ParseAReplyVariantCnameChain)218 TEST_F(LibraryTest, ParseAReplyVariantCnameChain) {
219 DNSPacket pkt;
220 pkt.set_qid(6366).set_rd().set_ra()
221 .add_question(new DNSQuestion("c1.localhost", ns_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();
235 EXPECT_EQ(ARES_SUCCESS, ares_parse_a_reply(data.data(), data.size(),
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
TEST_F(LibraryTest,DISABLED_ParseAReplyVariantCnameLast)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", ns_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();
257 EXPECT_EQ(ARES_SUCCESS, ares_parse_a_reply(data.data(), data.size(),
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
TEST_F(LibraryTest,ParseAReplyErrors)271 TEST_F(LibraryTest, ParseAReplyErrors) {
272 DNSPacket pkt;
273 pkt.set_qid(0x1234).set_response().set_aa()
274 .add_question(new DNSQuestion("example.com", ns_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();
285 EXPECT_EQ(ARES_EBADRESP, ares_parse_a_reply(data.data(), data.size(),
286 &host, info, &count));
287 EXPECT_EQ(nullptr, host);
288 pkt.add_question(new DNSQuestion("example.com", ns_t_a));
289
290 // Question != answer
291 pkt.questions_.clear();
292 pkt.add_question(new DNSQuestion("Axample.com", ns_t_a));
293 data = pkt.data();
294 EXPECT_EQ(ARES_ENODATA, ares_parse_a_reply(data.data(), data.size(),
295 &host, info, &count));
296 EXPECT_EQ(nullptr, host);
297 pkt.questions_.clear();
298 pkt.add_question(new DNSQuestion("example.com", ns_t_a));
299
300 #ifdef DISABLED
301 // Not a response.
302 pkt.set_response(false);
303 data = pkt.data();
304 EXPECT_EQ(ARES_EBADRESP, ares_parse_a_reply(data.data(), data.size(),
305 &host, info, &count));
306 EXPECT_EQ(nullptr, host);
307 pkt.set_response(true);
308
309 // Bad return code.
310 pkt.set_rcode(ns_r_formerr);
311 data = pkt.data();
312 EXPECT_EQ(ARES_ENODATA, ares_parse_a_reply(data.data(), data.size(),
313 &host, info, &count));
314 EXPECT_EQ(nullptr, host);
315 pkt.set_rcode(ns_r_noerror);
316 #endif
317
318 // Two questions
319 pkt.add_question(new DNSQuestion("example.com", ns_t_a));
320 data = pkt.data();
321 EXPECT_EQ(ARES_EBADRESP, ares_parse_a_reply(data.data(), data.size(),
322 &host, info, &count));
323 EXPECT_EQ(nullptr, host);
324 pkt.questions_.clear();
325 pkt.add_question(new DNSQuestion("example.com", ns_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();
331 EXPECT_EQ(ARES_ENODATA, ares_parse_a_reply(data.data(), data.size(),
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();
340 EXPECT_EQ(ARES_ENODATA, ares_parse_a_reply(data.data(), data.size(),
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++) {
348 EXPECT_EQ(ARES_EBADRESP, ares_parse_a_reply(data.data(), len,
349 &host, info, &count));
350 EXPECT_EQ(nullptr, host);
351 EXPECT_EQ(ARES_EBADRESP, ares_parse_a_reply(data.data(), len,
352 nullptr, info, &count));
353 }
354 }
355
TEST_F(LibraryTest,ParseAReplyAllocFail)356 TEST_F(LibraryTest, ParseAReplyAllocFail) {
357 DNSPacket pkt;
358 pkt.set_qid(0x1234).set_response().set_aa()
359 .add_question(new DNSQuestion("example.com", ns_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);
371 EXPECT_EQ(ARES_ENOMEM, ares_parse_a_reply(data.data(), data.size(),
372 &host, info, &count)) << ii;
373 EXPECT_EQ(nullptr, host);
374 }
375 }
376
377 } // namespace test
378 } // namespace ares
379