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