Kea 2.2.0
name.cc
Go to the documentation of this file.
1// Copyright (C) 2009-2019 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
9#include <cctype>
10#include <iterator>
11#include <functional>
12#include <vector>
13#include <iostream>
14#include <algorithm>
15
17#include <util/buffer.h>
18#include <dns/exceptions.h>
19#include <dns/name.h>
20#include <dns/name_internal.h>
21#include <dns/messagerenderer.h>
22#include <dns/labelsequence.h>
23
24using namespace std;
25using namespace isc::util;
27using namespace isc::dns::name::internal;
28
29namespace isc {
30namespace dns {
31
32namespace {
51const signed char digitvalue[256] = {
52 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 16
53 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 32
54 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 48
55 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, // 64
56 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 80
57 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 96
58 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 112
59 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 128
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,
66 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
67 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 256
68};
69}
70
71namespace name {
72namespace internal {
73const uint8_t maptolower[] = {
74 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
75 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
76 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
77 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
78 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
79 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
80 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
81 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
82 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, // ..., 'A' - 'G'
83 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, // 'H' - 'O'
84 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, // 'P' - 'W'
85 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, // 'X' - 'Z', ...
86 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
87 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
88 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
89 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
90 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
91 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
92 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
93 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
94 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
95 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
96 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
97 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
98 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
99 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
100 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
101 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
102 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
103 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
104 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
105 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
106};
107} // end of internal
108} // end of name
109
110namespace {
114typedef enum {
115 ft_init = 0, // begin of the name
116 ft_start, // begin of a label
117 ft_ordinary, // parsing an ordinary label
118 ft_initialescape, // just found '\'
119 ft_escape, // begin of handling a '\'-escaped sequence
120 ft_escdecimal // parsing a '\DDD' octet.
121} ft_state;
122
123// The parser of name from a string. It is a template, because
124// some parameters are used with two different types, while others
125// are private type aliases.
126template<class Iterator, class Offsets, class Data>
127void
128stringParse(Iterator s, Iterator send, bool downcase, Offsets& offsets,
129 Data& ndata)
130{
131 const Iterator orig_s(s);
132 //
133 // Initialize things to make the compiler happy; they're not required.
134 //
135 unsigned int digits = 0;
136 unsigned int value = 0;
137 unsigned int count = 0;
138
139 //
140 // Set up the state machine.
141 //
142 bool done = false;
143 bool is_root = false;
144 const bool empty = s == send;
145 ft_state state = ft_init;
146
147 // Prepare the output buffers.
148 offsets.reserve(Name::MAX_LABELS);
149 offsets.push_back(0);
150 ndata.reserve(Name::MAX_WIRE);
151
152 // should we refactor this code using, e.g, the state pattern? Probably
153 // not at this point, as this is based on proved code (derived from BIND9)
154 // and it's less likely that we'll have more variations in the domain name
155 // syntax. If this ever happens next time, we should consider refactor
156 // the code, rather than adding more states and cases below.
157 while (ndata.size() < Name::MAX_WIRE && s != send && !done) {
158 unsigned char c = *s++;
159
160 switch (state) {
161 case ft_init:
162 //
163 // Is this the root name?
164 //
165 if (c == '.') {
166 if (s != send) {
167 isc_throw(EmptyLabel,
168 "non terminating empty label in " <<
169 string(orig_s, send));
170 }
171 is_root = true;
172 } else if (c == '@' && s == send) {
173 // handle a single '@' as the root name.
174 is_root = true;
175 }
176
177 if (is_root) {
178 ndata.push_back(0);
179 done = true;
180 break;
181 }
182
183 // FALLTHROUGH
184 case ft_start:
185 ndata.push_back(0); // placeholder for the label length field
186 count = 0;
187 if (c == '\\') {
188 state = ft_initialescape;
189 break;
190 }
191 state = ft_ordinary;
192 isc_throw_assert(ndata.size() < Name::MAX_WIRE);
193 // FALLTHROUGH
194 case ft_ordinary:
195 if (c == '.') {
196 if (count == 0) {
197 isc_throw(EmptyLabel,
198 "duplicate period in " << string(orig_s, send));
199 }
200 ndata.at(offsets.back()) = count;
201 offsets.push_back(ndata.size());
202 if (s == send) {
203 ndata.push_back(0);
204 done = true;
205 }
206 state = ft_start;
207 } else if (c == '\\') {
208 state = ft_escape;
209 } else {
210 if (++count > Name::MAX_LABELLEN) {
211 isc_throw(TooLongLabel,
212 "label is too long in " << string(orig_s, send));
213 }
214 ndata.push_back(downcase ? maptolower[c] : c);
215 }
216 break;
217 case ft_initialescape:
218 if (c == '[') {
219 // This looks like a bitstring label, which was deprecated.
220 // Intentionally drop it.
221 isc_throw(BadLabelType,
222 "invalid label type in " << string(orig_s, send));
223 }
224 // FALLTHROUGH
225 case ft_escape:
226 if (!isdigit(c & 0xff)) {
227 if (++count > Name::MAX_LABELLEN) {
228 isc_throw(TooLongLabel,
229 "label is too long in " << string(orig_s, send));
230 }
231 ndata.push_back(downcase ? maptolower[c] : c);
232 state = ft_ordinary;
233 break;
234 }
235 digits = 0;
236 value = 0;
237 state = ft_escdecimal;
238 // FALLTHROUGH
239 case ft_escdecimal:
240 if (!isdigit(c & 0xff)) {
241 isc_throw(BadEscape,
242 "mixture of escaped digit and non-digit in "
243 << string(orig_s, send));
244 }
245 value *= 10;
246 value += digitvalue[c];
247 digits++;
248 if (digits == 3) {
249 if (value > 255) {
250 isc_throw(BadEscape,
251 "escaped decimal is too large in "
252 << string(orig_s, send));
253 }
254 if (++count > Name::MAX_LABELLEN) {
255 isc_throw(TooLongLabel,
256 "label is too long in " << string(orig_s, send));
257 }
258 ndata.push_back(downcase ? maptolower[value] : value);
259 state = ft_ordinary;
260 }
261 break;
262 default:
263 // impossible case
264 isc_throw_assert(false);
265 }
266 }
267
268 if (!done) { // no trailing '.' was found.
269 if (ndata.size() == Name::MAX_WIRE) {
270 isc_throw(TooLongName,
271 "name is too long for termination in " <<
272 string(orig_s, send));
273 }
274 isc_throw_assert(s == send);
275 if (state != ft_ordinary) {
276 isc_throw(IncompleteName,
277 "incomplete textual name in " <<
278 (empty ? "<empty>" : string(orig_s, send)));
279 }
280 if (state == ft_ordinary) {
281 isc_throw_assert(count != 0);
282 ndata.at(offsets.back()) = count;
283
284 offsets.push_back(ndata.size());
285 // add a trailing \0
286 ndata.push_back('\0');
287 }
288 }
289}
290
291}
292
293Name::Name(const std::string &namestring, bool downcase) {
294 // Prepare inputs for the parser
295 const std::string::const_iterator s = namestring.begin();
296 const std::string::const_iterator send = namestring.end();
297
298 // Prepare outputs
299 NameOffsets offsets;
300 NameString ndata;
301
302 // To the parsing
303 stringParse(s, send, downcase, offsets, ndata);
304
305 // And get the output
306 labelcount_ = offsets.size();
307 isc_throw_assert(labelcount_ > 0 && labelcount_ <= Name::MAX_LABELS);
308 ndata_.assign(ndata.data(), ndata.size());
309 length_ = ndata_.size();
310 offsets_.assign(offsets.begin(), offsets.end());
311}
312
313Name::Name(const char* namedata, size_t data_len, const Name* origin,
314 bool downcase)
315{
316 // Check validity of data
317 if (namedata == NULL || data_len == 0) {
319 "No data provided to Name constructor");
320 }
321 // If the last character is not a dot, it is a relative to origin.
322 // It is safe to check now, we know there's at least one character.
323 const bool absolute = (namedata[data_len - 1] == '.');
324 // If we are not absolute, we need the origin to complete the name.
325 if (!absolute && origin == NULL) {
327 "No origin available and name is relative");
328 }
329 // Prepare inputs for the parser
330 const char* end = namedata + data_len;
331
332 // Prepare outputs
333 NameOffsets offsets;
334 NameString ndata;
335
336 // Do the actual parsing
337 stringParse(namedata, end, downcase, offsets, ndata);
338
339 // Get the output
340 labelcount_ = offsets.size();
341 isc_throw_assert(labelcount_ > 0 && labelcount_ <= Name::MAX_LABELS);
342 ndata_.assign(ndata.data(), ndata.size());
343 length_ = ndata_.size();
344 offsets_.assign(offsets.begin(), offsets.end());
345
346 if (!absolute) {
347 // Now, extend the data with the ones from origin. But eat the
348 // last label (the empty one).
349
350 // Drop the last character of the data (the \0) and append a copy of
351 // the origin's data
352 ndata_.erase(ndata_.end() - 1);
353 ndata_.append(origin->ndata_);
354
355 // Do a similar thing with offsets. However, we need to move them
356 // so they point after the prefix we parsed before.
357 size_t offset = offsets_.back();
358 offsets_.pop_back();
359 size_t offset_count = offsets_.size();
360 offsets_.insert(offsets_.end(), origin->offsets_.begin(),
361 origin->offsets_.end());
362 for (NameOffsets::iterator it(offsets_.begin() + offset_count);
363 it != offsets_.end(); ++it) {
364 *it += offset;
365 }
366
367 // Adjust sizes.
368 length_ = ndata_.size();
369 labelcount_ = offsets_.size();
370
371 // And check the sizes are OK.
372 if (labelcount_ > Name::MAX_LABELS || length_ > Name::MAX_WIRE) {
373 isc_throw(TooLongName, "Combined name is too long");
374 }
375 }
376}
377
378namespace {
382typedef enum {
383 fw_start = 0, // beginning of a label
384 fw_ordinary, // inside an ordinary (non compressed) label
385 fw_newcurrent // beginning of a compression pointer
386} fw_state;
387}
388
389Name::Name(InputBuffer& buffer, bool downcase) {
390 NameOffsets offsets;
391 offsets.reserve(Name::MAX_LABELS);
392
393 /*
394 * Initialize things to make the compiler happy; they're not required.
395 */
396 unsigned int n = 0;
397
398 //
399 // Set up.
400 //
401 bool done = false;
402 unsigned int nused = 0;
403 bool seen_pointer = false;
404 fw_state state = fw_start;
405
406 unsigned int cused = 0; // Bytes of compressed name data used
407 unsigned int current = buffer.getPosition();
408 unsigned int pos_begin = current;
409 unsigned int biggest_pointer = current;
410
411 // Make the compiler happy; this is not required.
412 // XXX: bad style in that we initialize it with a dummy value and define
413 // it far from where it's used. But alternatives seemed even worse.
414 unsigned int new_current = 0;
415
416 //
417 // Note: The following code is not optimized for speed, but
418 // rather for correctness. Speed will be addressed in the future.
419 //
420 while (current < buffer.getLength() && !done) {
421 unsigned int c = buffer.readUint8();
422 current++;
423 if (!seen_pointer) {
424 cused++;
425 }
426
427 switch (state) {
428 case fw_start:
429 if (c <= MAX_LABELLEN) {
430 offsets.push_back(nused);
431 if (nused + c + 1 > Name::MAX_WIRE) {
432 isc_throw(DNSMessageFORMERR, "wire name is too long: "
433 << nused + c + 1 << " bytes");
434 }
435 nused += c + 1;
436 ndata_.push_back(c);
437 if (c == 0) {
438 done = true;
439 }
440 n = c;
441 state = fw_ordinary;
443 //
444 // Ordinary 14-bit pointer.
445 //
446 new_current = c & ~COMPRESS_POINTER_MARK8;
447 n = 1;
448 state = fw_newcurrent;
449 } else {
450 // this case includes local compression pointer, which hasn't
451 // been standardized.
452 isc_throw(DNSMessageFORMERR, "unknown label character: " << c);
453 }
454 break;
455 case fw_ordinary:
456 if (downcase) {
457 c = maptolower[c];
458 }
459 ndata_.push_back(c);
460 if (--n == 0) {
461 state = fw_start;
462 }
463 break;
464 case fw_newcurrent:
465 new_current *= 256;
466 new_current += c;
467 if (--n != 0) {
468 break;
469 }
470 if (new_current >= biggest_pointer) {
472 "bad compression pointer (out of range): " <<
473 new_current);
474 }
475 biggest_pointer = new_current;
476 current = new_current;
477 buffer.setPosition(current);
478 seen_pointer = true;
479 state = fw_start;
480 break;
481 default:
482 isc_throw_assert(false);
483 }
484 }
485
486 if (!done) {
487 isc_throw(DNSMessageFORMERR, "incomplete wire-format name");
488 }
489
490 labelcount_ = offsets.size();
491 length_ = nused;
492 offsets_.assign(offsets.begin(), offsets.end());
493 buffer.setPosition(pos_begin + cused);
494}
495
496void
498 buffer.writeData(ndata_.data(), ndata_.size());
499}
500
501void
503 renderer.writeName(*this);
504}
505
506std::string
507Name::toText(bool omit_final_dot) const {
508 LabelSequence ls(*this);
509 return (ls.toText(omit_final_dot));
510}
511
512std::string
513Name::toRawText(bool omit_final_dot) const {
514 LabelSequence ls(*this);
515 return (ls.toRawText(omit_final_dot));
516}
517
519Name::compare(const Name& other) const {
520 const LabelSequence ls1(*this);
521 const LabelSequence ls2(other);
522 return (ls1.compare(ls2));
523}
524
525bool
526Name::equals(const Name& other) const {
527 if (length_ != other.length_ || labelcount_ != other.labelcount_) {
528 return (false);
529 }
530
531 for (unsigned int l = labelcount_, pos = 0; l > 0; --l) {
532 uint8_t count = ndata_[pos];
533 if (count != other.ndata_[pos]) {
534 return (false);
535 }
536 ++pos;
537
538 while (count-- > 0) {
539 uint8_t label1 = ndata_[pos];
540 uint8_t label2 = other.ndata_[pos];
541
542 if (maptolower[label1] != maptolower[label2]) {
543 return (false);
544 }
545 ++pos;
546 }
547 }
548
549 return (true);
550}
551
552bool
553Name::leq(const Name& other) const {
554 return (compare(other).getOrder() <= 0);
555}
556
557bool
558Name::geq(const Name& other) const {
559 return (compare(other).getOrder() >= 0);
560}
561
562bool
563Name::lthan(const Name& other) const {
564 return (compare(other).getOrder() < 0);
565}
566
567bool
568Name::gthan(const Name& other) const {
569 return (compare(other).getOrder() > 0);
570}
571
572bool
574 return (length_ >= 2 && ndata_[0] == 1 && ndata_[1] == '*');
575}
576
577Name
578Name::concatenate(const Name& suffix) const {
579 isc_throw_assert(length_ > 0 && suffix.length_ > 0);
580 isc_throw_assert(labelcount_ > 0 && suffix.labelcount_ > 0);
581
582 unsigned int length = length_ + suffix.length_ - 1;
583 if (length > Name::MAX_WIRE) {
584 isc_throw(TooLongName, "names are too long to concatenate");
585 }
586
587 Name retname;
588 retname.ndata_.reserve(length);
589 retname.ndata_.assign(ndata_, 0, length_ - 1);
590 retname.ndata_.insert(retname.ndata_.end(),
591 suffix.ndata_.begin(), suffix.ndata_.end());
592 isc_throw_assert(retname.ndata_.size() == length);
593 retname.length_ = length;
594
595 //
596 // Setup the offsets vector. Copy the offsets of this (prefix) name,
597 // excluding that for the trailing dot, and append the offsets of the
598 // suffix name with the additional offset of the length of the prefix.
599 //
600 unsigned int labels = labelcount_ + suffix.labelcount_ - 1;
602 retname.offsets_.reserve(labels);
603 retname.offsets_.assign(&offsets_[0], &offsets_[0] + labelcount_ - 1);
604 transform(suffix.offsets_.begin(), suffix.offsets_.end(),
605 back_inserter(retname.offsets_),
606 [this] (char x) { return (x + length_ - 1); });
607 isc_throw_assert(retname.offsets_.size() == labels);
608 retname.labelcount_ = labels;
609
610 return (retname);
611}
612
613Name
615 Name retname;
616 //
617 // Set up offsets: The size of the string and number of labels will
618 // be the same in as in the original.
619 //
620 retname.offsets_.reserve(labelcount_);
621 retname.ndata_.reserve(length_);
622
623 // Copy the original name, label by label, from tail to head.
624 NameOffsets::const_reverse_iterator rit0 = offsets_.rbegin();
625 NameOffsets::const_reverse_iterator rit1 = rit0 + 1;
626 NameString::const_iterator n0 = ndata_.begin();
627 retname.offsets_.push_back(0);
628 while (rit1 != offsets_.rend()) {
629 retname.ndata_.append(n0 + *rit1, n0 + *rit0);
630 retname.offsets_.push_back(retname.ndata_.size());
631 ++rit0;
632 ++rit1;
633 }
634 retname.ndata_.push_back(0);
635
636 retname.labelcount_ = labelcount_;
637 retname.length_ = length_;
638
639 return (retname);
640}
641
642Name
643Name::split(const unsigned int first, const unsigned int n) const {
644 if (n == 0 || n > labelcount_ || first > labelcount_ - n) {
645 isc_throw(OutOfRange, "Name::split: invalid split range");
646 }
647
648 Name retname;
649 // If the specified range doesn't include the trailing dot, we need one
650 // more label for that.
651 unsigned int newlabels = (first + n == labelcount_) ? n : n + 1;
652
653 //
654 // Set up offsets: copy the corresponding range of the original offsets
655 // with subtracting an offset of the prefix length.
656 //
657 retname.offsets_.reserve(newlabels);
658 transform(offsets_.begin() + first, offsets_.begin() + first + newlabels,
659 back_inserter(retname.offsets_),
660 [&](char x) { return (x - offsets_[first]); });
661
662 //
663 // Set up the new name. At this point the tail of the new offsets specifies
664 // the position of the trailing dot, which should be equal to the length of
665 // the extracted portion excluding the dot. First copy that part from the
666 // original name, and append the trailing dot explicitly.
667 //
668 retname.ndata_.reserve(retname.offsets_.back() + 1);
669 retname.ndata_.assign(ndata_, offsets_[first], retname.offsets_.back());
670 retname.ndata_.push_back(0);
671
672 retname.length_ = retname.ndata_.size();
673 retname.labelcount_ = retname.offsets_.size();
674 isc_throw_assert(retname.labelcount_ == newlabels);
675
676 return (retname);
677}
678
679Name
680Name::split(const unsigned int level) const {
681 if (level >= getLabelCount()) {
682 isc_throw(OutOfRange, "invalid level for name split (" << level
683 << ") for name " << *this);
684 }
685
686 return (split(level, getLabelCount() - level));
687}
688
689Name&
691 unsigned int nlen = length_;
692 unsigned int labels = labelcount_;
693 unsigned int pos = 0;
694
695 while (labels > 0 && nlen > 0) {
696 --labels;
697 --nlen;
698
699 // we assume a valid name, and do abort() if the assumption fails
700 // rather than throwing an exception.
701 unsigned int count = ndata_.at(pos++);
703 isc_throw_assert(nlen >= count);
704
705 while (count > 0) {
706 ndata_.at(pos) =
707 maptolower[ndata_.at(pos)];
708 ++pos;
709 --nlen;
710 --count;
711 }
712 }
713
714 return (*this);
715}
716
717std::ostream&
718operator<<(std::ostream& os, const Name& name) {
719 os << name.toText();
720 return (os);
721}
722
723}
724}
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.
Light-weight Accessor to Name data.
Definition: labelsequence.h:35
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:96
This is a supplemental class used only as a return value of Name::compare() and LabelSequence::compar...
Definition: name.h:117
The Name class encapsulates DNS names.
Definition: name.h:223
static const size_t MAX_LABELLEN
Max allowable length of labels of a domain name.
Definition: name.h:708
Name reverse() const
Reverse the labels of a name.
Definition: name.cc:614
bool lthan(const Name &other) const
Less-than comparison for Name against other
Definition: name.cc:563
NameComparisonResult compare(const Name &other) const
Compare two Names.
Definition: name.cc:519
bool equals(const Name &other) const
Return true iff two names are equal.
Definition: name.cc:526
bool geq(const Name &other) const
Greater-than or equal comparison for Name against other
Definition: name.cc:558
static const size_t MAX_WIRE
Max allowable length of domain names.
Definition: name.h:699
Name split(unsigned int first, unsigned int n) const
Extract a specified subpart of Name.
Definition: name.cc:643
std::string toText(bool omit_final_dot=false) const
Convert the Name to a string.
Definition: name.cc:507
void toWire(AbstractMessageRenderer &renderer) const
Render the Name in the wire format with compression.
Definition: name.cc:502
unsigned int getLabelCount() const
Returns the number of labels contained in the Name.
Definition: name.h:370
static const size_t MAX_LABELS
Max allowable labels of domain names.
Definition: name.h:705
bool gthan(const Name &other) const
Greater-than comparison for Name against other
Definition: name.cc:568
Name concatenate(const Name &suffix) const
Concatenate two names.
Definition: name.cc:578
std::string toRawText(bool omit_final_dot=false) const
Convert the LabelSequence to a string without escape sequences.
Definition: name.cc:513
static const uint16_t COMPRESS_POINTER_MARK8
A 8-bit masked value indicating a start of compression pointer.
Definition: name.h:717
bool leq(const Name &other) const
Less-than or equal comparison for Name against other
Definition: name.cc:553
Name & downcase()
Downcase all upper case alphabet characters in the name.
Definition: name.cc:690
bool isWildcard() const
Test if this is a wildcard name.
Definition: name.cc:573
A standard DNS module exception that is thrown if the name parser encounters too long a name.
Definition: name.h:40
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:115
size_t getPosition() const
Return the current read position.
Definition: buffer.h:102
uint8_t readUint8()
Read an unsigned 8-bit integer from the buffer and return it.
Definition: buffer.h:130
size_t getLength() const
Return the length of the data stored in the buffer.
Definition: buffer.h:100
The OutputBuffer class is a buffer abstraction for manipulating mutable data.
Definition: buffer.h:294
void writeData(const void *data, size_t len)
Copy an arbitrary length of data into the buffer.
Definition: buffer.h:550
#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:73
ostream & operator<<(std::ostream &os, const EDNS &edns)
Insert the EDNS as a string into stream.
Definition: edns.cc:172
Definition: edns.h:19
Defines the logger used by the top-level component of kea-lfc.