Kea  2.3.4-git
option_custom.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_CUSTOM_H
8 #define OPTION_CUSTOM_H
9 
10 #include <asiolink/io_address.h>
11 #include <dhcp/option.h>
12 #include <dhcp/option_definition.h>
13 #include <exceptions/isc_assert.h>
14 #include <util/io_utilities.h>
15 
16 namespace isc {
17 namespace dhcp {
18 
32 class OptionCustom : public Option {
33 public:
34 
44  OptionCustom(const OptionDefinition& def, Universe u);
45 
61  OptionCustom(const OptionDefinition& def, Universe u, const OptionBuffer& data);
62 
83 
85  virtual OptionPtr clone() const;
86 
91  void addArrayDataField(const asiolink::IOAddress& address);
92 
96  void addArrayDataField(const bool value);
97 
102  template<typename T>
103  void addArrayDataField(const T value) {
104  checkArrayType();
105  OptionDataType data_type = definition_.getType();
106  // Handle record last field.
107  if (data_type == OPT_RECORD_TYPE) {
108  data_type = definition_.getRecordFields().back();
109  }
110  if (OptionDataTypeTraits<T>::type != data_type) {
112  "specified data type " << data_type << " does not"
113  " match the data type in an option definition");
114  }
115 
116  OptionBuffer buf;
117  OptionDataTypeUtil::writeInt<T>(value, buf);
118  buffers_.push_back(buf);
119  }
120 
124  void addArrayDataField(const std::string& value);
125 
129  void addArrayDataField(const OpaqueDataTuple& value);
130 
135  void addArrayDataField(const PrefixLen& prefix_len,
136  const asiolink::IOAddress& prefix);
137 
142  void addArrayDataField(const PSIDLen& psid_len, const PSID& psid);
143 
147  uint32_t getDataFieldsNum() const { return (buffers_.size()); }
148 
155  asiolink::IOAddress readAddress(const uint32_t index = 0) const;
156 
164  void writeAddress(const asiolink::IOAddress& address,
165  const uint32_t index = 0);
166 
173  const OptionBuffer& readBinary(const uint32_t index = 0) const;
174 
179  void writeBinary(const OptionBuffer& buf, const uint32_t index = 0);
180 
187  std::string readTuple(const uint32_t index = 0) const;
188 
195  void readTuple(OpaqueDataTuple& tuple, const uint32_t index = 0) const;
196 
201  void writeTuple(const std::string& value, const uint32_t index = 0);
202 
207  void writeTuple(const OpaqueDataTuple& value, const uint32_t index = 0);
208 
215  bool readBoolean(const uint32_t index = 0) const;
216 
223  void writeBoolean(const bool value, const uint32_t index = 0);
224 
233  std::string readFqdn(const uint32_t index = 0) const;
234 
241  void writeFqdn(const std::string& fqdn, const uint32_t index = 0);
242 
251  template<typename T>
252  T readInteger(const uint32_t index = 0) const {
253  // Check that the index is not out of range.
254  checkIndex(index);
255  // Check that T points to a valid integer type and this type
256  // is consistent with an option definition.
257  checkDataType<T>(index);
258  // When we created the buffer we have checked that it has a
259  // valid size so this condition here should be always fulfilled.
260  isc_throw_assert(buffers_[index].size() == OptionDataTypeTraits<T>::len);
261  // Read an integer value.
262  return (OptionDataTypeUtil::readInt<T>(buffers_[index]));
263  }
264 
273  template<typename T>
274  void writeInteger(const T value, const uint32_t index = 0) {
275  // Check that the index is not out of range.
276  checkIndex(index);
277  // Check that T points to a valid integer type and this type
278  // is consistent with an option definition.
279  checkDataType<T>(index);
280  // Get some temporary buffer.
281  OptionBuffer buf;
282  // Try to write to the buffer.
283  OptionDataTypeUtil::writeInt<T>(value, buf);
284  // If successful, replace the old buffer with new one.
285  std::swap(buffers_[index], buf);
286  }
287 
294  PrefixTuple readPrefix(const uint32_t index = 0) const;
295 
303  void writePrefix(const PrefixLen& prefix_len,
304  const asiolink::IOAddress& prefix,
305  const uint32_t index = 0);
306 
313  PSIDTuple readPsid(const uint32_t index = 0) const;
314 
324  void writePsid(const PSIDLen& psid_len, const PSID& psid,
325  const uint32_t index = 0);
326 
333  std::string readString(const uint32_t index = 0) const;
334 
339  void writeString(const std::string& text,
340  const uint32_t index = 0);
341 
346  virtual void pack(isc::util::OutputBuffer& buf, bool check = true) const;
347 
352  virtual void unpack(OptionBufferConstIter begin,
354 
360  virtual std::string toText(int indent = 0) const;
361 
366  virtual uint16_t len() const;
367 
374  void initialize(const OptionBufferConstIter first,
375  const OptionBufferConstIter last);
376 
377 private:
378 
386  inline void checkArrayType() const {
387  if (!definition_.getArrayType()) {
388  isc_throw(InvalidOperation, "failed to add new array entry to an"
389  << " option. The option is not an array.");
390  }
391  }
392 
403  template<typename T>
404  // cppcheck-suppress unusedPrivateFunction
405  void checkDataType(const uint32_t index) const;
406 
412  void checkIndex(const uint32_t index) const;
413 
418  void createBuffer(OptionBuffer& buffer,
419  const OptionDataType data_type) const;
420 
422  void createBuffers();
423 
433  size_t bufferLength(const OptionDataType data_type, bool in_array,
434  OptionBuffer::const_iterator begin,
435  OptionBuffer::const_iterator end) const;
436 
440  void createBuffers(const OptionBuffer& data_buf);
441 
448  std::string dataFieldToText(const OptionDataType data_type,
449  const uint32_t index) const;
450 
454  using Option::setData;
455 
457  OptionDefinition definition_;
458 
462  std::vector<OptionBuffer> buffers_;
463 };
464 
466 typedef boost::shared_ptr<OptionCustom> OptionCustomPtr;
467 
468 template<typename T>
469 void
470 OptionCustom::checkDataType(const uint32_t index) const {
471  // Check that the requested return type is a supported integer.
473  isc_throw(isc::dhcp::InvalidDataType, "specified data type"
474  " is not a supported integer type.");
475  }
476 
477  // Get the option definition type.
478  OptionDataType data_type = definition_.getType();
479  if (data_type == OPT_RECORD_TYPE) {
480  const OptionDefinition::RecordFieldsCollection& record_fields =
481  definition_.getRecordFields();
482  if (definition_.getArrayType()) {
483  // If the array flag is set the last record field is an array.
484  if (index < record_fields.size()) {
485  // Get the data type to be returned.
486  data_type = record_fields[index];
487  } else {
488  // Get the data type to be returned from the last record field.
489  data_type = record_fields.back();
490  }
491  } else {
492  // When we initialized buffers we have already checked that
493  // the number of these buffers is equal to number of option
494  // fields in the record so the condition below should be met.
495  isc_throw_assert(index < record_fields.size());
496  // Get the data type to be returned.
497  data_type = record_fields[index];
498  }
499  }
500 
501  if (OptionDataTypeTraits<T>::type != data_type) {
503  "specified data type " << data_type << " does not"
504  " match the data type in an option definition for field"
505  " index " << index);
506  }
507 }
508 } // namespace isc::dhcp
509 } // namespace isc
510 
511 #endif // OPTION_CUSTOM_H
void writeTuple(const std::string &value, const uint32_t index=0)
Write a length and string tuple into a buffer.
void addArrayDataField(const asiolink::IOAddress &address)
Create new buffer and set its value as an IP address.
#define isc_throw_assert(expr)
Replacement for assert() that throws if the expression is false.
Definition: isc_assert.h:18
Encapsulates PSID length.
asiolink::IOAddress readAddress(const uint32_t index=0) const
Read a buffer as IP address.
Base class representing a DHCP option definition.
boost::shared_ptr< OptionCustom > OptionCustomPtr
A pointer to the OptionCustom object.
uint32_t getDataFieldsNum() const
Return a number of the data fields.
bool readBoolean(const uint32_t index=0) const
Read a buffer as boolean value.
void writeAddress(const asiolink::IOAddress &address, const uint32_t index=0)
Write an IP address into a buffer.
std::vector< OptionDataType > RecordFieldsCollection
List of fields within the record.
std::string readFqdn(const uint32_t index=0) const
Read a buffer as FQDN.
virtual void pack(isc::util::OutputBuffer &buf, bool check=true) const
Writes DHCP option in a wire format to a buffer.
OptionCustom(const OptionDefinition &def, Universe u)
Constructor, used for options to be sent.
boost::shared_ptr< Option > OptionPtr
Definition: option.h:36
Universe
defines option universe DHCPv4 or DHCPv6
Definition: option.h:83
std::pair< PrefixLen, asiolink::IOAddress > PrefixTuple
Defines a pair of prefix length / value.
Exception to be thrown when invalid type specified as template parameter.
virtual void unpack(OptionBufferConstIter begin, OptionBufferConstIter end)
Parses received buffer.
void writeBoolean(const bool value, const uint32_t index=0)
Write a boolean value into a buffer.
PSIDTuple readPsid(const uint32_t index=0) const
Read a buffer as a PSID length / value tuple.
virtual uint16_t len() const
Returns length of the complete option (data length + DHCPv4/DHCPv6 option header) ...
std::vector< uint8_t > OptionBuffer
buffer types used in DHCP code.
Definition: option.h:24
std::string readTuple(const uint32_t index=0) const
Read a buffer as length and string tuple.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
OptionDataType
Data types of DHCP option fields.
Encapsulates PSID value.
virtual OptionPtr clone() const
Copies this option and returns a pointer to the copy.
void writePsid(const PSIDLen &psid_len, const PSID &psid, const uint32_t index=0)
Write PSID length / value into a buffer.
void writePrefix(const PrefixLen &prefix_len, const asiolink::IOAddress &prefix, const uint32_t index=0)
Write prefix length and value into a buffer.
void check() const
A protected method used for option correctness.
Definition: option.cc:90
PrefixTuple readPrefix(const uint32_t index=0) const
Read a buffer as variable length prefix.
The OutputBuffer class is a buffer abstraction for manipulating mutable data.
Definition: buffer.h:294
OptionBuffer::const_iterator OptionBufferConstIter
const_iterator for walking over OptionBuffer
Definition: option.h:30
std::pair< PSIDLen, PSID > PSIDTuple
Defines a pair of PSID length / value.
Defines the logger used by the top-level component of kea-lfc.
void writeInteger(const T value, const uint32_t index=0)
Write an integer value into a buffer.
const RecordFieldsCollection & getRecordFields() const
Return list of record fields.
void writeBinary(const OptionBuffer &buf, const uint32_t index=0)
Write binary data into a buffer.
virtual std::string toText(int indent=0) const
Returns string representation of the option.
A generic exception that is thrown if a function is called in a prohibited way.
void writeFqdn(const std::string &fqdn, const uint32_t index=0)
Write an FQDN into a buffer.
Represents a single instance of the opaque data preceded by length.
T readInteger(const uint32_t index=0) const
Read a buffer as integer value.
Trait class for data types supported in DHCP option definitions.
std::string readString(const uint32_t index=0) const
Read a buffer as string value.
bool getArrayType() const
Return array type indicator.
OptionDataType getType() const
Return option data type.
Option with defined data fields represented as buffers that can be accessed using data field index...
Definition: option_custom.h:32
void setData(InputIterator first, InputIterator last)
Sets content of this option from buffer.
Definition: option.h:427
Encapsulates prefix length.
void writeString(const std::string &text, const uint32_t index=0)
Write a string value into a buffer.
void addArrayDataField(const T value)
Create new buffer and store integer value in it.
void initialize(const OptionBufferConstIter first, const OptionBufferConstIter last)
Sets content of this option from buffer.
const OptionBuffer & readBinary(const uint32_t index=0) const
Read a buffer as binary data.