Kea 2.2.0
option_data_types.cc
Go to the documentation of this file.
1// Copyright (C) 2012-2021 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/labelsequence.h>
11#include <dns/name.h>
12#include <util/strutil.h>
13#include <util/encode/hex.h>
14#include <algorithm>
15#include <limits>
16
17using namespace isc::asiolink;
18
19namespace {
25std::vector<uint16_t> psid_bitmask = { 0xffff,
26 0x8000, 0xc000, 0xe000, 0xf000,
27 0xf800, 0xfc00, 0xfe00, 0xff00,
28 0xff80, 0xffc0, 0xffe0, 0xfff0,
29 0xfff8, 0xfffc, 0xfffe, 0xffff
30};
31}
32
33namespace isc {
34namespace dhcp {
35
36OptionDataTypeUtil::OptionDataTypeUtil() {
37 data_types_["empty"] = OPT_EMPTY_TYPE;
38 data_types_["binary"] = OPT_BINARY_TYPE;
39 data_types_["boolean"] = OPT_BOOLEAN_TYPE;
40 data_types_["int8"] = OPT_INT8_TYPE;
41 data_types_["int16"] = OPT_INT16_TYPE;
42 data_types_["int32"] = OPT_INT32_TYPE;
43 data_types_["uint8"] = OPT_UINT8_TYPE;
44 data_types_["uint16"] = OPT_UINT16_TYPE;
45 data_types_["uint32"] = OPT_UINT32_TYPE;
46 data_types_["ipv4-address"] = OPT_IPV4_ADDRESS_TYPE;
47 data_types_["ipv6-address"] = OPT_IPV6_ADDRESS_TYPE;
48 data_types_["ipv6-prefix"] = OPT_IPV6_PREFIX_TYPE;
49 data_types_["psid"] = OPT_PSID_TYPE;
50 data_types_["string"] = OPT_STRING_TYPE;
51 data_types_["tuple"] = OPT_TUPLE_TYPE;
52 data_types_["fqdn"] = OPT_FQDN_TYPE;
53 data_types_["record"] = OPT_RECORD_TYPE;
54
55 data_type_names_[OPT_EMPTY_TYPE] = "empty";
56 data_type_names_[OPT_BINARY_TYPE] = "binary";
57 data_type_names_[OPT_BOOLEAN_TYPE] = "boolean";
58 data_type_names_[OPT_INT8_TYPE] = "int8";
59 data_type_names_[OPT_INT16_TYPE] = "int16";
60 data_type_names_[OPT_INT32_TYPE] = "int32";
61 data_type_names_[OPT_UINT8_TYPE] = "uint8";
62 data_type_names_[OPT_UINT16_TYPE] = "uint16";
63 data_type_names_[OPT_UINT32_TYPE] = "uint32";
64 data_type_names_[OPT_IPV4_ADDRESS_TYPE] = "ipv4-address";
65 data_type_names_[OPT_IPV6_ADDRESS_TYPE] = "ipv6-address";
66 data_type_names_[OPT_IPV6_PREFIX_TYPE] = "ipv6-prefix";
67 data_type_names_[OPT_PSID_TYPE] = "psid";
68 data_type_names_[OPT_STRING_TYPE] = "string";
69 data_type_names_[OPT_TUPLE_TYPE] = "tuple";
70 data_type_names_[OPT_FQDN_TYPE] = "fqdn";
71 data_type_names_[OPT_RECORD_TYPE] = "record";
72 // The "unknown" data type is declared here so as
73 // it can be returned by reference by a getDataTypeName
74 // function it no other type is suitable. Other than that
75 // this is unused.
76 data_type_names_[OPT_UNKNOWN_TYPE] = "unknown";
77}
78
80OptionDataTypeUtil::getDataType(const std::string& data_type) {
81 return (OptionDataTypeUtil::instance().getDataTypeImpl(data_type));
82}
83
85OptionDataTypeUtil::getDataTypeImpl(const std::string& data_type) const {
86 std::map<std::string, OptionDataType>::const_iterator data_type_it =
87 data_types_.find(data_type);
88 if (data_type_it != data_types_.end()) {
89 return (data_type_it->second);
90 }
91 return (OPT_UNKNOWN_TYPE);
92}
93
94int
96 switch (data_type) {
98 case OPT_INT8_TYPE:
99 case OPT_UINT8_TYPE:
100 return (1);
101
102 case OPT_INT16_TYPE:
103 case OPT_UINT16_TYPE:
104 return (2);
105
106 case OPT_INT32_TYPE:
107 case OPT_UINT32_TYPE:
108 return (4);
109
111 return (asiolink::V4ADDRESS_LEN);
112
114 return (asiolink::V6ADDRESS_LEN);
115
116 case OPT_PSID_TYPE:
117 return (3);
118
119 default:
120 ;
121 }
122 return (0);
123}
124
125const std::string&
127 return (OptionDataTypeUtil::instance().getDataTypeNameImpl(data_type));
128}
129
130const std::string&
131OptionDataTypeUtil::getDataTypeNameImpl(const OptionDataType data_type) const {
132 std::map<OptionDataType, std::string>::const_iterator data_type_it =
133 data_type_names_.find(data_type);
134 if (data_type_it != data_type_names_.end()) {
135 return (data_type_it->second);
136 }
137 return (data_type_names_.find(OPT_UNKNOWN_TYPE)->second);
138}
139
140OptionDataTypeUtil&
141OptionDataTypeUtil::instance() {
142 static OptionDataTypeUtil instance;
143 return (instance);
144}
145
146asiolink::IOAddress
147OptionDataTypeUtil::readAddress(const std::vector<uint8_t>& buf,
148 const short family) {
149 using namespace isc::asiolink;
150 if (family == AF_INET) {
151 if (buf.size() < V4ADDRESS_LEN) {
152 isc_throw(BadDataTypeCast, "unable to read data from the buffer as"
153 << " IPv4 address. Invalid buffer size: " << buf.size());
154 }
155 return (IOAddress::fromBytes(AF_INET, &buf[0]));
156 } else if (family == AF_INET6) {
157 if (buf.size() < V6ADDRESS_LEN) {
158 isc_throw(BadDataTypeCast, "unable to read data from the buffer as"
159 << " IPv6 address. Invalid buffer size: " << buf.size());
160 }
161 return (IOAddress::fromBytes(AF_INET6, &buf[0]));
162 } else {
163 isc_throw(BadDataTypeCast, "unable to read data from the buffer as"
164 << " IP address. Invalid family: " << family);
165 }
166}
167
168void
170 std::vector<uint8_t>& buf) {
171 const std::vector<uint8_t>& vec = address.toBytes();
172 buf.insert(buf.end(), vec.begin(), vec.end());
173}
174
175void
176OptionDataTypeUtil::writeBinary(const std::string& hex_str,
177 std::vector<uint8_t>& buf) {
178 // Binary value means that the value is encoded as a string
179 // of hexadecimal digits. We need to decode this string
180 // to the binary format here.
181 OptionBuffer binary;
182 try {
183 util::encode::decodeHex(hex_str, binary);
184 } catch (const Exception& ex) {
185 isc_throw(BadDataTypeCast, "unable to cast " << hex_str
186 << " to binary data type: " << ex.what());
187 }
188 // Decode was successful so append decoded binary value
189 // to the buffer.
190 buf.insert(buf.end(), binary.begin(), binary.end());
191}
192
193std::string
194OptionDataTypeUtil::readTuple(const std::vector<uint8_t>& buf,
195 OpaqueDataTuple::LengthFieldType lengthfieldtype) {
196 if (lengthfieldtype == OpaqueDataTuple::LENGTH_1_BYTE) {
197 if (buf.size() < 1) {
198 isc_throw(BadDataTypeCast, "unable to read data from the buffer as"
199 << " tuple (length). Invalid buffer size: "
200 << buf.size());
201 }
202 uint8_t len = buf[0];
203 if (buf.size() < 1 + len) {
204 isc_throw(BadDataTypeCast, "unable to read data from the buffer as"
205 << " tuple (length " << static_cast<unsigned>(len)
206 << "). Invalid buffer size: " << buf.size());
207 }
208 std::string value;
209 value.resize(len);
210 std::memcpy(&value[0], &buf[1], len);
211 return (value);
212 } else if (lengthfieldtype == OpaqueDataTuple::LENGTH_2_BYTES) {
213 if (buf.size() < 2) {
214 isc_throw(BadDataTypeCast, "unable to read data from the buffer as"
215 << " tuple (length). Invalid buffer size: "
216 << buf.size());
217 }
218 uint16_t len = isc::util::readUint16(&buf[0], 2);
219 if (buf.size() < 2 + len) {
220 isc_throw(BadDataTypeCast, "unable to read data from the buffer as"
221 << " tuple (length " << len
222 << "). Invalid buffer size: " << buf.size());
223 }
224 std::string value;
225 value.resize(len);
226 std::memcpy(&value[0], &buf[2], len);
227 return (value);
228 } else {
229 isc_throw(BadDataTypeCast, "unable to read data from the buffer as"
230 << " tuple. Invalid length type field: "
231 << static_cast<unsigned>(lengthfieldtype));
232 }
233}
234
235void
236OptionDataTypeUtil::readTuple(const std::vector<uint8_t>& buf,
237 OpaqueDataTuple& tuple) {
238 try {
239 tuple.unpack(buf.begin(), buf.end());
240 } catch (const OpaqueDataTupleError& ex) {
242 }
243}
244
245void
246OptionDataTypeUtil::writeTuple(const std::string& value,
247 OpaqueDataTuple::LengthFieldType lengthfieldtype,
248 std::vector<uint8_t>& buf) {
249 if (lengthfieldtype == OpaqueDataTuple::LENGTH_1_BYTE) {
250 if (value.size() > std::numeric_limits<uint8_t>::max()) {
251 isc_throw(BadDataTypeCast, "invalid tuple value (size "
252 << value.size() << " larger than "
253 << +std::numeric_limits<uint8_t>::max() << ")");
254 }
255 buf.push_back(static_cast<uint8_t>(value.size()));
256
257 } else if (lengthfieldtype == OpaqueDataTuple::LENGTH_2_BYTES) {
258 if (value.size() > std::numeric_limits<uint16_t>::max()) {
259 isc_throw(BadDataTypeCast, "invalid tuple value (size "
260 << value.size() << " larger than "
261 << std::numeric_limits<uint16_t>::max() << ")");
262 }
263 buf.resize(buf.size() + 2);
264 isc::util::writeUint16(static_cast<uint16_t>(value.size()),
265 &buf[buf.size() - 2], 2);
266 } else {
267 isc_throw(BadDataTypeCast, "unable to write data to the buffer as"
268 << " tuple. Invalid length type field: "
269 << static_cast<unsigned>(lengthfieldtype));
270 }
271 buf.insert(buf.end(), value.begin(), value.end());
272}
273
274void
276 std::vector<uint8_t>& buf) {
277 if (tuple.getLength() == 0) {
278 isc_throw(BadDataTypeCast, "invalid empty tuple value");
279 }
281 if (tuple.getLength() > std::numeric_limits<uint8_t>::max()) {
282 isc_throw(BadDataTypeCast, "invalid tuple value (size "
283 << tuple.getLength() << " larger than "
284 << +std::numeric_limits<uint8_t>::max() << ")");
285 }
286 buf.push_back(static_cast<uint8_t>(tuple.getLength()));
287
289 if (tuple.getLength() > std::numeric_limits<uint16_t>::max()) {
290 isc_throw(BadDataTypeCast, "invalid tuple value (size "
291 << tuple.getLength() << " larger than "
292 << std::numeric_limits<uint16_t>::max() << ")");
293 }
294 buf.resize(buf.size() + 2);
295 isc::util::writeUint16(static_cast<uint16_t>(tuple.getLength()),
296 &buf[buf.size() - 2], 2);
297 } else {
298 isc_throw(BadDataTypeCast, "unable to write data to the buffer as"
299 << " tuple. Invalid length type field: "
300 << tuple.getLengthFieldType());
301 }
302 buf.insert(buf.end(), tuple.getData().begin(), tuple.getData().end());
303}
304
305bool
306OptionDataTypeUtil::readBool(const std::vector<uint8_t>& buf) {
307 if (buf.empty()) {
308 isc_throw(BadDataTypeCast, "unable to read the buffer as boolean"
309 << " value. Invalid buffer size " << buf.size());
310 }
311 if (buf[0] == 1) {
312 return (true);
313 } else if (buf[0] == 0) {
314 return (false);
315 }
316 isc_throw(BadDataTypeCast, "unable to read the buffer as boolean"
317 << " value. Invalid value " << static_cast<int>(buf[0]));
318}
319
320void
322 std::vector<uint8_t>& buf) {
323 buf.push_back(static_cast<uint8_t>(value ? 1 : 0));
324}
325
326std::string
327OptionDataTypeUtil::readFqdn(const std::vector<uint8_t>& buf) {
328 // If buffer is empty emit an error.
329 if (buf.empty()) {
330 isc_throw(BadDataTypeCast, "unable to read FQDN from a buffer."
331 << " The buffer is empty.");
332 }
333 // Set up an InputBuffer so as we can use isc::dns::Name object to get the FQDN.
334 isc::util::InputBuffer in_buf(static_cast<const void*>(&buf[0]), buf.size());
335 try {
336 // Try to create an object from the buffer. If exception is thrown
337 // it means that the buffer doesn't hold a valid domain name (invalid
338 // syntax).
339 isc::dns::Name name(in_buf);
340 return (name.toText());
341 } catch (const isc::Exception& ex) {
342 // Unable to convert the data in the buffer into FQDN.
344 }
345}
346
347void
348OptionDataTypeUtil::writeFqdn(const std::string& fqdn,
349 std::vector<uint8_t>& buf,
350 bool downcase) {
351 try {
352 isc::dns::Name name(fqdn, downcase);
353 isc::dns::LabelSequence labels(name);
354 if (labels.getDataLength() > 0) {
355 size_t read_len = 0;
356 const uint8_t* data = labels.getData(&read_len);
357 buf.insert(buf.end(), data, data + read_len);
358 }
359 } catch (const isc::Exception& ex) {
361 }
362}
363
364unsigned int
365OptionDataTypeUtil::getLabelCount(const std::string& text_name) {
366 // The isc::dns::Name class doesn't accept empty names. However, in some
367 // cases we may be dealing with empty names (e.g. sent by the DHCP clients).
368 // Empty names should not be sent as hostnames but if they are, for some
369 // reason, we don't want to throw an exception from this function. We
370 // rather want to signal empty name by returning 0 number of labels.
371 if (text_name.empty()) {
372 return (0);
373 }
374 try {
375 isc::dns::Name name(text_name);
376 return (name.getLabelCount());
377 } catch (const isc::Exception& ex) {
379 }
380}
381
383OptionDataTypeUtil::readPrefix(const std::vector<uint8_t>& buf) {
384 // Prefix typically consists of the prefix length and the
385 // actual value. If prefix length is 0, the buffer length should
386 // be at least 1 byte to hold this length value.
387 if (buf.empty()) {
388 isc_throw(BadDataTypeCast, "unable to read prefix length from "
389 "a truncated buffer");
390 }
391
392 // Surround everything with try-catch to unify exceptions being
393 // thrown by various functions and constructors.
394 try {
395 // Try to create PrefixLen object from the prefix length held
396 // in the buffer. This may cause an exception if the length is
397 // invalid (greater than 128).
398 PrefixLen prefix_len(buf.at(0));
399
400 // Convert prefix length to bytes, because we operate on bytes,
401 // rather than bits.
402 uint8_t prefix_len_bytes = (prefix_len.asUint8() / 8);
403 // Check if we need to zero pad any bits. This is the case when
404 // the prefix length is not divisible by 8 (bits per byte). The
405 // calculations below may require some explanations. We first
406 // perform prefix_len % 8 to get the number of useful bits beyond
407 // the current prefix_len_bytes value. By substracting it from 8
408 // we get the number of zero padded bits, but with the special
409 // case of 8 when the result of substraction is 0. The value of
410 // 8 really means no padding so we make a modulo division once
411 // again to turn 8s to 0s.
412 const uint8_t zero_padded_bits =
413 static_cast<uint8_t>((8 - (prefix_len.asUint8() % 8)) % 8);
414 // If there are zero padded bits, it means that we need an extra
415 // byte to be retrieved from the buffer.
416 if (zero_padded_bits > 0) {
417 ++prefix_len_bytes;
418 }
419
420 // Make sure that the buffer is long enough. We substract 1 to
421 // also account for the fact that the buffer includes a prefix
422 // length besides a prefix.
423 if ((buf.size() - 1) < prefix_len_bytes) {
424 isc_throw(BadDataTypeCast, "unable to read a prefix having length of "
425 << prefix_len.asUnsigned() << " from a truncated buffer");
426 }
427
428 // It is possible for a prefix to be zero if the prefix length
429 // is zero.
431
432 // If there is anything more than prefix length is this buffer
433 // we need to read it.
434 if (buf.size() > 1) {
435 // Buffer has to be copied, because we will modify its
436 // contents by setting certain bits to 0, if necessary.
437 std::vector<uint8_t> prefix_buf(buf.begin() + 1, buf.end());
438 // All further conversions require that the buffer length is
439 // 16 bytes.
440 if (prefix_buf.size() < V6ADDRESS_LEN) {
441 prefix_buf.resize(V6ADDRESS_LEN);
442 if (prefix_len_bytes < prefix_buf.size()) {
443 // Zero all bits in the buffer beyond prefix length
444 // position.
445 std::fill(prefix_buf.begin() + prefix_len_bytes,
446 prefix_buf.end(), 0);
447
448 if (zero_padded_bits) {
449 // There is a byte that require zero padding. We
450 // achieve that by shifting the value of that byte
451 // back and forth by the number of zeroed bits.
452 prefix_buf.at(prefix_len_bytes - 1) =
453 (prefix_buf.at(prefix_len_bytes - 1)
454 >> zero_padded_bits)
455 << zero_padded_bits;
456 }
457 }
458 }
459 // Convert the buffer to the IOAddress object.
460 prefix = IOAddress::fromBytes(AF_INET6, &prefix_buf[0]);
461 }
462
463 return (std::make_pair(prefix_len, prefix));
464
465 } catch (const BadDataTypeCast& ex) {
466 // Pass through the BadDataTypeCast exceptions.
467 throw;
468
469 } catch (const std::exception& ex) {
470 // If an exception of a different type has been thrown, insert
471 // a text that indicates that the failure occurred during reading
472 // the prefix and modify exception type to BadDataTypeCast.
473 isc_throw(BadDataTypeCast, "unable to read a prefix from a buffer: "
474 << ex.what());
475 }
476}
477
478void
480 const IOAddress& prefix,
481 std::vector<uint8_t>& buf) {
482 // Prefix must be an IPv6 prefix.
483 if (!prefix.isV6()) {
484 isc_throw(BadDataTypeCast, "illegal prefix value "
485 << prefix);
486 }
487
488 // We don't need to validate the prefix_len value, because it is
489 // already validated by the PrefixLen class.
490 buf.push_back(prefix_len.asUint8());
491
492 // Convert the prefix length to a number of bytes.
493 uint8_t prefix_len_bytes = prefix_len.asUint8() / 8;
494 // Check if there are any bits that require zero padding. See the
495 // commentary in readPrefix to see how this is calculated.
496 const uint8_t zero_padded_bits =
497 static_cast<uint8_t>((8 - (prefix_len.asUint8() % 8)) % 8);
498 // If zero padding is needed it means that we need to extend the
499 // buffer to hold the "partially occupied" byte.
500 if (zero_padded_bits > 0) {
501 ++prefix_len_bytes;
502 }
503
504 // Convert the prefix to byte representation and append it to
505 // our output buffer.
506 std::vector<uint8_t> prefix_bytes = prefix.toBytes();
507 buf.insert(buf.end(), prefix_bytes.begin(),
508 prefix_bytes.begin() + prefix_len_bytes);
509 // If the last byte requires zero padding we achieve that by shifting
510 // bits back and forth by the number of insignificant bits.
511 if (zero_padded_bits) {
512 *buf.rbegin() = (*buf.rbegin() >> zero_padded_bits) << zero_padded_bits;
513 }
514}
515
517OptionDataTypeUtil::readPsid(const std::vector<uint8_t>& buf) {
518 if (buf.size() < 3) {
519 isc_throw(BadDataTypeCast, "unable to read PSID from the buffer."
520 << " Invalid buffer size " << buf.size()
521 << ". Expected 3 bytes (PSID length and PSID value)");
522 }
523
524 // Read PSID length.
525 uint8_t psid_len = buf[0];
526
527 // PSID length must not be greater than 16 bits.
528 if (psid_len > (sizeof(uint16_t) * 8)) {
529 isc_throw(BadDataTypeCast, "invalid PSID length value "
530 << static_cast<unsigned>(psid_len)
531 << ", this value is expected to be in range of 0 to 16");
532 }
533
534 // Read two bytes of PSID value.
535 uint16_t psid = isc::util::readUint16(&buf[1], 2);
536
537 // We need to check that the PSID value does not exceed the maximum value
538 // for a specified PSID length. That means that all bits placed further than
539 // psid_len from the left must be set to 0.
540 // The value 0 is a special case because the RFC explicitly says that the
541 // PSID value should be ignored if psid_len is 0.
542 if ((psid & ~psid_bitmask[psid_len]) != 0) {
543 isc_throw(BadDataTypeCast, "invalid PSID value " << psid
544 << " for a specified PSID length "
545 << static_cast<unsigned>(psid_len));
546 }
547
548 // All is good, so we can convert the PSID value read from the buffer to
549 // the port set number.
550 if (psid_len == 0) {
551 // Shift by 16 always gives zero (CID 1398333)
552 psid = 0;
553 } else {
554 psid >>= (sizeof(psid) * 8 - psid_len);
555 }
556 return (std::make_pair(PSIDLen(psid_len), PSID(psid)));
557}
558
559void
560OptionDataTypeUtil::writePsid(const PSIDLen& psid_len, const PSID& psid,
561 std::vector<uint8_t>& buf) {
562 if (psid_len.asUint8() > (sizeof(psid) * 8)) {
563 isc_throw(BadDataTypeCast, "invalid PSID length value "
564 << psid_len.asUnsigned()
565 << ", this value is expected to be in range of 0 to 16");
566 }
567
568 if ((psid_len.asUint8() > 0) &&
569 (psid.asUint16() > (0xFFFF >> (sizeof(uint16_t) * 8 - psid_len.asUint8())))) {
570 isc_throw(BadDataTypeCast, "invalid PSID value " << psid.asUint16()
571 << " for a specified PSID length "
572 << psid_len.asUnsigned());
573 }
574
575 buf.resize(buf.size() + 3);
576 buf.at(buf.size() - 3) = psid_len.asUint8();
577 isc::util::writeUint16(static_cast<uint16_t>
578 (psid.asUint16() << (sizeof(uint16_t) * 8 - psid_len.asUint8())),
579 &buf[buf.size() - 2], 2);
580}
581
582std::string
583OptionDataTypeUtil::readString(const std::vector<uint8_t>& buf) {
584 std::string value;
585 if (!buf.empty()) {
586 // Per RFC 2132, section 2 we need to drop trailing NULLs
587 auto begin = buf.begin();
588 auto end = util::str::seekTrimmed(begin, buf.end(), 0x0);
589 if (std::distance(begin, end) == 0) {
590 isc_throw(isc::OutOfRange, "string value carried by the option "
591 "contained only NULLs");
592 }
593
594 value.insert(value.end(), begin, end);
595 }
596
597 return (value);
598}
599
600void
601OptionDataTypeUtil::writeString(const std::string& value,
602 std::vector<uint8_t>& buf) {
603 if (value.size() > 0) {
604 buf.insert(buf.end(), value.begin(), value.end());
605 }
606}
607
608} // end of isc::dhcp namespace
609} // end of isc namespace
This is a base class for exceptions thrown from the DNS library module.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
A generic exception that is thrown if a parameter given to a method would refer to or modify out-of-r...
Exception to be thrown when cast to the data type was unsuccessful.
Exception to be thrown when the operation on OpaqueDataTuple object results in an error.
Represents a single instance of the opaque data preceded by length.
const Buffer & getData() const
Returns a reference to the buffer holding tuple data.
LengthFieldType
Size of the length field in the tuple.
LengthFieldType getLengthFieldType() const
Returns tuple length data field type.
void unpack(InputIterator begin, InputIterator end)
Parses wire data and creates a tuple from it.
size_t getLength() const
Returns the length of the data in the tuple.
static PrefixTuple readPrefix(const std::vector< uint8_t > &buf)
Read prefix from a buffer.
static asiolink::IOAddress readAddress(const std::vector< uint8_t > &buf, const short family)
Read IPv4 or IPv6 address from a buffer.
static unsigned int getLabelCount(const std::string &text_name)
Return the number of labels in the Name.
static void writeFqdn(const std::string &fqdn, std::vector< uint8_t > &buf, const bool downcase=false)
Append FQDN into a buffer.
static void writePrefix(const PrefixLen &prefix_len, const asiolink::IOAddress &prefix, std::vector< uint8_t > &buf)
Append prefix into a buffer.
static const std::string & getDataTypeName(const OptionDataType data_type)
Return option data type name from the data type enumerator.
static OptionDataType getDataType(const std::string &data_type)
Return option data type from its name.
static void writeBinary(const std::string &hex_str, std::vector< uint8_t > &buf)
Append hex-encoded binary values to a buffer.
static int getDataTypeLen(const OptionDataType data_type)
Get data type buffer length.
static std::string readFqdn(const std::vector< uint8_t > &buf)
Read FQDN from a buffer as a string value.
static std::string readTuple(const std::vector< uint8_t > &buf, OpaqueDataTuple::LengthFieldType lengthfieldtype)
Read length and string tuple from a buffer.
static void writeAddress(const asiolink::IOAddress &address, std::vector< uint8_t > &buf)
Append IPv4 or IPv6 address to a buffer.
static PSIDTuple readPsid(const std::vector< uint8_t > &buf)
Read PSID length / value tuple from a buffer.
static void writePsid(const PSIDLen &psid_len, const PSID &psid, std::vector< uint8_t > &buf)
Append PSID length/value into a buffer.
static void writeString(const std::string &value, std::vector< uint8_t > &buf)
Write UTF8-encoded string into a buffer.
static void writeTuple(const std::string &value, OpaqueDataTuple::LengthFieldType lengthfieldtype, std::vector< uint8_t > &buf)
Append length and string tuple to a buffer.
static void writeBool(const bool value, std::vector< uint8_t > &buf)
Append boolean value into a buffer.
static bool readBool(const std::vector< uint8_t > &buf)
Read boolean value from a buffer.
static std::string readString(const std::vector< uint8_t > &buf)
Read string value from a buffer.
Encapsulates PSID length.
uint8_t asUint8() const
Returns PSID length as uint8_t value.
unsigned int asUnsigned() const
Returns PSID length as unsigned int.
Encapsulates PSID value.
uint16_t asUint16() const
Returns PSID value as a number.
Encapsulates prefix length.
unsigned int asUnsigned() const
Returns prefix length as unsigned int.
uint8_t asUint8() const
Returns prefix length as uint8_t value.
Light-weight Accessor to Name data.
Definition: labelsequence.h:35
const uint8_t * getData(size_t *len) const
Return the wire-format data for this LabelSequence.
size_t getDataLength() const
Return the length of the wire-format data of this LabelSequence.
The Name class encapsulates DNS names.
Definition: name.h:223
std::string toText(bool omit_final_dot=false) const
Convert the Name to a string.
Definition: name.cc:507
unsigned int getLabelCount() const
Returns the number of labels contained in the Name.
Definition: name.h:370
The InputBuffer class is a buffer abstraction for manipulating read-only data.
Definition: buffer.h:81
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
std::pair< PSIDLen, PSID > PSIDTuple
Defines a pair of PSID length / value.
OptionDataType
Data types of DHCP option fields.
std::pair< PrefixLen, asiolink::IOAddress > PrefixTuple
Defines a pair of prefix length / value.
std::vector< uint8_t > OptionBuffer
buffer types used in DHCP code.
Definition: option.h:24
void decodeHex(const string &input, vector< uint8_t > &result)
Decode a text encoded in the base16 ('hex') format into the original data.
Definition: base_n.cc:474
Iterator seekTrimmed(Iterator begin, Iterator end, uint8_t trim_val)
Finds the "trimmed" end of a buffer.
Definition: strutil.h:72
uint8_t * writeUint16(uint16_t value, void *buffer, size_t length)
Write Unsigned 16-Bit Integer to Buffer.
Definition: io_utilities.h:55
uint16_t readUint16(const void *buffer, size_t length)
Read Unsigned 16-Bit Integer from Buffer.
Definition: io_utilities.h:28
Defines the logger used by the top-level component of kea-lfc.