Kea  2.3.3-git
option_data_types.h
Go to the documentation of this file.
1 // Copyright (C) 2012-2022 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 #ifndef OPTION_DATA_TYPES_H
8 #define OPTION_DATA_TYPES_H
9 
10 #include <asiolink/io_address.h>
11 #include <dhcp/opaque_data_tuple.h>
12 #include <dhcp/option.h>
13 #include <exceptions/exceptions.h>
14 #include <util/io_utilities.h>
15 
16 #include <stdint.h>
17 #include <utility>
18 
19 namespace isc {
20 namespace dhcp {
21 
23 class InvalidDataType : public Exception {
24 public:
25  InvalidDataType(const char* file, size_t line, const char* what) :
26  isc::Exception(file, line, what) { };
27 };
28 
30 class BadDataTypeCast : public Exception {
31 public:
32  BadDataTypeCast(const char* file, size_t line, const char* what) :
33  isc::Exception(file, line, what) { };
34 };
35 
64 };
65 
68  const char* name; // option name
69  uint16_t code; // option code
70  const char* space; // option space
71  OptionDataType type; // data type
72  bool array; // is array
73  const OptionDataType* records; // record fields
74  size_t records_size; // number of fields in a record
75  const char* encapsulates; // option space encapsulated by the
76  // particular option.
77 };
78 
81  const struct OptionDefParams* optionDefParams; // parameters structure
82  const int size; // structure size
83  const char* space; // option space
84 };
85 
91 template<typename T>
93  static const bool valid = false;
94  static const int len = 0;
95  static const bool integer_type = false;
96  static const OptionDataType type = OPT_UNKNOWN_TYPE;
97 };
98 
100 template<>
102  static const bool valid = true;
103  static const int len = 0;
104  static const bool integer_type = false;
105  static const OptionDataType type = OPT_BINARY_TYPE;
106 };
107 
109 template<>
110 struct OptionDataTypeTraits<bool> {
111  static const bool valid = true;
112  static const int len = sizeof(uint8_t);
113  static const bool integer_type = false;
114  static const OptionDataType type = OPT_BOOLEAN_TYPE;
115 };
116 
118 template<>
119 struct OptionDataTypeTraits<int8_t> {
120  static const bool valid = true;
121  static const int len = 1;
122  static const bool integer_type = true;
123  static const OptionDataType type = OPT_INT8_TYPE;
124 };
125 
127 template<>
128 struct OptionDataTypeTraits<int16_t> {
129  static const bool valid = true;
130  static const int len = 2;
131  static const bool integer_type = true;
132  static const OptionDataType type = OPT_INT16_TYPE;
133 };
134 
136 template<>
137 struct OptionDataTypeTraits<int32_t> {
138  static const bool valid = true;
139  static const int len = 4;
140  static const bool integer_type = true;
141  static const OptionDataType type = OPT_INT32_TYPE;
142 };
143 
145 template<>
146 struct OptionDataTypeTraits<uint8_t> {
147  static const bool valid = true;
148  static const int len = 1;
149  static const bool integer_type = true;
150  static const OptionDataType type = OPT_UINT8_TYPE;
151 };
152 
154 template<>
155 struct OptionDataTypeTraits<uint16_t> {
156  static const bool valid = true;
157  static const int len = 2;
158  static const bool integer_type = true;
159  static const OptionDataType type = OPT_UINT16_TYPE;
160 };
161 
163 template<>
164 struct OptionDataTypeTraits<uint32_t> {
165  static const bool valid = true;
166  static const int len = 4;
167  static const bool integer_type = true;
168  static const OptionDataType type = OPT_UINT32_TYPE;
169 };
170 
172 template<>
174  static const bool valid = true;
175  // The len value is used to determine the size of the data
176  // to be written to an option buffer. IOAddress object may
177  // either represent an IPv4 or IPv6 addresses which have
178  // different lengths. Thus we can't put fixed value here.
179  // The length of a data to be written into an option buffer
180  // have to be determined in the runtime for a particular
181  // IOAddress object. Thus setting len to zero.
182  static const int len = 0;
183  static const bool integer_type = false;
185 };
186 
188 template<>
189 struct OptionDataTypeTraits<std::string> {
190  static const bool valid = true;
191  // The len value is used to determine the size of the data
192  // to be written to an option buffer. For strings this
193  // size is unknown until we actually deal with the particular
194  // string to be written. Thus setting it to zero.
195  static const int len = 0;
196  static const bool integer_type = false;
197  static const OptionDataType type = OPT_STRING_TYPE;
198 };
199 
201 class PSIDLen {
202 public:
203 
205  PSIDLen() : psid_len_(0) { }
206 
214  explicit PSIDLen(const uint8_t psid_len)
215  : psid_len_(psid_len) {
216  if (psid_len_ > sizeof(uint16_t) * 8) {
217  isc_throw(isc::OutOfRange, "invalid value "
218  << asUnsigned() << " of PSID length");
219  }
220  }
221 
223  uint8_t asUint8() const {
224  return (psid_len_);
225  }
226 
235  unsigned int asUnsigned() const {
236  return (static_cast<unsigned>(psid_len_));
237  }
238 
239 private:
240 
242  uint8_t psid_len_;
243 };
244 
246 class PSID {
247 public:
248 
250  PSID() : psid_(0) { }
251 
257  explicit PSID(const uint16_t psid)
258  : psid_(psid) {
259  }
260 
262  uint16_t asUint16() const {
263  return (psid_);
264  }
265 
266 private:
267 
269  uint16_t psid_;
270 
271 };
272 
274 typedef std::pair<PSIDLen, PSID> PSIDTuple;
275 
277 class PrefixLen {
278 public:
279 
281  PrefixLen() : prefix_len_(0) { }
282 
290  explicit PrefixLen(const uint8_t prefix_len)
291  : prefix_len_(prefix_len) {
292  }
293 
295  uint8_t asUint8() const {
296  return (prefix_len_);
297  }
298 
304  unsigned int asUnsigned() const {
305  return (static_cast<unsigned>(prefix_len_));
306  }
307 
308 private:
309 
311  uint8_t prefix_len_;
312 };
313 
315 typedef std::pair<PrefixLen, asiolink::IOAddress> PrefixTuple;
316 
329 public:
330 
335  static OptionDataType getDataType(const std::string& data_type);
336 
341  static const std::string& getDataTypeName(const OptionDataType data_type);
342 
359  static int getDataTypeLen(const OptionDataType data_type);
360 
369  static asiolink::IOAddress readAddress(const std::vector<uint8_t>& buf,
370  const short family);
371 
376  static void writeAddress(const asiolink::IOAddress& address,
377  std::vector<uint8_t>& buf);
378 
384  static void writeBinary(const std::string& hex_str,
385  std::vector<uint8_t>& buf);
386 
394  static std::string readTuple(const std::vector<uint8_t>& buf,
395  OpaqueDataTuple::LengthFieldType lengthfieldtype);
396 
403  static void readTuple(const std::vector<uint8_t>& buf,
404  OpaqueDataTuple& tuple);
405 
411  static void writeTuple(const std::string& value,
412  OpaqueDataTuple::LengthFieldType lengthfieldtype,
413  std::vector<uint8_t>& buf);
414 
419  static void writeTuple(const OpaqueDataTuple& tuple,
420  std::vector<uint8_t>& buf);
421 
429  static bool readBool(const std::vector<uint8_t>& buf);
430 
438  static void writeBool(const bool value, std::vector<uint8_t>& buf);
439 
448  template<typename T>
449  static T readInt(const std::vector<uint8_t>& buf) {
451  isc_throw(isc::dhcp::InvalidDataType, "specified data type to be returned"
452  " by readInteger is unsupported integer type");
453  }
454 
455  if (buf.size() < OptionDataTypeTraits<T>::len) {
457  "failed to read an integer value from a buffer"
458  << " - buffer is truncated.");
459  }
460 
461  T value;
463  case 1:
464  value = *(buf.begin());
465  break;
466  case 2:
467  // Calling readUint16 works either for unsigned
468  // or signed types.
469  value = isc::util::readUint16(&(*buf.begin()), buf.size());
470  break;
471  case 4:
472  // Calling readUint32 works either for unsigned
473  // or signed types.
474  value = isc::util::readUint32(&(*buf.begin()), buf.size());
475  break;
476  default:
477  // This should not happen because we made checks on data types
478  // but it does not hurt to keep throw statement here.
480  "invalid size of the data type to be read as integer.");
481  }
482  return (value);
483  }
484 
490  template<typename T>
491  static void writeInt(const T value,
492  std::vector<uint8_t>& buf) {
494  isc_throw(InvalidDataType, "provided data type is not the supported.");
495  }
497  case 1:
498  buf.push_back(static_cast<uint8_t>(value));
499  break;
500  case 2:
501  buf.resize(buf.size() + 2);
502  isc::util::writeUint16(static_cast<uint16_t>(value), &buf[buf.size() - 2], 2);
503  break;
504  case 4:
505  buf.resize(buf.size() + 4);
506  isc::util::writeUint32(static_cast<uint32_t>(value), &buf[buf.size() - 4], 4);
507  break;
508  default:
509  // The cases above cover whole range of possible data lengths because
510  // we check at the beginning of this function that given data type is
511  // a supported integer type which can be only 1,2 or 4 bytes long.
512  ;
513  }
514  }
515 
526  static std::string readFqdn(const std::vector<uint8_t>& buf);
527 
542  static void writeFqdn(const std::string& fqdn,
543  std::vector<uint8_t>& buf,
544  const bool downcase = false);
545 
555  static unsigned int getLabelCount(const std::string& text_name);
556 
567  static PrefixTuple readPrefix(const std::vector<uint8_t>& buf);
568 
577  static void writePrefix(const PrefixLen& prefix_len,
578  const asiolink::IOAddress& prefix,
579  std::vector<uint8_t>& buf);
580 
590  static PSIDTuple readPsid(const std::vector<uint8_t>& buf);
591 
607  static void writePsid(const PSIDLen& psid_len, const PSID& psid,
608  std::vector<uint8_t>& buf);
609 
617  static std::string readString(const std::vector<uint8_t>& buf);
618 
623  static void writeString(const std::string& value,
624  std::vector<uint8_t>& buf);
625 private:
626 
629  std::map<std::string, OptionDataType> data_types_;
630 
633  std::map<OptionDataType, std::string> data_type_names_;
634 
640 
649  static OptionDataTypeUtil& instance();
650 
655  OptionDataType getDataTypeImpl(const std::string& data_type) const;
656 
661  const std::string& getDataTypeNameImpl(const OptionDataType data_type) const;
662 };
663 
664 
665 } // isc::dhcp namespace
666 } // isc namespace
667 
668 #endif // OPTION_DATA_TYPES_H
Encapsulation of option definition parameters and the structure size.
PrefixLen(const uint8_t prefix_len)
Constructor.
Encapsulates PSID length.
uint8_t * writeUint32(uint32_t value, uint8_t *buffer, size_t length)
Write Unsigned 32-Bit Integer to Buffer.
Definition: io_utilities.h:136
static T readInt(const std::vector< uint8_t > &buf)
Read integer value from a buffer.
PSIDLen(const uint8_t psid_len)
Constructor.
Utility class for option data types.
InvalidDataType(const char *file, size_t line, const char *what)
PSIDLen()
Default constructor.
STL namespace.
std::pair< PrefixLen, asiolink::IOAddress > PrefixTuple
Defines a pair of prefix length / value.
Parameters being used to make up an option definition.
uint16_t asUint16() const
Returns PSID value as a number.
Exception to be thrown when invalid type specified as template parameter.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
const OptionDataType * records
std::vector< uint8_t > OptionBuffer
buffer types used in DHCP code.
Definition: option.h:24
uint8_t asUint8() const
Returns prefix length as uint8_t value.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
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.
Definition: io_utilities.h:55
Encapsulates PSID value.
uint8_t asUint8() const
Returns PSID length as uint8_t value.
PSID(const uint16_t psid)
Constructor.
PSID()
Default constructor.
uint32_t readUint32(const uint8_t *buffer, size_t length)
Read Unsigned 32-Bit Integer from Buffer.
Definition: io_utilities.h:79
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-lfc.
uint16_t readUint16(const void *buffer, size_t length)
Read Unsigned 16-Bit Integer from Buffer.
Definition: io_utilities.h:28
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...
PrefixLen()
Default constructor.
Exception to be thrown when cast to the data type was unsuccessful.
Trait class for data types supported in DHCP option definitions.
unsigned int asUnsigned() const
Returns PSID length as unsigned int.
const struct OptionDefParams * optionDefParams
Encapsulates prefix length.
static void writeInt(const T value, std::vector< uint8_t > &buf)
Append integer or unsigned integer value to a buffer.
BadDataTypeCast(const char *file, size_t line, const char *what)
unsigned int asUnsigned() const
Returns prefix length as unsigned int.