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