Kea  1.5.0
option_definition.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 
9 #include <dhcp/dhcp4.h>
10 #include <dhcp/dhcp6.h>
11 #include <dhcp/option4_addrlst.h>
13 #include <dhcp/option6_addrlst.h>
15 #include <dhcp/option6_ia.h>
16 #include <dhcp/option6_iaaddr.h>
17 #include <dhcp/option6_iaprefix.h>
18 #include <dhcp/option6_pdexclude.h>
20 #include <dhcp/option_custom.h>
21 #include <dhcp/option_definition.h>
22 #include <dhcp/option_int.h>
23 #include <dhcp/option_int_array.h>
25 #include <dhcp/option_string.h>
26 #include <dhcp/option_vendor.h>
28 #include <util/encode/hex.h>
29 #include <dns/labelsequence.h>
30 #include <dns/name.h>
31 #include <util/strutil.h>
32 #include <boost/algorithm/string/classification.hpp>
33 #include <boost/algorithm/string/predicate.hpp>
34 #include <boost/dynamic_bitset.hpp>
35 #include <sstream>
36 
37 using namespace std;
38 using namespace isc::util;
39 
40 namespace isc {
41 namespace dhcp {
42 
43 OptionDefinition::OptionDefinition(const std::string& name,
44  const uint16_t code,
45  const std::string& type,
46  const bool array_type /* = false */)
47  : name_(name),
48  code_(code),
49  type_(OPT_UNKNOWN_TYPE),
50  array_type_(array_type),
51  encapsulated_space_(""),
52  record_fields_(),
53  user_context_(),
54  option_space_name_() {
55  // Data type is held as enum value by this class.
56  // Use the provided option type string to get the
57  // corresponding enum value.
58  type_ = OptionDataTypeUtil::getDataType(type);
59 }
60 
61 OptionDefinition::OptionDefinition(const std::string& name,
62  const uint16_t code,
63  const OptionDataType type,
64  const bool array_type /* = false */)
65  : name_(name),
66  code_(code),
67  type_(type),
68  array_type_(array_type),
69  encapsulated_space_("") {
70 }
71 
72 OptionDefinition::OptionDefinition(const std::string& name,
73  const uint16_t code,
74  const std::string& type,
75  const char* encapsulated_space)
76  : name_(name),
77  code_(code),
78  // Data type is held as enum value by this class.
79  // Use the provided option type string to get the
80  // corresponding enum value.
81  type_(OptionDataTypeUtil::getDataType(type)),
82  array_type_(false),
83  encapsulated_space_(encapsulated_space),
84  record_fields_(),
85  user_context_(),
86  option_space_name_() {
87 }
88 
89 OptionDefinition::OptionDefinition(const std::string& name,
90  const uint16_t code,
91  const OptionDataType type,
92  const char* encapsulated_space)
93  : name_(name),
94  code_(code),
95  type_(type),
96  array_type_(false),
97  encapsulated_space_(encapsulated_space),
98  record_fields_(),
99  user_context_(),
100  option_space_name_() {
101 }
102 
103 bool
105  return (name_ == other.name_ &&
106  code_ == other.code_ &&
107  type_ == other.type_ &&
108  array_type_ == other.array_type_ &&
109  encapsulated_space_ == other.encapsulated_space_ &&
110  record_fields_ == other.record_fields_ &&
111  option_space_name_ == other.option_space_name_);
112 }
113 
114 void
115 OptionDefinition::addRecordField(const std::string& data_type_name) {
116  OptionDataType data_type = OptionDataTypeUtil::getDataType(data_type_name);
117  addRecordField(data_type);
118 }
119 
120 void
122  if (type_ != OPT_RECORD_TYPE) {
123  isc_throw(isc::InvalidOperation, "'record' option type must be used"
124  " to add data fields to the record");
125  }
126  if (data_type >= OPT_RECORD_TYPE ||
127  data_type == OPT_ANY_ADDRESS_TYPE ||
128  data_type == OPT_EMPTY_TYPE) {
130  "attempted to add invalid data type to the record.");
131  }
132  record_fields_.push_back(data_type);
133 }
134 
135 OptionPtr
137  OptionBufferConstIter begin,
138  OptionBufferConstIter end) const {
139 
140  try {
141  // Some of the options are represented by the specialized classes derived
142  // from Option class (e.g. IA_NA, IAADDR). Although, they can be also
143  // represented by the generic classes, we want the object of the specialized
144  // type to be returned. Therefore, we first check that if we are dealing
145  // with such an option. If the instance is returned we just exit at this
146  // point. If not, we will search for a generic option type to return.
147  OptionPtr option = factorySpecialFormatOption(u, begin, end);
148  if (option) {
149  return (option);
150  }
151 
152  switch(type_) {
153  case OPT_EMPTY_TYPE:
154  if (getEncapsulatedSpace().empty()) {
155  return (factoryEmpty(u, type));
156  } else {
157  return (OptionPtr(new OptionCustom(*this, u, begin, end)));
158  }
159 
160  case OPT_BINARY_TYPE:
161  return (factoryGeneric(u, type, begin, end));
162 
163  case OPT_UINT8_TYPE:
164  return (array_type_ ?
165  factoryIntegerArray<uint8_t>(u, type, begin, end) :
166  factoryInteger<uint8_t>(u, type, getEncapsulatedSpace(),
167  begin, end));
168 
169  case OPT_INT8_TYPE:
170  return (array_type_ ?
171  factoryIntegerArray<int8_t>(u, type, begin, end) :
172  factoryInteger<int8_t>(u, type, getEncapsulatedSpace(),
173  begin, end));
174 
175  case OPT_UINT16_TYPE:
176  return (array_type_ ?
177  factoryIntegerArray<uint16_t>(u, type, begin, end) :
178  factoryInteger<uint16_t>(u, type, getEncapsulatedSpace(),
179  begin, end));
180 
181  case OPT_INT16_TYPE:
182  return (array_type_ ?
183  factoryIntegerArray<uint16_t>(u, type, begin, end) :
184  factoryInteger<int16_t>(u, type, getEncapsulatedSpace(),
185  begin, end));
186 
187  case OPT_UINT32_TYPE:
188  return (array_type_ ?
189  factoryIntegerArray<uint32_t>(u, type, begin, end) :
190  factoryInteger<uint32_t>(u, type, getEncapsulatedSpace(),
191  begin, end));
192 
193  case OPT_INT32_TYPE:
194  return (array_type_ ?
195  factoryIntegerArray<uint32_t>(u, type, begin, end) :
196  factoryInteger<int32_t>(u, type, getEncapsulatedSpace(),
197  begin, end));
198 
200  // If definition specifies that an option is an array
201  // of IPv4 addresses we return an instance of specialized
202  // class (OptionAddrLst4). For non-array types there is no
203  // specialized class yet implemented so we drop through
204  // to return an instance of OptionCustom.
205  if (array_type_) {
206  return (factoryAddrList4(type, begin, end));
207  }
208  break;
209 
211  // Handle array type only here (see comments for
212  // OPT_IPV4_ADDRESS_TYPE case).
213  if (array_type_) {
214  return (factoryAddrList6(type, begin, end));
215  }
216  break;
217 
218  case OPT_STRING_TYPE:
219  return (OptionPtr(new OptionString(u, type, begin, end)));
220 
221  case OPT_TUPLE_TYPE:
222  // Handle array type only here (see comments for
223  // OPT_IPV4_ADDRESS_TYPE case).
224  if (array_type_) {
225  return (factoryOpaqueDataTuples(u, type, begin, end));
226  }
227  break;
228 
229  default:
230  // Do nothing. We will return generic option a few lines down.
231  ;
232  }
233  return (OptionPtr(new OptionCustom(*this, u, begin, end)));
234  } catch (const SkipRemainingOptionsError& ex) {
235  // We need to throw this one as is.
236  throw ex;
237  } catch (const Exception& ex) {
239  }
240 }
241 
242 OptionPtr
244  const OptionBuffer& buf) const {
245  return (optionFactory(u, type, buf.begin(), buf.end()));
246 }
247 
248 OptionPtr
250  const std::vector<std::string>& values) const {
251  OptionBuffer buf;
252  if (!array_type_ && type_ != OPT_RECORD_TYPE) {
253  if (values.empty()) {
254  if (type_ != OPT_EMPTY_TYPE) {
255  isc_throw(InvalidOptionValue, "no option value specified");
256  }
257  } else {
258  writeToBuffer(u, util::str::trim(values[0]), type_, buf);
259  }
260  } else if (array_type_ && type_ != OPT_RECORD_TYPE) {
261  for (size_t i = 0; i < values.size(); ++i) {
262  writeToBuffer(u, util::str::trim(values[i]), type_, buf);
263  }
264  } else if (type_ == OPT_RECORD_TYPE) {
265  const RecordFieldsCollection& records = getRecordFields();
266  if (records.size() > values.size()) {
267  isc_throw(InvalidOptionValue, "number of data fields for the option"
268  << " type '" << getCode() << "' is greater than number"
269  << " of values provided.");
270  }
271  for (size_t i = 0; i < records.size(); ++i) {
272  writeToBuffer(u, util::str::trim(values[i]), records[i], buf);
273  }
274  if (array_type_ && (values.size() > records.size())) {
275  for (size_t i = records.size(); i < values.size(); ++i) {
276  writeToBuffer(u, util::str::trim(values[i]),
277  records.back(), buf);
278  }
279  }
280  }
281  return (optionFactory(u, type, buf.begin(), buf.end()));
282 }
283 
284 void
286 
287  using namespace boost::algorithm;
288 
289  std::ostringstream err_str;
290 
291  // Allowed characters in the option name are: lower or
292  // upper case letters, digits, underscores and hyphens.
293  // Empty option spaces are not allowed.
294  if (!all(name_, boost::is_from_range('a', 'z') ||
295  boost::is_from_range('A', 'Z') ||
296  boost::is_digit() ||
297  boost::is_any_of(std::string("-_"))) ||
298  name_.empty() ||
299  // Hyphens and underscores are not allowed at the beginning
300  // and at the end of the option name.
301  all(find_head(name_, 1), boost::is_any_of(std::string("-_"))) ||
302  all(find_tail(name_, 1), boost::is_any_of(std::string("-_")))) {
303  err_str << "invalid option name '" << name_ << "'";
304 
305  } else if (!encapsulated_space_.empty() &&
306  !OptionSpace::validateName(encapsulated_space_)) {
307  err_str << "invalid encapsulated option space name: '"
308  << encapsulated_space_ << "'";
309 
310  } else if (type_ >= OPT_UNKNOWN_TYPE) {
311  // Option definition must be of a known type.
312  err_str << "option type " << type_ << " not supported.";
313 
314  } else if (type_ == OPT_RECORD_TYPE) {
315  // At least two data fields should be added to the record. Otherwise
316  // non-record option definition could be used.
317  if (getRecordFields().size() < 2) {
318  err_str << "invalid number of data fields: "
319  << getRecordFields().size()
320  << " specified for the option of type 'record'. Expected at"
321  << " least 2 fields.";
322 
323  } else {
324  // If the number of fields is valid we have to check if their order
325  // is valid too. We check that string or binary data fields are not
326  // laid before other fields. But we allow that they are laid at the
327  // end of an option.
328  const RecordFieldsCollection& fields = getRecordFields();
329  for (RecordFieldsConstIter it = fields.begin();
330  it != fields.end(); ++it) {
331  if (*it == OPT_STRING_TYPE &&
332  it < fields.end() - 1) {
333  err_str << "string data field can't be laid before data"
334  << " fields of other types.";
335  break;
336  }
337  if (*it == OPT_BINARY_TYPE &&
338  it < fields.end() - 1) {
339  err_str << "binary data field can't be laid before data"
340  << " fields of other types.";
341  break;
342  }
344  if (*it == OPT_EMPTY_TYPE) {
345  err_str << "empty data type can't be stored as a field in"
346  << " an option record.";
347  break;
348  }
349  }
350  // If the array flag is set the last field is an array.
351  if (err_str.str().empty() && array_type_) {
352  const OptionDataType& last_type = fields.back();
353  if (last_type == OPT_STRING_TYPE) {
354  err_str << "array of strings is not"
355  << "a valid option definition.";
356  } else if (last_type == OPT_BINARY_TYPE) {
357  err_str << "array of binary values is not"
358  << " a valid option definition.";
359  }
360  // Empty type was already checked.
361  }
362  }
363 
364  } else if (array_type_) {
365  if (type_ == OPT_STRING_TYPE) {
366  // Array of strings is not allowed because there is no way
367  // to determine the size of a particular string and thus there
368  // it no way to tell when other data fields begin.
369  err_str << "array of strings is not a valid option definition.";
370  } else if (type_ == OPT_BINARY_TYPE) {
371  err_str << "array of binary values is not"
372  << " a valid option definition.";
373 
374  } else if (type_ == OPT_EMPTY_TYPE) {
375  err_str << "array of empty value is not"
376  << " a valid option definition.";
377 
378  }
379  }
380 
381  // Non-empty error string means that we have hit the error. We throw
382  // exception and include error string.
383  if (!err_str.str().empty()) {
384  isc_throw(MalformedOptionDefinition, err_str.str());
385  }
386 }
387 
388 bool
389 OptionDefinition::haveIAx6Format(OptionDataType first_type) const {
390  return (haveType(OPT_RECORD_TYPE) &&
391  !getArrayType() &&
392  record_fields_.size() == 3 &&
393  record_fields_[0] == first_type &&
394  record_fields_[1] == OPT_UINT32_TYPE &&
395  record_fields_[2] == OPT_UINT32_TYPE);
396 }
397 
398 bool
400  // Expect that IA_NA option format is defined as record.
401  // Although it consists of 3 elements of the same (uint32)
402  // type it can't be defined as array of uint32 elements because
403  // arrays do not impose limitations on number of elements in
404  // the array while this limitation is needed for IA_NA - need
405  // exactly 3 elements.
406  return (haveIAx6Format(OPT_UINT32_TYPE));
407 }
408 
409 bool
411  return (haveIAx6Format(OPT_IPV6_ADDRESS_TYPE));
412 }
413 
414 bool
416  return (haveType(OPT_RECORD_TYPE) &&
417  !getArrayType() &&
418  record_fields_.size() == 4 &&
419  record_fields_[0] == OPT_UINT32_TYPE &&
420  record_fields_[1] == OPT_UINT32_TYPE &&
421  record_fields_[2] == OPT_UINT8_TYPE &&
422  record_fields_[3] == OPT_IPV6_ADDRESS_TYPE);
423 }
424 
425 bool
427  return (haveType(OPT_RECORD_TYPE) &&
428  !getArrayType() &&
429  record_fields_.size() == 4 &&
430  record_fields_[0] == OPT_UINT8_TYPE &&
431  record_fields_[1] == OPT_UINT8_TYPE &&
432  record_fields_[2] == OPT_UINT8_TYPE &&
433  record_fields_[3] == OPT_FQDN_TYPE);
434 }
435 
436 bool
438  return (haveType(OPT_RECORD_TYPE) &&
439  !getArrayType() &&
440  (record_fields_.size() == 2) &&
441  (record_fields_[0] == OPT_UINT8_TYPE) &&
442  (record_fields_[1] == OPT_FQDN_TYPE));
443 }
444 
445 bool
447  return (true);
448 }
449 
450 bool
452  return (getType() == OPT_UINT32_TYPE && !getEncapsulatedSpace().empty());
453 }
454 
455 bool
457  return (haveType(OPT_RECORD_TYPE) &&
458  (record_fields_.size() == 2) &&
459  (record_fields_[0] == OPT_UINT32_TYPE) &&
460  (record_fields_[1] == OPT_BINARY_TYPE));
461 }
462 
463 bool
465  return (haveType(OPT_RECORD_TYPE) &&
466  (record_fields_.size() == 2) &&
467  (record_fields_[0] == OPT_UINT32_TYPE) &&
468  (record_fields_[1] == OPT_BINARY_TYPE));
469 }
470 
471 bool
473  return (haveType(OPT_RECORD_TYPE) &&
474  (record_fields_.size() == 2) &&
475  (record_fields_[0] == OPT_UINT16_TYPE) &&
476  (record_fields_[1] == OPT_STRING_TYPE));
477 }
478 
479 bool
481  return (haveType(OPT_RECORD_TYPE) &&
482  (record_fields_.size() == 2) &&
483  (record_fields_[0] == OPT_BOOLEAN_TYPE) &&
484  (record_fields_[1] == OPT_STRING_TYPE));
485 }
486 
487 bool
489  return (haveType(OPT_TUPLE_TYPE) && getArrayType());
490 }
491 
492 bool
494  return (haveType(OPT_FQDN_TYPE) && getArrayType());
495 }
496 
497 bool
498 OptionDefinition::convertToBool(const std::string& value_str) const {
499  // Case-insensitive check that the input is one of: "true" or "false".
500  if (boost::iequals(value_str, "true")) {
501  return (true);
502 
503  } else if (boost::iequals(value_str, "false")) {
504  return (false);
505 
506  }
507 
508  // The input string is neither "true" nor "false", so let's check
509  // if it is not an integer wrapped in a string.
510  int result;
511  try {
512  result = boost::lexical_cast<int>(value_str);
513 
514  } catch (const boost::bad_lexical_cast&) {
515  isc_throw(BadDataTypeCast, "unable to covert the value '"
516  << value_str << "' to boolean data type");
517  }
518  // The boolean value is encoded in DHCP option as 0 or 1. Therefore,
519  // we only allow a user to specify those values for options which
520  // have boolean fields.
521  if (result != 1 && result != 0) {
522  isc_throw(BadDataTypeCast, "unable to convert '" << value_str
523  << "' to boolean data type");
524  }
525  return (static_cast<bool>(result));
526 }
527 
528 template<typename T>
529 T
530 OptionDefinition::lexicalCastWithRangeCheck(const std::string& value_str)
531  const {
532  // The lexical cast should be attempted when converting to an integer
533  // value only.
535  isc_throw(BadDataTypeCast,
536  "must not convert '" << value_str
537  << "' to non-integer data type");
538  }
539 
540  // We use the 64-bit value here because it has wider range than
541  // any other type we use here and it allows to detect out of
542  // bounds conditions e.g. negative value specified for uintX_t
543  // data type. Obviously if the value exceeds the limits of int64
544  // this function will not handle that properly.
545  int64_t result = 0;
546  try {
547  result = boost::lexical_cast<int64_t>(value_str);
548 
549  } catch (const boost::bad_lexical_cast&) {
550  // boost::lexical_cast does not handle hexadecimal
551  // but stringstream does so do it the hard way.
552  std::stringstream ss;
553  ss << std::hex << value_str;
554  ss >> result;
555  if (ss.fail() || !ss.eof()) {
556  isc_throw(BadDataTypeCast, "unable to convert the value '"
557  << value_str << "' to integer data type");
558  }
559  }
560  // Perform range checks.
562  if (result > numeric_limits<T>::max() ||
563  result < numeric_limits<T>::min()) {
564  isc_throw(BadDataTypeCast, "unable to convert '"
565  << value_str << "' to numeric type. This value is "
566  " expected to be in the range of "
567  << numeric_limits<T>::min()
568  << ".." << numeric_limits<T>::max());
569  }
570  }
571  return (static_cast<T>(result));
572 }
573 
574 void
575 OptionDefinition::writeToBuffer(Option::Universe u,
576  const std::string& value,
577  const OptionDataType type,
578  OptionBuffer& buf) const {
579  // We are going to write value given by value argument to the buffer.
580  // The actual type of the value is given by second argument. Check
581  // this argument to determine how to write this value to the buffer.
582  switch (type) {
583  case OPT_BINARY_TYPE:
585  return;
586  case OPT_BOOLEAN_TYPE:
587  // We encode the true value as 1 and false as 0 on 8 bits.
588  // That way we actually waste 7 bits but it seems to be the
589  // simpler way to encode boolean.
590  // @todo Consider if any other encode methods can be used.
591  OptionDataTypeUtil::writeBool(convertToBool(value), buf);
592  return;
593  case OPT_INT8_TYPE:
594  OptionDataTypeUtil::writeInt<uint8_t>
595  (lexicalCastWithRangeCheck<int8_t>(value),
596  buf);
597  return;
598  case OPT_INT16_TYPE:
599  OptionDataTypeUtil::writeInt<uint16_t>
600  (lexicalCastWithRangeCheck<int16_t>(value),
601  buf);
602  return;
603  case OPT_INT32_TYPE:
604  OptionDataTypeUtil::writeInt<uint32_t>
605  (lexicalCastWithRangeCheck<int32_t>(value),
606  buf);
607  return;
608  case OPT_UINT8_TYPE:
609  OptionDataTypeUtil::writeInt<uint8_t>
610  (lexicalCastWithRangeCheck<uint8_t>(value),
611  buf);
612  return;
613  case OPT_UINT16_TYPE:
614  OptionDataTypeUtil::writeInt<uint16_t>
615  (lexicalCastWithRangeCheck<uint16_t>(value),
616  buf);
617  return;
618  case OPT_UINT32_TYPE:
619  OptionDataTypeUtil::writeInt<uint32_t>
620  (lexicalCastWithRangeCheck<uint32_t>(value),
621  buf);
622  return;
625  {
626  asiolink::IOAddress address(value);
627  if (!address.isV4() && !address.isV6()) {
628  isc_throw(BadDataTypeCast, "provided address "
629  << address
630  << " is not a valid IPv4 or IPv6 address.");
631  }
632  OptionDataTypeUtil::writeAddress(address, buf);
633  return;
634  }
636  {
637  std::string txt = value;
638 
639  // first let's remove any whitespaces
640  boost::erase_all(txt, " "); // space
641  boost::erase_all(txt, "\t"); // tabulation
642 
643  // Is this prefix/len notation?
644  size_t pos = txt.find("/");
645 
646  if (pos == string::npos) {
647  isc_throw(BadDataTypeCast, "provided address/prefix "
648  << value
649  << " is not valid.");
650  }
651 
652  std::string txt_address = txt.substr(0, pos);
653  isc::asiolink::IOAddress address = isc::asiolink::IOAddress(txt_address);
654  if (!address.isV6()) {
655  isc_throw(BadDataTypeCast, "provided address "
656  << txt_address
657  << " is not a valid IPv4 or IPv6 address.");
658  }
659 
660  std::string txt_prefix = txt.substr(pos + 1);
661  uint8_t len = 0;
662  try {
663  // start with the first character after /
664  len = lexicalCastWithRangeCheck<uint8_t>(txt_prefix);
665  } catch (...) {
666  isc_throw(BadDataTypeCast, "provided prefix "
667  << txt_prefix
668  << " is not valid.");
669  }
670 
671  // Write a prefix.
672  OptionDataTypeUtil::writePrefix(PrefixLen(len), address, buf);
673 
674  return;
675  }
676  case OPT_PSID_TYPE:
677  {
678  std::string txt = value;
679 
680  // first let's remove any whitespaces
681  boost::erase_all(txt, " "); // space
682  boost::erase_all(txt, "\t"); // tabulation
683 
684  // Is this prefix/len notation?
685  size_t pos = txt.find("/");
686 
687  if (pos == string::npos) {
688  isc_throw(BadDataTypeCast, "provided PSID value "
689  << value << " is not valid");
690  }
691 
692  const std::string txt_psid = txt.substr(0, pos);
693  const std::string txt_psid_len = txt.substr(pos + 1);
694 
695  uint16_t psid = 0;
696  uint8_t psid_len = 0;
697 
698  try {
699  psid = lexicalCastWithRangeCheck<uint16_t>(txt_psid);
700  } catch (...) {
701  isc_throw(BadDataTypeCast, "provided PSID "
702  << txt_psid << " is not valid");
703  }
704 
705  try {
706  psid_len = lexicalCastWithRangeCheck<uint8_t>(txt_psid_len);
707  } catch (...) {
708  isc_throw(BadDataTypeCast, "provided PSID length "
709  << txt_psid_len << " is not valid");
710  }
711 
712  OptionDataTypeUtil::writePsid(PSIDLen(psid_len), PSID(psid), buf);
713  return;
714  }
715  case OPT_STRING_TYPE:
717  return;
718  case OPT_FQDN_TYPE:
719  OptionDataTypeUtil::writeFqdn(value, buf);
720  return;
721  case OPT_TUPLE_TYPE:
722  {
725  OptionDataTypeUtil::writeTuple(value, lft, buf);
726  return;
727  }
728  default:
729  // We hit this point because invalid option data type has been specified
730  // This may be the case because 'empty' or 'record' data type has been
731  // specified. We don't throw exception here because it will be thrown
732  // at the exit point from this function.
733  ;
734  }
735  isc_throw(isc::BadValue, "attempt to write invalid option data field type"
736  " into the option buffer: " << type);
737 
738 }
739 
740 OptionPtr
742  OptionBufferConstIter begin,
743  OptionBufferConstIter end) {
744  boost::shared_ptr<Option4AddrLst> option(new Option4AddrLst(type, begin,
745  end));
746  return (option);
747 }
748 
749 OptionPtr
751  OptionBufferConstIter begin,
752  OptionBufferConstIter end) {
753  boost::shared_ptr<Option6AddrLst> option(new Option6AddrLst(type, begin,
754  end));
755  return (option);
756 }
757 
758 
759 OptionPtr
761  OptionPtr option(new Option(u, type));
762  return (option);
763 }
764 
765 OptionPtr
767  OptionBufferConstIter begin,
768  OptionBufferConstIter end) {
769  OptionPtr option(new Option(u, type, begin, end));
770  return (option);
771 }
772 
773 OptionPtr
775  OptionBufferConstIter begin,
776  OptionBufferConstIter end) {
777  if (std::distance(begin, end) < Option6IA::OPTION6_IA_LEN) {
778  isc_throw(isc::OutOfRange, "input option buffer has invalid size,"
779  << " expected at least " << Option6IA::OPTION6_IA_LEN
780  << " bytes");
781  }
782  boost::shared_ptr<Option6IA> option(new Option6IA(type, begin, end));
783  return (option);
784 }
785 
786 OptionPtr
788  OptionBufferConstIter begin,
789  OptionBufferConstIter end) {
790  if (std::distance(begin, end) < Option6IAAddr::OPTION6_IAADDR_LEN) {
792  "input option buffer has invalid size, expected at least "
793  << Option6IAAddr::OPTION6_IAADDR_LEN << " bytes");
794  }
795  boost::shared_ptr<Option6IAAddr> option(new Option6IAAddr(type, begin,
796  end));
797  return (option);
798 }
799 
800 OptionPtr
802  OptionBufferConstIter begin,
803  OptionBufferConstIter end) {
804  if (std::distance(begin, end) < Option6IAPrefix::OPTION6_IAPREFIX_LEN) {
806  "input option buffer has invalid size, expected at least "
808  }
809  boost::shared_ptr<Option6IAPrefix> option(new Option6IAPrefix(type, begin,
810  end));
811  return (option);
812 }
813 
814 OptionPtr
816  uint16_t type,
817  OptionBufferConstIter begin,
818  OptionBufferConstIter end) {
819  boost::shared_ptr<OptionOpaqueDataTuples>
820  option(new OptionOpaqueDataTuples(u, type, begin, end));
821 
822  return (option);
823 }
824 
825 OptionPtr
826 OptionDefinition::factoryFqdnList(Option::Universe u,
827  OptionBufferConstIter begin,
828  OptionBufferConstIter end) const {
829 
830  const std::vector<uint8_t> data(begin, end);
831  if (data.empty()) {
832  isc_throw(InvalidOptionValue, "FQDN list option has invalid length of 0");
833  }
834  InputBuffer in_buf(static_cast<const void*>(&data[0]), data.size());
835  std::vector<uint8_t> out_buf;
836  out_buf.reserve(data.size());
837  while (in_buf.getPosition() < in_buf.getLength()) {
838  // Reuse readFqdn and writeFqdn code but on the whole buffer
839  // so the DNS name code handles compression for us.
840  try {
841  isc::dns::Name name(in_buf);
842  isc::dns::LabelSequence labels(name);
843  if (labels.getDataLength() > 0) {
844  size_t read_len = 0;
845  const uint8_t* label = labels.getData(&read_len);
846  out_buf.insert(out_buf.end(), label, label + read_len);
847  }
848  } catch (const isc::Exception& ex) {
849  isc_throw(InvalidOptionValue, ex.what());
850  }
851  }
852  return OptionPtr(new OptionCustom(*this, u,
853  out_buf.begin(), out_buf.end()));
854 }
855 
856 OptionPtr
857 OptionDefinition::factorySpecialFormatOption(Option::Universe u,
858  OptionBufferConstIter begin,
859  OptionBufferConstIter end) const {
860  if (u == Option::V6) {
861  if ((getCode() == D6O_IA_NA || getCode() == D6O_IA_PD) &&
862  haveIA6Format()) {
863  // Return Option6IA instance for IA_PD and IA_NA option
864  // types only. We don't want to return Option6IA for other
865  // options that comprise 3 UINT32 data fields because
866  // Option6IA accessors' and modifiers' names are derived
867  // from the IA_NA and IA_PD options' field names: IAID,
868  // T1, T2. Using functions such as getIAID, getT1 etc. for
869  // options other than IA_NA and IA_PD would be bad practice
870  // and cause confusion.
871  return (factoryIA6(getCode(), begin, end));
872 
873  } else if (getCode() == D6O_IAADDR && haveIAAddr6Format()) {
874  // Return Option6IAAddr option instance for the IAADDR
875  // option only for the same reasons as described in
876  // for IA_NA and IA_PD above.
877  return (factoryIAAddr6(getCode(), begin, end));
878  } else if (getCode() == D6O_IAPREFIX && haveIAPrefix6Format()) {
879  return (factoryIAPrefix6(getCode(), begin, end));
880  } else if (getCode() == D6O_CLIENT_FQDN && haveClientFqdnFormat()) {
881  // FQDN option requires special processing. Thus, there is
882  // a specialized class to handle it.
883  return (OptionPtr(new Option6ClientFqdn(begin, end)));
884  } else if (getCode() == D6O_VENDOR_OPTS && haveVendor6Format()) {
885  // Vendor-Specific Information (option code 17)
886  return (OptionPtr(new OptionVendor(Option::V6, begin, end)));
887  } else if (getCode() == D6O_VENDOR_CLASS && haveVendorClass6Format()) {
888  // Vendor Class (option code 16).
889  return (OptionPtr(new OptionVendorClass(Option::V6, begin, end)));
890  } else if (getCode() == D6O_STATUS_CODE && haveStatusCodeFormat()) {
891  // Status Code (option code 13)
892  return (OptionPtr(new Option6StatusCode(begin, end)));
894  // Bootfile params (option code 60)
895  return (factoryOpaqueDataTuples(Option::V6, getCode(), begin, end));
896  } else if ((getCode() == D6O_PD_EXCLUDE) && haveType(OPT_IPV6_PREFIX_TYPE)) {
897  // Prefix Exclude (option code 67)
898  return (OptionPtr(new Option6PDExclude(begin, end)));
899  }
900  } else {
902  return (OptionPtr(new Option4SlpServiceScope(begin, end)));
903  } else if ((getCode() == DHO_FQDN) && haveFqdn4Format()) {
904  return (OptionPtr(new Option4ClientFqdn(begin, end)));
905  } else if (haveCompressedFqdnListFormat()) {
906  return (factoryFqdnList(Option::V4, begin, end));
907  } else if ((getCode() == DHO_VIVCO_SUBOPTIONS) &&
909  // V-I Vendor Class (option code 124).
910  return (OptionPtr(new OptionVendorClass(Option::V4, begin, end)));
911  } else if (getCode() == DHO_VIVSO_SUBOPTIONS && haveVendor4Format()) {
912  // Vendor-Specific Information (option code 125).
913  return (OptionPtr(new OptionVendor(Option::V4, begin, end)));
914 
915  }
916  }
917  return (OptionPtr());
918 }
919 
920 } // end of isc::dhcp namespace
921 } // end of isc namespace
code_
uint16_t code_
Definition: rrparamregistry.cc:71
isc::dhcp::OPT_UNKNOWN_TYPE
@ OPT_UNKNOWN_TYPE
Definition: option_data_types.h:64
isc::dhcp::OptionBuffer
std::vector< uint8_t > OptionBuffer
buffer types used in DHCP code.
Definition: option.h:25
isc::dhcp::OPT_UINT32_TYPE
@ OPT_UINT32_TYPE
Definition: option_data_types.h:54
isc::dhcp::OptionDefinition::equals
bool equals(const OptionDefinition &other) const
Check if option definition is equal to other.
Definition: option_definition.cc:104
isc::dhcp::OpaqueDataTuple::LENGTH_1_BYTE
@ LENGTH_1_BYTE
Definition: opaque_data_tuple.h:56
isc::dhcp::Option6AddrLst
DHCPv6 Option class for handling list of IPv6 addresses.
Definition: option6_addrlst.h:22
isc::dhcp::OptionDefinition::validate
void validate() const
Check if the option definition is valid.
Definition: option_definition.cc:285
isc::dhcp::OptionDefinition::haveClientFqdnFormat
bool haveClientFqdnFormat() const
Check if specified format is OPTION_CLIENT_FQDN option format.
Definition: option_definition.cc:437
isc::dhcp::DHO_FQDN
@ DHO_FQDN
Definition: dhcp4.h:150
isc::dhcp::Option6IA::OPTION6_IA_LEN
static const size_t OPTION6_IA_LEN
Length of IA_NA and IA_PD content.
Definition: option6_ia.h:26
isc::dhcp::OptionCustom
Option with defined data fields represented as buffers that can be accessed using data field index.
Definition: option_custom.h:31
isc::dhcp::OptionString
Class which represents an option carrying a single string value.
Definition: option_string.h:27
isc::dhcp::DHO_SERVICE_SCOPE
@ DHO_SERVICE_SCOPE
Definition: dhcp4.h:148
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
option6_ia.h
D6O_IA_PD
@ D6O_IA_PD
Definition: dhcp6.h:45
isc::dhcp::OptionDefinition::factoryAddrList6
static OptionPtr factoryAddrList6(uint16_t type, OptionBufferConstIter begin, OptionBufferConstIter end)
Factory to create option with address list.
Definition: option_definition.cc:750
isc::dhcp::OptionDefinition::haveOpaqueDataTuplesFormat
bool haveOpaqueDataTuplesFormat() const
Check if the option has format of OpaqueDataTuples type options.
Definition: option_definition.cc:488
isc::dhcp::OptionOpaqueDataTuples
This class encapsulates a collection of data tuples and could be used by multiple options.
Definition: option_opaque_data_tuples.h:36
isc::dhcp::OptionDataTypeTraits::integer_type
static const bool integer_type
Definition: option_data_types.h:95
isc::util::str::trim
string trim(const string &instring)
Trim Leading and Trailing Spaces.
Definition: strutil.cc:53
isc::dhcp::OPT_BOOLEAN_TYPE
@ OPT_BOOLEAN_TYPE
Definition: option_data_types.h:48
isc::dhcp::OptionDefinition::addRecordField
void addRecordField(const std::string &data_type_name)
Adds data field to the record.
Definition: option_definition.cc:115
isc::dhcp::OPT_IPV4_ADDRESS_TYPE
@ OPT_IPV4_ADDRESS_TYPE
Definition: option_data_types.h:56
isc::dhcp::OptionDefinition::haveFqdn4Format
bool haveFqdn4Format() const
Check if option has format of the DHCPv4 Client FQDN Option.
Definition: option_definition.cc:426
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::OptionDefinition::factoryAddrList4
static OptionPtr factoryAddrList4(uint16_t type, OptionBufferConstIter begin, OptionBufferConstIter end)
Factory to create option with address list.
Definition: option_definition.cc:741
isc::dhcp::Option6IAAddr
Definition: option6_iaaddr.h:22
isc::dhcp::Option6IAPrefix
Class that represents IAPREFIX option in DHCPv6.
Definition: option6_iaprefix.h:51
option6_client_fqdn.h
isc::dhcp::OPT_STRING_TYPE
@ OPT_STRING_TYPE
Definition: option_data_types.h:60
name.h
isc::dhcp::OptionDataTypeUtil::writeBinary
static void writeBinary(const std::string &hex_str, std::vector< uint8_t > &buf)
Append hex-encoded binary values to a buffer.
Definition: option_data_types.cc:161
option_string.h
isc::dhcp::OptionDefinition::factoryIA6
static OptionPtr factoryIA6(uint16_t type, OptionBufferConstIter begin, OptionBufferConstIter end)
Factory for IA-type of option.
Definition: option_definition.cc:774
isc::dhcp::OptionDataTypeUtil
Utility class for option data types.
Definition: option_data_types.h:328
isc::dhcp::OptionDefinition::factoryOpaqueDataTuples
static OptionPtr factoryOpaqueDataTuples(Option::Universe u, uint16_t type, OptionBufferConstIter begin, OptionBufferConstIter end)
Factory to create option with tuple list.
Definition: option_definition.cc:815
option_opaque_data_tuples.h
D6O_VENDOR_OPTS
@ D6O_VENDOR_OPTS
Definition: dhcp6.h:37
option6_iaprefix.h
isc::dhcp::OpaqueDataTuple::LengthFieldType
LengthFieldType
Size of the length field in the tuple.
Definition: opaque_data_tuple.h:55
isc::dhcp::OPT_EMPTY_TYPE
@ OPT_EMPTY_TYPE
Definition: option_data_types.h:46
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
labelsequence.h
isc::dhcp::OptionDefinition
Base class representing a DHCP option definition.
Definition: option_definition.h:137
isc::dhcp::OptionDefinition::haveIA6Format
bool haveIA6Format() const
Check if specified format is IA_NA option format.
Definition: option_definition.cc:399
isc::Exception
This is a base class for exceptions thrown from the DNS library module.
Definition: exceptions/exceptions.h:23
isc::dhcp::MalformedOptionDefinition
Exception to be thrown when option definition is invalid.
Definition: option_definition.h:36
dhcp4.h
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::util
Definition: edns.h:19
isc::dhcp::Option6IA
Definition: option6_ia.h:22
isc
Defines the logger used by the top-level component of kea-dhcp-ddns.
Definition: agent_parser.cc:144
isc::Exception::what
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
Definition: exceptions/exceptions.cc:32
isc::dhcp::OptionDefinition::haveIAAddr6Format
bool haveIAAddr6Format() const
Check if specified format is IAADDR option format.
Definition: option_definition.cc:410
isc::dhcp::OptionDefinition::haveVendorClass4Format
bool haveVendorClass4Format() const
Check if the option has format of DHCPv4 V-I Vendor Class option.
Definition: option_definition.cc:456
strutil.h
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::InvalidOperation
A generic exception that is thrown if a function is called in a prohibited way.
Definition: exceptions/exceptions.h:143
isc::dhcp::InvalidOptionValue
Exception to be thrown when invalid option value has been specified for a particular option definitio...
Definition: option_definition.h:29
isc::BadValue
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
Definition: exceptions/exceptions.h:132
isc::dhcp::OptionDefinition::factoryGeneric
static OptionPtr factoryGeneric(Option::Universe u, uint16_t type, OptionBufferConstIter begin, OptionBufferConstIter end)
Factory to create generic option.
Definition: option_definition.cc:766
isc::dhcp::OPT_INT16_TYPE
@ OPT_INT16_TYPE
Definition: option_data_types.h:50
isc::dhcp::OptionDataTypeUtil::getDataType
static OptionDataType getDataType(const std::string &data_type)
Return option data type from its name.
Definition: option_data_types.cc:65
isc::dns::Name
The Name class encapsulates DNS names.
Definition: name.h:223
isc::dhcp::OPT_UINT8_TYPE
@ OPT_UINT8_TYPE
Definition: option_data_types.h:52
isc::dhcp::Option6IAAddr::OPTION6_IAADDR_LEN
static const size_t OPTION6_IAADDR_LEN
length of the fixed part of the IAADDR option
Definition: option6_iaaddr.h:26
isc::dhcp::OptionDefinition::haveStatusCodeFormat
bool haveStatusCodeFormat() const
Check if the option has format of DHCPv6 Status Code option.
Definition: option_definition.cc:472
isc::dhcp::OptionDefinition::getArrayType
bool getArrayType() const
Return array type indicator.
Definition: option_definition.h:259
isc::dhcp::OptionDefinition::haveIAPrefix6Format
bool haveIAPrefix6Format() const
Check if specified format is IAPREFIX option format.
Definition: option_definition.cc:415
isc::dhcp::OPT_INT8_TYPE
@ OPT_INT8_TYPE
Definition: option_data_types.h:49
isc::dhcp::SkipRemainingOptionsError
Exception thrown during option unpacking This exception is thrown when an error has occurred,...
Definition: option.h:52
isc::dhcp::OptionDefinition::haveCompressedFqdnListFormat
bool haveCompressedFqdnListFormat() const
Check if the option has format of CompressedFqdnList options.
Definition: option_definition.cc:493
isc::dhcp::OptionDefinition::getCode
uint16_t getCode() const
Return option code.
Definition: option_definition.h:264
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
option_definition.h
isc::dhcp::OptionDefinition::OptionDefinition
OptionDefinition(const std::string &name, const uint16_t code, const std::string &type, const bool array_type=false)
Constructor.
Definition: option_definition.cc:43
isc::dhcp::OpaqueDataTuple::LENGTH_2_BYTES
@ LENGTH_2_BYTES
Definition: opaque_data_tuple.h:57
D6O_IA_NA
@ D6O_IA_NA
Definition: dhcp6.h:23
isc::dhcp::OPT_RECORD_TYPE
@ OPT_RECORD_TYPE
Definition: option_data_types.h:63
isc::dhcp::OPT_BINARY_TYPE
@ OPT_BINARY_TYPE
Definition: option_data_types.h:47
dhcp6.h
isc::dhcp::OPT_PSID_TYPE
@ OPT_PSID_TYPE
Definition: option_data_types.h:59
isc::dhcp::OptionDefinition::haveServiceScopeFormat
bool haveServiceScopeFormat() const
Check if option has format of the SLP Service Scope Option.
Definition: option_definition.cc:480
option_vendor.h
isc::util::InputBuffer
The InputBuffer class is a buffer abstraction for manipulating read-only data.
Definition: buffer.h:81
isc::dhcp::OptionDefinition::factoryIAAddr6
static OptionPtr factoryIAAddr6(uint16_t type, OptionBufferConstIter begin, OptionBufferConstIter end)
Factory for IAADDR-type of option.
Definition: option_definition.cc:787
D6O_VENDOR_CLASS
@ D6O_VENDOR_CLASS
Definition: dhcp6.h:36
option_vendor_class.h
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
D6O_IAADDR
@ D6O_IAADDR
Definition: dhcp6.h:25
isc::dhcp::OptionDefinition::haveVendor6Format
bool haveVendor6Format() const
Check if option has a format of the Vendor-Specific Information Option.
Definition: option_definition.cc:451
isc::dhcp::OptionDataType
OptionDataType
Data types of DHCP option fields.
Definition: option_data_types.h:45
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::Option::V6
@ V6
Definition: option.h:67
isc::dhcp::OptionPtr
boost::shared_ptr< Option > OptionPtr
Definition: option.h:37
name_
const Name & name_
Definition: dns/message.cc:693
isc::dhcp::OptionDefinition::getType
OptionDataType getType() const
Return option data type.
Definition: option_definition.h:288
isc::dhcp::DHO_VIVSO_SUBOPTIONS
@ DHO_VIVSO_SUBOPTIONS
Definition: dhcp4.h:185
isc::dhcp::OptionDefinition::haveVendor4Format
bool haveVendor4Format() const
Check if the option has format of Vendor-Identifying Vendor Specific Options.
Definition: option_definition.cc:446
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::OptionDefinition::factoryEmpty
static OptionPtr factoryEmpty(Option::Universe u, uint16_t type)
Empty option factory.
Definition: option_definition.cc:760
isc::dhcp::OPT_FQDN_TYPE
@ OPT_FQDN_TYPE
Definition: option_data_types.h:62
D6O_STATUS_CODE
@ D6O_STATUS_CODE
Definition: dhcp6.h:33
option6_iaaddr.h
isc::dhcp::OptionDefinition::optionFactory
OptionPtr optionFactory(Option::Universe u, uint16_t type, OptionBufferConstIter begin, OptionBufferConstIter end) const
Option factory.
Definition: option_definition.cc:136
isc::dhcp::OptionSpace::validateName
static bool validateName(const std::string &name)
Checks that the provided option space name is valid.
Definition: option_space.cc:26
isc::dhcp::OPT_TUPLE_TYPE
@ OPT_TUPLE_TYPE
Definition: option_data_types.h:61
isc::dhcp::Option
Definition: option.h:58
isc::dhcp::OPT_UINT16_TYPE
@ OPT_UINT16_TYPE
Definition: option_data_types.h:53
D6O_IAPREFIX
@ D6O_IAPREFIX
Definition: dhcp6.h:46
option6_pdexclude.h
isc::dhcp::OptionDefinition::RecordFieldsConstIter
std::vector< OptionDataType >::const_iterator RecordFieldsConstIter
Const iterator for record data fields.
Definition: option_definition.h:143
isc::dhcp::OPT_IPV6_ADDRESS_TYPE
@ OPT_IPV6_ADDRESS_TYPE
Definition: option_data_types.h:57
option_custom.h
option_int.h
isc::dhcp::OptionBufferConstIter
OptionBuffer::const_iterator OptionBufferConstIter
const_iterator for walking over OptionBuffer
Definition: option.h:31
option4_addrlst.h
option_int_array.h
D6O_CLIENT_FQDN
@ D6O_CLIENT_FQDN
Definition: dhcp6.h:59
isc::dhcp::OptionDefinition::haveVendorClass6Format
bool haveVendorClass6Format() const
Check if the option has format of DHCPv6 Vendor Class option.
Definition: option_definition.cc:464
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::DHO_VIVCO_SUBOPTIONS
@ DHO_VIVCO_SUBOPTIONS
Definition: dhcp4.h:184
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
option4_client_fqdn.h
isc::dhcp::Option6IAPrefix::OPTION6_IAPREFIX_LEN
static const size_t OPTION6_IAPREFIX_LEN
length of the fixed part of the IAPREFIX option
Definition: option6_iaprefix.h:55
option6_status_code.h
isc::dhcp::OptionDefinition::getEncapsulatedSpace
std::string getEncapsulatedSpace() const
Return name of the encapsulated option space.
Definition: option_definition.h:269
isc::dhcp::OptionDefinition::factoryIAPrefix6
static OptionPtr factoryIAPrefix6(uint16_t type, OptionBufferConstIter begin, OptionBufferConstIter end)
Factory for IAPREFIX-type of option.
Definition: option_definition.cc:801
D6O_PD_EXCLUDE
@ D6O_PD_EXCLUDE
Definition: dhcp6.h:87
isc::dhcp::OPT_ANY_ADDRESS_TYPE
@ OPT_ANY_ADDRESS_TYPE
Definition: option_data_types.h:55
option6_addrlst.h
D6O_BOOTFILE_PARAM
@ D6O_BOOTFILE_PARAM
Definition: dhcp6.h:80
isc::dns::LabelSequence
Light-weight Accessor to Name data.
Definition: labelsequence.h:35
isc::dhcp::Option4AddrLst
DHCPv4 Option class for handling list of IPv4 addresses.
Definition: option4_addrlst.h:34