32 #include <boost/algorithm/string/classification.hpp> 33 #include <boost/algorithm/string/predicate.hpp> 34 #include <boost/dynamic_bitset.hpp> 35 #include <boost/make_shared.hpp> 44 OptionDefinition::OptionDefinition(
const std::string& name,
46 const std::string& space,
47 const std::string& type,
48 const bool array_type )
52 array_type_(array_type),
53 encapsulated_space_(
""),
56 option_space_name_(space) {
65 const std::string& space,
67 const bool array_type )
71 array_type_(array_type),
72 encapsulated_space_(
""),
73 option_space_name_(space){
78 const std::string& space,
79 const std::string& type,
80 const char* encapsulated_space)
88 encapsulated_space_(encapsulated_space),
91 option_space_name_(space) {
96 const std::string& space,
98 const char* encapsulated_space)
103 encapsulated_space_(encapsulated_space),
106 option_space_name_(space) {
112 const std::string& space,
113 const std::string& type,
114 const bool array_type) {
115 return (boost::make_shared<OptionDefinition>(name, code, space, type, array_type));
121 const std::string& space,
123 const bool array_type) {
124 return (boost::make_shared<OptionDefinition>(name, code, space, type, array_type));
130 const std::string& space,
131 const std::string& type,
132 const char* encapsulated_space) {
133 return (boost::make_shared<OptionDefinition>(name, code, space, type, encapsulated_space));
139 const std::string& space,
141 const char* encapsulated_space) {
142 return (boost::make_shared<OptionDefinition>(name, code, space, type, encapsulated_space));
147 return (name_ == other.name_ &&
148 code_ == other.code_ &&
149 type_ == other.type_ &&
150 array_type_ == other.array_type_ &&
151 encapsulated_space_ == other.encapsulated_space_ &&
152 record_fields_ == other.record_fields_ &&
153 option_space_name_ == other.option_space_name_);
166 "'record' option type must be used instead of '" 168 <<
"' to add data fields to the record");
174 "attempted to add invalid data type '" 176 <<
"' to the record.");
178 record_fields_.push_back(data_type);
193 OptionPtr option = factorySpecialFormatOption(u, begin, end);
210 return (array_type_ ?
211 factoryIntegerArray<uint8_t>(u, type, begin, end) :
216 return (array_type_ ?
217 factoryIntegerArray<int8_t>(u, type, begin, end) :
222 return (array_type_ ?
223 factoryIntegerArray<uint16_t>(u, type, begin, end) :
228 return (array_type_ ?
229 factoryIntegerArray<uint16_t>(u, type, begin, end) :
234 return (array_type_ ?
235 factoryIntegerArray<uint32_t>(u, type, begin, end) :
240 return (array_type_ ?
241 factoryIntegerArray<uint32_t>(u, type, begin, end) :
299 const std::vector<std::string>& values)
const {
302 if (values.empty()) {
310 for (
size_t i = 0; i < values.size(); ++i) {
315 if (records.size() > values.size()) {
317 <<
" type '" <<
getCode() <<
"' is greater than number" 318 <<
" of values provided.");
320 for (
size_t i = 0; i < records.size(); ++i) {
323 if (array_type_ && (values.size() > records.size())) {
324 for (
size_t i = records.size(); i < values.size(); ++i) {
326 records.back(), buf);
336 using namespace boost::algorithm;
338 std::ostringstream err_str;
343 if (!all(
name_, boost::is_from_range(
'a',
'z') ||
344 boost::is_from_range(
'A',
'Z') ||
346 boost::is_any_of(std::string(
"-_"))) ||
350 all(find_head(
name_, 1), boost::is_any_of(std::string(
"-_"))) ||
351 all(find_tail(
name_, 1), boost::is_any_of(std::string(
"-_")))) {
352 err_str <<
"invalid option name '" <<
name_ <<
"'";
355 err_str <<
"invalid option space name: '" 356 << option_space_name_ <<
"'";
358 }
else if (!encapsulated_space_.empty() &&
360 err_str <<
"invalid encapsulated option space name: '" 361 << encapsulated_space_ <<
"'";
365 err_str <<
"option type " << type_ <<
" not supported.";
371 err_str <<
"invalid number of data fields: " 373 <<
" specified for the option of type 'record'. Expected at" 374 <<
" least 2 fields.";
383 it != fields.end(); ++it) {
385 it < fields.end() - 1) {
386 err_str <<
"string data field can't be laid before data" 387 <<
" fields of other types.";
391 it < fields.end() - 1) {
392 err_str <<
"binary data field can't be laid before data" 393 <<
" fields of other types.";
398 err_str <<
"empty data type can't be stored as a field in" 399 <<
" an option record.";
404 if (err_str.str().empty() && array_type_) {
408 <<
"array of strings is not a valid option definition.";
410 err_str <<
"array of binary values is not a valid option " 417 }
else if (array_type_) {
422 err_str <<
"array of strings is not a valid option definition.";
424 err_str <<
"array of binary values is not" 425 <<
" a valid option definition.";
428 err_str <<
"array of empty value is not" 429 <<
" a valid option definition.";
436 if (!err_str.str().empty()) {
442 OptionDefinition::haveCompressedFqdnListFormat()
const {
447 OptionDefinition::convertToBool(
const std::string& value_str)
const {
449 if (boost::iequals(value_str,
"true")) {
452 }
else if (boost::iequals(value_str,
"false")) {
461 result = boost::lexical_cast<
int>(value_str);
463 }
catch (
const boost::bad_lexical_cast&) {
465 << value_str <<
"' to boolean data type");
470 if (result != 1 && result != 0) {
472 <<
"' to boolean data type");
474 return (static_cast<bool>(result));
479 OptionDefinition::lexicalCastWithRangeCheck(
const std::string& value_str)
485 "must not convert '" << value_str
486 <<
"' to non-integer data type");
496 result = boost::lexical_cast<int64_t>(value_str);
498 }
catch (
const boost::bad_lexical_cast&) {
501 std::stringstream ss;
502 ss << std::hex << value_str;
504 if (ss.fail() || !ss.eof()) {
506 << value_str <<
"' to integer data type");
511 if (result > numeric_limits<T>::max() ||
512 result < numeric_limits<T>::min()) {
514 << value_str <<
"' to numeric type. This value is " 515 "expected to be in the range of " 516 << +numeric_limits<T>::min() <<
".." 517 << +numeric_limits<T>::max());
520 return (static_cast<T>(result));
525 const std::string& value,
543 OptionDataTypeUtil::writeInt<uint8_t>
544 (lexicalCastWithRangeCheck<int8_t>(value),
548 OptionDataTypeUtil::writeInt<uint16_t>
549 (lexicalCastWithRangeCheck<int16_t>(value),
553 OptionDataTypeUtil::writeInt<uint32_t>
554 (lexicalCastWithRangeCheck<int32_t>(value),
558 OptionDataTypeUtil::writeInt<uint8_t>
559 (lexicalCastWithRangeCheck<uint8_t>(value),
563 OptionDataTypeUtil::writeInt<uint16_t>
564 (lexicalCastWithRangeCheck<uint16_t>(value),
568 OptionDataTypeUtil::writeInt<uint32_t>
569 (lexicalCastWithRangeCheck<uint32_t>(value),
576 if (!address.
isV4() && !address.
isV6()) {
579 <<
" is not a valid IPv4 or IPv6 address.");
586 std::string txt = value;
589 boost::erase_all(txt,
" ");
590 boost::erase_all(txt,
"\t");
593 size_t pos = txt.find(
"/");
595 if (pos == string::npos) {
598 <<
" is not valid.");
601 std::string txt_address = txt.substr(0, pos);
603 if (!address.
isV6()) {
606 <<
" is not a valid IPv4 or IPv6 address.");
609 std::string txt_prefix = txt.substr(pos + 1);
613 len = lexicalCastWithRangeCheck<uint8_t>(txt_prefix);
617 <<
" is not valid.");
627 std::string txt = value;
630 boost::erase_all(txt,
" ");
631 boost::erase_all(txt,
"\t");
634 size_t pos = txt.find(
"/");
636 if (pos == string::npos) {
638 << value <<
" is not valid");
641 const std::string txt_psid = txt.substr(0, pos);
642 const std::string txt_psid_len = txt.substr(pos + 1);
645 uint8_t psid_len = 0;
648 psid = lexicalCastWithRangeCheck<uint16_t>(txt_psid);
651 << txt_psid <<
" is not valid");
655 psid_len = lexicalCastWithRangeCheck<uint8_t>(txt_psid_len);
658 << txt_psid_len <<
" is not valid");
685 " into the option buffer: " << type);
693 boost::shared_ptr<Option4AddrLst> option(
new Option4AddrLst(type, begin,
702 boost::shared_ptr<Option6AddrLst> option(
new Option6AddrLst(type, begin,
731 boost::shared_ptr<Option6IA> option(
new Option6IA(type, begin, end));
741 "input option buffer has invalid size, expected at least " 744 boost::shared_ptr<Option6IAAddr> option(
new Option6IAAddr(type, begin,
755 "input option buffer has invalid size, expected at least " 758 boost::shared_ptr<Option6IAPrefix> option(
new Option6IAPrefix(type, begin,
768 boost::shared_ptr<OptionOpaqueDataTuples>
779 const std::vector<uint8_t> data(begin, end);
783 InputBuffer in_buf(static_cast<const void*>(&data[0]), data.size());
784 std::vector<uint8_t> out_buf;
785 out_buf.reserve(data.size());
786 while (in_buf.getPosition() < in_buf.getLength()) {
794 const uint8_t* label = labels.
getData(&read_len);
795 out_buf.insert(out_buf.end(), label, label + read_len);
802 out_buf.begin(), out_buf.end()));
880 if ((u ==
Option::V4) && haveCompressedFqdnListFormat()) {
881 return (factoryFqdnList(
Option::V4, begin, end));
The Name class encapsulates DNS names.
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.
Encapsulates PSID length.
static OptionDefinitionPtr create(const std::string &name, const uint16_t code, const std::string &space, const std::string &type, const bool array_type=false)
Factory function creating an instance of the OptionDefinition.
Exception to be thrown when invalid option value has been specified for a particular option definitio...
Represents DHCPv6 Client FQDN Option (code 39).
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.
static void writePsid(const PSIDLen &psid_len, const PSID &psid, std::vector< uint8_t > &buf)
Append PSID length/value into a buffer.
static const std::string & getDataTypeName(const OptionDataType data_type)
Return option data type name from the data type enumerator.
Exception thrown during option unpacking This exception is thrown when an error has occurred...
DHCPv4 Option class for handling list of IPv4 addresses.
This class represents SLP Service Scope option (79) from RFC2610.
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
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.
DHCPv6 option class representing Prefix Exclude Option (RFC 6603).
DHCPv6 Option class for handling list of IPv6 addresses.
static OptionPtr factoryEmpty(Option::Universe u, uint16_t type)
Empty option factory.
OptionDefinition(const std::string &name, const uint16_t code, const std::string &space, const std::string &type, const bool array_type=false)
Constructor.
Represents DHCPv4 Client FQDN Option (code 81).
size_t getDataLength() const
Return the length of the wire-format data of this LabelSequence.
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.
static OptionPtr factoryIAPrefix6(uint16_t type, OptionBufferConstIter begin, OptionBufferConstIter end)
Factory for IAPREFIX-type of option.
This class represents Status Code option (13) from RFC 8415.
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...
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.
const uint8_t * getData(size_t *len) const
Return the wire-format data for this LabelSequence.
bool isV6() const
Convenience function to check for an IPv6 address.
bool isV4() const
Convenience function to check for an IPv4 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-lfc.
static OptionPtr factoryGeneric(Option::Universe u, uint16_t type, OptionBufferConstIter begin, OptionBufferConstIter end)
Factory to create generic option.
static const size_t OPTION6_IAPREFIX_LEN
length of the fixed part of the IAPREFIX option
const RecordFieldsCollection & getRecordFields() const
Return list of record fields.
#define DHCP6_OPTION_SPACE
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.
#define DHCP4_OPTION_SPACE
global std option spaces
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...
boost::shared_ptr< OptionDefinition > OptionDefinitionPtr
Pointer to option definition object.
Exception thrown during option unpacking This exception is thrown when an error has occurred unpackin...
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.
Exception to be thrown when cast to the data type was unsuccessful.
Trait class for data types supported in DHCP option definitions.
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.
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.
std::string getEncapsulatedSpace() const
Return name of the encapsulated option space.
Encapsulates prefix length.
Class which represents an option carrying a single string value.
This class represents vendor-specific information option.
Light-weight Accessor to Name data.
This class encapsulates DHCPv6 Vendor Class and DHCPv4 V-I Vendor Class options.