option_definition.cc 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717
  1. // Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #include <config.h>
  15. #include <dhcp/dhcp4.h>
  16. #include <dhcp/dhcp6.h>
  17. #include <dhcp/option4_addrlst.h>
  18. #include <dhcp/option4_client_fqdn.h>
  19. #include <dhcp/option6_addrlst.h>
  20. #include <dhcp/option6_ia.h>
  21. #include <dhcp/option6_iaaddr.h>
  22. #include <dhcp/option6_iaprefix.h>
  23. #include <dhcp/option6_client_fqdn.h>
  24. #include <dhcp/option6_status_code.h>
  25. #include <dhcp/option_custom.h>
  26. #include <dhcp/option_definition.h>
  27. #include <dhcp/option_int.h>
  28. #include <dhcp/option_int_array.h>
  29. #include <dhcp/option_space.h>
  30. #include <dhcp/option_string.h>
  31. #include <dhcp/option_vendor.h>
  32. #include <dhcp/option_vendor_class.h>
  33. #include <util/encode/hex.h>
  34. #include <util/strutil.h>
  35. #include <boost/algorithm/string/classification.hpp>
  36. #include <boost/algorithm/string/predicate.hpp>
  37. using namespace std;
  38. using namespace isc::util;
  39. namespace isc {
  40. namespace dhcp {
  41. OptionDefinition::OptionDefinition(const std::string& name,
  42. const uint16_t code,
  43. const std::string& type,
  44. const bool array_type /* = false */)
  45. : name_(name),
  46. code_(code),
  47. type_(OPT_UNKNOWN_TYPE),
  48. array_type_(array_type),
  49. encapsulated_space_("") {
  50. // Data type is held as enum value by this class.
  51. // Use the provided option type string to get the
  52. // corresponding enum value.
  53. type_ = OptionDataTypeUtil::getDataType(type);
  54. }
  55. OptionDefinition::OptionDefinition(const std::string& name,
  56. const uint16_t code,
  57. const OptionDataType type,
  58. const bool array_type /* = false */)
  59. : name_(name),
  60. code_(code),
  61. type_(type),
  62. array_type_(array_type),
  63. encapsulated_space_("") {
  64. }
  65. OptionDefinition::OptionDefinition(const std::string& name,
  66. const uint16_t code,
  67. const std::string& type,
  68. const char* encapsulated_space)
  69. : name_(name),
  70. code_(code),
  71. // Data type is held as enum value by this class.
  72. // Use the provided option type string to get the
  73. // corresponding enum value.
  74. type_(OptionDataTypeUtil::getDataType(type)),
  75. array_type_(false),
  76. encapsulated_space_(encapsulated_space) {
  77. }
  78. OptionDefinition::OptionDefinition(const std::string& name,
  79. const uint16_t code,
  80. const OptionDataType type,
  81. const char* encapsulated_space)
  82. : name_(name),
  83. code_(code),
  84. type_(type),
  85. array_type_(false),
  86. encapsulated_space_(encapsulated_space) {
  87. }
  88. bool
  89. OptionDefinition::equals(const OptionDefinition& other) const {
  90. return (name_ == other.name_ &&
  91. code_ == other.code_ &&
  92. type_ == other.type_ &&
  93. array_type_ == other.array_type_ &&
  94. encapsulated_space_ == other.encapsulated_space_ &&
  95. record_fields_ == other.record_fields_);
  96. }
  97. void
  98. OptionDefinition::addRecordField(const std::string& data_type_name) {
  99. OptionDataType data_type = OptionDataTypeUtil::getDataType(data_type_name);
  100. addRecordField(data_type);
  101. }
  102. void
  103. OptionDefinition::addRecordField(const OptionDataType data_type) {
  104. if (type_ != OPT_RECORD_TYPE) {
  105. isc_throw(isc::InvalidOperation, "'record' option type must be used"
  106. " to add data fields to the record");
  107. }
  108. if (data_type >= OPT_RECORD_TYPE ||
  109. data_type == OPT_ANY_ADDRESS_TYPE ||
  110. data_type == OPT_EMPTY_TYPE) {
  111. isc_throw(isc::BadValue,
  112. "attempted to add invalid data type to the record.");
  113. }
  114. record_fields_.push_back(data_type);
  115. }
  116. OptionPtr
  117. OptionDefinition::optionFactory(Option::Universe u, uint16_t type,
  118. OptionBufferConstIter begin,
  119. OptionBufferConstIter end,
  120. UnpackOptionsCallback callback) const {
  121. try {
  122. // Some of the options are represented by the specialized classes derived
  123. // from Option class (e.g. IA_NA, IAADDR). Although, they can be also
  124. // represented by the generic classes, we want the object of the specialized
  125. // type to be returned. Therefore, we first check that if we are dealing
  126. // with such an option. If the instance is returned we just exit at this
  127. // point. If not, we will search for a generic option type to return.
  128. OptionPtr option = factorySpecialFormatOption(u, begin, end, callback);
  129. if (option) {
  130. return (option);
  131. }
  132. switch(type_) {
  133. case OPT_EMPTY_TYPE:
  134. if (getEncapsulatedSpace().empty()) {
  135. return (factoryEmpty(u, type));
  136. } else {
  137. return (OptionPtr(new OptionCustom(*this, u, begin, end)));
  138. }
  139. case OPT_BINARY_TYPE:
  140. return (factoryGeneric(u, type, begin, end));
  141. case OPT_UINT8_TYPE:
  142. return (array_type_ ?
  143. factoryIntegerArray<uint8_t>(u, type, begin, end) :
  144. factoryInteger<uint8_t>(u, type, getEncapsulatedSpace(),
  145. begin, end, callback));
  146. case OPT_INT8_TYPE:
  147. return (array_type_ ?
  148. factoryIntegerArray<int8_t>(u, type, begin, end) :
  149. factoryInteger<int8_t>(u, type, getEncapsulatedSpace(),
  150. begin, end, callback));
  151. case OPT_UINT16_TYPE:
  152. return (array_type_ ?
  153. factoryIntegerArray<uint16_t>(u, type, begin, end) :
  154. factoryInteger<uint16_t>(u, type, getEncapsulatedSpace(),
  155. begin, end, callback));
  156. case OPT_INT16_TYPE:
  157. return (array_type_ ?
  158. factoryIntegerArray<uint16_t>(u, type, begin, end) :
  159. factoryInteger<int16_t>(u, type, getEncapsulatedSpace(),
  160. begin, end, callback));
  161. case OPT_UINT32_TYPE:
  162. return (array_type_ ?
  163. factoryIntegerArray<uint32_t>(u, type, begin, end) :
  164. factoryInteger<uint32_t>(u, type, getEncapsulatedSpace(),
  165. begin, end, callback));
  166. case OPT_INT32_TYPE:
  167. return (array_type_ ?
  168. factoryIntegerArray<uint32_t>(u, type, begin, end) :
  169. factoryInteger<int32_t>(u, type, getEncapsulatedSpace(),
  170. begin, end, callback));
  171. case OPT_IPV4_ADDRESS_TYPE:
  172. // If definition specifies that an option is an array
  173. // of IPv4 addresses we return an instance of specialized
  174. // class (OptionAddrLst4). For non-array types there is no
  175. // specialized class yet implemented so we drop through
  176. // to return an instance of OptionCustom.
  177. if (array_type_) {
  178. return (factoryAddrList4(type, begin, end));
  179. }
  180. break;
  181. case OPT_IPV6_ADDRESS_TYPE:
  182. // Handle array type only here (see comments for
  183. // OPT_IPV4_ADDRESS_TYPE case).
  184. if (array_type_) {
  185. return (factoryAddrList6(type, begin, end));
  186. }
  187. break;
  188. case OPT_STRING_TYPE:
  189. return (OptionPtr(new OptionString(u, type, begin, end)));
  190. default:
  191. // Do nothing. We will return generic option a few lines down.
  192. ;
  193. }
  194. return (OptionPtr(new OptionCustom(*this, u, begin, end)));
  195. } catch (const Exception& ex) {
  196. isc_throw(InvalidOptionValue, ex.what());
  197. }
  198. }
  199. OptionPtr
  200. OptionDefinition::optionFactory(Option::Universe u, uint16_t type,
  201. const OptionBuffer& buf,
  202. UnpackOptionsCallback callback) const {
  203. return (optionFactory(u, type, buf.begin(), buf.end(), callback));
  204. }
  205. OptionPtr
  206. OptionDefinition::optionFactory(Option::Universe u, uint16_t type,
  207. const std::vector<std::string>& values) const {
  208. OptionBuffer buf;
  209. if (!array_type_ && type_ != OPT_RECORD_TYPE) {
  210. if (values.empty()) {
  211. isc_throw(InvalidOptionValue, "no option value specified");
  212. }
  213. writeToBuffer(util::str::trim(values[0]), type_, buf);
  214. } else if (array_type_ && type_ != OPT_RECORD_TYPE) {
  215. for (size_t i = 0; i < values.size(); ++i) {
  216. writeToBuffer(util::str::trim(values[i]), type_, buf);
  217. }
  218. } else if (type_ == OPT_RECORD_TYPE) {
  219. const RecordFieldsCollection& records = getRecordFields();
  220. if (records.size() > values.size()) {
  221. isc_throw(InvalidOptionValue, "number of data fields for the option"
  222. << " type '" << getCode() << "' is greater than number"
  223. << " of values provided.");
  224. }
  225. for (size_t i = 0; i < records.size(); ++i) {
  226. writeToBuffer(util::str::trim(values[i]),
  227. records[i], buf);
  228. }
  229. }
  230. return (optionFactory(u, type, buf.begin(), buf.end()));
  231. }
  232. void
  233. OptionDefinition::validate() const {
  234. using namespace boost::algorithm;
  235. std::ostringstream err_str;
  236. // Allowed characters in the option name are: lower or
  237. // upper case letters, digits, underscores and hyphens.
  238. // Empty option spaces are not allowed.
  239. if (!all(name_, boost::is_from_range('a', 'z') ||
  240. boost::is_from_range('A', 'Z') ||
  241. boost::is_digit() ||
  242. boost::is_any_of(std::string("-_"))) ||
  243. name_.empty() ||
  244. // Hyphens and underscores are not allowed at the beginning
  245. // and at the end of the option name.
  246. all(find_head(name_, 1), boost::is_any_of(std::string("-_"))) ||
  247. all(find_tail(name_, 1), boost::is_any_of(std::string("-_")))) {
  248. err_str << "invalid option name '" << name_ << "'";
  249. } else if (!encapsulated_space_.empty() &&
  250. !OptionSpace::validateName(encapsulated_space_)) {
  251. err_str << "invalid encapsulated option space name: '"
  252. << encapsulated_space_ << "'";
  253. } else if (type_ >= OPT_UNKNOWN_TYPE) {
  254. // Option definition must be of a known type.
  255. err_str << "option type " << type_ << " not supported.";
  256. } else if (array_type_) {
  257. if (type_ == OPT_STRING_TYPE) {
  258. // Array of strings is not allowed because there is no way
  259. // to determine the size of a particular string and thus there
  260. // it no way to tell when other data fields begin.
  261. err_str << "array of strings is not a valid option definition.";
  262. } else if (type_ == OPT_BINARY_TYPE) {
  263. err_str << "array of binary values is not"
  264. << " a valid option definition.";
  265. } else if (type_ == OPT_EMPTY_TYPE) {
  266. err_str << "array of empty value is not"
  267. << " a valid option definition.";
  268. }
  269. } else if (type_ == OPT_RECORD_TYPE) {
  270. // At least two data fields should be added to the record. Otherwise
  271. // non-record option definition could be used.
  272. if (getRecordFields().size() < 2) {
  273. err_str << "invalid number of data fields: "
  274. << getRecordFields().size()
  275. << " specified for the option of type 'record'. Expected at"
  276. << " least 2 fields.";
  277. } else {
  278. // If the number of fields is valid we have to check if their order
  279. // is valid too. We check that string or binary data fields are not
  280. // laid before other fields. But we allow that they are laid at the
  281. // end of an option.
  282. const RecordFieldsCollection& fields = getRecordFields();
  283. for (RecordFieldsConstIter it = fields.begin();
  284. it != fields.end(); ++it) {
  285. if (*it == OPT_STRING_TYPE &&
  286. it < fields.end() - 1) {
  287. err_str << "string data field can't be laid before data"
  288. << " fields of other types.";
  289. break;
  290. }
  291. if (*it == OPT_BINARY_TYPE &&
  292. it < fields.end() - 1) {
  293. err_str << "binary data field can't be laid before data"
  294. << " fields of other types.";
  295. }
  296. /// Empty type is not allowed within a record.
  297. if (*it == OPT_EMPTY_TYPE) {
  298. err_str << "empty data type can't be stored as a field in"
  299. << " an option record.";
  300. break;
  301. }
  302. }
  303. }
  304. }
  305. // Non-empty error string means that we have hit the error. We throw
  306. // exception and include error string.
  307. if (!err_str.str().empty()) {
  308. isc_throw(MalformedOptionDefinition, err_str.str());
  309. }
  310. }
  311. bool
  312. OptionDefinition::haveIAx6Format(OptionDataType first_type) const {
  313. return (haveType(OPT_RECORD_TYPE) &&
  314. record_fields_.size() == 3 &&
  315. record_fields_[0] == first_type &&
  316. record_fields_[1] == OPT_UINT32_TYPE &&
  317. record_fields_[2] == OPT_UINT32_TYPE);
  318. }
  319. bool
  320. OptionDefinition::haveIA6Format() const {
  321. // Expect that IA_NA option format is defined as record.
  322. // Although it consists of 3 elements of the same (uint32)
  323. // type it can't be defined as array of uint32 elements because
  324. // arrays do not impose limitations on number of elements in
  325. // the array while this limitation is needed for IA_NA - need
  326. // exactly 3 elements.
  327. return (haveIAx6Format(OPT_UINT32_TYPE));
  328. }
  329. bool
  330. OptionDefinition::haveIAAddr6Format() const {
  331. return (haveIAx6Format(OPT_IPV6_ADDRESS_TYPE));
  332. }
  333. bool
  334. OptionDefinition::haveIAPrefix6Format() const {
  335. return (haveType(OPT_RECORD_TYPE) &&
  336. record_fields_.size() == 4 &&
  337. record_fields_[0] == OPT_UINT32_TYPE &&
  338. record_fields_[1] == OPT_UINT32_TYPE &&
  339. record_fields_[2] == OPT_UINT8_TYPE &&
  340. record_fields_[3] == OPT_IPV6_ADDRESS_TYPE);
  341. }
  342. bool
  343. OptionDefinition::haveFqdn4Format() const {
  344. return (haveType(OPT_RECORD_TYPE) &&
  345. record_fields_.size() == 4 &&
  346. record_fields_[0] == OPT_UINT8_TYPE &&
  347. record_fields_[1] == OPT_UINT8_TYPE &&
  348. record_fields_[2] == OPT_UINT8_TYPE &&
  349. record_fields_[3] == OPT_FQDN_TYPE);
  350. }
  351. bool
  352. OptionDefinition::haveClientFqdnFormat() const {
  353. return (haveType(OPT_RECORD_TYPE) &&
  354. (record_fields_.size() == 2) &&
  355. (record_fields_[0] == OPT_UINT8_TYPE) &&
  356. (record_fields_[1] == OPT_FQDN_TYPE));
  357. }
  358. bool
  359. OptionDefinition::haveVendor4Format() const {
  360. return (true);
  361. }
  362. bool
  363. OptionDefinition::haveVendor6Format() const {
  364. return (getType() == OPT_UINT32_TYPE && !getEncapsulatedSpace().empty());
  365. }
  366. bool
  367. OptionDefinition::haveVendorClass4Format() const {
  368. return (haveType(OPT_RECORD_TYPE) &&
  369. (record_fields_.size() == 2) &&
  370. (record_fields_[0] == OPT_UINT32_TYPE) &&
  371. (record_fields_[1] == OPT_BINARY_TYPE));
  372. }
  373. bool
  374. OptionDefinition::haveVendorClass6Format() const {
  375. return (haveType(OPT_RECORD_TYPE) &&
  376. (record_fields_.size() == 2) &&
  377. (record_fields_[0] == OPT_UINT32_TYPE) &&
  378. (record_fields_[1] == OPT_BINARY_TYPE));
  379. }
  380. bool
  381. OptionDefinition::haveStatusCodeFormat() const {
  382. return (haveType(OPT_RECORD_TYPE) &&
  383. (record_fields_.size() == 2) &&
  384. (record_fields_[0] == OPT_UINT16_TYPE) &&
  385. (record_fields_[1] == OPT_STRING_TYPE));
  386. }
  387. bool
  388. OptionDefinition::convertToBool(const std::string& value_str) const {
  389. // Case insensitve check that the input is one of: "true" or "false".
  390. if (boost::iequals(value_str, "true")) {
  391. return (true);
  392. } else if (boost::iequals(value_str, "false")) {
  393. return (false);
  394. }
  395. // The input string is neither "true" nor "false", so let's check
  396. // if it is not an integer wrapped in a string.
  397. int result;
  398. try {
  399. result = boost::lexical_cast<int>(value_str);
  400. } catch (const boost::bad_lexical_cast&) {
  401. isc_throw(BadDataTypeCast, "unable to covert the value '"
  402. << value_str << "' to boolean data type");
  403. }
  404. // The boolean value is encoded in DHCP option as 0 or 1. Therefore,
  405. // we only allow a user to specify those values for options which
  406. // have boolean fields.
  407. if (result != 1 && result != 0) {
  408. isc_throw(BadDataTypeCast, "unable to convert '" << value_str
  409. << "' to boolean data type");
  410. }
  411. return (static_cast<bool>(result));
  412. }
  413. template<typename T>
  414. T
  415. OptionDefinition::lexicalCastWithRangeCheck(const std::string& value_str)
  416. const {
  417. // The lexical cast should be attempted when converting to an integer
  418. // value only.
  419. if (!OptionDataTypeTraits<T>::integer_type) {
  420. isc_throw(BadDataTypeCast,
  421. "must not convert '" << value_str
  422. << "' to non-integer data type");
  423. }
  424. // We use the 64-bit value here because it has wider range than
  425. // any other type we use here and it allows to detect out of
  426. // bounds conditions e.g. negative value specified for uintX_t
  427. // data type. Obviously if the value exceeds the limits of int64
  428. // this function will not handle that properly.
  429. int64_t result = 0;
  430. try {
  431. result = boost::lexical_cast<int64_t>(value_str);
  432. } catch (const boost::bad_lexical_cast&) {
  433. isc_throw(BadDataTypeCast, "unable to convert the value '"
  434. << value_str << "' to integer data type");
  435. }
  436. // Perform range checks.
  437. if (OptionDataTypeTraits<T>::integer_type) {
  438. if (result > numeric_limits<T>::max() ||
  439. result < numeric_limits<T>::min()) {
  440. isc_throw(BadDataTypeCast, "unable to convert '"
  441. << value_str << "' to numeric type. This value is "
  442. " expected to be in the range of "
  443. << numeric_limits<T>::min()
  444. << ".." << numeric_limits<T>::max());
  445. }
  446. }
  447. return (static_cast<T>(result));
  448. }
  449. void
  450. OptionDefinition::writeToBuffer(const std::string& value,
  451. const OptionDataType type,
  452. OptionBuffer& buf) const {
  453. // We are going to write value given by value argument to the buffer.
  454. // The actual type of the value is given by second argument. Check
  455. // this argument to determine how to write this value to the buffer.
  456. switch (type) {
  457. case OPT_BINARY_TYPE:
  458. OptionDataTypeUtil::writeBinary(value, buf);
  459. return;
  460. case OPT_BOOLEAN_TYPE:
  461. // We encode the true value as 1 and false as 0 on 8 bits.
  462. // That way we actually waste 7 bits but it seems to be the
  463. // simpler way to encode boolean.
  464. // @todo Consider if any other encode methods can be used.
  465. OptionDataTypeUtil::writeBool(convertToBool(value), buf);
  466. return;
  467. case OPT_INT8_TYPE:
  468. OptionDataTypeUtil::writeInt<uint8_t>
  469. (lexicalCastWithRangeCheck<int8_t>(value),
  470. buf);
  471. return;
  472. case OPT_INT16_TYPE:
  473. OptionDataTypeUtil::writeInt<uint16_t>
  474. (lexicalCastWithRangeCheck<int16_t>(value),
  475. buf);
  476. return;
  477. case OPT_INT32_TYPE:
  478. OptionDataTypeUtil::writeInt<uint32_t>
  479. (lexicalCastWithRangeCheck<int32_t>(value),
  480. buf);
  481. return;
  482. case OPT_UINT8_TYPE:
  483. OptionDataTypeUtil::writeInt<uint8_t>
  484. (lexicalCastWithRangeCheck<uint8_t>(value),
  485. buf);
  486. return;
  487. case OPT_UINT16_TYPE:
  488. OptionDataTypeUtil::writeInt<uint16_t>
  489. (lexicalCastWithRangeCheck<uint16_t>(value),
  490. buf);
  491. return;
  492. case OPT_UINT32_TYPE:
  493. OptionDataTypeUtil::writeInt<uint32_t>
  494. (lexicalCastWithRangeCheck<uint32_t>(value),
  495. buf);
  496. return;
  497. case OPT_IPV4_ADDRESS_TYPE:
  498. case OPT_IPV6_ADDRESS_TYPE:
  499. {
  500. asiolink::IOAddress address(value);
  501. if (!address.isV4() && !address.isV6()) {
  502. isc_throw(BadDataTypeCast, "provided address "
  503. << address
  504. << " is not a valid IPv4 or IPv6 address.");
  505. }
  506. OptionDataTypeUtil::writeAddress(address, buf);
  507. return;
  508. }
  509. case OPT_STRING_TYPE:
  510. OptionDataTypeUtil::writeString(value, buf);
  511. return;
  512. case OPT_FQDN_TYPE:
  513. OptionDataTypeUtil::writeFqdn(value, buf);
  514. return;
  515. default:
  516. // We hit this point because invalid option data type has been specified
  517. // This may be the case because 'empty' or 'record' data type has been
  518. // specified. We don't throw exception here because it will be thrown
  519. // at the exit point from this function.
  520. ;
  521. }
  522. isc_throw(isc::BadValue, "attempt to write invalid option data field type"
  523. " into the option buffer: " << type);
  524. }
  525. OptionPtr
  526. OptionDefinition::factoryAddrList4(uint16_t type,
  527. OptionBufferConstIter begin,
  528. OptionBufferConstIter end) {
  529. boost::shared_ptr<Option4AddrLst> option(new Option4AddrLst(type, begin,
  530. end));
  531. return (option);
  532. }
  533. OptionPtr
  534. OptionDefinition::factoryAddrList6(uint16_t type,
  535. OptionBufferConstIter begin,
  536. OptionBufferConstIter end) {
  537. boost::shared_ptr<Option6AddrLst> option(new Option6AddrLst(type, begin,
  538. end));
  539. return (option);
  540. }
  541. OptionPtr
  542. OptionDefinition::factoryEmpty(Option::Universe u, uint16_t type) {
  543. OptionPtr option(new Option(u, type));
  544. return (option);
  545. }
  546. OptionPtr
  547. OptionDefinition::factoryGeneric(Option::Universe u, uint16_t type,
  548. OptionBufferConstIter begin,
  549. OptionBufferConstIter end) {
  550. OptionPtr option(new Option(u, type, begin, end));
  551. return (option);
  552. }
  553. OptionPtr
  554. OptionDefinition::factoryIA6(uint16_t type,
  555. OptionBufferConstIter begin,
  556. OptionBufferConstIter end) {
  557. if (std::distance(begin, end) < Option6IA::OPTION6_IA_LEN) {
  558. isc_throw(isc::OutOfRange, "input option buffer has invalid size,"
  559. << " expected at least " << Option6IA::OPTION6_IA_LEN
  560. << " bytes");
  561. }
  562. boost::shared_ptr<Option6IA> option(new Option6IA(type, begin, end));
  563. return (option);
  564. }
  565. OptionPtr
  566. OptionDefinition::factoryIAAddr6(uint16_t type,
  567. OptionBufferConstIter begin,
  568. OptionBufferConstIter end) {
  569. if (std::distance(begin, end) < Option6IAAddr::OPTION6_IAADDR_LEN) {
  570. isc_throw(isc::OutOfRange,
  571. "input option buffer has invalid size, expected at least "
  572. << Option6IAAddr::OPTION6_IAADDR_LEN << " bytes");
  573. }
  574. boost::shared_ptr<Option6IAAddr> option(new Option6IAAddr(type, begin,
  575. end));
  576. return (option);
  577. }
  578. OptionPtr
  579. OptionDefinition::factoryIAPrefix6(uint16_t type,
  580. OptionBufferConstIter begin,
  581. OptionBufferConstIter end) {
  582. if (std::distance(begin, end) < Option6IAPrefix::OPTION6_IAPREFIX_LEN) {
  583. isc_throw(isc::OutOfRange,
  584. "input option buffer has invalid size, expected at least "
  585. << Option6IAPrefix::OPTION6_IAPREFIX_LEN << " bytes");
  586. }
  587. boost::shared_ptr<Option6IAPrefix> option(new Option6IAPrefix(type, begin,
  588. end));
  589. return (option);
  590. }
  591. OptionPtr
  592. OptionDefinition::factorySpecialFormatOption(Option::Universe u,
  593. OptionBufferConstIter begin,
  594. OptionBufferConstIter end,
  595. UnpackOptionsCallback) const {
  596. if (u == Option::V6) {
  597. if ((getCode() == D6O_IA_NA || getCode() == D6O_IA_PD) &&
  598. haveIA6Format()) {
  599. // Return Option6IA instance for IA_PD and IA_NA option
  600. // types only. We don't want to return Option6IA for other
  601. // options that comprise 3 UINT32 data fields because
  602. // Option6IA accessors' and modifiers' names are derived
  603. // from the IA_NA and IA_PD options' field names: IAID,
  604. // T1, T2. Using functions such as getIAID, getT1 etc. for
  605. // options other than IA_NA and IA_PD would be bad practice
  606. // and cause confusion.
  607. return (factoryIA6(getCode(), begin, end));
  608. } else if (getCode() == D6O_IAADDR && haveIAAddr6Format()) {
  609. // Rerurn Option6IAAddr option instance for the IAADDR
  610. // option only for the same reasons as described in
  611. // for IA_NA and IA_PD above.
  612. return (factoryIAAddr6(getCode(), begin, end));
  613. } else if (getCode() == D6O_IAPREFIX && haveIAPrefix6Format()) {
  614. return (factoryIAPrefix6(getCode(), begin, end));
  615. } else if (getCode() == D6O_CLIENT_FQDN && haveClientFqdnFormat()) {
  616. // FQDN option requires special processing. Thus, there is
  617. // a specialized class to handle it.
  618. return (OptionPtr(new Option6ClientFqdn(begin, end)));
  619. } else if (getCode() == D6O_VENDOR_OPTS && haveVendor6Format()) {
  620. // Vendor-Specific Information (option code 17)
  621. return (OptionPtr(new OptionVendor(Option::V6, begin, end)));
  622. } else if (getCode() == D6O_VENDOR_CLASS && haveVendorClass6Format()) {
  623. // Vendor Class (option code 16).
  624. return (OptionPtr(new OptionVendorClass(Option::V6, begin, end)));
  625. } else if (getCode() == D6O_STATUS_CODE && haveStatusCodeFormat()) {
  626. // Status Code (option code 13)
  627. return (OptionPtr(new Option6StatusCode(begin, end)));
  628. }
  629. } else {
  630. if ((getCode() == DHO_FQDN) && haveFqdn4Format()) {
  631. return (OptionPtr(new Option4ClientFqdn(begin, end)));
  632. } else if ((getCode() == DHO_VIVCO_SUBOPTIONS) &&
  633. haveVendorClass4Format()) {
  634. // V-I Vendor Class (option code 124).
  635. return (OptionPtr(new OptionVendorClass(Option::V4, begin, end)));
  636. } else if (getCode() == DHO_VIVSO_SUBOPTIONS && haveVendor4Format()) {
  637. // Vendor-Specific Information (option code 125).
  638. return (OptionPtr(new OptionVendor(Option::V4, begin, end)));
  639. }
  640. }
  641. return (OptionPtr());
  642. }
  643. } // end of isc::dhcp namespace
  644. } // end of isc namespace