Kea  2.1.7-git
option_data_types.h
Go to the documentation of this file.
1 // Copyright (C) 2012-2021 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 
404  static void readTuple(const std::vector<uint8_t>& buf,
405  OpaqueDataTuple& tuple);
406 
412  static void writeTuple(const std::string& value,
413  OpaqueDataTuple::LengthFieldType lengthfieldtype,
414  std::vector<uint8_t>& buf);
415 
420  static void writeTuple(const OpaqueDataTuple& tuple,
421  std::vector<uint8_t>& buf);
422 
430  static bool readBool(const std::vector<uint8_t>& buf);
431 
439  static void writeBool(const bool value, std::vector<uint8_t>& buf);
440 
449  template<typename T>
450  static T readInt(const std::vector<uint8_t>& buf) {
452  isc_throw(isc::dhcp::InvalidDataType, "specified data type to be returned"
453  " by readInteger is unsupported integer type");
454  }
455 
456  if (buf.size() < OptionDataTypeTraits<T>::len) {
458  "failed to read an integer value from a buffer"
459  << " - buffer is truncated.");
460  }
461 
462  T value;
464  case 1:
465  value = *(buf.begin());
466  break;
467  case 2:
468  // Calling readUint16 works either for unsigned
469  // or signed types.
470  value = isc::util::readUint16(&(*buf.begin()), buf.size());
471  break;
472  case 4:
473  // Calling readUint32 works either for unsigned
474  // or signed types.
475  value = isc::util::readUint32(&(*buf.begin()), buf.size());
476  break;
477  default:
478  // This should not happen because we made checks on data types
479  // but it does not hurt to keep throw statement here.
481  "invalid size of the data type to be read as integer.");
482  }
483  return (value);
484  }
485 
491  template<typename T>
492  static void writeInt(const T value,
493  std::vector<uint8_t>& buf) {
495  isc_throw(InvalidDataType, "provided data type is not the supported.");
496  }
498  case 1:
499  buf.push_back(static_cast<uint8_t>(value));
500  break;
501  case 2:
502  buf.resize(buf.size() + 2);
503  isc::util::writeUint16(static_cast<uint16_t>(value), &buf[buf.size() - 2], 2);
504  break;
505  case 4:
506  buf.resize(buf.size() + 4);
507  isc::util::writeUint32(static_cast<uint32_t>(value), &buf[buf.size() - 4], 4);
508  break;
509  default:
510  // The cases above cover whole range of possible data lengths because
511  // we check at the beginning of this function that given data type is
512  // a supported integer type which can be only 1,2 or 4 bytes long.
513  ;
514  }
515  }
516 
527  static std::string readFqdn(const std::vector<uint8_t>& buf);
528 
543  static void writeFqdn(const std::string& fqdn,
544  std::vector<uint8_t>& buf,
545  const bool downcase = false);
546 
556  static unsigned int getLabelCount(const std::string& text_name);
557 
568  static PrefixTuple readPrefix(const std::vector<uint8_t>& buf);
569 
578  static void writePrefix(const PrefixLen& prefix_len,
579  const asiolink::IOAddress& prefix,
580  std::vector<uint8_t>& buf);
581 
591  static PSIDTuple readPsid(const std::vector<uint8_t>& buf);
592 
608  static void writePsid(const PSIDLen& psid_len, const PSID& psid,
609  std::vector<uint8_t>& buf);
610 
618  static std::string readString(const std::vector<uint8_t>& buf);
619 
624  static void writeString(const std::string& value,
625  std::vector<uint8_t>& buf);
626 private:
627 
630  std::map<std::string, OptionDataType> data_types_;
631 
634  std::map<OptionDataType, std::string> data_type_names_;
635 
641 
650  static OptionDataTypeUtil& instance();
651 
656  OptionDataType getDataTypeImpl(const std::string& data_type) const;
657 
662  const std::string& getDataTypeNameImpl(const OptionDataType data_type) const;
663 };
664 
665 
666 } // isc::dhcp namespace
667 } // isc namespace
668 
669 #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.