49const signed char digitvalue[256] = {
50 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
51 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
52 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
53 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
54 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
55 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
56 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
57 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
58 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
59 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
60 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
61 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
62 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
63 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
64 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
65 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
71const uint8_t maptolower[] = {
72 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
73 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
74 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
75 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
76 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
77 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
78 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
79 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
80 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
81 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
82 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
83 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
84 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
85 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
86 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
87 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
88 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
89 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
90 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
91 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
92 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
93 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
94 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
95 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
96 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
97 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
98 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
99 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
100 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
101 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
102 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
103 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
124template<
class Iterator,
class Offsets,
class Data>
126stringParse(Iterator s, Iterator send,
bool downcase, Offsets& offsets,
129 const Iterator orig_s(s);
133 unsigned int digits = 0;
134 unsigned int value = 0;
135 unsigned int count = 0;
141 bool is_root =
false;
142 const bool empty = s == send;
143 ft_state state = ft_init;
147 offsets.push_back(0);
156 unsigned char c = *s++;
166 "non terminating empty label in " <<
167 string(orig_s, send));
170 }
else if (c ==
'@' && s == send) {
186 state = ft_initialescape;
196 "duplicate period in " <<
string(orig_s, send));
198 ndata.at(offsets.back()) = count;
199 offsets.push_back(ndata.size());
205 }
else if (c ==
'\\') {
210 "label is too long in " <<
string(orig_s, send));
212 ndata.push_back(downcase ? maptolower[c] : c);
215 case ft_initialescape:
220 "invalid label type in " <<
string(orig_s, send));
224 if (!isdigit(c & 0xff)) {
227 "label is too long in " <<
string(orig_s, send));
229 ndata.push_back(downcase ? maptolower[c] : c);
235 state = ft_escdecimal;
238 if (!isdigit(c & 0xff)) {
240 "mixture of escaped digit and non-digit in "
241 <<
string(orig_s, send));
244 value += digitvalue[c];
249 "escaped decimal is too large in "
250 <<
string(orig_s, send));
254 "label is too long in " <<
string(orig_s, send));
256 ndata.push_back(downcase ? maptolower[value] : value);
269 "name is too long for termination in " <<
270 string(orig_s, send));
273 if (state != ft_ordinary) {
275 "incomplete textual name in " <<
276 (empty ?
"<empty>" : string(orig_s, send)));
278 if (state == ft_ordinary) {
280 ndata.at(offsets.back()) = count;
282 offsets.push_back(ndata.size());
284 ndata.push_back(
'\0');
291Name::Name(
const std::string &namestring,
bool downcase) {
293 const std::string::const_iterator s = namestring.begin();
294 const std::string::const_iterator send = namestring.end();
301 stringParse(s, send,
downcase, offsets, ndata);
304 labelcount_ = offsets.size();
306 ndata_.assign(ndata.data(), ndata.data() + ndata.size());
307 length_ = ndata_.size();
308 offsets_.assign(offsets.begin(), offsets.end());
311Name::Name(
const char* namedata,
size_t data_len,
const Name* origin,
314 if (!namedata || data_len == 0) {
316 "No data provided to Name constructor");
320 const bool absolute = (namedata[data_len - 1] ==
'.');
322 if (!absolute && !origin) {
324 "No origin available and name is relative");
327 const char* end = namedata + data_len;
334 stringParse(namedata, end,
downcase, offsets, ndata);
337 labelcount_ = offsets.size();
339 ndata_.assign(ndata.data(), ndata.data() + ndata.size());
340 length_ = ndata_.size();
341 offsets_.assign(offsets.begin(), offsets.end());
349 ndata_.erase(ndata_.end() - 1);
350 ndata_.insert(ndata_.end(), origin->ndata_.begin(), origin->ndata_.end());
354 size_t offset = offsets_.back();
356 size_t offset_count = offsets_.size();
357 offsets_.insert(offsets_.end(), origin->offsets_.begin(),
358 origin->offsets_.end());
359 for (
auto it(offsets_.begin() + offset_count); it != offsets_.end(); ++it) {
364 length_ = ndata_.size();
365 labelcount_ = offsets_.size();
398 unsigned int nused = 0;
399 bool seen_pointer =
false;
400 fw_state state = fw_start;
402 unsigned int cused = 0;
403 unsigned int current = buffer.getPosition();
404 unsigned int pos_begin = current;
405 unsigned int biggest_pointer = current;
410 unsigned int new_current = 0;
416 while (current < buffer.getLength() && !done) {
417 unsigned int c = buffer.readUint8();
426 offsets.push_back(nused);
429 << nused + c + 1 <<
" bytes");
442 new_current = c & ~COMPRESS_POINTER_MARK8;
444 state = fw_newcurrent;
466 if (new_current >= biggest_pointer) {
468 "bad compression pointer (out of range): " <<
471 biggest_pointer = new_current;
472 current = new_current;
473 buffer.setPosition(current);
486 labelcount_ = offsets.size();
488 offsets_.assign(offsets.begin(), offsets.end());
489 buffer.setPosition(pos_begin + cused);
494 buffer.writeData(ndata_.data(), ndata_.size());
499 renderer.writeName(*
this);
505 return (ls.toText(omit_final_dot));
511 return (ls.toRawText(omit_final_dot));
518 return (ls1.compare(ls2));
523 if (length_ != other.length_ || labelcount_ != other.labelcount_) {
527 for (
unsigned int l = labelcount_, pos = 0; l > 0; --l) {
528 uint8_t count = ndata_[pos];
529 if (count != other.ndata_[pos]) {
534 while (count-- > 0) {
535 uint8_t label1 = ndata_[pos];
536 uint8_t label2 = other.ndata_[pos];
538 if (maptolower[label1] != maptolower[label2]) {
550 return (
compare(other).getOrder() <= 0);
555 return (
compare(other).getOrder() >= 0);
560 return (
compare(other).getOrder() < 0);
565 return (
compare(other).getOrder() > 0);
570 return (length_ >= 2 && ndata_[0] == 1 && ndata_[1] ==
'*');
578 unsigned int length = length_ + suffix.length_ - 1;
584 retname.ndata_.reserve(length);
585 retname.ndata_.assign(ndata_.data(), ndata_.data() + length_ - 1);
586 retname.ndata_.insert(retname.ndata_.end(),
587 suffix.ndata_.begin(), suffix.ndata_.end());
589 retname.length_ = length;
596 unsigned int labels = labelcount_ + suffix.labelcount_ - 1;
598 retname.offsets_.reserve(labels);
599 retname.offsets_.assign(&offsets_[0], &offsets_[0] + labelcount_ - 1);
600 transform(suffix.offsets_.begin(), suffix.offsets_.end(),
601 back_inserter(retname.offsets_),
602 [
this] (
char x) { return (x + length_ - 1); });
604 retname.labelcount_ = labels;
616 retname.offsets_.reserve(labelcount_);
617 retname.ndata_.reserve(length_);
620 NameOffsets::const_reverse_iterator rit0 = offsets_.rbegin();
621 NameOffsets::const_reverse_iterator rit1 = rit0 + 1;
622 NameString::const_iterator n0 = ndata_.begin();
623 retname.offsets_.push_back(0);
624 while (rit1 != offsets_.rend()) {
625 retname.ndata_.insert(retname.ndata_.end(), n0 + *rit1, n0 + *rit0);
626 retname.offsets_.push_back(retname.ndata_.size());
630 retname.ndata_.push_back(0);
632 retname.labelcount_ = labelcount_;
633 retname.length_ = length_;
639Name::split(
const unsigned int first,
const unsigned int n)
const {
640 if (n == 0 || n > labelcount_ || first > labelcount_ - n) {
647 unsigned int newlabels = (first + n == labelcount_) ? n : n + 1;
653 retname.offsets_.reserve(newlabels);
654 transform(offsets_.begin() + first, offsets_.begin() + first + newlabels,
655 back_inserter(retname.offsets_),
656 [&](
char x) { return (x - offsets_[first]); });
664 retname.ndata_.reserve(retname.offsets_.back() + 1);
665 auto it = ndata_.data() + offsets_[first];
666 retname.ndata_.assign(it, it + retname.offsets_.back());
667 retname.ndata_.push_back(0);
669 retname.length_ = retname.ndata_.size();
670 retname.labelcount_ = retname.offsets_.size();
680 <<
") for name " << *
this);
688 unsigned int nlen = length_;
689 unsigned int labels = labelcount_;
690 unsigned int pos = 0;
692 while (labels > 0 && nlen > 0) {
698 unsigned int count = ndata_.at(pos++);
704 maptolower[ndata_.at(pos)];
A generic exception that is thrown if a parameter given to a method or function is considered invalid...
A generic exception that is thrown if a parameter given to a method would refer to or modify out-of-r...
The AbstractMessageRenderer class is an abstract base class that provides common interfaces for rende...
A standard DNS module exception that is thrown if the name parser fails to decode a back-slash escape...
A standard DNS module exception that is thrown if the name parser encounters an obsolete or incomplet...
A standard DNS module exception that is thrown if the name parser encounters an empty label in the mi...
A standard DNS module exception that is thrown if the name parser finds the input (string or wire-for...
Light-weight Accessor to Name data.
Thrown when origin is null and is needed.
This is a supplemental class used only as a return value of Name::compare() and LabelSequence::compar...
The Name class encapsulates DNS names.
static const size_t MAX_LABELLEN
Max allowable length of labels of a domain name.
Name reverse() const
Reverse the labels of a name.
bool lthan(const Name &other) const
Less-than comparison for Name against other
NameComparisonResult compare(const Name &other) const
Compare two Names.
bool equals(const Name &other) const
Return true iff two names are equal.
bool geq(const Name &other) const
Greater-than or equal comparison for Name against other
static const size_t MAX_WIRE
Max allowable length of domain names.
Name split(unsigned int first, unsigned int n) const
Extract a specified subpart of Name.
std::string toText(bool omit_final_dot=false) const
Convert the Name to a string.
void toWire(AbstractMessageRenderer &renderer) const
Render the Name in the wire format with compression.
unsigned int getLabelCount() const
Returns the number of labels contained in the Name.
static const size_t MAX_LABELS
Max allowable labels of domain names.
bool gthan(const Name &other) const
Greater-than comparison for Name against other
Name concatenate(const Name &suffix) const
Concatenate two names.
std::string toRawText(bool omit_final_dot=false) const
Convert the LabelSequence to a string without escape sequences.
static const uint16_t COMPRESS_POINTER_MARK8
A 8-bit masked value indicating a start of compression pointer.
bool leq(const Name &other) const
Less-than or equal comparison for Name against other
Name & downcase()
Downcase all upper case alphabet characters in the name.
bool isWildcard() const
Test if this is a wildcard name.
The OutputBuffer class is a buffer abstraction for manipulating mutable data.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
#define isc_throw_assert(expr)
Replacement for assert() that throws if the expression is false.
ostream & operator<<(std::ostream &os, const EDNS &edns)
Insert the EDNS as a string into stream.
Defines the logger used by the top-level component of kea-lfc.