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,ParseTxtReplyOK)10 TEST_F(LibraryTest, ParseTxtReplyOK) {
11 DNSPacket pkt;
12 std::string expected1 = "txt1.example.com";
13 std::string expected2a = "txt2a";
14 std::string expected2b("ABC\0ABC", 7);
15 pkt.set_qid(0x1234).set_response().set_aa()
16 .add_question(new DNSQuestion("example.com", ns_t_mx))
17 .add_answer(new DNSTxtRR("example.com", 100, {expected1}))
18 .add_answer(new DNSTxtRR("example.com", 100, {expected2a, expected2b}));
19 std::vector<byte> data = pkt.data();
20
21 struct ares_txt_reply* txt = nullptr;
22 EXPECT_EQ(ARES_SUCCESS, ares_parse_txt_reply(data.data(), data.size(), &txt));
23 ASSERT_NE(nullptr, txt);
24 EXPECT_EQ(std::vector<byte>(expected1.data(), expected1.data() + expected1.size()),
25 std::vector<byte>(txt->txt, txt->txt + txt->length));
26
27 struct ares_txt_reply* txt2 = txt->next;
28 ASSERT_NE(nullptr, txt2);
29 EXPECT_EQ(std::vector<byte>(expected2a.data(), expected2a.data() + expected2a.size()),
30 std::vector<byte>(txt2->txt, txt2->txt + txt2->length));
31
32 struct ares_txt_reply* txt3 = txt2->next;
33 ASSERT_NE(nullptr, txt3);
34 EXPECT_EQ(std::vector<byte>(expected2b.data(), expected2b.data() + expected2b.size()),
35 std::vector<byte>(txt3->txt, txt3->txt + txt3->length));
36 EXPECT_EQ(nullptr, txt3->next);
37
38 ares_free_data(txt);
39 }
40
TEST_F(LibraryTest,ParseTxtExtReplyOK)41 TEST_F(LibraryTest, ParseTxtExtReplyOK) {
42 DNSPacket pkt;
43 std::string expected1 = "txt1.example.com";
44 std::string expected2a = "txt2a";
45 std::string expected2b("ABC\0ABC", 7);
46 pkt.set_qid(0x1234).set_response().set_aa()
47 .add_question(new DNSQuestion("example.com", ns_t_mx))
48 .add_answer(new DNSTxtRR("example.com", 100, {expected1}))
49 .add_answer(new DNSTxtRR("example.com", 100, {expected2a, expected2b}));
50 std::vector<byte> data = pkt.data();
51
52 struct ares_txt_ext* txt = nullptr;
53 EXPECT_EQ(ARES_SUCCESS, ares_parse_txt_reply_ext(data.data(), data.size(), &txt));
54 ASSERT_NE(nullptr, txt);
55 EXPECT_EQ(std::vector<byte>(expected1.data(), expected1.data() + expected1.size()),
56 std::vector<byte>(txt->txt, txt->txt + txt->length));
57 EXPECT_EQ(1, txt->record_start);
58
59 struct ares_txt_ext* txt2 = txt->next;
60 ASSERT_NE(nullptr, txt2);
61 EXPECT_EQ(std::vector<byte>(expected2a.data(), expected2a.data() + expected2a.size()),
62 std::vector<byte>(txt2->txt, txt2->txt + txt2->length));
63 EXPECT_EQ(1, txt2->record_start);
64
65 struct ares_txt_ext* txt3 = txt2->next;
66 ASSERT_NE(nullptr, txt3);
67 EXPECT_EQ(std::vector<byte>(expected2b.data(), expected2b.data() + expected2b.size()),
68 std::vector<byte>(txt3->txt, txt3->txt + txt3->length));
69 EXPECT_EQ(nullptr, txt3->next);
70 EXPECT_EQ(0, txt3->record_start);
71
72 ares_free_data(txt);
73 }
74
TEST_F(LibraryTest,ParseTxtMalformedReply1)75 TEST_F(LibraryTest, ParseTxtMalformedReply1) {
76 std::vector<byte> data = {
77 0x12, 0x34, // qid
78 0x84, // response + query + AA + not-TC + not-RD
79 0x00, // not-RA + not-Z + not-AD + not-CD + rc=NoError
80 0x00, 0x01, // num questions
81 0x00, 0x01, // num answer RRs
82 0x00, 0x00, // num authority RRs
83 0x00, 0x00, // num additional RRs
84 // Question
85 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e',
86 0x03, 'c', 'o', 'm',
87 0x00,
88 0x00, 0x10, // type TXT
89 0x00, 0x01, // class IN
90 // Answer 1
91 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e',
92 0x03, 'c', 'o', 'm',
93 0x00,
94 0x00, 0x10, // RR type
95 0x00, 0x01, // class IN
96 0x01, 0x02, 0x03, 0x04, // TTL
97 0x00, 0x03, // rdata length
98 0x12, 'a', 'b', // invalid length
99 };
100
101 struct ares_txt_reply* txt = nullptr;
102 EXPECT_EQ(ARES_EBADRESP, ares_parse_txt_reply(data.data(), data.size(), &txt));
103 ASSERT_EQ(nullptr, txt);
104 }
105
TEST_F(LibraryTest,ParseTxtMalformedReply2)106 TEST_F(LibraryTest, ParseTxtMalformedReply2) {
107 std::vector<byte> data = {
108 0x12, 0x34, // qid
109 0x84, // response + query + AA + not-TC + not-RD
110 0x00, // not-RA + not-Z + not-AD + not-CD + rc=NoError
111 0x00, 0x01, // num questions
112 0x00, 0x01, // num answer RRs
113 0x00, 0x00, // num authority RRs
114 0x00, 0x00, // num additional RRs
115 // Question
116 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e',
117 0x03, 'c', 'o', 'm',
118 0x00,
119 0x00, 0x10, // type TXT
120 0x00, 0x01, // class IN
121 // Answer 1
122 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e',
123 0x03, 'c', 'o', 'm',
124 0x00,
125 0x00, 0x10, // RR type
126 // truncated
127 };
128
129 struct ares_txt_reply* txt = nullptr;
130 EXPECT_EQ(ARES_EBADRESP, ares_parse_txt_reply(data.data(), data.size(), &txt));
131 ASSERT_EQ(nullptr, txt);
132 }
133
TEST_F(LibraryTest,ParseTxtMalformedReply3)134 TEST_F(LibraryTest, ParseTxtMalformedReply3) {
135 std::vector<byte> data = {
136 0x12, 0x34, // qid
137 0x84, // response + query + AA + not-TC + not-RD
138 0x00, // not-RA + not-Z + not-AD + not-CD + rc=NoError
139 0x00, 0x01, // num questions
140 0x00, 0x01, // num answer RRs
141 0x00, 0x00, // num authority RRs
142 0x00, 0x00, // num additional RRs
143 // Question
144 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e',
145 0x03, 'c', 'o', 'm',
146 0x00,
147 0x00, 0x10, // type TXT
148 0x00, 0x01, // class IN
149 // Answer 1
150 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e',
151 0x03, 'c', 'o', 'm',
152 0x00,
153 0x00, 0x10, // RR type
154 0x00, 0x01, // class IN
155 0x01, 0x02, 0x03, 0x04, // TTL
156 0x00, 0x13, // rdata length INVALID
157 0x02, 'a', 'b',
158 };
159
160 struct ares_txt_reply* txt = nullptr;
161 EXPECT_EQ(ARES_EBADRESP, ares_parse_txt_reply(data.data(), data.size(), &txt));
162 ASSERT_EQ(nullptr, txt);
163 }
164
TEST_F(LibraryTest,ParseTxtMalformedReply4)165 TEST_F(LibraryTest, ParseTxtMalformedReply4) {
166 std::vector<byte> data = {
167 0x12, 0x34, // qid
168 0x84, // response + query + AA + not-TC + not-RD
169 0x00, // not-RA + not-Z + not-AD + not-CD + rc=NoError
170 0x00, 0x01, // num questions
171 0x00, 0x01, // num answer RRs
172 0x00, 0x00, // num authority RRs
173 0x00, 0x00, // num additional RRs
174 // Question
175 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e',
176 0x03, 'c', 'o', 'm',
177 0x00,
178 0x00, 0x10, // type TXT
179 0x00, // TRUNCATED
180 };
181
182 struct ares_txt_reply* txt = nullptr;
183 EXPECT_EQ(ARES_EBADRESP, ares_parse_txt_reply(data.data(), data.size(), &txt));
184 ASSERT_EQ(nullptr, txt);
185 }
186
TEST_F(LibraryTest,ParseTxtReplyErrors)187 TEST_F(LibraryTest, ParseTxtReplyErrors) {
188 DNSPacket pkt;
189 std::string expected1 = "txt1.example.com";
190 std::string expected2a = "txt2a";
191 std::string expected2b = "txt2b";
192 pkt.set_qid(0x1234).set_response().set_aa()
193 .add_question(new DNSQuestion("example.com", ns_t_mx))
194 .add_answer(new DNSTxtRR("example.com", 100, {expected1}))
195 .add_answer(new DNSTxtRR("example.com", 100, {expected1}))
196 .add_answer(new DNSTxtRR("example.com", 100, {expected2a, expected2b}));
197 std::vector<byte> data = pkt.data();
198 struct ares_txt_reply* txt = nullptr;
199
200 // No question.
201 pkt.questions_.clear();
202 data = pkt.data();
203 txt = nullptr;
204 EXPECT_EQ(ARES_EBADRESP, ares_parse_txt_reply(data.data(), data.size(), &txt));
205 EXPECT_EQ(nullptr, txt);
206 pkt.add_question(new DNSQuestion("example.com", ns_t_mx));
207
208 #ifdef DISABLED
209 // Question != answer
210 pkt.questions_.clear();
211 pkt.add_question(new DNSQuestion("Axample.com", ns_t_txt));
212 data = pkt.data();
213 EXPECT_EQ(ARES_ENODATA, ares_parse_txt_reply(data.data(), data.size(), &txt));
214 pkt.questions_.clear();
215 pkt.add_question(new DNSQuestion("example.com", ns_t_txt));
216 #endif
217
218 // Two questions.
219 pkt.add_question(new DNSQuestion("example.com", ns_t_mx));
220 data = pkt.data();
221 txt = nullptr;
222 EXPECT_EQ(ARES_EBADRESP, ares_parse_txt_reply(data.data(), data.size(), &txt));
223 EXPECT_EQ(nullptr, txt);
224 pkt.questions_.clear();
225 pkt.add_question(new DNSQuestion("example.com", ns_t_mx));
226
227 // No answer.
228 pkt.answers_.clear();
229 data = pkt.data();
230 txt = nullptr;
231 EXPECT_EQ(ARES_ENODATA, ares_parse_txt_reply(data.data(), data.size(), &txt));
232 EXPECT_EQ(nullptr, txt);
233 pkt.add_answer(new DNSTxtRR("example.com", 100, {expected1}));
234
235 // Truncated packets.
236 for (size_t len = 1; len < data.size(); len++) {
237 txt = nullptr;
238 EXPECT_NE(ARES_SUCCESS, ares_parse_txt_reply(data.data(), len, &txt));
239 EXPECT_EQ(nullptr, txt);
240 }
241 }
242
TEST_F(LibraryTest,ParseTxtReplyAllocFail)243 TEST_F(LibraryTest, ParseTxtReplyAllocFail) {
244 DNSPacket pkt;
245 std::string expected1 = "txt1.example.com";
246 std::string expected2a = "txt2a";
247 std::string expected2b = "txt2b";
248 pkt.set_qid(0x1234).set_response().set_aa()
249 .add_question(new DNSQuestion("example.com", ns_t_mx))
250 .add_answer(new DNSCnameRR("example.com", 300, "c.example.com"))
251 .add_answer(new DNSTxtRR("c.example.com", 100, {expected1}))
252 .add_answer(new DNSTxtRR("c.example.com", 100, {expected1}))
253 .add_answer(new DNSTxtRR("c.example.com", 100, {expected2a, expected2b}));
254 std::vector<byte> data = pkt.data();
255 struct ares_txt_reply* txt = nullptr;
256
257 for (int ii = 1; ii <= 13; ii++) {
258 ClearFails();
259 SetAllocFail(ii);
260 EXPECT_EQ(ARES_ENOMEM, ares_parse_txt_reply(data.data(), data.size(), &txt)) << ii;
261 }
262 }
263
264
265 } // namespace test
266 } // namespace ares
267