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 
16 using namespace isc::asiolink;
17 
18 namespace isc {
19 namespace dhcp {
20 
21 OptionDataTypeUtil::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 
65 OptionDataTypeUtil::getDataType(const std::string& data_type) {
66  return (OptionDataTypeUtil::instance().getDataTypeImpl(data_type));
67 }
68 
70 OptionDataTypeUtil::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 
79 int
80 OptionDataTypeUtil::getDataTypeLen(const OptionDataType data_type) {
81  switch (data_type) {
82  case OPT_BOOLEAN_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 
110 const std::string&
111 OptionDataTypeUtil::getDataTypeName(const OptionDataType data_type) {
112  return (OptionDataTypeUtil::instance().getDataTypeNameImpl(data_type));
113 }
114 
115 const std::string&
116 OptionDataTypeUtil::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 
125 OptionDataTypeUtil&
126 OptionDataTypeUtil::instance() {
127  static OptionDataTypeUtil instance;
128  return (instance);
129 }
130 
131 asiolink::IOAddress
132 OptionDataTypeUtil::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 
153 void
154 OptionDataTypeUtil::writeAddress(const asiolink::IOAddress& address,
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 
160 void
161 OptionDataTypeUtil::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 
178 std::string
179 OptionDataTypeUtil::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 
220 void
221 OptionDataTypeUtil::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 
230 void
231 OptionDataTypeUtil::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 
259 void
260 OptionDataTypeUtil::writeTuple(const OpaqueDataTuple& tuple,
261  std::vector<uint8_t>& buf) {
262  if (tuple.getLength() == 0) {
263  isc_throw(BadDataTypeCast, "invalid empty tuple value");
264  }
265  if (tuple.getLengthFieldType() == OpaqueDataTuple::LENGTH_1_BYTE) {
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 
273  } else if (tuple.getLengthFieldType() == OpaqueDataTuple::LENGTH_2_BYTES) {
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 
290 bool
291 OptionDataTypeUtil::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 
305 void
306 OptionDataTypeUtil::writeBool(const bool value,
307  std::vector<uint8_t>& buf) {
308  buf.push_back(static_cast<uint8_t>(value ? 1 : 0));
309 }
310 
311 std::string
312 OptionDataTypeUtil::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 
332 void
333 OptionDataTypeUtil::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 
349 unsigned int
350 OptionDataTypeUtil::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 
368 OptionDataTypeUtil::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 
463 void
464 OptionDataTypeUtil::writePrefix(const PrefixLen& prefix_len,
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 
501 PSIDTuple
502 OptionDataTypeUtil::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 
549 void
550 OptionDataTypeUtil::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 
573 std::string
574 OptionDataTypeUtil::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 
582 void
583 OptionDataTypeUtil::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
The Name class encapsulates DNS names.
Definition: name.h:223
Encapsulates PSID length.
std::pair< PrefixLen, asiolink::IOAddress > PrefixTuple
Defines a pair of prefix length / value.
unsigned int getLabelCount() const
Returns the number of labels contained in the Name.
Definition: name.h:370
uint16_t asUint16() const
Returns PSID value as a number.
size_t getDataLength() const
Return the length of the wire-format data of this LabelSequence.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
std::vector< uint8_t > OptionBuffer
buffer types used in DHCP code.
Definition: option.h:25
LengthFieldType getLengthFieldType() const
Returns tuple length data field type.
uint8_t asUint8() const
Returns prefix length as uint8_t value.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
OptionDataType
Data types of DHCP option fields.
uint8_t * writeUint16(uint16_t value, void *buffer, size_t length)
Write Unsigned 16-Bit Integer to Buffer.
Definition: io_utilities.h:55
Encapsulates PSID value.
const uint8_t * getData(size_t *len) const
Return the wire-format data for this LabelSequence.
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 asUint8() const
Returns PSID length as uint8_t value.
std::string toText(bool omit_final_dot=false) const
Convert the Name to a string.
Definition: name.cc:507
LengthFieldType
Size of the length field in the tuple.
std::pair< PSIDLen, PSID > PSIDTuple
Defines a pair of PSID length / value.
This is a base class for exceptions thrown from the DNS library module.
Defines the logger used by the top-level component of kea-dhcp-ddns.
uint16_t readUint16(const void *buffer, size_t length)
Read Unsigned 16-Bit Integer from Buffer.
Definition: io_utilities.h:28
void unpack(InputIterator begin, InputIterator end)
Parses wire data and creates a tuple from it.
const Buffer & getData() const
Returns a reference to the buffer holding tuple data.
Represents a single instance of the opaque data preceded by length.
The InputBuffer class is a buffer abstraction for manipulating read-only data.
Definition: buffer.h:81
size_t getLength() const
Returns the length of the data in the tuple.
Exception to be thrown when cast to the data type was unsuccessful.
unsigned int asUnsigned() const
Returns PSID length as unsigned int.
Encapsulates prefix length.
Light-weight Accessor to Name data.
Definition: labelsequence.h:35
Exception to be thrown when the operation on OpaqueDataTuple object results in an error.