Kea  1.9.9-git
option_custom.h
Go to the documentation of this file.
1 // Copyright (C) 2012-2020 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 
345  virtual void pack(isc::util::OutputBuffer& buf) const;
346 
351  virtual void unpack(OptionBufferConstIter begin,
353 
359  virtual std::string toText(int indent = 0) const;
360 
365  virtual uint16_t len() const;
366 
373  void initialize(const OptionBufferConstIter first,
374  const OptionBufferConstIter last);
375 
376 private:
377 
385  inline void checkArrayType() const {
386  if (!definition_.getArrayType()) {
387  isc_throw(InvalidOperation, "failed to add new array entry to an"
388  << " option. The option is not an array.");
389  }
390  }
391 
402  template<typename T>
403  // cppcheck-suppress unusedPrivateFunction
404  void checkDataType(const uint32_t index) const;
405 
411  void checkIndex(const uint32_t index) const;
412 
417  void createBuffer(OptionBuffer& buffer,
418  const OptionDataType data_type) const;
419 
421  void createBuffers();
422 
432  size_t bufferLength(const OptionDataType data_type, bool in_array,
433  OptionBuffer::const_iterator begin,
434  OptionBuffer::const_iterator end) const;
435 
439  void createBuffers(const OptionBuffer& data_buf);
440 
447  std::string dataFieldToText(const OptionDataType data_type,
448  const uint32_t index) const;
449 
453  using Option::setData;
454 
456  OptionDefinition definition_;
457 
461  std::vector<OptionBuffer> buffers_;
462 };
463 
465 typedef boost::shared_ptr<OptionCustom> OptionCustomPtr;
466 
467 template<typename T>
468 void
469 OptionCustom::checkDataType(const uint32_t index) const {
470  // Check that the requested return type is a supported integer.
472  isc_throw(isc::dhcp::InvalidDataType, "specified data type"
473  " is not a supported integer type.");
474  }
475 
476  // Get the option definition type.
477  OptionDataType data_type = definition_.getType();
478  if (data_type == OPT_RECORD_TYPE) {
479  const OptionDefinition::RecordFieldsCollection& record_fields =
480  definition_.getRecordFields();
481  if (definition_.getArrayType()) {
482  // If the array flag is set the last record field is an array.
483  if (index < record_fields.size()) {
484  // Get the data type to be returned.
485  data_type = record_fields[index];
486  } else {
487  // Get the data type to be returned from the last record field.
488  data_type = record_fields.back();
489  }
490  } else {
491  // When we initialized buffers we have already checked that
492  // the number of these buffers is equal to number of option
493  // fields in the record so the condition below should be met.
494  isc_throw_assert(index < record_fields.size());
495  // Get the data type to be returned.
496  data_type = record_fields[index];
497  }
498  }
499 
500  if (OptionDataTypeTraits<T>::type != data_type) {
502  "specified data type " << data_type << " does not"
503  " match the data type in an option definition for field"
504  " index " << index);
505  }
506 }
507 } // namespace isc::dhcp
508 } // namespace isc
509 
510 #endif // OPTION_CUSTOM_H
bool getArrayType() const
Return array type indicator.
void writeTuple(const std::string &value, const uint32_t index=0)
Write a length and string tuple into a buffer.
virtual void pack(isc::util::OutputBuffer &buf) const
Writes DHCP option in a wire format to 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.
Base class representing a DHCP option definition.
boost::shared_ptr< OptionCustom > OptionCustomPtr
A pointer to the OptionCustom object.
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.
virtual std::string toText(int indent=0) const
Returns string representation of the option.
asiolink::IOAddress readAddress(const uint32_t index=0) const
Read a buffer as IP address.
OptionCustom(const OptionDefinition &def, Universe u)
Constructor, used for options to be sent.
boost::shared_ptr< Option > OptionPtr
Definition: option.h:36
std::string readFqdn(const uint32_t index=0) const
Read a buffer as FQDN.
Universe
defines option universe DHCPv4 or DHCPv6
Definition: option.h:82
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.
std::string readString(const uint32_t index=0) const
Read a buffer as string value.
void writeBoolean(const bool value, const uint32_t index=0)
Write a boolean value into a buffer.
bool readBoolean(const uint32_t index=0) const
Read a buffer as boolean value.
std::vector< uint8_t > OptionBuffer
buffer types used in DHCP code.
Definition: option.h:24
#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.
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.
std::string readTuple(const uint32_t index=0) const
Read a buffer as length and string tuple.
T readInteger(const uint32_t index=0) const
Read a buffer as integer value.
virtual uint16_t len() const
Returns length of the complete option (data length + DHCPv4/DHCPv6 option header) ...
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-dhcp-ddns.
const RecordFieldsCollection & getRecordFields() const
Return list of record fields.
PSIDTuple readPsid(const uint32_t index=0) const
Read a buffer as a PSID length / value tuple.
void writeInteger(const T value, const uint32_t index=0)
Write an integer value into a buffer.
void writeBinary(const OptionBuffer &buf, const uint32_t index=0)
Write binary data into a buffer.
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.
Trait class for data types supported in DHCP option definitions.
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:408
Encapsulates prefix length.
void writeString(const std::string &text, const uint32_t index=0)
Write a string value into a buffer.
uint32_t getDataFieldsNum() const
Return a number of the data fields.
void addArrayDataField(const T value)
Create new buffer and store integer value in it.
virtual OptionPtr clone() const
Copies this option and returns a pointer to the copy.
OptionDataType getType() const
Return option data type.
const OptionBuffer & readBinary(const uint32_t index=0) const
Read a buffer as binary data.
void initialize(const OptionBufferConstIter first, const OptionBufferConstIter last)
Sets content of this option from buffer.
PrefixTuple readPrefix(const uint32_t index=0) const
Read a buffer as variable length prefix.