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
void writeTuple(const std::string &value, const uint32_t index=0)
Write a length and string tuple into a buffer.
std::string suboptionsToText(const int indent=0) const
Returns collection of suboptions in the textual format.
Definition: option.cc:313
void addArrayDataField(const asiolink::IOAddress &address)
Create new buffer and set its value as an IP address.
Encapsulates PSID length.
asiolink::IOAddress readAddress(const uint32_t index=0) const
Read a buffer as IP address.
Base class representing a DHCP option definition.
uint32_t getDataFieldsNum() const
Return a number of the data fields.
void writeAddress(const asiolink::IOAddress &address, const uint32_t index=0)
Write an IP address into a buffer.
bool readBoolean(const uint32_t index=0) const
Read a buffer as boolean value.
std::vector< OptionDataType > RecordFieldsCollection
List of fields within the record.
static void writePsid(const PSIDLen &psid_len, const PSID &psid, std::vector< uint8_t > &buf)
Append PSID length/value into a buffer.
void packHeader(isc::util::OutputBuffer &buf) const
Store option's header in a buffer.
Definition: option.cc:117
static const std::string & getDataTypeName(const OptionDataType data_type)
Return option data type name from the data type enumerator.
static std::string readFqdn(const std::vector< uint8_t > &buf)
Read FQDN from a buffer as a string value.
std::string readFqdn(const uint32_t index=0) const
Read a buffer as FQDN.
OptionCustom(const OptionDefinition &def, Universe u)
Constructor, used for options to be sent.
static void writeBool(const bool value, std::vector< uint8_t > &buf)
Append boolean value into a buffer.
boost::shared_ptr< Option > OptionPtr
Definition: option.h:37
static void writeFqdn(const std::string &fqdn, std::vector< uint8_t > &buf, const bool downcase=false)
Append FQDN into a buffer.
static int getDataTypeLen(const OptionDataType data_type)
Get data type buffer length.
Universe
defines option universe DHCPv4 or DHCPv6
Definition: option.h:67
static void writePrefix(const PrefixLen &prefix_len, const asiolink::IOAddress &prefix, std::vector< uint8_t > &buf)
Append prefix into a buffer.
static bool readBool(const std::vector< uint8_t > &buf)
Read boolean value from a buffer.
std::pair< PrefixLen, asiolink::IOAddress > PrefixTuple
Defines a pair of prefix length / value.
virtual void unpack(OptionBufferConstIter begin, OptionBufferConstIter end)
Parses received buffer.
void writeBoolean(const bool value, const uint32_t index=0)
Write a boolean value into a buffer.
virtual uint16_t getHeaderLen() const
Returns length of header (2 for v4, 4 for v6)
Definition: option.cc:328
PSIDTuple readPsid(const uint32_t index=0) const
Read a buffer as a PSID length / value tuple.
static PSIDTuple readPsid(const std::vector< uint8_t > &buf)
Read PSID length / value tuple from a buffer.
virtual uint16_t len() const
Returns length of the complete option (data length + DHCPv4/DHCPv6 option header)
std::vector< uint8_t > OptionBuffer
buffer types used in DHCP code.
Definition: option.h:25
std::string readTuple(const uint32_t index=0) const
Read a buffer as length and string tuple.
void writeData(const void *data, size_t len)
Copy an arbitrary length of data into the buffer.
Definition: buffer.h:547
static void writeTuple(const std::string &value, OpaqueDataTuple::LengthFieldType lengthfieldtype, std::vector< uint8_t > &buf)
Append length and string tuple to a buffer.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
static std::string readString(const std::vector< uint8_t > &buf)
Read string value from a buffer.
std::string headerToText(const int indent=0, const std::string &type_name="") const
Returns option header in the textual format.
Definition: option.cc:294
OptionDataType
Data types of DHCP option fields.
Universe getUniverse() const
returns option universe (V4 or V6)
Definition: option.h:190
Encapsulates PSID value.
virtual OptionPtr clone() const
Copies this option and returns a pointer to the copy.
OptionCollection options_
collection for storing suboptions
Definition: option.h:521
void writePsid(const PSIDLen &psid_len, const PSID &psid, const uint32_t index=0)
Write PSID length / value into a buffer.
virtual const OptionBuffer & getData() const
Returns pointer to actual data.
Definition: option.h:268
void writePrefix(const PrefixLen &prefix_len, const asiolink::IOAddress &prefix, const uint32_t index=0)
Write prefix length and value into a buffer.
void setEncapsulatedSpace(const std::string &encapsulated_space)
Sets the name of the option space encapsulated by this option.
Definition: option.h:374
PrefixTuple readPrefix(const uint32_t index=0) const
Read a buffer as variable length prefix.
The OutputBuffer class is a buffer abstraction for manipulating mutable data.
Definition: buffer.h:294
OptionBuffer::const_iterator OptionBufferConstIter
const_iterator for walking over OptionBuffer
Definition: option.h:31
LengthFieldType
Size of the length field in the tuple.
static asiolink::IOAddress readAddress(const std::vector< uint8_t > &buf, const short family)
Read IPv4 or IPv6 address from a buffer.
std::pair< PSIDLen, PSID > PSIDTuple
Defines a pair of PSID length / value.
Defines the logger used by the top-level component of kea-dhcp-ddns.
void packOptions(isc::util::OutputBuffer &buf) const
Store sub options in a buffer.
Definition: option.cc:137
string encodeHex(const vector< uint8_t > &binary)
Encode binary data in the base16 ('hex') format.
Definition: base_n.cc:461
virtual void pack(isc::util::OutputBuffer &buf) const
Writes DHCP option in a wire format to a buffer.
void unpackOptions(const OptionBuffer &buf)
Builds a collection of sub options from the buffer.
Definition: option.cc:156
const RecordFieldsCollection & getRecordFields() const
Return list of record fields.
void writeBinary(const OptionBuffer &buf, const uint32_t index=0)
Write binary data into a buffer.
static std::string readTuple(const std::vector< uint8_t > &buf, OpaqueDataTuple::LengthFieldType lengthfieldtype)
Read length and string tuple from a buffer.
virtual std::string toText(int indent=0) const
Returns string representation of the option.
std::string getEncapsulatedSpace() const
Returns the name of the option space encapsulated by this option.
Definition: option.h:381
static void writeAddress(const asiolink::IOAddress &address, std::vector< uint8_t > &buf)
Append IPv4 or IPv6 address to a buffer.
void validate() const
Check if the option definition is valid.
void writeFqdn(const std::string &fqdn, const uint32_t index=0)
Write an FQDN into a buffer.
static PrefixTuple readPrefix(const std::vector< uint8_t > &buf)
Read prefix from a buffer.
Represents a single instance of the opaque data preceded by length.
A generic exception that is thrown if a parameter given to a method would refer to or modify out-of-r...
std::vector< OptionDataType >::const_iterator RecordFieldsConstIter
Const iterator for record data fields.
Exception to be thrown when cast to the data type was unsuccessful.
std::string readString(const uint32_t index=0) const
Read a buffer as string value.
bool getArrayType() const
Return array type indicator.
OptionDataType getType() const
Return option data type.
void setData(InputIterator first, InputIterator last)
Sets content of this option from buffer.
Definition: option.h:366
static void writeString(const std::string &value, std::vector< uint8_t > &buf)
Write UTF8-encoded string into a buffer.
std::string getEncapsulatedSpace() const
Return name of the encapsulated option space.
Encapsulates prefix length.
void writeString(const std::string &text, const uint32_t index=0)
Write a string value into a buffer.
void initialize(const OptionBufferConstIter first, const OptionBufferConstIter last)
Sets content of this option from buffer.
const OptionBuffer & readBinary(const uint32_t index=0) const
Read a buffer as binary data.