BIND 10 trac826, updated. b38415d5eb6577d2d998e92ac5968971613a1743 [trac826] update lib/dhcp and bin/dhcp6

BIND 10 source code commits bind10-changes at lists.isc.org
Thu Oct 20 21:13:31 UTC 2011


The branch, trac826 has been updated
       via  b38415d5eb6577d2d998e92ac5968971613a1743 (commit)
      from  f76e44186e127f56537263d779e794857cdc1072 (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 b38415d5eb6577d2d998e92ac5968971613a1743
Author: Francis Dupont <fdupont at isc.org>
Date:   Thu Oct 20 23:13:16 2011 +0200

    [trac826] update lib/dhcp and bin/dhcp6
    
    According to the last master and trac1224 (thanks to Tomasz)

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

Summary of changes:
 src/bin/dhcp6/Makefile.am                          |   20 +-
 src/bin/dhcp6/dhcp6.h                              |  184 ---------
 src/bin/dhcp6/dhcp6_srv.cc                         |  208 +++++++++-
 src/bin/dhcp6/dhcp6_srv.h                          |  150 ++++++-
 src/bin/dhcp6/iface_mgr.cc                         |  147 +++-----
 src/bin/dhcp6/iface_mgr.h                          |  281 ++++++++++----
 src/bin/dhcp6/main.cc                              |   12 +-
 src/bin/dhcp6/pkt6.cc                              |   47 ---
 src/bin/dhcp6/pkt6.h                               |   62 ---
 src/bin/dhcp6/tests/Makefile.am                    |    7 +-
 src/bin/dhcp6/tests/dhcp6_srv_unittest.cc          |  106 +++++-
 src/bin/dhcp6/tests/iface_mgr_unittest.cc          |  206 ++++++++--
 src/bin/dhcp6/tests/pkt6_unittest.cc               |   48 ---
 src/lib/asiolink/io_address.cc                     |   12 +-
 src/lib/asiolink/io_address.h                      |   10 +-
 src/lib/asiolink/tests/io_address_unittest.cc      |    8 +-
 src/lib/dhcp/Makefile.am                           |   15 +-
 src/lib/dhcp/dhcp4.h                               |  191 +++++++++
 src/lib/dhcp/dhcp6.h                               |   20 +-
 src/lib/dhcp/libdhcp.cc                            |   45 +--
 src/lib/dhcp/libdhcp.h                             |   17 +-
 src/lib/dhcp/option.cc                             |   92 +++--
 src/lib/dhcp/option.h                              |  156 +++++---
 src/lib/dhcp/option6_addrlst.cc                    |   62 ++--
 src/lib/dhcp/option6_addrlst.h                     |   26 +-
 src/lib/dhcp/option6_ia.cc                         |  106 +++---
 src/lib/dhcp/option6_ia.h                          |  110 ++++--
 src/lib/dhcp/option6_iaaddr.cc                     |   92 ++---
 src/lib/dhcp/option6_iaaddr.h                      |  138 +++++--
 src/lib/dhcp/pkt4.cc                               |  180 ++++++++
 src/lib/dhcp/pkt4.h                                |  371 +++++++++++++++++
 src/lib/dhcp/pkt6.cc                               |  172 ++------
 src/lib/dhcp/pkt6.h                                |  284 ++++++++++----
 src/lib/dhcp/tests/Makefile.am                     |    3 +-
 src/lib/dhcp/tests/libdhcp_unittest.cc             |   48 +--
 src/lib/dhcp/tests/option6_addrlst_unittest.cc     |  139 ++++---
 src/lib/dhcp/tests/option6_ia_unittest.cc          |   96 +++--
 src/lib/dhcp/tests/option6_iaaddr_unittest.cc      |   67 ++--
 src/lib/dhcp/tests/option_unittest.cc              |   74 +++--
 src/lib/dhcp/tests/pkt4_unittest.cc                |  428 ++++++++++++++++++++
 src/lib/dhcp/tests/pkt6_unittest.cc                |   85 ++++-
 src/lib/dhcp/tests/run_unittests.cc                |    6 +-
 src/lib/util/io_utilities.h                        |   45 ++-
 src/lib/util/tests/io_utilities_unittest.cc        |   50 +++
 win32build/VS2008/b10-dhcp6/b10-dhcp6.vcproj       |   12 -
 .../VS2008/b10-dhcp6_tests/b10-dhcp6_tests.vcproj  |   12 -
 win32build/VS2008/libdhcp/libdhcp.vcproj           |   12 +
 .../VS2008/libdhcp_tests/libdhcp_tests.vcproj      |    4 +
 .../VS2008/libutil_tests/libutil_tests.vcproj      |    4 +-
 win32build/VS2010+x64/b10-dhcp6/b10-dhcp6.vcxproj  |    3 -
 .../VS2010+x64/b10-dhcp6/b10-dhcp6.vcxproj.filters |    9 -
 .../b10-dhcp6_tests/b10-dhcp6_tests.vcxproj        |    3 -
 .../b10-dhcp6_tests.vcxproj.filters                |    9 -
 win32build/VS2010+x64/libdhcp/libdhcp.vcxproj      |    3 +
 .../VS2010+x64/libdhcp/libdhcp.vcxproj.filters     |    9 +
 .../VS2010+x64/libdhcp_tests/libdhcp_tests.vcxproj |    3 +-
 .../libdhcp_tests/libdhcp_tests.vcxproj.filters    |    5 +-
 .../VS2010+x64/libutil_tests/libutil_tests.vcxproj |   10 +-
 win32build/VS2010/b10-dhcp6/b10-dhcp6.vcxproj      |    3 -
 .../VS2010/b10-dhcp6/b10-dhcp6.vcxproj.filters     |    9 -
 .../VS2010/b10-dhcp6_tests/b10-dhcp6_tests.vcxproj |    3 -
 .../b10-dhcp6_tests.vcxproj.filters                |    9 -
 win32build/VS2010/libdhcp/libdhcp.vcxproj          |    3 +
 win32build/VS2010/libdhcp/libdhcp.vcxproj.filters  |    9 +
 .../VS2010/libdhcp_tests/libdhcp_tests.vcxproj     |    3 +-
 .../libdhcp_tests/libdhcp_tests.vcxproj.filters    |    3 +
 .../VS2010/libutil_tests/libutil_tests.vcxproj     |    6 +-
 67 files changed, 3280 insertions(+), 1492 deletions(-)
 delete mode 100644 src/bin/dhcp6/dhcp6.h
 delete mode 100644 src/bin/dhcp6/pkt6.cc
 delete mode 100644 src/bin/dhcp6/pkt6.h
 delete mode 100644 src/bin/dhcp6/tests/pkt6_unittest.cc
 create mode 100644 src/lib/dhcp/dhcp4.h
 create mode 100644 src/lib/dhcp/pkt4.cc
 create mode 100644 src/lib/dhcp/pkt4.h
 create mode 100644 src/lib/dhcp/tests/pkt4_unittest.cc

-----------------------------------------------------------------------
diff --git a/src/bin/dhcp6/Makefile.am b/src/bin/dhcp6/Makefile.am
index 805d6bb..690ba5f 100644
--- a/src/bin/dhcp6/Makefile.am
+++ b/src/bin/dhcp6/Makefile.am
@@ -4,9 +4,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
 AM_CPPFLAGS += -I$(top_srcdir)/src/bin -I$(top_builddir)/src/bin
 AM_CPPFLAGS += -I$(top_srcdir)/src/lib/dns -I$(top_builddir)/src/lib/dns
 AM_CPPFLAGS += -I$(top_srcdir)/src/lib/cc -I$(top_builddir)/src/lib/cc
-AM_CPPFLAGS += -I$(top_srcdir)/src/lib/asiolink
-AM_CPPFLAGS += -I$(top_builddir)/src/lib/asiolink
-AM_CPPFLAGS += $(BOOST_INCLUDES)
+ AM_CPPFLAGS += $(BOOST_INCLUDES)
 
 AM_CXXFLAGS = $(B10_CXXFLAGS)
 
@@ -31,20 +29,14 @@ spec_config.h: spec_config.h.pre
 
 BUILT_SOURCES = spec_config.h
 pkglibexec_PROGRAMS = b10-dhcp6
-b10_dhcp6_SOURCES = main.cc iface_mgr.cc pkt6.cc dhcp6_srv.cc
-b10_dhcp6_SOURCES += iface_mgr.h pkt6.h dhcp6_srv.h dhcp6.h
-b10_dhcp6_LDADD =  $(top_builddir)/src/lib/datasrc/libdatasrc.la
-b10_dhcp6_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
-b10_dhcp6_LDADD += $(top_builddir)/src/lib/util/libutil.la
-b10_dhcp6_LDADD += $(top_builddir)/src/lib/config/libcfgclient.la
-b10_dhcp6_LDADD += $(top_builddir)/src/lib/cc/libcc.la
+
+b10_dhcp6_SOURCES = main.cc iface_mgr.cc dhcp6_srv.cc
+b10_dhcp6_SOURCES += iface_mgr.h dhcp6_srv.h
+
+b10_dhcp6_LDADD = $(top_builddir)/src/lib/dhcp/libdhcp.la
 b10_dhcp6_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
-b10_dhcp6_LDADD += $(top_builddir)/src/lib/asiodns/libasiodns.la
 b10_dhcp6_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
 b10_dhcp6_LDADD += $(top_builddir)/src/lib/log/liblog.la
-b10_dhcp6_LDADD += $(top_builddir)/src/lib/xfr/libxfr.la
-b10_dhcp6_LDADD += $(top_builddir)/src/lib/server_common/libserver_common.la
-b10_dhcp6_LDADD += $(SQLITE_LIBS)
 
 # TODO: config.h.in is wrong because doesn't honor pkgdatadir
 # and can't use @datadir@ because doesn't expand default ${prefix}
diff --git a/src/bin/dhcp6/dhcp6.h b/src/bin/dhcp6/dhcp6.h
deleted file mode 100644
index b5512f3..0000000
--- a/src/bin/dhcp6/dhcp6.h
+++ /dev/null
@@ -1,184 +0,0 @@
-// Copyright (C) 2006-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 DHCP6_H
-#define DHCP6_H
-
-/* DHCPv6 Option codes: */
-
-#define D6O_CLIENTID				1 /* RFC3315 */
-#define D6O_SERVERID				2
-#define D6O_IA_NA				3
-#define D6O_IA_TA				4
-#define D6O_IAADDR				5
-#define D6O_ORO					6
-#define D6O_PREFERENCE				7
-#define D6O_ELAPSED_TIME			8
-#define D6O_RELAY_MSG				9
-/* Option code 10 unassigned. */
-#define D6O_AUTH				11
-#define D6O_UNICAST				12
-#define D6O_STATUS_CODE				13
-#define D6O_RAPID_COMMIT			14
-#define D6O_USER_CLASS				15
-#define D6O_VENDOR_CLASS			16
-#define D6O_VENDOR_OPTS				17
-#define D6O_INTERFACE_ID			18
-#define D6O_RECONF_MSG				19
-#define D6O_RECONF_ACCEPT			20
-#define D6O_SIP_SERVERS_DNS			21 /* RFC3319 */
-#define D6O_SIP_SERVERS_ADDR			22 /* RFC3319 */
-#define D6O_NAME_SERVERS			23 /* RFC3646 */
-#define D6O_DOMAIN_SEARCH			24 /* RFC3646 */
-#define D6O_IA_PD				25 /* RFC3633 */
-#define D6O_IAPREFIX				26 /* RFC3633 */
-#define D6O_NIS_SERVERS				27 /* RFC3898 */
-#define D6O_NISP_SERVERS			28 /* RFC3898 */
-#define D6O_NIS_DOMAIN_NAME			29 /* RFC3898 */
-#define D6O_NISP_DOMAIN_NAME			30 /* RFC3898 */
-#define D6O_SNTP_SERVERS			31 /* RFC4075 */
-#define D6O_INFORMATION_REFRESH_TIME		32 /* RFC4242 */
-#define D6O_BCMCS_SERVER_D			33 /* RFC4280 */
-#define D6O_BCMCS_SERVER_A			34 /* RFC4280 */
-/* 35 is unassigned */
-#define D6O_GEOCONF_CIVIC			36 /* RFC4776 */
-#define D6O_REMOTE_ID				37 /* RFC4649 */
-#define D6O_SUBSCRIBER_ID			38 /* RFC4580 */
-#define D6O_CLIENT_FQDN				39 /* RFC4704 */
-#define D6O_PANA_AGENT				40 /* paa-option */
-#define D6O_NEW_POSIX_TIMEZONE			41 /* RFC4833 */
-#define D6O_NEW_TZDB_TIMEZONE			42 /* RFC4833 */
-#define D6O_ERO					43 /* RFC4994 */
-#define D6O_LQ_QUERY				44 /* RFC5007 */
-#define D6O_CLIENT_DATA				45 /* RFC5007 */
-#define D6O_CLT_TIME				46 /* RFC5007 */
-#define D6O_LQ_RELAY_DATA			47 /* RFC5007 */
-#define D6O_LQ_CLIENT_LINK			48 /* RFC5007 */
-
-/* 
- * Status Codes, from RFC 3315 section 24.4, and RFC 3633, 5007.
- */
-#define STATUS_Success		 0
-#define STATUS_UnspecFail	 1
-#define STATUS_NoAddrsAvail	 2
-#define STATUS_NoBinding	 3
-#define STATUS_NotOnLink	 4 
-#define STATUS_UseMulticast	 5 
-#define STATUS_NoPrefixAvail	 6
-#define STATUS_UnknownQueryType	 7
-#define STATUS_MalformedQuery	 8
-#define STATUS_NotConfigured	 9
-#define STATUS_NotAllowed	10
-
-/* 
- * DHCPv6 message types, defined in section 5.3 of RFC 3315 
- */
-#define DHCPV6_SOLICIT		    1
-#define DHCPV6_ADVERTISE	    2
-#define DHCPV6_REQUEST		    3
-#define DHCPV6_CONFIRM		    4
-#define DHCPV6_RENEW		    5
-#define DHCPV6_REBIND		    6
-#define DHCPV6_REPLY		    7
-#define DHCPV6_RELEASE		    8
-#define DHCPV6_DECLINE		    9
-#define DHCPV6_RECONFIGURE	   10
-#define DHCPV6_INFORMATION_REQUEST 11
-#define DHCPV6_RELAY_FORW	   12
-#define DHCPV6_RELAY_REPL	   13
-#define DHCPV6_LEASEQUERY	   14
-#define DHCPV6_LEASEQUERY_REPLY    15
-
-extern const char *dhcpv6_type_names[];
-extern const int dhcpv6_type_name_max;
-
-/* DUID type definitions (RFC3315 section 9).
- */
-#define DUID_LLT	1
-#define DUID_EN		2
-#define DUID_LL		3
-
-/* Offsets into IA_*'s where Option spaces commence.  */
-#define IA_NA_OFFSET 12 /* IAID, T1, T2, all 4 octets each */
-#define IA_TA_OFFSET  4 /* IAID only, 4 octets */
-#define IA_PD_OFFSET 12 /* IAID, T1, T2, all 4 octets each */
-
-/* Offset into IAADDR's where Option spaces commence. */
-#define IAADDR_OFFSET 24
-
-/* Offset into IAPREFIX's where Option spaces commence. */
-#define IAPREFIX_OFFSET 25
-
-/* Offset into LQ_QUERY's where Option spaces commence. */
-#define LQ_QUERY_OFFSET 17
-
-/* 
- * DHCPv6 well-known multicast addressess, from section 5.1 of RFC 3315 
- */
-#define ALL_DHCP_RELAY_AGENTS_AND_SERVERS "ff02::1:2"
-#define ALL_DHCP_SERVERS "ff05::1:3"
-
-#define DHCP6_CLIENT_PORT 546
-#define DHCP6_SERVER_PORT 547
-
-/*
- * DHCPv6 Retransmission Constants (RFC3315 section 5.5, RFC 5007)
- */
-
-#define SOL_MAX_DELAY     1
-#define SOL_TIMEOUT       1
-#define SOL_MAX_RT      120
-#define REQ_TIMEOUT       1
-#define REQ_MAX_RT       30
-#define REQ_MAX_RC       10
-#define CNF_MAX_DELAY     1
-#define CNF_TIMEOUT       1
-#define CNF_MAX_RT        4
-#define CNF_MAX_RD       10
-#define REN_TIMEOUT      10
-#define REN_MAX_RT      600
-#define REB_TIMEOUT      10
-#define REB_MAX_RT      600
-#define INF_MAX_DELAY     1
-#define INF_TIMEOUT       1
-#define INF_MAX_RT      120
-#define REL_TIMEOUT       1
-#define REL_MAX_RC        5
-#define DEC_TIMEOUT       1
-#define DEC_MAX_RC        5
-#define REC_TIMEOUT       2
-#define REC_MAX_RC        8
-#define HOP_COUNT_LIMIT  32
-#define LQ6_TIMEOUT       1
-#define LQ6_MAX_RT       10
-#define LQ6_MAX_RC        5
-
-/* Leasequery query-types (RFC 5007) */
-
-#define LQ6QT_BY_ADDRESS	1
-#define LQ6QT_BY_CLIENTID	2
-
-/*
- * DUID time starts 2000-01-01.
- * This constant is the number of seconds since 1970-01-01,
- * when the Unix epoch began.
- */
-#define DUID_TIME_EPOCH 946684800
-
-/* Information-Request Time option (RFC 4242) */
-
-#define IRT_DEFAULT	86400
-#define IRT_MINIMUM	600
-
-#endif
diff --git a/src/bin/dhcp6/dhcp6_srv.cc b/src/bin/dhcp6/dhcp6_srv.cc
index 101b079..03fd357 100644
--- a/src/bin/dhcp6/dhcp6_srv.cc
+++ b/src/bin/dhcp6/dhcp6_srv.cc
@@ -12,14 +12,20 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
-#include <config.h>
+#include "config.h"
 
-#include "dhcp6/pkt6.h"
+#include "dhcp/dhcp6.h"
+#include "dhcp/pkt6.h"
 #include "dhcp6/iface_mgr.h"
 #include "dhcp6/dhcp6_srv.h"
+#include "dhcp/option6_ia.h"
+#include "dhcp/option6_iaaddr.h"
+#include "asiolink/io_address.h"
 
 using namespace std;
 using namespace isc;
+using namespace isc::dhcp;
+using namespace isc::asiolink;
 
 Dhcpv6Srv::Dhcpv6Srv() {
     cout << "Initialization" << endl;
@@ -27,6 +33,12 @@ Dhcpv6Srv::Dhcpv6Srv() {
     // first call to instance() will create IfaceMgr (it's a singleton)
     // it may throw something if things go wrong
     IfaceMgr::instance();
+
+    /// @todo: instantiate LeaseMgr here once it is imlpemented.
+
+    setServerID();
+
+    shutdown = false;
 }
 
 Dhcpv6Srv::~Dhcpv6Srv() {
@@ -35,27 +47,187 @@ Dhcpv6Srv::~Dhcpv6Srv() {
 
 bool
 Dhcpv6Srv::run() {
-    for (;;) {
-        Pkt6* pkt;
+    while (!shutdown) {
+        boost::shared_ptr<Pkt6> query; // client's message
+        boost::shared_ptr<Pkt6> rsp;   // server's response
 
-        pkt = IfaceMgr::instance().receive();
+        query = IfaceMgr::instance().receive();
 
-        if (pkt) {
-            cout << "Received " << pkt->data_len_ << " bytes, echoing back."
-                 << endl;
-            IfaceMgr::instance().send(*pkt);
-            delete pkt;
-        }
+        if (query) {
+            if (!query->unpack()) {
+                cout << "Failed to parse incoming packet" << endl;
+                continue;
+            }
+            switch (query->getType()) {
+            case DHCPV6_SOLICIT:
+                rsp = processSolicit(query);
+                break;
+            case DHCPV6_REQUEST:
+                rsp = processRequest(query);
+                break;
+            case DHCPV6_RENEW:
+                rsp = processRenew(query);
+                break;
+            case DHCPV6_REBIND:
+                rsp = processRebind(query);
+                break;
+            case DHCPV6_CONFIRM:
+                rsp = processConfirm(query);
+                break;
+            case DHCPV6_RELEASE:
+                rsp = processRelease(query);
+                break;
+            case DHCPV6_DECLINE:
+                rsp = processDecline(query);
+                break;
+            case DHCPV6_INFORMATION_REQUEST:
+                rsp = processInfRequest(query);
+                break;
+            default:
+                cout << "Unknown pkt type received:"
+                     << query->getType() << endl;
+            }
 
-	// TODO add support for config session (see src/bin/auth/main.cc)
-	//      so this daemon can be controlled from bob
-#ifdef _WIN32
-        Sleep(1000);
-#else
-        sleep(1);
-#endif
+            cout << "Received " << query->data_len_ << " bytes packet type="
+                 << query->getType() << endl;
+            cout << query->toText();
+            if (rsp) {
+                rsp->remote_addr_ = query->remote_addr_;
+                rsp->local_addr_ = query->local_addr_;
+                rsp->remote_port_ = DHCP6_CLIENT_PORT;
+                rsp->local_port_ = DHCP6_SERVER_PORT;
+                rsp->ifindex_ = query->ifindex_;
+                rsp->iface_ = query->iface_;
+                cout << "Replying with:" << rsp->getType() << endl;
+                cout << rsp->toText();
+                cout << "----" << endl;
+                if (rsp->pack()) {
+                    cout << "#### pack successful." << endl;
+                }
+                IfaceMgr::instance().send(rsp);
+            }
+        }
 
+        // TODO add support for config session (see src/bin/auth/main.cc)
+        //      so this daemon can be controlled from bob
     }
 
     return (true);
 }
+
+void
+Dhcpv6Srv::setServerID() {
+    /// TODO implement this for real once interface detection is done.
+    /// Use hardcoded server-id for now
+
+    boost::shared_array<uint8_t> srvid(new uint8_t[14]);
+    srvid[0] = 0;
+    srvid[1] = 1; // DUID type 1 = DUID-LLT (see section 9.2 of RFC3315)
+    srvid[2] = 0;
+    srvid[3] = 6; // HW type = ethernet (I think. I'm typing this from my head
+                  // in hotel, without Internet connection)
+    for (int i=4; i<14; i++) {
+        srvid[i]=i-4;
+    }
+    serverid_ = boost::shared_ptr<Option>(new Option(Option::V6,
+                                                     D6O_SERVERID,
+                                                     srvid,
+                                                     0, 14));
+}
+
+boost::shared_ptr<Pkt6>
+Dhcpv6Srv::processSolicit(boost::shared_ptr<Pkt6> solicit) {
+
+    boost::shared_ptr<Pkt6> reply(new Pkt6(DHCPV6_ADVERTISE,
+                                           solicit->getTransid(),
+                                           Pkt6::UDP));
+
+    /// TODO Rewrite this once LeaseManager is implemented.
+
+    // answer client's IA (this is mostly a dummy,
+    // so let's answer only first IA and hope there is only one)
+    boost::shared_ptr<Option> ia_opt = solicit->getOption(D6O_IA_NA);
+    if (ia_opt) {
+        // found IA
+        Option* tmp = ia_opt.get();
+        Option6IA* ia_req = dynamic_cast<Option6IA*>(tmp);
+        if (ia_req) {
+            boost::shared_ptr<Option6IA>
+                ia_rsp(new Option6IA(D6O_IA_NA, ia_req->getIAID()));
+            ia_rsp->setT1(1500);
+            ia_rsp->setT2(2600);
+            boost::shared_ptr<Option6IAAddr>
+                addr(new Option6IAAddr(D6O_IAADDR,
+                                       IOAddress("2001:db8:1234:5678::abcd"),
+                                       5000, 7000));
+            ia_rsp->addOption(addr);
+            reply->addOption(ia_rsp);
+        }
+    }
+
+    // add client-id
+    boost::shared_ptr<Option> clientid = solicit->getOption(D6O_CLIENTID);
+    if (clientid) {
+        reply->addOption(clientid);
+    }
+
+    // add server-id
+    reply->addOption(getServerID());
+    return reply;
+}
+
+boost::shared_ptr<Pkt6>
+Dhcpv6Srv::processRequest(boost::shared_ptr<Pkt6> request) {
+    /// TODO: Implement processRequest() for real
+    boost::shared_ptr<Pkt6> reply = processSolicit(request);
+    reply->setType(DHCPV6_REPLY);
+    return reply;
+}
+
+boost::shared_ptr<Pkt6>
+Dhcpv6Srv::processRenew(boost::shared_ptr<Pkt6> renew) {
+    boost::shared_ptr<Pkt6> reply(new Pkt6(DHCPV6_REPLY,
+                                           renew->getTransid(),
+                                           Pkt6::UDP));
+    return reply;
+}
+
+boost::shared_ptr<Pkt6>
+Dhcpv6Srv::processRebind(boost::shared_ptr<Pkt6> rebind) {
+    boost::shared_ptr<Pkt6> reply(new Pkt6(DHCPV6_REPLY,
+                                           rebind->getTransid(),
+                                           Pkt6::UDP));
+    return reply;
+}
+
+boost::shared_ptr<Pkt6>
+Dhcpv6Srv::processConfirm(boost::shared_ptr<Pkt6> confirm) {
+    boost::shared_ptr<Pkt6> reply(new Pkt6(DHCPV6_REPLY,
+                                           confirm->getTransid(),
+                                           Pkt6::UDP));
+    return reply;
+}
+
+boost::shared_ptr<Pkt6>
+Dhcpv6Srv::processRelease(boost::shared_ptr<Pkt6> release) {
+    boost::shared_ptr<Pkt6> reply(new Pkt6(DHCPV6_REPLY,
+                                           release->getTransid(),
+                                           Pkt6::UDP));
+    return reply;
+}
+
+boost::shared_ptr<Pkt6>
+Dhcpv6Srv::processDecline(boost::shared_ptr<Pkt6> decline) {
+    boost::shared_ptr<Pkt6> reply(new Pkt6(DHCPV6_REPLY,
+                                           decline->getTransid(),
+                                           Pkt6::UDP));
+    return reply;
+}
+
+boost::shared_ptr<Pkt6>
+Dhcpv6Srv::processInfRequest(boost::shared_ptr<Pkt6> infRequest) {
+    boost::shared_ptr<Pkt6> reply(new Pkt6(DHCPV6_REPLY,
+                                           infRequest->getTransid(),
+                                           Pkt6::UDP));
+    return reply;
+}
diff --git a/src/bin/dhcp6/dhcp6_srv.h b/src/bin/dhcp6/dhcp6_srv.h
index a02f5f6..4daef3a 100644
--- a/src/bin/dhcp6/dhcp6_srv.h
+++ b/src/bin/dhcp6/dhcp6_srv.h
@@ -15,26 +15,142 @@
 #ifndef DHCPV6_SRV_H
 #define DHCPV6_SRV_H
 
+#include <boost/shared_ptr.hpp>
+#include <boost/noncopyable.hpp>
+#include "dhcp/pkt6.h"
+#include "dhcp/option.h"
 #include <iostream>
 
 namespace isc {
-    class Dhcpv6Srv {
-    private:
-        // defined private on purpose. We don't want to have more than
-        // one copy
-        Dhcpv6Srv(const Dhcpv6Srv& src);
-        Dhcpv6Srv& operator=(const Dhcpv6Srv& src);
-
-    public:
-        // default constructor
-        Dhcpv6Srv();
-        ~Dhcpv6Srv();
-
-        bool run();
-
-    protected:
-        bool shutdown;
-    };
+
+namespace dhcp {
+/// @brief DHCPv6 server service.
+///
+/// This singleton class represents DHCPv6 server. It contains all
+/// top-level methods and routines necessary for server operation.
+/// In particular, it instantiates IfaceMgr, loads or generates DUID
+/// that is going to be used as server-identifier, receives incoming
+/// packets, processes them, manages leases assignment and generates
+/// appropriate responses.
+class Dhcpv6Srv : public boost::noncopyable {
+
+public:
+    /// @brief Default constructor.
+    ///
+    /// Instantiates necessary services, required to run DHCPv6 server.
+    /// In particular, creates IfaceMgr that will be responsible for
+    /// network interaction. Will instantiate lease manager, and load
+    /// old or create new DUID.
+    Dhcpv6Srv();
+
+    /// @brief Destructor. Used during DHCPv6 service shutdown.
+    ~Dhcpv6Srv();
+
+    /// @brief Returns server-intentifier option
+    ///
+    /// @return server-id option
+    boost::shared_ptr<isc::dhcp::Option>
+    getServerID() { return serverid_; }
+
+    /// @brief Main server processing loop.
+    ///
+    /// Main server processing loop. Receives incoming packets, verifies
+    /// their correctness, generates appropriate answer (if needed) and
+    /// transmits respones.
+    ///
+    /// @return true, if being shut down gracefully, fail if experienced
+    ///         critical error.
+    bool run();
+
+protected:
+    /// @brief Processes incoming SOLICIT and returns response.
+    ///
+    /// Processes received SOLICIT message and verifies that its sender
+    /// should be served. In particular IA, TA and PD options are populated
+    /// with to-be assinged addresses, temporary addresses and delegated
+    /// prefixes, respectively. In the usual 4 message exchange, server is
+    /// expected to respond with ADVERTISE message. However, if client
+    /// requests rapid-commit and server supports it, REPLY will be sent
+    /// instead of ADVERTISE and requested leases will be assigned
+    /// immediately.
+    ///
+    /// @param solicit SOLICIT message received from client
+    ///
+    /// @return ADVERTISE, REPLY message or NULL
+    boost::shared_ptr<Pkt6>
+    processSolicit(boost::shared_ptr<Pkt6> solicit);
+
+    /// @brief Processes incoming REQUEST and returns REPLY response.
+    ///
+    /// Processes incoming REQUEST message and verifies that its sender
+    /// should be served. In particular IA, TA and PD options are populated
+    /// with assinged addresses, temporary addresses and delegated
+    /// prefixes, respectively. Uses LeaseMgr to allocate or update existing
+    /// leases.
+    ///
+    /// @param request a message received from client
+    ///
+    /// @return REPLY message or NULL
+    boost::shared_ptr<Pkt6>
+    processRequest(boost::shared_ptr<Pkt6> request);
+
+    /// @brief Stub function that will handle incoming RENEW messages.
+    ///
+    /// @param renew message received from client
+    boost::shared_ptr<Pkt6>
+    processRenew(boost::shared_ptr<Pkt6> renew);
+
+    /// @brief Stub function that will handle incoming REBIND messages.
+    ///
+    /// @param rebind message received from client
+    boost::shared_ptr<Pkt6>
+    processRebind(boost::shared_ptr<Pkt6> rebind);
+
+    /// @brief Stub function that will handle incoming CONFIRM messages.
+    ///
+    /// @param confirm message received from client
+    boost::shared_ptr<Pkt6>
+    processConfirm(boost::shared_ptr<Pkt6> confirm);
+
+    /// @brief Stub function that will handle incoming RELEASE messages.
+    ///
+    /// @param release message received from client
+    boost::shared_ptr<Pkt6>
+    processRelease(boost::shared_ptr<Pkt6> release);
+
+    /// @brief Stub function that will handle incoming DECLINE messages.
+    ///
+    /// @param decline message received from client
+    boost::shared_ptr<Pkt6>
+    processDecline(boost::shared_ptr<Pkt6> decline);
+
+    /// @brief Stub function that will handle incoming INF-REQUEST messages.
+    ///
+    /// @param infRequest message received from client
+    boost::shared_ptr<Pkt6>
+    processInfRequest(boost::shared_ptr<Pkt6> infRequest);
+
+    /// @brief Sets server-identifier.
+    ///
+    /// This method attempts to set server-identifier DUID. It loads it
+    /// from a file. If file load fails, it generates new DUID using
+    /// interface link-layer addresses (EUI-64) + timestamp (DUID type
+    /// duid-llt, see RFC3315, section 9.2). If there are no suitable
+    /// interfaces present, exception it thrown
+    ///
+    /// @throws isc::Unexpected Failed to read DUID file and no suitable
+    ///         interfaces for new DUID generation are detected.
+    void setServerID();
+
+    /// server DUID (to be sent in server-identifier option)
+    boost::shared_ptr<isc::dhcp::Option> serverid_;
+
+    /// indicates if shutdown is in progress. Setting it to true will
+    /// initiate server shutdown procedure.
+    volatile bool shutdown;
 };
 
+}; // namespace isc::dhcp
+}; // namespace isc
+
 #endif // DHCP6_SRV_H
diff --git a/src/bin/dhcp6/iface_mgr.cc b/src/bin/dhcp6/iface_mgr.cc
index ca41440..f54cba4 100644
--- a/src/bin/dhcp6/iface_mgr.cc
+++ b/src/bin/dhcp6/iface_mgr.cc
@@ -23,17 +23,18 @@
 #include <arpa/inet.h>
 #endif
 
+#include "dhcp/dhcp6.h"
 #include "dhcp6/iface_mgr.h"
-#include "dhcp6/dhcp6.h"
 #include "exceptions/exceptions.h"
 
 using namespace std;
 using namespace isc;
 using namespace isc::asiolink;
+using namespace isc::dhcp;
 
 namespace isc {
 
-// IfaceMgr is a singleton implementation
+/// IfaceMgr is a singleton implementation
 IfaceMgr* IfaceMgr::instance_ = 0;
 
 void
@@ -49,14 +50,16 @@ IfaceMgr::instanceCreate() {
 
 IfaceMgr&
 IfaceMgr::instance() {
-    if (instance_ == 0)
+    if (instance_ == 0) {
         instanceCreate();
+    }
     return (*instance_);
 }
 
 IfaceMgr::Iface::Iface(const std::string& name, int ifindex)
     :name_(name), ifindex_(ifindex), mac_len_(0) {
-    memset(mac_, 0, 20);
+
+    memset(mac_, 0, sizeof(mac_));
 }
 
 std::string
@@ -69,18 +72,26 @@ IfaceMgr::Iface::getFullName() const {
 std::string
 IfaceMgr::Iface::getPlainMac() const {
     ostringstream tmp;
-    for (int i=0; i<mac_len_; i++) {
-        tmp.fill('0');
+    tmp.fill('0');
+    tmp << hex;
+    for (int i = 0; i < mac_len_; i++) {
         tmp.width(2);
-        tmp << (hex) << (int) mac_[i];
-        if (i<mac_len_-1) {
+        tmp << mac_[i];
+        if (i < mac_len_-1) {
             tmp << ":";
         }
     }
     return (tmp.str());
 }
 
-IfaceMgr::IfaceMgr() {
+IfaceMgr::IfaceMgr()
+#ifdef _WIN32
+    :control_buf_len_(WSA_CMSG_SPACE(sizeof(struct in6_pktinfo))),
+#else
+    :control_buf_len_(CMSG_SPACE(sizeof(struct in6_pktinfo))),
+#endif
+     control_buf_(new char[control_buf_len_])
+{
 
     cout << "IfaceMgr initialization." << endl;
 
@@ -88,8 +99,8 @@ IfaceMgr::IfaceMgr() {
         // required for sending/receiving packets
         // let's keep it in front, just in case someone
         // wants to send anything during initialization
-        control_buf_len_ = CMSG_SPACE(sizeof(struct in6_pktinfo));
-        control_buf_ = new char[control_buf_len_];
+
+        // control_buf_ = boost::scoped_array<char>();
 
         detectIfaces();
 
@@ -108,11 +119,8 @@ IfaceMgr::IfaceMgr() {
 }
 
 IfaceMgr::~IfaceMgr() {
-    if (control_buf_) {
-        delete [] control_buf_;
-        control_buf_ = 0;
-        control_buf_len_ = 0;
-    }
+    // control_buf_ is deleted automatically (scoped_ptr)
+    control_buf_len_ = 0;
 }
 
 void
@@ -245,18 +253,6 @@ IfaceMgr::getIface(const std::string& ifname) {
     return (NULL); // not found
 }
 
-
-/**
- * Opens UDP/IPv6 socket and binds it to specific address, interface and port.
- *
- * @param ifname name of the interface
- * @param addr address to be bound.
- * @param port UDP port.
- * @param mcast Should multicast address also be bound?
- *
- * @return socket descriptor, if socket creation, binding and multicast
- * group join were all successful. -1 otherwise.
- */
 int
 IfaceMgr::openSocket(const std::string& ifname,
                      const IOAddress& addr,
@@ -377,15 +373,6 @@ IfaceMgr::openSocket(const std::string& ifname,
     return (sock);
 }
 
-/**
- * joins multicast group
- *
- * @param sock socket file descriptor
- * @param ifname name of the interface (DHCPv6 uses link-scoped mc groups)
- * @param mcast multicast address to join (string)
- *
- * @return true if joined successfully, false otherwise
- */
 bool
 IfaceMgr::joinMcast(int sock, const std::string& ifname,
 const std::string & mcast) {
@@ -411,19 +398,8 @@ const std::string & mcast) {
     return (true);
 }
 
-/**
- * Sends UDP packet over IPv6.
- *
- * All parameters for actual transmission are specified in
- * Pkt6 structure itself. That includes destination address,
- * src/dst port and interface over which data will be sent.
- *
- * @param pkt A packet object that is going to be sent.
- *
- * @return True, if transmission was successful. False otherwise.
- */
 bool
-IfaceMgr::send(Pkt6 &pkt) {
+IfaceMgr::send(boost::shared_ptr<Pkt6>& pkt) {
 #ifdef _WIN32
     WSAMSG m;
     WSABUF v;
@@ -438,7 +414,7 @@ IfaceMgr::send(Pkt6 &pkt) {
 #else
     struct cmsghdr *cmsg;
 #endif
-    memset(control_buf_, 0, control_buf_len_);
+    memset(&control_buf_[0], 0, control_buf_len_);
 
     /*
      * Initialize our message header structure.
@@ -451,17 +427,17 @@ IfaceMgr::send(Pkt6 &pkt) {
     sockaddr_in6 to;
     memset(&to, 0, sizeof(to));
     to.sin6_family = AF_INET6;
-    to.sin6_port = htons(pkt.remote_port_);
+    to.sin6_port = htons(pkt->remote_port_);
     memcpy(&to.sin6_addr,
-           pkt.remote_addr_.getAddress().to_v6().to_bytes().data(),
+           pkt->remote_addr_.getAddress().to_v6().to_bytes().data(),
            16);
-    to.sin6_scope_id = pkt.ifindex_;
+    to.sin6_scope_id = pkt->ifindex_;
 
 #ifdef _WIN32
     m.name = (struct sockaddr *)&to;
     m.namelen = sizeof(to);
 #else
-    m.msg_name = &to;
+    m.msg_name = (struct sockaddr *)&to;
     m.msg_namelen = sizeof(to);
 #endif
 
@@ -471,13 +447,13 @@ IfaceMgr::send(Pkt6 &pkt) {
      * of data to send, so we declare a single vector entry.)
      */
 #ifdef _WIN32
-    v.buf = (char *) &pkt.data_[0];
-    v.len = pkt.data_len_;
+    v.buf = (char *) &pkt->data_[0];
+    v.len = pkt->data_len_;
     m.lpBuffers = &v;
     m.dwBufferCount = 1;
 #else
-    v.iov_base = (char *) &pkt.data_[0];
-    v.iov_len = pkt.data_len_;
+    v.iov_base = (char *) &pkt->data_[0];
+    v.iov_len = pkt->data_len_;
     m.msg_iov = &v;
     m.msg_iovlen = 1;
 #endif
@@ -491,18 +467,18 @@ IfaceMgr::send(Pkt6 &pkt) {
      * kernel decide what that should be.
      */
 #ifdef _WIN32
-    m.Control.buf = control_buf_;
+    m.Control.buf = &control_buf_[0];
     m.Control.len = control_buf_len_;
-    cmsg = CMSG_FIRSTHDR(&m);
+    cmsg = WSA_CMSG_FIRSTHDR(&m);
     cmsg->cmsg_level = IPPROTO_IPV6;
     cmsg->cmsg_type = IPV6_PKTINFO;
     cmsg->cmsg_len = WSA_CMSG_LEN(sizeof(*pktinfo));
     pktinfo = (struct in6_pktinfo *)WSA_CMSG_DATA(cmsg);
     memset(pktinfo, 0, sizeof(*pktinfo));
-    pktinfo->ipi6_ifindex = pkt.ifindex_;
+    pktinfo->ipi6_ifindex = pkt->ifindex_;
     m.Control.len = cmsg->cmsg_len;
 #else
-    m.msg_control = control_buf_;
+    m.msg_control = &control_buf_[0];
     m.msg_controllen = control_buf_len_;
     cmsg = CMSG_FIRSTHDR(&m);
     cmsg->cmsg_level = IPPROTO_IPV6;
@@ -510,7 +486,7 @@ IfaceMgr::send(Pkt6 &pkt) {
     cmsg->cmsg_len = CMSG_LEN(sizeof(*pktinfo));
     pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsg);
     memset(pktinfo, 0, sizeof(*pktinfo));
-    pktinfo->ipi6_ifindex = pkt.ifindex_;
+    pktinfo->ipi6_ifindex = pkt->ifindex_;
     m.msg_controllen = cmsg->cmsg_len;
 #endif
 
@@ -528,26 +504,16 @@ IfaceMgr::send(Pkt6 &pkt) {
     }
     cout << "Sent " << result << " bytes." << endl;
 
-    cout << "Sent " << pkt.data_len_ << " bytes over "
-         << pkt.iface_ << "/" << pkt.ifindex_ << " interface: "
-         << " dst=" << pkt.remote_addr_.toText()
-         << ", src=" << pkt.local_addr_.toText()
+    cout << "Sent " << pkt->data_len_ << " bytes over "
+         << pkt->iface_ << "/" << pkt->ifindex_ << " interface: "
+         << " dst=" << pkt->remote_addr_.toText()
+         << ", src=" << pkt->local_addr_.toText()
          << endl;
 
     return (result >= 0);
 }
 
-
-/**
- * Attempts to receive UDP/IPv6 packet over open sockets.
- *
- * TODO Start using select() and add timeout to be able
- * to not wait infinitely, but rather do something useful
- * (e.g. remove expired leases)
- *
- * @return Object prepresenting received packet.
- */
-Pkt6*
+boost::shared_ptr<Pkt6>
 IfaceMgr::receive() {
 #ifdef _WIN32
     GUID WSARecvMsg_GUID = WSAID_WSARECVMSG;
@@ -567,7 +533,7 @@ IfaceMgr::receive() {
     struct in6_pktinfo* pktinfo;
     struct sockaddr_in6 from;
     struct in6_addr to_addr;
-    Pkt6* pkt;
+    boost::shared_ptr<Pkt6> pkt;
     char addr_str[INET6_ADDRSTRLEN];
 
     try {
@@ -578,13 +544,13 @@ IfaceMgr::receive() {
         // we use larger buffer. This buffer limit is checked
         // during reception (see iov_len below), so we are
         // safe
-        pkt = new Pkt6(65536);
+        pkt = boost::shared_ptr<Pkt6>(new Pkt6(65536));
     } catch (const std::exception&) {
         cout << "Failed to create new packet." << endl;
-        return (0);
+        return (boost::shared_ptr<Pkt6>()); // NULL
     }
 
-    memset(control_buf_, 0, control_buf_len_);
+    memset(&control_buf_[0], 0, control_buf_len_);
 
     memset(&from, 0, sizeof(from));
     memset(&to_addr, 0, sizeof(to_addr));
@@ -616,7 +582,7 @@ IfaceMgr::receive() {
     m.lpBuffers = &v;
     m.dwBufferCount = 1;
 #else
-    v.iov_base = (char*)&pkt->data_[0];
+    v.iov_base = (char *)&pkt->data_[0];
     v.iov_len = pkt->data_len_;
     m.msg_iov = &v;
     m.msg_iovlen = 1;
@@ -631,10 +597,10 @@ IfaceMgr::receive() {
      * should get the destination address from that.
      */
 #ifdef _WIN32
-    m.Control.buf = control_buf_;
+    m.Control.buf = &control_buf_[0];
     m.Control.len = control_buf_len_;
 #else
-    m.msg_control = control_buf_;
+    m.msg_control = &control_buf_[0];
     m.msg_controllen = control_buf_len_;
 #endif
 
@@ -687,17 +653,16 @@ IfaceMgr::receive() {
         }
         if (!found_pktinfo) {
             cout << "Unable to find pktinfo" << endl;
-            delete pkt;
-            return (0);
+            return (boost::shared_ptr<Pkt6>()); // NULL
         }
     } else {
         cout << "Failed to receive data." << endl;
-        delete pkt;
-        return (0);
+        return (boost::shared_ptr<Pkt6>()); // NULL
     }
 
     // That's ugly.
     // TODO add IOAddress constructor that will take struct in6_addr*
+    // TODO: there's from_bytes() method added in IOAddress. Use it!
 #ifdef _WIN32
 #define DECONST (void *)
 #else
@@ -706,6 +671,7 @@ IfaceMgr::receive() {
     inet_ntop(AF_INET6, DECONST &to_addr, addr_str,INET6_ADDRSTRLEN);
     pkt->local_addr_ = IOAddress(string(addr_str));
 
+    // TODO: there's from_bytes() method added in IOAddress. Use it!
     inet_ntop(AF_INET6, DECONST &from.sin6_addr, addr_str, INET6_ADDRSTRLEN);
     pkt->remote_addr_ = IOAddress(string(addr_str));
 
@@ -717,8 +683,7 @@ IfaceMgr::receive() {
     } else {
         cout << "Received packet over unknown interface (ifindex="
              << pkt->ifindex_ << ")." << endl;
-        delete pkt;
-        return (0);
+        return (boost::shared_ptr<Pkt6>()); // NULL
     }
 
     pkt->data_len_ = result;
diff --git a/src/bin/dhcp6/iface_mgr.h b/src/bin/dhcp6/iface_mgr.h
index 118dc33..45f6afe 100644
--- a/src/bin/dhcp6/iface_mgr.h
+++ b/src/bin/dhcp6/iface_mgr.h
@@ -15,89 +15,216 @@
 #ifndef IFACE_MGR_H
 #define IFACE_MGR_H
 
+#include <stdint.h>
 #include <list>
+#include <boost/shared_ptr.hpp>
+#include <boost/scoped_array.hpp>
+#include <boost/noncopyable.hpp>
 #include "asiolink/io_address.h"
-#include "dhcp6/pkt6.h"
+#include "dhcp/pkt6.h"
 
 namespace isc {
 
-    /**
-     * IfaceMgr is an interface manager class that detects available network
-     * interfaces, configured addresses, link-local addresses, and provides
-     * API for using sockets.
-     *
-     */
-    class IfaceMgr {
-    public:
-        typedef std::list<isc::asiolink::IOAddress> Addr6Lst;
-        struct Iface { // TODO: could be a class as well
-            std::string name_; // network interface name
-            int ifindex_; // interface index (a value that uniquely indentifies
-                          // an interface
-            Addr6Lst addrs_;
-            char mac_[20]; // Infiniband used 20 bytes indentifiers
-            int mac_len_;
-
-            Iface(const std::string& name, int ifindex);
-            std::string getFullName() const;
-            std::string getPlainMac() const;
-
-            int sendsock_; // socket used to sending data
-            int recvsock_; // socket used for receiving data
-
-            // next field is not needed, let's keep it in cointainers
-        };
-
-        // TODO performance improvement: we may change this into
-        //      2 maps (ifindex-indexed and name-indexed) and
-        //      also hide it (make it public make tests easier for now)
-        typedef std::list<Iface> IfaceLst;
-
-        static IfaceMgr& instance();
-
-        Iface * getIface(int ifindex);
-        Iface * getIface(const std::string& ifname);
-
-        void printIfaces(std::ostream& out = std::cout);
-
-        bool send(Pkt6& pkt);
-        Pkt6* receive();
-
-        // don't use private, we need derived classes in tests
-    protected:
-        IfaceMgr(); // don't create IfaceMgr directly, use instance() method
-        ~IfaceMgr();
-
-        void detectIfaces();
-
-        int openSocket(const std::string& ifname,
-                       const isc::asiolink::IOAddress& addr,
-                       int port);
-
-        // TODO: having 2 maps (ifindex->iface and ifname->iface would)
-        //      probably be better for performance reasons
-        IfaceLst ifaces_;
-
-        static IfaceMgr * instance_;
-
-        // TODO: Also keep this interface on Iface once interface detection
-        // is implemented. We may need it e.g. to close all sockets on
-        // specific interface
-        int recvsock_; // TODO: should be fd_set eventually, but we have only
-        int sendsock_; // 2 sockets for now. Will do for until next release
-        // we can't use the same socket, as receiving socket
-        // is bound to multicast address. And we all know what happens
-        // to people who try to use multicast as source address.
-
-        char * control_buf_;
-        int control_buf_len_;
-
-    private:
-        bool openSockets();
-        static void instanceCreate();
-        bool joinMcast(int sock, const std::string& ifname,
-                       const std::string& mcast);
+namespace dhcp {
+/// @brief handles network interfaces, transmission and reception
+///
+/// IfaceMgr is an interface manager class that detects available network
+/// interfaces, configured addresses, link-local addresses, and provides
+/// API for using sockets.
+///
+class IfaceMgr : public boost::noncopyable {
+public:
+    /// type that defines list of addresses
+    typedef std::list<isc::asiolink::IOAddress> Addr6Lst;
+
+    /// maximum MAC address length (Infiniband uses 20 bytes)
+    static const unsigned int MAX_MAC_LEN = 20;
+
+    /// @brief represents a single network interface
+    ///
+    /// Iface structure represents network interface with all useful
+    /// information, like name, interface index, MAC address and
+    /// list of assigned addresses
+    struct Iface {
+        /// constructor
+        Iface(const std::string& name, int ifindex);
+
+        /// returns full interface name in format ifname/ifindex
+        std::string getFullName() const;
+
+        /// returns link-layer address a plain text
+        std::string getPlainMac() const;
+
+        /// network interface name
+        std::string name_;
+
+        /// interface index (a value that uniquely indentifies an interface)
+        int ifindex_;
+
+        /// list of assigned addresses
+        Addr6Lst addrs_;
+
+        /// link-layer address
+        uint8_t mac_[MAX_MAC_LEN];
+
+        /// length of link-layer address (usually 6)
+        int mac_len_;
+
+        /// socket used to sending data
+        int sendsock_;
+
+        /// socket used for receiving data
+        int recvsock_;
     };
+
+    // TODO performance improvement: we may change this into
+    //      2 maps (ifindex-indexed and name-indexed) and
+    //      also hide it (make it public make tests easier for now)
+
+    /// type that holds a list of interfaces
+    typedef std::list<Iface> IfaceLst;
+
+    /// IfaceMgr is a singleton class. This method returns reference
+    /// to its sole instance.
+    ///
+    /// @return the only existing instance of interface manager
+    static IfaceMgr& instance();
+
+    /// @brief Returns interface with specified interface index
+    ///
+    /// @param ifindex index of searched interface
+    ///
+    /// @return interface with requested index (or NULL if no such
+    ///         interface is present)
+    ///
+    Iface*
+    getIface(int ifindex);
+
+    /// @brief Returns interface with specified interface name
+    ///
+    /// @param ifname name of searched interface
+    ///
+    /// @return interface with requested name (or NULL if no such
+    ///         interface is present)
+    ///
+    Iface*
+    getIface(const std::string& ifname);
+
+    /// debugging method that prints out all available interfaces
+    ///
+    /// @param out specifies stream to print list of interfaces to
+    void
+    printIfaces(std::ostream& out = std::cout);
+
+    /// @brief Sends a packet.
+    ///
+    /// Sends a packet. All parameters for actual transmission are specified in
+    /// Pkt6 structure itself. That includes destination address, src/dst port
+    /// and interface over which data will be sent.
+    ///
+    /// @param pkt packet to be sent
+    ///
+    /// @return true if sending was successful
+    bool
+    send(boost::shared_ptr<Pkt6>& pkt);
+
+    /// @brief Tries to receive packet over open sockets.
+    ///
+    /// Attempts to receive a single packet of any of the open sockets.
+    /// If reception is successful and all information about its sender
+    /// are obtained, Pkt6 object is created and returned.
+    ///
+    /// TODO Start using select() and add timeout to be able
+    /// to not wait infinitely, but rather do something useful
+    /// (e.g. remove expired leases)
+    ///
+    /// @return Pkt6 object representing received packet (or NULL)
+    boost::shared_ptr<Pkt6> receive();
+
+    // don't use private, we need derived classes in tests
+protected:
+
+    /// @brief Protected constructor.
+    ///
+    /// Protected constructor. This is a singleton class. We don't want
+    /// anyone to create instances of IfaceMgr. Use instance() method
+    IfaceMgr();
+
+    ~IfaceMgr();
+
+    /// @brief Detects network interfaces.
+    ///
+    /// This method will eventually detect available interfaces. For now
+    /// it offers stub implementation. First interface name and link-local
+    /// IPv6 address is read from intefaces.txt file.
+    void
+    detectIfaces();
+
+    ///
+    /// Opens UDP/IPv6 socket and binds it to address, interface and port.
+    ///
+    /// @param ifname name of the interface
+    /// @param addr address to be bound.
+    /// @param port UDP port.
+    ///
+    /// @return socket descriptor, if socket creation, binding and multicast
+    /// group join were all successful. -1 otherwise.
+    int openSocket(const std::string& ifname,
+                   const isc::asiolink::IOAddress& addr,
+                   int port);
+
+    // TODO: having 2 maps (ifindex->iface and ifname->iface would)
+    //      probably be better for performance reasons
+
+    /// List of available interfaces
+    IfaceLst ifaces_;
+
+    /// a pointer to a sole instance of this class (a singleton)
+    static IfaceMgr * instance_;
+
+    // TODO: Also keep this interface on Iface once interface detection
+    // is implemented. We may need it e.g. to close all sockets on
+    // specific interface
+    int recvsock_; // TODO: should be fd_set eventually, but we have only
+    int sendsock_; // 2 sockets for now. Will do for until next release
+    // we can't use the same socket, as receiving socket
+    // is bound to multicast address. And we all know what happens
+    // to people who try to use multicast as source address.
+
+    /// length of the control_buf_ array
+    int control_buf_len_;
+
+    /// control-buffer, used in transmission and reception
+    boost::scoped_array<char> control_buf_;
+
+private:
+    /// Opens sockets on detected interfaces.
+    bool
+    openSockets();
+
+    /// creates a single instance of this class (a singleton implementation)
+    static void
+    instanceCreate();
+
+    /// @brief Joins IPv6 multicast group on a socket.
+    ///
+    /// Socket must be created and bound to an address. Note that this
+    /// address is different than the multicast address. For example DHCPv6
+    /// server should bind its socket to link-local address (fe80::1234...)
+    /// and later join ff02::1:2 multicast group.
+    ///
+    /// @param sock socket fd (socket must be bound)
+    /// @param ifname interface name (for link-scoped multicast groups)
+    /// @param mcast multicast address to join (e.g. "ff02::1:2")
+    ///
+    /// @return true if multicast join was successful
+    ///
+    bool
+    joinMcast(int sock, const std::string& ifname,
+              const std::string& mcast);
 };
 
+}; // namespace isc::dhcp
+}; // namespace isc
+
 #endif
diff --git a/src/bin/dhcp6/main.cc b/src/bin/dhcp6/main.cc
index a73434f..407b81f 100644
--- a/src/bin/dhcp6/main.cc
+++ b/src/bin/dhcp6/main.cc
@@ -33,23 +33,23 @@
 #include <iostream>
 
 #include <exceptions/exceptions.h>
+#if 0
+// TODO cc is not used yet. It should be eventually
 #include <cc/session.h>
 #include <config/ccsession.h>
+#endif
 
 #include <util/buffer.h>
 #include <log/dummylog.h>
 
 #include <dhcp6/spec_config.h>
-#include <dhcp6/dhcp6_srv.h>
+#include "dhcp6/dhcp6_srv.h"
 
 using namespace std;
 using namespace isc::util;
-using namespace isc::data;
-using namespace isc::cc;
-using namespace isc::config;
-using namespace isc::util;
 
 using namespace isc;
+using namespace isc::dhcp;
 
 namespace {
 
@@ -109,8 +109,6 @@ main(int argc, char* argv[]) {
             specfile = string(DHCP6_SPECFILE_LOCATION);
         }
 
-        // auth_server = new AuthSrv(cache, xfrout_client);
-        // auth_server->setVerbose(verbose_mode);
         cout << "[b10-dhcp6] Initiating DHCPv6 operation." << endl;
 
         Dhcpv6Srv* srv = new Dhcpv6Srv();
diff --git a/src/bin/dhcp6/pkt6.cc b/src/bin/dhcp6/pkt6.cc
deleted file mode 100644
index 0d8fa60..0000000
--- a/src/bin/dhcp6/pkt6.cc
+++ /dev/null
@@ -1,47 +0,0 @@
-// 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 "dhcp6/dhcp6.h"
-#include "dhcp6/pkt6.h"
-#include <iostream>
-
-namespace isc {
-
-///
-/// constructor
-///
-/// \param dataLen - length of the data to be allocated
-///
-Pkt6::Pkt6(int dataLen)
-    :local_addr_("::"),
-     remote_addr_("::") {
-    try {
-	data_ = boost::shared_array<char>(new char[dataLen]);
-	data_len_ = dataLen;
-    } catch (const std::exception&) {
-	// TODO move to LOG_FATAL()
-	// let's continue with empty pkt for now
-        std::cout << "Failed to allocate " << dataLen << " bytes."
-                  << std::endl;
-        data_len_ = 0;
-    }
-}
-
-Pkt6::~Pkt6() {
-    // no need to delete anything shared_ptr will take care of data_
-}
-
-};
diff --git a/src/bin/dhcp6/pkt6.h b/src/bin/dhcp6/pkt6.h
deleted file mode 100644
index c833a13..0000000
--- a/src/bin/dhcp6/pkt6.h
+++ /dev/null
@@ -1,62 +0,0 @@
-// 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 PKT6_H
-#define PKT6_H
-
-#include <iostream>
-#include <boost/shared_array.hpp>
-#include "asiolink/io_address.h"
-
-namespace isc {
-
-    class Pkt6 {
-    public:
-        Pkt6(int len);
-        ~Pkt6();
-
-        // XXX: probably need getter/setter wrappers
-        //      and hide fields as protected
-        // buffer that holds memory. It is shared_array as options may
-        // share pointer to this buffer
-        boost::shared_array<char> data_;
-
-        // length of the data
-        int data_len_;
-
-        // local address (destination if receiving packet, source if sending packet)
-        isc::asiolink::IOAddress local_addr_;
-
-        // remote address (source if receiving packet, destination if sending packet)
-        isc::asiolink::IOAddress remote_addr_;
-
-        // name of the network interface the packet was received/to be sent over
-        std::string iface_;
-
-        // interface index (each network interface has assigned unique ifindex
-        // it is functional equvalent of name, but sometimes more useful, e.g.
-        // when using crazy systems that allow spaces in interface names (Windows)
-        int ifindex_;
-
-        // local TDP or UDP port
-        int local_port_;
-
-        // remote TCP or UDP port
-        int remote_port_;
-
-        // XXX: add *a lot* here
-    };
-}
-
-#endif
diff --git a/src/bin/dhcp6/tests/Makefile.am b/src/bin/dhcp6/tests/Makefile.am
index ae9d8e3..985368e 100644
--- a/src/bin/dhcp6/tests/Makefile.am
+++ b/src/bin/dhcp6/tests/Makefile.am
@@ -45,11 +45,9 @@ if HAVE_GTEST
 
 TESTS += dhcp6_unittests
 
-dhcp6_unittests_SOURCES = ../pkt6.h ../pkt6.cc
-dhcp6_unittests_SOURCES += ../iface_mgr.h ../iface_mgr.cc
+dhcp6_unittests_SOURCES = ../iface_mgr.h ../iface_mgr.cc
 dhcp6_unittests_SOURCES += ../dhcp6_srv.h ../dhcp6_srv.cc
 dhcp6_unittests_SOURCES += dhcp6_unittests.cc
-dhcp6_unittests_SOURCES += pkt6_unittest.cc
 dhcp6_unittests_SOURCES += iface_mgr_unittest.cc
 dhcp6_unittests_SOURCES += dhcp6_srv_unittest.cc
 
@@ -58,8 +56,7 @@ dhcp6_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
 dhcp6_unittests_LDADD = $(GTEST_LDADD)
 dhcp6_unittests_LDADD += $(SQLITE_LIBS)
 dhcp6_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
-dhcp6_unittests_LDADD += $(top_builddir)/src/lib/config/libcfgclient.la
-dhcp6_unittests_LDADD += $(top_builddir)/src/lib/cc/libcc.la
+dhcp6_unittests_LDADD += $(top_builddir)/src/lib/dhcp/libdhcp.la
 dhcp6_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
 dhcp6_unittests_LDADD += $(top_builddir)/src/lib/log/liblog.la
 endif
diff --git a/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc b/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc
index 8f74f86..7d882d4 100644
--- a/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc
+++ b/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc
@@ -23,12 +23,33 @@
 #endif
 #include <gtest/gtest.h>
 
+#include "dhcp/dhcp6.h"
 #include "dhcp6/dhcp6_srv.h"
+#include "dhcp/option6_ia.h"
 
 using namespace std;
 using namespace isc;
+using namespace isc::dhcp;
+
+// namespace has to be named, because friends are defined in Dhcpv6Srv class
+// Maybe it should be isc::test?
+namespace test {
+
+class NakedDhcpv6Srv: public Dhcpv6Srv {
+    // "naked" Interface Manager, exposes internal fields
+public:
+    NakedDhcpv6Srv() { }
+
+    boost::shared_ptr<Pkt6>
+    processSolicit(boost::shared_ptr<Pkt6>& request) {
+        return Dhcpv6Srv::processSolicit(request);
+    }
+    boost::shared_ptr<Pkt6>
+    processRequest(boost::shared_ptr<Pkt6>& request) {
+        return Dhcpv6Srv::processRequest(request);
+    }
+};
 
-namespace {
 class Dhcpv6SrvTest : public ::testing::Test {
 public:
     Dhcpv6SrvTest() {
@@ -36,21 +57,94 @@ public:
 };
 
 TEST_F(Dhcpv6SrvTest, basic) {
-    // there's almost no code now. What's there provides echo capability 
+    // there's almost no code now. What's there provides echo capability
     // that is just a proof of concept and will be removed soon
     // No need to thoroughly test it
 
     // srv has stubbed interface detection. It will read
     // interfaces.txt instead. It will pretend to have detected
     // fe80::1234 link-local address on eth0 interface. Obviously
-
     // an attempt to bind this socket will fail.
     EXPECT_NO_THROW( {
         Dhcpv6Srv * srv = new Dhcpv6Srv();
 
-	delete srv;
-	});
-    
+        delete srv;
+        });
+
+}
+
+TEST_F(Dhcpv6SrvTest, Solicit_basic) {
+    NakedDhcpv6Srv * srv = 0;
+    EXPECT_NO_THROW( srv = new NakedDhcpv6Srv(); );
+
+    // a dummy content for client-id
+    boost::shared_array<uint8_t> clntDuid(new uint8_t[32]);
+    for (int i=0; i<32; i++)
+        clntDuid[i] = 100+i;
+
+    boost::shared_ptr<Pkt6> sol =
+        boost::shared_ptr<Pkt6>(new Pkt6(DHCPV6_SOLICIT,
+                                         1234, Pkt6::UDP));
+
+    boost::shared_ptr<Option6IA> ia =
+        boost::shared_ptr<Option6IA>(new Option6IA(D6O_IA_NA, 234));
+    ia->setT1(1501);
+    ia->setT2(2601);
+    sol->addOption(ia);
+
+    // Let's not send address in solicit yet
+    // boost::shared_ptr<Option6IAAddr> addr(new Option6IAAddr(D6O_IAADDR,
+    //    IOAddress("2001:db8:1234:ffff::ffff"), 5001, 7001));
+    // ia->addOption(addr);
+    // sol->addOption(ia);
+
+    // constructed very simple SOLICIT message with:
+    // - client-id option (mandatory)
+    // - IA option (a request for address, without any addresses)
+
+    // expected returned ADVERTISE message:
+    // - copy of client-id
+    // - server-id
+    // - IA that includes IAADDR
+
+    boost::shared_ptr<Option> clientid =
+        boost::shared_ptr<Option>(new Option(Option::V6, D6O_CLIENTID,
+                                             clntDuid, 0, 16));
+    sol->addOption(clientid);
+
+    boost::shared_ptr<Pkt6> reply = srv->processSolicit(sol);
+
+    // check if we get response at all
+    ASSERT_TRUE( reply != boost::shared_ptr<Pkt6>() );
+
+    EXPECT_EQ( DHCPV6_ADVERTISE, reply->getType() );
+    EXPECT_EQ( 1234, reply->getTransid() );
+
+    boost::shared_ptr<Option> tmp = reply->getOption(D6O_IA_NA);
+    ASSERT_TRUE( tmp );
+
+    Option6IA * reply_ia = dynamic_cast<Option6IA*> ( tmp.get() );
+    EXPECT_EQ( 234, reply_ia->getIAID() );
+
+    // check that there's an address included
+    EXPECT_TRUE( reply_ia->getOption(D6O_IAADDR));
+
+    // check that server included our own client-id
+    tmp = reply->getOption(D6O_CLIENTID);
+    ASSERT_TRUE( tmp );
+    EXPECT_EQ(clientid->getType(), tmp->getType() );
+    ASSERT_EQ(clientid->len(), tmp->len() );
+    EXPECT_FALSE(memcmp(clientid->getData(), tmp->getData(), tmp->len() ) );
+    // check that server included its server-id
+    tmp = reply->getOption(D6O_SERVERID);
+    EXPECT_EQ(tmp->getType(), srv->getServerID()->getType() );
+    ASSERT_EQ(tmp->len(),  srv->getServerID()->len() );
+    EXPECT_FALSE( memcmp(tmp->getData(), srv->getServerID()->getData(),
+                      tmp->len()) );
+
+    // more checks to be implemented
+    delete srv;
+
 }
 
 }
diff --git a/src/bin/dhcp6/tests/iface_mgr_unittest.cc b/src/bin/dhcp6/tests/iface_mgr_unittest.cc
index 31b20ba..bbda769 100644
--- a/src/bin/dhcp6/tests/iface_mgr_unittest.cc
+++ b/src/bin/dhcp6/tests/iface_mgr_unittest.cc
@@ -26,12 +26,16 @@
 #include <gtest/gtest.h>
 
 #include "asiolink/io_address.h"
-#include "dhcp6/pkt6.h"
+#include "dhcp/pkt6.h"
 #include "dhcp6/iface_mgr.h"
 
 using namespace std;
 using namespace isc;
 using namespace isc::asiolink;
+using namespace isc::dhcp;
+
+// name of loopback interface detection
+char LOOPBACK[32] = "lo";
 
 namespace {
 const char* const INTERFACE_FILE = TEST_DATA_BUILDDIR "/interfaces.txt";
@@ -59,6 +63,130 @@ public:
     }
 };
 
+// We need some known interface to work reliably. Loopback interface
+// is named lo on Linux and lo0 on BSD boxes. We need to find out
+// which is available. This is not a real test, but rather a workaround
+// that will go away when interface detection is implemented.
+
+// NOTE: At this stage of development, write access to current directory
+// during running tests is required.
+TEST_F(IfaceMgrTest, loDetect) {
+
+    unlink("interfaces.txt");
+
+    ofstream interfaces("interfaces.txt", ios::ate);
+    interfaces << "lo ::1";
+    interfaces.close();
+
+    NakedIfaceMgr * ifacemgr = new NakedIfaceMgr();
+    IOAddress loAddr("::1");
+    IOAddress mcastAddr("ff02::1:2");
+
+    // bind multicast socket to port 10547
+    int socket1 = ifacemgr->openSocket("lo", mcastAddr, 10547);
+    // this fails on BSD (there's no lo interface there)
+
+    // poor man's interface dection
+    // it will go away as soon as proper interface detection
+    // is implemented
+#ifdef _WIN32
+    if (socket1 != INVALID_SOCKET) {
+        cout << "This is Linux, using lo as loopback." << endl;
+        closesocket(socket1);
+    }
+#else
+    if (socket1>0) {
+        cout << "This is Linux, using lo as loopback." << endl;
+        close(socket1);
+    }
+#endif
+    else {
+        // this fails on Linux and succeeds on BSD
+        socket1 = ifacemgr->openSocket("lo0", mcastAddr, 10547);
+#ifdef _WIN32
+        if (socket1 != INVALID_SOCKET) {
+            sprintf(LOOPBACK, "lo0");
+            cout << "This is BSD, using lo0 as loopback." << endl;
+            closesocket(socket1);
+        }
+#else
+        if (socket1>0) {
+            sprintf(LOOPBACK, "lo0");
+            cout << "This is BSD, using lo0 as loopback." << endl;
+            close(socket1);
+        }
+#endif
+        else {
+            cout << "Failed to detect loopback interface. Neither "
+                 << "lo or lo0 worked. I give up." << endl;
+            ASSERT_TRUE(false);
+        }
+    }
+
+    delete ifacemgr;
+}
+
+// uncomment this test to create packet writer. It will
+// write incoming DHCPv6 packets as C arrays. That is useful
+// for generating test sequences based on actual traffic
+//
+// TODO: this potentially should be moved to a separate tool
+//
+
+#if 0
+TEST_F(IfaceMgrTest, dhcp6Sniffer) {
+    // testing socket operation in a portable way is tricky
+    // without interface detection implemented
+
+    unlink("interfaces.txt");
+
+    ofstream interfaces("interfaces.txt", ios::ate);
+    interfaces << "eth0 fe80::21e:8cff:fe9b:7349";
+    interfaces.close();
+
+    NakedIfaceMgr * ifacemgr = new NakedIfaceMgr();
+
+    Pkt6 * pkt = 0;
+    int cnt = 0;
+    cout << "---8X-----------------------------------------" << endl;
+    while (true) {
+        pkt = ifacemgr->receive();
+
+        cout << "// Received " << pkt->data_len_ << " bytes packet:" << endl;
+        cout << "Pkt6 *capture" << cnt++ << "() {" << endl;
+        cout << "    Pkt6* pkt;" << endl;
+        cout << "    pkt = new Pkt6(" << pkt->data_len_ << ");" << endl;
+        cout << "    pkt->remote_port_ = " << pkt-> remote_port_ << ";" << endl;
+        cout << "    pkt->remote_addr_ = IOAddress(\""
+             << pkt->remote_addr_.toText() << "\");" << endl;
+        cout << "    pkt->local_port_ = " << pkt-> local_port_ << ";" << endl;
+        cout << "    pkt->local_addr_ = IOAddress(\""
+             << pkt->local_addr_.toText() << "\");" << endl;
+        cout << "    pkt->ifindex_ = " << pkt->ifindex_ << ";" << endl;
+        cout << "    pkt->iface_ = \"" << pkt->iface_ << "\";" << endl;
+
+        // TODO it is better to declare an array and then memcpy it to
+        // packet.
+        for (int i=0; i< pkt->data_len_; i++) {
+            cout << "    pkt->data_[" << i << "]="
+                 << (int)(unsigned char)pkt->data_[i] << "; ";
+            if (!(i%4))
+                cout << endl;
+        }
+        cout << endl;
+        cout << "    return (pkt);" << endl;
+        cout << "}" << endl << endl;
+
+        delete pkt;
+    }
+    cout << "---8X-----------------------------------------" << endl;
+
+    // never happens. Infinite loop is infinite
+    delete pkt;
+    delete ifacemgr;
+}
+#endif
+
 TEST_F(IfaceMgrTest, basic) {
     // checks that IfaceManager can be instantiated
 
@@ -77,23 +205,34 @@ TEST_F(IfaceMgrTest, ifaceClass) {
 
 }
 
-// TODO: Implement getPlainMac() test as soon as interface detection is implemented.
+// TODO: Implement getPlainMac() test as soon as interface detection
+// is implemented.
 TEST_F(IfaceMgrTest, getIface) {
 
     cout << "Interface checks. Please ignore socket binding errors." << endl;
     NakedIfaceMgr * ifacemgr = new NakedIfaceMgr();
 
     // interface name, ifindex
-    IfaceMgr::Iface iface1("lo", 1);
+    IfaceMgr::Iface iface1("lo1", 1);
     IfaceMgr::Iface iface2("eth5", 2);
     IfaceMgr::Iface iface3("en3", 5);
     IfaceMgr::Iface iface4("e1000g0", 3);
 
+    // note: real interfaces may be detected as well
     ifacemgr->getIfacesLst().push_back(iface1);
     ifacemgr->getIfacesLst().push_back(iface2);
     ifacemgr->getIfacesLst().push_back(iface3);
     ifacemgr->getIfacesLst().push_back(iface4);
 
+    cout << "There are " << ifacemgr->getIfacesLst().size()
+         << " interfaces." << endl;
+    for (IfaceMgr::IfaceLst::iterator iface=ifacemgr->getIfacesLst().begin();
+         iface != ifacemgr->getIfacesLst().end();
+         ++iface) {
+        cout << "  " << iface->name_ << "/" << iface->ifindex_ << endl;
+    }
+
+
     // check that interface can be retrieved by ifindex
     IfaceMgr::Iface * tmp = ifacemgr->getIface(5);
     // ASSERT_NE(NULL, tmp); is not supported. hmmmm.
@@ -103,10 +242,10 @@ TEST_F(IfaceMgrTest, getIface) {
     EXPECT_EQ(5, tmp->ifindex_);
 
     // check that interface can be retrieved by name
-    tmp = ifacemgr->getIface("lo");
+    tmp = ifacemgr->getIface("lo1");
     ASSERT_TRUE( tmp != NULL );
 
-    EXPECT_STREQ( "lo", tmp->name_.c_str() );
+    EXPECT_STREQ( "lo1", tmp->name_.c_str() );
     EXPECT_EQ(1, tmp->ifindex_);
 
     // check that non-existing interfaces are not returned
@@ -158,15 +297,15 @@ TEST_F(IfaceMgrTest, DISABLED_sockets) {
     IOAddress loAddr("::1");
 
     // bind multicast socket to port 10547
-    int socket1 = ifacemgr->openSocket("lo", loAddr, 10547);
+    int socket1 = ifacemgr->openSocket(LOOPBACK, loAddr, 10547);
 #ifdef _WIN32
-    EXPECT_NE(socket1, INVALID_SOCKET);
+    EXPECT_NE(socket1, INVALID_SOCKET); // socket != INVALID_SOCKET
 #else
     EXPECT_GT(socket1, 0); // socket > 0
 #endif
 
     // bind unicast socket to port 10548
-    int socket2 = ifacemgr->openSocket("lo", loAddr, 10548);
+    int socket2 = ifacemgr->openSocket(LOOPBACK, loAddr, 10548);
 #ifdef _WIN32
     EXPECT_NE(socket2, INVALID_SOCKET);
 #else
@@ -175,12 +314,13 @@ TEST_F(IfaceMgrTest, DISABLED_sockets) {
 
     // expect success. This address/port is already bound, but
     // we are using SO_REUSEADDR, so we can bind it twice
-    int socket3 = ifacemgr->openSocket("lo", loAddr, 10547);
-#ifdef _WIN32
-    EXPECT_NE(socket3, INVALID_SOCKET);
-#else
-    EXPECT_GT(socket3, 0); // socket > 0
-#endif
+    int socket3 = ifacemgr->openSocket(LOOPBACK, loAddr, 10547);
+
+    // rebinding succeeds on Linux, fails on BSD
+    // TODO: add OS-specific defines here (or modify code to
+    // behave the same way on all OSes, but that may not be
+    // possible
+    // EXPECT_GT(socket3, 0); // socket > 0
 
     // we now have 3 sockets open at the same time. Looks good.
 
@@ -209,18 +349,18 @@ TEST_F(IfaceMgrTest, DISABLED_socketsMcast) {
     IOAddress mcastAddr("ff02::1:2");
 
     // bind multicast socket to port 10547
-    int socket1 = ifacemgr->openSocket("lo", mcastAddr, 10547);
+    int socket1 = ifacemgr->openSocket(LOOPBACK, mcastAddr, 10547);
 #ifdef _WIN32
-    EXPECT_NE(socket1, INVALID_SOCKET);
+    EXPECT_NE(socket1, INVALID_SOCKET); // socket != INVALID_SOCKET
 #else
     EXPECT_GT(socket1, 0); // socket > 0
 #endif
 
     // expect success. This address/port is already bound, but
     // we are using SO_REUSEADDR, so we can bind it twice
-    int socket2 = ifacemgr->openSocket("lo", mcastAddr, 10547);
+    int socket2 = ifacemgr->openSocket(LOOPBACK, mcastAddr, 10547);
 #ifdef _WIN32
-    EXPECT_NE(socket1, INVALID_SOCKET);
+    EXPECT_NE(socket2, INVALID_SOCKET);
 #else
     EXPECT_GT(socket2, 0);
 #endif
@@ -250,49 +390,47 @@ TEST_F(IfaceMgrTest, DISABLED_sendReceive) {
     // without interface detection implemented
 
     fstream fakeifaces(INTERFACE_FILE, ios::out|ios::trunc);
-    fakeifaces << "lo ::1";
+    fakeifaces << LOOPBACK << " ::1";
     fakeifaces.close();
 
     NakedIfaceMgr * ifacemgr = new NakedIfaceMgr();
 
     // let's assume that every supported OS have lo interface
     IOAddress loAddr("::1");
-    int socket1 = ifacemgr->openSocket("lo", loAddr, 10547);
-    int socket2 = ifacemgr->openSocket("lo", loAddr, 10546);
+    int socket1 = ifacemgr->openSocket(LOOPBACK, loAddr, 10547);
+    int socket2 = ifacemgr->openSocket(LOOPBACK, loAddr, 10546);
 
     ifacemgr->setSendSock(socket2);
     ifacemgr->setRecvSock(socket1);
 
-    Pkt6 sendPkt(128);
+    boost::shared_ptr<Pkt6> sendPkt(new Pkt6(128) );
 
     // prepare dummy payload
     for (int i=0;i<128; i++) {
-        sendPkt.data_[i] = i;
+        sendPkt->data_[i] = i;
     }
 
-    sendPkt.remote_port_ = 10547;
-    sendPkt.remote_addr_ = IOAddress("::1");
-    sendPkt.ifindex_ = 1;
-    sendPkt.iface_ = "lo";
+    sendPkt->remote_port_ = 10547;
+    sendPkt->remote_addr_ = IOAddress("::1");
+    sendPkt->ifindex_ = 1;
+    sendPkt->iface_ = LOOPBACK;
 
-    Pkt6 * rcvPkt;
+    boost::shared_ptr<Pkt6> rcvPkt;
 
     EXPECT_EQ(true, ifacemgr->send(sendPkt));
 
     rcvPkt = ifacemgr->receive();
 
-    ASSERT_TRUE( rcvPkt != NULL ); // received our own packet
+    ASSERT_TRUE( rcvPkt ); // received our own packet
 
     // let's check that we received what was sent
-    EXPECT_EQ(sendPkt.data_len_, rcvPkt->data_len_);
-    EXPECT_EQ(0, memcmp(&sendPkt.data_[0], &rcvPkt->data_[0],
+    EXPECT_EQ(sendPkt->data_len_, rcvPkt->data_len_);
+    EXPECT_EQ(0, memcmp(&sendPkt->data_[0], &rcvPkt->data_[0],
                         rcvPkt->data_len_) );
 
-    EXPECT_EQ(sendPkt.remote_addr_.toText(), rcvPkt->remote_addr_.toText());
+    EXPECT_EQ(sendPkt->remote_addr_.toText(), rcvPkt->remote_addr_.toText());
     EXPECT_EQ(rcvPkt->remote_port_, 10546);
 
-    delete rcvPkt;
-
     delete ifacemgr;
 }
 
diff --git a/src/bin/dhcp6/tests/pkt6_unittest.cc b/src/bin/dhcp6/tests/pkt6_unittest.cc
deleted file mode 100644
index 86c6cb2..0000000
--- a/src/bin/dhcp6/tests/pkt6_unittest.cc
+++ /dev/null
@@ -1,48 +0,0 @@
-// 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>
-
-#ifdef _WIN32
-#include <ws2tcpip.h>
-#else
-#include <arpa/inet.h>
-#endif
-#include <gtest/gtest.h>
-
-
-#include "dhcp6/pkt6.h"
-
-using namespace std;
-using namespace isc;
-
-namespace {
-// empty class for now, but may be extended once Addr6 becomes bigger
-class Pkt6Test : public ::testing::Test {
-public:
-    Pkt6Test() {
-    }
-};
-
-TEST_F(Pkt6Test, constructor) {
-    Pkt6 * pkt1 = new Pkt6(17);
-    
-    ASSERT_EQ(pkt1->data_len_, 17);
-
-    delete pkt1;
-}
-
-}
diff --git a/src/lib/asiolink/io_address.cc b/src/lib/asiolink/io_address.cc
index da9223e..dabf82d 100644
--- a/src/lib/asiolink/io_address.cc
+++ b/src/lib/asiolink/io_address.cc
@@ -27,7 +27,7 @@
 #include <exceptions/exceptions.h>
 #include <asiolink/io_address.h>
 #include <asiolink/io_error.h>
-
+#include <boost/static_assert.hpp>
 
 using namespace asio;
 using asio::ip::udp;
@@ -59,23 +59,23 @@ IOAddress::toText() const {
 }
 
 IOAddress
-IOAddress::from_bytes(short family, const char* data) {
-    static char addr_str[INET6_ADDRSTRLEN];
+IOAddress::from_bytes(short family, const uint8_t* data) {
     if (data == NULL) {
         isc_throw(BadValue, "NULL pointer received.");
-    }
+    } else
     if ( (family != AF_INET) && (family != AF_INET6) ) {
         isc_throw(BadValue, "Invalid family type. Only AF_INET and AF_INET6"
                   << "are supported");
     }
 
+    BOOST_STATIC_ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN);
+    char addr_str[INET6_ADDRSTRLEN];
 #ifdef _WIN32
 #define DECONST (void *)
 #else
 #define DECONST
 #endif
-
-    inet_ntop(family, DECONST data, addr_str,INET6_ADDRSTRLEN);
+    inet_ntop(family, DECONST data, addr_str, INET6_ADDRSTRLEN);
     return IOAddress(string(addr_str));
 }
 
diff --git a/src/lib/asiolink/io_address.h b/src/lib/asiolink/io_address.h
index 59ba8e7..3306341 100644
--- a/src/lib/asiolink/io_address.h
+++ b/src/lib/asiolink/io_address.h
@@ -15,6 +15,8 @@
 #ifndef __IO_ADDRESS_H
 #define __IO_ADDRESS_H 1
 
+#include <stdint.h>
+
 // IMPORTANT NOTE: only very few ASIO headers files can be included in
 // this file.  In particular, asio.hpp should never be included here.
 // See the description of the namespace below.
@@ -31,6 +33,12 @@
 namespace isc {
 namespace asiolink {
 
+    /// Defines length of IPv6 address.
+    const static size_t V6ADDRESS_LEN = 16;
+
+    /// Defines length of IPv4 address.
+    const static size_t V4ADDRESS_LEN = 4;
+
 /// \brief The \c IOAddress class represents an IP addresses (version
 /// agnostic)
 ///
@@ -97,7 +105,7 @@ public:
     ///
     /// \return Created IOAddress object
     static IOAddress
-    from_bytes(short family, const char* data);
+    from_bytes(short family, const uint8_t* data);
 
     /// \brief Compare addresses for equality
     ///
diff --git a/src/lib/asiolink/tests/io_address_unittest.cc b/src/lib/asiolink/tests/io_address_unittest.cc
index 3abd535..eddb0e8 100644
--- a/src/lib/asiolink/tests/io_address_unittest.cc
+++ b/src/lib/asiolink/tests/io_address_unittest.cc
@@ -18,6 +18,8 @@
 #include <asiolink/io_error.h>
 #include <asiolink/io_address.h>
 
+#include <cstring>
+
 using namespace isc::asiolink;
 
 TEST(IOAddressTest, fromText) {
@@ -64,11 +66,11 @@ TEST(IOAddressTest, Family) {
 
 TEST(IOAddressTest, from_bytes) {
     // 2001:db8:1::dead:beef
-    char v6[] = {
+    uint8_t v6[] = {
         0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0, 0,
         0, 0, 0, 0, 0xde, 0xad, 0xbe, 0xef };
 
-    char v4[] = { 192, 0 , 2, 3 };
+    uint8_t v4[] = { 192, 0 , 2, 3 };
 
     IOAddress addr("::");
     EXPECT_NO_THROW({
@@ -79,5 +81,5 @@ TEST(IOAddressTest, from_bytes) {
     EXPECT_NO_THROW({
         addr = IOAddress::from_bytes(AF_INET, v4);
     });
-    EXPECT_EQ(addr, IOAddress("192.0.2.3"));
+    EXPECT_EQ(addr.toText(), IOAddress("192.0.2.3").toText());
 }
diff --git a/src/lib/dhcp/Makefile.am b/src/lib/dhcp/Makefile.am
index 5170c1c..72317ab 100644
--- a/src/lib/dhcp/Makefile.am
+++ b/src/lib/dhcp/Makefile.am
@@ -1,10 +1,10 @@
 SUBDIRS = . tests
 
 AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
-AM_CPPFLAGS += -I$(top_srcdir)/src/lib/asiolink
-AM_CPPFLAGS += -I$(top_builddir)/src/lib/asiolink
 AM_CPPFLAGS += $(BOOST_INCLUDES)
 
+AM_CXXFLAGS = $(B10_CXXFLAGS)
+
 CLEANFILES = *.gcno *.gcda
 
 lib_LTLIBRARIES = libdhcp.la
@@ -16,20 +16,11 @@ libdhcp_la_SOURCES += option6_iaaddr.cc option6_iaaddr.h
 libdhcp_la_SOURCES += option6_addrlst.cc option6_addrlst.h
 libdhcp_la_SOURCES += dhcp6.h
 libdhcp_la_SOURCES += pkt6.cc pkt6.h
+libdhcp_la_SOURCES += pkt4.cc pkt4.h
 
 EXTRA_DIST  = README
 #EXTRA_DIST += log_messages.mes
 
-# Note: the ordering matters: -Wno-... must follow -Wextra (defined in
-# B10_CXXFLAGS)
 libdhcp_la_CXXFLAGS = $(AM_CXXFLAGS)
-if USE_GXX
-libdhcp_la_CXXFLAGS += -Wall
-endif
-if USE_CLANGPP
-# Same for clang++, but we need to turn off -Werror completely.
-libdhcp_la_CXXFLAGS += -Wall
-endif
 libdhcp_la_CPPFLAGS = $(AM_CPPFLAGS) $(LOG4CPLUS_INCLUDES)
-libdhcp_la_LDFLAGS  = $(LOG4CPLUS_LDFLAGS)
 libdhcp_la_LIBADD   = $(top_builddir)/src/lib/util/libutil.la
diff --git a/src/lib/dhcp/dhcp4.h b/src/lib/dhcp/dhcp4.h
new file mode 100644
index 0000000..854dca6
--- /dev/null
+++ b/src/lib/dhcp/dhcp4.h
@@ -0,0 +1,191 @@
+/* dhcp.h
+
+   Protocol structures... */
+
+/*
+ * Copyright (c) 2004-2011 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1995-2003 by Internet Software Consortium
+ *
+ * Permission to use, copy, modify, and 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.
+ *
+ *   Internet Systems Consortium, Inc.
+ *   950 Charter Street
+ *   Redwood City, CA 94063
+ *   <info at isc.org>
+ *   https://www.isc.org/
+ *
+ * This software has been written for Internet Systems Consortium
+ * by Ted Lemon in cooperation with Vixie Enterprises.  To learn more
+ * about Internet Systems Consortium, see ``https://www.isc.org''.
+ * To learn more about Vixie Enterprises, see ``http://www.vix.com''.
+ */
+
+/* 
+ * NOTE: This files is imported from ISC DHCP. It uses C notation.
+ *       Format kept for easier merge.
+ */
+
+#ifndef DHCP_H
+#define DHCP_H
+
+#define DHCP_UDP_OVERHEAD	(20 + /* IP header */			\
+			        8)   /* UDP header */
+#define DHCP_SNAME_LEN		64
+#define DHCP_FILE_LEN		128
+#define DHCP_FIXED_NON_UDP	236
+#define DHCP_FIXED_LEN		(DHCP_FIXED_NON_UDP + DHCP_UDP_OVERHEAD)
+						/* Everything but options. */
+#define BOOTP_MIN_LEN		300
+
+#define DHCP_MTU_MAX		1500
+#define DHCP_MTU_MIN            576
+
+#define DHCP_MAX_OPTION_LEN	(DHCP_MTU_MAX - DHCP_FIXED_LEN)
+#define DHCP_MIN_OPTION_LEN     (DHCP_MTU_MIN - DHCP_FIXED_LEN)
+
+/* BOOTP (rfc951) message types */
+#define	BOOTREQUEST	1
+#define BOOTREPLY	2
+
+/* Possible values for flags field... */
+#define BOOTP_BROADCAST 32768L
+
+/* Possible values for hardware type (htype) field... */
+#define HTYPE_ETHER	1               /* Ethernet 10Mbps              */
+#define HTYPE_IEEE802	6               /* IEEE 802.2 Token Ring...	*/
+#define HTYPE_FDDI	8		/* FDDI...			*/
+
+/* Magic cookie validating dhcp options field (and bootp vendor
+   extensions field). */
+#define DHCP_OPTIONS_COOKIE	"\143\202\123\143"
+
+/* DHCP Option codes: */
+
+#define DHO_PAD					0
+#define DHO_SUBNET_MASK				1
+#define DHO_TIME_OFFSET				2
+#define DHO_ROUTERS				3
+#define DHO_TIME_SERVERS			4
+#define DHO_NAME_SERVERS			5
+#define DHO_DOMAIN_NAME_SERVERS			6
+#define DHO_LOG_SERVERS				7
+#define DHO_COOKIE_SERVERS			8
+#define DHO_LPR_SERVERS				9
+#define DHO_IMPRESS_SERVERS			10
+#define DHO_RESOURCE_LOCATION_SERVERS		11
+#define DHO_HOST_NAME				12
+#define DHO_BOOT_SIZE				13
+#define DHO_MERIT_DUMP				14
+#define DHO_DOMAIN_NAME				15
+#define DHO_SWAP_SERVER				16
+#define DHO_ROOT_PATH				17
+#define DHO_EXTENSIONS_PATH			18
+#define DHO_IP_FORWARDING			19
+#define DHO_NON_LOCAL_SOURCE_ROUTING		20
+#define DHO_POLICY_FILTER			21
+#define DHO_MAX_DGRAM_REASSEMBLY		22
+#define DHO_DEFAULT_IP_TTL			23
+#define DHO_PATH_MTU_AGING_TIMEOUT		24
+#define DHO_PATH_MTU_PLATEAU_TABLE		25
+#define DHO_INTERFACE_MTU			26
+#define DHO_ALL_SUBNETS_LOCAL			27
+#define DHO_BROADCAST_ADDRESS			28
+#define DHO_PERFORM_MASK_DISCOVERY		29
+#define DHO_MASK_SUPPLIER			30
+#define DHO_ROUTER_DISCOVERY			31
+#define DHO_ROUTER_SOLICITATION_ADDRESS		32
+#define DHO_STATIC_ROUTES			33
+#define DHO_TRAILER_ENCAPSULATION		34
+#define DHO_ARP_CACHE_TIMEOUT			35
+#define DHO_IEEE802_3_ENCAPSULATION		36
+#define DHO_DEFAULT_TCP_TTL			37
+#define DHO_TCP_KEEPALIVE_INTERVAL		38
+#define DHO_TCP_KEEPALIVE_GARBAGE		39
+#define DHO_NIS_DOMAIN				40
+#define DHO_NIS_SERVERS				41
+#define DHO_NTP_SERVERS				42
+#define DHO_VENDOR_ENCAPSULATED_OPTIONS		43
+#define DHO_NETBIOS_NAME_SERVERS		44
+#define DHO_NETBIOS_DD_SERVER			45
+#define DHO_NETBIOS_NODE_TYPE			46
+#define DHO_NETBIOS_SCOPE			47
+#define DHO_FONT_SERVERS			48
+#define DHO_X_DISPLAY_MANAGER			49
+#define DHO_DHCP_REQUESTED_ADDRESS		50
+#define DHO_DHCP_LEASE_TIME			51
+#define DHO_DHCP_OPTION_OVERLOAD		52
+#define DHO_DHCP_MESSAGE_TYPE			53
+#define DHO_DHCP_SERVER_IDENTIFIER		54
+#define DHO_DHCP_PARAMETER_REQUEST_LIST		55
+#define DHO_DHCP_MESSAGE			56
+#define DHO_DHCP_MAX_MESSAGE_SIZE		57
+#define DHO_DHCP_RENEWAL_TIME			58
+#define DHO_DHCP_REBINDING_TIME			59
+#define DHO_VENDOR_CLASS_IDENTIFIER		60
+#define DHO_DHCP_CLIENT_IDENTIFIER		61
+#define DHO_NWIP_DOMAIN_NAME			62
+#define DHO_NWIP_SUBOPTIONS			63
+#define DHO_USER_CLASS				77
+#define DHO_FQDN				81
+#define DHO_DHCP_AGENT_OPTIONS			82
+#define DHO_AUTHENTICATE			90  /* RFC3118, was 210 */
+#define DHO_CLIENT_LAST_TRANSACTION_TIME	91
+#define DHO_ASSOCIATED_IP			92
+#define DHO_SUBNET_SELECTION			118 /* RFC3011! */
+#define DHO_DOMAIN_SEARCH			119 /* RFC3397 */
+#define DHO_VIVCO_SUBOPTIONS			124
+#define DHO_VIVSO_SUBOPTIONS			125
+
+#define DHO_END					255
+
+/* DHCP message types. */
+#define DHCPDISCOVER		1
+#define DHCPOFFER		2
+#define DHCPREQUEST		3
+#define DHCPDECLINE		4
+#define DHCPACK			5
+#define DHCPNAK			6
+#define DHCPRELEASE		7
+#define DHCPINFORM		8
+#define DHCPLEASEQUERY		10
+#define DHCPLEASEUNASSIGNED	11
+#define DHCPLEASEUNKNOWN	12
+#define DHCPLEASEACTIVE		13
+
+
+/* Relay Agent Information option subtypes: */
+#define RAI_CIRCUIT_ID	1
+#define RAI_REMOTE_ID	2
+#define RAI_AGENT_ID	3
+#define RAI_LINK_SELECT	5
+
+/* FQDN suboptions: */
+#define FQDN_NO_CLIENT_UPDATE		1
+#define FQDN_SERVER_UPDATE		2
+#define FQDN_ENCODED			3
+#define FQDN_RCODE1			4
+#define FQDN_RCODE2			5
+#define FQDN_HOSTNAME			6
+#define FQDN_DOMAINNAME			7
+#define FQDN_FQDN			8
+#define FQDN_SUBOPTION_COUNT		8
+
+/* Enterprise Suboptions: */
+#define VENDOR_ISC_SUBOPTIONS		2495
+
+#define DHCP4_CLIENT_PORT 68
+#define DHCP4_SERVER_PORT 67
+
+
+#endif /* DHCP_H */
+
diff --git a/src/lib/dhcp/dhcp6.h b/src/lib/dhcp/dhcp6.h
index b3ee0bf..6012003 100644
--- a/src/lib/dhcp/dhcp6.h
+++ b/src/lib/dhcp/dhcp6.h
@@ -22,18 +22,18 @@
 #define D6O_IA_NA                               3
 #define D6O_IA_TA                               4
 #define D6O_IAADDR                              5
-#define D6O_ORO                                         6
+#define D6O_ORO                                 6
 #define D6O_PREFERENCE                          7
 #define D6O_ELAPSED_TIME                        8
 #define D6O_RELAY_MSG                           9
 /* Option code 10 unassigned. */
 #define D6O_AUTH                                11
 #define D6O_UNICAST                             12
-#define D6O_STATUS_CODE                                 13
+#define D6O_STATUS_CODE                         13
 #define D6O_RAPID_COMMIT                        14
 #define D6O_USER_CLASS                          15
 #define D6O_VENDOR_CLASS                        16
-#define D6O_VENDOR_OPTS                                 17
+#define D6O_VENDOR_OPTS                         17
 #define D6O_INTERFACE_ID                        18
 #define D6O_RECONF_MSG                          19
 #define D6O_RECONF_ACCEPT                       20
@@ -43,7 +43,7 @@
 #define D6O_DOMAIN_SEARCH                       24 /* RFC3646 */
 #define D6O_IA_PD                               25 /* RFC3633 */
 #define D6O_IAPREFIX                            26 /* RFC3633 */
-#define D6O_NIS_SERVERS                                 27 /* RFC3898 */
+#define D6O_NIS_SERVERS                         27 /* RFC3898 */
 #define D6O_NISP_SERVERS                        28 /* RFC3898 */
 #define D6O_NIS_DOMAIN_NAME                     29 /* RFC3898 */
 #define D6O_NISP_DOMAIN_NAME                    30 /* RFC3898 */
@@ -55,13 +55,13 @@
 #define D6O_GEOCONF_CIVIC                       36 /* RFC4776 */
 #define D6O_REMOTE_ID                           37 /* RFC4649 */
 #define D6O_SUBSCRIBER_ID                       38 /* RFC4580 */
-#define D6O_CLIENT_FQDN                                 39 /* RFC4704 */
+#define D6O_CLIENT_FQDN                         39 /* RFC4704 */
 #define D6O_PANA_AGENT                          40 /* paa-option */
 #define D6O_NEW_POSIX_TIMEZONE                  41 /* RFC4833 */
 #define D6O_NEW_TZDB_TIMEZONE                   42 /* RFC4833 */
-#define D6O_ERO                                         43 /* RFC4994 */
+#define D6O_ERO                                 43 /* RFC4994 */
 #define D6O_LQ_QUERY                            44 /* RFC5007 */
-#define D6O_CLIENT_DATA                                 45 /* RFC5007 */
+#define D6O_CLIENT_DATA                         45 /* RFC5007 */
 #define D6O_CLT_TIME                            46 /* RFC5007 */
 #define D6O_LQ_RELAY_DATA                       47 /* RFC5007 */
 #define D6O_LQ_CLIENT_LINK                      48 /* RFC5007 */
@@ -76,7 +76,7 @@
 #define STATUS_NotOnLink         4
 #define STATUS_UseMulticast      5
 #define STATUS_NoPrefixAvail     6
-#define STATUS_UnknownQueryType          7
+#define STATUS_UnknownQueryType  7
 #define STATUS_MalformedQuery    8
 #define STATUS_NotConfigured     9
 #define STATUS_NotAllowed       10
@@ -106,8 +106,8 @@ extern const int dhcpv6_type_name_max;
 /* DUID type definitions (RFC3315 section 9).
  */
 #define DUID_LLT        1
-#define DUID_EN                 2
-#define DUID_LL                 3
+#define DUID_EN         2
+#define DUID_LL         3
 
 /* Offsets into IA_*'s where Option spaces commence.  */
 #define IA_NA_OFFSET 12 /* IAID, T1, T2, all 4 octets each */
diff --git a/src/lib/dhcp/libdhcp.cc b/src/lib/dhcp/libdhcp.cc
index 3685bc0..e7154d9 100644
--- a/src/lib/dhcp/libdhcp.cc
+++ b/src/lib/dhcp/libdhcp.cc
@@ -12,16 +12,16 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
-#include <config.h>
+#include "config.h"
 
 #include <boost/shared_array.hpp>
 #include <boost/shared_ptr.hpp>
-#include <dhcp/libdhcp.h>
-#include <dhcp/dhcp6.h>
+#include "dhcp/libdhcp.h"
+#include "dhcp/dhcp6.h"
 
-#include <dhcp/option.h>
-#include <dhcp/option6_ia.h>
-#include <dhcp/option6_iaaddr.h>
+#include "dhcp/option.h"
+#include "dhcp/option6_ia.h"
+#include "dhcp/option6_iaaddr.h"
 
 using namespace std;
 using namespace isc::dhcp;
@@ -29,15 +29,11 @@ using namespace isc::dhcp;
 // static array with factories for options
 std::map<unsigned short, Option::Factory*> LibDHCP::v6factories_;
 
-std::string
-LibDHCP::version() {
-    return PACKAGE_VERSION;
-}
-
 unsigned int
-LibDHCP::unpackOptions6(boost::shared_array<char> buf, unsigned int buf_len,
+LibDHCP::unpackOptions6(const boost::shared_array<uint8_t> buf,
+                        unsigned int buf_len,
                         unsigned int offset, unsigned int parse_len,
-                        isc::dhcp::Option::Option6Lst& options) {
+                        isc::dhcp::Option::Option6Collection& options) {
     if (offset + parse_len > buf_len) {
         isc_throw(OutOfRange, "Option parse failed. Tried to parse "
                   << parse_len << " bytes at offset " << offset
@@ -45,12 +41,10 @@ LibDHCP::unpackOptions6(boost::shared_array<char> buf, unsigned int buf_len,
     }
     unsigned int end = offset + parse_len;
 
-    while (offset<end) {
-        unsigned int opt_type = static_cast<unsigned char>(buf[offset])*256
-            + static_cast<unsigned char>(buf[offset+1]);
+    while (offset +4 <= end) {
+        uint16_t opt_type = buf[offset]*256 + buf[offset+1];
         offset += 2;
-        unsigned int opt_len = static_cast<unsigned char>(buf[offset]*256)
-            + static_cast<unsigned char>(buf[offset+1]);
+        uint16_t opt_len = buf[offset]*256 + buf[offset+1];
         offset += 2;
 
         if (offset + opt_len > end ) {
@@ -62,8 +56,7 @@ LibDHCP::unpackOptions6(boost::shared_array<char> buf, unsigned int buf_len,
         case D6O_IA_NA:
         case D6O_IA_PD:
             // cout << "Creating Option6IA" << endl;
-            opt = boost::shared_ptr<Option>(new Option6IA(Option::V6,
-                                                          opt_type,
+            opt = boost::shared_ptr<Option>(new Option6IA(opt_type,
                                                           buf, buf_len,
                                                           offset,
                                                           opt_len));
@@ -92,12 +85,12 @@ LibDHCP::unpackOptions6(boost::shared_array<char> buf, unsigned int buf_len,
 }
 
 unsigned int
-LibDHCP::packOptions6(boost::shared_array<char> data,
+LibDHCP::packOptions6(boost::shared_array<uint8_t> data,
                       unsigned int data_len,
                       unsigned int offset,
-                      isc::dhcp::Option::Option6Lst& options) {
+                      const isc::dhcp::Option::Option6Collection& options) {
     try {
-        for (isc::dhcp::Option::Option6Lst::iterator it = options.begin();
+        for (isc::dhcp::Option::Option6Collection::const_iterator it = options.begin();
              it != options.end();
              ++it) {
             unsigned short opt_len = (*it).second->len();
@@ -108,9 +101,9 @@ LibDHCP::packOptions6(boost::shared_array<char> data,
             offset = (*it).second->pack(data, data_len, offset);
         }
     }
-    catch (Exception e) {
-        cout << "Packet build failed." << endl;
-        return (-1);
+    catch (const Exception&) {
+        cout << "Packet build failed (Option build failed)." << endl;
+        throw;
     }
     return (offset);
 }
diff --git a/src/lib/dhcp/libdhcp.h b/src/lib/dhcp/libdhcp.h
index edc2d6c..c2ac949 100644
--- a/src/lib/dhcp/libdhcp.h
+++ b/src/lib/dhcp/libdhcp.h
@@ -16,7 +16,7 @@
 #define LIBDHCP_H_
 
 #include <iostream>
-#include <dhcp/pkt6.h>
+#include "dhcp/pkt6.h"
 
 namespace isc {
 namespace dhcp {
@@ -24,13 +24,6 @@ namespace dhcp {
 class LibDHCP {
 
 public:
-    /// Returns version of the library.
-    ///
-    /// @return string that contains libdhcp version.
-    ///
-    static std::string
-    version();
-
     /// Builds collection of options.
     ///
     /// Builds raw (on-wire) data for provided collection of options.
@@ -44,9 +37,9 @@ public:
     ///         used byte)
     ///
     static unsigned int
-    packOptions6(boost::shared_array<char> buf, unsigned int buf_len,
+    packOptions6(boost::shared_array<uint8_t> buf, unsigned int buf_len,
                  unsigned int offset,
-                 isc::dhcp::Option::Option6Lst& options);
+                 const isc::dhcp::Option::Option6Collection& options);
 
     ///
     /// Parses provided buffer and creates Option objects.
@@ -62,9 +55,9 @@ public:
     /// @return offset to first byte after last parsed option
     ///
     static unsigned int
-    unpackOptions6(boost::shared_array<char> buf, unsigned int buf_len,
+    unpackOptions6(const boost::shared_array<uint8_t> buf, unsigned int buf_len,
                    unsigned int offset, unsigned int parse_len,
-                   isc::dhcp::Option::Option6Lst& options_);
+                   isc::dhcp::Option::Option6Collection& options_);
 
     ///
     /// Registers factory method that produces options of specific option types.
diff --git a/src/lib/dhcp/option.cc b/src/lib/dhcp/option.cc
index 6a52055..b0b30ca 100644
--- a/src/lib/dhcp/option.cc
+++ b/src/lib/dhcp/option.cc
@@ -22,13 +22,15 @@
 #include <sstream>
 #include <iomanip>
 #include <boost/shared_array.hpp>
-#include <exceptions/exceptions.h>
+#include "exceptions/exceptions.h"
+#include "util/io_utilities.h"
 
-#include <dhcp/option.h>
-#include <dhcp/libdhcp.h>
+#include "dhcp/option.h"
+#include "dhcp/libdhcp.h"
 
 using namespace std;
 using namespace isc::dhcp;
+using namespace isc::util;
 
 Option::Option(Universe u, unsigned short type)
     :universe_(u), type_(type), data_len_(0) {
@@ -36,7 +38,8 @@ 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,
+               const boost::shared_array<uint8_t>& buf,
                unsigned int offset, unsigned int len)
     :universe_(u), type_(type), data_(buf),
      data_len_(len), offset_(offset)
@@ -47,7 +50,7 @@ Option::Option(Universe u, unsigned short type, boost::shared_array<char> buf,
 }
 
 unsigned int
-Option::pack(boost::shared_array<char> buf,
+Option::pack(boost::shared_array<uint8_t>& buf,
              unsigned int buf_len,
              unsigned int offset) {
     switch (universe_) {
@@ -62,24 +65,24 @@ Option::pack(boost::shared_array<char> buf,
 
 
 unsigned int
-Option::pack4(boost::shared_array<char> buf,
+Option::pack4(boost::shared_array<uint8_t>& buf,
              unsigned int buf_len,
              unsigned int offset) {
     if ( offset+len() > buf_len ) {
         isc_throw(OutOfRange, "Failed to pack v4 option=" <<
                   type_ << ",len=" << data_len_ << ": too small buffer.");
     }
-    char *ptr = &buf[offset];
+    uint8_t *ptr = &buf[offset];
     ptr[0] = type_;
     ptr[1] = data_len_;
     ptr += 2;
-    memcpy(ptr, &data_[0], data_len_+4);
+    memcpy(ptr, &data_[0], data_len_);
 
     return offset + len();
 }
 
 unsigned int
-Option::pack6(boost::shared_array<char> buf,
+Option::pack6(boost::shared_array<uint8_t>& buf,
              unsigned int buf_len,
              unsigned int offset) {
     if ( offset+len() > buf_len ) {
@@ -87,23 +90,23 @@ Option::pack6(boost::shared_array<char> buf,
                   type_ << ",len=" << len() << ": too small buffer.");
     }
 
-    int length = len() - getHeaderLen();
+    uint8_t * ptr = &buf[offset];
+
+    ptr = writeUint16(type_, ptr);
+
+    ptr = writeUint16(len() - getHeaderLen(), ptr);
 
-    char * ptr = &buf[offset];
-    *(uint16_t*)ptr = htons(type_);
-    ptr += 2;
-    *(uint16_t*)ptr = htons(length);
-    ptr += 2;
     if (data_len_)
         memcpy(ptr, &data_[offset_], data_len_);
 
-    offset += 4 + data_len_; // end of this option
+    // end of fixed part of this option
+    offset += OPTION6_HDR_LEN + data_len_;
 
-    return LibDHCP::packOptions6(buf, buf_len, offset, optionLst_);
+    return LibDHCP::packOptions6(buf, buf_len, offset, options_);
 }
 
 unsigned int
-Option::unpack(boost::shared_array<char> buf,
+Option::unpack(const boost::shared_array<uint8_t>& buf,
                unsigned int buf_len,
                unsigned int offset,
                unsigned int parse_len) {
@@ -120,7 +123,7 @@ Option::unpack(boost::shared_array<char> buf,
 }
 
 unsigned int
-Option::unpack4(boost::shared_array<char>,
+Option::unpack4(const boost::shared_array<uint8_t>&,
                 unsigned int ,
                 unsigned int ,
                 unsigned int ) {
@@ -129,7 +132,7 @@ Option::unpack4(boost::shared_array<char>,
 }
 
 unsigned int
-Option::unpack6(boost::shared_array<char> buf,
+Option::unpack6(const boost::shared_array<uint8_t>& buf,
                 unsigned int buf_len,
                 unsigned int offset,
                 unsigned int parse_len) {
@@ -146,25 +149,30 @@ Option::unpack6(boost::shared_array<char> buf,
     data_len_ = buf_len;
 
     return LibDHCP::unpackOptions6(buf, buf_len, offset, parse_len,
-                                   optionLst_);
+                                   options_);
 }
 
-unsigned short Option::len() {
+unsigned short
+Option::len() {
+
+    // length of the whole option is header and data stored in this option...
     int length = getHeaderLen() + data_len_;
 
-    for (Option::Option6Lst::iterator it = optionLst_.begin();
-         it != optionLst_.end();
+    // ... and sum of lengths of all suboptions
+    for (Option::Option6Collection::iterator it = options_.begin();
+         it != options_.end();
          ++it) {
         length += (*it).second->len();
     }
 
+    // note that this is not equal to lenght field. This value denotes
+    // number of bytes required to store this option. length option should
+    // contain (len()-getHeaderLen()) value.
     return (length);
 }
 
-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
+bool
+Option::valid() {
     if (universe_ != V4 &&
         universe_ != V6) {
         return (false);
@@ -175,15 +183,16 @@ bool Option::valid() {
 
 void
 isc::dhcp::Option::addOption(boost::shared_ptr<isc::dhcp::Option> opt) {
-    optionLst_.insert(pair<int, boost::shared_ptr<Option> >(opt->getType(),
+    options_.insert(pair<int, boost::shared_ptr<Option> >(opt->getType(),
                                                             opt));
 
 }
 
 boost::shared_ptr<isc::dhcp::Option>
 Option::getOption(unsigned short opt_type) {
-    isc::dhcp::Option::Option6Lst::const_iterator x = optionLst_.find(opt_type);
-    if (x!=optionLst_.end()) {
+    isc::dhcp::Option::Option6Collection::const_iterator x =
+        options_.find(opt_type);
+    if ( x != options_.end() ) {
         return (*x).second;
     }
     return boost::shared_ptr<isc::dhcp::Option>(); // NULL
@@ -191,9 +200,9 @@ Option::getOption(unsigned short opt_type) {
 
 bool
 Option::delOption(unsigned short opt_type) {
-    isc::dhcp::Option::Option6Lst::iterator x = optionLst_.find(opt_type);
-    if (x!=optionLst_.end()) {
-        optionLst_.erase(x);
+    isc::dhcp::Option::Option6Collection::iterator x = options_.find(opt_type);
+    if ( x != options_.end() ) {
+        options_.erase(x);
         return true; // delete successful
     }
     return (false); // option not found, can't delete
@@ -206,19 +215,19 @@ std::string Option::toText(int indent /* =0 */ ) {
     for (int i=0; i<indent; i++)
         tmp << " ";
 
-    tmp << "type=" << type_ << ", len=" << data_len_ << ":";
+    tmp << "type=" << type_ << ", len=" << data_len_ << ": ";
 
     for (unsigned int i=0; i<data_len_; i++) {
         if (i) {
             tmp << ":";
         }
         tmp << setfill('0') << setw(2) << hex
-            << (unsigned short)(unsigned char)data_[offset_+i];
+            << static_cast<unsigned short>(data_[offset_+i]);
     }
 
     // print suboptions
-    for (Option6Lst::const_iterator opt=optionLst_.begin();
-         opt!=optionLst_.end();
+    for (Option6Collection::const_iterator opt=options_.begin();
+         opt!=options_.end();
          ++opt) {
         tmp << (*opt).second->toText(indent+2);
     }
@@ -230,7 +239,7 @@ Option::getType() {
     return type_;
 }
 
-char*
+uint8_t*
 Option::getData() {
     if (data_len_) {
         return (&data_[offset_]);
@@ -243,14 +252,13 @@ unsigned short
 Option::getHeaderLen() {
     switch (universe_) {
     case V4:
-        return 2; // header length for v4
+        return OPTION4_HDR_LEN; // header length for v4
     case V6:
-        return 4; // header length for v6
+        return OPTION6_HDR_LEN; // header length for v6
     }
     return 0; // should not happen
 }
 
-
 Option::~Option() {
 
 }
diff --git a/src/lib/dhcp/option.h b/src/lib/dhcp/option.h
index 65f1ba8..5caacdb 100644
--- a/src/lib/dhcp/option.h
+++ b/src/lib/dhcp/option.h
@@ -15,8 +15,10 @@
 #ifndef OPTION_H_
 #define OPTION_H_
 
+#include <stdint.h>
 #include <string>
 #include <map>
+#include <boost/shared_ptr.hpp>
 #include <boost/shared_array.hpp>
 
 namespace isc {
@@ -24,36 +26,78 @@ namespace dhcp {
 
 class Option {
 public:
+    /// length of the usual DHCPv4 option header (there are exceptions)
+    const static size_t OPTION4_HDR_LEN = 2;
+
+    /// length of any DHCPv6 option header
+    const static size_t OPTION6_HDR_LEN = 4;
+
+    /// defines option universe DHCPv4 or DHCPv6
     enum Universe { V4, V6 };
-    typedef std::map<unsigned int, boost::shared_ptr<Option> > Option4Lst;
-    typedef std::multimap<unsigned int, boost::shared_ptr<Option> > Option6Lst;
+
+    /// a collection of DHCPv4 options
+    typedef std::map<unsigned int, boost::shared_ptr<Option> >
+    Option4Collection;
+
+    /// a collection of DHCPv6 options
+    typedef std::multimap<unsigned int, boost::shared_ptr<Option> >
+    Option6Collection;
+
+    /// @brief a factory function prototype
+    ///
+    /// @param u option universe (DHCPv4 or DHCPv6)
+    /// @param type option type
+    /// @param buf pointer to a buffer
+    /// @param offset offset to first data byte in that buffer
+    /// @param len data length of this option
+    ///
+    /// @return a pointer to a created option object
     typedef boost::shared_ptr<Option> Factory(Option::Universe u,
                                               unsigned short type,
-                                              boost::shared_array<char> buf,
+                                              boost::shared_array<uint8_t>& buf,
                                               unsigned int offset,
                                               unsigned int len);
 
-    // ctor, used for options constructed, usually during transmission
+    /// @brief ctor, used for options constructed, usually during transmission
+    ///
+    /// @param u option universe (DHCPv4 or DHCPv6)
+    /// @param type option type
     Option(Universe u, unsigned short type);
 
-    // 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
-    Option(Universe u, unsigned short type, boost::shared_array<char> buf,
-           unsigned int offset,
+    /// @brief 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
+    ///
+    /// @param u specifies universe (V4 or V6)
+    /// @param type option type
+    /// @param buf pointer to a buffer
+    /// @param offset offset in a buffer pointing to first byte of data
+    /// @param len length of the option data
+    Option(Universe u, unsigned short type,
+           const boost::shared_array<uint8_t>& buf, unsigned int offset,
            unsigned int len);
 
-    // writes option in wire-format to buf, returns pointer to first unused
-    // byte after stored option
+    /// @brief writes option in wire-format to buf
+    ///
+    /// Writes option in wire-format to buffer, returns pointer to first unused
+    /// byte after stored option (that is useful for writing options one after
+    /// another)
+    ///
+    /// @param buf pointer to a buffer
+    /// @param buf_len length of the buffer
+    /// @param offset offset to place, where option shout be stored
+    ///
+    /// @return offset to first unused byte after stored option
+    ///
     virtual unsigned int
-    pack(boost::shared_array<char> buf,
+    pack(boost::shared_array<uint8_t>& buf,
          unsigned int buf_len,
          unsigned int offset);
 
-    ///
     /// @brief Parses buffer.
     ///
     /// Parses received buffer, returns offset to the first unused byte after
@@ -64,29 +108,24 @@ public:
     /// @param offset offset, where start parsing option
     /// @param parse_len how many bytes should be parsed
     ///
-    /// @return offset after last parsed option
-    ///
+    /// @return offset after last parsed octet
     virtual unsigned int
-    unpack(boost::shared_array<char> buf,
+    unpack(const boost::shared_array<uint8_t>& buf,
            unsigned int buf_len,
            unsigned int offset,
            unsigned int parse_len);
 
-    ///
     /// Returns string representation of the option.
     ///
     /// @param indent number of spaces before printing text
     ///
     /// @return string with text representation.
-    ///
     virtual std::string
     toText(int indent = 0);
 
-    ///
     /// Returns option type (0-255 for DHCPv4, 0-65535 for DHCPv6)
     ///
     /// @return option type
-    ///
     unsigned short
     getType();
 
@@ -94,32 +133,39 @@ public:
     /// option header)
     ///
     /// @return length of the option
-    ///
     virtual unsigned short
     len();
 
     /// @brief Returns length of header (2 for v4, 4 for v6)
     ///
     /// @return length of option header
-    ///
     virtual unsigned short
     getHeaderLen();
 
     /// returns if option is valid (e.g. option may be truncated)
+    ///
+    /// @return true, if option is valid
     virtual bool
     valid();
 
     /// Returns pointer to actual data.
     ///
     /// @return pointer to actual data (or NULL if there is no data)
-    ///
-    virtual char*
+    virtual uint8_t*
     getData();
 
     /// Adds a sub-option.
     ///
-    /// @param opt shared pointer to a suboption that is going to be added.
+    /// Some DHCPv6 options can have suboptions. This method allows adding
+    /// options within options.
     ///
+    /// Note: option is passed by value. That is very convenient as it allows
+    /// downcasting from any derived classes, e.g. shared_ptr<Option6_IA> type
+    /// can be passed directly, without any casts. That would not be possible
+    /// with passing by reference. addOption() is expected to be used in
+    /// many places. Requiring casting is not feasible.
+    ///
+    /// @param opt shared pointer to a suboption that is going to be added.
     void
     addOption(boost::shared_ptr<Option> opt);
 
@@ -128,7 +174,6 @@ public:
     /// @param type type of requested suboption
     ///
     /// @return shared_ptr to requested suoption
-    ///
     boost::shared_ptr<isc::dhcp::Option>
     getOption(unsigned short type);
 
@@ -137,19 +182,15 @@ public:
     /// @param type Type of option to be deleted.
     ///
     /// @return true if option was deleted, false if no such option existed
-    ///
     bool
     delOption(unsigned short type);
 
-    /// TODO Need to implement getOptions() as well
-
-    // just to force that every option has virtual dtor
+    /// just to force that every option has virtual dtor
     virtual
     ~Option();
 
 protected:
 
-    ///
     /// Builds raw (over-wire) buffer of this option, including all
     /// defined suboptions. Version for building DHCPv4 options.
     ///
@@ -158,13 +199,11 @@ protected:
     /// @param offset offset from start of the buf buffer
     ///
     /// @return offset to the next byte after last used byte
-    ///
     virtual unsigned int
-    pack4(boost::shared_array<char> buf,
+    pack4(boost::shared_array<uint8_t>& buf,
           unsigned int buf_len,
           unsigned int offset);
 
-    ///
     /// Builds raw (over-wire) buffer of this option, including all
     /// defined suboptions. Version for building DHCPv4 options.
     ///
@@ -173,13 +212,11 @@ protected:
     /// @param offset offset from start of the buf buffer
     ///
     /// @return offset to the next byte after last used byte
-    ///
     virtual unsigned int
-    pack6(boost::shared_array<char> buf,
+    pack6(boost::shared_array<uint8_t>& buf,
           unsigned int buf_len,
           unsigned int offset);
 
-    ///
     /// Parses provided buffer and creates DHCPv4 options.
     ///
     /// @param buf buffer that contains raw buffer to parse (on-wire format)
@@ -187,14 +224,12 @@ protected:
     /// @param offset offset from start of the buf buffer
     ///
     /// @return offset to the next byte after last parsed byte
-    ///
     virtual unsigned int
-    unpack4(boost::shared_array<char> buf,
+    unpack4(const boost::shared_array<uint8_t>& buf,
             unsigned int buf_len,
             unsigned int offset,
             unsigned int parse_len);
 
-    ///
     /// Parses provided buffer and creates DHCPv6 options.
     ///
     /// @param buf buffer that contains raw buffer to parse (on-wire format)
@@ -202,26 +237,35 @@ protected:
     /// @param offset offset from start of the buf buffer
     ///
     /// @return offset to the next byte after last parsed byte
-    ///
     virtual unsigned int
-    unpack6(boost::shared_array<char> buf,
+    unpack6(const boost::shared_array<uint8_t>& buf,
             unsigned int buf_len,
             unsigned int offset,
             unsigned int parse_len);
 
-    Universe universe_; // option universe (V4 or V6)
-    unsigned short type_; // option type (0-255 for DHCPv4, 0-65535 for DHCPv6)
+    /// option universe (V4 or V6)
+    Universe universe_;
+
+    /// option type (0-255 for DHCPv4, 0-65535 for DHCPv6)
+    unsigned short type_;
+
+    /// shared pointer to a buffer (usually a part of packet)
+    boost::shared_array<uint8_t> data_;
+
+    /// length of data only. Use len() if you want to
+    /// know proper length with option header overhead
+    unsigned int data_len_;
+
+    /// data is a shared_pointer that points out to the
+    /// whole packet. offset_ specifies where data for
+    /// this option begins.
+    unsigned int offset_;
 
-    boost::shared_array<char> data_;
-    unsigned int data_len_; // length of data only. Use len() if you want to
-                            // know proper length with option header overhead
-    unsigned int offset_; // data is a shared_pointer that points out to the
-                          // whole packet. offset_ specifies where data for
-                          // this option begins.
+    /// collection for storing suboptions
+    Option6Collection options_;
 
-    // TODO: probably 2 different containers have to be used for v4 (unique
-    // options) and v6 (options with the same type can repeat)
-    Option6Lst optionLst_;
+    /// TODO: probably 2 different containers have to be used for v4 (unique
+    /// options) and v6 (options with the same type can repeat)
 };
 
 } // namespace isc::dhcp
diff --git a/src/lib/dhcp/option6_addrlst.cc b/src/lib/dhcp/option6_addrlst.cc
index a4d7e3c..1ab297e 100644
--- a/src/lib/dhcp/option6_addrlst.cc
+++ b/src/lib/dhcp/option6_addrlst.cc
@@ -19,33 +19,32 @@
 #include <arpa/inet.h>
 #endif
 #include <sstream>
-#include <exceptions/exceptions.h>
+#include "exceptions/exceptions.h"
 
-#include <dhcp/libdhcp.h>
-#include <dhcp/option6_addrlst.h>
-#include <dhcp/dhcp6.h>
-#include <asiolink/io_address.h>
+#include "asiolink/io_address.h"
+#include "util/io_utilities.h"
+#include "dhcp/libdhcp.h"
+#include "dhcp/option6_addrlst.h"
+#include "dhcp/dhcp6.h"
 
 using namespace std;
 using namespace isc;
 using namespace isc::dhcp;
 using namespace isc::asiolink;
-
+using namespace isc::util;
 
 Option6AddrLst::Option6AddrLst(unsigned short type,
-                               std::vector<isc::asiolink::IOAddress>& addrs)
-    :Option(V6, type) {
-    addrs_ = addrs;
+                               const AddressContainer& addrs)
+    :Option(V6, type), addrs_(addrs) {
 }
 
 Option6AddrLst::Option6AddrLst(unsigned short type,
-                               isc::asiolink::IOAddress addr)
-    :Option(V6, type) {
-    addrs_.push_back(addr);
+                               const isc::asiolink::IOAddress& addr)
+    :Option(V6, type), addrs_(1,addr) {
 }
 
 Option6AddrLst::Option6AddrLst(unsigned short type,
-                               boost::shared_array<char> buf,
+                               boost::shared_array<uint8_t> buf,
                                unsigned int buf_len,
                                unsigned int offset,
                                unsigned int option_len)
@@ -54,18 +53,18 @@ Option6AddrLst::Option6AddrLst(unsigned short type,
 }
 
 void
-Option6AddrLst::setAddress(isc::asiolink::IOAddress addr) {
+Option6AddrLst::setAddress(const isc::asiolink::IOAddress& addr) {
     addrs_.clear();
     addrs_.push_back(addr);
 }
 
 void
-Option6AddrLst::setAddresses(std::vector<isc::asiolink::IOAddress>& addrs) {
+Option6AddrLst::setAddresses(const AddressContainer& addrs) {
     addrs_ = addrs;
 }
 
 unsigned int
-Option6AddrLst::pack(boost::shared_array<char> buf,
+Option6AddrLst::pack(boost::shared_array<uint8_t>& buf,
                     unsigned int buf_len,
                     unsigned int offset) {
     if (len() > buf_len) {
@@ -73,29 +72,32 @@ Option6AddrLst::pack(boost::shared_array<char> buf,
                   << ", buffer=" << buf_len << ": too small buffer.");
     }
 
-    *(uint16_t*)&buf[offset] = htons(type_);
-    offset += 2;
-    *(uint16_t*)&buf[offset] = htons(len()-4); // len() returns complete option
-    // length. len field contains length without 4-byte option header
-    offset += 2;
+    writeUint16(type_, &buf[offset]);
+    offset += sizeof(uint16_t);
+
+    // len() returns complete option length.
+    // len field contains length without 4-byte option header
+    writeUint16(len() - OPTION6_HDR_LEN, &buf[offset]);
+    offset += sizeof(uint16_t);
 
-    for (std::vector<IOAddress>::const_iterator addr=addrs_.begin();
+    // this wrapping is *ugly*. I wish there was a a
+    for (AddressContainer::const_iterator addr=addrs_.begin();
          addr!=addrs_.end();
          ++addr) {
         memcpy(&buf[offset],
                addr->getAddress().to_v6().to_bytes().data(),
-               16);
-        offset += 16;
+               V6ADDRESS_LEN);
+        offset += V6ADDRESS_LEN;
     }
 
     return offset;
 }
 
 unsigned int
-Option6AddrLst::unpack(boost::shared_array<char> buf,
-                  unsigned int buf_len,
-                  unsigned int offset,
-                  unsigned int option_len) {
+Option6AddrLst::unpack(const boost::shared_array<uint8_t>& buf,
+                       unsigned int buf_len,
+                       unsigned int offset,
+                       unsigned int option_len) {
     if (offset+option_len > buf_len) {
         isc_throw(OutOfRange, "Option " << type_
                   << " truncated.");
@@ -122,7 +124,7 @@ std::string Option6AddrLst::toText(int indent /* =0 */) {
 
     tmp << "type=" << type_ << " " << addrs_.size() << "addr(s): ";
 
-    for (AddrsContainer::const_iterator addr=addrs_.begin();
+    for (AddressContainer::const_iterator addr=addrs_.begin();
          addr!=addrs_.end();
          ++addr) {
         tmp << addr->toText() << " ";
@@ -132,5 +134,5 @@ std::string Option6AddrLst::toText(int indent /* =0 */) {
 
 unsigned short Option6AddrLst::len() {
 
-    return (4 /* DHCPv6 option header len */ + addrs_.size()*16);
+    return (OPTION6_HDR_LEN + addrs_.size()*16);
 }
diff --git a/src/lib/dhcp/option6_addrlst.h b/src/lib/dhcp/option6_addrlst.h
index f17e28d..c5b32af 100644
--- a/src/lib/dhcp/option6_addrlst.h
+++ b/src/lib/dhcp/option6_addrlst.h
@@ -16,8 +16,8 @@
 #define OPTION6_ADDRLST_H_
 
 #include <vector>
-#include <asiolink/io_address.h>
-#include <dhcp/option.h>
+#include "asiolink/io_address.h"
+#include "dhcp/option.h"
 
 namespace isc {
 namespace dhcp {
@@ -29,9 +29,9 @@ namespace dhcp {
 ///
 class Option6AddrLst: public Option {
 
-
 public:
-    typedef std::vector<isc::asiolink::IOAddress> AddrsContainer;
+    /// a container for (IPv6) addresses
+    typedef std::vector<isc::asiolink::IOAddress> AddressContainer;
 
     /// @brief Constructor used during option generation.
     ///
@@ -39,7 +39,7 @@ public:
     /// @param addrs vector of addresses to be stored
     ///
     Option6AddrLst(unsigned short type,
-                   AddrsContainer& addrs);
+                   const AddressContainer& addrs);
 
     /// @brief Simplified constructor for a single address
     ///
@@ -47,7 +47,7 @@ public:
     /// @param addr a single address to be stored
     ///
     Option6AddrLst(unsigned short type,
-                   isc::asiolink::IOAddress addr);
+                   const isc::asiolink::IOAddress& addr);
 
     /// @brief Constructor used for parsing received option
     ///
@@ -57,7 +57,7 @@ public:
     /// @param offset offset to beginning of option data
     /// @param len length of option data
     ///
-    Option6AddrLst(unsigned short type, boost::shared_array<char> buf,
+    Option6AddrLst(unsigned short type, boost::shared_array<uint8_t> buf,
                    unsigned int buf_len,
                    unsigned int offset,
                    unsigned int len);
@@ -71,7 +71,7 @@ public:
     /// @return offset to the next unused char (just after stored option)
     ///
     unsigned int
-    pack(boost::shared_array<char> buf, unsigned int buf_len,
+    pack(boost::shared_array<uint8_t>& buf, unsigned int buf_len,
          unsigned int offset);
 
     /// @brief Parses received data
@@ -84,7 +84,7 @@ public:
     /// @return offset to the next unparsed char (just after parsed option)
     ///
     virtual unsigned int
-    unpack(boost::shared_array<char> buf,
+    unpack(const boost::shared_array<uint8_t>& buf,
            unsigned int buf_len,
            unsigned int offset,
            unsigned int parse_len);
@@ -95,13 +95,13 @@ public:
     ///
     /// @param addr a single address to be added
     ///
-    void setAddress(isc::asiolink::IOAddress addr);
+    void setAddress(const isc::asiolink::IOAddress& addr);
 
     /// @brief Sets list of addresses.
     ///
     /// @param addrs a vector of addresses to be added
     ///
-    void setAddresses(std::vector<isc::asiolink::IOAddress>& addrs);
+    void setAddresses(const AddressContainer& addrs);
 
     /// @brief Returns vector with addresses.
     ///
@@ -111,14 +111,14 @@ public:
     ///
     /// @return vector with addresses
     ///
-    AddrsContainer
+    AddressContainer
     getAddresses() { return addrs_; };
 
     // returns data length (data length + DHCPv4/DHCPv6 option header)
     virtual unsigned short len();
 
 protected:
-    AddrsContainer addrs_;
+    AddressContainer addrs_;
 };
 
 } // isc::dhcp namespace
diff --git a/src/lib/dhcp/option6_ia.cc b/src/lib/dhcp/option6_ia.cc
index 8f01191..a3a8a36 100644
--- a/src/lib/dhcp/option6_ia.cc
+++ b/src/lib/dhcp/option6_ia.cc
@@ -19,76 +19,80 @@
 #include <arpa/inet.h>
 #endif
 #include <sstream>
-#include <exceptions/exceptions.h>
+#include "exceptions/exceptions.h"
 
-#include <dhcp/libdhcp.h>
-#include <dhcp/option6_ia.h>
-#include <dhcp/dhcp6.h>
+#include "dhcp/libdhcp.h"
+#include "dhcp/option6_ia.h"
+#include "dhcp/dhcp6.h"
+#include "util/io_utilities.h"
 
 using namespace std;
 using namespace isc;
 using namespace isc::dhcp;
+using namespace isc::util;
 
-Option6IA::Option6IA(Universe u, unsigned short type, unsigned int iaid)
-    :Option(u, type), iaid_(iaid) {
-
+Option6IA::Option6IA(unsigned short type, unsigned int iaid)
+    :Option(Option::V6, 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) {
+Option6IA::Option6IA(unsigned short type,
+                     const boost::shared_array<uint8_t>& buf,
+                     unsigned int buf_len,
+                     unsigned int offset,
+                     unsigned int option_len)
+    :Option(Option::V6, type) {
     unpack(buf, buf_len, offset, option_len);
 }
 
 unsigned int
-Option6IA::pack(boost::shared_array<char> buf,
+Option6IA::pack(boost::shared_array<uint8_t>& buf,
                 unsigned int buf_len,
                 unsigned int offset) {
     if (offset + len() > buf_len) {
-        isc_throw(OutOfRange, "Failed to pack IA option: len=" << 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;
-    *(uint16_t*)ptr = htons(len() - 4); // len() returns complete option length
-    // len field contains length without 4-byte option header
-    ptr += 2;
-    
-    *(uint32_t*)ptr = htonl(iaid_);
-    ptr += 4;
 
-    *(uint32_t*)ptr = htonl(t1_);
-    ptr += 4;
+    if (len() < 16 ) {
+        isc_throw(OutOfRange, "Attempt to build malformed IA option: len="
+                  << len() << " is too small (at least 16 is required).");
+    }
+
+    uint8_t* ptr = &buf[offset];
 
-    *(uint32_t*)ptr = htonl(t2_);
-    ptr += 4;
+    ptr = writeUint16(type_, ptr);
+    ptr = writeUint16(len() - OPTION6_HDR_LEN, ptr);
+    offset += OPTION6_HDR_LEN;
 
-    offset = LibDHCP::packOptions6(buf, buf_len, offset+16, optionLst_);
+    ptr = writeUint32(iaid_, ptr);
+    ptr = writeUint32(t1_, ptr);
+    ptr = writeUint32(t2_, ptr);
+    offset += OPTION6_IA_LEN;
+
+    offset = LibDHCP::packOptions6(buf, buf_len, offset, options_);
     return offset;
 }
 
-unsigned int 
-Option6IA::unpack(boost::shared_array<char> buf,
+unsigned int
+Option6IA::unpack(const boost::shared_array<uint8_t>& buf,
                   unsigned int buf_len,
-                  unsigned int offset, 
+                  unsigned int offset,
                   unsigned int parse_len) {
-    if (parse_len<12 || offset+12>buf_len) {
+    if ( parse_len < OPTION6_IA_LEN || offset + OPTION6_IA_LEN > 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_);
+    
+    iaid_ = readUint32(&buf[offset]);
+    offset += sizeof(uint32_t);
+
+    t1_ = readUint32(&buf[offset]);
+    offset += sizeof(uint32_t);
+
+    t2_ = readUint32(&buf[offset]);
+    offset += sizeof(uint32_t);
+
+    offset = LibDHCP::unpackOptions6(buf, buf_len, offset,
+                                     parse_len - OPTION6_IA_LEN, options_);
 
     return (offset);
 }
@@ -111,10 +115,10 @@ std::string Option6IA::toText(int indent /* = 0*/) {
         tmp << "(unknown)";
     }
     tmp << " iaid=" << iaid_ << ", t1=" << t1_ << ", t2=" << t2_
-        << " " << optionLst_.size() << " sub-options:" << endl;
+        << " " << options_.size() << " sub-options:" << endl;
 
-    for (Option6Lst::const_iterator opt=optionLst_.begin();
-         opt!=optionLst_.end();
+    for (Option6Collection::const_iterator opt=options_.begin();
+         opt!=options_.end();
          ++opt) {
         tmp << (*opt).second->toText(indent+2);
     }
@@ -122,15 +126,15 @@ std::string Option6IA::toText(int indent /* = 0*/) {
 }
 
 unsigned short Option6IA::len() {
-    
-    unsigned short length = 4/*header*/ + 12 /* option content */; // header
+
+    unsigned short length = OPTION6_HDR_LEN /*header (4)*/ +
+        OPTION6_IA_LEN  /* option content (12) */;
 
     // length of all suboptions
-    for (Option::Option6Lst::iterator it = optionLst_.begin();
-         it != optionLst_.end();
+    for (Option::Option6Collection::iterator it = options_.begin();
+         it != options_.end();
          ++it) {
         length += (*it).second->len();
     }
     return (length);
 }
-
diff --git a/src/lib/dhcp/option6_ia.h b/src/lib/dhcp/option6_ia.h
index 802f39c..516b2fc 100644
--- a/src/lib/dhcp/option6_ia.h
+++ b/src/lib/dhcp/option6_ia.h
@@ -15,7 +15,8 @@
 #ifndef OPTION_IA_H_
 #define OPTION_IA_H_
 
-#include <dhcp/option.h>
+#include <stdint.h>
+#include "option.h"
 
 namespace isc {
 namespace dhcp {
@@ -23,61 +24,110 @@ 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
+    /// Length of IA_NA and IA_PD content
+    const static size_t OPTION6_IA_LEN = 12;
+
+    /// @brief ctor, used for options constructed, usually during transmission
+    ///
+    /// @param type option type (usually 4 for IA_NA, 25 for IA_PD)
+    /// @param iaid identity association identifier (id of IA)
+    Option6IA(uint16_t type, unsigned int iaid);
+
+    /// @brief 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
+    ///
+    /// @param type option type (usually 4 for IA_NA, 25 for IA_PD)
+    /// @param buf buffer to be parsed
+    /// @param buf_len buffer length
+    /// @param offset offset in buffer
+    /// @param len number of bytes to parse
+    Option6IA(uint16_t type, const boost::shared_array<uint8_t>& 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.
+    ///
+    /// @param buf buffer (option will be stored here)
+    /// @param buf_len (buffer length)
+    /// @param offset offset place where option should be stored
+    ///
+    /// @return offset to the first unused byte after stored option
     unsigned int
-    pack(boost::shared_array<char> buf, unsigned int buf_len,
+    pack(boost::shared_array<uint8_t>& buf, unsigned int buf_len,
          unsigned int offset);
 
-    // parses received buffer, returns offset to the first unused byte after
-    // parsed option
+    /// @brief Parses received buffer
+    ///
+    /// Parses received buffer and returns offset to the first unused byte after
+    /// parsed option.
+    ///
+    /// @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 octet
     virtual unsigned int
-    unpack(boost::shared_array<char> buf,
-           unsigned int buf_len,
-           unsigned int offset,
-           unsigned int parse_len);
+    unpack(const boost::shared_array<uint8_t>& buf, unsigned int buf_len,
+           unsigned int offset, unsigned int parse_len);
 
     /// Provides human readable text representation
     ///
-    /// @param indent number of leading space characterss
+    /// @param indent number of leading space characters
     ///
     /// @return string with text represenation
-    ///
     virtual std::string
     toText(int indent = 0);
 
+    /// Sets T1 timer.
+    ///
+    /// @param t1 t1 value to be set
     void setT1(unsigned int t1) { t1_=t1; }
+
+
+    /// Sets T2 timer.
+    ///
+    /// @param t2 t2 value to be set
     void setT2(unsigned int t2) { t2_=t2; }
 
-    unsigned int getIAID() { return iaid_; }
-    unsigned int getT1()   { return t1_; }
-    unsigned int getT2()   { return t2_; }
+    /// Returns IA identifier.
+    ///
+    /// @return IAID value.
+    ///
+    unsigned int getIAID() const { return iaid_; }
+
+    /// Returns T1 timer.
+    ///
+    /// @return T1 value.
+    unsigned int getT1() const { return t1_; }
+
+    /// Returns T2 timer.
+    ///
+    /// @return T2 value.
+    unsigned int getT2() const { return t2_; }
 
     /// @brief returns complete length of option
     ///
     /// Returns length of this option, including option header and suboptions
     ///
-    /// @return length
+    /// @return length of this option
     virtual unsigned short
     len();
 
 protected:
+
+    /// keeps IA identifier
     unsigned int iaid_;
+
+    /// keeps T1 timer value
     unsigned int t1_;
+
+    /// keeps T2 timer value
     unsigned int t2_;
 };
 
diff --git a/src/lib/dhcp/option6_iaaddr.cc b/src/lib/dhcp/option6_iaaddr.cc
index 0216d5f..ce2e64a 100644
--- a/src/lib/dhcp/option6_iaaddr.cc
+++ b/src/lib/dhcp/option6_iaaddr.cc
@@ -19,37 +19,37 @@
 #include <arpa/inet.h>
 #endif
 #include <sstream>
-#include <exceptions/exceptions.h>
+#include "exceptions/exceptions.h"
 
-#include <dhcp/libdhcp.h>
-#include <dhcp/option6_iaaddr.h>
-#include <dhcp/dhcp6.h>
-#include <asiolink/io_address.h>
+#include "dhcp/libdhcp.h"
+#include "dhcp/option6_iaaddr.h"
+#include "dhcp/dhcp6.h"
+#include "asiolink/io_address.h"
+#include "util/io_utilities.h"
 
 using namespace std;
 using namespace isc;
 using namespace isc::dhcp;
 using namespace isc::asiolink;
+using namespace isc::util;
 
 Option6IAAddr::Option6IAAddr(unsigned short type,
-                             isc::asiolink::IOAddress addr,
-                             unsigned int pref,
-                             unsigned int valid)
+                             const 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,
+                             boost::shared_array<uint8_t> buf,
+                             unsigned int buf_len, unsigned int offset,
                              unsigned int option_len)
-    :Option(V6, type), addr_(IOAddress("::")) {
+    :Option(V6, type), addr_("::") {
     unpack(buf, buf_len, offset, option_len);
 }
 
 unsigned int
-Option6IAAddr::pack(boost::shared_array<char> buf,
+Option6IAAddr::pack(boost::shared_array<uint8_t>& buf,
                     unsigned int buf_len,
                     unsigned int offset) {
     if (len() > buf_len) {
@@ -57,55 +57,48 @@ Option6IAAddr::pack(boost::shared_array<char> buf,
                   << ", buffer=" << buf_len << ": too small buffer.");
     }
 
-    *(uint16_t*)&buf[offset] = htons(type_);
-    offset += 2;
-    *(uint16_t*)&buf[offset] = htons(len()-4); // len() returns complete option
-    // length. len field contains length without 4-byte option header
-    offset += 2;
+    uint8_t* ptr = &buf[offset];
 
-    memcpy(&buf[offset], addr_.getAddress().to_v6().to_bytes().data(), 16);
-    offset += 16;
+    ptr = writeUint16(type_, ptr);
 
-    *(uint32_t*)&buf[offset] = htonl(preferred_);
-    offset += 4;
-    *(uint32_t*)&buf[offset] = htonl(valid_);
-    offset += 4;
+    // len() returns complete option length. len field contains
+    // length without 4-byte option header
+    ptr = writeUint16(len() - OPTION6_HDR_LEN, ptr);
+    offset += OPTION6_HDR_LEN;
+
+    memcpy(ptr, addr_.getAddress().to_v6().to_bytes().data(), 16);
+    ptr += V6ADDRESS_LEN;
+
+    ptr = writeUint32(preferred_, ptr);
+
+    ptr = writeUint32(valid_, ptr);
+    offset += OPTION6_IAADDR_LEN;
 
     // parse suboption (there shouldn't be any)
-    offset = LibDHCP::packOptions6(buf, buf_len, offset, optionLst_);
+    offset = LibDHCP::packOptions6(buf, buf_len, offset, options_);
     return offset;
 }
 
 unsigned int
-Option6IAAddr::unpack(boost::shared_array<char> buf,
+Option6IAAddr::unpack(const boost::shared_array<uint8_t>& buf,
                   unsigned int buf_len,
                   unsigned int offset,
                   unsigned int parse_len) {
-    if (parse_len<24 || offset+24>buf_len) {
+    if ( parse_len < OPTION6_IAADDR_LEN || offset + OPTION6_IAADDR_LEN > buf_len) {
         isc_throw(OutOfRange, "Option " << type_ << " truncated");
     }
 
     // 16 bytes: IPv6 address
-    /// TODO Implement fromBytes() method in IOAddress
-    char addr_str[INET6_ADDRSTRLEN];
+    addr_ = IOAddress::from_bytes(AF_INET6, &buf[offset]);
+    offset += V6ADDRESS_LEN;
 
-#ifdef _WIN32
-#define DECONST (void *)
-#else
-#define DECONST
-#endif
-
-    inet_ntop(AF_INET6, DECONST &buf[offset], addr_str,INET6_ADDRSTRLEN);
-    addr_ = IOAddress(string(addr_str));
-    offset += 16;
+    preferred_ = readUint32(&buf[offset]);
+    offset += sizeof(uint32_t);
 
-    preferred_ = ntohl(*(uint32_t*)&buf[offset]);
-    offset +=4;
-
-    valid_ = ntohl(*(uint32_t*)&buf[offset]);
-    offset +=4;
+    valid_ = readUint32(&buf[offset]);
+    offset += sizeof(uint32_t);
     offset = LibDHCP::unpackOptions6(buf, buf_len, offset,
-                                     parse_len - 24, optionLst_);
+                                     parse_len - 24, options_);
 
     return offset;
 }
@@ -119,8 +112,8 @@ std::string Option6IAAddr::toText(int indent /* =0 */) {
         << ", preferred-lft=" << preferred_  << ", valid-lft="
         << valid_ << endl;
 
-    for (Option6Lst::const_iterator opt=optionLst_.begin();
-         opt!=optionLst_.end();
+    for (Option6Collection::const_iterator opt=options_.begin();
+         opt!=options_.end();
          ++opt) {
         tmp << (*opt).second->toText(indent+2);
     }
@@ -129,14 +122,13 @@ std::string Option6IAAddr::toText(int indent /* =0 */) {
 
 unsigned short Option6IAAddr::len() {
 
-    unsigned short length = 4/*header*/ + 24 /* content */; // header
+    unsigned short length = OPTION6_HDR_LEN + OPTION6_IAADDR_LEN;
 
     // length of all suboptions
     // TODO implement:
     // protected: unsigned short Option::lenHelper(int header_size);
-
-    for (Option::Option6Lst::iterator it = optionLst_.begin();
-         it != optionLst_.end();
+    for (Option::Option6Collection::iterator it = options_.begin();
+         it != options_.end();
          ++it) {
         length += (*it).second->len();
     }
diff --git a/src/lib/dhcp/option6_iaaddr.h b/src/lib/dhcp/option6_iaaddr.h
index bf2d289..60c5c48 100644
--- a/src/lib/dhcp/option6_iaaddr.h
+++ b/src/lib/dhcp/option6_iaaddr.h
@@ -15,66 +15,132 @@
 #ifndef OPTION6_IAADDR_H_
 #define OPTION6_IAADDR_H_
 
-#include <asiolink/io_address.h>
-#include <dhcp/option.h>
+#include "asiolink/io_address.h"
+#include "dhcp/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
+    /// length of the fixed part of the IAADDR option
+    static const size_t OPTION6_IAADDR_LEN = 24;
+
+    /// @brief ctor, used for options constructed (during transmission)
+    ///
+    /// @param type option type
+    /// @param addr reference to an address
+    /// @param preferred address preferred lifetime (in seconds)
+    /// @param valid address valid lifetime (in seconds)
+    Option6IAAddr(unsigned short type, const isc::asiolink::IOAddress& addr,
+                  unsigned int preferred, 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
+    ///
+    /// @param type option type
+    /// @param buf pointer to a buffer
+    /// @param offset offset to first data byte in that buffer
+    /// @param len data length of this option
+    Option6IAAddr(unsigned short type, boost::shared_array<uint8_t> buf,
+                  unsigned int buf_len, unsigned int offset, unsigned int len);
+
+    /// @brief Writes option in wire-format.
+    ///
+    /// Writes option in wire-format to buf, returns pointer to first unused
+    /// byte after stored option.
+    ///
+    /// @param buf pointer to a buffer
+    /// @param buf_len length of the buffer
+    /// @param offset offset to place, where option shout be stored
+    ///
+    /// @return offset to first unused byte after stored option
     unsigned int
-    pack(boost::shared_array<char> buf, unsigned int buf_len, 
+    pack(boost::shared_array<uint8_t>& 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, 
+    /// @brief Parses buffer.
+    ///
+    /// Parses received buffer, returns offset to the first unused byte after
+    /// parsed option.
+    ///
+    /// @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 octet
+    virtual unsigned int
+    unpack(const boost::shared_array<uint8_t>& buf,
            unsigned int buf_len,
-           unsigned int offset, 
+           unsigned int offset,
            unsigned int parse_len);
 
-    virtual std::string toText(int indent = 0);
+    /// Returns string representation of the option.
+    ///
+    /// @param indent number of spaces before printing text
+    ///
+    /// @return string with text representation.
+    virtual std::string
+    toText(int indent = 0);
 
-    void setAddress(isc::asiolink::IOAddress addr) { addr_ = addr; }
+
+    /// sets address in this option.
+    ///
+    /// @param addr address to be sent in this option
+    void setAddress(const isc::asiolink::IOAddress& addr) { addr_ = addr; }
+
+    /// Sets preferred lifetime (in seconds)
+    ///
+    /// @param pref address preferred lifetime (in seconds)
+    ///
     void setPreferred(unsigned int pref) { preferred_=pref; }
+
+    /// Sets valid lifetime (in seconds).
+    ///
+    /// @param valid address valid lifetime (in seconds)
+    ///
     void setValid(unsigned int valid) { valid_=valid; }
 
-    isc::asiolink::IOAddress getAddress() { return addr_; }
-    unsigned int getPreferred()   { return preferred_; }
-    unsigned int getValid()   { return valid_; }
+    /// Returns  address contained within this option.
+    ///
+    /// @return address
+    isc::asiolink::IOAddress
+    getAddress() const { return addr_; }
 
-    // returns data length (data length + DHCPv4/DHCPv6 option header)
-    virtual unsigned short len();
+    /// Returns preferred lifetime of an address.
+    ///
+    /// @return preferred lifetime (in seconds)
+    unsigned int
+    getPreferred() const { return preferred_; }
+
+    /// Returns valid lifetime of an address.
+    ///
+    /// @return valid lifetime (in seconds)
+    unsigned int
+    getValid() const { return valid_; }
+
+    /// returns data length (data length + DHCPv4/DHCPv6 option header)
+    virtual unsigned short
+    len();
 
 protected:
+    /// contains an IPv6 address
     isc::asiolink::IOAddress addr_;
+
+    /// contains preferred-lifetime timer (in seconds)
     unsigned int preferred_;
+
+    /// contains valid-lifetime timer (in seconds)
     unsigned int valid_;
 };
 
 } // isc::dhcp namespace
 } // isc namespace
-    
+
 #endif /* OPTION_IA_H_ */
diff --git a/src/lib/dhcp/pkt4.cc b/src/lib/dhcp/pkt4.cc
new file mode 100644
index 0000000..a9a5caa
--- /dev/null
+++ b/src/lib/dhcp/pkt4.cc
@@ -0,0 +1,180 @@
+// 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 <dhcp/pkt4.h>
+#include <dhcp/libdhcp.h>
+#include <dhcp/dhcp4.h>
+#include <exceptions/exceptions.h>
+#include <asiolink/io_address.h>
+#include <iostream>
+#include <sstream>
+
+using namespace std;
+using namespace isc::dhcp;
+using namespace isc::asiolink;
+
+namespace isc {
+
+Pkt4::Pkt4(uint8_t msg_type, uint32_t transid)
+     :local_addr_(IOAddress("0.0.0.0")),
+      remote_addr_(IOAddress("0.0.0.0")),
+      iface_(""),
+      ifindex_(0),
+      local_port_(DHCP4_SERVER_PORT),
+      remote_port_(DHCP4_CLIENT_PORT),
+      op_(DHCPTypeToBootpType(msg_type)),
+      htype_(HTYPE_ETHER),
+      hlen_(0),
+      hops_(0),
+      transid_(transid),
+      secs_(0),
+      flags_(0),
+      ciaddr_(IOAddress("0.0.0.0")),
+      yiaddr_(IOAddress("0.0.0.0")),
+      siaddr_(IOAddress("0.0.0.0")),
+      giaddr_(IOAddress("0.0.0.0")),
+      bufferIn_(0), // not used, this is TX packet
+      bufferOut_(DHCPV4_PKT_HDR_LEN),
+      msg_type_(msg_type)
+{
+    /// TODO: fixed fields, uncomment in ticket #1224
+    memset(chaddr_, 0, MAX_CHADDR_LEN);
+    memset(sname_, 0, MAX_SNAME_LEN);
+    memset(file_, 0, MAX_FILE_LEN);
+}
+
+Pkt4::Pkt4(const uint8_t* data, size_t len)
+     :local_addr_(IOAddress("0.0.0.0")),
+      remote_addr_(IOAddress("0.0.0.0")),
+      iface_(""),
+      ifindex_(-1),
+      local_port_(DHCP4_SERVER_PORT),
+      remote_port_(DHCP4_CLIENT_PORT),
+      /// TODO Fixed fields, uncomment in ticket #1224
+      op_(BOOTREQUEST),
+      transid_(transid_),
+      secs_(0),
+      flags_(0),
+      ciaddr_(IOAddress("0.0.0.0")),
+      yiaddr_(IOAddress("0.0.0.0")),
+      siaddr_(IOAddress("0.0.0.0")),
+      giaddr_(IOAddress("0.0.0.0")),
+      bufferIn_(0), // not used, this is TX packet
+      bufferOut_(DHCPV4_PKT_HDR_LEN),
+      msg_type_(DHCPDISCOVER)
+{
+    if (len < DHCPV4_PKT_HDR_LEN) {
+        isc_throw(OutOfRange, "Truncated DHCPv4 packet (len=" << len
+                  << " received, at least 236 bytes expected.");
+    }
+    bufferIn_.writeData(data, len);
+}
+
+size_t
+Pkt4::len() {
+    size_t length = DHCPV4_PKT_HDR_LEN; // DHCPv4 header
+
+    /// TODO: Include options here (ticket #1228)
+    return (length);
+}
+
+bool
+Pkt4::pack() {
+    /// TODO: Implement this (ticket #1227)
+
+    return (false);
+}
+bool
+Pkt4::unpack() {
+    /// TODO: Implement this (ticket #1226)
+
+    return (false);
+}
+
+std::string
+Pkt4::toText() {
+    stringstream tmp;
+    tmp << "localAddr=[" << local_addr_.toText() << "]:" << local_port_
+        << " remoteAddr=[" << remote_addr_.toText()
+        << "]:" << remote_port_ << endl;
+    tmp << "msgtype=" << msg_type_
+        << ", transid=0x" << hex << transid_ << dec
+        << endl;
+
+    return tmp.str();
+}
+
+void
+Pkt4::setHWAddr(uint8_t hType, uint8_t hlen, const uint8_t* macAddr) {
+    /// TODO Rewrite this once support for client-identifier option
+    /// is implemented (ticket 1228?)
+    if (hlen>MAX_CHADDR_LEN) {
+        isc_throw(OutOfRange, "Hardware address (len=" << hlen
+                  << " too long. Max " << MAX_CHADDR_LEN << " supported.");
+    }
+    htype_ = hType;
+    hlen_ = hlen;
+    memset(chaddr_, 0, MAX_CHADDR_LEN);
+    memcpy(chaddr_, macAddr, hlen);
+}
+
+void
+Pkt4::setSname(const uint8_t* sname, size_t snameLen /*= MAX_SNAME_LEN*/) {
+    if (snameLen > MAX_SNAME_LEN) {
+        isc_throw(OutOfRange, "sname field (len=" << snameLen
+                  << ") too long, Max " << MAX_SNAME_LEN << " supported.");
+    }
+    memset(sname_, 0, MAX_SNAME_LEN);
+    memcpy(sname_, sname, snameLen);
+
+    // no need to store snameLen as any empty space is filled with 0s
+}
+
+void
+Pkt4::setFile(const uint8_t* file, size_t fileLen /*= MAX_FILE_LEN*/) {
+    if (fileLen > MAX_FILE_LEN) {
+        isc_throw(OutOfRange, "file field (len=" << fileLen
+                  << ") too long, Max " << MAX_FILE_LEN << " supported.");
+    }
+    memset(file_, 0, MAX_FILE_LEN);
+    memcpy(file_, file, fileLen);
+
+    // no need to store snameLen as any empty space is filled with 0s
+}
+
+uint8_t
+Pkt4::DHCPTypeToBootpType(uint8_t dhcpType) {
+    switch (dhcpType) {
+    case DHCPDISCOVER:
+    case DHCPREQUEST:
+    case DHCPDECLINE:
+    case DHCPRELEASE:
+    case DHCPINFORM:
+    case DHCPLEASEQUERY:
+        return (BOOTREQUEST);
+    case DHCPACK:
+    case DHCPNAK:
+    case DHCPOFFER:
+    case DHCPLEASEUNASSIGNED:
+    case DHCPLEASEUNKNOWN:
+    case DHCPLEASEACTIVE:
+        return (BOOTREPLY);
+    default:
+        isc_throw(OutOfRange, "Invalid message type: "
+                  << static_cast<int>(dhcpType) );
+    }
+}
+
+};
diff --git a/src/lib/dhcp/pkt4.h b/src/lib/dhcp/pkt4.h
new file mode 100644
index 0000000..cc20ad8
--- /dev/null
+++ b/src/lib/dhcp/pkt4.h
@@ -0,0 +1,371 @@
+// 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 PKT4_H
+#define PKT4_H
+
+#include <iostream>
+#include <boost/shared_ptr.hpp>
+#include <boost/shared_array.hpp>
+#include "asiolink/io_address.h"
+#include "util/buffer.h"
+#include "dhcp/option.h"
+
+namespace isc {
+
+namespace dhcp {
+
+class Pkt4 {
+public:
+
+    // length of the CHADDR field in DHCPv4 message
+    const static size_t MAX_CHADDR_LEN = 16;
+
+    // length of the SNAME field in DHCPv4 message
+    const static size_t MAX_SNAME_LEN = 64;
+
+    // length of the FILE field in DHCPv4 message
+    const static size_t MAX_FILE_LEN = 128;
+
+    /// specifes DHCPv4 packet header length (fixed part)
+    const static size_t DHCPV4_PKT_HDR_LEN = 236;
+
+    /// Constructor, used in replying to a message
+    ///
+    /// @param msg_type type of message (e.g. DHCPDISOVER=1)
+    /// @param transid transaction-id
+    Pkt4(uint8_t msg_type, uint32_t transid);
+
+    /// Constructor, used in message transmission
+    ///
+    /// Creates new message. Transaction-id will randomized.
+    ///
+    /// @param data pointer to received data
+    /// @param len size of buffer to be allocated for this packet.
+    Pkt4(const uint8_t* data, size_t len);
+
+    /// @brief Prepares on-wire format.
+    ///
+    /// Prepares on-wire format of message and all its options.
+    /// Options must be stored in options_ field.
+    /// Output buffer will be stored in data_. Length
+    /// will be set in data_len_.
+    ///
+    /// @return true if packing procedure was successful
+    bool
+    pack();
+
+    /// @brief Parses on-wire form of UDP DHCPv6 packet.
+    ///
+    /// Parses received packet, stored in on-wire format in data_.
+    /// data_len_ must be set to indicate data length.
+    /// Will create a collection of option objects that will
+    /// be stored in options_ container.
+    ///
+    /// @return true, if build was successful
+    bool 
+    unpack();
+
+    /// @brief Returns text representation of the packet.
+    ///
+    /// This function is useful mainly for debugging.
+    ///
+    /// @return string with text representation
+    std::string
+    toText();
+
+    /// @brief Returns calculated length of the packet.
+    ///
+    /// This function returns size of required buffer to buld this packet.
+    /// To use that function, options_ field must be set.
+    ///
+    /// @return number of bytes required to build this packet
+    size_t
+    len();
+
+    /// Sets hops field
+    ///
+    /// @param hops value to be set
+    void
+    setHops(uint8_t hops) { hops_ = hops; };
+
+    /// Returns hops field
+    ///
+    /// @return hops field
+    uint8_t
+    getHops() { return (hops_); };
+
+    // Note: There's no need to manipulate OP field directly,
+    // thus no setOp() method. See op_ comment.
+
+    /// Returns op field
+    ///
+    /// @return op field
+    uint8_t
+    getOp() { return (op_); };
+
+    /// Sets secs field
+    ///
+    /// @param secs value to be set
+    void
+    setSecs(uint16_t secs) { secs_ = secs; };
+
+    /// Returns secs field
+    ///
+    /// @return secs field
+    uint16_t
+    getSecs() { return (secs_); };
+
+    /// Sets flags field
+    ///
+    /// @param flags value to be set
+    void
+    setFlags(uint16_t flags) { flags_ = flags; };
+
+    /// Returns flags field
+    ///
+    /// @return flags field
+    uint16_t
+    getFlags() { return (flags_); };
+
+
+    /// Returns ciaddr field
+    ///
+    /// @return ciaddr field
+    isc::asiolink::IOAddress&
+    getCiaddr() { return (ciaddr_); };
+
+    /// Sets ciaddr field
+    ///
+    /// @param ciaddr value to be set
+    void
+    setCiaddr(const isc::asiolink::IOAddress& ciaddr) { ciaddr_ = ciaddr; };
+
+
+    /// Returns siaddr field
+    ///
+    /// @return siaddr field
+    isc::asiolink::IOAddress&
+    getSiaddr() { return (siaddr_); };
+
+    /// Sets siaddr field
+    ///
+    /// @param siaddr value to be set
+    void
+    setSiaddr(const isc::asiolink::IOAddress& siaddr) { siaddr_ = siaddr; };
+
+
+    /// Returns yiaddr field
+    ///
+    /// @return yiaddr field
+    isc::asiolink::IOAddress&
+    getYiaddr() { return (yiaddr_); };
+
+    /// Sets yiaddr field
+    ///
+    /// @param yiaddr value to be set
+    void
+    setYiaddr(const isc::asiolink::IOAddress& yiaddr) { yiaddr_ = yiaddr; };
+
+
+    /// Returns giaddr field
+    ///
+    /// @return giaddr field
+    isc::asiolink::IOAddress&
+    getGiaddr() { return (giaddr_); };
+
+    /// Sets giaddr field
+    ///
+    /// @param giaddr value to be set
+    void
+    setGiaddr(const isc::asiolink::IOAddress& giaddr) { giaddr_ = giaddr; };
+
+    /// Returns value of transaction-id field
+    ///
+    /// @return transaction-id
+    uint32_t getTransid() { return (transid_); };
+
+    /// Returns message type (e.g. 1 = DHCPDISCOVER)
+    ///
+    /// @return message type
+    uint8_t
+    getType() { return (msg_type_); }
+
+    /// Sets message type (e.g. 1 = DHCPDISCOVER)
+    ///
+    /// @param type message type to be set
+    void setType(uint8_t type) { msg_type_=type; };
+
+    /// @brief Returns sname field
+    ///
+    /// Note: This is 64 bytes long field. It doesn't have to be
+    /// null-terminated. Do no use strlen() or similar on it.
+    ///
+    /// @return sname field
+    const uint8_t*
+    getSname() { return (sname_); };
+
+    /// Sets sname field
+    ///
+    /// @param sname value to be set
+    void
+    setSname(const uint8_t* sname, size_t snameLen = MAX_SNAME_LEN);
+
+    /// @brief Returns file field
+    ///
+    /// Note: This is 128 bytes long field. It doesn't have to be
+    /// null-terminated. Do no use strlen() or similar on it.
+    ///
+    /// @return pointer to file field
+    const uint8_t*
+    getFile() { return (file_); };
+
+    /// Sets file field
+    ///
+    /// @param file value to be set
+    void
+    setFile(const uint8_t* file, size_t fileLen = MAX_FILE_LEN);
+
+    /// Sets hardware address
+    ///
+    /// @param hwType hardware type (will be sent in htype field)
+    /// @param hlen hardware length (will be sent in hlen field)
+    /// @param macAddr pointer to hardware address
+    void setHWAddr(uint8_t hType, uint8_t hlen,
+                   const uint8_t* macAddr);
+
+    /// Returns htype field
+    ///
+    /// @return hardware type
+    uint8_t
+    getHtype() { return (htype_); };
+
+    /// Returns hlen field
+    ///
+    /// @return hardware address length
+    uint8_t
+    getHlen() { return (hlen_); };
+
+    /// @brief Returns chaddr field
+    ///
+    /// Note: This is 16 bytes long field. It doesn't have to be
+    /// null-terminated. Do no use strlen() or similar on it.
+    ///
+    /// @return pointer to hardware address
+    const uint8_t*
+    getChaddr() { return (chaddr_); };
+
+
+protected:
+
+    /// converts DHCP message type to BOOTP op type
+    ///
+    /// @param dhcpType DHCP message type (e.g. DHCPDISCOVER)
+    ///
+    /// @return BOOTP type (BOOTREQUEST or BOOTREPLY)
+    uint8_t
+    DHCPTypeToBootpType(uint8_t dhcpType);
+
+    /// local address (dst if receiving packet, src if sending packet)
+    isc::asiolink::IOAddress local_addr_;
+
+    /// remote address (src if receiving packet, dst if sending packet)
+    isc::asiolink::IOAddress remote_addr_;
+
+    /// name of the network interface the packet was received/to be sent over
+    std::string iface_;
+
+    /// @brief interface index
+    ///
+    /// interface index (each network interface has assigned unique ifindex
+    /// it is functional equvalent of name, but sometimes more useful, e.g.
+    /// when using crazy systems that allow spaces in interface names
+    /// e.g. windows
+    int ifindex_;
+
+    /// local UDP port
+    int local_port_;
+
+    /// remote UDP port
+    int remote_port_;
+
+    /// message operation code (kept due to BOOTP format, this is NOT DHCPv4 type)
+    ///
+    /// Note: This is legacy BOOTP field. There's no need to manipulate it 
+    /// directly. Its value is set based on DHCP message type.
+    uint8_t op_;
+
+    /// link-layer address type
+    uint8_t htype_;
+
+    /// link-layer address length
+    uint8_t hlen_;
+
+    /// Number of relay agents traversed
+    uint8_t hops_;
+
+    /// DHCPv4 transaction-id (32 bits, not 24 bits as in DHCPv6)
+    uint32_t transid_;
+
+    /// elapsed (number of seconds since beginning of transmission)
+    uint16_t secs_;
+
+    /// flags
+    uint16_t flags_;
+
+    // ciaddr field (32 bits): Client's IP address
+    isc::asiolink::IOAddress ciaddr_;
+
+    // yiaddr field (32 bits): Client's IP address ("your"), set by server
+    isc::asiolink::IOAddress yiaddr_;
+
+    // siaddr field (32 bits): next server IP address in boot process(e.g.TFTP)
+    isc::asiolink::IOAddress siaddr_;
+
+    // giaddr field (32 bits): Gateway IP address
+    isc::asiolink::IOAddress giaddr_;
+
+    // ciaddr field (32 bits): Client's IP address
+    uint8_t chaddr_[16]; 
+    
+    // sname 64 bytes
+    uint8_t sname_[64];
+
+    // file
+    uint8_t file_[128];
+
+    // end of real DHCPv4 fields
+
+    /// input buffer (used during message reception)
+    /// Note that it must be modifiable as hooks can modify incoming buffer),
+    /// thus OutputBuffer, not InputBuffer
+    isc::util::OutputBuffer bufferIn_;
+
+    /// output buffer (used during message 
+    isc::util::OutputBuffer bufferOut_;
+
+    /// message type (e.g. 1=DHCPDISCOVER)
+    /// TODO: this will eventually be replaced with DHCP Message Type 
+    /// option (option 53)
+    uint8_t msg_type_;
+
+    /// collection of options present in this message
+    isc::dhcp::Option::Option4Collection options_;
+}; // Pkt4 class
+
+} // isc::dhcp namespace
+
+} // isc namespace
+
+#endif
diff --git a/src/lib/dhcp/pkt6.cc b/src/lib/dhcp/pkt6.cc
index 8dc3f6f..dbc6c8e 100644
--- a/src/lib/dhcp/pkt6.cc
+++ b/src/lib/dhcp/pkt6.cc
@@ -12,12 +12,11 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
-
-#include <config.h>
-#include <dhcp/dhcp6.h>
-#include <dhcp/pkt6.h>
-#include <dhcp/libdhcp.h>
-#include <exceptions/exceptions.h>
+#include "config.h"
+#include "dhcp/dhcp6.h"
+#include "dhcp/pkt6.h"
+#include "dhcp/libdhcp.h"
+#include "exceptions/exceptions.h"
 #include <iostream>
 #include <sstream>
 
@@ -26,60 +25,45 @@ using namespace isc::dhcp;
 
 namespace isc {
 
-/**
- * Constructor.
- *
- * @param dataLen size of buffer to be allocated for this packet.
- * @param proto protocol (usually UDP, but TCP will be supported eventually)
- */
-Pkt6::Pkt6(unsigned int dataLen, DHCPv6Proto_ proto /* = UDP */)
-    :local_addr_("::"),
+Pkt6::Pkt6(unsigned int dataLen, DHCPv6Proto proto /* = UDP */)
+    :data_len_(dataLen),
+     local_addr_("::"),
      remote_addr_("::"),
-     proto_(proto)
+     iface_(""),
+     ifindex_(-1),
+     local_port_(-1),
+     remote_port_(-1),
+     proto_(proto),
+     msg_type_(-1),
+     transid_(rand()%0xffffff)
 {
-    try {
-        data_ = boost::shared_array<char>(new char[dataLen]);
-        data_len_ = dataLen;
-    } catch (const std::exception&) {
-        // TODO move to LOG_FATAL()
-        // let's continue with empty pkt for now
-        std::cout << "Failed to allocate " << dataLen << " bytes."
-                  << std::endl;
-        data_len_ = 0;
-    }
-}
 
+    data_ = boost::shared_array<uint8_t>(new uint8_t[dataLen]);
+    data_len_ = dataLen;
+}
 
-Pkt6::Pkt6(unsigned char msg_type,
+Pkt6::Pkt6(uint8_t msg_type,
            unsigned int transid,
-           DHCPv6Proto_ proto /*= UDP*/)
+           DHCPv6Proto proto /*= UDP*/)
     :local_addr_("::"),
      remote_addr_("::"),
+     iface_(""),
+     ifindex_(-1),
+     local_port_(-1),
+     remote_port_(-1),
      proto_(proto),
      msg_type_(msg_type),
      transid_(transid) {
 
-    try {
-        data_ = boost::shared_array<char>(new char[4]);
-        data_len_ = 4;
-    } catch (Exception e) {
-        cout << "Packet creation failed:" << e.what() << endl;
-    }
-    data_len_ = 0;
+    data_ = boost::shared_array<uint8_t>(new uint8_t[4]);
+    data_len_ = 4;
 }
 
-/**
- * Returns calculated length of the packet.
- *
- * This function returns size of required buffer to buld this packet.
- * To use that function, options_ field must be set.
- *
- * @return number of bytes required to build this packet
- */
-unsigned short Pkt6::len() {
-    unsigned int length = 4; // DHCPv6 header
+unsigned short
+Pkt6::len() {
+    unsigned int length = DHCPV6_PKT_HDR_LEN; // DHCPv6 header
 
-    for (Option::Option6Lst::iterator it = options_.begin();
+    for (Option::Option6Collection::iterator it = options_.begin();
          it != options_.end();
          ++it) {
         length += (*it).second->len();
@@ -89,13 +73,6 @@ unsigned short Pkt6::len() {
 }
 
 
-/**
- * Builds on wire packet.
- *
- * Prepares on wire packet format.
- *
- * @return true if preparation was successful
- */
 bool
 Pkt6::pack() {
     switch (proto_) {
@@ -109,12 +86,6 @@ Pkt6::pack() {
     return (false); // never happens
 }
 
-
-/**
- * Build on wire packet (in UDP format).
- *
- * @return true if packet build was successful, false otherwise
- */
 bool
 Pkt6::packUDP() {
     unsigned short length = len();
@@ -122,16 +93,13 @@ Pkt6::packUDP() {
         cout << "Previous len=" << data_len_ << ", allocating new buffer: len="
              << length << endl;
 
-        try {
-            data_ = boost::shared_array<char>(new char[length]);
-            data_len_ = length;
-        } catch (Exception e) {
-            cout << "Failed to allocate " << length << "-byte buffer:"
-                 << e.what() << endl;
-            return (false);
-        }
+        // May throw exception if out of memory. That is rather fatal,
+        // so we don't catch this
+        data_ = boost::shared_array<uint8_t>(new uint8_t[length]);
+        data_len_ = length;
     }
 
+    data_len_ = length;
     try {
         // DHCPv6 header: message-type (1 octect) + transaction id (3 octets)
         data_[0] = msg_type_;
@@ -146,14 +114,13 @@ Pkt6::packUDP() {
                                                       4/*offset*/,
                                                       options_);
 
-
         // sanity check
         if (offset != length) {
             isc_throw(OutOfRange, "Packet build failed: expected size="
                       << length << ", actual len=" << offset);
         }
     }
-    catch (Exception e) {
+    catch (const Exception& e) {
         cout << "Packet build failed:" << e.what() << endl;
         return (false);
     }
@@ -161,14 +128,6 @@ Pkt6::packUDP() {
     return (true);
 }
 
-
-/**
- * Builds on wire packet for TCP transmission.
- *
- * @note This function is not implemented yet.
- *
- * @return
- */
 bool
 Pkt6::packTCP() {
     /// TODO Implement this function.
@@ -176,13 +135,6 @@ Pkt6::packTCP() {
               "not implemented yet.");
 }
 
-/**
- * Dispatch method that handles binary packet parsing.
- *
- * This method calls appropriate dispatch function (unpackUDP or unpackTCP)
- *
- * @return true, if parsing was successful, false otherwise
- */
 bool
 Pkt6::unpack() {
     switch (proto_) {
@@ -196,11 +148,6 @@ Pkt6::unpack() {
     return (false); // never happens
 }
 
-/**
- * This method unpacks UDP packet.
- *
- * @return true, if parsing was successful, false otherwise
- */
 bool
 Pkt6::unpackUDP() {
     if (data_len_ < 4) {
@@ -209,8 +156,8 @@ Pkt6::unpackUDP() {
         return (false);
     }
     msg_type_ = data_[0];
-    transid_ = ( ((unsigned char)data_[1]) << 16 ) + 
-        (((unsigned char)data_[2]) << 8) + ((unsigned char)data_[3]);
+    transid_ = ( (data_[1]) << 16 ) +
+        ((data_[2]) << 8) + (data_[3]);
     transid_ = transid_ & 0xffffff;
 
     unsigned int offset = LibDHCP::unpackOptions6(data_,
@@ -227,11 +174,6 @@ Pkt6::unpackUDP() {
     return (true);
 }
 
-/**
- * This method unpacks TDP packet.
- *
- * @return true, if parsing was successful, false otherwise
- */
 bool
 Pkt6::unpackTCP() {
     isc_throw(Unexpected, "DHCPv6 over TCP (bulk leasequery and failover) "
@@ -239,13 +181,6 @@ Pkt6::unpackTCP() {
 }
 
 
-/**
- * Returns text representation of the packet.
- *
- * This function is useful mainly for debugging.
- *
- * @return string with text representation
- */
 std::string
 Pkt6::toText() {
     stringstream tmp;
@@ -254,7 +189,7 @@ Pkt6::toText() {
         << "]:" << remote_port_ << endl;
     tmp << "msgtype=" << msg_type_ << ", transid=0x" << hex << transid_
         << dec << endl;
-    for (isc::dhcp::Option::Option6Lst::iterator opt=options_.begin();
+    for (isc::dhcp::Option::Option6Collection::iterator opt=options_.begin();
          opt != options_.end();
          ++opt) {
         tmp << opt->second->toText() << std::endl;
@@ -262,36 +197,15 @@ Pkt6::toText() {
     return tmp.str();
 }
 
-/**
- * Returns the first option of specified type.
- *
- * Returns the first option of specified type. Note that in DHCPv6 several
- * instances of the same option are allowed (and frequently used).
- * See getOptions().
- *
- * @param opt_type option type we are looking for
- *
- * @return pointer to found option (or NULL)
- */
 boost::shared_ptr<isc::dhcp::Option>
 Pkt6::getOption(unsigned short opt_type) {
-    isc::dhcp::Option::Option6Lst::const_iterator x = options_.find(opt_type);
+    isc::dhcp::Option::Option6Collection::const_iterator x = options_.find(opt_type);
     if (x!=options_.end()) {
         return (*x).second;
     }
     return boost::shared_ptr<isc::dhcp::Option>(); // NULL
 }
 
-/**
- * Returns message type.
- *
- * @return message type.
- */
-unsigned char
-Pkt6::getType() {
-    return (msg_type_);
-}
-
 void
 Pkt6::addOption(boost::shared_ptr<Option> opt) {
     options_.insert(pair<int, boost::shared_ptr<Option> >(opt->getType(), opt));
@@ -299,7 +213,7 @@ Pkt6::addOption(boost::shared_ptr<Option> opt) {
 
 bool
 Pkt6::delOption(unsigned short type) {
-    isc::dhcp::Option::Option6Lst::iterator x = options_.find(type);
+    isc::dhcp::Option::Option6Collection::iterator x = options_.find(type);
     if (x!=options_.end()) {
         options_.erase(x);
         return (true); // delete successful
@@ -307,8 +221,4 @@ Pkt6::delOption(unsigned short type) {
     return (false); // can't find option to be deleted
 }
 
-Pkt6::~Pkt6() {
-    // no need to delete anything shared_ptr will take care of data_
-}
-
 };
diff --git a/src/lib/dhcp/pkt6.h b/src/lib/dhcp/pkt6.h
index d24328d..d089444 100644
--- a/src/lib/dhcp/pkt6.h
+++ b/src/lib/dhcp/pkt6.h
@@ -18,89 +18,217 @@
 #include <iostream>
 #include <boost/shared_ptr.hpp>
 #include <boost/shared_array.hpp>
-#include <asiolink/io_address.h>
-#include <dhcp/option.h>
+#include "asiolink/io_address.h"
+#include "dhcp/option.h"
 
 namespace isc {
 
+namespace dhcp {
 
-    class Pkt6 {
-    public:
-        enum DHCPv6Proto_ {
-            UDP = 0, // most packets are UDP
-            TCP = 1  // there are TCP DHCPv6 packet (bulk leasequery, failover)
-        };
-
-        Pkt6(unsigned char msg_type,
-             unsigned int transid,
-             DHCPv6Proto_ proto = UDP);
-        Pkt6(unsigned int len, DHCPv6Proto_ proto = UDP);
-        ~Pkt6();
-
-        bool pack();
-        bool unpack();
-
-        DHCPv6Proto_ getProto();
-        void setProto(DHCPv6Proto_ proto = Pkt6::UDP);
-
-        // returns text representation, useful for debugging
-        std::string toText();
-
-        unsigned short len();
-
-        unsigned char getType();
-        void setType(unsigned char type) { msg_type_=type; };
-        unsigned int getTransid() { return transid_; };
-
-        /// TODO need getter/setter wrappers
-        ///      and hide following fields as protected
-        /// buffer that holds memory. It is shared_array as options may
-        /// share pointer to this buffer
-        boost::shared_array<char> data_;
-
-        // length of the data
-        unsigned int data_len_;
-
-        // local address (dst if receiving packet, src if sending packet)
-        isc::asiolink::IOAddress local_addr_;
-
-        // remote address (src if receiving packet, dst if sending packet)
-        isc::asiolink::IOAddress remote_addr_;
-
-        // name of the network interface the packet was received/to be sent over
-        std::string iface_;
-
-        // interface index (each network interface has assigned unique ifindex
-        // it is functional equvalent of name, but sometimes more useful, e.g.
-        // when using crazy systems that allow spaces in interface names
-        // e.g. windows
-        int ifindex_;
-
-        // local TDP or UDP port
-        int local_port_;
-
-        // remote TCP or UDP port
-        int remote_port_;
-
-        void addOption(boost::shared_ptr<isc::dhcp::Option> opt);
-        boost::shared_ptr<isc::dhcp::Option> getOption(unsigned short type);
-        bool delOption(unsigned short type);
-        /// TODO Need to implement getOptions() as well
-
-        // XXX: add *a lot* here
-        isc::dhcp::Option::Option6Lst options_;
-
-    protected:
-        bool packTCP();
-        bool packUDP();
-        bool unpackTCP();
-        bool unpackUDP();
-
-        DHCPv6Proto_ proto_; // UDP (most) or TCP (bulk leasequery or failover)
-        int msg_type_; // DHCPv6 message type
-        unsigned int transid_;  // DHCPv6 transaction-id
+class Pkt6 {
+public:
+    /// specifes DHCPv6 packet header length
+    const static size_t DHCPV6_PKT_HDR_LEN = 4;
 
+    /// DHCPv6 transport protocol
+    enum DHCPv6Proto {
+        UDP = 0, // most packets are UDP
+        TCP = 1  // there are TCP DHCPv6 packets (bulk leasequery, failover)
     };
-}
+
+    /// Constructor, used in replying to a message
+    ///
+    /// @param msg_type type of message (SOLICIT=1, ADVERTISE=2, ...)
+    /// @param transid transaction-id
+    /// @param proto protocol (TCP or UDP)
+    Pkt6(unsigned char msg_type,
+         unsigned int transid,
+         DHCPv6Proto proto = UDP);
+
+    /// Constructor, used in message transmission
+    ///
+    /// Creates new message. Transaction-id will randomized.
+    ///
+    /// @param len size of buffer to be allocated for this packet.
+    /// @param proto protocol (usually UDP, but TCP will be supported eventually)
+    Pkt6(unsigned int len, DHCPv6Proto proto = UDP);
+
+    /// @brief Prepares on-wire format.
+    ///
+    /// Prepares on-wire format of message and all its options.
+    /// Options must be stored in options_ field.
+    /// Output buffer will be stored in data_. Length
+    /// will be set in data_len_.
+    ///
+    /// @return true if packing procedure was successful
+    bool
+    pack();
+
+    /// @brief Dispatch method that handles binary packet parsing.
+    ///
+    /// This method calls appropriate dispatch function (unpackUDP or
+    /// unpackTCP).
+    ///
+    /// @return true if parsing was successful
+    bool
+    unpack();
+
+    /// Returns protocol of this packet (UDP or TCP)
+    ///
+    /// @return protocol type
+    DHCPv6Proto
+    getProto();
+
+    /// Sets protocol of this packet.
+    ///
+    /// @param proto protocol (UDP or TCP)
+    ///
+    void
+    setProto(DHCPv6Proto proto = UDP) { proto_ = proto; }
+
+    /// @brief Returns text representation of the packet.
+    ///
+    /// This function is useful mainly for debugging.
+    ///
+    /// @return string with text representation
+    std::string
+    toText();
+
+    /// @brief Returns calculated length of the packet.
+    ///
+    /// This function returns size of required buffer to buld this packet.
+    /// To use that function, options_ field must be set.
+    ///
+    /// @return number of bytes required to build this packet
+    unsigned short
+    len();
+
+    /// Returns message type (e.g. 1 = SOLICIT)
+    ///
+    /// @return message type
+    unsigned char
+    getType() { return (msg_type_); }
+
+    /// Sets message type (e.g. 1 = SOLICIT)
+    ///
+    /// @param type message type to be set
+    void setType(unsigned char type) { msg_type_=type; };
+
+    /// Returns value of transaction-id field
+    ///
+    /// @return transaction-id
+    unsigned int getTransid() { return (transid_); };
+
+    /// Adds an option to this packet.
+    ///
+    /// @param opt option to be added.
+    void addOption(boost::shared_ptr<isc::dhcp::Option> opt);
+
+    /// @brief Returns the first option of specified type.
+    ///
+    /// Returns the first option of specified type. Note that in DHCPv6 several
+    /// instances of the same option are allowed (and frequently used).
+    /// See getOptions().
+    ///
+    /// @param opt_type option type we are looking for
+    ///
+    /// @return pointer to found option (or NULL)
+    boost::shared_ptr<isc::dhcp::Option>
+    getOption(unsigned short type);
+
+    /// Attempts to delete first suboption of requested type
+    ///
+    /// @param type Type of option to be deleted.
+    ///
+    /// @return true if option was deleted, false if no such option existed
+    bool
+    delOption(unsigned short type);
+
+    /// TODO need getter/setter wrappers
+    ///      and hide following fields as protected
+
+    /// buffer that holds memory. It is shared_array as options may
+    /// share pointer to this buffer
+    boost::shared_array<uint8_t> data_;
+
+    /// length of the data
+    unsigned int data_len_;
+
+    /// local address (dst if receiving packet, src if sending packet)
+    isc::asiolink::IOAddress local_addr_;
+
+    /// remote address (src if receiving packet, dst if sending packet)
+    isc::asiolink::IOAddress remote_addr_;
+
+    /// name of the network interface the packet was received/to be sent over
+    std::string iface_;
+
+    /// @brief interface index
+    ///
+    /// interface index (each network interface has assigned unique ifindex
+    /// it is functional equvalent of name, but sometimes more useful, e.g.
+    /// when using crazy systems that allow spaces in interface names
+    /// e.g. windows
+    int ifindex_;
+
+    /// local TDP or UDP port
+    int local_port_;
+
+    /// remote TCP or UDP port
+    int remote_port_;
+
+    /// TODO Need to implement getOptions() as well
+
+    /// collection of options present in this message
+    isc::dhcp::Option::Option6Collection options_;
+
+protected:
+    /// Builds on wire packet for TCP transmission.
+    ///
+    /// TODO This function is not implemented yet.
+    ///
+    /// @return true, if build was successful
+    bool packTCP();
+
+    /// Builds on wire packet for UDP transmission.
+    ///
+    /// @return true, if build was successful
+    bool packUDP();
+
+    /// @brief Parses on-wire form of TCP DHCPv6 packet.
+    ///
+    /// Parses received packet, stored in on-wire format in data_.
+    /// data_len_ must be set to indicate data length.
+    /// Will create a collection of option objects that will
+    /// be stored in options_ container.
+    ///
+    /// TODO This function is not implemented yet.
+    ///
+    /// @return true, if build was successful
+    bool unpackTCP();
+
+    /// @brief Parses on-wire form of UDP DHCPv6 packet.
+    ///
+    /// Parses received packet, stored in on-wire format in data_.
+    /// data_len_ must be set to indicate data length.
+    /// Will create a collection of option objects that will
+    /// be stored in options_ container.
+    ///
+    /// @return true, if build was successful
+    bool unpackUDP();
+
+    /// UDP (usually) or TCP (bulk leasequery or failover)
+    DHCPv6Proto proto_;
+
+    /// DHCPv6 message type
+    int msg_type_;
+
+    /// DHCPv6 transaction-id
+    unsigned int transid_;
+}; // Pkt6 class
+
+} // isc::dhcp namespace
+
+} // isc namespace
 
 #endif
diff --git a/src/lib/dhcp/tests/Makefile.am b/src/lib/dhcp/tests/Makefile.am
index c00bef5..41cabba 100644
--- a/src/lib/dhcp/tests/Makefile.am
+++ b/src/lib/dhcp/tests/Makefile.am
@@ -22,6 +22,7 @@ libdhcp_unittests_SOURCES += ../option6_ia.h ../option6_ia.cc option6_ia_unittes
 libdhcp_unittests_SOURCES += ../option6_addrlst.h ../option6_addrlst.cc option6_addrlst_unittest.cc
 libdhcp_unittests_SOURCES += ../option.h ../option.cc option_unittest.cc
 libdhcp_unittests_SOURCES += ../pkt6.h ../pkt6.cc pkt6_unittest.cc
+libdhcp_unittests_SOURCES += ../pkt4.h ../pkt4.cc pkt4_unittest.cc
 
 libdhcp_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) $(LOG4CPLUS_INCLUDES)
 libdhcp_unittests_LDFLAGS  = $(AM_LDFLAGS)  $(GTEST_LDFLAGS)
@@ -34,11 +35,9 @@ libdhcp_unittests_CXXFLAGS += -Wno-unused-variable
 endif
 libdhcp_unittests_LDADD  = $(GTEST_LDADD)
 libdhcp_unittests_LDADD += $(top_builddir)/src/lib/log/liblog.la
-libdhcp_unittests_LDADD += $(top_builddir)/src/lib/util/unittests/libutil_unittests.la
 libdhcp_unittests_LDADD += $(top_builddir)/src/lib/util/libutil.la
 libdhcp_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
 libdhcp_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
-libdhcp_unittests_LDADD += $(top_builddir)/src/lib/util/unittests/libutil_unittests.la
 endif
 
 noinst_PROGRAMS = $(TESTS)
diff --git a/src/lib/dhcp/tests/libdhcp_unittest.cc b/src/lib/dhcp/tests/libdhcp_unittest.cc
index 2bff539..bfd0f6e 100644
--- a/src/lib/dhcp/tests/libdhcp_unittest.cc
+++ b/src/lib/dhcp/tests/libdhcp_unittest.cc
@@ -23,8 +23,8 @@
 #endif
 #include <gtest/gtest.h>
 
-#include <dhcp/libdhcp.h>
-
+#include "dhcp/libdhcp.h"
+#include "config.h"
 
 using namespace std;
 using namespace isc;
@@ -37,18 +37,20 @@ public:
     }
 };
 
-TEST_F(LibDhcpTest, basic) {
-    // dummy test
-
-    EXPECT_EQ(LibDHCP::version(), PACKAGE_VERSION);
-}
+static const uint8_t packed[] = {
+    0, 12, 0, 5, 100, 101, 102, 103, 104, // opt1 (9 bytes)
+    0, 13, 0, 3, 105, 106, 107, // opt2 (7 bytes)
+    0, 14, 0, 2, 108, 109, // opt3 (6 bytes)
+    1,  0, 0, 4, 110, 111, 112, 113, // opt4 (8 bytes)
+    1,  1, 0, 1, 114 // opt5 (5 bytes)
+};
 
 TEST_F(LibDhcpTest, packOptions6) {
-    boost::shared_array<char> buf(new char[512]);
-    isc::dhcp::Option::Option6Lst opts; // list of options
+    boost::shared_array<uint8_t> buf(new uint8_t[512]);
+    isc::dhcp::Option::Option6Collection opts; // list of options
 
     // generate content for options
-    for (int i=0;i<64;i++) {
+    for (int i = 0; i < 64; i++) {
         buf[i]=i+100;
     }
 
@@ -58,14 +60,6 @@ TEST_F(LibDhcpTest, packOptions6) {
     boost::shared_ptr<Option> opt4(new Option(Option::V6,256, buf,10, 4));
     boost::shared_ptr<Option> opt5(new Option(Option::V6,257, buf,14, 1));
 
-    char expected[] = {
-        0, 12, 0, 5, 100, 101, 102, 103, 104, // opt1
-        0, 13, 0, 3, 105, 106, 107, // opt2
-        0, 14, 0, 2, 108, 109, // opt3
-        1,  0, 0, 4, 110, 111, 112, 113, // opt4
-        1,  1, 0, 1, 114
-    };
-
     opts.insert(pair<int, boost::shared_ptr<Option> >(opt1->getType(), opt1));
     opts.insert(pair<int, boost::shared_ptr<Option> >(opt1->getType(), opt2));
     opts.insert(pair<int, boost::shared_ptr<Option> >(opt1->getType(), opt3));
@@ -77,28 +71,20 @@ TEST_F(LibDhcpTest, packOptions6) {
          offset = LibDHCP::packOptions6(buf, 512, 100, opts);
     });
     EXPECT_EQ(135, offset); // options should take 35 bytes
-    EXPECT_EQ(0, memcmp(&buf[100], expected, 35) );
+    EXPECT_EQ(0, memcmp(&buf[100], packed, 35) );
 }
 
 TEST_F(LibDhcpTest, unpackOptions6) {
 
     // just couple of random options
-    char packed[] = {
-        0, 12, 0, 5, 100, 101, 102, 103, 104, // opt1 (9 bytes)
-        0, 13, 0, 3, 105, 106, 107, // opt2 (7 bytes)
-        0, 14, 0, 2, 108, 109, // opt3 (6 bytes)
-        1,  0, 0, 4, 110, 111, 112, 113, // opt4 (8 bytes)
-        1,  1, 0, 1, 114 // opt5 (5 bytes)
-    };
     // Option is used as a simple option implementation
     // More advanced uses are validated in tests dedicated for
     // specific derived classes.
-
-    isc::dhcp::Option::Option6Lst options; // list of options
+    isc::dhcp::Option::Option6Collection options; // list of options
 
     // we can't use packed directly, as shared_array would try to
     // free it eventually
-    boost::shared_array<char> buf(new char[512]);
+    boost::shared_array<uint8_t> buf(new uint8_t[512]);
     memcpy(&buf[0], packed, 35);
 
     unsigned int offset;
@@ -109,8 +95,8 @@ TEST_F(LibDhcpTest, unpackOptions6) {
     EXPECT_EQ(35, offset); // parsed first 35 bytes (offset 0..34)
     EXPECT_EQ(options.size(), 5); // there should be 5 options
 
-    isc::dhcp::Option::Option6Lst::const_iterator x = options.find(12);
-    ASSERT_FALSE(x == options.end()); // option 12 should exist
+    isc::dhcp::Option::Option6Collection::const_iterator x = options.find(12);
+    ASSERT_FALSE(x == options.end()); // option 1 should exist
     EXPECT_EQ(12, x->second->getType());  // this should be option 12
     ASSERT_EQ(9, x->second->len()); // it should be of length 9
     EXPECT_EQ(0, memcmp(x->second->getData(), packed+4, 5)); // data len=5
diff --git a/src/lib/dhcp/tests/option6_addrlst_unittest.cc b/src/lib/dhcp/tests/option6_addrlst_unittest.cc
index 2a2b2a1..d54282a 100644
--- a/src/lib/dhcp/tests/option6_addrlst_unittest.cc
+++ b/src/lib/dhcp/tests/option6_addrlst_unittest.cc
@@ -23,10 +23,10 @@
 #endif
 #include <gtest/gtest.h>
 
-#include <asiolink/io_address.h>
-#include <dhcp/dhcp6.h>
-#include <dhcp/option.h>
-#include <dhcp/option6_addrlst.h>
+#include "asiolink/io_address.h"
+#include "dhcp/dhcp6.h"
+#include "dhcp/option.h"
+#include "dhcp/option6_addrlst.h"
 
 using namespace std;
 using namespace isc;
@@ -42,7 +42,14 @@ public:
 
 TEST_F(Option6AddrLstTest, basic) {
 
-    unsigned char sampledata[] = {
+    // limiting tests to just a 2001:db8::/32 as is *wrong*.
+    // Good tests check corner cases as well.
+    // ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff checks
+    // for integer overflow
+    // ff02::face:b00c checks if multicast addresses
+    // can be represented properly.
+
+    uint8_t sampledata[] = {
         // 2001:db8:1::dead:beef
         0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0, 0,
         0, 0, 0, 0, 0xde, 0xad, 0xbe, 0xef,
@@ -56,7 +63,7 @@ TEST_F(Option6AddrLstTest, basic) {
         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
     };
 
-    unsigned char expected1[] = {
+    uint8_t expected1[] = {
         D6O_NAME_SERVERS/256, D6O_NAME_SERVERS%256,//type
         0, 16, // len = 16 (1 address)
         0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0, 0,
@@ -64,7 +71,7 @@ TEST_F(Option6AddrLstTest, basic) {
 
     };
 
-    unsigned char expected2[] = {
+    uint8_t expected2[] = {
         D6O_SIP_SERVERS_ADDR/256, D6O_SIP_SERVERS_ADDR%256,
         0, 32, // len = 32 (2 addresses)
         // 2001:db8:1::dead:beef
@@ -80,7 +87,7 @@ TEST_F(Option6AddrLstTest, basic) {
         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
     };
 
-    unsigned char expected3[] = {
+    uint8_t expected3[] = {
         D6O_NIS_SERVERS/256, D6O_NIS_SERVERS%256,
         0, 48,
         // 2001:db8:1::dead:beef
@@ -96,23 +103,21 @@ TEST_F(Option6AddrLstTest, basic) {
         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
     };
 
-    boost::shared_array<char> buf(new char[300]);
-    for (int i=0; i<300; i++)
+    boost::shared_array<uint8_t> buf(new uint8_t[300]);
+    for (int i = 0; i < 300; i++)
         buf[i] = 0;
 
     memcpy(&buf[0], sampledata, 48);
 
     // just a single address
-    Option6AddrLst* opt1 = new Option6AddrLst(D6O_NAME_SERVERS,
-                                              buf,
-                                              128,
-                                              0,
-                                              16);
-
+    Option6AddrLst* opt1 = 0;
+    EXPECT_NO_THROW(
+        opt1 = new Option6AddrLst(D6O_NAME_SERVERS, buf, 128, 0, 16);
+    );
 
     EXPECT_EQ(D6O_NAME_SERVERS, opt1->getType());
     EXPECT_EQ(20, opt1->len());
-    Option6AddrLst::AddrsContainer addrs = opt1->getAddresses();
+    Option6AddrLst::AddressContainer addrs = opt1->getAddresses();
     ASSERT_EQ(1, addrs.size());
     IOAddress addr = addrs[0];
     EXPECT_EQ("2001:db8:1::dead:beef", addr.toText());
@@ -125,11 +130,10 @@ TEST_F(Option6AddrLstTest, basic) {
     EXPECT_EQ( 0, memcmp(expected1, &buf[100], 20) );
 
     // two addresses
-    Option6AddrLst* opt2 = new Option6AddrLst(D6O_SIP_SERVERS_ADDR,
-                                              buf,
-                                              128,
-                                              0,
-                                              32);
+    Option6AddrLst* opt2 = 0;
+    EXPECT_NO_THROW(
+        opt2 = new Option6AddrLst(D6O_SIP_SERVERS_ADDR, buf, 128, 0, 32);
+    );
     EXPECT_EQ(D6O_SIP_SERVERS_ADDR, opt2->getType());
     EXPECT_EQ(36, opt2->len());
     addrs = opt2->getAddresses();
@@ -144,13 +148,11 @@ TEST_F(Option6AddrLstTest, basic) {
     EXPECT_EQ(150+36, offset);
     EXPECT_EQ( 0, memcmp(expected2, &buf[150], 36));
 
-
     // three addresses
-    Option6AddrLst* opt3 = new Option6AddrLst(D6O_NIS_SERVERS,
-                                              buf,
-                                              128,
-                                              0,
-                                              48);
+    Option6AddrLst* opt3 = 0;
+    EXPECT_NO_THROW(
+        opt3 = new Option6AddrLst(D6O_NIS_SERVERS, buf, 128, 0, 48);
+    );
 
     EXPECT_EQ(D6O_NIS_SERVERS, opt3->getType());
     EXPECT_EQ(52, opt3->len());
@@ -167,46 +169,67 @@ TEST_F(Option6AddrLstTest, basic) {
     EXPECT_EQ(252, offset);
     EXPECT_EQ( 0, memcmp(expected3, &buf[200], 52) );
 
-    delete opt1;
-    delete opt2;
-    delete opt3;
+    EXPECT_NO_THROW(
+        delete opt1;
+        delete opt2;
+        delete opt3;
+    );
 }
 
 TEST_F(Option6AddrLstTest, constructors) {
-     Option6AddrLst * opt1 = new Option6AddrLst(1234,
-                                                IOAddress("::1"));
-     EXPECT_EQ(1234, opt1->getType());
-
-     Option6AddrLst::AddrsContainer addrs = opt1->getAddresses();
-     ASSERT_EQ(1, addrs.size() );
-     EXPECT_EQ("::1", addrs[0].toText());
 
-     addrs.clear();
-     addrs.push_back(IOAddress(string("fe80::1234")));
-     addrs.push_back(IOAddress(string("2001:db8:1::baca")));
+    Option6AddrLst* opt1 = 0;
+    EXPECT_NO_THROW(
+        opt1 = new Option6AddrLst(1234, IOAddress("::1"));
+    );
+    EXPECT_EQ(1234, opt1->getType());
 
-     Option6AddrLst * opt2 = new Option6AddrLst(5678,
-                                                addrs);
-
-     Option6AddrLst::AddrsContainer check = opt2->getAddresses();
-     ASSERT_EQ(2, check.size() );
-     EXPECT_EQ("fe80::1234", check[0].toText());
-     EXPECT_EQ("2001:db8:1::baca", check[1].toText());
-
-     delete opt1;
-     delete opt2;
+    Option6AddrLst::AddressContainer addrs = opt1->getAddresses();
+    ASSERT_EQ(1, addrs.size() );
+    EXPECT_EQ("::1", addrs[0].toText());
+
+    addrs.clear();
+    addrs.push_back(IOAddress(string("fe80::1234")));
+    addrs.push_back(IOAddress(string("2001:db8:1::baca")));
+
+    Option6AddrLst* opt2 = 0;
+    EXPECT_NO_THROW(
+        opt2 = new Option6AddrLst(5678, addrs);
+    );
+
+    Option6AddrLst::AddressContainer check = opt2->getAddresses();
+    ASSERT_EQ(2, check.size() );
+    EXPECT_EQ("fe80::1234", check[0].toText());
+    EXPECT_EQ("2001:db8:1::baca", check[1].toText());
+
+    EXPECT_NO_THROW(
+        delete opt1;
+        delete opt2;
+    );
 }
 
 TEST_F(Option6AddrLstTest, setAddress) {
-    Option6AddrLst * opt1 = new Option6AddrLst(1234,
-                                                IOAddress("::1"));
-    opt1->setAddress(IOAddress("::2"));
-
-    Option6AddrLst::AddrsContainer addrs = opt1->getAddresses();
+    Option6AddrLst* opt1 = 0;
+    EXPECT_NO_THROW(
+        opt1 = new Option6AddrLst(1234, IOAddress("::1"));
+    );
+    opt1->setAddress(IOAddress("2001:db8:1::2"));
+    /// TODO It used to be ::2 address, but io_address represents
+    /// it as ::0.0.0.2. Purpose of this test is to verify
+    /// that setAddress() works, not deal with subtleties of
+    /// io_address handling of IPv4-mapped IPv6 addresses, we
+    /// switched to a more common address. User interested
+    /// in pursuing this matter further is encouraged to look
+    /// at section 2.5.5 of RFC4291 (and possibly implement
+    /// a test for IOAddress)
+
+    Option6AddrLst::AddressContainer addrs = opt1->getAddresses();
     ASSERT_EQ(1, addrs.size() );
-    EXPECT_EQ("::2", addrs[0].toText());
+    EXPECT_EQ("2001:db8:1::2", addrs[0].toText());
 
-    delete opt1;
+    EXPECT_NO_THROW(
+        delete opt1;
+    );
 }
 
 } // namespace
diff --git a/src/lib/dhcp/tests/option6_ia_unittest.cc b/src/lib/dhcp/tests/option6_ia_unittest.cc
index 1f3bbde..b396575 100644
--- a/src/lib/dhcp/tests/option6_ia_unittest.cc
+++ b/src/lib/dhcp/tests/option6_ia_unittest.cc
@@ -15,7 +15,6 @@
 #include <config.h>
 #include <iostream>
 #include <sstream>
-#include <boost/shared_ptr.hpp>
 
 #ifdef _WIN32
 #include <ws2tcpip.h>
@@ -24,10 +23,13 @@
 #endif
 #include <gtest/gtest.h>
 
-#include <dhcp/dhcp6.h>
-#include <dhcp/option.h>
-#include <dhcp/option6_ia.h>
-#include <dhcp/option6_iaaddr.h>
+#include <boost/shared_array.hpp>
+#include <boost/shared_ptr.hpp>
+
+#include "dhcp/dhcp6.h"
+#include "dhcp/option.h"
+#include "dhcp/option6_ia.h"
+#include "dhcp/option6_iaaddr.h"
 
 using namespace std;
 using namespace isc;
@@ -43,28 +45,27 @@ public:
 
 TEST_F(Option6IATest, basic) {
 
-    boost::shared_array<char> simple_buf(new char[128]);
-    for (int i=0; i<128; i++)
+    boost::shared_array<uint8_t> simple_buf(new uint8_t[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[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[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;
+    simple_buf[8] = 0x84; // T2
+    simple_buf[9] = 0x03;
+    simple_buf[10] = 0x02;
+    simple_buf[11] = 0x01;
 
     // create an option
     // unpack() is called from constructor
-    Option6IA* opt = new Option6IA(Option::V6,
-                                   D6O_IA_NA,
+    Option6IA* opt = new Option6IA(D6O_IA_NA,
                                    simple_buf,
                                    128,
                                    0,
@@ -110,16 +111,17 @@ TEST_F(Option6IATest, basic) {
                           (simple_buf[74] << 8) +
                           (simple_buf[75]) );
 
-    delete opt;
+    EXPECT_NO_THROW(
+        delete opt;
+    );
 }
 
 TEST_F(Option6IATest, simple) {
-    boost::shared_array<char> simple_buf(new char[128]);
-    for (int i=0; i<128; i++)
+    boost::shared_array<uint8_t> simple_buf(new uint8_t[128]);
+    for (int i = 0; i < 128; i++)
         simple_buf[i] = 0;
 
-    Option6IA * ia = new Option6IA(Option::V6, D6O_IA_NA,
-                                   1234);
+    Option6IA * ia = new Option6IA(D6O_IA_NA, 1234);
     ia->setT1(2345);
     ia->setT2(3456);
 
@@ -128,20 +130,21 @@ TEST_F(Option6IATest, simple) {
     EXPECT_EQ(2345, ia->getT1());
     EXPECT_EQ(3456, ia->getT2());
 
-    delete ia;
+    EXPECT_NO_THROW(
+        delete ia;
+    );
 }
 
 // test if option can build suboptions
 TEST_F(Option6IATest, suboptions_pack) {
-    boost::shared_array<char> buf(new char[128]);
+    boost::shared_array<uint8_t> buf(new uint8_t[128]);
     for (int i=0; i<128; i++)
         buf[i] = 0;
     buf[0] = 0xff;
     buf[1] = 0xfe;
     buf[2] = 0xfc;
 
-    Option6IA * ia = new Option6IA(Option::V6, D6O_IA_NA,
-                                   0x13579ace);
+    Option6IA * ia = new Option6IA(D6O_IA_NA, 0x13579ace);
     ia->setT1(0x2345);
     ia->setT2(0x3456);
 
@@ -159,7 +162,7 @@ TEST_F(Option6IATest, suboptions_pack) {
     ASSERT_EQ(4, sub1->len());
     ASSERT_EQ(48, ia->len());
 
-    unsigned char expected[] = {
+    uint8_t expected[] = {
         D6O_IA_NA/256, D6O_IA_NA%256, // type
         0, 44, // length
         0x13, 0x57, 0x9a, 0xce, // iaid
@@ -184,14 +187,16 @@ TEST_F(Option6IATest, suboptions_pack) {
 
     EXPECT_EQ(0, memcmp(&buf[10], expected, 48));
 
-    delete ia;
+    EXPECT_NO_THROW(
+        delete ia;
+    );
 }
 
 // test if option can parse suboptions
 TEST_F(Option6IATest, suboptions_unpack) {
 
 
-    unsigned char expected[] = {
+    uint8_t expected[] = {
         D6O_IA_NA/256, D6O_IA_NA%256, // type
         0, 28, // length
         0x13, 0x57, 0x9a, 0xce, // iaid
@@ -211,18 +216,19 @@ TEST_F(Option6IATest, suboptions_unpack) {
         0, 0 // len
     };
 
-    boost::shared_array<char> buf(new char[128]);
-    for (int i=0; i<128; i++)
+    boost::shared_array<uint8_t> buf(new uint8_t[128]);
+    for (int i = 0; i < 128; i++)
         buf[i] = 0;
     memcpy(&buf[0], expected, 48);
 
-    Option6IA * ia;
+    Option6IA* ia = 0;
     EXPECT_NO_THROW({
-            ia = new Option6IA(Option::V6, D6O_IA_NA,
-                               buf, 128, 4, 44);
-    });
+        ia = new Option6IA(D6O_IA_NA, buf, 128, 4, 44);
 
-    cout << "Parsed option:" << endl << ia->toText() << endl;
+        // let's limit verbosity of this test
+        // cout << "Parsed option:" << endl << ia->toText() << endl;
+    });
+    ASSERT_TRUE(ia);
 
     EXPECT_EQ(D6O_IA_NA, ia->getType());
     EXPECT_EQ(0x13579ace, ia->getIAID());
@@ -244,18 +250,18 @@ TEST_F(Option6IATest, suboptions_unpack) {
 
     // checks for dummy option
     subopt = ia->getOption(0xcafe);
-    ASSERT_FALSE(subopt == boost::shared_ptr<Option>()); // non-NULL
+    ASSERT_TRUE(subopt); // should be non-NULL
 
     EXPECT_EQ(0xcafe, subopt->getType());
     EXPECT_EQ(4, subopt->len());
     EXPECT_EQ(NULL, subopt->getData());
 
     subopt = ia->getOption(1); // get option 1
-    ASSERT_EQ(subopt, boost::shared_ptr<Option>()); // NULL
+    ASSERT_FALSE(subopt); // should be NULL
 
-    delete ia;
+    EXPECT_NO_THROW(
+        delete ia;
+    );
 }
 
-
-
 }
diff --git a/src/lib/dhcp/tests/option6_iaaddr_unittest.cc b/src/lib/dhcp/tests/option6_iaaddr_unittest.cc
index 92e92ab..0f355c2 100644
--- a/src/lib/dhcp/tests/option6_iaaddr_unittest.cc
+++ b/src/lib/dhcp/tests/option6_iaaddr_unittest.cc
@@ -23,9 +23,9 @@
 #endif
 #include <gtest/gtest.h>
 
-#include <dhcp/dhcp6.h>
-#include <dhcp/option.h>
-#include <dhcp/option6_iaaddr.h>
+#include "dhcp/dhcp6.h"
+#include "dhcp/option.h"
+#include "dhcp/option6_iaaddr.h"
 
 using namespace std;
 using namespace isc;
@@ -38,39 +38,41 @@ public:
     }
 };
 
+/// TODO reenable this once ticket #1313 is implemented.
 TEST_F(Option6IAAddrTest, basic) {
 
-    boost::shared_array<char> simple_buf(new char[128]);
-    for (int i=0; i<128; i++)
+    boost::shared_array<uint8_t> simple_buf(new uint8_t[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 
+
+    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, 
+                                           0,
                                            24);
-    
+
     // pack this option again in the same buffer, but in
     // different place
     int offset = opt->pack(simple_buf, 128, 50);
@@ -80,21 +82,26 @@ TEST_F(Option6IAAddrTest, basic) {
     // 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(3000000000U, opt->getValid());
 
     EXPECT_EQ(D6O_IAADDR, opt->getType());
 
+    EXPECT_EQ(Option::OPTION6_HDR_LEN + Option6IAAddr::OPTION6_IAADDR_LEN,
+              opt->len());
+
     // 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;
+    EXPECT_NO_THROW(
+        delete opt;
+    );
 }
 
 }
diff --git a/src/lib/dhcp/tests/option_unittest.cc b/src/lib/dhcp/tests/option_unittest.cc
index 606d7ac..d4bd018 100644
--- a/src/lib/dhcp/tests/option_unittest.cc
+++ b/src/lib/dhcp/tests/option_unittest.cc
@@ -24,8 +24,8 @@
 #include <gtest/gtest.h>
 #include <boost/shared_ptr.hpp>
 
-#include <dhcp/dhcp6.h>
-#include <dhcp/option.h>
+#include "dhcp/dhcp6.h"
+#include "dhcp/option.h"
 
 using namespace std;
 using namespace isc;
@@ -47,7 +47,9 @@ TEST_F(OptionTest, basic4) {
     EXPECT_EQ(NULL, opt->getData());
     EXPECT_EQ(2, opt->len()); // just v4 header
 
-    delete opt;
+    EXPECT_NO_THROW(
+        delete opt;
+    );
 }
 
 // tests simple constructor
@@ -59,14 +61,16 @@ TEST_F(OptionTest, basic6) {
     EXPECT_EQ(NULL, opt->getData());
     EXPECT_EQ(4, opt->len()); // just v6 header
 
-    delete opt;
+    EXPECT_NO_THROW(
+        delete opt;
+    );
 }
 
 // tests contructor used in pkt reception
 // option contains actual data
 TEST_F(OptionTest, data1) {
-    boost::shared_array<char> buf(new char[32]);
-    for (int i=0; i<32; i++)
+    boost::shared_array<uint8_t> buf(new uint8_t[32]);
+    for (int i = 0; i < 32; i++)
         buf[i] = 100+i;
     Option* opt = new Option(Option::V6, 333, //type
                              buf,
@@ -89,28 +93,30 @@ TEST_F(OptionTest, data1) {
     // payload
     EXPECT_EQ(0, memcmp(&buf[3], &buf[24], 7) );
 
-    delete opt;
+    EXPECT_NO_THROW(
+        delete opt;
+    );
 }
 
 // another text that tests the same thing, just
 // with different input parameters
 TEST_F(OptionTest, data2) {
 
-    boost::shared_array<char> simple_buf(new char[128]);
-    for (int i=0; i<128; i++)
+    boost::shared_array<uint8_t> simple_buf(new uint8_t[128]);
+    for (int i = 0; i < 128; i++)
         simple_buf[i] = 0;
-    simple_buf[0]=0xa1;
-    simple_buf[1]=0xa2;
-    simple_buf[2]=0xa3;
-    simple_buf[3]=0xa4;
+    simple_buf[0] = 0xa1;
+    simple_buf[1] = 0xa2;
+    simple_buf[2] = 0xa3;
+    simple_buf[3] = 0xa4;
 
     // create an option (unpack content)
-    Option* opt = new Option(Option::V6, 
+    Option* opt = new Option(Option::V6,
                              D6O_CLIENTID,
                              simple_buf,
-                             0, 
+                             0,
                              4);
-    
+
     // pack this option again in the same buffer, but in
     // different place
     int offset18 = opt->pack(simple_buf, 128, 10);
@@ -127,11 +133,13 @@ TEST_F(OptionTest, data2) {
 
     // if option length is correct
     EXPECT_EQ(4, simple_buf[12]*256 + simple_buf[13]);
-    
+
     // if option content is correct
     EXPECT_EQ(0, memcmp(&simple_buf[0], &simple_buf[14],4));
 
-    delete opt;
+    EXPECT_NO_THROW(
+        delete opt;
+    );
 }
 
 // check that an option can contain 2 suboptions:
@@ -141,7 +149,7 @@ TEST_F(OptionTest, data2) {
 //  +----opt3
 //
 TEST_F(OptionTest, suboptions1) {
-    boost::shared_array<char> buf(new char[128]);
+    boost::shared_array<uint8_t> buf(new uint8_t[128]);
     for (int i=0; i<128; i++)
         buf[i] = 100+i;
     Option* opt1 = new Option(Option::V6, 65535, //type
@@ -163,7 +171,7 @@ TEST_F(OptionTest, suboptions1) {
     EXPECT_EQ(9, opt3->len());
     EXPECT_EQ(20, opt1->len());
 
-    unsigned char expected[] = {
+    uint8_t expected[] = {
         0xff, 0xff, 0, 16, 100, 101, 102,
         0, 7, 0, 5, 103, 104, 105, 106, 107,
         0, 13, 0, 0 // no data at all
@@ -175,7 +183,9 @@ TEST_F(OptionTest, suboptions1) {
     // payload
     EXPECT_EQ(0, memcmp(&buf[20], expected, 20) );
 
-    delete opt1;
+    EXPECT_NO_THROW(
+        delete opt1;
+    );
 }
 
 // check that an option can contain 2 suboptions:
@@ -185,7 +195,7 @@ TEST_F(OptionTest, suboptions1) {
 //        +----opt3
 //
 TEST_F(OptionTest, suboptions2) {
-    boost::shared_array<char> buf(new char[128]);
+    boost::shared_array<uint8_t> buf(new uint8_t[128]);
     for (int i=0; i<128; i++)
         buf[i] = 100+i;
     Option* opt1 = new Option(Option::V6, 65535, //type
@@ -203,7 +213,7 @@ TEST_F(OptionTest, suboptions2) {
     // opt2 len = 4 (just header) + len(opt3)
     // opt1 len = 7 + len(opt2)
 
-    unsigned char expected[] = {
+    uint8_t expected[] = {
         0xff, 0xff, 0, 16, 100, 101, 102,
         0, 13, 0, 9,
         0, 7, 0, 5, 103, 104, 105, 106, 107,
@@ -215,11 +225,13 @@ TEST_F(OptionTest, suboptions2) {
     // payload
     EXPECT_EQ(0, memcmp(&buf[20], expected, 20) );
 
-    delete opt1;
+    EXPECT_NO_THROW(
+        delete opt1;
+    );
 }
 
 TEST_F(OptionTest, addgetdel) {
-    boost::shared_array<char> buf(new char[128]);
+    boost::shared_array<uint8_t> buf(new uint8_t[128]);
     for (int i=0; i<128; i++)
         buf[i] = 100+i;
     Option* parent = new Option(Option::V6, 65535); //type
@@ -257,3 +269,15 @@ TEST_F(OptionTest, addgetdel) {
 }
 
 }
+
+TEST_F(OptionTest, toText) {
+    boost::shared_array<uint8_t> buf(new uint8_t[3]);
+    buf[0] = 0;
+    buf[1] = 0xf;
+    buf[2] = 0xff;
+
+    boost::shared_ptr<Option> opt(new Option(Option::V6, 258,
+                                             buf, 0, 3));
+
+    EXPECT_EQ("type=258, len=3: 00:0f:ff", opt->toText());
+}
diff --git a/src/lib/dhcp/tests/pkt4_unittest.cc b/src/lib/dhcp/tests/pkt4_unittest.cc
new file mode 100644
index 0000000..e7c4286
--- /dev/null
+++ b/src/lib/dhcp/tests/pkt4_unittest.cc
@@ -0,0 +1,428 @@
+// 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>
+#ifdef _WIN32
+#include <ws2tcpip.h>
+#else
+#include <arpa/inet.h>
+#endif
+#include <gtest/gtest.h>
+#include <boost/static_assert.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/shared_array.hpp>
+
+#include "asiolink/io_address.h"
+#include "dhcp/pkt4.h"
+#include "dhcp/dhcp4.h"
+#include "exceptions/exceptions.h"
+
+using namespace std;
+using namespace isc;
+using namespace isc::asiolink;
+using namespace isc::dhcp;
+using namespace boost;
+
+// can't compare const to value directly, as it gives strange
+// linker errors in gtest.h
+
+static size_t DHCPV4_PKT_HDR_LEN = Pkt4::DHCPV4_PKT_HDR_LEN;
+
+namespace {
+
+TEST(Pkt4Test, constructor) {
+
+    ASSERT_EQ(236U, DHCPV4_PKT_HDR_LEN);
+    Pkt4 * pkt = 0;
+
+    // minimal 
+    uint8_t testData[250];
+    for (int i=0 ; i < 250; i++)
+        testData[i]=i; 
+
+    // positive case1. Normal received packet
+    EXPECT_NO_THROW(
+        pkt = new Pkt4(testData, 236);
+    );
+
+    EXPECT_EQ(236, pkt->len());
+
+    EXPECT_NO_THROW(
+        delete pkt;
+        pkt = 0;
+    );
+
+    // positive case2. Normal outgoing packet
+    EXPECT_NO_THROW(
+        pkt = new Pkt4(DHCPDISCOVER, 0xffffffff);
+    );
+
+    // DHCPv4 packet must be at least 236 bytes long
+    EXPECT_EQ(DHCPV4_PKT_HDR_LEN, pkt->len());
+    EXPECT_EQ(DHCPDISCOVER, pkt->getType());
+    EXPECT_EQ(0xffffffff, pkt->getTransid());
+    EXPECT_NO_THROW(
+        delete pkt;
+        pkt = 0;
+    );
+
+    // negative case. Should drop truncated messages
+    EXPECT_THROW(
+        pkt = new Pkt4(testData, 235),
+        OutOfRange
+    );
+    if (pkt) {
+        // test failed anyway. Exception should have been thrown
+        delete pkt;
+    }
+}
+
+// a sample transaction-id
+const static uint32_t dummyTransid = 0x12345678;
+
+// a dummy MAC address
+const uint8_t dummyMacAddr[] = {0, 1, 2, 3, 4, 5};
+
+// a dummy MAC address, padded with 0s
+const uint8_t dummyChaddr[16] = {0, 1, 2, 3, 4, 5, 0, 0, 
+                                 0, 0, 0, 0, 0, 0, 0, 0 };
+
+// let's use some creative test content here (128 chars + \0)
+const uint8_t dummyFile[] = "Lorem ipsum dolor sit amet, consectetur "
+    "adipiscing elit. Proin mollis placerat metus, at "
+    "lacinia orci ornare vitae. Mauris amet.";
+    
+// yet another type of test content (64 chars + \0)
+const uint8_t dummySname[] = "Lorem ipsum dolor sit amet, consectetur "
+    "adipiscing elit posuere.";
+
+BOOST_STATIC_ASSERT(sizeof(dummyFile)  == Pkt4::MAX_FILE_LEN + 1);
+BOOST_STATIC_ASSERT(sizeof(dummySname) == Pkt4::MAX_SNAME_LEN + 1);
+
+/// Generates test packet
+///
+/// Allocates and generates test packet, with all fixed
+/// fields set to non-zero values. Content is not always
+/// reasonable.
+///
+/// See generateTestPacket2() function that returns
+/// exactly the same packet in on-wire format.
+///
+/// @return pointer to allocated Pkt4 object.
+boost::shared_ptr<Pkt4>
+generateTestPacket1() {
+
+    boost::shared_ptr<Pkt4> pkt(new Pkt4(DHCPDISCOVER, dummyTransid));
+    // hwType = 6(ETHERNET), hlen = 6(MAC address len)
+    pkt->setHWAddr(6, 6, dummyMacAddr); 
+    pkt->setHops(13); // 13 relays. Wow!
+    // transaction-id is already set
+    pkt->setSecs(42);
+    pkt->setFlags( 0xffffU ); // all flags set
+    pkt->setCiaddr(IOAddress("192.0.2.1"));
+    pkt->setYiaddr(IOAddress("1.2.3.4"));
+    pkt->setSiaddr(IOAddress("192.0.2.255"));
+    pkt->setGiaddr(IOAddress("255.255.255.255"));
+    // chaddr already set with setHWAddr()
+    pkt->setSname(dummySname, 64); 
+    pkt->setFile(dummyFile, 128);
+
+    return (pkt);
+}
+
+/// Generates test packet
+///
+/// Allocates and generates on-wire buffer that represents
+/// test packet, with all fixed fields set to non-zero values. 
+/// Content is not always reasonable.
+///
+/// See generateTestPacket1() function that returns
+/// exactly the same packet as Pkt4 object.
+///
+/// @return pointer to allocated Pkt4 object
+shared_array<uint8_t>
+generateTestPacket2() {
+
+    shared_array<uint8_t> buf(new uint8_t[Pkt4::DHCPV4_PKT_HDR_LEN]);
+
+    // that is only part of the header. It contains all "short" fields, 
+    // larger fields are constructed separately
+    uint8_t hdr[] = {
+        1, 6, 6, 13, // op, htype, hlen, hops,
+        0x12, 0x34, 0x56, 0x78, // transaction-id
+        0, 42, 0xff, 0xff, // 42 secs, 0xffff flags
+        192, 0, 2, 1, // ciaddr
+        1, 2, 3, 4, // yiaddr
+        192, 0, 2, 255, // siaddr
+        255, 255, 255, 255, // giaddr
+    };
+
+    BOOST_STATIC_ASSERT(28 == sizeof(hdr));
+
+    size_t offset = 0;
+
+    memcpy(&buf[0] + offset, hdr, sizeof(hdr));
+    offset += sizeof(hdr);
+
+    memcpy(&buf[0] + offset, dummyMacAddr, 6); // chaddr is 16 bytes
+    offset += Pkt4::MAX_CHADDR_LEN;
+    memcpy(&buf[0] + offset, dummySname, 64); // sname is 64 bytes
+    offset += Pkt4::MAX_SNAME_LEN;
+    memcpy(&buf[0] + offset, dummyFile, 128);
+    offset += Pkt4::MAX_FILE_LEN;
+
+    return (buf);
+}
+
+TEST(Pkt4Test, fixedFields) {
+
+    boost::shared_ptr<Pkt4> pkt = generateTestPacket1();
+
+    // ok, let's check packet values
+    EXPECT_EQ(1, pkt->getOp());
+    EXPECT_EQ(6, pkt->getHtype());
+    EXPECT_EQ(6, pkt->getHlen());
+    EXPECT_EQ(13, pkt->getHops());
+    EXPECT_EQ(dummyTransid, pkt->getTransid());
+    EXPECT_EQ(42, pkt->getSecs());
+    EXPECT_EQ(0xffff, pkt->getFlags());
+
+    EXPECT_EQ(string("192.0.2.1"), pkt->getCiaddr().toText());
+    EXPECT_EQ(string("1.2.3.4"), pkt->getYiaddr().toText());
+    EXPECT_EQ(string("192.0.2.255"), pkt->getSiaddr().toText());
+    EXPECT_EQ(string("255.255.255.255"), pkt->getGiaddr().toText());
+
+    // chaddr is always 16 bytes long and contains link-layer addr (MAC)
+    EXPECT_FALSE( memcmp(dummyChaddr, pkt->getChaddr(), 16) );
+
+    EXPECT_FALSE( memcmp(dummySname, pkt->getSname(), 64) );
+
+    EXPECT_FALSE( memcmp(dummyFile, pkt->getFile(), 128) );
+
+    EXPECT_EQ(DHCPDISCOVER, pkt->getType());
+}
+
+#if 0
+/// TODO Uncomment when ticket #1227 is implemented
+TEST(Pkt4Test, fixedFieldsPack) {
+    boost::shared_ptr<Pkt4> pkt = generateTestPacket1();
+    shared_array<uint8_t> expectedFormat = generateTestPacket2();
+
+    EXPECT_NO_THROW(
+        pkt->pack();
+    );
+
+    ASSERT_EQ(Pkt4::DHCPV4_PKT_HDR_LEN, pkt->len());
+
+    EXPECT_EQ(0, memcmp(&expectedFormat[0], pkt->getData(), pkt->len()));
+}
+
+/// TODO Uncomment when ticket #1226 is implemented
+TEST(Pkt4Test, fixedFieldsUnpack) {
+    shared_array<uint8_t> expectedFormat = generateTestPkt2();
+
+    boost::shared_ptr<Pkt4> pkt(new Pkt4(&expectedFormat[0], 
+                                  Pkt4::DHCPV4_PKT_HDR_LEN));
+
+    // ok, let's check packet values
+    EXPECT_EQ(1, pkt->getOp());
+    EXPECT_EQ(6, pkt->getHtype());
+    EXPECT_EQ(6, pkt->getHlen());
+    EXPECT_EQ(13, pkt->getHops());
+    EXPECT_EQ(transid, pkt->getTransid());
+    EXPECT_EQ(42, pkt->getSecs());
+    EXPECT_EQ(0xffff, pkt->getFlags());
+
+    EXPECT_EQ(string("192.0.2.1"), pkt->getCiaddr.toText());
+    EXPECT_EQ(string("1.2.3.4"), pkt->getYiaddr.toText());
+    EXPECT_EQ(string("192.0.2.255"), pkt->getSiaddr.toText());
+    EXPECT_EQ(string("255.255.255.255"), pkt->getGiaddr.toText());
+
+    // chaddr is always 16 bytes long and contains link-layer addr (MAC)
+    EXPECT_FALSE( memcmp(expectedChaddr, pkt->getChaddr(), 16) );
+
+    EXPECT_FALSE( memcmp(expectedSname, pkt->getSname(), 64) );
+
+    EXPECT_FALSE( memcmp(expectedFile, pkt->getFile(), 128) );
+
+    EXPECT_EQ(DHCPSOLICIT, pkt->getType());
+}
+#endif
+
+// this test is for hardware addresses (htype, hlen and chaddr fields)
+TEST(Pkt4Test, hwAddr) {
+
+    uint8_t mac[Pkt4::MAX_CHADDR_LEN];
+    uint8_t expectedChaddr[Pkt4::MAX_CHADDR_LEN];
+
+    Pkt4* pkt = 0;
+    // let's test each hlen, from 0 till 16
+    for (int macLen=0; macLen < Pkt4::MAX_CHADDR_LEN; macLen++) {
+        for (int i=0; i < Pkt4::MAX_CHADDR_LEN; i++) {
+            mac[i] = 0;
+            expectedChaddr[i] = 0;
+        }
+        for (int i=0; i < macLen; i++) {
+            mac[i] = 128+i;
+            expectedChaddr[i] = 128+i;
+        }
+        
+        // type and transaction doesn't matter in this test
+        pkt = new Pkt4(DHCPOFFER, 1234);
+        pkt->setHWAddr(255-macLen*10, // just weird htype
+                       macLen,
+                       mac);
+        EXPECT_EQ(0, memcmp(expectedChaddr, pkt->getChaddr(), 
+                            Pkt4::MAX_CHADDR_LEN));
+
+#if 0
+        /// TODO Uncomment when ticket #1227 is implemented)
+        EXPECT_NO_THROW( 
+            pkt->pack();
+        );
+
+        // CHADDR starts at offset 28 in DHCP packet
+        EXPECT_EQ(0, memcmp(pkt->getData()+28, expectedChaddr, 
+                            Pkt4::MAX_CHADDR_LEN));
+#endif
+
+        delete pkt;
+    }
+
+    /// TODO: extend this test once options support is implemented. HW address
+    /// longer than 16 bytes should be stored in client-identifier option
+}
+
+TEST(Pkt4Test, msgTypes) {
+
+    struct msgType {
+        uint8_t dhcp;
+        uint8_t bootp;
+    };
+
+    msgType types[] = {
+        {DHCPDISCOVER, BOOTREQUEST},
+        {DHCPOFFER, BOOTREPLY},
+        {DHCPREQUEST, BOOTREQUEST},
+        {DHCPDECLINE, BOOTREQUEST},
+        {DHCPACK, BOOTREPLY},
+        {DHCPNAK, BOOTREPLY},
+        {DHCPRELEASE, BOOTREQUEST},
+        {DHCPINFORM, BOOTREQUEST},
+        {DHCPLEASEQUERY, BOOTREQUEST},
+        {DHCPLEASEUNASSIGNED, BOOTREPLY},
+        {DHCPLEASEUNKNOWN, BOOTREPLY},
+        {DHCPLEASEACTIVE, BOOTREPLY}
+    };
+
+    Pkt4* pkt = 0;
+    for (int i=0; i < sizeof(types)/sizeof(msgType); i++) {
+
+        pkt = new Pkt4(types[i].dhcp, 0);
+        EXPECT_EQ(types[i].dhcp, pkt->getType());
+
+        EXPECT_EQ(types[i].bootp, pkt->getOp());
+
+        delete pkt;
+        pkt = 0;
+    }
+
+    EXPECT_THROW(
+        pkt = new Pkt4(100, 0), // there's no message type 100
+        OutOfRange
+    );
+    if (pkt) {
+        delete pkt;
+    }
+}
+
+// this test verifies handling of sname field
+TEST(Pkt4Test, sname) {
+
+    uint8_t sname[Pkt4::MAX_SNAME_LEN];
+    uint8_t expectedSname[Pkt4::MAX_SNAME_LEN];
+
+    Pkt4* pkt = 0;
+    // let's test each sname length, from 0 till 64
+    for (int snameLen=0; snameLen < Pkt4::MAX_SNAME_LEN; snameLen++) {
+        for (int i=0; i < Pkt4::MAX_SNAME_LEN; i++) {
+            sname[i] = 0;
+            expectedSname[i] = 0;
+        }
+        for (int i=0; i < snameLen; i++) {
+            sname[i] = i;
+            expectedSname[i] = i;
+        }
+        
+        // type and transaction doesn't matter in this test
+        pkt = new Pkt4(DHCPOFFER, 1234);
+        pkt->setSname(sname, snameLen);
+
+        EXPECT_EQ(0, memcmp(expectedSname, pkt->getSname(), Pkt4::MAX_SNAME_LEN));
+
+#if 0
+        /// TODO Uncomment when ticket #1227 is implemented)
+        EXPECT_NO_THROW( 
+            pkt->pack();
+        );
+
+        // SNAME starts at offset 44 in DHCP packet
+        EXPECT_EQ(0, memcmp(pkt->getData()+44, expectedChaddr, Pkt4::MAX_SNAME_LEN));
+#endif
+
+        delete pkt;
+    }
+}
+
+TEST(Pkt4Test, file) {
+
+    uint8_t file[Pkt4::MAX_FILE_LEN];
+    uint8_t expectedFile[Pkt4::MAX_FILE_LEN];
+
+    Pkt4* pkt = 0;
+    // let's test each file length, from 0 till 64
+    for (int fileLen=0; fileLen < Pkt4::MAX_FILE_LEN; fileLen++) {
+        for (int i=0; i < Pkt4::MAX_FILE_LEN; i++) {
+            file[i] = 0;
+            expectedFile[i] = 0;
+        }
+        for (int i=0; i < fileLen; i++) {
+            file[i] = i;
+            expectedFile[i] = i;
+        }
+        
+        // type and transaction doesn't matter in this test
+        pkt = new Pkt4(DHCPOFFER, 1234);
+        pkt->setFile(file, fileLen);
+
+        EXPECT_EQ(0, memcmp(expectedFile, pkt->getFile(), Pkt4::MAX_FILE_LEN));
+
+#if 0
+        /// TODO Uncomment when ticket #1227 is implemented)
+        EXPECT_NO_THROW( 
+            pkt->pack();
+        );
+
+        // FILE starts at offset 44 in DHCP packet
+        EXPECT_EQ(0, memcmp(pkt->getData()+44, expectedChaddr, Pkt4::MAX_FILE_LEN));
+#endif
+
+        delete pkt;
+    }
+
+}
+
+} // end of anonymous namespace
diff --git a/src/lib/dhcp/tests/pkt6_unittest.cc b/src/lib/dhcp/tests/pkt6_unittest.cc
index b31d89a..c8ec049 100644
--- a/src/lib/dhcp/tests/pkt6_unittest.cc
+++ b/src/lib/dhcp/tests/pkt6_unittest.cc
@@ -22,10 +22,10 @@
 #endif
 #include <gtest/gtest.h>
 
-#include <asiolink/io_address.h>
-#include <dhcp/option.h>
-#include <dhcp/pkt6.h>
-#include <dhcp/dhcp6.h>
+#include "asiolink/io_address.h"
+#include "dhcp/option.h"
+#include "dhcp/pkt6.h"
+#include "dhcp/dhcp6.h"
 
 using namespace std;
 using namespace isc;
@@ -43,7 +43,7 @@ public:
 TEST_F(Pkt6Test, constructor) {
     Pkt6 * pkt1 = new Pkt6(17);
 
-    ASSERT_EQ(pkt1->data_len_, 17);
+    EXPECT_EQ(pkt1->data_len_, 17);
 
     delete pkt1;
 }
@@ -89,30 +89,85 @@ Pkt6 *capture1() {
     return (pkt);
 }
 
-TEST_F(Pkt6Test, parse_solicit1) {
+TEST_F(Pkt6Test, unpack_solicit1) {
     Pkt6 * sol = capture1();
 
     ASSERT_EQ(true, sol->unpack());
 
-    boost::shared_ptr<isc::dhcp::Option> null;
+    // check for length
+    EXPECT_EQ(98, sol->len() );
+
+    // check for type
+    EXPECT_EQ(DHCPV6_SOLICIT, sol->getType() );
 
     // check that all present options are returned
-    EXPECT_NE(null, sol->getOption(D6O_CLIENTID)); // client-id is present
-    EXPECT_NE(null, sol->getOption(D6O_IA_NA));    // IA_NA is present
-    EXPECT_NE(null, sol->getOption(D6O_ELAPSED_TIME));  // elapsed is present
-    EXPECT_NE(null, sol->getOption(D6O_NAME_SERVERS));
-    EXPECT_NE(null, sol->getOption(D6O_ORO));
+    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));
 
     // let's check that non-present options are not returned
-    EXPECT_EQ(null, sol->getOption(D6O_SERVERID)); // server-id is missing
-    EXPECT_EQ(null, sol->getOption(D6O_IA_TA));
-    EXPECT_EQ(null, sol->getOption(D6O_IAADDR));
+    EXPECT_FALSE(sol->getOption(D6O_SERVERID)); // server-id is missing
+    EXPECT_FALSE(sol->getOption(D6O_IA_TA));
+    EXPECT_FALSE(sol->getOption(D6O_IAADDR));
 
     std::cout << sol->toText();
 
     delete sol;
 }
 
+TEST_F(Pkt6Test, packUnpack) {
+
+    Pkt6 * parent = new Pkt6(100);
+
+    parent->setType(DHCPV6_SOLICIT);
+
+    boost::shared_ptr<Option> opt1(new Option(Option::V6, 1));
+    boost::shared_ptr<Option> opt2(new Option(Option::V6, 2));
+    boost::shared_ptr<Option> opt3(new Option(Option::V6, 100));
+    // 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());
+    int transid = parent->getTransid();
+    // transaction-id was randomized, let's remember it
+
+    // calculated length should be 16
+    EXPECT_EQ( Pkt6::DHCPV6_PKT_HDR_LEN + 3*Option::OPTION6_HDR_LEN, 
+               parent->len() );
+
+    EXPECT_TRUE( parent->pack() );
+
+    //
+    EXPECT_EQ( Pkt6::DHCPV6_PKT_HDR_LEN + 3*Option::OPTION6_HDR_LEN, 
+               parent->len() );
+
+    // let's delete options from options_ collection
+    // they still be defined in packed 
+    parent->options_.clear();
+
+    // that that removed options are indeed are gone
+    EXPECT_EQ( 4, parent->len() );
+
+    // now recreate options list
+    EXPECT_TRUE( parent->unpack() );
+
+    // transid, message-type should be the same as before
+    EXPECT_EQ(transid, parent->getTransid());
+    EXPECT_EQ(DHCPV6_SOLICIT, parent->getType());
+    
+    EXPECT_TRUE( parent->getOption(1));
+    EXPECT_TRUE( parent->getOption(2));
+    EXPECT_TRUE( parent->getOption(100));
+    EXPECT_FALSE( parent->getOption(4));
+    
+    delete parent;
+}
+
 TEST_F(Pkt6Test, addGetDelOptions) {
     Pkt6 * parent = new Pkt6(100);
 
diff --git a/src/lib/dhcp/tests/run_unittests.cc b/src/lib/dhcp/tests/run_unittests.cc
index 8a9d1e5..db27f76 100644
--- a/src/lib/dhcp/tests/run_unittests.cc
+++ b/src/lib/dhcp/tests/run_unittests.cc
@@ -13,7 +13,6 @@
 // PERFORMANCE OF THIS SOFTWARE.
 
 #include <gtest/gtest.h>
-#include <util/unittests/run_all.h>
 
 #include <log/logger_support.h>
 
@@ -21,5 +20,8 @@ int
 main(int argc, char* argv[]) {
     ::testing::InitGoogleTest(&argc, argv);
     isc::log::initLogger();
-    return (isc::util::unittests::run_all());
+
+    int result = RUN_ALL_TESTS();
+
+    return (result);
 }
diff --git a/src/lib/util/io_utilities.h b/src/lib/util/io_utilities.h
index ecab3ce..61d4c9c 100644
--- a/src/lib/util/io_utilities.h
+++ b/src/lib/util/io_utilities.h
@@ -48,13 +48,54 @@ readUint16(const void* buffer) {
 /// \param value 16-bit value to convert
 /// \param buffer Data buffer at least two bytes long into which the 16-bit
 ///        value is written in network-byte order.
-
-inline void
+///
+/// \return pointer to the next byte after stored value
+inline uint8_t*
 writeUint16(uint16_t value, void* buffer) {
     uint8_t* byte_buffer = static_cast<uint8_t*>(buffer);
 
     byte_buffer[0] = static_cast<uint8_t>((value & 0xff00U) >> 8);
     byte_buffer[1] = static_cast<uint8_t>(value & 0x00ffU);
+
+    return (byte_buffer + sizeof(uint16_t));
+}
+
+/// \brief Read Unsigned 32-Bit Integer from Buffer
+///
+/// \param buffer Data buffer at least four bytes long of which the first four
+///        bytes are assumed to represent a 32-bit integer in network-byte
+///        order.
+///
+/// \return Value of 32-bit unsigned integer
+inline uint32_t
+readUint32(const uint8_t* buffer) {
+    const uint8_t* byte_buffer = static_cast<const uint8_t*>(buffer);
+
+    uint32_t result = (static_cast<uint32_t>(byte_buffer[0])) << 24;
+    result |= (static_cast<uint32_t>(byte_buffer[1])) << 16;
+    result |= (static_cast<uint32_t>(byte_buffer[2])) << 8;
+    result |= (static_cast<uint32_t>(byte_buffer[3]));
+
+    return (result);
+}
+
+/// \brief Write Unisgned 32-Bit Integer to Buffer
+///
+/// \param value 32-bit value to convert
+/// \param buffer Data buffer at least four bytes long into which the 32-bit
+///        value is written in network-byte order.
+///
+/// \return pointer to the next byte after stored value
+inline uint8_t*
+writeUint32(uint32_t value, uint8_t* buffer) {
+    uint8_t* byte_buffer = static_cast<uint8_t*>(buffer);
+
+    byte_buffer[0] = static_cast<uint8_t>((value & 0xff000000U) >> 24);
+    byte_buffer[1] = static_cast<uint8_t>((value & 0x00ff0000U) >> 16);
+    byte_buffer[2] = static_cast<uint8_t>((value & 0x0000ff00U) >>  8);
+    byte_buffer[3] = static_cast<uint8_t>((value & 0x000000ffU));
+
+    return (byte_buffer + sizeof(uint32_t));
 }
 
 } // namespace util
diff --git a/src/lib/util/tests/io_utilities_unittest.cc b/src/lib/util/tests/io_utilities_unittest.cc
index 4aad560..c509e2c 100644
--- a/src/lib/util/tests/io_utilities_unittest.cc
+++ b/src/lib/util/tests/io_utilities_unittest.cc
@@ -19,6 +19,11 @@
 
 #include <cstddef>
 
+#ifdef _WIN32
+#include <ws2tcpip.h>
+#else
+#include <arpa/inet.h>
+#endif
 #include <gtest/gtest.h>
 
 #include <util/buffer.h>
@@ -71,3 +76,48 @@ TEST(asioutil, writeUint16) {
         EXPECT_EQ(ref[1], test[1]);
     }
 }
+
+// test data shared amount readUint32 and writeUint32 tests
+const static uint32_t test32[] = {
+    0,
+    1,
+    2000,
+    0x80000000,
+    0xffffffff
+};
+
+TEST(asioutil, readUint32) {
+    uint8_t data[8];
+
+    // make sure that we can read data, regardless of
+    // the memory alignment. That' why we need to repeat
+    // it 4 times.
+    for (int offset=0; offset < 4; offset++) {
+        for (int i=0; i < sizeof(test32)/sizeof(uint32_t); i++) {
+            uint32_t tmp = htonl(test32[i]);
+            memcpy(&data[offset], &tmp, sizeof(uint32_t));
+
+            EXPECT_EQ(test32[i], readUint32(&data[offset]));
+        }
+    }
+}
+
+
+TEST(asioutil, writeUint32) {
+    uint8_t data[8];
+
+    // make sure that we can write data, regardless of
+    // the memory alignment. That's why we need to repeat
+    // it 4 times.
+    for (int offset=0; offset < 4; offset++) {
+        for (int i=0; i < sizeof(test32)/sizeof(uint32_t); i++) {
+            uint8_t* ptr = writeUint32(test32[i], &data[offset]);
+
+            EXPECT_EQ(&data[offset]+sizeof(uint32_t), ptr);
+
+            uint32_t tmp = htonl(test32[i]);
+
+            EXPECT_EQ(0, memcmp(&tmp, &data[offset], sizeof(uint32_t)));
+        }
+    }
+}
diff --git a/win32build/VS2008/b10-dhcp6/b10-dhcp6.vcproj b/win32build/VS2008/b10-dhcp6/b10-dhcp6.vcproj
index 4e1299f..5efc045 100755
--- a/win32build/VS2008/b10-dhcp6/b10-dhcp6.vcproj
+++ b/win32build/VS2008/b10-dhcp6/b10-dhcp6.vcproj
@@ -196,10 +196,6 @@
 				RelativePath="..\..\..\src\bin\dhcp6\main.cc"
 				>
 			</File>
-			<File
-				RelativePath="..\..\..\src\bin\dhcp6\pkt6.cc"
-				>
-			</File>
 		</Filter>
 		<Filter
 			Name="Header Files"
@@ -207,10 +203,6 @@
 			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
 			>
 			<File
-				RelativePath="..\..\..\src\bin\dhcp6\dhcp6.h"
-				>
-			</File>
-			<File
 				RelativePath="..\..\..\src\bin\dhcp6\dhcp6_srv.h"
 				>
 			</File>
@@ -223,10 +215,6 @@
 				>
 			</File>
 			<File
-				RelativePath="..\..\..\src\bin\dhcp6\pkt6.h"
-				>
-			</File>
-			<File
 				RelativePath="..\..\..\src\bin\dhcp6\spec_config.h"
 				>
 			</File>
diff --git a/win32build/VS2008/b10-dhcp6_tests/b10-dhcp6_tests.vcproj b/win32build/VS2008/b10-dhcp6_tests/b10-dhcp6_tests.vcproj
index 7671813..38377ae 100755
--- a/win32build/VS2008/b10-dhcp6_tests/b10-dhcp6_tests.vcproj
+++ b/win32build/VS2008/b10-dhcp6_tests/b10-dhcp6_tests.vcproj
@@ -198,14 +198,6 @@
 				RelativePath="..\..\..\src\bin\dhcp6\tests\iface_mgr_unittest.cc"
 				>
 			</File>
-			<File
-				RelativePath="..\..\..\src\bin\dhcp6\pkt6.cc"
-				>
-			</File>
-			<File
-				RelativePath="..\..\..\src\bin\dhcp6\tests\pkt6_unittest.cc"
-				>
-			</File>
 		</Filter>
 		<Filter
 			Name="Header Files"
@@ -220,10 +212,6 @@
 				RelativePath="..\..\..\src\bin\dhcp6\iface_mgr.h"
 				>
 			</File>
-			<File
-				RelativePath="..\..\..\src\bin\dhcp6\pkt6.h"
-				>
-			</File>
 		</Filter>
 		<Filter
 			Name="Resource Files"
diff --git a/win32build/VS2008/libdhcp/libdhcp.vcproj b/win32build/VS2008/libdhcp/libdhcp.vcproj
index 43add6e..56b96cc 100755
--- a/win32build/VS2008/libdhcp/libdhcp.vcproj
+++ b/win32build/VS2008/libdhcp/libdhcp.vcproj
@@ -171,6 +171,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\..\src\lib\dhcp\pkt4.cc"
+				>
+			</File>
+			<File
 				RelativePath="..\..\..\src\lib\dhcp\pkt6.cc"
 				>
 			</File>
@@ -181,6 +185,10 @@
 			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
 			>
 			<File
+				RelativePath="..\..\..\src\lib\dhcp\dhcp4.h"
+				>
+			</File>
+			<File
 				RelativePath="..\..\..\src\lib\dhcp\dhcp6.h"
 				>
 			</File>
@@ -205,6 +213,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\..\src\lib\dhcp\pkt4.h"
+				>
+			</File>
+			<File
 				RelativePath="..\..\..\src\lib\dhcp\pkt6.h"
 				>
 			</File>
diff --git a/win32build/VS2008/libdhcp_tests/libdhcp_tests.vcproj b/win32build/VS2008/libdhcp_tests/libdhcp_tests.vcproj
index f2562a8..1dfb663 100755
--- a/win32build/VS2008/libdhcp_tests/libdhcp_tests.vcproj
+++ b/win32build/VS2008/libdhcp_tests/libdhcp_tests.vcproj
@@ -199,6 +199,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\..\src\lib\dhcp\tests\pkt4_unittest.cc"
+				>
+			</File>
+			<File
 				RelativePath="..\..\..\src\lib\dhcp\tests\pkt6_unittest.cc"
 				>
 			</File>
diff --git a/win32build/VS2008/libutil_tests/libutil_tests.vcproj b/win32build/VS2008/libutil_tests/libutil_tests.vcproj
index f53bf7c..be6c653 100755
--- a/win32build/VS2008/libutil_tests/libutil_tests.vcproj
+++ b/win32build/VS2008/libutil_tests/libutil_tests.vcproj
@@ -62,7 +62,7 @@
 			<Tool
 				Name="VCLinkerTool"
 				LinkLibraryDependencies="false"
-				AdditionalDependencies="libexceptions.lib libutil.lib libutil_io.lib libutil_unittests.lib gtestd.lib"
+				AdditionalDependencies="libexceptions.lib libutil.lib libutil_io.lib libutil_unittests.lib gtestd.lib ws2_32.lib"
 				OutputFile="$(OutDir)\run_unittests.exe"
 				LinkIncremental="2"
 				AdditionalLibraryDirectories=""..\libexceptions\$(ConfigurationName)";"..\libutil\$(ConfigurationName)";"..\libutil_io\$(ConfigurationName)";"..\libutil_unittests\$(ConfigurationName)";"..\..\..\..\gtest\md9\$(ConfigurationName)""
@@ -139,7 +139,7 @@
 			<Tool
 				Name="VCLinkerTool"
 				LinkLibraryDependencies="false"
-				AdditionalDependencies="libexceptions.lib libutil.lib libutil_io.lib libutil_unittests.lib gtest.lib"
+				AdditionalDependencies="libexceptions.lib libutil.lib libutil_io.lib libutil_unittests.lib gtest.lib ws2_32.lib"
 				OutputFile="$(OutDir)\run_unittests.exe"
 				LinkIncremental="1"
 				AdditionalLibraryDirectories=""..\libexceptions\$(ConfigurationName)";"..\libutil\$(ConfigurationName)";"..\libutil_io\$(ConfigurationName)";"..\libutil_unittests\$(ConfigurationName)";"..\..\..\..\gtest\md9\$(ConfigurationName)""
diff --git a/win32build/VS2010+x64/b10-dhcp6/b10-dhcp6.vcxproj b/win32build/VS2010+x64/b10-dhcp6/b10-dhcp6.vcxproj
index 05d7f12..130737e 100755
--- a/win32build/VS2010+x64/b10-dhcp6/b10-dhcp6.vcxproj
+++ b/win32build/VS2010+x64/b10-dhcp6/b10-dhcp6.vcxproj
@@ -177,10 +177,8 @@ copy spec_config.h.win32 spec_config.h
     </PreBuildEvent>
   </ItemDefinitionGroup>
   <ItemGroup>
-    <ClInclude Include="..\..\..\src\bin\dhcp6\dhcp6.h" />
     <ClInclude Include="..\..\..\src\bin\dhcp6\dhcp6_srv.h" />
     <ClInclude Include="..\..\..\src\bin\dhcp6\iface_mgr.h" />
-    <ClInclude Include="..\..\..\src\bin\dhcp6\pkt6.h" />
     <ClInclude Include="..\..\..\src\bin\dhcp6\spec_config.h" />
     <ClInclude Include="..\..\getopt.h" />
   </ItemGroup>
@@ -188,7 +186,6 @@ copy spec_config.h.win32 spec_config.h
     <ClCompile Include="..\..\..\src\bin\dhcp6\dhcp6_srv.cc" />
     <ClCompile Include="..\..\..\src\bin\dhcp6\iface_mgr.cc" />
     <ClCompile Include="..\..\..\src\bin\dhcp6\main.cc" />
-    <ClCompile Include="..\..\..\src\bin\dhcp6\pkt6.cc" />
     <ClCompile Include="..\..\getopt.cc" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
diff --git a/win32build/VS2010+x64/b10-dhcp6/b10-dhcp6.vcxproj.filters b/win32build/VS2010+x64/b10-dhcp6/b10-dhcp6.vcxproj.filters
index 6972f39..d51f865 100755
--- a/win32build/VS2010+x64/b10-dhcp6/b10-dhcp6.vcxproj.filters
+++ b/win32build/VS2010+x64/b10-dhcp6/b10-dhcp6.vcxproj.filters
@@ -24,12 +24,6 @@
     <ClInclude Include="..\..\getopt.h">
       <Filter>Header Files</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\..\src\bin\dhcp6\dhcp6.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\..\src\bin\dhcp6\pkt6.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\..\src\bin\dhcp6\spec_config.h">
       <Filter>Header Files</Filter>
     </ClInclude>
@@ -47,8 +41,5 @@
     <ClCompile Include="..\..\getopt.cc">
       <Filter>Source Files</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\..\src\bin\dhcp6\pkt6.cc">
-      <Filter>Source Files</Filter>
-    </ClCompile>
   </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/win32build/VS2010+x64/b10-dhcp6_tests/b10-dhcp6_tests.vcxproj b/win32build/VS2010+x64/b10-dhcp6_tests/b10-dhcp6_tests.vcxproj
index 8038bd9..d5b841a 100755
--- a/win32build/VS2010+x64/b10-dhcp6_tests/b10-dhcp6_tests.vcxproj
+++ b/win32build/VS2010+x64/b10-dhcp6_tests/b10-dhcp6_tests.vcxproj
@@ -163,16 +163,13 @@
   <ItemGroup>
     <ClInclude Include="..\..\..\src\bin\dhcp6\dhcp6_srv.h" />
     <ClInclude Include="..\..\..\src\bin\dhcp6\iface_mgr.h" />
-    <ClInclude Include="..\..\..\src\bin\dhcp6\pkt6.h" />
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\..\src\bin\dhcp6\dhcp6_srv.cc" />
     <ClCompile Include="..\..\..\src\bin\dhcp6\iface_mgr.cc" />
-    <ClCompile Include="..\..\..\src\bin\dhcp6\pkt6.cc" />
     <ClCompile Include="..\..\..\src\bin\dhcp6\tests\dhcp6_srv_unittest.cc" />
     <ClCompile Include="..\..\..\src\bin\dhcp6\tests\dhcp6_unittests.cc" />
     <ClCompile Include="..\..\..\src\bin\dhcp6\tests\iface_mgr_unittest.cc" />
-    <ClCompile Include="..\..\..\src\bin\dhcp6\tests\pkt6_unittest.cc" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
diff --git a/win32build/VS2010+x64/b10-dhcp6_tests/b10-dhcp6_tests.vcxproj.filters b/win32build/VS2010+x64/b10-dhcp6_tests/b10-dhcp6_tests.vcxproj.filters
index 774c898..e08588f 100755
--- a/win32build/VS2010+x64/b10-dhcp6_tests/b10-dhcp6_tests.vcxproj.filters
+++ b/win32build/VS2010+x64/b10-dhcp6_tests/b10-dhcp6_tests.vcxproj.filters
@@ -21,9 +21,6 @@
     <ClInclude Include="..\..\..\src\bin\dhcp6\iface_mgr.h">
       <Filter>Header Files</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\..\src\bin\dhcp6\pkt6.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\..\src\bin\dhcp6\dhcp6_srv.cc">
@@ -41,11 +38,5 @@
     <ClCompile Include="..\..\..\src\bin\dhcp6\tests\iface_mgr_unittest.cc">
       <Filter>Source Files</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\..\src\bin\dhcp6\tests\pkt6_unittest.cc">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\..\src\bin\dhcp6\pkt6.cc">
-      <Filter>Source Files</Filter>
-    </ClCompile>
   </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/win32build/VS2010+x64/libdhcp/libdhcp.vcxproj b/win32build/VS2010+x64/libdhcp/libdhcp.vcxproj
index 6366e0c..d2d3c61 100755
--- a/win32build/VS2010+x64/libdhcp/libdhcp.vcxproj
+++ b/win32build/VS2010+x64/libdhcp/libdhcp.vcxproj
@@ -19,12 +19,14 @@
     </ProjectConfiguration>
   </ItemGroup>
   <ItemGroup>
+    <ClInclude Include="..\..\..\src\lib\dhcp\dhcp4.h" />
     <ClInclude Include="..\..\..\src\lib\dhcp\dhcp6.h" />
     <ClInclude Include="..\..\..\src\lib\dhcp\libdhcp.h" />
     <ClInclude Include="..\..\..\src\lib\dhcp\option.h" />
     <ClInclude Include="..\..\..\src\lib\dhcp\option6_addrlst.h" />
     <ClInclude Include="..\..\..\src\lib\dhcp\option6_ia.h" />
     <ClInclude Include="..\..\..\src\lib\dhcp\option6_iaaddr.h" />
+    <ClInclude Include="..\..\..\src\lib\dhcp\pkt4.h" />
     <ClInclude Include="..\..\..\src\lib\dhcp\pkt6.h" />
   </ItemGroup>
   <ItemGroup>
@@ -33,6 +35,7 @@
     <ClCompile Include="..\..\..\src\lib\dhcp\option6_addrlst.cc" />
     <ClCompile Include="..\..\..\src\lib\dhcp\option6_ia.cc" />
     <ClCompile Include="..\..\..\src\lib\dhcp\option6_iaaddr.cc" />
+    <ClCompile Include="..\..\..\src\lib\dhcp\pkt4.cc" />
     <ClCompile Include="..\..\..\src\lib\dhcp\pkt6.cc" />
   </ItemGroup>
   <PropertyGroup Label="Globals">
diff --git a/win32build/VS2010+x64/libdhcp/libdhcp.vcxproj.filters b/win32build/VS2010+x64/libdhcp/libdhcp.vcxproj.filters
index 7f69742..40c2c6e 100755
--- a/win32build/VS2010+x64/libdhcp/libdhcp.vcxproj.filters
+++ b/win32build/VS2010+x64/libdhcp/libdhcp.vcxproj.filters
@@ -36,6 +36,12 @@
     <ClInclude Include="..\..\..\src\lib\dhcp\pkt6.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\..\src\lib\dhcp\dhcp4.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\..\src\lib\dhcp\pkt4.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\..\src\lib\dhcp\libdhcp.cc">
@@ -56,5 +62,8 @@
     <ClCompile Include="..\..\..\src\lib\dhcp\pkt6.cc">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\..\src\lib\dhcp\pkt4.cc">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/win32build/VS2010+x64/libdhcp_tests/libdhcp_tests.vcxproj b/win32build/VS2010+x64/libdhcp_tests/libdhcp_tests.vcxproj
index d5eb0f8..c2bc468 100755
--- a/win32build/VS2010+x64/libdhcp_tests/libdhcp_tests.vcxproj
+++ b/win32build/VS2010+x64/libdhcp_tests/libdhcp_tests.vcxproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup Label="ProjectConfigurations">
     <ProjectConfiguration Include="Debug|Win32">
@@ -166,6 +166,7 @@
     <ClCompile Include="..\..\..\src\lib\dhcp\tests\option6_iaaddr_unittest.cc" />
     <ClCompile Include="..\..\..\src\lib\dhcp\tests\option6_ia_unittest.cc" />
     <ClCompile Include="..\..\..\src\lib\dhcp\tests\option_unittest.cc" />
+    <ClCompile Include="..\..\..\src\lib\dhcp\tests\pkt4_unittest.cc" />
     <ClCompile Include="..\..\..\src\lib\dhcp\tests\pkt6_unittest.cc" />
     <ClCompile Include="..\..\..\src\lib\dhcp\tests\run_unittests.cc" />
   </ItemGroup>
diff --git a/win32build/VS2010+x64/libdhcp_tests/libdhcp_tests.vcxproj.filters b/win32build/VS2010+x64/libdhcp_tests/libdhcp_tests.vcxproj.filters
index 060fbe5..540d2df 100755
--- a/win32build/VS2010+x64/libdhcp_tests/libdhcp_tests.vcxproj.filters
+++ b/win32build/VS2010+x64/libdhcp_tests/libdhcp_tests.vcxproj.filters
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup>
     <Filter Include="Source Files">
@@ -30,6 +30,9 @@
     <ClCompile Include="..\..\..\src\lib\dhcp\tests\option6_iaaddr_unittest.cc">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\..\src\lib\dhcp\tests\pkt4_unittest.cc">
+      <Filter>Source Files</Filter>
+    </ClCompile>
     <ClCompile Include="..\..\..\src\lib\dhcp\tests\pkt6_unittest.cc">
       <Filter>Source Files</Filter>
     </ClCompile>
diff --git a/win32build/VS2010+x64/libutil_tests/libutil_tests.vcxproj b/win32build/VS2010+x64/libutil_tests/libutil_tests.vcxproj
index dc76c7f..03fccb4 100755
--- a/win32build/VS2010+x64/libutil_tests/libutil_tests.vcxproj
+++ b/win32build/VS2010+x64/libutil_tests/libutil_tests.vcxproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup Label="ProjectConfigurations">
     <ProjectConfiguration Include="Debug|Win32">
@@ -97,7 +97,7 @@
       <SubSystem>Console</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <OutputFile>$(OutDir)run_unittests$(TargetExt)</OutputFile>
-      <AdditionalDependencies>libexceptions.lib;libutil.lib;libutil_io.lib;libutil_unittests.lib;gtestd.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>libexceptions.lib;libutil.lib;libutil_io.lib;libutil_unittests.lib;gtestd.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <AdditionalLibraryDirectories>..\libexceptions\$(Configuration);..\libutil\$(Configuration);..\libutil_io\$(Configuration);..\libutil_unittests\$(Configuration);..\..\..\..\gtest\x64\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
     </Link>
   </ItemDefinitionGroup>
@@ -114,7 +114,7 @@
       <SubSystem>Console</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <OutputFile>$(OutDir)run_unittests$(TargetExt)</OutputFile>
-      <AdditionalDependencies>libexceptions.lib;libutil.lib;libutil_io.lib;libutil_unittests.lib;gtestd.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>libexceptions.lib;libutil.lib;libutil_io.lib;libutil_unittests.lib;gtestd.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <AdditionalLibraryDirectories>..\libexceptions\$(Configuration);..\libutil\$(Configuration);..\libutil_io\$(Configuration);..\libutil_unittests\$(Configuration);..\..\..\..\gtest\x64\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
     </Link>
   </ItemDefinitionGroup>
@@ -135,7 +135,7 @@
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
       <OutputFile>$(OutDir)run_unittests$(TargetExt)</OutputFile>
-      <AdditionalDependencies>libexceptions.lib;libutil.lib;libutil_io.lib;libutil_unittests.lib;gtest.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>libexceptions.lib;libutil.lib;libutil_io.lib;libutil_unittests.lib;gtest.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <AdditionalLibraryDirectories>..\libexceptions\$(Configuration);..\libutil\$(Configuration);..\libutil_io\$(Configuration);..\libutil_unittests\$(Configuration);..\..\..\..\gtest\x64\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
     </Link>
   </ItemDefinitionGroup>
@@ -156,7 +156,7 @@
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
       <OutputFile>$(OutDir)run_unittests$(TargetExt)</OutputFile>
-      <AdditionalDependencies>libexceptions.lib;libutil.lib;libutil_io.lib;libutil_unittests.lib;gtest.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>libexceptions.lib;libutil.lib;libutil_io.lib;libutil_unittests.lib;gtest.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <AdditionalLibraryDirectories>..\libexceptions\$(Configuration);..\libutil\$(Configuration);..\libutil_io\$(Configuration);..\libutil_unittests\$(Configuration);..\..\..\..\gtest\x64\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
     </Link>
   </ItemDefinitionGroup>
diff --git a/win32build/VS2010/b10-dhcp6/b10-dhcp6.vcxproj b/win32build/VS2010/b10-dhcp6/b10-dhcp6.vcxproj
index 35c21cf..652004d 100755
--- a/win32build/VS2010/b10-dhcp6/b10-dhcp6.vcxproj
+++ b/win32build/VS2010/b10-dhcp6/b10-dhcp6.vcxproj
@@ -94,10 +94,8 @@ copy spec_config.h.win32 spec_config.h
     </PreBuildEvent>
   </ItemDefinitionGroup>
   <ItemGroup>
-    <ClInclude Include="..\..\..\src\bin\dhcp6\dhcp6.h" />
     <ClInclude Include="..\..\..\src\bin\dhcp6\dhcp6_srv.h" />
     <ClInclude Include="..\..\..\src\bin\dhcp6\iface_mgr.h" />
-    <ClInclude Include="..\..\..\src\bin\dhcp6\pkt6.h" />
     <ClInclude Include="..\..\..\src\bin\dhcp6\spec_config.h" />
     <ClInclude Include="..\..\getopt.h" />
   </ItemGroup>
@@ -105,7 +103,6 @@ copy spec_config.h.win32 spec_config.h
     <ClCompile Include="..\..\..\src\bin\dhcp6\dhcp6_srv.cc" />
     <ClCompile Include="..\..\..\src\bin\dhcp6\iface_mgr.cc" />
     <ClCompile Include="..\..\..\src\bin\dhcp6\main.cc" />
-    <ClCompile Include="..\..\..\src\bin\dhcp6\pkt6.cc" />
     <ClCompile Include="..\..\getopt.cc" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
diff --git a/win32build/VS2010/b10-dhcp6/b10-dhcp6.vcxproj.filters b/win32build/VS2010/b10-dhcp6/b10-dhcp6.vcxproj.filters
index 6972f39..d51f865 100755
--- a/win32build/VS2010/b10-dhcp6/b10-dhcp6.vcxproj.filters
+++ b/win32build/VS2010/b10-dhcp6/b10-dhcp6.vcxproj.filters
@@ -24,12 +24,6 @@
     <ClInclude Include="..\..\getopt.h">
       <Filter>Header Files</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\..\src\bin\dhcp6\dhcp6.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\..\src\bin\dhcp6\pkt6.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\..\src\bin\dhcp6\spec_config.h">
       <Filter>Header Files</Filter>
     </ClInclude>
@@ -47,8 +41,5 @@
     <ClCompile Include="..\..\getopt.cc">
       <Filter>Source Files</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\..\src\bin\dhcp6\pkt6.cc">
-      <Filter>Source Files</Filter>
-    </ClCompile>
   </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/win32build/VS2010/b10-dhcp6_tests/b10-dhcp6_tests.vcxproj b/win32build/VS2010/b10-dhcp6_tests/b10-dhcp6_tests.vcxproj
index 73c04d0..bffa09e 100755
--- a/win32build/VS2010/b10-dhcp6_tests/b10-dhcp6_tests.vcxproj
+++ b/win32build/VS2010/b10-dhcp6_tests/b10-dhcp6_tests.vcxproj
@@ -88,16 +88,13 @@
   <ItemGroup>
     <ClInclude Include="..\..\..\src\bin\dhcp6\dhcp6_srv.h" />
     <ClInclude Include="..\..\..\src\bin\dhcp6\iface_mgr.h" />
-    <ClInclude Include="..\..\..\src\bin\dhcp6\pkt6.h" />
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\..\src\bin\dhcp6\dhcp6_srv.cc" />
     <ClCompile Include="..\..\..\src\bin\dhcp6\iface_mgr.cc" />
-    <ClCompile Include="..\..\..\src\bin\dhcp6\pkt6.cc" />
     <ClCompile Include="..\..\..\src\bin\dhcp6\tests\dhcp6_srv_unittest.cc" />
     <ClCompile Include="..\..\..\src\bin\dhcp6\tests\dhcp6_unittests.cc" />
     <ClCompile Include="..\..\..\src\bin\dhcp6\tests\iface_mgr_unittest.cc" />
-    <ClCompile Include="..\..\..\src\bin\dhcp6\tests\pkt6_unittest.cc" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
diff --git a/win32build/VS2010/b10-dhcp6_tests/b10-dhcp6_tests.vcxproj.filters b/win32build/VS2010/b10-dhcp6_tests/b10-dhcp6_tests.vcxproj.filters
index 774c898..e08588f 100755
--- a/win32build/VS2010/b10-dhcp6_tests/b10-dhcp6_tests.vcxproj.filters
+++ b/win32build/VS2010/b10-dhcp6_tests/b10-dhcp6_tests.vcxproj.filters
@@ -21,9 +21,6 @@
     <ClInclude Include="..\..\..\src\bin\dhcp6\iface_mgr.h">
       <Filter>Header Files</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\..\src\bin\dhcp6\pkt6.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\..\src\bin\dhcp6\dhcp6_srv.cc">
@@ -41,11 +38,5 @@
     <ClCompile Include="..\..\..\src\bin\dhcp6\tests\iface_mgr_unittest.cc">
       <Filter>Source Files</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\..\src\bin\dhcp6\tests\pkt6_unittest.cc">
-      <Filter>Source Files</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\..\src\bin\dhcp6\pkt6.cc">
-      <Filter>Source Files</Filter>
-    </ClCompile>
   </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/win32build/VS2010/libdhcp/libdhcp.vcxproj b/win32build/VS2010/libdhcp/libdhcp.vcxproj
index dff25f4..724b380 100755
--- a/win32build/VS2010/libdhcp/libdhcp.vcxproj
+++ b/win32build/VS2010/libdhcp/libdhcp.vcxproj
@@ -11,12 +11,14 @@
     </ProjectConfiguration>
   </ItemGroup>
   <ItemGroup>
+    <ClInclude Include="..\..\..\src\lib\dhcp\dhcp4.h" />
     <ClInclude Include="..\..\..\src\lib\dhcp\dhcp6.h" />
     <ClInclude Include="..\..\..\src\lib\dhcp\libdhcp.h" />
     <ClInclude Include="..\..\..\src\lib\dhcp\option.h" />
     <ClInclude Include="..\..\..\src\lib\dhcp\option6_addrlst.h" />
     <ClInclude Include="..\..\..\src\lib\dhcp\option6_ia.h" />
     <ClInclude Include="..\..\..\src\lib\dhcp\option6_iaaddr.h" />
+    <ClInclude Include="..\..\..\src\lib\dhcp\pkt4.h" />
     <ClInclude Include="..\..\..\src\lib\dhcp\pkt6.h" />
   </ItemGroup>
   <ItemGroup>
@@ -25,6 +27,7 @@
     <ClCompile Include="..\..\..\src\lib\dhcp\option6_addrlst.cc" />
     <ClCompile Include="..\..\..\src\lib\dhcp\option6_ia.cc" />
     <ClCompile Include="..\..\..\src\lib\dhcp\option6_iaaddr.cc" />
+    <ClCompile Include="..\..\..\src\lib\dhcp\pkt4.cc" />
     <ClCompile Include="..\..\..\src\lib\dhcp\pkt6.cc" />
   </ItemGroup>
   <PropertyGroup Label="Globals">
diff --git a/win32build/VS2010/libdhcp/libdhcp.vcxproj.filters b/win32build/VS2010/libdhcp/libdhcp.vcxproj.filters
index 7f69742..40c2c6e 100755
--- a/win32build/VS2010/libdhcp/libdhcp.vcxproj.filters
+++ b/win32build/VS2010/libdhcp/libdhcp.vcxproj.filters
@@ -36,6 +36,12 @@
     <ClInclude Include="..\..\..\src\lib\dhcp\pkt6.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\..\src\lib\dhcp\dhcp4.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\..\src\lib\dhcp\pkt4.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\..\src\lib\dhcp\libdhcp.cc">
@@ -56,5 +62,8 @@
     <ClCompile Include="..\..\..\src\lib\dhcp\pkt6.cc">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\..\src\lib\dhcp\pkt4.cc">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/win32build/VS2010/libdhcp_tests/libdhcp_tests.vcxproj b/win32build/VS2010/libdhcp_tests/libdhcp_tests.vcxproj
index 39cbfdc..4188c91 100755
--- a/win32build/VS2010/libdhcp_tests/libdhcp_tests.vcxproj
+++ b/win32build/VS2010/libdhcp_tests/libdhcp_tests.vcxproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup Label="ProjectConfigurations">
     <ProjectConfiguration Include="Debug|Win32">
@@ -91,6 +91,7 @@
     <ClCompile Include="..\..\..\src\lib\dhcp\tests\option6_iaaddr_unittest.cc" />
     <ClCompile Include="..\..\..\src\lib\dhcp\tests\option6_ia_unittest.cc" />
     <ClCompile Include="..\..\..\src\lib\dhcp\tests\option_unittest.cc" />
+    <ClCompile Include="..\..\..\src\lib\dhcp\tests\pkt4_unittest.cc" />
     <ClCompile Include="..\..\..\src\lib\dhcp\tests\pkt6_unittest.cc" />
     <ClCompile Include="..\..\..\src\lib\dhcp\tests\run_unittests.cc" />
   </ItemGroup>
diff --git a/win32build/VS2010/libdhcp_tests/libdhcp_tests.vcxproj.filters b/win32build/VS2010/libdhcp_tests/libdhcp_tests.vcxproj.filters
index 060fbe5..392181b 100755
--- a/win32build/VS2010/libdhcp_tests/libdhcp_tests.vcxproj.filters
+++ b/win32build/VS2010/libdhcp_tests/libdhcp_tests.vcxproj.filters
@@ -36,5 +36,8 @@
     <ClCompile Include="..\..\..\src\lib\dhcp\tests\run_unittests.cc">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\..\src\lib\dhcp\tests\pkt4_unittest.cc">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/win32build/VS2010/libutil_tests/libutil_tests.vcxproj b/win32build/VS2010/libutil_tests/libutil_tests.vcxproj
index 5cba41f..b1ea84f 100755
--- a/win32build/VS2010/libutil_tests/libutil_tests.vcxproj
+++ b/win32build/VS2010/libutil_tests/libutil_tests.vcxproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup Label="ProjectConfigurations">
     <ProjectConfiguration Include="Debug|Win32">
@@ -60,7 +60,7 @@
       <SubSystem>Console</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <OutputFile>$(OutDir)run_unittests$(TargetExt)</OutputFile>
-      <AdditionalDependencies>libexceptions.lib;libutil.lib;libutil_io.lib;libutil_unittests.lib;gtestd.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>libexceptions.lib;libutil.lib;libutil_io.lib;libutil_unittests.lib;gtestd.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <AdditionalLibraryDirectories>..\libexceptions\$(Configuration);..\libutil\$(Configuration);..\libutil_io\$(Configuration);..\libutil_unittests\$(Configuration);..\..\..\..\gtest\md10\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
     </Link>
   </ItemDefinitionGroup>
@@ -81,7 +81,7 @@
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
       <OutputFile>$(OutDir)run_unittests$(TargetExt)</OutputFile>
-      <AdditionalDependencies>libexceptions.lib;libutil.lib;libutil_io.lib;libutil_unittests.lib;gtest.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>libexceptions.lib;libutil.lib;libutil_io.lib;libutil_unittests.lib;gtest.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <AdditionalLibraryDirectories>..\libexceptions\$(Configuration);..\libutil\$(Configuration);..\libutil_io\$(Configuration);..\libutil_unittests\$(Configuration);..\..\..\..\gtest\md10\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
     </Link>
   </ItemDefinitionGroup>




More information about the bind10-changes mailing list