22 OptionDataTypeUtil::OptionDataTypeUtil() {
66 OptionDataTypeUtil::getDataType(
const std::string& data_type) {
67 return (OptionDataTypeUtil::instance().getDataTypeImpl(data_type));
71 OptionDataTypeUtil::getDataTypeImpl(
const std::string& data_type)
const {
72 std::map<std::string, OptionDataType>::const_iterator data_type_it =
73 data_types_.find(data_type);
74 if (data_type_it != data_types_.end()) {
75 return (data_type_it->second);
97 return (asiolink::V4ADDRESS_LEN);
100 return (asiolink::V6ADDRESS_LEN);
113 return (OptionDataTypeUtil::instance().getDataTypeNameImpl(data_type));
117 OptionDataTypeUtil::getDataTypeNameImpl(
const OptionDataType data_type)
const {
118 std::map<OptionDataType, std::string>::const_iterator data_type_it =
119 data_type_names_.find(data_type);
120 if (data_type_it != data_type_names_.end()) {
121 return (data_type_it->second);
127 OptionDataTypeUtil::instance() {
128 static OptionDataTypeUtil instance;
133 OptionDataTypeUtil::readAddress(
const std::vector<uint8_t>& buf,
134 const short family) {
136 if (family == AF_INET) {
137 if (buf.size() < V4ADDRESS_LEN) {
139 <<
" IPv4 address. Invalid buffer size: " << buf.size());
142 }
else if (family == AF_INET6) {
143 if (buf.size() < V6ADDRESS_LEN) {
145 <<
" IPv6 address. Invalid buffer size: " << buf.size());
150 <<
" IP address. Invalid family: " << family);
156 std::vector<uint8_t>& buf) {
157 const std::vector<uint8_t>& vec = address.
toBytes();
158 buf.insert(buf.end(), vec.begin(), vec.end());
162 OptionDataTypeUtil::writeBinary(
const std::string& hex_str,
163 std::vector<uint8_t>& buf) {
172 <<
" to binary data type: " << ex.
what());
176 buf.insert(buf.end(), binary.begin(), binary.end());
180 OptionDataTypeUtil::readTuple(
const std::vector<uint8_t>& buf,
182 if (lengthfieldtype == OpaqueDataTuple::LENGTH_1_BYTE) {
183 if (buf.size() < 1) {
185 <<
" tuple (length). Invalid buffer size: "
188 uint8_t len = buf[0];
189 if (buf.size() < 1 + len) {
191 <<
" tuple (length " << static_cast<unsigned>(len)
192 <<
"). Invalid buffer size: " << buf.size());
196 std::memcpy(&value[0], &buf[1], len);
198 }
else if (lengthfieldtype == OpaqueDataTuple::LENGTH_2_BYTES) {
199 if (buf.size() < 2) {
201 <<
" tuple (length). Invalid buffer size: "
205 if (buf.size() < 2 + len) {
207 <<
" tuple (length " << len
208 <<
"). Invalid buffer size: " << buf.size());
212 std::memcpy(&value[0], &buf[2], len);
216 <<
" tuple. Invalid length type field: "
217 << static_cast<unsigned>(lengthfieldtype));
222 OptionDataTypeUtil::readTuple(
const std::vector<uint8_t>& buf,
225 tuple.
unpack(buf.begin(), buf.end());
232 OptionDataTypeUtil::writeTuple(
const std::string& value,
234 std::vector<uint8_t>& buf) {
235 if (lengthfieldtype == OpaqueDataTuple::LENGTH_1_BYTE) {
236 if (value.size() > std::numeric_limits<uint8_t>::max()) {
238 << value.size() <<
" larger than "
239 << +std::numeric_limits<uint8_t>::max() <<
")");
241 buf.push_back(static_cast<uint8_t>(value.size()));
243 }
else if (lengthfieldtype == OpaqueDataTuple::LENGTH_2_BYTES) {
244 if (value.size() > std::numeric_limits<uint16_t>::max()) {
246 << value.size() <<
" larger than "
247 << std::numeric_limits<uint16_t>::max() <<
")");
249 buf.resize(buf.size() + 2);
251 &buf[buf.size() - 2], 2);
254 <<
" tuple. Invalid length type field: "
255 << static_cast<unsigned>(lengthfieldtype));
257 buf.insert(buf.end(), value.begin(), value.end());
262 std::vector<uint8_t>& buf) {
267 if (tuple.
getLength() > std::numeric_limits<uint8_t>::max()) {
270 << +std::numeric_limits<uint8_t>::max() <<
")");
272 buf.push_back(static_cast<uint8_t>(tuple.
getLength()));
275 if (tuple.
getLength() > std::numeric_limits<uint16_t>::max()) {
278 << std::numeric_limits<uint16_t>::max() <<
")");
280 buf.resize(buf.size() + 2);
282 &buf[buf.size() - 2], 2);
285 <<
" tuple. Invalid length type field: "
288 buf.insert(buf.end(), tuple.
getData().begin(), tuple.
getData().end());
292 OptionDataTypeUtil::readBool(
const std::vector<uint8_t>& buf) {
295 <<
" value. Invalid buffer size " << buf.size());
299 }
else if (buf[0] == 0) {
303 <<
" value. Invalid value " << static_cast<int>(buf[0]));
307 OptionDataTypeUtil::writeBool(
const bool value,
308 std::vector<uint8_t>& buf) {
309 buf.push_back(static_cast<uint8_t>(value ? 1 : 0));
313 OptionDataTypeUtil::readFqdn(
const std::vector<uint8_t>& buf) {
317 <<
" The buffer is empty.");
334 OptionDataTypeUtil::writeFqdn(
const std::string& fqdn,
335 std::vector<uint8_t>& buf,
342 const uint8_t* data = labels.
getData(&read_len);
343 buf.insert(buf.end(), data, data + read_len);
351 OptionDataTypeUtil::getLabelCount(
const std::string& text_name) {
357 if (text_name.empty()) {
369 OptionDataTypeUtil::readPrefix(
const std::vector<uint8_t>& buf) {
375 "a truncated buffer");
388 uint8_t prefix_len_bytes = (prefix_len.asUint8() / 8);
398 const uint8_t zero_padded_bits =
399 static_cast<uint8_t
>((8 - (prefix_len.asUint8() % 8)) % 8);
402 if (zero_padded_bits > 0) {
409 if ((buf.size() - 1) < prefix_len_bytes) {
411 << prefix_len.asUnsigned() <<
" from a truncated buffer");
420 if (buf.size() > 1) {
423 std::vector<uint8_t> prefix_buf(buf.begin() + 1, buf.end());
426 if (prefix_buf.size() < V6ADDRESS_LEN) {
427 prefix_buf.resize(V6ADDRESS_LEN);
428 if (prefix_len_bytes < prefix_buf.size()) {
431 std::fill(prefix_buf.begin() + prefix_len_bytes,
432 prefix_buf.end(), 0);
434 if (zero_padded_bits) {
438 prefix_buf.at(prefix_len_bytes - 1) =
439 (prefix_buf.at(prefix_len_bytes - 1)
449 return (std::make_pair(prefix_len, prefix));
455 }
catch (
const std::exception& ex) {
465 OptionDataTypeUtil::writePrefix(
const PrefixLen& prefix_len,
467 std::vector<uint8_t>& buf) {
469 if (!prefix.
isV6()) {
476 buf.push_back(prefix_len.
asUint8());
479 uint8_t prefix_len_bytes = prefix_len.
asUint8() / 8;
482 const uint8_t zero_padded_bits =
483 static_cast<uint8_t
>((8 - (prefix_len.
asUint8() % 8)) % 8);
486 if (zero_padded_bits > 0) {
492 std::vector<uint8_t> prefix_bytes = prefix.
toBytes();
493 buf.insert(buf.end(), prefix_bytes.begin(),
494 prefix_bytes.begin() + prefix_len_bytes);
497 if (zero_padded_bits) {
498 *buf.rbegin() = (*buf.rbegin() >> zero_padded_bits) << zero_padded_bits;
503 OptionDataTypeUtil::readPsid(
const std::vector<uint8_t>& buf) {
504 if (buf.size() < 3) {
506 <<
" Invalid buffer size " << buf.size()
507 <<
". Expected 3 bytes (PSID length and PSID value)");
511 uint8_t psid_len = buf[0];
514 if (psid_len >
sizeof(uint16_t) * 8) {
516 << static_cast<unsigned>(psid_len)
517 <<
", this value is expected to be in range of 0 to 16");
531 if ((psid_len > 0) &&
532 ((psid & static_cast<uint16_t>(static_cast<uint16_t>(0xFFFF << psid_len)
533 >> psid_len)) != 0)) {
535 <<
" for a specified PSID length "
536 << static_cast<unsigned>(psid_len));
541 if (psid_len ==
sizeof(psid) * 8) {
545 psid = psid >> (
sizeof(psid) * 8 - psid_len);
547 return (std::make_pair(
PSIDLen(psid_len),
PSID(psid)));
551 OptionDataTypeUtil::writePsid(
const PSIDLen& psid_len,
const PSID& psid,
552 std::vector<uint8_t>& buf) {
553 if (psid_len.
asUint8() >
sizeof(psid) * 8) {
556 <<
", this value is expected to be in range of 0 to 16");
560 (psid.
asUint16() > (0xFFFF >> (
sizeof(uint16_t) * 8 - psid_len.
asUint8())))) {
562 <<
" for a specified PSID length "
566 buf.resize(buf.size() + 3);
567 buf.at(buf.size() - 3) = psid_len.
asUint8();
570 &buf[buf.size() - 2], 2);
575 OptionDataTypeUtil::readString(
const std::vector<uint8_t>& buf) {
579 auto begin = buf.begin();
581 if (std::distance(begin, end) == 0) {
583 "contained only NULLs");
586 value.insert(value.end(), begin, end);
593 OptionDataTypeUtil::writeString(
const std::string& value,
594 std::vector<uint8_t>& buf) {
595 if (value.size() > 0) {
596 buf.insert(buf.end(), value.begin(), value.end());
The Name class encapsulates DNS names.
Encapsulates PSID length.
LengthFieldType getLengthFieldType() const
Returns tuple length data field type.
std::string toText(bool omit_final_dot=false) const
Convert the Name to a string.
unsigned int asUnsigned() const
Returns PSID length as unsigned int.
uint16_t asUint16() const
Returns PSID value as a number.
std::pair< PrefixLen, asiolink::IOAddress > PrefixTuple
Defines a pair of prefix length / value.
uint8_t asUint8() const
Returns PSID length as uint8_t value.
void unpack(InputIterator begin, InputIterator end)
Parses wire data and creates a tuple from it.
std::vector< uint8_t > OptionBuffer
buffer types used in DHCP code.
std::vector< uint8_t > toBytes() const
Return address as set of bytes.
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.
size_t getDataLength() const
Return the length of the wire-format data of this LabelSequence.
void decodeHex(const string &input, vector< uint8_t > &result)
Decode a text encoded in the base16 ('hex') format into the original data.
unsigned int getLabelCount() const
Returns the number of labels contained in the Name.
uint8_t asUint8() const
Returns prefix length as uint8_t value.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
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.
const uint8_t * getData(size_t *len) const
Return the wire-format data for this LabelSequence.
uint16_t readUint16(const void *buffer, size_t length)
Read Unsigned 16-Bit Integer from Buffer.
const Buffer & getData() const
Returns a reference to the buffer holding tuple data.
Represents a single instance of the opaque data preceded by length.
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.
Iterator seekTrimmed(Iterator begin, Iterator end, uint8_t trim_val)
Finds the "trimmed" end of a buffer.
Exception to be thrown when cast to the data type was unsuccessful.
The IOAddress class represents an IP addresses (version agnostic)
size_t getLength() const
Returns the length of the data in the tuple.
Encapsulates prefix length.
Light-weight Accessor to Name data.
Exception to be thrown when the operation on OpaqueDataTuple object results in an error...