Commit 90615322 authored by Marcin Siodelski's avatar Marcin Siodelski
Browse files

[4497] Implemented deep copy of DHCP options.

parent ee88ec85
......@@ -53,6 +53,31 @@ Option::Option(Universe u, uint16_t type, OptionBufferConstIter first,
check();
}
Option::Option(const Option& option)
: universe_(option.universe_), type_(option.type_),
data_(option.data_), options_(),
encapsulated_space_(option.encapsulated_space_) {
option.getOptionsCopy(options_);
}
Option&
Option::operator=(const Option& rhs) {
if (&rhs != this) {
universe_ = rhs.universe_;
type_ = rhs.type_;
data_ = rhs.data_;
rhs.getOptionsCopy(options_);
encapsulated_space_ = rhs.encapsulated_space_;
}
return (*this);
}
OptionPtr
Option::clone() const {
OptionPtr option(new Option(*this));
return (option);
}
void
Option::check() const {
if ( (universe_ != V4) && (universe_ != V6) ) {
......@@ -180,6 +205,18 @@ OptionPtr Option::getOption(uint16_t opt_type) const {
return OptionPtr(); // NULL
}
void
Option::getOptionsCopy(OptionCollection& options_copy) const {
OptionCollection local_options;
for (OptionCollection::const_iterator it = options_.begin();
it != options_.end(); ++it) {
OptionPtr copy = it->second->clone();
local_options.insert(std::make_pair(it->second->getType(),
copy));
}
options_copy.swap(local_options);
}
bool Option::delOption(uint16_t opt_type) {
isc::dhcp::OptionCollection::iterator x = options_.find(opt_type);
if ( x != options_.end() ) {
......
......@@ -144,6 +144,12 @@ public:
Option(Universe u, uint16_t type, OptionBufferConstIter first,
OptionBufferConstIter last);
Option(const Option& option);
Option& operator=(const Option& rhs);
virtual OptionPtr clone() const;
/// @brief returns option universe (V4 or V6)
///
/// @return universe type
......@@ -257,6 +263,8 @@ public:
return (options_);
}
void getOptionsCopy(OptionCollection& options_copy) const;
/// Attempts to delete first suboption of requested type
///
/// @param type Type of option to be deleted.
......@@ -364,6 +372,13 @@ public:
protected:
template<typename OptionType>
OptionPtr cloneInternal() const {
boost::shared_ptr<OptionType>
option(new OptionType(*dynamic_cast<const OptionType*>(this)));
return (option);
}
/// @brief Store option's header in a buffer.
///
/// This method writes option's header into a buffer in the
......
......@@ -55,6 +55,11 @@ Option4AddrLst::Option4AddrLst(uint8_t type, const IOAddress& addr)
setAddress(addr);
}
OptionPtr
Option4AddrLst::clone() const {
return (cloneInternal<Option4AddrLst>());
}
void
Option4AddrLst::pack(isc::util::OutputBuffer& buf) const {
......
......@@ -80,6 +80,8 @@ public:
Option4AddrLst(uint8_t type, OptionBufferConstIter first,
OptionBufferConstIter last);
virtual OptionPtr clone() const;
/// @brief Writes option in a wire-format to a buffer.
///
/// Method will throw if option storing fails for some reason.
......
......@@ -346,11 +346,17 @@ Option4ClientFqdn::Option4ClientFqdn(const Option4ClientFqdn& source)
impl_(new Option4ClientFqdnImpl(*source.impl_)) {
}
OptionPtr
Option4ClientFqdn::clone() const {
return (cloneInternal<Option4ClientFqdn>());
}
Option4ClientFqdn&
// This assignment operator handles assignment to self, it uses copy
// constructor of Option4ClientFqdnImpl to copy all required values.
// cppcheck-suppress operatorEqToSelf
Option4ClientFqdn::operator=(const Option4ClientFqdn& source) {
Option::operator=(source);
Option4ClientFqdnImpl* old_impl = impl_;
impl_ = new Option4ClientFqdnImpl(*source.impl_);
delete(old_impl);
......@@ -396,6 +402,11 @@ Option4ClientFqdn::setFlag(const uint8_t flag, const bool set_flag) {
impl_->flags_ = new_flag;
}
std::pair<Option4ClientFqdn::Rcode, Option4ClientFqdn::Rcode>
Option4ClientFqdn::getRcode() const {
return (std::make_pair(impl_->rcode1_, impl_->rcode2_));
}
void
Option4ClientFqdn::setRcode(const Rcode& rcode) {
impl_->rcode1_ = rcode;
......
// Copyright (C) 2013-2015 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2013-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
......@@ -11,6 +11,7 @@
#include <dns/name.h>
#include <string>
#include <utility>
namespace isc {
namespace dhcp {
......@@ -215,9 +216,11 @@ public:
explicit Option4ClientFqdn(OptionBufferConstIter first,
OptionBufferConstIter last);
/// @brief Copy constructor
/// @brief Copy constructor
Option4ClientFqdn(const Option4ClientFqdn& source);
virtual OptionPtr clone() const;
/// @brief Destructor
virtual ~Option4ClientFqdn();
......@@ -251,6 +254,12 @@ public:
/// @brief Sets the flag field value to 0.
void resetFlags();
/// @brief Returns @c Rcode objects representing value of RCODE1 and RCODE2.
///
/// @return Pair of Rcode objects of which first is the RCODE1 and the
/// second is RCODE2.
std::pair<Rcode, Rcode> getRcode() const;
/// @brief Set Rcode value.
///
/// @param rcode An @c Rcode object representing value of RCODE1 and RCODE2.
......
......@@ -41,6 +41,11 @@ Option6AddrLst::Option6AddrLst(uint16_t type, OptionBufferConstIter begin,
unpack(begin, end);
}
OptionPtr
Option6AddrLst::clone() const {
return (cloneInternal<Option6AddrLst>());
}
void
Option6AddrLst::setAddress(const isc::asiolink::IOAddress& addr) {
if (!addr.isV6()) {
......
......@@ -45,6 +45,8 @@ public:
Option6AddrLst(uint16_t type, OptionBufferConstIter begin,
OptionBufferConstIter end);
virtual OptionPtr clone() const;
/// @brief Assembles on-wire form of this option
///
/// @param buf pointer to packet buffer
......
......@@ -293,11 +293,17 @@ Option6ClientFqdn::Option6ClientFqdn(const Option6ClientFqdn& source)
impl_(new Option6ClientFqdnImpl(*source.impl_)) {
}
OptionPtr
Option6ClientFqdn::clone() const {
return (cloneInternal<Option6ClientFqdn>());
}
Option6ClientFqdn&
// This assignment operator handles assignment to self, it uses copy
// constructor of Option6ClientFqdnImpl to copy all required values.
// cppcheck-suppress operatorEqToSelf
Option6ClientFqdn::operator=(const Option6ClientFqdn& source) {
Option::operator=(source);
Option6ClientFqdnImpl* old_impl = impl_;
impl_ = new Option6ClientFqdnImpl(*source.impl_);
delete(old_impl);
......
......@@ -137,9 +137,11 @@ public:
explicit Option6ClientFqdn(OptionBufferConstIter first,
OptionBufferConstIter last);
/// @brief Copy constructor
/// @brief Copy constructor
Option6ClientFqdn(const Option6ClientFqdn& source);
virtual OptionPtr clone() const;
/// @brief Destructor
virtual ~Option6ClientFqdn();
......
......@@ -48,6 +48,11 @@ Option6IA::Option6IA(uint16_t type, OptionBufferConstIter begin,
unpack(begin, end);
}
OptionPtr
Option6IA::clone() const {
return (cloneInternal<Option6IA>());
}
void Option6IA::pack(isc::util::OutputBuffer& buf) const {
buf.writeUint16(type_);
buf.writeUint16(len() - OPTION6_HDR_LEN);
......
......@@ -39,6 +39,8 @@ public:
Option6IA(uint16_t type, OptionBuffer::const_iterator begin,
OptionBuffer::const_iterator end);
virtual OptionPtr clone() const;
/// Writes option in wire-format to buf, returns pointer to first unused
/// byte after stored option.
///
......
......@@ -42,6 +42,11 @@ Option6IAAddr::Option6IAAddr(uint32_t type, OptionBuffer::const_iterator begin,
unpack(begin, end);
}
OptionPtr
Option6IAAddr::clone() const {
return (cloneInternal<Option6IAAddr>());
}
void Option6IAAddr::pack(isc::util::OutputBuffer& buf) const {
buf.writeUint16(type_);
......
......@@ -46,6 +46,8 @@ public:
Option6IAAddr(uint32_t type, OptionBuffer::const_iterator begin,
OptionBuffer::const_iterator end);
virtual OptionPtr clone() const;
/// @brief Writes option in wire-format.
///
/// Writes option in wire-format to buf, returns pointer to first unused
......
......@@ -44,6 +44,11 @@ Option6IAPrefix::Option6IAPrefix(uint32_t type, OptionBuffer::const_iterator beg
unpack(begin, end);
}
OptionPtr
Option6IAPrefix::clone() const {
return (cloneInternal<Option6IAPrefix>());
}
void Option6IAPrefix::pack(isc::util::OutputBuffer& buf) const {
if (!addr_.isV6()) {
isc_throw(isc::BadValue, addr_ << " is not an IPv6 address");
......
......@@ -74,6 +74,8 @@ public:
Option6IAPrefix(uint32_t type, OptionBuffer::const_iterator begin,
OptionBuffer::const_iterator end);
virtual OptionPtr clone() const;
/// @brief Writes option in wire-format.
///
/// Writes option in wire-format to buf, returns pointer to first unused
......
......@@ -40,6 +40,11 @@ Option6StatusCode::Option6StatusCode(OptionBufferConstIter begin,
unpack(begin, end);
}
OptionPtr
Option6StatusCode::clone() const {
return (cloneInternal<Option6StatusCode>());
}
void
Option6StatusCode::pack(isc::util::OutputBuffer& buf) const {
// Pack option header.
......
......@@ -37,6 +37,8 @@ public:
/// @param end Iterator to end of option data (first byte after option end).
Option6StatusCode(OptionBufferConstIter begin, OptionBufferConstIter end);
virtual OptionPtr clone() const;
/// @brief Writes option in wire-format.
///
/// Writes option in wire-format to buf, returns pointer to first unused
......
......@@ -40,6 +40,11 @@ OptionCustom::OptionCustom(const OptionDefinition& def,
createBuffers(getData());
}
OptionPtr
OptionCustom::clone() const {
return (cloneInternal<OptionCustom>());
}
void
OptionCustom::addArrayDataField(const asiolink::IOAddress& address) {
checkArrayType();
......
......@@ -79,6 +79,8 @@ public:
OptionCustom(const OptionDefinition& def, Universe u,
OptionBufferConstIter first, OptionBufferConstIter last);
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
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment