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