You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

922 lines
28 KiB

  1. /*
  2. * This file is part of PowerDNS or dnsdist.
  3. * Copyright -- PowerDNS.COM B.V. and its contributors
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of version 2 of the GNU General Public License as
  7. * published by the Free Software Foundation.
  8. *
  9. * In addition, for the avoidance of any doubt, permission is granted to
  10. * link this program with OpenSSL and to (re)distribute the binaries
  11. * produced as the result of such linking.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  21. */
  22. #ifdef HAVE_CONFIG_H
  23. #include "config.h"
  24. #endif
  25. #include "utility.hh"
  26. #include "dnsrecords.hh"
  27. #include "iputils.hh"
  28. void DNSResourceRecord::setContent(const string &cont) {
  29. content = cont;
  30. switch(qtype.getCode()) {
  31. case QType::SRV:
  32. case QType::MX:
  33. if (content.size() >= 2 && *(content.rbegin()+1) == ' ')
  34. return;
  35. /* Falls through. */
  36. case QType::CNAME:
  37. case QType::DNAME:
  38. case QType::NS:
  39. case QType::PTR:
  40. if (content.size() >= 2 && *(content.rbegin()) == '.')
  41. boost::erase_tail(content, 1);
  42. }
  43. }
  44. string DNSResourceRecord::getZoneRepresentation(bool noDot) const {
  45. ostringstream ret;
  46. vector<string> parts;
  47. string last;
  48. switch(qtype.getCode()) {
  49. case QType::SRV:
  50. case QType::MX:
  51. stringtok(parts, content);
  52. if (!parts.size())
  53. return "";
  54. last = *parts.rbegin();
  55. ret << content;
  56. if (last == ".")
  57. break;
  58. if (*(last.rbegin()) != '.' && !noDot)
  59. ret << ".";
  60. break;
  61. case QType::CNAME:
  62. case QType::DNAME:
  63. case QType::NS:
  64. case QType::PTR:
  65. ret<<content;
  66. if (*(content.rbegin()) != '.' && !noDot)
  67. ret<<".";
  68. break;
  69. default:
  70. ret<<content;
  71. break;
  72. }
  73. return ret.str();
  74. }
  75. bool DNSResourceRecord::operator==(const DNSResourceRecord& rhs)
  76. {
  77. string lcontent=toLower(content);
  78. string rcontent=toLower(rhs.content);
  79. return
  80. tie(qname, qtype, lcontent, ttl) ==
  81. tie(rhs.qname, rhs.qtype, rcontent, rhs.ttl);
  82. }
  83. boilerplate_conv(A, QType::A, conv.xfrIP(d_ip));
  84. ARecordContent::ARecordContent(uint32_t ip)
  85. {
  86. d_ip = ip;
  87. }
  88. ARecordContent::ARecordContent(const ComboAddress& ca)
  89. {
  90. d_ip = ca.sin4.sin_addr.s_addr;
  91. }
  92. AAAARecordContent::AAAARecordContent(const ComboAddress& ca)
  93. {
  94. d_ip6.assign((const char*)ca.sin6.sin6_addr.s6_addr, 16);
  95. }
  96. ComboAddress ARecordContent::getCA(int port) const
  97. {
  98. ComboAddress ret;
  99. ret.sin4.sin_family=AF_INET;
  100. ret.sin4.sin_port=htons(port);
  101. memcpy(&ret.sin4.sin_addr.s_addr, &d_ip, sizeof(ret.sin4.sin_addr.s_addr));
  102. return ret;
  103. }
  104. ComboAddress AAAARecordContent::getCA(int port) const
  105. {
  106. ComboAddress ret;
  107. ret.reset();
  108. ret.sin4.sin_family=AF_INET6;
  109. ret.sin6.sin6_port = htons(port);
  110. memcpy(&ret.sin6.sin6_addr.s6_addr, d_ip6.c_str(), sizeof(ret.sin6.sin6_addr.s6_addr));
  111. return ret;
  112. }
  113. void ARecordContent::doRecordCheck(const DNSRecord& dr)
  114. {
  115. if(dr.d_clen!=4)
  116. throw MOADNSException("Wrong size for A record ("+std::to_string(dr.d_clen)+")");
  117. }
  118. boilerplate_conv(AAAA, QType::AAAA, conv.xfrIP6(d_ip6); );
  119. boilerplate_conv(NS, QType::NS, conv.xfrName(d_content, true));
  120. boilerplate_conv(PTR, QType::PTR, conv.xfrName(d_content, true));
  121. boilerplate_conv(CNAME, QType::CNAME, conv.xfrName(d_content, true));
  122. boilerplate_conv(ALIAS, QType::ALIAS, conv.xfrName(d_content, false));
  123. boilerplate_conv(DNAME, QType::DNAME, conv.xfrName(d_content));
  124. boilerplate_conv(MB, QType::MB, conv.xfrName(d_madname, true));
  125. boilerplate_conv(MG, QType::MG, conv.xfrName(d_mgmname, true));
  126. boilerplate_conv(MR, QType::MR, conv.xfrName(d_alias, true));
  127. boilerplate_conv(MINFO, QType::MINFO, conv.xfrName(d_rmailbx, true); conv.xfrName(d_emailbx, true));
  128. boilerplate_conv(TXT, QType::TXT, conv.xfrText(d_text, true));
  129. #ifdef HAVE_LUA_RECORDS
  130. boilerplate_conv(LUA, QType::LUA, conv.xfrType(d_type); conv.xfrText(d_code, true));
  131. #endif
  132. boilerplate_conv(ENT, 0, );
  133. boilerplate_conv(SPF, 99, conv.xfrText(d_text, true));
  134. boilerplate_conv(HINFO, QType::HINFO, conv.xfrText(d_cpu); conv.xfrText(d_host));
  135. boilerplate_conv(RP, QType::RP,
  136. conv.xfrName(d_mbox);
  137. conv.xfrName(d_info)
  138. );
  139. boilerplate_conv(OPT, QType::OPT,
  140. conv.xfrBlob(d_data)
  141. );
  142. #ifdef HAVE_LUA_RECORDS
  143. string LUARecordContent::getCode() const
  144. {
  145. // in d_code, series of "part1" "part2"
  146. vector<string> parts;
  147. stringtok(parts, d_code, "\"");
  148. string ret;
  149. for(const auto& p : parts) {
  150. ret += p;
  151. ret.append(1, ' ');
  152. }
  153. return ret;
  154. }
  155. #endif
  156. void OPTRecordContent::getData(vector<pair<uint16_t, string> >& options)
  157. {
  158. string::size_type pos=0;
  159. uint16_t code, len;
  160. while(d_data.size() >= 4 + pos) {
  161. code = 256 * (unsigned char)d_data[pos] + (unsigned char)d_data[pos+1];
  162. len = 256 * (unsigned char)d_data[pos+2] + (unsigned char)d_data[pos+3];
  163. pos+=4;
  164. if(pos + len > d_data.size())
  165. break;
  166. string field(d_data.c_str() + pos, len);
  167. pos+=len;
  168. options.push_back(make_pair(code, std::move(field)));
  169. }
  170. }
  171. boilerplate_conv(TSIG, QType::TSIG,
  172. conv.xfrName(d_algoName);
  173. conv.xfr48BitInt(d_time);
  174. conv.xfr16BitInt(d_fudge);
  175. uint16_t size=d_mac.size();
  176. conv.xfr16BitInt(size);
  177. if (size>0) conv.xfrBlobNoSpaces(d_mac, size);
  178. conv.xfr16BitInt(d_origID);
  179. conv.xfr16BitInt(d_eRcode);
  180. size=d_otherData.size();
  181. conv.xfr16BitInt(size);
  182. if (size>0) conv.xfrBlobNoSpaces(d_otherData, size);
  183. );
  184. MXRecordContent::MXRecordContent(uint16_t preference, const DNSName& mxname): d_preference(preference), d_mxname(mxname)
  185. {
  186. }
  187. boilerplate_conv(MX, QType::MX,
  188. conv.xfr16BitInt(d_preference);
  189. conv.xfrName(d_mxname, true);
  190. )
  191. boilerplate_conv(KX, QType::KX,
  192. conv.xfr16BitInt(d_preference);
  193. conv.xfrName(d_exchanger, false);
  194. )
  195. boilerplate_conv(IPSECKEY, QType::IPSECKEY,
  196. conv.xfr8BitInt(d_preference);
  197. conv.xfr8BitInt(d_gatewaytype);
  198. conv.xfr8BitInt(d_algorithm);
  199. // now we need to determine values
  200. switch(d_gatewaytype) {
  201. case 0: // NO KEY
  202. break;
  203. case 1: // IPv4 GW
  204. conv.xfrIP(d_ip4);
  205. break;
  206. case 2: // IPv6 GW
  207. conv.xfrIP6(d_ip6);
  208. break;
  209. case 3: // DNS label
  210. conv.xfrName(d_gateway, false);
  211. break;
  212. default:
  213. throw MOADNSException("Parsing record content: invalid gateway type");
  214. };
  215. switch(d_algorithm) {
  216. case 0:
  217. break;
  218. case 1:
  219. case 2:
  220. conv.xfrBlob(d_publickey);
  221. break;
  222. default:
  223. throw MOADNSException("Parsing record content: invalid algorithm type");
  224. }
  225. )
  226. boilerplate_conv(DHCID, 49,
  227. conv.xfrBlob(d_content);
  228. )
  229. boilerplate_conv(AFSDB, QType::AFSDB,
  230. conv.xfr16BitInt(d_subtype);
  231. conv.xfrName(d_hostname);
  232. )
  233. boilerplate_conv(NAPTR, QType::NAPTR,
  234. conv.xfr16BitInt(d_order); conv.xfr16BitInt(d_preference);
  235. conv.xfrText(d_flags); conv.xfrText(d_services); conv.xfrText(d_regexp);
  236. conv.xfrName(d_replacement);
  237. )
  238. SRVRecordContent::SRVRecordContent(uint16_t preference, uint16_t weight, uint16_t port, const DNSName& target)
  239. : d_weight(weight), d_port(port), d_target(target), d_preference(preference)
  240. {}
  241. boilerplate_conv(SRV, QType::SRV,
  242. conv.xfr16BitInt(d_preference); conv.xfr16BitInt(d_weight); conv.xfr16BitInt(d_port);
  243. conv.xfrName(d_target);
  244. )
  245. SOARecordContent::SOARecordContent(const DNSName& mname, const DNSName& rname, const struct soatimes& st)
  246. : d_mname(mname), d_rname(rname), d_st(st)
  247. {
  248. }
  249. boilerplate_conv(SOA, QType::SOA,
  250. conv.xfrName(d_mname, true);
  251. conv.xfrName(d_rname, true);
  252. conv.xfr32BitInt(d_st.serial);
  253. conv.xfr32BitInt(d_st.refresh);
  254. conv.xfr32BitInt(d_st.retry);
  255. conv.xfr32BitInt(d_st.expire);
  256. conv.xfr32BitInt(d_st.minimum);
  257. );
  258. #undef KEY
  259. boilerplate_conv(KEY, QType::KEY,
  260. conv.xfr16BitInt(d_flags);
  261. conv.xfr8BitInt(d_protocol);
  262. conv.xfr8BitInt(d_algorithm);
  263. conv.xfrBlob(d_certificate);
  264. );
  265. boilerplate_conv(CERT, 37,
  266. conv.xfr16BitInt(d_type);
  267. if (d_type == 0) throw MOADNSException("CERT type 0 is reserved");
  268. conv.xfr16BitInt(d_tag);
  269. conv.xfr8BitInt(d_algorithm);
  270. conv.xfrBlob(d_certificate);
  271. )
  272. boilerplate_conv(TLSA, 52,
  273. conv.xfr8BitInt(d_certusage);
  274. conv.xfr8BitInt(d_selector);
  275. conv.xfr8BitInt(d_matchtype);
  276. conv.xfrHexBlob(d_cert, true);
  277. )
  278. boilerplate_conv(OPENPGPKEY, 61,
  279. conv.xfrBlob(d_keyring);
  280. )
  281. boilerplate_conv(SMIMEA, 53,
  282. conv.xfr8BitInt(d_certusage);
  283. conv.xfr8BitInt(d_selector);
  284. conv.xfr8BitInt(d_matchtype);
  285. conv.xfrHexBlob(d_cert, true);
  286. )
  287. DSRecordContent::DSRecordContent() {}
  288. boilerplate_conv(DS, 43,
  289. conv.xfr16BitInt(d_tag);
  290. conv.xfr8BitInt(d_algorithm);
  291. conv.xfr8BitInt(d_digesttype);
  292. conv.xfrHexBlob(d_digest, true); // keep reading across spaces
  293. )
  294. CDSRecordContent::CDSRecordContent() {}
  295. boilerplate_conv(CDS, 59,
  296. conv.xfr16BitInt(d_tag);
  297. conv.xfr8BitInt(d_algorithm);
  298. conv.xfr8BitInt(d_digesttype);
  299. conv.xfrHexBlob(d_digest, true); // keep reading across spaces
  300. )
  301. DLVRecordContent::DLVRecordContent() {}
  302. boilerplate_conv(DLV,32769 ,
  303. conv.xfr16BitInt(d_tag);
  304. conv.xfr8BitInt(d_algorithm);
  305. conv.xfr8BitInt(d_digesttype);
  306. conv.xfrHexBlob(d_digest, true); // keep reading across spaces
  307. )
  308. boilerplate_conv(SSHFP, 44,
  309. conv.xfr8BitInt(d_algorithm);
  310. conv.xfr8BitInt(d_fptype);
  311. conv.xfrHexBlob(d_fingerprint, true);
  312. )
  313. boilerplate_conv(RRSIG, 46,
  314. conv.xfrType(d_type);
  315. conv.xfr8BitInt(d_algorithm);
  316. conv.xfr8BitInt(d_labels);
  317. conv.xfr32BitInt(d_originalttl);
  318. conv.xfrTime(d_sigexpire);
  319. conv.xfrTime(d_siginception);
  320. conv.xfr16BitInt(d_tag);
  321. conv.xfrName(d_signer);
  322. conv.xfrBlob(d_signature);
  323. )
  324. RRSIGRecordContent::RRSIGRecordContent() {}
  325. boilerplate_conv(DNSKEY, 48,
  326. conv.xfr16BitInt(d_flags);
  327. conv.xfr8BitInt(d_protocol);
  328. conv.xfr8BitInt(d_algorithm);
  329. conv.xfrBlob(d_key);
  330. )
  331. DNSKEYRecordContent::DNSKEYRecordContent() {}
  332. boilerplate_conv(CDNSKEY, 60,
  333. conv.xfr16BitInt(d_flags);
  334. conv.xfr8BitInt(d_protocol);
  335. conv.xfr8BitInt(d_algorithm);
  336. conv.xfrBlob(d_key);
  337. )
  338. CDNSKEYRecordContent::CDNSKEYRecordContent() {}
  339. boilerplate_conv(RKEY, 57,
  340. conv.xfr16BitInt(d_flags);
  341. conv.xfr8BitInt(d_protocol);
  342. conv.xfr8BitInt(d_algorithm);
  343. conv.xfrBlob(d_key);
  344. )
  345. RKEYRecordContent::RKEYRecordContent() {}
  346. /* EUI48 start */
  347. void EUI48RecordContent::report(void)
  348. {
  349. regist(1, QType::EUI48, &make, &make, "EUI48");
  350. }
  351. std::shared_ptr<DNSRecordContent> EUI48RecordContent::make(const DNSRecord &dr, PacketReader& pr)
  352. {
  353. if(dr.d_clen!=6)
  354. throw MOADNSException("Wrong size for EUI48 record");
  355. auto ret=std::make_shared<EUI48RecordContent>();
  356. pr.copyRecord((uint8_t*) &ret->d_eui48, 6);
  357. return ret;
  358. }
  359. std::shared_ptr<DNSRecordContent> EUI48RecordContent::make(const string& zone)
  360. {
  361. // try to parse
  362. auto ret=std::make_shared<EUI48RecordContent>();
  363. // format is 6 hex bytes and dashes
  364. if (sscanf(zone.c_str(), "%2hhx-%2hhx-%2hhx-%2hhx-%2hhx-%2hhx",
  365. ret->d_eui48, ret->d_eui48+1, ret->d_eui48+2,
  366. ret->d_eui48+3, ret->d_eui48+4, ret->d_eui48+5) != 6) {
  367. throw MOADNSException("Asked to encode '"+zone+"' as an EUI48 address, but does not parse");
  368. }
  369. return ret;
  370. }
  371. void EUI48RecordContent::toPacket(DNSPacketWriter& pw)
  372. {
  373. string blob(d_eui48, d_eui48+6);
  374. pw.xfrBlob(blob);
  375. }
  376. string EUI48RecordContent::getZoneRepresentation(bool noDot) const
  377. {
  378. char tmp[18];
  379. snprintf(tmp,sizeof(tmp),"%02x-%02x-%02x-%02x-%02x-%02x",
  380. d_eui48[0], d_eui48[1], d_eui48[2],
  381. d_eui48[3], d_eui48[4], d_eui48[5]);
  382. return tmp;
  383. }
  384. /* EUI48 end */
  385. /* EUI64 start */
  386. void EUI64RecordContent::report(void)
  387. {
  388. regist(1, QType::EUI64, &make, &make, "EUI64");
  389. }
  390. std::shared_ptr<DNSRecordContent> EUI64RecordContent::make(const DNSRecord &dr, PacketReader& pr)
  391. {
  392. if(dr.d_clen!=8)
  393. throw MOADNSException("Wrong size for EUI64 record");
  394. auto ret=std::make_shared<EUI64RecordContent>();
  395. pr.copyRecord((uint8_t*) &ret->d_eui64, 8);
  396. return ret;
  397. }
  398. std::shared_ptr<DNSRecordContent> EUI64RecordContent::make(const string& zone)
  399. {
  400. // try to parse
  401. auto ret=std::make_shared<EUI64RecordContent>();
  402. // format is 8 hex bytes and dashes
  403. if (sscanf(zone.c_str(), "%2hhx-%2hhx-%2hhx-%2hhx-%2hhx-%2hhx-%2hhx-%2hhx",
  404. ret->d_eui64, ret->d_eui64+1, ret->d_eui64+2,
  405. ret->d_eui64+3, ret->d_eui64+4, ret->d_eui64+5,
  406. ret->d_eui64+6, ret->d_eui64+7) != 8) {
  407. throw MOADNSException("Asked to encode '"+zone+"' as an EUI64 address, but does not parse");
  408. }
  409. return ret;
  410. }
  411. void EUI64RecordContent::toPacket(DNSPacketWriter& pw)
  412. {
  413. string blob(d_eui64, d_eui64+8);
  414. pw.xfrBlob(blob);
  415. }
  416. string EUI64RecordContent::getZoneRepresentation(bool noDot) const
  417. {
  418. char tmp[24];
  419. snprintf(tmp,sizeof(tmp),"%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x",
  420. d_eui64[0], d_eui64[1], d_eui64[2],
  421. d_eui64[3], d_eui64[4], d_eui64[5],
  422. d_eui64[6], d_eui64[7]);
  423. return tmp;
  424. }
  425. /* EUI64 end */
  426. /* APL start */
  427. /* https://tools.ietf.org/html/rfc3123 */
  428. void APLRecordContent::report(void)
  429. {
  430. regist(1, QType::APL, &make, &make, "APL");
  431. }
  432. // Parse incoming packets (e.g. nsupdate)
  433. std::shared_ptr<DNSRecordContent> APLRecordContent::make(const DNSRecord &dr, PacketReader& pr) {
  434. uint8_t temp;
  435. APLRDataElement ard;
  436. size_t processed = 0;
  437. auto ret=std::make_shared<APLRecordContent>();
  438. while (processed<dr.d_clen) {
  439. pr.xfr16BitInt(ard.d_family);
  440. pr.xfr8BitInt(ard.d_prefix);
  441. pr.xfr8BitInt(temp);
  442. ard.d_n = (temp & 128) >> 7;
  443. ard.d_afdlength = temp & 127;
  444. if (ard.d_family == APL_FAMILY_IPV4) {
  445. if (ard.d_afdlength > 4) {
  446. throw MOADNSException("Invalid IP length for IPv4 APL");
  447. }
  448. memset(ard.d_ip.d_ip4, 0, sizeof(ard.d_ip.d_ip4));
  449. for (u_int i=0; i < ard.d_afdlength; i++)
  450. pr.xfr8BitInt(ard.d_ip.d_ip4[i]);
  451. } else if (ard.d_family == APL_FAMILY_IPV6) {
  452. if (ard.d_afdlength > 16) {
  453. throw MOADNSException("Invalid IP length for IPv6 APL");
  454. }
  455. memset(ard.d_ip.d_ip6, 0, sizeof(ard.d_ip.d_ip6));
  456. for (u_int i=0; i < ard.d_afdlength; i++)
  457. pr.xfr8BitInt(ard.d_ip.d_ip6[i]);
  458. } else
  459. throw MOADNSException("Unknown family for APL record");
  460. processed += 4 + ard.d_afdlength;
  461. ret->aplrdata.push_back(ard);
  462. }
  463. return ret;
  464. }
  465. // Parse a single APL <apitem>
  466. APLRDataElement APLRecordContent::parseAPLElement(const string& element) {
  467. string record;
  468. Netmask nm;
  469. unsigned int bytes;
  470. bool done_trimming;
  471. APLRDataElement ard;
  472. // Parse the optional leading ! (negate)
  473. if (element.at(0) == '!') {
  474. ard.d_n = true;
  475. record = element.substr(1, element.length()-1);
  476. } else {
  477. ard.d_n = false;
  478. record = element;
  479. }
  480. if (record.find("/") == string::npos) { // Required by RFC section 5
  481. throw MOADNSException("Asked to decode '"+element+"' as an APL record, but missing subnet mask");
  482. }
  483. if (record.find("1:", 0) == 0) { // IPv4
  484. uint32_t v4ip;
  485. ard.d_family = APL_FAMILY_IPV4;
  486. // Ensure that a mask is provided
  487. // Read IPv4 string into a Netmask object
  488. nm = Netmask(record.substr(2, record.length() - 2));
  489. ard.d_prefix = nm.getBits();
  490. if (nm.getNetwork().isIPv4() == 0)
  491. throw MOADNSException("Asked to decode '"+element+"' as an APL v4 record");
  492. // Section 4.1 of RFC 3123 (don't send trailing "0" bytes)
  493. // Copy data; using array of bytes since we might end up truncating them in the packet
  494. v4ip = ntohl(nm.getNetwork().sin4.sin_addr.s_addr);
  495. memset(ard.d_ip.d_ip4, 0, sizeof(ard.d_ip.d_ip4));
  496. bytes = 4; // Start by assuming we'll send 4 bytes
  497. done_trimming = false;
  498. for (int i=0; i<4; i++) {
  499. ard.d_ip.d_ip4[3-i] = (v4ip & 255);
  500. // Remove trailing "0" bytes from packet and update length
  501. if ((v4ip & 255) == 0 and !done_trimming) {
  502. bytes--;
  503. } else {
  504. done_trimming = true;
  505. }
  506. v4ip = v4ip >> 8;
  507. }
  508. ard.d_afdlength = bytes;
  509. } else if (record.find("2:", 0) == 0) { // IPv6
  510. ard.d_family = APL_FAMILY_IPV6;
  511. // Parse IPv6 string into a Netmask object
  512. nm = Netmask(record.substr(2, record.length() - 2));
  513. ard.d_prefix = nm.getBits();
  514. if (nm.getNetwork().isIPv6() == 0)
  515. throw MOADNSException("Asked to decode '"+element+"' as an APL v6 record");
  516. // Section 4.2 of RFC 3123 (don't send trailing "0" bytes)
  517. // Remove trailing "0" bytes from packet and reduce length
  518. memset(ard.d_ip.d_ip6, 0, sizeof(ard.d_ip.d_ip6));
  519. bytes = 16; // Start by assuming we'll send 16 bytes
  520. done_trimming = false;
  521. for (int i=0; i<16; i++) {
  522. ard.d_ip.d_ip6[15-i] = nm.getNetwork().sin6.sin6_addr.s6_addr[15-i];
  523. if (nm.getNetwork().sin6.sin6_addr.s6_addr[15-i] == 0 and !done_trimming) {
  524. // trailing 0 byte, update length
  525. bytes--;
  526. } else {
  527. done_trimming = true;
  528. }
  529. }
  530. ard.d_afdlength = bytes;
  531. } else {
  532. throw MOADNSException("Asked to encode '"+element+"' as an IPv6 APL record but got unknown Address Family");
  533. }
  534. return ard;
  535. }
  536. // Parse backend record (0, 1 or more <apitem>)
  537. std::shared_ptr<DNSRecordContent> APLRecordContent::make(const string& zone) {
  538. APLRDataElement ard;
  539. vector<string> elements;
  540. auto ret=std::make_shared<APLRecordContent>();
  541. boost::split(elements, zone, boost::is_any_of(" "));
  542. for (std::vector<std::string>::iterator elem = elements.begin() ; elem != elements.end(); ++elem) {
  543. if (!elem->empty()) {
  544. ard = ret->parseAPLElement(*elem);
  545. ret->aplrdata.push_back(ard);
  546. }
  547. }
  548. return ret;
  549. }
  550. // DNSRecord to Packet conversion
  551. void APLRecordContent::toPacket(DNSPacketWriter& pw) {
  552. for (std::vector<APLRDataElement>::iterator ard = aplrdata.begin() ; ard != aplrdata.end(); ++ard) {
  553. pw.xfr16BitInt(ard->d_family);
  554. pw.xfr8BitInt(ard->d_prefix);
  555. pw.xfr8BitInt((ard->d_n << 7) + ard->d_afdlength);
  556. if (ard->d_family == APL_FAMILY_IPV4) {
  557. for (int i=0; i<ard->d_afdlength; i++) {
  558. pw.xfr8BitInt(ard->d_ip.d_ip4[i]);
  559. }
  560. } else if (ard->d_family == APL_FAMILY_IPV6) {
  561. for (int i=0; i<ard->d_afdlength; i++) {
  562. pw.xfr8BitInt(ard->d_ip.d_ip6[i]);
  563. }
  564. }
  565. }
  566. }
  567. // Decode record into string
  568. string APLRecordContent::getZoneRepresentation(bool noDot) const {
  569. string s_n, s_family, output;
  570. ComboAddress ca;
  571. Netmask nm;
  572. output = "";
  573. for (std::vector<APLRDataElement>::const_iterator ard = aplrdata.begin() ; ard != aplrdata.end(); ++ard) {
  574. // Negation flag
  575. if (ard->d_n) {
  576. s_n = "!";
  577. } else {
  578. s_n = "";
  579. }
  580. if (ard->d_family == APL_FAMILY_IPV4) { // IPv4
  581. s_family = std::to_string(APL_FAMILY_IPV4);
  582. ca = ComboAddress();
  583. memcpy(&ca.sin4.sin_addr.s_addr, ard->d_ip.d_ip4, sizeof(ca.sin4.sin_addr.s_addr));
  584. } else if (ard->d_family == APL_FAMILY_IPV6) { // IPv6
  585. s_family = std::to_string(APL_FAMILY_IPV6);
  586. ca = ComboAddress();
  587. ca.sin4.sin_family = AF_INET6;
  588. memset(&ca.sin6.sin6_addr.s6_addr, 0, sizeof(ca.sin6.sin6_addr.s6_addr));
  589. memcpy(&ca.sin6.sin6_addr.s6_addr, ard->d_ip.d_ip6, ard->d_afdlength);
  590. } else {
  591. throw MOADNSException("Asked to decode APL record but got unknown Address Family");
  592. }
  593. nm = Netmask(ca, ard->d_prefix);
  594. output += s_n + s_family + ":" + nm.toString();
  595. if (std::next(ard) != aplrdata.end())
  596. output += " ";
  597. }
  598. return output;
  599. }
  600. /* APL end */
  601. boilerplate_conv(TKEY, QType::TKEY,
  602. conv.xfrName(d_algo);
  603. conv.xfr32BitInt(d_inception);
  604. conv.xfr32BitInt(d_expiration);
  605. conv.xfr16BitInt(d_mode);
  606. conv.xfr16BitInt(d_error);
  607. conv.xfr16BitInt(d_keysize);
  608. if (d_keysize>0) conv.xfrBlobNoSpaces(d_key, d_keysize);
  609. conv.xfr16BitInt(d_othersize);
  610. if (d_othersize>0) conv.xfrBlobNoSpaces(d_other, d_othersize);
  611. )
  612. TKEYRecordContent::TKEYRecordContent() { d_othersize = 0; } // fix CID#1288932
  613. boilerplate_conv(URI, QType::URI,
  614. conv.xfr16BitInt(d_priority);
  615. conv.xfr16BitInt(d_weight);
  616. conv.xfrText(d_target, true, false);
  617. )
  618. boilerplate_conv(CAA, QType::CAA,
  619. conv.xfr8BitInt(d_flags);
  620. conv.xfrUnquotedText(d_tag, true);
  621. conv.xfrText(d_value, true, false); /* no lenField */
  622. )
  623. static uint16_t makeTag(const std::string& data)
  624. {
  625. const unsigned char* key=(const unsigned char*)data.c_str();
  626. unsigned int keysize=data.length();
  627. unsigned long ac; /* assumed to be 32 bits or larger */
  628. unsigned int i; /* loop index */
  629. for ( ac = 0, i = 0; i < keysize; ++i )
  630. ac += (i & 1) ? key[i] : key[i] << 8;
  631. ac += (ac >> 16) & 0xFFFF;
  632. return ac & 0xFFFF;
  633. }
  634. uint16_t DNSKEYRecordContent::getTag() const
  635. {
  636. DNSKEYRecordContent tmp(*this);
  637. return makeTag(tmp.serialize(DNSName())); // this can't be const for some reason
  638. }
  639. uint16_t DNSKEYRecordContent::getTag()
  640. {
  641. return makeTag(this->serialize(DNSName()));
  642. }
  643. /*
  644. * Fills `eo` by parsing the EDNS(0) OPT RR (RFC 6891)
  645. */
  646. bool getEDNSOpts(const MOADNSParser& mdp, EDNSOpts* eo)
  647. {
  648. eo->d_extFlags=0;
  649. if(mdp.d_header.arcount && !mdp.d_answers.empty()) {
  650. for(const MOADNSParser::answers_t::value_type& val : mdp.d_answers) {
  651. if(val.first.d_place == DNSResourceRecord::ADDITIONAL && val.first.d_type == QType::OPT) {
  652. eo->d_packetsize=val.first.d_class;
  653. EDNS0Record stuff;
  654. uint32_t ttl=ntohl(val.first.d_ttl);
  655. static_assert(sizeof(EDNS0Record) == sizeof(uint32_t), "sizeof(EDNS0Record) must match sizeof(uint32_t)");
  656. memcpy(&stuff, &ttl, sizeof(stuff));
  657. eo->d_extRCode=stuff.extRCode;
  658. eo->d_version=stuff.version;
  659. eo->d_extFlags = ntohs(stuff.extFlags);
  660. auto orc = getRR<OPTRecordContent>(val.first);
  661. if(orc == nullptr)
  662. return false;
  663. orc->getData(eo->d_options);
  664. return true;
  665. }
  666. }
  667. }
  668. return false;
  669. }
  670. DNSRecord makeOpt(const uint16_t udpsize, const uint16_t extRCode, const uint16_t extFlags)
  671. {
  672. EDNS0Record stuff;
  673. stuff.extRCode=0;
  674. stuff.version=0;
  675. stuff.extFlags=htons(extFlags);
  676. DNSRecord dr;
  677. static_assert(sizeof(EDNS0Record) == sizeof(dr.d_ttl), "sizeof(EDNS0Record) must match sizeof(DNSRecord.d_ttl)");
  678. memcpy(&dr.d_ttl, &stuff, sizeof(stuff));
  679. dr.d_ttl=ntohl(dr.d_ttl);
  680. dr.d_name=g_rootdnsname;
  681. dr.d_type = QType::OPT;
  682. dr.d_class=udpsize;
  683. dr.d_place=DNSResourceRecord::ADDITIONAL;
  684. dr.d_content = std::make_shared<OPTRecordContent>();
  685. // if we ever do options, I think we stuff them into OPTRecordContent::data
  686. return dr;
  687. }
  688. void reportBasicTypes()
  689. {
  690. ARecordContent::report();
  691. AAAARecordContent::report();
  692. NSRecordContent::report();
  693. CNAMERecordContent::report();
  694. MXRecordContent::report();
  695. SOARecordContent::report();
  696. SRVRecordContent::report();
  697. PTRRecordContent::report();
  698. DNSRecordContent::regist(QClass::CHAOS, QType::TXT, &TXTRecordContent::make, &TXTRecordContent::make, "TXT");
  699. TXTRecordContent::report();
  700. #ifdef HAVE_LUA_RECORDS
  701. LUARecordContent::report();
  702. #endif
  703. DNSRecordContent::regist(QClass::IN, QType::ANY, 0, 0, "ANY");
  704. DNSRecordContent::regist(QClass::IN, QType::AXFR, 0, 0, "AXFR");
  705. DNSRecordContent::regist(QClass::IN, QType::IXFR, 0, 0, "IXFR");
  706. }
  707. void reportOtherTypes()
  708. {
  709. MBRecordContent::report();
  710. MGRecordContent::report();
  711. MRRecordContent::report();
  712. AFSDBRecordContent::report();
  713. DNAMERecordContent::report();
  714. ALIASRecordContent::report();
  715. SPFRecordContent::report();
  716. NAPTRRecordContent::report();
  717. KXRecordContent::report();
  718. LOCRecordContent::report();
  719. ENTRecordContent::report();
  720. HINFORecordContent::report();
  721. RPRecordContent::report();
  722. KEYRecordContent::report();
  723. DNSKEYRecordContent::report();
  724. DHCIDRecordContent::report();
  725. CDNSKEYRecordContent::report();
  726. RKEYRecordContent::report();
  727. RRSIGRecordContent::report();
  728. DSRecordContent::report();
  729. CDSRecordContent::report();
  730. SSHFPRecordContent::report();
  731. CERTRecordContent::report();
  732. NSECRecordContent::report();
  733. NSEC3RecordContent::report();
  734. NSEC3PARAMRecordContent::report();
  735. TLSARecordContent::report();
  736. SMIMEARecordContent::report();
  737. OPENPGPKEYRecordContent::report();
  738. DLVRecordContent::report();
  739. DNSRecordContent::regist(QClass::ANY, QType::TSIG, &TSIGRecordContent::make, &TSIGRecordContent::make, "TSIG");
  740. DNSRecordContent::regist(QClass::ANY, QType::TKEY, &TKEYRecordContent::make, &TKEYRecordContent::make, "TKEY");
  741. //TSIGRecordContent::report();
  742. OPTRecordContent::report();
  743. EUI48RecordContent::report();
  744. EUI64RecordContent::report();
  745. MINFORecordContent::report();
  746. URIRecordContent::report();
  747. CAARecordContent::report();
  748. APLRecordContent::report();
  749. }
  750. void reportAllTypes()
  751. {
  752. reportBasicTypes();
  753. reportOtherTypes();
  754. }
  755. ComboAddress getAddr(const DNSRecord& dr, uint16_t defport)
  756. {
  757. if(auto addr=getRR<ARecordContent>(dr)) {
  758. return addr->getCA(defport);
  759. }
  760. else
  761. return getRR<AAAARecordContent>(dr)->getCA(defport);
  762. }
  763. /**
  764. * Check if the DNSNames that should be hostnames, are hostnames
  765. */
  766. void checkHostnameCorrectness(const DNSResourceRecord& rr)
  767. {
  768. if (rr.qtype.getCode() == QType::NS || rr.qtype.getCode() == QType::MX || rr.qtype.getCode() == QType::SRV) {
  769. DNSName toCheck;
  770. if (rr.qtype.getCode() == QType::SRV) {
  771. vector<string> parts;
  772. stringtok(parts, rr.getZoneRepresentation());
  773. if (parts.size() == 4) toCheck = DNSName(parts[3]);
  774. } else if (rr.qtype.getCode() == QType::MX) {
  775. vector<string> parts;
  776. stringtok(parts, rr.getZoneRepresentation());
  777. if (parts.size() == 2) toCheck = DNSName(parts[1]);
  778. } else {
  779. toCheck = DNSName(rr.content);
  780. }
  781. if (toCheck.empty()) {
  782. throw std::runtime_error("unable to extract hostname from content");
  783. }
  784. else if ((rr.qtype.getCode() == QType::MX || rr.qtype.getCode() == QType::SRV) && toCheck == g_rootdnsname) {
  785. // allow null MX/SRV
  786. } else if(!toCheck.isHostname()) {
  787. throw std::runtime_error(boost::str(boost::format("non-hostname content %s") % toCheck.toString()));
  788. }
  789. }
  790. }
  791. #if 0
  792. static struct Reporter
  793. {
  794. Reporter()
  795. {
  796. reportAllTypes();
  797. }
  798. } reporter __attribute__((init_priority(65535)));
  799. #endif