21 OptionDataTypeUtil::OptionDataTypeUtil() {
65 OptionDataTypeUtil::getDataType(
const std::string& data_type) {
66 return (OptionDataTypeUtil::instance().getDataTypeImpl(data_type));
70 OptionDataTypeUtil::getDataTypeImpl(
const std::string& data_type)
const {
71 std::map<std::string, OptionDataType>::const_iterator data_type_it =
72 data_types_.find(data_type);
73 if (data_type_it != data_types_.end()) {
74 return (data_type_it->second);
96 return (asiolink::V4ADDRESS_LEN);
99 return (asiolink::V6ADDRESS_LEN);
112 return (OptionDataTypeUtil::instance().getDataTypeNameImpl(data_type));
116 OptionDataTypeUtil::getDataTypeNameImpl(
const OptionDataType data_type)
const {
117 std::map<OptionDataType, std::string>::const_iterator data_type_it =
118 data_type_names_.find(data_type);
119 if (data_type_it != data_type_names_.end()) {
120 return (data_type_it->second);
126 OptionDataTypeUtil::instance() {
127 static OptionDataTypeUtil instance;
132 OptionDataTypeUtil::readAddress(
const std::vector<uint8_t>& buf,
133 const short family) {
135 if (family == AF_INET) {
136 if (buf.size() < V4ADDRESS_LEN) {
138 <<
" IPv4 address. Invalid buffer size: " << buf.size());
141 }
else if (family == AF_INET6) {
142 if (buf.size() < V6ADDRESS_LEN) {
144 <<
" IPv6 address. Invalid buffer size: " << buf.size());
149 <<
" IP address. Invalid family: " << family);
155 std::vector<uint8_t>& buf) {
156 const std::vector<uint8_t>& vec = address.
toBytes();
157 buf.insert(buf.end(), vec.begin(), vec.end());
161 OptionDataTypeUtil::writeBinary(
const std::string& hex_str,
162 std::vector<uint8_t>& buf) {
171 <<
" to binary data type: " << ex.
what());
175 buf.insert(buf.end(), binary.begin(), binary.end());
179 OptionDataTypeUtil::readTuple(
const std::vector<uint8_t>& buf,
181 if (lengthfieldtype == OpaqueDataTuple::LENGTH_1_BYTE) {
182 if (buf.size() < 1) {
184 <<
" tuple (length). Invalid buffer size: " 187 uint8_t len = buf[0];
188 if (buf.size() < 1 + len) {
190 <<
" tuple (length " << static_cast<unsigned>(len)
191 <<
"). Invalid buffer size: " << buf.size());
195 std::memcpy(&value[0], &buf[1], len);
197 }
else if (lengthfieldtype == OpaqueDataTuple::LENGTH_2_BYTES) {
198 if (buf.size() < 2) {
200 <<
" tuple (length). Invalid buffer size: " 204 if (buf.size() < 2 + len) {
206 <<
" tuple (length " << len
207 <<
"). Invalid buffer size: " << buf.size());
211 std::memcpy(&value[0], &buf[2], len);
215 <<
" tuple. Invalid length type field: " 216 << static_cast<unsigned>(lengthfieldtype));
221 OptionDataTypeUtil::readTuple(
const std::vector<uint8_t>& buf,
224 tuple.
unpack(buf.begin(), buf.end());
231 OptionDataTypeUtil::writeTuple(
const std::string& value,
233 std::vector<uint8_t>& buf) {
234 if (lengthfieldtype == OpaqueDataTuple::LENGTH_1_BYTE) {
235 if (value.size() > std::numeric_limits<uint8_t>::max()) {
237 << value.size() <<
" larger than " 238 << std::numeric_limits<uint8_t>::max() <<
")");
240 buf.push_back(static_cast<uint8_t>(value.size()));
242 }
else if (lengthfieldtype == OpaqueDataTuple::LENGTH_2_BYTES) {
243 if (value.size() > std::numeric_limits<uint16_t>::max()) {
245 << value.size() <<
" larger than " 246 << std::numeric_limits<uint16_t>::max() <<
")");
248 buf.resize(buf.size() + 2);
250 &buf[buf.size() - 2], 2);
253 <<
" tuple. Invalid length type field: " 254 << static_cast<unsigned>(lengthfieldtype));
256 buf.insert(buf.end(), value.begin(), value.end());
261 std::vector<uint8_t>& buf) {
266 if (tuple.
getLength() > std::numeric_limits<uint8_t>::max()) {
269 << std::numeric_limits<uint8_t>::max() <<
")");
271 buf.push_back(static_cast<uint8_t>(tuple.
getLength()));
274 if (tuple.
getLength() > std::numeric_limits<uint16_t>::max()) {
277 << std::numeric_limits<uint16_t>::max() <<
")");
279 buf.resize(buf.size() + 2);
281 &buf[buf.size() - 2], 2);
284 <<
" tuple. Invalid length type field: " 287 buf.insert(buf.end(), tuple.
getData().begin(), tuple.
getData().end());
291 OptionDataTypeUtil::readBool(
const std::vector<uint8_t>& buf) {
294 <<
" value. Invalid buffer size " << buf.size());
298 }
else if (buf[0] == 0) {
302 <<
" value. Invalid value " << static_cast<int>(buf[0]));
306 OptionDataTypeUtil::writeBool(
const bool value,
307 std::vector<uint8_t>& buf) {
308 buf.push_back(static_cast<uint8_t>(value ? 1 : 0));
312 OptionDataTypeUtil::readFqdn(
const std::vector<uint8_t>& buf) {
316 <<
" The buffer is empty.");
333 OptionDataTypeUtil::writeFqdn(
const std::string& fqdn,
334 std::vector<uint8_t>& buf,
341 const uint8_t* data = labels.
getData(&read_len);
342 buf.insert(buf.end(), data, data + read_len);
350 OptionDataTypeUtil::getLabelCount(
const std::string& text_name) {
356 if (text_name.empty()) {
368 OptionDataTypeUtil::readPrefix(
const std::vector<uint8_t>& buf) {
374 "a truncated buffer");
387 uint8_t prefix_len_bytes = (prefix_len.asUint8() / 8);
397 const uint8_t zero_padded_bits =
398 static_cast<uint8_t>((8 - (prefix_len.asUint8() % 8)) % 8);
401 if (zero_padded_bits > 0) {
408 if ((buf.size() - 1) < prefix_len_bytes) {
410 << prefix_len.asUnsigned() <<
" from a truncated buffer");
419 if (buf.size() > 1) {
422 std::vector<uint8_t> prefix_buf(buf.begin() + 1, buf.end());
425 if (prefix_buf.size() < V6ADDRESS_LEN) {
426 prefix_buf.resize(V6ADDRESS_LEN);
427 if (prefix_len_bytes < prefix_buf.size()) {
430 std::fill(prefix_buf.begin() + prefix_len_bytes,
431 prefix_buf.end(), 0);
433 if (zero_padded_bits) {
437 prefix_buf.at(prefix_len_bytes - 1) =
438 (prefix_buf.at(prefix_len_bytes - 1)
448 return (std::make_pair(prefix_len, prefix));
454 }
catch (
const std::exception& ex) {
464 OptionDataTypeUtil::writePrefix(
const PrefixLen& prefix_len,
466 std::vector<uint8_t>& buf) {
468 if (!prefix.
isV6()) {
475 buf.push_back(prefix_len.
asUint8());
478 uint8_t prefix_len_bytes = prefix_len.
asUint8() / 8;
481 const uint8_t zero_padded_bits =
482 static_cast<uint8_t>((8 - (prefix_len.
asUint8() % 8)) % 8);
485 if (zero_padded_bits > 0) {
491 std::vector<uint8_t> prefix_bytes = prefix.
toBytes();
492 buf.insert(buf.end(), prefix_bytes.begin(),
493 prefix_bytes.begin() + prefix_len_bytes);
496 if (zero_padded_bits) {
497 *buf.rbegin() = (*buf.rbegin() >> zero_padded_bits) << zero_padded_bits;
502 OptionDataTypeUtil::readPsid(
const std::vector<uint8_t>& buf) {
503 if (buf.size() < 3) {
505 <<
" Invalid buffer size " << buf.size()
506 <<
". Expected 3 bytes (PSID length and PSID value)");
510 uint8_t psid_len = buf[0];
513 if (psid_len >
sizeof(uint16_t) * 8) {
515 << static_cast<unsigned>(psid_len)
516 <<
", this value is expected to be in range of 0 to 16");
530 if ((psid_len > 0) &&
531 ((psid & static_cast<uint16_t>(static_cast<uint16_t>(0xFFFF << psid_len)
532 >> psid_len)) != 0)) {
534 <<
" for a specified PSID length " 535 << static_cast<unsigned>(psid_len));
540 if (psid_len ==
sizeof(psid) * 8) {
544 psid = psid >> (
sizeof(psid) * 8 - psid_len);
546 return (std::make_pair(
PSIDLen(psid_len),
PSID(psid)));
550 OptionDataTypeUtil::writePsid(
const PSIDLen& psid_len,
const PSID& psid,
551 std::vector<uint8_t>& buf) {
552 if (psid_len.
asUint8() >
sizeof(psid) * 8) {
555 <<
", this value is expected to be in range of 0 to 16");
559 (psid.
asUint16() > (0xFFFF >> (
sizeof(uint16_t) * 8 - psid_len.
asUint8())))) {
561 <<
" for a specified PSID length " 565 buf.resize(buf.size() + 3);
566 buf.at(buf.size() - 3) = psid_len.
asUint8();
569 &buf[buf.size() - 2], 2);
574 OptionDataTypeUtil::readString(
const std::vector<uint8_t>& buf) {
577 value.insert(value.end(), buf.begin(), buf.end());
583 OptionDataTypeUtil::writeString(
const std::string& value,
584 std::vector<uint8_t>& buf) {
585 if (value.size() > 0) {
586 buf.insert(buf.end(), value.begin(), value.end());
The Name class encapsulates DNS names.
Encapsulates PSID length.
std::pair< PrefixLen, asiolink::IOAddress > PrefixTuple
Defines a pair of prefix length / value.
unsigned int getLabelCount() const
Returns the number of labels contained in the Name.
uint16_t asUint16() const
Returns PSID value as a number.
size_t getDataLength() const
Return the length of the wire-format data of this LabelSequence.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
std::vector< uint8_t > OptionBuffer
buffer types used in DHCP code.
LengthFieldType getLengthFieldType() const
Returns tuple length data field type.
uint8_t asUint8() const
Returns prefix length as uint8_t value.
static const IOAddress & IPV6_ZERO_ADDRESS()
Returns an IPv6 zero address.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
static IOAddress fromBytes(short family, const uint8_t *data)
Creates an address from over wire data.
OptionDataType
Data types of DHCP option fields.
uint8_t * writeUint16(uint16_t value, void *buffer, size_t length)
Write Unsigned 16-Bit Integer to Buffer.
const uint8_t * getData(size_t *len) const
Return the wire-format data for this LabelSequence.
void decodeHex(const string &input, vector< uint8_t > &result)
Decode a text encoded in the base16 ('hex') format into the original data.
std::vector< uint8_t > toBytes() const
Return address as set of bytes.
uint8_t asUint8() const
Returns PSID length as uint8_t value.
std::string toText(bool omit_final_dot=false) const
Convert the Name to a string.
bool isV6() const
Convenience function to check for an IPv6 address.
LengthFieldType
Size of the length field in the tuple.
std::pair< PSIDLen, PSID > PSIDTuple
Defines a pair of PSID length / value.
This is a base class for exceptions thrown from the DNS library module.
Defines the logger used by the top-level component of kea-dhcp-ddns.
uint16_t readUint16(const void *buffer, size_t length)
Read Unsigned 16-Bit Integer from Buffer.
void unpack(InputIterator begin, InputIterator end)
Parses wire data and creates a tuple from it.
const Buffer & getData() const
Returns a reference to the buffer holding tuple data.
Represents a single instance of the opaque data preceded by length.
size_t getLength() const
Returns the length of the data in the tuple.
Exception to be thrown when cast to the data type was unsuccessful.
The IOAddress class represents an IP addresses (version agnostic)
unsigned int asUnsigned() const
Returns PSID length as unsigned int.
Encapsulates prefix length.
Light-weight Accessor to Name data.
Exception to be thrown when the operation on OpaqueDataTuple object results in an error.