pkt6_unittest.cc 7.86 KB
Newer Older
1
// Copyright (C) 2011-2012 Internet Systems Consortium, Inc. ("ISC")
2 3 4 5 6 7 8 9 10 11 12 13 14
//
// 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.

15 16 17 18
#include <config.h>
#include <iostream>
#include <sstream>
#include <arpa/inet.h>
19
#include <boost/date_time/posix_time/posix_time.hpp>
20 21
#include <gtest/gtest.h>

22 23 24 25
#include <asiolink/io_address.h>
#include <dhcp/option.h>
#include <dhcp/pkt6.h>
#include <dhcp/dhcp6.h>
26 27 28

using namespace std;
using namespace isc;
29
using namespace isc::asiolink;
30
using namespace isc::dhcp;
31

32
namespace {
33 34 35 36 37 38 39 40
// empty class for now, but may be extended once Addr6 becomes bigger
class Pkt6Test : public ::testing::Test {
public:
    Pkt6Test() {
    }
};

TEST_F(Pkt6Test, constructor) {
41 42
    uint8_t data[] = { 0, 1, 2, 3, 4, 5 };
    Pkt6 * pkt1 = new Pkt6(data, sizeof(data) );
43

44
    EXPECT_EQ(6, pkt1->getData().size());
45
    EXPECT_EQ(0, memcmp( &pkt1->getData()[0], data, sizeof(data)));
46

47
    delete pkt1;
48
}
49

50 51 52 53 54 55 56 57
/// @brief returns captured actual SOLICIT packet
///
/// Captured SOLICIT packet with transid=0x3d79fb and options: client-id,
/// in_na, dns-server, elapsed-time, option-request
/// This code was autogenerated (see src/bin/dhcp6/tests/iface_mgr_unittest.c),
/// but we spent some time to make is less ugly than it used to be.
///
/// @return pointer to Pkt6 that represents received SOLICIT
58
Pkt6* capture1() {
59
    Pkt6* pkt;
60
    uint8_t data[98];
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
    data[0]  = 1;
    data[1]  = 1;       data[2]  = 2;     data[3] = 3;      data[4]  = 0;
    data[5]  = 1;       data[6]  = 0;     data[7] = 14;     data[8]  = 0;
    data[9]  = 1;       data[10] = 0;     data[11] = 1;     data[12] = 21;
    data[13] = 158;     data[14] = 60;    data[15] = 22;    data[16] = 0;
    data[17] = 30;      data[18] = 140;   data[19] = 155;   data[20] = 115;
    data[21] = 73;      data[22] = 0;     data[23] = 3;     data[24] = 0;
    data[25] = 40;      data[26] = 0;     data[27] = 0;     data[28] = 0;
    data[29] = 1;       data[30] = 255;   data[31] = 255;   data[32] = 255;
    data[33] = 255;     data[34] = 255;   data[35] = 255;   data[36] = 255;
    data[37] = 255;     data[38] = 0;     data[39] = 5;     data[40] = 0;
    data[41] = 24;      data[42] = 32;    data[43] = 1;     data[44] = 13;
    data[45] = 184;     data[46] = 0;     data[47] = 1;     data[48] = 0;
    data[49] = 0;       data[50] = 0;     data[51] = 0;     data[52] = 0;
    data[53] = 0;       data[54] = 0;     data[55] = 0;     data[56] = 18;
    data[57] = 52;      data[58] = 255;   data[59] = 255;   data[60] = 255;
    data[61] = 255;     data[62] = 255;   data[63] = 255;   data[64] = 255;
    data[65] = 255;     data[66] = 0;     data[67] = 23;    data[68] = 0;
    data[69] = 16;      data[70] = 32;    data[71] = 1;     data[72] = 13;
    data[73] = 184;     data[74] = 0;     data[75] = 1;     data[76] = 0;
    data[77] = 0;       data[78] = 0;     data[79] = 0;     data[80] = 0;
    data[81] = 0;       data[82] = 0;     data[83] = 0;     data[84] = 221;
    data[85] = 221;     data[86] = 0;     data[87] = 8;     data[88] = 0;
    data[89] = 2;       data[90] = 0;     data[91] = 100;   data[92] = 0;
    data[93] = 6;       data[94] = 0;     data[95] = 2;     data[96] = 0;
    data[97] = 23;
87 88 89 90 91 92 93 94 95

    pkt = new Pkt6(data, sizeof(data));
    pkt->setRemotePort(546);
    pkt->setRemoteAddr(IOAddress("fe80::21e:8cff:fe9b:7349"));
    pkt->setLocalPort(0);
    pkt->setLocalAddr(IOAddress("ff02::1:2"));
    pkt->setIndex(2);
    pkt->setIface("eth0");

96 97 98
    return (pkt);
}

99

100
TEST_F(Pkt6Test, unpack_solicit1) {
101
    Pkt6* sol = capture1();
102 103 104

    ASSERT_EQ(true, sol->unpack());

105 106 107 108 109
    // check for length
    EXPECT_EQ(98, sol->len() );

    // check for type
    EXPECT_EQ(DHCPV6_SOLICIT, sol->getType() );
110 111

    // check that all present options are returned
112 113 114 115 116
    EXPECT_TRUE(sol->getOption(D6O_CLIENTID)); // client-id is present
    EXPECT_TRUE(sol->getOption(D6O_IA_NA));    // IA_NA is present
    EXPECT_TRUE(sol->getOption(D6O_ELAPSED_TIME));  // elapsed is present
    EXPECT_TRUE(sol->getOption(D6O_NAME_SERVERS));
    EXPECT_TRUE(sol->getOption(D6O_ORO));
117 118

    // let's check that non-present options are not returned
119 120 121
    EXPECT_FALSE(sol->getOption(D6O_SERVERID)); // server-id is missing
    EXPECT_FALSE(sol->getOption(D6O_IA_TA));
    EXPECT_FALSE(sol->getOption(D6O_IAADDR));
122 123 124 125

    delete sol;
}

126 127
TEST_F(Pkt6Test, packUnpack) {

128
    Pkt6* parent = new Pkt6(DHCPV6_SOLICIT, 0x020304);
129

130 131 132
    OptionPtr opt1(new Option(Option::V6, 1));
    OptionPtr opt2(new Option(Option::V6, 2));
    OptionPtr opt3(new Option(Option::V6, 100));
133 134 135 136 137 138 139 140 141
    // let's not use zero-length option type 3 as it is IA_NA

    parent->addOption(opt1);
    parent->addOption(opt2);
    parent->addOption(opt3);

    EXPECT_EQ(DHCPV6_SOLICIT, parent->getType());

    // calculated length should be 16
142 143
    EXPECT_EQ(Pkt6::DHCPV6_PKT_HDR_LEN + 3 * Option::OPTION6_HDR_LEN,
              parent->len());
144

145
    EXPECT_TRUE(parent->pack());
146

147 148
    EXPECT_EQ(Pkt6::DHCPV6_PKT_HDR_LEN + 3 * Option::OPTION6_HDR_LEN,
              parent->len());
149

150
    // create second packet,based on assembled data from the first one
151
    Pkt6* clone = new Pkt6(static_cast<const uint8_t*>(parent->getBuffer().getData()),
152
                           parent->getBuffer().getLength());
153 154

    // now recreate options list
155
    EXPECT_TRUE( clone->unpack() );
156 157

    // transid, message-type should be the same as before
158 159 160 161 162 163 164 165
    EXPECT_EQ(parent->getTransid(), parent->getTransid());
    EXPECT_EQ(DHCPV6_SOLICIT, clone->getType());

    EXPECT_TRUE( clone->getOption(1));
    EXPECT_TRUE( clone->getOption(2));
    EXPECT_TRUE( clone->getOption(100));
    EXPECT_FALSE( clone->getOption(4));

166
    delete parent;
167
    delete clone;
168 169
}

170
TEST_F(Pkt6Test, addGetDelOptions) {
171
    Pkt6* parent = new Pkt6(DHCPV6_SOLICIT, random() );
172

173 174 175
    OptionPtr opt1(new Option(Option::V6, 1));
    OptionPtr opt2(new Option(Option::V6, 2));
    OptionPtr opt3(new Option(Option::V6, 2));
176 177 178 179 180 181 182 183 184

    parent->addOption(opt1);
    parent->addOption(opt2);

    // getOption() test
    EXPECT_EQ(opt1, parent->getOption(1));
    EXPECT_EQ(opt2, parent->getOption(2));

    // expect NULL
185
    EXPECT_EQ(OptionPtr(), parent->getOption(4));
186 187 188 189 190 191 192 193

    // now there are 2 options of type 2
    parent->addOption(opt3);

    // let's delete one of them
    EXPECT_EQ(true, parent->delOption(2));

    // there still should be the other option 2
194
    EXPECT_NE(OptionPtr(), parent->getOption(2));
195 196 197 198 199

    // let's delete the other option 2
    EXPECT_EQ(true, parent->delOption(2));

    // no more options with type=2
200
    EXPECT_EQ(OptionPtr(), parent->getOption(2));
201 202 203 204 205 206 207

    // let's try to delete - should fail
    EXPECT_TRUE(false ==  parent->delOption(2));

    delete parent;
}

208 209
TEST_F(Pkt6Test, Timestamp) {
    Pkt6* pkt = new Pkt6(DHCPV6_SOLICIT, 0x020304);
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
    // 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);

    delete pkt;
230 231
}

232
}