Kea 2.5.5
option4_dnr.cc
Go to the documentation of this file.
1// Copyright (C) 2023 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#include <config.h>
8
9#include <dhcp/option4_dnr.h>
10#include <dns/labelsequence.h>
11#include <util/strutil.h>
12
13using namespace isc::asiolink;
14using namespace isc::util;
15
16namespace isc {
17namespace dhcp {
18
20 : Option(V4, DHO_V4_DNR) {
21 unpack(begin, end);
22}
23
26 return (cloneInternal<Option4Dnr>());
27}
28
29void
30Option4Dnr::pack(OutputBuffer& buf, bool check) const {
31 packHeader(buf, check);
32 for (const DnrInstance& dnr_instance : dnr_instances_) {
33 buf.writeUint16(dnr_instance.getDnrInstanceDataLength());
34 buf.writeUint16(dnr_instance.getServicePriority());
35 buf.writeUint8(dnr_instance.getAdnLength());
36 dnr_instance.packAdn(buf);
37 if (dnr_instance.isAdnOnlyMode()) {
38 continue;
39 }
40
41 buf.writeUint8(dnr_instance.getAddrLength());
42 dnr_instance.packAddresses(buf);
43 dnr_instance.packSvcParams(buf);
44 }
45}
46
47void
49 setData(begin, end);
50 while (begin != end) {
51 DnrInstance dnr_instance(V4);
52 if (std::distance(begin, end) < dnr_instance.getMinimalLength()) {
53 isc_throw(OutOfRange, dnr_instance.getLogPrefix()
54 << "DNR instance data truncated to size "
55 << std::distance(begin, end));
56 }
57
58 // Unpack DnrInstanceDataLength.
59 dnr_instance.unpackDnrInstanceDataLength(begin, end);
60
61 const OptionBufferConstIter dnr_instance_end = begin +
62 dnr_instance.getDnrInstanceDataLength();
63
64 // Unpack Service priority.
65 dnr_instance.unpackServicePriority(begin);
66
67 // Unpack ADN len + ADN.
68 dnr_instance.unpackAdn(begin, dnr_instance_end);
69
70 if (begin == dnr_instance_end) {
71 // ADN only mode, other fields are not included.
72 addDnrInstance(dnr_instance);
73 continue;
74 }
75
76 dnr_instance.setAdnOnlyMode(false);
77
78 // Unpack Addr Len + IPv4 Address(es).
79 dnr_instance.unpackAddresses(begin, dnr_instance_end);
80
81 // SvcParams (variable length) field is last.
82 dnr_instance.unpackSvcParams(begin, dnr_instance_end);
83
84 addDnrInstance(dnr_instance);
85 }
86}
87
88std::string
89Option4Dnr::toText(int indent) const {
90 std::ostringstream stream;
91 std::string in(indent, ' '); // base indentation
92 stream << in << "type=" << type_ << "(V4_DNR), "
93 << "len=" << (len() - getHeaderLen());
94 int i = 0;
95 for (const DnrInstance& dnr_instance : dnr_instances_) {
96 stream << ", DNR Instance " << ++i
97 << "(Instance len=" << dnr_instance.getDnrInstanceDataLength() << ", "
98 << dnr_instance.getDnrInstanceAsText() << ")";
99 }
100
101 return (stream.str());
102}
103
104uint16_t
106 uint16_t len = OPTION4_HDR_LEN;
107 for (const DnrInstance& dnr_instance : dnr_instances_) {
108 len += dnr_instance.getDnrInstanceDataLength() +
109 dnr_instance.getDnrInstanceDataLengthSize();
110 }
111
112 return (len);
113}
114
115void
117 dnr_instances_.push_back(dnr_instance);
118}
119
120const std::unordered_set<std::string> DnrInstance::FORBIDDEN_SVC_PARAMS = {"ipv4hint", "ipv6hint"};
121
123 : universe_(universe), dnr_instance_data_length_(0), service_priority_(0),
124 adn_length_(0), addr_length_(0), svc_params_length_(0),
125 adn_only_mode_(true), dnr_instance_data_length_size_(0),
126 adn_length_size_(0), addr_length_size_(0), minimal_length_(0) {
127 initMembers();
128}
129
131 const uint16_t service_priority,
132 const std::string& adn,
133 const DnrInstance::AddressContainer& ip_addresses,
134 const std::string& svc_params)
135 : universe_(universe), dnr_instance_data_length_(0),
136 service_priority_(service_priority), adn_length_(0),
137 addr_length_(0), ip_addresses_(ip_addresses), svc_params_length_(0),
138 adn_only_mode_(true), svc_params_(svc_params),
139 dnr_instance_data_length_size_(0), adn_length_size_(0),
140 addr_length_size_(0), minimal_length_(0) {
141 initMembers();
142 setAdn(adn);
143 checkFields();
144}
145
147 const uint16_t service_priority,
148 const std::string& adn)
149 : universe_(universe), dnr_instance_data_length_(0),
150 service_priority_(service_priority), adn_length_(0),
151 addr_length_(0), svc_params_length_(0), adn_only_mode_(true),
152 dnr_instance_data_length_size_(0), adn_length_size_(0),
153 addr_length_size_(0), minimal_length_(0) {
154 initMembers();
155 setAdn(adn);
156}
157
158void
160 if (!adn_) {
161 // This should not happen since Encrypted DNS options are designed
162 // to always include an authentication domain name.
164 << "Mandatory Authentication Domain Name fully "
165 "qualified domain-name is missing");
166 }
167
168 isc::dns::LabelSequence label_sequence(*adn_);
169 if (label_sequence.getDataLength() > 0) {
170 size_t data_length = 0;
171 const uint8_t* data = label_sequence.getData(&data_length);
172 buf.writeData(data, data_length);
173 }
174}
175
176void
178 AddressContainer::const_iterator address = ip_addresses_.begin();
179 while (address != ip_addresses_.end()) {
180 buf.writeUint32(address->toUint32());
181 ++address;
182 }
183}
184
185void
187 if (svc_params_length_ > 0) {
188 buf.writeData(&(*svc_params_.begin()), svc_params_length_);
189 }
190}
191
192std::string
194 return (adn_) ? (adn_->toText()) : ("");
195}
196
197void
198DnrInstance::setAdn(const std::string& adn) {
199 std::string trimmed_adn = str::trim(adn);
200 if (trimmed_adn.empty()) {
202 << "Mandatory Authentication Domain Name fully "
203 "qualified domain-name must not be empty");
204 }
205
206 try {
207 adn_.reset(new isc::dns::Name(trimmed_adn, true));
208 } catch (const Exception& ex) {
210 << "Failed to parse "
211 "fully qualified domain-name from string - "
212 << ex.what());
213 }
214
215 size_t adn_len = 0;
216 isc::dns::LabelSequence label_sequence(*adn_);
217 label_sequence.getData(&adn_len);
218 if (adn_len > std::numeric_limits<uint16_t>::max()) {
219 isc_throw(InvalidOptionDnrDomainName, getLogPrefix() << "Given ADN FQDN length " << adn_len
220 << " is bigger than uint_16 MAX");
221 }
222
223 adn_length_ = adn_len;
224 if (universe_ == Option::V4) {
226 }
227}
228
229void
232 OpaqueDataTuple adn_tuple(lft);
233 try {
234 adn_tuple.unpack(begin, end);
235 } catch (const Exception& ex) {
236 isc_throw(BadValue, getLogPrefix() << "failed to unpack ADN data"
237 << " - " << ex.what());
238 }
239
240 adn_length_ = adn_tuple.getLength();
241
242 // Encrypted DNS options are designed to always include an authentication domain name,
243 // so when there is no FQDN included, we shall throw an exception.
244 if (adn_length_ == 0) {
246 << "Mandatory Authentication Domain Name fully "
247 "qualified domain-name is missing");
248 }
249
250 InputBuffer name_buf(adn_tuple.getData().data(), adn_length_);
251 try {
252 adn_.reset(new isc::dns::Name(name_buf, true));
253 } catch (const Exception& ex) {
255 << "Failed to parse "
256 "fully qualified domain-name from wire format "
257 "- " << ex.what());
258 }
259
260 begin += adn_length_ + getAdnLengthSize();
261}
262
263void
264DnrInstance::checkSvcParams(bool from_wire_data) {
265 std::string svc_params = str::trim(svc_params_);
266 if (svc_params.empty()) {
268 << "Provided Svc Params field is empty");
269 }
270
271 if (!from_wire_data) {
272 // If Service Params field was not parsed from on-wire data,
273 // but actually was provided with ctor, let's calculate svc_params_length_.
274 auto svc_params_len = svc_params.length();
275 if (svc_params_len > std::numeric_limits<uint16_t>::max()) {
277 << "Given Svc Params length " << svc_params_len
278 << " is bigger than uint_16 MAX");
279 }
280
281 svc_params_length_ = svc_params_len;
282 // If Service Params field was not parsed from on-wire data,
283 // but actually was provided with ctor, let's replace it with trimmed value.
284 svc_params_ = svc_params;
285 }
286
287 // SvcParams are a whitespace-separated list, with each SvcParam
288 // consisting of a SvcParamKey=SvcParamValue pair or a standalone SvcParamKey.
289 // SvcParams in presentation format MAY appear in any order, but keys MUST NOT be repeated.
290
291 // Let's put all elements of a whitespace-separated list into a vector.
292 std::vector<std::string> tokens = str::tokens(svc_params, " ");
293
294 // Set of keys used to check if a key is not repeated.
295 std::unordered_set<std::string> keys;
296 // String sanitizer is used to check keys syntax.
297 str::StringSanitizerPtr sanitizer;
298 // SvcParamKeys are lower-case alphanumeric strings. Key names
299 // contain 1-63 characters from the ranges "a"-"z", "0"-"9", and "-".
300 std::string regex = "[^a-z0-9-]";
301 sanitizer.reset(new str::StringSanitizer(regex, ""));
302
303 // Now let's check each SvcParamKey=SvcParamValue pair.
304 for (const std::string& token : tokens) {
305 std::vector<std::string> key_val = str::tokens(token, "=");
306 if (key_val.size() > 2) {
308 getLogPrefix() << "Wrong Svc Params syntax - more than one "
309 "equals sign found in SvcParamKey=SvcParamValue pair");
310 }
311
312 // SvcParam Key related checks come below.
313 std::string key = key_val[0];
314 if (key.length() > 63) {
316 getLogPrefix() << "Wrong Svc Params syntax - key had more than 63 "
317 "characters - " << key);
318 }
319
320 if (FORBIDDEN_SVC_PARAMS.find(key) != FORBIDDEN_SVC_PARAMS.end()) {
321 isc_throw(InvalidOptionDnrSvcParams, getLogPrefix() << "Wrong Svc Params syntax - key "
322 << key << " must not be used");
323 }
324
325 auto insert_res = keys.insert(key);
326 if (!insert_res.second) {
327 isc_throw(InvalidOptionDnrSvcParams, getLogPrefix() << "Wrong Svc Params syntax - key "
328 << key << " was duplicated");
329 }
330
331 std::string sanitized_key = sanitizer->scrub(key);
332 if (sanitized_key.size() < key.size()) {
335 << "Wrong Svc Params syntax - invalid character used in key - " << key);
336 }
337 }
338}
339
340void
342 if (svc_params_.empty() && ip_addresses_.empty()) {
343 // ADN only mode, nothing more to do.
344 return;
345 }
346
347 if (!svc_params_.empty() && ip_addresses_.empty()) {
348 // As per draft-ietf-add-dnr 3.1.8:
349 // If additional data is supplied (i.e. not ADN only mode),
350 // the option includes at least one valid IP address.
351 isc_throw(OutOfRange, getLogPrefix() << "No IP address given. Since this is not ADN only "
352 "mode, at least one valid IP address must "
353 "be included");
354 }
355
356 if (!svc_params_.empty()) {
357 checkSvcParams(false);
358 }
359
360 adn_only_mode_ = false;
361 const uint8_t addr_field_len = (universe_ == Option::V4) ? V4ADDRESS_LEN : V6ADDRESS_LEN;
362 const uint16_t max_addr_len = (universe_ == Option::V4) ? std::numeric_limits<uint8_t>::max() :
363 std::numeric_limits<uint16_t>::max();
364 auto addr_len = ip_addresses_.size() * addr_field_len;
365 if (addr_len > max_addr_len) {
366 isc_throw(OutOfRange, getLogPrefix() << "Given IP addresses length " << addr_len
367 << " is bigger than MAX " << max_addr_len);
368 }
369
370 addr_length_ = addr_len;
371 if (universe_ == Option::V4) {
373 }
374}
375
376std::string
378 std::ostringstream stream;
379 stream << "service_priority=" << service_priority_ << ", adn_length=" << adn_length_ << ", "
380 << "adn='" << getAdnAsText() << "'";
381 if (!adn_only_mode_) {
382 stream << ", addr_length=" << addr_length_ << ", address(es):";
383 for (const auto& address : ip_addresses_) {
384 stream << " " << address.toText();
385 }
386
387 if (svc_params_length_ > 0) {
388 stream << ", svc_params='" + svc_params_ + "'";
389 }
390 }
391
392 return (stream.str());
393}
394
395uint16_t
398 if (!adn_only_mode_) {
400 }
401
402 return (len);
403}
404
405void
407 ip_addresses_.push_back(ip_address);
408}
409
410void
414 if (std::distance(begin, end) < dnr_instance_data_length_) {
416 << "DNR instance data truncated to size "
417 << std::distance(begin, end) << " but it was supposed to be "
419 }
420}
421
422void
425 begin += SERVICE_PRIORITY_SIZE;
426}
427
428void
431 try {
432 addr_tuple.unpack(begin, end);
433 } catch (const Exception& ex) {
434 isc_throw(BadValue, getLogPrefix() << "failed to unpack IP Addresses data"
435 << " - " << ex.what());
436 }
437
438 addr_length_ = addr_tuple.getLength();
439 // It MUST be a multiple of 4.
440 if ((addr_length_ % V4ADDRESS_LEN) != 0) {
442 << "Addr Len=" << addr_length_ << " is not divisible by 4");
443 }
444
445 // As per draft-ietf-add-dnr 3.1.8:
446 // If additional data is supplied (i.e. not ADN only mode),
447 // the option includes at least one valid IP address.
448 if (addr_length_ == 0) {
450 << "Addr Len=" << addr_length_
451 << " but it must contain at least one valid IP address");
452 }
453
454 begin += getAddrLengthSize();
455 OptionBufferConstIter addr_begin = begin;
456 OptionBufferConstIter addr_end = addr_begin + addr_length_;
457
458 while (addr_begin != addr_end) {
459 const uint8_t* ptr = &(*addr_begin);
460 addIpAddress(IOAddress(readUint32(ptr, std::distance(addr_begin, addr_end))));
461 addr_begin += V4ADDRESS_LEN;
462 begin += V4ADDRESS_LEN;
463 }
464}
465
466void
468 svc_params_length_ = std::distance(begin, end);
469 if (svc_params_length_ > 0) {
470 svc_params_.assign(begin, end);
472 begin += svc_params_length_;
473 }
474}
475
476void
477DnrInstance::initMembers() {
478 dnr_instance_data_length_size_ = (universe_ == Option::V6) ? 0 : 2;
479 adn_length_size_ = (universe_ == Option::V6) ? 2 : 1;
480 addr_length_size_ = (universe_ == Option::V6) ? 2 : 1;
481 minimal_length_ = dnr_instance_data_length_size_ + SERVICE_PRIORITY_SIZE + adn_length_size_;
482 log_prefix_ =
483 (universe_ == Option::V4) ?
484 ("DHCPv4 Encrypted DNS Option (" + std::to_string(DHO_V4_DNR) + ") malformed: ") :
485 ("DHCPv6 Encrypted DNS Option (" + std::to_string(D6O_V6_DNR) + ") malformed: ");
486}
487
488} // namespace dhcp
489} // namespace isc
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...
Represents DNR Instance which is used both in DHCPv4 and DHCPv6 Encrypted DNS Option.
Definition: option4_dnr.h:50
Option::Universe universe_
Either V4 or V6 Option universe.
Definition: option4_dnr.h:337
std::vector< isc::asiolink::IOAddress > AddressContainer
A Type defined for container holding IP addresses.
Definition: option4_dnr.h:53
std::string getDnrInstanceAsText() const
Returns string representation of the DNR instance.
Definition: option4_dnr.cc:377
void unpackSvcParams(OptionBufferConstIter &begin, OptionBufferConstIter end)
Unpacks Service Parameters from wire data buffer and stores it in svc_params_.
Definition: option4_dnr.cc:467
void setAdnOnlyMode(bool adn_only_mode)
Setter of the adn_only_mode_ field.
Definition: option4_dnr.h:224
uint16_t dnr_instance_data_length_
Length of all following data inside this DNR instance in octets.
Definition: option4_dnr.h:349
uint16_t getDnrInstanceDataLength() const
Getter of the dnr_instance_data_length_.
Definition: option4_dnr.h:111
uint8_t getMinimalLength() const
Returns minimal length of the DNR instance data (without headers) in octets.
Definition: option4_dnr.h:177
AddressContainer ip_addresses_
Vector container holding one or more IP addresses.
Definition: option4_dnr.h:366
uint8_t getAdnLengthSize() const
Returns size in octets of ADN Length field.
Definition: option4_dnr.h:192
void unpackDnrInstanceDataLength(OptionBufferConstIter &begin, OptionBufferConstIter end)
Unpacks DNR Instance Data Length from wire data buffer and stores it in dnr_instance_data_length_.
Definition: option4_dnr.cc:411
void packAdn(isc::util::OutputBuffer &buf) const
Writes the ADN FQDN in the wire format into a buffer.
Definition: option4_dnr.cc:159
uint16_t addr_length_
Length of included IP addresses in octets.
Definition: option4_dnr.h:358
virtual void unpackAddresses(OptionBufferConstIter &begin, OptionBufferConstIter end)
Unpacks IP address(es) from wire data and stores it/them in ip_addresses_.
Definition: option4_dnr.cc:429
uint8_t getAddrLengthSize() const
Returns size in octets of Addr Length field.
Definition: option4_dnr.h:182
uint16_t svc_params_length_
Length of Service Parameters field in octets.
Definition: option4_dnr.h:369
void unpackServicePriority(OptionBufferConstIter &begin)
Unpacks Service Priority from wire data buffer and stores it in service_priority_.
Definition: option4_dnr.cc:423
uint16_t service_priority_
The priority of this instance compared to other DNR instances.
Definition: option4_dnr.h:352
void checkSvcParams(bool from_wire_data=true)
Checks SvcParams field if encoded correctly and throws in case of issue found.
Definition: option4_dnr.cc:264
void packSvcParams(isc::util::OutputBuffer &buf) const
Writes the Service Parameters in the wire format into a buffer.
Definition: option4_dnr.cc:186
virtual void packAddresses(isc::util::OutputBuffer &buf) const
Writes the IP address(es) in the wire format into a buffer.
Definition: option4_dnr.cc:177
std::string getAdnAsText() const
Returns the Authentication domain name in the text format.
Definition: option4_dnr.cc:193
std::string getLogPrefix() const
Returns Log prefix depending on V4/V6 Option universe.
Definition: option4_dnr.h:199
static const std::unordered_set< std::string > FORBIDDEN_SVC_PARAMS
Set of forbidden SvcParams.
Definition: option4_dnr.h:63
void checkFields()
Checks IP address(es) field if data is correct and throws in case of issue found.
Definition: option4_dnr.cc:341
bool adn_only_mode_
Flag stating whether ADN only mode is used or not.
Definition: option4_dnr.h:375
void setAdn(const std::string &adn)
Sets Authentication domain name from given string.
Definition: option4_dnr.cc:198
uint16_t adn_length_
Length of the authentication-domain-name data in octets.
Definition: option4_dnr.h:355
uint16_t dnrInstanceLen() const
Calculates and returns length of DNR Instance data in octets.
Definition: option4_dnr.cc:396
void addIpAddress(const asiolink::IOAddress &ip_address)
Adds IP address to ip_addresses_ container.
Definition: option4_dnr.cc:406
void unpackAdn(OptionBufferConstIter &begin, OptionBufferConstIter end)
Unpacks the ADN from given wire data buffer and stores it in adn_ field.
Definition: option4_dnr.cc:230
static const uint8_t SERVICE_PRIORITY_SIZE
Size in octets of Service Priority field.
Definition: option4_dnr.h:56
uint8_t getDnrInstanceDataLengthSize() const
Returns size in octets of DNR Instance Data Length field.
Definition: option4_dnr.h:187
boost::shared_ptr< isc::dns::Name > adn_
Authentication domain name field of variable length.
Definition: option4_dnr.h:344
std::string svc_params_
Service Parameters (SvcParams) (variable length).
Definition: option4_dnr.h:381
DnrInstance(Option::Universe universe)
Constructor of the empty DNR Instance.
Definition: option4_dnr.cc:122
Exception thrown when invalid domain name is specified.
Definition: option4_dnr.h:23
Exception thrown when Service parameters have wrong format.
Definition: option4_dnr.h:31
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.
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.
Definition: option4_dnr.cc:25
void addDnrInstance(DnrInstance &dnr_instance)
Adds given DNR instance to Option's DNR Instance container.
Definition: option4_dnr.cc:116
std::string toText(int indent=0) const override
Returns string representation of the option.
Definition: option4_dnr.cc:89
void unpack(OptionBufferConstIter begin, OptionBufferConstIter end) override
Parses received wire data buffer.
Definition: option4_dnr.cc:48
DnrInstanceContainer dnr_instances_
Container holding DNR Instances.
Definition: option4_dnr.h:517
uint16_t len() const override
Returns length of the complete option (data length + DHCPv4/DHCPv6 option header)
Definition: option4_dnr.cc:105
void pack(util::OutputBuffer &buf, bool check=true) const override
Writes option in wire-format to a buffer.
Definition: option4_dnr.cc:30
Option4Dnr()
Constructor of the empty Option.
Definition: option4_dnr.h:459
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)
Definition: option.h:590
virtual uint16_t getHeaderLen() const
Returns length of header (2 for v4, 4 for v6)
Definition: option.cc:321
Universe
defines option universe DHCPv4 or DHCPv6
Definition: option.h:83
void setData(InputIterator first, InputIterator last)
Sets content of this option from buffer.
Definition: option.h:427
void packHeader(isc::util::OutputBuffer &buf, bool check=true) const
Store option's header in a buffer.
Definition: option.cc:119
void check() const
A protected method used for option correctness.
Definition: option.cc:90
static const size_t OPTION4_HDR_LEN
length of the usual DHCPv4 option header (there are exceptions)
Definition: option.h:77
Light-weight Accessor to Name data.
Definition: labelsequence.h:35
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.
Definition: name.h:223
The InputBuffer class is a buffer abstraction for manipulating read-only data.
Definition: buffer.h:81
The OutputBuffer class is a buffer abstraction for manipulating mutable data.
Definition: buffer.h:294
void writeUint8(uint8_t data)
Write an unsigned 8-bit integer into the buffer.
Definition: buffer.h:466
void writeUint16(uint16_t data)
Write an unsigned 16-bit integer in host byte order into the buffer in network byte order.
Definition: buffer.h:490
void writeData(const void *data, size_t len)
Copy an arbitrary length of data into the buffer.
Definition: buffer.h:550
void writeUint32(uint32_t data)
Write an unsigned 32-bit integer in host byte order into the buffer in network byte order.
Definition: buffer.h:520
Implements a regular expression based string scrubber.
Definition: strutil.h:311
@ D6O_V6_DNR
Definition: dhcp6.h:159
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
@ DHO_V4_DNR
Definition: dhcp4.h:218
OptionBuffer::const_iterator OptionBufferConstIter
const_iterator for walking over OptionBuffer
Definition: option.h:30
boost::shared_ptr< Option > OptionPtr
Definition: option.h:37
boost::shared_ptr< StringSanitizer > StringSanitizerPtr
Type representing the pointer to the StringSanitizer.
Definition: strutil.h:359
string trim(const string &instring)
Trim Leading and Trailing Spaces.
Definition: strutil.cc:53
vector< string > tokens(const std::string &text, const std::string &delim, bool escape)
Split String into Tokens.
Definition: strutil.cc:77
Definition: edns.h:19
uint32_t readUint32(const void *buffer, size_t length)
Read Unsigned 32-Bit Integer from Buffer.
Definition: io_utilities.h:79
uint16_t readUint16(const void *buffer, size_t length)
Read Unsigned 16-Bit Integer from Buffer.
Definition: io_utilities.h:28
Defines the logger used by the top-level component of kea-lfc.