Kea 2.5.8
option_data_types.cc
Go to the documentation of this file.
1// Copyright (C) 2012-2024 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
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
198 if (u == Option::V4) {
200 }
202}
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 + 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 + 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 // If buffer is empty emit an error.
340 if (buf.empty()) {
341 isc_throw(BadDataTypeCast, "unable to read FQDN from a buffer."
342 << " The buffer is empty.");
343 }
344 // Set up an InputBuffer so as we can use isc::dns::Name object to get the FQDN.
345 isc::util::InputBuffer in_buf(static_cast<const void*>(&buf[0]), buf.size());
346 try {
347 // Try to create an object from the buffer. If exception is thrown
348 // it means that the buffer doesn't hold a valid domain name (invalid
349 // syntax).
350 isc::dns::Name name(in_buf);
351 return (name.toText());
352 } catch (const isc::Exception& ex) {
353 // Unable to convert the data in the buffer into FQDN.
355 }
356}
357
358void
359OptionDataTypeUtil::writeFqdn(const std::string& fqdn,
360 std::vector<uint8_t>& buf,
361 bool downcase) {
362 try {
363 isc::dns::Name name(fqdn, downcase);
364 isc::dns::LabelSequence labels(name);
365 if (labels.getDataLength() > 0) {
366 size_t read_len = 0;
367 const uint8_t* data = labels.getData(&read_len);
368 buf.insert(buf.end(), data, data + read_len);
369 }
370 } catch (const isc::Exception& ex) {
372 }
373}
374
375unsigned int
376OptionDataTypeUtil::getLabelCount(const std::string& text_name) {
377 // The isc::dns::Name class doesn't accept empty names. However, in some
378 // cases we may be dealing with empty names (e.g. sent by the DHCP clients).
379 // Empty names should not be sent as hostnames but if they are, for some
380 // reason, we don't want to throw an exception from this function. We
381 // rather want to signal empty name by returning 0 number of labels.
382 if (text_name.empty()) {
383 return (0);
384 }
385 try {
386 isc::dns::Name name(text_name);
387 return (name.getLabelCount());
388 } catch (const isc::Exception& ex) {
390 }
391}
392
394OptionDataTypeUtil::readPrefix(const std::vector<uint8_t>& buf) {
395 // Prefix typically consists of the prefix length and the
396 // actual value. If prefix length is 0, the buffer length should
397 // be at least 1 byte to hold this length value.
398 if (buf.empty()) {
399 isc_throw(BadDataTypeCast, "unable to read prefix length from "
400 "a truncated buffer");
401 }
402
403 // Surround everything with try-catch to unify exceptions being
404 // thrown by various functions and constructors.
405 try {
406 // Try to create PrefixLen object from the prefix length held
407 // in the buffer. This may cause an exception if the length is
408 // invalid (greater than 128).
409 PrefixLen prefix_len(buf.at(0));
410
411 // Convert prefix length to bytes, because we operate on bytes,
412 // rather than bits.
413 uint8_t prefix_len_bytes = (prefix_len.asUint8() / 8);
414 // Check if we need to zero pad any bits. This is the case when
415 // the prefix length is not divisible by 8 (bits per byte). The
416 // calculations below may require some explanations. We first
417 // perform prefix_len % 8 to get the number of useful bits beyond
418 // the current prefix_len_bytes value. By substracting it from 8
419 // we get the number of zero padded bits, but with the special
420 // case of 8 when the result of substraction is 0. The value of
421 // 8 really means no padding so we make a modulo division once
422 // again to turn 8s to 0s.
423 const uint8_t zero_padded_bits =
424 static_cast<uint8_t>((8 - (prefix_len.asUint8() % 8)) % 8);
425 // If there are zero padded bits, it means that we need an extra
426 // byte to be retrieved from the buffer.
427 if (zero_padded_bits > 0) {
428 ++prefix_len_bytes;
429 }
430
431 // Make sure that the buffer is long enough. We substract 1 to
432 // also account for the fact that the buffer includes a prefix
433 // length besides a prefix.
434 if ((buf.size() - 1) < prefix_len_bytes) {
435 isc_throw(BadDataTypeCast, "unable to read a prefix having length of "
436 << prefix_len.asUnsigned() << " from a truncated buffer");
437 }
438
439 // It is possible for a prefix to be zero if the prefix length
440 // is zero.
442
443 // If there is anything more than prefix length is this buffer
444 // we need to read it.
445 if (buf.size() > 1) {
446 // Buffer has to be copied, because we will modify its
447 // contents by setting certain bits to 0, if necessary.
448 std::vector<uint8_t> prefix_buf(buf.begin() + 1, buf.end());
449 // All further conversions require that the buffer length is
450 // 16 bytes.
451 if (prefix_buf.size() < V6ADDRESS_LEN) {
452 prefix_buf.resize(V6ADDRESS_LEN);
453 if (prefix_len_bytes < prefix_buf.size()) {
454 // Zero all bits in the buffer beyond prefix length
455 // position.
456 std::fill(prefix_buf.begin() + prefix_len_bytes,
457 prefix_buf.end(), 0);
458
459 if (zero_padded_bits) {
460 // There is a byte that require zero padding. We
461 // achieve that by shifting the value of that byte
462 // back and forth by the number of zeroed bits.
463 prefix_buf.at(prefix_len_bytes - 1) =
464 (prefix_buf.at(prefix_len_bytes - 1)
465 >> zero_padded_bits)
466 << zero_padded_bits;
467 }
468 }
469 }
470 // Convert the buffer to the IOAddress object.
471 prefix = IOAddress::fromBytes(AF_INET6, &prefix_buf[0]);
472 }
473
474 return (std::make_pair(prefix_len, prefix));
475
476 } catch (const BadDataTypeCast& ex) {
477 // Pass through the BadDataTypeCast exceptions.
478 throw;
479
480 } catch (const std::exception& ex) {
481 // If an exception of a different type has been thrown, insert
482 // a text that indicates that the failure occurred during reading
483 // the prefix and modify exception type to BadDataTypeCast.
484 isc_throw(BadDataTypeCast, "unable to read a prefix from a buffer: "
485 << ex.what());
486 }
487}
488
489void
491 const IOAddress& prefix,
492 std::vector<uint8_t>& buf) {
493 // Prefix must be an IPv6 prefix.
494 if (!prefix.isV6()) {
495 isc_throw(BadDataTypeCast, "illegal prefix value "
496 << prefix);
497 }
498
499 // We don't need to validate the prefix_len value, because it is
500 // already validated by the PrefixLen class.
501 buf.push_back(prefix_len.asUint8());
502
503 // Convert the prefix length to a number of bytes.
504 uint8_t prefix_len_bytes = prefix_len.asUint8() / 8;
505 // Check if there are any bits that require zero padding. See the
506 // commentary in readPrefix to see how this is calculated.
507 const uint8_t zero_padded_bits =
508 static_cast<uint8_t>((8 - (prefix_len.asUint8() % 8)) % 8);
509 // If zero padding is needed it means that we need to extend the
510 // buffer to hold the "partially occupied" byte.
511 if (zero_padded_bits > 0) {
512 ++prefix_len_bytes;
513 }
514
515 // Convert the prefix to byte representation and append it to
516 // our output buffer.
517 std::vector<uint8_t> prefix_bytes = prefix.toBytes();
518 buf.insert(buf.end(), prefix_bytes.begin(),
519 prefix_bytes.begin() + prefix_len_bytes);
520 // If the last byte requires zero padding we achieve that by shifting
521 // bits back and forth by the number of insignificant bits.
522 if (zero_padded_bits) {
523 *buf.rbegin() = (*buf.rbegin() >> zero_padded_bits) << zero_padded_bits;
524 }
525}
526
528OptionDataTypeUtil::readPsid(const std::vector<uint8_t>& buf) {
529 if (buf.size() < 3) {
530 isc_throw(BadDataTypeCast, "unable to read PSID from the buffer."
531 << " Invalid buffer size " << buf.size()
532 << ". Expected 3 bytes (PSID length and PSID value)");
533 }
534
535 // Read PSID length.
536 uint8_t psid_len = buf[0];
537
538 // PSID length must not be greater than 16 bits.
539 if (psid_len > (sizeof(uint16_t) * 8)) {
540 isc_throw(BadDataTypeCast, "invalid PSID length value "
541 << static_cast<unsigned>(psid_len)
542 << ", this value is expected to be in range of 0 to 16");
543 }
544
545 // Read two bytes of PSID value.
546 uint16_t psid = isc::util::readUint16(&buf[1], 2);
547
548 // We need to check that the PSID value does not exceed the maximum value
549 // for a specified PSID length. That means that all bits placed further than
550 // psid_len from the left must be set to 0.
551 // The value 0 is a special case because the RFC explicitly says that the
552 // PSID value should be ignored if psid_len is 0.
553 if ((psid & ~psid_bitmask[psid_len]) != 0) {
554 isc_throw(BadDataTypeCast, "invalid PSID value " << psid
555 << " for a specified PSID length "
556 << static_cast<unsigned>(psid_len));
557 }
558
559 // All is good, so we can convert the PSID value read from the buffer to
560 // the port set number.
561 if (psid_len == 0) {
562 // Shift by 16 always gives zero (CID 1398333)
563 psid = 0;
564 } else {
565 psid >>= (sizeof(psid) * 8 - psid_len);
566 }
567 return (std::make_pair(PSIDLen(psid_len), PSID(psid)));
568}
569
570void
571OptionDataTypeUtil::writePsid(const PSIDLen& psid_len, const PSID& psid,
572 std::vector<uint8_t>& buf) {
573 if (psid_len.asUint8() > (sizeof(psid) * 8)) {
574 isc_throw(BadDataTypeCast, "invalid PSID length value "
575 << psid_len.asUnsigned()
576 << ", this value is expected to be in range of 0 to 16");
577 }
578
579 if ((psid_len.asUint8() > 0) &&
580 (psid.asUint16() > (0xFFFF >> (sizeof(uint16_t) * 8 - psid_len.asUint8())))) {
581 isc_throw(BadDataTypeCast, "invalid PSID value " << psid.asUint16()
582 << " for a specified PSID length "
583 << psid_len.asUnsigned());
584 }
585
586 buf.resize(buf.size() + 3);
587 buf.at(buf.size() - 3) = psid_len.asUint8();
588 isc::util::writeUint16(static_cast<uint16_t>
589 (psid.asUint16() << (sizeof(uint16_t) * 8 - psid_len.asUint8())),
590 &buf[buf.size() - 2], 2);
591}
592
593std::string
594OptionDataTypeUtil::readString(const std::vector<uint8_t>& buf) {
595 std::string value;
596 if (!buf.empty()) {
597 // Per RFC 2132, section 2 we need to drop trailing NULLs
598 auto begin = buf.begin();
599 auto end = util::str::seekTrimmed(begin, buf.end(), 0x0);
600 if (std::distance(begin, end) == 0) {
601 isc_throw(isc::OutOfRange, "string value carried by the option "
602 "contained only NULLs");
603 }
604
605 value.insert(value.end(), begin, end);
606 }
607
608 return (value);
609}
610
611void
612OptionDataTypeUtil::writeString(const std::string& value,
613 std::vector<uint8_t>& buf) {
614 if (value.size() > 0) {
615 buf.insert(buf.end(), value.begin(), value.end());
616 }
617}
618
619} // end of isc::dhcp namespace
620} // 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:219
std::string toText(bool omit_final_dot=false) const
Convert the Name to a string.
Definition: name.cc:503
unsigned int getLabelCount() const
Returns the number of labels contained in the Name.
Definition: name.h:366
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 &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.