]>
git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/dnsrecords.cc
2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
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.
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.
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include "dnsrecords.hh"
30 void DNSResourceRecord::setContent(const string
&cont
) {
32 switch(qtype
.getCode()) {
35 if (content
.size() >= 2 && *(content
.rbegin()+1) == ' ')
42 boost::erase_tail(content
, 1);
46 string
DNSResourceRecord::getZoneRepresentation(bool noDot
) const {
51 switch(qtype
.getCode()) {
54 stringtok(parts
, content
);
57 last
= *parts
.rbegin();
61 if (*(last
.rbegin()) != '.' && !noDot
)
69 if (*(content
.rbegin()) != '.' && !noDot
)
79 bool DNSResourceRecord::operator==(const DNSResourceRecord
& rhs
)
81 string lcontent
=toLower(content
);
82 string rcontent
=toLower(rhs
.content
);
85 tie(qname
, qtype
, lcontent
, ttl
) ==
86 tie(rhs
.qname
, rhs
.qtype
, rcontent
, rhs
.ttl
);
89 boilerplate_conv(A
, QType::A
, conv
.xfrIP(d_ip
));
91 ARecordContent::ARecordContent(uint32_t ip
)
96 ARecordContent::ARecordContent(const ComboAddress
& ca
)
98 d_ip
= ca
.sin4
.sin_addr
.s_addr
;
101 AAAARecordContent::AAAARecordContent(const ComboAddress
& ca
)
103 d_ip6
.assign((const char*)ca
.sin6
.sin6_addr
.s6_addr
, 16);
108 ComboAddress
ARecordContent::getCA(int port
) const
111 ret
.sin4
.sin_family
=AF_INET
;
112 ret
.sin4
.sin_port
=htons(port
);
113 memcpy(&ret
.sin4
.sin_addr
.s_addr
, &d_ip
, sizeof(ret
.sin4
.sin_addr
.s_addr
));
117 ComboAddress
AAAARecordContent::getCA(int port
) const
122 ret
.sin4
.sin_family
=AF_INET6
;
123 ret
.sin6
.sin6_port
= htons(port
);
124 memcpy(&ret
.sin6
.sin6_addr
.s6_addr
, d_ip6
.c_str(), sizeof(ret
.sin6
.sin6_addr
.s6_addr
));
129 void ARecordContent::doRecordCheck(const DNSRecord
& dr
)
132 throw MOADNSException("Wrong size for A record ("+std::to_string(dr
.d_clen
)+")");
135 boilerplate_conv(AAAA
, QType::AAAA
, conv
.xfrIP6(d_ip6
); );
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));
140 boilerplate_conv(ALIAS
, QType::ALIAS
, conv
.xfrName(d_content
, false));
141 boilerplate_conv(DNAME
, QType::DNAME
, conv
.xfrName(d_content
));
142 boilerplate_conv(MB
, QType::MB
, conv
.xfrName(d_madname
, true));
143 boilerplate_conv(MG
, QType::MG
, conv
.xfrName(d_mgmname
, true));
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));
146 boilerplate_conv(TXT
, QType::TXT
, conv
.xfrText(d_text
, true));
147 #ifdef HAVE_LUA_RECORDS
148 boilerplate_conv(LUA
, QType::LUA
, conv
.xfrType(d_type
); conv
.xfrText(d_code
, true));
150 boilerplate_conv(ENT
, 0, );
151 boilerplate_conv(SPF
, 99, conv
.xfrText(d_text
, true));
152 boilerplate_conv(HINFO
, QType::HINFO
, conv
.xfrText(d_cpu
); conv
.xfrText(d_host
));
154 boilerplate_conv(RP
, QType::RP
,
155 conv
.xfrName(d_mbox
);
160 boilerplate_conv(OPT
, QType::OPT
,
164 #ifdef HAVE_LUA_RECORDS
165 string
LUARecordContent::getCode()
167 // in d_code, series of "part1" "part2"
168 vector
<string
> parts
;
169 stringtok(parts
, d_code
, "\"");
171 for(const auto& p
: parts
) {
179 void OPTRecordContent::getData(vector
<pair
<uint16_t, string
> >& options
)
181 string::size_type pos
=0;
183 while(d_data
.size() >= 4 + pos
) {
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];
188 if(pos
+ len
> d_data
.size())
191 string
field(d_data
.c_str() + pos
, len
);
193 options
.push_back(make_pair(code
, field
));
197 boilerplate_conv(TSIG
, QType::TSIG
,
198 conv
.xfrName(d_algoName
);
199 conv
.xfr48BitInt(d_time
);
200 conv
.xfr16BitInt(d_fudge
);
201 uint16_t size
=d_mac
.size();
202 conv
.xfr16BitInt(size
);
203 if (size
>0) conv
.xfrBlobNoSpaces(d_mac
, size
);
204 conv
.xfr16BitInt(d_origID
);
205 conv
.xfr16BitInt(d_eRcode
);
206 size
=d_otherData
.size();
207 conv
.xfr16BitInt(size
);
208 if (size
>0) conv
.xfrBlobNoSpaces(d_otherData
, size
);
211 MXRecordContent::MXRecordContent(uint16_t preference
, const DNSName
& mxname
): d_preference(preference
), d_mxname(mxname
)
215 boilerplate_conv(MX
, QType::MX
,
216 conv
.xfr16BitInt(d_preference
);
217 conv
.xfrName(d_mxname
, true);
220 boilerplate_conv(KX
, QType::KX
,
221 conv
.xfr16BitInt(d_preference
);
222 conv
.xfrName(d_exchanger
, false);
225 boilerplate_conv(IPSECKEY
, QType::IPSECKEY
,
226 conv
.xfr8BitInt(d_preference
);
227 conv
.xfr8BitInt(d_gatewaytype
);
228 conv
.xfr8BitInt(d_algorithm
);
230 // now we need to determine values
231 switch(d_gatewaytype
) {
241 conv
.xfrName(d_gateway
, false);
244 throw MOADNSException("Parsing record content: invalid gateway type");
247 switch(d_algorithm
) {
252 conv
.xfrBlob(d_publickey
);
255 throw MOADNSException("Parsing record content: invalid algorithm type");
259 boilerplate_conv(DHCID
, 49,
260 conv
.xfrBlob(d_content
);
264 boilerplate_conv(AFSDB
, QType::AFSDB
,
265 conv
.xfr16BitInt(d_subtype
);
266 conv
.xfrName(d_hostname
);
270 boilerplate_conv(NAPTR
, QType::NAPTR
,
271 conv
.xfr16BitInt(d_order
); conv
.xfr16BitInt(d_preference
);
272 conv
.xfrText(d_flags
); conv
.xfrText(d_services
); conv
.xfrText(d_regexp
);
273 conv
.xfrName(d_replacement
);
277 SRVRecordContent::SRVRecordContent(uint16_t preference
, uint16_t weight
, uint16_t port
, const DNSName
& target
)
278 : d_weight(weight
), d_port(port
), d_target(target
), d_preference(preference
)
281 boilerplate_conv(SRV
, QType::SRV
,
282 conv
.xfr16BitInt(d_preference
); conv
.xfr16BitInt(d_weight
); conv
.xfr16BitInt(d_port
);
283 conv
.xfrName(d_target
);
286 SOARecordContent::SOARecordContent(const DNSName
& mname
, const DNSName
& rname
, const struct soatimes
& st
)
287 : d_mname(mname
), d_rname(rname
), d_st(st
)
291 boilerplate_conv(SOA
, QType::SOA
,
292 conv
.xfrName(d_mname
, true);
293 conv
.xfrName(d_rname
, true);
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
);
301 boilerplate_conv(KEY
, QType::KEY
,
302 conv
.xfr16BitInt(d_flags
);
303 conv
.xfr8BitInt(d_protocol
);
304 conv
.xfr8BitInt(d_algorithm
);
305 conv
.xfrBlob(d_certificate
);
308 boilerplate_conv(CERT
, 37,
309 conv
.xfr16BitInt(d_type
);
310 if (d_type
== 0) throw MOADNSException("CERT type 0 is reserved");
312 conv
.xfr16BitInt(d_tag
);
313 conv
.xfr8BitInt(d_algorithm
);
314 conv
.xfrBlob(d_certificate
);
317 boilerplate_conv(TLSA
, 52,
318 conv
.xfr8BitInt(d_certusage
);
319 conv
.xfr8BitInt(d_selector
);
320 conv
.xfr8BitInt(d_matchtype
);
321 conv
.xfrHexBlob(d_cert
, true);
324 boilerplate_conv(OPENPGPKEY
, 61,
325 conv
.xfrBlob(d_keyring
);
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);
335 DSRecordContent::DSRecordContent() {}
336 boilerplate_conv(DS
, 43,
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
343 CDSRecordContent::CDSRecordContent() {}
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
351 DLVRecordContent::DLVRecordContent() {}
352 boilerplate_conv(DLV
,32769 ,
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
360 boilerplate_conv(SSHFP
, 44,
361 conv
.xfr8BitInt(d_algorithm
);
362 conv
.xfr8BitInt(d_fptype
);
363 conv
.xfrHexBlob(d_fingerprint
, true);
366 boilerplate_conv(RRSIG
, 46,
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
);
374 conv
.xfrName(d_signer
);
375 conv
.xfrBlob(d_signature
);
378 RRSIGRecordContent::RRSIGRecordContent() {}
380 boilerplate_conv(DNSKEY
, 48,
381 conv
.xfr16BitInt(d_flags
);
382 conv
.xfr8BitInt(d_protocol
);
383 conv
.xfr8BitInt(d_algorithm
);
386 DNSKEYRecordContent::DNSKEYRecordContent() {}
388 boilerplate_conv(CDNSKEY
, 60,
389 conv
.xfr16BitInt(d_flags
);
390 conv
.xfr8BitInt(d_protocol
);
391 conv
.xfr8BitInt(d_algorithm
);
394 CDNSKEYRecordContent::CDNSKEYRecordContent() {}
396 boilerplate_conv(RKEY
, 57,
397 conv
.xfr16BitInt(d_flags
);
398 conv
.xfr8BitInt(d_protocol
);
401 RKEYRecordContent::RKEYRecordContent() {}
404 void EUI48RecordContent::report(void)
406 regist(1, QType::EUI48
, &make
, &make
, "EUI48");
408 std::shared_ptr
<DNSRecordContent
> EUI48RecordContent::make(const DNSRecord
&dr
, PacketReader
& pr
)
411 throw MOADNSException("Wrong size for EUI48 record");
413 auto ret
=std::make_shared
<EUI48RecordContent
>();
414 pr
.copyRecord((uint8_t*) &ret
->d_eui48
, 6);
417 std::shared_ptr
<DNSRecordContent
> EUI48RecordContent::make(const string
& zone
)
420 auto ret
=std::make_shared
<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) {
425 throw MOADNSException("Asked to encode '"+zone
+"' as an EUI48 address, but does not parse");
429 void EUI48RecordContent::toPacket(DNSPacketWriter
& pw
)
431 string
blob(d_eui48
, d_eui48
+6);
434 string
EUI48RecordContent::getZoneRepresentation(bool noDot
) const
437 snprintf(tmp
,sizeof(tmp
),"%02x-%02x-%02x-%02x-%02x-%02x",
438 d_eui48
[0], d_eui48
[1], d_eui48
[2],
439 d_eui48
[3], d_eui48
[4], d_eui48
[5]);
447 void EUI64RecordContent::report(void)
449 regist(1, QType::EUI64
, &make
, &make
, "EUI64");
451 std::shared_ptr
<DNSRecordContent
> EUI64RecordContent::make(const DNSRecord
&dr
, PacketReader
& pr
)
454 throw MOADNSException("Wrong size for EUI64 record");
456 auto ret
=std::make_shared
<EUI64RecordContent
>();
457 pr
.copyRecord((uint8_t*) &ret
->d_eui64
, 8);
460 std::shared_ptr
<DNSRecordContent
> EUI64RecordContent::make(const string
& zone
)
463 auto ret
=std::make_shared
<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");
473 void EUI64RecordContent::toPacket(DNSPacketWriter
& pw
)
475 string
blob(d_eui64
, d_eui64
+8);
478 string
EUI64RecordContent::getZoneRepresentation(bool noDot
) const
481 snprintf(tmp
,sizeof(tmp
),"%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x",
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]);
490 boilerplate_conv(TKEY
, QType::TKEY
,
491 conv
.xfrName(d_algo
);
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
);
501 TKEYRecordContent::TKEYRecordContent() { d_othersize
= 0; } // fix CID#1288932
503 boilerplate_conv(URI
, QType::URI
,
504 conv
.xfr16BitInt(d_priority
);
505 conv
.xfr16BitInt(d_weight
);
506 conv
.xfrText(d_target
, true, false);
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 */
515 static uint16_t makeTag(const std::string
& data
)
517 const unsigned char* key
=(const unsigned char*)data
.c_str();
518 unsigned int keysize
=data
.length();
520 unsigned long ac
; /* assumed to be 32 bits or larger */
521 unsigned int i
; /* loop index */
523 for ( ac
= 0, i
= 0; i
< keysize
; ++i
)
524 ac
+= (i
& 1) ? key
[i
] : key
[i
] << 8;
525 ac
+= (ac
>> 16) & 0xFFFF;
529 uint16_t DNSKEYRecordContent::getTag() const
531 DNSKEYRecordContent
tmp(*this);
532 return makeTag(tmp
.serialize(DNSName())); // this can't be const for some reason
535 uint16_t DNSKEYRecordContent::getTag()
537 return makeTag(this->serialize(DNSName()));
542 * Fills `eo` by parsing the EDNS(0) OPT RR (RFC 6891)
544 bool getEDNSOpts(const MOADNSParser
& mdp
, EDNSOpts
* eo
)
547 if(mdp
.d_header
.arcount
&& !mdp
.d_answers
.empty()) {
548 for(const MOADNSParser::answers_t::value_type
& val
: mdp
.d_answers
) {
549 if(val
.first
.d_place
== DNSResourceRecord::ADDITIONAL
&& val
.first
.d_type
== QType::OPT
) {
550 eo
->d_packetsize
=val
.first
.d_class
;
553 uint32_t ttl
=ntohl(val
.first
.d_ttl
);
554 static_assert(sizeof(EDNS0Record
) == sizeof(uint32_t), "sizeof(EDNS0Record) must match sizeof(uint32_t)");
555 memcpy(&stuff
, &ttl
, sizeof(stuff
));
557 eo
->d_extRCode
=stuff
.extRCode
;
558 eo
->d_version
=stuff
.version
;
559 eo
->d_extFlags
= ntohs(stuff
.extFlags
);
560 auto orc
= getRR
<OPTRecordContent
>(val
.first
);
563 orc
->getData(eo
->d_options
);
571 DNSRecord
makeOpt(const uint16_t udpsize
, const uint16_t extRCode
, const uint16_t extFlags
)
576 stuff
.extFlags
=htons(extFlags
);
578 static_assert(sizeof(EDNS0Record
) == sizeof(dr
.d_ttl
), "sizeof(EDNS0Record) must match sizeof(DNSRecord.d_ttl)");
579 memcpy(&dr
.d_ttl
, &stuff
, sizeof(stuff
));
580 dr
.d_ttl
=ntohl(dr
.d_ttl
);
581 dr
.d_name
=g_rootdnsname
;
582 dr
.d_type
= QType::OPT
;
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
590 void reportBasicTypes()
592 ARecordContent::report();
593 AAAARecordContent::report();
594 NSRecordContent::report();
595 CNAMERecordContent::report();
596 MXRecordContent::report();
597 SOARecordContent::report();
598 SRVRecordContent::report();
599 PTRRecordContent::report();
600 DNSRecordContent::regist(QClass::CHAOS
, QType::TXT
, &TXTRecordContent::make
, &TXTRecordContent::make
, "TXT");
601 TXTRecordContent::report();
602 #ifdef HAVE_LUA_RECORDS
603 LUARecordContent::report();
605 DNSRecordContent::regist(QClass::IN
, QType::ANY
, 0, 0, "ANY");
606 DNSRecordContent::regist(QClass::IN
, QType::AXFR
, 0, 0, "AXFR");
607 DNSRecordContent::regist(QClass::IN
, QType::IXFR
, 0, 0, "IXFR");
610 void reportOtherTypes()
612 MBRecordContent::report();
613 MGRecordContent::report();
614 MRRecordContent::report();
615 AFSDBRecordContent::report();
616 DNAMERecordContent::report();
617 ALIASRecordContent::report();
618 SPFRecordContent::report();
619 NAPTRRecordContent::report();
620 LOCRecordContent::report();
621 ENTRecordContent::report();
622 HINFORecordContent::report();
623 RPRecordContent::report();
624 KEYRecordContent::report();
625 DNSKEYRecordContent::report();
626 DHCIDRecordContent::report();
627 CDNSKEYRecordContent::report();
628 RKEYRecordContent::report();
629 RRSIGRecordContent::report();
630 DSRecordContent::report();
631 CDSRecordContent::report();
632 SSHFPRecordContent::report();
633 CERTRecordContent::report();
634 NSECRecordContent::report();
635 NSEC3RecordContent::report();
636 NSEC3PARAMRecordContent::report();
637 TLSARecordContent::report();
638 SMIMEARecordContent::report();
639 OPENPGPKEYRecordContent::report();
640 DLVRecordContent::report();
641 DNSRecordContent::regist(QClass::ANY
, QType::TSIG
, &TSIGRecordContent::make
, &TSIGRecordContent::make
, "TSIG");
642 DNSRecordContent::regist(QClass::ANY
, QType::TKEY
, &TKEYRecordContent::make
, &TKEYRecordContent::make
, "TKEY");
643 //TSIGRecordContent::report();
644 OPTRecordContent::report();
645 EUI48RecordContent::report();
646 EUI64RecordContent::report();
647 MINFORecordContent::report();
648 URIRecordContent::report();
649 CAARecordContent::report();
652 void reportAllTypes()
658 ComboAddress
getAddr(const DNSRecord
& dr
, uint16_t defport
)
660 if(auto addr
=getRR
<ARecordContent
>(dr
)) {
661 return addr
->getCA(defport
);
664 return getRR
<AAAARecordContent
>(dr
)->getCA(defport
);
668 * Check if the DNSNames that should be hostnames, are hostnames
670 void checkHostnameCorrectness(const DNSResourceRecord
& rr
)
672 if (rr
.qtype
.getCode() == QType::NS
|| rr
.qtype
.getCode() == QType::MX
|| rr
.qtype
.getCode() == QType::SRV
) {
674 if (rr
.qtype
.getCode() == QType::SRV
) {
675 vector
<string
> parts
;
676 stringtok(parts
, rr
.getZoneRepresentation());
677 if (parts
.size() == 4) toCheck
= DNSName(parts
[3]);
678 } else if (rr
.qtype
.getCode() == QType::MX
) {
679 vector
<string
> parts
;
680 stringtok(parts
, rr
.getZoneRepresentation());
681 if (parts
.size() == 2) toCheck
= DNSName(parts
[1]);
683 toCheck
= DNSName(rr
.content
);
686 if (toCheck
.empty()) {
687 throw std::runtime_error("unable to extract hostname from content");
689 else if ((rr
.qtype
.getCode() == QType::MX
|| rr
.qtype
.getCode() == QType::SRV
) && toCheck
== g_rootdnsname
) {
691 } else if(!toCheck
.isHostname()) {
692 throw std::runtime_error(boost::str(boost::format("non-hostname content %s") % toCheck
.toString()));
698 static struct Reporter
704 } reporter
__attribute__((init_priority(65535)));