Browse Source

[master] Merge remote-tracking branch 'github/master'

Tomek Mrugalski 9 years ago
parent
commit
4ff6f946cd

+ 2 - 1
src/lib/dhcp/Makefile.am

@@ -15,7 +15,7 @@ CLEANFILES = *.gcno *.gcda
 lib_LTLIBRARIES = libkea-dhcp++.la
 libkea_dhcp___la_SOURCES  =
 libkea_dhcp___la_SOURCES += classify.cc classify.h
-libkea_dhcp___la_SOURCES += dhcp6.h dhcp4.h
+libkea_dhcp___la_SOURCES += dhcp6.h dhcp4.h dhcp4o6.h
 libkea_dhcp___la_SOURCES += duid.cc duid.h
 libkea_dhcp___la_SOURCES += hwaddr.cc hwaddr.h
 libkea_dhcp___la_SOURCES += iface_mgr.cc iface_mgr.h
@@ -48,6 +48,7 @@ libkea_dhcp___la_SOURCES += protocol_util.cc protocol_util.h
 libkea_dhcp___la_SOURCES += pkt.cc pkt.h
 libkea_dhcp___la_SOURCES += pkt6.cc pkt6.h
 libkea_dhcp___la_SOURCES += pkt4.cc pkt4.h
+libkea_dhcp___la_SOURCES += pkt4o6.cc pkt4o6.h
 libkea_dhcp___la_SOURCES += pkt_filter.h pkt_filter.cc
 libkea_dhcp___la_SOURCES += pkt_filter6.h pkt_filter6.cc
 libkea_dhcp___la_SOURCES += pkt_filter_inet.cc pkt_filter_inet.h

+ 2 - 2
src/lib/dhcp/dhcp6.h

@@ -110,8 +110,8 @@
 //#define D6O_ADDRSEL                             84 /* RFC7078 */
 //#define D6O_ADDRSEL_TABLE                       85 /* RFC7078 */
 //#define D6O_V6_PCP_SERVER                       86 /* RFC7291 */
-//#define D6O_DHCPV4_MSG                          87 /* RFC7341 */
-//#define D6O_DHCPV4_O_DHCPV6_SERVER              88 /* RFC7341 */
+#define D6O_DHCPV4_MSG                          87 /* RFC7341 */
+#define D6O_DHCPV4_O_DHCPV6_SERVER              88 /* RFC7341 */
 //#define D6O_S46_RULE                            89 /* RFC7598 */
 //#define D6O_S46_BR                              90 /* RFC7598 */
 //#define D6O_S46_DMR                             91 /* RFC7598 */

+ 60 - 0
src/lib/dhcp/pkt4o6.cc

@@ -0,0 +1,60 @@
+// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <config.h>
+
+#include <dhcp/dhcp6.h>
+#include <dhcp/option.h>
+#include <dhcp/pkt4o6.h>
+#include <exceptions/exceptions.h>
+#include <util/buffer.h>
+
+using namespace isc::asiolink;
+using namespace isc::dhcp;
+using namespace isc::util;
+using namespace std;
+
+namespace isc {
+namespace dhcp {
+
+Pkt4o6::Pkt4o6(const OptionBuffer& pkt4, const Pkt6Ptr& pkt6)
+    :Pkt4(&pkt4[0], pkt4.size()), pkt6_(pkt6)
+{
+    static_cast<void>(pkt6->delOption(D6O_DHCPV4_MSG));
+    setIface(pkt6->getIface());
+    setIndex(pkt6->getIndex());
+    setRemoteAddr(pkt6->getRemoteAddr());
+}
+
+Pkt4o6::Pkt4o6(const Pkt4Ptr& pkt4, const Pkt6Ptr& pkt6)
+    :Pkt4(*pkt4), pkt6_(pkt6) {
+}
+
+void Pkt4o6::pack() {
+    // Convert wire-format Pkt4 data in the form of OptionBuffer.
+    Pkt4::pack();
+    OutputBuffer& buf = getBuffer();
+    const uint8_t* ptr = static_cast<const uint8_t*>(buf.getData());
+    OptionBuffer msg(ptr, ptr + buf.getLength());
+
+    // Build the DHCPv4 Message option for the DHCPv6 message, and pack the
+    // entire stuff.
+    OptionPtr dhcp4_msg(new Option(Option::V6, D6O_DHCPV4_MSG, msg));
+    pkt6_->addOption(dhcp4_msg);
+    pkt6_->pack();
+}
+
+} // end of namespace isc::dhcp
+
+} // end of namespace isc

