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,ParseRootName)10 TEST_F(LibraryTest, ParseRootName) {
11   DNSPacket pkt;
12   pkt.set_qid(0x1234).set_response().set_aa()
13     .add_question(new DNSQuestion(".", T_A))
14     .add_answer(new DNSARR(".", 100, {0x02, 0x03, 0x04, 0x05}));
15   std::vector<byte> data = pkt.data();
16 
17   struct hostent *host = nullptr;
18   struct ares_addrttl info[2];
19   int count = 2;
20   EXPECT_EQ(ARES_SUCCESS, ares_parse_a_reply(data.data(), data.size(),
21                                              &host, info, &count));
22   EXPECT_EQ(1, count);
23   std::stringstream ss;
24   ss << HostEnt(host);
25   EXPECT_EQ("{'' aliases=[] addrs=[2.3.4.5]}", ss.str());
26   ares_free_hostent(host);
27 }
28 
TEST_F(LibraryTest,ParseIndirectRootName)29 TEST_F(LibraryTest, ParseIndirectRootName) {
30   std::vector<byte> data = {
31     0x12, 0x34,  // qid
32     0x84, // response + query + AA + not-TC + not-RD
33     0x00, // not-RA + not-Z + not-AD + not-CD + rc=NoError
34     0x00, 0x01,  // num questions
35     0x00, 0x01,  // num answer RRs
36     0x00, 0x00,  // num authority RRs
37     0x00, 0x00,  // num additional RRs
38     // Question
39     0xC0, 0x04,  // weird: pointer to a random zero earlier in the message
40     0x00, 0x01,  // type A
41     0x00, 0x01,  // class IN
42     // Answer 1
43     0xC0, 0x04,
44     0x00, 0x01,  // RR type
45     0x00, 0x01,  // class IN
46     0x01, 0x02, 0x03, 0x04, // TTL
47     0x00, 0x04,  // rdata length
48     0x02, 0x03, 0x04, 0x05,
49   };
50 
51   struct hostent *host = nullptr;
52   struct ares_addrttl info[2];
53   int count = 2;
54   EXPECT_EQ(ARES_SUCCESS, ares_parse_a_reply(data.data(), data.size(),
55                                              &host, info, &count));
56   EXPECT_EQ(1, count);
57   std::stringstream ss;
58   ss << HostEnt(host);
59   EXPECT_EQ("{'' aliases=[] addrs=[2.3.4.5]}", ss.str());
60   ares_free_hostent(host);
61 }
62 
63 
64 #if 0 /* We are validating hostnames now, its not clear how this would ever be valid */
65 TEST_F(LibraryTest, ParseEscapedName) {
66   std::vector<byte> data = {
67     0x12, 0x34,  // qid
68     0x84, // response + query + AA + not-TC + not-RD
69     0x00, // not-RA + not-Z + not-AD + not-CD + rc=NoError
70     0x00, 0x01,  // num questions
71     0x00, 0x01,  // num answer RRs
72     0x00, 0x00,  // num authority RRs
73     0x00, 0x00,  // num additional RRs
74     // Question
75     0x05, 'a', '\\', 'b', '.', 'c',
76     0x03, 'c', 'o', 'm',
77     0x00,
78     0x00, 0x01,  // type A
79     0x00, 0x01,  // class IN
80     // Answer 1
81     0x05, 'a', '\\', 'b', '.', 'c',
82     0x03, 'c', 'o', 'm',
83     0x00,
84     0x00, 0x01,  // RR type
85     0x00, 0x01,  // class IN
86     0x01, 0x02, 0x03, 0x04, // TTL
87     0x00, 0x04,  // rdata length
88     0x02, 0x03, 0x04, 0x05,
89   };
90   struct hostent *host = nullptr;
91   struct ares_addrttl info[2];
92   int count = 2;
93   EXPECT_EQ(ARES_SUCCESS, ares_parse_a_reply(data.data(), data.size(),
94                                              &host, info, &count));
95   EXPECT_EQ(1, count);
96   HostEnt hent(host);
97   std::stringstream ss;
98   ss << hent;
99   // The printable name is expanded with escapes.
100   EXPECT_EQ(11, hent.name_.size());
101   EXPECT_EQ('a', hent.name_[0]);
102   EXPECT_EQ('\\', hent.name_[1]);
103   EXPECT_EQ('\\', hent.name_[2]);
104   EXPECT_EQ('b', hent.name_[3]);
105   EXPECT_EQ('\\', hent.name_[4]);
106   EXPECT_EQ('.', hent.name_[5]);
107   EXPECT_EQ('c', hent.name_[6]);
108   ares_free_hostent(host);
109 }
110 #endif
111 
TEST_F(LibraryTest,ParsePartialCompressedName)112 TEST_F(LibraryTest, ParsePartialCompressedName) {
113   std::vector<byte> data = {
114     0x12, 0x34,  // qid
115     0x84, // response + query + AA + not-TC + not-RD
116     0x00, // not-RA + not-Z + not-AD + not-CD + rc=NoError
117     0x00, 0x01,  // num questions
118     0x00, 0x01,  // num answer RRs
119     0x00, 0x00,  // num authority RRs
120     0x00, 0x00,  // num additional RRs
121     // Question
122     0x03, 'w', 'w', 'w',
123     0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e',
124     0x03, 'c', 'o', 'm',
125     0x00,
126     0x00, 0x01,  // type A
127     0x00, 0x01,  // class IN
128     // Answer 1
129     0x03, 'w', 'w', 'w',
130     0xc0, 0x10,  // offset 16
131     0x00, 0x01,  // RR type
132     0x00, 0x01,  // class IN
133     0x01, 0x02, 0x03, 0x04, // TTL
134     0x00, 0x04,  // rdata length
135     0x02, 0x03, 0x04, 0x05,
136   };
137   struct hostent *host = nullptr;
138   struct ares_addrttl info[2];
139   int count = 2;
140   EXPECT_EQ(ARES_SUCCESS, ares_parse_a_reply(data.data(), data.size(),
141                                              &host, info, &count));
142   ASSERT_NE(nullptr, host);
143   std::stringstream ss;
144   ss << HostEnt(host);
145   EXPECT_EQ("{'www.example.com' aliases=[] addrs=[2.3.4.5]}", ss.str());
146   ares_free_hostent(host);
147 }
148 
TEST_F(LibraryTest,ParseFullyCompressedName)149 TEST_F(LibraryTest, ParseFullyCompressedName) {
150   std::vector<byte> data = {
151     0x12, 0x34,  // qid
152     0x84, // response + query + AA + not-TC + not-RD
153     0x00, // not-RA + not-Z + not-AD + not-CD + rc=NoError
154     0x00, 0x01,  // num questions
155     0x00, 0x01,  // num answer RRs
156     0x00, 0x00,  // num authority RRs
157     0x00, 0x00,  // num additional RRs
158     // Question
159     0x03, 'w', 'w', 'w',
160     0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e',
161     0x03, 'c', 'o', 'm',
162     0x00,
163     0x00, 0x01,  // type A
164     0x00, 0x01,  // class IN
165     // Answer 1
166     0xc0, 0x0c,  // offset 12
167     0x00, 0x01,  // RR type
168     0x00, 0x01,  // class IN
169     0x01, 0x02, 0x03, 0x04, // TTL
170     0x00, 0x04,  // rdata length
171     0x02, 0x03, 0x04, 0x05,
172   };
173   struct hostent *host = nullptr;
174   struct ares_addrttl info[2];
175   int count = 2;
176   EXPECT_EQ(ARES_SUCCESS, ares_parse_a_reply(data.data(), data.size(),
177                                              &host, info, &count));
178   ASSERT_NE(nullptr, host);
179   std::stringstream ss;
180   ss << HostEnt(host);
181   EXPECT_EQ("{'www.example.com' aliases=[] addrs=[2.3.4.5]}", ss.str());
182   ares_free_hostent(host);
183 }
184 
TEST_F(LibraryTest,ParseFullyCompressedName2)185 TEST_F(LibraryTest, ParseFullyCompressedName2) {
186   std::vector<byte> data = {
187     0x12, 0x34,  // qid
188     0x84, // response + query + AA + not-TC + not-RD
189     0x00, // not-RA + not-Z + not-AD + not-CD + rc=NoError
190     0x00, 0x01,  // num questions
191     0x00, 0x01,  // num answer RRs
192     0x00, 0x00,  // num authority RRs
193     0x00, 0x00,  // num additional RRs
194     // Question
195     0xC0, 0x12,  // pointer to later in message
196     0x00, 0x01,  // type A
197     0x00, 0x01,  // class IN
198     // Answer 1
199     0x03, 'w', 'w', 'w',
200     0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e',
201     0x03, 'c', 'o', 'm',
202     0x00,
203     0x00, 0x01,  // RR type
204     0x00, 0x01,  // class IN
205     0x01, 0x02, 0x03, 0x04, // TTL
206     0x00, 0x04,  // rdata length
207     0x02, 0x03, 0x04, 0x05,
208   };
209   struct hostent *host = nullptr;
210   struct ares_addrttl info[2];
211   int count = 2;
212   EXPECT_EQ(ARES_SUCCESS, ares_parse_a_reply(data.data(), data.size(),
213                                              &host, info, &count));
214   ASSERT_NE(nullptr, host);
215   std::stringstream ss;
216   ss << HostEnt(host);
217   EXPECT_EQ("{'www.example.com' aliases=[] addrs=[2.3.4.5]}", ss.str());
218   ares_free_hostent(host);
219 }
220 
221 }  // namespace test
222 }  // namespace ares
223