BIND 10 trac1186, updated. a9043d3da8c85f523fd24910cd11856a265ea59c [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.

BIND 10 source code commits bind10-changes at lists.isc.org
Wed Aug 24 18:21:08 UTC 2011


The branch, trac1186 has been updated
       via  a9043d3da8c85f523fd24910cd11856a265ea59c (commit)
      from  38ca18436e35147ca7839ee95a4a976b81d7a124 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit a9043d3da8c85f523fd24910cd11856a265ea59c
Author: Tomek Mrugalski <tomasz at isc.org>
Date:   Wed Aug 24 20:20:34 2011 +0200

    [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.

-----------------------------------------------------------------------

Summary of changes:
 src/lib/dhcp/Makefile.am                           |    2 +
 src/lib/dhcp/libdhcp.cc                            |  112 ++++++++++++------
 src/lib/dhcp/libdhcp.h                             |   20 ++--
 src/lib/dhcp/option.cc                             |  104 +++++++++-------
 src/lib/dhcp/option.h                              |   57 ++++++----
 src/lib/dhcp/option6_ia.cc                         |  129 ++++++++++++++++++++
 src/lib/dhcp/option6_ia.h                          |   75 +++++++++++
 src/lib/dhcp/option6_iaaddr.cc                     |  129 ++++++++++++++++++++
 src/lib/dhcp/option6_iaaddr.h                      |   80 ++++++++++++
 src/lib/dhcp/pkt6.cc                               |   17 ++--
 src/lib/dhcp/tests/Makefile.am                     |    2 +
 src/lib/dhcp/tests/libdhcp_unittest.cc             |    3 +-
 src/lib/dhcp/tests/option6_ia_unittest.cc          |  106 ++++++++++++++++
 ...tion_unittest.cc => option6_iaaddr_unittest.cc} |   63 ++++++----
 src/lib/dhcp/tests/option_unittest.cc              |    4 +-
 src/lib/dhcp/tests/pkt6_unittest.cc                |    2 +-
 16 files changed, 755 insertions(+), 150 deletions(-)
 create mode 100644 src/lib/dhcp/option6_ia.cc
 create mode 100644 src/lib/dhcp/option6_ia.h
 create mode 100644 src/lib/dhcp/option6_iaaddr.cc
 create mode 100644 src/lib/dhcp/option6_iaaddr.h
 create mode 100644 src/lib/dhcp/tests/option6_ia_unittest.cc
 copy src/lib/dhcp/tests/{option_unittest.cc => option6_iaaddr_unittest.cc} (54%)

-----------------------------------------------------------------------
diff --git a/src/lib/dhcp/Makefile.am b/src/lib/dhcp/Makefile.am
index a0ddc56..973453c 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 d03fd3c..4e816ee 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 5ffa00f..32a6ef1 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 363c89c..0391487 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 24ae83e..de1e46d 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 0000000..c4edf3f
--- /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 0000000..20667e1
--- /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 0000000..47a1a64
--- /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 0000000..89412ab
--- /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 ecafce7..c6e8901 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 8de7f3c..f2b88bf 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 a35f0e4..116f91b 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 0000000..29dfcbf
--- /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 0000000..eae8260
--- /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 6087609..cb9034c 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 c68c414..0b3829f 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;




More information about the bind10-changes mailing list