123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673 |
- // Copyright (C) 2011-2012 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 <asiolink/io_address.h>
- #include <dhcp/dhcp4.h>
- #include <dhcp/pkt4.h>
- #include <exceptions/exceptions.h>
- #include <util/buffer.h>
- #include <boost/shared_array.hpp>
- #include <boost/shared_ptr.hpp>
- #include <boost/static_assert.hpp>
- #include <gtest/gtest.h>
- #include <iostream>
- #include <sstream>
- #include <arpa/inet.h>
- using namespace std;
- using namespace isc;
- using namespace isc::asiolink;
- using namespace isc::dhcp;
- using namespace isc::util;
- // don't import the entire boost namespace. It will unexpectedly hide uint8_t
- // for some systems.
- using boost::scoped_ptr;
- namespace {
- TEST(Pkt4Test, constructor) {
- ASSERT_EQ(236U, static_cast<size_t>(Pkt4::DHCPV4_PKT_HDR_LEN) );
- Pkt4* pkt = 0;
- // Just some dummy payload.
- uint8_t testData[250];
- for (int i = 0; i < 250; i++) {
- testData[i]=i;
- }
- // Positive case1. Normal received packet.
- EXPECT_NO_THROW(
- pkt = new Pkt4(testData, Pkt4::DHCPV4_PKT_HDR_LEN);
- );
- EXPECT_EQ(static_cast<size_t>(Pkt4::DHCPV4_PKT_HDR_LEN), pkt->len());
- EXPECT_NO_THROW(
- delete pkt;
- pkt = 0;
- );
- // Positive case2. Normal outgoing packet.
- EXPECT_NO_THROW(
- pkt = new Pkt4(DHCPDISCOVER, 0xffffffff);
- );
- // DHCPv4 packet must be at least 236 bytes long, with Message Type
- // Option taking extra 3 bytes it is 239
- EXPECT_EQ(static_cast<size_t>(Pkt4::DHCPV4_PKT_HDR_LEN) + 3, pkt->len());
- EXPECT_EQ(DHCPDISCOVER, pkt->getType());
- EXPECT_EQ(0xffffffff, pkt->getTransid());
- EXPECT_NO_THROW(
- delete pkt;
- pkt = 0;
- );
- // Negative case. Should drop truncated messages.
- EXPECT_THROW(
- pkt = new Pkt4(testData, Pkt4::DHCPV4_PKT_HDR_LEN-1),
- OutOfRange
- );
- if (pkt) {
- // Test failed. Exception should have been thrown, but
- // object was created instead. Let's clean this up.
- delete pkt;
- pkt = 0;
- }
- }
- // a sample data
- const uint8_t dummyOp = BOOTREQUEST;
- const uint8_t dummyHtype = 6;
- const uint8_t dummyHlen = 6;
- const uint8_t dummyHops = 13;
- const uint32_t dummyTransid = 0x12345678;
- const uint16_t dummySecs = 42;
- const uint16_t dummyFlags = BOOTP_BROADCAST;
- const IOAddress dummyCiaddr("192.0.2.1");
- const IOAddress dummyYiaddr("1.2.3.4");
- const IOAddress dummySiaddr("192.0.2.255");
- const IOAddress dummyGiaddr("255.255.255.255");
- // a dummy MAC address
- const uint8_t dummyMacAddr[] = {0, 1, 2, 3, 4, 5};
- // a dummy MAC address, padded with 0s
- const uint8_t dummyChaddr[16] = {0, 1, 2, 3, 4, 5, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0 };
- // let's use some creative test content here (128 chars + \0)
- const uint8_t dummyFile[] = "Lorem ipsum dolor sit amet, consectetur "
- "adipiscing elit. Proin mollis placerat metus, at "
- "lacinia orci ornare vitae. Mauris amet.";
- // yet another type of test content (64 chars + \0)
- const uint8_t dummySname[] = "Lorem ipsum dolor sit amet, consectetur "
- "adipiscing elit posuere.";
- BOOST_STATIC_ASSERT(sizeof(dummyFile) == Pkt4::MAX_FILE_LEN + 1);
- BOOST_STATIC_ASSERT(sizeof(dummySname) == Pkt4::MAX_SNAME_LEN + 1);
- /// @brief Generates test packet.
- ///
- /// Allocates and generates test packet, with all fixed
- /// fields set to non-zero values. Content is not always
- /// reasonable.
- ///
- /// See generateTestPacket2() function that returns
- /// exactly the same packet in on-wire format.
- ///
- /// @return pointer to allocated Pkt4 object.
- boost::shared_ptr<Pkt4>
- generateTestPacket1() {
- boost::shared_ptr<Pkt4> pkt(new Pkt4(DHCPDISCOVER, dummyTransid));
- vector<uint8_t> vectorMacAddr(dummyMacAddr, dummyMacAddr
- +sizeof(dummyMacAddr));
- // hwType = 6(ETHERNET), hlen = 6(MAC address len)
- pkt->setHWAddr(dummyHtype, dummyHlen, vectorMacAddr);
- pkt->setHops(dummyHops); // 13 relays. Wow!
- // Transaction-id is already set.
- pkt->setSecs(dummySecs);
- pkt->setFlags(dummyFlags); // all flags set
- pkt->setCiaddr(dummyCiaddr);
- pkt->setYiaddr(dummyYiaddr);
- pkt->setSiaddr(dummySiaddr);
- pkt->setGiaddr(dummyGiaddr);
- // Chaddr already set with setHWAddr().
- pkt->setSname(dummySname, 64);
- pkt->setFile(dummyFile, 128);
- return (pkt);
- }
- /// @brief Generates test packet.
- ///
- /// Allocates and generates on-wire buffer that represents
- /// test packet, with all fixed fields set to non-zero values.
- /// Content is not always reasonable.
- ///
- /// See generateTestPacket1() function that returns
- /// exactly the same packet as Pkt4 object.
- ///
- /// @return pointer to allocated Pkt4 object
- // Returns a vector containing a DHCPv4 packet header.
- vector<uint8_t>
- generateTestPacket2() {
- // That is only part of the header. It contains all "short" fields,
- // larger fields are constructed separately.
- uint8_t hdr[] = {
- 1, 6, 6, 13, // op, htype, hlen, hops,
- 0x12, 0x34, 0x56, 0x78, // transaction-id
- 0, 42, 0x80, 0x00, // 42 secs, BROADCAST flags
- 192, 0, 2, 1, // ciaddr
- 1, 2, 3, 4, // yiaddr
- 192, 0, 2, 255, // siaddr
- 255, 255, 255, 255, // giaddr
- };
- // Initialize the vector with the header fields defined above.
- vector<uint8_t> buf(hdr, hdr + sizeof(hdr));
- // Append the large header fields.
- copy(dummyChaddr, dummyChaddr + Pkt4::MAX_CHADDR_LEN, back_inserter(buf));
- copy(dummySname, dummySname + Pkt4::MAX_SNAME_LEN, back_inserter(buf));
- copy(dummyFile, dummyFile + Pkt4::MAX_FILE_LEN, back_inserter(buf));
- // Should now have all the header, so check. The "static_cast" is used
- // to get round an odd bug whereby the linker appears not to find the
- // definition of DHCPV4_PKT_HDR_LEN if it appears within an EXPECT_EQ().
- EXPECT_EQ(static_cast<size_t>(Pkt4::DHCPV4_PKT_HDR_LEN), buf.size());
- return (buf);
- }
- TEST(Pkt4Test, fixedFields) {
- boost::shared_ptr<Pkt4> pkt = generateTestPacket1();
- // ok, let's check packet values
- EXPECT_EQ(dummyOp, pkt->getOp());
- EXPECT_EQ(dummyHtype, pkt->getHtype());
- EXPECT_EQ(dummyHlen, pkt->getHlen());
- EXPECT_EQ(dummyHops, pkt->getHops());
- EXPECT_EQ(dummyTransid, pkt->getTransid());
- EXPECT_EQ(dummySecs, pkt->getSecs());
- EXPECT_EQ(dummyFlags, pkt->getFlags());
- EXPECT_EQ(dummyCiaddr.toText(), pkt->getCiaddr().toText());
- EXPECT_EQ(dummyYiaddr.toText(), pkt->getYiaddr().toText());
- EXPECT_EQ(dummySiaddr.toText(), pkt->getSiaddr().toText());
- EXPECT_EQ(dummyGiaddr.toText(), pkt->getGiaddr().toText());
- // Chaddr contains link-layer addr (MAC). It is no longer always 16 bytes
- // long and its length depends on hlen value (it is up to 16 bytes now).
- ASSERT_EQ(pkt->getHWAddr()->hwaddr_.size(), dummyHlen);
- EXPECT_EQ(0, memcmp(dummyChaddr, &pkt->getHWAddr()->hwaddr_[0], dummyHlen));
- EXPECT_EQ(0, memcmp(dummySname, &pkt->getSname()[0], 64));
- EXPECT_EQ(0, memcmp(dummyFile, &pkt->getFile()[0], 128));
- EXPECT_EQ(DHCPDISCOVER, pkt->getType());
- }
- TEST(Pkt4Test, fixedFieldsPack) {
- boost::shared_ptr<Pkt4> pkt = generateTestPacket1();
- vector<uint8_t> expectedFormat = generateTestPacket2();
- EXPECT_NO_THROW(
- pkt->pack();
- );
- // Minimum packet size is 236 bytes + 3 bytes of mandatory
- // DHCP Message Type Option
- ASSERT_EQ(static_cast<size_t>(Pkt4::DHCPV4_PKT_HDR_LEN) + 3, pkt->len());
- // redundant but MUCH easier for debug in gdb
- const uint8_t* exp = &expectedFormat[0];
- const uint8_t* got = static_cast<const uint8_t*>(pkt->getBuffer().getData());
- EXPECT_EQ(0, memcmp(exp, got, Pkt4::DHCPV4_PKT_HDR_LEN));
- }
- /// TODO Uncomment when ticket #1226 is implemented
- TEST(Pkt4Test, fixedFieldsUnpack) {
- vector<uint8_t> expectedFormat = generateTestPacket2();
- expectedFormat.push_back(0x63); // magic cookie
- expectedFormat.push_back(0x82);
- expectedFormat.push_back(0x53);
- expectedFormat.push_back(0x63);
- expectedFormat.push_back(0x35); // message-type
- expectedFormat.push_back(0x1);
- expectedFormat.push_back(0x1);
- boost::shared_ptr<Pkt4> pkt(new Pkt4(&expectedFormat[0],
- expectedFormat.size()));;
- EXPECT_NO_THROW(
- pkt->unpack()
- );
- // ok, let's check packet values
- EXPECT_EQ(dummyOp, pkt->getOp());
- EXPECT_EQ(dummyHtype, pkt->getHtype());
- EXPECT_EQ(dummyHlen, pkt->getHlen());
- EXPECT_EQ(dummyHops, pkt->getHops());
- EXPECT_EQ(dummyTransid, pkt->getTransid());
- EXPECT_EQ(dummySecs, pkt->getSecs());
- EXPECT_EQ(dummyFlags, pkt->getFlags());
- EXPECT_EQ(dummyCiaddr.toText(), pkt->getCiaddr().toText());
- EXPECT_EQ(string("1.2.3.4"), pkt->getYiaddr().toText());
- EXPECT_EQ(string("192.0.2.255"), pkt->getSiaddr().toText());
- EXPECT_EQ(string("255.255.255.255"), pkt->getGiaddr().toText());
- // chaddr is always 16 bytes long and contains link-layer addr (MAC)
- EXPECT_EQ(0, memcmp(dummyChaddr, &pkt->getHWAddr()->hwaddr_[0], dummyHlen));
- ASSERT_EQ(static_cast<size_t>(Pkt4::MAX_SNAME_LEN), pkt->getSname().size());
- EXPECT_EQ(0, memcmp(dummySname, &pkt->getSname()[0], Pkt4::MAX_SNAME_LEN));
- ASSERT_EQ(static_cast<size_t>(Pkt4::MAX_FILE_LEN), pkt->getFile().size());
- EXPECT_EQ(0, memcmp(dummyFile, &pkt->getFile()[0], Pkt4::MAX_FILE_LEN));
- EXPECT_EQ(DHCPDISCOVER, pkt->getType());
- }
- // this test is for hardware addresses (htype, hlen and chaddr fields)
- TEST(Pkt4Test, hwAddr) {
- vector<uint8_t> mac;
- uint8_t expectedChaddr[Pkt4::MAX_CHADDR_LEN];
- // We resize vector to specified length. It is more natural for fixed-length
- // field, than clear it (shrink size to 0) and push_back each element
- // (growing length back to MAX_CHADDR_LEN).
- mac.resize(Pkt4::MAX_CHADDR_LEN);
- Pkt4* pkt = 0;
- // let's test each hlen, from 0 till 16
- for (int macLen = 0; macLen < Pkt4::MAX_CHADDR_LEN; macLen++) {
- for (int i = 0; i < Pkt4::MAX_CHADDR_LEN; i++) {
- mac[i] = 0;
- expectedChaddr[i] = 0;
- }
- for (int i = 0; i < macLen; i++) {
- mac[i] = 128 + i;
- expectedChaddr[i] = 128 + i;
- }
- // type and transaction doesn't matter in this test
- pkt = new Pkt4(DHCPOFFER, 1234);
- pkt->setHWAddr(255-macLen*10, // just weird htype
- macLen,
- mac);
- EXPECT_EQ(0, memcmp(expectedChaddr, &pkt->getHWAddr()->hwaddr_[0],
- Pkt4::MAX_CHADDR_LEN));
- EXPECT_NO_THROW(
- pkt->pack();
- );
- // CHADDR starts at offset 28 in DHCP packet
- const uint8_t* ptr =
- static_cast<const uint8_t*>(pkt->getBuffer().getData())+28;
- EXPECT_EQ(0, memcmp(ptr, expectedChaddr, Pkt4::MAX_CHADDR_LEN));
- delete pkt;
- }
- /// TODO: extend this test once options support is implemented. HW address
- /// longer than 16 bytes should be stored in client-identifier option
- }
- TEST(Pkt4Test, msgTypes) {
- struct msgType {
- uint8_t dhcp;
- uint8_t bootp;
- };
- msgType types[] = {
- {DHCPDISCOVER, BOOTREQUEST},
- {DHCPOFFER, BOOTREPLY},
- {DHCPREQUEST, BOOTREQUEST},
- {DHCPDECLINE, BOOTREQUEST},
- {DHCPACK, BOOTREPLY},
- {DHCPNAK, BOOTREPLY},
- {DHCPRELEASE, BOOTREQUEST},
- {DHCPINFORM, BOOTREQUEST},
- {DHCPLEASEQUERY, BOOTREQUEST},
- {DHCPLEASEUNASSIGNED, BOOTREPLY},
- {DHCPLEASEUNKNOWN, BOOTREPLY},
- {DHCPLEASEACTIVE, BOOTREPLY}
- };
- Pkt4* pkt = 0;
- for (int i = 0; i < sizeof(types) / sizeof(msgType); i++) {
- pkt = new Pkt4(types[i].dhcp, 0);
- EXPECT_EQ(types[i].dhcp, pkt->getType());
- EXPECT_EQ(types[i].bootp, pkt->getOp());
- delete pkt;
- pkt = 0;
- }
- EXPECT_THROW(
- pkt = new Pkt4(100, 0), // there's no message type 100
- OutOfRange
- );
- if (pkt) {
- delete pkt;
- }
- }
- // this test verifies handling of sname field
- TEST(Pkt4Test, sname) {
- uint8_t sname[Pkt4::MAX_SNAME_LEN];
- Pkt4* pkt = 0;
- // let's test each sname length, from 0 till 64
- for (int snameLen=0; snameLen < Pkt4::MAX_SNAME_LEN; snameLen++) {
- for (int i = 0; i < Pkt4::MAX_SNAME_LEN; i++) {
- sname[i] = 0;
- }
- for (int i = 0; i < snameLen; i++) {
- sname[i] = i;
- }
- // type and transaction doesn't matter in this test
- pkt = new Pkt4(DHCPOFFER, 1234);
- pkt->setSname(sname, snameLen);
- EXPECT_EQ(0, memcmp(sname, &pkt->getSname()[0], Pkt4::MAX_SNAME_LEN));
- EXPECT_NO_THROW(
- pkt->pack();
- );
- // SNAME starts at offset 44 in DHCP packet
- const uint8_t* ptr =
- static_cast<const uint8_t*>(pkt->getBuffer().getData())+44;
- EXPECT_EQ(0, memcmp(ptr, sname, Pkt4::MAX_SNAME_LEN));
- delete pkt;
- }
- // Check that a null argument generates an exception.
- Pkt4 pkt4(DHCPOFFER, 1234);
- EXPECT_THROW(pkt4.setSname(NULL, Pkt4::MAX_SNAME_LEN), InvalidParameter);
- EXPECT_THROW(pkt4.setSname(NULL, 0), InvalidParameter);
- }
- TEST(Pkt4Test, file) {
- uint8_t file[Pkt4::MAX_FILE_LEN];
- Pkt4* pkt = 0;
- // Let's test each file length, from 0 till 128.
- for (int fileLen = 0; fileLen < Pkt4::MAX_FILE_LEN; fileLen++) {
- for (int i = 0; i < Pkt4::MAX_FILE_LEN; i++) {
- file[i] = 0;
- }
- for (int i = 0; i < fileLen; i++) {
- file[i] = i;
- }
- // Type and transaction doesn't matter in this test.
- pkt = new Pkt4(DHCPOFFER, 1234);
- pkt->setFile(file, fileLen);
- EXPECT_EQ(0, memcmp(file, &pkt->getFile()[0], Pkt4::MAX_FILE_LEN));
- //
- EXPECT_NO_THROW(
- pkt->pack();
- );
- // FILE starts at offset 108 in DHCP packet.
- const uint8_t* ptr =
- static_cast<const uint8_t*>(pkt->getBuffer().getData())+108;
- EXPECT_EQ(0, memcmp(ptr, file, Pkt4::MAX_FILE_LEN));
- delete pkt;
- }
- // Check that a null argument generates an exception.
- Pkt4 pkt4(DHCPOFFER, 1234);
- EXPECT_THROW(pkt4.setFile(NULL, Pkt4::MAX_FILE_LEN), InvalidParameter);
- EXPECT_THROW(pkt4.setFile(NULL, 0), InvalidParameter);
- }
- /// V4 Options being used for pack/unpack testing.
- /// For test simplicity, all selected options have
- /// variable length data so as there are no restrictions
- /// on a length of their data.
- static uint8_t v4Opts[] = {
- 12, 3, 0, 1, 2, // Hostname
- 14, 3, 10, 11, 12, // Merit Dump File
- 53, 1, 2, // Message Type (required to not throw exception during unpack)
- 60, 3, 20, 21, 22, // Class Id
- 128, 3, 30, 31, 32, // Vendor specific
- 254, 3, 40, 41, 42, // Reserved
- };
- TEST(Pkt4Test, options) {
- Pkt4* pkt = new Pkt4(DHCPOFFER, 0);
- vector<uint8_t> payload[5];
- for (int i = 0; i < 5; i++) {
- payload[i].push_back(i*10);
- payload[i].push_back(i*10+1);
- payload[i].push_back(i*10+2);
- }
- boost::shared_ptr<Option> opt1(new Option(Option::V4, 12, payload[0]));
- boost::shared_ptr<Option> opt3(new Option(Option::V4, 14, payload[1]));
- boost::shared_ptr<Option> opt2(new Option(Option::V4, 60, payload[2]));
- boost::shared_ptr<Option> opt5(new Option(Option::V4,128, payload[3]));
- boost::shared_ptr<Option> opt4(new Option(Option::V4,254, payload[4]));
- pkt->addOption(opt1);
- pkt->addOption(opt2);
- pkt->addOption(opt3);
- pkt->addOption(opt4);
- pkt->addOption(opt5);
- EXPECT_TRUE(pkt->getOption(12));
- EXPECT_TRUE(pkt->getOption(60));
- EXPECT_TRUE(pkt->getOption(14));
- EXPECT_TRUE(pkt->getOption(128));
- EXPECT_TRUE(pkt->getOption(254));
- EXPECT_FALSE(pkt->getOption(127)); // no such option
- // options are unique in DHCPv4. It should not be possible
- // to add more than one option of the same type.
- EXPECT_THROW(
- pkt->addOption(opt1),
- BadValue
- );
- EXPECT_NO_THROW(
- pkt->pack();
- );
- const OutputBuffer& buf = pkt->getBuffer();
- // check that all options are stored, they should take sizeof(v4Opts),
- // DHCP magic cookie (4 bytes), and OPTION_END added (just one byte)
- ASSERT_EQ(static_cast<size_t>(Pkt4::DHCPV4_PKT_HDR_LEN) + sizeof(DHCP_OPTIONS_COOKIE)
- + sizeof(v4Opts) + 1, buf.getLength());
- // that that this extra data actually contain our options
- const uint8_t* ptr = static_cast<const uint8_t*>(buf.getData());
- ptr += Pkt4::DHCPV4_PKT_HDR_LEN + sizeof(DHCP_OPTIONS_COOKIE); // rewind to end of fixed part
- EXPECT_EQ(0, memcmp(ptr, v4Opts, sizeof(v4Opts)));
- EXPECT_EQ(DHO_END, static_cast<uint8_t>(*(ptr + sizeof(v4Opts))));
- // delOption() checks
- EXPECT_TRUE(pkt->getOption(12)); // Sanity check: option 12 is still there
- EXPECT_TRUE(pkt->delOption(12)); // We should be able to remove it
- EXPECT_FALSE(pkt->getOption(12)); // It should not be there anymore
- EXPECT_FALSE(pkt->delOption(12)); // And removal should fail
- EXPECT_NO_THROW(
- delete pkt;
- );
- }
- TEST(Pkt4Test, unpackOptions) {
- vector<uint8_t> expectedFormat = generateTestPacket2();
- expectedFormat.push_back(0x63);
- expectedFormat.push_back(0x82);
- expectedFormat.push_back(0x53);
- expectedFormat.push_back(0x63);
- for (int i = 0; i < sizeof(v4Opts); i++) {
- expectedFormat.push_back(v4Opts[i]);
- }
- // now expectedFormat contains fixed format and 5 options
- boost::shared_ptr<Pkt4> pkt(new Pkt4(&expectedFormat[0],
- expectedFormat.size()));
- EXPECT_NO_THROW(
- pkt->unpack()
- );
- EXPECT_TRUE(pkt->getOption(12));
- EXPECT_TRUE(pkt->getOption(60));
- EXPECT_TRUE(pkt->getOption(14));
- EXPECT_TRUE(pkt->getOption(128));
- EXPECT_TRUE(pkt->getOption(254));
- boost::shared_ptr<Option> x = pkt->getOption(12);
- ASSERT_TRUE(x); // option 1 should exist
- EXPECT_EQ(12, x->getType()); // this should be option 12
- ASSERT_EQ(3, x->getData().size()); // it should be of length 3
- EXPECT_EQ(5, x->len()); // total option length 5
- EXPECT_EQ(0, memcmp(&x->getData()[0], v4Opts+2, 3)); // data len=3
- x = pkt->getOption(14);
- ASSERT_TRUE(x); // option 13 should exist
- EXPECT_EQ(14, x->getType()); // this should be option 13
- ASSERT_EQ(3, x->getData().size()); // it should be of length 3
- EXPECT_EQ(5, x->len()); // total option length 5
- EXPECT_EQ(0, memcmp(&x->getData()[0], v4Opts+7, 3)); // data len=3
- x = pkt->getOption(60);
- ASSERT_TRUE(x); // option 60 should exist
- EXPECT_EQ(60, x->getType()); // this should be option 60
- ASSERT_EQ(3, x->getData().size()); // it should be of length 3
- EXPECT_EQ(5, x->len()); // total option length 5
- EXPECT_EQ(0, memcmp(&x->getData()[0], v4Opts+15, 3)); // data len=3
- x = pkt->getOption(128);
- ASSERT_TRUE(x); // option 3 should exist
- EXPECT_EQ(128, x->getType()); // this should be option 254
- ASSERT_EQ(3, x->getData().size()); // it should be of length 3
- EXPECT_EQ(5, x->len()); // total option length 5
- EXPECT_EQ(0, memcmp(&x->getData()[0], v4Opts+20, 3)); // data len=3
- x = pkt->getOption(254);
- ASSERT_TRUE(x); // option 3 should exist
- EXPECT_EQ(254, x->getType()); // this should be option 254
- ASSERT_EQ(3, x->getData().size()); // it should be of length 3
- EXPECT_EQ(5, x->len()); // total option length 5
- EXPECT_EQ(0, memcmp(&x->getData()[0], v4Opts+25, 3)); // data len=3
- }
- // This test verifies methods that are used for manipulating meta fields
- // i.e. fields that are not part of DHCPv4 (e.g. interface name).
- TEST(Pkt4Test, metaFields) {
- Pkt4* pkt = new Pkt4(DHCPOFFER, 1234);
- pkt->setIface("loooopback");
- pkt->setIndex(42);
- pkt->setRemoteAddr(IOAddress("1.2.3.4"));
- pkt->setLocalAddr(IOAddress("4.3.2.1"));
- EXPECT_EQ("loooopback", pkt->getIface());
- EXPECT_EQ(42, pkt->getIndex());
- EXPECT_EQ("1.2.3.4", pkt->getRemoteAddr().toText());
- EXPECT_EQ("4.3.2.1", pkt->getLocalAddr().toText());
- delete pkt;
- }
- TEST(Pkt4Test, Timestamp) {
- scoped_ptr<Pkt4> pkt(new Pkt4(DHCPOFFER, 1234));
- // Just after construction timestamp is invalid
- ASSERT_TRUE(pkt->getTimestamp().is_not_a_date_time());
- // Update packet time.
- pkt->updateTimestamp();
- // Get updated packet time.
- boost::posix_time::ptime ts_packet = pkt->getTimestamp();
- // After timestamp is updated it should be date-time.
- ASSERT_FALSE(ts_packet.is_not_a_date_time());
- // Check current time.
- boost::posix_time::ptime ts_now =
- boost::posix_time::microsec_clock::universal_time();
- // Calculate period between packet time and now.
- boost::posix_time::time_period ts_period(ts_packet, ts_now);
- // Duration should be positive or zero.
- EXPECT_TRUE(ts_period.length().total_microseconds() >= 0);
- }
- TEST(Pkt4Test, hwaddr) {
- scoped_ptr<Pkt4> pkt(new Pkt4(DHCPOFFER, 1234));
- const uint8_t hw[] = { 2, 4, 6, 8, 10, 12 }; // MAC
- const uint8_t hw_type = 123; // hardware type
- HWAddrPtr hwaddr(new HWAddr(hw, sizeof(hw), hw_type));
- // setting NULL hardware address is not allowed
- EXPECT_THROW(pkt->setHWAddr(HWAddrPtr()), BadValue);
- pkt->setHWAddr(hwaddr);
- EXPECT_EQ(hw_type, pkt->getHtype());
- EXPECT_EQ(sizeof(hw), pkt->getHlen());
- EXPECT_TRUE(hwaddr == pkt->getHWAddr());
- }
- } // end of anonymous namespace
|