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