BIND 10 trac917, updated. ecf9f48f4b4c3beaf97ae0e83c11f4547f024734 [917] cleanup

BIND 10 source code commits bind10-changes at lists.isc.org
Fri Oct 28 07:56:11 UTC 2011


The branch, trac917 has been updated
  discards  5854038d674dab1ca2fc3bc18c4cb16126c0a3f8 (commit)
  discards  c3b7f88cc1a608b6de8a521134bba6c81d2d2ffc (commit)
  discards  9d18d4545d84c99924e0ff19cd976de919b94132 (commit)
  discards  e0959b404650b0564d42b2f8eb492810acf57215 (commit)
  discards  58f111274eeceb60f572a604404cd4c3ceda171d (commit)
  discards  a458d69d94b2a7506395e7a24e5c2a9146791553 (commit)
  discards  70c6c3e923d4fb68dd8b7506cfaf41a8042a9cea (commit)
       via  ecf9f48f4b4c3beaf97ae0e83c11f4547f024734 (commit)
       via  4d39e13d7f5ae5c30277f602f669f0421e2bf05c (commit)
       via  3bf84d5c678f9f86df6382cf30e694404e2f77cb (commit)
       via  12a6217c59bf48ead2e11aaaedb774af7a618701 (commit)
       via  cb57c9fcaa897752dd7599dcc15d647fb880285f (commit)
       via  1294219279910a89d4a99e6292cea8e13a4c301e (commit)
       via  61dd61b8f259b0938646fa2539fe928608a0fbad (commit)
       via  f1306bd835659173f3fffcfbe1bf8971dc62efd9 (commit)
       via  7cc8a7d6c32472021b34e43d43a288cfa263f007 (commit)
       via  0a7bd2339e604fb26b7bd94bd8c548b188d60adc (commit)
       via  a72886e643864bb6f86ab47b115a55e0c7f7fcad (commit)
       via  6442c07428bf7b8abeb73c4b6a7729ecd4b853c5 (commit)
       via  4f6c6441787be0a145917ae8935b70bb89f27b7a (commit)
       via  e13d28918a391060d9c1f286d19308cb10975cd9 (commit)
       via  5b7e0424c3d826d5c7a9a247d63c7d716b08e470 (commit)
       via  1e9bb55e135af5a0d8dc353a2ffde7c5b247f92a (commit)
       via  738b11db9f13c00f5a9ddfb3ab9996fbf85c42d8 (commit)
       via  1fc79b932eaa88be33c224e4eea3fc58907e98bd (commit)
       via  8d36a0115d1b3051b88c9f9687103fa2427e749c (commit)
       via  65bd895a45fd28c43f748f07aad5fb9321fa6a0a (commit)
       via  a1e64504a4d039b4c7f7434451f169c475a1a35a (commit)
       via  9e6570256e27c28b20a17fc34de5689ee4685091 (commit)
       via  3db6583d93c42b3cb01ac5619d59d19645bd60bf (commit)
       via  1d43b46ab58077daaaf5cae3c6aa3e0eb76eb5d8 (commit)
       via  784f0a8916465d6ec9c47db9f7f3af0fbd564bed (commit)
       via  5cb4d41cf68ac18fb5a5db68046e3d06b6552e20 (commit)
       via  b5d072cfe24be6ad1636dfdb50405ff32473a413 (commit)
       via  6060fcf2a39711ba5d842a311ea03a47054f2ffc (commit)
       via  cf1ce254c246be39069e7e7277e1c506e1b239a0 (commit)
       via  44147cd660a85ea909f54e496ae3c8ad1ed583fa (commit)
       via  ea78ae80aa517556f7c5ac722f324baaf422f08e (commit)
       via  ba1568e6482268cea9dbf7f980a17423133c65eb (commit)
       via  bad7607f03104c81cf7224f6fd71db009219ad51 (commit)
       via  56d5c4a16e39b3aa6c1786e1ceebb8550c0429e3 (commit)
       via  96e22f4284307b1d5f15e03837559711bb4f580c (commit)
       via  b1380ef8f0534540970ee93a24f955db89891e05 (commit)
       via  f7c85718e562f5cbbd6eafeb2549a21f358afba8 (commit)
       via  f08602b2e2a311b9662e65c36c56f9f38461c194 (commit)
       via  6e68b97b050e40e073f736d84b62b3e193dd870a (commit)
       via  78252609c39a14fb24a879c74108705c7cffed49 (commit)
       via  ad134a3c515577b5fbff5d05733bdf8d4265fb45 (commit)
       via  3c5fd61a4a294c75b6e90dd5a78aec980c387432 (commit)
       via  4e4e22281cd1c9dbec42d7c0a2842c92a69b1e8e (commit)
       via  d3fbd47b4323cbd12fdf3c07af74a6dd7514492a (commit)
       via  6e65029d717a44a8250ca6d7e9b57c2927ea6d11 (commit)
       via  46e8133ce6aced930a85be2536b5cf1e493e9ab2 (commit)
       via  431973bb16c68442614aac015f38e44ed39e960a (commit)
       via  3872fd58983155a69817da3744db56ab665e9707 (commit)
       via  a670d589923976af730c4387c7c4707552efad0d (commit)
       via  edffc4851f7373294b6486a5d6171f406f7e1de6 (commit)
       via  299473702fedd1cab6967683ad7172b88c35f353 (commit)
       via  1814e37c1b61225bdb05ea81c3fcc6ea3320e8d9 (commit)
       via  b3daacd1da0cefe8adfef38f8d324db55a7f2cc1 (commit)
       via  499668edac6fd5929dc43391e3281046d0512388 (commit)
       via  c30cda06f4b0ce0dfeb99badab779b72175000f9 (commit)
       via  0a6bcde01f641bf024e9179d2e753d7d2ef4df41 (commit)
       via  587102b55b9cee15faf4fd9d9c4c3ad81c88666d (commit)
       via  3a86448c1c0a34fd3d27b3395167a63d5e59e733 (commit)
       via  03265efc1c833609c21c4e6d2daf8227d20f68b9 (commit)
       via  b341cd21229db04e564fc8da0398e3ddfe883e46 (commit)
       via  7714dea5be87f0708ab858bf369390128d2cd2be (commit)
       via  6d197660434d715c4e57c6acf792ffdb0528c147 (commit)
       via  d8ac168592885baab953cbe6e416afc6b72d9e7d (commit)
       via  6ecf994e0d3580064d6c8a490dfba1a02e9930ee (commit)
       via  1b328591b9bd5f366bc6e205aad0cde28e447442 (commit)
       via  61488d93393fff47ea8cce1c2b41ac004802caaf (commit)
       via  0a54d27ad889cc8931bc5a0b6549325c4fb3e45f (commit)
       via  6a54cfb961dae9f44120ae2da4bd4c3693f9ea49 (commit)
       via  81c031de6abed68c9fb4a89b2a71474f36488b9b (commit)
       via  ae199c79e42520e8e521668c6f9435796ca92aa3 (commit)
       via  541ea699442bece13605d34e182ff89bca384a43 (commit)
       via  f546d730bb772a8a4b9ea1737ed63d888755673a (commit)
       via  9895253cc3a1cb1431a04a4b6d8e9dc82a3e3bc8 (commit)
       via  7e8b9cdec8bb9e79069a4534d896a9a4061c3b88 (commit)
       via  a0cf3955fceb4d810997dfefed7abbf57e4ee1cf (commit)
       via  1032195dcf567dcdd1b500ebf177c415ff9aeba3 (commit)
       via  ad24f1d258542fecf0e83187f6ed5cc8cdce8ca2 (commit)
       via  9ebdb058e61cae1dda642fcb00ced7b7554b44fb (commit)
       via  b88c94b7119650217408d800847dfbbbcea7306c (commit)
       via  419b9d48771946a1b0b75b7412cd2da3e7f81a5a (commit)
       via  1f311bbc22d17a747ad394ffd00cb130f2999ede (commit)
       via  fb49d74df87f9e87a7d14b16a3a84b31976a92fe (commit)
       via  1817f1e8fd4a3635b8b5e0d581f6a2aa61b5e955 (commit)
       via  68ee3818bcbecebf3e6789e81ea79d551a4ff3e8 (commit)
       via  ca1d0935b9d65aa1f26dbe4f0cfc0c4db7701900 (commit)
       via  1561a91d494d02fbddbac1023b2c84367cb1887d (commit)
       via  1a4da963a4b1378332c74feb96ff8556d11bbbc8 (commit)
       via  acab4a018b927cf5887b6de8135dbae0d2dcdbff (commit)
       via  84ded89c2309b41f3d7656ffa0112021436ec4cd (commit)
       via  5bb1a0ebbed603d81656d5e87196191f1b00aad5 (commit)
       via  fd5db1f7aa6f49091b4e66193b0379679eede4c4 (commit)
       via  190d4380c54493561eda99d66739f31e515f8e4e (commit)
       via  2a08eafed9264b790ada134bdee7ee02c995c50e (commit)
       via  2d84595398e0a29bd042b848e986e8aa7bc40f75 (commit)
       via  021f3f24fcd053a92b6ee305b984f1a6a550cebc (commit)
       via  937b5a6f47d4506193de9a3ed77adcef2cb1fd35 (commit)
       via  c110fcc95f61b07871fd6fe7e24a495a3f49b89c (commit)
       via  58e72cb159391aa0c7832d08ddb0df361514918e (commit)
       via  26f4192ca701bafca9460e994c61715916091e37 (commit)
       via  86b3f90af4f0f643e44fd3f7cfd11d89a42e4ebd (commit)
       via  67ea6de047d4dbd63c25fe7f03f5d5cc2452ad7d (commit)
       via  ce532896000ddcc026045a08ddb9ae2b96ae7ba9 (commit)
       via  ddf232dc82203a777e0a59aa9b8252aaf5117548 (commit)
       via  41c8d6f1170f06e1da8908666444c88b08906f1e (commit)
       via  14909927e06d884129baf8baf7fd8760b2dea196 (commit)
       via  4a345eca2184ebccec3a17902056d03f5d00e540 (commit)
       via  6217a55056c1e2e6fa8d82357d86b218de43ded4 (commit)
       via  32012c8148dbf25fea0a490bd8453fcfb3854cbb (commit)
       via  01bc2a7ff47131144717e923108f71eda283475b (commit)
       via  cee641fd3d12341d6bfce5a6fbd913e3aebc1e8e (commit)
       via  ed787b2156b0a7a88ace941447783c53991a254c (commit)
       via  621c92d9a19379bb43e98c821183be1aa4d97c7b (commit)
       via  e9c6c3cf86e3b1b02c64bf567f0c20f6c1e2f589 (commit)
       via  004e1238d580d601f7fd8847ff1c4933de465942 (commit)
       via  5da6a0f0e8829140999c69bfb551a305c6bf0257 (commit)
       via  25ce3ceaf98ed34ad3a4ebe3cac901c0b6e15a97 (commit)
       via  5756a9c761748b960b974f422963fbf8e5498378 (commit)
       via  566e635f4f2647a82457acb9c047d890f4cb459b (commit)
       via  76f58b2ff1ebc572cef465f5be1445e08e4bf0fb (commit)
       via  f89dbf486bbbd41c3f4e85c15d2cda91706a37ba (commit)
       via  a91fbbe9905680873c4f0acf5cff1d712aa68831 (commit)
       via  86cab473cc0113b0f83755c14db4035bae675065 (commit)
       via  ca22c5ab2322ab7620e4b84589da6761fdaa3b62 (commit)
       via  838acbebc584fee662143c303b7a110563f4e0de (commit)
       via  c5d29c73bcd554111ada4dec49f61cfde497cb6c (commit)
       via  4ec7a8d9ab678f28abf3b37d40acdf159344cf0f (commit)
       via  92b2aa9c962e9ca1cec80f44bee713afa1ac53f3 (commit)
       via  6b9d28f7602143bb85fcfcefbaa35cde95fdbde3 (commit)
       via  223b19a30e4897c7281bb40c9f366a01c8f449ca (commit)
       via  bfea61834be28bc3c2413afb586971fc04056a41 (commit)
       via  620072324ac5f111f8fd40a4ba6d10879c44e211 (commit)
       via  522d27a63d1ff318173e7e4aeb6c1265aba93ca5 (commit)
       via  c4291199d0ebab1cdb49b80101239b9582c13148 (commit)
       via  9d9680719eb0ce32ea039386bfe767dfa41d1968 (commit)
       via  2f39435c981e3cb14d2c4e9551af93fbbfc28109 (commit)
       via  2276752655f67044fb6ae8f7e14e9ba5f6ee6638 (commit)
       via  54ba29f03a62c84ee9cbf1c92db74b57327a1868 (commit)
       via  6433a51cb6e72309eb027411ea4fa98adb97a7f8 (commit)
       via  4865dbd45b6f94b20b562b11224754313e74bf25 (commit)
       via  c7b8783766258a4321622b7d7e2bb02a647d0864 (commit)
       via  b8d8ea4cfb87fd12abe113cf63edbae4a342e6c1 (commit)
       via  6ce36056a14fad339ffc6528343aadf12065ca44 (commit)
       via  8dbb407ba4adc1bbaf061b5680bafd35c778cd90 (commit)
       via  f9ff938c75816df97f318a839f01be3f01c93f2a (commit)
       via  a69020025379d5430fff394465348aa430533458 (commit)
       via  af27ec87f09d82918b96c9dd6d236b4e39989f7f (commit)
       via  b47533e918cb5b0c2befe7b0da315819b009c47f (commit)
       via  f4c7155d41cb008a1a180e567e142ce096a21b88 (commit)
       via  d647a4589362d2b6efee86e58c9fb38e7084deb4 (commit)
       via  ad26a33ce7624ea2a9b8685f1255db0c1f80bfa8 (commit)
       via  5f9a52abbd9f785ab878e71907c8b6dfa587fab1 (commit)
       via  8b024ff407a6987a4c7e55f51b9d08c1c9a185d3 (commit)
       via  c38fc5257ebbd0cd444e6b9cedb466b31df66cea (commit)
       via  044381e03b7f178c7c322861960b79c8a27bb4b1 (commit)
       via  f2b5473fc2f2dfa13485fe9822e84fadd69ac950 (commit)
       via  0cfe2c51b17627d777cec9c33f9652b61f14427c (commit)
       via  0b6ac7ed34c708e6e92c41dc28bc8589864cecd3 (commit)
       via  c12ca1170ad094e0450efeb462328ec6b6ec7e1f (commit)
       via  4cfd27849ef6f2e99ee346763695fbc64742d783 (commit)
       via  b126cf8dbf225ff5b12c9a7b6a241d80babf8a42 (commit)
       via  03753df452d1871af6f82824286cc07ab40493f9 (commit)
       via  6c2de9d212bbb3193304a1ae4fd54ca9137262ff (commit)
       via  a95e95882763d10fac105a93826d79d5ebe4a449 (commit)
       via  19722a540a20a2dc5370df4d8f1f0bb326175001 (commit)
       via  8724a537b4f7d9d93bf06c2df860ea83f247461b (commit)
       via  f5b0e46b8cc66dc5aeef4df4d4e938ab0f4cd3da (commit)
       via  5f5d0ee169a33ed2edf6d80ed1c7f557b993eaf5 (commit)
       via  a1363e4b0e747cf0814e6f6575311aba9aac1ef2 (commit)
       via  8028d7abe44464aacaf7e8cb82a5a23d39fb4489 (commit)
       via  0fc138613824f16378ba2b5462886cb2d97a318a (commit)
       via  4a843f9058e625685cf2338fe89c9a89af3c1777 (commit)
       via  5275b7b65e2ce2acf92528868c9859dd4407c4c1 (commit)
       via  44f582bd7d16b11259cda469de5f56bad9768059 (commit)
       via  48b88725698f7e4979f577c0e86689160aa758c5 (commit)
       via  a46eed49d48d22fcf83eeed363b559e4b60bd840 (commit)
       via  1afd287718c25b673beb31903eb80bfc9f268d87 (commit)
       via  a4766a155b7821c9b7eb5e126988007a95118dc9 (commit)
       via  f1a85d0c97636ce15d830ef56c3440298f3773a7 (commit)
       via  419fe34aec67a7bf30991f7df7b568133d8eb541 (commit)
       via  96d5830820c86c06517fc3f4c0f1c95c478237db (commit)
       via  5ab87bf933008827bc39aed0cd4e6bf4cd71a062 (commit)

This update added new revisions after undoing existing revisions.  That is
to say, the old revision is not a strict subset of the new revision.  This
situation occurs when you --force push a change and generate a repository
containing something like this:

 * -- * -- B -- O -- O -- O (5854038d674dab1ca2fc3bc18c4cb16126c0a3f8)
            \
             N -- N -- N (ecf9f48f4b4c3beaf97ae0e83c11f4547f024734)

When this happens we assume that you've already had alert emails for all
of the O revisions, and so we here report only the revisions in the N
branch from the common base, B.

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 ecf9f48f4b4c3beaf97ae0e83c11f4547f024734
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Oct 28 16:54:53 2011 +0900

    [917] cleanup

commit 4d39e13d7f5ae5c30277f602f669f0421e2bf05c
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Oct 28 14:43:28 2011 +0900

    [917] fix the function check_XSL_URL_PATH and add tests by module and by item

commit 3bf84d5c678f9f86df6382cf30e694404e2f77cb
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Wed Oct 19 21:20:06 2011 +0900

    [917] implement stats_spec2xsl function and modify the xsl template file and unittest

commit 12a6217c59bf48ead2e11aaaedb774af7a618701
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Wed Oct 19 16:04:47 2011 +0900

    [917] fix assertion failures due to changes of the spec file of the mock auth

commit cb57c9fcaa897752dd7599dcc15d647fb880285f
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Wed Oct 19 15:52:48 2011 +0900

    [917] implement stats_spec2xsd function and modify the xsd template file

commit 1294219279910a89d4a99e6292cea8e13a4c301e
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Tue Oct 18 19:15:12 2011 +0900

    [917] implement stats_data2xml and modify definition of per-zone count

commit 61dd61b8f259b0938646fa2539fe928608a0fbad
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Sun Oct 16 13:33:17 2011 +0900

    Revert "[917] split XXX_URL_PATH into BASE_URL_PATH and XXX_URL_PATH"
    
    This reverts commit a458d69d94b2a7506395e7a24e5c2a9146791553.

commit f1306bd835659173f3fffcfbe1bf8971dc62efd9
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Oct 14 21:04:06 2011 +0900

    [917] split XXX_URL_PATH into BASE_URL_PATH and XXX_URL_PATH

commit 7cc8a7d6c32472021b34e43d43a288cfa263f007
Author: Naoki Kambe <kambe at jprs.co.jp>
Date:   Fri Oct 14 16:49:07 2011 +0900

    [917] implement per-zone queried counts in the Mock of Auth in Stats

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

Summary of changes:
 ChangeLog                                          |   56 +
 configure.ac                                       |   26 +-
 doc/Doxyfile                                       |    2 +-
 doc/guide/Makefile.am                              |   10 +-
 src/bin/auth/auth_log.h                            |    8 +-
 src/bin/auth/auth_messages.mes                     |    1 -
 src/bin/auth/common.cc                             |    9 +-
 src/bin/auth/query.cc                              |  115 ++-
 src/bin/auth/query.h                               |   43 +-
 src/bin/auth/spec_config.h.pre.in                  |   32 +-
 src/bin/auth/tests/Makefile.am                     |    2 +-
 src/bin/auth/tests/query_unittest.cc               |  269 +++-
 src/bin/bind10/bind10_src.py.in                    |   26 +-
 src/bin/bind10/tests/bind10_test.py.in             |   13 +
 src/bin/cmdctl/cmdctl.py.in                        |   11 +-
 src/bin/dhcp6/Makefile.am                          |   30 +-
 src/bin/dhcp6/b10-dhcp6.8                          |   29 +-
 src/bin/dhcp6/b10-dhcp6.xml                        |   98 ++
 src/bin/dhcp6/dhcp6.h                              |  184 ---
 src/bin/dhcp6/dhcp6_srv.cc                         |  202 +++-
 src/bin/dhcp6/dhcp6_srv.h                          |  150 ++-
 src/bin/dhcp6/iface_mgr.cc                         |  127 +--
 src/bin/dhcp6/iface_mgr.h                          |  282 +++-
 src/bin/dhcp6/main.cc                              |   10 +-
 src/bin/dhcp6/pkt6.cc                              |   46 -
 src/bin/dhcp6/pkt6.h                               |   62 -
 src/bin/dhcp6/tests/Makefile.am                    |    7 +-
 src/bin/dhcp6/tests/dhcp6_srv_unittest.cc          |  107 ++-
 src/bin/dhcp6/tests/iface_mgr_unittest.cc          |  179 ++-
 src/bin/dhcp6/tests/pkt6_unittest.cc               |   44 -
 src/bin/msgq/Makefile.am                           |    2 +-
 src/bin/msgq/msgq.py.in                            |   33 +-
 src/bin/resolver/resolver.cc                       |    2 +-
 src/bin/resolver/resolver_log.h                    |   12 +-
 src/bin/resolver/tests/Makefile.am                 |    2 +-
 src/bin/sockcreator/tests/Makefile.am              |    2 +-
 src/bin/stats/stats.py.in                          |    5 +-
 src/bin/stats/stats_httpd.py.in                    |    7 +-
 src/bin/stats/tests/Makefile.am                    |    3 +-
 src/bin/stats/tests/b10-stats-httpd_test.py        |   89 +-
 src/bin/stats/tests/isc/log_messages/Makefile.am   |    7 -
 src/bin/stats/tests/isc/log_messages/__init__.py   |   18 -
 .../tests/isc/log_messages/stats_httpd_messages.py |   16 -
 .../stats/tests/isc/log_messages/stats_messages.py |   16 -
 src/bin/stats/tests/test_utils.py                  |   13 +-
 src/bin/xfrin/tests/xfrin_test.py                  |  121 ++-
 src/bin/xfrin/xfrin.py.in                          |  157 ++-
 src/bin/xfrin/xfrin_messages.mes                   |   15 +
 src/bin/xfrout/tests/xfrout_test.py.in             |    2 +-
 src/bin/xfrout/xfrout.py.in                        |    2 +-
 src/bin/zonemgr/zonemgr.py.in                      |    8 +-
 src/lib/Makefile.am                                |    2 +-
 src/lib/acl/tests/Makefile.am                      |    2 +-
 src/lib/asiodns/io_fetch.cc                        |   12 +-
 src/lib/asiodns/tests/Makefile.am                  |    2 +-
 src/lib/asiolink/io_address.cc                     |   20 +-
 src/lib/asiolink/io_address.h                      |   16 +
 src/lib/asiolink/tests/Makefile.am                 |    2 +-
 src/lib/asiolink/tests/io_address_unittest.cc      |   20 +
 src/lib/bench/Makefile.am                          |    2 +-
 src/lib/bench/tests/Makefile.am                    |    2 +-
 src/lib/cache/logger.h                             |   17 +-
 src/lib/cache/tests/Makefile.am                    |    2 +-
 src/lib/cc/logger.h                                |   23 +-
 src/lib/cc/tests/Makefile.am                       |    2 +-
 src/lib/config/config_log.h                        |   11 +-
 src/lib/config/tests/Makefile.am                   |    4 +-
 src/lib/cryptolink/tests/Makefile.am               |    2 +-
 src/lib/datasrc/database.cc                        |   15 +-
 src/lib/datasrc/logger.h                           |   16 +-
 src/lib/datasrc/tests/Makefile.am                  |    2 +-
 src/lib/datasrc/tests/database_unittest.cc         |  137 ++-
 src/lib/datasrc/zone.h                             |   93 +-
 src/lib/dhcp/Makefile.am                           |   26 +
 src/lib/dhcp/README                                |   11 +
 src/lib/dhcp/dhcp4.h                               |  191 +++
 src/lib/dhcp/dhcp6.h                               |  184 +++
 src/lib/dhcp/libdhcp.cc                            |  130 ++
 src/lib/dhcp/libdhcp.h                             |   83 ++
 src/lib/dhcp/option.cc                             |  260 ++++
 src/lib/dhcp/option.h                              |  273 ++++
 src/lib/dhcp/option6_addrlst.cc                    |  134 ++
 src/lib/dhcp/option6_addrlst.h                     |  127 ++
 src/lib/dhcp/option6_ia.cc                         |  136 ++
 src/lib/dhcp/option6_ia.h                          |  137 ++
 src/lib/dhcp/option6_iaaddr.cc                     |  132 ++
 src/lib/dhcp/option6_iaaddr.h                      |  146 ++
 src/lib/dhcp/pkt4.cc                               |  189 +++
 src/lib/dhcp/pkt4.h                                |  380 +++++
 src/lib/dhcp/pkt6.cc                               |  225 +++
 src/lib/dhcp/pkt6.h                                |  234 +++
 src/lib/dhcp/tests/Makefile.am                     |   43 +
 src/lib/dhcp/tests/libdhcp_unittest.cc             |  137 ++
 src/lib/dhcp/tests/option6_addrlst_unittest.cc     |  231 +++
 src/lib/dhcp/tests/option6_ia_unittest.cc          |  264 ++++
 src/lib/dhcp/tests/option6_iaaddr_unittest.cc      |  103 ++
 src/lib/dhcp/tests/option_unittest.cc              |  279 ++++
 src/lib/dhcp/tests/pkt4_unittest.cc                |  432 ++++++
 src/lib/dhcp/tests/pkt6_unittest.cc                |  207 +++
 src/lib/dhcp/tests/run_unittests.cc                |   27 +
 src/lib/dns/python/message_python.cc               |  113 +-
 src/lib/dns/python/rrset_python.cc                 |   33 +-
 src/lib/dns/python/tests/message_python_test.py    |   17 +-
 src/lib/dns/python/tests/rrset_python_test.py      |    7 +
 src/lib/dns/rdata/generic/nsec_47.cc               |    5 +
 src/lib/dns/rdata/generic/nsec_47.h                |   10 +
 src/lib/dns/tests/Makefile.am                      |    2 +-
 src/lib/dns/tests/rdata_nsec_unittest.cc           |    6 +
 src/lib/exceptions/tests/Makefile.am               |    2 +-
 src/lib/log/Makefile.am                            |    3 +-
 src/lib/log/README                                 |    5 +
 src/lib/log/log_dbglevels.h                        |   93 ++
 src/lib/log/macros.h                               |    1 +
 src/lib/log/tests/Makefile.am                      |    6 +-
 src/lib/nsas/nsas_log.h                            |    6 +-
 src/lib/nsas/tests/Makefile.am                     |    2 +-
 src/lib/python/isc/bind10/sockcreator.py           |    3 +-
 src/lib/python/isc/config/ccsession.py             |   12 +-
 src/lib/python/isc/datasrc/datasrc.cc              |    4 +
 src/lib/python/isc/datasrc/finder_inc.cc           |   57 +-
 src/lib/python/isc/datasrc/finder_python.cc        |   16 +-
 src/lib/python/isc/datasrc/iterator_python.cc      |    6 +-
 src/lib/python/isc/datasrc/tests/datasrc_test.py   |   42 +
 src/lib/python/isc/datasrc/updater_python.cc       |   15 +-
 src/lib/python/isc/log/log.cc                      |   37 +-
 src/lib/python/isc/log/tests/log_test.py           |   10 +
 src/lib/resolve/resolve_log.h                      |    8 +-
 src/lib/resolve/tests/Makefile.am                  |    2 +-
 src/lib/server_common/logger.h                     |   11 +-
 src/lib/server_common/tests/Makefile.am            |    2 +-
 src/lib/testutils/Makefile.am                      |    2 +-
 src/lib/testutils/dnsmessage_test.h                |   28 +-
 src/lib/util/io_utilities.h                        |   45 +-
 src/lib/util/pyunittests/Makefile.am               |    2 +-
 src/lib/util/tests/Makefile.am                     |    2 +-
 src/lib/util/tests/io_utilities_unittest.cc        |   46 +
 src/lib/util/unittests/Makefile.am                 |    2 +-
 tests/system/README                                |   53 +-
 tests/system/cleanall.sh                           |    2 +-
 tests/system/common/rndc.conf                      |   25 +
 tests/system/common/rndc.key                       |   22 +
 tests/system/conf.sh.in                            |   45 +-
 tests/system/ixfr/README                           |   86 ++
 tests/system/ixfr/b10-config.db.in                 |   23 +
 tests/system/ixfr/clean_ns.sh                      |   28 +
 tests/system/ixfr/common_tests.sh.in               |   78 +
 tests/system/ixfr/db.example.common                | 1556 ++++++++++++++++++++
 tests/system/ixfr/db.example.n0.in                 |   29 +
 tests/system/ixfr/db.example.n2.in                 |   28 +
 tests/system/ixfr/db.example.n2.refresh.in         |   28 +
 tests/system/ixfr/db.example.n4.in                 |   31 +
 tests/system/ixfr/db.example.n6.in                 |   29 +
 tests/system/ixfr/in-1/clean.sh                    |    1 +
 tests/system/ixfr/in-1/ns1/README                  |    3 +
 tests/system/ixfr/in-1/nsx2/README                 |    3 +
 tests/system/ixfr/in-1/setup.sh.in                 |   30 +
 tests/system/ixfr/in-1/tests.sh                    |   37 +
 tests/system/ixfr/in-2/clean.sh                    |    1 +
 tests/system/ixfr/in-2/ns1/README                  |    3 +
 tests/system/ixfr/in-2/nsx2/README                 |    3 +
 tests/system/ixfr/in-2/setup.sh.in                 |   29 +
 tests/system/ixfr/in-2/tests.sh                    |   81 +
 tests/system/ixfr/in-3/clean.sh                    |    1 +
 tests/system/ixfr/in-3/ns1/README                  |    3 +
 tests/system/ixfr/in-3/nsx2/README                 |    3 +
 tests/system/ixfr/in-3/setup.sh.in                 |   29 +
 tests/system/ixfr/in-3/tests.sh                    |   55 +
 tests/system/ixfr/in-4/clean.sh                    |    1 +
 tests/system/ixfr/in-4/ns1/README                  |    3 +
 tests/system/ixfr/in-4/nsx2/README                 |    3 +
 tests/system/ixfr/in-4/setup.sh.in                 |   30 +
 tests/system/ixfr/in-4/tests.sh                    |   53 +
 tests/system/ixfr/ixfr_init.sh.in                  |  330 +++++
 tests/system/ixfr/named_noixfr.conf                |   41 +
 tests/system/ixfr/named_nonotify.conf              |   40 +
 tests/system/ixfr/named_notify.conf                |   41 +
 tests/system/run.sh                                |  125 --
 tests/system/run.sh.in                             |  125 ++
 tests/system/start.pl                              |    4 +-
 tests/tools/badpacket/Makefile.am                  |    2 +-
 tests/tools/badpacket/tests/Makefile.am            |    2 +-
 181 files changed, 10238 insertions(+), 1407 deletions(-)
 create mode 100644 src/bin/dhcp6/b10-dhcp6.xml
 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
 delete mode 100644 src/bin/stats/tests/isc/log_messages/Makefile.am
 delete mode 100644 src/bin/stats/tests/isc/log_messages/__init__.py
 delete mode 100644 src/bin/stats/tests/isc/log_messages/stats_httpd_messages.py
 delete mode 100644 src/bin/stats/tests/isc/log_messages/stats_messages.py
 create mode 100644 src/lib/dhcp/Makefile.am
 create mode 100644 src/lib/dhcp/README
 create mode 100644 src/lib/dhcp/dhcp4.h
 create mode 100644 src/lib/dhcp/dhcp6.h
 create mode 100644 src/lib/dhcp/libdhcp.cc
 create mode 100644 src/lib/dhcp/libdhcp.h
 create mode 100644 src/lib/dhcp/option.cc
 create mode 100644 src/lib/dhcp/option.h
 create mode 100644 src/lib/dhcp/option6_addrlst.cc
 create mode 100644 src/lib/dhcp/option6_addrlst.h
 create mode 100644 src/lib/dhcp/option6_ia.cc
 create mode 100644 src/lib/dhcp/option6_ia.h
 create mode 100644 src/lib/dhcp/option6_iaaddr.cc
 create mode 100644 src/lib/dhcp/option6_iaaddr.h
 create mode 100644 src/lib/dhcp/pkt4.cc
 create mode 100644 src/lib/dhcp/pkt4.h
 create mode 100644 src/lib/dhcp/pkt6.cc
 create mode 100644 src/lib/dhcp/pkt6.h
 create mode 100644 src/lib/dhcp/tests/Makefile.am
 create mode 100644 src/lib/dhcp/tests/libdhcp_unittest.cc
 create mode 100644 src/lib/dhcp/tests/option6_addrlst_unittest.cc
 create mode 100644 src/lib/dhcp/tests/option6_ia_unittest.cc
 create mode 100644 src/lib/dhcp/tests/option6_iaaddr_unittest.cc
 create mode 100644 src/lib/dhcp/tests/option_unittest.cc
 create mode 100644 src/lib/dhcp/tests/pkt4_unittest.cc
 create mode 100644 src/lib/dhcp/tests/pkt6_unittest.cc
 create mode 100644 src/lib/dhcp/tests/run_unittests.cc
 create mode 100644 src/lib/log/log_dbglevels.h
 create mode 100644 tests/system/common/rndc.conf
 create mode 100644 tests/system/common/rndc.key
 create mode 100644 tests/system/ixfr/README
 create mode 100644 tests/system/ixfr/b10-config.db.in
 create mode 100644 tests/system/ixfr/clean_ns.sh
 create mode 100644 tests/system/ixfr/common_tests.sh.in
 create mode 100644 tests/system/ixfr/db.example.common
 create mode 100644 tests/system/ixfr/db.example.n0.in
 create mode 100644 tests/system/ixfr/db.example.n2.in
 create mode 100644 tests/system/ixfr/db.example.n2.refresh.in
 create mode 100644 tests/system/ixfr/db.example.n4.in
 create mode 100644 tests/system/ixfr/db.example.n6.in
 create mode 120000 tests/system/ixfr/in-1/clean.sh
 create mode 100644 tests/system/ixfr/in-1/ns1/README
 create mode 100644 tests/system/ixfr/in-1/nsx2/README
 create mode 100644 tests/system/ixfr/in-1/setup.sh.in
 create mode 100644 tests/system/ixfr/in-1/tests.sh
 create mode 120000 tests/system/ixfr/in-2/clean.sh
 create mode 100644 tests/system/ixfr/in-2/ns1/README
 create mode 100644 tests/system/ixfr/in-2/nsx2/README
 create mode 100644 tests/system/ixfr/in-2/setup.sh.in
 create mode 100644 tests/system/ixfr/in-2/tests.sh
 create mode 120000 tests/system/ixfr/in-3/clean.sh
 create mode 100644 tests/system/ixfr/in-3/ns1/README
 create mode 100644 tests/system/ixfr/in-3/nsx2/README
 create mode 100644 tests/system/ixfr/in-3/setup.sh.in
 create mode 100644 tests/system/ixfr/in-3/tests.sh
 create mode 120000 tests/system/ixfr/in-4/clean.sh
 create mode 100644 tests/system/ixfr/in-4/ns1/README
 create mode 100644 tests/system/ixfr/in-4/nsx2/README
 create mode 100644 tests/system/ixfr/in-4/setup.sh.in
 create mode 100644 tests/system/ixfr/in-4/tests.sh
 create mode 100644 tests/system/ixfr/ixfr_init.sh.in
 create mode 100644 tests/system/ixfr/named_noixfr.conf
 create mode 100644 tests/system/ixfr/named_nonotify.conf
 create mode 100644 tests/system/ixfr/named_notify.conf
 delete mode 100755 tests/system/run.sh
 create mode 100755 tests/system/run.sh.in

-----------------------------------------------------------------------
diff --git a/ChangeLog b/ChangeLog
index 92f98dd..4c242db 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,59 @@
+305.	[bug]		jinmei
+	Python isc.dns, isc.datasrc, xfrin, xfrout: fixed reference leak
+	in Message.get_question(), Message.get_section(),
+	RRset.get_rdata(), and DataSourceClient.get_updater().
+	The leak caused severe memory leak in b10-xfrin, and (although no
+	one reported it) should have caused less visible leak in
+	b10-xfrout.  b10-xfrin had its own leak, which was also fixed.
+	(Trac #1028, git a72886e643864bb6f86ab47b115a55e0c7f7fcad)
+
+304.	[bug]		jelte
+	The run_bind10.sh test script now no longer runs processes from
+	an installed version of BIND 10, but will correctly use the
+	build tree paths.
+	(Trac #1246, git 1d43b46ab58077daaaf5cae3c6aa3e0eb76eb5d8)
+
+303.	[bug]		jinmei
+	Changed the installation path for the UNIX domain file used
+	for the communication between b10-auth and b10-xfrout to a
+	"@PACKAGE@" subdirectory (e.g. from /usr/local/var to
+	/usr/local/var/bind10-devel).  This should be transparent change
+	because this file is automatically created and cleaned up, but
+	if the old file somehow remains, it can now be safely removed.
+	(Trac #869, git 96e22f4284307b1d5f15e03837559711bb4f580c)
+
+302.	[bug]		jelte
+	msgq no longer crashes if the remote end is closed while msgq
+	tries to send data. It will now simply drop the message and close
+	the connection itself.
+	(Trac #1180, git 6e68b97b050e40e073f736d84b62b3e193dd870a)
+
+301.	[func]		stephen
+	Add system test for IXFR over TCP.
+	(Trac #1213, git 68ee3818bcbecebf3e6789e81ea79d551a4ff3e8)
+
+300.	[func]*		tomek
+	libdhcp: DHCP packet library was implemented. Currently it handles
+	packet reception, option parsing, option generation and output
+	packet building. Generic and specialized classes for several
+	DHCPv6 options (IA_NA, IAADDR, address-list) are available. A
+	simple code was added that leverages libdhcp. It is a skeleton
+	DHCPv6 server. It receives incoming SOLICIT and REQUEST messages
+	and responds with proper ADVERTISE and REPLY. Note that since
+	LeaseManager is not implemented, server assigns the same
+	hardcoded lease for every client. This change removes existing
+	DHCPv6 echo server as it was only a proof of concept code.
+	(Trac #1186, git 67ea6de047d4dbd63c25fe7f03f5d5cc2452ad7d)
+
+299.	[build]		jreed
+	Do not install the libfake_session, libtestutils, or libbench
+	libraries. They are used by tests within the source tree.
+	Convert all test-related makefiles to build test code at
+	regular make time to better work with test-driven development.
+	This reverts some of #1901. (The tests are ran using "make
+	check".)
+	(Trac #1286, git cee641fd3d12341d6bfce5a6fbd913e3aebc1e8e)
+
 bind10-devel-20111014 released on October 14, 2011
 
 298.	[doc]		jreed
diff --git a/configure.ac b/configure.ac
index b0f5f45..1fdf5bf 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,7 +2,7 @@
 # Process this file with autoconf to produce a configure script.
 
 AC_PREREQ([2.59])
-AC_INIT(bind10-devel, 20110809, bind10-dev at isc.org)
+AC_INIT(bind10-devel, 20111021, bind10-dev at isc.org)
 AC_CONFIG_SRCDIR(README)
 AM_INIT_AUTOMAKE
 AC_CONFIG_HEADERS([config.h])
@@ -770,6 +770,8 @@ fi
 #
 AC_PATH_PROGS(PERL, perl5 perl)
 AC_SUBST(PERL)
+AC_PATH_PROGS(AWK, gawk awk)
+AC_SUBST(AWK)
 
 AC_ARG_ENABLE(man, [AC_HELP_STRING([--enable-man],
   [regenerate man pages [default=no]])], enable_man=yes, enable_man=no)
@@ -870,6 +872,8 @@ AC_CONFIG_FILES([Makefile
                  src/lib/dns/python/Makefile
                  src/lib/dns/python/tests/Makefile
                  src/lib/dns/benchmarks/Makefile
+                 src/lib/dhcp/Makefile
+                 src/lib/dhcp/tests/Makefile
                  src/lib/exceptions/Makefile
                  src/lib/exceptions/tests/Makefile
                  src/lib/datasrc/Makefile
@@ -965,9 +969,22 @@ AC_OUTPUT([doc/version.ent
            src/lib/util/python/gen_wiredata.py
            src/lib/server_common/tests/data_path.h
            tests/system/conf.sh
+           tests/system/run.sh
            tests/system/glue/setup.sh
            tests/system/glue/nsx1/b10-config.db
            tests/system/bindctl/nsx1/b10-config.db.template
+           tests/system/ixfr/db.example.n0
+           tests/system/ixfr/db.example.n2
+           tests/system/ixfr/db.example.n2.refresh
+           tests/system/ixfr/db.example.n4
+           tests/system/ixfr/db.example.n6
+           tests/system/ixfr/ixfr_init.sh
+           tests/system/ixfr/b10-config.db
+           tests/system/ixfr/common_tests.sh
+           tests/system/ixfr/in-1/setup.sh
+           tests/system/ixfr/in-2/setup.sh
+           tests/system/ixfr/in-3/setup.sh
+           tests/system/ixfr/in-4/setup.sh
           ], [
            chmod +x src/bin/cmdctl/run_b10-cmdctl.sh
            chmod +x src/bin/xfrin/run_b10-xfrin.sh
@@ -996,6 +1013,13 @@ AC_OUTPUT([doc/version.ent
            chmod +x src/lib/util/python/gen_wiredata.py
            chmod +x src/lib/python/isc/log/tests/log_console.py
            chmod +x tests/system/conf.sh
+           chmod +x tests/system/run.sh
+           chmod +x tests/system/ixfr/ixfr_init.sh
+           chmod +x tests/system/ixfr/common_tests.sh
+           chmod +x tests/system/ixfr/in-1/setup.sh
+           chmod +x tests/system/ixfr/in-2/setup.sh
+           chmod +x tests/system/ixfr/in-3/setup.sh
+           chmod +x tests/system/ixfr/in-4/setup.sh
           ])
 AC_OUTPUT
 
diff --git a/doc/Doxyfile b/doc/Doxyfile
index 8be9098..ee5aaf8 100644
--- a/doc/Doxyfile
+++ b/doc/Doxyfile
@@ -574,7 +574,7 @@ INPUT                  = ../src/lib/exceptions ../src/lib/cc \
     ../src/lib/log/compiler ../src/lib/asiolink/ ../src/lib/nsas \
     ../src/lib/testutils ../src/lib/cache ../src/lib/server_common/ \
     ../src/bin/sockcreator/ ../src/lib/util/ \
-    ../src/lib/resolve ../src/lib/acl ../src/bin/dhcp6
+    ../src/lib/resolve ../src/lib/acl ../src/bin/dhcp6 ../src/lib/dhcp
 
 # This tag can be used to specify the character encoding of the source files
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
diff --git a/doc/guide/Makefile.am b/doc/guide/Makefile.am
index f7fcddb..239f235 100644
--- a/doc/guide/Makefile.am
+++ b/doc/guide/Makefile.am
@@ -2,11 +2,6 @@ EXTRA_DIST = bind10-guide.css
 EXTRA_DIST += bind10-guide.xml bind10-guide.html bind10-guide.txt
 EXTRA_DIST += bind10-messages.xml bind10-messages.html
 
-HTML2TXT = elinks -dump -no-numbering -no-references
-
-bind10-guide.txt: bind10-guide.html
-	$(HTML2TXT) $(srcdir)/bind10-guide.html > $@
-
 # This is not a "man" manual, but reuse this for now for docbook.
 if ENABLE_MAN
 
@@ -20,6 +15,11 @@ bind10-guide.html: bind10-guide.xml
 		http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl \
 		$(srcdir)/bind10-guide.xml
 
+HTML2TXT = elinks -dump -no-numbering -no-references
+
+bind10-guide.txt: bind10-guide.html
+	$(HTML2TXT) $(srcdir)/bind10-guide.html > $@
+
 bind10-messages.html: bind10-messages.xml
 	xsltproc --novalid --xinclude --nonet \
 		--path $(top_builddir)/doc \
diff --git a/src/bin/auth/auth_log.h b/src/bin/auth/auth_log.h
index 5205624..e0cae0f 100644
--- a/src/bin/auth/auth_log.h
+++ b/src/bin/auth/auth_log.h
@@ -28,19 +28,19 @@ namespace auth {
 /// output.
 
 // Debug messages indicating normal startup are logged at this debug level.
-const int DBG_AUTH_START = 10;
+const int DBG_AUTH_START = DBGLVL_START_SHUT;
 
 // Debug level used to log setting information (such as configuration changes).
-const int DBG_AUTH_OPS = 30;
+const int DBG_AUTH_OPS = DBGLVL_COMMAND;
 
 // Trace detailed operations, including errors raised when processing invalid
 // packets.  (These are not logged at severities of WARN or higher for fear
 // that a set of deliberately invalid packets set to the authoritative server
 // could overwhelm the logging.)
-const int DBG_AUTH_DETAIL = 50;
+const int DBG_AUTH_DETAIL = DBGLVL_TRACE_BASIC;
 
 // This level is used to log the contents of packets received and sent.
-const int DBG_AUTH_MESSAGES = 70;
+const int DBG_AUTH_MESSAGES = DBGLVL_TRACE_DETAIL_DATA;
 
 /// Define the logger for the "auth" module part of b10-auth.  We could define
 /// a logger in each file, but we would want to define a common name to avoid
diff --git a/src/bin/auth/auth_messages.mes b/src/bin/auth/auth_messages.mes
index 1ffa687..4706690 100644
--- a/src/bin/auth/auth_messages.mes
+++ b/src/bin/auth/auth_messages.mes
@@ -260,4 +260,3 @@ NOTIFY request will not be honored.
 % AUTH_INVALID_STATISTICS_DATA invalid specification of statistics data specified
 An error was encountered when the authoritiative server specified
 statistics data which is invalid for the auth specification file.
-
diff --git a/src/bin/auth/common.cc b/src/bin/auth/common.cc
index 35381a1..a7031f3 100644
--- a/src/bin/auth/common.cc
+++ b/src/bin/auth/common.cc
@@ -12,22 +12,25 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
+#include <string>
+
 #include <auth/common.h>
 #include <auth/spec_config.h>
 #include <stdlib.h>
 
 using std::string;
 
-string getXfroutSocketPath() {
+string
+getXfroutSocketPath() {
     if (getenv("B10_FROM_BUILD") != NULL) {
-        if (getenv("B10_FROM_SOURCE_LOCALSTATEDIR")) {
+        if (getenv("B10_FROM_SOURCE_LOCALSTATEDIR") != NULL) {
             return (string(getenv("B10_FROM_SOURCE_LOCALSTATEDIR")) +
                     "/auth_xfrout_conn");
         } else {
             return (string(getenv("B10_FROM_BUILD")) + "/auth_xfrout_conn");
         }
     } else {
-        if (getenv("BIND10_XFROUT_SOCKET_FILE")) {
+        if (getenv("BIND10_XFROUT_SOCKET_FILE") != NULL) {
             return (getenv("BIND10_XFROUT_SOCKET_FILE"));
         } else {
             return (UNIX_SOCKET_FILE);
diff --git a/src/bin/auth/query.cc b/src/bin/auth/query.cc
index ab6404e..5e8a9b1 100644
--- a/src/bin/auth/query.cc
+++ b/src/bin/auth/query.cc
@@ -12,6 +12,7 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
+#include <algorithm>            // for std::max
 #include <vector>
 #include <boost/foreach.hpp>
 
@@ -31,24 +32,24 @@ namespace isc {
 namespace auth {
 
 void
-Query::getAdditional(ZoneFinder& zone, const RRset& rrset) const {
+Query::addAdditional(ZoneFinder& zone, const RRset& rrset) {
     RdataIteratorPtr rdata_iterator(rrset.getRdataIterator());
     for (; !rdata_iterator->isLast(); rdata_iterator->next()) {
         const Rdata& rdata(rdata_iterator->getCurrent());
         if (rrset.getType() == RRType::NS()) {
             // Need to perform the search in the "GLUE OK" mode.
             const generic::NS& ns = dynamic_cast<const generic::NS&>(rdata);
-            findAddrs(zone, ns.getNSName(), ZoneFinder::FIND_GLUE_OK);
+            addAdditionalAddrs(zone, ns.getNSName(), ZoneFinder::FIND_GLUE_OK);
         } else if (rrset.getType() == RRType::MX()) {
             const generic::MX& mx(dynamic_cast<const generic::MX&>(rdata));
-            findAddrs(zone, mx.getMXName());
+            addAdditionalAddrs(zone, mx.getMXName());
         }
     }
 }
 
 void
-Query::findAddrs(ZoneFinder& zone, const Name& qname,
-                 const ZoneFinder::FindOptions options) const
+Query::addAdditionalAddrs(ZoneFinder& zone, const Name& qname,
+                          const ZoneFinder::FindOptions options)
 {
     // Out of zone name
     NameComparisonResult result = zone.getOrigin().compare(qname);
@@ -87,12 +88,12 @@ Query::findAddrs(ZoneFinder& zone, const Name& qname,
 }
 
 void
-Query::putSOA(ZoneFinder& zone) const {
-    ZoneFinder::FindResult soa_result(zone.find(zone.getOrigin(),
+Query::addSOA(ZoneFinder& finder) {
+    ZoneFinder::FindResult soa_result(finder.find(finder.getOrigin(),
         RRType::SOA(), NULL, dnssec_opt_));
     if (soa_result.code != ZoneFinder::SUCCESS) {
         isc_throw(NoSOA, "There's no SOA record in zone " <<
-            zone.getOrigin().toText());
+            finder.getOrigin().toText());
     } else {
         /*
          * FIXME:
@@ -104,26 +105,88 @@ Query::putSOA(ZoneFinder& zone) const {
     }
 }
 
+// Note: unless the data source client implementation or the zone content
+// is broken, 'nsec' should be a valid NSEC RR.  Likewise, the call to
+// find() in this method should result in NXDOMAIN and an NSEC RR that proves
+// the non existent of matching wildcard.  If these assumptions aren't met
+// due to a buggy data source implementation or a broken zone, we'll let
+// underlying libdns++ modules throw an exception, which would result in
+// either an SERVFAIL response or just ignoring the query.  We at least prevent
+// a complete crash due to such broken behavior.
 void
-Query::getAuthAdditional(ZoneFinder& zone) const {
+Query::addNXDOMAINProof(ZoneFinder& finder, ConstRRsetPtr nsec) {
+    if (nsec->getRdataCount() == 0) {
+        isc_throw(BadNSEC, "NSEC for NXDOMAIN is empty");
+        return;
+    }
+
+    // Add the NSEC proving NXDOMAIN to the authority section.
+    response_.addRRset(Message::SECTION_AUTHORITY,
+                       boost::const_pointer_cast<RRset>(nsec), dnssec_);
+
+    // Next, identify the best possible wildcard name that would match
+    // the query name.  It's the longer common suffix with the qname
+    // between the owner or the next domain of the NSEC that proves NXDOMAIN,
+    // prefixed by the wildcard label, "*".  For example, for query name
+    // a.b.example.com, if the NXDOMAIN NSEC is
+    // b.example.com. NSEC c.example.com., the longer suffix is b.example.com.,
+    // and the best possible wildcard is *.b.example.com.  If the NXDOMAIN
+    // NSEC is a.example.com. NSEC c.b.example.com., the longer suffix
+    // is the next domain of the NSEC, and we get the same wildcard name.
+    const int qlabels = qname_.getLabelCount();
+    const int olabels = qname_.compare(nsec->getName()).getCommonLabels();
+    const int nlabels = qname_.compare(
+        dynamic_cast<const generic::NSEC&>(nsec->getRdataIterator()->
+                                           getCurrent()).
+        getNextName()).getCommonLabels();
+    const int common_labels = std::max(olabels, nlabels);
+    const Name wildname(Name("*").concatenate(qname_.split(qlabels -
+                                                           common_labels)));
+
+    // Confirm the wildcard doesn't exist (this should result in NXDOMAIN;
+    // otherwise we shouldn't have got NXDOMAIN for the original query in
+    // the first place).
+    const ZoneFinder::FindResult fresult = finder.find(wildname,
+                                                       RRType::NSEC(), NULL,
+                                                       dnssec_opt_);
+    if (fresult.code != ZoneFinder::NXDOMAIN || !fresult.rrset ||
+        fresult.rrset->getRdataCount() == 0) {
+        isc_throw(BadNSEC, "Unexpected result for wildcard NXDOMAIN proof");
+        return;
+    }
+
+    // Add the (no-) wildcard proof only when it's different from the NSEC
+    // that proves NXDOMAIN; sometimes they can be the same.
+    // Note: name comparison is relatively expensive.  When we are at the
+    // stage of performance optimization, we should consider optimizing this
+    // for some optimized data source implementations.
+    if (nsec->getName() != fresult.rrset->getName()) {
+        response_.addRRset(Message::SECTION_AUTHORITY,
+                           boost::const_pointer_cast<RRset>(fresult.rrset),
+                           dnssec_);
+    }
+}
+
+void
+Query::addAuthAdditional(ZoneFinder& finder) {
     // Fill in authority and addtional sections.
-    ZoneFinder::FindResult ns_result = zone.find(zone.getOrigin(),
-                                                 RRType::NS(), NULL,
-                                                 dnssec_opt_);
+    ZoneFinder::FindResult ns_result = finder.find(finder.getOrigin(),
+                                                   RRType::NS(), NULL,
+                                                   dnssec_opt_);
     // zone origin name should have NS records
     if (ns_result.code != ZoneFinder::SUCCESS) {
         isc_throw(NoApexNS, "There's no apex NS records in zone " <<
-                zone.getOrigin().toText());
+                finder.getOrigin().toText());
     } else {
         response_.addRRset(Message::SECTION_AUTHORITY,
             boost::const_pointer_cast<RRset>(ns_result.rrset), dnssec_);
         // Handle additional for authority section
-        getAdditional(zone, *ns_result.rrset);
+        addAdditional(finder, *ns_result.rrset);
     }
 }
 
 void
-Query::process() const {
+Query::process() {
     bool keep_doing = true;
     const bool qtype_is_any = (qtype_ == RRType::ANY());
 
@@ -141,6 +204,7 @@ Query::process() const {
         response_.setRcode(Rcode::REFUSED());
         return;
     }
+    ZoneFinder& zfinder = *result.zone_finder;
 
     // Found a zone which is the nearest ancestor to QNAME, set the AA bit
     response_.setHeaderFlag(Message::HEADERFLAG_AA);
@@ -149,8 +213,7 @@ Query::process() const {
         keep_doing = false;
         std::auto_ptr<RRsetList> target(qtype_is_any ? new RRsetList : NULL);
         const ZoneFinder::FindResult db_result(
-            result.zone_finder->find(qname_, qtype_, target.get(),
-                                     dnssec_opt_));
+            zfinder.find(qname_, qtype_, target.get(), dnssec_opt_));
         switch (db_result.code) {
             case ZoneFinder::DNAME: {
                 // First, put the dname into the answer
@@ -217,14 +280,14 @@ Query::process() const {
                         response_.addRRset(Message::SECTION_ANSWER, rrset,
                                            dnssec_);
                         // Handle additional for answer section
-                        getAdditional(*result.zone_finder, *rrset.get());
+                        addAdditional(*result.zone_finder, *rrset.get());
                     }
                 } else {
                     response_.addRRset(Message::SECTION_ANSWER,
                         boost::const_pointer_cast<RRset>(db_result.rrset),
                         dnssec_);
                     // Handle additional for answer section
-                    getAdditional(*result.zone_finder, *db_result.rrset);
+                    addAdditional(*result.zone_finder, *db_result.rrset);
                 }
                 // If apex NS records haven't been provided in the answer
                 // section, insert apex NS records into the authority section
@@ -234,7 +297,7 @@ Query::process() const {
                     db_result.code != ZoneFinder::SUCCESS ||
                     (qtype_ != RRType::NS() && !qtype_is_any))
                 {
-                    getAuthAdditional(*result.zone_finder);
+                    addAuthAdditional(*result.zone_finder);
                 }
                 break;
             case ZoneFinder::DELEGATION:
@@ -242,16 +305,20 @@ Query::process() const {
                 response_.addRRset(Message::SECTION_AUTHORITY,
                     boost::const_pointer_cast<RRset>(db_result.rrset),
                     dnssec_);
-                getAdditional(*result.zone_finder, *db_result.rrset);
+                addAdditional(*result.zone_finder, *db_result.rrset);
                 break;
             case ZoneFinder::NXDOMAIN:
-                // Just empty answer with SOA in authority section
                 response_.setRcode(Rcode::NXDOMAIN());
-                putSOA(*result.zone_finder);
+                addSOA(*result.zone_finder);
+
+                // If DNSSEC proof is requested and we've got it, add it.
+                if (dnssec_ && db_result.rrset) {
+                    addNXDOMAINProof(zfinder, db_result.rrset);
+                }
                 break;
             case ZoneFinder::NXRRSET:
                 // Just empty answer with SOA in authority section
-                putSOA(*result.zone_finder);
+                addSOA(*result.zone_finder);
                 break;
             default:
                 // These are new result codes (WILDCARD and WILDCARD_NXRRSET)
diff --git a/src/bin/auth/query.h b/src/bin/auth/query.h
index 0ebbed8..f43dc77 100644
--- a/src/bin/auth/query.h
+++ b/src/bin/auth/query.h
@@ -69,10 +69,16 @@ private:
     /// Adds a SOA of the zone into the authority zone of response_.
     /// Can throw NoSOA.
     ///
-    void putSOA(isc::datasrc::ZoneFinder& zone) const;
+    void addSOA(isc::datasrc::ZoneFinder& finder);
+
+    /// Add NSEC RRs that prove an NXDOMAIN result.
+    ///
+    /// This corresponds to Section 3.1.3.2 of RFC 4035.
+    void addNXDOMAINProof(isc::datasrc::ZoneFinder& finder,
+                          isc::dns::ConstRRsetPtr nsec);
 
     /// \brief Look up additional data (i.e., address records for the names
-    /// included in NS or MX records).
+    /// included in NS or MX records) and add them to the additional section.
     ///
     /// Note: Any additional data which has already been provided in the
     /// answer section (i.e., if the original query happend to be for the
@@ -85,8 +91,8 @@ private:
     /// query is to be found.
     /// \param rrset The RRset (i.e., NS or MX rrset) which require additional
     /// processing.
-    void getAdditional(isc::datasrc::ZoneFinder& zone,
-                       const isc::dns::RRset& rrset) const;
+    void addAdditional(isc::datasrc::ZoneFinder& zone,
+                       const isc::dns::RRset& rrset);
 
     /// \brief Find address records for a specified name.
     ///
@@ -104,13 +110,13 @@ private:
     /// be found.
     /// \param qname The name in rrset RDATA.
     /// \param options The search options.
-    void findAddrs(isc::datasrc::ZoneFinder& zone,
-                   const isc::dns::Name& qname,
-                   const isc::datasrc::ZoneFinder::FindOptions options
-                   = isc::datasrc::ZoneFinder::FIND_DEFAULT) const;
+    void addAdditionalAddrs(isc::datasrc::ZoneFinder& zone,
+                            const isc::dns::Name& qname,
+                            const isc::datasrc::ZoneFinder::FindOptions options
+                            = isc::datasrc::ZoneFinder::FIND_DEFAULT);
 
     /// \brief Look up a zone's NS RRset and their address records for an
-    /// authoritative answer.
+    /// authoritative answer, and add them to the additional section.
     ///
     /// On returning an authoritative answer, insert a zone's NS into the
     /// authority section and AAAA/A RRs of each of the NS RDATA into the
@@ -125,9 +131,9 @@ private:
     /// include AAAA/A RRs under a zone cut in additional section. (BIND 9
     /// excludes under-cut RRs; NSD include them.)
     ///
-    /// \param zone The \c ZoneFinder through which the NS and additional data
-    /// for the query are to be found.
-    void getAuthAdditional(isc::datasrc::ZoneFinder& zone) const;
+    /// \param finder The \c ZoneFinder through which the NS and additional
+    /// data for the query are to be found.
+    void addAuthAdditional(isc::datasrc::ZoneFinder& finder);
 
 public:
     /// Constructor from query parameters.
@@ -176,7 +182,7 @@ public:
     /// This might throw BadZone or any of its specific subclasses, but that
     /// shouldn't happen in real-life (as BadZone means wrong data, it should
     /// have been rejected upon loading).
-    void process() const;
+    void process();
 
     /// \short Bad zone data encountered.
     ///
@@ -210,6 +216,17 @@ public:
         {}
     };
 
+    /// An invalid result is given when a valid NSEC is expected
+    ///
+    // This can only happen when the underlying data source implementation or
+    /// the zone is broken.  By throwing an exception we treat such cases
+    /// as SERVFAIL.
+    struct BadNSEC : public BadZone {
+        BadNSEC(const char* file, size_t line, const char* what) :
+            BadZone(file, line, what)
+        {}
+    };
+
 private:
     const isc::datasrc::DataSourceClient& datasrc_client_;
     const isc::dns::Name& qname_;
diff --git a/src/bin/auth/spec_config.h.pre.in b/src/bin/auth/spec_config.h.pre.in
index 52581dd..1b1df19 100644
--- a/src/bin/auth/spec_config.h.pre.in
+++ b/src/bin/auth/spec_config.h.pre.in
@@ -1,16 +1,16 @@
-// Copyright (C) 2009  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.
-
-#define AUTH_SPECFILE_LOCATION "@prefix@/share/@PACKAGE@/auth.spec"
-#define UNIX_SOCKET_FILE "@@LOCALSTATEDIR@@/auth_xfrout_conn"
+// Copyright (C) 2009  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.
+
+#define AUTH_SPECFILE_LOCATION "@prefix@/share/@PACKAGE@/auth.spec"
+#define UNIX_SOCKET_FILE "@@LOCALSTATEDIR@@/@PACKAGE@/auth_xfrout_conn"
diff --git a/src/bin/auth/tests/Makefile.am b/src/bin/auth/tests/Makefile.am
index a4bd6fa..d27386e 100644
--- a/src/bin/auth/tests/Makefile.am
+++ b/src/bin/auth/tests/Makefile.am
@@ -67,4 +67,4 @@ run_unittests_LDADD += $(top_builddir)/src/lib/nsas/libnsas.la
 run_unittests_LDADD += $(top_builddir)/src/lib/util/unittests/libutil_unittests.la
 endif
 
-check_PROGRAMS = $(TESTS)
+noinst_PROGRAMS = $(TESTS)
diff --git a/src/bin/auth/tests/query_unittest.cc b/src/bin/auth/tests/query_unittest.cc
index b2d1094..c5eb231 100644
--- a/src/bin/auth/tests/query_unittest.cc
+++ b/src/bin/auth/tests/query_unittest.cc
@@ -17,6 +17,7 @@
 #include <map>
 
 #include <boost/bind.hpp>
+#include <boost/scoped_ptr.hpp>
 
 #include <dns/masterload.h>
 #include <dns/message.h>
@@ -91,8 +92,49 @@ const char* const other_zone_rrs =
     "cnamemailer.example.com. 3600 IN CNAME www.example.com.\n"
     "cnamemx.example.com. 3600 IN MX 10 cnamemailer.example.com.\n"
     "mx.delegation.example.com. 3600 IN A 192.0.2.100\n";
-
-// This is a mock Zone class for testing.
+// Used in NXDOMAIN proof test.  We are going to test some unusual case where
+// the best possible wildcard is below the "next domain" of the NSEC RR that
+// proves the NXDOMAIN, i.e.,
+// mx.example.com. (exist)
+// (.no.example.com. (qname, NXDOMAIN)
+// ).no.example.com. (exist)
+// *.no.example.com. (best possible wildcard, not exist)
+const char* const no_txt =
+    ").no.example.com. 3600 IN AAAA 2001:db8::53\n";
+// NSEC records.
+const char* const nsec_apex_txt =
+    "example.com. 3600 IN NSEC cname.example.com. NS SOA NSEC RRSIG\n";
+const char* const nsec_mx_txt =
+    "mx.example.com. 3600 IN NSEC ).no.example.com. MX NSEC RRSIG\n";
+const char* const nsec_no_txt =
+    ").no.example.com. 3600 IN NSEC nz.no.example.com. AAAA NSEC RRSIG\n";
+
+// We'll also test the case where a single NSEC proves both NXDOMAIN and the
+// non existence of wildcard.  The following records will be used for that
+// test.
+// ).no.example.com. (exist, whose NSEC proves everything)
+// *.no.example.com. (best possible wildcard, not exist)
+// nx.no.example.com. (NXDOMAIN)
+// nz.no.example.com. (exist)
+const char* const nz_txt =
+    "nz.no.example.com. 3600 IN AAAA 2001:db8::5300\n";
+const char* const nsec_nz_txt =
+    "nz.no.example.com. 3600 IN NSEC noglue.example.com. AAAA NSEC RRSIG\n";
+const char* const nsec_nxdomain_txt =
+    "noglue.example.com. 3600 IN NSEC www.example.com. A\n";
+
+// A helper function that generates a textual representation of RRSIG RDATA
+// for the given covered type.  The resulting RRSIG may not necessarily make
+// sense in terms of the DNSSEC protocol, but for our testing purposes it's
+// okay.
+string
+getCommonRRSIGText(const string& type) {
+    return (type +
+            string(" 5 3 3600 20000101000000 20000201000000 12345 "
+                   "example.com. FAKEFAKEFAKE"));
+}
+
+// This is a mock Zone Finder class for testing.
 // It is a derived class of ZoneFinder for the convenient of tests.
 // Its find() method emulates the common behavior of protocol compliant
 // ZoneFinder classes, but simplifies some minor cases and also supports broken
@@ -112,16 +154,24 @@ public:
         has_SOA_(true),
         has_apex_NS_(true),
         rrclass_(RRClass::IN()),
-        include_rrsig_anyway_(false)
+        include_rrsig_anyway_(false),
+        nsec_name_(origin_)
     {
         stringstream zone_stream;
         zone_stream << soa_txt << zone_ns_txt << ns_addrs_txt <<
             delegation_txt << mx_txt << www_a_txt << cname_txt <<
             cname_nxdom_txt << cname_out_txt << dname_txt << dname_a_txt <<
-            other_zone_rrs;
+            other_zone_rrs << no_txt << nz_txt <<
+            nsec_apex_txt << nsec_mx_txt << nsec_no_txt << nsec_nz_txt <<
+            nsec_nxdomain_txt;
 
         masterLoad(zone_stream, origin_, rrclass_,
                    boost::bind(&MockZoneFinder::loadRRset, this, _1));
+
+        empty_nsec_rrset_ = ConstRRsetPtr(new RRset(Name::ROOT_NAME(),
+                                                    RRClass::IN(),
+                                                    RRType::NSEC(),
+                                                    RRTTL(3600)));
     }
     virtual isc::dns::Name getOrigin() const { return (origin_); }
     virtual isc::dns::RRClass getClass() const { return (rrclass_); }
@@ -141,10 +191,24 @@ public:
     // Turn this on if you want it to return RRSIGs regardless of FIND_GLUE_OK
     void setIncludeRRSIGAnyway(bool on) { include_rrsig_anyway_ = on; }
 
+    // Once called, this "faked" result will be returned when NSEC is expected
+    // for the specified query name.
+    void setNSECResult(const Name& nsec_name, Result code,
+                       ConstRRsetPtr rrset)
+    {
+        nsec_name_ = nsec_name;
+        nsec_result_.reset(new ZoneFinder::FindResult(code, rrset));
+    }
+
     Name findPreviousName(const Name&) const {
         isc_throw(isc::NotImplemented, "Mock doesn't support previous name");
     }
 
+public:
+    // We allow the tests to use these for convenience
+    ConstRRsetPtr delegation_rrset_;
+    ConstRRsetPtr empty_nsec_rrset_;
+
 private:
     typedef map<RRType, ConstRRsetPtr> RRsetStore;
     typedef map<Name, RRsetStore> Domains;
@@ -160,23 +224,17 @@ private:
         // Add some signatures
         } else if (rrset->getName() == Name("example.com.") &&
                    rrset->getType() == RRType::NS()) {
-            rrset->addRRsig(RdataPtr(new generic::RRSIG("NS 5 3 3600 "
-                                                        "20000101000000 "
-                                                        "20000201000000 "
-                                                        "12345 example.com. "
-                                                        "FAKEFAKEFAKE")));
-        } else if (rrset->getType() == RRType::A()) {
-            rrset->addRRsig(RdataPtr(new generic::RRSIG("A 5 3 3600 "
-                                                        "20000101000000 "
-                                                        "20000201000000 "
-                                                        "12345 example.com. "
-                                                        "FAKEFAKEFAKE")));
-        } else if (rrset->getType() == RRType::AAAA()) {
-            rrset->addRRsig(RdataPtr(new generic::RRSIG("AAAA 5 3 3600 "
-                                                        "20000101000000 "
-                                                        "20000201000000 "
-                                                        "12345 example.com. "
-                                                        "FAKEFAKEFAKE")));
+            // For NS, we only have RRSIG for the origin name.
+            rrset->addRRsig(RdataPtr(new generic::RRSIG(
+                                         getCommonRRSIGText("NS"))));
+        } else {
+            // For others generate RRSIG unconditionally.  Technically this
+            // is wrong because we shouldn't have it for names under a zone
+            // cut.  But in our tests that doesn't matter, so we add them
+            // just for simplicity.
+            rrset->addRRsig(RdataPtr(new generic::RRSIG(
+                                         getCommonRRSIGText(rrset->getType().
+                                                            toText()))));
         }
     }
 
@@ -186,10 +244,12 @@ private:
     const Name dname_name_;
     bool has_SOA_;
     bool has_apex_NS_;
-    ConstRRsetPtr delegation_rrset_;
     ConstRRsetPtr dname_rrset_;
     const RRClass rrclass_;
     bool include_rrsig_anyway_;
+    // The following two will be used for faked NSEC cases
+    Name nsec_name_;
+    boost::scoped_ptr<ZoneFinder::FindResult> nsec_result_;
 };
 
 ZoneFinder::FindResult
@@ -267,7 +327,33 @@ MockZoneFinder::find(const Name& name, const RRType& type,
         return (FindResult(NXRRSET, RRsetPtr()));
     }
 
-    // query name isn't found in our domains.  returns NXDOMAIN.
+    // query name isn't found in our domains.  This is an NXDOMAIN case.
+    // If we need DNSSEC proof, find the "previous name" that has an NSEC RR
+    // and return NXDOMAIN with the found NSEC.  Otherwise, just return the
+    // NXDOMAIN code and NULL.  If DNSSEC proof is requested but no NSEC is
+    // found, we return NULL, too.  (For simplicity under the test conditions
+    // we don't care about pathological cases such as the name is "smaller"
+    // than the origin)
+    if ((options & FIND_DNSSEC) != 0) {
+        // Emulate a broken DataSourceClient for some special names.
+        if (nsec_result_ && nsec_name_ == name) {
+            return (*nsec_result_);
+        }
+
+        // Normal case
+        // XXX: some older g++ complains about operator!= if we use
+        // const_reverse_iterator
+        for (Domains::reverse_iterator it = domains_.rbegin();
+             it != domains_.rend();
+             ++it) {
+            RRsetStore::const_iterator nsec_it;
+            if ((*it).first < name &&
+                (nsec_it = (*it).second.find(RRType::NSEC()))
+                != (*it).second.end()) {
+                return (FindResult(NXDOMAIN, (*nsec_it).second));
+            }
+        }
+    }
     return (FindResult(NXDOMAIN, RRsetPtr()));
 }
 
@@ -433,8 +519,9 @@ TEST_F(QueryTest, exactAnyMatch) {
     EXPECT_NO_THROW(Query(memory_client, Name("noglue.example.com"),
                           RRType::ANY(), response).process());
 
-    responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 3, 2,
-                  "noglue.example.com. 3600 IN A 192.0.2.53\n",
+    responseCheck(response, Rcode::NOERROR(), AA_FLAG, 2, 3, 2,
+                  (string("noglue.example.com. 3600 IN A 192.0.2.53\n") +
+                   string(nsec_nxdomain_txt)).c_str(),
                   zone_ns_txt,
                   "glue.delegation.example.com. 3600 IN A 192.0.2.153\n"
                   "glue.delegation.example.com. 3600 IN AAAA 2001:db8::53\n");
@@ -445,19 +532,17 @@ TEST_F(QueryTest, apexAnyMatch) {
     // in the answer section from the additional.
     EXPECT_NO_THROW(Query(memory_client, Name("example.com"),
                           RRType::ANY(), response).process());
-    responseCheck(response, Rcode::NOERROR(), AA_FLAG, 4, 0, 3,
-                  "example.com. 3600 IN SOA . . 0 0 0 0 0\n"
-                  "example.com. 3600 IN NS glue.delegation.example.com.\n"
-                  "example.com. 3600 IN NS noglue.example.com.\n"
-                  "example.com. 3600 IN NS example.net.\n",
+    responseCheck(response, Rcode::NOERROR(), AA_FLAG, 5, 0, 3,
+                  (string(soa_txt) + string(zone_ns_txt) +
+                   string(nsec_apex_txt)).c_str(),
                   NULL, ns_addrs_txt, mock_finder->getOrigin());
 }
 
 TEST_F(QueryTest, mxANYMatch) {
     EXPECT_NO_THROW(Query(memory_client, Name("mx.example.com"),
                           RRType::ANY(), response).process());
-    responseCheck(response, Rcode::NOERROR(), AA_FLAG, 3, 3, 4,
-                  mx_txt, zone_ns_txt,
+    responseCheck(response, Rcode::NOERROR(), AA_FLAG, 4, 3, 4,
+                  (string(mx_txt) + string(nsec_mx_txt)).c_str(), zone_ns_txt,
                   (string(ns_addrs_txt) + string(www_a_txt)).c_str());
 }
 
@@ -502,6 +587,128 @@ TEST_F(QueryTest, nxdomain) {
                   NULL, soa_txt, NULL, mock_finder->getOrigin());
 }
 
+TEST_F(QueryTest, nxdomainWithNSEC) {
+    // NXDOMAIN with DNSSEC proof.  We should have SOA, NSEC that proves
+    // NXDOMAIN and NSEC that proves nonexistence of matching wildcard,
+    // as well as their RRSIGs.
+    EXPECT_NO_THROW(Query(memory_client, Name("nxdomain.example.com"), qtype,
+                          response, true).process());
+    responseCheck(response, Rcode::NXDOMAIN(), AA_FLAG, 0, 6, 0,
+                  NULL, (string(soa_txt) +
+                         string("example.com. 3600 IN RRSIG ") +
+                         getCommonRRSIGText("SOA") + "\n" +
+                         string(nsec_nxdomain_txt) + "\n" +
+                         string("noglue.example.com. 3600 IN RRSIG ") +
+                         getCommonRRSIGText("NSEC") + "\n" +
+                         string(nsec_apex_txt) + "\n" +
+                         string("example.com. 3600 IN RRSIG ") +
+                         getCommonRRSIGText("NSEC")).c_str(),
+                  NULL, mock_finder->getOrigin());
+}
+
+TEST_F(QueryTest, nxdomainWithNSEC2) {
+    // See comments about no_txt.  In this case the best possible wildcard
+    // is derived from the next domain of the NSEC that proves NXDOMAIN, and
+    // the NSEC to provide the non existence of wildcard is different from
+    // the first NSEC.
+    Query(memory_client, Name("(.no.example.com"), qtype,
+          response, true).process();
+    responseCheck(response, Rcode::NXDOMAIN(), AA_FLAG, 0, 6, 0,
+                  NULL, (string(soa_txt) +
+                         string("example.com. 3600 IN RRSIG ") +
+                         getCommonRRSIGText("SOA") + "\n" +
+                         string(nsec_mx_txt) + "\n" +
+                         string("mx.example.com. 3600 IN RRSIG ") +
+                         getCommonRRSIGText("NSEC") + "\n" +
+                         string(nsec_no_txt) + "\n" +
+                         string(").no.example.com. 3600 IN RRSIG ") +
+                         getCommonRRSIGText("NSEC")).c_str(),
+                  NULL, mock_finder->getOrigin());
+}
+
+TEST_F(QueryTest, nxdomainWithNSECDuplicate) {
+    // See comments about nz_txt.  In this case we only need one NSEC,
+    // which proves both NXDOMAIN and the non existence of wildcard.
+    Query(memory_client, Name("nx.no.example.com"), qtype,
+          response, true).process();
+    responseCheck(response, Rcode::NXDOMAIN(), AA_FLAG, 0, 4, 0,
+                  NULL, (string(soa_txt) +
+                         string("example.com. 3600 IN RRSIG ") +
+                         getCommonRRSIGText("SOA") + "\n" +
+                         string(nsec_no_txt) + "\n" +
+                         string(").no.example.com. 3600 IN RRSIG ") +
+                         getCommonRRSIGText("NSEC")).c_str(),
+                  NULL, mock_finder->getOrigin());
+}
+
+TEST_F(QueryTest, nxdomainBadNSEC1) {
+    // ZoneFinder::find() returns NXDOMAIN with non NSEC RR.
+    mock_finder->setNSECResult(Name("badnsec.example.com"),
+                               ZoneFinder::NXDOMAIN,
+                               mock_finder->delegation_rrset_);
+    EXPECT_THROW(Query(memory_client, Name("badnsec.example.com"), qtype,
+                       response, true).process(),
+                 std::bad_cast);
+}
+
+TEST_F(QueryTest, nxdomainBadNSEC2) {
+    // ZoneFinder::find() returns NXDOMAIN with an empty NSEC RR.
+    mock_finder->setNSECResult(Name("emptynsec.example.com"),
+                               ZoneFinder::NXDOMAIN,
+                               mock_finder->empty_nsec_rrset_);
+    EXPECT_THROW(Query(memory_client, Name("emptynsec.example.com"), qtype,
+                       response, true).process(),
+                 Query::BadNSEC);
+}
+
+TEST_F(QueryTest, nxdomainBadNSEC3) {
+    // "no-wildcard proof" returns SUCCESS.  it should be NXDOMAIN.
+    mock_finder->setNSECResult(Name("*.example.com"),
+                               ZoneFinder::SUCCESS,
+                               mock_finder->delegation_rrset_);
+    EXPECT_THROW(Query(memory_client, Name("nxdomain.example.com"), qtype,
+                       response, true).process(),
+                 Query::BadNSEC);
+}
+
+TEST_F(QueryTest, nxdomainBadNSEC4) {
+    // "no-wildcard proof" doesn't return RRset.
+    mock_finder->setNSECResult(Name("*.example.com"),
+                               ZoneFinder::NXDOMAIN, ConstRRsetPtr());
+    EXPECT_THROW(Query(memory_client, Name("nxdomain.example.com"), qtype,
+                       response, true).process(),
+                 Query::BadNSEC);
+}
+
+TEST_F(QueryTest, nxdomainBadNSEC5) {
+    // "no-wildcard proof" returns non NSEC.
+    mock_finder->setNSECResult(Name("*.example.com"),
+                               ZoneFinder::NXDOMAIN,
+                               mock_finder->delegation_rrset_);
+    // This is a bit odd, but we'll simply include the returned RRset.
+    Query(memory_client, Name("nxdomain.example.com"), qtype,
+          response, true).process();
+    responseCheck(response, Rcode::NXDOMAIN(), AA_FLAG, 0, 8, 0,
+                  NULL, (string(soa_txt) +
+                         string("example.com. 3600 IN RRSIG ") +
+                         getCommonRRSIGText("SOA") + "\n" +
+                         string(nsec_nxdomain_txt) + "\n" +
+                         string("noglue.example.com. 3600 IN RRSIG ") +
+                         getCommonRRSIGText("NSEC") + "\n" +
+                         delegation_txt).c_str(),
+                  NULL, mock_finder->getOrigin());
+}
+
+TEST_F(QueryTest, nxdomainBadNSEC6) {
+    // "no-wildcard proof" returns empty NSEC.
+    mock_finder->setNSECResult(Name("*.example.com"),
+                               ZoneFinder::NXDOMAIN,
+                               mock_finder->empty_nsec_rrset_);
+    EXPECT_THROW(Query(memory_client, Name("nxdomain.example.com"), qtype,
+                       response, true).process(),
+                 Query::BadNSEC);
+}
+
 TEST_F(QueryTest, nxrrset) {
     EXPECT_NO_THROW(Query(memory_client, Name("www.example.com"),
                           RRType::TXT(), response).process());
diff --git a/src/bin/bind10/bind10_src.py.in b/src/bin/bind10/bind10_src.py.in
index 94747f2..22309d6 100755
--- a/src/bin/bind10/bind10_src.py.in
+++ b/src/bin/bind10/bind10_src.py.in
@@ -44,10 +44,12 @@ import os
 # installed on the system
 if "B10_FROM_SOURCE" in os.environ:
     SPECFILE_LOCATION = os.environ["B10_FROM_SOURCE"] + "/src/bin/bind10/bob.spec"
+    ADD_LIBEXEC_PATH = False
 else:
     PREFIX = "@prefix@"
     DATAROOTDIR = "@datarootdir@"
     SPECFILE_LOCATION = "@datadir@/@PACKAGE@/bob.spec".replace("${datarootdir}", DATAROOTDIR).replace("${prefix}", PREFIX)
+    ADD_LIBEXEC_PATH = True
     
 import subprocess
 import signal
@@ -61,6 +63,7 @@ from optparse import OptionParser, OptionValueError
 import io
 import pwd
 import posix
+import copy
 
 import isc.cc
 import isc.util.process
@@ -74,8 +77,8 @@ logger = isc.log.Logger("boss")
 
 # Pending system-wide debug level definitions, the ones we
 # use here are hardcoded for now
-DBG_PROCESS = 10
-DBG_COMMANDS = 30
+DBG_PROCESS = logger.DBGLVL_TRACE_BASIC
+DBG_COMMANDS = logger.DBGLVL_TRACE_DETAIL
 
 # Assign this process some longer name
 isc.util.process.rename(sys.argv[0])
@@ -184,9 +187,9 @@ class ProcessInfo:
         # Environment variables for the child process will be a copy of those
         # of the boss process with any additional specific variables given
         # on construction (self.env).
-        spawn_env = os.environ
+        spawn_env = copy.deepcopy(os.environ)
         spawn_env.update(self.env)
-        if 'B10_FROM_SOURCE' not in os.environ:
+        if ADD_LIBEXEC_PATH:
             spawn_env['PATH'] = "@@LIBEXECDIR@@:" + spawn_env['PATH']
         self.process = subprocess.Popen(self.args,
                                         stdin=subprocess.PIPE,
@@ -355,8 +358,10 @@ class BoB:
 
     def start_creator(self):
         self.curproc = 'b10-sockcreator'
-        self.sockcreator = isc.bind10.sockcreator.Creator("@@LIBEXECDIR@@:" +
-                                                          os.environ['PATH'])
+        creator_path = os.environ['PATH']
+        if ADD_LIBEXEC_PATH:
+            creator_path = "@@LIBEXECDIR@@:" + creator_path
+        self.sockcreator = isc.bind10.sockcreator.Creator(creator_path)
 
     def stop_creator(self, kill=False):
         if self.sockcreator is None:
@@ -498,7 +503,8 @@ class BoB:
         self.log_starting("ccsession")
         self.ccs = isc.config.ModuleCCSession(SPECFILE_LOCATION, 
                                       self.config_handler,
-                                      self.command_handler)
+                                      self.command_handler,
+                                      socket_file = self.msgq_socket_file)
         self.ccs.start()
         self.log_started()
 
@@ -587,7 +593,11 @@ class BoB:
         # a cleaner solution, but for a short term workaround we specify the
         # path here, unconditionally, and without even bothering which
         # environment variable should be used.
-        if not "B10_FROM_SOURCE" in os.environ:
+        #
+        # We reuse the ADD_LIBEXEC_PATH variable to see whether we need to
+        # do this, as the conditions that make this workaround needed are
+        # the same as for the libexec path addition
+        if ADD_LIBEXEC_PATH:
             cur_path = os.getenv('DYLD_LIBRARY_PATH')
             cur_path = '' if cur_path is None else ':' + cur_path
             c_channel_env['DYLD_LIBRARY_PATH'] = "@@LIBDIR@@" + cur_path
diff --git a/src/bin/bind10/tests/bind10_test.py.in b/src/bin/bind10/tests/bind10_test.py.in
index 2efd940..1bd6ab4 100644
--- a/src/bin/bind10/tests/bind10_test.py.in
+++ b/src/bin/bind10/tests/bind10_test.py.in
@@ -21,6 +21,7 @@ from bind10_src import ProcessInfo, BoB, parse_args, dump_pid, unlink_pid_file,
 import unittest
 import sys
 import os
+import copy
 import signal
 import socket
 from isc.net.addr import IPAddr
@@ -360,6 +361,10 @@ class TestStartStopProcessesBob(unittest.TestCase):
     of processes and that the right processes are started and stopped
     according to changes in configuration.
     """
+    def check_environment_unchanged(self):
+        # Check whether the environment has not been changed
+        self.assertEqual(original_os_environ, os.environ)
+
     def check_started(self, bob, core, auth, resolver):
         """
         Check that the right sets of services are started. The ones that
@@ -379,6 +384,7 @@ class TestStartStopProcessesBob(unittest.TestCase):
         self.assertEqual(bob.stats, core)
         self.assertEqual(bob.stats_httpd, core)
         self.assertEqual(bob.cmdctl, core)
+        self.check_environment_unchanged()
 
     def check_preconditions(self, bob):
         self.check_started(bob, False, False, False)
@@ -389,6 +395,7 @@ class TestStartStopProcessesBob(unittest.TestCase):
         should be started. Some processes still need to be running.
         """
         self.check_started(bob, True, False, False)
+        self.check_environment_unchanged()
 
     def check_started_both(self, bob):
         """
@@ -396,18 +403,21 @@ class TestStartStopProcessesBob(unittest.TestCase):
         (auth and resolver) are enabled.
         """
         self.check_started(bob, True, True, True)
+        self.check_environment_unchanged()
 
     def check_started_auth(self, bob):
         """
         Check the set of processes needed to run auth only is started.
         """
         self.check_started(bob, True, True, False)
+        self.check_environment_unchanged()
 
     def check_started_resolver(self, bob):
         """
         Check the set of processes needed to run resolver only is started.
         """
         self.check_started(bob, True, False, True)
+        self.check_environment_unchanged()
 
     def check_started_dhcp(self, bob, v4, v6):
         """
@@ -426,6 +436,7 @@ class TestStartStopProcessesBob(unittest.TestCase):
         # there should be exactly one DHCPv6 daemon (if v6==True)
         self.assertEqual(v4==True, v4found==1)
         self.assertEqual(v6==True, v6found==1)
+        self.check_environment_unchanged()
 
     # Checks the processes started when starting neither auth nor resolver
     # is specified.
@@ -799,5 +810,7 @@ class TestBrittle(unittest.TestCase):
         self.assertFalse(bob.runnable)
 
 if __name__ == '__main__':
+    # store os.environ for test_unchanged_environment
+    original_os_environ = copy.deepcopy(os.environ)
     isc.log.resetUnitTestRootLogger()
     unittest.main()
diff --git a/src/bin/cmdctl/cmdctl.py.in b/src/bin/cmdctl/cmdctl.py.in
index fcd69b8..a791aa3 100755
--- a/src/bin/cmdctl/cmdctl.py.in
+++ b/src/bin/cmdctl/cmdctl.py.in
@@ -49,17 +49,12 @@ from hashlib import sha1
 from isc.util import socketserver_mixin
 from isc.log_messages.cmdctl_messages import *
 
-# TODO: these debug-levels are hard-coded here; we are planning on
-# creating a general set of debug levels, see ticket #1074. When done,
-# we should remove these values and use the general ones in the
-# logger.debug calls
-
-# Debug level for communication with BIND10
-DBG_CMDCTL_MESSAGING = 30
-
 isc.log.init("b10-cmdctl")
 logger = isc.log.Logger("cmdctl")
 
+# Debug level for communication with BIND10
+DBG_CMDCTL_MESSAGING = logger.DBGLVL_COMMAND
+
 try:
     import threading
 except ImportError:
diff --git a/src/bin/dhcp6/Makefile.am b/src/bin/dhcp6/Makefile.am
index 805d6bb..b0f8cd9 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)
 
@@ -21,30 +19,26 @@ CLEANFILES = *.gcno *.gcda spec_config.h
 man_MANS = b10-dhcp6.8
 EXTRA_DIST = $(man_MANS) dhcp6.spec interfaces.txt
 
-#if ENABLE_MAN
-#b10-dhcp6.8: b10-dhcp6.xml
-#	xsltproc --novalid --xinclude --nonet -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $(srcdir)/b10-dhcp6.xml
-#endif
+if ENABLE_MAN
+
+b10-dhcp6.8: b10-dhcp6.xml
+	xsltproc --novalid --xinclude --nonet -o $@ http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $(srcdir)/b10-dhcp6.xml
+
+endif
 
 spec_config.h: spec_config.h.pre
 	$(SED) -e "s|@@LOCALSTATEDIR@@|$(localstatedir)|" 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/b10-dhcp6.8 b/src/bin/dhcp6/b10-dhcp6.8
index a05bf71..1f34a9a 100644
--- a/src/bin/dhcp6/b10-dhcp6.8
+++ b/src/bin/dhcp6/b10-dhcp6.8
@@ -1,13 +1,13 @@
 '\" t
-.\"     Title: b10-dhpc6
+.\"     Title: b10-dhcp6
 .\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
 .\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
-.\"      Date: March 8, 2011
+.\"      Date: October 27, 2011
 .\"    Manual: BIND10
 .\"    Source: BIND10
 .\"  Language: English
 .\"
-.TH "B10\-DHCP6" "8" "March 8, 2011" "BIND10" "BIND10"
+.TH "B10\-DHCP6" "8" "October 27, 2011" "BIND10" "BIND10"
 .\" -----------------------------------------------------------------
 .\" * set default formatting
 .\" -----------------------------------------------------------------
@@ -19,31 +19,32 @@
 .\" * MAIN CONTENT STARTS HERE *
 .\" -----------------------------------------------------------------
 .SH "NAME"
-b10-dhcp6 \- DHCPv6 daemon in BIND10 architecture
+b10-dhcp6 \- DHCPv6 server in BIND 10 architecture
 .SH "SYNOPSIS"
-.HP \w'\fBb10\-dhcp6
+.HP \w'\fBb10\-dhcp6\fR\ 'u
 \fBb10\-dhcp6\fR [\fB\-v\fR]
 .SH "DESCRIPTION"
 .PP
 The
 \fBb10\-dhcp6\fR
-daemon will provide DHCPv6 server implementation when it becomes functional.
+daemon will provide the DHCPv6 server implementation when it becomes functional\&.
+.SH "ARGUMENTS"
 .PP
+The arguments are as follows:
+.PP
+\fB\-v\fR
+.RS 4
+Enable verbose mode\&.
+.RE
 .SH "SEE ALSO"
 .PP
 
-\fBb10-cfgmgr\fR(8),
-\fBb10-loadzone\fR(8),
-\fBb10-msgq\fR(8),
-\fBb10-stats\fR(8),
-\fBb10-zonemgr\fR(8),
-\fBbind10\fR(8),
-BIND 10 Guide\&.
+\fBbind10\fR(8)\&.
 .SH "HISTORY"
 .PP
 The
 \fBb10\-dhcp6\fR
-daemon was first coded in June 2011\&.
+daemon was first coded in June 2011 by Tomek Mrugalski\&.
 .SH "COPYRIGHT"
 .br
 Copyright \(co 2011 Internet Systems Consortium, Inc. ("ISC")
diff --git a/src/bin/dhcp6/b10-dhcp6.xml b/src/bin/dhcp6/b10-dhcp6.xml
new file mode 100644
index 0000000..53227db
--- /dev/null
+++ b/src/bin/dhcp6/b10-dhcp6.xml
@@ -0,0 +1,98 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+               "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+	       [<!ENTITY mdash "—">]>
+<!--
+ - 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.
+-->
+
+<refentry>
+
+  <refentryinfo>
+    <date>October 27, 2011</date>
+  </refentryinfo>
+
+  <refmeta>
+    <refentrytitle>b10-dhcp6</refentrytitle>
+    <manvolnum>8</manvolnum>
+    <refmiscinfo>BIND10</refmiscinfo>
+  </refmeta>
+
+  <refnamediv>
+    <refname>b10-dhcp6</refname>
+    <refpurpose>DHCPv6 server in BIND 10 architecture</refpurpose>
+  </refnamediv>
+
+  <docinfo>
+    <copyright>
+      <year>2011</year>
+      <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+    </copyright>
+  </docinfo>
+
+  <refsynopsisdiv>
+    <cmdsynopsis>
+      <command>b10-dhcp6</command>
+      <arg><option>-v</option></arg>
+    </cmdsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>DESCRIPTION</title>
+    <para>
+      The <command>b10-dhcp6</command> daemon will provide the
+       DHCPv6 server implementation when it becomes functional.
+    </para>
+
+  </refsect1>
+
+  <refsect1>
+    <title>ARGUMENTS</title>
+
+    <para>The arguments are as follows:</para>
+
+    <variablelist>
+
+      <varlistentry>
+        <term><option>-v</option></term>
+        <listitem><para>
+          Enable verbose mode.
+<!-- TODO: what does this do? -->
+        </para></listitem>
+      </varlistentry>
+
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>SEE ALSO</title>
+    <para>
+      <citerefentry>
+        <refentrytitle>bind10</refentrytitle><manvolnum>8</manvolnum>
+      </citerefentry>.
+    </para>
+  </refsect1>
+
+  <refsect1>
+    <title>HISTORY</title>
+    <para>
+      The <command>b10-dhcp6</command> daemon was first coded in
+      June 2011 by Tomek Mrugalski.
+    </para>
+  </refsect1>
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
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 4d9244f..ba5afec 100644
--- a/src/bin/dhcp6/dhcp6_srv.cc
+++ b/src/bin/dhcp6/dhcp6_srv.cc
@@ -12,12 +12,18 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
-#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;
@@ -25,6 +31,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() {
@@ -33,23 +45,187 @@ Dhcpv6Srv::~Dhcpv6Srv() {
 
 bool
 Dhcpv6Srv::run() {
-    while (true) {
-        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
-        sleep(1);
+            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 1e2551a..a96db07 100644
--- a/src/bin/dhcp6/iface_mgr.cc
+++ b/src/bin/dhcp6/iface_mgr.cc
@@ -18,17 +18,18 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
+#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
@@ -44,14 +45,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
@@ -64,18 +67,22 @@ 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()
+    :control_buf_len_(CMSG_SPACE(sizeof(struct in6_pktinfo))),
+     control_buf_(new char[control_buf_len_])
+{
 
     cout << "IfaceMgr initialization." << endl;
 
@@ -83,8 +90,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();
 
@@ -103,11 +110,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
@@ -225,18 +229,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,
@@ -321,15 +313,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) {
@@ -355,25 +338,14 @@ 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) {
     struct msghdr m;
     struct iovec v;
     int result;
     struct in6_pktinfo *pktinfo;
     struct cmsghdr *cmsg;
-    memset(control_buf_, 0, control_buf_len_);
+    memset(&control_buf_[0], 0, control_buf_len_);
 
     /*
      * Initialize our message header structure.
@@ -386,11 +358,11 @@ 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_;
 
     m.msg_name = &to;
     m.msg_namelen = sizeof(to);
@@ -400,8 +372,8 @@ IfaceMgr::send(Pkt6 &pkt) {
      * "scatter-gather" stuff... we only have a single chunk
      * of data to send, so we declare a single vector entry.)
      */
-    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;
 
@@ -413,7 +385,7 @@ IfaceMgr::send(Pkt6 &pkt) {
      * source address if we wanted, but we can safely let the
      * kernel decide what that should be.
      */
-    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;
@@ -421,7 +393,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;
 
     result = sendmsg(sendsock_, &m, 0);
@@ -430,26 +402,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);
 }
 
-
-/**
- * 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() {
     struct msghdr m;
     struct iovec v;
@@ -458,7 +420,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 {
@@ -469,13 +431,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& ex) {
         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));
@@ -509,7 +471,7 @@ IfaceMgr::receive() {
      * information (when we initialized the interface), so we
      * should get the destination address from that.
      */
-    m.msg_control = control_buf_;
+    m.msg_control = &control_buf_[0];
     m.msg_controllen = control_buf_len_;
 
     result = recvmsg(recvsock_, &m, 0);
@@ -537,20 +499,20 @@ 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!
     inet_ntop(AF_INET6, &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, &from.sin6_addr, addr_str, INET6_ADDRSTRLEN);
     pkt->remote_addr_ = IOAddress(string(addr_str));
 
@@ -562,8 +524,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 39061da..249c7ef 100644
--- a/src/bin/dhcp6/iface_mgr.h
+++ b/src/bin/dhcp6/iface_mgr.h
@@ -16,88 +16,214 @@
 #define IFACE_MGR_H
 
 #include <list>
-#include "io_address.h"
-#include "dhcp6/pkt6.h"
+#include <boost/shared_ptr.hpp>
+#include <boost/scoped_array.hpp>
+#include <boost/noncopyable.hpp>
+#include "asiolink/io_address.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 95d2261..5323811 100644
--- a/src/bin/dhcp6/main.cc
+++ b/src/bin/dhcp6/main.cc
@@ -26,8 +26,11 @@
 #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>
@@ -37,12 +40,9 @@
 
 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 {
 
@@ -97,8 +97,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 5dcab86..0000000
--- a/src/bin/dhcp6/pkt6.cc
+++ /dev/null
@@ -1,46 +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 "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& ex) {
-	// 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 9a14d92..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 "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 96c767e..f9a1d9d 100644
--- a/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc
+++ b/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc
@@ -19,13 +19,33 @@
 #include <arpa/inet.h>
 #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() {
@@ -33,21 +53,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 c9a9d72..5ce73f8 100644
--- a/src/bin/dhcp6/tests/iface_mgr_unittest.cc
+++ b/src/bin/dhcp6/tests/iface_mgr_unittest.cc
@@ -21,12 +21,16 @@
 #include <gtest/gtest.h>
 
 #include "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";
@@ -54,6 +58,113 @@ 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
+    if (socket1>0) {
+        cout << "This is Linux, using lo as loopback." << endl;
+        close(socket1);
+    } else {
+        // this fails on Linux and succeeds on BSD
+        socket1 = ifacemgr->openSocket("lo0", mcastAddr, 10547);
+        if (socket1>0) {
+            sprintf(LOOPBACK, "lo0");
+            cout << "This is BSD, using lo0 as loopback." << endl;
+            close(socket1);
+        } 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
 
@@ -72,23 +183,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.
@@ -98,10 +220,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
@@ -153,17 +275,22 @@ 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);
     EXPECT_GT(socket1, 0); // socket > 0
 
     // bind unicast socket to port 10548
-    int socket2 = ifacemgr->openSocket("lo", loAddr, 10548);
+    int socket2 = ifacemgr->openSocket(LOOPBACK, loAddr, 10548);
     EXPECT_GT(socket2, 0);
 
     // 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);
-    EXPECT_GT(socket3, 0); // socket > 0
+    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.
 
@@ -186,12 +313,12 @@ 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);
     EXPECT_GT(socket1, 0); // socket > 0
 
     // 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);
     EXPECT_GT(socket2, 0);
 
     // there's no good way to test negative case here.
@@ -214,49 +341,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 5054c45..0000000
--- a/src/bin/dhcp6/tests/pkt6_unittest.cc
+++ /dev/null
@@ -1,44 +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>
-
-#include <arpa/inet.h>
-#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/bin/msgq/Makefile.am b/src/bin/msgq/Makefile.am
index 0eebf00..908cab5 100644
--- a/src/bin/msgq/Makefile.am
+++ b/src/bin/msgq/Makefile.am
@@ -1,7 +1,7 @@
 SUBDIRS = . tests
 
 pkglibexecdir = $(libexecdir)/@PACKAGE@
- 
+
 pkglibexec_SCRIPTS = b10-msgq
 
 CLEANFILES = b10-msgq msgq.pyc
diff --git a/src/bin/msgq/msgq.py.in b/src/bin/msgq/msgq.py.in
index 06fe840..333ae89 100755
--- a/src/bin/msgq/msgq.py.in
+++ b/src/bin/msgq/msgq.py.in
@@ -28,7 +28,6 @@ import struct
 import errno
 import time
 import select
-import pprint
 import random
 from optparse import OptionParser, OptionValueError
 import isc.util.process
@@ -96,10 +95,10 @@ class MsgQ:
                                "@PACKAGE_NAME@",
                                "msgq_socket").replace("${prefix}",
                                                       "@prefix@")
-    
+
     def __init__(self, socket_file=None, verbose=False):
         """Initialize the MsgQ master.
-        
+
         The socket_file specifies the path to the UNIX domain socket
         that the msgq process listens on. If it is None, the
         environment variable BIND10_MSGQ_SOCKET_FILE is used. If that
@@ -135,7 +134,7 @@ class MsgQ:
             self.poller = select.poll()
         except AttributeError:
             self.kqueue = select.kqueue()
-    
+
     def add_kqueue_socket(self, socket, write_filter=False):
         """Add a kquque filter for a socket.  By default the read
         filter is used; if write_filter is set to True, the write
@@ -167,7 +166,7 @@ class MsgQ:
                              self.socket_file)
 
         self.listen_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
-        
+
         if os.path.exists(self.socket_file):
             os.remove(self.socket_file)
         try:
@@ -196,7 +195,7 @@ class MsgQ:
 
         if self.verbose:
             sys.stdout.write("[b10-msgq] Listening\n")
-        
+
         self.runnable = True
 
     def process_accept(self):
@@ -293,9 +292,6 @@ class MsgQ:
             sys.stderr.write("[b10-msgq] Routing decode error: %s\n" % err)
             return
 
-#        sys.stdout.write("\t" + pprint.pformat(routingmsg) + "\n")
-#        sys.stdout.write("\t" + pprint.pformat(data) + "\n")
-
         self.process_command(fd, sock, routingmsg, data)
 
     def process_command(self, fd, sock, routing, data):
@@ -357,7 +353,18 @@ class MsgQ:
         if fileno in self.sendbuffs:
             amount_sent = 0
         else:
-            amount_sent = self.__send_data(sock, msg)
+            try:
+                amount_sent = self.__send_data(sock, msg)
+            except socket.error as sockerr:
+                # in the case the other side seems gone, kill the socket
+                # and drop the send action
+                if sockerr.errno == errno.EPIPE:
+                    print("[b10-msgq] SIGPIPE on send, dropping message " +
+                          "and closing connection")
+                    self.kill_socket(fileno, sock)
+                    return
+                else:
+                    raise
 
         # Still something to send
         if amount_sent < len(msg):
@@ -448,12 +455,12 @@ class MsgQ:
 
     def run(self):
         """Process messages.  Forever.  Mostly."""
-        
+
         if self.poller:
             self.run_poller()
         else:
             self.run_kqueue()
-    
+
     def run_poller(self):
         while True:
             try:
@@ -511,7 +518,7 @@ def signal_handler(signal, frame):
 
 if __name__ == "__main__":
     def check_port(option, opt_str, value, parser):
-        """Function to insure that the port we are passed is actually 
+        """Function to insure that the port we are passed is actually
         a valid port number. Used by OptionParser() on startup."""
         intval = int(value)
         if (intval < 0) or (intval > 65535):
diff --git a/src/bin/resolver/resolver.cc b/src/bin/resolver/resolver.cc
index 6af383a..bb1eb3b 100644
--- a/src/bin/resolver/resolver.cc
+++ b/src/bin/resolver/resolver.cc
@@ -540,7 +540,7 @@ ResolverImpl::processNormalQuery(const IOMessage& io_message,
     // ACL passed.  Reject inappropriate queries for the resolver.
     if (qtype == RRType::AXFR()) {
         if (io_message.getSocket().getProtocol() == IPPROTO_UDP) {
-            // Can't process AXFR request receoved over UDP
+            // Can't process AXFR request received over UDP
             LOG_DEBUG(resolver_logger, RESOLVER_DBG_PROCESS, RESOLVER_AXFR_UDP);
             makeErrorMessage(query_message, answer_message, buffer,
                              Rcode::FORMERR());
diff --git a/src/bin/resolver/resolver_log.h b/src/bin/resolver/resolver_log.h
index 8378b98..e0e3fda 100644
--- a/src/bin/resolver/resolver_log.h
+++ b/src/bin/resolver/resolver_log.h
@@ -23,20 +23,20 @@
 /// Defines the levels used to output debug messages in the resolver.  Note that
 /// higher numbers equate to more verbose (and detailed) output.
 
-// Initialization
-const int RESOLVER_DBG_INIT = 10;
+// Initialization and shutdown of the resolver.
+const int RESOLVER_DBG_INIT = DBGLVL_START_SHUT;
 
 // Configuration messages
-const int RESOLVER_DBG_CONFIG = 30;
+const int RESOLVER_DBG_CONFIG = DBGLVL_COMMAND;
 
 // Trace sending and receiving of messages
-const int RESOLVER_DBG_IO = 50;
+const int RESOLVER_DBG_IO = DBGLVL_TRACE_BASIC;
 
 // Trace processing of messages
-const int RESOLVER_DBG_PROCESS = 70;
+const int RESOLVER_DBG_PROCESS = DBGLVL_TRACE_DETAIL;
 
 // Detailed message information
-const int RESOLVER_DBG_DETAIL = 90;
+const int RESOLVER_DBG_DETAIL = DBGLVL_TRACE_DETAIL_DATA;
 
 
 /// \brief Resolver Logger
diff --git a/src/bin/resolver/tests/Makefile.am b/src/bin/resolver/tests/Makefile.am
index 14d92fe..12ddab3 100644
--- a/src/bin/resolver/tests/Makefile.am
+++ b/src/bin/resolver/tests/Makefile.am
@@ -60,4 +60,4 @@ run_unittests_CXXFLAGS += -Wno-unused-parameter
 endif
 endif
 
-check_PROGRAMS = $(TESTS)
+noinst_PROGRAMS = $(TESTS)
diff --git a/src/bin/sockcreator/tests/Makefile.am b/src/bin/sockcreator/tests/Makefile.am
index b3ca344..223e761 100644
--- a/src/bin/sockcreator/tests/Makefile.am
+++ b/src/bin/sockcreator/tests/Makefile.am
@@ -21,4 +21,4 @@ run_unittests_LDADD += $(top_builddir)/src/lib/util/unittests/libutil_unittests.
 run_unittests_LDADD += $(top_builddir)/src/lib/util/io/libutil_io.la
 endif
 
-check_PROGRAMS = $(TESTS)
+noinst_PROGRAMS = $(TESTS)
diff --git a/src/bin/stats/stats.py.in b/src/bin/stats/stats.py.in
index da00818..3a7f47a 100755
--- a/src/bin/stats/stats.py.in
+++ b/src/bin/stats/stats.py.in
@@ -32,9 +32,8 @@ from isc.log_messages.stats_messages import *
 isc.log.init("b10-stats")
 logger = isc.log.Logger("stats")
 
-# Some constants for debug levels, these should be removed when we
-# have #1074
-DBG_STATS_MESSAGING = 30
+# Some constants for debug levels.
+DBG_STATS_MESSAGING = logger.DBGLVL_COMMAND
 
 # This is for boot_time of Stats
 _BASETIME = gmtime()
diff --git a/src/bin/stats/stats_httpd.py.in b/src/bin/stats/stats_httpd.py.in
index 08d60bb..b3df28c 100644
--- a/src/bin/stats/stats_httpd.py.in
+++ b/src/bin/stats/stats_httpd.py.in
@@ -41,10 +41,9 @@ from isc.log_messages.stats_httpd_messages import *
 isc.log.init("b10-stats-httpd")
 logger = isc.log.Logger("stats-httpd")
 
-# Some constants for debug levels, these should be removed when we
-# have #1074
-DBG_STATHTTPD_INIT = 10
-DBG_STATHTTPD_MESSAGING = 30
+# Some constants for debug levels.
+DBG_STATHTTPD_INIT = logger.DBGLVL_START_SHUT
+DBG_STATHTTPD_MESSAGING = logger.DBGLVL_COMMAND
 
 # If B10_FROM_SOURCE is set in the environment, we use data files
 # from a directory relative to that, otherwise we use the ones
diff --git a/src/bin/stats/tests/Makefile.am b/src/bin/stats/tests/Makefile.am
index b5edc59..afd572f 100644
--- a/src/bin/stats/tests/Makefile.am
+++ b/src/bin/stats/tests/Makefile.am
@@ -1,7 +1,7 @@
 PYCOVERAGE_RUN = @PYCOVERAGE_RUN@
 PYTESTS = b10-stats_test.py b10-stats-httpd_test.py
 EXTRA_DIST = $(PYTESTS) test_utils.py
-CLEANFILES = test_utils.pyc
+CLEANFILES = test_utils.pyc msgq_socket_test
 
 # If necessary (rare cases), explicitly specify paths to dynamic libraries
 # required by loadable python modules.
@@ -22,6 +22,7 @@ endif
 	$(LIBRARY_PATH_PLACEHOLDER) \
 	PYTHONPATH=$(COMMON_PYTHON_PATH):$(abs_top_builddir)/src/bin/stats:$(abs_top_builddir)/src/bin/stats/tests:$(abs_top_builddir)/src/bin/msgq:$(abs_top_builddir)/src/lib/python/isc/config \
 	B10_FROM_SOURCE=$(abs_top_srcdir) \
+	BIND10_MSGQ_SOCKET_FILE=$(abs_top_builddir)/msgq_socket \
 	CONFIG_TESTDATA_PATH=$(abs_top_srcdir)/src/lib/config/tests/testdata \
 	$(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
 	done
diff --git a/src/bin/stats/tests/b10-stats-httpd_test.py b/src/bin/stats/tests/b10-stats-httpd_test.py
index 1fe7aca..e0dafc2 100644
--- a/src/bin/stats/tests/b10-stats-httpd_test.py
+++ b/src/bin/stats/tests/b10-stats-httpd_test.py
@@ -134,23 +134,6 @@ class TestHttpHandler(unittest.TestCase):
         self.assertEqual(len(self.stats_httpd.httpd), 1)
         self.assertEqual((self.address, self.port), self.stats_httpd.http_addrs[0])
 
-        """
-        self.client.putrequest('GET', stats_httpd.XML_URL_PATH)
-        self.client.endheaders()
-        response = self.client.getresponse()
-        self.assertEqual(response.getheader("Content-type"), "text/xml")
-        self.assertTrue(int(response.getheader("Content-Length")) > 0)
-        self.assertEqual(response.status, 200)
-        root = xml.etree.ElementTree.parse(response).getroot()
-        self.assertTrue(root.tag.find('statistics') > 0)
-        for (k,v) in root.attrib.items():
-            if k.find('schemaLocation') > 0:
-                self.assertEqual(v, stats_httpd.XSD_NAMESPACE + ' ' + stats_httpd.XSD_URL_PATH)
-        for mod in DUMMY_DATA:
-            for (item, value) in DUMMY_DATA[mod].items():
-                self.assertIsNotNone(root.find(mod + '/' + item))
-        """
-
         def check_XML_URL_PATH(mod=None, item=None):
             url_path = stats_httpd.XML_URL_PATH
             if mod is not None:
@@ -226,7 +209,12 @@ class TestHttpHandler(unittest.TestCase):
                 check_XSD_URL_PATH(mod=m, item=k)
 
         def check_XSL_URL_PATH(mod=None, item=None):
-            self.client.putrequest('GET', stats_httpd.XSL_URL_PATH)
+            url_path = stats_httpd.XSL_URL_PATH
+            if mod is not None:
+                url_path = url_path + '/' + mod
+                if item is not None:
+                    url_path = url_path + '/' + item
+            self.client.putrequest('GET', url_path)
             self.client.endheaders()
             response = self.client.getresponse()
             self.assertEqual(response.getheader("Content-type"), "text/xml")
@@ -257,65 +245,12 @@ class TestHttpHandler(unittest.TestCase):
 
         # URL is '/bind10/statistics/xsl'
         check_XSL_URL_PATH(mod=None, item=None)
-        #for m in DUMMY_DATA:
-        #    # URL is '/bind10/statistics/xsl/Module'
-        #    check_XSL_URL_PATH(mod=m)
-        #    for k in DUMMY_DATA[m].keys():
-        #        # URL is '/bind10/statistics/xsl/Module/Item'
-        #        check_XSL_URL_PATH(mod=m, item=k)
-
-        """
-        # URL is '/bind10/statitics/xsd/Auth/queries.tcp/'
-        self.client.putrequest('GET', stats_httpd.XSD_URL_PATH + '/Auth/queries.tcp/')
-        self.client.endheaders()
-        response = self.client.getresponse()
-        self.assertEqual(response.getheader("Content-type"), "text/xml")
-        self.assertTrue(int(response.getheader("Content-Length")) > 0)
-        self.assertEqual(response.status, 200)
-        root = xml.etree.ElementTree.parse(response).getroot()
-        url_xmlschema = '{http://www.w3.org/2001/XMLSchema}'
-        tags = [ url_xmlschema + t for t in [ 'element', 'complexType', 'all', 'element' ] ]
-        xsdpath = '/'.join(tags)
-        self.assertTrue(root.tag.find('schema') > 0)
-        self.assertTrue(hasattr(root, 'attrib'))
-        self.assertTrue('targetNamespace' in root.attrib)
-        self.assertEqual(root.attrib['targetNamespace'],
-                         stats_httpd.XSD_NAMESPACE)
-        for elm in root.findall(xsdpath):
-            self.assertIsNotNone(elm.attrib['name'])
-            self.assertTrue(elm.attrib['name'] in DUMMY_DATA)
-        """
-
-        # URL is '/bind10/statitics/xsl'
-
-        """
-        # URL is '/bind10/statitics/xsl/Auth/queries.tcp/'
-        self.client.putrequest('GET', stats_httpd.XSL_URL_PATH + '/Auth/queries.tcp/')
-        self.client.endheaders()
-        response = self.client.getresponse()
-        self.assertEqual(response.getheader("Content-type"), "text/xml")
-        self.assertTrue(int(response.getheader("Content-Length")) > 0)
-        self.assertEqual(response.status, 200)
-        root = xml.etree.ElementTree.parse(response).getroot()
-        url_trans = '{http://www.w3.org/1999/XSL/Transform}'
-        url_xhtml = '{http://www.w3.org/1999/xhtml}'
-        xslpath = url_trans + 'template/' + url_xhtml + 'tr'
-        self.assertEqual(root.tag, url_trans + 'stylesheet')
-        for tr in root.findall(xslpath):
-            tds = tr.findall(url_xhtml + 'td')
-            self.assertIsNotNone(tds)
-            self.assertEqual(type(tds), list)
-            self.assertTrue(len(tds) > 2)
-            self.assertTrue(hasattr(tds[0], 'text'))
-            self.assertTrue(tds[0].text in DUMMY_DATA)
-            valueof = tds[2].find(url_trans + 'value-of')
-            self.assertIsNotNone(valueof)
-            self.assertTrue(hasattr(valueof, 'attrib'))
-            self.assertIsNotNone(valueof.attrib)
-            self.assertTrue('select' in valueof.attrib)
-            self.assertTrue(valueof.attrib['select'] in \
-                                [ tds[0].text+'/'+item for item in DUMMY_DATA[tds[0].text].keys() ])
-        """
+        for m in DUMMY_DATA:
+            # URL is '/bind10/statistics/xsl/Module'
+            check_XSL_URL_PATH(mod=m)
+            for k in DUMMY_DATA[m].keys():
+                # URL is '/bind10/statistics/xsl/Module/Item'
+                check_XSL_URL_PATH(mod=m, item=k)
 
         # 302 redirect
         self.client._http_vsn_str = 'HTTP/1.1'
diff --git a/src/bin/stats/tests/isc/log_messages/Makefile.am b/src/bin/stats/tests/isc/log_messages/Makefile.am
deleted file mode 100644
index 90b4499..0000000
--- a/src/bin/stats/tests/isc/log_messages/Makefile.am
+++ /dev/null
@@ -1,7 +0,0 @@
-EXTRA_DIST = __init__.py stats_messages.py stats_httpd_messages.py
-CLEANFILES = __init__.pyc stats_messages.pyc stats_httpd_messages.pyc
-
-CLEANDIRS = __pycache__
-
-clean-local:
-	rm -rf $(CLEANDIRS)
diff --git a/src/bin/stats/tests/isc/log_messages/__init__.py b/src/bin/stats/tests/isc/log_messages/__init__.py
deleted file mode 100644
index 58e99e3..0000000
--- a/src/bin/stats/tests/isc/log_messages/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright (C) 2011  Internet Systems 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 INTERNET SYSTEMS CONSORTIUM
-# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# INTERNET SYSTEMS CONSORTIUM 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.
-
-'''
-This is a fake package that acts as a forwarder to the real package.
-'''
diff --git a/src/bin/stats/tests/isc/log_messages/stats_httpd_messages.py b/src/bin/stats/tests/isc/log_messages/stats_httpd_messages.py
deleted file mode 100644
index 0adb0f0..0000000
--- a/src/bin/stats/tests/isc/log_messages/stats_httpd_messages.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright (C) 2011  Internet Systems 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 INTERNET SYSTEMS CONSORTIUM
-# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# INTERNET SYSTEMS CONSORTIUM 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.
-
-from work.stats_httpd_messages import *
diff --git a/src/bin/stats/tests/isc/log_messages/stats_messages.py b/src/bin/stats/tests/isc/log_messages/stats_messages.py
deleted file mode 100644
index c05a6a8..0000000
--- a/src/bin/stats/tests/isc/log_messages/stats_messages.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright (C) 2011  Internet Systems 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 INTERNET SYSTEMS CONSORTIUM
-# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-# INTERNET SYSTEMS CONSORTIUM 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.
-
-from work.stats_messages import *
diff --git a/src/bin/stats/tests/test_utils.py b/src/bin/stats/tests/test_utils.py
index 20c5b16..83d3cde 100644
--- a/src/bin/stats/tests/test_utils.py
+++ b/src/bin/stats/tests/test_utils.py
@@ -16,10 +16,6 @@ import isc.config.cfgmgr
 import stats
 import stats_httpd
 
-# Change value of BIND10_MSGQ_SOCKET_FILE in environment variables
-if 'BIND10_MSGQ_SOCKET_FILE' not in os.environ:
-    os.environ['BIND10_MSGQ_SOCKET_FILE'] = tempfile.mktemp(prefix='msgq_socket_')
-
 class SignalHandler():
     """A signal handler class for deadlock in unittest"""
     def __init__(self, fail_handler, timeout=20):
@@ -112,7 +108,7 @@ class MockMsgq:
             self.msgq.shutdown()
 
     def shutdown(self):
-        # do nothing for avoiding shutting down the msgq twice
+        # do nothing
         pass
 
 class MockCfgmgr:
@@ -417,3 +413,10 @@ class BaseModules:
         self.cfgmgr.shutdown()
         # MockMsgq
         self.msgq.shutdown()
+        # remove the unused socket file
+        socket_file = self.msgq.server.msgq.socket_file
+        try:
+            if os.path.exists(socket_file):
+                os.remove(socket_file)
+        except OSError:
+            pass
diff --git a/src/bin/xfrin/tests/xfrin_test.py b/src/bin/xfrin/tests/xfrin_test.py
index 65bd968..401b4a7 100644
--- a/src/bin/xfrin/tests/xfrin_test.py
+++ b/src/bin/xfrin/tests/xfrin_test.py
@@ -16,6 +16,7 @@
 import unittest
 import shutil
 import socket
+import sys
 import io
 from isc.testutils.tsigctx_mock import MockTSIGContext
 from xfrin import *
@@ -216,8 +217,8 @@ class MockXfrin(Xfrin):
                                  request_type, check_soa)
 
 class MockXfrinConnection(XfrinConnection):
-    def __init__(self, sock_map, zone_name, rrclass, shutdown_event,
-                 master_addr):
+    def __init__(self, sock_map, zone_name, rrclass, datasrc_client,
+                 shutdown_event, master_addr, tsig_key=None):
         super().__init__(sock_map, zone_name, rrclass, MockDataSourceClient(),
                          shutdown_event, master_addr)
         self.query_data = b''
@@ -300,8 +301,9 @@ class TestXfrinState(unittest.TestCase):
     def setUp(self):
         self.sock_map = {}
         self.conn = MockXfrinConnection(self.sock_map, TEST_ZONE_NAME,
-                                        TEST_RRCLASS, threading.Event(),
+                                        TEST_RRCLASS, None, threading.Event(),
                                         TEST_MASTER_IPV4_ADDRINFO)
+        self.conn.init_socket()
         self.begin_soa = RRset(TEST_ZONE_NAME, TEST_RRCLASS, RRType.SOA(),
                                RRTTL(3600))
         self.begin_soa.add_rdata(Rdata(RRType.SOA(), TEST_RRCLASS,
@@ -585,8 +587,9 @@ class TestXfrinConnection(unittest.TestCase):
             os.remove(TEST_DB_FILE)
         self.sock_map = {}
         self.conn = MockXfrinConnection(self.sock_map, TEST_ZONE_NAME,
-                                        TEST_RRCLASS, threading.Event(),
+                                        TEST_RRCLASS, None, threading.Event(),
                                         TEST_MASTER_IPV4_ADDRINFO)
+        self.conn.init_socket()
         self.soa_response_params = {
             'questions': [example_soa_question],
             'bad_qid': False,
@@ -720,14 +723,16 @@ class TestAXFR(TestXfrinConnection):
         # to confirm an AF_INET6 socket has been created.  A naive application
         # tends to assume it's IPv4 only and hardcode AF_INET.  This test
         # uncovers such a bug.
-        c = MockXfrinConnection({}, TEST_ZONE_NAME, TEST_RRCLASS,
+        c = MockXfrinConnection({}, TEST_ZONE_NAME, TEST_RRCLASS, None,
                                 threading.Event(), TEST_MASTER_IPV6_ADDRINFO)
+        c.init_socket()
         c.bind(('::', 0))
         c.close()
 
     def test_init_chclass(self):
-        c = MockXfrinConnection({}, TEST_ZONE_NAME, RRClass.CH(),
+        c = MockXfrinConnection({}, TEST_ZONE_NAME, RRClass.CH(), None,
                                 threading.Event(), TEST_MASTER_IPV4_ADDRINFO)
+        c.init_socket()
         axfrmsg = c._create_query(RRType.AXFR())
         self.assertEqual(axfrmsg.get_question()[0].get_class(),
                          RRClass.CH())
@@ -1679,6 +1684,110 @@ class TestXfrinRecorder(unittest.TestCase):
         self.recorder.decrement(TEST_ZONE_NAME)
         self.assertEqual(self.recorder.xfrin_in_progress(TEST_ZONE_NAME), False)
 
+class TestXfrinProcess(unittest.TestCase):
+    def setUp(self):
+        self.unlocked = False
+        self.conn_closed = False
+        self.do_raise_on_close = False
+        self.do_raise_on_connect = False
+        self.do_raise_on_publish = False
+        self.master = (socket.AF_INET, socket.SOCK_STREAM,
+                       (TEST_MASTER_IPV4_ADDRESS, TEST_MASTER_PORT))
+
+    def tearDown(self):
+        # whatever happens the lock acquired in xfrin_recorder.increment
+        # must always be released.  We checked the condition for all test
+        # cases.
+        self.assertTrue(self.unlocked)
+
+        # Same for the connection
+        self.assertTrue(self.conn_closed)
+
+    def increment(self, zone_name):
+        '''Fake method of xfrin_recorder.increment.
+
+        '''
+        self.unlocked = False
+
+    def decrement(self, zone_name):
+        '''Fake method of xfrin_recorder.decrement.
+
+        '''
+        self.unlocked = True
+
+    def publish_xfrin_news(self, zone_name, rrclass, ret):
+        '''Fake method of serve.publish_xfrin_news
+
+        '''
+        if self.do_raise_on_publish:
+            raise XfrinTestException('Emulated exception in publish')
+
+    def connect_to_master(self, conn):
+        self.sock_fd = conn.fileno()
+        if self.do_raise_on_connect:
+            raise XfrinTestException('Emulated exception in connect')
+        return True
+
+    def conn_close(self, conn):
+        self.conn_closed = True
+        XfrinConnection.close(conn)
+        if self.do_raise_on_close:
+            raise XfrinTestException('Emulated exception in connect')
+
+    def create_xfrinconn(self, sock_map, zone_name, rrclass, datasrc_client,
+                         shutdown_event, master_addrinfo, tsig_key):
+        conn = MockXfrinConnection(sock_map, zone_name, rrclass,
+                                   datasrc_client, shutdown_event,
+                                   master_addrinfo, tsig_key)
+
+        # An awkward check that would specifically identify an old bug
+        # where initialziation of XfrinConnection._tsig_ctx_creator caused
+        # self reference and subsequently led to reference leak.
+        orig_ref = sys.getrefcount(conn)
+        conn._tsig_ctx_creator = None
+        self.assertEqual(orig_ref, sys.getrefcount(conn))
+
+        # Replace some methods for connect with our internal ones for the
+        # convenience of tests
+        conn.connect_to_master = lambda : self.connect_to_master(conn)
+        conn.do_xfrin = lambda x, y : XFRIN_OK
+        conn.close = lambda : self.conn_close(conn)
+
+        return conn
+
+    def test_process_xfrin_normal(self):
+        # Normal, successful case.  We only check that things are cleaned up
+        # at the tearDown time.
+        process_xfrin(self, self, TEST_ZONE_NAME, TEST_RRCLASS, None, None,
+                      self.master,  False, None, RRType.AXFR(),
+                      self.create_xfrinconn)
+
+    def test_process_xfrin_exception_on_connect(self):
+        # connect_to_master() will raise an exception.  Things must still be
+        # cleaned up.
+        self.do_raise_on_connect = True
+        process_xfrin(self, self, TEST_ZONE_NAME, TEST_RRCLASS, None, None,
+                      self.master,  False, None, RRType.AXFR(),
+                      self.create_xfrinconn)
+
+    def test_process_xfrin_exception_on_close(self):
+        # connect() will result in exception, and even the cleanup close()
+        # will fail with an exception.  This should be quite likely a bug,
+        # but we deal with that case.
+        self.do_raise_on_connect = True
+        self.do_raise_on_close = True
+        process_xfrin(self, self, TEST_ZONE_NAME, TEST_RRCLASS, None, None,
+                      self.master,  False, None, RRType.AXFR(),
+                      self.create_xfrinconn)
+
+    def test_process_xfrin_exception_on_publish(self):
+        # xfr succeeds but notifying the zonemgr fails with exception.
+        # everything must still be cleaned up.
+        self.do_raise_on_publish = True
+        process_xfrin(self, self, TEST_ZONE_NAME, TEST_RRCLASS, None, None,
+                      self.master,  False, None, RRType.AXFR(),
+                      self.create_xfrinconn)
+
 class TestXfrin(unittest.TestCase):
     def setUp(self):
         # redirect output
diff --git a/src/bin/xfrin/xfrin.py.in b/src/bin/xfrin/xfrin.py.in
index 1f5d9a1..bd5635e 100755
--- a/src/bin/xfrin/xfrin.py.in
+++ b/src/bin/xfrin/xfrin.py.in
@@ -64,8 +64,8 @@ ZONE_MANAGER_MODULE_NAME = 'Zonemgr'
 REFRESH_FROM_ZONEMGR = 'refresh_from_zonemgr'
 ZONE_XFRIN_FAILED = 'zone_xfrin_failed'
 
-# Constants for debug levels, to be removed when we have #1074.
-DBG_XFRIN_TRACE = 3
+# Constants for debug levels.
+DBG_XFRIN_TRACE = logger.DBGLVL_TRACE_BASIC
 
 # These two default are currently hard-coded. For config this isn't
 # necessary, but we need these defaults for optional command arguments
@@ -323,6 +323,7 @@ class XfrinFirstData(XfrinState):
                  conn.zone_str())
             # We are now going to add RRs to the new zone.  We need create
             # a Diff object.  It will be used throughtout the XFR session.
+            # DISABLE FOR DEBUG
             conn._diff = Diff(conn._datasrc_client, conn._zone_name, True)
             self.set_xfrstate(conn, XfrinAXFR())
         return False
@@ -468,21 +469,27 @@ class XfrinConnection(asyncore.dispatcher):
         # Data source handler
         self._datasrc_client = datasrc_client
 
-        self.create_socket(master_addrinfo[0], master_addrinfo[1])
         self._sock_map = sock_map
         self._soa_rr_count = 0
         self._idle_timeout = idle_timeout
-        self.setblocking(1)
         self._shutdown_event = shutdown_event
-        self._master_address = master_addrinfo[2]
+        self._master_addrinfo = master_addrinfo
         self._tsig_key = tsig_key
         self._tsig_ctx = None
         # tsig_ctx_creator is introduced to allow tests to use a mock class for
         # easier tests (in normal case we always use the default)
-        self._tsig_ctx_creator = self.__create_tsig_ctx
+        self._tsig_ctx_creator = lambda key : TSIGContext(key)
 
-    def __create_tsig_ctx(self, key):
-        return TSIGContext(key)
+    def init_socket(self):
+        '''Initialize the underlyig socket.
+
+        This is essentially a part of __init__() and is expected to be
+        called immediately after the constructor.  It's separated from
+        the constructor because otherwise we might not be able to close
+        it if the constructor raises an exception after opening the socket.
+        '''
+        self.create_socket(self._master_addrinfo[0], self._master_addrinfo[1])
+        self.setblocking(1)
 
     def __set_xfrstate(self, new_state):
         self.__state = new_state
@@ -498,10 +505,11 @@ class XfrinConnection(asyncore.dispatcher):
         '''Connect to master in TCP.'''
 
         try:
-            self.connect(self._master_address)
+            self.connect(self._master_addrinfo[2])
             return True
         except socket.error as e:
-            logger.error(XFRIN_CONNECT_MASTER, self._master_address, str(e))
+            logger.error(XFRIN_CONNECT_MASTER, self._master_addrinfo[2],
+                         str(e))
             return False
 
     def _get_zone_soa(self):
@@ -697,7 +705,6 @@ class XfrinConnection(asyncore.dispatcher):
             # (if not yet - possible in case of xfr-level exception) as soon
             # as possible
             self._diff = None
-            self.close()
 
         return ret
 
@@ -730,33 +737,6 @@ class XfrinConnection(asyncore.dispatcher):
         if msg.get_rr_count(Message.SECTION_QUESTION) > 1:
             raise XfrinException('query section count greater than 1')
 
-    def _handle_answer_section(self, answer_section):
-        '''Return a generator for the reponse in one tcp package to a zone transfer.'''
-
-        for rrset in answer_section:
-            rrset_name = rrset.get_name().to_text()
-            rrset_ttl = int(rrset.get_ttl().to_text())
-            rrset_class = rrset.get_class().to_text()
-            rrset_type = rrset.get_type().to_text()
-
-            for rdata in rrset.get_rdata():
-                # Count the soa record count
-                if rrset.get_type() == RRType.SOA():
-                    self._soa_rr_count += 1
-
-                    # XXX: the current DNS message parser can't preserve the
-                    # RR order or separete the beginning and ending SOA RRs.
-                    # As a short term workaround, we simply ignore the second
-                    # SOA, and ignore the erroneous case where the transfer
-                    # session doesn't end with an SOA.
-                    if (self._soa_rr_count == 2):
-                        # Avoid inserting soa record twice
-                        break
-
-                rdata_text = rdata.to_text()
-                yield (rrset_name, rrset_ttl, rrset_class, rrset_type,
-                       rdata_text)
-
     def _handle_xfrin_responses(self):
         read_next_msg = True
         while read_next_msg:
@@ -794,47 +774,82 @@ class XfrinConnection(asyncore.dispatcher):
 
         return False
 
-    def log_info(self, msg, type='info'):
-        # Overwrite the log function, log nothing
-        pass
-
-def process_xfrin(server, xfrin_recorder, zone_name, rrclass, db_file,
-                  shutdown_event, master_addrinfo, check_soa, tsig_key,
-                  request_type):
-    xfrin_recorder.increment(zone_name)
-
-    # Create a data source client used in this XFR session.  Right now we
-    # still assume an sqlite3-based data source, and use both the old and new
-    # data source APIs.  We also need to use a mock client for tests.
-    # For a temporary workaround to deal with these situations, we skip the
-    # creation when the given file is none (the test case).  Eventually
-    # this code will be much cleaner.
-    datasrc_client = None
-    if db_file is not None:
-        # temporary hardcoded sqlite initialization. Once we decide on
-        # the config specification, we need to update this (TODO)
-        # this may depend on #1207, or any followup ticket created for #1207
-        datasrc_type = "sqlite3"
-        datasrc_config = "{ \"database_file\": \"" + db_file + "\"}"
-        datasrc_client = DataSourceClient(datasrc_type, datasrc_config)
-
-    # Create a TCP connection for the XFR session and perform the operation.
-    sock_map = {}
-    conn = XfrinConnection(sock_map, zone_name, rrclass, datasrc_client,
-                           shutdown_event, master_addrinfo, tsig_key)
-    # XXX: We still need _db_file for temporary workaround in _create_query().
-    # This should be removed when we eliminate the need for the workaround.
-    conn._db_file = db_file
+def __process_xfrin(server, zone_name, rrclass, db_file,
+                    shutdown_event, master_addrinfo, check_soa, tsig_key,
+                    request_type, conn_class=XfrinConnection):
+    conn = None
+    exception = None
     ret = XFRIN_FAIL
-    if conn.connect_to_master():
-        ret = conn.do_xfrin(check_soa, request_type)
+    try:
+        # Create a data source client used in this XFR session.  Right now we
+        # still assume an sqlite3-based data source, and use both the old and
+        # new data source APIs.  We also need to use a mock client for tests.
+        # For a temporary workaround to deal with these situations, we skip the
+        # creation when the given file is none (the test case).  Eventually
+        # this code will be much cleaner.
+        datasrc_client = None
+        if db_file is not None:
+            # temporary hardcoded sqlite initialization. Once we decide on
+            # the config specification, we need to update this (TODO)
+            # this may depend on #1207, or any followup ticket created for #1207
+            datasrc_type = "sqlite3"
+            datasrc_config = "{ \"database_file\": \"" + db_file + "\"}"
+            datasrc_client = DataSourceClient(datasrc_type, datasrc_config)
+
+        # Create a TCP connection for the XFR session and perform the operation
+        sock_map = {}
+        conn = conn_class(sock_map, zone_name, rrclass, datasrc_client,
+                          shutdown_event, master_addrinfo, tsig_key)
+        conn.init_socket()
+        # XXX: We still need _db_file for temporary workaround in _create_query().
+        # This should be removed when we eliminate the need for the workaround.
+        conn._db_file = db_file
+        if conn.connect_to_master():
+            ret = conn.do_xfrin(check_soa, request_type)
+    except Exception as ex:
+        # If exception happens, just remember it here so that we can re-raise
+        # after cleaning up things.  We don't log it here because we want
+        # eliminate smallest possibility of having an exception in logging
+        # itself.
+        exception = ex
+
+    # asyncore.dispatcher requires explicit close() unless its lifetime
+    # from born to destruction is closed within asyncore.loop, which is not
+    # the case for us.  We always close() here, whether or not do_xfrin
+    # succeeds, and even when we see an unexpected exception.
+    if conn is not None:
+        conn.close()
 
     # Publish the zone transfer result news, so zonemgr can reset the
     # zone timer, and xfrout can notify the zone's slaves if the result
     # is success.
     server.publish_xfrin_news(zone_name, rrclass, ret)
+
+    if exception is not None:
+        raise exception
+
+def process_xfrin(server, xfrin_recorder, zone_name, rrclass, db_file,
+                  shutdown_event, master_addrinfo, check_soa, tsig_key,
+                  request_type, conn_class=XfrinConnection):
+    # Even if it should be rare, the main process of xfrin session can
+    # raise an exception.  In order to make sure the lock in xfrin_recorder
+    # is released in any cases, we delegate the main part to the helper
+    # function in the try block, catch any exceptions, then release the lock.
+    xfrin_recorder.increment(zone_name)
+    exception = None
+    try:
+        __process_xfrin(server, zone_name, rrclass, db_file,
+                        shutdown_event, master_addrinfo, check_soa, tsig_key,
+                        request_type, conn_class)
+    except Exception as ex:
+        # don't log it until we complete decrement().
+        exception = ex
     xfrin_recorder.decrement(zone_name)
 
+    if exception is not None:
+        typestr = "AXFR" if request_type == RRType.AXFR() else "IXFR"
+        logger.error(XFRIN_XFR_PROCESS_FAILURE, typestr, zone_name.to_text(),
+                     str(rrclass), str(exception))
 
 class XfrinRecorder:
     def __init__(self):
diff --git a/src/bin/xfrin/xfrin_messages.mes b/src/bin/xfrin/xfrin_messages.mes
index e5d1733..81bd649 100644
--- a/src/bin/xfrin/xfrin_messages.mes
+++ b/src/bin/xfrin/xfrin_messages.mes
@@ -29,6 +29,21 @@ this can only happen for AXFR.
 The XFR transfer for the given zone has failed due to a protocol error.
 The error is shown in the log message.
 
+% XFRIN_XFR_PROCESS_FAILURE %1 transfer of zone %2/%3 failed: %4
+An XFR session failed outside the main protocol handling.  This
+includes an error at the data source level at the initialization
+phase, unexpected failure in the network connection setup to the
+master server, or even more unexpected failure due to unlikely events
+such as memory allocation failure.  Details of the error are shown in
+the log message.  In general, these errors are not really expected
+ones, and indicate an installation error or a program bug.  The
+session handler thread tries to clean up all intermediate resources
+even on these errors, but it may be incomplete.  So, if this log
+message continuously appears, system resource consumption should be
+checked, and you may even want to disable the corresponding transfers.
+You may also want to file a bug report if this message appears so
+often.
+
 % XFRIN_XFR_TRANSFER_STARTED %1 transfer of zone %2 started
 A connection to the master server has been made, the serial value in
 the SOA record has been checked, and a zone transfer has been started.
diff --git a/src/bin/xfrout/tests/xfrout_test.py.in b/src/bin/xfrout/tests/xfrout_test.py.in
index 85979a0..0a9fd3c 100644
--- a/src/bin/xfrout/tests/xfrout_test.py.in
+++ b/src/bin/xfrout/tests/xfrout_test.py.in
@@ -922,7 +922,7 @@ class TestInitialization(unittest.TestCase):
         self.setEnv("BIND10_XFROUT_SOCKET_FILE", None)
         xfrout.init_paths()
         self.assertEqual(xfrout.UNIX_SOCKET_FILE,
-                         "@@LOCALSTATEDIR@@/auth_xfrout_conn")
+                         "@@LOCALSTATEDIR@@/@PACKAGE_NAME@/auth_xfrout_conn")
 
     def testProvidedSocket(self):
         self.setEnv("B10_FROM_BUILD", None)
diff --git a/src/bin/xfrout/xfrout.py.in b/src/bin/xfrout/xfrout.py.in
index 8049e29..cf3b04f 100755
--- a/src/bin/xfrout/xfrout.py.in
+++ b/src/bin/xfrout/xfrout.py.in
@@ -85,7 +85,7 @@ def init_paths():
         if "BIND10_XFROUT_SOCKET_FILE" in os.environ:
             UNIX_SOCKET_FILE = os.environ["BIND10_XFROUT_SOCKET_FILE"]
         else:
-            UNIX_SOCKET_FILE = "@@LOCALSTATEDIR@@/auth_xfrout_conn"
+            UNIX_SOCKET_FILE = "@@LOCALSTATEDIR@@/@PACKAGE_NAME@/auth_xfrout_conn"
 
 init_paths()
 
diff --git a/src/bin/zonemgr/zonemgr.py.in b/src/bin/zonemgr/zonemgr.py.in
index 5c8d9b5..5bdb765 100755
--- a/src/bin/zonemgr/zonemgr.py.in
+++ b/src/bin/zonemgr/zonemgr.py.in
@@ -43,10 +43,10 @@ from isc.log_messages.zonemgr_messages import *
 isc.log.init("b10-zonemgr")
 logger = isc.log.Logger("zonemgr")
 
-# Constants for debug levels, to be removed when we have #1074.
-DBG_START_SHUT = 0
-DBG_ZONEMGR_COMMAND = 10
-DBG_ZONEMGR_BASIC = 40
+# Constants for debug levels.
+DBG_START_SHUT = logger.DBGLVL_START_SHUT
+DBG_ZONEMGR_COMMAND = logger.DBGLVL_COMMAND
+DBG_ZONEMGR_BASIC = logger.DBGLVL_TRACE_BASIC
 
 isc.util.process.rename()
 
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index 04eee45..a569ea7 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -1,3 +1,3 @@
 SUBDIRS = exceptions util log cryptolink dns cc config acl xfr bench \
           asiolink asiodns nsas cache resolve testutils datasrc \
-          server_common python
+          server_common python dhcp
diff --git a/src/lib/acl/tests/Makefile.am b/src/lib/acl/tests/Makefile.am
index 2074c64..6369511 100644
--- a/src/lib/acl/tests/Makefile.am
+++ b/src/lib/acl/tests/Makefile.am
@@ -37,4 +37,4 @@ run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
 run_unittests_LDADD += $(top_builddir)/src/lib/acl/libdnsacl.la
 endif
 
-check_PROGRAMS = $(TESTS)
+noinst_PROGRAMS = $(TESTS)
diff --git a/src/lib/asiodns/io_fetch.cc b/src/lib/asiodns/io_fetch.cc
index 31b5f50..466be3e 100644
--- a/src/lib/asiodns/io_fetch.cc
+++ b/src/lib/asiodns/io_fetch.cc
@@ -61,17 +61,13 @@ namespace asiodns {
 
 /// Use the ASIO logger
 
-namespace {
-
 isc::log::Logger logger("asiolink");
+
 // Log debug verbosity
-enum {
-    DBG_IMPORTANT = 1,
-    DBG_COMMON = 20,
-    DBG_ALL = 50
-};
 
-}
+const int DBG_IMPORTANT = DBGLVL_TRACE_BASIC;
+const int DBG_COMMON = DBGLVL_TRACE_DETAIL;
+const int DBG_ALL = DBGLVL_TRACE_DETAIL + 20;
 
 /// \brief IOFetch Data
 ///
diff --git a/src/lib/asiodns/tests/Makefile.am b/src/lib/asiodns/tests/Makefile.am
index 5a45430..f49d485 100644
--- a/src/lib/asiodns/tests/Makefile.am
+++ b/src/lib/asiodns/tests/Makefile.am
@@ -47,4 +47,4 @@ run_unittests_CXXFLAGS += -Wno-error
 endif
 endif
 
-check_PROGRAMS = $(TESTS)
+noinst_PROGRAMS = $(TESTS)
diff --git a/src/lib/asiolink/io_address.cc b/src/lib/asiolink/io_address.cc
index 7e2f5d4..51c0332 100644
--- a/src/lib/asiolink/io_address.cc
+++ b/src/lib/asiolink/io_address.cc
@@ -23,7 +23,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;
@@ -54,6 +54,22 @@ IOAddress::toText() const {
     return (asio_address_.to_string());
 }
 
+IOAddress
+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];
+    inet_ntop(family, data, addr_str, INET6_ADDRSTRLEN);
+    return IOAddress(string(addr_str));
+}
+
 short
 IOAddress::getFamily() const {
     if (asio_address_.is_v4()) {
@@ -63,7 +79,7 @@ IOAddress::getFamily() const {
     }
 }
 
-const asio::ip::address& 
+const asio::ip::address&
 IOAddress::getAddress() const {
     return asio_address_;
 }
diff --git a/src/lib/asiolink/io_address.h b/src/lib/asiolink/io_address.h
index 1b488fa..9fac580 100644
--- a/src/lib/asiolink/io_address.h
+++ b/src/lib/asiolink/io_address.h
@@ -29,6 +29,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)
 ///
@@ -87,6 +93,16 @@ public:
     /// \return AF_INET for IPv4 or AF_INET6 for IPv6.
     short getFamily() const;
 
+
+    /// \brief Creates an address from over wire data.
+    ///
+    /// \param family AF_NET for IPv4 or AF_NET6 for IPv6.
+    /// \param data pointer to first char of data
+    ///
+    /// \return Created IOAddress object
+    static IOAddress
+    from_bytes(short family, const uint8_t* data);
+
     /// \brief Compare addresses for equality
     ///
     /// \param other Address to compare against.
diff --git a/src/lib/asiolink/tests/Makefile.am b/src/lib/asiolink/tests/Makefile.am
index 94643c0..984cf07 100644
--- a/src/lib/asiolink/tests/Makefile.am
+++ b/src/lib/asiolink/tests/Makefile.am
@@ -53,4 +53,4 @@ run_unittests_CXXFLAGS += -Wno-error
 endif
 endif
 
-check_PROGRAMS = $(TESTS)
+noinst_PROGRAMS = $(TESTS)
diff --git a/src/lib/asiolink/tests/io_address_unittest.cc b/src/lib/asiolink/tests/io_address_unittest.cc
index 56368a1..eddb0e8 100644
--- a/src/lib/asiolink/tests/io_address_unittest.cc
+++ b/src/lib/asiolink/tests/io_address_unittest.cc
@@ -63,3 +63,23 @@ TEST(IOAddressTest, Family) {
     EXPECT_EQ(AF_INET, IOAddress("192.0.2.1").getFamily());
     EXPECT_EQ(AF_INET6, IOAddress("2001:0DB8:0:0::0012").getFamily());
 }
+
+TEST(IOAddressTest, from_bytes) {
+    // 2001:db8:1::dead:beef
+    uint8_t v6[] = {
+        0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0, 0,
+        0, 0, 0, 0, 0xde, 0xad, 0xbe, 0xef };
+
+    uint8_t v4[] = { 192, 0 , 2, 3 };
+
+    IOAddress addr("::");
+    EXPECT_NO_THROW({
+        addr = IOAddress::from_bytes(AF_INET6, v6);
+    });
+    EXPECT_EQ("2001:db8:1::dead:beef", addr.toText());
+
+    EXPECT_NO_THROW({
+        addr = IOAddress::from_bytes(AF_INET, v4);
+    });
+    EXPECT_EQ(addr.toText(), IOAddress("192.0.2.3").toText());
+}
diff --git a/src/lib/bench/Makefile.am b/src/lib/bench/Makefile.am
index 866404f..514b3b3 100644
--- a/src/lib/bench/Makefile.am
+++ b/src/lib/bench/Makefile.am
@@ -6,6 +6,6 @@ AM_CXXFLAGS = $(B10_CXXFLAGS)
 
 CLEANFILES = *.gcno *.gcda
 
-lib_LTLIBRARIES = libbench.la
+noinst_LTLIBRARIES = libbench.la
 libbench_la_SOURCES = benchmark_util.h benchmark_util.cc
 EXTRA_DIST = benchmark.h
diff --git a/src/lib/bench/tests/Makefile.am b/src/lib/bench/tests/Makefile.am
index 2a6e2c6..3f8a678 100644
--- a/src/lib/bench/tests/Makefile.am
+++ b/src/lib/bench/tests/Makefile.am
@@ -22,6 +22,6 @@ run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
 run_unittests_LDADD += $(GTEST_LDADD)
 endif
 
-check_PROGRAMS = $(TESTS)
+noinst_PROGRAMS = $(TESTS)
 
 EXTRA_DIST = testdata/query.txt
diff --git a/src/lib/cache/logger.h b/src/lib/cache/logger.h
index 8159ed4..3bba413 100644
--- a/src/lib/cache/logger.h
+++ b/src/lib/cache/logger.h
@@ -31,14 +31,13 @@ namespace cache {
 /// \brief The logger for this library
 extern isc::log::Logger logger;
 
-enum {
-    /// \brief Trace basic operations
-    DBG_TRACE_BASIC = 10,
-    /// \brief Trace data operations
-    DBG_TRACE_DATA = 40,
-};
-
-}
-}
+/// \brief Trace basic operations
+const int DBG_TRACE_BASIC = DBGLVL_TRACE_BASIC;
+
+/// \brief Trace data operations
+const int DBG_TRACE_DATA = DBGLVL_TRACE_BASIC_DATA;
+
+} // namespace cache
+} // namespace isc
 
 #endif
diff --git a/src/lib/cache/tests/Makefile.am b/src/lib/cache/tests/Makefile.am
index 0b95036..a215c56 100644
--- a/src/lib/cache/tests/Makefile.am
+++ b/src/lib/cache/tests/Makefile.am
@@ -62,7 +62,7 @@ run_unittests_LDADD += $(top_builddir)/src/lib/util/unittests/libutil_unittests.
 run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
 endif
 
-check_PROGRAMS = $(TESTS)
+noinst_PROGRAMS = $(TESTS)
 
 EXTRA_DIST  = testdata/message_cname_referral.wire
 EXTRA_DIST += testdata/message_example_com_soa.wire
diff --git a/src/lib/cc/logger.h b/src/lib/cc/logger.h
index 567ccee..34b5809 100644
--- a/src/lib/cc/logger.h
+++ b/src/lib/cc/logger.h
@@ -28,20 +28,19 @@
 namespace isc {
 namespace cc {
 
-enum {
-    /// \brief Trace basic operation
-    DBG_TRACE_BASIC = 10,
-    /// \brief Trace even details
-    ///
-    /// This includes messages being sent and received, waiting for messages
-    /// and alike.
-    DBG_TRACE_DETAILED = 80
-};
+/// Trace basic operation
+const int DBG_TRACE_BASIC = DBGLVL_TRACE_BASIC;
 
-/// \brief Logger for this library
+/// This includes messages being sent and received, waiting for messages
+/// and alike.
+const int DBG_TRACE_DETAILED = DBGLVL_TRACE_DETAIL;
+
+// Declaration of the logger.
 extern isc::log::Logger logger;
 
-}
-}
+} // namespace cc
+} // namespace isc
+
+/// \brief Logger for this library
 
 #endif
diff --git a/src/lib/cc/tests/Makefile.am b/src/lib/cc/tests/Makefile.am
index eebd103..4760855 100644
--- a/src/lib/cc/tests/Makefile.am
+++ b/src/lib/cc/tests/Makefile.am
@@ -32,4 +32,4 @@ run_unittests_LDADD +=  $(top_builddir)/src/lib/exceptions/libexceptions.la
 
 endif
 
-check_PROGRAMS = $(TESTS)
+noinst_PROGRAMS = $(TESTS)
diff --git a/src/lib/config/config_log.h b/src/lib/config/config_log.h
index 74e6a84..21709fd 100644
--- a/src/lib/config/config_log.h
+++ b/src/lib/config/config_log.h
@@ -30,15 +30,10 @@ namespace config {
 /// Define the logger used to log messages.  We could define it in multiple
 /// modules, but defining in a single module and linking to it saves time and
 /// space.
-extern isc::log::Logger config_logger;    // isc::config::config_logger is the CONFIG logger
+extern isc::log::Logger config_logger;
 
-/// \brief Debug Levels
-///
-/// Debug levels used in the configuration library
-enum {
-    DBG_CONFIG_PROCESS = 40     // Enumerate configuration elements as they
-                                // ... are processed.
-};
+// Enumerate configuration elements as they are processed.
+const int DBG_CONFIG_PROCESS = DBGLVL_TRACE_BASIC;
 
 } // namespace config
 } // namespace isc
diff --git a/src/lib/config/tests/Makefile.am b/src/lib/config/tests/Makefile.am
index 4fb147d..2f1fc6f 100644
--- a/src/lib/config/tests/Makefile.am
+++ b/src/lib/config/tests/Makefile.am
@@ -11,7 +11,7 @@ endif
 
 CLEANFILES = *.gcno *.gcda
 
-lib_LTLIBRARIES = libfake_session.la
+noinst_LTLIBRARIES = libfake_session.la
 libfake_session_la_SOURCES = fake_session.h fake_session.cc
 
 TESTS =
@@ -31,4 +31,4 @@ run_unittests_LDADD += $(top_builddir)/src/lib/util/unittests/libutil_unittests.
 
 endif
 
-check_PROGRAMS = $(TESTS)
+noinst_PROGRAMS = $(TESTS)
diff --git a/src/lib/cryptolink/tests/Makefile.am b/src/lib/cryptolink/tests/Makefile.am
index 2861edc..fbdd13f 100644
--- a/src/lib/cryptolink/tests/Makefile.am
+++ b/src/lib/cryptolink/tests/Makefile.am
@@ -24,4 +24,4 @@ run_unittests_LDADD += $(top_builddir)/src/lib/util/unittests/libutil_unittests.
 run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
 endif
 
-check_PROGRAMS = $(TESTS)
+noinst_PROGRAMS = $(TESTS)
diff --git a/src/lib/datasrc/database.cc b/src/lib/datasrc/database.cc
index e476297..d35f6e8 100644
--- a/src/lib/datasrc/database.cc
+++ b/src/lib/datasrc/database.cc
@@ -417,7 +417,7 @@ DatabaseClient::Finder::find(const isc::dns::Name& name,
     size_t last_known(origin_label_count);
     const size_t current_label_count(name.getLabelCount());
     // This is how many labels we remove to get origin
-    size_t remove_labels(current_label_count - origin_label_count);
+    const size_t remove_labels(current_label_count - origin_label_count);
 
     // Now go trough all superdomains from origin down
     for (int i(remove_labels); i > 0; --i) {
@@ -508,13 +508,18 @@ DatabaseClient::Finder::find(const isc::dns::Name& name,
                     arg(accessor_->getDBName()).arg(name);
                 records_found = true;
                 get_cover = dnssec_data;
+            } else if ((options & NO_WILDCARD) != 0) {
+                // If wildcard check is disabled, the search will ultimately
+                // terminate with NXDOMAIN. If DNSSEC is enabled, flag that
+                // we need to get the NSEC records to prove this.
+                if (dnssec_data) {
+                    get_cover = true;
+                }
             } else {
                 // It's not empty non-terminal. So check for wildcards.
                 // We remove labels one by one and look for the wildcard there.
                 // Go up to first non-empty domain.
-
-                remove_labels = current_label_count - last_known;
-                for (size_t i(1); i <= remove_labels; ++ i) {
+                for (size_t i(1); i <= current_label_count - last_known; ++i) {
                     // Construct the name with *
                     const Name superdomain(name.split(i));
                     const string wildcard("*." + superdomain.toText());
@@ -553,7 +558,7 @@ DatabaseClient::Finder::find(const isc::dns::Name& name,
                             if (cni != found.second.end() &&
                                 type != RRType::CNAME()) {
                                 result_rrset = cni->second;
-                                result_status = CNAME;
+                                result_status = WILDCARD_CNAME;
                             } else if (nsi != found.second.end()) {
                                 result_rrset = nsi->second;
                                 result_status = DELEGATION;
diff --git a/src/lib/datasrc/logger.h b/src/lib/datasrc/logger.h
index ac5d50b..c360900 100644
--- a/src/lib/datasrc/logger.h
+++ b/src/lib/datasrc/logger.h
@@ -31,14 +31,14 @@ namespace datasrc {
 /// \brief The logger for this library
 extern isc::log::Logger logger;
 
-enum {
-    /// \brief Trace basic operations
-    DBG_TRACE_BASIC = 10,
-    /// \brief Trace data changes and lookups as well
-    DBG_TRACE_DATA = 20,
-    /// \brief Detailed even about how the lookups happen
-    DBG_TRACE_DETAILED = 50
-};
+/// \brief Trace basic operations
+const int DBG_TRACE_BASIC = DBGLVL_TRACE_BASIC;
+
+/// \brief Trace data changes and lookups as well
+const int DBG_TRACE_DATA = DBGLVL_TRACE_BASIC_DATA;
+
+/// \brief Detailed even about how the lookups happen
+const int DBG_TRACE_DETAILED = DBGLVL_TRACE_DETAIL;
 
 }
 }
diff --git a/src/lib/datasrc/tests/Makefile.am b/src/lib/datasrc/tests/Makefile.am
index 0be8cd2..3d2ba6d 100644
--- a/src/lib/datasrc/tests/Makefile.am
+++ b/src/lib/datasrc/tests/Makefile.am
@@ -62,7 +62,7 @@ run_unittests_LDADD += $(top_builddir)/src/lib/testutils/libtestutils.la
 run_unittests_LDADD += $(top_builddir)/src/lib/util/unittests/libutil_unittests.la
 endif
 
-check_PROGRAMS = $(TESTS)
+noinst_PROGRAMS = $(TESTS)
 
 EXTRA_DIST =  testdata/brokendb.sqlite3
 EXTRA_DIST += testdata/example.com.signed
diff --git a/src/lib/datasrc/tests/database_unittest.cc b/src/lib/datasrc/tests/database_unittest.cc
index 8cd70ef..de6b5fa 100644
--- a/src/lib/datasrc/tests/database_unittest.cc
+++ b/src/lib/datasrc/tests/database_unittest.cc
@@ -175,8 +175,11 @@ const char* const TEST_RECORDS[][5] = {
     {"*.delegatedwild.example.org.", "A", "3600", "", "192.0.2.5"},
     {"wild.*.foo.example.org.", "A", "3600", "", "192.0.2.5"},
     {"wild.*.foo.*.bar.example.org.", "A", "3600", "", "192.0.2.5"},
+    {"wild.*.foo.*.bar.example.org.", "NSEC", "3600", "",
+     "brokenns1.example.org. A NSEC"},
     {"bao.example.org.", "NSEC", "3600", "", "wild.*.foo.*.bar.example.org. NSEC"},
     {"*.cnamewild.example.org.", "CNAME", "3600", "", "www.example.org."},
+    {"*.dnamewild.example.org.", "DNAME", "3600", "", "dname.example.com."},
     {"*.nswild.example.org.", "NS", "3600", "", "ns.example.com."},
     // For NSEC empty non-terminal
     {"l.example.org.", "NSEC", "3600", "", "empty.nonterminal.example.org. NSEC"},
@@ -258,9 +261,16 @@ private:
  * implementation of the optional functionality.
  */
 class MockAccessor : public NopAccessor {
-    // Type of mock database "row"s
-    typedef std::map<std::string, std::vector< std::vector<std::string> > >
-        Domains;
+    // Type of mock database "row"s.  This is a map whose keys are the
+    // own names.  We internally sort them by the name comparison order.
+    struct NameCompare : public binary_function<string, string, bool> {
+        bool operator()(const string& n1, const string& n2) const {
+            return (Name(n1).compare(Name(n2)).getOrder() < 0);
+        }
+    };
+    typedef std::map<std::string,
+                     std::vector< std::vector<std::string> >,
+                     NameCompare > Domains;
 
 public:
     MockAccessor() : rollbacked_(false) {
@@ -554,30 +564,36 @@ public:
     virtual std::string findPreviousName(int id, const std::string& rname)
         const
     {
-        // Hardcoded for now, but we could compute it from the data
-        // Maybe do it when it is needed some time in future?
         if (id == -1) {
             isc_throw(isc::NotImplemented, "Test not implemented behaviour");
-        } else if (id == 42) {
-            if (rname == "org.example.nonterminal.") {
-                return ("l.example.org.");
-            } else if (rname == "org.example.aa.") {
-                return ("example.org.");
-            } else if (rname == "org.example.www2." ||
-                       rname == "org.example.www1.") {
-                return ("www.example.org.");
-            } else if (rname == "org.example.badnsec2.") {
+        } else if (id == READONLY_ZONE_ID) {
+            // For some specific names we intentionally return broken or
+            // unexpected result.
+            if (rname == "org.example.badnsec2.") {
                 return ("badnsec1.example.org.");
             } else if (rname == "org.example.brokenname.") {
                 return ("brokenname...example.org.");
-            } else if (rname == "org.example.bar.*.") {
-                return ("bao.example.org.");
             } else if (rname == "org.example.notimplnsec." ||
                        rname == "org.example.wild.here.") {
                 isc_throw(isc::NotImplemented, "Not implemented in this test");
-            } else {
+            }
+
+            // For the general case, we search for the first name N in the
+            // domains that meets N >= reverse(rname) using lower_bound.
+            // The "previous name" is the name of the previous entry of N.
+            // Note that Domains are internally sorted by the Name comparison
+            // order.  Due to the API requirement we are given a reversed
+            // name (rname), so we need to reverse it again to convert it
+            // to the original name.
+            Domains::const_iterator it(readonly_records_->lower_bound(
+                                           Name(rname).reverse().toText()));
+            if (it == readonly_records_->begin()) {
                 isc_throw(isc::Unexpected, "Unexpected name");
             }
+            if (it == readonly_records_->end()) {
+                return ((*readonly_records_->rbegin()).first);
+            }
+            return ((*(--it)).first);
         } else {
             isc_throw(isc::Unexpected, "Unknown zone ID");
         }
@@ -1027,8 +1043,8 @@ doFindTest(ZoneFinder& finder,
            const ZoneFinder::FindOptions options = ZoneFinder::FIND_DEFAULT)
 {
     SCOPED_TRACE("doFindTest " + name.toText() + " " + type.toText());
-    ZoneFinder::FindResult result =
-        finder.find(name, type, NULL, options);
+    const ZoneFinder::FindResult result = finder.find(name, type, NULL,
+                                                      options);
     ASSERT_EQ(expected_result, result.code) << name << " " << type;
     if (!expected_rdatas.empty() && result.rrset) {
         checkRRset(result.rrset, expected_name != Name(".") ? expected_name :
@@ -1595,21 +1611,21 @@ TYPED_TEST(DatabaseClientTest, wildcard) {
         "bar.example.org",
         NULL
     };
+    // Unless FIND_DNSSEC is specified, this is no different from other
+    // NXRRSET case.
     for (const char** name(negative_names); *name != NULL; ++ name) {
         doFindTest(*finder, isc::dns::Name(*name), this->qtype_,
                    this->qtype_, this->rrttl_, ZoneFinder::NXRRSET,
                    this->expected_rdatas_, this->expected_sig_rdatas_);
-        // FIXME: What should be returned in this case? How does the
-        // DNSSEC logic handle it?
     }
 
+    // With FIND_DNSSEC, it should result in WILDCARD_NXRRSET.
     const char* negative_dnssec_names[] = {
         "a.bar.example.org.",
         "foo.baz.bar.example.org.",
         "a.foo.bar.example.org.",
         NULL
     };
-
     this->expected_rdatas_.clear();
     this->expected_rdatas_.push_back("wild.*.foo.*.bar.example.org. NSEC");
     this->expected_sig_rdatas_.clear();
@@ -1620,15 +1636,27 @@ TYPED_TEST(DatabaseClientTest, wildcard) {
                    Name("bao.example.org."), ZoneFinder::FIND_DNSSEC);
     }
 
-    // Some strange things in the wild node
+    // CNAME on a wildcard.  Maybe not so common, but not disallowed.
     this->expected_rdatas_.clear();
     this->expected_rdatas_.push_back("www.example.org.");
     this->expected_sig_rdatas_.clear();
     doFindTest(*finder, isc::dns::Name("a.cnamewild.example.org."),
                isc::dns::RRType::TXT(), isc::dns::RRType::CNAME(),
-               this->rrttl_, ZoneFinder::CNAME,
+               this->rrttl_, ZoneFinder::WILDCARD_CNAME,
                this->expected_rdatas_, this->expected_sig_rdatas_);
 
+    // DNAME on a wildcard.  In our implementation we ignore DNAMEs on a
+    // wildcard, but at a higher level we say the behavior is "unspecified".
+    // rfc2672bis strongly discourages the mixture of DNAME and wildcard
+    // (with SHOULD NOT).
+    this->expected_rdatas_.clear();
+    this->expected_sig_rdatas_.clear();
+    doFindTest(*finder, Name("a.dnamewild.example.org."),
+               this->qtype_, this->qtype_, this->rrttl_,
+               ZoneFinder::WILDCARD_NXRRSET, this->expected_rdatas_,
+               this->expected_sig_rdatas_);
+
+    // Some strange things in the wild node
     this->expected_rdatas_.clear();
     this->expected_rdatas_.push_back("ns.example.com.");
     doFindTest(*finder, isc::dns::Name("a.nswild.example.org."),
@@ -1637,6 +1665,67 @@ TYPED_TEST(DatabaseClientTest, wildcard) {
                this->expected_rdatas_, this->expected_sig_rdatas_);
 }
 
+TYPED_TEST(DatabaseClientTest, noWildcard) {
+    // Tests with the NO_WILDCARD flag.
+
+    shared_ptr<DatabaseClient::Finder> finder(this->getFinder());
+
+    // This would match *.wild.example.org, but with NO_WILDCARD should
+    // result in NXDOMAIN.
+    this->expected_rdatas_.push_back("cancel.here.wild.example.org. A "
+                                     "NSEC RRSIG");
+    this->expected_sig_rdatas_.push_back("NSEC 5 3 3600 20000101000000 "
+                                         "20000201000000 12345 example.org. "
+                                         "FAKEFAKEFAKE");
+    doFindTest(*finder, isc::dns::Name("a.wild.example.org"),
+               RRType::NSEC(), RRType::NSEC(), this->rrttl_,
+               ZoneFinder::NXDOMAIN, this->expected_rdatas_,
+               this->expected_sig_rdatas_, Name("*.wild.example.org."),
+               ZoneFinder::FIND_DNSSEC | ZoneFinder::NO_WILDCARD);
+
+    // Should be the same without FIND_DNSSEC (but in this case no RRsets
+    // will be returned)
+    doFindTest(*finder, isc::dns::Name("a.wild.example.org"),
+               RRType::NSEC(), RRType::NSEC(), this->rrttl_,
+               ZoneFinder::NXDOMAIN, this->empty_rdatas_,
+               this->empty_rdatas_, Name::ROOT_NAME(), // name is dummy
+               ZoneFinder::NO_WILDCARD);
+
+    // Same for wildcard empty non terminal.
+    this->expected_rdatas_.clear();
+    this->expected_rdatas_.push_back("brokenns1.example.org. A NSEC");
+    doFindTest(*finder, isc::dns::Name("a.bar.example.org"),
+               RRType::NSEC(), RRType::NSEC(), this->rrttl_,
+               ZoneFinder::NXDOMAIN, this->expected_rdatas_,
+               this->empty_rdatas_, Name("wild.*.foo.*.bar.example.org"),
+               ZoneFinder::FIND_DNSSEC | ZoneFinder::NO_WILDCARD);
+
+    // Search for a wildcard name with NO_WILDCARD.  There should be no
+    // difference.  This is, for example, necessary to provide non existence
+    // of matching wildcard for isnx.nonterminal.example.org.
+    this->expected_rdatas_.clear();
+    this->expected_rdatas_.push_back("empty.nonterminal.example.org. NSEC");
+    doFindTest(*finder, isc::dns::Name("*.nonterminal.example.org"),
+               RRType::NSEC(), RRType::NSEC(), this->rrttl_,
+               ZoneFinder::NXDOMAIN, this->expected_rdatas_,
+               this->empty_rdatas_, Name("l.example.org"),
+               ZoneFinder::FIND_DNSSEC | ZoneFinder::NO_WILDCARD);
+
+    // On the other hand, if there's exact match for the wildcard name
+    // it should be found regardless of NO_WILDCARD.
+    this->expected_rdatas_.clear();
+    this->expected_rdatas_.push_back("192.0.2.5");
+    this->expected_sig_rdatas_.clear();
+    this->expected_sig_rdatas_.push_back("A 5 3 3600 20000101000000 "
+                                         "20000201000000 12345 example.org. "
+                                         "FAKEFAKEFAKE");
+    doFindTest(*finder, isc::dns::Name("*.wild.example.org"),
+               this->qtype_, this->qtype_, this->rrttl_,
+               ZoneFinder::SUCCESS, this->expected_rdatas_,
+               this->expected_sig_rdatas_, Name("*.wild.example.org"),
+               ZoneFinder::NO_WILDCARD);
+}
+
 TYPED_TEST(DatabaseClientTest, NXRRSET_NSEC) {
     // The domain exists, but doesn't have this RRType
     // So we should get its NSEC
diff --git a/src/lib/datasrc/zone.h b/src/lib/datasrc/zone.h
index c83b14b..fa1c744 100644
--- a/src/lib/datasrc/zone.h
+++ b/src/lib/datasrc/zone.h
@@ -63,32 +63,70 @@ public:
     /// actually the best wildcard we have). Data sources that don't
     /// support DNSSEC don't need to distinguish them.
     ///
-    /// In case of NXRRSET related results, the returned NSEC record
-    /// belongs to the domain which would provide the result if it
-    /// contained the correct type (in case of NXRRSET, it is the queried
-    /// domain, in case of WILDCARD_NXRRSET, it is the wildcard domain
-    /// that matched the query name). In case of an empty nonterminal,
-    /// an NSEC is provided for the interval where the empty nonterminal
-    /// lives. The end of the interval is the subdomain causing existence
-    /// of the empty nonterminal (if there's sub.x.example.com, and no record
-    /// in x.example.com, then x.example.com exists implicitly - is the empty
-    /// nonterminal and sub.x.example.com is the subdomain causing it).
+    /// In case of CNAME, if the CNAME is a wildcard (i.e., its owner name
+    /// starts with the label "*"), WILDCARD_CNAME will be returned instead
+    /// of CNAME.
+    ///
+    /// In case of NXDOMAIN, the returned NSEC covers the queried domain
+    /// that proves that the query name does not exist in the zone.  Note that
+    /// this does not necessarily prove it doesn't even match a wildcard
+    /// (even if the result of NXDOMAIN can only happen when there's no
+    /// matching wildcard either).  It is caller's responsibility to provide
+    /// a proof that there is no matching wildcard if that proof is necessary.
+    ///
+    /// Various variants of "no data" cases are complicated, when involves
+    /// DNSSEC and wildcard processing.  Referring to Section 3.1.3 of
+    /// RFC4035, we need to consider the following cases:
+    /// -# (Normal) no data: there is a matching non-wildcard name with a
+    ///    different RR type.  This is the "No Data" case of the RFC.
+    /// -# (Normal) empty non terminal: there is no matching (exact or
+    ///    wildcard) name, but there is a subdomain with an RR of the query
+    ///    name.  This is one case of "Name Error" of the RFC.
+    /// -# Wildcard empty non terminal: similar to 2a, but the empty name
+    ///    is a wildcard, and matches the query name by wildcard expansion.
+    ///    This is a special case of "Name Error" of the RFC.
+    /// -# Wildcard no data: there is no exact match name, but there is a
+    ///    wildcard name that matches the query name with a different type
+    ///    of RR.  This is the "Wildcard No Data" case of the RFC.
+    ///
+    /// In any case, \c find() will result in \c NXRRSET with no RRset
+    /// unless the \c FIND_DNSSEC option is specified.  The rest of the
+    /// discussion only applies to the case where this option is specified.
+    ///
+    /// In case 1, \c find() will result in NXRRSET, and return NSEC of the
+    /// matching name.
+    ///
+    /// In case 2, \c find() will result in NXRRSET, and return NSEC for the
+    /// interval where the empty nonterminal lives. The end of the interval
+    /// is the subdomain causing existence of the empty nonterminal (if
+    /// there's sub.x.example.com, and no record in x.example.com, then
+    /// x.example.com exists implicitly - is the empty nonterminal and
+    /// sub.x.example.com is the subdomain causing it).  Note that this NSEC
+    /// proves not only the existence of empty non terminal name but also
+    /// the non existence of possibly matching wildcard name, because
+    /// there can be no better wildcard match than the exact matching empty
+    /// name.
+    ///
+    /// In case 3, \c find() will result in WILDCARD_NXRRSET, and return NSEC
+    /// for the interval where the wildcard empty nonterminal lives.
+    /// Cases 2 and 3 are especially complicated and confusing.  See the
+    /// examples below.
+    ///
+    /// In case 4, \c find() will result in WILDCARD_NXRRSET, and return
+    /// NSEC of the matching wildcard name.
     ///
     /// Examples: if zone "example.com" has the following record:
     /// \code
-    /// a.b.example.com. NSEC c.example.com.
+    /// a.example.com. NSEC a.b.example.com.
     /// \endcode
-    /// a call to \c find() for "b.example.com." will result in NXRRSET,
-    /// and if the FIND_DNSSEC option is set this NSEC will be returned.
+    /// a call to \c find() for "b.example.com." with the FIND_DNSSEC option
+    /// will result in NXRRSET, and this NSEC will be returned.
     /// Likewise, if zone "example.org" has the following record,
     /// \code
-    /// x.*.example.org. NSEC a.example.org.
+    /// a.example.org. NSEC x.*.b.example.org.
     /// \endcode
-    /// a call to \c find() for "y.example.org" will result in
-    /// WILDCARD_NXRRSET (*.example.org is an empty nonterminal wildcard node),
-    /// and if the FIND_DNSSEC option is set this NSEC will be returned.
-    ///
-    /// In case of NXDOMAIN, the returned NSEC covers the queried domain.
+    /// a call to \c find() for "y.b.example.org" with FIND_DNSSEC will
+    /// result in NXRRSET_NXRRSET, and this NSEC will be returned.
     enum Result {
         SUCCESS,                ///< An exact match is found.
         DELEGATION,             ///< The search encounters a zone cut.
@@ -97,6 +135,7 @@ public:
         CNAME,    ///< The search encounters and returns a CNAME RR
         DNAME,    ///< The search encounters and returns a DNAME RR
         WILDCARD, ///< Succes by wildcard match, for DNSSEC
+        WILDCARD_CNAME, ///< CNAME on wildcard, search returns CNAME, for DNSSEC
         WILDCARD_NXRRSET ///< NXRRSET on wildcard, for DNSSEC
     };
 
@@ -138,10 +177,11 @@ public:
     enum FindOptions {
         FIND_DEFAULT = 0,       ///< The default options
         FIND_GLUE_OK = 1,       ///< Allow search under a zone cut
-        FIND_DNSSEC = 2         ///< Require DNSSEC data in the answer
+        FIND_DNSSEC = 2,        ///< Require DNSSEC data in the answer
                                 ///< (RRSIG, NSEC, etc.). The implementation
                                 ///< is allowed to include it even if it is
                                 ///< not set.
+        NO_WILDCARD = 4         ///< Do not try wildcard matching.
     };
 
     ///
@@ -181,6 +221,7 @@ public:
     /// for the data that best matches the given name and type.
     /// This method is expected to be "intelligent", and identifies the
     /// best possible answer for the search key.  Specifically,
+    ///
     /// - If the search name belongs under a zone cut, it returns the code
     ///   of \c DELEGATION and the NS RRset at the zone cut.
     /// - If there is no matching name, it returns the code of \c NXDOMAIN,
@@ -199,12 +240,14 @@ public:
     /// - If the target isn't NULL, all RRsets under the domain are inserted
     ///   there and SUCCESS (or NXDOMAIN, in case of empty domain) is returned
     ///   instead of normall processing. This is intended to handle ANY query.
-    ///   \note: this behavior is controversial as we discussed in
-    ///   https://lists.isc.org/pipermail/bind10-dev/2011-January/001918.html
-    ///   We should revisit the interface before we heavily rely on it.
+    ///
+    /// \note This behavior is controversial as we discussed in
+    /// https://lists.isc.org/pipermail/bind10-dev/2011-January/001918.html
+    /// We should revisit the interface before we heavily rely on it.
     ///
     /// The \c options parameter specifies customized behavior of the search.
     /// Their semantics is as follows (they are or bit-field):
+    ///
     /// - \c FIND_GLUE_OK Allow search under a zone cut.  By default the search
     ///   will stop once it encounters a zone cut.  If this option is specified
     ///   it remembers information about the highest zone cut and continues
@@ -216,6 +259,10 @@ public:
     /// - \c FIND_DNSSEC Request that DNSSEC data (like NSEC, RRSIGs) are
     ///   returned with the answer. It is allowed for the data source to
     ///   include them even when not requested.
+    /// - \c NO_WILDCARD Do not try wildcard matching.  This option is of no
+    ///   use for normal lookups; it's intended to be used to get a DNSSEC
+    ///   proof of the non existence of any matching wildcard or non existence
+    ///   of an exact match when a wildcard match is found.
     ///
     /// A derived version of this method may involve internal resource
     /// allocation, especially for constructing the resulting RRset, and may
diff --git a/src/lib/dhcp/Makefile.am b/src/lib/dhcp/Makefile.am
new file mode 100644
index 0000000..64dda17
--- /dev/null
+++ b/src/lib/dhcp/Makefile.am
@@ -0,0 +1,26 @@
+SUBDIRS = . tests
+
+AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
+AM_CPPFLAGS += $(BOOST_INCLUDES)
+
+AM_CXXFLAGS = $(B10_CXXFLAGS)
+
+CLEANFILES = *.gcno *.gcda
+
+lib_LTLIBRARIES = libdhcp.la
+libdhcp_la_SOURCES  =
+libdhcp_la_SOURCES += libdhcp.cc libdhcp.h
+libdhcp_la_SOURCES += option.cc option.h
+libdhcp_la_SOURCES += option6_ia.cc option6_ia.h
+libdhcp_la_SOURCES += option6_iaaddr.cc option6_iaaddr.h
+libdhcp_la_SOURCES += option6_addrlst.cc option6_addrlst.h
+libdhcp_la_SOURCES += dhcp6.h dhcp4.h
+libdhcp_la_SOURCES += pkt6.cc pkt6.h
+libdhcp_la_SOURCES += pkt4.cc pkt4.h
+
+EXTRA_DIST  = README
+#EXTRA_DIST += log_messages.mes
+
+libdhcp_la_CXXFLAGS = $(AM_CXXFLAGS)
+libdhcp_la_CPPFLAGS = $(AM_CPPFLAGS) $(LOG4CPLUS_INCLUDES)
+libdhcp_la_LIBADD   = $(top_builddir)/src/lib/util/libutil.la
diff --git a/src/lib/dhcp/README b/src/lib/dhcp/README
new file mode 100644
index 0000000..6c5353d
--- /dev/null
+++ b/src/lib/dhcp/README
@@ -0,0 +1,11 @@
+This directory holds implementation for libdhcp.
+
+
+Basic Ideas
+===========
+
+
+Notes
+=====
+This work just begun. Don't expect to see much useful code here.
+We are working on it.
\ No newline at end of file
diff --git a/src/lib/dhcp/dhcp4.h b/src/lib/dhcp/dhcp4.h
new file mode 100644
index 0000000..98381ac
--- /dev/null
+++ b/src/lib/dhcp/dhcp4.h
@@ -0,0 +1,191 @@
+/*
+ * 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
+
+#include <stdint.h>
+
+namespace isc {
+namespace dhcp {
+
+/* BOOTP (rfc951) message types */
+enum BOOTPTypes {
+    BOOTREQUEST = 1,
+    BOOTREPLY = 2
+};
+
+/* Possible values for flags field... */
+static const uint16_t BOOTP_BROADCAST = 32768L;
+
+/* Possible values for hardware type (htype) field... */
+enum HType {
+    HTYPE_ETHER = 1,   /* Ethernet 10Mbps */
+    HTYPE_IEEE802 = 6, /* IEEE 802.2 Token Ring */
+    HTYPE_FDDI = 8     /* FDDI */
+    /// TODO Add infiniband here
+};
+
+/* DHCP Option codes: */
+enum DHCPOptionType {
+    DHO_PAD                          = 0,
+    DHO_SUBNET_MASK                  = 1,
+    DHO_TIME_OFFSET                  = 2,
+    DHO_ROUTERS                      = 3,
+    DHO_TIME_SERVERS                 = 4,
+    DHO_NAME_SERVERS                 = 5,
+    DHO_DOMAIN_NAME_SERVERS          = 6,
+    DHO_LOG_SERVERS                  = 7,
+    DHO_COOKIE_SERVERS               = 8,
+    DHO_LPR_SERVERS                  = 9,
+    DHO_IMPRESS_SERVERS              = 10,
+    DHO_RESOURCE_LOCATION_SERVERS    = 11,
+    DHO_HOST_NAME                    = 12,
+    DHO_BOOT_SIZE                    = 13,
+    DHO_MERIT_DUMP                   = 14,
+    DHO_DOMAIN_NAME                  = 15,
+    DHO_SWAP_SERVER                  = 16,
+    DHO_ROOT_PATH                    = 17,
+    DHO_EXTENSIONS_PATH              = 18,
+    DHO_IP_FORWARDING                = 19,
+    DHO_NON_LOCAL_SOURCE_ROUTING     = 20,
+    DHO_POLICY_FILTER                = 21,
+    DHO_MAX_DGRAM_REASSEMBLY         = 22,
+    DHO_DEFAULT_IP_TTL               = 23,
+    DHO_PATH_MTU_AGING_TIMEOUT       = 24,
+    DHO_PATH_MTU_PLATEAU_TABLE       = 25,
+    DHO_INTERFACE_MTU                = 26,
+    DHO_ALL_SUBNETS_LOCAL            = 27,
+    DHO_BROADCAST_ADDRESS            = 28,
+    DHO_PERFORM_MASK_DISCOVERY       = 29,
+    DHO_MASK_SUPPLIER                = 30,
+    DHO_ROUTER_DISCOVERY             = 31,
+    DHO_ROUTER_SOLICITATION_ADDRESS  = 32,
+    DHO_STATIC_ROUTES                = 33,
+    DHO_TRAILER_ENCAPSULATION        = 34,
+    DHO_ARP_CACHE_TIMEOUT            = 35,
+    DHO_IEEE802_3_ENCAPSULATION      = 36,
+    DHO_DEFAULT_TCP_TTL              = 37,
+    DHO_TCP_KEEPALIVE_INTERVAL       = 38,
+    DHO_TCP_KEEPALIVE_GARBAGE        = 39,
+    DHO_NIS_DOMAIN                   = 40,
+    DHO_NIS_SERVERS                  = 41,
+    DHO_NTP_SERVERS                  = 42,
+    DHO_VENDOR_ENCAPSULATED_OPTIONS  = 43,
+    DHO_NETBIOS_NAME_SERVERS         = 44,
+    DHO_NETBIOS_DD_SERVER            = 45,
+    DHO_NETBIOS_NODE_TYPE            = 46,
+    DHO_NETBIOS_SCOPE                = 47,
+    DHO_FONT_SERVERS                 = 48,
+    DHO_X_DISPLAY_MANAGER            = 49,
+    DHO_DHCP_REQUESTED_ADDRESS       = 50,
+    DHO_DHCP_LEASE_TIME              = 51,
+    DHO_DHCP_OPTION_OVERLOAD         = 52,
+    DHO_DHCP_MESSAGE_TYPE            = 53,
+    DHO_DHCP_SERVER_IDENTIFIER       = 54,
+    DHO_DHCP_PARAMETER_REQUEST_LIST  = 55,
+    DHO_DHCP_MESSAGE                 = 56,
+    DHO_DHCP_MAX_MESSAGE_SIZE        = 57,
+    DHO_DHCP_RENEWAL_TIME            = 58,
+    DHO_DHCP_REBINDING_TIME          = 59,
+    DHO_VENDOR_CLASS_IDENTIFIER      = 60,
+    DHO_DHCP_CLIENT_IDENTIFIER       = 61,
+    DHO_NWIP_DOMAIN_NAME             = 62,
+    DHO_NWIP_SUBOPTIONS              = 63,
+    DHO_USER_CLASS                   = 77,
+    DHO_FQDN                         = 81,
+    DHO_DHCP_AGENT_OPTIONS           = 82,
+    DHO_AUTHENTICATE                 = 90,  /* RFC3118, was 210 */
+    DHO_CLIENT_LAST_TRANSACTION_TIME = 91,
+    DHO_ASSOCIATED_IP                = 92,
+    DHO_SUBNET_SELECTION             = 118, /* RFC3011! */
+    DHO_DOMAIN_SEARCH                = 119, /* RFC3397 */
+    DHO_VIVCO_SUBOPTIONS             = 124,
+    DHO_VIVSO_SUBOPTIONS             = 125,
+
+    DHO_END                          = 255
+};
+
+/* DHCP message types. */
+enum DHCPMessageType {
+    DHCPDISCOVER        =  1,
+    DHCPOFFER           =  2,
+    DHCPREQUEST         =  3,
+    DHCPDECLINE         =  4,
+    DHCPACK             =  5,
+    DHCPNAK             =  6,
+    DHCPRELEASE         =  7,
+    DHCPINFORM          =  8,
+    DHCPLEASEQUERY      =  10,
+    DHCPLEASEUNASSIGNED =  11,
+    DHCPLEASEUNKNOWN    =  12,
+    DHCPLEASEACTIVE     =  13
+};
+
+static const uint16_t DHCP4_CLIENT_PORT = 68;
+static const uint16_t DHCP4_SERVER_PORT = 67;
+
+/// Magic cookie validating dhcp options field (and bootp vendor
+/// extensions field).
+///static const char* DHCP_OPTIONS_COOKIE = "\143\202\123\143";
+
+// TODO: Following are leftovers from dhcp.h import from ISC DHCP
+// They will be converted to C++-style defines once they will start
+// to be used.
+#if 0
+/* 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
+
+#endif
+
+} // end of isc::dhcp namespace
+} // end of isc namespace
+
+#endif /* DHCP_H */
diff --git a/src/lib/dhcp/dhcp6.h b/src/lib/dhcp/dhcp6.h
new file mode 100644
index 0000000..6012003
--- /dev/null
+++ b/src/lib/dhcp/dhcp6.h
@@ -0,0 +1,184 @@
+// 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/lib/dhcp/libdhcp.cc b/src/lib/dhcp/libdhcp.cc
new file mode 100644
index 0000000..8e6314e
--- /dev/null
+++ b/src/lib/dhcp/libdhcp.cc
@@ -0,0 +1,130 @@
+// 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 <boost/shared_array.hpp>
+#include <boost/shared_ptr.hpp>
+#include "dhcp/libdhcp.h"
+#include "config.h"
+#include "dhcp6.h"
+
+#include "option.h"
+#include "option6_ia.h"
+#include "option6_iaaddr.h"
+
+using namespace std;
+using namespace isc::dhcp;
+
+// static array with factories for options
+std::map<unsigned short, Option::Factory*> LibDHCP::v6factories_;
+
+unsigned int
+LibDHCP::unpackOptions6(const boost::shared_array<uint8_t> buf,
+                        unsigned int buf_len,
+                        unsigned int offset, unsigned int parse_len,
+                        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
+                  << ":  out of buffer");
+    }
+    unsigned int end = offset + parse_len;
+
+    while (offset +4 <= end) {
+        uint16_t opt_type = buf[offset]*256 + buf[offset+1];
+        offset += 2;
+        uint16_t opt_len = buf[offset]*256 + buf[offset+1];
+        offset += 2;
+
+        if (offset + opt_len > end ) {
+            cout << "Option " << opt_type << " truncated." << endl;
+            return (offset);
+        }
+        boost::shared_ptr<Option> opt;
+        switch (opt_type) {
+        case D6O_IA_NA:
+        case D6O_IA_PD:
+            // cout << "Creating Option6IA" << endl;
+            opt = boost::shared_ptr<Option>(new Option6IA(opt_type,
+                                                          buf, buf_len,
+                                                          offset,
+                                                          opt_len));
+            break;
+        case D6O_IAADDR:
+            // cout << "Creating Option6IAAddr" << endl;
+            opt = boost::shared_ptr<Option>(new Option6IAAddr(opt_type,
+                                                              buf, buf_len,
+                                                              offset, opt_len));
+            break;
+        default:
+            // cout << "Creating Option" << endl;
+            opt = boost::shared_ptr<Option>(new Option(Option::V6,
+                                                       opt_type,
+                                                       buf,
+                                                       offset,
+                                                       opt_len));
+            break;
+        }
+        // add option to options
+        options.insert(pair<int, boost::shared_ptr<Option> >(opt_type, opt));
+        offset += opt_len;
+    }
+
+    return (offset);
+}
+
+unsigned int
+LibDHCP::packOptions6(boost::shared_array<uint8_t> data,
+                      unsigned int data_len,
+                      unsigned int offset,
+                      const isc::dhcp::Option::Option6Collection& options) {
+    try {
+        for (isc::dhcp::Option::Option6Collection::const_iterator it = options.begin();
+             it != options.end();
+             ++it) {
+            unsigned short opt_len = (*it).second->len();
+            if (offset + opt_len > data_len) {
+                isc_throw(OutOfRange, "Failed to build option " <<
+                          (*it).first << ": out of buffer");
+            }
+            offset = (*it).second->pack(data, data_len, offset);
+        }
+    }
+    catch (const Exception& e) {
+        cout << "Packet build failed (Option build failed)." << endl;
+        throw;
+    }
+    return (offset);
+}
+
+bool
+LibDHCP::OptionFactoryRegister(Option::Universe u,
+                               unsigned short opt_type,
+                               Option::Factory * factory) {
+    switch (u) {
+    case Option::V6: {
+        if (v6factories_.find(opt_type)!=v6factories_.end()) {
+            isc_throw(BadValue, "There is already DHCPv6 factory registered "
+                     << "for option type "  << opt_type);
+        }
+        v6factories_[opt_type]=factory;
+        return true;
+    }
+    case Option::V4:
+    default:{
+        isc_throw(BadValue, "This universe type is not supported yet.");
+        return false; // never happens
+    }
+    }
+
+}
diff --git a/src/lib/dhcp/libdhcp.h b/src/lib/dhcp/libdhcp.h
new file mode 100644
index 0000000..c2ac949
--- /dev/null
+++ b/src/lib/dhcp/libdhcp.h
@@ -0,0 +1,83 @@
+// 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 LIBDHCP_H_
+#define LIBDHCP_H_
+
+#include <iostream>
+#include "dhcp/pkt6.h"
+
+namespace isc {
+namespace dhcp {
+
+class LibDHCP {
+
+public:
+    /// Builds collection of options.
+    ///
+    /// Builds raw (on-wire) data for provided collection of options.
+    ///
+    /// @param buf shared pointer to buffer. Data will be stored there.
+    /// @param buf_len buffer length. Used for buffer overflow protection.
+    /// @param offset Offset from beginning of the buffer, where store options
+    /// @param options collection of options to store to
+    ///
+    /// @return offset to the first unused byte in buffer (next one after last
+    ///         used byte)
+    ///
+    static unsigned int
+    packOptions6(boost::shared_array<uint8_t> buf, unsigned int buf_len,
+                 unsigned int offset,
+                 const isc::dhcp::Option::Option6Collection& options);
+
+    ///
+    /// Parses provided buffer and creates Option objects.
+    ///
+    /// Parses provided buf array and stores created Option objects
+    /// in options container.
+    ///
+    /// @param buf Buffer to be parsed.
+    /// @param offset Specifies offset for the first option.
+    /// @param options Reference to option container. Options will be
+    ///        put here.
+    ///
+    /// @return offset to first byte after last parsed option
+    ///
+    static unsigned int
+    unpackOptions6(const boost::shared_array<uint8_t> buf, unsigned int buf_len,
+                   unsigned int offset, unsigned int parse_len,
+                   isc::dhcp::Option::Option6Collection& options_);
+
+    ///
+    /// Registers factory method that produces options of specific option types.
+    ///
+    /// @param u universe of the option (V4 or V6)
+    /// @param opt_type option-type
+    /// @param factory function pointer
+    ///
+    /// @return true, if registration was successful, false otherwise
+    ///
+    static bool
+    OptionFactoryRegister(Option::Universe u,
+                          unsigned short type,
+                          Option::Factory * factory);
+protected:
+    // pointers to factories that produce DHCPv6 options
+    static std::map<unsigned short, Option::Factory*> v6factories_;
+};
+
+}
+}
+
+#endif
diff --git a/src/lib/dhcp/option.cc b/src/lib/dhcp/option.cc
new file mode 100644
index 0000000..dd45c34
--- /dev/null
+++ b/src/lib/dhcp/option.cc
@@ -0,0 +1,260 @@
+// 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 <string.h>
+#include <stdint.h>
+#include <arpa/inet.h>
+#include <sstream>
+#include <iomanip>
+#include <boost/shared_array.hpp>
+#include "exceptions/exceptions.h"
+#include "util/io_utilities.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) {
+
+
+}
+
+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)
+      {
+
+    // sanity checks
+    // TODO: universe must be in V4 and V6
+}
+
+unsigned int
+Option::pack(boost::shared_array<uint8_t>& buf,
+             unsigned int buf_len,
+             unsigned int offset) {
+    switch (universe_) {
+    case V4:
+        return pack4(buf, buf_len, offset);
+    case V6:
+        return pack6(buf, buf_len, offset);
+    default:
+        isc_throw(BadValue, "Unknown universe defined for Option " << type_);
+    }
+}
+
+
+unsigned int
+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.");
+    }
+    uint8_t *ptr = &buf[offset];
+    ptr[0] = type_;
+    ptr[1] = data_len_;
+    ptr += 2;
+    memcpy(ptr, &data_[0], data_len_);
+
+    return offset + len();
+}
+
+unsigned int
+Option::pack6(boost::shared_array<uint8_t>& buf,
+             unsigned int buf_len,
+             unsigned int offset) {
+    if ( offset+len() > buf_len ) {
+        isc_throw(OutOfRange, "Failed to pack v6 option=" <<
+                  type_ << ",len=" << len() << ": too small buffer.");
+    }
+
+    uint8_t * ptr = &buf[offset];
+
+    ptr = writeUint16(type_, ptr);
+
+    ptr = writeUint16(len() - getHeaderLen(), ptr);
+
+    if (data_len_)
+        memcpy(ptr, &data_[offset_], data_len_);
+
+    // end of fixed part of this option
+    offset += OPTION6_HDR_LEN + data_len_;
+
+    return LibDHCP::packOptions6(buf, buf_len, offset, options_);
+}
+
+unsigned int
+Option::unpack(const boost::shared_array<uint8_t>& buf,
+               unsigned int buf_len,
+               unsigned int offset,
+               unsigned int parse_len) {
+    switch (universe_) {
+    case V4:
+        return unpack4(buf, buf_len, offset, parse_len);
+    case V6:
+        return unpack6(buf, buf_len, offset, parse_len);
+    default:
+        isc_throw(BadValue, "Unknown universe defined for Option " << type_);
+    }
+
+    return 0; // should not happen
+}
+
+unsigned int
+Option::unpack4(const boost::shared_array<uint8_t>&,
+                unsigned int ,
+                unsigned int ,
+                unsigned int ) {
+    isc_throw(Unexpected, "IPv4 support not implemented yet.");
+    return 0;
+}
+
+unsigned int
+Option::unpack6(const boost::shared_array<uint8_t>& buf,
+                unsigned int buf_len,
+                unsigned int offset,
+                unsigned int parse_len) {
+
+    if (buf_len < offset+parse_len) {
+        isc_throw(OutOfRange, "Failed to unpack DHCPv6 option len="
+                  << parse_len << " offset=" << offset
+                  << " from buffer (length=" << buf_len
+                  << "): too small buffer.");
+    }
+
+    data_ = buf;
+    offset_ = offset;
+    data_len_ = buf_len;
+
+    return LibDHCP::unpackOptions6(buf, buf_len, offset, parse_len,
+                                   options_);
+}
+
+unsigned short
+Option::len() {
+
+    // length of the whole option is header and data stored in this option...
+    int length = getHeaderLen() + data_len_;
+
+    // ... 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() {
+    if (universe_ != V4 &&
+        universe_ != V6) {
+        return (false);
+    }
+
+    return (true);
+}
+
+void
+isc::dhcp::Option::addOption(boost::shared_ptr<isc::dhcp::Option> opt) {
+    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::Option6Collection::const_iterator x =
+        options_.find(opt_type);
+    if ( x != options_.end() ) {
+        return (*x).second;
+    }
+    return boost::shared_ptr<isc::dhcp::Option>(); // NULL
+}
+
+bool
+Option::delOption(unsigned short opt_type) {
+    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
+}
+
+
+std::string Option::toText(int indent /* =0 */ ) {
+    std::stringstream tmp;
+
+    for (int i=0; i<indent; i++)
+        tmp << " ";
+
+    tmp << "type=" << type_ << ", len=" << data_len_ << ": ";
+
+    for (unsigned int i=0; i<data_len_; i++) {
+        if (i) {
+            tmp << ":";
+        }
+        tmp << setfill('0') << setw(2) << hex
+            << static_cast<unsigned short>(data_[offset_+i]);
+    }
+
+    // print suboptions
+    for (Option6Collection::const_iterator opt=options_.begin();
+         opt!=options_.end();
+         ++opt) {
+        tmp << (*opt).second->toText(indent+2);
+    }
+    return tmp.str();
+}
+
+unsigned short
+Option::getType() {
+    return type_;
+}
+
+uint8_t*
+Option::getData() {
+    if (data_len_) {
+        return (&data_[offset_]);
+    } else {
+        return (NULL);
+    }
+}
+
+unsigned short
+Option::getHeaderLen() {
+    switch (universe_) {
+    case V4:
+        return OPTION4_HDR_LEN; // header length for v4
+    case 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
new file mode 100644
index 0000000..5be1be3
--- /dev/null
+++ b/src/lib/dhcp/option.h
@@ -0,0 +1,273 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef OPTION_H_
+#define OPTION_H_
+
+#include <string>
+#include <map>
+#include <boost/shared_ptr.hpp>
+#include <boost/shared_array.hpp>
+
+namespace isc {
+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 };
+
+    /// 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<uint8_t>& buf,
+                                              unsigned int offset,
+                                              unsigned int len);
+
+    /// @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);
+
+    /// @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);
+
+    /// @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<uint8_t>& buf,
+         unsigned int buf_len,
+         unsigned int offset);
+
+    /// @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 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();
+
+    /// Returns length of the complete option (data length + DHCPv4/DHCPv6
+    /// 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 uint8_t*
+    getData();
+
+    /// Adds a sub-option.
+    ///
+    /// 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);
+
+    /// Returns shared_ptr to suboption of specific type
+    ///
+    /// @param type type of requested suboption
+    ///
+    /// @return shared_ptr to requested suoption
+    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);
+
+    /// 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.
+    ///
+    /// @param buf output buffer (built options will be stored here)
+    /// @param buf_len buffer length (used for buffer overflow checks)
+    /// @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<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.
+    ///
+    /// @param buf output buffer (built options will be stored here)
+    /// @param buf_len buffer length (used for buffer overflow checks)
+    /// @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<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)
+    /// @param buf_len buffer length (used for buffer overflow checks)
+    /// @param offset offset from start of the buf buffer
+    ///
+    /// @return offset to the next byte after last parsed byte
+    virtual unsigned int
+    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)
+    /// @param buf_len buffer length (used for buffer overflow checks)
+    /// @param offset offset from start of the buf buffer
+    ///
+    /// @return offset to the next byte after last parsed byte
+    virtual unsigned int
+    unpack6(const boost::shared_array<uint8_t>& buf,
+            unsigned int buf_len,
+            unsigned int offset,
+            unsigned int parse_len);
+
+    /// 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_;
+
+    /// 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)
+};
+
+} // namespace isc::dhcp
+} // namespace isc
+
+#endif
diff --git a/src/lib/dhcp/option6_addrlst.cc b/src/lib/dhcp/option6_addrlst.cc
new file mode 100644
index 0000000..fc981fa
--- /dev/null
+++ b/src/lib/dhcp/option6_addrlst.cc
@@ -0,0 +1,134 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <stdint.h>
+#include <arpa/inet.h>
+#include <sstream>
+#include "exceptions/exceptions.h"
+
+#include "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,
+                               const AddressContainer& addrs)
+    :Option(V6, type), addrs_(addrs) {
+}
+
+Option6AddrLst::Option6AddrLst(unsigned short type,
+                               const isc::asiolink::IOAddress& addr)
+    :Option(V6, type), addrs_(1,addr) {
+}
+
+Option6AddrLst::Option6AddrLst(unsigned short type,
+                               boost::shared_array<uint8_t> buf,
+                               unsigned int buf_len,
+                               unsigned int offset,
+                               unsigned int option_len)
+    :Option(V6, type) {
+    unpack(buf, buf_len, offset, option_len);
+}
+
+void
+Option6AddrLst::setAddress(const isc::asiolink::IOAddress& addr) {
+    addrs_.clear();
+    addrs_.push_back(addr);
+}
+
+void
+Option6AddrLst::setAddresses(const AddressContainer& addrs) {
+    addrs_ = addrs;
+}
+
+unsigned int
+Option6AddrLst::pack(boost::shared_array<uint8_t>& buf,
+                    unsigned int buf_len,
+                    unsigned int offset) {
+    if (len() > buf_len) {
+        isc_throw(OutOfRange, "Failed to pack IA option: len=" << len()
+                  << ", buffer=" << buf_len << ": too small buffer.");
+    }
+
+    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);
+
+    // 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(),
+               V6ADDRESS_LEN);
+        offset += V6ADDRESS_LEN;
+    }
+
+    return offset;
+}
+
+unsigned int
+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.");
+    }
+
+    if (option_len%16) {
+        isc_throw(OutOfRange, "Option " << type_
+                  << " malformed: len=" << option_len
+                  << " is not divisible by 16.");
+    }
+    while (option_len > 0) {
+        addrs_.push_back(IOAddress::from_bytes(AF_INET6, &buf[offset]));
+        offset += 16;
+        option_len -= 16;
+    }
+
+    return offset;
+}
+
+std::string Option6AddrLst::toText(int indent /* =0 */) {
+    stringstream tmp;
+    for (int i=0; i<indent; i++)
+        tmp << " ";
+
+    tmp << "type=" << type_ << " " << addrs_.size() << "addr(s): ";
+
+    for (AddressContainer::const_iterator addr=addrs_.begin();
+         addr!=addrs_.end();
+         ++addr) {
+        tmp << addr->toText() << " ";
+    }
+    return tmp.str();
+}
+
+unsigned short Option6AddrLst::len() {
+
+    return (OPTION6_HDR_LEN + addrs_.size()*16);
+}
diff --git a/src/lib/dhcp/option6_addrlst.h b/src/lib/dhcp/option6_addrlst.h
new file mode 100644
index 0000000..c5b32af
--- /dev/null
+++ b/src/lib/dhcp/option6_addrlst.h
@@ -0,0 +1,127 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef OPTION6_ADDRLST_H_
+#define OPTION6_ADDRLST_H_
+
+#include <vector>
+#include "asiolink/io_address.h"
+#include "dhcp/option.h"
+
+namespace isc {
+namespace dhcp {
+
+/// @brief Option class for handling list of IPv6 addresses.
+///
+/// This class handles a list of IPv6 addresses. An example of such option
+/// is dns-servers option. It can also be used to handle single address.
+///
+class Option6AddrLst: public Option {
+
+public:
+    /// a container for (IPv6) addresses
+    typedef std::vector<isc::asiolink::IOAddress> AddressContainer;
+
+    /// @brief Constructor used during option generation.
+    ///
+    /// @param type option type
+    /// @param addrs vector of addresses to be stored
+    ///
+    Option6AddrLst(unsigned short type,
+                   const AddressContainer& addrs);
+
+    /// @brief Simplified constructor for a single address
+    ///
+    /// @param type option type
+    /// @param addr a single address to be stored
+    ///
+    Option6AddrLst(unsigned short type,
+                   const isc::asiolink::IOAddress& addr);
+
+    /// @brief Constructor used for parsing received option
+    ///
+    /// @param type option type
+    /// @param buf pointer to packet buffer
+    /// @param buf_len length of packet buffer
+    /// @param offset offset to beginning of option data
+    /// @param len length of option data
+    ///
+    Option6AddrLst(unsigned short type, boost::shared_array<uint8_t> buf,
+                   unsigned int buf_len,
+                   unsigned int offset,
+                   unsigned int len);
+
+    /// @brief Assembles on-wire form of this option
+    ///
+    /// @param buf pointer to packet buffer
+    /// @param buf_len length of packet buffer
+    /// @param offset offset to place, where option is to be stored
+    ///
+    /// @return offset to the next unused char (just after stored option)
+    ///
+    unsigned int
+    pack(boost::shared_array<uint8_t>& buf, unsigned int buf_len,
+         unsigned int offset);
+
+    /// @brief Parses received data
+    ///
+    /// @param buf pointer to packet buffer
+    /// @param buf_len length of packet buffer
+    /// @param offset offset to option data
+    /// @param parse_len specified option data length
+    ///
+    /// @return offset to the next unparsed char (just after parsed option)
+    ///
+    virtual unsigned int
+    unpack(const boost::shared_array<uint8_t>& buf,
+           unsigned int buf_len,
+           unsigned int offset,
+           unsigned int parse_len);
+
+    virtual std::string toText(int indent = 0);
+
+    /// @brief Sets a single address.
+    ///
+    /// @param addr a single address to be added
+    ///
+    void setAddress(const isc::asiolink::IOAddress& addr);
+
+    /// @brief Sets list of addresses.
+    ///
+    /// @param addrs a vector of addresses to be added
+    ///
+    void setAddresses(const AddressContainer& addrs);
+
+    /// @brief Returns vector with addresses.
+    ///
+    /// As user may want to use/modify this list, it is better to return
+    /// a copy rather than const reference to the original. This is
+    /// usually one or two addresses long, so it is not a big deal.
+    ///
+    /// @return vector with addresses
+    ///
+    AddressContainer
+    getAddresses() { return addrs_; };
+
+    // returns data length (data length + DHCPv4/DHCPv6 option header)
+    virtual unsigned short len();
+
+protected:
+    AddressContainer addrs_;
+};
+
+} // isc::dhcp namespace
+} // isc namespace
+
+#endif /* OPTION_ADDRLST_H_ */
diff --git a/src/lib/dhcp/option6_ia.cc b/src/lib/dhcp/option6_ia.cc
new file mode 100644
index 0000000..ee314db
--- /dev/null
+++ b/src/lib/dhcp/option6_ia.cc
@@ -0,0 +1,136 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <stdint.h>
+#include <arpa/inet.h>
+#include <sstream>
+#include "exceptions/exceptions.h"
+
+#include "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(unsigned short type, unsigned int iaid)
+    :Option(Option::V6, type), iaid_(iaid) {
+}
+
+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<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()
+                  << ", buffer=" << buf_len << ": too small buffer.");
+    }
+
+    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];
+
+    ptr = writeUint16(type_, ptr);
+    ptr = writeUint16(len() - OPTION6_HDR_LEN, ptr);
+    offset += OPTION6_HDR_LEN;
+
+    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(const boost::shared_array<uint8_t>& buf,
+                  unsigned int buf_len,
+                  unsigned int offset,
+                  unsigned int parse_len) {
+    if ( parse_len < OPTION6_IA_LEN || offset + OPTION6_IA_LEN > buf_len) {
+        isc_throw(OutOfRange, "Option " << type_ << " truncated");
+    }
+    
+    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);
+}
+
+std::string Option6IA::toText(int indent /* = 0*/) {
+    stringstream tmp;
+
+    for (int i=0; i<indent; i++)
+        tmp << " ";
+    tmp << "type=" << type_;
+
+    switch (type_) {
+    case D6O_IA_NA:
+        tmp << "(IA_NA)";
+        break;
+    case D6O_IA_PD:
+        tmp << "(IA_PD)";
+        break;
+    default:
+        tmp << "(unknown)";
+    }
+    tmp << " iaid=" << iaid_ << ", t1=" << t1_ << ", t2=" << t2_
+        << " " << options_.size() << " sub-options:" << endl;
+
+    for (Option6Collection::const_iterator opt=options_.begin();
+         opt!=options_.end();
+         ++opt) {
+        tmp << (*opt).second->toText(indent+2);
+    }
+    return tmp.str();
+}
+
+unsigned short Option6IA::len() {
+
+    unsigned short length = OPTION6_HDR_LEN /*header (4)*/ +
+        OPTION6_IA_LEN  /* option content (12) */;
+
+    // length of all suboptions
+    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
new file mode 100644
index 0000000..516b2fc
--- /dev/null
+++ b/src/lib/dhcp/option6_ia.h
@@ -0,0 +1,137 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef OPTION_IA_H_
+#define OPTION_IA_H_
+
+#include <stdint.h>
+#include "option.h"
+
+namespace isc {
+namespace dhcp {
+
+class Option6IA: public Option {
+
+public:
+    /// 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<uint8_t>& buf, unsigned int buf_len,
+         unsigned int offset);
+
+    /// @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(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 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; }
+
+    /// 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 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_;
+};
+
+} // isc::dhcp namespace
+} // isc namespace
+
+#endif /* OPTION_IA_H_ */
diff --git a/src/lib/dhcp/option6_iaaddr.cc b/src/lib/dhcp/option6_iaaddr.cc
new file mode 100644
index 0000000..d5b57dd
--- /dev/null
+++ b/src/lib/dhcp/option6_iaaddr.cc
@@ -0,0 +1,132 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <stdint.h>
+#include <arpa/inet.h>
+#include <sstream>
+#include "exceptions/exceptions.h"
+
+#include "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,
+                             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<uint8_t> buf,
+                             unsigned int buf_len, unsigned int offset,
+                             unsigned int option_len)
+    :Option(V6, type), addr_("::") {
+    unpack(buf, buf_len, offset, option_len);
+}
+
+unsigned int
+Option6IAAddr::pack(boost::shared_array<uint8_t>& buf,
+                    unsigned int buf_len,
+                    unsigned int offset) {
+    if (len() > buf_len) {
+        isc_throw(OutOfRange, "Failed to pack IA option: len=" << len()
+                  << ", buffer=" << buf_len << ": too small buffer.");
+    }
+
+    uint8_t* ptr = &buf[offset];
+
+    ptr = writeUint16(type_, ptr);
+
+    // 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, options_);
+    return offset;
+}
+
+unsigned int
+Option6IAAddr::unpack(const boost::shared_array<uint8_t>& buf,
+                  unsigned int buf_len,
+                  unsigned int offset,
+                  unsigned int parse_len) {
+    if ( parse_len < OPTION6_IAADDR_LEN || offset + OPTION6_IAADDR_LEN > buf_len) {
+        isc_throw(OutOfRange, "Option " << type_ << " truncated");
+    }
+
+    // 16 bytes: IPv6 address
+    addr_ = IOAddress::from_bytes(AF_INET6, &buf[offset]);
+    offset += V6ADDRESS_LEN;
+
+    preferred_ = readUint32(&buf[offset]);
+    offset += sizeof(uint32_t);
+
+    valid_ = readUint32(&buf[offset]);
+    offset += sizeof(uint32_t);
+    offset = LibDHCP::unpackOptions6(buf, buf_len, offset,
+                                     parse_len - 24, options_);
+
+    return offset;
+}
+
+std::string Option6IAAddr::toText(int indent /* =0 */) {
+    stringstream tmp;
+    for (int i=0; i<indent; i++)
+        tmp << " ";
+
+    tmp << "type=" << type_ << "(IAADDR) addr=" << addr_.toText()
+        << ", preferred-lft=" << preferred_  << ", valid-lft="
+        << valid_ << endl;
+
+    for (Option6Collection::const_iterator opt=options_.begin();
+         opt!=options_.end();
+         ++opt) {
+        tmp << (*opt).second->toText(indent+2);
+    }
+    return tmp.str();
+}
+
+unsigned short Option6IAAddr::len() {
+
+    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::Option6Collection::iterator it = options_.begin();
+         it != options_.end();
+         ++it) {
+        length += (*it).second->len();
+    }
+    return (length);
+}
diff --git a/src/lib/dhcp/option6_iaaddr.h b/src/lib/dhcp/option6_iaaddr.h
new file mode 100644
index 0000000..60c5c48
--- /dev/null
+++ b/src/lib/dhcp/option6_iaaddr.h
@@ -0,0 +1,146 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef OPTION6_IAADDR_H_
+#define OPTION6_IAADDR_H_
+
+#include "asiolink/io_address.h"
+#include "dhcp/option.h"
+
+namespace isc {
+namespace dhcp {
+
+class Option6IAAddr: public Option {
+
+public:
+    /// 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<uint8_t>& buf, unsigned int buf_len,
+         unsigned int offset);
+
+    /// @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 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);
+
+
+    /// 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; }
+
+    /// Returns  address contained within this option.
+    ///
+    /// @return address
+    isc::asiolink::IOAddress
+    getAddress() const { return addr_; }
+
+    /// 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..d8e05d9
--- /dev/null
+++ b/src/lib/dhcp/pkt4.cc
@@ -0,0 +1,189 @@
+// 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 <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 {
+namespace dhcp {
+
+const IOAddress DEFAULT_ADDRESS("0.0.0.0");
+
+Pkt4::Pkt4(uint8_t msg_type, uint32_t transid)
+     :local_addr_(DEFAULT_ADDRESS),
+      remote_addr_(DEFAULT_ADDRESS),
+      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_(DEFAULT_ADDRESS),
+      yiaddr_(DEFAULT_ADDRESS),
+      siaddr_(DEFAULT_ADDRESS),
+      giaddr_(DEFAULT_ADDRESS),
+      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_(DEFAULT_ADDRESS),
+      remote_addr_(DEFAULT_ADDRESS),
+      iface_(""),
+      ifindex_(-1),
+      local_port_(DHCP4_SERVER_PORT),
+      remote_port_(DHCP4_CLIENT_PORT),
+      /// TODO Fixed fields, uncomment in ticket #1224
+      op_(BOOTREQUEST),
+      transid_(0),
+      secs_(0),
+      flags_(0),
+      ciaddr_(DEFAULT_ADDRESS),
+      yiaddr_(DEFAULT_ADDRESS),
+      siaddr_(DEFAULT_ADDRESS),
+      giaddr_(DEFAULT_ADDRESS),
+      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 std::vector<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.");
+    }
+    if ( (macAddr.size() == 0) && (hlen > 0) ) {
+        isc_throw(OutOfRange, "Invalid HW Address specified");
+    }
+
+    htype_ = hType;
+    hlen_ = hlen;
+    memset(chaddr_, 0, MAX_CHADDR_LEN);
+    memcpy(chaddr_, &macAddr[0], 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 fileLen 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) );
+    }
+}
+
+} // end of namespace isc::dhcp
+
+} // end of namespace isc
diff --git a/src/lib/dhcp/pkt4.h b/src/lib/dhcp/pkt4.h
new file mode 100644
index 0000000..7ac0ca9
--- /dev/null
+++ b/src/lib/dhcp/pkt4.h
@@ -0,0 +1,380 @@
+// 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 <vector>
+#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;
+
+    /// specifies 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);
+
+    /// @brief Constructor, used in message reception.
+    ///
+    /// Creates new message. Pkt4 will copy data to bufferIn_
+    /// buffer on creation.
+    ///
+    /// @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 of DHCPv4 packet.
+    ///
+    /// Prepares on-wire format of message and all its options.
+    /// Options must be stored in options_ field.
+    /// Output buffer will be stored in bufferOut_.
+    ///
+    /// @return true if packing procedure was successful
+    bool
+    pack();
+
+    /// @brief Parses on-wire form of DHCPv4 packet.
+    ///
+    /// Parses received packet, stored in on-wire format in bufferIn_.
+    ///
+    /// Will create a collection of option objects that will
+    /// be stored in options_ container.
+    ///
+    /// @return true, if parsing 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 the size of the required buffer to build the packet.
+    ///
+    /// Returns the size of the required buffer to build the packet with
+    /// the current set of packet options.
+    ///
+    /// @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 not use strlen() or similar on it.
+    ///
+    /// @return sname field
+    const std::vector<uint8_t>
+    getSname() { return (std::vector<uint8_t>(sname_, &sname_[MAX_SNAME_LEN])); };
+
+    /// 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 not use strlen() or similar on it.
+    ///
+    /// @return pointer to file field
+    const std::vector<uint8_t>
+    getFile() { return (std::vector<uint8_t>(file_, &file_[MAX_FILE_LEN])); };
+
+    /// Sets file field
+    ///
+    /// @param file value to be set
+    void
+    setFile(const uint8_t* file, size_t fileLen = MAX_FILE_LEN);
+
+    /// @brief Sets hardware address.
+    ///
+    /// Sets parameters of hardware address. hlen specifies
+    /// length of macAddr buffer. Content of macAddr buffer
+    /// will be copied to appropriate field.
+    ///
+    /// Note: macAddr must be a buffer of at least hlen bytes.
+    ///
+    /// @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 std::vector<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
+    ///
+    /// 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. MS Windows)
+    int ifindex_;
+
+    /// local UDP port
+    int local_port_;
+
+    /// remote UDP port
+    int remote_port_;
+
+    /// @brief message operation code
+    ///
+    /// Note: This is legacy BOOTP field. There's no need to manipulate it
+    /// directly. Its value is set based on DHCP message type. Note that
+    /// DHCPv4 protocol reuses BOOTP message format, so this field is
+    /// kept due to BOOTP format. This is NOT DHCPv4 type (DHCPv4 message
+    /// type is kept in message type option).
+    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_;
+
+    /// Hardware address field (16 bytes)
+    uint8_t chaddr_[MAX_CHADDR_LEN];
+
+    /// sname field (64 bytes)
+    uint8_t sname_[MAX_SNAME_LEN];
+
+    /// file field (128 bytes)
+    uint8_t file_[MAX_FILE_LEN];
+
+    // 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
new file mode 100644
index 0000000..b00652a
--- /dev/null
+++ b/src/lib/dhcp/pkt6.cc
@@ -0,0 +1,225 @@
+// 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 "dhcp/dhcp6.h"
+#include "dhcp/pkt6.h"
+#include "dhcp/libdhcp.h"
+#include "exceptions/exceptions.h"
+#include <iostream>
+#include <sstream>
+
+using namespace std;
+using namespace isc::dhcp;
+
+namespace isc {
+
+Pkt6::Pkt6(unsigned int dataLen, DHCPv6Proto proto /* = UDP */)
+    :data_len_(dataLen),
+     local_addr_("::"),
+     remote_addr_("::"),
+     iface_(""),
+     ifindex_(-1),
+     local_port_(-1),
+     remote_port_(-1),
+     proto_(proto),
+     msg_type_(-1),
+     transid_(rand()%0xffffff)
+{
+
+    data_ = boost::shared_array<uint8_t>(new uint8_t[dataLen]);
+    data_len_ = dataLen;
+}
+
+Pkt6::Pkt6(uint8_t msg_type,
+           unsigned int transid,
+           DHCPv6Proto proto /*= UDP*/)
+    :local_addr_("::"),
+     remote_addr_("::"),
+     iface_(""),
+     ifindex_(-1),
+     local_port_(-1),
+     remote_port_(-1),
+     proto_(proto),
+     msg_type_(msg_type),
+     transid_(transid) {
+
+    data_ = boost::shared_array<uint8_t>(new uint8_t[4]);
+    data_len_ = 4;
+}
+
+unsigned short
+Pkt6::len() {
+    unsigned int length = DHCPV6_PKT_HDR_LEN; // DHCPv6 header
+
+    for (Option::Option6Collection::iterator it = options_.begin();
+         it != options_.end();
+         ++it) {
+        length += (*it).second->len();
+    }
+
+    return (length);
+}
+
+
+bool
+Pkt6::pack() {
+    switch (proto_) {
+    case UDP:
+        return packUDP();
+    case TCP:
+        return packTCP();
+    default:
+        isc_throw(BadValue, "Invalid protocol specified (non-TCP, non-UDP)");
+    }
+    return (false); // never happens
+}
+
+bool
+Pkt6::packUDP() {
+    unsigned short length = len();
+    if (data_len_ < length) {
+        cout << "Previous len=" << data_len_ << ", allocating new buffer: len="
+             << length << endl;
+
+        // 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_;
+
+        // store 3-octet transaction-id
+        data_[1] = (transid_ >> 16) & 0xff;
+        data_[2] = (transid_ >> 8) & 0xff;
+        data_[3] = (transid_) & 0xff;
+
+        // the rest are options
+        unsigned short offset = LibDHCP::packOptions6(data_, length,
+                                                      4/*offset*/,
+                                                      options_);
+
+        // sanity check
+        if (offset != length) {
+            isc_throw(OutOfRange, "Packet build failed: expected size="
+                      << length << ", actual len=" << offset);
+        }
+    }
+    catch (const Exception& e) {
+        cout << "Packet build failed:" << e.what() << endl;
+        return (false);
+    }
+    // Limited verbosity of this method
+    // cout << "Packet built, len=" << len() << endl;
+    return (true);
+}
+
+bool
+Pkt6::packTCP() {
+    /// TODO Implement this function.
+    isc_throw(Unexpected, "DHCPv6 over TCP (bulk leasequery and failover)"
+              "not implemented yet.");
+}
+
+bool
+Pkt6::unpack() {
+    switch (proto_) {
+    case UDP:
+        return unpackUDP();
+    case TCP:
+        return unpackTCP();
+    default:
+        isc_throw(BadValue, "Invalid protocol specified (non-TCP, non-UDP)");
+    }
+    return (false); // never happens
+}
+
+bool
+Pkt6::unpackUDP() {
+    if (data_len_ < 4) {
+        std::cout << "DHCPv6 packet truncated. Only " << data_len_
+                  << " bytes. Need at least 4." << std::endl;
+        return (false);
+    }
+    msg_type_ = data_[0];
+    transid_ = ( (data_[1]) << 16 ) +
+        ((data_[2]) << 8) + (data_[3]);
+    transid_ = transid_ & 0xffffff;
+
+    unsigned int offset = LibDHCP::unpackOptions6(data_,
+                                                  data_len_,
+                                                  4, //offset
+                                                  data_len_ - 4,
+                                                  options_);
+    if (offset != data_len_) {
+        cout << "DHCPv6 packet contains trailing garbage. Parsed "
+             << offset << " bytes, packet is " << data_len_ << " bytes."
+             << endl;
+        // just a warning. Ignore trailing garbage and continue
+    }
+    return (true);
+}
+
+bool
+Pkt6::unpackTCP() {
+    isc_throw(Unexpected, "DHCPv6 over TCP (bulk leasequery and failover) "
+              "not implemented yet.");
+}
+
+
+std::string
+Pkt6::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;
+    for (isc::dhcp::Option::Option6Collection::iterator opt=options_.begin();
+         opt != options_.end();
+         ++opt) {
+        tmp << opt->second->toText() << std::endl;
+    }
+    return tmp.str();
+}
+
+boost::shared_ptr<isc::dhcp::Option>
+Pkt6::getOption(unsigned short 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
+}
+
+void
+Pkt6::addOption(boost::shared_ptr<Option> opt) {
+    options_.insert(pair<int, boost::shared_ptr<Option> >(opt->getType(), opt));
+}
+
+bool
+Pkt6::delOption(unsigned short type) {
+    isc::dhcp::Option::Option6Collection::iterator x = options_.find(type);
+    if (x!=options_.end()) {
+        options_.erase(x);
+        return (true); // delete successful
+    }
+    return (false); // can't find option to be deleted
+}
+
+};
diff --git a/src/lib/dhcp/pkt6.h b/src/lib/dhcp/pkt6.h
new file mode 100644
index 0000000..d089444
--- /dev/null
+++ b/src/lib/dhcp/pkt6.h
@@ -0,0 +1,234 @@
+// 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_ptr.hpp>
+#include <boost/shared_array.hpp>
+#include "asiolink/io_address.h"
+#include "dhcp/option.h"
+
+namespace isc {
+
+namespace dhcp {
+
+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
new file mode 100644
index 0000000..41cabba
--- /dev/null
+++ b/src/lib/dhcp/tests/Makefile.am
@@ -0,0 +1,43 @@
+SUBDIRS = .
+
+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)
+
+if USE_STATIC_LINK
+AM_LDFLAGS = -static
+endif
+
+CLEANFILES = *.gcno *.gcda
+
+TESTS =
+if HAVE_GTEST
+TESTS += libdhcp_unittests
+libdhcp_unittests_SOURCES  = run_unittests.cc
+libdhcp_unittests_SOURCES += ../libdhcp.h ../libdhcp.cc libdhcp_unittest.cc
+libdhcp_unittests_SOURCES += ../option6_iaaddr.h ../option6_iaaddr.cc option6_iaaddr_unittest.cc
+libdhcp_unittests_SOURCES += ../option6_ia.h ../option6_ia.cc option6_ia_unittest.cc
+libdhcp_unittests_SOURCES += ../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)
+
+libdhcp_unittests_CXXFLAGS = $(AM_CXXFLAGS)
+if USE_CLANGPP
+# This is to workaround unused variables tcout and tcerr in
+# log4cplus's streams.h.
+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/libutil.la
+libdhcp_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
+libdhcp_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
+endif
+
+noinst_PROGRAMS = $(TESTS)
diff --git a/src/lib/dhcp/tests/libdhcp_unittest.cc b/src/lib/dhcp/tests/libdhcp_unittest.cc
new file mode 100644
index 0000000..d9d7c47
--- /dev/null
+++ b/src/lib/dhcp/tests/libdhcp_unittest.cc
@@ -0,0 +1,137 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <config.h>
+#include <iostream>
+#include <sstream>
+
+#include <arpa/inet.h>
+#include <gtest/gtest.h>
+
+#include "dhcp/libdhcp.h"
+#include "config.h"
+
+using namespace std;
+using namespace isc;
+using namespace isc::dhcp;
+
+namespace {
+class LibDhcpTest : public ::testing::Test {
+public:
+    LibDhcpTest() {
+    }
+};
+
+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<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++) {
+        buf[i]=i+100;
+    }
+
+    boost::shared_ptr<Option> opt1(new Option(Option::V6, 12, buf, 0, 5));
+    boost::shared_ptr<Option> opt2(new Option(Option::V6, 13, buf, 5, 3));
+    boost::shared_ptr<Option> opt3(new Option(Option::V6, 14, buf, 8, 2));
+    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));
+
+    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));
+    opts.insert(pair<int, boost::shared_ptr<Option> >(opt1->getType(), opt4));
+    opts.insert(pair<int, boost::shared_ptr<Option> >(opt1->getType(), opt5));
+
+    unsigned int offset;
+    EXPECT_NO_THROW ({
+         offset = LibDHCP::packOptions6(buf, 512, 100, opts);
+    });
+    EXPECT_EQ(135, offset); // options should take 35 bytes
+    EXPECT_EQ(0, memcmp(&buf[100], packed, 35) );
+}
+
+TEST_F(LibDhcpTest, unpackOptions6) {
+
+    // just couple of random options
+    // Option is used as a simple option implementation
+    // More advanced uses are validated in tests dedicated for
+    // specific derived classes.
+    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<uint8_t> buf(new uint8_t[512]);
+    memcpy(&buf[0], packed, 35);
+
+    unsigned int offset;
+    EXPECT_NO_THROW ({
+        offset = LibDHCP::unpackOptions6(buf, 512, 0, 35, options);
+    });
+
+    EXPECT_EQ(35, offset); // parsed first 35 bytes (offset 0..34)
+    EXPECT_EQ(options.size(), 5); // there should be 5 options
+
+    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
+
+    x = options.find(13);
+    ASSERT_FALSE(x == options.end()); // option 13 should exist
+    EXPECT_EQ(13, x->second->getType());  // this should be option 13
+    ASSERT_EQ(7, x->second->len()); // it should be of length 7
+    EXPECT_EQ(0, memcmp(x->second->getData(), packed+13, 3)); // data len=3
+
+    x = options.find(14);
+    ASSERT_FALSE(x == options.end()); // option 3 should exist
+    EXPECT_EQ(14, x->second->getType());  // this should be option 14
+    ASSERT_EQ(6, x->second->len()); // it should be of length 6
+    EXPECT_EQ(0, memcmp(x->second->getData(), packed+20, 2)); // data len=2
+
+    x = options.find(256);
+    ASSERT_FALSE(x == options.end()); // option 256 should exist
+    EXPECT_EQ(256, x->second->getType());  // this should be option 256
+    ASSERT_EQ(8, x->second->len()); // it should be of length 7
+    EXPECT_EQ(0, memcmp(x->second->getData(), packed+26, 4)); // data len=4
+
+    x = options.find(257);
+    ASSERT_FALSE(x == options.end()); // option 257 should exist
+    EXPECT_EQ(257, x->second->getType());  // this should be option 257
+    ASSERT_EQ(5, x->second->len()); // it should be of length 5
+    EXPECT_EQ(0, memcmp(x->second->getData(), packed+34, 1)); // data len=1
+
+    x = options.find(0);
+    EXPECT_TRUE(x == options.end()); // option 0 not found
+
+    x = options.find(1); // 1 is htons(256) on little endians. Worth checking
+    EXPECT_TRUE(x == options.end()); // option 1 not found
+
+    x = options.find(2);
+    EXPECT_TRUE(x == options.end()); // option 2 not found
+
+    x = options.find(32000);
+    EXPECT_TRUE(x == options.end()); // option 32000 not found
+}
+
+}
diff --git a/src/lib/dhcp/tests/option6_addrlst_unittest.cc b/src/lib/dhcp/tests/option6_addrlst_unittest.cc
new file mode 100644
index 0000000..2a2fc1a
--- /dev/null
+++ b/src/lib/dhcp/tests/option6_addrlst_unittest.cc
@@ -0,0 +1,231 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <config.h>
+#include <iostream>
+#include <sstream>
+
+#include <arpa/inet.h>
+#include <gtest/gtest.h>
+
+#include "io_address.h"
+#include "dhcp/dhcp6.h"
+#include "dhcp/option.h"
+#include "dhcp/option6_addrlst.h"
+
+using namespace std;
+using namespace isc;
+using namespace isc::dhcp;
+using namespace isc::asiolink;
+
+namespace {
+class Option6AddrLstTest : public ::testing::Test {
+public:
+    Option6AddrLstTest() {
+    }
+};
+
+TEST_F(Option6AddrLstTest, basic) {
+
+    // 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,
+
+        // ff02::face:b00c
+        0xff, 02, 0, 0, 0, 0, 0 , 0,
+        0, 0, 0, 0, 0xfa, 0xce, 0xb0, 0x0c,
+
+        // ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+    };
+
+    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,
+        0, 0, 0, 0, 0xde, 0xad, 0xbe, 0xef,
+
+    };
+
+    uint8_t expected2[] = {
+        D6O_SIP_SERVERS_ADDR/256, D6O_SIP_SERVERS_ADDR%256,
+        0, 32, // len = 32 (2 addresses)
+        // 2001:db8:1::dead:beef
+        0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0, 0,
+        0, 0, 0, 0, 0xde, 0xad, 0xbe, 0xef,
+
+        // ff02::face:b00c
+        0xff, 02, 0, 0, 0, 0, 0 , 0,
+        0, 0, 0, 0, 0xfa, 0xce, 0xb0, 0x0c,
+
+        // ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+    };
+
+    uint8_t expected3[] = {
+        D6O_NIS_SERVERS/256, D6O_NIS_SERVERS%256,
+        0, 48,
+        // 2001:db8:1::dead:beef
+        0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0, 0,
+        0, 0, 0, 0, 0xde, 0xad, 0xbe, 0xef,
+
+        // ff02::face:b00c
+        0xff, 02, 0, 0, 0, 0, 0 , 0,
+        0, 0, 0, 0, 0xfa, 0xce, 0xb0, 0x0c,
+
+        // ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+    };
+
+    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 = 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::AddressContainer addrs = opt1->getAddresses();
+    ASSERT_EQ(1, addrs.size());
+    IOAddress addr = addrs[0];
+    EXPECT_EQ("2001:db8:1::dead:beef", addr.toText());
+
+    // pack this option again in the same buffer, but in
+    // different place
+    int offset = opt1->pack(buf,300, 100);
+
+    EXPECT_EQ(120, offset);
+    EXPECT_EQ( 0, memcmp(expected1, &buf[100], 20) );
+
+    // two addresses
+    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();
+    ASSERT_EQ(2, addrs.size());
+    EXPECT_EQ("2001:db8:1::dead:beef", addrs[0].toText());
+    EXPECT_EQ("ff02::face:b00c", addrs[1].toText());
+
+    // pack this option again in the same buffer, but in
+    // different place
+    offset = opt2->pack(buf,300, 150);
+
+    EXPECT_EQ(150+36, offset);
+    EXPECT_EQ( 0, memcmp(expected2, &buf[150], 36));
+
+    // three addresses
+    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());
+    addrs = opt3->getAddresses();
+    ASSERT_EQ(3, addrs.size());
+    EXPECT_EQ("2001:db8:1::dead:beef", addrs[0].toText());
+    EXPECT_EQ("ff02::face:b00c", addrs[1].toText());
+    EXPECT_EQ("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", addrs[2].toText());
+
+    // pack this option again in the same buffer, but in
+    // different place
+    offset = opt3->pack(buf,300, 200);
+
+    EXPECT_EQ(252, offset);
+    EXPECT_EQ( 0, memcmp(expected3, &buf[200], 52) );
+
+    EXPECT_NO_THROW(
+        delete opt1;
+        delete opt2;
+        delete opt3;
+    );
+}
+
+TEST_F(Option6AddrLstTest, constructors) {
+
+    Option6AddrLst* opt1 = 0;
+    EXPECT_NO_THROW(
+        opt1 = new Option6AddrLst(1234, IOAddress("::1"));
+    );
+    EXPECT_EQ(1234, opt1->getType());
+
+    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 = 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("2001:db8:1::2", addrs[0].toText());
+
+    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
new file mode 100644
index 0000000..91aaba4
--- /dev/null
+++ b/src/lib/dhcp/tests/option6_ia_unittest.cc
@@ -0,0 +1,264 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <config.h>
+#include <iostream>
+#include <sstream>
+
+#include <arpa/inet.h>
+#include <gtest/gtest.h>
+
+#include <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;
+using namespace isc::dhcp;
+using namespace isc::asiolink;
+
+namespace {
+class Option6IATest : public ::testing::Test {
+public:
+    Option6IATest() {
+    }
+};
+
+TEST_F(Option6IATest, basic) {
+
+    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[4] = 0x81; // T1
+    simple_buf[5] = 0x02;
+    simple_buf[6] = 0x03;
+    simple_buf[7] = 0x04;
+
+    simple_buf[8] = 0x84; // T2
+    simple_buf[9] = 0x03;
+    simple_buf[10] = 0x02;
+    simple_buf[11] = 0x01;
+
+    // create an option
+    // unpack() is called from constructor
+    Option6IA* opt = new Option6IA(D6O_IA_NA,
+                                   simple_buf,
+                                   128,
+                                   0,
+                                   12);
+
+    EXPECT_EQ(D6O_IA_NA, opt->getType());
+    EXPECT_EQ(0xa1a2a3a4, opt->getIAID());
+    EXPECT_EQ(0x81020304, opt->getT1());
+    EXPECT_EQ(0x84030201, opt->getT2());
+
+    // pack this option again in the same buffer, but in
+    // different place
+
+    // test for pack()
+    int offset = opt->pack(simple_buf, 128, 60);
+
+    // 4 bytes header + 4 bytes content
+    EXPECT_EQ(12, opt->len() - 4);
+    EXPECT_EQ(D6O_IA_NA, opt->getType());
+
+    EXPECT_EQ(offset, 76); // 60 + lenght(IA_NA) = 76
+
+    // check if pack worked properly:
+    // if option type is correct
+    EXPECT_EQ(D6O_IA_NA, simple_buf[60]*256 + simple_buf[61]);
+
+    // if option length is correct
+    EXPECT_EQ(12, simple_buf[62]*256 + simple_buf[63]);
+
+    // if iaid is correct
+    unsigned int iaid = htonl(*(unsigned int*)&simple_buf[64]);
+    EXPECT_EQ(0xa1a2a3a4, iaid );
+
+   // if T1 is correct
+    EXPECT_EQ(0x81020304, (simple_buf[68] << 24) +
+                          (simple_buf[69] << 16) +
+                          (simple_buf[70] << 8) +
+                          (simple_buf[71]) );
+
+    // if T1 is correct
+    EXPECT_EQ(0x84030201, (simple_buf[72] << 24) +
+                          (simple_buf[73] << 16) +
+                          (simple_buf[74] << 8) +
+                          (simple_buf[75]) );
+
+    EXPECT_NO_THROW(
+        delete opt;
+    );
+}
+
+TEST_F(Option6IATest, simple) {
+    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(D6O_IA_NA, 1234);
+    ia->setT1(2345);
+    ia->setT2(3456);
+
+    EXPECT_EQ(D6O_IA_NA, ia->getType());
+    EXPECT_EQ(1234, ia->getIAID());
+    EXPECT_EQ(2345, ia->getT1());
+    EXPECT_EQ(3456, ia->getT2());
+
+    EXPECT_NO_THROW(
+        delete ia;
+    );
+}
+
+// test if option can build suboptions
+TEST_F(Option6IATest, suboptions_pack) {
+    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(D6O_IA_NA, 0x13579ace);
+    ia->setT1(0x2345);
+    ia->setT2(0x3456);
+
+    boost::shared_ptr<Option> sub1(new Option(Option::V6,
+                                              0xcafe));
+
+    boost::shared_ptr<Option6IAAddr> addr1(
+        new Option6IAAddr(D6O_IAADDR, IOAddress("2001:db8:1234:5678::abcd"),
+                          0x5000, 0x7000));
+
+    ia->addOption(sub1);
+    ia->addOption(addr1);
+
+    ASSERT_EQ(28, addr1->len());
+    ASSERT_EQ(4, sub1->len());
+    ASSERT_EQ(48, ia->len());
+
+    uint8_t expected[] = {
+        D6O_IA_NA/256, D6O_IA_NA%256, // type
+        0, 44, // length
+        0x13, 0x57, 0x9a, 0xce, // iaid
+        0, 0, 0x23, 0x45,  // T1
+        0, 0, 0x34, 0x56,  // T2
+
+        // iaaddr suboption
+        D6O_IAADDR/256, D6O_IAADDR%256, // type
+        0, 24, // len
+        0x20, 0x01, 0xd, 0xb8, 0x12,0x34, 0x56, 0x78,
+        0, 0, 0, 0, 0, 0, 0xab, 0xcd, // IP address
+        0, 0, 0x50, 0, // preferred-lifetime
+        0, 0, 0x70, 0, // valid-lifetime
+
+        // suboption
+        0xca, 0xfe, // type
+        0, 0 // len
+    };
+
+    int offset = ia->pack(buf, 128, 10);
+    ASSERT_EQ(offset, 10 + 48);
+
+    EXPECT_EQ(0, memcmp(&buf[10], expected, 48));
+
+    EXPECT_NO_THROW(
+        delete ia;
+    );
+}
+
+// test if option can parse suboptions
+TEST_F(Option6IATest, suboptions_unpack) {
+
+
+    uint8_t expected[] = {
+        D6O_IA_NA/256, D6O_IA_NA%256, // type
+        0, 28, // length
+        0x13, 0x57, 0x9a, 0xce, // iaid
+        0, 0, 0x23, 0x45,  // T1
+        0, 0, 0x34, 0x56,  // T2
+
+        // iaaddr suboption
+        D6O_IAADDR/256, D6O_IAADDR%256, // type
+        0, 24, // len
+        0x20, 0x01, 0xd, 0xb8, 0x12,0x34, 0x56, 0x78,
+        0, 0, 0, 0, 0, 0, 0xab, 0xcd, // IP address
+        0, 0, 0x50, 0, // preferred-lifetime
+        0, 0, 0x70, 0, // valid-lifetime
+
+        // suboption
+        0xca, 0xfe, // type
+        0, 0 // len
+    };
+
+    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 = 0;
+    EXPECT_NO_THROW({
+        ia = new Option6IA(D6O_IA_NA, buf, 128, 4, 44);
+
+        // 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());
+    EXPECT_EQ(0x2345, ia->getT1());
+    EXPECT_EQ(0x3456, ia->getT2());
+
+    boost::shared_ptr<Option> subopt = ia->getOption(D6O_IAADDR);
+    ASSERT_NE(boost::shared_ptr<Option>(), subopt); // non-NULL
+
+    // checks for address option
+    Option6IAAddr * addr = dynamic_cast<Option6IAAddr*>(subopt.get());
+    ASSERT_TRUE(NULL != addr);
+
+    EXPECT_EQ(D6O_IAADDR, addr->getType());
+    EXPECT_EQ(28, addr->len());
+    EXPECT_EQ(0x5000, addr->getPreferred());
+    EXPECT_EQ(0x7000, addr->getValid());
+    EXPECT_EQ("2001:db8:1234:5678::abcd", addr->getAddress().toText());
+
+    // checks for dummy option
+    subopt = ia->getOption(0xcafe);
+    ASSERT_TRUE(subopt); // should be non-NULL
+
+    EXPECT_EQ(0xcafe, subopt->getType());
+    EXPECT_EQ(4, subopt->len());
+    // there should be no data at all
+    EXPECT_EQ(static_cast<void*>(NULL), subopt->getData());
+
+    subopt = ia->getOption(1); // get option 1
+    ASSERT_FALSE(subopt); // should be NULL
+
+    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
new file mode 100644
index 0000000..d1f7628
--- /dev/null
+++ b/src/lib/dhcp/tests/option6_iaaddr_unittest.cc
@@ -0,0 +1,103 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <config.h>
+#include <iostream>
+#include <sstream>
+
+#include <arpa/inet.h>
+#include <gtest/gtest.h>
+
+#include "dhcp/dhcp6.h"
+#include "dhcp/option.h"
+#include "dhcp/option6_iaaddr.h"
+
+using namespace std;
+using namespace isc;
+using namespace isc::dhcp;
+
+namespace {
+class Option6IAAddrTest : public ::testing::Test {
+public:
+    Option6IAAddrTest() {
+    }
+};
+
+/// TODO reenable this once ticket #1313 is implemented.
+TEST_F(Option6IAAddrTest, basic) {
+
+    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
+
+    // create an option (unpack content)
+    Option6IAAddr* opt = new Option6IAAddr(D6O_IAADDR,
+                                           simple_buf,
+                                           128,
+                                           0,
+                                           24);
+
+    // pack this option again in the same buffer, but in
+    // different place
+    int offset = opt->pack(simple_buf, 128, 50);
+
+    EXPECT_EQ(78, offset);
+
+    // 4 bytes header + 4 bytes content
+    EXPECT_EQ("2001:db8:1::dead:beef", opt->getAddress().toText());
+    EXPECT_EQ(1000, opt->getPreferred());
+    EXPECT_EQ(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));
+
+    EXPECT_NO_THROW(
+        delete opt;
+    );
+}
+
+}
diff --git a/src/lib/dhcp/tests/option_unittest.cc b/src/lib/dhcp/tests/option_unittest.cc
new file mode 100644
index 0000000..49426ae
--- /dev/null
+++ b/src/lib/dhcp/tests/option_unittest.cc
@@ -0,0 +1,279 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <config.h>
+#include <iostream>
+#include <sstream>
+
+#include <arpa/inet.h>
+#include <gtest/gtest.h>
+#include <boost/shared_ptr.hpp>
+
+#include "dhcp/dhcp6.h"
+#include "dhcp/option.h"
+
+using namespace std;
+using namespace isc;
+using namespace isc::dhcp;
+
+namespace {
+class OptionTest : public ::testing::Test {
+public:
+    OptionTest() {
+    }
+};
+
+// v4 is not really implemented yet. A simple test will do for now
+TEST_F(OptionTest, basic4) {
+
+    Option* opt = new Option(Option::V4, 17);
+
+    EXPECT_EQ(17, opt->getType());
+    EXPECT_EQ(static_cast<uint8_t*>(NULL), opt->getData());
+    EXPECT_EQ(2, opt->len()); // just v4 header
+
+    EXPECT_NO_THROW(
+        delete opt;
+    );
+}
+
+// tests simple constructor
+TEST_F(OptionTest, basic6) {
+
+    Option* opt = new Option(Option::V6, 1);
+
+    EXPECT_EQ(1, opt->getType());
+    EXPECT_EQ(static_cast<uint8_t*>(NULL), opt->getData());
+    EXPECT_EQ(4, opt->len()); // just v6 header
+
+    EXPECT_NO_THROW(
+        delete opt;
+    );
+}
+
+// tests contructor used in pkt reception
+// option contains actual data
+TEST_F(OptionTest, data1) {
+    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,
+                             3, // offset
+                             7); // 7 bytes of data
+    EXPECT_EQ(333, opt->getType());
+    ASSERT_EQ(&buf[3], opt->getData());
+    ASSERT_EQ(11, opt->len());
+    EXPECT_EQ(0, memcmp(&buf[3], opt->getData(), 7) );
+
+    int offset = opt->pack(buf, 32, 20);
+    EXPECT_EQ(31, offset);
+
+    EXPECT_EQ(buf[20], 333/256); // type
+    EXPECT_EQ(buf[21], 333%256);
+
+    EXPECT_EQ(buf[22], 0); // len
+    EXPECT_EQ(buf[23], 7);
+
+    // payload
+    EXPECT_EQ(0, memcmp(&buf[3], &buf[24], 7) );
+
+    EXPECT_NO_THROW(
+        delete opt;
+    );
+}
+
+// another text that tests the same thing, just
+// with different input parameters
+TEST_F(OptionTest, data2) {
+
+    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;
+
+    // create an option (unpack content)
+    Option* opt = new Option(Option::V6,
+                             D6O_CLIENTID,
+                             simple_buf,
+                             0,
+                             4);
+
+    // pack this option again in the same buffer, but in
+    // different place
+    int offset18 = opt->pack(simple_buf, 128, 10);
+
+    // 4 bytes header + 4 bytes content
+    EXPECT_EQ(8, opt->len());
+    EXPECT_EQ(D6O_CLIENTID, opt->getType());
+
+    EXPECT_EQ(offset18, 18);
+
+    // check if pack worked properly:
+    // if option type is correct
+    EXPECT_EQ(D6O_CLIENTID, simple_buf[10]*256 + simple_buf[11]);
+
+    // 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));
+
+    EXPECT_NO_THROW(
+        delete opt;
+    );
+}
+
+// check that an option can contain 2 suboptions:
+// opt1
+//  +----opt2
+//  |
+//  +----opt3
+//
+TEST_F(OptionTest, suboptions1) {
+    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
+                              buf,
+                              0, // offset
+                              3); // 3 bytes of data
+    boost::shared_ptr<Option> opt2(new Option(Option::V6, 13));
+    boost::shared_ptr<Option> opt3(new Option(Option::V6, 7,
+                                              buf,
+                                              3, // offset
+                                              5)); // 5 bytes of data
+    opt1->addOption(opt2);
+    opt1->addOption(opt3);
+    // opt2 len = 4 (just header)
+    // opt3 len = 9 4(header)+5(data)
+    // opt1 len = 7 + suboptions() = 7 + 4 + 9 = 20
+
+    EXPECT_EQ(4, opt2->len());
+    EXPECT_EQ(9, opt3->len());
+    EXPECT_EQ(20, opt1->len());
+
+    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
+    };
+
+    int offset = opt1->pack(buf, 128, 20);
+    EXPECT_EQ(40, offset);
+
+    // payload
+    EXPECT_EQ(0, memcmp(&buf[20], expected, 20) );
+
+    EXPECT_NO_THROW(
+        delete opt1;
+    );
+}
+
+// check that an option can contain 2 suboptions:
+// opt1
+//  +----opt2
+//        |
+//        +----opt3
+//
+TEST_F(OptionTest, suboptions2) {
+    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
+                              buf,
+                              0, // offset
+                              3); // 3 bytes of data
+    boost::shared_ptr<Option> opt2(new Option(Option::V6, 13));
+    boost::shared_ptr<Option> opt3(new Option(Option::V6, 7,
+                                              buf,
+                                              3, // offset
+                                              5)); // 5 bytes of data
+    opt1->addOption(opt2);
+    opt2->addOption(opt3);
+    // opt3 len = 9 4(header)+5(data)
+    // opt2 len = 4 (just header) + len(opt3)
+    // opt1 len = 7 + len(opt2)
+
+    uint8_t expected[] = {
+        0xff, 0xff, 0, 16, 100, 101, 102,
+        0, 13, 0, 9,
+        0, 7, 0, 5, 103, 104, 105, 106, 107,
+    };
+
+    int offset = opt1->pack(buf, 128, 20);
+    EXPECT_EQ(40, offset);
+
+    // payload
+    EXPECT_EQ(0, memcmp(&buf[20], expected, 20) );
+
+    EXPECT_NO_THROW(
+        delete opt1;
+    );
+}
+
+TEST_F(OptionTest, addgetdel) {
+    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
+    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, 2));
+
+    parent->addOption(opt1);
+    parent->addOption(opt2);
+
+    // getOption() test
+    EXPECT_EQ(opt1, parent->getOption(1));
+    EXPECT_EQ(opt2, parent->getOption(2));
+
+    // expect NULL
+    EXPECT_EQ(boost::shared_ptr<Option>(), parent->getOption(4));
+
+    // now there are 2 options of type 2
+    parent->addOption(opt3);
+
+    // let's delete one of them
+    EXPECT_EQ(true, parent->delOption(2));
+
+    // there still should be the other option 2
+    EXPECT_NE(boost::shared_ptr<Option>(), parent->getOption(2));
+
+    // let's delete the other option 2
+    EXPECT_EQ(true, parent->delOption(2));
+
+    // no more options with type=2
+    EXPECT_EQ(boost::shared_ptr<Option>(), parent->getOption(2));
+
+    // let's try to delete - should fail
+    EXPECT_TRUE(false ==  parent->delOption(2));
+}
+
+}
+
+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..3988fb0
--- /dev/null
+++ b/src/lib/dhcp/tests/pkt4_unittest.cc
@@ -0,0 +1,432 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <config.h>
+#include <iostream>
+#include <sstream>
+#include <arpa/inet.h>
+#include <gtest/gtest.h>
+#include <boost/static_assert.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/shared_array.hpp>
+
+#include "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. Exception should have been thrown, but
+        // object was created instead. Let's clean this up
+        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));
+
+    vector<uint8_t> vectorMacAddr(dummyMacAddr, dummyMacAddr
+                                  +sizeof(dummyMacAddr));
+
+    // hwType = 6(ETHERNET), hlen = 6(MAC address len)
+    pkt->setHWAddr(6, 6, vectorMacAddr);
+    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
+// Returns a vector containing a DHCPv4 packet header.
+#if 0
+vector<uint8_t>
+generateTestPacket2() {
+
+    // 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
+    };
+
+    // Initialize the vector with the header fields defined above.
+    vector<uint8_t> buf(hdr, hdr + sizeof(hdr));
+
+    // Append the large header fields.
+    copy(dummyMacAddr, dummyMacAddr + Pkt4::MAX_CHADDR_LEN, back_inserter(buf));
+    copy(dummySname, dummySname + Pkt4::MAX_SNAME_LEN, back_inserter(buf));
+    copy(dummyFile, dummyFile + Pkt4::MAX_FILE_LEN, back_inserter(buf));
+
+    // Should now have all the header, so check.  The "static_cast" is used
+    // to get round an odd bug whereby the linker appears not to find the
+    // definition of DHCPV4_PKT_HDR_LEN if it appears within an EXPECT_EQ().
+    EXPECT_EQ(static_cast<size_t>(Pkt4::DHCPV4_PKT_HDR_LEN), buf.size());
+
+    return (buf);
+}
+#endif
+
+TEST(Pkt4Test, fixedFields) {
+
+    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_EQ(0, memcmp(dummyChaddr, pkt->getChaddr(), 16));
+
+    EXPECT_EQ(0, memcmp(dummySname, &pkt->getSname()[0], 64));
+
+    EXPECT_EQ(0, memcmp(dummyFile, &pkt->getFile()[0], 128));
+
+    EXPECT_EQ(DHCPDISCOVER, pkt->getType());
+}
+
+#if 0
+/// TODO Uncomment when ticket #1227 is implemented
+TEST(Pkt4Test, fixedFieldsPack) {
+    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();
+
+    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_EQ(0, memcmp(expectedChaddr, pkt->getChaddr(), 16));
+
+    EXPECT_EQ(0, memcmp(expectedSname, pkt->getSname(), 64));
+
+    EXPECT_EQ(0, 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) {
+
+    vector<uint8_t> mac;
+    uint8_t expectedChaddr[Pkt4::MAX_CHADDR_LEN];
+
+    mac.resize(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()[0], 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()[0], 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
new file mode 100644
index 0000000..0f110ba
--- /dev/null
+++ b/src/lib/dhcp/tests/pkt6_unittest.cc
@@ -0,0 +1,207 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <config.h>
+#include <iostream>
+#include <sstream>
+#include <arpa/inet.h>
+#include <gtest/gtest.h>
+
+#include "io_address.h"
+#include "dhcp/option.h"
+#include "dhcp/pkt6.h"
+#include "dhcp/dhcp6.h"
+
+using namespace std;
+using namespace isc;
+using namespace isc::asiolink;
+using namespace isc::dhcp;
+
+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);
+
+    EXPECT_EQ(pkt1->data_len_, 17);
+
+    delete pkt1;
+}
+
+// captured actual SOLICIT packet: transid=0x3d79fb
+// options: client-id, in_na, dns-server, elapsed-time, option-request
+// this code is autogenerated (see src/bin/dhcp6/tests/iface_mgr_unittest.c)
+Pkt6 *capture1() {
+    Pkt6* pkt;
+    pkt = new Pkt6(98);
+    pkt->remote_port_ = 546;
+    pkt->remote_addr_ = IOAddress("fe80::21e:8cff:fe9b:7349");
+    pkt->local_port_ = 0;
+    pkt->local_addr_ = IOAddress("ff02::1:2");
+    pkt->ifindex_ = 2;
+    pkt->iface_ = "eth0";
+    pkt->data_[0]=1;
+    pkt->data_[1]=01;     pkt->data_[2]=02;     pkt->data_[3]=03;     pkt->data_[4]=0;
+    pkt->data_[5]=1;     pkt->data_[6]=0;     pkt->data_[7]=14;     pkt->data_[8]=0;
+    pkt->data_[9]=1;     pkt->data_[10]=0;     pkt->data_[11]=1;     pkt->data_[12]=21;
+    pkt->data_[13]=158;     pkt->data_[14]=60;     pkt->data_[15]=22;     pkt->data_[16]=0;
+    pkt->data_[17]=30;     pkt->data_[18]=140;     pkt->data_[19]=155;     pkt->data_[20]=115;
+    pkt->data_[21]=73;     pkt->data_[22]=0;     pkt->data_[23]=3;     pkt->data_[24]=0;
+    pkt->data_[25]=40;     pkt->data_[26]=0;     pkt->data_[27]=0;     pkt->data_[28]=0;
+    pkt->data_[29]=1;     pkt->data_[30]=255;     pkt->data_[31]=255;     pkt->data_[32]=255;
+    pkt->data_[33]=255;     pkt->data_[34]=255;     pkt->data_[35]=255;     pkt->data_[36]=255;
+    pkt->data_[37]=255;     pkt->data_[38]=0;     pkt->data_[39]=5;     pkt->data_[40]=0;
+    pkt->data_[41]=24;     pkt->data_[42]=32;     pkt->data_[43]=1;     pkt->data_[44]=13;
+    pkt->data_[45]=184;     pkt->data_[46]=0;     pkt->data_[47]=1;     pkt->data_[48]=0;
+    pkt->data_[49]=0;     pkt->data_[50]=0;     pkt->data_[51]=0;     pkt->data_[52]=0;
+    pkt->data_[53]=0;     pkt->data_[54]=0;     pkt->data_[55]=0;     pkt->data_[56]=18;
+    pkt->data_[57]=52;     pkt->data_[58]=255;     pkt->data_[59]=255;     pkt->data_[60]=255;
+    pkt->data_[61]=255;     pkt->data_[62]=255;     pkt->data_[63]=255;     pkt->data_[64]=255;
+    pkt->data_[65]=255;     pkt->data_[66]=0;     pkt->data_[67]=23;     pkt->data_[68]=0;
+    pkt->data_[69]=16;     pkt->data_[70]=32;     pkt->data_[71]=1;     pkt->data_[72]=13;
+    pkt->data_[73]=184;     pkt->data_[74]=0;     pkt->data_[75]=1;     pkt->data_[76]=0;
+    pkt->data_[77]=0;     pkt->data_[78]=0;     pkt->data_[79]=0;     pkt->data_[80]=0;
+    pkt->data_[81]=0;     pkt->data_[82]=0;     pkt->data_[83]=0;     pkt->data_[84]=221;
+    pkt->data_[85]=221;     pkt->data_[86]=0;     pkt->data_[87]=8;     pkt->data_[88]=0;
+    pkt->data_[89]=2;     pkt->data_[90]=0;     pkt->data_[91]=100;     pkt->data_[92]=0;
+    pkt->data_[93]=6;     pkt->data_[94]=0;     pkt->data_[95]=2;     pkt->data_[96]=0;
+    pkt->data_[97]=23;
+    return (pkt);
+}
+
+TEST_F(Pkt6Test, unpack_solicit1) {
+    Pkt6 * sol = capture1();
+
+    ASSERT_EQ(true, sol->unpack());
+
+    // 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_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_FALSE(sol->getOption(D6O_SERVERID)); // server-id is missing
+    EXPECT_FALSE(sol->getOption(D6O_IA_TA));
+    EXPECT_FALSE(sol->getOption(D6O_IAADDR));
+
+    // let's limit verbosity of this test
+    // 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);
+
+    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, 2));
+
+    parent->addOption(opt1);
+    parent->addOption(opt2);
+
+    // getOption() test
+    EXPECT_EQ(opt1, parent->getOption(1));
+    EXPECT_EQ(opt2, parent->getOption(2));
+
+    // expect NULL
+    EXPECT_EQ(boost::shared_ptr<Option>(), parent->getOption(4));
+
+    // now there are 2 options of type 2
+    parent->addOption(opt3);
+
+    // let's delete one of them
+    EXPECT_EQ(true, parent->delOption(2));
+
+    // there still should be the other option 2
+    EXPECT_NE(boost::shared_ptr<Option>(), parent->getOption(2));
+
+    // let's delete the other option 2
+    EXPECT_EQ(true, parent->delOption(2));
+
+    // no more options with type=2
+    EXPECT_EQ(boost::shared_ptr<Option>(), parent->getOption(2));
+
+    // let's try to delete - should fail
+    EXPECT_TRUE(false ==  parent->delOption(2));
+
+    delete parent;
+}
+
+
+}
diff --git a/src/lib/dhcp/tests/run_unittests.cc b/src/lib/dhcp/tests/run_unittests.cc
new file mode 100644
index 0000000..db27f76
--- /dev/null
+++ b/src/lib/dhcp/tests/run_unittests.cc
@@ -0,0 +1,27 @@
+// 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 <gtest/gtest.h>
+
+#include <log/logger_support.h>
+
+int
+main(int argc, char* argv[]) {
+    ::testing::InitGoogleTest(&argc, argv);
+    isc::log::initLogger();
+
+    int result = RUN_ALL_TESTS();
+
+    return (result);
+}
diff --git a/src/lib/dns/python/message_python.cc b/src/lib/dns/python/message_python.cc
index 2349401..48fff94 100644
--- a/src/lib/dns/python/message_python.cc
+++ b/src/lib/dns/python/message_python.cc
@@ -16,6 +16,7 @@
 #include <Python.h>
 
 #include <exceptions/exceptions.h>
+#include <util/python/pycppwrapper_util.h>
 #include <dns/message.h>
 #include <dns/rcode.h>
 #include <dns/tsig.h>
@@ -38,6 +39,7 @@ using namespace std;
 using namespace isc::dns;
 using namespace isc::dns::python;
 using namespace isc::util;
+using namespace isc::util::python;
 
 // Import pydoc text
 #include "message_python_inc.cc"
@@ -64,8 +66,8 @@ PyObject* Message_setEDNS(s_Message* self, PyObject* args);
 PyObject* Message_getTSIGRecord(s_Message* self);
 PyObject* Message_getRRCount(s_Message* self, PyObject* args);
 // use direct iterators for these? (or simply lists for now?)
-PyObject* Message_getQuestion(s_Message* self);
-PyObject* Message_getSection(s_Message* self, PyObject* args);
+PyObject* Message_getQuestion(PyObject* self, PyObject*);
+PyObject* Message_getSection(PyObject* self, PyObject* args);
 //static PyObject* Message_beginQuestion(s_Message* self, PyObject* args);
 //static PyObject* Message_endQuestion(s_Message* self, PyObject* args);
 //static PyObject* Message_beginSection(s_Message* self, PyObject* args);
@@ -127,10 +129,10 @@ PyMethodDef Message_methods[] = {
     },
     { "get_rr_count", reinterpret_cast<PyCFunction>(Message_getRRCount), METH_VARARGS,
       "Returns the number of RRs contained in the given section." },
-    { "get_question", reinterpret_cast<PyCFunction>(Message_getQuestion), METH_NOARGS,
+    { "get_question", Message_getQuestion, METH_NOARGS,
       "Returns a list of all Question objects in the message "
       "(should be either 0 or 1)" },
-    { "get_section", reinterpret_cast<PyCFunction>(Message_getSection), METH_VARARGS,
+    { "get_section", Message_getSection, METH_VARARGS,
       "Returns a list of all RRset objects in the given section of the message\n"
       "The argument must be of type Section" },
     { "add_question", reinterpret_cast<PyCFunction>(Message_addQuestion), METH_VARARGS,
@@ -409,50 +411,59 @@ Message_getRRCount(s_Message* self, PyObject* args) {
     }
 }
 
+// This is a helper templated class commonly used for getQuestion and
+// getSection in order to build a list of Message section items.
+template <typename ItemType, typename CreatorParamType>
+class SectionInserter {
+    typedef PyObject* (*creator_t)(const CreatorParamType&);
+public:
+    SectionInserter(PyObject* pylist, creator_t creator) :
+        pylist_(pylist), creator_(creator)
+    {}
+    void operator()(ItemType item) {
+        if (PyList_Append(pylist_, PyObjectContainer(creator_(*item)).get())
+            == -1) {
+            isc_throw(PyCPPWrapperException, "PyList_Append failed, "
+                      "probably due to short memory");
+        }
+    }
+private:
+    PyObject* pylist_;
+    creator_t creator_;
+};
+
+typedef SectionInserter<ConstQuestionPtr, Question> QuestionInserter;
+typedef SectionInserter<ConstRRsetPtr, RRset> RRsetInserter;
+
 // TODO use direct iterators for these? (or simply lists for now?)
 PyObject*
-Message_getQuestion(s_Message* self) {
-    QuestionIterator qi, qi_end;
+Message_getQuestion(PyObject* po_self, PyObject*) {
+    const s_Message* const self = static_cast<s_Message*>(po_self);
+
     try {
-        qi = self->cppobj->beginQuestion();
-        qi_end = self->cppobj->endQuestion();
+        PyObjectContainer list_container(PyList_New(0));
+        for_each(self->cppobj->beginQuestion(),
+                 self->cppobj->endQuestion(),
+                 QuestionInserter(list_container.get(), createQuestionObject));
+        return (list_container.release());
     } catch (const InvalidMessageSection& ex) {
         PyErr_SetString(po_InvalidMessageSection, ex.what());
-        return (NULL);
-    } catch (...) {
-        PyErr_SetString(po_IscException,
-                        "Unexpected exception in getting section iterators");
-        return (NULL);
-    }
-
-    PyObject* list = PyList_New(0);
-    if (list == NULL) {
-        return (NULL);
-    }
-
-    try {
-        for (; qi != qi_end; ++qi) {
-            if (PyList_Append(list, createQuestionObject(**qi)) == -1) {
-                Py_DECREF(list);
-                return (NULL);
-            }
-        }
-        return (list);
     } catch (const exception& ex) {
         const string ex_what =
-            "Unexpected failure getting Question section: " +
+            "Unexpected failure in Message.get_question: " +
             string(ex.what());
         PyErr_SetString(po_IscException, ex_what.c_str());
     } catch (...) {
         PyErr_SetString(PyExc_SystemError,
-                        "Unexpected failure getting Question section");
+                        "Unexpected failure in Message.get_question");
     }
-    Py_DECREF(list);
     return (NULL);
 }
 
 PyObject*
-Message_getSection(s_Message* self, PyObject* args) {
+Message_getSection(PyObject* po_self, PyObject* args) {
+    const s_Message* const self = static_cast<s_Message*>(po_self);
+
     unsigned int section;
     if (!PyArg_ParseTuple(args, "I", &section)) {
         PyErr_Clear();
@@ -460,46 +471,28 @@ Message_getSection(s_Message* self, PyObject* args) {
                         "no valid type in get_section argument");
         return (NULL);
     }
-    RRsetIterator rrsi, rrsi_end;
+
     try {
-        rrsi = self->cppobj->beginSection(
-            static_cast<Message::Section>(section));
-        rrsi_end = self->cppobj->endSection(
-            static_cast<Message::Section>(section));
+        PyObjectContainer list_container(PyList_New(0));
+        const Message::Section msgsection =
+            static_cast<Message::Section>(section);
+        for_each(self->cppobj->beginSection(msgsection),
+                 self->cppobj->endSection(msgsection),
+                 RRsetInserter(list_container.get(), createRRsetObject));
+        return (list_container.release());
     } catch (const isc::OutOfRange& ex) {
         PyErr_SetString(PyExc_OverflowError, ex.what());
-        return (NULL);
     } catch (const InvalidMessageSection& ex) {
         PyErr_SetString(po_InvalidMessageSection, ex.what());
-        return (NULL);
-    } catch (...) {
-        PyErr_SetString(po_IscException,
-                        "Unexpected exception in getting section iterators");
-        return (NULL);
-    }
-
-    PyObject* list = PyList_New(0);
-    if (list == NULL) {
-        return (NULL);
-    }
-    try {
-        for (; rrsi != rrsi_end; ++rrsi) {
-            if (PyList_Append(list, createRRsetObject(**rrsi)) == -1) {
-                    Py_DECREF(list);
-                    return (NULL);
-            }
-        }
-        return (list);
     } catch (const exception& ex) {
         const string ex_what =
-            "Unexpected failure creating Question object: " +
+            "Unexpected failure in Message.get_section: " +
             string(ex.what());
         PyErr_SetString(po_IscException, ex_what.c_str());
     } catch (...) {
         PyErr_SetString(PyExc_SystemError,
-                        "Unexpected failure creating Question object");
+                        "Unexpected failure in Message.get_section");
     }
-    Py_DECREF(list);
     return (NULL);
 }
 
diff --git a/src/lib/dns/python/rrset_python.cc b/src/lib/dns/python/rrset_python.cc
index 9fc3d79..73a19e7 100644
--- a/src/lib/dns/python/rrset_python.cc
+++ b/src/lib/dns/python/rrset_python.cc
@@ -63,7 +63,7 @@ PyObject* RRset_toText(s_RRset* self);
 PyObject* RRset_str(PyObject* self);
 PyObject* RRset_toWire(s_RRset* self, PyObject* args);
 PyObject* RRset_addRdata(s_RRset* self, PyObject* args);
-PyObject* RRset_getRdata(s_RRset* self);
+PyObject* RRset_getRdata(PyObject* po_self, PyObject*);
 PyObject* RRset_removeRRsig(s_RRset* self);
 
 // TODO: iterator?
@@ -94,7 +94,7 @@ PyMethodDef RRset_methods[] = {
       "returned" },
     { "add_rdata", reinterpret_cast<PyCFunction>(RRset_addRdata), METH_VARARGS,
       "Adds the rdata for one RR to the RRset.\nTakes an Rdata object as an argument" },
-    { "get_rdata", reinterpret_cast<PyCFunction>(RRset_getRdata), METH_NOARGS,
+    { "get_rdata", RRset_getRdata, METH_NOARGS,
       "Returns a List containing all Rdata elements" },
     { "remove_rrsig", reinterpret_cast<PyCFunction>(RRset_removeRRsig), METH_NOARGS,
       "Clears the list of RRsigs for this RRset" },
@@ -291,22 +291,26 @@ RRset_addRdata(s_RRset* self, PyObject* args) {
 }
 
 PyObject*
-RRset_getRdata(s_RRset* self) {
-    PyObject* list = PyList_New(0);
-
-    RdataIteratorPtr it = self->cppobj->getRdataIterator();
+RRset_getRdata(PyObject* po_self, PyObject*) {
+    const s_RRset* const self = static_cast<s_RRset*>(po_self);
 
     try {
-        for (; !it->isLast(); it->next()) {
-            const rdata::Rdata *rd = &it->getCurrent();
-            if (PyList_Append(list,
-                    createRdataObject(createRdata(self->cppobj->getType(),
-                                      self->cppobj->getClass(), *rd))) == -1) {
-                Py_DECREF(list);
-                return (NULL);
+        PyObjectContainer list_container(PyList_New(0));
+
+        for (RdataIteratorPtr it = self->cppobj->getRdataIterator();
+             !it->isLast(); it->next()) {
+            if (PyList_Append(list_container.get(),
+                              PyObjectContainer(
+                                  createRdataObject(
+                                      createRdata(self->cppobj->getType(),
+                                                  self->cppobj->getClass(),
+                                                  it->getCurrent()))).get())
+                == -1) {
+                isc_throw(PyCPPWrapperException, "PyList_Append failed, "
+                          "probably due to short memory");
             }
         }
-        return (list);
+        return (list_container.release());
     } catch (const exception& ex) {
         const string ex_what =
             "Unexpected failure getting rrset Rdata: " +
@@ -316,7 +320,6 @@ RRset_getRdata(s_RRset* self) {
         PyErr_SetString(PyExc_SystemError,
                         "Unexpected failure getting rrset Rdata");
     }
-    Py_DECREF(list);
     return (NULL);
 }
 
diff --git a/src/lib/dns/python/tests/message_python_test.py b/src/lib/dns/python/tests/message_python_test.py
index 8f2d732..86574fb 100644
--- a/src/lib/dns/python/tests/message_python_test.py
+++ b/src/lib/dns/python/tests/message_python_test.py
@@ -17,6 +17,7 @@
 # Tests for the message part of the pydnspp module
 #
 
+import sys
 import unittest
 import os
 from pydnspp import *
@@ -230,6 +231,14 @@ class MessageTest(unittest.TestCase):
         self.assertTrue(compare_rrset_list(section_rrset, self.r.get_section(Message.SECTION_ANSWER)))
         self.assertEqual(2, self.r.get_rr_count(Message.SECTION_ANSWER))
 
+        # We always make a new deep copy in get_section(), so the reference
+        # count of the returned list and its each item should be 1; otherwise
+        # they would leak.
+        self.assertEqual(1, sys.getrefcount(self.r.get_section(
+                    Message.SECTION_ANSWER)))
+        self.assertEqual(1, sys.getrefcount(self.r.get_section(
+                    Message.SECTION_ANSWER)[0]))
+
         self.assertFalse(compare_rrset_list(section_rrset, self.r.get_section(Message.SECTION_AUTHORITY)))
         self.assertEqual(0, self.r.get_rr_count(Message.SECTION_AUTHORITY))
         self.r.add_rrset(Message.SECTION_AUTHORITY, self.rrset_a)
@@ -242,7 +251,7 @@ class MessageTest(unittest.TestCase):
         self.assertTrue(compare_rrset_list(section_rrset, self.r.get_section(Message.SECTION_ADDITIONAL)))
         self.assertEqual(2, self.r.get_rr_count(Message.SECTION_ADDITIONAL))
 
-    def test_add_question(self):
+    def test_add_and_get_question(self):
         self.assertRaises(TypeError, self.r.add_question, "wrong", "wrong")
         q = Question(Name("example.com"), RRClass("IN"), RRType("A"))
         qs = [q]
@@ -252,6 +261,12 @@ class MessageTest(unittest.TestCase):
         self.assertTrue(compare_rrset_list(qs, self.r.get_question()))
         self.assertEqual(1, self.r.get_rr_count(Message.SECTION_QUESTION))
 
+        # We always make a new deep copy in get_section(), so the reference
+        # count of the returned list and its each item should be 1; otherwise
+        # they would leak.
+        self.assertEqual(1, sys.getrefcount(self.r.get_question()))
+        self.assertEqual(1, sys.getrefcount(self.r.get_question()[0]))
+
     def test_add_rrset(self):
         self.assertRaises(TypeError, self.r.add_rrset, "wrong")
         self.assertRaises(TypeError, self.r.add_rrset)
diff --git a/src/lib/dns/python/tests/rrset_python_test.py b/src/lib/dns/python/tests/rrset_python_test.py
index e0eab4a..de475a7 100644
--- a/src/lib/dns/python/tests/rrset_python_test.py
+++ b/src/lib/dns/python/tests/rrset_python_test.py
@@ -17,6 +17,7 @@
 # Tests for the rrtype part of the pydnspp module
 #
 
+import sys
 import unittest
 import os
 from pydnspp import *
@@ -110,6 +111,12 @@ class TestModuleSpec(unittest.TestCase):
                 ]
         self.assertEqual(rdata, self.rrset_a.get_rdata())
         self.assertEqual([], self.rrset_a_empty.get_rdata())
+
+        # We always make a new deep copy in get_rdata(), so the reference
+        # count of the returned list and its each item should be 1; otherwise
+        # they would leak.
+        self.assertEqual(1, sys.getrefcount(self.rrset_a.get_rdata()))
+        self.assertEqual(1, sys.getrefcount(self.rrset_a.get_rdata()[0]))
         
 if __name__ == '__main__':
     unittest.main()
diff --git a/src/lib/dns/rdata/generic/nsec_47.cc b/src/lib/dns/rdata/generic/nsec_47.cc
index 93b8b5f..4723c23 100644
--- a/src/lib/dns/rdata/generic/nsec_47.cc
+++ b/src/lib/dns/rdata/generic/nsec_47.cc
@@ -178,6 +178,11 @@ NSEC::toWire(AbstractMessageRenderer& renderer) const {
     renderer.writeData(&impl_->typebits_[0], impl_->typebits_.size());
 }
 
+const Name&
+NSEC::getNextName() const {
+    return (impl_->nextname_);
+}
+
 int
 NSEC::compare(const Rdata& other) const {
     const NSEC& other_nsec = dynamic_cast<const NSEC&>(other);
diff --git a/src/lib/dns/rdata/generic/nsec_47.h b/src/lib/dns/rdata/generic/nsec_47.h
index b86a25b..005dd3a 100644
--- a/src/lib/dns/rdata/generic/nsec_47.h
+++ b/src/lib/dns/rdata/generic/nsec_47.h
@@ -38,6 +38,16 @@ public:
     // END_COMMON_MEMBERS
     NSEC& operator=(const NSEC& source);
     ~NSEC();
+
+    // specialized methods
+
+    /// Return the next domain name.
+    ///
+    /// \exception std::bad_alloc Resource allocation failure in name copy.
+    ///
+    /// \return The next domain name field in the form of \c Name object.
+    const Name& getNextName() const;
+
 private:
     NSECImpl* impl_;
 };
diff --git a/src/lib/dns/tests/Makefile.am b/src/lib/dns/tests/Makefile.am
index e4c577e..ceeb3b8 100644
--- a/src/lib/dns/tests/Makefile.am
+++ b/src/lib/dns/tests/Makefile.am
@@ -73,4 +73,4 @@ run_unittests_LDADD += $(top_builddir)/src/lib/util/unittests/libutil_unittests.
 run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
 endif
 
-check_PROGRAMS = $(TESTS)
+noinst_PROGRAMS = $(TESTS)
diff --git a/src/lib/dns/tests/rdata_nsec_unittest.cc b/src/lib/dns/tests/rdata_nsec_unittest.cc
index 5aa1e9c..f081cd8 100644
--- a/src/lib/dns/tests/rdata_nsec_unittest.cc
+++ b/src/lib/dns/tests/rdata_nsec_unittest.cc
@@ -89,4 +89,10 @@ TEST_F(Rdata_NSEC_Test, assign) {
     EXPECT_EQ(0, rdata_nsec.compare(rdata_nsec2));
 }
 
+TEST_F(Rdata_NSEC_Test, getNextName) {
+    // The implementation is quite trivial, so we simply check it's actually
+    // defined and does work as intended in a simple case.
+    EXPECT_EQ(Name("www2.isc.org"), generic::NSEC((nsec_txt)).getNextName());
+}
+
 }
diff --git a/src/lib/exceptions/tests/Makefile.am b/src/lib/exceptions/tests/Makefile.am
index 35161a1..2444b02 100644
--- a/src/lib/exceptions/tests/Makefile.am
+++ b/src/lib/exceptions/tests/Makefile.am
@@ -20,4 +20,4 @@ run_unittests_LDADD = $(GTEST_LDADD)
 run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
 endif
 
-check_PROGRAMS = $(TESTS)
+noinst_PROGRAMS = $(TESTS)
diff --git a/src/lib/log/Makefile.am b/src/lib/log/Makefile.am
index 9f52724..957d350 100644
--- a/src/lib/log/Makefile.am
+++ b/src/lib/log/Makefile.am
@@ -9,6 +9,7 @@ lib_LTLIBRARIES = liblog.la
 liblog_la_SOURCES  =
 liblog_la_SOURCES += dummylog.h dummylog.cc
 liblog_la_SOURCES += logimpl_messages.cc logimpl_messages.h
+liblog_la_SOURCES += log_dbglevels.h
 liblog_la_SOURCES += log_formatter.h log_formatter.cc
 liblog_la_SOURCES += logger.cc logger.h
 liblog_la_SOURCES += logger_impl.cc logger_impl.h
@@ -21,8 +22,8 @@ liblog_la_SOURCES += logger_name.cc logger_name.h
 liblog_la_SOURCES += logger_specification.h
 liblog_la_SOURCES += logger_support.cc logger_support.h
 liblog_la_SOURCES += logger_unittest_support.cc logger_unittest_support.h
-liblog_la_SOURCES += macros.h
 liblog_la_SOURCES += log_messages.cc log_messages.h
+liblog_la_SOURCES += macros.h
 liblog_la_SOURCES += message_dictionary.cc message_dictionary.h
 liblog_la_SOURCES += message_exception.h
 liblog_la_SOURCES += message_initializer.cc message_initializer.h
diff --git a/src/lib/log/README b/src/lib/log/README
index 3747cb1..3693abb 100644
--- a/src/lib/log/README
+++ b/src/lib/log/README
@@ -477,6 +477,11 @@ the severity system:
 When a particular severity is set, it - and all severities and/or debug
 levels above it - will be logged.
 
+To try to ensure that the information from different modules is roughly
+comparable for the same debug level, a set of standard debug levels has
+been defined for common type of debug output.  However, modules are free
+to set their own debug levels or define additional ones.
+
 Logging Sources v Logging Severities
 ------------------------------------
 When logging events, make a distinction between events related to the
diff --git a/src/lib/log/log_dbglevels.h b/src/lib/log/log_dbglevels.h
new file mode 100644
index 0000000..d713714
--- /dev/null
+++ b/src/lib/log/log_dbglevels.h
@@ -0,0 +1,93 @@
+// 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 __LOG_DBGLVLS_H
+#define __LOG_DBGLVLS_H
+
+/// \file
+///
+/// When a message is logged with DEBUG severity, the debug level associated
+/// with the message is also specified.  This debug level is a number
+/// ranging from 0 to 99; the idea is that the higher the debug level, the
+/// more detailed the message.
+///
+/// If debug messages are being logged, the logging system allows them to be
+/// filtered by debug level - only messages logged with a level equal to or
+/// less than the set debug level will be output.  (For example, if the
+/// filter is set to 30, only debug messages logged with levels in the range
+/// 0 to 30 will be output; messages logged with levels 31 to 99 will be
+/// suppressed.)
+///
+/// Levels of 30 or below are reserved for debug messages that are most
+/// likely to be useful for an administrator. Levels 31 to 99 are for use by
+/// someone familiar with the code. "Useful for an administrator" is,
+/// admittedly, a subjective term: it is loosely defined as messages helping
+/// someone diagnose a problem that they could solve without needing to dive
+/// into the code.  So it covers things like start-up steps and configuration
+/// messages.
+///
+/// In practice, this means that levels of 30 and below are most-likely to
+/// be used by the top-level programs, and 31 and above by the various
+/// libraries.
+///
+/// This file defines a set of standard debug levels for use across all loggers.
+/// In this way users can have some expection of what will be output when
+/// enabling debugging.  Symbols are prefixed DBGLVL so as not to clash with
+/// DBG_ symbols in the various modules.
+///
+/// \note If the names of debug constants are changed, or if ones are added or
+/// removed, edit the file src/lib/python/isc/log/log.cc to update the log
+/// level definitions available to Python.  The change does not need to be
+/// made if only the numeric values of constants are updated.
+
+namespace {
+
+/// Process startup/shutdown debug messages.  Note that these are _debug_
+/// messages, as other messages related to startup and shutdown may be output
+/// with another severity.  For example, when the authoritative server starts
+/// up, the "server started" message could be output at a severity of INFO.
+/// "Server starting" and messages indicating the stages in startup should be
+/// debug messages output at this severity.
+///
+/// This is given a value of 0 as that is the level selected if debugging is
+/// enabled without giving a level.
+const int DBGLVL_START_SHUT = 0;
+
+/// This debug level is reserved for logging the exchange of messages/commands
+/// between processes, including configuration messages.
+const int DBGLVL_COMMAND = 10;
+
+/// If the commands have associated data, this level is when they are printed.
+/// This includes configuration messages.
+const int DBGLVL_COMMAND_DATA = 20;
+
+// The following constants are suggested values for common operations.
+// Depending on the exact nature of the code, modules may or may not use these
+// levels.
+
+/// Trace basic operations.
+const int DBGLVL_TRACE_BASIC = 40;
+
+/// Trace data associated with the basic operations.
+const int DBGLVL_TRACE_BASIC_DATA = 45;
+
+/// Trace detailed operations.
+const int DBGLVL_TRACE_DETAIL = 50;
+
+/// Trace data associated with detailed operations.
+const int DBGLVL_TRACE_DETAIL_DATA = 55;
+
+}   // Anonymous namespace
+
+#endif // __LOG_DBGLVLS_H
diff --git a/src/lib/log/macros.h b/src/lib/log/macros.h
index 3128131..42fb42e 100644
--- a/src/lib/log/macros.h
+++ b/src/lib/log/macros.h
@@ -16,6 +16,7 @@
 #define __LOG_MACROS_H
 
 #include <log/logger.h>
+#include <log/log_dbglevels.h>
 
 /// \brief Macro to conveniently test debug output and log it
 #define LOG_DEBUG(LOGGER, LEVEL, MESSAGE) \
diff --git a/src/lib/log/tests/Makefile.am b/src/lib/log/tests/Makefile.am
index 8ca561d..a5f793c 100644
--- a/src/lib/log/tests/Makefile.am
+++ b/src/lib/log/tests/Makefile.am
@@ -45,7 +45,7 @@ run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
 run_unittests_LDADD += $(top_builddir)/src/lib/util/unittests/libutil_unittests.la
 endif
 
-check_PROGRAMS = logger_example
+noinst_PROGRAMS = logger_example
 logger_example_SOURCES = logger_example.cc
 logger_example_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
 logger_example_LDFLAGS = $(AM_LDFLAGS) $(LOG4CPLUS_LDFLAGS)
@@ -53,7 +53,7 @@ logger_example_LDADD  = $(top_builddir)/src/lib/log/liblog.la
 logger_example_LDADD += $(top_builddir)/src/lib/util/libutil.la
 logger_example_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
 
-check_PROGRAMS += init_logger_test
+noinst_PROGRAMS += init_logger_test
 init_logger_test_SOURCES = init_logger_test.cc
 init_logger_test_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
 init_logger_test_LDFLAGS = $(AM_LDFLAGS) $(LOG4CPLUS_LDFLAGS)
@@ -61,7 +61,7 @@ init_logger_test_LDADD  = $(top_builddir)/src/lib/log/liblog.la
 init_logger_test_LDADD += $(top_builddir)/src/lib/util/libutil.la
 init_logger_test_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
 
-check_PROGRAMS += $(TESTS)
+noinst_PROGRAMS += $(TESTS)
 
 # Additional test using the shell.  These are principally tests
 # where the global logging environment is affected, and where the
diff --git a/src/lib/nsas/nsas_log.h b/src/lib/nsas/nsas_log.h
index ec6844f..031f46d 100644
--- a/src/lib/nsas/nsas_log.h
+++ b/src/lib/nsas/nsas_log.h
@@ -29,15 +29,15 @@ namespace nsas {
 // The first level traces normal operations - asking the NSAS for an address,
 // and cancelling a lookup.  It also records when the NSAS calls back to the
 // resolver to resolve something.
-const int NSAS_DBG_TRACE = 10;
+const int NSAS_DBG_TRACE = DBGLVL_TRACE_BASIC;
 
 // The next level extends the normal operations and records the results of the
 // lookups.
-const int NSAS_DBG_RESULTS = 20;
+const int NSAS_DBG_RESULTS = DBGLVL_TRACE_BASIC_DATA;
 
 // Additional information on the usage of the names - the RTT values obtained
 // when queries were done.
-const int NSAS_DBG_RTT = 30;
+const int NSAS_DBG_RTT = DBGLVL_TRACE_DETAIL_DATA;
 
 
 /// \brief NSAS Logger
diff --git a/src/lib/nsas/tests/Makefile.am b/src/lib/nsas/tests/Makefile.am
index 8845187..420e897 100644
--- a/src/lib/nsas/tests/Makefile.am
+++ b/src/lib/nsas/tests/Makefile.am
@@ -60,4 +60,4 @@ run_unittests_LDADD += $(top_builddir)/src/lib/util/unittests/libutil_unittests.
 run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
 endif
 
-check_PROGRAMS = $(TESTS)
+noinst_PROGRAMS = $(TESTS)
diff --git a/src/lib/python/isc/bind10/sockcreator.py b/src/lib/python/isc/bind10/sockcreator.py
index 8e5b019..7522d4a 100644
--- a/src/lib/python/isc/bind10/sockcreator.py
+++ b/src/lib/python/isc/bind10/sockcreator.py
@@ -16,6 +16,7 @@
 import socket
 import struct
 import os
+import copy
 import subprocess
 from isc.log_messages.bind10_messages import *
 from libutil_io_python import recv_fd
@@ -207,7 +208,7 @@ class Creator(Parser):
         # stdin as well as stdout, so we dup it before passing it there.
         remote2 = socket.fromfd(remote.fileno(), socket.AF_UNIX,
                                 socket.SOCK_STREAM)
-        env = os.environ
+        env = copy.deepcopy(os.environ)
         env['PATH'] = path
         self.__process = subprocess.Popen(['b10-sockcreator'], env=env,
                                           stdin=remote.fileno(),
diff --git a/src/lib/python/isc/config/ccsession.py b/src/lib/python/isc/config/ccsession.py
index 11a13ec..c7eb8ad 100644
--- a/src/lib/python/isc/config/ccsession.py
+++ b/src/lib/python/isc/config/ccsession.py
@@ -143,7 +143,9 @@ class ModuleCCSession(ConfigData):
        callbacks are called when 'check_command' is called on the
        ModuleCCSession"""
        
-    def __init__(self, spec_file_name, config_handler, command_handler, cc_session=None, handle_logging_config=True):
+    def __init__(self, spec_file_name, config_handler, command_handler,
+                 cc_session=None, handle_logging_config=True,
+                 socket_file = None):
         """Initialize a ModuleCCSession. This does *NOT* send the
            specification and request the configuration yet. Use start()
            for that once the ModuleCCSession has been initialized.
@@ -165,6 +167,12 @@ class ModuleCCSession(ConfigData):
            logger manager when the logging configuration gets updated.
            The module does not need to do anything except intializing
            its loggers, and provide log messages. Defaults to true.
+
+           socket_file: If cc_session was none, this optional argument
+           specifies which socket file to use to connect to msgq. It
+           will be overridden by the environment variable
+           MSGQ_SOCKET_FILE. If none, and no environment variable is
+           set, it will use the system default.
         """
         module_spec = isc.config.module_spec_from_file(spec_file_name)
         ConfigData.__init__(self, module_spec)
@@ -175,7 +183,7 @@ class ModuleCCSession(ConfigData):
         self.set_command_handler(command_handler)
 
         if not cc_session:
-            self._session = Session()
+            self._session = Session(socket_file)
         else:
             self._session = cc_session
         self._session.group_subscribe(self._module_name, "*")
diff --git a/src/lib/python/isc/datasrc/datasrc.cc b/src/lib/python/isc/datasrc/datasrc.cc
index 7676104..6ab29d8 100644
--- a/src/lib/python/isc/datasrc/datasrc.cc
+++ b/src/lib/python/isc/datasrc/datasrc.cc
@@ -132,6 +132,8 @@ initModulePart_ZoneFinder(PyObject* mod) {
                              Py_BuildValue("I", ZoneFinder::WILDCARD));
         installClassVariable(zonefinder_type, "WILDCARD_NXRRSET",
                              Py_BuildValue("I", ZoneFinder::WILDCARD_NXRRSET));
+        installClassVariable(zonefinder_type, "WILDCARD_CNAME",
+                             Py_BuildValue("I", ZoneFinder::WILDCARD_CNAME));
 
         installClassVariable(zonefinder_type, "FIND_DEFAULT",
                              Py_BuildValue("I", ZoneFinder::FIND_DEFAULT));
@@ -139,6 +141,8 @@ initModulePart_ZoneFinder(PyObject* mod) {
                              Py_BuildValue("I", ZoneFinder::FIND_GLUE_OK));
         installClassVariable(zonefinder_type, "FIND_DNSSEC",
                              Py_BuildValue("I", ZoneFinder::FIND_DNSSEC));
+        installClassVariable(zonefinder_type, "NO_WILDCARD",
+                             Py_BuildValue("I", ZoneFinder::NO_WILDCARD));
     } catch (const std::exception& ex) {
         const std::string ex_what =
             "Unexpected failure in ZoneFinder initialization: " +
diff --git a/src/lib/python/isc/datasrc/finder_inc.cc b/src/lib/python/isc/datasrc/finder_inc.cc
index bc8e62c..4a00e78 100644
--- a/src/lib/python/isc/datasrc/finder_inc.cc
+++ b/src/lib/python/isc/datasrc/finder_inc.cc
@@ -42,11 +42,20 @@ Return the RR class of the zone.\n\
 \n\
 ";
 
+// Main changes from the C++ doxygen version:
+// - Return type: use tuple instead of the dedicated FindResult type
+// - NULL->None
+// - exceptions
 const char* const ZoneFinder_find_doc = "\
-find(name, type, target=NULL, options=FIND_DEFAULT) -> (code, FindResult)\n\
+find(name, type, target=None, options=FIND_DEFAULT) -> (integer, RRset)\n\
 \n\
 Search the zone for a given pair of domain name and RR type.\n\
 \n\
+Each derived version of this method searches the underlying backend\n\
+for the data that best matches the given name and type. This method is\n\
+expected to be \"intelligent\", and identifies the best possible\n\
+answer for the search key. Specifically,\n\
+\n\
 - If the search name belongs under a zone cut, it returns the code of\n\
   DELEGATION and the NS RRset at the zone cut.\n\
 - If there is no matching name, it returns the code of NXDOMAIN, and,\n\
@@ -62,40 +71,46 @@ Search the zone for a given pair of domain name and RR type.\n\
   and the code of SUCCESS will be returned.\n\
 - If the search name matches a delegation point of DNAME, it returns\n\
   the code of DNAME and that DNAME RR.\n\
-- If the result was synthesized by a wildcard match, it returns the\n\
-  code WILDCARD and the synthesized RRset\n\
-- If the query matched a wildcard name, but not its type, it returns the\n\
-  code WILDCARD_NXRRSET, and None\n\
-- If the target is a list, all RRsets under the domain are inserted\n\
+- If the target isn't None, all RRsets under the domain are inserted\n\
   there and SUCCESS (or NXDOMAIN, in case of empty domain) is returned\n\
   instead of normall processing. This is intended to handle ANY query.\n\
-  : this behavior is controversial as we discussed in\n\
-  https://lists.isc.org/pipermail/bind10-dev/2011-January/001918.html\n\
-  We should revisit the interface before we heavily rely on it. The\n\
-  options parameter specifies customized behavior of the search. Their\n\
-  semantics is as follows:\n\
-  (This feature is disable at this time)\n\
-- GLUE_OK Allow search under a zone cut. By default the search will\n\
-  stop once it encounters a zone cut. If this option is specified it\n\
-  remembers information about the highest zone cut and continues the\n\
-  search until it finds an exact match for the given name or it\n\
+\n\
+Note: This behavior is controversial as we discussed in\n\
+https://lists.isc.org/pipermail/bind10-dev/2011-January/001918.html We\n\
+should revisit the interface before we heavily rely on it.\n\
+\n\
+The options parameter specifies customized behavior of the search.\n\
+Their semantics is as follows (they are or bit-field):\n\
+\n\
+- FIND_GLUE_OK Allow search under a zone cut. By default the search\n\
+  will stop once it encounters a zone cut. If this option is specified\n\
+  it remembers information about the highest zone cut and continues\n\
+  the search until it finds an exact match for the given name or it\n\
   detects there is no exact match. If an exact match is found, RRsets\n\
   for that name are searched just like the normal case; otherwise, if\n\
   the search has encountered a zone cut, DELEGATION with the\n\
   information of the highest zone cut will be returned.\n\
+- FIND_DNSSEC Request that DNSSEC data (like NSEC, RRSIGs) are\n\
+  returned with the answer. It is allowed for the data source to\n\
+  include them even when not requested.\n\
+- NO_WILDCARD Do not try wildcard matching. This option is of no use\n\
+  for normal lookups; it's intended to be used to get a DNSSEC proof\n\
+  of the non existence of any matching wildcard or non existence of an\n\
+  exact match when a wildcard match is found.\n\
+\n\
 \n\
-This method raises an isc.datasrc.Error exception if there is an internal\n\
-error in the datasource.\n\
+This method raises an isc.datasrc.Error exception if there is an\n\
+internal error in the datasource.\n\
 \n\
 Parameters:\n\
   name       The domain name to be searched for.\n\
   type       The RR type to be searched for.\n\
-  target     If target is not NULL, insert all RRs under the domain\n\
+  target     If target is not None, insert all RRs under the domain\n\
              into it.\n\
   options    The search options.\n\
 \n\
-Return Value(s): A tuple of a result code an a FindResult object enclosing\n\
-the search result (see above).\n\
+Return Value(s): A tuple of a result code (integer) and an RRset object\n\
+enclosing the search result (see above).\n\
 ";
 
 const char* const ZoneFinder_find_previous_name_doc = "\
diff --git a/src/lib/python/isc/datasrc/finder_python.cc b/src/lib/python/isc/datasrc/finder_python.cc
index cb02724..6585049 100644
--- a/src/lib/python/isc/datasrc/finder_python.cc
+++ b/src/lib/python/isc/datasrc/finder_python.cc
@@ -268,16 +268,16 @@ PyTypeObject zonefinder_type = {
 
 PyObject*
 createZoneFinderObject(isc::datasrc::ZoneFinderPtr source, PyObject* base_obj) {
-    s_ZoneFinder* py_zi = static_cast<s_ZoneFinder*>(
+    s_ZoneFinder* py_zf = static_cast<s_ZoneFinder*>(
         zonefinder_type.tp_alloc(&zonefinder_type, 0));
-    if (py_zi != NULL) {
-        py_zi->cppobj = source;
-        py_zi->base_obj = base_obj;
-    }
-    if (base_obj != NULL) {
-        Py_INCREF(base_obj);
+    if (py_zf != NULL) {
+        py_zf->cppobj = source;
+        py_zf->base_obj = base_obj;
+        if (base_obj != NULL) {
+            Py_INCREF(base_obj);
+        }
     }
-    return (py_zi);
+    return (py_zf);
 }
 
 } // namespace python
diff --git a/src/lib/python/isc/datasrc/iterator_python.cc b/src/lib/python/isc/datasrc/iterator_python.cc
index c52ab4a..eb368ba 100644
--- a/src/lib/python/isc/datasrc/iterator_python.cc
+++ b/src/lib/python/isc/datasrc/iterator_python.cc
@@ -204,9 +204,9 @@ createZoneIteratorObject(isc::datasrc::ZoneIteratorPtr source,
     if (py_zi != NULL) {
         py_zi->cppobj = source;
         py_zi->base_obj = base_obj;
-    }
-    if (base_obj != NULL) {
-        Py_INCREF(base_obj);
+        if (base_obj != NULL) {
+            Py_INCREF(base_obj);
+        }
     }
     return (py_zi);
 }
diff --git a/src/lib/python/isc/datasrc/tests/datasrc_test.py b/src/lib/python/isc/datasrc/tests/datasrc_test.py
index 75a0cfb..dcb8904 100644
--- a/src/lib/python/isc/datasrc/tests/datasrc_test.py
+++ b/src/lib/python/isc/datasrc/tests/datasrc_test.py
@@ -15,10 +15,12 @@
 
 import isc.log
 import isc.datasrc
+from isc.datasrc import ZoneFinder
 import isc.dns
 import unittest
 import os
 import shutil
+import sys
 import json
 
 TESTDATA_PATH = os.environ['TESTDATA_PATH'] + os.sep
@@ -191,6 +193,29 @@ class DataSrcClient(unittest.TestCase):
         # can't construct directly
         self.assertRaises(TypeError, isc.datasrc.ZoneFinder)
 
+    def test_findoptions(self):
+        '''A simple test to confirm no option is specified by default.
+
+        '''
+        self.assertFalse(ZoneFinder.FIND_DEFAULT & ZoneFinder.FIND_GLUE_OK)
+        self.assertFalse(ZoneFinder.FIND_DEFAULT & ZoneFinder.FIND_DNSSEC)
+        self.assertFalse(ZoneFinder.FIND_DEFAULT & ZoneFinder.NO_WILDCARD)
+
+    def test_findresults(self):
+        '''A simple test to confirm result codes are (defined and) different
+        for some combinations.
+
+        '''
+        self.assertNotEqual(ZoneFinder.SUCCESS, ZoneFinder.DELEGATION)
+        self.assertNotEqual(ZoneFinder.DELEGATION, ZoneFinder.NXDOMAIN)
+        self.assertNotEqual(ZoneFinder.NXDOMAIN, ZoneFinder.NXRRSET)
+        self.assertNotEqual(ZoneFinder.NXRRSET, ZoneFinder.CNAME)
+        self.assertNotEqual(ZoneFinder.CNAME, ZoneFinder.DNAME)
+        self.assertNotEqual(ZoneFinder.DNAME, ZoneFinder.WILDCARD)
+        self.assertNotEqual(ZoneFinder.WILDCARD, ZoneFinder.WILDCARD_CNAME)
+        self.assertNotEqual(ZoneFinder.WILDCARD_CNAME,
+                            ZoneFinder.WILDCARD_NXRRSET)
+
     def test_find(self):
         dsc = isc.datasrc.DataSourceClient("sqlite3", READ_ZONE_DB_CONFIG)
 
@@ -470,6 +495,23 @@ class DataSrcUpdater(unittest.TestCase):
                          dsc.get_updater(isc.dns.Name("notexistent.example"),
                                          True))
 
+    def test_client_reference(self):
+        # Temporarily create various objects using factory methods of the
+        # client.  The created objects won't be stored anywhere and
+        # immediately released.  The creation shouldn't affect the reference
+        # to the base client.
+        dsc = isc.datasrc.DataSourceClient("sqlite3", WRITE_ZONE_DB_CONFIG)
+        orig_ref = sys.getrefcount(dsc)
+
+        dsc.find_zone(isc.dns.Name("example.com"))
+        self.assertEqual(orig_ref, sys.getrefcount(dsc))
+
+        dsc.get_iterator(isc.dns.Name("example.com."))
+        self.assertEqual(orig_ref, sys.getrefcount(dsc))
+
+        dsc.get_updater(isc.dns.Name("example.com"), True)
+        self.assertEqual(orig_ref, sys.getrefcount(dsc))
+
 if __name__ == "__main__":
     isc.log.init("bind10")
     unittest.main()
diff --git a/src/lib/python/isc/datasrc/updater_python.cc b/src/lib/python/isc/datasrc/updater_python.cc
index e447622..29d2ffe 100644
--- a/src/lib/python/isc/datasrc/updater_python.cc
+++ b/src/lib/python/isc/datasrc/updater_python.cc
@@ -270,15 +270,16 @@ PyObject*
 createZoneUpdaterObject(isc::datasrc::ZoneUpdaterPtr source,
                         PyObject* base_obj)
 {
-    s_ZoneUpdater* py_zi = static_cast<s_ZoneUpdater*>(
+    s_ZoneUpdater* py_zu = static_cast<s_ZoneUpdater*>(
         zoneupdater_type.tp_alloc(&zoneupdater_type, 0));
-    if (py_zi != NULL) {
-        py_zi->cppobj = source;
-    }
-    if (base_obj != NULL) {
-        Py_INCREF(base_obj);
+    if (py_zu != NULL) {
+        py_zu->cppobj = source;
+        py_zu->base_obj = base_obj;
+        if (base_obj != NULL) {
+            Py_INCREF(base_obj);
+        }
     }
-    return (py_zi);
+    return (py_zu);
 }
 
 } // namespace python
diff --git a/src/lib/python/isc/log/log.cc b/src/lib/python/isc/log/log.cc
index 5bb6a94..c7112b3 100644
--- a/src/lib/python/isc/log/log.cc
+++ b/src/lib/python/isc/log/log.cc
@@ -28,7 +28,11 @@
 #include <string>
 #include <boost/bind.hpp>
 
+#include <util/python/pycppwrapper_util.h>
+#include <log/log_dbglevels.h>
+
 using namespace isc::log;
+using namespace isc::util::python;
 using std::string;
 using boost::bind;
 
@@ -723,7 +727,38 @@ PyInit_log(void) {
                                &logger_type))) < 0) {
         return (NULL);
     }
-    Py_INCREF(&logger_type);
 
+    // Add in the definitions of the standard debug levels.  These can then
+    // be referred to in Python through the constants log.DBGLVL_XXX.
+    // N.B. These should be kept in sync with the constants defined in
+    // log_dbglevels.h.
+    try {
+        installClassVariable(logger_type, "DBGLVL_START_SHUT",
+                             Py_BuildValue("I", DBGLVL_START_SHUT));
+        installClassVariable(logger_type, "DBGLVL_COMMAND",
+                             Py_BuildValue("I", DBGLVL_COMMAND));
+        installClassVariable(logger_type, "DBGLVL_COMMAND_DATA",
+                             Py_BuildValue("I", DBGLVL_COMMAND_DATA));
+        installClassVariable(logger_type, "DBGLVL_TRACE_BASIC",
+                             Py_BuildValue("I", DBGLVL_TRACE_BASIC));
+        installClassVariable(logger_type, "DBGLVL_TRACE_BASIC_DATA",
+                             Py_BuildValue("I", DBGLVL_TRACE_BASIC_DATA));
+        installClassVariable(logger_type, "DBGLVL_TRACE_DETAIL",
+                             Py_BuildValue("I", DBGLVL_TRACE_DETAIL));
+        installClassVariable(logger_type, "DBGLVL_TRACE_DETAIL_DATA",
+                             Py_BuildValue("I", DBGLVL_TRACE_DETAIL_DATA));
+    } catch (const std::exception& ex) {
+        const std::string ex_what =
+            "Unexpected failure in Log initialization: " +
+            std::string(ex.what());
+        PyErr_SetString(PyExc_SystemError, ex_what.c_str());
+        return (NULL);
+    } catch (...) {
+        PyErr_SetString(PyExc_SystemError,
+                        "Unexpected failure in Log initialization");
+        return (NULL);
+    }
+
+    Py_INCREF(&logger_type);
     return (mod);
 }
diff --git a/src/lib/python/isc/log/tests/log_test.py b/src/lib/python/isc/log/tests/log_test.py
index 4292b6c..8deaeae 100644
--- a/src/lib/python/isc/log/tests/log_test.py
+++ b/src/lib/python/isc/log/tests/log_test.py
@@ -159,5 +159,15 @@ class Logger(unittest.TestCase):
         # Bad type
         self.assertRaises(TypeError, logger.debug, "42", "hello")
 
+    def test_dbglevel_constants(self):
+        """
+            Just check a constant to make sure it is defined and is the
+            correct value.  (The constant chosen has a non-zero value to
+            ensure that the code has both define the constant and set its
+            value correctly.)
+        """
+        logger = isc.log.Logger("child")
+        self.assertEqual(logger.DBGLVL_COMMAND, 10)
+
 if __name__ == '__main__':
     unittest.main()
diff --git a/src/lib/resolve/resolve_log.h b/src/lib/resolve/resolve_log.h
index 1f2869e..828b9d3 100644
--- a/src/lib/resolve/resolve_log.h
+++ b/src/lib/resolve/resolve_log.h
@@ -27,17 +27,17 @@ namespace resolve {
 /// Note that higher numbers equate to more verbose (and detailed) output.
 
 // The first level traces normal operations
-const int RESLIB_DBG_TRACE = 10;
+const int RESLIB_DBG_TRACE = DBGLVL_TRACE_BASIC;
 
 // The next level extends the normal operations and records the results of the
 // lookups.
-const int RESLIB_DBG_RESULTS = 20;
+const int RESLIB_DBG_RESULTS = DBGLVL_TRACE_BASIC_DATA;
 
 // Report cache lookups and results
-const int RESLIB_DBG_CACHE = 40;
+const int RESLIB_DBG_CACHE = DBGLVL_TRACE_DETAIL_DATA;
 
 // Indicate when callbacks are called
-const int RESLIB_DBG_CB = 50;
+const int RESLIB_DBG_CB = DBGLVL_TRACE_DETAIL_DATA + 10;
 
 
 /// \brief Resolver Library Logger
diff --git a/src/lib/resolve/tests/Makefile.am b/src/lib/resolve/tests/Makefile.am
index 7c42c36..cf05d9b 100644
--- a/src/lib/resolve/tests/Makefile.am
+++ b/src/lib/resolve/tests/Makefile.am
@@ -38,4 +38,4 @@ run_unittests_LDADD +=  $(top_builddir)/src/lib/exceptions/libexceptions.la
 
 endif
 
-check_PROGRAMS = $(TESTS)
+noinst_PROGRAMS = $(TESTS)
diff --git a/src/lib/server_common/logger.h b/src/lib/server_common/logger.h
index cfca1f3..ae07865 100644
--- a/src/lib/server_common/logger.h
+++ b/src/lib/server_common/logger.h
@@ -31,12 +31,11 @@ namespace server_common {
 /// \brief The logger for this library
 extern isc::log::Logger logger;
 
-enum {
-    /// \brief Trace basic operations
-    DBG_TRACE_BASIC = 10,
-    /// \brief Print also values used
-    DBG_TRACE_VALUES = 40
-};
+/// \brief Trace basic operations
+const int DBG_TRACE_BASIC = DBGLVL_TRACE_BASIC;
+
+/// \brief Print also values used
+const int DBG_TRACE_VALUES = DBGLVL_TRACE_BASIC_DATA;
 
 }
 }
diff --git a/src/lib/server_common/tests/Makefile.am b/src/lib/server_common/tests/Makefile.am
index d07be52..d7e113a 100644
--- a/src/lib/server_common/tests/Makefile.am
+++ b/src/lib/server_common/tests/Makefile.am
@@ -49,6 +49,6 @@ run_unittests_LDADD += $(top_builddir)/src/lib/config/libcfgclient.la
 run_unittests_LDADD += $(top_builddir)/src/lib/config/tests/libfake_session.la
 endif
 
-check_PROGRAMS = $(TESTS)
+noinst_PROGRAMS = $(TESTS)
 
 EXTRA_DIST = testdata/spec.spec
diff --git a/src/lib/testutils/Makefile.am b/src/lib/testutils/Makefile.am
index ae5c6da..a511d24 100644
--- a/src/lib/testutils/Makefile.am
+++ b/src/lib/testutils/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS += $(BOOST_INCLUDES)
 AM_CXXFLAGS=$(B10_CXXFLAGS)
 
 if HAVE_GTEST
-lib_LTLIBRARIES = libtestutils.la
+noinst_LTLIBRARIES = libtestutils.la
 
 libtestutils_la_SOURCES = srv_test.h srv_test.cc
 libtestutils_la_SOURCES += dnsmessage_test.h dnsmessage_test.cc
diff --git a/src/lib/testutils/dnsmessage_test.h b/src/lib/testutils/dnsmessage_test.h
index a8b7284..1aba526 100644
--- a/src/lib/testutils/dnsmessage_test.h
+++ b/src/lib/testutils/dnsmessage_test.h
@@ -21,6 +21,7 @@
 #include <dns/message.h>
 #include <dns/name.h>
 #include <dns/masterload.h>
+#include <dns/rdataclass.h>
 #include <dns/rrclass.h>
 #include <dns/rrset.h>
 
@@ -113,13 +114,32 @@ void rrsetCheck(isc::dns::ConstRRsetPtr expected_rrset,
 /// The definitions in this name space are not supposed to be used publicly,
 /// but are given here because they are used in templated functions.
 namespace detail {
-// Helper matching class used in rrsetsCheck()
+// Helper matching class used in rrsetsCheck().  Basically we only have to
+// check the equality of name, RR type and RR class, but for RRSIGs we need
+// special additional checks because they are essentially different if their
+// 'type covered' are different.  For simplicity, we only compare the types
+// of the first RRSIG RDATAs (and only check when they exist); if there's
+// further difference in the RDATA, the main comparison checks will detect it.
 struct RRsetMatch : public std::unary_function<isc::dns::ConstRRsetPtr, bool> {
     RRsetMatch(isc::dns::ConstRRsetPtr target) : target_(target) {}
     bool operator()(isc::dns::ConstRRsetPtr rrset) const {
-        return (rrset->getType() == target_->getType() &&
-                rrset->getClass() == target_->getClass() &&
-                rrset->getName() == target_->getName());
+        if (rrset->getType() != target_->getType() ||
+            rrset->getClass() != target_->getClass() ||
+            rrset->getName() != target_->getName()) {
+            return (false);
+        }
+        if (rrset->getType() != isc::dns::RRType::RRSIG()) {
+            return (true);
+        }
+        if (rrset->getRdataCount() == 0 || target_->getRdataCount() == 0) {
+            return (true);
+        }
+        isc::dns::RdataIteratorPtr rdit = rrset->getRdataIterator();
+        isc::dns::RdataIteratorPtr targetit = target_->getRdataIterator();
+        return (dynamic_cast<const isc::dns::rdata::generic::RRSIG&>(
+                    rdit->getCurrent()).typeCovered() ==
+                dynamic_cast<const isc::dns::rdata::generic::RRSIG&>(
+                    targetit->getCurrent()).typeCovered());
     }
     const isc::dns::ConstRRsetPtr target_;
 };
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/pyunittests/Makefile.am b/src/lib/util/pyunittests/Makefile.am
index 02fb8c2..dd2d39a 100644
--- a/src/lib/util/pyunittests/Makefile.am
+++ b/src/lib/util/pyunittests/Makefile.am
@@ -2,7 +2,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
 AM_CPPFLAGS += $(BOOST_INCLUDES)
 AM_CXXFLAGS = $(B10_CXXFLAGS)
 
-check_LTLIBRARIES = pyunittests_util.la
+noinst_LTLIBRARIES = pyunittests_util.la
 
 pyunittests_util_la_SOURCES = pyunittests_util.cc
 pyunittests_util_la_CPPFLAGS = $(AM_CPPFLAGS) $(PYTHON_INCLUDES)
diff --git a/src/lib/util/tests/Makefile.am b/src/lib/util/tests/Makefile.am
index b61804e..47243f8 100644
--- a/src/lib/util/tests/Makefile.am
+++ b/src/lib/util/tests/Makefile.am
@@ -40,4 +40,4 @@ run_unittests_LDADD += \
 run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
 endif
 
-check_PROGRAMS = $(TESTS)
+noinst_PROGRAMS = $(TESTS)
diff --git a/src/lib/util/tests/io_utilities_unittest.cc b/src/lib/util/tests/io_utilities_unittest.cc
index 4aad560..4293c7e 100644
--- a/src/lib/util/tests/io_utilities_unittest.cc
+++ b/src/lib/util/tests/io_utilities_unittest.cc
@@ -19,6 +19,7 @@
 
 #include <cstddef>
 
+#include <arpa/inet.h>
 #include <gtest/gtest.h>
 
 #include <util/buffer.h>
@@ -71,3 +72,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/src/lib/util/unittests/Makefile.am b/src/lib/util/unittests/Makefile.am
index 8006262..bbb0d49 100644
--- a/src/lib/util/unittests/Makefile.am
+++ b/src/lib/util/unittests/Makefile.am
@@ -1,7 +1,7 @@
 AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
 AM_CXXFLAGS = $(B10_CXXFLAGS)
 
-check_LTLIBRARIES = libutil_unittests.la
+noinst_LTLIBRARIES = libutil_unittests.la
 libutil_unittests_la_SOURCES = fork.h fork.cc resolver.h
 libutil_unittests_la_SOURCES += newhook.h newhook.cc
 libutil_unittests_la_SOURCES += testdata.h testdata.cc
diff --git a/tests/system/README b/tests/system/README
index a43d49e..a1c0a97 100644
--- a/tests/system/README
+++ b/tests/system/README
@@ -5,48 +5,49 @@ See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
 This is a simple test environment for running BIND 10 system tests
 involving multiple name servers.  It was originally developed for BIND
 9, and has been ported to test BIND 10 implementations.  Ideally we
-should share the same framework for both versions, so some part of
-the original setup are kept, even though they are BIND 9 specific and
-not currently used.
+should share the same framework for both versions, so some part of the
+original setup are kept, even though they are BIND 9 specific and not
+currently used.
 
-Also, these tests generally rely on BIND 9 programs, most commonly its
-dig, and will sometimes be its name server (named).  So, the test
+Also, these tests generally rely on BIND 9 programs, most commonly
+its dig, and will sometimes be its name server (named).  So, the test
 environment assumes that there's a source tree of BIND 9 where its
-programs are built, and that an environment variable "BIND9_TOP" is
-set to point to the top directory of the source tree.
+programs are built, and that an environment variable "BIND9_TOP" is set
+to point to the top directory of the source tree.
 
 There are multiple test suites, each in a separate subdirectory and
 involving a different DNS setup.  They are:
 
   bindctl/      Some basic management operations using the bindctl tool
-  glue/		Glue handling tests
+  glue/		    Glue handling tests
+  ixfr/         Incremental transfer tests
+
 (the following tests are planned to be added soon)
-  dnssec/	DNSSEC tests
+  dnssec/	    DNSSEC tests
   masterfile/	Master file parser
-  xfer/		Zone transfer tests
+  axfr/         Full-transfer tests
 
 Typically each test suite sets up 2-5 instances of BIND 10 (or BIND 9
-named) and then performs one or more tests against them.  Within the
-test suite subdirectory, each instance has a separate subdirectory
-containing its configuration data.  By convention, these
-subdirectories are named "nsx1", "nsx2", etc for BIND 10 ("x" means
-BIND 10), and "ns1", "ns2", etc. for BIND 9.
+named) and then performs one or more tests against them.  Within the test
+suite subdirectory, each instance has a separate subdirectory containing
+its configuration data.  By convention, these subdirectories are named
+"nsx1", "nsx2", etc for BIND 10 ("x" means BIND 10), and "ns1", "ns2",
+etc. for BIND 9.
 
 The tests are completely self-contained and do not require access to
-the real DNS.  Generally, one of the test servers (ns[x]1) is set up
-as a root name server and is listed in the hints file of the others.
+the real DNS.  Generally, one of the test servers (ns[x]1) is set up as
+a root name server and is listed in the hints file of the others.
 
-To enable all servers to run on the same machine, they bind to
-separate virtual IP address on the loopback interface.  ns[x]1 runs on
-10.53.0.1, ns[x]2 on 10.53.0.2, etc.  Before running any tests, you
-must set up these addresses by running "ifconfig.sh up" as root.
+To enable all servers to run on the same machine, they bind to separate
+virtual IP address on the loopback interface.  ns[x]1 runs on 10.53.0.1,
+ns[x]2 on 10.53.0.2, etc.  Before running any tests, you must set up
+these addresses by running "ifconfig.sh up" as root.
 
 Mac OS X:
-If you wish to make the interfaces survive across reboots
-copy org.isc.bind.system and org.isc.bind.system to
-/Library/LaunchDaemons then run
-"launchctl load /Library/LaunchDaemons/org.isc.bind.system.plist" as
-root.
+If you wish to make the interfaces survive across reboots copy
+org.isc.bind.system and org.isc.bind.system to /Library/LaunchDaemons
+then run "launchctl load /Library/LaunchDaemons/org.isc.bind.system.plist"
+as root.
 
 The servers use port 53210 instead of the usual port 53, so they can be
 run without root privileges once the interfaces have been set up.
diff --git a/tests/system/cleanall.sh b/tests/system/cleanall.sh
index d23d103..434c6b1 100755
--- a/tests/system/cleanall.sh
+++ b/tests/system/cleanall.sh
@@ -27,7 +27,7 @@ find . -type f \( \
 
 status=0
 
-for d in ./.* ./*
+for d in ./.* ./* ./*/*
 do
    case $d in ./.|./..) continue ;; esac
    test -d $d || continue
diff --git a/tests/system/common/rndc.conf b/tests/system/common/rndc.conf
new file mode 100644
index 0000000..a897548
--- /dev/null
+++ b/tests/system/common/rndc.conf
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2004, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * 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.
+ */
+
+options {
+        default-key     "rndc_key";
+};
+
+key rndc_key {
+        algorithm       hmac-md5;
+        secret          "1234abcd8765";
+};
diff --git a/tests/system/common/rndc.key b/tests/system/common/rndc.key
new file mode 100644
index 0000000..c2c3457
--- /dev/null
+++ b/tests/system/common/rndc.key
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+/* $Id: rndc.key,v 1.3 2011-03-12 04:59:47 tbox Exp $ */
+
+key rndc_key {
+        secret "1234abcd8765";
+        algorithm hmac-md5;
+};
diff --git a/tests/system/conf.sh.in b/tests/system/conf.sh.in
index 66aa3f5..92f72fa 100755
--- a/tests/system/conf.sh.in
+++ b/tests/system/conf.sh.in
@@ -35,23 +35,36 @@ if [ -z $BIND9_TOP ]; then
 fi
 
 # Find the top of the source and test trees.
-TOP=@abs_top_srcdir@
-TEST_TOP=@abs_builddir@
-
-RUN_BIND10=$TOP/src/bin/bind10/run_bind10.sh
-RUN_BINDCTL=$TOP/src/bin/bindctl/run_bindctl.sh
-BINDCTL_CSV_DIR=@abs_srcdir@/common/
-B10_LOADZONE=$TOP/src/bin/loadzone/run_loadzone.sh
-BIND9_NAMED=$BIND9_TOP/bin/named/named
-DIG=$BIND9_TOP/bin/dig/dig
+export TOP=@abs_top_srcdir@
+export TEST_TOP=@abs_builddir@
+
+# Programs
+export RUN_BIND10=$TOP/src/bin/bind10/run_bind10.sh
+export RUN_BINDCTL=$TOP/src/bin/bindctl/run_bindctl.sh
+export BINDCTL_CSV_DIR=@abs_srcdir@/common/
+export B10_LOADZONE=$TOP/src/bin/loadzone/run_loadzone.sh
+export BIND9_NAMED=$BIND9_TOP/bin/named/named
+export DIG=$BIND9_TOP/bin/dig/dig
+export RNDC=$BIND9_TOP/bin/rndc/rndc
+
 # Test tools borrowed from BIND 9's system test (without change).
-TESTSOCK=$BIND9_TOP/bin/tests/system/testsock.pl
-DIGCOMP=$BIND9_TOP/bin/tests/system/digcomp.pl
+export TESTSOCK=$BIND9_TOP/bin/tests/system/testsock.pl
+export DIGCOMP=$BIND9_TOP/bin/tests/system/digcomp.pl
+
+export SUBDIRS="bindctl glue ixfr/in-2"
+# Add appropriate subdirectories to the above statement as the tests become
+# available.
+#SUBDIRS="dnssec masterfile ixfr/in-1 ixfr/in-2 ixfr/in-4"
 
-SUBDIRS="bindctl glue"
-#SUBDIRS="dnssec masterfile xfer"
+# PERL will be an empty string if no perl interpreter was found.  A similar
+# comment applies to AWK.
+export PERL=@PERL@
+export AWK=@AWK@
 
-# PERL will be an empty string if no perl interpreter was found.
-PERL=@PERL@
+# Other constants
+export RNDC_PORT=9953
+export DNS_PORT=53210
 
-export RUN_BIND10 BIND9_NAMED DIG SUBDIRS PERL TESTSOCK
+export TESTS_TOP=$TOP/tests
+export SYSTEM_TOP=$TESTS_TOP/system
+export IXFR_TOP=$SYSTEM_TOP/ixfr
diff --git a/tests/system/ixfr/README b/tests/system/ixfr/README
new file mode 100644
index 0000000..51cba8a
--- /dev/null
+++ b/tests/system/ixfr/README
@@ -0,0 +1,86 @@
+Introduction
+============
+The directories in-1 to in-4 implement the following tests of the IXFR-in
+capability of BIND 10.
+
+in-1: Check that BIND 10 can receive IXFR in a single UDP packet.
+in-2: Check that BIND 10 can receive IXFR via TCP.
+in-3: Check that BIND 10 will request AXFR if the server does not support IXFR.
+in-4: Check that BIND 10 will request IXFR when its SOA refresh times out
+
+The tests are described more fully in the document:
+
+http://bind10.isc.org/wiki/IxfrSystemTests
+
+Overview
+========
+All the tests use two nameservers:
+
+* A BIND 9 nameserver acting as the IXFR server (using the nomenclature
+of RFC 1995).
+* A BIND 10 nameserver acting at the IXFR client.
+
+In general, the tests attempt to set up the server and client independently.
+Communication is established between the systems by updating their
+configurations and a notification sent to the client.  This should cause the
+client to request an IXFR from the server. (The exception is test 4, where the
+request is a result of the expiration of the SOA refresh time.)
+
+A check of zone files - or in these tests, of SOA serial number - can only
+reveal that a transfer has taken place.  To check what has happened,
+e.g. whether the transfer was via UDP or whether a TCP request took place,
+the BIND 10 log file is searched for known message IDs.
+
+The searching of the log files for message IDs is one of the reasons that,
+unlike other system tests, the IXFR set of tests is broken up into separate
+tests that require the stopping and starting of nameservers (and tidying up of
+log files) between each test.  Doing this means that only the existence of a
+particular message ID needs to be checked - there is no risk that another test
+produced it.  The other reason is that the each IXFR test requires the
+nameservers to be in a specific state at the start of the test; this is easier
+to assure if they are not updating one another as the result of configuration
+settings established in the previous test.
+
+Test Files
+==========
+
+Data Files
+----------
+(All within tests/system/ixfr.  Some .in files are processed to substitute
+for build variables in the build process to give the files listed here.)
+
+db.example.nX. These files hold the RRs for a zone for which should not
+fit within a single UDP packet.  The files are different versions of the zone
+- the N-0 version (i.e. the latest version - "N" - the "-0" is present so
+that the files have a consistent name), N-2 etc. (See the full description
+of the tests for the meaning of N-2 etc.)
+
+db.example.common: A set of RRs to bulk out the zone to be larger than can
+be contained in a single UDP packet.
+
+db.example.n2.refresh: The N-2 version of the zone, but with a small SOA
+refresh time (for test 4).
+
+named_xxxx.conf: Various BIND 9 configuration files with NOTIFYs and/or
+IXFR enabled or disabled.
+
+Directories
+-----------
+The tests/system/ixfr directory holds the IXFR tests.  Within that
+directory are subdirectories in-1 through in-4 for each test.  And within
+each test directory are the directories ns1 (for the BIND 9 nameserver)
+and nsx2 (for the BIND 10 nameserver).
+
+Shell Scripts
+-------------
+The IXFR tests use the same framework as the rest of the system tests,
+being based around shell scripts.  Many have a ".in" form as they require
+substitution of build variables before they can be used, and so are
+listed in configure.ac.  The files specific to the IXFR tests are:
+
+tests/system/ixfr/ixfr_init.sh.in: defines environment variables and shell
+subroutines used in the tests.  (This references system/conf.sh.in which
+defines most of them.)
+
+tests/system/ixfr/common_tests.sh.in: tests in-1 and in-2 are virtually
+identical - this holds the common code.
diff --git a/tests/system/ixfr/b10-config.db.in b/tests/system/ixfr/b10-config.db.in
new file mode 100644
index 0000000..946d80f
--- /dev/null
+++ b/tests/system/ixfr/b10-config.db.in
@@ -0,0 +1,23 @@
+{"version": 2,
+    "Xfrin": {
+        "zones": [{
+            "master_addr": "10.53.0.1",
+            "master_port": 53210,
+            "name": "example.",
+            "use_ixfr": true
+        }]
+    },
+    "Auth": {
+        "listen_on": [{
+            "address": "10.53.0.2",
+            "port": 53210
+        }],
+        "database_file": "@abs_builddir@/zone.sqlite3"
+    },
+    "Zonemgr": {
+        "secondary_zones": [{
+            "name": "example.",
+            "class": "IN"
+        }]
+    }
+}
diff --git a/tests/system/ixfr/clean_ns.sh b/tests/system/ixfr/clean_ns.sh
new file mode 100644
index 0000000..88f4ff1
--- /dev/null
+++ b/tests/system/ixfr/clean_ns.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+#
+# 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.
+
+# Clean up nameserver directories after zone transfer tests.
+
+rm -f ns1/named.conf
+rm -f ns1/db.example*
+rm -f ns1/named.memstats
+
+rm -f nsx2/bind10.run
+rm -f nsx2/b10-config.db
+rm -f ../zone.sqlite3
+
+rm -f client.dig
+rm -f server.dig
diff --git a/tests/system/ixfr/common_tests.sh.in b/tests/system/ixfr/common_tests.sh.in
new file mode 100644
index 0000000..90d0284
--- /dev/null
+++ b/tests/system/ixfr/common_tests.sh.in
@@ -0,0 +1,78 @@
+#!/bin/sh
+#
+# 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.
+
+# \file
+# This script is used in a couple of IXFR tests.
+#
+# Preconditions:\n
+# The BIND 9 nameserver (ns1, 10.53.0.1, acting as the IXFR server) is loaded
+# with the N-4 version of the zone.  (It may hold prior versions as well.)
+# Notifications are disabled.
+#
+# The BIND 10 nameserver (nsx2, 10.53.0.2, acting as the IXFR client) is loaded
+# with an earlier (unspecified) version of the zone.
+#
+# Actions:\n
+# This script updates the IXFR server with the N-2 and N-0 versions of the zone.
+# It then updates the BIND 10 configuration so that it looks for IXFRs from
+# the IXFR server and causes the server to send the client a NOTIFY.  After
+# waiting for the client to update from the server, it compares ther zones of
+# the two system, reporting an error if they are different.
+#
+# Caller Actions:\n
+# The caller can pre-load the BIND 10 IXFR client with whatever version of the
+# zone it requires.  It can also load the BIND 9 IXFR server with zones earlier
+# than N-4.
+#
+# After this test has finished, it is up to the caller to check the logs
+# to see if they report the expected behavior.
+#
+# \return 0 if the script executed successfully, non-zero otherwise
+
+# Set up variables etc.
+. @abs_top_builddir@/tests/system/conf.sh
+. $IXFR_TOP/ixfr_init.sh
+
+set -e
+
+# Store the SOA serial number of the BIND 10 client for later use.
+old_client_serial=`$DIG_SOA @$CLIENT_IP | $AWK '{print $3}'`
+echo "I:$CLIENT_NAME SOA serial of IXFR client is $old_client_serial"
+
+# Load the BIND 9 system (the IXFR server) with the "n - 2" and "n" version of
+# the zones.  With ixfr-from-differences set to "yes", the nameserver should
+# generate the differences between them.
+echo "I:$SERVER_NAME updating IXFR-server for ixfr-in tests"
+update_server_zone $SERVER_NAME $SERVER_IP $IXFR_TOP/db.example.n2
+
+# Wait a bit - it seems that if two updates are loaded in quick succession,
+# the second sometimes gets lost.
+sleep 5
+update_server_zone $SERVER_NAME $SERVER_IP $IXFR_TOP/db.example.n0
+
+echo "I:$CLIENT_NAME forcing IXFR client to retrieve new version of the zone"
+$RUN_BINDCTL << .
+Xfrin retransfer zone_name="example"
+.
+
+# Wait for the client to update itself.
+wait_for_update $CLIENT_NAME $CLIENT_IP $old_client_serial
+
+# Has updated, compare the client and server's versions of the zone s- they
+# should be the same.
+compare_zones $SERVER_NAME $SERVER_IP $CLIENT_NAME $CLIENT_IP
+
+set +e
diff --git a/tests/system/ixfr/db.example.common b/tests/system/ixfr/db.example.common
new file mode 100644
index 0000000..90435ce
--- /dev/null
+++ b/tests/system/ixfr/db.example.common
@@ -0,0 +1,1556 @@
+; 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.
+
+; This files holds a number of AAAA records to bulk out a zone file beyond
+; 16kB.  It is used in tests where it is required that the contents of a zone
+; do not fit into a single UDP packet.
+
+aaaa-000		IN	AAAA	2001:db8::0000
+aaaa-001		IN	AAAA	2001:db8::0001
+aaaa-002		IN	AAAA	2001:db8::0002
+aaaa-003		IN	AAAA	2001:db8::0003
+aaaa-004		IN	AAAA	2001:db8::0004
+aaaa-005		IN	AAAA	2001:db8::0005
+aaaa-006		IN	AAAA	2001:db8::0006
+aaaa-007		IN	AAAA	2001:db8::0007
+aaaa-008		IN	AAAA	2001:db8::0008
+aaaa-009		IN	AAAA	2001:db8::0009
+aaaa-010		IN	AAAA	2001:db8::000a
+aaaa-011		IN	AAAA	2001:db8::000b
+aaaa-012		IN	AAAA	2001:db8::000c
+aaaa-013		IN	AAAA	2001:db8::000d
+aaaa-014		IN	AAAA	2001:db8::000e
+aaaa-015		IN	AAAA	2001:db8::000f
+aaaa-016		IN	AAAA	2001:db8::0010
+aaaa-017		IN	AAAA	2001:db8::0011
+aaaa-018		IN	AAAA	2001:db8::0012
+aaaa-019		IN	AAAA	2001:db8::0013
+aaaa-020		IN	AAAA	2001:db8::0014
+aaaa-021		IN	AAAA	2001:db8::0015
+aaaa-022		IN	AAAA	2001:db8::0016
+aaaa-023		IN	AAAA	2001:db8::0017
+aaaa-024		IN	AAAA	2001:db8::0018
+aaaa-025		IN	AAAA	2001:db8::0019
+aaaa-026		IN	AAAA	2001:db8::001a
+aaaa-027		IN	AAAA	2001:db8::001b
+aaaa-028		IN	AAAA	2001:db8::001c
+aaaa-029		IN	AAAA	2001:db8::001d
+aaaa-030		IN	AAAA	2001:db8::001e
+aaaa-031		IN	AAAA	2001:db8::001f
+aaaa-032		IN	AAAA	2001:db8::0020
+aaaa-033		IN	AAAA	2001:db8::0021
+aaaa-034		IN	AAAA	2001:db8::0022
+aaaa-035		IN	AAAA	2001:db8::0023
+aaaa-036		IN	AAAA	2001:db8::0024
+aaaa-037		IN	AAAA	2001:db8::0025
+aaaa-038		IN	AAAA	2001:db8::0026
+aaaa-039		IN	AAAA	2001:db8::0027
+aaaa-040		IN	AAAA	2001:db8::0028
+aaaa-041		IN	AAAA	2001:db8::0029
+aaaa-042		IN	AAAA	2001:db8::002a
+aaaa-043		IN	AAAA	2001:db8::002b
+aaaa-044		IN	AAAA	2001:db8::002c
+aaaa-045		IN	AAAA	2001:db8::002d
+aaaa-046		IN	AAAA	2001:db8::002e
+aaaa-047		IN	AAAA	2001:db8::002f
+aaaa-048		IN	AAAA	2001:db8::0030
+aaaa-049		IN	AAAA	2001:db8::0031
+aaaa-050		IN	AAAA	2001:db8::0032
+aaaa-051		IN	AAAA	2001:db8::0033
+aaaa-052		IN	AAAA	2001:db8::0034
+aaaa-053		IN	AAAA	2001:db8::0035
+aaaa-054		IN	AAAA	2001:db8::0036
+aaaa-055		IN	AAAA	2001:db8::0037
+aaaa-056		IN	AAAA	2001:db8::0038
+aaaa-057		IN	AAAA	2001:db8::0039
+aaaa-058		IN	AAAA	2001:db8::003a
+aaaa-059		IN	AAAA	2001:db8::003b
+aaaa-060		IN	AAAA	2001:db8::003c
+aaaa-061		IN	AAAA	2001:db8::003d
+aaaa-062		IN	AAAA	2001:db8::003e
+aaaa-063		IN	AAAA	2001:db8::003f
+aaaa-064		IN	AAAA	2001:db8::0040
+aaaa-065		IN	AAAA	2001:db8::0041
+aaaa-066		IN	AAAA	2001:db8::0042
+aaaa-067		IN	AAAA	2001:db8::0043
+aaaa-068		IN	AAAA	2001:db8::0044
+aaaa-069		IN	AAAA	2001:db8::0045
+aaaa-070		IN	AAAA	2001:db8::0046
+aaaa-071		IN	AAAA	2001:db8::0047
+aaaa-072		IN	AAAA	2001:db8::0048
+aaaa-073		IN	AAAA	2001:db8::0049
+aaaa-074		IN	AAAA	2001:db8::004a
+aaaa-075		IN	AAAA	2001:db8::004b
+aaaa-076		IN	AAAA	2001:db8::004c
+aaaa-077		IN	AAAA	2001:db8::004d
+aaaa-078		IN	AAAA	2001:db8::004e
+aaaa-079		IN	AAAA	2001:db8::004f
+aaaa-080		IN	AAAA	2001:db8::0050
+aaaa-081		IN	AAAA	2001:db8::0051
+aaaa-082		IN	AAAA	2001:db8::0052
+aaaa-083		IN	AAAA	2001:db8::0053
+aaaa-084		IN	AAAA	2001:db8::0054
+aaaa-085		IN	AAAA	2001:db8::0055
+aaaa-086		IN	AAAA	2001:db8::0056
+aaaa-087		IN	AAAA	2001:db8::0057
+aaaa-088		IN	AAAA	2001:db8::0058
+aaaa-089		IN	AAAA	2001:db8::0059
+aaaa-090		IN	AAAA	2001:db8::005a
+aaaa-091		IN	AAAA	2001:db8::005b
+aaaa-092		IN	AAAA	2001:db8::005c
+aaaa-093		IN	AAAA	2001:db8::005d
+aaaa-094		IN	AAAA	2001:db8::005e
+aaaa-095		IN	AAAA	2001:db8::005f
+aaaa-096		IN	AAAA	2001:db8::0060
+aaaa-097		IN	AAAA	2001:db8::0061
+aaaa-098		IN	AAAA	2001:db8::0062
+aaaa-099		IN	AAAA	2001:db8::0063
+aaaa-100		IN	AAAA	2001:db8::0064
+aaaa-101		IN	AAAA	2001:db8::0065
+aaaa-102		IN	AAAA	2001:db8::0066
+aaaa-103		IN	AAAA	2001:db8::0067
+aaaa-104		IN	AAAA	2001:db8::0068
+aaaa-105		IN	AAAA	2001:db8::0069
+aaaa-106		IN	AAAA	2001:db8::006a
+aaaa-107		IN	AAAA	2001:db8::006b
+aaaa-108		IN	AAAA	2001:db8::006c
+aaaa-109		IN	AAAA	2001:db8::006d
+aaaa-110		IN	AAAA	2001:db8::006e
+aaaa-111		IN	AAAA	2001:db8::006f
+aaaa-112		IN	AAAA	2001:db8::0070
+aaaa-113		IN	AAAA	2001:db8::0071
+aaaa-114		IN	AAAA	2001:db8::0072
+aaaa-115		IN	AAAA	2001:db8::0073
+aaaa-116		IN	AAAA	2001:db8::0074
+aaaa-117		IN	AAAA	2001:db8::0075
+aaaa-118		IN	AAAA	2001:db8::0076
+aaaa-119		IN	AAAA	2001:db8::0077
+aaaa-120		IN	AAAA	2001:db8::0078
+aaaa-121		IN	AAAA	2001:db8::0079
+aaaa-122		IN	AAAA	2001:db8::007a
+aaaa-123		IN	AAAA	2001:db8::007b
+aaaa-124		IN	AAAA	2001:db8::007c
+aaaa-125		IN	AAAA	2001:db8::007d
+aaaa-126		IN	AAAA	2001:db8::007e
+aaaa-127		IN	AAAA	2001:db8::007f
+aaaa-128		IN	AAAA	2001:db8::0080
+aaaa-129		IN	AAAA	2001:db8::0081
+aaaa-130		IN	AAAA	2001:db8::0082
+aaaa-131		IN	AAAA	2001:db8::0083
+aaaa-132		IN	AAAA	2001:db8::0084
+aaaa-133		IN	AAAA	2001:db8::0085
+aaaa-134		IN	AAAA	2001:db8::0086
+aaaa-135		IN	AAAA	2001:db8::0087
+aaaa-136		IN	AAAA	2001:db8::0088
+aaaa-137		IN	AAAA	2001:db8::0089
+aaaa-138		IN	AAAA	2001:db8::008a
+aaaa-139		IN	AAAA	2001:db8::008b
+aaaa-140		IN	AAAA	2001:db8::008c
+aaaa-141		IN	AAAA	2001:db8::008d
+aaaa-142		IN	AAAA	2001:db8::008e
+aaaa-143		IN	AAAA	2001:db8::008f
+aaaa-144		IN	AAAA	2001:db8::0090
+aaaa-145		IN	AAAA	2001:db8::0091
+aaaa-146		IN	AAAA	2001:db8::0092
+aaaa-147		IN	AAAA	2001:db8::0093
+aaaa-148		IN	AAAA	2001:db8::0094
+aaaa-149		IN	AAAA	2001:db8::0095
+aaaa-150		IN	AAAA	2001:db8::0096
+aaaa-151		IN	AAAA	2001:db8::0097
+aaaa-152		IN	AAAA	2001:db8::0098
+aaaa-153		IN	AAAA	2001:db8::0099
+aaaa-154		IN	AAAA	2001:db8::009a
+aaaa-155		IN	AAAA	2001:db8::009b
+aaaa-156		IN	AAAA	2001:db8::009c
+aaaa-157		IN	AAAA	2001:db8::009d
+aaaa-158		IN	AAAA	2001:db8::009e
+aaaa-159		IN	AAAA	2001:db8::009f
+aaaa-160		IN	AAAA	2001:db8::00a0
+aaaa-161		IN	AAAA	2001:db8::00a1
+aaaa-162		IN	AAAA	2001:db8::00a2
+aaaa-163		IN	AAAA	2001:db8::00a3
+aaaa-164		IN	AAAA	2001:db8::00a4
+aaaa-165		IN	AAAA	2001:db8::00a5
+aaaa-166		IN	AAAA	2001:db8::00a6
+aaaa-167		IN	AAAA	2001:db8::00a7
+aaaa-168		IN	AAAA	2001:db8::00a8
+aaaa-169		IN	AAAA	2001:db8::00a9
+aaaa-170		IN	AAAA	2001:db8::00aa
+aaaa-171		IN	AAAA	2001:db8::00ab
+aaaa-172		IN	AAAA	2001:db8::00ac
+aaaa-173		IN	AAAA	2001:db8::00ad
+aaaa-174		IN	AAAA	2001:db8::00ae
+aaaa-175		IN	AAAA	2001:db8::00af
+aaaa-176		IN	AAAA	2001:db8::00b0
+aaaa-177		IN	AAAA	2001:db8::00b1
+aaaa-178		IN	AAAA	2001:db8::00b2
+aaaa-179		IN	AAAA	2001:db8::00b3
+aaaa-180		IN	AAAA	2001:db8::00b4
+aaaa-181		IN	AAAA	2001:db8::00b5
+aaaa-182		IN	AAAA	2001:db8::00b6
+aaaa-183		IN	AAAA	2001:db8::00b7
+aaaa-184		IN	AAAA	2001:db8::00b8
+aaaa-185		IN	AAAA	2001:db8::00b9
+aaaa-186		IN	AAAA	2001:db8::00ba
+aaaa-187		IN	AAAA	2001:db8::00bb
+aaaa-188		IN	AAAA	2001:db8::00bc
+aaaa-189		IN	AAAA	2001:db8::00bd
+aaaa-190		IN	AAAA	2001:db8::00be
+aaaa-191		IN	AAAA	2001:db8::00bf
+aaaa-192		IN	AAAA	2001:db8::00c0
+aaaa-193		IN	AAAA	2001:db8::00c1
+aaaa-194		IN	AAAA	2001:db8::00c2
+aaaa-195		IN	AAAA	2001:db8::00c3
+aaaa-196		IN	AAAA	2001:db8::00c4
+aaaa-197		IN	AAAA	2001:db8::00c5
+aaaa-198		IN	AAAA	2001:db8::00c6
+aaaa-199		IN	AAAA	2001:db8::00c7
+aaaa-200		IN	AAAA	2001:db8::00c8
+aaaa-201		IN	AAAA	2001:db8::00c9
+aaaa-202		IN	AAAA	2001:db8::00ca
+aaaa-203		IN	AAAA	2001:db8::00cb
+aaaa-204		IN	AAAA	2001:db8::00cc
+aaaa-205		IN	AAAA	2001:db8::00cd
+aaaa-206		IN	AAAA	2001:db8::00ce
+aaaa-207		IN	AAAA	2001:db8::00cf
+aaaa-208		IN	AAAA	2001:db8::00d0
+aaaa-209		IN	AAAA	2001:db8::00d1
+aaaa-210		IN	AAAA	2001:db8::00d2
+aaaa-211		IN	AAAA	2001:db8::00d3
+aaaa-212		IN	AAAA	2001:db8::00d4
+aaaa-213		IN	AAAA	2001:db8::00d5
+aaaa-214		IN	AAAA	2001:db8::00d6
+aaaa-215		IN	AAAA	2001:db8::00d7
+aaaa-216		IN	AAAA	2001:db8::00d8
+aaaa-217		IN	AAAA	2001:db8::00d9
+aaaa-218		IN	AAAA	2001:db8::00da
+aaaa-219		IN	AAAA	2001:db8::00db
+aaaa-220		IN	AAAA	2001:db8::00dc
+aaaa-221		IN	AAAA	2001:db8::00dd
+aaaa-222		IN	AAAA	2001:db8::00de
+aaaa-223		IN	AAAA	2001:db8::00df
+aaaa-224		IN	AAAA	2001:db8::00e0
+aaaa-225		IN	AAAA	2001:db8::00e1
+aaaa-226		IN	AAAA	2001:db8::00e2
+aaaa-227		IN	AAAA	2001:db8::00e3
+aaaa-228		IN	AAAA	2001:db8::00e4
+aaaa-229		IN	AAAA	2001:db8::00e5
+aaaa-230		IN	AAAA	2001:db8::00e6
+aaaa-231		IN	AAAA	2001:db8::00e7
+aaaa-232		IN	AAAA	2001:db8::00e8
+aaaa-233		IN	AAAA	2001:db8::00e9
+aaaa-234		IN	AAAA	2001:db8::00ea
+aaaa-235		IN	AAAA	2001:db8::00eb
+aaaa-236		IN	AAAA	2001:db8::00ec
+aaaa-237		IN	AAAA	2001:db8::00ed
+aaaa-238		IN	AAAA	2001:db8::00ee
+aaaa-239		IN	AAAA	2001:db8::00ef
+aaaa-240		IN	AAAA	2001:db8::00f0
+aaaa-241		IN	AAAA	2001:db8::00f1
+aaaa-242		IN	AAAA	2001:db8::00f2
+aaaa-243		IN	AAAA	2001:db8::00f3
+aaaa-244		IN	AAAA	2001:db8::00f4
+aaaa-245		IN	AAAA	2001:db8::00f5
+aaaa-246		IN	AAAA	2001:db8::00f6
+aaaa-247		IN	AAAA	2001:db8::00f7
+aaaa-248		IN	AAAA	2001:db8::00f8
+aaaa-249		IN	AAAA	2001:db8::00f9
+aaaa-250		IN	AAAA	2001:db8::00fa
+aaaa-251		IN	AAAA	2001:db8::00fb
+aaaa-252		IN	AAAA	2001:db8::00fc
+aaaa-253		IN	AAAA	2001:db8::00fd
+aaaa-254		IN	AAAA	2001:db8::00fe
+aaaa-255		IN	AAAA	2001:db8::00ff
+aaaa-256		IN	AAAA	2001:db8::0100
+aaaa-257		IN	AAAA	2001:db8::0101
+aaaa-258		IN	AAAA	2001:db8::0102
+aaaa-259		IN	AAAA	2001:db8::0103
+aaaa-260		IN	AAAA	2001:db8::0104
+aaaa-261		IN	AAAA	2001:db8::0105
+aaaa-262		IN	AAAA	2001:db8::0106
+aaaa-263		IN	AAAA	2001:db8::0107
+aaaa-264		IN	AAAA	2001:db8::0108
+aaaa-265		IN	AAAA	2001:db8::0109
+aaaa-266		IN	AAAA	2001:db8::010a
+aaaa-267		IN	AAAA	2001:db8::010b
+aaaa-268		IN	AAAA	2001:db8::010c
+aaaa-269		IN	AAAA	2001:db8::010d
+aaaa-270		IN	AAAA	2001:db8::010e
+aaaa-271		IN	AAAA	2001:db8::010f
+aaaa-272		IN	AAAA	2001:db8::0110
+aaaa-273		IN	AAAA	2001:db8::0111
+aaaa-274		IN	AAAA	2001:db8::0112
+aaaa-275		IN	AAAA	2001:db8::0113
+aaaa-276		IN	AAAA	2001:db8::0114
+aaaa-277		IN	AAAA	2001:db8::0115
+aaaa-278		IN	AAAA	2001:db8::0116
+aaaa-279		IN	AAAA	2001:db8::0117
+aaaa-280		IN	AAAA	2001:db8::0118
+aaaa-281		IN	AAAA	2001:db8::0119
+aaaa-282		IN	AAAA	2001:db8::011a
+aaaa-283		IN	AAAA	2001:db8::011b
+aaaa-284		IN	AAAA	2001:db8::011c
+aaaa-285		IN	AAAA	2001:db8::011d
+aaaa-286		IN	AAAA	2001:db8::011e
+aaaa-287		IN	AAAA	2001:db8::011f
+aaaa-288		IN	AAAA	2001:db8::0120
+aaaa-289		IN	AAAA	2001:db8::0121
+aaaa-290		IN	AAAA	2001:db8::0122
+aaaa-291		IN	AAAA	2001:db8::0123
+aaaa-292		IN	AAAA	2001:db8::0124
+aaaa-293		IN	AAAA	2001:db8::0125
+aaaa-294		IN	AAAA	2001:db8::0126
+aaaa-295		IN	AAAA	2001:db8::0127
+aaaa-296		IN	AAAA	2001:db8::0128
+aaaa-297		IN	AAAA	2001:db8::0129
+aaaa-298		IN	AAAA	2001:db8::012a
+aaaa-299		IN	AAAA	2001:db8::012b
+aaaa-300		IN	AAAA	2001:db8::012c
+aaaa-301		IN	AAAA	2001:db8::012d
+aaaa-302		IN	AAAA	2001:db8::012e
+aaaa-303		IN	AAAA	2001:db8::012f
+aaaa-304		IN	AAAA	2001:db8::0130
+aaaa-305		IN	AAAA	2001:db8::0131
+aaaa-306		IN	AAAA	2001:db8::0132
+aaaa-307		IN	AAAA	2001:db8::0133
+aaaa-308		IN	AAAA	2001:db8::0134
+aaaa-309		IN	AAAA	2001:db8::0135
+aaaa-310		IN	AAAA	2001:db8::0136
+aaaa-311		IN	AAAA	2001:db8::0137
+aaaa-312		IN	AAAA	2001:db8::0138
+aaaa-313		IN	AAAA	2001:db8::0139
+aaaa-314		IN	AAAA	2001:db8::013a
+aaaa-315		IN	AAAA	2001:db8::013b
+aaaa-316		IN	AAAA	2001:db8::013c
+aaaa-317		IN	AAAA	2001:db8::013d
+aaaa-318		IN	AAAA	2001:db8::013e
+aaaa-319		IN	AAAA	2001:db8::013f
+aaaa-320		IN	AAAA	2001:db8::0140
+aaaa-321		IN	AAAA	2001:db8::0141
+aaaa-322		IN	AAAA	2001:db8::0142
+aaaa-323		IN	AAAA	2001:db8::0143
+aaaa-324		IN	AAAA	2001:db8::0144
+aaaa-325		IN	AAAA	2001:db8::0145
+aaaa-326		IN	AAAA	2001:db8::0146
+aaaa-327		IN	AAAA	2001:db8::0147
+aaaa-328		IN	AAAA	2001:db8::0148
+aaaa-329		IN	AAAA	2001:db8::0149
+aaaa-330		IN	AAAA	2001:db8::014a
+aaaa-331		IN	AAAA	2001:db8::014b
+aaaa-332		IN	AAAA	2001:db8::014c
+aaaa-333		IN	AAAA	2001:db8::014d
+aaaa-334		IN	AAAA	2001:db8::014e
+aaaa-335		IN	AAAA	2001:db8::014f
+aaaa-336		IN	AAAA	2001:db8::0150
+aaaa-337		IN	AAAA	2001:db8::0151
+aaaa-338		IN	AAAA	2001:db8::0152
+aaaa-339		IN	AAAA	2001:db8::0153
+aaaa-340		IN	AAAA	2001:db8::0154
+aaaa-341		IN	AAAA	2001:db8::0155
+aaaa-342		IN	AAAA	2001:db8::0156
+aaaa-343		IN	AAAA	2001:db8::0157
+aaaa-344		IN	AAAA	2001:db8::0158
+aaaa-345		IN	AAAA	2001:db8::0159
+aaaa-346		IN	AAAA	2001:db8::015a
+aaaa-347		IN	AAAA	2001:db8::015b
+aaaa-348		IN	AAAA	2001:db8::015c
+aaaa-349		IN	AAAA	2001:db8::015d
+aaaa-350		IN	AAAA	2001:db8::015e
+aaaa-351		IN	AAAA	2001:db8::015f
+aaaa-352		IN	AAAA	2001:db8::0160
+aaaa-353		IN	AAAA	2001:db8::0161
+aaaa-354		IN	AAAA	2001:db8::0162
+aaaa-355		IN	AAAA	2001:db8::0163
+aaaa-356		IN	AAAA	2001:db8::0164
+aaaa-357		IN	AAAA	2001:db8::0165
+aaaa-358		IN	AAAA	2001:db8::0166
+aaaa-359		IN	AAAA	2001:db8::0167
+aaaa-360		IN	AAAA	2001:db8::0168
+aaaa-361		IN	AAAA	2001:db8::0169
+aaaa-362		IN	AAAA	2001:db8::016a
+aaaa-363		IN	AAAA	2001:db8::016b
+aaaa-364		IN	AAAA	2001:db8::016c
+aaaa-365		IN	AAAA	2001:db8::016d
+aaaa-366		IN	AAAA	2001:db8::016e
+aaaa-367		IN	AAAA	2001:db8::016f
+aaaa-368		IN	AAAA	2001:db8::0170
+aaaa-369		IN	AAAA	2001:db8::0171
+aaaa-370		IN	AAAA	2001:db8::0172
+aaaa-371		IN	AAAA	2001:db8::0173
+aaaa-372		IN	AAAA	2001:db8::0174
+aaaa-373		IN	AAAA	2001:db8::0175
+aaaa-374		IN	AAAA	2001:db8::0176
+aaaa-375		IN	AAAA	2001:db8::0177
+aaaa-376		IN	AAAA	2001:db8::0178
+aaaa-377		IN	AAAA	2001:db8::0179
+aaaa-378		IN	AAAA	2001:db8::017a
+aaaa-379		IN	AAAA	2001:db8::017b
+aaaa-380		IN	AAAA	2001:db8::017c
+aaaa-381		IN	AAAA	2001:db8::017d
+aaaa-382		IN	AAAA	2001:db8::017e
+aaaa-383		IN	AAAA	2001:db8::017f
+aaaa-384		IN	AAAA	2001:db8::0180
+aaaa-385		IN	AAAA	2001:db8::0181
+aaaa-386		IN	AAAA	2001:db8::0182
+aaaa-387		IN	AAAA	2001:db8::0183
+aaaa-388		IN	AAAA	2001:db8::0184
+aaaa-389		IN	AAAA	2001:db8::0185
+aaaa-390		IN	AAAA	2001:db8::0186
+aaaa-391		IN	AAAA	2001:db8::0187
+aaaa-392		IN	AAAA	2001:db8::0188
+aaaa-393		IN	AAAA	2001:db8::0189
+aaaa-394		IN	AAAA	2001:db8::018a
+aaaa-395		IN	AAAA	2001:db8::018b
+aaaa-396		IN	AAAA	2001:db8::018c
+aaaa-397		IN	AAAA	2001:db8::018d
+aaaa-398		IN	AAAA	2001:db8::018e
+aaaa-399		IN	AAAA	2001:db8::018f
+aaaa-400		IN	AAAA	2001:db8::0190
+aaaa-401		IN	AAAA	2001:db8::0191
+aaaa-402		IN	AAAA	2001:db8::0192
+aaaa-403		IN	AAAA	2001:db8::0193
+aaaa-404		IN	AAAA	2001:db8::0194
+aaaa-405		IN	AAAA	2001:db8::0195
+aaaa-406		IN	AAAA	2001:db8::0196
+aaaa-407		IN	AAAA	2001:db8::0197
+aaaa-408		IN	AAAA	2001:db8::0198
+aaaa-409		IN	AAAA	2001:db8::0199
+aaaa-410		IN	AAAA	2001:db8::019a
+aaaa-411		IN	AAAA	2001:db8::019b
+aaaa-412		IN	AAAA	2001:db8::019c
+aaaa-413		IN	AAAA	2001:db8::019d
+aaaa-414		IN	AAAA	2001:db8::019e
+aaaa-415		IN	AAAA	2001:db8::019f
+aaaa-416		IN	AAAA	2001:db8::01a0
+aaaa-417		IN	AAAA	2001:db8::01a1
+aaaa-418		IN	AAAA	2001:db8::01a2
+aaaa-419		IN	AAAA	2001:db8::01a3
+aaaa-420		IN	AAAA	2001:db8::01a4
+aaaa-421		IN	AAAA	2001:db8::01a5
+aaaa-422		IN	AAAA	2001:db8::01a6
+aaaa-423		IN	AAAA	2001:db8::01a7
+aaaa-424		IN	AAAA	2001:db8::01a8
+aaaa-425		IN	AAAA	2001:db8::01a9
+aaaa-426		IN	AAAA	2001:db8::01aa
+aaaa-427		IN	AAAA	2001:db8::01ab
+aaaa-428		IN	AAAA	2001:db8::01ac
+aaaa-429		IN	AAAA	2001:db8::01ad
+aaaa-430		IN	AAAA	2001:db8::01ae
+aaaa-431		IN	AAAA	2001:db8::01af
+aaaa-432		IN	AAAA	2001:db8::01b0
+aaaa-433		IN	AAAA	2001:db8::01b1
+aaaa-434		IN	AAAA	2001:db8::01b2
+aaaa-435		IN	AAAA	2001:db8::01b3
+aaaa-436		IN	AAAA	2001:db8::01b4
+aaaa-437		IN	AAAA	2001:db8::01b5
+aaaa-438		IN	AAAA	2001:db8::01b6
+aaaa-439		IN	AAAA	2001:db8::01b7
+aaaa-440		IN	AAAA	2001:db8::01b8
+aaaa-441		IN	AAAA	2001:db8::01b9
+aaaa-442		IN	AAAA	2001:db8::01ba
+aaaa-443		IN	AAAA	2001:db8::01bb
+aaaa-444		IN	AAAA	2001:db8::01bc
+aaaa-445		IN	AAAA	2001:db8::01bd
+aaaa-446		IN	AAAA	2001:db8::01be
+aaaa-447		IN	AAAA	2001:db8::01bf
+aaaa-448		IN	AAAA	2001:db8::01c0
+aaaa-449		IN	AAAA	2001:db8::01c1
+aaaa-450		IN	AAAA	2001:db8::01c2
+aaaa-451		IN	AAAA	2001:db8::01c3
+aaaa-452		IN	AAAA	2001:db8::01c4
+aaaa-453		IN	AAAA	2001:db8::01c5
+aaaa-454		IN	AAAA	2001:db8::01c6
+aaaa-455		IN	AAAA	2001:db8::01c7
+aaaa-456		IN	AAAA	2001:db8::01c8
+aaaa-457		IN	AAAA	2001:db8::01c9
+aaaa-458		IN	AAAA	2001:db8::01ca
+aaaa-459		IN	AAAA	2001:db8::01cb
+aaaa-460		IN	AAAA	2001:db8::01cc
+aaaa-461		IN	AAAA	2001:db8::01cd
+aaaa-462		IN	AAAA	2001:db8::01ce
+aaaa-463		IN	AAAA	2001:db8::01cf
+aaaa-464		IN	AAAA	2001:db8::01d0
+aaaa-465		IN	AAAA	2001:db8::01d1
+aaaa-466		IN	AAAA	2001:db8::01d2
+aaaa-467		IN	AAAA	2001:db8::01d3
+aaaa-468		IN	AAAA	2001:db8::01d4
+aaaa-469		IN	AAAA	2001:db8::01d5
+aaaa-470		IN	AAAA	2001:db8::01d6
+aaaa-471		IN	AAAA	2001:db8::01d7
+aaaa-472		IN	AAAA	2001:db8::01d8
+aaaa-473		IN	AAAA	2001:db8::01d9
+aaaa-474		IN	AAAA	2001:db8::01da
+aaaa-475		IN	AAAA	2001:db8::01db
+aaaa-476		IN	AAAA	2001:db8::01dc
+aaaa-477		IN	AAAA	2001:db8::01dd
+aaaa-478		IN	AAAA	2001:db8::01de
+aaaa-479		IN	AAAA	2001:db8::01df
+aaaa-480		IN	AAAA	2001:db8::01e0
+aaaa-481		IN	AAAA	2001:db8::01e1
+aaaa-482		IN	AAAA	2001:db8::01e2
+aaaa-483		IN	AAAA	2001:db8::01e3
+aaaa-484		IN	AAAA	2001:db8::01e4
+aaaa-485		IN	AAAA	2001:db8::01e5
+aaaa-486		IN	AAAA	2001:db8::01e6
+aaaa-487		IN	AAAA	2001:db8::01e7
+aaaa-488		IN	AAAA	2001:db8::01e8
+aaaa-489		IN	AAAA	2001:db8::01e9
+aaaa-490		IN	AAAA	2001:db8::01ea
+aaaa-491		IN	AAAA	2001:db8::01eb
+aaaa-492		IN	AAAA	2001:db8::01ec
+aaaa-493		IN	AAAA	2001:db8::01ed
+aaaa-494		IN	AAAA	2001:db8::01ee
+aaaa-495		IN	AAAA	2001:db8::01ef
+aaaa-496		IN	AAAA	2001:db8::01f0
+aaaa-497		IN	AAAA	2001:db8::01f1
+aaaa-498		IN	AAAA	2001:db8::01f2
+aaaa-499		IN	AAAA	2001:db8::01f3
+aaaa-500		IN	AAAA	2001:db8::01f4
+aaaa-501		IN	AAAA	2001:db8::01f5
+aaaa-502		IN	AAAA	2001:db8::01f6
+aaaa-503		IN	AAAA	2001:db8::01f7
+aaaa-504		IN	AAAA	2001:db8::01f8
+aaaa-505		IN	AAAA	2001:db8::01f9
+aaaa-506		IN	AAAA	2001:db8::01fa
+aaaa-507		IN	AAAA	2001:db8::01fb
+aaaa-508		IN	AAAA	2001:db8::01fc
+aaaa-509		IN	AAAA	2001:db8::01fd
+aaaa-510		IN	AAAA	2001:db8::01fe
+aaaa-511		IN	AAAA	2001:db8::01ff
+
+bbbb-000		IN	AAAA	2001:db8::1:0000
+bbbb-001		IN	AAAA	2001:db8::1:0001
+bbbb-002		IN	AAAA	2001:db8::1:0002
+bbbb-003		IN	AAAA	2001:db8::1:0003
+bbbb-004		IN	AAAA	2001:db8::1:0004
+bbbb-005		IN	AAAA	2001:db8::1:0005
+bbbb-006		IN	AAAA	2001:db8::1:0006
+bbbb-007		IN	AAAA	2001:db8::1:0007
+bbbb-008		IN	AAAA	2001:db8::1:0008
+bbbb-009		IN	AAAA	2001:db8::1:0009
+bbbb-010		IN	AAAA	2001:db8::1:000a
+bbbb-011		IN	AAAA	2001:db8::1:000b
+bbbb-012		IN	AAAA	2001:db8::1:000c
+bbbb-013		IN	AAAA	2001:db8::1:000d
+bbbb-014		IN	AAAA	2001:db8::1:000e
+bbbb-015		IN	AAAA	2001:db8::1:000f
+bbbb-016		IN	AAAA	2001:db8::1:0010
+bbbb-017		IN	AAAA	2001:db8::1:0011
+bbbb-018		IN	AAAA	2001:db8::1:0012
+bbbb-019		IN	AAAA	2001:db8::1:0013
+bbbb-020		IN	AAAA	2001:db8::1:0014
+bbbb-021		IN	AAAA	2001:db8::1:0015
+bbbb-022		IN	AAAA	2001:db8::1:0016
+bbbb-023		IN	AAAA	2001:db8::1:0017
+bbbb-024		IN	AAAA	2001:db8::1:0018
+bbbb-025		IN	AAAA	2001:db8::1:0019
+bbbb-026		IN	AAAA	2001:db8::1:001a
+bbbb-027		IN	AAAA	2001:db8::1:001b
+bbbb-028		IN	AAAA	2001:db8::1:001c
+bbbb-029		IN	AAAA	2001:db8::1:001d
+bbbb-030		IN	AAAA	2001:db8::1:001e
+bbbb-031		IN	AAAA	2001:db8::1:001f
+bbbb-032		IN	AAAA	2001:db8::1:0020
+bbbb-033		IN	AAAA	2001:db8::1:0021
+bbbb-034		IN	AAAA	2001:db8::1:0022
+bbbb-035		IN	AAAA	2001:db8::1:0023
+bbbb-036		IN	AAAA	2001:db8::1:0024
+bbbb-037		IN	AAAA	2001:db8::1:0025
+bbbb-038		IN	AAAA	2001:db8::1:0026
+bbbb-039		IN	AAAA	2001:db8::1:0027
+bbbb-040		IN	AAAA	2001:db8::1:0028
+bbbb-041		IN	AAAA	2001:db8::1:0029
+bbbb-042		IN	AAAA	2001:db8::1:002a
+bbbb-043		IN	AAAA	2001:db8::1:002b
+bbbb-044		IN	AAAA	2001:db8::1:002c
+bbbb-045		IN	AAAA	2001:db8::1:002d
+bbbb-046		IN	AAAA	2001:db8::1:002e
+bbbb-047		IN	AAAA	2001:db8::1:002f
+bbbb-048		IN	AAAA	2001:db8::1:0030
+bbbb-049		IN	AAAA	2001:db8::1:0031
+bbbb-050		IN	AAAA	2001:db8::1:0032
+bbbb-051		IN	AAAA	2001:db8::1:0033
+bbbb-052		IN	AAAA	2001:db8::1:0034
+bbbb-053		IN	AAAA	2001:db8::1:0035
+bbbb-054		IN	AAAA	2001:db8::1:0036
+bbbb-055		IN	AAAA	2001:db8::1:0037
+bbbb-056		IN	AAAA	2001:db8::1:0038
+bbbb-057		IN	AAAA	2001:db8::1:0039
+bbbb-058		IN	AAAA	2001:db8::1:003a
+bbbb-059		IN	AAAA	2001:db8::1:003b
+bbbb-060		IN	AAAA	2001:db8::1:003c
+bbbb-061		IN	AAAA	2001:db8::1:003d
+bbbb-062		IN	AAAA	2001:db8::1:003e
+bbbb-063		IN	AAAA	2001:db8::1:003f
+bbbb-064		IN	AAAA	2001:db8::1:0040
+bbbb-065		IN	AAAA	2001:db8::1:0041
+bbbb-066		IN	AAAA	2001:db8::1:0042
+bbbb-067		IN	AAAA	2001:db8::1:0043
+bbbb-068		IN	AAAA	2001:db8::1:0044
+bbbb-069		IN	AAAA	2001:db8::1:0045
+bbbb-070		IN	AAAA	2001:db8::1:0046
+bbbb-071		IN	AAAA	2001:db8::1:0047
+bbbb-072		IN	AAAA	2001:db8::1:0048
+bbbb-073		IN	AAAA	2001:db8::1:0049
+bbbb-074		IN	AAAA	2001:db8::1:004a
+bbbb-075		IN	AAAA	2001:db8::1:004b
+bbbb-076		IN	AAAA	2001:db8::1:004c
+bbbb-077		IN	AAAA	2001:db8::1:004d
+bbbb-078		IN	AAAA	2001:db8::1:004e
+bbbb-079		IN	AAAA	2001:db8::1:004f
+bbbb-080		IN	AAAA	2001:db8::1:0050
+bbbb-081		IN	AAAA	2001:db8::1:0051
+bbbb-082		IN	AAAA	2001:db8::1:0052
+bbbb-083		IN	AAAA	2001:db8::1:0053
+bbbb-084		IN	AAAA	2001:db8::1:0054
+bbbb-085		IN	AAAA	2001:db8::1:0055
+bbbb-086		IN	AAAA	2001:db8::1:0056
+bbbb-087		IN	AAAA	2001:db8::1:0057
+bbbb-088		IN	AAAA	2001:db8::1:0058
+bbbb-089		IN	AAAA	2001:db8::1:0059
+bbbb-090		IN	AAAA	2001:db8::1:005a
+bbbb-091		IN	AAAA	2001:db8::1:005b
+bbbb-092		IN	AAAA	2001:db8::1:005c
+bbbb-093		IN	AAAA	2001:db8::1:005d
+bbbb-094		IN	AAAA	2001:db8::1:005e
+bbbb-095		IN	AAAA	2001:db8::1:005f
+bbbb-096		IN	AAAA	2001:db8::1:0060
+bbbb-097		IN	AAAA	2001:db8::1:0061
+bbbb-098		IN	AAAA	2001:db8::1:0062
+bbbb-099		IN	AAAA	2001:db8::1:0063
+bbbb-100		IN	AAAA	2001:db8::1:0064
+bbbb-101		IN	AAAA	2001:db8::1:0065
+bbbb-102		IN	AAAA	2001:db8::1:0066
+bbbb-103		IN	AAAA	2001:db8::1:0067
+bbbb-104		IN	AAAA	2001:db8::1:0068
+bbbb-105		IN	AAAA	2001:db8::1:0069
+bbbb-106		IN	AAAA	2001:db8::1:006a
+bbbb-107		IN	AAAA	2001:db8::1:006b
+bbbb-108		IN	AAAA	2001:db8::1:006c
+bbbb-109		IN	AAAA	2001:db8::1:006d
+bbbb-110		IN	AAAA	2001:db8::1:006e
+bbbb-111		IN	AAAA	2001:db8::1:006f
+bbbb-112		IN	AAAA	2001:db8::1:0070
+bbbb-113		IN	AAAA	2001:db8::1:0071
+bbbb-114		IN	AAAA	2001:db8::1:0072
+bbbb-115		IN	AAAA	2001:db8::1:0073
+bbbb-116		IN	AAAA	2001:db8::1:0074
+bbbb-117		IN	AAAA	2001:db8::1:0075
+bbbb-118		IN	AAAA	2001:db8::1:0076
+bbbb-119		IN	AAAA	2001:db8::1:0077
+bbbb-120		IN	AAAA	2001:db8::1:0078
+bbbb-121		IN	AAAA	2001:db8::1:0079
+bbbb-122		IN	AAAA	2001:db8::1:007a
+bbbb-123		IN	AAAA	2001:db8::1:007b
+bbbb-124		IN	AAAA	2001:db8::1:007c
+bbbb-125		IN	AAAA	2001:db8::1:007d
+bbbb-126		IN	AAAA	2001:db8::1:007e
+bbbb-127		IN	AAAA	2001:db8::1:007f
+bbbb-128		IN	AAAA	2001:db8::1:0080
+bbbb-129		IN	AAAA	2001:db8::1:0081
+bbbb-130		IN	AAAA	2001:db8::1:0082
+bbbb-131		IN	AAAA	2001:db8::1:0083
+bbbb-132		IN	AAAA	2001:db8::1:0084
+bbbb-133		IN	AAAA	2001:db8::1:0085
+bbbb-134		IN	AAAA	2001:db8::1:0086
+bbbb-135		IN	AAAA	2001:db8::1:0087
+bbbb-136		IN	AAAA	2001:db8::1:0088
+bbbb-137		IN	AAAA	2001:db8::1:0089
+bbbb-138		IN	AAAA	2001:db8::1:008a
+bbbb-139		IN	AAAA	2001:db8::1:008b
+bbbb-140		IN	AAAA	2001:db8::1:008c
+bbbb-141		IN	AAAA	2001:db8::1:008d
+bbbb-142		IN	AAAA	2001:db8::1:008e
+bbbb-143		IN	AAAA	2001:db8::1:008f
+bbbb-144		IN	AAAA	2001:db8::1:0090
+bbbb-145		IN	AAAA	2001:db8::1:0091
+bbbb-146		IN	AAAA	2001:db8::1:0092
+bbbb-147		IN	AAAA	2001:db8::1:0093
+bbbb-148		IN	AAAA	2001:db8::1:0094
+bbbb-149		IN	AAAA	2001:db8::1:0095
+bbbb-150		IN	AAAA	2001:db8::1:0096
+bbbb-151		IN	AAAA	2001:db8::1:0097
+bbbb-152		IN	AAAA	2001:db8::1:0098
+bbbb-153		IN	AAAA	2001:db8::1:0099
+bbbb-154		IN	AAAA	2001:db8::1:009a
+bbbb-155		IN	AAAA	2001:db8::1:009b
+bbbb-156		IN	AAAA	2001:db8::1:009c
+bbbb-157		IN	AAAA	2001:db8::1:009d
+bbbb-158		IN	AAAA	2001:db8::1:009e
+bbbb-159		IN	AAAA	2001:db8::1:009f
+bbbb-160		IN	AAAA	2001:db8::1:00a0
+bbbb-161		IN	AAAA	2001:db8::1:00a1
+bbbb-162		IN	AAAA	2001:db8::1:00a2
+bbbb-163		IN	AAAA	2001:db8::1:00a3
+bbbb-164		IN	AAAA	2001:db8::1:00a4
+bbbb-165		IN	AAAA	2001:db8::1:00a5
+bbbb-166		IN	AAAA	2001:db8::1:00a6
+bbbb-167		IN	AAAA	2001:db8::1:00a7
+bbbb-168		IN	AAAA	2001:db8::1:00a8
+bbbb-169		IN	AAAA	2001:db8::1:00a9
+bbbb-170		IN	AAAA	2001:db8::1:00aa
+bbbb-171		IN	AAAA	2001:db8::1:00ab
+bbbb-172		IN	AAAA	2001:db8::1:00ac
+bbbb-173		IN	AAAA	2001:db8::1:00ad
+bbbb-174		IN	AAAA	2001:db8::1:00ae
+bbbb-175		IN	AAAA	2001:db8::1:00af
+bbbb-176		IN	AAAA	2001:db8::1:00b0
+bbbb-177		IN	AAAA	2001:db8::1:00b1
+bbbb-178		IN	AAAA	2001:db8::1:00b2
+bbbb-179		IN	AAAA	2001:db8::1:00b3
+bbbb-180		IN	AAAA	2001:db8::1:00b4
+bbbb-181		IN	AAAA	2001:db8::1:00b5
+bbbb-182		IN	AAAA	2001:db8::1:00b6
+bbbb-183		IN	AAAA	2001:db8::1:00b7
+bbbb-184		IN	AAAA	2001:db8::1:00b8
+bbbb-185		IN	AAAA	2001:db8::1:00b9
+bbbb-186		IN	AAAA	2001:db8::1:00ba
+bbbb-187		IN	AAAA	2001:db8::1:00bb
+bbbb-188		IN	AAAA	2001:db8::1:00bc
+bbbb-189		IN	AAAA	2001:db8::1:00bd
+bbbb-190		IN	AAAA	2001:db8::1:00be
+bbbb-191		IN	AAAA	2001:db8::1:00bf
+bbbb-192		IN	AAAA	2001:db8::1:00c0
+bbbb-193		IN	AAAA	2001:db8::1:00c1
+bbbb-194		IN	AAAA	2001:db8::1:00c2
+bbbb-195		IN	AAAA	2001:db8::1:00c3
+bbbb-196		IN	AAAA	2001:db8::1:00c4
+bbbb-197		IN	AAAA	2001:db8::1:00c5
+bbbb-198		IN	AAAA	2001:db8::1:00c6
+bbbb-199		IN	AAAA	2001:db8::1:00c7
+bbbb-200		IN	AAAA	2001:db8::1:00c8
+bbbb-201		IN	AAAA	2001:db8::1:00c9
+bbbb-202		IN	AAAA	2001:db8::1:00ca
+bbbb-203		IN	AAAA	2001:db8::1:00cb
+bbbb-204		IN	AAAA	2001:db8::1:00cc
+bbbb-205		IN	AAAA	2001:db8::1:00cd
+bbbb-206		IN	AAAA	2001:db8::1:00ce
+bbbb-207		IN	AAAA	2001:db8::1:00cf
+bbbb-208		IN	AAAA	2001:db8::1:00d0
+bbbb-209		IN	AAAA	2001:db8::1:00d1
+bbbb-210		IN	AAAA	2001:db8::1:00d2
+bbbb-211		IN	AAAA	2001:db8::1:00d3
+bbbb-212		IN	AAAA	2001:db8::1:00d4
+bbbb-213		IN	AAAA	2001:db8::1:00d5
+bbbb-214		IN	AAAA	2001:db8::1:00d6
+bbbb-215		IN	AAAA	2001:db8::1:00d7
+bbbb-216		IN	AAAA	2001:db8::1:00d8
+bbbb-217		IN	AAAA	2001:db8::1:00d9
+bbbb-218		IN	AAAA	2001:db8::1:00da
+bbbb-219		IN	AAAA	2001:db8::1:00db
+bbbb-220		IN	AAAA	2001:db8::1:00dc
+bbbb-221		IN	AAAA	2001:db8::1:00dd
+bbbb-222		IN	AAAA	2001:db8::1:00de
+bbbb-223		IN	AAAA	2001:db8::1:00df
+bbbb-224		IN	AAAA	2001:db8::1:00e0
+bbbb-225		IN	AAAA	2001:db8::1:00e1
+bbbb-226		IN	AAAA	2001:db8::1:00e2
+bbbb-227		IN	AAAA	2001:db8::1:00e3
+bbbb-228		IN	AAAA	2001:db8::1:00e4
+bbbb-229		IN	AAAA	2001:db8::1:00e5
+bbbb-230		IN	AAAA	2001:db8::1:00e6
+bbbb-231		IN	AAAA	2001:db8::1:00e7
+bbbb-232		IN	AAAA	2001:db8::1:00e8
+bbbb-233		IN	AAAA	2001:db8::1:00e9
+bbbb-234		IN	AAAA	2001:db8::1:00ea
+bbbb-235		IN	AAAA	2001:db8::1:00eb
+bbbb-236		IN	AAAA	2001:db8::1:00ec
+bbbb-237		IN	AAAA	2001:db8::1:00ed
+bbbb-238		IN	AAAA	2001:db8::1:00ee
+bbbb-239		IN	AAAA	2001:db8::1:00ef
+bbbb-240		IN	AAAA	2001:db8::1:00f0
+bbbb-241		IN	AAAA	2001:db8::1:00f1
+bbbb-242		IN	AAAA	2001:db8::1:00f2
+bbbb-243		IN	AAAA	2001:db8::1:00f3
+bbbb-244		IN	AAAA	2001:db8::1:00f4
+bbbb-245		IN	AAAA	2001:db8::1:00f5
+bbbb-246		IN	AAAA	2001:db8::1:00f6
+bbbb-247		IN	AAAA	2001:db8::1:00f7
+bbbb-248		IN	AAAA	2001:db8::1:00f8
+bbbb-249		IN	AAAA	2001:db8::1:00f9
+bbbb-250		IN	AAAA	2001:db8::1:00fa
+bbbb-251		IN	AAAA	2001:db8::1:00fb
+bbbb-252		IN	AAAA	2001:db8::1:00fc
+bbbb-253		IN	AAAA	2001:db8::1:00fd
+bbbb-254		IN	AAAA	2001:db8::1:00fe
+bbbb-255		IN	AAAA	2001:db8::1:00ff
+bbbb-256		IN	AAAA	2001:db8::1:0100
+bbbb-257		IN	AAAA	2001:db8::1:0101
+bbbb-258		IN	AAAA	2001:db8::1:0102
+bbbb-259		IN	AAAA	2001:db8::1:0103
+bbbb-260		IN	AAAA	2001:db8::1:0104
+bbbb-261		IN	AAAA	2001:db8::1:0105
+bbbb-262		IN	AAAA	2001:db8::1:0106
+bbbb-263		IN	AAAA	2001:db8::1:0107
+bbbb-264		IN	AAAA	2001:db8::1:0108
+bbbb-265		IN	AAAA	2001:db8::1:0109
+bbbb-266		IN	AAAA	2001:db8::1:010a
+bbbb-267		IN	AAAA	2001:db8::1:010b
+bbbb-268		IN	AAAA	2001:db8::1:010c
+bbbb-269		IN	AAAA	2001:db8::1:010d
+bbbb-270		IN	AAAA	2001:db8::1:010e
+bbbb-271		IN	AAAA	2001:db8::1:010f
+bbbb-272		IN	AAAA	2001:db8::1:0110
+bbbb-273		IN	AAAA	2001:db8::1:0111
+bbbb-274		IN	AAAA	2001:db8::1:0112
+bbbb-275		IN	AAAA	2001:db8::1:0113
+bbbb-276		IN	AAAA	2001:db8::1:0114
+bbbb-277		IN	AAAA	2001:db8::1:0115
+bbbb-278		IN	AAAA	2001:db8::1:0116
+bbbb-279		IN	AAAA	2001:db8::1:0117
+bbbb-280		IN	AAAA	2001:db8::1:0118
+bbbb-281		IN	AAAA	2001:db8::1:0119
+bbbb-282		IN	AAAA	2001:db8::1:011a
+bbbb-283		IN	AAAA	2001:db8::1:011b
+bbbb-284		IN	AAAA	2001:db8::1:011c
+bbbb-285		IN	AAAA	2001:db8::1:011d
+bbbb-286		IN	AAAA	2001:db8::1:011e
+bbbb-287		IN	AAAA	2001:db8::1:011f
+bbbb-288		IN	AAAA	2001:db8::1:0120
+bbbb-289		IN	AAAA	2001:db8::1:0121
+bbbb-290		IN	AAAA	2001:db8::1:0122
+bbbb-291		IN	AAAA	2001:db8::1:0123
+bbbb-292		IN	AAAA	2001:db8::1:0124
+bbbb-293		IN	AAAA	2001:db8::1:0125
+bbbb-294		IN	AAAA	2001:db8::1:0126
+bbbb-295		IN	AAAA	2001:db8::1:0127
+bbbb-296		IN	AAAA	2001:db8::1:0128
+bbbb-297		IN	AAAA	2001:db8::1:0129
+bbbb-298		IN	AAAA	2001:db8::1:012a
+bbbb-299		IN	AAAA	2001:db8::1:012b
+bbbb-300		IN	AAAA	2001:db8::1:012c
+bbbb-301		IN	AAAA	2001:db8::1:012d
+bbbb-302		IN	AAAA	2001:db8::1:012e
+bbbb-303		IN	AAAA	2001:db8::1:012f
+bbbb-304		IN	AAAA	2001:db8::1:0130
+bbbb-305		IN	AAAA	2001:db8::1:0131
+bbbb-306		IN	AAAA	2001:db8::1:0132
+bbbb-307		IN	AAAA	2001:db8::1:0133
+bbbb-308		IN	AAAA	2001:db8::1:0134
+bbbb-309		IN	AAAA	2001:db8::1:0135
+bbbb-310		IN	AAAA	2001:db8::1:0136
+bbbb-311		IN	AAAA	2001:db8::1:0137
+bbbb-312		IN	AAAA	2001:db8::1:0138
+bbbb-313		IN	AAAA	2001:db8::1:0139
+bbbb-314		IN	AAAA	2001:db8::1:013a
+bbbb-315		IN	AAAA	2001:db8::1:013b
+bbbb-316		IN	AAAA	2001:db8::1:013c
+bbbb-317		IN	AAAA	2001:db8::1:013d
+bbbb-318		IN	AAAA	2001:db8::1:013e
+bbbb-319		IN	AAAA	2001:db8::1:013f
+bbbb-320		IN	AAAA	2001:db8::1:0140
+bbbb-321		IN	AAAA	2001:db8::1:0141
+bbbb-322		IN	AAAA	2001:db8::1:0142
+bbbb-323		IN	AAAA	2001:db8::1:0143
+bbbb-324		IN	AAAA	2001:db8::1:0144
+bbbb-325		IN	AAAA	2001:db8::1:0145
+bbbb-326		IN	AAAA	2001:db8::1:0146
+bbbb-327		IN	AAAA	2001:db8::1:0147
+bbbb-328		IN	AAAA	2001:db8::1:0148
+bbbb-329		IN	AAAA	2001:db8::1:0149
+bbbb-330		IN	AAAA	2001:db8::1:014a
+bbbb-331		IN	AAAA	2001:db8::1:014b
+bbbb-332		IN	AAAA	2001:db8::1:014c
+bbbb-333		IN	AAAA	2001:db8::1:014d
+bbbb-334		IN	AAAA	2001:db8::1:014e
+bbbb-335		IN	AAAA	2001:db8::1:014f
+bbbb-336		IN	AAAA	2001:db8::1:0150
+bbbb-337		IN	AAAA	2001:db8::1:0151
+bbbb-338		IN	AAAA	2001:db8::1:0152
+bbbb-339		IN	AAAA	2001:db8::1:0153
+bbbb-340		IN	AAAA	2001:db8::1:0154
+bbbb-341		IN	AAAA	2001:db8::1:0155
+bbbb-342		IN	AAAA	2001:db8::1:0156
+bbbb-343		IN	AAAA	2001:db8::1:0157
+bbbb-344		IN	AAAA	2001:db8::1:0158
+bbbb-345		IN	AAAA	2001:db8::1:0159
+bbbb-346		IN	AAAA	2001:db8::1:015a
+bbbb-347		IN	AAAA	2001:db8::1:015b
+bbbb-348		IN	AAAA	2001:db8::1:015c
+bbbb-349		IN	AAAA	2001:db8::1:015d
+bbbb-350		IN	AAAA	2001:db8::1:015e
+bbbb-351		IN	AAAA	2001:db8::1:015f
+bbbb-352		IN	AAAA	2001:db8::1:0160
+bbbb-353		IN	AAAA	2001:db8::1:0161
+bbbb-354		IN	AAAA	2001:db8::1:0162
+bbbb-355		IN	AAAA	2001:db8::1:0163
+bbbb-356		IN	AAAA	2001:db8::1:0164
+bbbb-357		IN	AAAA	2001:db8::1:0165
+bbbb-358		IN	AAAA	2001:db8::1:0166
+bbbb-359		IN	AAAA	2001:db8::1:0167
+bbbb-360		IN	AAAA	2001:db8::1:0168
+bbbb-361		IN	AAAA	2001:db8::1:0169
+bbbb-362		IN	AAAA	2001:db8::1:016a
+bbbb-363		IN	AAAA	2001:db8::1:016b
+bbbb-364		IN	AAAA	2001:db8::1:016c
+bbbb-365		IN	AAAA	2001:db8::1:016d
+bbbb-366		IN	AAAA	2001:db8::1:016e
+bbbb-367		IN	AAAA	2001:db8::1:016f
+bbbb-368		IN	AAAA	2001:db8::1:0170
+bbbb-369		IN	AAAA	2001:db8::1:0171
+bbbb-370		IN	AAAA	2001:db8::1:0172
+bbbb-371		IN	AAAA	2001:db8::1:0173
+bbbb-372		IN	AAAA	2001:db8::1:0174
+bbbb-373		IN	AAAA	2001:db8::1:0175
+bbbb-374		IN	AAAA	2001:db8::1:0176
+bbbb-375		IN	AAAA	2001:db8::1:0177
+bbbb-376		IN	AAAA	2001:db8::1:0178
+bbbb-377		IN	AAAA	2001:db8::1:0179
+bbbb-378		IN	AAAA	2001:db8::1:017a
+bbbb-379		IN	AAAA	2001:db8::1:017b
+bbbb-380		IN	AAAA	2001:db8::1:017c
+bbbb-381		IN	AAAA	2001:db8::1:017d
+bbbb-382		IN	AAAA	2001:db8::1:017e
+bbbb-383		IN	AAAA	2001:db8::1:017f
+bbbb-384		IN	AAAA	2001:db8::1:0180
+bbbb-385		IN	AAAA	2001:db8::1:0181
+bbbb-386		IN	AAAA	2001:db8::1:0182
+bbbb-387		IN	AAAA	2001:db8::1:0183
+bbbb-388		IN	AAAA	2001:db8::1:0184
+bbbb-389		IN	AAAA	2001:db8::1:0185
+bbbb-390		IN	AAAA	2001:db8::1:0186
+bbbb-391		IN	AAAA	2001:db8::1:0187
+bbbb-392		IN	AAAA	2001:db8::1:0188
+bbbb-393		IN	AAAA	2001:db8::1:0189
+bbbb-394		IN	AAAA	2001:db8::1:018a
+bbbb-395		IN	AAAA	2001:db8::1:018b
+bbbb-396		IN	AAAA	2001:db8::1:018c
+bbbb-397		IN	AAAA	2001:db8::1:018d
+bbbb-398		IN	AAAA	2001:db8::1:018e
+bbbb-399		IN	AAAA	2001:db8::1:018f
+bbbb-400		IN	AAAA	2001:db8::1:0190
+bbbb-401		IN	AAAA	2001:db8::1:0191
+bbbb-402		IN	AAAA	2001:db8::1:0192
+bbbb-403		IN	AAAA	2001:db8::1:0193
+bbbb-404		IN	AAAA	2001:db8::1:0194
+bbbb-405		IN	AAAA	2001:db8::1:0195
+bbbb-406		IN	AAAA	2001:db8::1:0196
+bbbb-407		IN	AAAA	2001:db8::1:0197
+bbbb-408		IN	AAAA	2001:db8::1:0198
+bbbb-409		IN	AAAA	2001:db8::1:0199
+bbbb-410		IN	AAAA	2001:db8::1:019a
+bbbb-411		IN	AAAA	2001:db8::1:019b
+bbbb-412		IN	AAAA	2001:db8::1:019c
+bbbb-413		IN	AAAA	2001:db8::1:019d
+bbbb-414		IN	AAAA	2001:db8::1:019e
+bbbb-415		IN	AAAA	2001:db8::1:019f
+bbbb-416		IN	AAAA	2001:db8::1:01a0
+bbbb-417		IN	AAAA	2001:db8::1:01a1
+bbbb-418		IN	AAAA	2001:db8::1:01a2
+bbbb-419		IN	AAAA	2001:db8::1:01a3
+bbbb-420		IN	AAAA	2001:db8::1:01a4
+bbbb-421		IN	AAAA	2001:db8::1:01a5
+bbbb-422		IN	AAAA	2001:db8::1:01a6
+bbbb-423		IN	AAAA	2001:db8::1:01a7
+bbbb-424		IN	AAAA	2001:db8::1:01a8
+bbbb-425		IN	AAAA	2001:db8::1:01a9
+bbbb-426		IN	AAAA	2001:db8::1:01aa
+bbbb-427		IN	AAAA	2001:db8::1:01ab
+bbbb-428		IN	AAAA	2001:db8::1:01ac
+bbbb-429		IN	AAAA	2001:db8::1:01ad
+bbbb-430		IN	AAAA	2001:db8::1:01ae
+bbbb-431		IN	AAAA	2001:db8::1:01af
+bbbb-432		IN	AAAA	2001:db8::1:01b0
+bbbb-433		IN	AAAA	2001:db8::1:01b1
+bbbb-434		IN	AAAA	2001:db8::1:01b2
+bbbb-435		IN	AAAA	2001:db8::1:01b3
+bbbb-436		IN	AAAA	2001:db8::1:01b4
+bbbb-437		IN	AAAA	2001:db8::1:01b5
+bbbb-438		IN	AAAA	2001:db8::1:01b6
+bbbb-439		IN	AAAA	2001:db8::1:01b7
+bbbb-440		IN	AAAA	2001:db8::1:01b8
+bbbb-441		IN	AAAA	2001:db8::1:01b9
+bbbb-442		IN	AAAA	2001:db8::1:01ba
+bbbb-443		IN	AAAA	2001:db8::1:01bb
+bbbb-444		IN	AAAA	2001:db8::1:01bc
+bbbb-445		IN	AAAA	2001:db8::1:01bd
+bbbb-446		IN	AAAA	2001:db8::1:01be
+bbbb-447		IN	AAAA	2001:db8::1:01bf
+bbbb-448		IN	AAAA	2001:db8::1:01c0
+bbbb-449		IN	AAAA	2001:db8::1:01c1
+bbbb-450		IN	AAAA	2001:db8::1:01c2
+bbbb-451		IN	AAAA	2001:db8::1:01c3
+bbbb-452		IN	AAAA	2001:db8::1:01c4
+bbbb-453		IN	AAAA	2001:db8::1:01c5
+bbbb-454		IN	AAAA	2001:db8::1:01c6
+bbbb-455		IN	AAAA	2001:db8::1:01c7
+bbbb-456		IN	AAAA	2001:db8::1:01c8
+bbbb-457		IN	AAAA	2001:db8::1:01c9
+bbbb-458		IN	AAAA	2001:db8::1:01ca
+bbbb-459		IN	AAAA	2001:db8::1:01cb
+bbbb-460		IN	AAAA	2001:db8::1:01cc
+bbbb-461		IN	AAAA	2001:db8::1:01cd
+bbbb-462		IN	AAAA	2001:db8::1:01ce
+bbbb-463		IN	AAAA	2001:db8::1:01cf
+bbbb-464		IN	AAAA	2001:db8::1:01d0
+bbbb-465		IN	AAAA	2001:db8::1:01d1
+bbbb-466		IN	AAAA	2001:db8::1:01d2
+bbbb-467		IN	AAAA	2001:db8::1:01d3
+bbbb-468		IN	AAAA	2001:db8::1:01d4
+bbbb-469		IN	AAAA	2001:db8::1:01d5
+bbbb-470		IN	AAAA	2001:db8::1:01d6
+bbbb-471		IN	AAAA	2001:db8::1:01d7
+bbbb-472		IN	AAAA	2001:db8::1:01d8
+bbbb-473		IN	AAAA	2001:db8::1:01d9
+bbbb-474		IN	AAAA	2001:db8::1:01da
+bbbb-475		IN	AAAA	2001:db8::1:01db
+bbbb-476		IN	AAAA	2001:db8::1:01dc
+bbbb-477		IN	AAAA	2001:db8::1:01dd
+bbbb-478		IN	AAAA	2001:db8::1:01de
+bbbb-479		IN	AAAA	2001:db8::1:01df
+bbbb-480		IN	AAAA	2001:db8::1:01e0
+bbbb-481		IN	AAAA	2001:db8::1:01e1
+bbbb-482		IN	AAAA	2001:db8::1:01e2
+bbbb-483		IN	AAAA	2001:db8::1:01e3
+bbbb-484		IN	AAAA	2001:db8::1:01e4
+bbbb-485		IN	AAAA	2001:db8::1:01e5
+bbbb-486		IN	AAAA	2001:db8::1:01e6
+bbbb-487		IN	AAAA	2001:db8::1:01e7
+bbbb-488		IN	AAAA	2001:db8::1:01e8
+bbbb-489		IN	AAAA	2001:db8::1:01e9
+bbbb-490		IN	AAAA	2001:db8::1:01ea
+bbbb-491		IN	AAAA	2001:db8::1:01eb
+bbbb-492		IN	AAAA	2001:db8::1:01ec
+bbbb-493		IN	AAAA	2001:db8::1:01ed
+bbbb-494		IN	AAAA	2001:db8::1:01ee
+bbbb-495		IN	AAAA	2001:db8::1:01ef
+bbbb-496		IN	AAAA	2001:db8::1:01f0
+bbbb-497		IN	AAAA	2001:db8::1:01f1
+bbbb-498		IN	AAAA	2001:db8::1:01f2
+bbbb-499		IN	AAAA	2001:db8::1:01f3
+bbbb-500		IN	AAAA	2001:db8::1:01f4
+bbbb-501		IN	AAAA	2001:db8::1:01f5
+bbbb-502		IN	AAAA	2001:db8::1:01f6
+bbbb-503		IN	AAAA	2001:db8::1:01f7
+bbbb-504		IN	AAAA	2001:db8::1:01f8
+bbbb-505		IN	AAAA	2001:db8::1:01f9
+bbbb-506		IN	AAAA	2001:db8::1:01fa
+bbbb-507		IN	AAAA	2001:db8::1:01fb
+bbbb-508		IN	AAAA	2001:db8::1:01fc
+bbbb-509		IN	AAAA	2001:db8::1:01fd
+bbbb-510		IN	AAAA	2001:db8::1:01fe
+bbbb-511		IN	AAAA	2001:db8::1:01ff
+
+cccc-000		IN	AAAA	2001:db8::2:0000
+cccc-001		IN	AAAA	2001:db8::2:0001
+cccc-002		IN	AAAA	2001:db8::2:0002
+cccc-003		IN	AAAA	2001:db8::2:0003
+cccc-004		IN	AAAA	2001:db8::2:0004
+cccc-005		IN	AAAA	2001:db8::2:0005
+cccc-006		IN	AAAA	2001:db8::2:0006
+cccc-007		IN	AAAA	2001:db8::2:0007
+cccc-008		IN	AAAA	2001:db8::2:0008
+cccc-009		IN	AAAA	2001:db8::2:0009
+cccc-010		IN	AAAA	2001:db8::2:000a
+cccc-011		IN	AAAA	2001:db8::2:000b
+cccc-012		IN	AAAA	2001:db8::2:000c
+cccc-013		IN	AAAA	2001:db8::2:000d
+cccc-014		IN	AAAA	2001:db8::2:000e
+cccc-015		IN	AAAA	2001:db8::2:000f
+cccc-016		IN	AAAA	2001:db8::2:0010
+cccc-017		IN	AAAA	2001:db8::2:0011
+cccc-018		IN	AAAA	2001:db8::2:0012
+cccc-019		IN	AAAA	2001:db8::2:0013
+cccc-020		IN	AAAA	2001:db8::2:0014
+cccc-021		IN	AAAA	2001:db8::2:0015
+cccc-022		IN	AAAA	2001:db8::2:0016
+cccc-023		IN	AAAA	2001:db8::2:0017
+cccc-024		IN	AAAA	2001:db8::2:0018
+cccc-025		IN	AAAA	2001:db8::2:0019
+cccc-026		IN	AAAA	2001:db8::2:001a
+cccc-027		IN	AAAA	2001:db8::2:001b
+cccc-028		IN	AAAA	2001:db8::2:001c
+cccc-029		IN	AAAA	2001:db8::2:001d
+cccc-030		IN	AAAA	2001:db8::2:001e
+cccc-031		IN	AAAA	2001:db8::2:001f
+cccc-032		IN	AAAA	2001:db8::2:0020
+cccc-033		IN	AAAA	2001:db8::2:0021
+cccc-034		IN	AAAA	2001:db8::2:0022
+cccc-035		IN	AAAA	2001:db8::2:0023
+cccc-036		IN	AAAA	2001:db8::2:0024
+cccc-037		IN	AAAA	2001:db8::2:0025
+cccc-038		IN	AAAA	2001:db8::2:0026
+cccc-039		IN	AAAA	2001:db8::2:0027
+cccc-040		IN	AAAA	2001:db8::2:0028
+cccc-041		IN	AAAA	2001:db8::2:0029
+cccc-042		IN	AAAA	2001:db8::2:002a
+cccc-043		IN	AAAA	2001:db8::2:002b
+cccc-044		IN	AAAA	2001:db8::2:002c
+cccc-045		IN	AAAA	2001:db8::2:002d
+cccc-046		IN	AAAA	2001:db8::2:002e
+cccc-047		IN	AAAA	2001:db8::2:002f
+cccc-048		IN	AAAA	2001:db8::2:0030
+cccc-049		IN	AAAA	2001:db8::2:0031
+cccc-050		IN	AAAA	2001:db8::2:0032
+cccc-051		IN	AAAA	2001:db8::2:0033
+cccc-052		IN	AAAA	2001:db8::2:0034
+cccc-053		IN	AAAA	2001:db8::2:0035
+cccc-054		IN	AAAA	2001:db8::2:0036
+cccc-055		IN	AAAA	2001:db8::2:0037
+cccc-056		IN	AAAA	2001:db8::2:0038
+cccc-057		IN	AAAA	2001:db8::2:0039
+cccc-058		IN	AAAA	2001:db8::2:003a
+cccc-059		IN	AAAA	2001:db8::2:003b
+cccc-060		IN	AAAA	2001:db8::2:003c
+cccc-061		IN	AAAA	2001:db8::2:003d
+cccc-062		IN	AAAA	2001:db8::2:003e
+cccc-063		IN	AAAA	2001:db8::2:003f
+cccc-064		IN	AAAA	2001:db8::2:0040
+cccc-065		IN	AAAA	2001:db8::2:0041
+cccc-066		IN	AAAA	2001:db8::2:0042
+cccc-067		IN	AAAA	2001:db8::2:0043
+cccc-068		IN	AAAA	2001:db8::2:0044
+cccc-069		IN	AAAA	2001:db8::2:0045
+cccc-070		IN	AAAA	2001:db8::2:0046
+cccc-071		IN	AAAA	2001:db8::2:0047
+cccc-072		IN	AAAA	2001:db8::2:0048
+cccc-073		IN	AAAA	2001:db8::2:0049
+cccc-074		IN	AAAA	2001:db8::2:004a
+cccc-075		IN	AAAA	2001:db8::2:004b
+cccc-076		IN	AAAA	2001:db8::2:004c
+cccc-077		IN	AAAA	2001:db8::2:004d
+cccc-078		IN	AAAA	2001:db8::2:004e
+cccc-079		IN	AAAA	2001:db8::2:004f
+cccc-080		IN	AAAA	2001:db8::2:0050
+cccc-081		IN	AAAA	2001:db8::2:0051
+cccc-082		IN	AAAA	2001:db8::2:0052
+cccc-083		IN	AAAA	2001:db8::2:0053
+cccc-084		IN	AAAA	2001:db8::2:0054
+cccc-085		IN	AAAA	2001:db8::2:0055
+cccc-086		IN	AAAA	2001:db8::2:0056
+cccc-087		IN	AAAA	2001:db8::2:0057
+cccc-088		IN	AAAA	2001:db8::2:0058
+cccc-089		IN	AAAA	2001:db8::2:0059
+cccc-090		IN	AAAA	2001:db8::2:005a
+cccc-091		IN	AAAA	2001:db8::2:005b
+cccc-092		IN	AAAA	2001:db8::2:005c
+cccc-093		IN	AAAA	2001:db8::2:005d
+cccc-094		IN	AAAA	2001:db8::2:005e
+cccc-095		IN	AAAA	2001:db8::2:005f
+cccc-096		IN	AAAA	2001:db8::2:0060
+cccc-097		IN	AAAA	2001:db8::2:0061
+cccc-098		IN	AAAA	2001:db8::2:0062
+cccc-099		IN	AAAA	2001:db8::2:0063
+cccc-100		IN	AAAA	2001:db8::2:0064
+cccc-101		IN	AAAA	2001:db8::2:0065
+cccc-102		IN	AAAA	2001:db8::2:0066
+cccc-103		IN	AAAA	2001:db8::2:0067
+cccc-104		IN	AAAA	2001:db8::2:0068
+cccc-105		IN	AAAA	2001:db8::2:0069
+cccc-106		IN	AAAA	2001:db8::2:006a
+cccc-107		IN	AAAA	2001:db8::2:006b
+cccc-108		IN	AAAA	2001:db8::2:006c
+cccc-109		IN	AAAA	2001:db8::2:006d
+cccc-110		IN	AAAA	2001:db8::2:006e
+cccc-111		IN	AAAA	2001:db8::2:006f
+cccc-112		IN	AAAA	2001:db8::2:0070
+cccc-113		IN	AAAA	2001:db8::2:0071
+cccc-114		IN	AAAA	2001:db8::2:0072
+cccc-115		IN	AAAA	2001:db8::2:0073
+cccc-116		IN	AAAA	2001:db8::2:0074
+cccc-117		IN	AAAA	2001:db8::2:0075
+cccc-118		IN	AAAA	2001:db8::2:0076
+cccc-119		IN	AAAA	2001:db8::2:0077
+cccc-120		IN	AAAA	2001:db8::2:0078
+cccc-121		IN	AAAA	2001:db8::2:0079
+cccc-122		IN	AAAA	2001:db8::2:007a
+cccc-123		IN	AAAA	2001:db8::2:007b
+cccc-124		IN	AAAA	2001:db8::2:007c
+cccc-125		IN	AAAA	2001:db8::2:007d
+cccc-126		IN	AAAA	2001:db8::2:007e
+cccc-127		IN	AAAA	2001:db8::2:007f
+cccc-128		IN	AAAA	2001:db8::2:0080
+cccc-129		IN	AAAA	2001:db8::2:0081
+cccc-130		IN	AAAA	2001:db8::2:0082
+cccc-131		IN	AAAA	2001:db8::2:0083
+cccc-132		IN	AAAA	2001:db8::2:0084
+cccc-133		IN	AAAA	2001:db8::2:0085
+cccc-134		IN	AAAA	2001:db8::2:0086
+cccc-135		IN	AAAA	2001:db8::2:0087
+cccc-136		IN	AAAA	2001:db8::2:0088
+cccc-137		IN	AAAA	2001:db8::2:0089
+cccc-138		IN	AAAA	2001:db8::2:008a
+cccc-139		IN	AAAA	2001:db8::2:008b
+cccc-140		IN	AAAA	2001:db8::2:008c
+cccc-141		IN	AAAA	2001:db8::2:008d
+cccc-142		IN	AAAA	2001:db8::2:008e
+cccc-143		IN	AAAA	2001:db8::2:008f
+cccc-144		IN	AAAA	2001:db8::2:0090
+cccc-145		IN	AAAA	2001:db8::2:0091
+cccc-146		IN	AAAA	2001:db8::2:0092
+cccc-147		IN	AAAA	2001:db8::2:0093
+cccc-148		IN	AAAA	2001:db8::2:0094
+cccc-149		IN	AAAA	2001:db8::2:0095
+cccc-150		IN	AAAA	2001:db8::2:0096
+cccc-151		IN	AAAA	2001:db8::2:0097
+cccc-152		IN	AAAA	2001:db8::2:0098
+cccc-153		IN	AAAA	2001:db8::2:0099
+cccc-154		IN	AAAA	2001:db8::2:009a
+cccc-155		IN	AAAA	2001:db8::2:009b
+cccc-156		IN	AAAA	2001:db8::2:009c
+cccc-157		IN	AAAA	2001:db8::2:009d
+cccc-158		IN	AAAA	2001:db8::2:009e
+cccc-159		IN	AAAA	2001:db8::2:009f
+cccc-160		IN	AAAA	2001:db8::2:00a0
+cccc-161		IN	AAAA	2001:db8::2:00a1
+cccc-162		IN	AAAA	2001:db8::2:00a2
+cccc-163		IN	AAAA	2001:db8::2:00a3
+cccc-164		IN	AAAA	2001:db8::2:00a4
+cccc-165		IN	AAAA	2001:db8::2:00a5
+cccc-166		IN	AAAA	2001:db8::2:00a6
+cccc-167		IN	AAAA	2001:db8::2:00a7
+cccc-168		IN	AAAA	2001:db8::2:00a8
+cccc-169		IN	AAAA	2001:db8::2:00a9
+cccc-170		IN	AAAA	2001:db8::2:00aa
+cccc-171		IN	AAAA	2001:db8::2:00ab
+cccc-172		IN	AAAA	2001:db8::2:00ac
+cccc-173		IN	AAAA	2001:db8::2:00ad
+cccc-174		IN	AAAA	2001:db8::2:00ae
+cccc-175		IN	AAAA	2001:db8::2:00af
+cccc-176		IN	AAAA	2001:db8::2:00b0
+cccc-177		IN	AAAA	2001:db8::2:00b1
+cccc-178		IN	AAAA	2001:db8::2:00b2
+cccc-179		IN	AAAA	2001:db8::2:00b3
+cccc-180		IN	AAAA	2001:db8::2:00b4
+cccc-181		IN	AAAA	2001:db8::2:00b5
+cccc-182		IN	AAAA	2001:db8::2:00b6
+cccc-183		IN	AAAA	2001:db8::2:00b7
+cccc-184		IN	AAAA	2001:db8::2:00b8
+cccc-185		IN	AAAA	2001:db8::2:00b9
+cccc-186		IN	AAAA	2001:db8::2:00ba
+cccc-187		IN	AAAA	2001:db8::2:00bb
+cccc-188		IN	AAAA	2001:db8::2:00bc
+cccc-189		IN	AAAA	2001:db8::2:00bd
+cccc-190		IN	AAAA	2001:db8::2:00be
+cccc-191		IN	AAAA	2001:db8::2:00bf
+cccc-192		IN	AAAA	2001:db8::2:00c0
+cccc-193		IN	AAAA	2001:db8::2:00c1
+cccc-194		IN	AAAA	2001:db8::2:00c2
+cccc-195		IN	AAAA	2001:db8::2:00c3
+cccc-196		IN	AAAA	2001:db8::2:00c4
+cccc-197		IN	AAAA	2001:db8::2:00c5
+cccc-198		IN	AAAA	2001:db8::2:00c6
+cccc-199		IN	AAAA	2001:db8::2:00c7
+cccc-200		IN	AAAA	2001:db8::2:00c8
+cccc-201		IN	AAAA	2001:db8::2:00c9
+cccc-202		IN	AAAA	2001:db8::2:00ca
+cccc-203		IN	AAAA	2001:db8::2:00cb
+cccc-204		IN	AAAA	2001:db8::2:00cc
+cccc-205		IN	AAAA	2001:db8::2:00cd
+cccc-206		IN	AAAA	2001:db8::2:00ce
+cccc-207		IN	AAAA	2001:db8::2:00cf
+cccc-208		IN	AAAA	2001:db8::2:00d0
+cccc-209		IN	AAAA	2001:db8::2:00d1
+cccc-210		IN	AAAA	2001:db8::2:00d2
+cccc-211		IN	AAAA	2001:db8::2:00d3
+cccc-212		IN	AAAA	2001:db8::2:00d4
+cccc-213		IN	AAAA	2001:db8::2:00d5
+cccc-214		IN	AAAA	2001:db8::2:00d6
+cccc-215		IN	AAAA	2001:db8::2:00d7
+cccc-216		IN	AAAA	2001:db8::2:00d8
+cccc-217		IN	AAAA	2001:db8::2:00d9
+cccc-218		IN	AAAA	2001:db8::2:00da
+cccc-219		IN	AAAA	2001:db8::2:00db
+cccc-220		IN	AAAA	2001:db8::2:00dc
+cccc-221		IN	AAAA	2001:db8::2:00dd
+cccc-222		IN	AAAA	2001:db8::2:00de
+cccc-223		IN	AAAA	2001:db8::2:00df
+cccc-224		IN	AAAA	2001:db8::2:00e0
+cccc-225		IN	AAAA	2001:db8::2:00e1
+cccc-226		IN	AAAA	2001:db8::2:00e2
+cccc-227		IN	AAAA	2001:db8::2:00e3
+cccc-228		IN	AAAA	2001:db8::2:00e4
+cccc-229		IN	AAAA	2001:db8::2:00e5
+cccc-230		IN	AAAA	2001:db8::2:00e6
+cccc-231		IN	AAAA	2001:db8::2:00e7
+cccc-232		IN	AAAA	2001:db8::2:00e8
+cccc-233		IN	AAAA	2001:db8::2:00e9
+cccc-234		IN	AAAA	2001:db8::2:00ea
+cccc-235		IN	AAAA	2001:db8::2:00eb
+cccc-236		IN	AAAA	2001:db8::2:00ec
+cccc-237		IN	AAAA	2001:db8::2:00ed
+cccc-238		IN	AAAA	2001:db8::2:00ee
+cccc-239		IN	AAAA	2001:db8::2:00ef
+cccc-240		IN	AAAA	2001:db8::2:00f0
+cccc-241		IN	AAAA	2001:db8::2:00f1
+cccc-242		IN	AAAA	2001:db8::2:00f2
+cccc-243		IN	AAAA	2001:db8::2:00f3
+cccc-244		IN	AAAA	2001:db8::2:00f4
+cccc-245		IN	AAAA	2001:db8::2:00f5
+cccc-246		IN	AAAA	2001:db8::2:00f6
+cccc-247		IN	AAAA	2001:db8::2:00f7
+cccc-248		IN	AAAA	2001:db8::2:00f8
+cccc-249		IN	AAAA	2001:db8::2:00f9
+cccc-250		IN	AAAA	2001:db8::2:00fa
+cccc-251		IN	AAAA	2001:db8::2:00fb
+cccc-252		IN	AAAA	2001:db8::2:00fc
+cccc-253		IN	AAAA	2001:db8::2:00fd
+cccc-254		IN	AAAA	2001:db8::2:00fe
+cccc-255		IN	AAAA	2001:db8::2:00ff
+cccc-256		IN	AAAA	2001:db8::2:0100
+cccc-257		IN	AAAA	2001:db8::2:0101
+cccc-258		IN	AAAA	2001:db8::2:0102
+cccc-259		IN	AAAA	2001:db8::2:0103
+cccc-260		IN	AAAA	2001:db8::2:0104
+cccc-261		IN	AAAA	2001:db8::2:0105
+cccc-262		IN	AAAA	2001:db8::2:0106
+cccc-263		IN	AAAA	2001:db8::2:0107
+cccc-264		IN	AAAA	2001:db8::2:0108
+cccc-265		IN	AAAA	2001:db8::2:0109
+cccc-266		IN	AAAA	2001:db8::2:010a
+cccc-267		IN	AAAA	2001:db8::2:010b
+cccc-268		IN	AAAA	2001:db8::2:010c
+cccc-269		IN	AAAA	2001:db8::2:010d
+cccc-270		IN	AAAA	2001:db8::2:010e
+cccc-271		IN	AAAA	2001:db8::2:010f
+cccc-272		IN	AAAA	2001:db8::2:0110
+cccc-273		IN	AAAA	2001:db8::2:0111
+cccc-274		IN	AAAA	2001:db8::2:0112
+cccc-275		IN	AAAA	2001:db8::2:0113
+cccc-276		IN	AAAA	2001:db8::2:0114
+cccc-277		IN	AAAA	2001:db8::2:0115
+cccc-278		IN	AAAA	2001:db8::2:0116
+cccc-279		IN	AAAA	2001:db8::2:0117
+cccc-280		IN	AAAA	2001:db8::2:0118
+cccc-281		IN	AAAA	2001:db8::2:0119
+cccc-282		IN	AAAA	2001:db8::2:011a
+cccc-283		IN	AAAA	2001:db8::2:011b
+cccc-284		IN	AAAA	2001:db8::2:011c
+cccc-285		IN	AAAA	2001:db8::2:011d
+cccc-286		IN	AAAA	2001:db8::2:011e
+cccc-287		IN	AAAA	2001:db8::2:011f
+cccc-288		IN	AAAA	2001:db8::2:0120
+cccc-289		IN	AAAA	2001:db8::2:0121
+cccc-290		IN	AAAA	2001:db8::2:0122
+cccc-291		IN	AAAA	2001:db8::2:0123
+cccc-292		IN	AAAA	2001:db8::2:0124
+cccc-293		IN	AAAA	2001:db8::2:0125
+cccc-294		IN	AAAA	2001:db8::2:0126
+cccc-295		IN	AAAA	2001:db8::2:0127
+cccc-296		IN	AAAA	2001:db8::2:0128
+cccc-297		IN	AAAA	2001:db8::2:0129
+cccc-298		IN	AAAA	2001:db8::2:012a
+cccc-299		IN	AAAA	2001:db8::2:012b
+cccc-300		IN	AAAA	2001:db8::2:012c
+cccc-301		IN	AAAA	2001:db8::2:012d
+cccc-302		IN	AAAA	2001:db8::2:012e
+cccc-303		IN	AAAA	2001:db8::2:012f
+cccc-304		IN	AAAA	2001:db8::2:0130
+cccc-305		IN	AAAA	2001:db8::2:0131
+cccc-306		IN	AAAA	2001:db8::2:0132
+cccc-307		IN	AAAA	2001:db8::2:0133
+cccc-308		IN	AAAA	2001:db8::2:0134
+cccc-309		IN	AAAA	2001:db8::2:0135
+cccc-310		IN	AAAA	2001:db8::2:0136
+cccc-311		IN	AAAA	2001:db8::2:0137
+cccc-312		IN	AAAA	2001:db8::2:0138
+cccc-313		IN	AAAA	2001:db8::2:0139
+cccc-314		IN	AAAA	2001:db8::2:013a
+cccc-315		IN	AAAA	2001:db8::2:013b
+cccc-316		IN	AAAA	2001:db8::2:013c
+cccc-317		IN	AAAA	2001:db8::2:013d
+cccc-318		IN	AAAA	2001:db8::2:013e
+cccc-319		IN	AAAA	2001:db8::2:013f
+cccc-320		IN	AAAA	2001:db8::2:0140
+cccc-321		IN	AAAA	2001:db8::2:0141
+cccc-322		IN	AAAA	2001:db8::2:0142
+cccc-323		IN	AAAA	2001:db8::2:0143
+cccc-324		IN	AAAA	2001:db8::2:0144
+cccc-325		IN	AAAA	2001:db8::2:0145
+cccc-326		IN	AAAA	2001:db8::2:0146
+cccc-327		IN	AAAA	2001:db8::2:0147
+cccc-328		IN	AAAA	2001:db8::2:0148
+cccc-329		IN	AAAA	2001:db8::2:0149
+cccc-330		IN	AAAA	2001:db8::2:014a
+cccc-331		IN	AAAA	2001:db8::2:014b
+cccc-332		IN	AAAA	2001:db8::2:014c
+cccc-333		IN	AAAA	2001:db8::2:014d
+cccc-334		IN	AAAA	2001:db8::2:014e
+cccc-335		IN	AAAA	2001:db8::2:014f
+cccc-336		IN	AAAA	2001:db8::2:0150
+cccc-337		IN	AAAA	2001:db8::2:0151
+cccc-338		IN	AAAA	2001:db8::2:0152
+cccc-339		IN	AAAA	2001:db8::2:0153
+cccc-340		IN	AAAA	2001:db8::2:0154
+cccc-341		IN	AAAA	2001:db8::2:0155
+cccc-342		IN	AAAA	2001:db8::2:0156
+cccc-343		IN	AAAA	2001:db8::2:0157
+cccc-344		IN	AAAA	2001:db8::2:0158
+cccc-345		IN	AAAA	2001:db8::2:0159
+cccc-346		IN	AAAA	2001:db8::2:015a
+cccc-347		IN	AAAA	2001:db8::2:015b
+cccc-348		IN	AAAA	2001:db8::2:015c
+cccc-349		IN	AAAA	2001:db8::2:015d
+cccc-350		IN	AAAA	2001:db8::2:015e
+cccc-351		IN	AAAA	2001:db8::2:015f
+cccc-352		IN	AAAA	2001:db8::2:0160
+cccc-353		IN	AAAA	2001:db8::2:0161
+cccc-354		IN	AAAA	2001:db8::2:0162
+cccc-355		IN	AAAA	2001:db8::2:0163
+cccc-356		IN	AAAA	2001:db8::2:0164
+cccc-357		IN	AAAA	2001:db8::2:0165
+cccc-358		IN	AAAA	2001:db8::2:0166
+cccc-359		IN	AAAA	2001:db8::2:0167
+cccc-360		IN	AAAA	2001:db8::2:0168
+cccc-361		IN	AAAA	2001:db8::2:0169
+cccc-362		IN	AAAA	2001:db8::2:016a
+cccc-363		IN	AAAA	2001:db8::2:016b
+cccc-364		IN	AAAA	2001:db8::2:016c
+cccc-365		IN	AAAA	2001:db8::2:016d
+cccc-366		IN	AAAA	2001:db8::2:016e
+cccc-367		IN	AAAA	2001:db8::2:016f
+cccc-368		IN	AAAA	2001:db8::2:0170
+cccc-369		IN	AAAA	2001:db8::2:0171
+cccc-370		IN	AAAA	2001:db8::2:0172
+cccc-371		IN	AAAA	2001:db8::2:0173
+cccc-372		IN	AAAA	2001:db8::2:0174
+cccc-373		IN	AAAA	2001:db8::2:0175
+cccc-374		IN	AAAA	2001:db8::2:0176
+cccc-375		IN	AAAA	2001:db8::2:0177
+cccc-376		IN	AAAA	2001:db8::2:0178
+cccc-377		IN	AAAA	2001:db8::2:0179
+cccc-378		IN	AAAA	2001:db8::2:017a
+cccc-379		IN	AAAA	2001:db8::2:017b
+cccc-380		IN	AAAA	2001:db8::2:017c
+cccc-381		IN	AAAA	2001:db8::2:017d
+cccc-382		IN	AAAA	2001:db8::2:017e
+cccc-383		IN	AAAA	2001:db8::2:017f
+cccc-384		IN	AAAA	2001:db8::2:0180
+cccc-385		IN	AAAA	2001:db8::2:0181
+cccc-386		IN	AAAA	2001:db8::2:0182
+cccc-387		IN	AAAA	2001:db8::2:0183
+cccc-388		IN	AAAA	2001:db8::2:0184
+cccc-389		IN	AAAA	2001:db8::2:0185
+cccc-390		IN	AAAA	2001:db8::2:0186
+cccc-391		IN	AAAA	2001:db8::2:0187
+cccc-392		IN	AAAA	2001:db8::2:0188
+cccc-393		IN	AAAA	2001:db8::2:0189
+cccc-394		IN	AAAA	2001:db8::2:018a
+cccc-395		IN	AAAA	2001:db8::2:018b
+cccc-396		IN	AAAA	2001:db8::2:018c
+cccc-397		IN	AAAA	2001:db8::2:018d
+cccc-398		IN	AAAA	2001:db8::2:018e
+cccc-399		IN	AAAA	2001:db8::2:018f
+cccc-400		IN	AAAA	2001:db8::2:0190
+cccc-401		IN	AAAA	2001:db8::2:0191
+cccc-402		IN	AAAA	2001:db8::2:0192
+cccc-403		IN	AAAA	2001:db8::2:0193
+cccc-404		IN	AAAA	2001:db8::2:0194
+cccc-405		IN	AAAA	2001:db8::2:0195
+cccc-406		IN	AAAA	2001:db8::2:0196
+cccc-407		IN	AAAA	2001:db8::2:0197
+cccc-408		IN	AAAA	2001:db8::2:0198
+cccc-409		IN	AAAA	2001:db8::2:0199
+cccc-410		IN	AAAA	2001:db8::2:019a
+cccc-411		IN	AAAA	2001:db8::2:019b
+cccc-412		IN	AAAA	2001:db8::2:019c
+cccc-413		IN	AAAA	2001:db8::2:019d
+cccc-414		IN	AAAA	2001:db8::2:019e
+cccc-415		IN	AAAA	2001:db8::2:019f
+cccc-416		IN	AAAA	2001:db8::2:01a0
+cccc-417		IN	AAAA	2001:db8::2:01a1
+cccc-418		IN	AAAA	2001:db8::2:01a2
+cccc-419		IN	AAAA	2001:db8::2:01a3
+cccc-420		IN	AAAA	2001:db8::2:01a4
+cccc-421		IN	AAAA	2001:db8::2:01a5
+cccc-422		IN	AAAA	2001:db8::2:01a6
+cccc-423		IN	AAAA	2001:db8::2:01a7
+cccc-424		IN	AAAA	2001:db8::2:01a8
+cccc-425		IN	AAAA	2001:db8::2:01a9
+cccc-426		IN	AAAA	2001:db8::2:01aa
+cccc-427		IN	AAAA	2001:db8::2:01ab
+cccc-428		IN	AAAA	2001:db8::2:01ac
+cccc-429		IN	AAAA	2001:db8::2:01ad
+cccc-430		IN	AAAA	2001:db8::2:01ae
+cccc-431		IN	AAAA	2001:db8::2:01af
+cccc-432		IN	AAAA	2001:db8::2:01b0
+cccc-433		IN	AAAA	2001:db8::2:01b1
+cccc-434		IN	AAAA	2001:db8::2:01b2
+cccc-435		IN	AAAA	2001:db8::2:01b3
+cccc-436		IN	AAAA	2001:db8::2:01b4
+cccc-437		IN	AAAA	2001:db8::2:01b5
+cccc-438		IN	AAAA	2001:db8::2:01b6
+cccc-439		IN	AAAA	2001:db8::2:01b7
+cccc-440		IN	AAAA	2001:db8::2:01b8
+cccc-441		IN	AAAA	2001:db8::2:01b9
+cccc-442		IN	AAAA	2001:db8::2:01ba
+cccc-443		IN	AAAA	2001:db8::2:01bb
+cccc-444		IN	AAAA	2001:db8::2:01bc
+cccc-445		IN	AAAA	2001:db8::2:01bd
+cccc-446		IN	AAAA	2001:db8::2:01be
+cccc-447		IN	AAAA	2001:db8::2:01bf
+cccc-448		IN	AAAA	2001:db8::2:01c0
+cccc-449		IN	AAAA	2001:db8::2:01c1
+cccc-450		IN	AAAA	2001:db8::2:01c2
+cccc-451		IN	AAAA	2001:db8::2:01c3
+cccc-452		IN	AAAA	2001:db8::2:01c4
+cccc-453		IN	AAAA	2001:db8::2:01c5
+cccc-454		IN	AAAA	2001:db8::2:01c6
+cccc-455		IN	AAAA	2001:db8::2:01c7
+cccc-456		IN	AAAA	2001:db8::2:01c8
+cccc-457		IN	AAAA	2001:db8::2:01c9
+cccc-458		IN	AAAA	2001:db8::2:01ca
+cccc-459		IN	AAAA	2001:db8::2:01cb
+cccc-460		IN	AAAA	2001:db8::2:01cc
+cccc-461		IN	AAAA	2001:db8::2:01cd
+cccc-462		IN	AAAA	2001:db8::2:01ce
+cccc-463		IN	AAAA	2001:db8::2:01cf
+cccc-464		IN	AAAA	2001:db8::2:01d0
+cccc-465		IN	AAAA	2001:db8::2:01d1
+cccc-466		IN	AAAA	2001:db8::2:01d2
+cccc-467		IN	AAAA	2001:db8::2:01d3
+cccc-468		IN	AAAA	2001:db8::2:01d4
+cccc-469		IN	AAAA	2001:db8::2:01d5
+cccc-470		IN	AAAA	2001:db8::2:01d6
+cccc-471		IN	AAAA	2001:db8::2:01d7
+cccc-472		IN	AAAA	2001:db8::2:01d8
+cccc-473		IN	AAAA	2001:db8::2:01d9
+cccc-474		IN	AAAA	2001:db8::2:01da
+cccc-475		IN	AAAA	2001:db8::2:01db
+cccc-476		IN	AAAA	2001:db8::2:01dc
+cccc-477		IN	AAAA	2001:db8::2:01dd
+cccc-478		IN	AAAA	2001:db8::2:01de
+cccc-479		IN	AAAA	2001:db8::2:01df
+cccc-480		IN	AAAA	2001:db8::2:01e0
+cccc-481		IN	AAAA	2001:db8::2:01e1
+cccc-482		IN	AAAA	2001:db8::2:01e2
+cccc-483		IN	AAAA	2001:db8::2:01e3
+cccc-484		IN	AAAA	2001:db8::2:01e4
+cccc-485		IN	AAAA	2001:db8::2:01e5
+cccc-486		IN	AAAA	2001:db8::2:01e6
+cccc-487		IN	AAAA	2001:db8::2:01e7
+cccc-488		IN	AAAA	2001:db8::2:01e8
+cccc-489		IN	AAAA	2001:db8::2:01e9
+cccc-490		IN	AAAA	2001:db8::2:01ea
+cccc-491		IN	AAAA	2001:db8::2:01eb
+cccc-492		IN	AAAA	2001:db8::2:01ec
+cccc-493		IN	AAAA	2001:db8::2:01ed
+cccc-494		IN	AAAA	2001:db8::2:01ee
+cccc-495		IN	AAAA	2001:db8::2:01ef
+cccc-496		IN	AAAA	2001:db8::2:01f0
+cccc-497		IN	AAAA	2001:db8::2:01f1
+cccc-498		IN	AAAA	2001:db8::2:01f2
+cccc-499		IN	AAAA	2001:db8::2:01f3
+cccc-500		IN	AAAA	2001:db8::2:01f4
+cccc-501		IN	AAAA	2001:db8::2:01f5
+cccc-502		IN	AAAA	2001:db8::2:01f6
+cccc-503		IN	AAAA	2001:db8::2:01f7
+cccc-504		IN	AAAA	2001:db8::2:01f8
+cccc-505		IN	AAAA	2001:db8::2:01f9
+cccc-506		IN	AAAA	2001:db8::2:01fa
+cccc-507		IN	AAAA	2001:db8::2:01fb
+cccc-508		IN	AAAA	2001:db8::2:01fc
+cccc-509		IN	AAAA	2001:db8::2:01fd
+cccc-510		IN	AAAA	2001:db8::2:01fe
+cccc-511		IN	AAAA	2001:db8::2:01ff
diff --git a/tests/system/ixfr/db.example.n0.in b/tests/system/ixfr/db.example.n0.in
new file mode 100644
index 0000000..92fa0b0
--- /dev/null
+++ b/tests/system/ixfr/db.example.n0.in
@@ -0,0 +1,29 @@
+; 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.
+
+$ORIGIN example.
+$TTL 3600
+
+@       IN	SOA	ns1.example. hostmaster.example. 100 3600 900 7200 300
+
+        IN	NS	ns1.example.
+        IN	NS	ns2.example.
+
+ns1     IN  A   192.0.2.1
+ns2     IN  A   192.0.2.2
+
+a-1     IN  A   192.0.2.101
+b-1     IN  A   192.0.2.201
+
+$INCLUDE @abs_top_builddir@/tests/system/ixfr/db.example.common
diff --git a/tests/system/ixfr/db.example.n2.in b/tests/system/ixfr/db.example.n2.in
new file mode 100644
index 0000000..6a999af
--- /dev/null
+++ b/tests/system/ixfr/db.example.n2.in
@@ -0,0 +1,28 @@
+; 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.
+
+$ORIGIN example.
+$TTL 3600
+
+@       IN	SOA	ns1.example. hostmaster.example. 98 3600 900 7200 300
+
+        IN	NS	ns1.example.
+        IN	NS	ns2.example.
+
+ns1     IN  A   192.0.2.1
+ns2     IN  A   192.0.2.2
+
+a-1     IN  A   192.0.2.101
+
+$INCLUDE @abs_top_builddir@/tests/system/ixfr/db.example.common
diff --git a/tests/system/ixfr/db.example.n2.refresh.in b/tests/system/ixfr/db.example.n2.refresh.in
new file mode 100644
index 0000000..2c59416
--- /dev/null
+++ b/tests/system/ixfr/db.example.n2.refresh.in
@@ -0,0 +1,28 @@
+; 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.
+
+$ORIGIN example.
+$TTL 3600
+
+@       IN	SOA	ns1.example. hostmaster.example. 98 30 2 7200 300
+
+        IN	NS	ns1.example.
+        IN	NS	ns2.example.
+
+ns1     IN  A   192.0.2.1
+ns2     IN  A   192.0.2.2
+
+a-1     IN  A   192.0.2.101
+
+$INCLUDE @abs_top_builddir@/tests/system/ixfr/db.example.common
diff --git a/tests/system/ixfr/db.example.n4.in b/tests/system/ixfr/db.example.n4.in
new file mode 100644
index 0000000..ae15a54
--- /dev/null
+++ b/tests/system/ixfr/db.example.n4.in
@@ -0,0 +1,31 @@
+; 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.
+
+$ORIGIN example.
+$TTL 3600
+
+@       IN	SOA	ns1.example. hostmaster.example. 96 3600 900 7200 300
+
+        IN	NS	ns1.example.
+        IN	NS	ns2.example.
+
+ns1     IN  A   192.0.2.1
+ns2     IN  A   192.0.2.2
+
+a-1     IN  A   192.0.2.101
+a-2     IN  A   192.0.2.102
+b-1     IN  A   192.0.2.201
+b-2     IN  A   192.0.2.202
+
+$INCLUDE @abs_top_builddir@/tests/system/ixfr/db.example.common
diff --git a/tests/system/ixfr/db.example.n6.in b/tests/system/ixfr/db.example.n6.in
new file mode 100644
index 0000000..33a82a0
--- /dev/null
+++ b/tests/system/ixfr/db.example.n6.in
@@ -0,0 +1,29 @@
+; 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.
+
+$ORIGIN example.
+$TTL 3600
+
+@       IN	SOA	ns1.example. hostmaster.example. 94 3600 900 7200 300
+
+        IN	NS	ns1.example.
+        IN	NS	ns2.example.
+
+ns1     IN  A   192.0.2.1
+ns2     IN  A   192.0.2.2
+
+a-1     IN  A   192.0.2.101
+a-2     IN  A   192.0.2.102
+b-1     IN  A   192.0.2.201
+b-2     IN  A   192.0.2.202
diff --git a/tests/system/ixfr/in-1/clean.sh b/tests/system/ixfr/in-1/clean.sh
new file mode 120000
index 0000000..099bebd
--- /dev/null
+++ b/tests/system/ixfr/in-1/clean.sh
@@ -0,0 +1 @@
+../clean_ns.sh
\ No newline at end of file
diff --git a/tests/system/ixfr/in-1/ns1/README b/tests/system/ixfr/in-1/ns1/README
new file mode 100644
index 0000000..aaa8a31
--- /dev/null
+++ b/tests/system/ixfr/in-1/ns1/README
@@ -0,0 +1,3 @@
+This directory should be empty. A README file is placed here to ensure git
+notes the directory's presence.  It can be removed if other files are placed
+here.
diff --git a/tests/system/ixfr/in-1/nsx2/README b/tests/system/ixfr/in-1/nsx2/README
new file mode 100644
index 0000000..aaa8a31
--- /dev/null
+++ b/tests/system/ixfr/in-1/nsx2/README
@@ -0,0 +1,3 @@
+This directory should be empty. A README file is placed here to ensure git
+notes the directory's presence.  It can be removed if other files are placed
+here.
diff --git a/tests/system/ixfr/in-1/setup.sh.in b/tests/system/ixfr/in-1/setup.sh.in
new file mode 100644
index 0000000..d4c3978
--- /dev/null
+++ b/tests/system/ixfr/in-1/setup.sh.in
@@ -0,0 +1,30 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007, 2011  Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2001, 2002  Internet Software Consortium.
+#
+# 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.
+
+. @abs_top_builddir@/tests/system/conf.sh
+
+# Clean up from last time
+sh clean.sh
+
+# Set up the initial version of the IXFR server - load the n-4 version of the
+# zone.  The configuration file enables IXFR and disabled notifies.
+cp -f $IXFR_TOP/named_nonotify.conf ns1/named.conf
+cp -f $IXFR_TOP/db.example.n4 ns1/db.example
+
+# Set up the IXFR client - load the same version of the zone.
+cp -f $IXFR_TOP/b10-config.db nsx2/b10-config.db
+${B10_LOADZONE} -o . -d $IXFR_TOP/zone.sqlite3 $IXFR_TOP/db.example.n4
diff --git a/tests/system/ixfr/in-1/tests.sh b/tests/system/ixfr/in-1/tests.sh
new file mode 100644
index 0000000..2f49ddf
--- /dev/null
+++ b/tests/system/ixfr/in-1/tests.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+#
+# 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.
+
+# \file
+# This script performs the first IXFR-IN test.  A BIND 9 nameserver (the
+# "server") contains a version of the zone (version N) and two previous
+# versions, N-2 and N-4.  A BIND 10 nameserver (the "client") is loaded with
+# version N-4 of the zone.  A NOTIFY is sent to it, and it is expected that
+# it will send an IXFR to the server and update itself with the latest version
+# of the zone.  (The changes are such that the update should be in the form of
+# a single UDP packet.)
+#
+# The pre-requisites for this test are the same as for the common tests, so
+# we can execute that directly.
+
+. ../common_tests.sh
+status=$?
+
+# TODO: Check the BIND 10 log, looking for the IXFR messages that indicate that
+# it has initiated an IXFR and that it received the update within a single
+# packet.
+
+echo "I:exit status: $status"
+exit $status
diff --git a/tests/system/ixfr/in-2/clean.sh b/tests/system/ixfr/in-2/clean.sh
new file mode 120000
index 0000000..099bebd
--- /dev/null
+++ b/tests/system/ixfr/in-2/clean.sh
@@ -0,0 +1 @@
+../clean_ns.sh
\ No newline at end of file
diff --git a/tests/system/ixfr/in-2/ns1/README b/tests/system/ixfr/in-2/ns1/README
new file mode 100644
index 0000000..aaa8a31
--- /dev/null
+++ b/tests/system/ixfr/in-2/ns1/README
@@ -0,0 +1,3 @@
+This directory should be empty. A README file is placed here to ensure git
+notes the directory's presence.  It can be removed if other files are placed
+here.
diff --git a/tests/system/ixfr/in-2/nsx2/README b/tests/system/ixfr/in-2/nsx2/README
new file mode 100644
index 0000000..aaa8a31
--- /dev/null
+++ b/tests/system/ixfr/in-2/nsx2/README
@@ -0,0 +1,3 @@
+This directory should be empty. A README file is placed here to ensure git
+notes the directory's presence.  It can be removed if other files are placed
+here.
diff --git a/tests/system/ixfr/in-2/setup.sh.in b/tests/system/ixfr/in-2/setup.sh.in
new file mode 100644
index 0000000..a5f64e5
--- /dev/null
+++ b/tests/system/ixfr/in-2/setup.sh.in
@@ -0,0 +1,29 @@
+#!/bin/sh
+#
+# 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.
+
+. @abs_top_builddir@/tests/system/conf.sh
+
+# Clean up from last time
+sh clean.sh
+
+# Set up the initial version of the IXFR server - load the n-6 version of the
+# zone.  The configuration file enables IXFR and disables notifies.
+cp -f $IXFR_TOP/named_nonotify.conf ns1/named.conf
+cp -f $IXFR_TOP/db.example.n6 ns1/db.example
+
+# Set up the IXFR client - load an earlier version of the zone
+cp -f $IXFR_TOP/b10-config.db nsx2/b10-config.db
+${B10_LOADZONE} -o . -d $IXFR_TOP/zone.sqlite3 $IXFR_TOP/db.example.n6
diff --git a/tests/system/ixfr/in-2/tests.sh b/tests/system/ixfr/in-2/tests.sh
new file mode 100644
index 0000000..7b1e2a8
--- /dev/null
+++ b/tests/system/ixfr/in-2/tests.sh
@@ -0,0 +1,81 @@
+#!/bin/sh
+#
+# 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.
+
+# \file
+# This script performs the first IXFR-IN test.  A BIND 9 nameserver (the
+# "server") contains a version of the zone (version N) and three previous
+# versions, N-2, N-4 and N-6.  A BIND 10 nameserver (the "client") is loaded
+# with version N-6 of the zone.  A NOTIFY is sent to it, and it is expected that
+# it will send an IXFR to the server and update itself with the latest version
+# of the zone.  (The changes are such that the update will have to take place
+# over TCP.)
+
+. ../ixfr_init.sh
+
+# On entry, the IXFR server is at version N-6.  The common tests assume that
+# it is an N-4, so update it.
+echo "I:$SERVER_NAME updating IXFR-server to suitable start version"
+update_server_zone $SERVER_NAME $SERVER_IP $IXFR_TOP/db.example.n4
+if [ $? -ne 0 ];
+then
+    exit 1
+fi
+
+# The pre-requisites for this test are the same as for the common tests, so
+# we can execute that directly.
+. ../common_tests.sh
+if [ $? -ne 0 ];
+then
+    exit 1
+fi
+
+# TEMPORARY: at the time of writing (October 2011) BIND 10 does not attempt
+# a UDP transfer first.  Therefore just check for TCP transfer.
+
+# Check that the client initiated and completed an IXFR.  Use a simple grep as
+# the syntax and capabilities of egrep may vary between systems.
+grep XFRIN_XFR_TRANSFER_STARTED nsx2/bind10.run | grep IXFR > /dev/null
+if [ $? -ne 0 ];
+then
+    echo "R:$CLIENT_NAME FAIL no 'IXFR started' message in the BIND 10 log"
+    exit 1
+fi
+
+grep XFRIN_XFR_TRANSFER_SUCCESS nsx2/bind10.run | grep IXFR > /dev/null
+if [ $? -ne 0 ];
+then
+    echo "R:$CLIENT_NAME FAIL no 'IXFR successful' message in the BIND 10 log"
+    exit 1
+fi
+
+# Look in the named log file to see if a TCP IXFR was requested.  Again use a
+# simple grep.
+grep "transfer of" ns1/named.run | grep "sending TCP message" > /dev/null
+if [ $? -ne 0 ];
+then
+    echo "R:$SERVER_NAME FAIL no 'sending TCP' message in the BIND 9 log"
+    exit 1
+fi
+
+grep "IXFR ended" ns1/named.run > /dev/null
+if [ $? -ne 0 ];
+then
+    echo "R:$SERVER_NAME FAIL no 'IXFR ended' message in the BIND 9 log"
+    exit 1
+fi
+
+echo "I:exit status: 0"
+exit 0
diff --git a/tests/system/ixfr/in-3/clean.sh b/tests/system/ixfr/in-3/clean.sh
new file mode 120000
index 0000000..099bebd
--- /dev/null
+++ b/tests/system/ixfr/in-3/clean.sh
@@ -0,0 +1 @@
+../clean_ns.sh
\ No newline at end of file
diff --git a/tests/system/ixfr/in-3/ns1/README b/tests/system/ixfr/in-3/ns1/README
new file mode 100644
index 0000000..aaa8a31
--- /dev/null
+++ b/tests/system/ixfr/in-3/ns1/README
@@ -0,0 +1,3 @@
+This directory should be empty. A README file is placed here to ensure git
+notes the directory's presence.  It can be removed if other files are placed
+here.
diff --git a/tests/system/ixfr/in-3/nsx2/README b/tests/system/ixfr/in-3/nsx2/README
new file mode 100644
index 0000000..aaa8a31
--- /dev/null
+++ b/tests/system/ixfr/in-3/nsx2/README
@@ -0,0 +1,3 @@
+This directory should be empty. A README file is placed here to ensure git
+notes the directory's presence.  It can be removed if other files are placed
+here.
diff --git a/tests/system/ixfr/in-3/setup.sh.in b/tests/system/ixfr/in-3/setup.sh.in
new file mode 100644
index 0000000..867e06e
--- /dev/null
+++ b/tests/system/ixfr/in-3/setup.sh.in
@@ -0,0 +1,29 @@
+#!/bin/sh
+#
+# 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.
+
+. @abs_top_builddir@/tests/system/conf.sh
+# Clean up from last time
+
+sh clean.sh
+
+# Set up the initial version of the IXFR server - load the latest version of
+# the zone.
+cp -f $IXFR_TOP/named_noixfr.conf ns1/named.conf
+cp -f $IXFR_TOP/db.example.n0 ns1/db.example
+
+# Set up the IXFR client - load a previous version of the zone.
+cp -f $IXFR_TOP/b10-config.db nsx2/b10-config.db
+${B10_LOADZONE} -o . -d $IXFR_TOP/zone.sqlite3 $IXFR_TOP/db.example.n2
diff --git a/tests/system/ixfr/in-3/tests.sh b/tests/system/ixfr/in-3/tests.sh
new file mode 100644
index 0000000..858b815
--- /dev/null
+++ b/tests/system/ixfr/in-3/tests.sh
@@ -0,0 +1,55 @@
+#!/bin/sh
+#
+# 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.
+
+# \file
+# This script performs the third IXFR-IN test.  A BIND 9 nameserver (the
+# "server") contains a version of the zone (version N) and has IXFRs disabled.
+# A BIND 10 nameserver (the "client") is loaded with version N-2 of the zone.
+# A NOTIFY is sent to it, and it is expected that it will send an IXFR to the
+# server; the server should not respond to the request, so the client should
+# then send an AXFR request and receive the latest copy of the zone.
+
+. ../ixfr_init.sh
+status=$?
+
+# Store the SOA serial number of the BIND 10 client for later use.
+old_client_serial=`$DIG_SOA @$CLIENT_IP | $AWK '{print $3}'`
+echo "I:SOA serial of IXFR client $CLIENT_NAME is $old_client_serial"
+
+# TODO: Need to alter configuration of BIND 10 server such that it accepts
+# NOTIFYs from and sends IXFR requests to the BIND 9 master.
+
+# If required, get the IXFR server to notify the IXFR client of the new zone.
+# Do this by allowing notifies and then triggering a re-notification of the
+# server.
+echo "I:notifying IXFR-client $CLIENT_NAME of presence of new version of zone"
+do_rndc $SERVER_NAME $SERVER_IP notify example
+status=`expr $status + $?`
+
+# Wait for the client to update itself.
+wait_for_update $CLIENT_NAME $CLIENT_IP $old_client_serial
+status=`expr $status + $?`
+
+# Has updated, get the latest serial of the client and server - they
+# should be the same.
+compare_soa $SERVER_NAME $SERVER_IP $CLIENT_NAME $CLIENT_IP
+status=`expr $status + $?`
+
+# TODO: Check the BIND 10 log, looking for the IXFR messages that indicate that
+# it has initiated an IXFR and then an AXFR.
+
+echo "I:exit status: $status"
+exit $status
diff --git a/tests/system/ixfr/in-4/clean.sh b/tests/system/ixfr/in-4/clean.sh
new file mode 120000
index 0000000..099bebd
--- /dev/null
+++ b/tests/system/ixfr/in-4/clean.sh
@@ -0,0 +1 @@
+../clean_ns.sh
\ No newline at end of file
diff --git a/tests/system/ixfr/in-4/ns1/README b/tests/system/ixfr/in-4/ns1/README
new file mode 100644
index 0000000..aaa8a31
--- /dev/null
+++ b/tests/system/ixfr/in-4/ns1/README
@@ -0,0 +1,3 @@
+This directory should be empty. A README file is placed here to ensure git
+notes the directory's presence.  It can be removed if other files are placed
+here.
diff --git a/tests/system/ixfr/in-4/nsx2/README b/tests/system/ixfr/in-4/nsx2/README
new file mode 100644
index 0000000..aaa8a31
--- /dev/null
+++ b/tests/system/ixfr/in-4/nsx2/README
@@ -0,0 +1,3 @@
+This directory should be empty. A README file is placed here to ensure git
+notes the directory's presence.  It can be removed if other files are placed
+here.
diff --git a/tests/system/ixfr/in-4/setup.sh.in b/tests/system/ixfr/in-4/setup.sh.in
new file mode 100644
index 0000000..7419e27
--- /dev/null
+++ b/tests/system/ixfr/in-4/setup.sh.in
@@ -0,0 +1,30 @@
+#!/bin/sh
+#
+# 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.
+
+. @abs_top_builddir@/tests/system/conf.sh
+# Clean up from last time
+
+sh clean.sh
+
+# Set up the initial version of the ixfr server - load the last-but-one version
+# of the zone.
+cp $IXFR_TOP/named_nonotify.conf ns1/named.conf
+cp -f $IXFR_TOP/db.example.n2.refresh ns1/db.example
+
+# Set up the IXFR client - load a previous version of the zone with a short
+# refresh time.
+cp -f $IXFR_TOP/b10-config.db nsx2/b10-config.db
+${B10_LOADZONE} -o . -d $IXFR_TOP/zone.sqlite3 $IXFR_TOP/db.example.n2.refresh
diff --git a/tests/system/ixfr/in-4/tests.sh b/tests/system/ixfr/in-4/tests.sh
new file mode 100644
index 0000000..3024253
--- /dev/null
+++ b/tests/system/ixfr/in-4/tests.sh
@@ -0,0 +1,53 @@
+#!/bin/sh
+#
+# 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.
+
+# \file
+# This script performs the fourth IXFR-IN test.  A BIND 9 nameserver (the
+# "server") contains a version of the zone (version N) and has IXFRs enabled.
+# A BIND 10 nameserver (the "client") is loaded with version N-2 of the zone
+# and a small refresh time.  After this expires, the IXFR client should send
+# an IXFR request to the IXFR server.
+
+. ../ixfr_init.sh
+status=$?
+
+# Ensure the server has the latest copy of the zone.  The implicit assumption
+# here is that starting the two systems and reloading the IXFR server takes
+# less time than the SOA refresh time set in the "db.example.n2.refresh" zone
+# file.
+cp $IXFR_TOP/db.example.n0 ns1/db.example
+do_rndc $SERVER_NAME $SERVER_IP reload
+
+# Store the SOA serial number of the BIND 10 client for later use.
+old_client_serial=`$DIG_SOA @$CLIENT_IP | $AWK '{print $3}'`
+echo "I:SOA serial of IXFR client $CLIENT_NAME is $old_client_serial"
+
+# Wait for the client to update itself. 30 seconds has been given as the
+# refresh interface and 2 seconds as the retry interval.  The wait_for_update
+# function will check for up to a minute looking for the new serial.
+wait_for_update $CLIENT_NAME $CLIENT_IP $old_client_serial
+status=`expr $status + $?`
+
+# Has updated, get the latest serial of the client and server - they
+# should be the same.
+compare_soa $SERVER_NAME $SERVER_IP $CLIENT_NAME $CLIENT_IP
+status=`expr $status + $?`
+
+# TODO: Check the BIND 10 log, looking for the IXFR messages that indicate that
+# the client has initiated the IXFR.
+
+echo "I:exit status: $status"
+exit $status
diff --git a/tests/system/ixfr/ixfr_init.sh.in b/tests/system/ixfr/ixfr_init.sh.in
new file mode 100644
index 0000000..ba6049e
--- /dev/null
+++ b/tests/system/ixfr/ixfr_init.sh.in
@@ -0,0 +1,330 @@
+#!/bin/sh
+#
+# Copyright (C) 2011  Internet Software Consortium.
+#
+# 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.
+
+# \file
+# This file should be run by all IXFR tests before doing anything else.  It
+# includes the main configuration script to set the environment variables as
+# well as defining useful shell subroutines.
+
+. @abs_top_builddir@/tests/system/conf.sh
+
+# Useful symbols used in the IXFR tests.
+
+# Short-hand for getting SOA - just supply address of the server
+DIG_SOA="$DIG +norecurse +short -p $DNS_PORT example. SOA"
+
+# All IXFR tests use a BIND 9 server serving a BIND 10 client.  These have the
+# smae name and use the same address in all tests.
+SERVER_NAME=ns1
+SERVER_IP=10.53.0.1   # BIND 9
+
+CLIENT_NAME=nsx2
+CLIENT_IP=10.53.0.2   # BIND 10
+
+# \brief Check Arguments
+#
+# Most functions take the name of  nameserver as the first argument and its IP
+# address as the second.  This function is passed "$*" and just checks that
+# both $1 and $2 are defined.
+#
+# \arg $* Arguments passed to caller
+#
+# \return status 0 => $1 and $2 are defined, 1 => they are not.
+check_name_ip() {
+
+    if [ "$1" = "" ];
+    then
+        echo "R:FAIL name of server not supplied"
+        return 1
+    fi
+
+    if [ "$2" = "" ];
+    then
+        echo "R:FAIL IP address of server not supplied"
+        return 1
+    fi
+
+    return 0
+}
+
+
+# \brief Perform RNDC Command
+#
+# Controls the BIND 9 IXFR server.  Called do_rndc (instead of rndc) to avoid
+# confusion if rndc itself is in the search path.
+#
+# \arg $1 - Name of the server (ns1, nsx2 etc.)
+# \arg $2 - IP address of the server
+# \arg $* - Command to execute (which may be multiple tokens)
+#
+# \return 0 on success, 1 on failure (in which case an error message will
+#         have been output).
+do_rndc () {
+
+    # If the following checks fail, the code is wrong.
+
+    check_name_ip $*
+    if [ $? -ne 0 ];
+    then
+        echo "R:FAIL do_rndc - name or ip address of server not supplied"
+        return 1
+    fi
+
+    name=$1
+    shift
+    ip=$1
+    shift
+
+    if [ "$1" = "" ];
+    then
+        echo "R:FAIL do_rndc - rndc command not supplied"
+        return 1
+    fi
+    
+    $RNDC -c $SYSTEM_TOP/common/rndc.conf -s $ip -p $RNDC_PORT $* 2>&1 \
+        | sed "s/^/I:$name /"
+}
+
+# \brief Wait for update
+#
+# Given a serial number and a server, poll the nameserver until the SOA serial
+# number is different from that given.  The poll takes place every five seconds
+# for a minute.
+#
+# \arg $1 - Name of the server
+# \arg $2 - IP address of the server
+# \arg $3 - Serial number to check against
+#
+# \return 0 if the serial number is different (requires another poll to obtain
+#         it), 1 if the serial number has not changed after one minute.
+wait_for_update() {
+
+    # If the following checks fail, the code is wrong.
+
+    check_name_ip $*
+    if [ $? -ne 0 ];
+    then
+        echo "R:FAIL wait_for_update - name or ip address of system not supplied"
+        return 1
+
+    fi
+
+    name=$1
+    shift
+    ip=$1
+    shift
+
+    serial=$1
+    if [ "$serial" = "" ];
+    then
+        echo "R:FAIL wait_for_update - serial number not supplied"
+        return 1
+    fi
+
+    # Now poll the server looking for the new serial number
+
+    echo "I:$name waiting for SOA serial to change from $serial"
+    for i in 1 2 3 4 5 6 7 8 9 10 11 12
+    do
+        if [ $i -gt 1 ];
+        then
+            sleep 5
+        fi
+
+        new_serial=`$DIG_SOA @$ip | $AWK '{print $3}'`
+        if [ "$new_serial" != "$serial" ];
+        then
+            echo "I:$name SOA serial was at $serial, now at $new_serial"
+            return 0
+        fi
+    done
+
+    echo "R:$name FAIL serial number has not updated"
+    return 1
+}
+
+
+
+# \brief Update server zone
+#
+# Reloads the example. zone in the BIND 9 IXFR server and waits a maximum of
+# one minute for it to be served.
+#
+# \arg $1 - Name of the server (ns1, nsx2 etc.)
+# \arg $2 - IP address of the server
+# \arg $3 - Zone file to load
+# \arg $* - Command to execute (which may be multiple tokens)
+#
+# \return 0 on success, 1 on failure (for which an error message will have
+#         been output).
+update_server_zone() {
+
+    # If the following checks fail, the code is wrong.
+
+    check_name_ip $*
+    if [ $? -ne 0 ];
+    then
+        echo "R:FAIL update_server_zone - name or ip address of server not supplied"
+        return 1
+    fi
+
+    name=$1
+    shift
+    ip=$1
+    shift
+
+    file=$1
+    shift
+    if [ "$file" = "" ];
+    then
+        echo "R:FAIL update_server_zone - new zone file not supplied"
+        return 1
+    fi
+
+    if [ ! -e $file ];
+    then
+        echo "R:FAIL update_server_zone - zone file does not exist: $file"
+        return 1
+    fi
+
+    old_serial=`$DIG_SOA @$ip | $AWK '{print $3}'`
+
+    echo "I:$name IXFR server loading $file"
+    cp $file $name/db.example
+    do_rndc $name $ip reload
+    if [ $? -ne 0 ];
+    then
+        return 1    # Message will have already been output
+    fi
+
+    wait_for_update $name $ip $old_serial
+    if [ $? -ne 0 ];
+    then
+        echo "R:$name FAIL IXFR server did not update zone after reload"
+        return 1
+    fi
+    new_serial=`$DIG_SOA @$ip | $AWK '{print $3}'`
+
+    return 0
+}
+
+# \brief Compare client and server SOAs
+#
+# Checks the SOAs of two systems and reports if they are not equal.
+#
+# \arg $1 Name of the IXFR server
+# \arg $2 IP of the IXFR server 
+# \arg $3 Name of the IXFR client
+# \arg $4 IP of the IXFR client
+#
+# \return 0 if the systems have the same SOA, 1 if not.  In the latter case,
+#         an error will be output.
+compare_soa() {
+
+    # If the following checks fail, the code is wrong.
+
+    check_name_ip $*
+    if [ $? -ne 0 ];
+    then
+        echo "R:FAIL compare_soa - name or ip address of server not supplied"
+        return 1
+    fi
+
+    server_name=$1
+    shift
+    server_ip=$1
+    shift
+
+    check_name_ip $*
+    if [ $? -ne 0 ];
+    then
+        echo "R:FAIL compare_soa - name or ip address of client not supplied"
+        return 1
+    fi
+
+    client_name=$1
+    shift
+    client_ip=$1
+    shift
+
+    client_serial=`$DIG_SOA @$client_ip | $AWK '{print $3}'`
+    server_serial=`$DIG_SOA @$server_ip | $AWK '{print $3}'`
+    if [ "$client_serial" != "$server_serial" ];
+    then
+        echo "R:FAIL client $client_name serial $client_serial not same as server $server_name serial $server_serial"
+        return 1
+    fi
+
+    return 0
+}
+
+# \brief Compare client and server zones
+#
+# Checks the zones of two systems and reports if they are not identical.
+#
+# The check is simplistic. Each zone is listed via "dig", after which comment
+# lines, blank lines and spaces/tabs are removed, and the result sorted.  The
+# output from each system is then compared.  They should be identical.
+#
+# \arg $1 Name of the IXFR server
+# \arg $2 IP of the IXFR server 
+# \arg $3 Name of the IXFR client
+# \arg $4 IP of the IXFR client
+#
+# \return 0 if the zones are the same, 1 if not.
+compare_zones() {
+
+    # If the following checks fail, the code is wrong.
+
+    check_name_ip $*
+    if [ $? -ne 0 ];
+    then
+        echo "R:FAIL compare_zones - name or ip address of server not supplied"
+        return 1
+    fi
+
+    server_name=$1
+    shift
+    server_ip=$1
+    shift
+
+    check_name_ip $*
+    if [ $? -ne 0 ];
+    then
+        echo "R:FAIL compare_zones - name or ip address of client not supplied"
+        return 1
+    fi
+
+    client_name=$1
+    shift
+    client_ip=$1
+    shift
+
+    $DIG @$client_ip -p $DNS_PORT example. axfr | grep -v '^;' | grep -v '^$' \
+         | sed -e 's/ //g' -e 's/\t//g' | sort > client.dig
+    $DIG @$server_ip -p $DNS_PORT example. axfr | grep -v '^;' | grep -v '^$' \
+         | sed -e 's/ //g' -e 's/\t//g' | sort > server.dig
+    diff client.dig server.dig
+    if [ $? -eq 0 ];
+    then
+        echo "I:client and server zones identical"
+    else
+        echo "R:FAIL client $client_name zone not same as server $server_name zone"
+        return 1
+    fi
+
+    return 0
+}
diff --git a/tests/system/ixfr/named_noixfr.conf b/tests/system/ixfr/named_noixfr.conf
new file mode 100644
index 0000000..b0d972a
--- /dev/null
+++ b/tests/system/ixfr/named_noixfr.conf
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2004, 2007, 2011  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * 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 "../../../common/rndc.key";
+
+controls {
+        inet 10.53.0.1 port 9953 allow { any; } keys { rndc_key; };
+};
+
+options {
+	query-source address 10.53.0.1;
+	notify-source 10.53.0.1;
+	transfer-source 10.53.0.1;
+	port 53210;
+	pid-file "named.pid";
+	listen-on { 10.53.0.1; };
+	listen-on-v6 { none; };
+	recursion no;
+	ixfr-from-differences no;
+	notify explicit;
+	also-notify { 10.53.0.2; };
+};
+
+zone "example" {
+	type master;
+	file "db.example";
+};
diff --git a/tests/system/ixfr/named_nonotify.conf b/tests/system/ixfr/named_nonotify.conf
new file mode 100644
index 0000000..c08c212
--- /dev/null
+++ b/tests/system/ixfr/named_nonotify.conf
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2004, 2007, 2011  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * 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 "../../../common/rndc.key";
+
+controls {
+        inet 10.53.0.1 port 9953 allow { any; } keys { rndc_key; };
+};
+
+options {
+	query-source address 10.53.0.1;
+	notify-source 10.53.0.1;
+	transfer-source 10.53.0.1;
+	port 53210;
+	pid-file "named.pid";
+	listen-on { 10.53.0.1; };
+	listen-on-v6 { none; };
+	recursion no;
+	ixfr-from-differences yes;
+	notify no;
+};
+
+zone "example" {
+	type master;
+	file "db.example";
+};
diff --git a/tests/system/ixfr/named_notify.conf b/tests/system/ixfr/named_notify.conf
new file mode 100644
index 0000000..df45e6f
--- /dev/null
+++ b/tests/system/ixfr/named_notify.conf
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2004, 2007, 2011  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * 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 "../../../common/rndc.key";
+
+controls {
+        inet 10.53.0.1 port 9953 allow { any; } keys { rndc_key; };
+};
+
+options {
+	query-source address 10.53.0.1;
+	notify-source 10.53.0.1;
+	transfer-source 10.53.0.1;
+	port 53210;
+	pid-file "named.pid";
+	listen-on { 10.53.0.1; };
+	listen-on-v6 { none; };
+	recursion no;
+	ixfr-from-differences yes;
+	notify explicit;
+	also-notify { 10.53.0.2; };
+};
+
+zone "example" {
+	type master;
+	file "db.example";
+};
diff --git a/tests/system/run.sh b/tests/system/run.sh
deleted file mode 100755
index 4f852f4..0000000
--- a/tests/system/run.sh
+++ /dev/null
@@ -1,125 +0,0 @@
-#!/bin/sh
-#
-# Copyright (C) 2004, 2007, 2010  Internet Systems Consortium, Inc. ("ISC")
-# Copyright (C) 2000, 2001  Internet Software Consortium.
-#
-# 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.
-
-#
-# Run a system test.
-#
-
-SYSTEMTESTTOP=.
-. $SYSTEMTESTTOP/conf.sh
-
-stopservers=true
-
-case $1 in
-   --keep) stopservers=false; shift ;;
-esac
-
-test $# -gt 0 || { echo "usage: $0 [--keep] test-directory" >&2; exit 1; }
-
-test=$1
-shift
-
-test -d $test || { echo "$0: $test: no such test" >&2; exit 1; }
-
-echo "S:$test:`date`" >&2
-echo "T:$test:1:A" >&2
-echo "A:System test $test" >&2
-
-if [ x$PERL = x ]
-then
-    echo "I:Perl not available.  Skipping test." >&2
-    echo "R:UNTESTED" >&2
-    echo "E:$test:`date`" >&2
-    exit 0;
-fi
-
-$PERL $TESTSOCK || {
-    echo "I:Network interface aliases not set up.  Skipping test." >&2;
-    echo "R:UNTESTED" >&2;
-    echo "E:$test:`date`" >&2;
-    exit 0;
-}
-
-
-# Check for test-specific prerequisites.
-test ! -f $test/prereq.sh || ( cd $test && sh prereq.sh "$@" )
-result=$?
-
-if [ $result -eq 0 ]; then
-    : prereqs ok
-else
-    echo "I:Prerequisites for $test missing, skipping test." >&2
-    [ $result -eq 255 ] && echo "R:SKIPPED" || echo "R:UNTESTED"
-    echo "E:$test:`date`" >&2
-    exit 0
-fi
-
-# Check for PKCS#11 support
-if
-    test ! -f $test/usepkcs11 || sh cleanpkcs11.sh
-then
-    : pkcs11 ok
-else
-    echo "I:Need PKCS#11 for $test, skipping test." >&2
-    echo "R:PKCS11ONLY" >&2
-    echo "E:$test:`date`" >&2
-    exit 0
-fi
-
-# Set up any dynamically generated test data
-if test -f $test/setup.sh
-then
-   ( cd $test && sh setup.sh "$@" )
-fi
-
-# Start name servers running
-$PERL start.pl $test || exit 1
-
-# Run the tests
-( cd $test ; sh tests.sh )
-
-status=$?
-
-if $stopservers
-then
-    :
-else
-    exit $status
-fi
-
-# Shutdown
-$PERL stop.pl $test
-
-status=`expr $status + $?`
-
-if [ $status != 0 ]; then
-	echo "R:FAIL"
-	# Don't clean up - we need the evidence.
-	find . -name core -exec chmod 0644 '{}' \;
-else
-	echo "R:PASS"
-
-	# Clean up.
-	if test -f $test/clean.sh
-	then
-	   ( cd $test && sh clean.sh "$@" )
-	fi
-fi
-
-echo "E:$test:`date`"
-
-exit $status
diff --git a/tests/system/run.sh.in b/tests/system/run.sh.in
new file mode 100755
index 0000000..619b865
--- /dev/null
+++ b/tests/system/run.sh.in
@@ -0,0 +1,125 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007, 2010  Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2000, 2001  Internet Software Consortium.
+#
+# 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.
+
+#
+# Run a system test.
+#
+
+SYSTEMTOP=@abs_top_builddir@/tests/system
+. $SYSTEMTOP/conf.sh
+
+stopservers=true
+
+case $1 in
+   --keep) stopservers=false; shift ;;
+esac
+
+test $# -gt 0 || { echo "usage: $0 [--keep] test-directory" >&2; exit 1; }
+
+test=$1
+shift
+
+test -d $test || { echo "$0: $test: no such test" >&2; exit 1; }
+
+echo "S:$test:`date`" >&2
+echo "T:$test:1:A" >&2
+echo "A:System test $test" >&2
+
+if [ x$PERL = x ]
+then
+    echo "I:Perl not available.  Skipping test." >&2
+    echo "R:UNTESTED" >&2
+    echo "E:$test:`date`" >&2
+    exit 0;
+fi
+
+$PERL $TESTSOCK || {
+    echo "I:Network interface aliases not set up.  Skipping test." >&2;
+    echo "R:UNTESTED" >&2;
+    echo "E:$test:`date`" >&2;
+    exit 0;
+}
+
+
+# Check for test-specific prerequisites.
+test ! -f $test/prereq.sh || ( cd $test && sh prereq.sh "$@" )
+result=$?
+
+if [ $result -eq 0 ]; then
+    : prereqs ok
+else
+    echo "I:Prerequisites for $test missing, skipping test." >&2
+    [ $result -eq 255 ] && echo "R:SKIPPED" || echo "R:UNTESTED"
+    echo "E:$test:`date`" >&2
+    exit 0
+fi
+
+# Check for PKCS#11 support
+if
+    test ! -f $test/usepkcs11 || sh cleanpkcs11.sh
+then
+    : pkcs11 ok
+else
+    echo "I:Need PKCS#11 for $test, skipping test." >&2
+    echo "R:PKCS11ONLY" >&2
+    echo "E:$test:`date`" >&2
+    exit 0
+fi
+
+# Set up any dynamically generated test data
+if test -f $test/setup.sh
+then
+   ( cd $test && sh setup.sh "$@" )
+fi
+
+# Start name servers running
+$PERL $SYSTEMTOP/start.pl $test || exit 1
+
+# Run the tests
+( cd $test ; sh tests.sh )
+
+status=$?
+
+if $stopservers
+then
+    :
+else
+    exit $status
+fi
+
+# Shutdown
+$PERL $SYSTEMTOP/stop.pl $test
+
+status=`expr $status + $?`
+
+if [ $status != 0 ]; then
+	echo "R:FAIL"
+	# Don't clean up - we need the evidence.
+	find . -name core -exec chmod 0644 '{}' \;
+else
+	echo "R:PASS"
+
+	# Clean up.
+	if test -f $test/clean.sh
+	then
+	   ( cd $test && sh clean.sh "$@" )
+	fi
+fi
+
+echo "E:$test:`date`"
+
+exit $status
diff --git a/tests/system/start.pl b/tests/system/start.pl
index 56f00c4..daa4577 100755
--- a/tests/system/start.pl
+++ b/tests/system/start.pl
@@ -53,7 +53,7 @@ if ($server && !-d "$test/$server") {
 my $topdir = abs_path("$test/..");
 my $testdir = abs_path("$test");
 my $RUN_BIND10 = $ENV{'RUN_BIND10'};
-my $NAMED = $ENV{'NAMED'};
+my $NAMED = $ENV{'BIND9_NAMED'};
 my $LWRESD = $ENV{'LWRESD'};
 my $DIG = $ENV{'DIG'};
 my $PERL = $ENV{'PERL'};
@@ -182,7 +182,7 @@ sub start_server {
 		exit 1;
 	}
 
-	#               print "I:starting server $server\n";
+	print "I:starting server $server\n";
 
 	chdir "$testdir/$server";
 
diff --git a/tests/tools/badpacket/Makefile.am b/tests/tools/badpacket/Makefile.am
index 61b76b2..fcba404 100644
--- a/tests/tools/badpacket/Makefile.am
+++ b/tests/tools/badpacket/Makefile.am
@@ -12,7 +12,7 @@ endif
 
 CLEANFILES = *.gcno *.gcda
 
-check_PROGRAMS  = badpacket
+noinst_PROGRAMS  = badpacket
 badpacket_SOURCES  = badpacket.cc
 badpacket_SOURCES += command_options.cc command_options.h
 badpacket_SOURCES += header_flags.h
diff --git a/tests/tools/badpacket/tests/Makefile.am b/tests/tools/badpacket/tests/Makefile.am
index a110e11..2daa664 100644
--- a/tests/tools/badpacket/tests/Makefile.am
+++ b/tests/tools/badpacket/tests/Makefile.am
@@ -29,4 +29,4 @@ run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
 run_unittests_LDADD += $(top_builddir)/src/lib/util/unittests/libutil_unittests.la
 endif
 
-check_PROGRAMS = $(TESTS)
+noinst_PROGRAMS = $(TESTS)




More information about the bind10-changes mailing list