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