ares-test-parse-ptr.cc (12235B)
1 /* MIT License 2 * 3 * Copyright (c) The c-ares project and its contributors 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a copy 6 * of this software and associated documentation files (the "Software"), to deal 7 * in the Software without restriction, including without limitation the rights 8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 * copies of the Software, and to permit persons to whom the Software is 10 * furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the next 13 * paragraph) shall be included in all copies or substantial portions of the 14 * Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 * 24 * SPDX-License-Identifier: MIT 25 */ 26 #include "ares-test.h" 27 #include "dns-proto.h" 28 29 #include <sstream> 30 #include <vector> 31 32 namespace ares { 33 namespace test { 34 35 TEST_F(LibraryTest, ParsePtrReplyOK) { 36 byte addrv4[4] = {0x10, 0x20, 0x30, 0x40}; 37 DNSPacket pkt; 38 pkt.set_qid(0x1234).set_response().set_aa() 39 .add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR)) 40 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other.com")); 41 std::vector<byte> data = pkt.data(); 42 43 struct hostent *host = nullptr; 44 EXPECT_EQ(ARES_SUCCESS, ares_parse_ptr_reply(data.data(), (int)data.size(), 45 addrv4, sizeof(addrv4), AF_INET, &host)); 46 ASSERT_NE(nullptr, host); 47 std::stringstream ss; 48 ss << HostEnt(host); 49 EXPECT_EQ("{'other.com' aliases=[other.com] addrs=[16.32.48.64]}", ss.str()); 50 ares_free_hostent(host); 51 } 52 53 TEST_F(LibraryTest, ParsePtrReplyCname) { 54 byte addrv4[4] = {0x10, 0x20, 0x30, 0x40}; 55 DNSPacket pkt; 56 pkt.set_qid(0x1234).set_response().set_aa() 57 .add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR)) 58 .add_answer(new DNSCnameRR("64.48.32.16.in-addr.arpa", 50, "64.48.32.8.in-addr.arpa")) 59 .add_answer(new DNSPtrRR("64.48.32.8.in-addr.arpa", 100, "other.com")); 60 std::vector<byte> data = pkt.data(); 61 62 struct hostent *host = nullptr; 63 EXPECT_EQ(ARES_SUCCESS, ares_parse_ptr_reply(data.data(), (int)data.size(), 64 addrv4, sizeof(addrv4), AF_INET, &host)); 65 ASSERT_NE(nullptr, host); 66 std::stringstream ss; 67 ss << HostEnt(host); 68 EXPECT_EQ("{'other.com' aliases=[other.com] addrs=[16.32.48.64]}", ss.str()); 69 ares_free_hostent(host); 70 } 71 72 73 struct DNSMalformedCnameRR : public DNSCnameRR { 74 DNSMalformedCnameRR(const std::string& name, int ttl, const std::string& other) 75 : DNSCnameRR(name, ttl, other) {} 76 std::vector<byte> data(const ares_dns_record_t *dnsrec) const { 77 std::vector<byte> data = DNSRR::data(dnsrec); 78 std::vector<byte> encname = EncodeString(other_); 79 encname[0] = encname[0] + 63; // invalid label length 80 int len = (int)encname.size(); 81 PushInt16(&data, len); 82 data.insert(data.end(), encname.begin(), encname.end()); 83 return data; 84 } 85 }; 86 87 TEST_F(LibraryTest, ParsePtrReplyMalformedCname) { 88 byte addrv4[4] = {0x10, 0x20, 0x30, 0x40}; 89 DNSPacket pkt; 90 pkt.set_qid(0x1234).set_response().set_aa() 91 .add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR)) 92 .add_answer(new DNSMalformedCnameRR("64.48.32.16.in-addr.arpa", 50, "64.48.32.8.in-addr.arpa")) 93 .add_answer(new DNSPtrRR("64.48.32.8.in-addr.arpa", 100, "other.com")); 94 std::vector<byte> data = pkt.data(); 95 96 struct hostent *host = nullptr; 97 EXPECT_EQ(ARES_EBADRESP, ares_parse_ptr_reply(data.data(), (int)data.size(), 98 addrv4, sizeof(addrv4), AF_INET, &host)); 99 ASSERT_EQ(nullptr, host); 100 } 101 102 TEST_F(LibraryTest, ParseManyPtrReply) { 103 byte addrv4[4] = {0x10, 0x20, 0x30, 0x40}; 104 DNSPacket pkt; 105 pkt.set_qid(0x1234).set_response().set_aa() 106 .add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR)) 107 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "main.com")) 108 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other1.com")) 109 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other2.com")) 110 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other3.com")) 111 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other4.com")) 112 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other5.com")) 113 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other6.com")) 114 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other7.com")) 115 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other8.com")) 116 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other9.com")); 117 std::vector<byte> data = pkt.data(); 118 119 struct hostent *host = nullptr; 120 EXPECT_EQ(ARES_SUCCESS, ares_parse_ptr_reply(data.data(), (int)data.size(), 121 addrv4, sizeof(addrv4), AF_INET, &host)); 122 ASSERT_NE(nullptr, host); 123 ares_free_hostent(host); 124 } 125 126 TEST_F(LibraryTest, ParsePtrReplyAdditional) { 127 byte addrv4[4] = {0x10, 0x20, 0x30, 0x40}; 128 DNSPacket pkt; 129 pkt.set_qid(0x1234).set_response().set_aa() 130 .add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR)) 131 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 55, "other.com")) 132 .add_auth(new DNSNsRR("16.in-addr.arpa", 234, "ns1.other.com")) 133 .add_auth(new DNSNsRR("16.in-addr.arpa", 234, "bb.ns2.other.com")) 134 .add_auth(new DNSNsRR("16.in-addr.arpa", 234, "ns3.other.com")) 135 .add_additional(new DNSARR("ns1.other.com", 229, {10,20,30,41})) 136 .add_additional(new DNSARR("bb.ns2.other.com", 229, {10,20,30,42})) 137 .add_additional(new DNSARR("ns3.other.com", 229, {10,20,30,43})); 138 std::vector<byte> data = pkt.data(); 139 140 struct hostent *host = nullptr; 141 EXPECT_EQ(ARES_SUCCESS, ares_parse_ptr_reply(data.data(), (int)data.size(), 142 addrv4, sizeof(addrv4), AF_INET, &host)); 143 ASSERT_NE(nullptr, host); 144 std::stringstream ss; 145 ss << HostEnt(host); 146 EXPECT_EQ("{'other.com' aliases=[other.com] addrs=[16.32.48.64]}", ss.str()); 147 ares_free_hostent(host); 148 } 149 150 TEST_F(LibraryTest, ParsePtrReplyErrors) { 151 byte addrv4[4] = {0x10, 0x20, 0x30, 0x40}; 152 DNSPacket pkt; 153 pkt.set_qid(0x1234).set_response().set_aa() 154 .add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR)) 155 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other.com")); 156 std::vector<byte> data; 157 struct hostent *host = nullptr; 158 159 // No question. 160 pkt.questions_.clear(); 161 data = pkt.data(); 162 EXPECT_EQ(ARES_EBADRESP, ares_parse_ptr_reply(data.data(), (int)data.size(), 163 addrv4, sizeof(addrv4), AF_INET, &host)); 164 pkt.add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR)); 165 166 // Question != answer, ok after #683 167 host = nullptr; 168 pkt.questions_.clear(); 169 pkt.add_question(new DNSQuestion("99.48.32.16.in-addr.arpa", T_PTR)); 170 data = pkt.data(); 171 EXPECT_EQ(ARES_SUCCESS, ares_parse_ptr_reply(data.data(), (int)data.size(), 172 addrv4, sizeof(addrv4), AF_INET, &host)); 173 ASSERT_NE(nullptr, host); 174 std::stringstream ss; 175 ss << HostEnt(host); 176 EXPECT_EQ("{'other.com' aliases=[other.com] addrs=[16.32.48.64]}", ss.str()); 177 ares_free_hostent(host); 178 179 host = nullptr; 180 pkt.questions_.clear(); 181 pkt.add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR)); 182 183 // Two questions. 184 pkt.add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR)); 185 data = pkt.data(); 186 EXPECT_EQ(ARES_EBADRESP, ares_parse_ptr_reply(data.data(), (int)data.size(), 187 addrv4, sizeof(addrv4), AF_INET, &host)); 188 EXPECT_EQ(nullptr, host); 189 pkt.questions_.clear(); 190 pkt.add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR)); 191 192 // Wrong sort of answer. 193 pkt.answers_.clear(); 194 pkt.add_answer(new DNSMxRR("example.com", 100, 100, "mx1.example.com")); 195 data = pkt.data(); 196 EXPECT_EQ(ARES_ENODATA, ares_parse_ptr_reply(data.data(), (int)data.size(), 197 addrv4, sizeof(addrv4), AF_INET, &host)); 198 EXPECT_EQ(nullptr, host); 199 pkt.answers_.clear(); 200 pkt.add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other.com")); 201 202 // No answer. 203 pkt.answers_.clear(); 204 data = pkt.data(); 205 EXPECT_EQ(ARES_ENODATA, ares_parse_ptr_reply(data.data(), (int)data.size(), 206 addrv4, sizeof(addrv4), AF_INET, &host)); 207 EXPECT_EQ(nullptr, host); 208 pkt.add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other.com")); 209 210 // Truncated packets. 211 data = pkt.data(); 212 for (size_t len = 1; len < data.size(); len++) { 213 EXPECT_EQ(ARES_EBADRESP, ares_parse_ptr_reply(data.data(), (int)len, 214 addrv4, sizeof(addrv4), AF_INET, &host)); 215 EXPECT_EQ(nullptr, host); 216 } 217 218 // Truncated packets with CNAME. 219 pkt.add_answer(new DNSCnameRR("64.48.32.16.in-addr.arpa", 50, "64.48.32.8.in-addr.arpa")); 220 data = pkt.data(); 221 for (size_t len = 1; len < data.size(); len++) { 222 EXPECT_EQ(ARES_EBADRESP, ares_parse_ptr_reply(data.data(), (int)len, 223 addrv4, sizeof(addrv4), AF_INET, &host)); 224 EXPECT_EQ(nullptr, host); 225 } 226 227 // Negative Length 228 EXPECT_EQ(ARES_EBADRESP, ares_parse_ptr_reply(data.data(), -1, 229 addrv4, sizeof(addrv4), AF_INET, &host)); 230 } 231 232 TEST_F(LibraryTest, ParsePtrReplyAllocFailSome) { 233 byte addrv4[4] = {0x10, 0x20, 0x30, 0x40}; 234 DNSPacket pkt; 235 pkt.set_qid(0x1234).set_response().set_aa() 236 .add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR)) 237 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "main.com")) 238 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other1.com")) 239 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other2.com")) 240 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other3.com")); 241 std::vector<byte> data = pkt.data(); 242 struct hostent *host = nullptr; 243 244 for (int ii = 1; ii <= 18; ii++) { 245 ClearFails(); 246 SetAllocFail(ii); 247 EXPECT_EQ(ARES_ENOMEM, ares_parse_ptr_reply(data.data(), (int)data.size(), 248 addrv4, sizeof(addrv4), AF_INET, &host)) << ii; 249 } 250 } 251 252 TEST_F(LibraryTest, ParsePtrReplyAllocFailMany) { 253 byte addrv4[4] = {0x10, 0x20, 0x30, 0x40}; 254 DNSPacket pkt; 255 pkt.set_qid(0x1234).set_response().set_aa() 256 .add_question(new DNSQuestion("64.48.32.16.in-addr.arpa", T_PTR)) 257 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "main.com")) 258 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other1.com")) 259 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other2.com")) 260 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other3.com")) 261 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other4.com")) 262 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other5.com")) 263 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other6.com")) 264 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other7.com")) 265 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other8.com")) 266 .add_answer(new DNSPtrRR("64.48.32.16.in-addr.arpa", 100, "other9.com")); 267 std::vector<byte> data = pkt.data(); 268 struct hostent *host = nullptr; 269 270 for (int ii = 1; ii <= 63; ii++) { 271 ClearFails(); 272 SetAllocFail(ii); 273 int rc = ares_parse_ptr_reply(data.data(), (int)data.size(), 274 addrv4, sizeof(addrv4), AF_INET, &host); 275 if (rc != ARES_ENOMEM) { 276 EXPECT_EQ(ARES_SUCCESS, rc); 277 ares_free_hostent(host); 278 host = nullptr; 279 } 280 } 281 } 282 283 284 } // namespace test 285 } // namespace ares