Kea 2.5.5
option_data_types.cc
Go to the documentation of this file.
1// Copyright (C) 2012-2023 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
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
195 if (u == Option::V4) {
197 }
199}
200
201std::string
202OptionDataTypeUtil::readTuple(const std::vector<uint8_t>& buf,
203 OpaqueDataTuple::LengthFieldType lengthfieldtype) {
204 if (lengthfieldtype == OpaqueDataTuple::LENGTH_1_BYTE) {
205 if (buf.size() < 1) {
206 isc_throw(BadDataTypeCast, "unable to read data from the buffer as"
207 << " tuple (length). Invalid buffer size: "
208 << buf.size());
209 }
210 uint8_t len = buf[0];
211 if (buf.size() < 1 + len) {
212 isc_throw(BadDataTypeCast, "unable to read data from the buffer as"
213 << " tuple (length " << static_cast<unsigned>(len)
214 << "). Invalid buffer size: " << buf.size());
215 }
216 std::string value;
217 value.resize(len);
218 std::memcpy(&value[0], &buf[1], len);
219 return (value);
220 } else if (lengthfieldtype == OpaqueDataTuple::LENGTH_2_BYTES) {
221 if (buf.size() < 2) {
222 isc_throw(BadDataTypeCast, "unable to read data from the buffer as"
223 << " tuple (length). Invalid buffer size: "
224 << buf.size());
225 }
226 uint16_t len = isc::util::readUint16(&buf[0], 2);
227 if (buf.size() < 2 + len) {
228 isc_throw(BadDataTypeCast, "unable to read data from the buffer as"
229 << " tuple (length " << len
230 << "). Invalid buffer size: " << buf.size());
231 }
232 std::string value;
233 value.resize(len);
234 std::memcpy(&value[0], &buf[2], len);
235 return (value);
236 } else {
237 isc_throw(BadDataTypeCast, "unable to read data from the buffer as"
238 << " tuple. Invalid length type field: "
239 << static_cast<unsigned>(lengthfieldtype));
240 }
241}
242
243void
244OptionDataTypeUtil::readTuple(const std::vector<uint8_t>& buf,
245 OpaqueDataTuple& tuple) {
246 try {
247 tuple.unpack(buf.begin(), buf.end());
248 } catch (const OpaqueDataTupleError& ex) {
250 }
251}
252
253void
254OptionDataTypeUtil::writeTuple(const std::string& value,
255 OpaqueDataTuple::LengthFieldType lengthfieldtype,
256 std::vector<uint8_t>& buf) {
257 if (lengthfieldtype == OpaqueDataTuple::LENGTH_1_BYTE) {
258 if (value.size() > std::numeric_limits<uint8_t>::max()) {
259 isc_throw(BadDataTypeCast, "invalid tuple value (size "
260 << value.size() << " larger than "
261 << +std::numeric_limits<uint8_t>::max() << ")");
262 }
263 buf.push_back(static_cast<uint8_t>(value.size()));
264
265 } else if (lengthfieldtype == OpaqueDataTuple::LENGTH_2_BYTES) {
266 if (value.size() > std::numeric_limits<uint16_t>::max()) {
267 isc_throw(BadDataTypeCast, "invalid tuple value (size "
268 << value.size() << " larger than "
269 << std::numeric_limits<uint16_t>::max() << ")");
270 }
271 buf.resize(buf.size() + 2);
272 isc::util::writeUint16(static_cast<uint16_t>(value.size()),
273 &buf[buf.size() - 2], 2);
274 } else {
275 isc_throw(BadDataTypeCast, "unable to write data to the buffer as"
276 << " tuple. Invalid length type field: "
277 << static_cast<unsigned>(lengthfieldtype));
278 }
279 buf.insert(buf.end(), value.begin(), value.end());
280}
281
282void
284 std::vector<uint8_t>& buf) {
285 if (tuple.getLength() == 0) {
286 isc_throw(BadDataTypeCast, "invalid empty tuple value");
287 }
289 if (tuple.getLength() > std::numeric_limits<uint8_t>::max()) {
290 isc_throw(BadDataTypeCast, "invalid tuple value (size "
291 << tuple.getLength() << " larger than "
292 << +std::numeric_limits<uint8_t>::max() << ")");
293 }
294 buf.push_back(static_cast<uint8_t>(tuple.getLength()));
295
297 if (tuple.getLength() > std::numeric_limits<uint16_t>::max()) {
298 isc_throw(BadDataTypeCast, "invalid tuple value (size "
299 << tuple.getLength() << " larger than "
300 << std::numeric_limits<uint16_t>::max() << ")");
301 }
302 buf.resize(buf.size() + 2);
303 isc::util::writeUint16(static_cast<uint16_t>(tuple.getLength()),
304 &buf[buf.size() - 2], 2);
305 } else {
306 isc_throw(BadDataTypeCast, "unable to write data to the buffer as"
307 << " tuple. Invalid length type field: "
308 << tuple.getLengthFieldType());
309 }
310 buf.insert(buf.end(), tuple.getData().begin(), tuple.getData().end());
311}
312
313bool
314OptionDataTypeUtil::readBool(const std::vector<uint8_t>& buf) {
315 if (buf.empty()) {
316 isc_throw(BadDataTypeCast, "unable to read the buffer as boolean"
317 << " value. Invalid buffer size " << buf.size());
318 }
319 if (buf[0] == 1) {
320 return (true);
321 } else if (buf[0] == 0) {
322 return (false);
323 }
324 isc_throw(BadDataTypeCast, "unable to read the buffer as boolean"
325 << " value. Invalid value " << static_cast<int>(buf[0]));
326}
327
328void
330 std::vector<uint8_t>& buf) {
331 buf.push_back(static_cast<uint8_t>(value ? 1 : 0));
332}
333
334std::string
335OptionDataTypeUtil::readFqdn(const std::vector<uint8_t>& buf) {
336 // If buffer is empty emit an error.
337 if (buf.empty()) {
338 isc_throw(BadDataTypeCast, "unable to read FQDN from a buffer."
339 << " The buffer is empty.");
340 }
341 // Set up an InputBuffer so as we can use isc::dns::Name object to get the FQDN.
342 isc::util::InputBuffer in_buf(static_cast<const void*>(&buf[0]), buf.size());
343 try {
344 // Try to create an object from the buffer. If exception is thrown
345 // it means that the buffer doesn't hold a valid domain name (invalid
346 // syntax).
347 isc::dns::Name name(in_buf);
348 return (name.toText());
349 } catch (const isc::Exception& ex) {
350 // Unable to convert the data in the buffer into FQDN.
352 }
353}
354
355void
356OptionDataTypeUtil::writeFqdn(const std::string& fqdn,
357 std::vector<uint8_t>& buf,
358 bool downcase) {
359 try {
360 isc::dns::Name name(fqdn, downcase);
361 isc::dns::LabelSequence labels(name);
362 if (labels.getDataLength() > 0) {
363 size_t read_len = 0;
364 const uint8_t* data = labels.getData(&read_len);
365 buf.insert(buf.end(), data, data + read_len);
366 }
367 } catch (const isc::Exception& ex) {
369 }
370}
371
372unsigned int
373OptionDataTypeUtil::getLabelCount(const std::string& text_name) {
374 // The isc::dns::Name class doesn't accept empty names. However, in some
375 // cases we may be dealing with empty names (e.g. sent by the DHCP clients).
376 // Empty names should not be sent as hostnames but if they are, for some
377 // reason, we don't want to throw an exception from this function. We
378 // rather want to signal empty name by returning 0 number of labels.
379 if (text_name.empty()) {
380 return (0);
381 }
382 try {
383 isc::dns::Name name(text_name);
384 return (name.getLabelCount());
385 } catch (const isc::Exception& ex) {
387 }
388}
389
391OptionDataTypeUtil::readPrefix(const std::vector<uint8_t>& buf) {
392 // Prefix typically consists of the prefix length and the
393 // actual value. If prefix length is 0, the buffer length should
394 // be at least 1 byte to hold this length value.
395 if (buf.empty()) {
396 isc_throw(BadDataTypeCast, "unable to read prefix length from "
397 "a truncated buffer");
398 }
399
400 // Surround everything with try-catch to unify exceptions being
401 // thrown by various functions and constructors.
402 try {
403 // Try to create PrefixLen object from the prefix length held
404 // in the buffer. This may cause an exception if the length is
405 // invalid (greater than 128).
406 PrefixLen prefix_len(buf.at(0));
407
408 // Convert prefix length to bytes, because we operate on bytes,
409 // rather than bits.
410 uint8_t prefix_len_bytes = (prefix_len.asUint8() / 8);
411 // Check if we need to zero pad any bits. This is the case when
412 // the prefix length is not divisible by 8 (bits per byte). The
413 // calculations below may require some explanations. We first
414 // perform prefix_len % 8 to get the number of useful bits beyond
415 // the current prefix_len_bytes value. By substracting it from 8
416 // we get the number of zero padded bits, but with the special
417 // case of 8 when the result of substraction is 0. The value of
418 // 8 really means no padding so we make a modulo division once
419 // again to turn 8s to 0s.
420 const uint8_t zero_padded_bits =
421 static_cast<uint8_t>((8 - (prefix_len.asUint8() % 8)) % 8);
422 // If there are zero padded bits, it means that we need an extra
423 // byte to be retrieved from the buffer.
424 if (zero_padded_bits > 0) {
425 ++prefix_len_bytes;
426 }
427
428 // Make sure that the buffer is long enough. We substract 1 to
429 // also account for the fact that the buffer includes a prefix
430 // length besides a prefix.
431 if ((buf.size() - 1) < prefix_len_bytes) {
432 isc_throw(BadDataTypeCast, "unable to read a prefix having length of "
433 << prefix_len.asUnsigned() << " from a truncated buffer");
434 }
435
436 // It is possible for a prefix to be zero if the prefix length
437 // is zero.
439
440 // If there is anything more than prefix length is this buffer
441 // we need to read it.
442 if (buf.size() > 1) {
443 // Buffer has to be copied, because we will modify its
444 // contents by setting certain bits to 0, if necessary.
445 std::vector<uint8_t> prefix_buf(buf.begin() + 1, buf.end());
446 // All further conversions require that the buffer length is
447 // 16 bytes.
448 if (prefix_buf.size() < V6ADDRESS_LEN) {
449 prefix_buf.resize(V6ADDRESS_LEN);
450 if (prefix_len_bytes < prefix_buf.size()) {
451 // Zero all bits in the buffer beyond prefix length
452 // position.
453 std::fill(prefix_buf.begin() + prefix_len_bytes,
454 prefix_buf.end(), 0);
455
456 if (zero_padded_bits) {
457 // There is a byte that require zero padding. We
458 // achieve that by shifting the value of that byte
459 // back and forth by the number of zeroed bits.
460 prefix_buf.at(prefix_len_bytes - 1) =
461 (prefix_buf.at(prefix_len_bytes - 1)
462 >> zero_padded_bits)
463 << zero_padded_bits;
464 }
465 }
466 }
467 // Convert the buffer to the IOAddress object.
468 prefix = IOAddress::fromBytes(AF_INET6, &prefix_buf[0]);
469 }
470
471 return (std::make_pair(prefix_len, prefix));
472
473 } catch (const BadDataTypeCast& ex) {
474 // Pass through the BadDataTypeCast exceptions.
475 throw;
476
477 } catch (const std::exception& ex) {
478 // If an exception of a different type has been thrown, insert
479 // a text that indicates that the failure occurred during reading
480 // the prefix and modify exception type to BadDataTypeCast.
481 isc_throw(BadDataTypeCast, "unable to read a prefix from a buffer: "
482 << ex.what());
483 }
484}
485
486void
488 const IOAddress& prefix,
489 std::vector<uint8_t>& buf) {
490 // Prefix must be an IPv6 prefix.
491 if (!prefix.isV6()) {
492 isc_throw(BadDataTypeCast, "illegal prefix value "
493 << prefix);
494 }
495
496 // We don't need to validate the prefix_len value, because it is
497 // already validated by the PrefixLen class.
498 buf.push_back(prefix_len.asUint8());
499
500 // Convert the prefix length to a number of bytes.
501 uint8_t prefix_len_bytes = prefix_len.asUint8() / 8;
502 // Check if there are any bits that require zero padding. See the
503 // commentary in readPrefix to see how this is calculated.
504 const uint8_t zero_padded_bits =
505 static_cast<uint8_t>((8 - (prefix_len.asUint8() % 8)) % 8);
506 // If zero padding is needed it means that we need to extend the
507 // buffer to hold the "partially occupied" byte.
508 if (zero_padded_bits > 0) {
509 ++prefix_len_bytes;
510 }
511
512 // Convert the prefix to byte representation and append it to
513 // our output buffer.
514 std::vector<uint8_t> prefix_bytes = prefix.toBytes();
515 buf.insert(buf.end(), prefix_bytes.begin(),
516 prefix_bytes.begin() + prefix_len_bytes);
517 // If the last byte requires zero padding we achieve that by shifting
518 // bits back and forth by the number of insignificant bits.
519 if (zero_padded_bits) {
520 *buf.rbegin() = (*buf.rbegin() >> zero_padded_bits) << zero_padded_bits;
521 }
522}
523
525OptionDataTypeUtil::readPsid(const std::vector<uint8_t>& buf) {
526 if (buf.size() < 3) {
527 isc_throw(BadDataTypeCast, "unable to read PSID from the buffer."
528 << " Invalid buffer size " << buf.size()
529 << ". Expected 3 bytes (PSID length and PSID value)");
530 }
531
532 // Read PSID length.
533 uint8_t psid_len = buf[0];
534
535 // PSID length must not be greater than 16 bits.
536 if (psid_len > (sizeof(uint16_t) * 8)) {
537 isc_throw(BadDataTypeCast, "invalid PSID length value "
538 << static_cast<unsigned>(psid_len)
539 << ", this value is expected to be in range of 0 to 16");
540 }
541
542 // Read two bytes of PSID value.
543 uint16_t psid = isc::util::readUint16(&buf[1], 2);
544
545 // We need to check that the PSID value does not exceed the maximum value
546 // for a specified PSID length. That means that all bits placed further than
547 // psid_len from the left must be set to 0.
548 // The value 0 is a special case because the RFC explicitly says that the
549 // PSID value should be ignored if psid_len is 0.
550 if ((psid & ~psid_bitmask[psid_len]) != 0) {
551 isc_throw(BadDataTypeCast, "invalid PSID value " << psid
552 << " for a specified PSID length "
553 << static_cast<unsigned>(psid_len));
554 }
555
556 // All is good, so we can convert the PSID value read from the buffer to
557 // the port set number.
558 if (psid_len == 0) {
559 // Shift by 16 always gives zero (CID 1398333)
560 psid = 0;
561 } else {
562 psid >>= (sizeof(psid) * 8 - psid_len);
563 }
564 return (std::make_pair(PSIDLen(psid_len), PSID(psid)));
565}
566
567void
568OptionDataTypeUtil::writePsid(const PSIDLen& psid_len, const PSID& psid,
569 std::vector<uint8_t>& buf) {
570 if (psid_len.asUint8() > (sizeof(psid) * 8)) {
571 isc_throw(BadDataTypeCast, "invalid PSID length value "
572 << psid_len.asUnsigned()
573 << ", this value is expected to be in range of 0 to 16");
574 }
575
576 if ((psid_len.asUint8() > 0) &&
577 (psid.asUint16() > (0xFFFF >> (sizeof(uint16_t) * 8 - psid_len.asUint8())))) {
578 isc_throw(BadDataTypeCast, "invalid PSID value " << psid.asUint16()
579 << " for a specified PSID length "
580 << psid_len.asUnsigned());
581 }
582
583 buf.resize(buf.size() + 3);
584 buf.at(buf.size() - 3) = psid_len.asUint8();
585 isc::util::writeUint16(static_cast<uint16_t>
586 (psid.asUint16() << (sizeof(uint16_t) * 8 - psid_len.asUint8())),
587 &buf[buf.size() - 2], 2);
588}
589
590std::string
591OptionDataTypeUtil::readString(const std::vector<uint8_t>& buf) {
592 std::string value;
593 if (!buf.empty()) {
594 // Per RFC 2132, section 2 we need to drop trailing NULLs
595 auto begin = buf.begin();
596 auto end = util::str::seekTrimmed(begin, buf.end(), 0x0);
597 if (std::distance(begin, end) == 0) {
598 isc_throw(isc::OutOfRange, "string value carried by the option "
599 "contained only NULLs");
600 }
601
602 value.insert(value.end(), begin, end);
603 }
604
605 return (value);
606}
607
608void
609OptionDataTypeUtil::writeString(const std::string& value,
610 std::vector<uint8_t>& buf) {
611 if (value.size() > 0) {
612 buf.insert(buf.end(), value.begin(), value.end());
613 }
614}
615
616} // end of isc::dhcp namespace
617} // 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 OpaqueDataTuple::LengthFieldType getTupleLenFieldType(Option::Universe u)
Returns Length Field Type for a tuple.
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.
Universe
defines option universe DHCPv4 or DHCPv6
Definition: option.h:83
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:488
Iterator seekTrimmed(Iterator begin, Iterator end, uint8_t trim_val)
Finds the "trimmed" end of a buffer.
Definition: strutil.h:73
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.