Kea  2.1.7-git
option_int_array.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_INT_ARRAY_H
8 #define OPTION_INT_ARRAY_H
9 
10 #include <dhcp/libdhcp++.h>
11 #include <dhcp/option.h>
12 #include <dhcp/option_data_types.h>
13 #include <util/io_utilities.h>
14 #include <boost/shared_ptr.hpp>
15 #include <sstream>
16 #include <stdint.h>
17 
18 namespace isc {
19 namespace dhcp {
20 
22 template<typename T>
23 class OptionIntArray;
24 
31 typedef boost::shared_ptr<OptionUint8Array> OptionUint8ArrayPtr;
33 typedef boost::shared_ptr<OptionUint16Array> OptionUint16ArrayPtr;
35 typedef boost::shared_ptr<OptionUint32Array> OptionUint32ArrayPtr;
37 
55 template<typename T>
56 class OptionIntArray : public Option {
57 private:
58 
60  typedef boost::shared_ptr<OptionIntArray<T> > OptionIntArrayTypePtr;
61 
62 public:
63 
73  OptionIntArray(const Option::Universe u, const uint16_t type)
74  : Option(u, type),
75  values_(0) {
77  isc_throw(dhcp::InvalidDataType, "non-integer type");
78  }
79  }
80 
91  OptionIntArray(const Option::Universe u, const uint16_t type,
92  const OptionBuffer& buf)
93  : Option(u, type) {
95  isc_throw(dhcp::InvalidDataType, "non-integer type");
96  }
97  unpack(buf.begin(), buf.end());
98  }
99 
115  OptionIntArray(const Option::Universe u, const uint16_t type,
117  : Option(u, type) {
119  isc_throw(dhcp::InvalidDataType, "non-integer type");
120  }
121  unpack(begin, end);
122  }
123 
125  virtual OptionPtr clone() const {
126  return (cloneInternal<OptionIntArray<T> >());
127  }
128 
132  void addValue(const T value) {
133  values_.push_back(value);
134  }
135 
144  virtual void pack(isc::util::OutputBuffer& buf, bool check = true) const {
145  // Pack option header.
146  packHeader(buf, check);
147  // Pack option data.
148  for (size_t i = 0; i < values_.size(); ++i) {
149  // Depending on the data type length we use different utility functions
150  // writeUint16 or writeUint32 which write the data in the network byte
151  // order to the provided buffer. The same functions can be safely used
152  // for either unsigned or signed integers so there is not need to create
153  // special cases for intX_t types.
155  case 1:
156  buf.writeUint8(values_[i]);
157  break;
158  case 2:
159  buf.writeUint16(values_[i]);
160  break;
161  case 4:
162  buf.writeUint32(values_[i]);
163  break;
164  default:
165  isc_throw(dhcp::InvalidDataType, "non-integer type");
166  }
167  }
168  // We don't pack sub-options here because we have array-type option.
169  // We don't allow sub-options in array-type options as there is no
170  // way to distinguish them from the data fields on option reception.
171  }
172 
185  if (distance(begin, end) == 0) {
186  isc_throw(OutOfRange, "option " << getType() << " empty");
187  }
188  if (distance(begin, end) % sizeof(T) != 0) {
189  isc_throw(OutOfRange, "OptionIntArray " << getType() << " truncated");
190  }
191  // @todo consider what to do if buffer is longer than data type.
192 
193  values_.clear();
194  while (begin != end) {
195  // Depending on the data type length we use different utility functions
196  // readUint16 or readUint32 which read the data laid in the network byte
197  // order from the provided buffer. The same functions can be safely used
198  // for either unsigned or signed integers so there is not need to create
199  // special cases for intX_t types.
200  int data_size_len = OptionDataTypeTraits<T>::len;
201  switch (data_size_len) {
202  case 1:
203  values_.push_back(*begin);
204  break;
205  case 2:
206  values_.push_back(isc::util::readUint16(&(*begin),
207  std::distance(begin, end)));
208  break;
209  case 4:
210  values_.push_back(isc::util::readUint32(&(*begin),
211  std::distance(begin, end)));
212  break;
213  default:
214  isc_throw(dhcp::InvalidDataType, "non-integer type");
215  }
216  // Use local variable to set a new value for this iterator.
217  // When using OptionDataTypeTraits<T>::len directly some versions
218  // of clang complain about unresolved reference to
219  // OptionDataTypeTraits structure during linking.
220  begin += data_size_len;
221  }
222  // We do not unpack sub-options here because we have array-type option.
223  // Such option have variable number of data fields, thus there is no
224  // way to assess where sub-options start.
225  }
226 
230  const std::vector<T>& getValues() const { return (values_); }
231 
235  void setValues(const std::vector<T>& values) { values_ = values; }
236 
242  virtual uint16_t len() const {
243  uint16_t length = (getUniverse() == Option::V4) ? OPTION4_HDR_LEN : OPTION6_HDR_LEN;
244  length += values_.size() * sizeof(T);
245  // length of all suboptions
246  for (OptionCollection::const_iterator it = options_.begin();
247  it != options_.end();
248  ++it) {
249  length += (*it).second->len();
250  }
251  return (length);
252  }
253 
260  virtual std::string toText(int indent = 0) const {
261  std::stringstream output;
262  output << headerToText(indent) << ":";
263 
265  for (typename std::vector<T>::const_iterator value = values_.begin();
266  value != values_.end(); ++value) {
267  output << " ";
268 
269  // For 1 byte long data types we need to cast to the integer
270  // because they are usually implemented as "char" types, in
271  // which case the character rather than number would be printed.
272  if (OptionDataTypeTraits<T>::len == 1) {
273  output << static_cast<int>(*value);
274 
275  } else {
276  output << *value;
277  }
278 
279  // Append data type.
280  output << "(" << data_type << ")";
281  }
282 
283  return (output.str());
284  }
285 
286 private:
287 
288  std::vector<T> values_;
289 };
290 
291 } // isc::dhcp namespace
292 } // isc namespace
293 
294 #endif // OPTION_INT_ARRAY_H
virtual OptionPtr clone() const
Copies this option and returns a pointer to the copy.
uint16_t getType() const
Returns option type (0-255 for DHCPv4, 0-65535 for DHCPv6)
Definition: option.h:293
static const std::string & getDataTypeName(const OptionDataType data_type)
Return option data type name from the data type enumerator.
OptionIntArray(const Option::Universe u, const uint16_t type)
Constructor.
boost::shared_ptr< OptionUint8Array > OptionUint8ArrayPtr
boost::shared_ptr< Option > OptionPtr
Definition: option.h:36
void addValue(const T value)
Adds a new value to the array.
Universe
defines option universe DHCPv4 or DHCPv6
Definition: option.h:83
void packHeader(isc::util::OutputBuffer &buf, bool check=true) const
Store option&#39;s header in a buffer.
Definition: option.cc:119
Exception to be thrown when invalid type specified as template parameter.
OptionPtr cloneInternal() const
Copies this option and returns a pointer to the copy.
Definition: option.h:497
std::vector< uint8_t > OptionBuffer
buffer types used in DHCP code.
Definition: option.h:24
static const size_t OPTION4_HDR_LEN
length of the usual DHCPv4 option header (there are exceptions)
Definition: option.h:77
OptionIntArray< uint16_t > OptionUint16Array
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
OptionIntArray< uint8_t > OptionUint8Array
std::string headerToText(const int indent=0, const std::string &type_name="") const
Returns option header in the textual format.
Definition: option.cc:288
virtual void unpack(OptionBufferConstIter begin, OptionBufferConstIter end)
Parses received buffer.
Universe getUniverse() const
returns option universe (V4 or V6)
Definition: option.h:233
virtual uint16_t len() const
returns complete length of option
Forward declaration to OptionIntArray.
virtual void pack(isc::util::OutputBuffer &buf, bool check=true) const
Writes option in wire-format to buf, returns pointer to first unused byte after stored option...
void setValues(const std::vector< T > &values)
Set option values.
OptionCollection options_
collection for storing suboptions
Definition: option.h:594
void check() const
A protected method used for option correctness.
Definition: option.cc:90
The OutputBuffer class is a buffer abstraction for manipulating mutable data.
Definition: buffer.h:294
uint32_t readUint32(const uint8_t *buffer, size_t length)
Read Unsigned 32-Bit Integer from Buffer.
Definition: io_utilities.h:79
OptionBuffer::const_iterator OptionBufferConstIter
const_iterator for walking over OptionBuffer
Definition: option.h:30
void writeUint32(uint32_t data)
Write an unsigned 32-bit integer in host byte order into the buffer in network byte order...
Definition: buffer.h:520
Defines the logger used by the top-level component of kea-lfc.
const std::vector< T > & getValues() const
Return collection of option values.
OptionIntArray(const Option::Universe u, const uint16_t type, OptionBufferConstIter begin, OptionBufferConstIter end)
Constructor.
uint16_t readUint16(const void *buffer, size_t length)
Read Unsigned 16-Bit Integer from Buffer.
Definition: io_utilities.h:28
boost::shared_ptr< OptionUint32Array > OptionUint32ArrayPtr
void writeUint8(uint8_t data)
Write an unsigned 8-bit integer into the buffer.
Definition: buffer.h:466
void writeUint16(uint16_t data)
Write an unsigned 16-bit integer in host byte order into the buffer in network byte order...
Definition: buffer.h:490
A generic exception that is thrown if a parameter given to a method would refer to or modify out-of-r...
Trait class for data types supported in DHCP option definitions.
OptionIntArray< uint32_t > OptionUint32Array
virtual std::string toText(int indent=0) const
Returns textual representation of the option.
boost::shared_ptr< OptionUint16Array > OptionUint16ArrayPtr
OptionIntArray(const Option::Universe u, const uint16_t type, const OptionBuffer &buf)
Constructor.
static const size_t OPTION6_HDR_LEN
length of any DHCPv6 option header
Definition: option.h:80