summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTomek Mrugalski <tomasz@isc.org>2011-08-24 20:20:34 +0200
committerTomek Mrugalski <tomasz@isc.org>2011-10-14 16:24:03 +0200
commitaf27ec87f09d82918b96c9dd6d236b4e39989f7f (patch)
tree85a424f8a7ba13254221437875003253e9390463 /src
parent[1186] libdhcp now is able to parse and build packets and options. (diff)
downloadkea-af27ec87f09d82918b96c9dd6d236b4e39989f7f.tar.xz
kea-af27ec87f09d82918b96c9dd6d236b4e39989f7f.zip
[878] Support for IA and IAADDR options and suboptions added.
- IA support (Option6IA class) added. - Support for suboptions in IA option. - IAADDR support (Option6IAAddr class) added. - Initial tests added for new classes added.
Diffstat (limited to 'src')
-rw-r--r--src/lib/dhcp/Makefile.am2
-rw-r--r--src/lib/dhcp/libdhcp.cc112
-rw-r--r--src/lib/dhcp/libdhcp.h20
-rw-r--r--src/lib/dhcp/option.cc104
-rw-r--r--src/lib/dhcp/option.h57
-rw-r--r--src/lib/dhcp/option6_ia.cc129
-rw-r--r--src/lib/dhcp/option6_ia.h75
-rw-r--r--src/lib/dhcp/option6_iaaddr.cc129
-rw-r--r--src/lib/dhcp/option6_iaaddr.h80
-rw-r--r--src/lib/dhcp/pkt6.cc17
-rw-r--r--src/lib/dhcp/tests/Makefile.am2
-rw-r--r--src/lib/dhcp/tests/libdhcp_unittest.cc3
-rw-r--r--src/lib/dhcp/tests/option6_ia_unittest.cc106
-rw-r--r--src/lib/dhcp/tests/option6_iaaddr_unittest.cc96
-rw-r--r--src/lib/dhcp/tests/option_unittest.cc4
-rw-r--r--src/lib/dhcp/tests/pkt6_unittest.cc2
16 files changed, 812 insertions, 126 deletions
diff --git a/src/lib/dhcp/Makefile.am b/src/lib/dhcp/Makefile.am
index a0ddc56f13..973453cb39 100644
--- a/src/lib/dhcp/Makefile.am
+++ b/src/lib/dhcp/Makefile.am
@@ -11,6 +11,8 @@ lib_LTLIBRARIES = libdhcp.la
libdhcp_la_SOURCES =
libdhcp_la_SOURCES += libdhcp.cc libdhcp.h
libdhcp_la_SOURCES += option.cc option.h
+libdhcp_la_SOURCES += option6_ia.cc option6_ia.h
+libdhcp_la_SOURCES += option6_iaaddr.cc option6_iaaddr.h
libdhcp_la_SOURCES += dhcp6.h
libdhcp_la_SOURCES += pkt6.cc pkt6.h
diff --git a/src/lib/dhcp/libdhcp.cc b/src/lib/dhcp/libdhcp.cc
index d03fd3cf66..4e816ee1a7 100644
--- a/src/lib/dhcp/libdhcp.cc
+++ b/src/lib/dhcp/libdhcp.cc
@@ -16,10 +16,18 @@
#include <boost/shared_ptr.hpp>
#include "dhcp/libdhcp.h"
#include "config.h"
+#include "dhcp6.h"
+
+#include "option.h"
+#include "option6_ia.h"
+#include "option6_iaaddr.h"
using namespace std;
using namespace isc::dhcp;
+// static array with factory
+std::map<unsigned short, Option::Factory*> LibDHCP::v6factories_;
+
std::string
LibDHCP::version() {
return PACKAGE_VERSION;
@@ -39,70 +47,102 @@ LibDHCP::version() {
* @return offset to first byte after last parsed option
*/
unsigned int
-LibDHCP::unpackOptions6(boost::shared_array<char>& buf,
- int buf_len,
- unsigned short offset,
+LibDHCP::unpackOptions6(boost::shared_array<char> buf, unsigned int buf_len,
+ unsigned int offset, unsigned int parse_len,
isc::dhcp::Option::Option6Lst& options) {
- int len = buf_len - offset;
- while (len>4) {
- int opt_type = buf[offset]*256 + buf[offset+1];
+ if (offset + parse_len > buf_len) {
+ isc_throw(OutOfRange, "Option parse failed. Tried to parse "
+ << parse_len << " bytes at offset " << offset
+ << ": out of buffer");
+ }
+ unsigned int end = offset + parse_len;
+
+ while (offset<end) {
+ unsigned int opt_type = buf[offset]*256 + buf[offset+1];
offset += 2;
- len -= 2;
- int opt_len = buf[offset]*256 + buf[offset+1];
+ unsigned int opt_len = buf[offset]*256 + buf[offset+1];
offset += 2;
- len -= 2;
- if (opt_len > len) {
- cout << "Packet truncated. Unable to parse option " << opt_type
- << ". " << len << " bytes left in buffer, but option "
- << "len=" << opt_len << endl;
+ if (offset + opt_len > end ) {
+ cout << "Option " << opt_type << " truncated." << endl;
return (offset);
}
-
- boost::shared_ptr<Option> opt(new Option(Option::V6,
- opt_type,
- buf,
- offset,
- opt_len));
+ boost::shared_ptr<Option> opt;
+ switch (opt_type) {
+ case D6O_IA_NA:
+ case D6O_IA_PD:
+ // cout << "Creating Option6IA" << endl;
+ opt = boost::shared_ptr<Option>(new Option6IA(Option::V6,
+ opt_type,
+ buf, buf_len,
+ offset,
+ opt_len));
+ break;
+ case D6O_IAADDR:
+ // cout << "Creating Option6IAAddr" << endl;
+ opt = boost::shared_ptr<Option>(new Option6IAAddr(opt_type,
+ buf, buf_len,
+ offset, opt_len));
+ break;
+ default:
+ // cout << "Creating Option" << endl;
+ opt = boost::shared_ptr<Option>(new Option(Option::V6,
+ opt_type,
+ buf,
+ offset,
+ opt_len));
+ break;
+ }
// add option to options
options.insert(pair<int, boost::shared_ptr<Option> >(opt_type, opt));
offset += opt_len;
- len -= opt_len;
- cout << "Parse opt=" << opt_type << ", opt_len=" << opt_len << ", bytes left=" << len << endl;
- }
-
- if (len != 0) {
- cout << "There are " << len << " bytes left to parse." << endl;
}
return (offset);
}
unsigned int
-LibDHCP::packOptions6(boost::shared_array<char>& data,
- int data_len,
- unsigned short offset,
+LibDHCP::packOptions6(boost::shared_array<char> data,
+ unsigned int data_len,
+ unsigned int offset,
isc::dhcp::Option::Option6Lst& options) {
- char* buf = &data[offset];
- char* end = &data[data_len-1]; // last byte in shared array
try {
for (isc::dhcp::Option::Option6Lst::iterator it = options.begin();
it != options.end();
++it) {
unsigned short opt_len = (*it).second->len();
- if (buf+opt_len > end) {
- isc_throw(OutOfRange, "Failed to build option" <<
+ if (offset + opt_len > data_len) {
+ isc_throw(OutOfRange, "Failed to build option " <<
(*it).first << ": out of buffer");
}
- buf = (*it).second->pack(buf, opt_len);
- offset += opt_len;
- data_len -= opt_len;
+ offset = (*it).second->pack(data, data_len, offset);
}
}
catch (Exception e) {
cout << "Packet build failed." << endl;
return (-1);
}
- cout << "Packet built" << endl;
return (offset);
}
+
+bool
+LibDHCP::OptionFactorRegister(Option::Universe u,
+ unsigned short opt_type,
+ Option::Factory * factory) {
+ switch (u) {
+ case Option::V6: {
+ if (v6factories_.find(opt_type)!=v6factories_.end()) {
+ isc_throw(BadValue, "There is already DHCPv6 factory registered "
+ << "for option type " << opt_type);
+ }
+ v6factories_[opt_type]=factory;
+ return true;
+ }
+ case Option::V4:
+ default:{
+ isc_throw(BadValue, "This universe type is not supported yet.");
+ return false; // never happens
+ }
+ }
+
+}
diff --git a/src/lib/dhcp/libdhcp.h b/src/lib/dhcp/libdhcp.h
index 5ffa00fc9e..32a6ef1e1c 100644
--- a/src/lib/dhcp/libdhcp.h
+++ b/src/lib/dhcp/libdhcp.h
@@ -27,20 +27,24 @@ public:
LibDHCP();
static std::string version();
- bool parsePkt6(Pkt6& pkt);
+ bool parsePkt6(Pkt6& pkt);
bool builtPkt6(Pkt6& pkt);
-
static unsigned int
- packOptions6(boost::shared_array<char>& buf,
- int buf_len,
- unsigned short offset,
+ packOptions6(boost::shared_array<char> buf, unsigned int buf_len,
+ unsigned int offset,
isc::dhcp::Option::Option6Lst& options_);
static unsigned int
- unpackOptions6(boost::shared_array<char>& buf,
- int buf_len,
- unsigned short offset,
+ unpackOptions6(boost::shared_array<char> buf, unsigned int buf_len,
+ unsigned int offset, unsigned int parse_len,
isc::dhcp::Option::Option6Lst& options_);
+
+ bool OptionFactorRegister(Option::Universe u,
+ unsigned short type,
+ Option::Factory * factory);
+protected:
+ // pointers to factories that produce DHCPv6 options
+ static std::map<unsigned short, Option::Factory*> v6factories_;
};
}
diff --git a/src/lib/dhcp/option.cc b/src/lib/dhcp/option.cc
index 363c89c4bf..0391487368 100644
--- a/src/lib/dhcp/option.cc
+++ b/src/lib/dhcp/option.cc
@@ -32,9 +32,9 @@ Option::Option(Universe u, unsigned short type)
}
-Option::Option(Universe u, unsigned short type, boost::shared_array<char> buf,
+Option::Option(Universe u, unsigned short type, boost::shared_array<char> buf,
unsigned int offset, unsigned int len)
- :universe_(u), type_(type), data_(buf),
+ :universe_(u), type_(type), data_(buf),
offset_(offset),
len_(len) {
@@ -42,51 +42,60 @@ Option::Option(Universe u, unsigned short type, boost::shared_array<char> buf,
// TODO: universe must be in V4 and V6
}
-char* Option::pack(char* buf, unsigned int len) {
+unsigned int
+Option::pack(boost::shared_array<char> buf,
+ unsigned int buf_len,
+ unsigned int offset) {
switch (universe_) {
case V4:
- return pack4(buf, len);
+ return pack4(buf, buf_len, offset);
case V6:
- return pack6(buf, len);
+ return pack6(buf, buf_len, offset);
default:
isc_throw(BadValue, "Unknown universe defined for Option " << type_);
}
-
- return NULL; // should not happen
}
-char*
-Option::pack4(char* buf, unsigned short len) {
- if (this->len()>len) {
- isc_throw(OutOfRange, "Failed to pack v4 option=" <<
+
+unsigned int
+Option::pack4(boost::shared_array<char> buf,
+ unsigned int buf_len,
+ unsigned int offset) {
+ if ( offset+len() > buf_len ) {
+ isc_throw(OutOfRange, "Failed to pack v4 option=" <<
type_ << ",len=" << len_ << ": too small buffer.");
}
- buf[0] = type_;
- buf[1] = len_;
- buf += 2;
- memcpy(buf, &data_[0], len_);
+ char *ptr = &buf[offset];
+ ptr[0] = type_;
+ ptr[1] = len_;
+ ptr += 2;
+ memcpy(ptr, &data_[0], len_);
- return buf + len_;
+ return offset + len();
}
-char* Option::pack6(char* buf, unsigned short len) {
- if (this->len()>len) {
- isc_throw(OutOfRange, "Failed to pack v6 option=" <<
+unsigned int
+Option::pack6(boost::shared_array<char> buf,
+ unsigned int buf_len,
+ unsigned int offset) {
+ if ( offset+len() > buf_len ) {
+ isc_throw(OutOfRange, "Failed to pack v6 option=" <<
type_ << ",len=" << len_ << ": too small buffer.");
}
- *(uint16_t*)buf = htons(type_);
- buf += 2;
- *(uint16_t*)buf = htons(len_);
- buf += 2;
- memcpy(buf, &data_[0], len_);
-
- return buf + len_;
+ char * ptr = &buf[offset];
+ *(uint16_t*)ptr = htons(type_);
+ ptr += 2;
+ *(uint16_t*)ptr = htons(len_);
+ ptr += 2;
+ memcpy(ptr, &data_[0], len_);
+
+ return offset + len();
}
-unsigned int
-Option::unpack(boost::shared_array<char> buf,
+unsigned int
+Option::unpack(boost::shared_array<char> buf,
unsigned int buf_len,
- unsigned int offset,
+ unsigned int offset,
unsigned int parse_len) {
switch (universe_) {
case V4:
@@ -100,41 +109,41 @@ Option::unpack(boost::shared_array<char> buf,
return 0; // should not happen
}
-unsigned int
-Option::unpack4(boost::shared_array<char>,
+unsigned int
+Option::unpack4(boost::shared_array<char>,
+ unsigned int ,
unsigned int ,
- unsigned int ,
unsigned int ) {
isc_throw(Unexpected, "IPv4 support not implemented yet.");
return 0;
}
-/**
+/**
* Parses buffer and creates collection of Option objects.
- *
+ *
* @param buf pointer to buffer
* @param buf_len length of buf
* @param offset offset, where start parsing option
* @param parse_len how many bytes should be parsed
- *
+ *
* @return offset after last parsed option
*/
-unsigned int
-Option::unpack6(boost::shared_array<char> buf,
+unsigned int
+Option::unpack6(boost::shared_array<char> buf,
unsigned int buf_len,
- unsigned int offset,
+ unsigned int offset,
unsigned int parse_len) {
if (buf_len < offset+parse_len) {
- isc_throw(OutOfRange, "Failed to unpack DHCPv6 option len="
- << parse_len << " offset=" << offset << " from buffer (length="
+ isc_throw(OutOfRange, "Failed to unpack DHCPv6 option len="
+ << parse_len << " offset=" << offset << " from buffer (length="
<< buf_len << "): too small buffer.");
}
-
+
data_ = buf;
offset_ = offset;
len_ = buf_len;
- return LibDHCP::unpackOptions6(buf, buf_len, offset,
+ return LibDHCP::unpackOptions6(buf, buf_len, offset, parse_len,
optionLst_);
}
@@ -155,7 +164,7 @@ bool Option::valid() {
// total length of buffer is not stored. shared_array is not very useful.
// we should either add buf_len field or better replace shared_array
// with shared_ptr to array
- if (universe_ != V4 &&
+ if (universe_ != V4 &&
universe_ != V6) {
return (false);
}
@@ -163,9 +172,9 @@ bool Option::valid() {
return (true);
}
-/**
+/**
* Converts generic option to string.
- *
+ *
* @return string that represents option.
*/
std::string Option::toText() {
@@ -176,12 +185,12 @@ std::string Option::toText() {
if (i) {
tmp << ":";
}
- tmp << setfill('0') << setw(2) << hex << (unsigned short)data_[offset_+i];
+ tmp << setfill('0') << setw(2) << hex << (unsigned short)(unsigned char)data_[offset_+i];
}
return tmp.str();
}
-unsigned short
+unsigned short
Option::getType() {
return type_;
}
@@ -189,4 +198,3 @@ Option::getType() {
Option::~Option() {
}
-
diff --git a/src/lib/dhcp/option.h b/src/lib/dhcp/option.h
index 24ae83e29e..de1e46de0e 100644
--- a/src/lib/dhcp/option.h
+++ b/src/lib/dhcp/option.h
@@ -24,39 +24,46 @@ namespace dhcp {
class Option {
public:
+ enum Universe { V4, V6 };
typedef std::map<unsigned int, boost::shared_ptr<Option> > Option4Lst;
typedef std::multimap<unsigned int, boost::shared_ptr<Option> > Option6Lst;
-
- enum Universe { V4, V6 };
+ typedef boost::shared_ptr<Option> Factory(Option::Universe u,
+ unsigned short type,
+ boost::shared_array<char> buf,
+ unsigned int offset,
+ unsigned int len);
// ctor, used for options constructed, usually during transmission
- Option(Universe u, unsigned short type);
+ Option(Universe u, unsigned short type);
// ctor, used for received options
- // boost::shared_array allows sharing a buffer, but it requires that
+ // boost::shared_array allows sharing a buffer, but it requires that
// different instances share pointer to the whole array, not point
// to different elements in shared array. Therefore we need to share
// pointer to the whole array and remember offset where data for
// this option begins
- Option(Universe u, unsigned short type, boost::shared_array<char> buf,
- unsigned int offset,
+ Option(Universe u, unsigned short type, boost::shared_array<char> buf,
+ unsigned int offset,
unsigned int len);
- // writes option in wire-format to buf, returns pointer to first unused
+ // writes option in wire-format to buf, returns pointer to first unused
// byte after stored option
- virtual char* pack(char* buf, unsigned int len);
+ virtual unsigned int
+ pack(boost::shared_array<char> buf,
+ unsigned int buf_len,
+ unsigned int offset);
- // parses received buffer, returns pointer to first unused byte
+ // parses received buffer, returns pointer to first unused byte
// after parsed option
// TODO: Do we need this overload? Commented out for now
// virtual const char* unpack(const char* buf, unsigned int len);
// parses received buffer, returns offset to the first unused byte after
// parsed option
- virtual unsigned int
- unpack(boost::shared_array<char> buf,
+ virtual unsigned int
+ unpack(boost::shared_array<char> buf,
unsigned int buf_len,
- unsigned int offset,
+ unsigned int offset,
unsigned int parse_len);
virtual std::string toText();
@@ -65,23 +72,29 @@ public:
// returns data length (data length + DHCPv4/DHCPv6 option header)
virtual unsigned short len();
-
+
// returns if option is valid (e.g. option may be truncated)
- virtual bool valid();
+ virtual bool valid();
// just to force that every option has virtual dtor
- virtual ~Option();
+ virtual ~Option();
protected:
- virtual char* pack4(char* buf, unsigned short len);
- virtual char* pack6(char* buf, unsigned short len);
- virtual unsigned int unpack4(boost::shared_array<char> buf,
+ virtual unsigned int
+ pack4(boost::shared_array<char> buf,
+ unsigned int buf_len,
+ unsigned int offset);
+ virtual unsigned int
+ pack6(boost::shared_array<char> buf,
+ unsigned int buf_len,
+ unsigned int offset);
+ virtual unsigned int unpack4(boost::shared_array<char> buf,
unsigned int buf_len,
- unsigned int offset,
+ unsigned int offset,
unsigned int parse_len);
- virtual unsigned int unpack6(boost::shared_array<char> buf,
+ virtual unsigned int unpack6(boost::shared_array<char> buf,
unsigned int buf_len,
- unsigned int offset,
+ unsigned int offset,
unsigned int parse_len);
Universe universe_;
@@ -92,7 +105,7 @@ protected:
unsigned int offset_; // data is a shared_pointer that points out to the
// whole packet. offset_ specifies where data for
// this option begins.
- unsigned int len_; // length of data only. Use len() if you want to know
+ unsigned int len_; // length of data only. Use len() if you want to know
// proper length with option header overhead
char * value_;
diff --git a/src/lib/dhcp/option6_ia.cc b/src/lib/dhcp/option6_ia.cc
new file mode 100644
index 0000000000..c4edf3f63f
--- /dev/null
+++ b/src/lib/dhcp/option6_ia.cc
@@ -0,0 +1,129 @@
+// Copyright (C) 2011 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 <stdint.h>
+#include <arpa/inet.h>
+#include <sstream>
+#include "exceptions/exceptions.h"
+
+#include "libdhcp.h"
+#include "option6_ia.h"
+#include "dhcp6.h"
+
+using namespace std;
+using namespace isc;
+using namespace isc::dhcp;
+
+Option6IA::Option6IA(Universe u, unsigned short type, unsigned int iaid)
+ :Option(u, type), iaid_(iaid) {
+
+}
+
+
+Option6IA::Option6IA(Universe u, unsigned short type,
+ boost::shared_array<char> buf,
+ unsigned int buf_len,
+ unsigned int offset,
+ unsigned int option_len)
+ :Option(u, type) {
+ unpack(buf, buf_len, offset, option_len);
+}
+
+unsigned int
+Option6IA::pack(boost::shared_array<char> buf,
+ unsigned int buf_len,
+ unsigned int offset) {
+ if (len() > buf_len) {
+ isc_throw(OutOfRange, "Failed to pack IA option: len=" << len()
+ << ", buffer=" << buf_len << ": too small buffer.");
+ }
+
+ char* ptr = &buf[offset];
+ *(uint16_t*)ptr = htons(type_);
+ ptr += 2;
+ buf_len -= 2;
+ *(uint16_t*)ptr = htons(len());
+ ptr += 2;
+ buf_len -= 2;
+
+ *(uint32_t*)ptr = htonl(iaid_);
+ ptr += 4;
+ buf_len -= 4;
+
+ *(uint32_t*)ptr = htonl(t1_);
+ ptr += 4;
+ buf_len -= 4;
+
+ *(uint32_t*)ptr = htonl(t2_);
+ ptr += 4;
+ buf_len -= 4;
+
+ offset = LibDHCP::packOptions6(buf, buf_len, offset+16, optionLst_);
+ return offset;
+}
+
+unsigned int
+Option6IA::unpack(boost::shared_array<char> buf,
+ unsigned int buf_len,
+ unsigned int offset,
+ unsigned int parse_len) {
+ if (parse_len<12 || offset+12>buf_len) {
+ isc_throw(OutOfRange, "Option " << type_ << " truncated");
+ }
+ iaid_ = ntohl(*(uint32_t*)&buf[offset]);
+ offset +=4;
+ t1_ = ntohl(*(uint32_t*)&buf[offset]);
+ offset +=4;
+ t2_ = ntohl(*(uint32_t*)&buf[offset]);
+ offset +=4;
+ offset = LibDHCP::unpackOptions6(buf, buf_len, offset,
+ parse_len - 12, optionLst_);
+
+ return (offset);
+}
+
+std::string Option6IA::toText() {
+ stringstream tmp;
+ switch (type_) {
+ case D6O_IA_NA:
+ tmp << "IA_NA";
+ break;
+ case D6O_IA_PD:
+ tmp << "IA_PD";
+ break;
+ }
+ tmp << " iaid=" << iaid_ << " t1=" << t1_ << " t2=" << t2_
+ << " " << optionLst_.size() << " sub-options:" << endl;
+
+ for (Option6Lst::const_iterator opt=optionLst_.begin();
+ opt!=optionLst_.end();
+ ++opt) {
+ tmp << " " << (*opt).second->toText();
+ }
+ return tmp.str();
+}
+
+unsigned short Option6IA::len() {
+
+ unsigned short length = 12; // header
+
+ // length of all suboptions
+ for (Option::Option6Lst::iterator it = optionLst_.begin();
+ it != optionLst_.end();
+ ++it) {
+ length += (*it).second->len();
+ }
+ return (length);
+}
+
diff --git a/src/lib/dhcp/option6_ia.h b/src/lib/dhcp/option6_ia.h
new file mode 100644
index 0000000000..20667e1b09
--- /dev/null
+++ b/src/lib/dhcp/option6_ia.h
@@ -0,0 +1,75 @@
+// Copyright (C) 2011 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 OPTION_IA_H_
+#define OPTION_IA_H_
+
+#include "option.h"
+
+namespace isc {
+namespace dhcp {
+
+class Option6IA: public Option {
+
+public:
+ // ctor, used for options constructed, usually during transmission
+ Option6IA(Universe u, unsigned short type, unsigned int iaid);
+
+ // ctor, used for received options
+ // boost::shared_array allows sharing a buffer, but it requires that
+ // different instances share pointer to the whole array, not point
+ // to different elements in shared array. Therefore we need to share
+ // pointer to the whole array and remember offset where data for
+ // this option begins
+ Option6IA(Universe u, unsigned short type, boost::shared_array<char> buf,
+ unsigned int buf_len,
+ unsigned int offset,
+ unsigned int len);
+
+ // writes option in wire-format to buf, returns pointer to first unused
+ // byte after stored option
+ unsigned int
+ pack(boost::shared_array<char> buf, unsigned int buf_len,
+ unsigned int offset);
+
+ // parses received buffer, returns offset to the first unused byte after
+ // parsed option
+ virtual unsigned int
+ unpack(boost::shared_array<char> buf,
+ unsigned int buf_len,
+ unsigned int offset,
+ unsigned int parse_len);
+
+ virtual std::string toText();
+
+ void setT1(unsigned int t1) { t1_=t1; }
+ void setT2(unsigned int t2) { t2_=t2; }
+
+ unsigned int getIAID() { return iaid_; }
+ unsigned int getT1() { return t1_; }
+ unsigned int getT2() { return t2_; }
+
+ // returns data length (data length + DHCPv4/DHCPv6 option header)
+ virtual unsigned short len();
+
+protected:
+ unsigned int iaid_;
+ unsigned int t1_;
+ unsigned int t2_;
+};
+
+} // isc::dhcp namespace
+} // isc namespace
+
+#endif /* OPTION_IA_H_ */
diff --git a/src/lib/dhcp/option6_iaaddr.cc b/src/lib/dhcp/option6_iaaddr.cc
new file mode 100644
index 0000000000..47a1a64b93
--- /dev/null
+++ b/src/lib/dhcp/option6_iaaddr.cc
@@ -0,0 +1,129 @@
+// Copyright (C) 2011 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 <stdint.h>
+#include <arpa/inet.h>
+#include <sstream>
+#include "exceptions/exceptions.h"
+
+#include "libdhcp.h"
+#include "option6_iaaddr.h"
+#include "dhcp6.h"
+#include "io_address.h"
+
+using namespace std;
+using namespace isc;
+using namespace isc::dhcp;
+using namespace isc::asiolink;
+
+Option6IAAddr::Option6IAAddr(unsigned short type,
+ isc::asiolink::IOAddress addr,
+ unsigned int pref,
+ unsigned int valid)
+ :Option(V6, type), addr_(addr), preferred_(pref),
+ valid_(valid) {
+}
+
+Option6IAAddr::Option6IAAddr(unsigned short type,
+ boost::shared_array<char> buf,
+ unsigned int buf_len,
+ unsigned int offset,
+ unsigned int option_len)
+ :Option(V6, type), addr_(IOAddress("::")) {
+ unpack(buf, buf_len, offset, option_len);
+}
+
+unsigned int
+Option6IAAddr::pack(boost::shared_array<char> buf,
+ unsigned int buf_len,
+ unsigned int offset) {
+ if (len() > buf_len) {
+ isc_throw(OutOfRange, "Failed to pack IA option: len=" << len()
+ << ", buffer=" << buf_len << ": too small buffer.");
+ }
+
+ *(uint16_t*)&buf[offset] = htons(type_);
+ offset += 2;
+ *(uint16_t*)&buf[offset] = htons(len());
+ offset += 2;
+
+ memcpy(&buf[offset], addr_.getAddress().to_v6().to_bytes().data(), 16);
+ offset += 16;
+
+ *(uint32_t*)&buf[offset] = htonl(preferred_);
+ offset += 4;
+ *(uint32_t*)&buf[offset] = htonl(valid_);
+ offset += 4;
+
+ // parse suboption (there shouldn't be any)
+ offset = LibDHCP::packOptions6(buf, buf_len, offset, optionLst_);
+ return offset;
+}
+
+unsigned int
+Option6IAAddr::unpack(boost::shared_array<char> buf,
+ unsigned int buf_len,
+ unsigned int offset,
+ unsigned int parse_len) {
+ if (parse_len<24 || offset+24>buf_len) {
+ isc_throw(OutOfRange, "Option " << type_ << " truncated");
+ }
+
+ // 16 bytes: IPv6 address
+ /// TODO Implement fromBytes() method in IOAddress
+ char addr_str[INET6_ADDRSTRLEN];
+ inet_ntop(AF_INET6, &buf[offset], addr_str,INET6_ADDRSTRLEN);
+ addr_ = IOAddress(string(addr_str));
+ offset += 16;
+
+ preferred_ = ntohl(*(uint32_t*)&buf[offset]);
+ offset +=4;
+
+ valid_ = ntohl(*(uint32_t*)&buf[offset]);
+ offset +=4;
+ offset = LibDHCP::unpackOptions6(buf, buf_len, offset,
+ parse_len - 24, optionLst_);
+
+ return offset;
+}
+
+std::string Option6IAAddr::toText() {
+ stringstream tmp;
+ tmp << "addr: " << addr_.toText() << ", preferred-lft=" << preferred_
+ << ", valid-lft=" << valid_ << endl;
+
+ for (Option6Lst::const_iterator opt=optionLst_.begin();
+ opt!=optionLst_.end();
+ ++opt) {
+ tmp << " " << (*opt).second->toText() << endl;
+ }
+ return tmp.str();
+}
+
+unsigned short Option6IAAddr::len() {
+
+ unsigned short length = 24; // header
+
+ // length of all suboptions
+ // TODO implement:
+ // protected: unsigned short Option::lenHelper(int header_size);
+
+ for (Option::Option6Lst::iterator it = optionLst_.begin();
+ it != optionLst_.end();
+ ++it) {
+ length += (*it).second->len();
+ }
+ return (length);
+}
+
diff --git a/src/lib/dhcp/option6_iaaddr.h b/src/lib/dhcp/option6_iaaddr.h
new file mode 100644
index 0000000000..89412ab211
--- /dev/null
+++ b/src/lib/dhcp/option6_iaaddr.h
@@ -0,0 +1,80 @@
+// Copyright (C) 2011 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 OPTION6_IAADDR_H_
+#define OPTION6_IAADDR_H_
+
+#include "io_address.h"
+#include "option.h"
+
+namespace isc {
+namespace dhcp {
+
+class Option6IAAddr: public Option {
+
+public:
+ // ctor, used for options constructed, usually during transmission
+ Option6IAAddr(unsigned short type,
+ isc::asiolink::IOAddress addr,
+ unsigned int prefered,
+ unsigned int valid);
+
+ // ctor, used for received options
+ // boost::shared_array allows sharing a buffer, but it requires that
+ // different instances share pointer to the whole array, not point
+ // to different elements in shared array. Therefore we need to share
+ // pointer to the whole array and remember offset where data for
+ // this option begins
+ Option6IAAddr(unsigned short type, boost::shared_array<char> buf,
+ unsigned int buf_len,
+ unsigned int offset,
+ unsigned int len);
+
+ // writes option in wire-format to buf, returns pointer to first unused
+ // byte after stored option
+ unsigned int
+ pack(boost::shared_array<char> buf, unsigned int buf_len,
+ unsigned int offset);
+
+ // parses received buffer, returns offset to the first unused byte after
+ // parsed option
+ virtual unsigned int
+ unpack(boost::shared_array<char> buf,
+ unsigned int buf_len,
+ unsigned int offset,
+ unsigned int parse_len);
+
+ virtual std::string toText();
+
+ void setAddress(isc::asiolink::IOAddress addr) { addr_ = addr; }
+ void setPreferred(unsigned int pref) { preferred_=pref; }
+ void setValid(unsigned int valid) { valid_=valid; }
+
+ isc::asiolink::IOAddress getAddress() { return addr_; }
+ unsigned int getPreferred() { return preferred_; }
+ unsigned int getValid() { return valid_; }
+
+ // returns data length (data length + DHCPv4/DHCPv6 option header)
+ virtual unsigned short len();
+
+protected:
+ isc::asiolink::IOAddress addr_;
+ unsigned int preferred_;
+ unsigned int valid_;
+};
+
+} // isc::dhcp namespace
+} // isc namespace
+
+#endif /* OPTION_IA_H_ */
diff --git a/src/lib/dhcp/pkt6.cc b/src/lib/dhcp/pkt6.cc
index ecafce756c..c6e890127e 100644
--- a/src/lib/dhcp/pkt6.cc
+++ b/src/lib/dhcp/pkt6.cc
@@ -66,7 +66,7 @@ unsigned short Pkt6::len() {
length += (*it).second->len();
}
- return length;
+ return (length);
}
@@ -87,7 +87,7 @@ Pkt6::pack() {
default:
isc_throw(BadValue, "Invalid protocol specified (non-TCP, non-UDP)");
}
- return false; // never happens
+ return (false); // never happens
}
@@ -123,10 +123,10 @@ Pkt6::packUDP() {
}
catch (Exception e) {
cout << "Packet build failed." << endl;
- return false;
+ return (false);
}
cout << "Packet built, len=" << len() << endl;
- return true;
+ return (true);
}
@@ -160,7 +160,7 @@ Pkt6::unpack() {
default:
isc_throw(BadValue, "Invalid protocol specified (non-TCP, non-UDP)");
}
- return false; // never happens
+ return (false); // never happens
}
/**
@@ -173,7 +173,7 @@ Pkt6::unpackUDP() {
if (data_len_ < 4) {
std::cout << "DHCPv6 packet truncated. Only " << data_len_
<< " bytes. Need at least 4." << std::endl;
- return false;
+ return (false);
}
msg_type_ = data_[0];
transid_ = (data_[1] << 16) + (data_[2] << 8) + data_[3];
@@ -181,6 +181,7 @@ Pkt6::unpackUDP() {
unsigned int offset = LibDHCP::unpackOptions6(data_,
data_len_,
4, //offset
+ data_len_ - 4,
options_);
if (offset != data_len_) {
cout << "DHCPv6 packet contains trailing garbage. Parsed "
@@ -188,7 +189,7 @@ Pkt6::unpackUDP() {
<< endl;
// just a warning. Ignore trailing garbage and continue
}
- return true;
+ return (true);
}
/**
@@ -249,7 +250,7 @@ Pkt6::getOption(unsigned short opt_type) {
*/
unsigned char
Pkt6::getType() {
- return msg_type_;
+ return (msg_type_);
}
Pkt6::~Pkt6() {
diff --git a/src/lib/dhcp/tests/Makefile.am b/src/lib/dhcp/tests/Makefile.am
index 8de7f3c4aa..f2b88bf2f1 100644
--- a/src/lib/dhcp/tests/Makefile.am
+++ b/src/lib/dhcp/tests/Makefile.am
@@ -17,6 +17,8 @@ if HAVE_GTEST
TESTS += libdhcp_unittests
libdhcp_unittests_SOURCES = run_unittests.cc
libdhcp_unittests_SOURCES += ../libdhcp.h ../libdhcp.cc libdhcp_unittest.cc
+libdhcp_unittests_SOURCES += ../option6_iaaddr.h ../option6_iaaddr.cc option6_iaaddr_unittest.cc
+libdhcp_unittests_SOURCES += ../option6_ia.h ../option6_ia.cc option6_ia_unittest.cc
libdhcp_unittests_SOURCES += ../option.h ../option.cc option_unittest.cc
libdhcp_unittests_SOURCES += ../pkt6.h ../pkt6.cc pkt6_unittest.cc
diff --git a/src/lib/dhcp/tests/libdhcp_unittest.cc b/src/lib/dhcp/tests/libdhcp_unittest.cc
index a35f0e4879..116f91be25 100644
--- a/src/lib/dhcp/tests/libdhcp_unittest.cc
+++ b/src/lib/dhcp/tests/libdhcp_unittest.cc
@@ -20,6 +20,7 @@
#include <gtest/gtest.h>
#include "dhcp/libdhcp.h"
+#include "config.h"
using namespace std;
using namespace isc;
@@ -35,7 +36,7 @@ public:
TEST_F(LibDhcpTest, basic) {
// dummy test
- EXPECT_EQ(LibDHCP::version(), "0");
+ EXPECT_EQ(LibDHCP::version(), PACKAGE_VERSION);
}
}
diff --git a/src/lib/dhcp/tests/option6_ia_unittest.cc b/src/lib/dhcp/tests/option6_ia_unittest.cc
new file mode 100644
index 0000000000..29dfcbf827
--- /dev/null
+++ b/src/lib/dhcp/tests/option6_ia_unittest.cc
@@ -0,0 +1,106 @@
+// Copyright (C) 2011 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 <iostream>
+#include <sstream>
+
+#include <arpa/inet.h>
+#include <gtest/gtest.h>
+
+#include "dhcp/dhcp6.h"
+#include "dhcp/option.h"
+#include "dhcp/option6_ia.h"
+
+using namespace std;
+using namespace isc;
+using namespace isc::dhcp;
+
+namespace {
+class Option6IATest : public ::testing::Test {
+public:
+ Option6IATest() {
+ }
+};
+
+TEST_F(Option6IATest, basic) {
+
+ boost::shared_array<char> simple_buf(new char[128]);
+ for (int i=0; i<128; i++)
+ simple_buf[i] = 0;
+ simple_buf[0]=0xa1; // iaid
+ simple_buf[1]=0xa2;
+ simple_buf[2]=0xa3;
+ simple_buf[3]=0xa4;
+
+ simple_buf[4]=0x81; // T1
+ simple_buf[5]=0x02;
+ simple_buf[6]=0x03;
+ simple_buf[7]=0x04;
+
+ simple_buf[8]=0x84; // T2
+ simple_buf[9]=0x03;
+ simple_buf[10]=0x02;
+ simple_buf[11]=0x01;
+
+ // create an option (unpack content)
+ Option6IA* opt = new Option6IA(Option::V6,
+ D6O_IA_NA,
+ simple_buf,
+ 128,
+ 0,
+ 12);
+
+ EXPECT_EQ(D6O_IA_NA, opt->getType());
+ EXPECT_EQ(0xa1a2a3a4, opt->getIAID());
+ EXPECT_EQ(0x81020304, opt->getT1());
+ EXPECT_EQ(0x84030201, opt->getT2());
+
+ // pack this option again in the same buffer, but in
+ // different place
+ int offset = opt->pack(simple_buf, 128, 60);
+
+ // 4 bytes header + 4 bytes content
+ EXPECT_EQ(12, opt->len());
+ EXPECT_EQ(D6O_IA_NA, opt->getType());
+
+ EXPECT_EQ(offset, 76); // 60 + lenght(IA_NA) = 76
+
+ // check if pack worked properly:
+ // if option type is correct
+ EXPECT_EQ(D6O_IA_NA, simple_buf[60]*256 + simple_buf[61]);
+
+ // if option length is correct
+ EXPECT_EQ(12, simple_buf[62]*256 + simple_buf[63]);
+
+ // if iaid is correct
+ unsigned int iaid = htonl(*(unsigned int*)&simple_buf[64]);
+ EXPECT_EQ(0xa1a2a3a4, iaid );
+
+ // if T1 is correct
+ EXPECT_EQ(0x81020304, (simple_buf[68] << 24) +
+ (simple_buf[69] << 16) +
+ (simple_buf[70] << 8) +
+ (simple_buf[71]) );
+
+ // if T1 is correct
+ EXPECT_EQ(0x84030201, (simple_buf[72] << 24) +
+ (simple_buf[73] << 16) +
+ (simple_buf[74] << 8) +
+ (simple_buf[75]) );
+
+ delete opt;
+}
+
+}
diff --git a/src/lib/dhcp/tests/option6_iaaddr_unittest.cc b/src/lib/dhcp/tests/option6_iaaddr_unittest.cc
new file mode 100644
index 0000000000..eae8260f16
--- /dev/null
+++ b/src/lib/dhcp/tests/option6_iaaddr_unittest.cc
@@ -0,0 +1,96 @@
+// Copyright (C) 2011 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 <iostream>
+#include <sstream>
+
+#include <arpa/inet.h>
+#include <gtest/gtest.h>
+
+#include "dhcp/dhcp6.h"
+#include "dhcp/option.h"
+#include "dhcp/option6_iaaddr.h"
+
+using namespace std;
+using namespace isc;
+using namespace isc::dhcp;
+
+namespace {
+class Option6IAAddrTest : public ::testing::Test {
+public:
+ Option6IAAddrTest() {
+ }
+};
+
+TEST_F(Option6IAAddrTest, basic) {
+
+ boost::shared_array<char> simple_buf(new char[128]);
+ for (int i=0; i<128; i++)
+ simple_buf[i] = 0;
+ simple_buf[0]=0x20;
+ simple_buf[1]=0x01;
+ simple_buf[2]=0x0d;
+ simple_buf[3]=0xb8;
+ simple_buf[4]=0x00;
+ simple_buf[5]=0x01;
+ simple_buf[12]=0xde;
+ simple_buf[13]=0xad;
+ simple_buf[14]=0xbe;
+ simple_buf[15]=0xef; // 2001:db8:1::dead:beef
+
+ simple_buf[16]=0x00;
+ simple_buf[17]=0x00;
+ simple_buf[18]=0x03;
+ simple_buf[19]=0xe8; // 1000
+
+ simple_buf[20]=0xb2;
+ simple_buf[21]=0xd0;
+ simple_buf[22]=0x5e;
+ simple_buf[23]=0x00; // 3.000.000.000
+
+ // create an option (unpack content)
+ Option6IAAddr* opt = new Option6IAAddr(D6O_IAADDR,
+ simple_buf,
+ 128,
+ 0,
+ 24);
+
+ // pack this option again in the same buffer, but in
+ // different place
+ int offset = opt->pack(simple_buf, 128, 50);
+
+ EXPECT_EQ(78, offset);
+
+ // 4 bytes header + 4 bytes content
+ EXPECT_EQ("2001:db8:1::dead:beef", opt->getAddress().toText());
+ EXPECT_EQ(1000, opt->getPreferred());
+ EXPECT_EQ(3000000000, opt->getValid());
+
+ EXPECT_EQ(D6O_IAADDR, opt->getType());
+
+ // check if pack worked properly:
+ // if option type is correct
+ EXPECT_EQ(D6O_IAADDR, simple_buf[50]*256 + simple_buf[51]);
+
+ // if option length is correct
+ EXPECT_EQ(24, simple_buf[52]*256 + simple_buf[53]);
+
+ // if option content is correct
+ EXPECT_EQ(0, memcmp(&simple_buf[0], &simple_buf[54],24));
+
+ delete opt;
+}
+
+}
diff --git a/src/lib/dhcp/tests/option_unittest.cc b/src/lib/dhcp/tests/option_unittest.cc
index 6087609611..cb9034cc1b 100644
--- a/src/lib/dhcp/tests/option_unittest.cc
+++ b/src/lib/dhcp/tests/option_unittest.cc
@@ -52,13 +52,13 @@ TEST_F(OptionTest, basic) {
// pack this option again in the same buffer, but in
// different place
- char* offset18 = opt->pack(&simple_buf[10], 8);
+ int offset18 = opt->pack(simple_buf, 128, 10);
// 4 bytes header + 4 bytes content
EXPECT_EQ(8, opt->len());
EXPECT_EQ(D6O_CLIENTID, opt->getType());
- EXPECT_EQ(offset18, &simple_buf[0]+18);
+ EXPECT_EQ(offset18, 18);
// check if pack worked properly:
// if option type is correct
diff --git a/src/lib/dhcp/tests/pkt6_unittest.cc b/src/lib/dhcp/tests/pkt6_unittest.cc
index c68c4143d5..0b3829faf4 100644
--- a/src/lib/dhcp/tests/pkt6_unittest.cc
+++ b/src/lib/dhcp/tests/pkt6_unittest.cc
@@ -56,7 +56,7 @@ Pkt6 *capture1() {
pkt->ifindex_ = 2;
pkt->iface_ = "eth0";
pkt->data_[0]=1;
- pkt->data_[1]=192; pkt->data_[2]=129; pkt->data_[3]=6; pkt->data_[4]=0;
+ pkt->data_[1]=01; pkt->data_[2]=02; pkt->data_[3]=03; pkt->data_[4]=0;
pkt->data_[5]=1; pkt->data_[6]=0; pkt->data_[7]=14; pkt->data_[8]=0;
pkt->data_[9]=1; pkt->data_[10]=0; pkt->data_[11]=1; pkt->data_[12]=21;
pkt->data_[13]=158; pkt->data_[14]=60; pkt->data_[15]=22; pkt->data_[16]=0;