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,ParsePtrReplyOK)10 TEST_F(LibraryTest, ParsePtrReplyOK) {
11 byte addrv4[4] = {0x10, 0x20, 0x30, 0x40};
12 DNSPacket pkt;
13 pkt.set_qid(0x1234).set_response().set_aa()
14 .add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR))
15 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other.com"));
16 std::vector<byte> data = pkt.data();
17
18 struct hostent *host = nullptr;
19 EXPECT_EQ(ARES_SUCCESS, ares_parse_ptr_reply(data.data(), data.size(),
20 addrv4, sizeof(addrv4), AF_INET, &host));
21 ASSERT_NE(nullptr, host);
22 std::stringstream ss;
23 ss << HostEnt(host);
24 EXPECT_EQ("{'other.com' aliases=[other.com] addrs=[16.32.48.64]}", ss.str());
25 ares_free_hostent(host);
26 }
27
TEST_F(LibraryTest,ParsePtrReplyCname)28 TEST_F(LibraryTest, ParsePtrReplyCname) {
29 byte addrv4[4] = {0x10, 0x20, 0x30, 0x40};
30 DNSPacket pkt;
31 pkt.set_qid(0x1234).set_response().set_aa()
32 .add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR))
33 .add_answer(new DNSCnameRR("64.48.32.16.in-addr.arpa", 50, "64.48.32.8.in-addr.arpa"))
34 .add_answer(new DNSPtrRR("64.48.32.8.in-addr.arpa", 100, "other.com"));
35 std::vector<byte> data = pkt.data();
36
37 struct hostent *host = nullptr;
38 EXPECT_EQ(ARES_SUCCESS, ares_parse_ptr_reply(data.data(), data.size(),
39 addrv4, sizeof(addrv4), AF_INET, &host));
40 ASSERT_NE(nullptr, host);
41 std::stringstream ss;
42 ss << HostEnt(host);
43 EXPECT_EQ("{'other.com' aliases=[other.com] addrs=[16.32.48.64]}", ss.str());
44 ares_free_hostent(host);
45 }
46
47
48 struct DNSMalformedCnameRR : public DNSCnameRR {
DNSMalformedCnameRRares::test::DNSMalformedCnameRR49 DNSMalformedCnameRR(const std::string& name, int ttl, const std::string& other)
50 : DNSCnameRR(name, ttl, other) {}
dataares::test::DNSMalformedCnameRR51 std::vector<byte> data() const {
52 std::vector<byte> data = DNSRR::data();
53 std::vector<byte> encname = EncodeString(other_);
54 encname[0] = encname[0] + 63; // invalid label length
55 int len = encname.size();
56 PushInt16(&data, len);
57 data.insert(data.end(), encname.begin(), encname.end());
58 return data;
59 }
60 };
61
TEST_F(LibraryTest,ParsePtrReplyMalformedCname)62 TEST_F(LibraryTest, ParsePtrReplyMalformedCname) {
63 byte addrv4[4] = {0x10, 0x20, 0x30, 0x40};
64 DNSPacket pkt;
65 pkt.set_qid(0x1234).set_response().set_aa()
66 .add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR))
67 .add_answer(new DNSMalformedCnameRR("64.48.32.16.in-addr.arpa", 50, "64.48.32.8.in-addr.arpa"))
68 .add_answer(new DNSPtrRR("64.48.32.8.in-addr.arpa", 100, "other.com"));
69 std::vector<byte> data = pkt.data();
70
71 struct hostent *host = nullptr;
72 EXPECT_EQ(ARES_EBADRESP, ares_parse_ptr_reply(data.data(), data.size(),
73 addrv4, sizeof(addrv4), AF_INET, &host));
74 ASSERT_EQ(nullptr, host);
75 }
76
TEST_F(LibraryTest,ParseManyPtrReply)77 TEST_F(LibraryTest, ParseManyPtrReply) {
78 byte addrv4[4] = {0x10, 0x20, 0x30, 0x40};
79 DNSPacket pkt;
80 pkt.set_qid(0x1234).set_response().set_aa()
81 .add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR))
82 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "main.com"))
83 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other1.com"))
84 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other2.com"))
85 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other3.com"))
86 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other4.com"))
87 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other5.com"))
88 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other6.com"))
89 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other7.com"))
90 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other8.com"))
91 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other9.com"));
92 std::vector<byte> data = pkt.data();
93
94 struct hostent *host = nullptr;
95 EXPECT_EQ(ARES_SUCCESS, ares_parse_ptr_reply(data.data(), data.size(),
96 addrv4, sizeof(addrv4), AF_INET, &host));
97 ASSERT_NE(nullptr, host);
98 ares_free_hostent(host);
99 }
100
TEST_F(LibraryTest,ParsePtrReplyAdditional)101 TEST_F(LibraryTest, ParsePtrReplyAdditional) {
102 byte addrv4[4] = {0x10, 0x20, 0x30, 0x40};
103 DNSPacket pkt;
104 pkt.set_qid(0x1234).set_response().set_aa()
105 .add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR))
106 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 55, "other.com"))
107 .add_auth(new DNSNsRR("16.in-addr.arpa", 234, "ns1.other.com"))
108 .add_auth(new DNSNsRR("16.in-addr.arpa", 234, "bb.ns2.other.com"))
109 .add_auth(new DNSNsRR("16.in-addr.arpa", 234, "ns3.other.com"))
110 .add_additional(new DNSARR("ns1.other.com", 229, {10,20,30,41}))
111 .add_additional(new DNSARR("bb.ns2.other.com", 229, {10,20,30,42}))
112 .add_additional(new DNSARR("ns3.other.com", 229, {10,20,30,43}));
113 std::vector<byte> data = pkt.data();
114
115 struct hostent *host = nullptr;
116 EXPECT_EQ(ARES_SUCCESS, ares_parse_ptr_reply(data.data(), data.size(),
117 addrv4, sizeof(addrv4), AF_INET, &host));
118 ASSERT_NE(nullptr, host);
119 std::stringstream ss;
120 ss << HostEnt(host);
121 EXPECT_EQ("{'other.com' aliases=[other.com] addrs=[16.32.48.64]}", ss.str());
122 ares_free_hostent(host);
123 }
124
TEST_F(LibraryTest,ParsePtrReplyErrors)125 TEST_F(LibraryTest, ParsePtrReplyErrors) {
126 byte addrv4[4] = {0x10, 0x20, 0x30, 0x40};
127 DNSPacket pkt;
128 pkt.set_qid(0x1234).set_response().set_aa()
129 .add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR))
130 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other.com"));
131 std::vector<byte> data;
132 struct hostent *host = nullptr;
133
134 // No question.
135 pkt.questions_.clear();
136 data = pkt.data();
137 EXPECT_EQ(ARES_EBADRESP, ares_parse_ptr_reply(data.data(), data.size(),
138 addrv4, sizeof(addrv4), AF_INET, &host));
139 pkt.add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR));
140
141 // Question != answer
142 pkt.questions_.clear();
143 pkt.add_question(new DNSQuestion("99.48.32.16.in-addr.arpa", T_PTR));
144 data = pkt.data();
145 EXPECT_EQ(ARES_ENODATA, ares_parse_ptr_reply(data.data(), data.size(),
146 addrv4, sizeof(addrv4), AF_INET, &host));
147 EXPECT_EQ(nullptr, host);
148 pkt.questions_.clear();
149 pkt.add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR));
150
151 // Two questions.
152 pkt.add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR));
153 data = pkt.data();
154 EXPECT_EQ(ARES_EBADRESP, ares_parse_ptr_reply(data.data(), data.size(),
155 addrv4, sizeof(addrv4), AF_INET, &host));
156 EXPECT_EQ(nullptr, host);
157 pkt.questions_.clear();
158 pkt.add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR));
159
160 // Wrong sort of answer.
161 pkt.answers_.clear();
162 pkt.add_answer(new DNSMxRR("example.com", 100, 100, "mx1.example.com"));
163 data = pkt.data();
164 EXPECT_EQ(ARES_ENODATA, ares_parse_ptr_reply(data.data(), data.size(),
165 addrv4, sizeof(addrv4), AF_INET, &host));
166 EXPECT_EQ(nullptr, host);
167 pkt.answers_.clear();
168 pkt.add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other.com"));
169
170 // No answer.
171 pkt.answers_.clear();
172 data = pkt.data();
173 EXPECT_EQ(ARES_ENODATA, ares_parse_ptr_reply(data.data(), data.size(),
174 addrv4, sizeof(addrv4), AF_INET, &host));
175 EXPECT_EQ(nullptr, host);
176 pkt.add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other.com"));
177
178 // Truncated packets.
179 data = pkt.data();
180 for (size_t len = 1; len < data.size(); len++) {
181 EXPECT_EQ(ARES_EBADRESP, ares_parse_ptr_reply(data.data(), len,
182 addrv4, sizeof(addrv4), AF_INET, &host));
183 EXPECT_EQ(nullptr, host);
184 }
185
186 // Truncated packets with CNAME.
187 pkt.add_answer(new DNSCnameRR("64.48.32.16.in-addr.arpa", 50, "64.48.32.8.in-addr.arpa"));
188 data = pkt.data();
189 for (size_t len = 1; len < data.size(); len++) {
190 EXPECT_EQ(ARES_EBADRESP, ares_parse_ptr_reply(data.data(), len,
191 addrv4, sizeof(addrv4), AF_INET, &host));
192 EXPECT_EQ(nullptr, host);
193 }
194 }
195
TEST_F(LibraryTest,ParsePtrReplyAllocFailSome)196 TEST_F(LibraryTest, ParsePtrReplyAllocFailSome) {
197 byte addrv4[4] = {0x10, 0x20, 0x30, 0x40};
198 DNSPacket pkt;
199 pkt.set_qid(0x1234).set_response().set_aa()
200 .add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR))
201 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "main.com"))
202 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other1.com"))
203 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other2.com"))
204 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other3.com"));
205 std::vector<byte> data = pkt.data();
206 struct hostent *host = nullptr;
207
208 for (int ii = 1; ii <= 18; ii++) {
209 ClearFails();
210 SetAllocFail(ii);
211 EXPECT_EQ(ARES_ENOMEM, ares_parse_ptr_reply(data.data(), data.size(),
212 addrv4, sizeof(addrv4), AF_INET, &host)) << ii;
213 }
214 }
215
TEST_F(LibraryTest,ParsePtrReplyAllocFailMany)216 TEST_F(LibraryTest, ParsePtrReplyAllocFailMany) {
217 byte addrv4[4] = {0x10, 0x20, 0x30, 0x40};
218 DNSPacket pkt;
219 pkt.set_qid(0x1234).set_response().set_aa()
220 .add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR))
221 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "main.com"))
222 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other1.com"))
223 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other2.com"))
224 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other3.com"))
225 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other4.com"))
226 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other5.com"))
227 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other6.com"))
228 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other7.com"))
229 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other8.com"))
230 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other9.com"));
231 std::vector<byte> data = pkt.data();
232 struct hostent *host = nullptr;
233
234 for (int ii = 1; ii <= 63; ii++) {
235 ClearFails();
236 SetAllocFail(ii);
237 int rc = ares_parse_ptr_reply(data.data(), data.size(),
238 addrv4, sizeof(addrv4), AF_INET, &host);
239 if (rc != ARES_ENOMEM) {
240 EXPECT_EQ(ARES_SUCCESS, rc);
241 ares_free_hostent(host);
242 host = nullptr;
243 }
244 }
245 }
246
247
248 } // namespace test
249 } // namespace ares
250