35#include <boost/algorithm/string/classification.hpp> 
   36#include <boost/algorithm/string/predicate.hpp> 
   37#include <boost/algorithm/string/replace.hpp> 
   38#include <boost/dynamic_bitset.hpp> 
   39#include <boost/make_shared.hpp> 
   50                                   const std::string& space,
 
   51                                   const std::string& type,
 
   52                                   const bool array_type )
 
   56      array_type_(array_type),
 
   57      encapsulated_space_(
""),
 
   60      option_space_name_(space) {
 
 
   69                                   const std::string& space,
 
   71                                   const bool array_type )
 
   75      array_type_(array_type),
 
   76      encapsulated_space_(
""),
 
   77      option_space_name_(space){
 
 
   82                                   const std::string& space,
 
   83                                   const std::string& type,
 
   84                                   const char* encapsulated_space)
 
   92      encapsulated_space_(encapsulated_space),
 
   95      option_space_name_(space) {
 
 
  100                                   const std::string& space,
 
  102                                   const char* encapsulated_space)
 
  107      encapsulated_space_(encapsulated_space),
 
  110      option_space_name_(space) {
 
 
  116                         const std::string& space,
 
  117                         const std::string& type,
 
  118                         const bool array_type) {
 
  119    return (boost::make_shared<OptionDefinition>(name, code, space, type, array_type));
 
 
  125                         const std::string& space,
 
  127                         const bool array_type) {
 
  128    return (boost::make_shared<OptionDefinition>(name, code, space, type, array_type));
 
 
  134                         const std::string& space,
 
  135                         const std::string& type,
 
  136                         const char* encapsulated_space) {
 
  137    return (boost::make_shared<OptionDefinition>(name, code, space, type, encapsulated_space));
 
 
  143                         const std::string& space,
 
  145                         const char* encapsulated_space) {
 
  146    return (boost::make_shared<OptionDefinition>(name, code, space, type, encapsulated_space));
 
 
  151    return (name_ == other.name_ &&
 
  152            code_ == other.code_ &&
 
  153            type_ == other.type_ &&
 
  154            array_type_ == other.array_type_ &&
 
  155            encapsulated_space_ == other.encapsulated_space_ &&
 
  156            record_fields_ == other.record_fields_ &&
 
  157            option_space_name_ == other.option_space_name_);
 
 
  170                  "'record' option type must be used instead of '" 
  172                      << 
"' to add data fields to the record");
 
  178                  "attempted to add invalid data type '" 
  180                      << 
"' to the record.");
 
  182    record_fields_.push_back(data_type);
 
 
  190                                bool convenient_notation)
 const {
 
  199        OptionPtr option = factorySpecialFormatOption(u, begin, end, convenient_notation);
 
  219            return (array_type_ ?
 
  225            return (array_type_ ?
 
  231            return (array_type_ ?
 
  237            return (array_type_ ?
 
  243            return (array_type_ ?
 
  249            return (array_type_ ?
 
 
  308                                const std::vector<std::string>& values)
 const {
 
  311        if (values.empty()) {
 
  327            std::ostringstream stream;
 
  329            for (
auto val : values) {
 
  330                boost::algorithm::replace_all(val, 
",", 
"\\,");
 
  345        for (
size_t i = 0; i < values.size(); ++i) {
 
  350        if (records.size() > values.size()) {
 
  352                      << 
" type '" <<  
getCode() << 
"' is greater than number" 
  353                      << 
" of values provided.");
 
  355        for (
size_t i = 0; i < records.size(); ++i) {
 
  358        if (array_type_ && (values.size() > records.size())) {
 
  359            for (
size_t i = records.size(); i < values.size(); ++i) {
 
  361                              records.back(), buf);
 
 
  371    using namespace boost::algorithm;
 
  373    std::ostringstream err_str;
 
  378    if (!all(name_, boost::is_from_range(
'a', 
'z') ||
 
  379             boost::is_from_range(
'A', 
'Z') ||
 
  381             boost::is_any_of(std::string(
"-_"))) ||
 
  385        all(find_head(name_, 1), boost::is_any_of(std::string(
"-_"))) ||
 
  386        all(find_tail(name_, 1), boost::is_any_of(std::string(
"-_")))) {
 
  387        err_str << 
"invalid option name '" << name_ << 
"'";
 
  390        err_str << 
"invalid option space name: '" 
  391                << option_space_name_ << 
"'";
 
  393    } 
else if (!encapsulated_space_.empty() &&
 
  395        err_str << 
"invalid encapsulated option space name: '" 
  396                << encapsulated_space_ << 
"'";
 
  400        err_str << 
"option type " << type_ << 
" not supported.";
 
  406            err_str << 
"invalid number of data fields: " 
  408                    << 
" specified for the option of type 'record'. Expected at" 
  409                    << 
" least 2 fields.";
 
  418                 it != fields.end(); ++it) {
 
  420                    it < fields.end() - 1) {
 
  421                    err_str << 
"string data field can't be laid before data" 
  422                            << 
" fields of other types.";
 
  426                    it < fields.end() - 1) {
 
  427                    err_str << 
"binary data field can't be laid before data" 
  428                            << 
" fields of other types.";
 
  433                    err_str << 
"empty data type can't be stored as a field in" 
  434                            << 
" an option record.";
 
  439                    err_str << 
"internal data type can't be stored as a field in" 
  440                            << 
" an option record.";
 
  445            if (err_str.str().empty() && array_type_) {
 
  449                        << 
"array of strings is not a valid option definition.";
 
  451                    err_str << 
"array of binary values is not a valid option " 
  458    } 
else if (array_type_) {
 
  463            err_str << 
"array of strings is not a valid option definition.";
 
  465            err_str << 
"array of binary values is not" 
  466                    << 
" a valid option definition.";
 
  469            err_str << 
"array of empty value is not" 
  470                    << 
" a valid option definition.";
 
  473            err_str << 
"array of internal type value is not" 
  474                    << 
" a valid option definition.";
 
  481    if (!err_str.str().empty()) {
 
 
  487OptionDefinition::haveCompressedFqdnListFormat()
 const {
 
  492OptionDefinition::convertToBool(
const std::string& value_str)
 const {
 
  494    if (boost::iequals(value_str, 
"true")) {
 
  497    } 
else if (boost::iequals(value_str, 
"false")) {
 
  506        result = boost::lexical_cast<int>(value_str);
 
  508    } 
catch (
const boost::bad_lexical_cast&) {
 
  509        isc_throw(BadDataTypeCast, 
"unable to covert the value '" 
  510                  << value_str << 
"' to boolean data type");
 
  515    if (result != 1 && result != 0) {
 
  516        isc_throw(BadDataTypeCast, 
"unable to convert '" << value_str
 
  517                  << 
"' to boolean data type");
 
  519    return (
static_cast<bool>(result));
 
  524OptionDefinition::lexicalCastWithRangeCheck(
const std::string& value_str)
 
  530                  "must not convert '" << value_str
 
  531                  << 
"' to non-integer data type");
 
  541        result = boost::lexical_cast<int64_t>(value_str);
 
  543    } 
catch (
const boost::bad_lexical_cast&) {
 
  546        std::stringstream ss;
 
  547        ss << std::hex << value_str;
 
  549        if (ss.fail() || !ss.eof()) {
 
  550            isc_throw(BadDataTypeCast, 
"unable to convert the value '" 
  551                      << value_str << 
"' to integer data type");
 
  556        if (result > numeric_limits<T>::max() ||
 
  557            result < numeric_limits<T>::min()) {
 
  558            isc_throw(BadDataTypeCast, 
"unable to convert '" 
  559                      << value_str << 
"' to numeric type. This value is " 
  560                         "expected to be in the range of " 
  561                      << +numeric_limits<T>::min() << 
".." 
  562                      << +numeric_limits<T>::max());
 
  565    return (
static_cast<T
>(result));
 
  570                                const std::string& value,
 
  589            (lexicalCastWithRangeCheck<int8_t>(value),
 
  594            (lexicalCastWithRangeCheck<int16_t>(value),
 
  599            (lexicalCastWithRangeCheck<int32_t>(value),
 
  604            (lexicalCastWithRangeCheck<uint8_t>(value),
 
  609            (lexicalCastWithRangeCheck<uint16_t>(value),
 
  614            (lexicalCastWithRangeCheck<uint32_t>(value),
 
  620            asiolink::IOAddress address(value);
 
  621            if (!address.isV4() && !address.isV6()) {
 
  622                isc_throw(BadDataTypeCast, 
"provided address " 
  624                          << 
" is not a valid IPv4 or IPv6 address.");
 
  631            std::string txt = value;
 
  634            boost::erase_all(txt, 
" "); 
 
  635            boost::erase_all(txt, 
"\t"); 
 
  638            size_t pos = txt.find(
"/");
 
  640            if (pos == string::npos) {
 
  641                isc_throw(BadDataTypeCast, 
"provided address/prefix " 
  643                          << 
" is not valid.");
 
  646            std::string txt_address = txt.substr(0, pos);
 
  647            isc::asiolink::IOAddress address = isc::asiolink::IOAddress(txt_address);
 
  648            if (!address.
isV6()) {
 
  649                isc_throw(BadDataTypeCast, 
"provided address " 
  651                          << 
" is not a valid IPv4 or IPv6 address.");
 
  654            std::string txt_prefix = txt.substr(pos + 1);
 
  658                len = lexicalCastWithRangeCheck<uint8_t>(txt_prefix);
 
  660                isc_throw(BadDataTypeCast, 
"provided prefix " 
  662                          << 
" is not valid.");
 
  672        std::string txt = value;
 
  675        boost::erase_all(txt, 
" "); 
 
  676        boost::erase_all(txt, 
"\t"); 
 
  679        size_t pos = txt.find(
"/");
 
  681        if (pos == string::npos) {
 
  682            isc_throw(BadDataTypeCast, 
"provided PSID value " 
  683                      << value << 
" is not valid");
 
  686        const std::string txt_psid = txt.substr(0, pos);
 
  687        const std::string txt_psid_len = txt.substr(pos + 1);
 
  690        uint8_t psid_len = 0;
 
  693            psid = lexicalCastWithRangeCheck<uint16_t>(txt_psid);
 
  695            isc_throw(BadDataTypeCast, 
"provided PSID " 
  696                      << txt_psid << 
" is not valid");
 
  700            psid_len = lexicalCastWithRangeCheck<uint8_t>(txt_psid_len);
 
  702            isc_throw(BadDataTypeCast, 
"provided PSID length " 
  703                      << txt_psid_len << 
" is not valid");
 
  733    isc_throw(isc::BadValue, 
"attempt to write invalid option data field type" 
  734              " into the option buffer: " << type);
 
  742    boost::shared_ptr<Option4AddrLst> option(
new Option4AddrLst(type, begin,
 
 
  751    boost::shared_ptr<Option6AddrLst> option(
new Option6AddrLst(type, begin,
 
 
  780    boost::shared_ptr<Option6IA> option(
new Option6IA(type, begin, end));
 
 
  790                  "input option buffer has invalid size, expected at least " 
  793    boost::shared_ptr<Option6IAAddr> option(
new Option6IAAddr(type, begin,
 
 
  804                  "input option buffer has invalid size, expected at least " 
  807    boost::shared_ptr<Option6IAPrefix> option(
new Option6IAPrefix(type, begin,
 
 
  817    boost::shared_ptr<OptionOpaqueDataTuples>
 
 
  829    boost::shared_ptr<OptionOpaqueDataTuples>
 
 
  840    const std::vector<uint8_t> 
data(begin, end);
 
  845    std::vector<uint8_t> out_buf;
 
  846    out_buf.reserve(
data.size());
 
  847    while (in_buf.getPosition() < in_buf.getLength()) {
 
  853            if (labels.getDataLength() > 0) {
 
  855                const uint8_t* label = labels.getData(&read_len);
 
  856                out_buf.insert(out_buf.end(), label, label + read_len);
 
  858        } 
catch (
const isc::Exception& ex) {
 
  861                              "invalid FQDN list content: " << ex.
what());
 
  867    return OptionPtr(
new OptionCustom(*
this, u,
 
  868                                      out_buf.begin(), out_buf.end()));
 
  875                                             bool convenient_notation)
 const {
 
  893            return (
OptionPtr(
new Option6ClientFqdn(begin, end)));
 
  908            return (
OptionPtr(
new Option6StatusCode(begin, end)));
 
  918            return (
OptionPtr(
new Option6PDExclude(begin, end)));
 
  921            return (
OptionPtr(
new Option6Dnr(begin, end, convenient_notation)));
 
  930            return (
OptionPtr(
new Option4SlpServiceScope(begin, end)));
 
  934            return (
OptionPtr(
new Option4ClientFqdn(begin, end)));
 
  937            return (
OptionPtr(
new OptionClasslessStaticRoute(begin, end, convenient_notation)));
 
  955            return (
OptionPtr(
new Option4Dnr(begin, end, convenient_notation)));
 
  961    if ((u == 
Option::V4) && haveCompressedFqdnListFormat()) {
 
  962        return (factoryFqdnList(
Option::V4, begin, end));
 
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
This is a base class for exceptions thrown from the DNS library module.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
A generic exception that is thrown if a function is called in a prohibited way.
A generic exception that is thrown if a parameter given to a method would refer to or modify out-of-r...
bool isV6() const
Convenience function to check for an IPv6 address.
Exception to be thrown when invalid option value has been specified for a particular option definitio...
LengthFieldType
Size of the length field in the tuple.
DHCPv4 Option class for handling list of IPv4 addresses.
DHCPv6 Option class for handling list of IPv6 addresses.
static const size_t OPTION6_IAADDR_LEN
length of the fixed part of the IAADDR option
Class that represents IAPREFIX option in DHCPv6.
static const size_t OPTION6_IAPREFIX_LEN
length of the fixed part of the IAPREFIX option
static const size_t OPTION6_IA_LEN
Length of IA_NA and IA_PD content.
Option with defined data fields represented as buffers that can be accessed using data field index.
Utility class for option data types.
static void writeFqdn(const std::string &fqdn, std::vector< uint8_t > &buf, const bool downcase=false)
Append FQDN into a buffer.
static void writePrefix(const PrefixLen &prefix_len, const asiolink::IOAddress &prefix, std::vector< uint8_t > &buf)
Append prefix into a buffer.
static void writeInt(const T value, std::vector< uint8_t > &buf)
Append integer or unsigned integer value to a buffer.
static const std::string & getDataTypeName(const OptionDataType data_type)
Return option data type name from the data type enumerator.
static OptionDataType getDataType(const std::string &data_type)
Return option data type from its name.
static void writeBinary(const std::string &hex_str, std::vector< uint8_t > &buf)
Append hex-encoded binary values to a buffer.
static void writeAddress(const asiolink::IOAddress &address, std::vector< uint8_t > &buf)
Append IPv4 or IPv6 address to a buffer.
static void writePsid(const PSIDLen &psid_len, const PSID &psid, std::vector< uint8_t > &buf)
Append PSID length/value into a buffer.
static void writeString(const std::string &value, std::vector< uint8_t > &buf)
Write UTF8-encoded string into a buffer.
static void writeTuple(const std::string &value, OpaqueDataTuple::LengthFieldType lengthfieldtype, std::vector< uint8_t > &buf)
Append length and string tuple to a buffer.
static OpaqueDataTuple::LengthFieldType getTupleLenFieldType(Option::Universe u)
Returns Length Field Type for a tuple.
static void writeBool(const bool value, std::vector< uint8_t > &buf)
Append boolean value into a buffer.
uint16_t getCode() const
Return option code.
static OptionPtr factoryEmpty(Option::Universe u, uint16_t type)
Empty option factory.
static OptionPtr factoryInteger(Option::Universe u, uint16_t type, const std::string &encapsulated_space, OptionBufferConstIter begin, OptionBufferConstIter end)
Factory function to create option with integer value.
static OptionPtr factoryIAPrefix6(uint16_t type, OptionBufferConstIter begin, OptionBufferConstIter end)
Factory for IAPREFIX-type of option.
static OptionPtr factoryIntegerArray(Option::Universe u, uint16_t type, OptionBufferConstIter begin, OptionBufferConstIter end)
Factory function to create option with array of integer values.
OptionDefinition(const std::string &name, const uint16_t code, const std::string &space, const std::string &type, const bool array_type=false)
Constructor.
static OptionPtr factoryAddrList6(uint16_t type, OptionBufferConstIter begin, OptionBufferConstIter end)
Factory to create option with address list.
static OptionPtr factoryAddrList4(uint16_t type, OptionBufferConstIter begin, OptionBufferConstIter end)
Factory to create option with address list.
std::vector< OptionDataType >::const_iterator RecordFieldsConstIter
Const iterator for record data fields.
OptionPtr optionFactory(Option::Universe u, uint16_t type, OptionBufferConstIter begin, OptionBufferConstIter end, bool convenient_notation=false) const
Option factory.
static OptionPtr factoryIAAddr6(uint16_t type, OptionBufferConstIter begin, OptionBufferConstIter end)
Factory for IAADDR-type of option.
void addRecordField(const std::string &data_type_name)
Adds data field to the record.
bool equals(const OptionDefinition &other) const
Check if option definition is equal to other.
const RecordFieldsCollection & getRecordFields() const
Return list of record fields.
void validate() const
Check if the option definition is valid.
std::vector< OptionDataType > RecordFieldsCollection
List of fields within the record.
static OptionPtr factoryIA6(uint16_t type, OptionBufferConstIter begin, OptionBufferConstIter end)
Factory for IA-type of option.
std::string getEncapsulatedSpace() const
Return name of the encapsulated option space.
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.
static OptionPtr factoryOpaqueDataTuples(Option::Universe u, uint16_t type, OptionBufferConstIter begin, OptionBufferConstIter end)
Factory to create option with tuple list.
bool getArrayType() const
Return array type indicator.
static OptionPtr factoryGeneric(Option::Universe u, uint16_t type, OptionBufferConstIter begin, OptionBufferConstIter end)
Factory to create generic option.
This class encapsulates a collection of data tuples and could be used by multiple options.
static bool validateName(const std::string &name)
Checks that the provided option space name is valid.
Class which represents an option carrying a single string value.
static bool lenient_parsing_
Governs whether options should be parsed less strictly.
Universe
defines option universe DHCPv4 or DHCPv6
Exception thrown during option unpacking This exception is thrown when an error has occurred,...
Exception thrown during option unpacking This exception is thrown when an error has occurred unpackin...
Light-weight Accessor to Name data.
The Name class encapsulates DNS names.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
@ DHO_CLASSLESS_STATIC_ROUTE
OptionBuffer::const_iterator OptionBufferConstIter
const_iterator for walking over OptionBuffer
OptionDataType
Data types of DHCP option fields.
boost::shared_ptr< OptionDefinition > OptionDefinitionPtr
Pointer to option definition object.
std::vector< uint8_t > OptionBuffer
buffer types used in DHCP code.
boost::shared_ptr< Option > OptionPtr
string trim(const string &input)
Trim leading and trailing spaces.
Defines the logger used by the top-level component of kea-lfc.
#define DHCP4_OPTION_SPACE
global std option spaces
#define DHCP6_OPTION_SPACE
static const bool integer_type