#include <boost/algorithm/string.hpp>
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
#include <exceptions/exceptions.h>
+#include <dhcp/dhcp6.h>
#include <dhcp/iface_mgr.h>
#include "command_options.h"
isc_throw(InvalidParameter,
"without an inteface server is required");
}
+
+ // If DUID is not specified from command line we need to
+ // generate one.
+ if (duid_prefix_.size() == 0) {
+ generateDuidPrefix();
+ }
}
void
}
}
+void
+CommandOptions::generateDuidPrefix() {
+ using namespace boost::posix_time;
+ // Duid prefix will be most likely generated only once but
+ // it is ok if it is called more then once so we simply
+ // regenerate it and discard previous value.
+ duid_prefix_.clear();
+ const uint8_t duid_prefix_len = 14;
+ duid_prefix_.resize(duid_prefix_len);
+ // The first four octets consist of DUID LLT and hardware type.
+ duid_prefix_[0] = DUID_LLT >> 8;
+ duid_prefix_[1] = DUID_LLT & 0xff;
+ duid_prefix_[2] = HWTYPE_ETHERNET >> 8;
+ duid_prefix_[3] = HWTYPE_ETHERNET & 0xff;
+
+ // As described in RFC3315: 'the time value is the time
+ // that the DUID is generated represented in seconds
+ // since midnight (UTC), January 1, 2000, modulo 2^32.'
+ ptime now = microsec_clock::universal_time();
+ ptime duid_epoch(from_iso_string("20000101T000000"));
+ time_period period(duid_epoch, now);
+ uint32_t duration_sec = htonl(period.length().total_seconds());
+ memcpy(&duid_prefix_[4], &duration_sec, 4);
+
+ // Set link layer address (6 octets). This value may be
+ // randomized before sending a packet to simulate different
+ // clients.
+ memcpy(&duid_prefix_[8], &mac_prefix_[0], 6);
+}
+
uint8_t
CommandOptions::convertHexString(const std::string& text) const {
unsigned int ui = 0;
/// \param base Base string given as -b duid=0F1234
/// \throws isc::InvalidParameter if DUID is invalid
void decodeDuid(const std::string& base);
+
+ /// \brief Generates DUID-LLT (based on link layer address).
+ ///
+ /// Function generates DUID based on link layer address and
+ /// initiates duid_prefix_ value with it.
+ void generateDuidPrefix();
/// \brief Converts two-digit hexadecimal string to a byte
///
EXPECT_EQ(0, opt.getClientsNum());
// default mac
- uint8_t mac[6] = { 0x00, 0x0C, 0x01, 0x02, 0x03, 0x04 };
+ const uint8_t mac[6] = { 0x00, 0x0C, 0x01, 0x02, 0x03, 0x04 };
std::vector<uint8_t> v1 = opt.getMacPrefix();
ASSERT_EQ(6, v1.size());
EXPECT_TRUE(std::equal(v1.begin(), v1.end(), mac));
+ // Check if DUID is initialized. The DUID-LLT is expected
+ // to start with DUID_LLT value of 1 and hardware ethernet
+ // type equal to 1 (HWETHER_TYPE).
+ const uint8_t duid_llt_and_hw[4] = { 0x0, 0x1, 0x0, 0x1 };
+ // We assume DUID-LLT length 14. This includes 4 octets of
+ // DUID_LLT value, two octets of hardware type, 4 octets
+ // of time value and 6 octets of variable link layer (MAC)
+ // address.
+ const int duid_llt_size = 14;
+ std::vector<uint8_t> v2 = opt.getDuidPrefix();
+ ASSERT_EQ(duid_llt_size, opt.getDuidPrefix().size());
+ EXPECT_TRUE(std::equal(v2.begin(), v2.begin() + 4,
+ duid_llt_and_hw));
+
EXPECT_EQ(0, opt.getBase().size());
EXPECT_EQ(0, opt.getNumRequests().size());
EXPECT_EQ(0, opt.getPeriod());