+ 83 - 0
src/lib/dhcp/pkt4o6.h

@@ -0,0 +1,83 @@
+// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef PKT4O6_H
+#define PKT4O6_H
+
+#include <dhcp/pkt4.h>
+#include <dhcp/pkt6.h>
+
+#include <boost/shared_ptr.hpp>
+
+namespace isc {
+
+namespace dhcp {
+
+/// @brief Represents DHCPv4-over-DHCPv6 packet
+///
+/// This class derives from @c Pkt4 in order to be handled by
+/// the DHCPv4 server code. It includes a shared pointer to the
+/// DHCPv6 message too.
+///
+/// This is an implementation of the DHCPv4-query/response DHCPv6 messages
+/// defined in RFC 7341 (http://ietf.org/rfc/rfc7341.txt).
+/// See also http://kea.isc.org/wiki/Dhcp4o6Design for design discussions.
+class Pkt4o6 : public Pkt4 {
+public:
+
+    /// @brief Constructor, used in message reception.
+    ///
+    /// @param pkt4 Content of the DHCPv4-message option
+    /// @param pkt6 encapsulating unpacked DHCPv6 message
+    /// the DHCPv4 message option will be removed
+    Pkt4o6(const OptionBuffer& pkt4, const Pkt6Ptr& pkt6);
+
+    /// @brief Constructor, used in replying to a message
+    ///
+    /// @param pkt4 DHCPv4 message
+    /// @param pkt6 DHCPv6 message
+    Pkt4o6(const Pkt4Ptr& pkt4, const Pkt6Ptr& pkt6);
+
+    /// @brief Returns encapsulating DHCPv6 message
+    Pkt6Ptr getPkt6() const { return (pkt6_); }
+
+    /// @brief Prepares on-wire format of DHCPv4-over-DHCPv6 packet.
+    ///
+    /// Calls pack() on both DHCPv4 and DHCPv6 parts
+    /// Inserts the DHCPv4-message option
+    /// @ref Pkt4::pack and @ref Pkt6::pack
+    virtual void pack();
+
+    /// @brief Checks if a DHCPv4 message has been transported over DHCPv6
+    ///
+    /// @return Boolean value which indicates whether the message is
+    /// transported over DHCPv6 (true) or native DHCPv4 (false)
+    virtual bool isDhcp4o6() const {
+        return (true);
+    }
+
+private:
+    /// Encapsulating DHCPv6 message
+    Pkt6Ptr pkt6_;
+
+}; // Pkt4o6 class
+
+/// @brief A pointer to Pkt4o6 object.
+typedef boost::shared_ptr<Pkt4o6> Pkt4o6Ptr;
+
+} // isc::dhcp namespace
+
+} // isc namespace
+
+#endif

+ 1 - 1
src/lib/dhcp/pkt6.h

@@ -244,7 +244,7 @@ public:
     /// @param option_code code of the requested option
     /// @param nesting_level see description above
     ///
-    /// @return pointer to the option (or NULL if there is no such option)
+     /// @return pointer to the option (or NULL if there is no such option)
     OptionPtr getRelayOption(uint16_t option_code, uint8_t nesting_level);
 
     /// @brief Return first instance of a specified option

+ 1 - 0
src/lib/dhcp/tests/Makefile.am

@@ -74,6 +74,7 @@ libdhcp___unittests_SOURCES += option_vendor_class_unittest.cc
 libdhcp___unittests_SOURCES  += pkt_captures4.cc pkt_captures6.cc pkt_captures.h
 libdhcp___unittests_SOURCES += pkt4_unittest.cc
 libdhcp___unittests_SOURCES += pkt6_unittest.cc
+libdhcp___unittests_SOURCES += pkt4o6_unittest.cc
 libdhcp___unittests_SOURCES += pkt_filter_unittest.cc
 libdhcp___unittests_SOURCES += pkt_filter_inet_unittest.cc
 libdhcp___unittests_SOURCES += pkt_filter_inet6_unittest.cc

+ 106 - 0
src/lib/dhcp/tests/pkt4o6_unittest.cc

