Kea 3.2.1-git
name.cc
Go to the documentation of this file.
1// Copyright (C) 2009-2026 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#include <config.h>
8
10#include <dns/name.h>
11#include <dns/name_internal.h>
12#include <dns/messagerenderer.h>
13#include <dns/labelsequence.h>
14
15#include <cctype>
16#include <iterator>
17#include <functional>
18#include <vector>
19#include <iostream>
20#include <algorithm>
21
22using namespace isc::util;
23using namespace isc::dns::name::internal;
24
25using namespace std;
26
27namespace isc {
28namespace dns {
29
30namespace {
49const signed char digitvalue[256] = {
50 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 16
51 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 32
52 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 48
53 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, // 64
54 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 80
55 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 96
56 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 112
57 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 128
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, // 256
66};
67}
68
69namespace name {
70namespace internal {
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, // ..., 'A' - 'G'
81 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, // 'H' - 'O'
82 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, // 'P' - 'W'
83 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, // 'X' - 'Z', ...
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
104};
105} // end of internal
106} // end of name
107
108namespace {
112typedef enum {
113 ft_init = 0, // begin of the name
114 ft_start, // begin of a label
115 ft_ordinary, // parsing an ordinary label
116 ft_initialescape, // just found '\'
117 ft_escape, // begin of handling a '\'-escaped sequence
118 ft_escdecimal // parsing a '\DDD' octet.
119} ft_state;
120
121// The parser of name from a string. It is a template, because
122// some parameters are used with two different types, while others
123// are private type aliases.
124template<class Iterator, class Offsets, class Data>
125void
126stringParse(Iterator s, Iterator send, bool downcase, Offsets& offsets,
127 Data& ndata) {
128 const Iterator orig_s(s);
129 //
130 // Initialize things to make the compiler happy; they're not required.
131 //
132 unsigned int digits = 0;
133 unsigned int value = 0;
134 unsigned int count = 0;
135
136 //
137 // Set up the state machine.
138 //
139 bool done = false;
140 bool is_root = false;
141 const bool empty = s == send;
142 ft_state state = ft_init;
143
144 // Prepare the output buffers.
145 offsets.reserve(Name::MAX_LABELS);
146 offsets.push_back(0);
147 ndata.reserve(Name::MAX_WIRE);
148
149 // should we refactor this code using, e.g, the state pattern? Probably
150 // not at this point, as this is based on proved code (derived from BIND9)
151 // and it's less likely that we'll have more variations in the domain name
152 // syntax. If this ever happens next time, we should consider refactor
153 // the code, rather than adding more states and cases below.
154 while (ndata.size() < Name::MAX_WIRE && s != send && !done) {
155 unsigned char c = *s++;
156
157 switch (state) {
158 case ft_init:
159 //
160 // Is this the root name?
161 //
162 if (c == '.') {
163 if (s != send) {
165 "non terminating empty label in " <<
166 string(orig_s, send));
167 }
168 is_root = true;
169 } else if (c == '@' && s == send) {
170 // handle a single '@' as the root name.
171 is_root = true;
172 }
173
174 if (is_root) {
175 ndata.push_back(0);
176 done = true;
177 break;
178 }
179
180 // FALLTHROUGH
181 case ft_start:
182 ndata.push_back(0); // placeholder for the label length field
183 count = 0;
184 if (c == '\\') {
185 state = ft_initialescape;
186 break;
187 }
188 state = ft_ordinary;
189 isc_throw_assert(ndata.size() < Name::MAX_WIRE);
190 // FALLTHROUGH
191 case ft_ordinary:
192 if (c == '.') {
193 if (count == 0) {
195 "duplicate period in " << string(orig_s, send));
196 }
197 ndata.at(offsets.back()) = count;
198 offsets.push_back(ndata.size());
199 if (s == send) {
200 ndata.push_back(0);
201 done = true;
202 }
203 state = ft_start;
204 } else if (c == '\\') {
205 state = ft_escape;
206 } else {
207 if (++count > Name::MAX_LABELLEN) {
209 "label is too long in " << string(orig_s, send));
210 }
211 ndata.push_back(downcase ? maptolower[c] : c);
212 }
213 break;
214 case ft_initialescape:
215 if (c == '[') {
216 // This looks like a bitstring label, which was deprecated.
217 // Intentionally drop it.
219 "invalid label type in " << string(orig_s, send));
220 }
221 // FALLTHROUGH
222 case ft_escape:
223 if (!isdigit(c & 0xff)) {
224 if (++count > Name::MAX_LABELLEN) {
226 "label is too long in " << string(orig_s, send));
227 }
228 ndata.push_back(downcase ? maptolower[c] : c);
229 state = ft_ordinary;
230 break;
231 }
232 digits = 0;
233 value = 0;
234 state = ft_escdecimal;
235 // FALLTHROUGH
236 case ft_escdecimal:
237 if (!isdigit(c & 0xff)) {
239 "mixture of escaped digit and non-digit in "
240 << string(orig_s, send));
241 }
242 value *= 10;
243 value += digitvalue[c];
244 digits++;
245 if (digits == 3) {
246 if (value > 255) {
248 "escaped decimal is too large in "
249 << string(orig_s, send));
250 }
251 if (++count > Name::MAX_LABELLEN) {
253 "label is too long in " << string(orig_s, send));
254 }
255 ndata.push_back(downcase ? maptolower[value] : value);
256 state = ft_ordinary;
257 }
258 break;
259 default:
260 // impossible case
261 isc_throw_assert(false);
262 }
263 }
264
265 if (!done) { // no trailing '.' was found.
266 if (ndata.size() == Name::MAX_WIRE) {
268 "name is too long for termination in " <<
269 string(orig_s, send));
270 }
271 isc_throw_assert(s == send);
272 if (state != ft_ordinary) {
274 "incomplete textual name in " <<
275 (empty ? "<empty>" : string(orig_s, send)));
276 }
277 if (state == ft_ordinary) {
278 isc_throw_assert(count != 0);
279 ndata.at(offsets.back()) = count;
280
281 offsets.push_back(ndata.size());
282 // add a trailing \0
283 ndata.push_back('\0');
284 }
285 }
286}
287
288}
289
290Name::Name(const std::string &namestring, bool downcase) {
291 // Prepare inputs for the parser
292 const std::string::const_iterator s = namestring.begin();
293 const std::string::const_iterator send = namestring.end();
294
295 // Prepare outputs
296 NameOffsets offsets;
297 NameString ndata;
298
299 // To the parsing
300 stringParse(s, send, downcase, offsets, ndata);
301
302 // And get the output
303 labelcount_ = offsets.size();
304 isc_throw_assert(labelcount_ > 0 && labelcount_ <= Name::MAX_LABELS);
305 ndata_.assign(ndata.data(), ndata.data() + ndata.size());
306 length_ = ndata_.size();
307 offsets_.assign(offsets.begin(), offsets.end());
308}
309
310Name::Name(const char* namedata, size_t data_len, const Name* origin,
311 bool downcase) {
312 // Check validity of data
313 if (!namedata || data_len == 0) {
315 "No data provided to Name constructor");
316 }
317 // If the last character is not a dot, it is a relative to origin.
318 // It is safe to check now, we know there's at least one character.
319 const bool absolute = (namedata[data_len - 1] == '.');
320 // If we are not absolute, we need the origin to complete the name.
321 if (!absolute && !origin) {
323 "No origin available and name is relative");
324 }
325 // Prepare inputs for the parser
326 const char* end = namedata + data_len;
327
328 // Prepare outputs
329 NameOffsets offsets;
330 NameString ndata;
331
332 // Do the actual parsing
333 stringParse(namedata, end, downcase, offsets, ndata);
334
335 // Get the output
336 labelcount_ = offsets.size();
337 isc_throw_assert(labelcount_ > 0 && labelcount_ <= Name::MAX_LABELS);
338 ndata_.assign(ndata.data(), ndata.data() + ndata.size());
339 length_ = ndata_.size();
340 offsets_.assign(offsets.begin(), offsets.end());
341
342 if (!absolute) {
343 // Now, extend the data with the ones from origin. But eat the
344 // last label (the empty one).
345
346 // Drop the last character of the data (the \0) and append a copy of
347 // the origin's data
348 ndata_.erase(ndata_.end() - 1);
349 ndata_.insert(ndata_.end(), origin->ndata_.begin(), origin->ndata_.end());
350
351 // Do a similar thing with offsets. However, we need to move them
352 // so they point after the prefix we parsed before.
353 size_t offset = offsets_.back();
354 offsets_.pop_back();
355 size_t offset_count = offsets_.size();
356 offsets_.insert(offsets_.end(), origin->offsets_.begin(),
357 origin->offsets_.end());
358 for (auto it(offsets_.begin() + offset_count); it != offsets_.end(); ++it) {
359 *it += offset;
360 }
361
362 // Adjust sizes.
363 length_ = ndata_.size();
364 labelcount_ = offsets_.size();
365
366 // And check the sizes are OK.
367 if (labelcount_ > Name::MAX_LABELS || length_ > Name::MAX_WIRE) {
368 isc_throw(TooLongName, "Combined name is too long");
369 }
370 }
371}
372
373namespace {
377typedef enum {
378 fw_start = 0, // beginning of a label
379 fw_ordinary, // inside an ordinary (non compressed) label
380 fw_newcurrent // beginning of a compression pointer
381} fw_state;
382}
383
384Name::Name(InputBuffer& buffer, bool downcase) {
385 NameOffsets offsets;
386 offsets.reserve(Name::MAX_LABELS);
387
388 /*
389 * Initialize things to make the compiler happy; they're not required.
390 */
391 unsigned int n = 0;
392
393 //
394 // Set up.
395 //
396 bool done = false;
397 unsigned int nused = 0;
398 bool seen_pointer = false;
399 fw_state state = fw_start;
400
401 unsigned int cused = 0; // Bytes of compressed name data used
402 unsigned int current = buffer.getPosition();
403 unsigned int pos_begin = current;
404 unsigned int biggest_pointer = current;
405
406 // Make the compiler happy; this is not required.
407 // XXX: bad style in that we initialize it with a dummy value and define
408 // it far from where it's used. But alternatives seemed even worse.
409 unsigned int new_current = 0;
410
411 //
412 // Note: The following code is not optimized for speed, but
413 // rather for correctness. Speed will be addressed in the future.
414 //
415 while (current < buffer.getLength() && !done) {
416 unsigned int c = buffer.readUint8();
417 current++;
418 if (!seen_pointer) {
419 cused++;
420 }
421
422 switch (state) {
423 case fw_start:
424 if (c <= MAX_LABELLEN) {
425 offsets.push_back(nused);
426 if (nused + c + 1 > Name::MAX_WIRE) {
427 isc_throw(DNSMessageFORMERR, "wire name is too long: "
428 << nused + c + 1 << " bytes");
429 }
430 nused += c + 1;
431 ndata_.push_back(c);
432 if (c == 0) {
433 done = true;
434 }
435 n = c;
436 state = fw_ordinary;
438 //
439 // Ordinary 14-bit pointer.
440 //
441 new_current = c & ~COMPRESS_POINTER_MARK8;
442 n = 1;
443 state = fw_newcurrent;
444 } else {
445 // this case includes local compression pointer, which hasn't
446 // been standardized.
447 isc_throw(DNSMessageFORMERR, "unknown label character: " << c);
448 }
449 break;
450 case fw_ordinary:
451 if (downcase) {
452 c = maptolower[c];
453 }
454 ndata_.push_back(c);
455 if (--n == 0) {
456 state = fw_start;
457 }
458 break;
459 case fw_newcurrent:
460 new_current *= 256;
461 new_current += c;
462 if (--n != 0) {
463 break;
464 }
465 if (new_current >= biggest_pointer) {
467 "bad compression pointer (out of range): " <<
468 new_current);
469 }
470 biggest_pointer = new_current;
471 current = new_current;
472 buffer.setPosition(current);
473 seen_pointer = true;
474 state = fw_start;
475 break;
476 default:
477 isc_throw_assert(false);
478 }
479 }
480
481 if (!done) {
482 isc_throw(DNSMessageFORMERR, "incomplete wire-format name");
483 }
484
485 labelcount_ = offsets.size();
486 isc_throw_assert(labelcount_ > 0 && labelcount_ <= Name::MAX_LABELS);
487 length_ = nused;
488 offsets_.assign(offsets.begin(), offsets.end());
489 buffer.setPosition(pos_begin + cused);
490}
491
492void
494 buffer.writeData(ndata_.data(), ndata_.size());
495}
496
497void
499 renderer.writeName(*this);
500}
501
502std::string
503Name::toText(bool omit_final_dot) const {
504 LabelSequence ls(*this);
505 return (ls.toText(omit_final_dot));
506}
507
508std::string
509Name::toRawText(bool omit_final_dot) const {
510 LabelSequence ls(*this);
511 return (ls.toRawText(omit_final_dot));
512}
513
515Name::compare(const Name& other) const {
516 const LabelSequence ls1(*this);
517 const LabelSequence ls2(other);
518 return (ls1.compare(ls2));
519}
520
521bool
522Name::equals(const Name& other) const {
523 if (length_ != other.length_ || labelcount_ != other.labelcount_) {
524 return (false);
525 }
526
527 for (unsigned int l = labelcount_, pos = 0; l > 0; --l) {
528 uint8_t count = ndata_[pos];
529 if (count != other.ndata_[pos]) {
530 return (false);
531 }
532 ++pos;
533
534 while (count-- > 0) {
535 uint8_t label1 = ndata_[pos];
536 uint8_t label2 = other.ndata_[pos];
537
538 if (maptolower[label1] != maptolower[label2]) {
539 return (false);
540 }
541 ++pos;
542 }
543 }
544
545 return (true);
546}
547
548bool
549Name::leq(const Name& other) const {
550 return (compare(other).getOrder() <= 0);
551}
552
553bool
554Name::geq(const Name& other) const {
555 return (compare(other).getOrder() >= 0);
556}
557
558bool
559Name::lthan(const Name& other) const {
560 return (compare(other).getOrder() < 0);
561}
562
563bool
564Name::gthan(const Name& other) const {
565 return (compare(other).getOrder() > 0);
566}
567
568bool
570 return (length_ >= 2 && ndata_[0] == 1 && ndata_[1] == '*');
571}
572
573Name
574Name::concatenate(const Name& suffix) const {
575 isc_throw_assert(length_ > 0 && suffix.length_ > 0);
576 isc_throw_assert(labelcount_ > 0 && suffix.labelcount_ > 0);
577
578 unsigned int length = length_ + suffix.length_ - 1;
579 if (length > Name::MAX_WIRE) {
580 isc_throw(TooLongName, "names are too long to concatenate");
581 }
582
583 Name retname;
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());
588 isc_throw_assert(retname.ndata_.size() == length);
589 retname.length_ = length;
590
591 //
592 // Setup the offsets vector. Copy the offsets of this (prefix) name,
593 // excluding that for the trailing dot, and append the offsets of the
594 // suffix name with the additional offset of the length of the prefix.
595 //
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); });
603 isc_throw_assert(retname.offsets_.size() == labels);
604 retname.labelcount_ = labels;
605
606 return (retname);
607}
608
609Name
611 Name retname;
612 //
613 // Set up offsets: The size of the string and number of labels will
614 // be the same in as in the original.
615 //
616 retname.offsets_.reserve(labelcount_);
617 retname.ndata_.reserve(length_);
618
619 // Copy the original name, label by label, from tail to head.
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());
627 ++rit0;
628 ++rit1;
629 }
630 retname.ndata_.push_back(0);
631
632 retname.labelcount_ = labelcount_;
633 retname.length_ = length_;
634
635 return (retname);
636}
637
638Name
639Name::split(const unsigned int first, const unsigned int n) const {
640 if (n == 0 || n > labelcount_ || first > labelcount_ - n) {
641 isc_throw(OutOfRange, "Name::split: invalid split range");
642 }
643
644 Name retname;
645 // If the specified range doesn't include the trailing dot, we need one
646 // more label for that.
647 unsigned int newlabels = (first + n == labelcount_) ? n : n + 1;
648
649 //
650 // Set up offsets: copy the corresponding range of the original offsets
651 // with subtracting an offset of the prefix length.
652 //
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]); });
657
658 //
659 // Set up the new name. At this point the tail of the new offsets specifies
660 // the position of the trailing dot, which should be equal to the length of
661 // the extracted portion excluding the dot. First copy that part from the
662 // original name, and append the trailing dot explicitly.
663 //
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);
668
669 retname.length_ = retname.ndata_.size();
670 retname.labelcount_ = retname.offsets_.size();
671 isc_throw_assert(retname.labelcount_ == newlabels);
672
673 return (retname);
674}
675
676Name
677Name::split(const unsigned int level) const {
678 if (level >= getLabelCount()) {
679 isc_throw(OutOfRange, "invalid level for name split (" << level
680 << ") for name " << *this);
681 }
682
683 return (split(level, getLabelCount() - level));
684}
685
686Name&
688 unsigned int nlen = length_;
689 unsigned int labels = labelcount_;
690 unsigned int pos = 0;
691
692 while (labels > 0 && nlen > 0) {
693 --labels;
694 --nlen;
695
696 // we assume a valid name, and do abort() if the assumption fails
697 // rather than throwing an exception.
698 unsigned int count = ndata_.at(pos++);
700 isc_throw_assert(nlen >= count);
701
702 while (count > 0) {
703 ndata_.at(pos) =
704 maptolower[ndata_.at(pos)];
705 ++pos;
706 --nlen;
707 --count;
708 }
709 }
710
711 return (*this);
712}
713
714std::ostream&
715operator<<(std::ostream& os, const Name& name) {
716 os << name.toText();
717 return (os);
718}
719
720}
721}
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...
virtual void writeName(const Name &name, bool compress=true)=0
Write a Name object into the internal buffer in wire format, with or without name compression.
A standard DNS module exception that is thrown if the name parser fails to decode a back-slash escape...
Definition name.h:68
A standard DNS module exception that is thrown if the name parser encounters an obsolete or incomplet...
Definition name.h:58
A standard DNS module exception that is thrown if the name parser encounters an empty label in the mi...
Definition name.h:26
A standard DNS module exception that is thrown if the name parser finds the input (string or wire-for...
Definition name.h:81
std::string toRawText(bool omit_final_dot) const
Convert the LabelSequence to a string without escape sequences.
NameComparisonResult compare(const LabelSequence &other, bool case_sensitive=false) const
Compares two label sequences.
std::string toText() const
Convert the LabelSequence to a string.
Thrown when origin is null and is needed.
Definition name.h:92
This is a supplemental class used only as a return value of Name::compare() and LabelSequence::compar...
Definition name.h:113
The Name class encapsulates DNS names.
Definition name.h:219
static const size_t MAX_LABELLEN
Max allowable length of labels of a domain name.
Definition name.h:704
Name reverse() const
Reverse the labels of a name.
Definition name.cc:610
bool lthan(const Name &other) const
Less-than comparison for Name against other.
Definition name.cc:559
NameComparisonResult compare(const Name &other) const
Compare two Names.
Definition name.cc:515
bool equals(const Name &other) const
Return true iff two names are equal.
Definition name.cc:522
bool geq(const Name &other) const
Greater-than or equal comparison for Name against other.
Definition name.cc:554
static const size_t MAX_WIRE
Max allowable length of domain names.
Definition name.h:695
Name split(unsigned int first, unsigned int n) const
Extract a specified subpart of Name.
Definition name.cc:639
friend class LabelSequence
Definition name.h:223
std::string toText(bool omit_final_dot=false) const
Convert the Name to a string.
Definition name.cc:503
void toWire(AbstractMessageRenderer &renderer) const
Render the Name in the wire format with compression.
Definition name.cc:498
unsigned int getLabelCount() const
Returns the number of labels contained in the Name.
Definition name.h:366
static const size_t MAX_LABELS
Max allowable labels of domain names.
Definition name.h:701
bool gthan(const Name &other) const
Greater-than comparison for Name against other.
Definition name.cc:564
Name concatenate(const Name &suffix) const
Concatenate two names.
Definition name.cc:574
std::string toRawText(bool omit_final_dot=false) const
Convert the LabelSequence to a string without escape sequences.
Definition name.cc:509
static const uint16_t COMPRESS_POINTER_MARK8
A 8-bit masked value indicating a start of compression pointer.
Definition name.h:713
bool leq(const Name &other) const
Less-than or equal comparison for Name against other.
Definition name.cc:549
Name & downcase()
Downcase all upper case alphabet characters in the name.
Definition name.cc:687
bool isWildcard() const
Test if this is a wildcard name.
Definition name.cc:569
A standard DNS module exception that is thrown if the name parser encounters too long a label.
Definition name.h:46
A standard DNS module exception that is thrown if the name parser encounters too long a name.
Definition name.h:36
The InputBuffer class is a buffer abstraction for manipulating read-only data.
Definition buffer.h:81
void setPosition(size_t position)
Set the read position of the buffer to the given value.
Definition buffer.h:112
size_t getPosition() const
Return the current read position.
Definition buffer.h:101
uint8_t readUint8()
Read an unsigned 8-bit integer from the buffer and return it.
Definition buffer.h:138
size_t getLength() const
Return the length of the data stored in the buffer.
Definition buffer.h:96
The OutputBuffer class is a buffer abstraction for manipulating mutable data.
Definition buffer.h:346
void writeData(const void *data, size_t len)
Copy an arbitrary length of data into the buffer.
Definition buffer.h:559
#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.
Definition isc_assert.h:18
const uint8_t maptolower[]
Definition name.cc:71
ostream & operator<<(std::ostream &os, const EDNS &edns)
Insert the EDNS as a string into stream.
Definition edns.cc:163
Defines the logger used by the top-level component of kea-lfc.