22 bool convenient_notation)
36 buf.
writeUint16(dnr_instance.getDnrInstanceDataLength());
39 dnr_instance.packAdn(buf);
40 if (dnr_instance.isAdnOnlyMode()) {
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) {
62 <<
"DNR instance data truncated to size "
63 << std::distance(begin, end));
76 dnr_instance.
unpackAdn(begin, dnr_instance_end);
78 if (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");
232 size_t data_length = 0;
233 const uint8_t* data = label_sequence.
getData(&data_length);
240 AddressContainer::const_iterator address =
ip_addresses_.begin();
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));
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.
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 parameter given to a method would refer to or modify out-of-r...
The IOAddress class represents an IP addresses (version agnostic)
bool isV6() const
Convenience function to check for an IPv6 address.
bool isV4() const
Convenience function to check for an IPv4 address.
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.
uint16_t getDnrInstanceDataLength() const
Getter of the dnr_instance_data_length_.
uint8_t getMinimalLength() const
Returns minimal length of the DNR instance data (without headers) 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.
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.
boost::bimap< std::string, uint16_t > SvcParamsMap
A Type defined for boost Bimap holding SvcParamKeys.
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.
const Buffer & getData() const
Returns a reference to the buffer holding tuple data.
LengthFieldType
Size of the length field in the tuple.
size_t getTotalLength() const
Returns a total size of the tuple, including length field.
void unpack(InputIterator begin, InputIterator end)
Parses wire data and creates a tuple from it.
size_t getLength() const
Returns the length of the data 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.
OptionPtr cloneInternal() const
Copies this option and returns a pointer to the copy.
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.
const uint8_t * getData(size_t *len) const
Return the wire-format data for this LabelSequence.
size_t getDataLength() const
Return the length of the wire-format data of this LabelSequence.
The Name class encapsulates DNS names.
The OutputBuffer class is a buffer abstraction for manipulating mutable data.
void writeUint8(uint8_t data)
Write an unsigned 8-bit integer into the buffer.
void writeUint16(uint16_t data)
Write an unsigned 16-bit integer in host byte order into the buffer in network byte order.
void writeData(const void *data, size_t len)
Copy an arbitrary length of data into the buffer.
void writeUint32(uint32_t data)
Write an unsigned 32-bit integer in host byte order into the buffer in network byte order.
#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.