@@ -0,0 +1,106 @@
+// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <config.h>
+
+#include <dhcp/dhcp6.h>
+#include <dhcp/option.h>
+#include <dhcp/pkt4.h>
+#include <dhcp/pkt6.h>
+#include <dhcp/pkt4o6.h>
+
+#include <boost/scoped_ptr.hpp>
+
+#include <gtest/gtest.h>
+
+using namespace isc::dhcp;
+
+namespace {
+
+/// @brief A Fixture class dedicated to testing of the Pkt4o6 class that
+///        represents a DHCPv4-over-DHCPv6 packet.
+class Pkt4o6Test : public ::testing::Test {
+protected:
+    Pkt4o6Test() :
+        data6_(6, 0),
+        pkt6_(new Pkt6(&data6_[0], data6_.size())),
+        pkt4_(new Pkt4(DHCPDISCOVER, 0x12345678))
+    {
+        pkt4_->pack();
+        const uint8_t* cp = static_cast<const uint8_t*>(
+            pkt4_->getBuffer().getData());
+        buffer4_.assign(cp, cp + pkt4_->getBuffer().getLength());
+    }
+
+protected:
+    // commonly used test data
+    const std::vector<uint8_t> data6_; // data for Pkt6 (content unimportant)
+    Pkt6Ptr pkt6_;                     // DHCPv6 message for 4o6
+    Pkt4Ptr pkt4_;                     // DHCPv4 message for 4o6
+    OptionBuffer buffer4_;             // wire-format data buffer of pkt4_
+};
+
+// This test verifies that the constructors are working as expected.
+TEST_F(Pkt4o6Test, construct) {
+    // Construct 4o6 packet, unpack the data to examine it
+    boost::scoped_ptr<Pkt4o6> pkt4o6(new Pkt4o6(buffer4_, pkt6_));
+    pkt4o6->unpack();
+    // Inspect its internal to confirm it's built as expected.  We also test
+    // isDhcp4o6() here.
+    EXPECT_TRUE(pkt4o6->isDhcp4o6());
+    EXPECT_EQ(pkt6_, pkt4o6->getPkt6());
+    EXPECT_EQ(DHCPDISCOVER, pkt4o6->getType());
+
+    // Same check for the other constructor.  It relies on the internal
+    // behavior of Pkt4's copy constructor, so we need to first unpack pkt4.
+    pkt4_.reset(new Pkt4(&buffer4_[0], buffer4_.size()));
+    pkt4_->unpack();
+    pkt4o6.reset(new Pkt4o6(pkt4_, pkt6_));
+    EXPECT_TRUE(pkt4o6->isDhcp4o6());
+    EXPECT_EQ(pkt6_, pkt4o6->getPkt6());
+    EXPECT_EQ(DHCPDISCOVER, pkt4o6->getType());
+}
+
+// This test verifies that the pack() method handles the building
+// process correctly.
+TEST_F(Pkt4o6Test, pack) {
+    // prepare unpacked DHCPv4 packet (see the note in constructor test)
+    pkt4_.reset(new Pkt4(&buffer4_[0], buffer4_.size()));
+    pkt4_->unpack();
+
+    // Construct 4o6 packet to be tested and pack the data.
+    Pkt4o6 pkt4o6(pkt4_, pkt6_);
+    pkt4o6.pack();
+
+    // The packed data should be:
+    // 4-byte DHCPv6 message header
+    // 4-byte header part of DHCPv4 message option
+    // Raw DHCPv4 message (data stored in buffer4_)
+    EXPECT_EQ(4 + 4 + buffer4_.size(),
+              pkt4o6.getPkt6()->getBuffer().getLength());
+
+    // Check the DHCPv4 message option content (Pkt4o6 class is not responsible
+    // for making it valid, so we won't examine it)
+    const uint8_t* cp = static_cast<const uint8_t*>(
+        pkt4o6.getPkt6()->getBuffer().getData());
+    EXPECT_EQ(0, cp[4]);
+    EXPECT_EQ(D6O_DHCPV4_MSG, cp[5]);
+    EXPECT_EQ((buffer4_.size() >> 8) & 0xff, cp[6]);
+    EXPECT_EQ(buffer4_.size() & 0xff, cp[7]);
+    EXPECT_EQ(0, memcmp(&cp[8], &buffer4_[0], buffer4_.size()));
+}
+
+/// @todo: Add a test that handles actual DHCP4o6 traffic capture
+///        once we get it. We should add the capture to pkt_captures{4,6}.cc
+}