22 bool convenient_notation)
29 return (cloneInternal<Option4Dnr>());
36 buf.writeUint16(dnr_instance.getDnrInstanceDataLength());
37 buf.writeUint16(dnr_instance.getServicePriority());
38 buf.writeUint8(dnr_instance.getAdnLength());
39 dnr_instance.packAdn(buf);
40 if (dnr_instance.isAdnOnlyMode()) {
44 buf.writeUint8(dnr_instance.getAddrLength());
45 dnr_instance.packAddresses(buf);
46 dnr_instance.packSvcParams(buf);
52 if (convenient_notation_) {
54 std::string config_txt = std::string(begin, end);
55 parseConfigData(config_txt);
58 while (begin != end) {
60 if (std::distance(begin, end) < dnr_instance.getMinimalLength()) {
62 <<
"DNR instance data truncated to size "
63 << std::distance(begin, end));
67 dnr_instance.unpackDnrInstanceDataLength(begin, end);
70 dnr_instance.getDnrInstanceDataLength();
73 dnr_instance.unpackServicePriority(begin);
76 dnr_instance.unpackAdn(begin, dnr_instance_end);
78 if (begin == dnr_instance_end) {
84 dnr_instance.setAdnOnlyMode(
false);
87 dnr_instance.unpackAddresses(begin, dnr_instance_end);
90 dnr_instance.unpackSvcParams(begin, dnr_instance_end);
99 std::ostringstream stream;
100 std::string in(indent,
' ');
101 stream << in <<
"type=" <<
type_ <<
"(V4_DNR), "
105 stream <<
", DNR Instance " << ++i
106 <<
"(Instance len=" << dnr_instance.getDnrInstanceDataLength() <<
", "
107 << dnr_instance.getDnrInstanceAsText() <<
")";
110 return (stream.str());
117 len += dnr_instance.getDnrInstanceDataLength() +
118 dnr_instance.getDnrInstanceDataLengthSize();
130Option4Dnr::parseConfigData(
const std::string& config_txt) {
148 std::vector<std::string> tokens =
str::tokens(config_txt, std::string(
"|"),
true);
150 for (
auto const& txt_dnr_instance : tokens) {
152 dnr_instance.parseDnrInstanceConfigData(txt_dnr_instance);
153 dnr_instance.setDnrInstanceDataLength();
161 boost::assign::list_of<DnrInstance::SvcParamsMap::relation>
164 (
"no-default-alpn", 2)
184 "stun.nat-discovery",
213 : universe_(universe), dnr_instance_data_length_(0), service_priority_(0), adn_length_(0),
214 addr_length_(0), svc_params_length_(0), adn_only_mode_(true), alpn_http_(false),
215 dnr_instance_data_length_size_(0), adn_length_size_(0), addr_length_size_(0),
226 <<
"Mandatory Authentication Domain Name fully "
227 "qualified domain-name is missing");
231 if (label_sequence.getDataLength() > 0) {
232 size_t data_length = 0;
233 const uint8_t* data = label_sequence.getData(&data_length);
234 buf.writeData(data, data_length);
240 AddressContainer::const_iterator address =
ip_addresses_.begin();
242 buf.writeUint32(address->toUint32());
256 return (
adn_) ? (
adn_->toText()) : (
"");
264 adn_tuple.unpack(begin, end);
267 <<
" - " << ex.what());
276 <<
"Mandatory Authentication Domain Name fully "
277 "qualified domain-name is missing");
285 <<
"Failed to parse fully qualified domain-name "
286 <<
"from wire format - " << ex.what());
293DnrInstance::svcParamValAsText(
const std::pair<uint16_t, OpaqueDataTuple>& svc_param)
const {
296 std::ostringstream stream;
301 switch (svc_param.first) {
305 alpn_begin = svc_param.second.getData().begin();
306 alpn_end = svc_param.second.getData().end();
307 while (alpn_begin != alpn_end) {
309 alpn_id_tuple.unpack(alpn_begin, alpn_end);
312 <<
"Exception happened when tried to parse ALPN IDs"
313 <<
". Error: " << e.what());
322 stream << alpn_id_tuple.getText();
323 alpn_begin += alpn_id_tuple.getTotalLength();
331 ret = std::to_string(
332 readUint16(svc_param.second.getData().data(), svc_param.second.getLength()));
337 ret = svc_param.second.getText();
346 std::ostringstream stream;
350 stream <<
", addr_length=" <<
addr_length_ <<
", address(es):";
352 stream <<
" " << address.toText();
356 stream <<
", svc_params='";
359 auto const& k =
SVC_PARAMS.right.at(it.first);
366 stream << k <<
"=" << svcParamValAsText(it);
373 return (stream.str());
397 <<
"DNR instance data truncated to size "
398 << std::distance(begin, end) <<
" but it was supposed to be "
413 addr_tuple.unpack(begin, end);
416 <<
" - " << ex.what());
423 <<
"Addr Len=" <<
addr_length_ <<
" is not divisible by 4");
432 <<
" but it must contain at least one valid IP address");
439 while (addr_begin != addr_end) {
440 const uint8_t* ptr = &(*addr_begin);
442 addr_begin += V4ADDRESS_LEN;
443 begin += V4ADDRESS_LEN;
454 int prev_svc_param_key = -1;
463 while (begin != end) {
466 if (std::distance(begin, end) < 4) {
468 << std::distance(begin, end));
471 uint16_t num_svc_param_key =
readUint16(&*begin, 2);
476 auto it =
SVC_PARAMS.right.find(num_svc_param_key);
479 getLogPrefix() <<
"Wrong Svc Params syntax - key " << num_svc_param_key
480 <<
" not found in SvcParamKeys registry");
483 std::string svc_param_key = it->second;
489 <<
"Wrong Svc Params syntax - key "
490 << svc_param_key <<
" must not be used");
497 getLogPrefix() <<
"Wrong Svc Params syntax - key " << svc_param_key
498 <<
" not supported in DNR option SvcParams");
508 <<
"Wrong Svc Params syntax - key "
509 << svc_param_key <<
" is duplicated.");
513 if (num_svc_param_key <= prev_svc_param_key) {
515 getLogPrefix() <<
"Wrong Svc Params syntax - SvcParamKeys"
516 <<
" SHALL appear in increasing numeric order.");
519 prev_svc_param_key = num_svc_param_key;
524 svc_param_tuple.unpack(begin, end);
528 <<
"Wrong Svc Params syntax - failed to unpack SvcParamVal for "
529 <<
"SvcParamKey " << svc_param_key <<
". Error: " << e.what());
532 svc_params_map_.insert(std::make_pair(num_svc_param_key, svc_param_tuple));
533 begin += svc_param_tuple.getTotalLength();
539DnrInstance::initMembers() {
546 (
"DHCPv4 Encrypted DNS Option (" + std::to_string(
DHO_V4_DNR) +
") malformed: ") :
547 (
"DHCPv6 Encrypted DNS Option (" + std::to_string(
D6O_V6_DNR) +
") malformed: ");
568 std::vector<std::string> tokens =
str::tokens(config_txt, std::string(
","),
true);
570 if (tokens.size() < 2) {
572 <<
"Service Priority and ADN");
575 if (tokens.size() > 4) {
577 <<
"fields: Service Priority, ADN, resolver IP "
578 <<
"address(es) and SvcParams");
582 std::string txt_svc_priority =
str::trim(tokens[0]);
585 }
catch (
const std::exception& e) {
587 <<
"from given value: " << txt_svc_priority
588 <<
". Error: " << e.what());
592 std::string txt_adn =
str::trim(tokens[1]);
595 }
catch (
const std::exception& e) {
597 <<
"from given value: " << txt_adn
598 <<
". Error: " << e.what());
604 <<
"Mandatory Authentication Domain Name fully "
605 <<
"qualified domain-name is missing");
608 if (tokens.size() > 2) {
612 std::string txt_addresses =
str::trim(tokens[2]);
614 parseIpAddresses(txt_addresses);
617 if (tokens.size() == 4) {
619 std::string txt_svc_params =
str::trim(tokens[3]);
621 parseSvcParams(txt_svc_params);
626DnrInstance::parseIpAddresses(
const std::string& txt_addresses) {
632 std::vector<std::string> addresses =
str::tokens(txt_addresses, std::string(
" "));
633 for (
auto const& txt_addr : addresses) {
644 <<
"Cannot parse " << ip_version <<
" address "
645 <<
"from given value: " << txt_addr <<
". Error: " << e.what());
661DnrInstance::parseSvcParams(
const std::string& txt_svc_params) {
663 std::vector<std::string> svc_params_pairs =
str::tokens(txt_svc_params, std::string(
" "));
665 for (
auto const& svc_param_pair : svc_params_pairs) {
667 if (key_val_tokens.size() != 2) {
669 getLogPrefix() <<
"Wrong Svc Params syntax - SvcParamKey=SvcParamValue "
670 <<
"pair syntax must be used");
674 std::string svc_param_key =
str::trim(key_val_tokens[0]);
680 <<
"Wrong Svc Params syntax - key "
681 << svc_param_key <<
" must not be used");
686 auto svc_params_iterator =
SVC_PARAMS.left.find(svc_param_key);
687 if (svc_params_iterator ==
SVC_PARAMS.left.end()) {
689 getLogPrefix() <<
"Wrong Svc Params syntax - key " << svc_param_key
690 <<
" not found in SvcParamKeys registry");
695 uint16_t num_svc_param_key = svc_params_iterator->second;
698 getLogPrefix() <<
"Wrong Svc Params syntax - key " << svc_param_key
699 <<
" not supported in DNR option SvcParams");
709 <<
"Wrong Svc Params syntax - key "
710 << svc_param_key <<
" is duplicated.");
714 std::string svc_param_val =
str::trim(key_val_tokens[1]);
715 if (svc_param_val.empty()) {
717 getLogPrefix() <<
"Wrong Svc Params syntax - empty SvcParamValue for key "
721 switch (num_svc_param_key) {
723 parseAlpnSvcParam(svc_param_val);
726 parsePortSvcParam(svc_param_val);
729 parseDohpathSvcParam(svc_param_val);
736 <<
"Wrong Svc Params syntax - key "
737 << num_svc_param_key <<
" not supported yet.");
744 getLogPrefix() <<
"Wrong Svc Params syntax - dohpath SvcParam missing. "
745 <<
"When alpn SvcParam indicates "
746 <<
"support for HTTP, dohpath must be present.");
769 out_buf.writeUint16(it->first);
774 (it->second).pack(out_buf);
779 const uint8_t* ptr =
static_cast<const uint8_t*
>(out_buf.getData());
787DnrInstance::parseAlpnSvcParam(
const std::string& svc_param_val) {
793 std::vector<std::string> alpn_ids_tokens =
str::tokens(svc_param_val, std::string(
","));
794 for (
auto const& alpn_id : alpn_ids_tokens) {
799 getLogPrefix() <<
"Wrong Svc Params syntax - alpn-id " << alpn_id
800 <<
" not found in ALPN-IDs registry");
804 if (alpn_id[0] ==
'h') {
809 alpn_id_tuple.append(alpn_id);
810 alpn_id_tuple.pack(out_buf);
813 svc_param_val_tuple.append(out_buf.getData(), out_buf.getLength());
819DnrInstance::parsePortSvcParam(
const std::string& svc_param_val) {
826 port = boost::lexical_cast<uint16_t>(svc_param_val);
827 }
catch (
const std::exception& e) {
829 <<
"Cannot parse uint_16 integer port nr "
830 <<
"from given value: " << svc_param_val
831 <<
". Error: " << e.what());
834 out_buf.writeUint16(port);
835 svc_param_val_tuple.append(out_buf.getData(), out_buf.getLength());
841DnrInstance::parseDohpathSvcParam(
const std::string& svc_param_val) {
850 std::vector<uint8_t> utf8_encoded;
854 if (svc_param_val.find(
"{?dns}") == std::string::npos) {
856 getLogPrefix() <<
"Wrong Svc Params syntax - dohpath SvcParamValue URI"
857 <<
" Template MUST contain a 'dns' variable.");
863 svc_param_val_tuple.append(utf8_encoded.begin(), utf8_encoded.size());
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.
A generic exception that is thrown if a parameter given to a method would refer to or modify out-of-r...
The IOAddress class represents an IP addresses (version agnostic)
Represents DNR Instance which is used both in DHCPv4 and DHCPv6 Encrypted DNS Option.
Option::Universe universe_
Either V4 or V6 Option universe.
static const std::set< uint8_t > SUPPORTED_SVC_PARAMS
Ordered set of supported SvcParamKeys.
std::string getDnrInstanceAsText() const
Returns string representation of the DNR instance.
void unpackSvcParams(OptionBufferConstIter &begin, OptionBufferConstIter end)
Unpacks Service Parameters from wire data buffer and stores it in svc_params_buf_.
void setAdnOnlyMode(bool adn_only_mode)
Setter of the adn_only_mode_ field.
std::map< uint16_t, OpaqueDataTuple > svc_params_map_
Service Parameters stored in a map.
uint16_t dnr_instance_data_length_
Length of all following data inside this DNR instance in octets.
OptionBuffer svc_params_buf_
Service Parameters (SvcParams) (variable length) as on-wire data buffer.
AddressContainer ip_addresses_
Vector container holding one or more IP addresses.
uint8_t getAdnLengthSize() const
Returns size in octets of ADN Length field.
void unpackDnrInstanceDataLength(OptionBufferConstIter &begin, OptionBufferConstIter end)
Unpacks DNR Instance Data Length from wire data buffer and stores it in dnr_instance_data_length_.
void packAdn(isc::util::OutputBuffer &buf) const
Writes the ADN FQDN in the wire format into a buffer.
uint16_t addr_length_
Length of included IP addresses in octets.
virtual void unpackAddresses(OptionBufferConstIter &begin, OptionBufferConstIter end)
Unpacks IP address(es) from wire data and stores it/them in ip_addresses_.
uint8_t getAddrLengthSize() const
Returns size in octets of Addr Length field.
uint16_t svc_params_length_
Length of Service Parameters field in octets.
void parseDnrInstanceConfigData(const std::string &config_txt)
Parses a convenient notation of the option data, which may be used in config.
void unpackServicePriority(OptionBufferConstIter &begin)
Unpacks Service Priority from wire data buffer and stores it in service_priority_.
uint16_t service_priority_
The priority of this instance compared to other DNR instances.
void packSvcParams(isc::util::OutputBuffer &buf) const
Writes the Service Parameters in the wire format into a buffer.
boost::bimap< std::string, uint16_t > SvcParamsMap
A Type defined for boost Bimap holding SvcParamKeys.
virtual void packAddresses(isc::util::OutputBuffer &buf) const
Writes the IP address(es) in the wire format into a buffer.
bool alpn_http_
Indicates whether the "alpn" SvcParam contains support for HTTP.
std::string getAdnAsText() const
Returns the Authentication domain name in the text format.
std::string getLogPrefix() const
Returns Log prefix depending on V4/V6 Option universe.
static const SvcParamsMap SVC_PARAMS
Service parameters, used in DNR options in DHCPv4 and DHCPv6, but also in RA and DNS.
static const std::unordered_set< std::string > ALPN_IDS
Possible ALPN protocol IDs.
static const std::unordered_set< std::string > FORBIDDEN_SVC_PARAMS
Set of forbidden SvcParams.
bool adn_only_mode_
Flag stating whether ADN only mode is used or not.
uint16_t adn_length_
Length of the authentication-domain-name data in octets.
uint16_t dnrInstanceLen() const
Calculates and returns length of DNR Instance data in octets.
void addIpAddress(const asiolink::IOAddress &ip_address)
Adds IP address to ip_addresses_ container.
void unpackAdn(OptionBufferConstIter &begin, OptionBufferConstIter end)
Unpacks the ADN from given wire data buffer and stores it in adn_ field.
static const uint8_t SERVICE_PRIORITY_SIZE
Size in octets of Service Priority field.
uint8_t getDnrInstanceDataLengthSize() const
Returns size in octets of DNR Instance Data Length field.
boost::shared_ptr< isc::dns::Name > adn_
Authentication domain name field of variable length.
DnrInstance(Option::Universe universe)
Constructor of the empty DNR Instance.
Exception thrown when invalid domain name is specified.
Exception thrown when Service parameters have wrong format.
Represents a single instance of the opaque data preceded by length.
LengthFieldType
Size of the length field in the tuple.
OptionPtr clone() const override
Copies this option and returns a pointer to the copy.
void addDnrInstance(DnrInstance &dnr_instance)
Adds given DNR instance to Option's DNR Instance container.
std::string toText(int indent=0) const override
Returns string representation of the option.
Option4Dnr(OptionBufferConstIter begin, OptionBufferConstIter end, bool convenient_notation=false)
Constructor of the Option from on-wire data.
void unpack(OptionBufferConstIter begin, OptionBufferConstIter end) override
Parses received wire data buffer.
DnrInstanceContainer dnr_instances_
Container holding DNR Instances.
uint16_t len() const override
Returns length of the complete option (data length + DHCPv4/DHCPv6 option header)
void pack(util::OutputBuffer &buf, bool check=true) const override
Writes option in wire-format to a buffer.
static OpaqueDataTuple::LengthFieldType getTupleLenFieldType(Option::Universe u)
Returns Length Field Type for a tuple.
uint16_t type_
option type (0-255 for DHCPv4, 0-65535 for DHCPv6)
virtual uint16_t getHeaderLen() const
Returns length of header (2 for v4, 4 for v6)
Universe
defines option universe DHCPv4 or DHCPv6
void setData(InputIterator first, InputIterator last)
Sets content of this option from buffer.
void packHeader(isc::util::OutputBuffer &buf, bool check=true) const
Store option's header in a buffer.
void check() const
A protected method used for option correctness.
static const size_t OPTION4_HDR_LEN
length of the usual DHCPv4 option header (there are exceptions)
Light-weight Accessor to Name data.
The Name class encapsulates DNS names.
The OutputBuffer class is a buffer abstraction for manipulating mutable data.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
OptionBuffer::const_iterator OptionBufferConstIter
const_iterator for walking over OptionBuffer
std::vector< uint8_t > OptionBuffer
buffer types used in DHCP code.
boost::shared_ptr< Option > OptionPtr
std::vector< uint8_t > encodeUtf8(const std::string &value)
Encode value string into UTF-8.
vector< string > tokens(const string &text, const string &delim, bool escape)
Split string into tokens.
string trim(const string &input)
Trim leading and trailing spaces.
uint16_t readUint16(void const *const buffer, size_t const length)
uint16_t wrapper over readUint.
uint32_t readUint32(void const *const buffer, size_t const length)
uint32_t wrapper over readUint.
Defines the logger used by the top-level component of kea-lfc.