]>
Commit | Line | Data |
---|---|---|
4192ca66 | 1 | /* |
12471842 PL |
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 | */ | |
870a0fe4 AT |
22 | #ifdef HAVE_CONFIG_H |
23 | #include "config.h" | |
24 | #endif | |
705f31ae | 25 | #include "utility.hh" |
4192ca66 | 26 | #include "dnsrecords.hh" |
447e0cff | 27 | #include "iputils.hh" |
fa8fd4d2 | 28 | |
2770fad0 | 29 | |
f7a69a4c RA |
30 | void DNSResourceRecord::setContent(const string &cont) { |
31 | content = cont; | |
b9bafae0 KM |
32 | switch(qtype.getCode()) { |
33 | case QType::SRV: | |
34 | case QType::MX: | |
35 | if (content.size() >= 2 && *(content.rbegin()+1) == ' ') | |
36 | return; | |
37 | case QType::CNAME: | |
165e5695 | 38 | case QType::DNAME: |
b9bafae0 | 39 | case QType::NS: |
b2e37c01 | 40 | case QType::PTR: |
b9bafae0 KM |
41 | if(!content.empty()) |
42 | boost::erase_tail(content, 1); | |
f7a69a4c RA |
43 | } |
44 | } | |
45 | ||
f21fc0aa | 46 | string DNSResourceRecord::getZoneRepresentation(bool noDot) const { |
f7a69a4c | 47 | ostringstream ret; |
65bf25b9 PD |
48 | vector<string> parts; |
49 | string last; | |
50 | ||
f7a69a4c RA |
51 | switch(qtype.getCode()) { |
52 | case QType::SRV: | |
53 | case QType::MX: | |
65bf25b9 | 54 | stringtok(parts, content); |
7f42bc91 PD |
55 | if (!parts.size()) |
56 | return ""; | |
65bf25b9 PD |
57 | last = *parts.rbegin(); |
58 | ret << content; | |
59 | if (last == ".") | |
60 | break; | |
61 | if (*(last.rbegin()) != '.' && !noDot) | |
62 | ret << "."; | |
63 | break; | |
f7a69a4c | 64 | case QType::CNAME: |
165e5695 | 65 | case QType::DNAME: |
f7a69a4c | 66 | case QType::NS: |
b2e37c01 | 67 | case QType::PTR: |
65bf25b9 | 68 | ret<<content; |
726dc0b2 PD |
69 | if (*(content.rbegin()) != '.' && !noDot) |
70 | ret<<"."; | |
b9bafae0 | 71 | break; |
f7a69a4c RA |
72 | default: |
73 | ret<<content; | |
74 | break; | |
75 | } | |
76 | return ret.str(); | |
77 | } | |
78 | ||
79 | bool DNSResourceRecord::operator==(const DNSResourceRecord& rhs) | |
80 | { | |
81 | string lcontent=toLower(content); | |
82 | string rcontent=toLower(rhs.content); | |
914353ca | 83 | |
914353ca | 84 | return |
675fa24c PD |
85 | tie(qname, qtype, lcontent, ttl) == |
86 | tie(rhs.qname, rhs.qtype, rcontent, rhs.ttl); | |
f7a69a4c RA |
87 | } |
88 | ||
3bb50daa | 89 | boilerplate_conv(A, QType::A, conv.xfrIP(d_ip)); |
8c1c9170 | 90 | |
5a1f298f | 91 | ARecordContent::ARecordContent(uint32_t ip) |
efb265e3 BH |
92 | { |
93 | d_ip = ip; | |
94 | } | |
95 | ||
5a1f298f | 96 | ARecordContent::ARecordContent(const ComboAddress& ca) |
447e0cff | 97 | { |
98 | d_ip = ca.sin4.sin_addr.s_addr; | |
99 | } | |
100 | ||
5a1f298f | 101 | AAAARecordContent::AAAARecordContent(const ComboAddress& ca) |
748eff9f | 102 | { |
447e0cff | 103 | d_ip6.assign((const char*)ca.sin6.sin6_addr.s6_addr, 16); |
748eff9f BH |
104 | } |
105 | ||
447e0cff | 106 | |
f4352636 | 107 | |
447e0cff | 108 | ComboAddress ARecordContent::getCA(int port) const |
109 | { | |
110 | ComboAddress ret; | |
111 | ret.sin4.sin_family=AF_INET; | |
112 | ret.sin4.sin_port=htons(port); | |
a683e8bd | 113 | memcpy(&ret.sin4.sin_addr.s_addr, &d_ip, sizeof(ret.sin4.sin_addr.s_addr)); |
447e0cff | 114 | return ret; |
115 | } | |
116 | ||
117 | ComboAddress AAAARecordContent::getCA(int port) const | |
118 | { | |
119 | ComboAddress ret; | |
d38e2ba9 | 120 | ret.reset(); |
447e0cff | 121 | |
122 | ret.sin4.sin_family=AF_INET6; | |
123 | ret.sin6.sin6_port = htons(port); | |
a683e8bd | 124 | memcpy(&ret.sin6.sin6_addr.s6_addr, d_ip6.c_str(), sizeof(ret.sin6.sin6_addr.s6_addr)); |
447e0cff | 125 | return ret; |
126 | } | |
127 | ||
128 | ||
2770fad0 BH |
129 | void ARecordContent::doRecordCheck(const DNSRecord& dr) |
130 | { | |
131 | if(dr.d_clen!=4) | |
335da0ba | 132 | throw MOADNSException("Wrong size for A record ("+std::to_string(dr.d_clen)+")"); |
a0a276c2 | 133 | } |
ff6a1e7b | 134 | |
3bb50daa | 135 | boilerplate_conv(AAAA, QType::AAAA, conv.xfrIP6(d_ip6); ); |
9d9c52ef | 136 | |
ad8fa726 PD |
137 | boilerplate_conv(NS, QType::NS, conv.xfrName(d_content, true)); |
138 | boilerplate_conv(PTR, QType::PTR, conv.xfrName(d_content, true)); | |
139 | boilerplate_conv(CNAME, QType::CNAME, conv.xfrName(d_content, true)); | |
85c6d90e | 140 | boilerplate_conv(ALIAS, QType::ALIAS, conv.xfrName(d_content, false)); |
ad8fa726 | 141 | boilerplate_conv(DNAME, QType::DNAME, conv.xfrName(d_content)); |
fa552262 CHB |
142 | boilerplate_conv(MB, QType::MB, conv.xfrName(d_madname, true)); |
143 | boilerplate_conv(MG, QType::MG, conv.xfrName(d_mgmname, true)); | |
ad8fa726 PD |
144 | boilerplate_conv(MR, QType::MR, conv.xfrName(d_alias, true)); |
145 | boilerplate_conv(MINFO, QType::MINFO, conv.xfrName(d_rmailbx, true); conv.xfrName(d_emailbx, true)); | |
3bb50daa | 146 | boilerplate_conv(TXT, QType::TXT, conv.xfrText(d_text, true)); |
8900e2e3 | 147 | #ifdef HAVE_LUA_RECORDS |
5dbd408c | 148 | boilerplate_conv(LUA, QType::LUA, conv.xfrType(d_type); conv.xfrText(d_code, true)); |
8900e2e3 | 149 | #endif |
acedb99e | 150 | boilerplate_conv(ENT, 0, ); |
ef6a78d5 | 151 | boilerplate_conv(SPF, 99, conv.xfrText(d_text, true)); |
3bb50daa | 152 | boilerplate_conv(HINFO, QType::HINFO, conv.xfrText(d_cpu); conv.xfrText(d_host)); |
ff6a1e7b | 153 | |
3bb50daa | 154 | boilerplate_conv(RP, QType::RP, |
ad8fa726 PD |
155 | conv.xfrName(d_mbox); |
156 | conv.xfrName(d_info) | |
232f0877 | 157 | ); |
ff6a1e7b | 158 | |
ff6a1e7b | 159 | |
3bb50daa | 160 | boilerplate_conv(OPT, QType::OPT, |
232f0877 CH |
161 | conv.xfrBlob(d_data) |
162 | ); | |
878435ce | 163 | |
8900e2e3 | 164 | #ifdef HAVE_LUA_RECORDS |
5f7d5c56 | 165 | string LUARecordContent::getCode() |
166 | { | |
167 | // in d_code, series of "part1" "part2" | |
168 | vector<string> parts; | |
169 | stringtok(parts, d_code, "\""); | |
170 | string ret; | |
171 | for(const auto& p : parts) { | |
172 | ret += p; | |
173 | ret.append(1, ' '); | |
174 | } | |
175 | return ret; | |
176 | } | |
8900e2e3 | 177 | #endif |
5f7d5c56 | 178 | |
7f7b8d55 BH |
179 | void OPTRecordContent::getData(vector<pair<uint16_t, string> >& options) |
180 | { | |
181 | string::size_type pos=0; | |
182 | uint16_t code, len; | |
183 | while(d_data.size() >= 4 + pos) { | |
17d6efc0 BH |
184 | code = 256 * (unsigned char)d_data[pos] + (unsigned char)d_data[pos+1]; |
185 | len = 256 * (unsigned char)d_data[pos+2] + (unsigned char)d_data[pos+3]; | |
7f7b8d55 BH |
186 | pos+=4; |
187 | ||
188 | if(pos + len > d_data.size()) | |
189 | break; | |
190 | ||
191 | string field(d_data.c_str() + pos, len); | |
192 | pos+=len; | |
7f7b8d55 BH |
193 | options.push_back(make_pair(code, field)); |
194 | } | |
195 | } | |
06ffdc52 | 196 | |
3bb50daa | 197 | boilerplate_conv(TSIG, QType::TSIG, |
ad8fa726 | 198 | conv.xfrName(d_algoName); |
232f0877 CH |
199 | conv.xfr48BitInt(d_time); |
200 | conv.xfr16BitInt(d_fudge); | |
201 | uint16_t size=d_mac.size(); | |
202 | conv.xfr16BitInt(size); | |
11c029c0 | 203 | if (size>0) conv.xfrBlobNoSpaces(d_mac, size); |
232f0877 CH |
204 | conv.xfr16BitInt(d_origID); |
205 | conv.xfr16BitInt(d_eRcode); | |
11c029c0 | 206 | size=d_otherData.size(); |
232f0877 | 207 | conv.xfr16BitInt(size); |
11c029c0 | 208 | if (size>0) conv.xfrBlobNoSpaces(d_otherData, size); |
232f0877 | 209 | ); |
06ffdc52 | 210 | |
5a1f298f | 211 | MXRecordContent::MXRecordContent(uint16_t preference, const DNSName& mxname): d_preference(preference), d_mxname(mxname) |
2770fad0 BH |
212 | { |
213 | } | |
ff6a1e7b | 214 | |
3bb50daa | 215 | boilerplate_conv(MX, QType::MX, |
232f0877 | 216 | conv.xfr16BitInt(d_preference); |
ad8fa726 | 217 | conv.xfrName(d_mxname, true); |
232f0877 | 218 | ) |
ff6a1e7b | 219 | |
3bb50daa | 220 | boilerplate_conv(KX, QType::KX, |
232f0877 | 221 | conv.xfr16BitInt(d_preference); |
ad8fa726 | 222 | conv.xfrName(d_exchanger, false); |
232f0877 | 223 | ) |
9fd71f2e | 224 | |
3bb50daa | 225 | boilerplate_conv(IPSECKEY, QType::IPSECKEY, |
1cafb958 AT |
226 | conv.xfr8BitInt(d_preference); |
227 | conv.xfr8BitInt(d_gatewaytype); | |
228 | conv.xfr8BitInt(d_algorithm); | |
229 | ||
230 | // now we need to determine values | |
231 | switch(d_gatewaytype) { | |
232 | case 0: // NO KEY | |
233 | break; | |
234 | case 1: // IPv4 GW | |
235 | conv.xfrIP(d_ip4); | |
236 | break; | |
237 | case 2: // IPv6 GW | |
238 | conv.xfrIP6(d_ip6); | |
239 | break; | |
240 | case 3: // DNS label | |
ad8fa726 | 241 | conv.xfrName(d_gateway, false); |
1cafb958 AT |
242 | break; |
243 | default: | |
244 | throw MOADNSException("Parsing record content: invalid gateway type"); | |
245 | }; | |
246 | ||
247 | switch(d_algorithm) { | |
248 | case 0: | |
249 | break; | |
250 | case 1: | |
251 | case 2: | |
252 | conv.xfrBlob(d_publickey); | |
253 | break; | |
254 | default: | |
255 | throw MOADNSException("Parsing record content: invalid algorithm type"); | |
74b3a069 AT |
256 | } |
257 | ) | |
9fd71f2e BH |
258 | |
259 | boilerplate_conv(DHCID, 49, | |
232f0877 CH |
260 | conv.xfrBlob(d_content); |
261 | ) | |
9fd71f2e BH |
262 | |
263 | ||
3bb50daa | 264 | boilerplate_conv(AFSDB, QType::AFSDB, |
232f0877 | 265 | conv.xfr16BitInt(d_subtype); |
ad8fa726 | 266 | conv.xfrName(d_hostname); |
232f0877 | 267 | ) |
37f47031 | 268 | |
ff6a1e7b | 269 | |
3bb50daa | 270 | boilerplate_conv(NAPTR, QType::NAPTR, |
232f0877 CH |
271 | conv.xfr16BitInt(d_order); conv.xfr16BitInt(d_preference); |
272 | conv.xfrText(d_flags); conv.xfrText(d_services); conv.xfrText(d_regexp); | |
ad8fa726 | 273 | conv.xfrName(d_replacement); |
232f0877 | 274 | ) |
8c1c9170 | 275 | |
ff6a1e7b | 276 | |
4a51ff72 | 277 | SRVRecordContent::SRVRecordContent(uint16_t preference, uint16_t weight, uint16_t port, const DNSName& target) |
5a1f298f | 278 | : d_weight(weight), d_port(port), d_target(target), d_preference(preference) |
2770fad0 | 279 | {} |
ff6a1e7b | 280 | |
3bb50daa | 281 | boilerplate_conv(SRV, QType::SRV, |
232f0877 | 282 | conv.xfr16BitInt(d_preference); conv.xfr16BitInt(d_weight); conv.xfr16BitInt(d_port); |
ad8fa726 | 283 | conv.xfrName(d_target); |
232f0877 | 284 | ) |
9d9c52ef | 285 | |
4a51ff72 | 286 | SOARecordContent::SOARecordContent(const DNSName& mname, const DNSName& rname, const struct soatimes& st) |
c613b06f | 287 | : d_mname(mname), d_rname(rname), d_st(st) |
a0a276c2 | 288 | { |
a0a276c2 | 289 | } |
9d9c52ef | 290 | |
13f9e280 | 291 | boilerplate_conv(SOA, QType::SOA, |
ad8fa726 PD |
292 | conv.xfrName(d_mname, true); |
293 | conv.xfrName(d_rname, true); | |
232f0877 CH |
294 | conv.xfr32BitInt(d_st.serial); |
295 | conv.xfr32BitInt(d_st.refresh); | |
296 | conv.xfr32BitInt(d_st.retry); | |
297 | conv.xfr32BitInt(d_st.expire); | |
298 | conv.xfr32BitInt(d_st.minimum); | |
299 | ); | |
4b5762f1 | 300 | #undef KEY |
3bb50daa | 301 | boilerplate_conv(KEY, QType::KEY, |
232f0877 CH |
302 | conv.xfr16BitInt(d_flags); |
303 | conv.xfr8BitInt(d_protocol); | |
304 | conv.xfr8BitInt(d_algorithm); | |
305 | conv.xfrBlob(d_certificate); | |
306 | ); | |
8c1c9170 | 307 | |
2475a4fc | 308 | boilerplate_conv(CERT, 37, |
232f0877 | 309 | conv.xfr16BitInt(d_type); |
689516b3 AT |
310 | if (d_type == 0) throw MOADNSException("CERT type 0 is reserved"); |
311 | ||
232f0877 CH |
312 | conv.xfr16BitInt(d_tag); |
313 | conv.xfr8BitInt(d_algorithm); | |
689516b3 AT |
314 | conv.xfrBlob(d_certificate); |
315 | ) | |
316 | ||
2a4e06e9 | 317 | boilerplate_conv(TLSA, 52, |
232f0877 CH |
318 | conv.xfr8BitInt(d_certusage); |
319 | conv.xfr8BitInt(d_selector); | |
320 | conv.xfr8BitInt(d_matchtype); | |
321 | conv.xfrHexBlob(d_cert, true); | |
322 | ) | |
323 | ||
68066337 | 324 | boilerplate_conv(OPENPGPKEY, 61, |
e7917c06 | 325 | conv.xfrBlob(d_keyring); |
68066337 JC |
326 | ) |
327 | ||
291935bb PL |
328 | boilerplate_conv(SMIMEA, 53, |
329 | conv.xfr8BitInt(d_certusage); | |
330 | conv.xfr8BitInt(d_selector); | |
331 | conv.xfr8BitInt(d_matchtype); | |
332 | conv.xfrHexBlob(d_cert, true); | |
333 | ) | |
334 | ||
5a1f298f | 335 | DSRecordContent::DSRecordContent() {} |
8c1c9170 | 336 | boilerplate_conv(DS, 43, |
232f0877 CH |
337 | conv.xfr16BitInt(d_tag); |
338 | conv.xfr8BitInt(d_algorithm); | |
339 | conv.xfr8BitInt(d_digesttype); | |
340 | conv.xfrHexBlob(d_digest, true); // keep reading across spaces | |
341 | ) | |
8c1c9170 | 342 | |
5a1f298f | 343 | CDSRecordContent::CDSRecordContent() {} |
882de365 PL |
344 | boilerplate_conv(CDS, 59, |
345 | conv.xfr16BitInt(d_tag); | |
346 | conv.xfr8BitInt(d_algorithm); | |
347 | conv.xfr8BitInt(d_digesttype); | |
348 | conv.xfrHexBlob(d_digest, true); // keep reading across spaces | |
349 | ) | |
350 | ||
5a1f298f | 351 | DLVRecordContent::DLVRecordContent() {} |
0b55f2f5 | 352 | boilerplate_conv(DLV,32769 , |
232f0877 CH |
353 | conv.xfr16BitInt(d_tag); |
354 | conv.xfr8BitInt(d_algorithm); | |
355 | conv.xfr8BitInt(d_digesttype); | |
356 | conv.xfrHexBlob(d_digest, true); // keep reading across spaces | |
357 | ) | |
0b55f2f5 BH |
358 | |
359 | ||
a40a693b | 360 | boilerplate_conv(SSHFP, 44, |
232f0877 CH |
361 | conv.xfr8BitInt(d_algorithm); |
362 | conv.xfr8BitInt(d_fptype); | |
02ca1c5b | 363 | conv.xfrHexBlob(d_fingerprint, true); |
232f0877 | 364 | ) |
a40a693b | 365 | |
8c1c9170 | 366 | boilerplate_conv(RRSIG, 46, |
232f0877 CH |
367 | conv.xfrType(d_type); |
368 | conv.xfr8BitInt(d_algorithm); | |
369 | conv.xfr8BitInt(d_labels); | |
370 | conv.xfr32BitInt(d_originalttl); | |
371 | conv.xfrTime(d_sigexpire); | |
372 | conv.xfrTime(d_siginception); | |
373 | conv.xfr16BitInt(d_tag); | |
ad8fa726 | 374 | conv.xfrName(d_signer); |
232f0877 CH |
375 | conv.xfrBlob(d_signature); |
376 | ) | |
377 | ||
5a1f298f | 378 | RRSIGRecordContent::RRSIGRecordContent() {} |
1c4d88c5 | 379 | |
8c1c9170 | 380 | boilerplate_conv(DNSKEY, 48, |
232f0877 CH |
381 | conv.xfr16BitInt(d_flags); |
382 | conv.xfr8BitInt(d_protocol); | |
383 | conv.xfr8BitInt(d_algorithm); | |
384 | conv.xfrBlob(d_key); | |
385 | ) | |
5a1f298f | 386 | DNSKEYRecordContent::DNSKEYRecordContent() {} |
1c4d88c5 | 387 | |
882de365 PL |
388 | boilerplate_conv(CDNSKEY, 60, |
389 | conv.xfr16BitInt(d_flags); | |
390 | conv.xfr8BitInt(d_protocol); | |
391 | conv.xfr8BitInt(d_algorithm); | |
392 | conv.xfrBlob(d_key); | |
393 | ) | |
5a1f298f | 394 | CDNSKEYRecordContent::CDNSKEYRecordContent() {} |
882de365 | 395 | |
3150a49c | 396 | boilerplate_conv(RKEY, 57, |
232f0877 CH |
397 | conv.xfr16BitInt(d_flags); |
398 | conv.xfr8BitInt(d_protocol); | |
399 | conv.xfrBlob(d_key); | |
400 | ) | |
5a1f298f | 401 | RKEYRecordContent::RKEYRecordContent() {} |
66a07c55 | 402 | |
3150a49c | 403 | /* EUI48 start */ |
66a07c55 AT |
404 | void EUI48RecordContent::report(void) |
405 | { | |
3bb50daa | 406 | regist(1, QType::EUI48, &make, &make, "EUI48"); |
66a07c55 AT |
407 | } |
408 | DNSRecordContent* EUI48RecordContent::make(const DNSRecord &dr, PacketReader& pr) | |
409 | { | |
410 | if(dr.d_clen!=6) | |
411 | throw MOADNSException("Wrong size for EUI48 record"); | |
412 | ||
413 | EUI48RecordContent* ret=new EUI48RecordContent(); | |
414 | pr.copyRecord((uint8_t*) &ret->d_eui48, 6); | |
415 | return ret; | |
416 | } | |
417 | DNSRecordContent* EUI48RecordContent::make(const string& zone) | |
418 | { | |
419 | // try to parse | |
420 | EUI48RecordContent *ret=new EUI48RecordContent(); | |
421 | // format is 6 hex bytes and dashes | |
422 | if (sscanf(zone.c_str(), "%2hhx-%2hhx-%2hhx-%2hhx-%2hhx-%2hhx", | |
423 | ret->d_eui48, ret->d_eui48+1, ret->d_eui48+2, | |
424 | ret->d_eui48+3, ret->d_eui48+4, ret->d_eui48+5) != 6) { | |
0fc965fd | 425 | throw MOADNSException("Asked to encode '"+zone+"' as an EUI48 address, but does not parse"); |
66a07c55 AT |
426 | } |
427 | return ret; | |
428 | } | |
429 | void EUI48RecordContent::toPacket(DNSPacketWriter& pw) | |
430 | { | |
431 | string blob(d_eui48, d_eui48+6); | |
432 | pw.xfrBlob(blob); | |
433 | } | |
f21fc0aa | 434 | string EUI48RecordContent::getZoneRepresentation(bool noDot) const |
66a07c55 AT |
435 | { |
436 | char tmp[18]; | |
a683e8bd | 437 | snprintf(tmp,sizeof(tmp),"%02x-%02x-%02x-%02x-%02x-%02x", |
66a07c55 AT |
438 | d_eui48[0], d_eui48[1], d_eui48[2], |
439 | d_eui48[3], d_eui48[4], d_eui48[5]); | |
440 | return tmp; | |
441 | } | |
442 | ||
443 | /* EUI48 end */ | |
444 | ||
445 | /* EUI64 start */ | |
446 | ||
447 | void EUI64RecordContent::report(void) | |
448 | { | |
3bb50daa | 449 | regist(1, QType::EUI64, &make, &make, "EUI64"); |
66a07c55 AT |
450 | } |
451 | DNSRecordContent* EUI64RecordContent::make(const DNSRecord &dr, PacketReader& pr) | |
452 | { | |
453 | if(dr.d_clen!=8) | |
454 | throw MOADNSException("Wrong size for EUI64 record"); | |
455 | ||
456 | EUI64RecordContent* ret=new EUI64RecordContent(); | |
457 | pr.copyRecord((uint8_t*) &ret->d_eui64, 8); | |
458 | return ret; | |
459 | } | |
460 | DNSRecordContent* EUI64RecordContent::make(const string& zone) | |
461 | { | |
462 | // try to parse | |
463 | EUI64RecordContent *ret=new EUI64RecordContent(); | |
464 | // format is 8 hex bytes and dashes | |
465 | if (sscanf(zone.c_str(), "%2hhx-%2hhx-%2hhx-%2hhx-%2hhx-%2hhx-%2hhx-%2hhx", | |
466 | ret->d_eui64, ret->d_eui64+1, ret->d_eui64+2, | |
467 | ret->d_eui64+3, ret->d_eui64+4, ret->d_eui64+5, | |
468 | ret->d_eui64+6, ret->d_eui64+7) != 8) { | |
469 | throw MOADNSException("Asked to encode '"+zone+"' as an EUI64 address, but does not parse"); | |
470 | } | |
471 | return ret; | |
472 | } | |
473 | void EUI64RecordContent::toPacket(DNSPacketWriter& pw) | |
474 | { | |
475 | string blob(d_eui64, d_eui64+8); | |
476 | pw.xfrBlob(blob); | |
477 | } | |
f21fc0aa | 478 | string EUI64RecordContent::getZoneRepresentation(bool noDot) const |
66a07c55 AT |
479 | { |
480 | char tmp[24]; | |
a683e8bd | 481 | snprintf(tmp,sizeof(tmp),"%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x", |
66a07c55 AT |
482 | d_eui64[0], d_eui64[1], d_eui64[2], |
483 | d_eui64[3], d_eui64[4], d_eui64[5], | |
484 | d_eui64[6], d_eui64[7]); | |
485 | return tmp; | |
486 | } | |
487 | ||
488 | /* EUI64 end */ | |
489 | ||
b3ac6324 | 490 | boilerplate_conv(TKEY, QType::TKEY, |
ad8fa726 | 491 | conv.xfrName(d_algo); |
b3ac6324 AT |
492 | conv.xfr32BitInt(d_inception); |
493 | conv.xfr32BitInt(d_expiration); | |
494 | conv.xfr16BitInt(d_mode); | |
495 | conv.xfr16BitInt(d_error); | |
496 | conv.xfr16BitInt(d_keysize); | |
497 | if (d_keysize>0) conv.xfrBlobNoSpaces(d_key, d_keysize); | |
498 | conv.xfr16BitInt(d_othersize); | |
499 | if (d_othersize>0) conv.xfrBlobNoSpaces(d_other, d_othersize); | |
500 | ) | |
5a1f298f | 501 | TKEYRecordContent::TKEYRecordContent() { d_othersize = 0; } // fix CID#1288932 |
66a07c55 | 502 | |
20966479 | 503 | boilerplate_conv(URI, QType::URI, |
fa38400f PD |
504 | conv.xfr16BitInt(d_priority); |
505 | conv.xfr16BitInt(d_weight); | |
20966479 PL |
506 | conv.xfrText(d_target, true, false); |
507 | ) | |
508 | ||
f75f6821 PL |
509 | boilerplate_conv(CAA, QType::CAA, |
510 | conv.xfr8BitInt(d_flags); | |
511 | conv.xfrUnquotedText(d_tag, true); | |
512 | conv.xfrText(d_value, true, false); /* no lenField */ | |
513 | ) | |
514 | ||
354ccf4e | 515 | static uint16_t makeTag(const std::string& data) |
1c4d88c5 | 516 | { |
1c4d88c5 BH |
517 | const unsigned char* key=(const unsigned char*)data.c_str(); |
518 | unsigned int keysize=data.length(); | |
519 | ||
520 | unsigned long ac; /* assumed to be 32 bits or larger */ | |
521 | unsigned int i; /* loop index */ | |
522 | ||
523 | for ( ac = 0, i = 0; i < keysize; ++i ) | |
524 | ac += (i & 1) ? key[i] : key[i] << 8; | |
525 | ac += (ac >> 16) & 0xFFFF; | |
526 | return ac & 0xFFFF; | |
527 | } | |
528 | ||
354ccf4e | 529 | uint16_t DNSKEYRecordContent::getTag() const |
530 | { | |
531 | DNSKEYRecordContent tmp(*this); | |
532 | return makeTag(tmp.serialize(DNSName())); // this can't be const for some reason | |
533 | } | |
534 | ||
535 | uint16_t DNSKEYRecordContent::getTag() | |
536 | { | |
537 | return makeTag(this->serialize(DNSName())); | |
538 | } | |
539 | ||
540 | ||
b88526ce PL |
541 | /* |
542 | * Fills `eo` by parsing the EDNS(0) OPT RR (RFC 6891) | |
543 | */ | |
7f7b8d55 BH |
544 | bool getEDNSOpts(const MOADNSParser& mdp, EDNSOpts* eo) |
545 | { | |
d6c335ab | 546 | eo->d_extFlags=0; |
0e4ab7bc | 547 | if(mdp.d_header.arcount && !mdp.d_answers.empty()) { |
ef7cd021 | 548 | for(const MOADNSParser::answers_t::value_type& val : mdp.d_answers) { |
e693ff5a | 549 | if(val.first.d_place == DNSResourceRecord::ADDITIONAL && val.first.d_type == QType::OPT) { |
232f0877 | 550 | eo->d_packetsize=val.first.d_class; |
0e4ab7bc | 551 | |
232f0877 CH |
552 | EDNS0Record stuff; |
553 | uint32_t ttl=ntohl(val.first.d_ttl); | |
a683e8bd | 554 | static_assert(sizeof(EDNS0Record) == sizeof(uint32_t), "sizeof(EDNS0Record) must match sizeof(uint32_t)"); |
232f0877 CH |
555 | memcpy(&stuff, &ttl, sizeof(stuff)); |
556 | ||
557 | eo->d_extRCode=stuff.extRCode; | |
558 | eo->d_version=stuff.version; | |
d6c335ab | 559 | eo->d_extFlags = ntohs(stuff.extFlags); |
dc9d2fe3 PL |
560 | auto orc = getRR<OPTRecordContent>(val.first); |
561 | if(orc == nullptr) | |
232f0877 CH |
562 | return false; |
563 | orc->getData(eo->d_options); | |
564 | return true; | |
0e4ab7bc BH |
565 | } |
566 | } | |
7f7b8d55 | 567 | } |
0e4ab7bc | 568 | return false; |
7f7b8d55 BH |
569 | } |
570 | ||
d6c335ab | 571 | DNSRecord makeOpt(const uint16_t udpsize, const uint16_t extRCode, const uint16_t extFlags) |
c541004c | 572 | { |
573 | EDNS0Record stuff; | |
574 | stuff.extRCode=0; | |
575 | stuff.version=0; | |
d6c335ab | 576 | stuff.extFlags=htons(extFlags); |
c541004c | 577 | DNSRecord dr; |
a683e8bd | 578 | static_assert(sizeof(EDNS0Record) == sizeof(dr.d_ttl), "sizeof(EDNS0Record) must match sizeof(DNSRecord.d_ttl)"); |
c541004c | 579 | memcpy(&dr.d_ttl, &stuff, sizeof(stuff)); |
580 | dr.d_ttl=ntohl(dr.d_ttl); | |
12c06211 | 581 | dr.d_name=g_rootdnsname; |
c541004c | 582 | dr.d_type = QType::OPT; |
583 | dr.d_class=udpsize; | |
584 | dr.d_place=DNSResourceRecord::ADDITIONAL; | |
585 | dr.d_content = std::make_shared<OPTRecordContent>(); | |
586 | // if we ever do options, I think we stuff them into OPTRecordContent::data | |
587 | return dr; | |
588 | } | |
589 | ||
7f7b8d55 | 590 | |
ea634573 | 591 | void reportBasicTypes() |
ff6a1e7b | 592 | { |
a9af3782 BH |
593 | ARecordContent::report(); |
594 | AAAARecordContent::report(); | |
595 | NSRecordContent::report(); | |
596 | CNAMERecordContent::report(); | |
597 | MXRecordContent::report(); | |
598 | SOARecordContent::report(); | |
599 | SRVRecordContent::report(); | |
600 | PTRRecordContent::report(); | |
3bb50daa | 601 | DNSRecordContent::regist(QClass::CHAOS, QType::TXT, &TXTRecordContent::make, &TXTRecordContent::make, "TXT"); |
a6a83beb | 602 | TXTRecordContent::report(); |
8900e2e3 | 603 | #ifdef HAVE_LUA_RECORDS |
6b547a53 | 604 | LUARecordContent::report(); |
8900e2e3 | 605 | #endif |
703761cc | 606 | DNSRecordContent::regist(QClass::IN, QType::ANY, 0, 0, "ANY"); |
c15e2752 AT |
607 | DNSRecordContent::regist(QClass::IN, QType::AXFR, 0, 0, "AXFR"); |
608 | DNSRecordContent::regist(QClass::IN, QType::IXFR, 0, 0, "IXFR"); | |
ea634573 BH |
609 | } |
610 | ||
611 | void reportOtherTypes() | |
612 | { | |
fa552262 CHB |
613 | MBRecordContent::report(); |
614 | MGRecordContent::report(); | |
615 | MRRecordContent::report(); | |
37f47031 | 616 | AFSDBRecordContent::report(); |
8dee0750 | 617 | DNAMERecordContent::report(); |
d59b894d | 618 | ALIASRecordContent::report(); |
ea634573 BH |
619 | SPFRecordContent::report(); |
620 | NAPTRRecordContent::report(); | |
c6a60874 | 621 | LOCRecordContent::report(); |
acedb99e | 622 | ENTRecordContent::report(); |
9770663f | 623 | HINFORecordContent::report(); |
ea634573 | 624 | RPRecordContent::report(); |
4b5762f1 | 625 | KEYRecordContent::report(); |
ea634573 | 626 | DNSKEYRecordContent::report(); |
ce834c99 | 627 | DHCIDRecordContent::report(); |
882de365 | 628 | CDNSKEYRecordContent::report(); |
3150a49c | 629 | RKEYRecordContent::report(); |
ea634573 BH |
630 | RRSIGRecordContent::report(); |
631 | DSRecordContent::report(); | |
882de365 | 632 | CDSRecordContent::report(); |
59a0f653 | 633 | SSHFPRecordContent::report(); |
2475a4fc | 634 | CERTRecordContent::report(); |
ea634573 | 635 | NSECRecordContent::report(); |
1c4d88c5 BH |
636 | NSEC3RecordContent::report(); |
637 | NSEC3PARAMRecordContent::report(); | |
07dbe87e | 638 | TLSARecordContent::report(); |
291935bb | 639 | SMIMEARecordContent::report(); |
68066337 | 640 | OPENPGPKEYRecordContent::report(); |
4fb75774 | 641 | DLVRecordContent::report(); |
703761cc | 642 | DNSRecordContent::regist(QClass::ANY, QType::TSIG, &TSIGRecordContent::make, &TSIGRecordContent::make, "TSIG"); |
b3ac6324 | 643 | DNSRecordContent::regist(QClass::ANY, QType::TKEY, &TKEYRecordContent::make, &TKEYRecordContent::make, "TKEY"); |
b7c7d872 | 644 | //TSIGRecordContent::report(); |
ea634573 | 645 | OPTRecordContent::report(); |
66a07c55 AT |
646 | EUI48RecordContent::report(); |
647 | EUI64RecordContent::report(); | |
5eea7309 | 648 | MINFORecordContent::report(); |
20966479 | 649 | URIRecordContent::report(); |
f75f6821 | 650 | CAARecordContent::report(); |
ea634573 BH |
651 | } |
652 | ||
653 | void reportAllTypes() | |
654 | { | |
655 | reportBasicTypes(); | |
656 | reportOtherTypes(); | |
657 | } | |
658 | ||
f1ae49f7 | 659 | ComboAddress getAddr(const DNSRecord& dr, uint16_t defport) |
660 | { | |
661 | if(auto addr=getRR<ARecordContent>(dr)) { | |
662 | return addr->getCA(defport); | |
663 | } | |
664 | else | |
665 | return getRR<AAAARecordContent>(dr)->getCA(defport); | |
666 | } | |
667 | ||
668 | ||
ea634573 BH |
669 | #if 0 |
670 | static struct Reporter | |
671 | { | |
672 | Reporter() | |
673 | { | |
674 | reportAllTypes(); | |
ff6a1e7b BH |
675 | } |
676 | } reporter __attribute__((init_priority(65535))); | |
250d1fd8 | 677 | #endif |