]>
git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/dnsrecords.cc
2 PowerDNS Versatile Database Driven Nameserver
3 Copyright (C) 2005 - 2009 PowerDNS.COM BV
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License version 2 as
7 published by the Free Software Foundation
9 Additionally, the license of this program contains a special
10 exception which allows to distribute the program in binary form when
11 it is linked against OpenSSL.
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.
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 St, Fifth Floor, Boston, MA 02110-1301 USA
24 #include "dnsrecords.hh"
25 #include <boost/foreach.hpp>
27 void DNSResourceRecord::setContent(const string
&cont
) {
29 if(!content
.empty() && (qtype
==QType::MX
|| qtype
==QType::NS
|| qtype
==QType::CNAME
))
30 boost::erase_tail(content
, 1);
32 if(qtype
.getCode() == QType::MX
) {
34 stringtok(parts
, content
);
35 priority
= atoi(parts
[0].c_str());
40 } else if(qtype
.getCode() == QType::SRV
) {
41 priority
= atoi(content
.c_str());
42 vector
<pair
<string::size_type
, string::size_type
> > fields
;
43 vstringtok(fields
, content
, " ");
44 if(fields
.size()==4) {
45 content
=string(content
.c_str() + fields
[1].first
, fields
[3].second
- fields
[1].first
);
46 content
=stripDot(content
);
51 string
DNSResourceRecord::getZoneRepresentation() {
53 switch(qtype
.getCode()) {
57 ret
<<" "<<content
<<".";
70 bool DNSResourceRecord::operator==(const DNSResourceRecord
& rhs
)
72 string lcontent
=toLower(content
);
73 string rcontent
=toLower(rhs
.content
);
75 string llabel
=toLower(qname
);
76 string rlabel
=toLower(rhs
.qname
);
79 tie(llabel
, qtype
, lcontent
, ttl
, priority
) ==
80 tie(rlabel
, rhs
.qtype
, rcontent
, rhs
.ttl
, rhs
.priority
);
85 DNSResourceRecord::DNSResourceRecord(const DNSRecord
&p
) {
89 boost::erase_tail(qname
, 1); // strip .
94 setContent(p
.d_content
->getZoneRepresentation());
98 boilerplate_conv(A
, ns_t_a
, conv
.xfrIP(d_ip
));
100 ARecordContent::ARecordContent(uint32_t ip
) : DNSRecordContent(ns_t_a
)
105 uint32_t ARecordContent::getIP() const
110 void ARecordContent::doRecordCheck(const DNSRecord
& dr
)
113 throw MOADNSException("Wrong size for A record ("+lexical_cast
<string
>(dr
.d_clen
)+")");
116 boilerplate_conv(AAAA
, ns_t_aaaa
, conv
.xfrIP6(d_ip6
); );
118 boilerplate_conv(NS
, ns_t_ns
, conv
.xfrLabel(d_content
, true));
119 boilerplate_conv(PTR
, ns_t_ptr
, conv
.xfrLabel(d_content
, true));
120 boilerplate_conv(CNAME
, ns_t_cname
, conv
.xfrLabel(d_content
, true));
121 boilerplate_conv(MR
, ns_t_mr
, conv
.xfrLabel(d_alias
, true));
122 boilerplate_conv(MINFO
, ns_t_minfo
, conv
.xfrLabel(d_rmailbx
, true); conv
.xfrLabel(d_emailbx
, true));
123 boilerplate_conv(TXT
, ns_t_txt
, conv
.xfrText(d_text
, true));
124 boilerplate_conv(SPF
, 99, conv
.xfrText(d_text
, true));
125 boilerplate_conv(HINFO
, ns_t_hinfo
, conv
.xfrText(d_cpu
); conv
.xfrText(d_host
));
127 boilerplate_conv(RP
, ns_t_rp
,
128 conv
.xfrLabel(d_mbox
);
129 conv
.xfrLabel(d_info
)
133 boilerplate_conv(OPT
, ns_t_opt
,
137 void OPTRecordContent::getData(vector
<pair
<uint16_t, string
> >& options
)
139 string::size_type pos
=0;
141 while(d_data
.size() >= 4 + pos
) {
142 code
= 256 * (unsigned char)d_data
[pos
] + (unsigned char)d_data
[pos
+1];
143 len
= 256 * (unsigned char)d_data
[pos
+2] + (unsigned char)d_data
[pos
+3];
146 if(pos
+ len
> d_data
.size())
149 string
field(d_data
.c_str() + pos
, len
);
151 options
.push_back(make_pair(code
, field
));
155 boilerplate_conv(TSIG
, ns_t_tsig
,
156 conv
.xfrLabel(d_algoName
);
157 conv
.xfr48BitInt(d_time
);
158 conv
.xfr16BitInt(d_fudge
);
159 uint16_t size
=d_mac
.size();
160 conv
.xfr16BitInt(size
);
161 conv
.xfrBlob(d_mac
, size
);
162 conv
.xfr16BitInt(d_origID
);
163 conv
.xfr16BitInt(d_eRcode
);
164 size
=d_otherData
.size();
165 conv
.xfr16BitInt(size
);
166 if (size
>0) conv
.xfrBlob(d_otherData
, size
);
169 MXRecordContent::MXRecordContent(uint16_t preference
, const string
& mxname
) : DNSRecordContent(ns_t_mx
), d_preference(preference
), d_mxname(mxname
)
173 boilerplate_conv(MX
, ns_t_mx
,
174 conv
.xfr16BitInt(d_preference
);
175 conv
.xfrLabel(d_mxname
, true);
178 boilerplate_conv(KX
, ns_t_kx
,
179 conv
.xfr16BitInt(d_preference
);
180 conv
.xfrLabel(d_exchanger
, false);
183 boilerplate_conv(IPSECKEY
, ns_t_ipseckey
,
184 conv
.xfr8BitInt(d_preference
);
185 conv
.xfr8BitInt(d_gatewaytype
);
186 conv
.xfr8BitInt(d_algorithm
);
188 // now we need to determine values
189 switch(d_gatewaytype
) {
199 conv
.xfrLabel(d_gateway
, false);
202 throw MOADNSException("Parsing record content: invalid gateway type");
205 switch(d_algorithm
) {
210 conv
.xfrBlob(d_publickey
);
213 throw MOADNSException("Parsing record content: invalid algorithm type");
217 boilerplate_conv(DHCID
, 49,
218 conv
.xfrBlob(d_content
);
222 boilerplate_conv(AFSDB
, ns_t_afsdb
,
223 conv
.xfr16BitInt(d_subtype
);
224 conv
.xfrLabel(d_hostname
);
228 boilerplate_conv(NAPTR
, ns_t_naptr
,
229 conv
.xfr16BitInt(d_order
); conv
.xfr16BitInt(d_preference
);
230 conv
.xfrText(d_flags
); conv
.xfrText(d_services
); conv
.xfrText(d_regexp
);
231 conv
.xfrLabel(d_replacement
);
235 SRVRecordContent::SRVRecordContent(uint16_t preference
, uint16_t weight
, uint16_t port
, const string
& target
)
236 : DNSRecordContent(ns_t_srv
), d_preference(preference
), d_weight(weight
), d_port(port
), d_target(target
)
239 boilerplate_conv(SRV
, ns_t_srv
,
240 conv
.xfr16BitInt(d_preference
); conv
.xfr16BitInt(d_weight
); conv
.xfr16BitInt(d_port
);
241 conv
.xfrLabel(d_target
);
244 SOARecordContent::SOARecordContent(const string
& mname
, const string
& rname
, const struct soatimes
& st
)
245 : DNSRecordContent(ns_t_soa
), d_mname(mname
), d_rname(rname
)
250 boilerplate_conv(SOA
, ns_t_soa
,
251 conv
.xfrLabel(d_mname
, true);
252 conv
.xfrLabel(d_rname
, true);
253 conv
.xfr32BitInt(d_st
.serial
);
254 conv
.xfr32BitInt(d_st
.refresh
);
255 conv
.xfr32BitInt(d_st
.retry
);
256 conv
.xfr32BitInt(d_st
.expire
);
257 conv
.xfr32BitInt(d_st
.minimum
);
260 boilerplate_conv(KEY
, ns_t_key
,
261 conv
.xfr16BitInt(d_flags
);
262 conv
.xfr8BitInt(d_protocol
);
263 conv
.xfr8BitInt(d_algorithm
);
264 conv
.xfrBlob(d_certificate
);
267 boilerplate_conv(CERT
, 37,
268 conv
.xfr16BitInt(d_type
);
269 if (d_type
== 0) throw MOADNSException("CERT type 0 is reserved");
271 conv
.xfr16BitInt(d_tag
);
272 conv
.xfr8BitInt(d_algorithm
);
273 conv
.xfrBlob(d_certificate
);
276 boilerplate_conv(TLSA
, 52,
277 conv
.xfr8BitInt(d_certusage
);
278 conv
.xfr8BitInt(d_selector
);
279 conv
.xfr8BitInt(d_matchtype
);
280 conv
.xfrHexBlob(d_cert
, true);
284 DSRecordContent::DSRecordContent() : DNSRecordContent(43) {}
285 boilerplate_conv(DS
, 43,
286 conv
.xfr16BitInt(d_tag
);
287 conv
.xfr8BitInt(d_algorithm
);
288 conv
.xfr8BitInt(d_digesttype
);
289 conv
.xfrHexBlob(d_digest
, true); // keep reading across spaces
292 DLVRecordContent::DLVRecordContent() : DNSRecordContent(32769) {}
293 boilerplate_conv(DLV
,32769 ,
294 conv
.xfr16BitInt(d_tag
);
295 conv
.xfr8BitInt(d_algorithm
);
296 conv
.xfr8BitInt(d_digesttype
);
297 conv
.xfrHexBlob(d_digest
, true); // keep reading across spaces
301 boilerplate_conv(SSHFP
, 44,
302 conv
.xfr8BitInt(d_algorithm
);
303 conv
.xfr8BitInt(d_fptype
);
304 conv
.xfrHexBlob(d_fingerprint
);
307 boilerplate_conv(RRSIG
, 46,
308 conv
.xfrType(d_type
);
309 conv
.xfr8BitInt(d_algorithm
);
310 conv
.xfr8BitInt(d_labels
);
311 conv
.xfr32BitInt(d_originalttl
);
312 conv
.xfrTime(d_sigexpire
);
313 conv
.xfrTime(d_siginception
);
314 conv
.xfr16BitInt(d_tag
);
315 conv
.xfrLabel(d_signer
);
316 conv
.xfrBlob(d_signature
);
319 RRSIGRecordContent::RRSIGRecordContent() : DNSRecordContent(46) {}
321 boilerplate_conv(DNSKEY
, 48,
322 conv
.xfr16BitInt(d_flags
);
323 conv
.xfr8BitInt(d_protocol
);
324 conv
.xfr8BitInt(d_algorithm
);
327 DNSKEYRecordContent::DNSKEYRecordContent() : DNSRecordContent(48) {}
329 boilerplate_conv(RKEY
, 57,
330 conv
.xfr16BitInt(d_flags
);
331 conv
.xfr8BitInt(d_protocol
);
334 RKEYRecordContent::RKEYRecordContent() : DNSRecordContent(57) {}
337 void EUI48RecordContent::report(void)
339 regist(1, ns_t_eui48
, &make
, &make
, "EUI48");
341 DNSRecordContent
* EUI48RecordContent::make(const DNSRecord
&dr
, PacketReader
& pr
)
344 throw MOADNSException("Wrong size for EUI48 record");
346 EUI48RecordContent
* ret
=new EUI48RecordContent();
347 pr
.copyRecord((uint8_t*) &ret
->d_eui48
, 6);
350 DNSRecordContent
* EUI48RecordContent::make(const string
& zone
)
353 EUI48RecordContent
*ret
=new EUI48RecordContent();
354 // format is 6 hex bytes and dashes
355 if (sscanf(zone
.c_str(), "%2hhx-%2hhx-%2hhx-%2hhx-%2hhx-%2hhx",
356 ret
->d_eui48
, ret
->d_eui48
+1, ret
->d_eui48
+2,
357 ret
->d_eui48
+3, ret
->d_eui48
+4, ret
->d_eui48
+5) != 6) {
358 throw MOADNSException("Asked to encode '"+zone
+"' as an EUI48 address, but does not parse");
362 void EUI48RecordContent::toPacket(DNSPacketWriter
& pw
)
364 string
blob(d_eui48
, d_eui48
+6);
367 string
EUI48RecordContent::getZoneRepresentation() const
370 snprintf(tmp
,18,"%02x-%02x-%02x-%02x-%02x-%02x",
371 d_eui48
[0], d_eui48
[1], d_eui48
[2],
372 d_eui48
[3], d_eui48
[4], d_eui48
[5]);
380 void EUI64RecordContent::report(void)
382 regist(1, ns_t_eui64
, &make
, &make
, "EUI64");
384 DNSRecordContent
* EUI64RecordContent::make(const DNSRecord
&dr
, PacketReader
& pr
)
387 throw MOADNSException("Wrong size for EUI64 record");
389 EUI64RecordContent
* ret
=new EUI64RecordContent();
390 pr
.copyRecord((uint8_t*) &ret
->d_eui64
, 8);
393 DNSRecordContent
* EUI64RecordContent::make(const string
& zone
)
396 EUI64RecordContent
*ret
=new EUI64RecordContent();
397 // format is 8 hex bytes and dashes
398 if (sscanf(zone
.c_str(), "%2hhx-%2hhx-%2hhx-%2hhx-%2hhx-%2hhx-%2hhx-%2hhx",
399 ret
->d_eui64
, ret
->d_eui64
+1, ret
->d_eui64
+2,
400 ret
->d_eui64
+3, ret
->d_eui64
+4, ret
->d_eui64
+5,
401 ret
->d_eui64
+6, ret
->d_eui64
+7) != 8) {
402 throw MOADNSException("Asked to encode '"+zone
+"' as an EUI64 address, but does not parse");
406 void EUI64RecordContent::toPacket(DNSPacketWriter
& pw
)
408 string
blob(d_eui64
, d_eui64
+8);
411 string
EUI64RecordContent::getZoneRepresentation() const
414 snprintf(tmp
,24,"%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x",
415 d_eui64
[0], d_eui64
[1], d_eui64
[2],
416 d_eui64
[3], d_eui64
[4], d_eui64
[5],
417 d_eui64
[6], d_eui64
[7]);
424 uint16_t DNSKEYRecordContent::getTag()
426 string data
=this->serialize("");
427 const unsigned char* key
=(const unsigned char*)data
.c_str();
428 unsigned int keysize
=data
.length();
430 unsigned long ac
; /* assumed to be 32 bits or larger */
431 unsigned int i
; /* loop index */
433 for ( ac
= 0, i
= 0; i
< keysize
; ++i
)
434 ac
+= (i
& 1) ? key
[i
] : key
[i
] << 8;
435 ac
+= (ac
>> 16) & 0xFFFF;
440 boilerplate_conv(URL
, QType::URL
,
441 conv
.xfrLabel(d_url
);
444 boilerplate_conv(MBOXFW
, QType::MBOXFW
,
445 conv
.xfrLabel(d_mboxfw
);
450 bool getEDNSOpts(const MOADNSParser
& mdp
, EDNSOpts
* eo
)
452 if(mdp
.d_header
.arcount
&& !mdp
.d_answers
.empty()) {
453 BOOST_FOREACH(const MOADNSParser::answers_t::value_type
& val
, mdp
.d_answers
) {
454 if(val
.first
.d_place
== DNSRecord::Additional
&& val
.first
.d_type
== QType::OPT
) {
455 eo
->d_packetsize
=val
.first
.d_class
;
458 uint32_t ttl
=ntohl(val
.first
.d_ttl
);
459 memcpy(&stuff
, &ttl
, sizeof(stuff
));
461 eo
->d_extRCode
=stuff
.extRCode
;
462 eo
->d_version
=stuff
.version
;
463 eo
->d_Z
= ntohs(stuff
.Z
);
464 OPTRecordContent
* orc
=
465 dynamic_cast<OPTRecordContent
*>(val
.first
.d_content
.get());
468 orc
->getData(eo
->d_options
);
477 void reportBasicTypes()
479 ARecordContent::report();
480 AAAARecordContent::report();
481 NSRecordContent::report();
482 CNAMERecordContent::report();
483 MXRecordContent::report();
484 SOARecordContent::report();
485 SRVRecordContent::report();
486 PTRRecordContent::report();
487 //DNSRecordContent::regist(3, ns_t_txt, &TXTRecordContent::make, &TXTRecordContent::make, "TXT");
488 TXTRecordContent::report();
489 DNSRecordContent::regist(1, QType::ANY
, 0, 0, "ANY");
492 void reportOtherTypes()
494 AFSDBRecordContent::report();
495 SPFRecordContent::report();
496 NAPTRRecordContent::report();
497 LOCRecordContent::report();
498 HINFORecordContent::report();
499 RPRecordContent::report();
500 KEYRecordContent::report();
501 DNSKEYRecordContent::report();
502 RKEYRecordContent::report();
503 RRSIGRecordContent::report();
504 DSRecordContent::report();
505 SSHFPRecordContent::report();
506 CERTRecordContent::report();
507 NSECRecordContent::report();
508 NSEC3RecordContent::report();
509 NSEC3PARAMRecordContent::report();
510 TLSARecordContent::report();
511 DLVRecordContent::report();
512 DNSRecordContent::regist(0xff, QType::TSIG
, &TSIGRecordContent::make
, &TSIGRecordContent::make
, "TSIG");
513 //TSIGRecordContent::report();
514 OPTRecordContent::report();
515 EUI48RecordContent::report();
516 EUI64RecordContent::report();
517 MINFORecordContent::report();
520 void reportFancyTypes()
522 URLRecordContent::report();
523 MBOXFWRecordContent::report();
526 void reportAllTypes()
533 static struct Reporter
539 } reporter
__attribute__((init_priority(65535)));