diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 12:15:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 12:15:43 +0000 |
commit | f5f56e1a1c4d9e9496fcb9d81131066a964ccd23 (patch) | |
tree | 49e44c6f87febed37efb953ab5485aa49f6481a7 /src/lib/dhcp/tests/option6_addrlst_unittest.cc | |
parent | Initial commit. (diff) | |
download | isc-kea-f5f56e1a1c4d9e9496fcb9d81131066a964ccd23.tar.xz isc-kea-f5f56e1a1c4d9e9496fcb9d81131066a964ccd23.zip |
Adding upstream version 2.4.1.upstream/2.4.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/lib/dhcp/tests/option6_addrlst_unittest.cc')
-rw-r--r-- | src/lib/dhcp/tests/option6_addrlst_unittest.cc | 276 |
1 files changed, 276 insertions, 0 deletions
diff --git a/src/lib/dhcp/tests/option6_addrlst_unittest.cc b/src/lib/dhcp/tests/option6_addrlst_unittest.cc new file mode 100644 index 0000000..ba2190d --- /dev/null +++ b/src/lib/dhcp/tests/option6_addrlst_unittest.cc @@ -0,0 +1,276 @@ +// Copyright (C) 2011-2015 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/. + +#include <config.h> + +#include <asiolink/io_address.h> +#include <dhcp/dhcp6.h> +#include <dhcp/option.h> +#include <dhcp/option6_addrlst.h> +#include <util/buffer.h> + +#include <gtest/gtest.h> +#include <boost/scoped_ptr.hpp> + +#include <iostream> +#include <sstream> + +#include <arpa/inet.h> + +using namespace std; +using namespace isc; +using namespace isc::dhcp; +using namespace isc::asiolink; +using namespace isc::util; +using boost::scoped_ptr; + +namespace { +class Option6AddrLstTest : public ::testing::Test { +public: + Option6AddrLstTest(): buf_(255), out_buf_(255) { + for (unsigned i = 0; i < 255; i++) { + buf_[i] = 255 - i; + } + } + OptionBuffer buf_; + OutputBuffer out_buf_; +}; + +TEST_F(Option6AddrLstTest, basic) { + + // Limiting tests to just a 2001:db8::/32 is *wrong*. + // Good tests check corner cases as well. + // ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff checks + // for integer overflow. + // ff02::face:b00c checks if multicast addresses + // can be represented properly. + + uint8_t sampledata[] = { + // 2001:db8:1::dead:beef + 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0, 0, + 0, 0, 0, 0, 0xde, 0xad, 0xbe, 0xef, + + // ff02::face:b00c + 0xff, 02, 0, 0, 0, 0, 0 , 0, + 0, 0, 0, 0, 0xfa, 0xce, 0xb0, 0x0c, + + // ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + }; + + uint8_t expected1[] = { + D6O_NAME_SERVERS/256, D6O_NAME_SERVERS%256,//type + 0, 16, // len = 16 (1 address) + 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0, 0, + 0, 0, 0, 0, 0xde, 0xad, 0xbe, 0xef, + + }; + + uint8_t expected2[] = { + D6O_SIP_SERVERS_ADDR/256, D6O_SIP_SERVERS_ADDR%256, + 0, 32, // len = 32 (2 addresses) + // 2001:db8:1::dead:beef + 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0, 0, + 0, 0, 0, 0, 0xde, 0xad, 0xbe, 0xef, + + // ff02::face:b00c + 0xff, 02, 0, 0, 0, 0, 0 , 0, + 0, 0, 0, 0, 0xfa, 0xce, 0xb0, 0x0c, + + // ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + }; + + uint8_t expected3[] = { + D6O_NIS_SERVERS/256, D6O_NIS_SERVERS%256, + 0, 48, + // 2001:db8:1::dead:beef + 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0, 0, + 0, 0, 0, 0, 0xde, 0xad, 0xbe, 0xef, + + // ff02::face:b00c + 0xff, 02, 0, 0, 0, 0, 0 , 0, + 0, 0, 0, 0, 0xfa, 0xce, 0xb0, 0x0c, + + // ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + }; + + memcpy(&buf_[0], sampledata, 48); + + // Just a single address + scoped_ptr<Option6AddrLst> opt1; + EXPECT_NO_THROW( + opt1.reset(new Option6AddrLst(D6O_NAME_SERVERS, + buf_.begin(), buf_.begin() + 16)); + ); + + EXPECT_EQ(Option::V6, opt1->getUniverse()); + + EXPECT_EQ(D6O_NAME_SERVERS, opt1->getType()); + EXPECT_EQ(20, opt1->len()); + Option6AddrLst::AddressContainer addrs = opt1->getAddresses(); + ASSERT_EQ(1, addrs.size()); + IOAddress addr = addrs[0]; + EXPECT_EQ("2001:db8:1::dead:beef", addr.toText()); + + // Pack this option + opt1->pack(out_buf_); + + EXPECT_EQ(20, out_buf_.getLength()); + EXPECT_EQ(0, memcmp(expected1, out_buf_.getData(), 20)); + + // Two addresses + scoped_ptr<Option6AddrLst> opt2; + EXPECT_NO_THROW( + opt2.reset(new Option6AddrLst(D6O_SIP_SERVERS_ADDR, + buf_.begin(), buf_.begin() + 32)); + ); + EXPECT_EQ(D6O_SIP_SERVERS_ADDR, opt2->getType()); + EXPECT_EQ(36, opt2->len()); + addrs = opt2->getAddresses(); + ASSERT_EQ(2, addrs.size()); + EXPECT_EQ("2001:db8:1::dead:beef", addrs[0].toText()); + EXPECT_EQ("ff02::face:b00c", addrs[1].toText()); + + // Pack this option + out_buf_.clear(); + opt2->pack(out_buf_); + + EXPECT_EQ(36, out_buf_.getLength() ); + EXPECT_EQ(0, memcmp(expected2, out_buf_.getData(), 36)); + + // Three addresses + scoped_ptr<Option6AddrLst> opt3; + EXPECT_NO_THROW( + opt3.reset(new Option6AddrLst(D6O_NIS_SERVERS, + buf_.begin(), buf_.begin() + 48)); + ); + + EXPECT_EQ(D6O_NIS_SERVERS, opt3->getType()); + EXPECT_EQ(52, opt3->len()); + addrs = opt3->getAddresses(); + ASSERT_EQ(3, addrs.size()); + EXPECT_EQ("2001:db8:1::dead:beef", addrs[0].toText()); + EXPECT_EQ("ff02::face:b00c", addrs[1].toText()); + EXPECT_EQ("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", addrs[2].toText()); + + // Pack this option + out_buf_.clear(); + opt3->pack(out_buf_); + + EXPECT_EQ(52, out_buf_.getLength()); + EXPECT_EQ(0, memcmp(expected3, out_buf_.getData(), 52)); + + EXPECT_NO_THROW(opt1.reset()); + EXPECT_NO_THROW(opt2.reset()); + EXPECT_NO_THROW(opt3.reset()); +} + +TEST_F(Option6AddrLstTest, constructors) { + + scoped_ptr<Option6AddrLst> opt1; + EXPECT_NO_THROW( + opt1.reset(new Option6AddrLst(1234, IOAddress("::1"))); + ); + EXPECT_EQ(Option::V6, opt1->getUniverse()); + EXPECT_EQ(1234, opt1->getType()); + + Option6AddrLst::AddressContainer addrs = opt1->getAddresses(); + ASSERT_EQ(1, addrs.size() ); + EXPECT_EQ("::1", addrs[0].toText()); + + addrs.clear(); + addrs.push_back(IOAddress(string("fe80::1234"))); + addrs.push_back(IOAddress(string("2001:db8:1::baca"))); + + scoped_ptr<Option6AddrLst> opt2; + EXPECT_NO_THROW( + opt2.reset(new Option6AddrLst(5678, addrs)); + ); + + Option6AddrLst::AddressContainer check = opt2->getAddresses(); + ASSERT_EQ(2, check.size() ); + EXPECT_EQ("fe80::1234", check[0].toText()); + EXPECT_EQ("2001:db8:1::baca", check[1].toText()); + + EXPECT_NO_THROW(opt1.reset()); + EXPECT_NO_THROW(opt2.reset()); +} + +TEST_F(Option6AddrLstTest, setAddress) { + scoped_ptr<Option6AddrLst> opt1; + EXPECT_NO_THROW( + opt1.reset(new Option6AddrLst(1234, IOAddress("::1"))); + ); + opt1->setAddress(IOAddress("2001:db8:1::2")); + /// TODO It used to be ::2 address, but io_address represents + /// it as ::0.0.0.2. Purpose of this test is to verify + /// that setAddress() works, not deal with subtleties of + /// io_address handling of IPv4-mapped IPv6 addresses, we + /// switched to a more common address. User interested + /// in pursuing this matter further is encouraged to look + /// at section 2.5.5 of RFC4291 (and possibly implement + /// a test for IOAddress) + + Option6AddrLst::AddressContainer addrs = opt1->getAddresses(); + ASSERT_EQ(1, addrs.size()); + EXPECT_EQ("2001:db8:1::2", addrs[0].toText()); + + EXPECT_NO_THROW(opt1.reset()); +} + +// This test checks that the option holding IPv6 address list can +// be converted to textual format. +TEST_F(Option6AddrLstTest, toText) { + Option6AddrLst opt(1234, IOAddress("2001:db8:1::1")); + // Generate a few IPv6 addresses. + Option6AddrLst::AddressContainer addresses; + for (int i = 2; i < 6; ++i) { + std::stringstream s; + s << "2001:db8:1::" << i; + addresses.push_back(IOAddress(s.str())); + } + opt.setAddresses(addresses); + + EXPECT_EQ("type=01234, len=00064: 2001:db8:1::2 2001:db8:1::3 " + "2001:db8:1::4 2001:db8:1::5", opt.toText()); +} + +// A helper for the 'empty' test. Exercise public interfaces of an empty +// Option6AddrLst. It assumes the option type is D6O_DHCPV4_O_DHCPV6_SERVER. +void +checkEmpty(Option6AddrLst& addrs) { + const uint8_t expected[] = { + D6O_DHCPV4_O_DHCPV6_SERVER/256, D6O_DHCPV4_O_DHCPV6_SERVER%256, + 0, 0 + }; + EXPECT_EQ(4, addrs.len()); // just 2-byte type and 2-byte len fields + EXPECT_EQ("type=00088, len=00000:", addrs.toText()); + + OutputBuffer out_buf(255); + addrs.pack(out_buf); + EXPECT_EQ(4, out_buf.getLength()); + EXPECT_EQ(0, memcmp(expected, out_buf.getData(), 4)); +} + +// Confirms no disruption happens for an empty set of addresses. +TEST_F(Option6AddrLstTest, empty) { + boost::scoped_ptr<Option6AddrLst> addrs( + new Option6AddrLst(D6O_DHCPV4_O_DHCPV6_SERVER, + Option6AddrLst::AddressContainer())); + checkEmpty(*addrs); + + const OptionBuffer empty_buf; + addrs.reset(new Option6AddrLst(D6O_DHCPV4_O_DHCPV6_SERVER, + empty_buf.begin(), empty_buf.end())); + checkEmpty(*addrs); +} + +} // namespace |