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