Kea  1.5.0
option_custom.cc
Go to the documentation of this file.
1 // Copyright (C) 2012-2018 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 #include <dhcp/libdhcp++.h>
10 #include <dhcp/option_custom.h>
11 #include <util/encode/hex.h>
12 
13 using namespace isc::asiolink;
14 
15 namespace isc {
16 namespace dhcp {
17 
18 OptionCustom::OptionCustom(const OptionDefinition& def,
19  Universe u)
20  : Option(u, def.getCode(), OptionBuffer()),
21  definition_(def) {
23  createBuffers();
24 }
25 
27  Universe u,
28  const OptionBuffer& data)
29  : Option(u, def.getCode(), data.begin(), data.end()),
30  definition_(def) {
32  createBuffers(getData());
33 }
34 
36  Universe u,
39  : Option(u, def.getCode(), first, last),
40  definition_(def) {
42  createBuffers(getData());
43 }
44 
47  return (cloneInternal<OptionCustom>());
48 }
49 
50 void
52  checkArrayType();
53 
54  if ((address.isV4() && definition_.getType() != OPT_IPV4_ADDRESS_TYPE) ||
55  (address.isV6() && definition_.getType() != OPT_IPV6_ADDRESS_TYPE)) {
56  isc_throw(BadDataTypeCast, "invalid address specified "
57  << address << ". Expected a valid IPv"
58  << (definition_.getType() == OPT_IPV4_ADDRESS_TYPE ?
59  "4" : "6") << " address.");
60  }
61 
62  OptionBuffer buf;
64  buffers_.push_back(buf);
65 }
66 
67 void
68 OptionCustom::addArrayDataField(const std::string& value) {
69  checkArrayType();
70 
73  OptionBuffer buf;
74  OptionDataTypeUtil::writeTuple(value, lft, buf);
75  buffers_.push_back(buf);
76 }
77 
78 void
80  checkArrayType();
81 
82  OptionBuffer buf;
84  buffers_.push_back(buf);
85 }
86 
87 void
89  checkArrayType();
90 
91  OptionBuffer buf;
93  buffers_.push_back(buf);
94 }
95 
96 void
98  const asiolink::IOAddress& prefix) {
99  checkArrayType();
100 
101  if (definition_.getType() != OPT_IPV6_PREFIX_TYPE) {
102  isc_throw(BadDataTypeCast, "IPv6 prefix can be specified only for"
103  " an option comprising an array of IPv6 prefix values");
104  }
105 
106  OptionBuffer buf;
107  OptionDataTypeUtil::writePrefix(prefix_len, prefix, buf);
108  buffers_.push_back(buf);
109 }
110 
111 void
112 OptionCustom::addArrayDataField(const PSIDLen& psid_len, const PSID& psid) {
113  checkArrayType();
114 
115  if (definition_.getType() != OPT_PSID_TYPE) {
116  isc_throw(BadDataTypeCast, "PSID value can be specified onlu for"
117  " an option comprising an array of PSID length / value"
118  " tuples");
119  }
120 
121  OptionBuffer buf;
122  OptionDataTypeUtil::writePsid(psid_len, psid, buf);
123  buffers_.push_back(buf);
124 }
125 
126 void
127 OptionCustom::checkIndex(const uint32_t index) const {
128  if (index >= buffers_.size()) {
129  isc_throw(isc::OutOfRange, "specified data field index " << index
130  << " is out of range.");
131  }
132 }
133 
134 void
135 OptionCustom::createBuffer(OptionBuffer& buffer,
136  const OptionDataType data_type) const {
137  // For data types that have a fixed size we can use the
138  // utility function to get the buffer's size.
139  size_t data_size = OptionDataTypeUtil::getDataTypeLen(data_type);
140 
141  // For variable data sizes the utility function returns zero.
142  // It is ok for string values because the default string
143  // is 'empty'. However for FQDN the empty value is not valid
144  // so we initialize it to '.'. For prefix there is a prefix
145  // length fixed field.
146  if (data_size == 0) {
147  if (data_type == OPT_FQDN_TYPE) {
148  OptionDataTypeUtil::writeFqdn(".", buffer);
149 
150  } else if (data_type == OPT_IPV6_PREFIX_TYPE) {
151  OptionDataTypeUtil::writePrefix(PrefixLen(0),
153  buffer);
154  }
155  } else {
156  // At this point we can resize the buffer. Note that
157  // for string values we are setting the empty buffer
158  // here.
159  buffer.resize(data_size);
160  }
161 }
162 
163 void
164 OptionCustom::createBuffers() {
165  definition_.validate();
166 
167  std::vector<OptionBuffer> buffers;
168 
169  OptionDataType data_type = definition_.getType();
170  // This function is called when an empty data buffer has been
171  // passed to the constructor. In such cases values for particular
172  // data fields will be set using modifier functions but for now
173  // we need to initialize a set of buffers that are specified
174  // for an option by its definition. Since there is no data yet,
175  // we are going to fill these buffers with default values.
176  if (data_type == OPT_RECORD_TYPE) {
177  // For record types we need to iterate over all data fields
178  // specified in option definition and create corresponding
179  // buffers for each of them.
181  definition_.getRecordFields();
182 
183  for (OptionDefinition::RecordFieldsConstIter field = fields.begin();
184  field != fields.end(); ++field) {
185  OptionBuffer buf;
186  createBuffer(buf, *field);
187  // We have the buffer with default value prepared so we
188  // add it to the set of buffers.
189  buffers.push_back(buf);
190  }
191  } else if (!definition_.getArrayType() &&
192  data_type != OPT_EMPTY_TYPE) {
193  // For either 'empty' options we don't have to create any buffers
194  // for obvious reason. For arrays we also don't create any buffers
195  // yet because the set of fields that belong to the array is open
196  // ended so we can't allocate required buffers until we know how
197  // many of them are needed.
198  // For non-arrays we have a single value being held by the option
199  // so we have to allocate exactly one buffer.
200  OptionBuffer buf;
201  createBuffer(buf, data_type);
202  // Add a buffer that we have created and leave.
203  buffers.push_back(buf);
204  }
205  // The 'swap' is used here because we want to make sure that we
206  // don't touch buffers_ until we successfully allocate all
207  // buffers to be stored there.
208  std::swap(buffers, buffers_);
209 }
210 
211 size_t
212 OptionCustom::bufferLength(const OptionDataType data_type, bool in_array,
213  OptionBuffer::const_iterator begin,
214  OptionBuffer::const_iterator end) const {
215  // For fixed-size data type such as boolean, integer, even
216  // IP address we can use the utility function to get the required
217  // buffer size.
218  size_t data_size = OptionDataTypeUtil::getDataTypeLen(data_type);
219 
220  // For variable size types (e.g. string) the function above will
221  // return 0 so we need to do a runtime check of the length.
222  if (data_size == 0) {
223  // FQDN is a special data type as it stores variable length data
224  // but the data length is encoded in the buffer. The easiest way
225  // to obtain the length of the data is to read the FQDN. The
226  // utility function will return the size of the buffer on success.
227  if (data_type == OPT_FQDN_TYPE) {
228  std::string fqdn =
230  // The size of the buffer holding an FQDN is always
231  // 1 byte larger than the size of the string
232  // representation of this FQDN.
233  data_size = fqdn.size() + 1;
234  } else if (!definition_.getArrayType() &&
235  ((data_type == OPT_BINARY_TYPE) ||
236  (data_type == OPT_STRING_TYPE))) {
237  // In other case we are dealing with string or binary value
238  // which size can't be determined. Thus we consume the
239  // remaining part of the buffer for it. Note that variable
240  // size data can be laid at the end of the option only and
241  // that the validate() function in OptionDefinition object
242  // should have checked wheter it is a case for this option.
243  data_size = std::distance(begin, end);
244  } else if (data_type == OPT_IPV6_PREFIX_TYPE) {
245  // The size of the IPV6 prefix type is determined as
246  // one byte (which is the size of the prefix in bits)
247  // followed by the prefix bits (right-padded with
248  // zeros to the nearest octet boundary)
249  if ((begin == end) && !in_array)
250  return 0;
251  PrefixTuple prefix =
253  // Data size comprises 1 byte holding a prefix length and the
254  // prefix length (in bytes) rounded to the nearest byte boundary.
255  data_size = sizeof(uint8_t) + (prefix.first.asUint8() + 7) / 8;
256  } else if (data_type == OPT_TUPLE_TYPE) {
258  getUniverse() == Option::V4 ?
261  std::string value =
263  data_size = value.size();
264  // The size of the buffer holding a tuple is always
265  // 1 or 2 byte larger than the size of the string
266  data_size += getUniverse() == Option::V4 ? 1 : 2;
267  } else {
268  // If we reached the end of buffer we assume that this option is
269  // truncated because there is no remaining data to initialize
270  // an option field.
271  isc_throw(OutOfRange, "option buffer truncated");
272  }
273  }
274 
275  return data_size;
276 }
277 
278 void
279 OptionCustom::createBuffers(const OptionBuffer& data_buf) {
280  // Check that the option definition is correct as we are going
281  // to use it to split the data_ buffer into set of sub buffers.
282  definition_.validate();
283 
284  std::vector<OptionBuffer> buffers;
285  OptionBuffer::const_iterator data = data_buf.begin();
286 
287  OptionDataType data_type = definition_.getType();
288  if (data_type == OPT_RECORD_TYPE) {
289  // An option comprises a record of data fields. We need to
290  // get types of these data fields to allocate enough space
291  // for each buffer.
293  definition_.getRecordFields();
294 
295  // Go over all data fields within a record.
296  for (OptionDefinition::RecordFieldsConstIter field = fields.begin();
297  field != fields.end(); ++field) {
298  size_t data_size = bufferLength(*field, false,
299  data, data_buf.end());
300 
301  // Our data field requires that there is a certain chunk of
302  // data left in the buffer. If not, option is truncated.
303  if (std::distance(data, data_buf.end()) < data_size) {
304  isc_throw(OutOfRange, "option buffer truncated");
305  }
306 
307  // Store the created buffer.
308  buffers.push_back(OptionBuffer(data, data + data_size));
309  // Proceed to the next data field.
310  data += data_size;
311  }
312 
313  // Get extra buffers when the last field is an array.
314  if (definition_.getArrayType()) {
315  while (data != data_buf.end()) {
316  // Code copied from the standard array case
317  size_t data_size = bufferLength(fields.back(), true,
318  data, data_buf.end());
319  assert(data_size > 0);
320  if (std::distance(data, data_buf.end()) < data_size) {
321  break;
322  }
323  buffers.push_back(OptionBuffer(data, data + data_size));
324  data += data_size;
325  }
326  }
327 
328  // Unpack suboptions if any.
329  else if (data != data_buf.end() && !getEncapsulatedSpace().empty()) {
330  unpackOptions(OptionBuffer(data, data_buf.end()));
331  }
332 
333  } else if (data_type != OPT_EMPTY_TYPE) {
334  // If data_type value is other than OPT_RECORD_TYPE, our option is
335  // empty (have no data at all) or it comprises one or more
336  // data fields of the same type. The type of those fields
337  // is held in the data_type variable so let's use it to determine
338  // a size of buffers.
339  size_t data_size = OptionDataTypeUtil::getDataTypeLen(data_type);
340  // The check below will fail if the input buffer is too short
341  // for the data size being held by this option.
342  // Note that data_size returned by getDataTypeLen may be zero
343  // if variable length data is being held by the option but
344  // this will not cause this check to throw exception.
345  if (std::distance(data, data_buf.end()) < data_size) {
346  isc_throw(OutOfRange, "option buffer truncated");
347  }
348  // For an array of values we are taking different path because
349  // we have to handle multiple buffers.
350  if (definition_.getArrayType()) {
351  while (data != data_buf.end()) {
352  data_size = bufferLength(data_type, true, data, data_buf.end());
353  // We don't perform other checks for data types that can't be
354  // used together with array indicator such as strings, empty field
355  // etc. This is because OptionDefinition::validate function should
356  // have checked this already. Thus data_size must be greater than
357  // zero.
358  assert(data_size > 0);
359  // Get chunks of data and store as a collection of buffers.
360  // Truncate any remaining part which length is not divisible by
361  // data_size. Note that it is ok to truncate the data if and only
362  // if the data buffer is long enough to keep at least one value.
363  // This has been checked above already.
364  if (std::distance(data, data_buf.end()) < data_size) {
365  break;
366  }
367  buffers.push_back(OptionBuffer(data, data + data_size));
368  data += data_size;
369  }
370  } else {
371  // For non-arrays the data_size can be zero because
372  // getDataTypeLen returns zero for variable size data types
373  // such as strings. Simply take whole buffer.
374  data_size = bufferLength(data_type, false, data, data_buf.end());
375  if ((data_size > 0) && (std::distance(data, data_buf.end()) >= data_size)) {
376  buffers.push_back(OptionBuffer(data, data + data_size));
377  data += data_size;
378  } else {
379  isc_throw(OutOfRange, "option buffer truncated");
380  }
381 
382  // Unpack suboptions if any.
383  if (data != data_buf.end() && !getEncapsulatedSpace().empty()) {
384  unpackOptions(OptionBuffer(data, data_buf.end()));
385  }
386  }
387  } else {
388  // Unpack suboptions if any.
389  if (data != data_buf.end() && !getEncapsulatedSpace().empty()) {
390  unpackOptions(OptionBuffer(data, data_buf.end()));
391  }
392  }
393  // If everything went ok we can replace old buffer set with new ones.
394  std::swap(buffers_, buffers);
395 }
396 
397 std::string
398 OptionCustom::dataFieldToText(const OptionDataType data_type,
399  const uint32_t index) const {
400  std::ostringstream text;
401 
402  // Get the value of the data field.
403  switch (data_type) {
404  case OPT_BINARY_TYPE:
405  text << util::encode::encodeHex(readBinary(index));
406  break;
407  case OPT_BOOLEAN_TYPE:
408  text << (readBoolean(index) ? "true" : "false");
409  break;
410  case OPT_INT8_TYPE:
411  text << static_cast<int>(readInteger<int8_t>(index));
412  break;
413  case OPT_INT16_TYPE:
414  text << readInteger<int16_t>(index);
415  break;
416  case OPT_INT32_TYPE:
417  text << readInteger<int32_t>(index);
418  break;
419  case OPT_UINT8_TYPE:
420  text << static_cast<unsigned>(readInteger<uint8_t>(index));
421  break;
422  case OPT_UINT16_TYPE:
423  text << readInteger<uint16_t>(index);
424  break;
425  case OPT_UINT32_TYPE:
426  text << readInteger<uint32_t>(index);
427  break;
430  text << readAddress(index);
431  break;
432  case OPT_FQDN_TYPE:
433  text << "\"" << readFqdn(index) << "\"";
434  break;
435  case OPT_TUPLE_TYPE:
436  text << "\"" << readTuple(index) << "\"";
437  break;
438  case OPT_STRING_TYPE:
439  text << "\"" << readString(index) << "\"";
440  break;
441  case OPT_PSID_TYPE:
442  {
443  PSIDTuple t = readPsid(index);
444  text << "len=" << t.first.asUnsigned() << ",psid=" << t.second.asUint16();
445  }
446  default:
447  ;
448  }
449 
450  // Append data field type in brackets.
451  text << " (" << OptionDataTypeUtil::getDataTypeName(data_type) << ")";
452 
453  return (text.str());
454 }
455 
456 void
458 
459  // Pack DHCP header (V4 or V6).
460  packHeader(buf);
461 
462  // Write data from buffers.
463  for (std::vector<OptionBuffer>::const_iterator it = buffers_.begin();
464  it != buffers_.end(); ++it) {
465  // In theory the createBuffers function should have taken
466  // care that there are no empty buffers added to the
467  // collection but it is almost always good to make sure.
468  if (!it->empty()) {
469  buf.writeData(&(*it)[0], it->size());
470  }
471  }
472 
473  // Write suboptions.
474  packOptions(buf);
475 }
476 
477 
478 IOAddress
479 OptionCustom::readAddress(const uint32_t index) const {
480  checkIndex(index);
481 
482  // The address being read can be either IPv4 or IPv6. The decision
483  // is made based on the buffer length. If it holds 4 bytes it is IPv4
484  // address, if it holds 16 bytes it is IPv6.
485  if (buffers_[index].size() == asiolink::V4ADDRESS_LEN) {
486  return (OptionDataTypeUtil::readAddress(buffers_[index], AF_INET));
487  } else if (buffers_[index].size() == asiolink::V6ADDRESS_LEN) {
488  return (OptionDataTypeUtil::readAddress(buffers_[index], AF_INET6));
489  } else {
490  isc_throw(BadDataTypeCast, "unable to read data from the buffer as"
491  << " IP address. Invalid buffer length "
492  << buffers_[index].size() << ".");
493  }
494 }
495 
496 void
498  const uint32_t index) {
499  checkIndex(index);
500 
501  if ((address.isV4() && buffers_[index].size() != V4ADDRESS_LEN) ||
502  (address.isV6() && buffers_[index].size() != V6ADDRESS_LEN)) {
503  isc_throw(BadDataTypeCast, "invalid address specified "
504  << address << ". Expected a valid IPv"
505  << (buffers_[index].size() == V4ADDRESS_LEN ? "4" : "6")
506  << " address.");
507  }
508 
509  OptionBuffer buf;
510  OptionDataTypeUtil::writeAddress(address, buf);
511  std::swap(buf, buffers_[index]);
512 }
513 
514 const OptionBuffer&
515 OptionCustom::readBinary(const uint32_t index) const {
516  checkIndex(index);
517  return (buffers_[index]);
518 }
519 
520 void
522  const uint32_t index) {
523  checkIndex(index);
524  buffers_[index] = buf;
525 }
526 
527 std::string
528 OptionCustom::readTuple(const uint32_t index) const {
529  checkIndex(index);
532  return (OptionDataTypeUtil::readTuple(buffers_[index], lft));
533 }
534 
535 void
537  const uint32_t index) const {
538  checkIndex(index);
539  OptionDataTypeUtil::readTuple(buffers_[index], tuple);
540 }
541 
542 void
543 OptionCustom::writeTuple(const std::string& value, const uint32_t index) {
544  checkIndex(index);
545 
546  buffers_[index].clear();
549  OptionDataTypeUtil::writeTuple(value, lft, buffers_[index]);
550 }
551 
552 void
553 OptionCustom::writeTuple(const OpaqueDataTuple& value, const uint32_t index) {
554  checkIndex(index);
555 
556  buffers_[index].clear();
557  OptionDataTypeUtil::writeTuple(value, buffers_[index]);
558 }
559 
560 bool
561 OptionCustom::readBoolean(const uint32_t index) const {
562  checkIndex(index);
563  return (OptionDataTypeUtil::readBool(buffers_[index]));
564 }
565 
566 void
567 OptionCustom::writeBoolean(const bool value, const uint32_t index) {
568  checkIndex(index);
569 
570  buffers_[index].clear();
571  OptionDataTypeUtil::writeBool(value, buffers_[index]);
572 }
573 
574 std::string
575 OptionCustom::readFqdn(const uint32_t index) const {
576  checkIndex(index);
577  return (OptionDataTypeUtil::readFqdn(buffers_[index]));
578 }
579 
580 void
581 OptionCustom::writeFqdn(const std::string& fqdn, const uint32_t index) {
582  checkIndex(index);
583 
584  // Create a temporary buffer where the FQDN will be written.
585  OptionBuffer buf;
586  // Try to write to the temporary buffer rather than to the
587  // buffers_ member directly guarantees that we don't modify
588  // (clear) buffers_ until we are sure that the provided FQDN
589  // is valid.
591  // If we got to this point it means that the FQDN is valid.
592  // We can move the contents of the temporary buffer to the
593  // target buffer.
594  std::swap(buffers_[index], buf);
595 }
596 
598 OptionCustom::readPrefix(const uint32_t index) const {
599  checkIndex(index);
600  return (OptionDataTypeUtil::readPrefix(buffers_[index]));
601 }
602 
603 void
605  const IOAddress& prefix,
606  const uint32_t index) {
607  checkIndex(index);
608 
609  OptionBuffer buf;
610  OptionDataTypeUtil::writePrefix(prefix_len, prefix, buf);
611  // If there are no errors while writing PSID to a buffer, we can
612  // replace the current buffer with a new buffer.
613  std::swap(buffers_[index], buf);
614 }
615 
616 
617 PSIDTuple
618 OptionCustom::readPsid(const uint32_t index) const {
619  checkIndex(index);
620  return (OptionDataTypeUtil::readPsid(buffers_[index]));
621 }
622 
623 void
624 OptionCustom::writePsid(const PSIDLen& psid_len, const PSID& psid,
625  const uint32_t index) {
626  checkIndex(index);
627 
628  OptionBuffer buf;
629  OptionDataTypeUtil::writePsid(psid_len, psid, buf);
630  // If there are no errors while writing PSID to a buffer, we can
631  // replace the current buffer with a new buffer.
632  std::swap(buffers_[index], buf);
633 }
634 
635 
636 std::string
637 OptionCustom::readString(const uint32_t index) const {
638  checkIndex(index);
639  return (OptionDataTypeUtil::readString(buffers_[index]));
640 }
641 
642 void
643 OptionCustom::writeString(const std::string& text, const uint32_t index) {
644  checkIndex(index);
645 
646  // Let's clear a buffer as we want to replace the value of the
647  // whole buffer. If we fail to clear the buffer the data will
648  // be appended.
649  buffers_[index].clear();
650  // If the text value is empty we can leave because the buffer
651  // is already empty.
652  if (!text.empty()) {
653  OptionDataTypeUtil::writeString(text, buffers_[index]);
654  }
655 }
656 
657 void
659  OptionBufferConstIter end) {
660  initialize(begin, end);
661 }
662 
663 uint16_t
665  // The length of the option is a sum of option header ...
666  size_t length = getHeaderLen();
667 
668  // ... lengths of all buffers that hold option data ...
669  for (std::vector<OptionBuffer>::const_iterator buf = buffers_.begin();
670  buf != buffers_.end(); ++buf) {
671  length += buf->size();
672  }
673 
674  // ... and lengths of all suboptions
675  for (OptionCollection::const_iterator it = options_.begin();
676  it != options_.end();
677  ++it) {
678  length += (*it).second->len();
679  }
680 
681  return (static_cast<uint16_t>(length));
682 }
683 
685  const OptionBufferConstIter last) {
686  setData(first, last);
687 
688  // Chop the data_ buffer into set of buffers that represent
689  // option fields data.
690  createBuffers(getData());
691 }
692 
693 std::string OptionCustom::toText(int indent) const {
694  std::stringstream output;
695 
696  output << headerToText(indent) << ":";
697 
698  OptionDataType data_type = definition_.getType();
699  if (data_type == OPT_RECORD_TYPE) {
701  definition_.getRecordFields();
702 
703  // For record types we iterate over fields defined in
704  // option definition and match the appropriate buffer
705  // with them.
706  for (OptionDefinition::RecordFieldsConstIter field = fields.begin();
707  field != fields.end(); ++field) {
708  output << " " << dataFieldToText(*field, std::distance(fields.begin(),
709  field));
710  }
711 
712  // If the last record field is an array iterate on extra buffers
713  if (definition_.getArrayType()) {
714  for (unsigned int i = fields.size(); i < getDataFieldsNum(); ++i) {
715  output << " " << dataFieldToText(fields.back(), i);
716  }
717  }
718  } else {
719  // For non-record types we iterate over all buffers
720  // and print the data type set globally for an option
721  // definition. We take the same code path for arrays
722  // and non-arrays as they only differ in such a way that
723  // non-arrays have just single data field.
724  for (unsigned int i = 0; i < getDataFieldsNum(); ++i) {
725  output << " " << dataFieldToText(definition_.getType(), i);
726  }
727  }
728 
729  // Append suboptions.
730  output << suboptionsToText(indent + 2);
731 
732  return (output.str());
733 }
734 
735 } // end of isc::dhcp namespace
736 } // end of isc namespace
isc::dhcp::OptionDataTypeUtil::getDataTypeLen
static int getDataTypeLen(const OptionDataType data_type)
Get data type buffer length.
Definition: option_data_types.cc:80
isc::dhcp::OptionBuffer
std::vector< uint8_t > OptionBuffer
buffer types used in DHCP code.
Definition: option.h:25
isc::dhcp::OptionDataTypeUtil::readString
static std::string readString(const std::vector< uint8_t > &buf)
Read string value from a buffer.
Definition: option_data_types.cc:574
isc::dhcp::OPT_UINT32_TYPE
@ OPT_UINT32_TYPE
Definition: option_data_types.h:54
isc::dhcp::OptionCustom::addArrayDataField
void addArrayDataField(const asiolink::IOAddress &address)
Create new buffer and set its value as an IP address.
Definition: option_custom.cc:51
isc::dhcp::OpaqueDataTuple::LENGTH_1_BYTE
@ LENGTH_1_BYTE
Definition: opaque_data_tuple.h:56
isc::dhcp::OptionDefinition::validate
void validate() const
Check if the option definition is valid.
Definition: option_definition.cc:285
isc::dhcp::OptionDataTypeUtil::readAddress
static asiolink::IOAddress readAddress(const std::vector< uint8_t > &buf, const short family)
Read IPv4 or IPv6 address from a buffer.
Definition: option_data_types.cc:132
isc::dhcp::OptionCustom::writeString
void writeString(const std::string &text, const uint32_t index=0)
Write a string value into a buffer.
Definition: option_custom.cc:643
isc::dhcp::OptionDataTypeUtil::getDataTypeName
static const std::string & getDataTypeName(const OptionDataType data_type)
Return option data type name from the data type enumerator.
Definition: option_data_types.cc:111
libdhcp++.h
isc::dhcp::OptionDataTypeUtil::writePrefix
static void writePrefix(const PrefixLen &prefix_len, const asiolink::IOAddress &prefix, std::vector< uint8_t > &buf)
Append prefix into a buffer.
Definition: option_data_types.cc:464
isc::dhcp::OptionDefinition::getRecordFields
const RecordFieldsCollection & getRecordFields() const
Return list of record fields.
Definition: option_definition.h:281
isc::dhcp::Option::suboptionsToText
std::string suboptionsToText(const int indent=0) const
Returns collection of suboptions in the textual format.
Definition: option.cc:313
isc::dhcp::OptionCustom::initialize
void initialize(const OptionBufferConstIter first, const OptionBufferConstIter last)
Sets content of this option from buffer.
Definition: option_custom.cc:684
option_data_types.h
isc::dhcp::OPT_BOOLEAN_TYPE
@ OPT_BOOLEAN_TYPE
Definition: option_data_types.h:48
isc::dhcp::OPT_IPV4_ADDRESS_TYPE
@ OPT_IPV4_ADDRESS_TYPE
Definition: option_data_types.h:56
isc::dhcp::OptionCustom::readString
std::string readString(const uint32_t index=0) const
Read a buffer as string value.
Definition: option_custom.cc:637
isc::dhcp::OptionDataTypeUtil::writeTuple
static void writeTuple(const std::string &value, OpaqueDataTuple::LengthFieldType lengthfieldtype, std::vector< uint8_t > &buf)
Append length and string tuple to a buffer.
Definition: option_data_types.cc:231
isc::dhcp::OptionCustom::writeTuple
void writeTuple(const std::string &value, const uint32_t index=0)
Write a length and string tuple into a buffer.
Definition: option_custom.cc:543
isc::dhcp::OPT_STRING_TYPE
@ OPT_STRING_TYPE
Definition: option_data_types.h:60
isc::dhcp::OpaqueDataTuple::LengthFieldType
LengthFieldType
Size of the length field in the tuple.
Definition: opaque_data_tuple.h:55
isc::dhcp::OptionCustom::writeFqdn
void writeFqdn(const std::string &fqdn, const uint32_t index=0)
Write an FQDN into a buffer.
Definition: option_custom.cc:581
isc::dhcp::OPT_EMPTY_TYPE
@ OPT_EMPTY_TYPE
Definition: option_data_types.h:46
isc::dhcp::OptionCustom::readAddress
asiolink::IOAddress readAddress(const uint32_t index=0) const
Read a buffer as IP address.
Definition: option_custom.cc:479
isc::dhcp::OptionDataTypeUtil::writeAddress
static void writeAddress(const asiolink::IOAddress &address, std::vector< uint8_t > &buf)
Append IPv4 or IPv6 address to a buffer.
Definition: option_data_types.cc:154
isc::dhcp::OptionDefinition
Base class representing a DHCP option definition.
Definition: option_definition.h:137
isc::dhcp::OptionCustom::writeAddress
void writeAddress(const asiolink::IOAddress &address, const uint32_t index=0)
Write an IP address into a buffer.
Definition: option_custom.cc:497
isc::dhcp::OptionCustom::len
virtual uint16_t len() const
Returns length of the complete option (data length + DHCPv4/DHCPv6 option header)
Definition: option_custom.cc:664
isc::dhcp::Option::getUniverse
Universe getUniverse() const
returns option universe (V4 or V6)
Definition: option.h:190
isc::dhcp::OptionDataTypeUtil::writeFqdn
static void writeFqdn(const std::string &fqdn, std::vector< uint8_t > &buf, const bool downcase=false)
Append FQDN into a buffer.
Definition: option_data_types.cc:333
isc
Defines the logger used by the top-level component of kea-dhcp-ddns.
Definition: agent_parser.cc:144
isc::dhcp::OptionCustom::readTuple
std::string readTuple(const uint32_t index=0) const
Read a buffer as length and string tuple.
Definition: option_custom.cc:528
hex.h
isc_throw
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Definition: exceptions/exceptions.h:192
isc::dhcp::OptionCustom::clone
virtual OptionPtr clone() const
Copies this option and returns a pointer to the copy.
Definition: option_custom.cc:46
isc::dhcp::Option::setEncapsulatedSpace
void setEncapsulatedSpace(const std::string &encapsulated_space)
Sets the name of the option space encapsulated by this option.
Definition: option.h:374
isc::dhcp::OPT_INT16_TYPE
@ OPT_INT16_TYPE
Definition: option_data_types.h:50
isc::dhcp::OptionDataTypeUtil::readBool
static bool readBool(const std::vector< uint8_t > &buf)
Read boolean value from a buffer.
Definition: option_data_types.cc:291
isc::dhcp::OPT_UINT8_TYPE
@ OPT_UINT8_TYPE
Definition: option_data_types.h:52
isc::dhcp::Option::packHeader
void packHeader(isc::util::OutputBuffer &buf) const
Store option's header in a buffer.
Definition: option.cc:117
isc::dhcp::OptionDataTypeUtil::readPrefix
static PrefixTuple readPrefix(const std::vector< uint8_t > &buf)
Read prefix from a buffer.
Definition: option_data_types.cc:368
isc::dhcp::PrefixLen
Encapsulates prefix length.
Definition: option_data_types.h:277
isc::util::OutputBuffer
The OutputBuffer class is a buffer abstraction for manipulating mutable data.
Definition: buffer.h:294
isc::dhcp::OptionDefinition::getArrayType
bool getArrayType() const
Return array type indicator.
Definition: option_definition.h:259
isc::dhcp::OptionCustom::toText
virtual std::string toText(int indent=0) const
Returns string representation of the option.
Definition: option_custom.cc:693
isc::dhcp::OPT_INT8_TYPE
@ OPT_INT8_TYPE
Definition: option_data_types.h:49
isc::dhcp::OptionDataTypeUtil::writeString
static void writeString(const std::string &value, std::vector< uint8_t > &buf)
Write UTF8-encoded string into a buffer.
Definition: option_data_types.cc:583
isc::dhcp::Option::unpackOptions
void unpackOptions(const OptionBuffer &buf)
Builds a collection of sub options from the buffer.
Definition: option.cc:156
isc::dhcp::OptionCustom::writePrefix
void writePrefix(const PrefixLen &prefix_len, const asiolink::IOAddress &prefix, const uint32_t index=0)
Write prefix length and value into a buffer.
Definition: option_custom.cc:604
isc::dhcp::PrefixTuple
std::pair< PrefixLen, asiolink::IOAddress > PrefixTuple
Defines a pair of prefix length / value.
Definition: option_data_types.h:315
isc::dhcp::OpaqueDataTuple::LENGTH_2_BYTES
@ LENGTH_2_BYTES
Definition: opaque_data_tuple.h:57
isc::dhcp::BadDataTypeCast
Exception to be thrown when cast to the data type was unsuccessful.
Definition: option_data_types.h:30
isc::dhcp::OPT_RECORD_TYPE
@ OPT_RECORD_TYPE
Definition: option_data_types.h:63
isc::dhcp::OptionDataTypeUtil::readFqdn
static std::string readFqdn(const std::vector< uint8_t > &buf)
Read FQDN from a buffer as a string value.
Definition: option_data_types.cc:312
isc::dhcp::OptionCustom::readBinary
const OptionBuffer & readBinary(const uint32_t index=0) const
Read a buffer as binary data.
Definition: option_custom.cc:515
isc::dhcp::OPT_BINARY_TYPE
@ OPT_BINARY_TYPE
Definition: option_data_types.h:47
isc::dhcp::OPT_PSID_TYPE
@ OPT_PSID_TYPE
Definition: option_data_types.h:59
isc::dhcp::OptionCustom::readBoolean
bool readBoolean(const uint32_t index=0) const
Read a buffer as boolean value.
Definition: option_custom.cc:561
isc::dhcp::OptionDataTypeUtil::readTuple
static std::string readTuple(const std::vector< uint8_t > &buf, OpaqueDataTuple::LengthFieldType lengthfieldtype)
Read length and string tuple from a buffer.
Definition: option_data_types.cc:179
isc::dhcp::Option::setData
void setData(InputIterator first, InputIterator last)
Sets content of this option from buffer.
Definition: option.h:366
isc::dhcp::OptionDataTypeUtil::writeBool
static void writeBool(const bool value, std::vector< uint8_t > &buf)
Append boolean value into a buffer.
Definition: option_data_types.cc:306
isc::dhcp::OptionCustom::pack
virtual void pack(isc::util::OutputBuffer &buf) const
Writes DHCP option in a wire format to a buffer.
Definition: option_custom.cc:457
isc::dhcp::OpaqueDataTuple
Represents a single instance of the opaque data preceded by length.
Definition: opaque_data_tuple.h:45
isc::dhcp::Option::packOptions
void packOptions(isc::util::OutputBuffer &buf) const
Store sub options in a buffer.
Definition: option.cc:137
isc::dhcp::OptionDataType
OptionDataType
Data types of DHCP option fields.
Definition: option_data_types.h:45
isc::util::encode::encodeHex
string encodeHex(const vector< uint8_t > &binary)
Encode binary data in the base16 ('hex') format.
Definition: base_n.cc:461
isc::OutOfRange
A generic exception that is thrown if a parameter given to a method would refer to or modify out-of-r...
Definition: exceptions/exceptions.h:115
isc::dhcp::OPT_INT32_TYPE
@ OPT_INT32_TYPE
Definition: option_data_types.h:51
isc::dhcp::OptionCustom::writeBinary
void writeBinary(const OptionBuffer &buf, const uint32_t index=0)
Write binary data into a buffer.
Definition: option_custom.cc:521
isc::dhcp::OptionCustom::getDataFieldsNum
uint32_t getDataFieldsNum() const
Return a number of the data fields.
Definition: option_custom.h:146
isc::dhcp::OptionPtr
boost::shared_ptr< Option > OptionPtr
Definition: option.h:37
isc::dhcp::OptionCustom::unpack
virtual void unpack(OptionBufferConstIter begin, OptionBufferConstIter end)
Parses received buffer.
Definition: option_custom.cc:658
isc::dhcp::OptionDefinition::getType
OptionDataType getType() const
Return option data type.
Definition: option_definition.h:288
isc::dhcp::OptionCustom::writeBoolean
void writeBoolean(const bool value, const uint32_t index=0)
Write a boolean value into a buffer.
Definition: option_custom.cc:567
isc::dhcp::OptionCustom::readPsid
PSIDTuple readPsid(const uint32_t index=0) const
Read a buffer as a PSID length / value tuple.
Definition: option_custom.cc:618
isc::dhcp::OptionCustom::readPrefix
PrefixTuple readPrefix(const uint32_t index=0) const
Read a buffer as variable length prefix.
Definition: option_custom.cc:598
isc::dhcp::PSIDLen
Encapsulates PSID length.
Definition: option_data_types.h:201
isc::dhcp::Option::Universe
Universe
defines option universe DHCPv4 or DHCPv6
Definition: option.h:67
isc::dhcp::OPT_IPV6_PREFIX_TYPE
@ OPT_IPV6_PREFIX_TYPE
Definition: option_data_types.h:58
isc::dhcp::Option::getData
virtual const OptionBuffer & getData() const
Returns pointer to actual data.
Definition: option.h:268
isc::util::OutputBuffer::writeData
void writeData(const void *data, size_t len)
Copy an arbitrary length of data into the buffer.
Definition: buffer.h:547
isc::dhcp::OPT_FQDN_TYPE
@ OPT_FQDN_TYPE
Definition: option_data_types.h:62
isc::dhcp::OPT_TUPLE_TYPE
@ OPT_TUPLE_TYPE
Definition: option_data_types.h:61
isc::dhcp::PSIDTuple
std::pair< PSIDLen, PSID > PSIDTuple
Defines a pair of PSID length / value.
Definition: option_data_types.h:274
isc::dhcp::Option
Definition: option.h:58
isc::dhcp::OPT_UINT16_TYPE
@ OPT_UINT16_TYPE
Definition: option_data_types.h:53
isc::dhcp::Option::headerToText
std::string headerToText(const int indent=0, const std::string &type_name="") const
Returns option header in the textual format.
Definition: option.cc:294
isc::dhcp::OptionDefinition::RecordFieldsConstIter
std::vector< OptionDataType >::const_iterator RecordFieldsConstIter
Const iterator for record data fields.
Definition: option_definition.h:143
isc::dhcp::PSID
Encapsulates PSID value.
Definition: option_data_types.h:246
isc::dhcp::OPT_IPV6_ADDRESS_TYPE
@ OPT_IPV6_ADDRESS_TYPE
Definition: option_data_types.h:57
option_custom.h
isc::dhcp::Option::getHeaderLen
virtual uint16_t getHeaderLen() const
Returns length of header (2 for v4, 4 for v6)
Definition: option.cc:328
isc::dhcp::OptionBufferConstIter
OptionBuffer::const_iterator OptionBufferConstIter
const_iterator for walking over OptionBuffer
Definition: option.h:31
isc::dhcp::Option::options_
OptionCollection options_
collection for storing suboptions
Definition: option.h:521
isc::dhcp::OptionDataTypeUtil::writePsid
static void writePsid(const PSIDLen &psid_len, const PSID &psid, std::vector< uint8_t > &buf)
Append PSID length/value into a buffer.
Definition: option_data_types.cc:550
isc::dhcp::OptionCustom::writePsid
void writePsid(const PSIDLen &psid_len, const PSID &psid, const uint32_t index=0)
Write PSID length / value into a buffer.
Definition: option_custom.cc:624
isc::dhcp::Option::V4
@ V4
Definition: option.h:67
isc::dhcp::OptionDefinition::RecordFieldsCollection
std::vector< OptionDataType > RecordFieldsCollection
List of fields within the record.
Definition: option_definition.h:141
isc::dhcp::OptionDefinition::getEncapsulatedSpace
std::string getEncapsulatedSpace() const
Return name of the encapsulated option space.
Definition: option_definition.h:269
isc::dhcp::Option::getEncapsulatedSpace
std::string getEncapsulatedSpace() const
Returns the name of the option space encapsulated by this option.
Definition: option.h:381
isc::dhcp::OptionDataTypeUtil::readPsid
static PSIDTuple readPsid(const std::vector< uint8_t > &buf)
Read PSID length / value tuple from a buffer.
Definition: option_data_types.cc:502
isc::dhcp::OptionCustom::readFqdn
std::string readFqdn(const uint32_t index=0) const
Read a buffer as FQDN.
Definition: option_custom.cc:575
isc::dhcp::OptionCustom::OptionCustom
OptionCustom(const OptionDefinition &def, Universe u)
Constructor, used for options to be sent.
Definition: option_custom.cc:18