32 #include <boost/algorithm/string/classification.hpp> 33 #include <boost/algorithm/string/predicate.hpp> 34 #include <boost/dynamic_bitset.hpp> 43 OptionDefinition::OptionDefinition(
const std::string& name,
45 const std::string& type,
46 const bool array_type )
50 array_type_(array_type),
51 encapsulated_space_(
""),
54 option_space_name_() {
64 const bool array_type )
68 array_type_(array_type),
69 encapsulated_space_(
"") {
74 const std::string& type,
75 const char* encapsulated_space)
83 encapsulated_space_(encapsulated_space),
86 option_space_name_() {
92 const char* encapsulated_space)
97 encapsulated_space_(encapsulated_space),
100 option_space_name_() {
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_);
124 " to add data fields to the record");
130 "attempted to add invalid data type to the record.");
132 record_fields_.push_back(data_type);
147 OptionPtr option = factorySpecialFormatOption(u, begin, end);
164 return (array_type_ ?
165 factoryIntegerArray<uint8_t>(u, type, begin, end) :
170 return (array_type_ ?
171 factoryIntegerArray<int8_t>(u, type, begin, end) :
176 return (array_type_ ?
177 factoryIntegerArray<uint16_t>(u, type, begin, end) :
182 return (array_type_ ?
183 factoryIntegerArray<uint16_t>(u, type, begin, end) :
188 return (array_type_ ?
189 factoryIntegerArray<uint32_t>(u, type, begin, end) :
194 return (array_type_ ?
195 factoryIntegerArray<uint32_t>(u, type, begin, end) :
250 const std::vector<std::string>& values)
const {
253 if (values.empty()) {
261 for (
size_t i = 0; i < values.size(); ++i) {
266 if (records.size() > values.size()) {
268 <<
" type '" <<
getCode() <<
"' is greater than number" 269 <<
" of values provided.");
271 for (
size_t i = 0; i < records.size(); ++i) {
274 if (array_type_ && (values.size() > records.size())) {
275 for (
size_t i = records.size(); i < values.size(); ++i) {
277 records.back(), buf);
287 using namespace boost::algorithm;
289 std::ostringstream err_str;
294 if (!all(
name_, boost::is_from_range(
'a',
'z') ||
295 boost::is_from_range(
'A',
'Z') ||
297 boost::is_any_of(std::string(
"-_"))) ||
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_ <<
"'";
305 }
else if (!encapsulated_space_.empty() &&
307 err_str <<
"invalid encapsulated option space name: '" 308 << encapsulated_space_ <<
"'";
312 err_str <<
"option type " << type_ <<
" not supported.";
318 err_str <<
"invalid number of data fields: " 320 <<
" specified for the option of type 'record'. Expected at" 321 <<
" least 2 fields.";
330 it != fields.end(); ++it) {
332 it < fields.end() - 1) {
333 err_str <<
"string data field can't be laid before data" 334 <<
" fields of other types.";
338 it < fields.end() - 1) {
339 err_str <<
"binary data field can't be laid before data" 340 <<
" fields of other types.";
345 err_str <<
"empty data type can't be stored as a field in" 346 <<
" an option record.";
351 if (err_str.str().empty() && array_type_) {
354 err_str <<
"array of strings is not" 355 <<
"a valid option definition.";
357 err_str <<
"array of binary values is not" 358 <<
" a valid option definition.";
364 }
else if (array_type_) {
369 err_str <<
"array of strings is not a valid option definition.";
371 err_str <<
"array of binary values is not" 372 <<
" a valid option definition.";
375 err_str <<
"array of empty value is not" 376 <<
" a valid option definition.";
383 if (!err_str.str().empty()) {
389 OptionDefinition::haveIAx6Format(
OptionDataType first_type)
const {
392 record_fields_.size() == 3 &&
393 record_fields_[0] == first_type &&
418 record_fields_.size() == 4 &&
429 record_fields_.size() == 4 &&
440 (record_fields_.size() == 2) &&
458 (record_fields_.size() == 2) &&
466 (record_fields_.size() == 2) &&
474 (record_fields_.size() == 2) &&
482 (record_fields_.size() == 2) &&
498 OptionDefinition::convertToBool(
const std::string& value_str)
const {
500 if (boost::iequals(value_str,
"true")) {
503 }
else if (boost::iequals(value_str,
"false")) {
512 result = boost::lexical_cast<int>(value_str);
514 }
catch (
const boost::bad_lexical_cast&) {
515 isc_throw(BadDataTypeCast,
"unable to covert the value '" 516 << value_str <<
"' to boolean data type");
521 if (result != 1 && result != 0) {
522 isc_throw(BadDataTypeCast,
"unable to convert '" << value_str
523 <<
"' to boolean data type");
525 return (static_cast<bool>(result));
530 OptionDefinition::lexicalCastWithRangeCheck(
const std::string& value_str)
536 "must not convert '" << value_str
537 <<
"' to non-integer data type");
547 result = boost::lexical_cast<int64_t>(value_str);
549 }
catch (
const boost::bad_lexical_cast&) {
552 std::stringstream ss;
553 ss << std::hex << value_str;
555 if (ss.fail() || !ss.eof()) {
556 isc_throw(BadDataTypeCast,
"unable to convert the value '" 557 << value_str <<
"' to integer data type");
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());
571 return (static_cast<T>(result));
576 const std::string& value,
594 OptionDataTypeUtil::writeInt<uint8_t>
595 (lexicalCastWithRangeCheck<int8_t>(value),
599 OptionDataTypeUtil::writeInt<uint16_t>
600 (lexicalCastWithRangeCheck<int16_t>(value),
604 OptionDataTypeUtil::writeInt<uint32_t>
605 (lexicalCastWithRangeCheck<int32_t>(value),
609 OptionDataTypeUtil::writeInt<uint8_t>
610 (lexicalCastWithRangeCheck<uint8_t>(value),
614 OptionDataTypeUtil::writeInt<uint16_t>
615 (lexicalCastWithRangeCheck<uint16_t>(value),
619 OptionDataTypeUtil::writeInt<uint32_t>
620 (lexicalCastWithRangeCheck<uint32_t>(value),
626 asiolink::IOAddress address(value);
627 if (!address.isV4() && !address.isV6()) {
628 isc_throw(BadDataTypeCast,
"provided address " 630 <<
" is not a valid IPv4 or IPv6 address.");
637 std::string txt = value;
640 boost::erase_all(txt,
" ");
641 boost::erase_all(txt,
"\t");
644 size_t pos = txt.find(
"/");
646 if (pos == string::npos) {
647 isc_throw(BadDataTypeCast,
"provided address/prefix " 649 <<
" is not valid.");
652 std::string txt_address = txt.substr(0, pos);
654 if (!address.
isV6()) {
655 isc_throw(BadDataTypeCast,
"provided address " 657 <<
" is not a valid IPv4 or IPv6 address.");
660 std::string txt_prefix = txt.substr(pos + 1);
664 len = lexicalCastWithRangeCheck<uint8_t>(txt_prefix);
666 isc_throw(BadDataTypeCast,
"provided prefix " 668 <<
" is not valid.");
678 std::string txt = value;
681 boost::erase_all(txt,
" ");
682 boost::erase_all(txt,
"\t");
685 size_t pos = txt.find(
"/");
687 if (pos == string::npos) {
688 isc_throw(BadDataTypeCast,
"provided PSID value " 689 << value <<
" is not valid");
692 const std::string txt_psid = txt.substr(0, pos);
693 const std::string txt_psid_len = txt.substr(pos + 1);
696 uint8_t psid_len = 0;
699 psid = lexicalCastWithRangeCheck<uint16_t>(txt_psid);
701 isc_throw(BadDataTypeCast,
"provided PSID " 702 << txt_psid <<
" is not valid");
706 psid_len = lexicalCastWithRangeCheck<uint8_t>(txt_psid_len);
708 isc_throw(BadDataTypeCast,
"provided PSID length " 709 << txt_psid_len <<
" is not valid");
736 " into the option buffer: " << type);
744 boost::shared_ptr<Option4AddrLst> option(
new Option4AddrLst(type, begin,
753 boost::shared_ptr<Option6AddrLst> option(
new Option6AddrLst(type, begin,
782 boost::shared_ptr<Option6IA> option(
new Option6IA(type, begin, end));
792 "input option buffer has invalid size, expected at least " 795 boost::shared_ptr<Option6IAAddr> option(
new Option6IAAddr(type, begin,
806 "input option buffer has invalid size, expected at least " 809 boost::shared_ptr<Option6IAPrefix> option(
new Option6IAPrefix(type, begin,
819 boost::shared_ptr<OptionOpaqueDataTuples>
830 const std::vector<uint8_t> data(begin, end);
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()) {
843 if (labels.getDataLength() > 0) {
845 const uint8_t* label = labels.getData(&read_len);
846 out_buf.insert(out_buf.end(), label, label + read_len);
852 return OptionPtr(
new OptionCustom(*
this, u,
853 out_buf.begin(), out_buf.end()));
883 return (
OptionPtr(
new Option6ClientFqdn(begin, end)));
892 return (
OptionPtr(
new Option6StatusCode(begin, end)));
898 return (
OptionPtr(
new Option6PDExclude(begin, end)));
902 return (
OptionPtr(
new Option4SlpServiceScope(begin, end)));
904 return (
OptionPtr(
new Option4ClientFqdn(begin, end)));
906 return (factoryFqdnList(
Option::V4, begin, end));
The Name class encapsulates DNS names.
static const bool integer_type
static const size_t OPTION6_IAADDR_LEN
length of the fixed part of the IAADDR option
bool equals(const OptionDefinition &other) const
Check if option definition is equal to other.
Exception to be thrown when invalid option value has been specified for a particular option definitio...
Base class representing a DHCP option definition.
std::vector< OptionDataType > RecordFieldsCollection
List of fields within the record.
static OptionPtr factoryAddrList4(uint16_t type, OptionBufferConstIter begin, OptionBufferConstIter end)
Factory to create option with address list.
bool haveVendorClass4Format() const
Check if the option has format of DHCPv4 V-I Vendor Class option.
static void writePsid(const PSIDLen &psid_len, const PSID &psid, std::vector< uint8_t > &buf)
Append PSID length/value into a buffer.
Exception thrown during option unpacking This exception is thrown when an error has occurred,...
DHCPv4 Option class for handling list of IPv4 addresses.
Utility class for option data types.
static bool validateName(const std::string &name)
Checks that the provided option space name is valid.
static void writeBool(const bool value, std::vector< uint8_t > &buf)
Append boolean value into a buffer.
boost::shared_ptr< Option > OptionPtr
OptionDefinition(const std::string &name, const uint16_t code, const std::string &type, const bool array_type=false)
Constructor.
static void writeFqdn(const std::string &fqdn, std::vector< uint8_t > &buf, const bool downcase=false)
Append FQDN into a buffer.
Universe
defines option universe DHCPv4 or DHCPv6
static void writePrefix(const PrefixLen &prefix_len, const asiolink::IOAddress &prefix, std::vector< uint8_t > &buf)
Append prefix into a buffer.
bool haveIA6Format() const
Check if specified format is IA_NA option format.
DHCPv6 Option class for handling list of IPv6 addresses.
static OptionPtr factoryEmpty(Option::Universe u, uint16_t type)
Empty option factory.
static OptionPtr factoryIA6(uint16_t type, OptionBufferConstIter begin, OptionBufferConstIter end)
Factory for IA-type of option.
OptionPtr optionFactory(Option::Universe u, uint16_t type, OptionBufferConstIter begin, OptionBufferConstIter end) const
Option factory.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
static OptionPtr factoryOpaqueDataTuples(Option::Universe u, uint16_t type, OptionBufferConstIter begin, OptionBufferConstIter end)
Factory to create option with tuple list.
std::vector< uint8_t > OptionBuffer
buffer types used in DHCP code.
bool haveClientFqdnFormat() const
Check if specified format is OPTION_CLIENT_FQDN option format.
static OptionPtr factoryIAPrefix6(uint16_t type, OptionBufferConstIter begin, OptionBufferConstIter end)
Factory for IAPREFIX-type of option.
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.
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
bool haveIAPrefix6Format() const
Check if specified format is IAPREFIX option format.
static OptionDataType getDataType(const std::string &data_type)
Return option data type from its name.
OptionDataType
Data types of DHCP option fields.
uint16_t getCode() const
Return option code.
static OptionPtr factoryAddrList6(uint16_t type, OptionBufferConstIter begin, OptionBufferConstIter end)
Factory to create option with address list.
bool haveVendor6Format() const
Check if option has a format of the Vendor-Specific Information Option.
bool isV6() const
Convenience function to check for an IPv6 address.
OptionBuffer::const_iterator OptionBufferConstIter
const_iterator for walking over OptionBuffer
LengthFieldType
Size of the length field in the tuple.
This is a base class for exceptions thrown from the DNS library module.
Defines the logger used by the top-level component of kea-dhcp-ddns.
static OptionPtr factoryGeneric(Option::Universe u, uint16_t type, OptionBufferConstIter begin, OptionBufferConstIter end)
Factory to create generic option.
bool haveVendorClass6Format() const
Check if the option has format of DHCPv6 Vendor Class option.
static const size_t OPTION6_IAPREFIX_LEN
length of the fixed part of the IAPREFIX option
bool haveIAAddr6Format() const
Check if specified format is IAADDR option format.
const RecordFieldsCollection & getRecordFields() const
Return list of record fields.
bool haveFqdn4Format() const
Check if option has format of the DHCPv4 Client FQDN Option.
void addRecordField(const std::string &data_type_name)
Adds data field to the record.
A generic exception that is thrown if a function is called in a prohibited way.
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.
static void writeBinary(const std::string &hex_str, std::vector< uint8_t > &buf)
Append hex-encoded binary values to a buffer.
A generic exception that is thrown if a parameter given to a method would refer to or modify out-of-r...
bool haveServiceScopeFormat() const
Check if option has format of the SLP Service Scope Option.
std::vector< OptionDataType >::const_iterator RecordFieldsConstIter
Const iterator for record data fields.
string trim(const string &instring)
Trim Leading and Trailing Spaces.
static const size_t OPTION6_IA_LEN
Length of IA_NA and IA_PD content.
static OptionPtr factoryIAAddr6(uint16_t type, OptionBufferConstIter begin, OptionBufferConstIter end)
Factory for IAADDR-type of option.
This class encapsulates a collection of data tuples and could be used by multiple options.
The IOAddress class represents an IP addresses (version agnostic)
bool getArrayType() const
Return array type indicator.
Class that represents IAPREFIX option in DHCPv6.
bool haveOpaqueDataTuplesFormat() const
Check if the option has format of OpaqueDataTuples type options.
OptionDataType getType() const
Return option data type.
Option with defined data fields represented as buffers that can be accessed using data field index.
static void writeString(const std::string &value, std::vector< uint8_t > &buf)
Write UTF8-encoded string into a buffer.
bool haveStatusCodeFormat() const
Check if the option has format of DHCPv6 Status Code option.
std::string getEncapsulatedSpace() const
Return name of the encapsulated option space.
bool haveCompressedFqdnListFormat() const
Check if the option has format of CompressedFqdnList options.
Class which represents an option carrying a single string value.
bool haveVendor4Format() const
Check if the option has format of Vendor-Identifying Vendor Specific Options.
Light-weight Accessor to Name data.