/usr/include/kea/dhcp/option_custom.h is in kea-dev 1.1.0-1build2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 | // Copyright (C) 2012-2016 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef OPTION_CUSTOM_H
#define OPTION_CUSTOM_H
#include <dhcp/option.h>
#include <dhcp/option_definition.h>
#include <util/io_utilities.h>
namespace isc {
namespace dhcp {
/// @brief Option with defined data fields represented as buffers that can
/// be accessed using data field index.
///
/// This class represents an option which has defined structure: data fields
/// of specific types and order. Those fields can be accessed using indexes,
/// where index 0 represents first data field within an option. The last
/// field can be accessed using index equal to 'number of fields' - 1.
/// Internally, the option data is stored as a collection of OptionBuffer
/// objects, each representing data for a particular data field. This data
/// can be converted to the actual data type using methods implemented
/// within this class. This class is used to represent those options that
/// can't be represented by any other specialized class (this excludes the
/// Option class which is generic and can be used to represent any option).
class OptionCustom : public Option {
public:
/// @brief Constructor, used for options to be sent.
///
/// This constructor creates an instance of an option with default
/// data set for all data fields. The option buffers are allocated
/// according to data size being stored in particular data fields.
/// For variable size data empty buffers are created.
///
/// @param def option definition.
/// @param u specifies universe (V4 or V6)
OptionCustom(const OptionDefinition& def, Universe u);
/// @brief Constructor, used for options to be sent.
///
/// This constructor creates an instance of an option from the whole
/// supplied buffer. This constructor is mainly used to create an
/// instances of options to be stored in outgoing DHCP packets.
/// The buffer used to create the instance of an option can be
/// created from the option data specified in server's configuration.
///
/// @param def option definition.
/// @param u specifies universe (V4 or V6).
/// @param data content of the option.
///
/// @throw OutOfRange if option buffer is truncated.
///
/// @todo list all exceptions thrown by ctor.
OptionCustom(const OptionDefinition& def, Universe u, const OptionBuffer& data);
/// @brief Constructor, used for received options.
///
/// This constructor creates an instance an option from the portion
/// of the buffer specified by iterators. This is mainly useful when
/// parsing received packets. Such packets are represented by a single
/// buffer holding option data and all sub options. Methods that are
/// parsing a packet, supply relevant portions of the packet buffer
/// to this constructor to create option instances out of it.
///
/// @param def option definition.
/// @param u specifies universe (V4 or V6).
/// @param first iterator to the first element that should be copied.
/// @param last iterator to the next element after the last one
/// to be copied.
///
/// @throw OutOfRange if option buffer is truncated.
///
/// @todo list all exceptions thrown by ctor.
OptionCustom(const OptionDefinition& def, Universe u,
OptionBufferConstIter first, OptionBufferConstIter last);
/// @brief Copies this option and returns a pointer to the copy.
virtual OptionPtr clone() const;
/// @brief Create new buffer and set its value as an IP address.
///
/// @param address IPv4 or IPv6 address to be written to
/// a buffer being created.
void addArrayDataField(const asiolink::IOAddress& address);
/// @brief Create new buffer and store boolean value in it.
///
/// @param value value to be stored in the created buffer.
void addArrayDataField(const bool value);
/// @brief Create new buffer and store integer value in it.
///
/// @param value value to be stored in the created buffer.
/// @tparam T integer type of the value being stored.
template<typename T>
void addArrayDataField(const T value) {
checkArrayType();
OptionDataType data_type = definition_.getType();
if (OptionDataTypeTraits<T>::type != data_type) {
isc_throw(isc::dhcp::InvalidDataType,
"specified data type " << data_type << " does not"
" match the data type in an option definition");
}
OptionBuffer buf;
OptionDataTypeUtil::writeInt<T>(value, buf);
buffers_.push_back(buf);
}
/// @brief Return a number of the data fields.
///
/// @return number of data fields held by the option.
uint32_t getDataFieldsNum() const { return (buffers_.size()); }
/// @brief Read a buffer as IP address.
///
/// @param index buffer index.
///
/// @return IP address read from a buffer.
/// @throw isc::OutOfRange if index is out of range.
asiolink::IOAddress readAddress(const uint32_t index = 0) const;
/// @brief Write an IP address into a buffer.
///
/// @param address IP address being written.
/// @param index buffer index.
///
/// @throw isc::OutOfRange if index is out of range.
/// @throw isc::dhcp::BadDataTypeCast if IP address is invalid.
void writeAddress(const asiolink::IOAddress& address,
const uint32_t index = 0);
/// @brief Read a buffer as binary data.
///
/// @param index buffer index.
///
/// @throw isc::OutOfRange if index is out of range.
/// @return read buffer holding binary data.
const OptionBuffer& readBinary(const uint32_t index = 0) const;
/// @brief Write binary data into a buffer.
///
/// @param buf buffer holding binary data to be written.
/// @param index buffer index.
void writeBinary(const OptionBuffer& buf, const uint32_t index = 0);
/// @brief Read a buffer as boolean value.
///
/// @param index buffer index.
///
/// @throw isc::OutOfRange if index is out of range.
/// @return read boolean value.
bool readBoolean(const uint32_t index = 0) const;
/// @brief Write a boolean value into a buffer.
///
/// @param value boolean value to be written.
/// @param index buffer index.
///
/// @throw isc::OutOfRange if index is out of range.
void writeBoolean(const bool value, const uint32_t index = 0);
/// @brief Read a buffer as FQDN.
///
/// @param index buffer index.
///
/// @throw isc::OutOfRange if buffer index is out of range.
/// @throw isc::dhcp::BadDataTypeCast if a buffer being read
/// does not hold a valid FQDN.
/// @return string representation if FQDN.
std::string readFqdn(const uint32_t index = 0) const;
/// @brief Write an FQDN into a buffer.
///
/// @param fqdn text representation of FQDN.
/// @param index buffer index.
///
/// @throw isc::OutOfRange if index is out of range.
void writeFqdn(const std::string& fqdn, const uint32_t index = 0);
/// @brief Read a buffer as integer value.
///
/// @param index buffer index.
/// @tparam integer type of a value being returned.
///
/// @throw isc::OutOfRange if index is out of range.
/// @throw isc::dhcp::InvalidDataType if T is invalid.
/// @return read integer value.
template<typename T>
T readInteger(const uint32_t index = 0) const {
// Check that the index is not out of range.
checkIndex(index);
// Check that T points to a valid integer type and this type
// is consistent with an option definition.
checkDataType<T>(index);
// When we created the buffer we have checked that it has a
// valid size so this condition here should be always fulfilled.
assert(buffers_[index].size() == OptionDataTypeTraits<T>::len);
// Read an integer value.
return (OptionDataTypeUtil::readInt<T>(buffers_[index]));
}
/// @brief Write an integer value into a buffer.
///
/// @param value integer value to be written.
/// @param index buffer index.
/// @tparam T integer type of a value being written.
///
/// @throw isc::OutOfRange if index is out of range.
/// @throw isc::dhcp::InvalidDataType if T is invalid.
template<typename T>
void writeInteger(const T value, const uint32_t index = 0) {
// Check that the index is not out of range.
checkIndex(index);
// Check that T points to a valid integer type and this type
// is consistent with an option definition.
checkDataType<T>(index);
// Get some temporary buffer.
OptionBuffer buf;
// Try to write to the buffer.
OptionDataTypeUtil::writeInt<T>(value, buf);
// If successful, replace the old buffer with new one.
std::swap(buffers_[index], buf);
}
/// @brief Read a buffer as string value.
///
/// @param index buffer index.
///
/// @return string value read from buffer.
/// @throw isc::OutOfRange if index is out of range.
std::string readString(const uint32_t index = 0) const;
/// @brief Write a string value into a buffer.
///
/// @param text the string value to be written.
/// @param index buffer index.
void writeString(const std::string& text,
const uint32_t index = 0);
/// @brief Writes DHCP option in a wire format to a buffer.
///
/// @param buf output buffer (option will be stored there).
virtual void pack(isc::util::OutputBuffer& buf) const;
/// @brief Parses received buffer.
///
/// @param begin iterator to first byte of option data
/// @param end iterator to end of option data (first byte after option end)
virtual void unpack(OptionBufferConstIter begin,
OptionBufferConstIter end);
/// @brief Returns string representation of the option.
///
/// @param indent number of spaces before printed text.
///
/// @return string with text representation.
virtual std::string toText(int indent = 0) const;
/// @brief Returns length of the complete option (data length +
/// DHCPv4/DHCPv6 option header)
///
/// @return length of the option
virtual uint16_t len() const;
/// @brief Sets content of this option from buffer.
///
/// Option will be resized to length of buffer.
///
/// @param first iterator pointing to beginning of buffer to copy.
/// @param last iterator pointing to end of buffer to copy.
void initialize(const OptionBufferConstIter first,
const OptionBufferConstIter last);
private:
/// @brief Verify that the option comprises an array of values.
///
/// This helper function is used by createArrayEntry functions
/// and throws an exception if the particular option is not
/// an array.
///
/// @throw isc::InvalidOperation if option is not an array.
inline void checkArrayType() const {
if (!definition_.getArrayType()) {
isc_throw(InvalidOperation, "failed to add new array entry to an"
<< " option. The option is not an array.");
}
}
/// @brief Verify that the integer type is consistent with option
/// field type.
///
/// This convenience function checks that the data type specified as T
/// is consistent with a type of a data field identified by index.
///
/// @param index data field index.
/// @tparam data type to be validated.
///
/// @throw isc::dhcp::InvalidDataType if the type is invalid.
template<typename T>
// cppcheck-suppress unusedPrivateFunction
void checkDataType(const uint32_t index) const;
/// @brief Check if data field index is valid.
///
/// @param index Data field index to check.
///
/// @throw isc::OutOfRange if index is out of range.
void checkIndex(const uint32_t index) const;
/// @brief Create a collection of non initialized buffers.
void createBuffers();
/// @brief Create collection of buffers representing data field values.
///
/// @param data_buf a buffer to be parsed.
void createBuffers(const OptionBuffer& data_buf);
/// @brief Return a text representation of a data field.
///
/// @param data_type data type of a field.
/// @param index data field buffer index within a custom option.
///
/// @return text representation of a data field.
std::string dataFieldToText(const OptionDataType data_type,
const uint32_t index) const;
/// Make this function private as we don't want it to be invoked
/// on OptionCustom object. We rather want that initialize to
/// be called instead.
using Option::setData;
/// Option definition used to create an option.
OptionDefinition definition_;
/// The collection of buffers holding data for option fields.
/// The order of buffers corresponds to the order of option
/// fields.
std::vector<OptionBuffer> buffers_;
};
/// A pointer to the OptionCustom object.
typedef boost::shared_ptr<OptionCustom> OptionCustomPtr;
template<typename T>
void
OptionCustom::checkDataType(const uint32_t index) const {
// Check that the requested return type is a supported integer.
if (!OptionDataTypeTraits<T>::integer_type) {
isc_throw(isc::dhcp::InvalidDataType, "specified data type"
" is not a supported integer type.");
}
// Get the option definition type.
OptionDataType data_type = definition_.getType();
if (data_type == OPT_RECORD_TYPE) {
const OptionDefinition::RecordFieldsCollection& record_fields =
definition_.getRecordFields();
// When we initialized buffers we have already checked that
// the number of these buffers is equal to number of option
// fields in the record so the condition below should be met.
assert(index < record_fields.size());
// Get the data type to be returned.
data_type = record_fields[index];
}
if (OptionDataTypeTraits<T>::type != data_type) {
isc_throw(isc::dhcp::InvalidDataType,
"specified data type " << data_type << " does not"
" match the data type in an option definition for field"
" index " << index);
}
}
} // namespace isc::dhcp
} // namespace isc
#endif // OPTION_CUSTOM_H
|