BIND 10 trac738, updated. c021505a1a0d6ecb15a8fd1592b94baff6d115f4 [trac738] Merge branch 'master' into trac738

BIND 10 source code commits bind10-changes at lists.isc.org
Fri Jun 24 13:25:27 UTC 2011


The branch, trac738 has been updated
       via  c021505a1a0d6ecb15a8fd1592b94baff6d115f4 (commit)
       via  fef88019d325474471a353304499e7919023912e (commit)
       via  e6b3d50483fb739da2ca83e493a1c30043ba0464 (commit)
       via  3f15151252dd734210582a2ae8923dada661231f (commit)
       via  e53411af37a32d0c9b14515bd90c1e701c69f6e9 (commit)
       via  edea2125fa0791f920e3dd9e45c8aa0c9bfc6eb5 (commit)
       via  24a865aeec3048620dea967cba9bb1df28cfd052 (commit)
       via  6756ff6dacd40b74676b4243bc12ea02a43f3ae9 (commit)
       via  6722a4d52b519ed768fa70b31cdd10da868cacbc (commit)
       via  ca9e1e2997420dea3e3b14fea010ab0af3d75f32 (commit)
       via  5fe9e2f204d67a9ed65ab8fc2a1feb09f6700b5b (commit)
       via  13eb9e8620e67d7c617423ac1992a720ecdfbf7d (commit)
       via  bf41f8dc2265ca0cd9ffb8b8c11047291e69ca3c (commit)
       via  926a65fa08617be677a93e9e388df0f229b01067 (commit)
       via  1c7930a7ba19706d388e4f8dcf2a55a886b74cd2 (commit)
       via  96f093b960839b26ce37d9ff470933eed9c2b135 (commit)
       via  e828a215cc73946fa3681fcd88c3ef76b68272bd (commit)
       via  0bea88f134736d6fd2872f77feaf309aca6c1bc6 (commit)
       via  2d39d007d30f65589cfe4b671dc91cdab70ed107 (commit)
       via  e9798fc8931856a7eaeee37155600146d7dc7c57 (commit)
       via  59e01319e369a7c8e4f9a326d603dee7e3924c6b (commit)
       via  ad5a633a9e77e561675aca5263853db8161e82fa (commit)
       via  0eb494bd7c49f0559c870d8a687ad0552f2feeb7 (commit)
       via  f79a424a36d3a5896c43c5cae5d88d690ecbe90e (commit)
       via  a1301a0545acc48bf2f94731cb26577806e3c383 (commit)
       via  40cf6abada7f06648643b14b9b7db21d0fde3b27 (commit)
       via  c4430b49b30dcd74226d272fa3da4812afc2c6f7 (commit)
       via  4fae538655882db7c085dab798b4fb29c4a9d8f1 (commit)
       via  b5cfd5e541d4bbb7f13ad93392018711e19ba0e5 (commit)
       via  a2158e5b2c17043f0f3aa194009408aa73bd62ce (commit)
       via  85b06e8c212c9733cc77e71d8a72c72161dc34f2 (commit)
       via  4f87326ae6c17e26769b4ae276001b49d5bb3561 (commit)
       via  06c9c2a763326d4b30ff9448f726928538fba94c (commit)
       via  70af8c7c72300e1afe1974de22c117ff5566487d (commit)
       via  03e690228b6f5184d67a4ff3de56a861fcac9a23 (commit)
       via  d749aee2ec681e0304dd53c63f276af98edeaf31 (commit)
       via  f9a545ca4c82e51fc7c47793fec34eb5deb19e46 (commit)
       via  a4f1f8de765810aecff1194c74a108682e3de28e (commit)
       via  c4c85ce1694bd421912d1902f2d614c15bebbea1 (commit)
       via  f78cf6ebc22712c470da4af720915b09ae8e8ebe (commit)
       via  4c250f85ed6ad7f697c42137f1e67aadacf73dac (commit)
       via  941eceae0a54d023dce0c43757b0104b8adbcc9c (commit)
       via  79143dc457f23670d860a2fa134b13eb62db490b (commit)
       via  80dd433545aecf82aa178365dbc6e0650e12907b (commit)
       via  d867ca0fabdb5398d6a964aa393fadf678af2bbf (commit)
       via  3eb58c78cacf7686435e963d423c6c035a737bc0 (commit)
       via  e90d2063e0bd98767fdcd38962ad5be6f2eda68e (commit)
       via  0699e756aead6ec1b3a80f5e044d8c3cb35e3280 (commit)
       via  384501f85cc9e66a686a96e349241442af29a56b (commit)
       via  707e700d4861b2c47235183ce6e98d985819dd2d (commit)
       via  a9d549be7404552a13a95db041e7e1da64729341 (commit)
       via  3eb8c8e08c993b1458a6d79f434e0305936bcd14 (commit)
       via  6fe98e3c2a669c9dc779980426a81fbe1ddcfff3 (commit)
       via  edfe1b966d53caf3ed9e17cd525b0d94beff0aaf (commit)
       via  fd9334b7d856c4f748919d035b2a4ad3c85b545b (commit)
       via  0fdc040591f07f5f876ff2a16ea363e9026346ae (commit)
      from  fc29e92af2bd2cfe8fa77dd311b9382680fd6324 (commit)

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

- Log -----------------------------------------------------------------
commit c021505a1a0d6ecb15a8fd1592b94baff6d115f4
Merge: fc29e92af2bd2cfe8fa77dd311b9382680fd6324 fef88019d325474471a353304499e7919023912e
Author: Stephen Morris <stephen at isc.org>
Date:   Fri Jun 24 14:08:01 2011 +0100

    [trac738] Merge branch 'master' into trac738
    
    Conflicts:
    	src/bin/auth/main.cc

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

Summary of changes:
 ChangeLog                                          |   11 +
 doc/guide/bind10-guide.html                        |   46 ++-
 doc/guide/bind10-guide.xml                         |   35 ++-
 src/bin/auth/main.cc                               |    1 -
 src/bin/bind10/run_bind10.sh.in                    |    2 +-
 src/bin/bind10/tests/Makefile.am                   |    8 +
 src/bin/bindctl/run_bindctl.sh.in                  |    8 +
 src/bin/bindctl/tests/Makefile.am                  |    8 +
 src/bin/cfgmgr/plugins/tests/Makefile.am           |    2 +-
 src/bin/cfgmgr/tests/Makefile.am                   |    8 +
 src/bin/cmdctl/tests/Makefile.am                   |    8 +
 src/bin/loadzone/run_loadzone.sh.in                |    8 +
 src/bin/loadzone/tests/correct/Makefile.am         |    9 +-
 src/bin/loadzone/tests/error/Makefile.am           |    9 +-
 src/bin/msgq/tests/Makefile.am                     |    8 +
 src/bin/tests/Makefile.am                          |    8 +
 src/bin/xfrin/tests/Makefile.am                    |    4 +-
 src/bin/xfrout/tests/Makefile.am                   |    4 +-
 src/bin/xfrout/xfrout.py.in                        |    2 +-
 src/bin/zonemgr/tests/Makefile.am                  |    8 +
 src/lib/acl/Makefile.am                            |   26 +-
 src/lib/{datasrc/logger.cc => acl/dns.cc}          |   17 +-
 src/lib/acl/dns.h                                  |   89 ++++
 src/lib/{log/log_formatter.cc => acl/loader.cc}    |   40 +-
 src/lib/acl/loader.h                               |  404 +++++++++++++++++++
 src/lib/acl/tests/Makefile.am                      |    8 +-
 src/lib/acl/tests/acl_test.cc                      |   68 +---
 .../tests/dns_test.cc}                             |   27 +-
 src/lib/acl/tests/loader_test.cc                   |  426 ++++++++++++++++++++
 src/lib/acl/tests/logcheck.h                       |   86 ++++
 src/lib/asiodns/asiodef.mes                        |    8 +-
 src/lib/config/ccsession.cc                        |    6 +-
 src/lib/config/ccsession.h                         |   19 +
 src/lib/datasrc/cache.cc                           |   17 +-
 src/lib/datasrc/messagedef.mes                     |   22 +-
 src/lib/exceptions/exceptions.h                    |   11 +
 src/lib/log/logger.cc                              |   10 +-
 src/lib/log/logger.h                               |   29 +-
 src/lib/log/logger_impl.cc                         |    2 +-
 src/lib/log/logger_manager.cc                      |    4 +-
 src/lib/log/logger_support.cc                      |   47 ++-
 src/lib/log/logger_support.h                       |   24 +-
 src/lib/log/tests/Makefile.am                      |    1 +
 src/lib/log/tests/destination_test.sh.in           |   24 +-
 src/lib/log/tests/local_file_test.sh.in            |   39 +-
 src/lib/log/tests/logger_support_unittest.cc       |   72 ++++
 src/lib/log/tests/severity_test.sh.in              |   52 ++--
 src/lib/python/isc/cc/tests/Makefile.am            |    8 +
 src/lib/python/isc/config/ccsession.py             |   32 ++-
 src/lib/python/isc/config/tests/Makefile.am        |    9 +
 src/lib/python/isc/config/tests/ccsession_test.py  |   39 ++-
 src/lib/python/isc/datasrc/tests/Makefile.am       |    8 +
 src/lib/python/isc/log/Makefile.am                 |    3 +
 src/lib/python/isc/log/__init__.py                 |   10 +-
 src/lib/python/isc/log/log.cc                      |   63 +++-
 src/lib/python/isc/log/tests/Makefile.am           |    3 +-
 src/lib/python/isc/log/tests/console.out           |    8 +-
 src/lib/python/isc/log/tests/log_test.py           |   30 ++
 src/lib/python/isc/net/tests/Makefile.am           |    8 +
 src/lib/python/isc/notify/tests/Makefile.am        |    2 +-
 src/lib/python/isc/util/tests/Makefile.am          |    8 +
 61 files changed, 1746 insertions(+), 260 deletions(-)
 mode change 100644 => 100755 src/bin/bindctl/run_bindctl.sh.in
 mode change 100644 => 100755 src/bin/loadzone/run_loadzone.sh.in
 copy src/lib/{datasrc/logger.cc => acl/dns.cc} (71%)
 create mode 100644 src/lib/acl/dns.h
 copy src/lib/{log/log_formatter.cc => acl/loader.cc} (51%)
 create mode 100644 src/lib/acl/loader.h
 copy src/lib/{asiolink/tests/io_socket_unittest.cc => acl/tests/dns_test.cc} (57%)
 create mode 100644 src/lib/acl/tests/loader_test.cc
 create mode 100644 src/lib/acl/tests/logcheck.h
 create mode 100644 src/lib/log/tests/logger_support_unittest.cc

-----------------------------------------------------------------------
diff --git a/ChangeLog b/ChangeLog
index 6c6da37..3b1d518 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+260.	[func]      stephen
+	Remove comma between message identification and the message
+	text in the new-style logging messages.
+	(Trac 1031, git 1c7930a7ba19706d388e4f8dcf2a55a886b74cd2)
+
+259.	[bug]       stephen
+	Logging now correctly initialized in b10-auth.  Also, fixed
+	bug whereby querying for "version.bind txt ch" would cause
+	b10-auth to crash if BIND 10 was started with the "-v" switch.
+	(Trac 1022,1023, git 926a65fa08617be677a93e9e388df0f229b01067)
+
 258.	[build]		jelte
 	Now builds and runs with Python 3.2
 	(Trac #710, git dae1d2e24f993e1eef9ab429326652f40a006dfb)
diff --git a/doc/guide/bind10-guide.html b/doc/guide/bind10-guide.html
index 069f508..5b127f3 100644
--- a/doc/guide/bind10-guide.html
+++ b/doc/guide/bind10-guide.html
@@ -1,12 +1,12 @@
 <html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>BIND 10 Guide</title><link rel="stylesheet" href="./bind10-guide.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.75.2"><meta name="description" content="BIND 10 is a Domain Name System (DNS) suite managed by Internet Systems Consortium (ISC). It includes DNS libraries and modular components for controlling authoritative and recursive DNS servers. This is the reference guide for BIND 10 version 20110519. The most up-to-date version of this document, along with other documents for BIND 10, can be found at ."></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="book" title="BIND 10 Guide"><div class="titlepage"><div><div><h1 class="title"><a name="id1168230298903"></a>BIND 10 Guide</h1></div><div><h2 class="subtitle">Administrator Reference for BIND 10</h2></div><div><p class="releaseinfo">This is the referenc
 e guide for BIND 10 version
-        20110519.</p></div><div><p class="copyright">Copyright © 2010 Internet Systems Consortium, Inc.</p></div><div><div class="abstract" title="Abstract"><p class="title"><b>Abstract</b></p><p>BIND 10 is a Domain Name System (DNS) suite managed by
+        20110519.</p></div><div><p class="copyright">Copyright © 2010-2011 Internet Systems Consortium, Inc.</p></div><div><div class="abstract" title="Abstract"><p class="title"><b>Abstract</b></p><p>BIND 10 is a Domain Name System (DNS) suite managed by
 	Internet Systems Consortium (ISC). It includes DNS libraries
 	and modular components for controlling authoritative and
 	recursive DNS servers.
       </p><p>
         This is the reference guide for BIND 10 version 20110519.
 	The most up-to-date version of this document, along with
-	other documents for BIND 10, can be found at <a class="ulink" href="http://bind10.isc.org/docs" target="_top">http://bind10.isc.org/docs</a>.  </p></div></div></div><hr></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="chapter"><a href="#intro">1. Introduction</a></span></dt><dd><dl><dt><span class="section"><a href="#id1168230299038">Supported Platforms</a></span></dt><dt><span class="section"><a href="#id1168230299065">Required Software</a></span></dt><dt><span class="section"><a href="#starting_stopping">Starting and Stopping the Server</a></span></dt><dt><span class="section"><a href="#managing_once_running">Managing BIND 10</a></span></dt></dl></dd><dt><span class="chapter"><a href="#installation">2. Installation</a></span></dt><dd><dl><dt><span class="section"><a href="#id1168230284846">Building Requirements</a></span></dt><dt><span class="section"><a href="#quickstart">Quick start</a></span></dt><dt><span class="section"><a href="#install">In
 stallation from source</a></span></dt><dd><dl><dt><span class="section"><a href="#id1168230285026">Download Tar File</a></span></dt><dt><span class="section"><a href="#id1168230285045">Retrieve from Git</a></span></dt><dt><span class="section"><a href="#id1168230285106">Configure before the build</a></span></dt><dt><span class="section"><a href="#id1168230285203">Build</a></span></dt><dt><span class="section"><a href="#id1168230285219">Install</a></span></dt><dt><span class="section"><a href="#id1168230285242">Install Hierarchy</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a href="#bind10">3. Starting BIND10 with <span class="command"><strong>bind10</strong></span></a></span></dt><dd><dl><dt><span class="section"><a href="#start">Starting BIND 10</a></span></dt></dl></dd><dt><span class="chapter"><a href="#msgq">4. Command channel</a></span></dt><dt><span class="chapter"><a href="#cfgmgr">5. Configuration manager</a></span></dt><dt><span class="chapter"><a hr
 ef="#cmdctl">6. Remote control daemon</a></span></dt><dd><dl><dt><span class="section"><a href="#cmdctl.spec">Configuration specification for b10-cmdctl</a></span></dt></dl></dd><dt><span class="chapter"><a href="#bindctl">7. Control and configure user interface</a></span></dt><dt><span class="chapter"><a href="#authserver">8. Authoritative Server</a></span></dt><dd><dl><dt><span class="section"><a href="#id1168230285816">Server Configurations</a></span></dt><dt><span class="section"><a href="#id1168230285881">Data Source Backends</a></span></dt><dt><span class="section"><a href="#id1168230285912">Loading Master Zones Files</a></span></dt></dl></dd><dt><span class="chapter"><a href="#xfrin">9. Incoming Zone Transfers</a></span></dt><dt><span class="chapter"><a href="#xfrout">10. Outbound Zone Transfers</a></span></dt><dt><span class="chapter"><a href="#zonemgr">11. Secondary Manager</a></span></dt><dt><span class="chapter"><a href="#resolverserver">12. Recursive Name Server<
 /a></span></dt><dd><dl><dt><span class="section"><a href="#id1168230286300">Forwarding</a></span></dt></dl></dd><dt><span class="chapter"><a href="#statistics">13. Statistics</a></span></dt></dl></div><div class="chapter" title="Chapter 1. Introduction"><div class="titlepage"><div><div><h2 class="title"><a name="intro"></a>Chapter 1. Introduction</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="section"><a href="#id1168230299038">Supported Platforms</a></span></dt><dt><span class="section"><a href="#id1168230299065">Required Software</a></span></dt><dt><span class="section"><a href="#starting_stopping">Starting and Stopping the Server</a></span></dt><dt><span class="section"><a href="#managing_once_running">Managing BIND 10</a></span></dt></dl></div><p>
+	other documents for BIND 10, can be found at <a class="ulink" href="http://bind10.isc.org/docs" target="_top">http://bind10.isc.org/docs</a>.  </p></div></div></div><hr></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="chapter"><a href="#intro">1. Introduction</a></span></dt><dd><dl><dt><span class="section"><a href="#id1168230299038">Supported Platforms</a></span></dt><dt><span class="section"><a href="#id1168230299065">Required Software</a></span></dt><dt><span class="section"><a href="#starting_stopping">Starting and Stopping the Server</a></span></dt><dt><span class="section"><a href="#managing_once_running">Managing BIND 10</a></span></dt></dl></dd><dt><span class="chapter"><a href="#installation">2. Installation</a></span></dt><dd><dl><dt><span class="section"><a href="#id1168230284848">Building Requirements</a></span></dt><dt><span class="section"><a href="#quickstart">Quick start</a></span></dt><dt><span class="section"><a href="#install">In
 stallation from source</a></span></dt><dd><dl><dt><span class="section"><a href="#id1168230285037">Download Tar File</a></span></dt><dt><span class="section"><a href="#id1168230285057">Retrieve from Git</a></span></dt><dt><span class="section"><a href="#id1168230285117">Configure before the build</a></span></dt><dt><span class="section"><a href="#id1168230285216">Build</a></span></dt><dt><span class="section"><a href="#id1168230285230">Install</a></span></dt><dt><span class="section"><a href="#id1168230285254">Install Hierarchy</a></span></dt></dl></dd></dl></dd><dt><span class="chapter"><a href="#bind10">3. Starting BIND10 with <span class="command"><strong>bind10</strong></span></a></span></dt><dd><dl><dt><span class="section"><a href="#start">Starting BIND 10</a></span></dt></dl></dd><dt><span class="chapter"><a href="#msgq">4. Command channel</a></span></dt><dt><span class="chapter"><a href="#cfgmgr">5. Configuration manager</a></span></dt><dt><span class="chapter"><a hr
 ef="#cmdctl">6. Remote control daemon</a></span></dt><dd><dl><dt><span class="section"><a href="#cmdctl.spec">Configuration specification for b10-cmdctl</a></span></dt></dl></dd><dt><span class="chapter"><a href="#bindctl">7. Control and configure user interface</a></span></dt><dt><span class="chapter"><a href="#authserver">8. Authoritative Server</a></span></dt><dd><dl><dt><span class="section"><a href="#id1168230285829">Server Configurations</a></span></dt><dt><span class="section"><a href="#id1168230285894">Data Source Backends</a></span></dt><dt><span class="section"><a href="#id1168230285924">Loading Master Zones Files</a></span></dt></dl></dd><dt><span class="chapter"><a href="#xfrin">9. Incoming Zone Transfers</a></span></dt><dt><span class="chapter"><a href="#xfrout">10. Outbound Zone Transfers</a></span></dt><dt><span class="chapter"><a href="#zonemgr">11. Secondary Manager</a></span></dt><dt><span class="chapter"><a href="#resolverserver">12. Recursive Name Server<
 /a></span></dt><dd><dl><dt><span class="section"><a href="#id1168230286380">Forwarding</a></span></dt></dl></dd><dt><span class="chapter"><a href="#statistics">13. Statistics</a></span></dt></dl></div><div class="chapter" title="Chapter 1. Introduction"><div class="titlepage"><div><div><h2 class="title"><a name="intro"></a>Chapter 1. Introduction</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="section"><a href="#id1168230299038">Supported Platforms</a></span></dt><dt><span class="section"><a href="#id1168230299065">Required Software</a></span></dt><dt><span class="section"><a href="#starting_stopping">Starting and Stopping the Server</a></span></dt><dt><span class="section"><a href="#managing_once_running">Managing BIND 10</a></span></dt></dl></div><p>
       BIND is the popular implementation of a DNS server, developer
       interfaces, and DNS tools.
       BIND 10 is a rewrite of BIND 9.  BIND 10 is written in C++ and Python
@@ -33,8 +33,10 @@
         3.1 is the minimum version which will work.
       </p><p>
 	BIND 10 uses the Botan crypto library for C++. It requires
-	at least Botan version 1.8. To build BIND 10, install the
-	Botan libraries and development include headers.
+	at least Botan version 1.8.
+      </p><p>
+	BIND 10 uses the log4cplus C++ logging library. It requires
+	at least log4cplus version 1.0.3.
       </p><p>
 	The authoritative server requires SQLite 3.3.9 or newer.
 	The <span class="command"><strong>b10-xfrin</strong></span>, <span class="command"><strong>b10-xfrout</strong></span>,
@@ -136,7 +138,10 @@
       and, of course, DNS. These include detailed developer
       documentation and code examples.
 
-    </p></div><div class="chapter" title="Chapter 2. Installation"><div class="titlepage"><div><div><h2 class="title"><a name="installation"></a>Chapter 2. Installation</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="section"><a href="#id1168230284846">Building Requirements</a></span></dt><dt><span class="section"><a href="#quickstart">Quick start</a></span></dt><dt><span class="section"><a href="#install">Installation from source</a></span></dt><dd><dl><dt><span class="section"><a href="#id1168230285026">Download Tar File</a></span></dt><dt><span class="section"><a href="#id1168230285045">Retrieve from Git</a></span></dt><dt><span class="section"><a href="#id1168230285106">Configure before the build</a></span></dt><dt><span class="section"><a href="#id1168230285203">Build</a></span></dt><dt><span class="section"><a href="#id1168230285219">Install</a></span></dt><dt><span class="section"><a href="#id1168230285242">Install Hierarchy<
 /a></span></dt></dl></dd></dl></div><div class="section" title="Building Requirements"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id1168230284846"></a>Building Requirements</h2></div></div></div><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>
+    </p></div><div class="chapter" title="Chapter 2. Installation"><div class="titlepage"><div><div><h2 class="title"><a name="installation"></a>Chapter 2. Installation</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="section"><a href="#id1168230284848">Building Requirements</a></span></dt><dt><span class="section"><a href="#quickstart">Quick start</a></span></dt><dt><span class="section"><a href="#install">Installation from source</a></span></dt><dd><dl><dt><span class="section"><a href="#id1168230285037">Download Tar File</a></span></dt><dt><span class="section"><a href="#id1168230285057">Retrieve from Git</a></span></dt><dt><span class="section"><a href="#id1168230285117">Configure before the build</a></span></dt><dt><span class="section"><a href="#id1168230285216">Build</a></span></dt><dt><span class="section"><a href="#id1168230285230">Install</a></span></dt><dt><span class="section"><a href="#id1168230285254">Install Hierarchy<
 /a></span></dt></dl></dd></dl></div><div class="section" title="Building Requirements"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id1168230284848"></a>Building Requirements</h2></div></div></div><p>
+          In addition to the run-time requirements, building BIND 10
+          from source code requires various development include headers.
+        </p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>
             Some operating systems have split their distribution packages into
             a run-time and a development package.  You will need to install
             the development package versions, which include header files and
@@ -147,6 +152,11 @@
   
   
         </p><p>
+	  To build BIND 10, also install the Botan (at least version
+	  1.8) and the log4cplus (at least version 1.0.3)
+          development include headers.
+        </p><p>
+
 	  The Python Library and Python _sqlite3 module are required to
           enable the Xfrout and Xfrin support.
         </p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>
@@ -156,7 +166,7 @@
           Building BIND 10 also requires a C++ compiler and
           standard development headers, make, and pkg-config.
           BIND 10 builds have been tested with GCC g++ 3.4.3, 4.1.2,
-          4.1.3, 4.2.1, 4.3.2, and 4.4.1.
+          4.1.3, 4.2.1, 4.3.2, and 4.4.1; Clang++ 2.8; and Sun C++ 5.10.
         </p></div><div class="section" title="Quick start"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="quickstart"></a>Quick start</h2></div></div></div><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>
           This quickly covers the standard steps for installing
           and deploying BIND 10 as an authoritative name server using
@@ -192,14 +202,14 @@
         the Git code revision control system or as a downloadable
         tar file. It may also be available in pre-compiled ready-to-use
         packages from operating system vendors.
-      </p><div class="section" title="Download Tar File"><div class="titlepage"><div><div><h3 class="title"><a name="id1168230285026"></a>Download Tar File</h3></div></div></div><p>
+      </p><div class="section" title="Download Tar File"><div class="titlepage"><div><div><h3 class="title"><a name="id1168230285037"></a>Download Tar File</h3></div></div></div><p>
           Downloading a release tar file is the recommended method to
           obtain the source code.
         </p><p>
           The BIND 10 releases are available as tar file downloads from
           <a class="ulink" href="ftp://ftp.isc.org/isc/bind10/" target="_top">ftp://ftp.isc.org/isc/bind10/</a>.
           Periodic development snapshots may also be available.
-        </p></div><div class="section" title="Retrieve from Git"><div class="titlepage"><div><div><h3 class="title"><a name="id1168230285045"></a>Retrieve from Git</h3></div></div></div><p>
+        </p></div><div class="section" title="Retrieve from Git"><div class="titlepage"><div><div><h3 class="title"><a name="id1168230285057"></a>Retrieve from Git</h3></div></div></div><p>
           Downloading this "bleeding edge" code is recommended only for
           developers or advanced users.  Using development code in a production
           environment is not recommended.
@@ -233,7 +243,7 @@
           <span class="command"><strong>autoheader</strong></span>,
           <span class="command"><strong>automake</strong></span>,
           and related commands.
-        </p></div><div class="section" title="Configure before the build"><div class="titlepage"><div><div><h3 class="title"><a name="id1168230285106"></a>Configure before the build</h3></div></div></div><p>
+        </p></div><div class="section" title="Configure before the build"><div class="titlepage"><div><div><h3 class="title"><a name="id1168230285117"></a>Configure before the build</h3></div></div></div><p>
           BIND 10 uses the GNU Build System to discover build environment
           details.
           To generate the makefiles using the defaults, simply run:
@@ -264,16 +274,16 @@
         </p><p>
           If the configure fails, it may be due to missing or old
           dependencies.
-        </p></div><div class="section" title="Build"><div class="titlepage"><div><div><h3 class="title"><a name="id1168230285203"></a>Build</h3></div></div></div><p>
+        </p></div><div class="section" title="Build"><div class="titlepage"><div><div><h3 class="title"><a name="id1168230285216"></a>Build</h3></div></div></div><p>
     After the configure step is complete, to build the executables
     from the C++ code and prepare the Python scripts, run:
 
           </p><pre class="screen">$ <strong class="userinput"><code>make</code></strong></pre><p>
-        </p></div><div class="section" title="Install"><div class="titlepage"><div><div><h3 class="title"><a name="id1168230285219"></a>Install</h3></div></div></div><p>
+        </p></div><div class="section" title="Install"><div class="titlepage"><div><div><h3 class="title"><a name="id1168230285230"></a>Install</h3></div></div></div><p>
           To install the BIND 10 executables, support files,
           and documentation, run:
           </p><pre class="screen">$ <strong class="userinput"><code>make install</code></strong></pre><p>
-        </p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>The install step may require superuser privileges.</p></div></div><div class="section" title="Install Hierarchy"><div class="titlepage"><div><div><h3 class="title"><a name="id1168230285242"></a>Install Hierarchy</h3></div></div></div><p>
+        </p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>The install step may require superuser privileges.</p></div></div><div class="section" title="Install Hierarchy"><div class="titlepage"><div><div><h3 class="title"><a name="id1168230285254"></a>Install Hierarchy</h3></div></div></div><p>
           The following is the layout of the complete BIND 10 installation:
           </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">
                 <code class="filename">bin/</code> —
@@ -490,12 +500,12 @@ shutdown
       the details and relays (over a <span class="command"><strong>b10-msgq</strong></span> command
       channel) the configuration on to the specified module.
     </p><p>
-    </p></div><div class="chapter" title="Chapter 8. Authoritative Server"><div class="titlepage"><div><div><h2 class="title"><a name="authserver"></a>Chapter 8. Authoritative Server</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="section"><a href="#id1168230285816">Server Configurations</a></span></dt><dt><span class="section"><a href="#id1168230285881">Data Source Backends</a></span></dt><dt><span class="section"><a href="#id1168230285912">Loading Master Zones Files</a></span></dt></dl></div><p>
+    </p></div><div class="chapter" title="Chapter 8. Authoritative Server"><div class="titlepage"><div><div><h2 class="title"><a name="authserver"></a>Chapter 8. Authoritative Server</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="section"><a href="#id1168230285829">Server Configurations</a></span></dt><dt><span class="section"><a href="#id1168230285894">Data Source Backends</a></span></dt><dt><span class="section"><a href="#id1168230285924">Loading Master Zones Files</a></span></dt></dl></div><p>
       The <span class="command"><strong>b10-auth</strong></span> is the authoritative DNS server.
       It supports EDNS0 and DNSSEC. It supports IPv6.
       Normally it is started by the <span class="command"><strong>bind10</strong></span> master
       process.
-    </p><div class="section" title="Server Configurations"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id1168230285816"></a>Server Configurations</h2></div></div></div><p>
+    </p><div class="section" title="Server Configurations"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id1168230285829"></a>Server Configurations</h2></div></div></div><p>
         <span class="command"><strong>b10-auth</strong></span> is configured via the
         <span class="command"><strong>b10-cfgmgr</strong></span> configuration manager.
         The module name is <span class="quote">“<span class="quote">Auth</span>”</span>.
@@ -515,7 +525,7 @@ This may be a temporary setting until then.
         </p><div class="variablelist"><dl><dt><span class="term">shutdown</span></dt><dd>Stop the authoritative DNS server.
               </dd></dl></div><p>
 
-      </p></div><div class="section" title="Data Source Backends"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id1168230285881"></a>Data Source Backends</h2></div></div></div><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>
+      </p></div><div class="section" title="Data Source Backends"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id1168230285894"></a>Data Source Backends</h2></div></div></div><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>
         For the development prototype release, <span class="command"><strong>b10-auth</strong></span>
         supports a SQLite3 data source backend and in-memory data source
         backend.
@@ -529,7 +539,7 @@ This may be a temporary setting until then.
         The default is <code class="filename">/usr/local/var/</code>.)
   This data file location may be changed by defining the
   <span class="quote">“<span class="quote">database_file</span>”</span> configuration.
-      </p></div><div class="section" title="Loading Master Zones Files"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id1168230285912"></a>Loading Master Zones Files</h2></div></div></div><p>
+      </p></div><div class="section" title="Loading Master Zones Files"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id1168230285924"></a>Loading Master Zones Files</h2></div></div></div><p>
         RFC 1035 style DNS master zone files may imported
         into a BIND 10 data source by using the
         <span class="command"><strong>b10-loadzone</strong></span> utility.
@@ -607,7 +617,7 @@ This may be a temporary setting until then.
     </p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>
      Access control (such as allowing notifies) is not yet provided.
      The primary/secondary service is not yet complete.
-    </p></div></div><div class="chapter" title="Chapter 12. Recursive Name Server"><div class="titlepage"><div><div><h2 class="title"><a name="resolverserver"></a>Chapter 12. Recursive Name Server</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="section"><a href="#id1168230286300">Forwarding</a></span></dt></dl></div><p>
+    </p></div></div><div class="chapter" title="Chapter 12. Recursive Name Server"><div class="titlepage"><div><div><h2 class="title"><a name="resolverserver"></a>Chapter 12. Recursive Name Server</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="section"><a href="#id1168230286380">Forwarding</a></span></dt></dl></div><p>
       The <span class="command"><strong>b10-resolver</strong></span> process is started by
       <span class="command"><strong>bind10</strong></span>.
 
@@ -636,7 +646,7 @@ This may be a temporary setting until then.
 > <strong class="userinput"><code>config set Resolver/listen_on [{ "address": "127.0.0.1", "port": 53 }]</code></strong>
 > <strong class="userinput"><code>config commit</code></strong>
 </pre><p>
-    </p><div class="section" title="Forwarding"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id1168230286300"></a>Forwarding</h2></div></div></div><p>
+    </p><div class="section" title="Forwarding"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id1168230286380"></a>Forwarding</h2></div></div></div><p>
 
         To enable forwarding, the upstream address and port must be
         configured to forward queries to, such as:
diff --git a/doc/guide/bind10-guide.xml b/doc/guide/bind10-guide.xml
index 5eb4dc7..eb6fea0 100644
--- a/doc/guide/bind10-guide.xml
+++ b/doc/guide/bind10-guide.xml
@@ -13,7 +13,7 @@
     <subtitle>Administrator Reference for BIND 10</subtitle>
 
     <copyright>
-      <year>2010</year><holder>Internet Systems Consortium, Inc.</holder>
+      <year>2010-2011</year><holder>Internet Systems Consortium, Inc.</holder>
     </copyright>
 
     <abstract>
@@ -81,15 +81,13 @@
 
       <para>
 	BIND 10 uses the Botan crypto library for C++. It requires
-	at least Botan version 1.8. To build BIND 10, install the
-	Botan libraries and development include headers.
+	at least Botan version 1.8.
       </para>
 
-<!--
-TODO
-Debian and Ubuntu:
- libgmp3-dev and libbz2-dev required for botan too
--->
+      <para>
+	BIND 10 uses the log4cplus C++ logging library. It requires
+	at least log4cplus version 1.0.3.
+      </para>
 
       <para>
 	The authoritative server requires SQLite 3.3.9 or newer.
@@ -303,6 +301,12 @@ var/
 
     <section>
       <title>Building Requirements</title>
+
+        <para>
+          In addition to the run-time requirements, building BIND 10
+          from source code requires various development include headers.
+        </para>
+
         <note>
           <simpara>
             Some operating systems have split their distribution packages into
@@ -320,6 +324,19 @@ var/
         </para>
 
         <para>
+	  To build BIND 10, also install the Botan (at least version
+	  1.8) and the log4cplus (at least version 1.0.3)
+          development include headers.
+        </para>
+
+<!--
+TODO
+Debian and Ubuntu:
+ libgmp3-dev and libbz2-dev required for botan too
+-->
+
+        <para>
+<!-- TODO: is this needed at build time? test time? -->
 	  The Python Library and Python _sqlite3 module are required to
           enable the Xfrout and Xfrin support.
         </para>
@@ -333,7 +350,7 @@ var/
           Building BIND 10 also requires a C++ compiler and
           standard development headers, make, and pkg-config.
           BIND 10 builds have been tested with GCC g++ 3.4.3, 4.1.2,
-          4.1.3, 4.2.1, 4.3.2, and 4.4.1.
+          4.1.3, 4.2.1, 4.3.2, and 4.4.1; Clang++ 2.8; and Sun C++ 5.10.
         </para>
     </section>
 
diff --git a/src/bin/auth/main.cc b/src/bin/auth/main.cc
index 07c1bfa..c8f6762 100644
--- a/src/bin/auth/main.cc
+++ b/src/bin/auth/main.cc
@@ -47,7 +47,6 @@
 #include <auth/auth_log.h>
 #include <asiodns/asiodns.h>
 #include <asiolink/asiolink.h>
-
 #include <log/logger_support.h>
 #include <server_common/keyring.h>
 
diff --git a/src/bin/bind10/run_bind10.sh.in b/src/bin/bind10/run_bind10.sh.in
index 89301bd..3a36e01 100755
--- a/src/bin/bind10/run_bind10.sh.in
+++ b/src/bin/bind10/run_bind10.sh.in
@@ -30,7 +30,7 @@ export PYTHONPATH
 # required by loadable python modules.
 SET_ENV_LIBRARY_PATH=@SET_ENV_LIBRARY_PATH@
 if test $SET_ENV_LIBRARY_PATH = yes; then
-	@ENV_LIBRARY_PATH@=@abs_top_builddir@/src/lib/dns/.libs:@abs_top_builddir@/src/lib/cryptolink/.libs:@abs_top_builddir@/src/lib/util/.libs:@abs_top_builddir@/src/lib/util/io/.libs:@abs_top_builddir@/src/lib/exceptions/.libs:$@ENV_LIBRARY_PATH@
+	@ENV_LIBRARY_PATH@=@abs_top_builddir@/src/lib/dns/.libs:@abs_top_builddir@/src/lib/cryptolink/.libs:@abs_top_builddir@/src/lib/cc/.libs:@abs_top_builddir@/src/lib/config/.libs:@abs_top_builddir@/src/lib/log/.libs:@abs_top_builddir@/src/lib/util/.libs:@abs_top_builddir@/src/lib/util/io/.libs:@abs_top_builddir@/src/lib/exceptions/.libs:$@ENV_LIBRARY_PATH@
 	export @ENV_LIBRARY_PATH@
 fi
 
diff --git a/src/bin/bind10/tests/Makefile.am b/src/bin/bind10/tests/Makefile.am
index 34d809a..3d8d57a 100644
--- a/src/bin/bind10/tests/Makefile.am
+++ b/src/bin/bind10/tests/Makefile.am
@@ -4,6 +4,13 @@ PYCOVERAGE_RUN = @PYCOVERAGE_RUN@
 PYTESTS = bind10_test.py
 EXTRA_DIST = $(PYTESTS)
 
+# If necessary (rare cases), explicitly specify paths to dynamic libraries
+# required by loadable python modules.
+LIBRARY_PATH_PLACEHOLDER =
+if SET_ENV_LIBRARY_PATH
+LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/cc/.libs:$(abs_top_builddir)/src/lib/config/.libs:$(abs_top_builddir)/src/lib/log/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$$$(ENV_LIBRARY_PATH)
+endif
+
 # test using command-line arguments, so use check-local target instead of TESTS
 check-local:
 if ENABLE_PYTHON_COVERAGE
@@ -13,6 +20,7 @@ if ENABLE_PYTHON_COVERAGE
 endif
 	for pytest in $(PYTESTS) ; do \
 	echo Running test: $$pytest ; \
+	$(LIBRARY_PATH_PLACEHOLDER) \
 	env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/bin/bind10 \
 	BIND10_MSGQ_SOCKET_FILE=$(abs_top_builddir)/msgq_socket \
 		$(PYCOVERAGE_RUN) $(abs_builddir)/$$pytest || exit ; \
diff --git a/src/bin/bindctl/run_bindctl.sh.in b/src/bin/bindctl/run_bindctl.sh.in
old mode 100644
new mode 100755
index 730ce1e..8f6ba59
--- a/src/bin/bindctl/run_bindctl.sh.in
+++ b/src/bin/bindctl/run_bindctl.sh.in
@@ -23,6 +23,14 @@ BINDCTL_PATH=@abs_top_builddir@/src/bin/bindctl
 PYTHONPATH=@abs_top_srcdir@/src/bin:@abs_top_builddir@/src/lib/python:@abs_top_builddir@/src/bin:@abs_top_srcdir@/src/lib/python
 export PYTHONPATH
 
+# If necessary (rare cases), explicitly specify paths to dynamic libraries
+# required by loadable python modules.
+SET_ENV_LIBRARY_PATH=@SET_ENV_LIBRARY_PATH@
+if test $SET_ENV_LIBRARY_PATH = yes; then
+	@ENV_LIBRARY_PATH@=@abs_top_builddir@/src/lib/dns/.libs:@abs_top_builddir@/src/lib/cryptolink/.libs:@abs_top_builddir@/src/lib/cc/.libs:@abs_top_builddir@/src/lib/config/.libs:@abs_top_builddir@/src/lib/log/.libs:@abs_top_builddir@/src/lib/util/.libs:@abs_top_builddir@/src/lib/util/io/.libs:@abs_top_builddir@/src/lib/exceptions/.libs:$@ENV_LIBRARY_PATH@
+	export @ENV_LIBRARY_PATH@
+fi
+
 B10_FROM_SOURCE=@abs_top_srcdir@
 export B10_FROM_SOURCE
 
diff --git a/src/bin/bindctl/tests/Makefile.am b/src/bin/bindctl/tests/Makefile.am
index d2bb90f..891d413 100644
--- a/src/bin/bindctl/tests/Makefile.am
+++ b/src/bin/bindctl/tests/Makefile.am
@@ -2,6 +2,13 @@ PYCOVERAGE_RUN = @PYCOVERAGE_RUN@
 PYTESTS = bindctl_test.py cmdparse_test.py
 EXTRA_DIST = $(PYTESTS)
 
+# If necessary (rare cases), explicitly specify paths to dynamic libraries
+# required by loadable python modules.
+LIBRARY_PATH_PLACEHOLDER =
+if SET_ENV_LIBRARY_PATH
+LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/cc/.libs:$(abs_top_builddir)/src/lib/config/.libs:$(abs_top_builddir)/src/lib/log/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$$$(ENV_LIBRARY_PATH)
+endif
+
 # test using command-line arguments, so use check-local target instead of TESTS
 check-local:
 if ENABLE_PYTHON_COVERAGE
@@ -11,6 +18,7 @@ if ENABLE_PYTHON_COVERAGE
 endif
 	for pytest in $(PYTESTS) ; do \
 	echo Running test: $$pytest ; \
+	$(LIBRARY_PATH_PLACEHOLDER) \
 	env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/bin/bindctl:$(abs_top_srcdir)/src/bin  \
 	$(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
 	done
diff --git a/src/bin/cfgmgr/plugins/tests/Makefile.am b/src/bin/cfgmgr/plugins/tests/Makefile.am
index 896dab7..725d391 100644
--- a/src/bin/cfgmgr/plugins/tests/Makefile.am
+++ b/src/bin/cfgmgr/plugins/tests/Makefile.am
@@ -7,7 +7,7 @@ EXTRA_DIST = $(PYTESTS)
 # required by loadable python modules.
 LIBRARY_PATH_PLACEHOLDER =
 if SET_ENV_LIBRARY_PATH
-LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/cryptolink/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs
+LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/cc/.libs:$(abs_top_builddir)/src/lib/config/.libs:$(abs_top_builddir)/src/lib/log/.libs:$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/cryptolink/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs
 endif
 
 # test using command-line arguments, so use check-local target instead of TESTS
diff --git a/src/bin/cfgmgr/tests/Makefile.am b/src/bin/cfgmgr/tests/Makefile.am
index f6fdd13..9f80e5d 100644
--- a/src/bin/cfgmgr/tests/Makefile.am
+++ b/src/bin/cfgmgr/tests/Makefile.am
@@ -3,6 +3,13 @@ PYTESTS = b10-cfgmgr_test.py
 
 EXTRA_DIST = $(PYTESTS) testdata/plugins/testplugin.py
 
+# If necessary (rare cases), explicitly specify paths to dynamic libraries
+# required by loadable python modules.
+LIBRARY_PATH_PLACEHOLDER =
+if SET_ENV_LIBRARY_PATH
+LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/cc/.libs:$(abs_top_builddir)/src/lib/config/.libs:$(abs_top_builddir)/src/lib/log/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$$$(ENV_LIBRARY_PATH)
+endif
+
 # test using command-line arguments, so use check-local target instead of TESTS
 check-local:
 if ENABLE_PYTHON_COVERAGE
@@ -13,6 +20,7 @@ endif
 	for pytest in $(PYTESTS) ; do \
 	echo Running test: $$pytest ; \
 	env TESTDATA_PATH=$(abs_srcdir)/testdata \
+	$(LIBRARY_PATH_PLACEHOLDER) \
 	env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/bin/cfgmgr \
 	$(PYCOVERAGE_RUN) $(abs_builddir)/$$pytest || exit ; \
 	done
diff --git a/src/bin/cmdctl/tests/Makefile.am b/src/bin/cmdctl/tests/Makefile.am
index 6a4d7d4..e4ec9d4 100644
--- a/src/bin/cmdctl/tests/Makefile.am
+++ b/src/bin/cmdctl/tests/Makefile.am
@@ -2,6 +2,13 @@ PYCOVERAGE_RUN=@PYCOVERAGE_RUN@
 PYTESTS = cmdctl_test.py
 EXTRA_DIST = $(PYTESTS)
 
+# If necessary (rare cases), explicitly specify paths to dynamic libraries
+# required by loadable python modules.
+LIBRARY_PATH_PLACEHOLDER =
+if SET_ENV_LIBRARY_PATH
+LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/cc/.libs:$(abs_top_builddir)/src/lib/config/.libs:$(abs_top_builddir)/src/lib/log/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$$$(ENV_LIBRARY_PATH)
+endif
+
 # test using command-line arguments, so use check-local target instead of TESTS
 check-local:
 if ENABLE_PYTHON_COVERAGE
@@ -11,6 +18,7 @@ if ENABLE_PYTHON_COVERAGE
 endif
 	for pytest in $(PYTESTS) ; do \
 	echo Running test: $$pytest ; \
+	$(LIBRARY_PATH_PLACEHOLDER) \
 	env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/bin/cmdctl \
 	CMDCTL_SPEC_PATH=$(abs_top_builddir)/src/bin/cmdctl \
 	CMDCTL_SRC_PATH=$(abs_top_srcdir)/src/bin/cmdctl \
diff --git a/src/bin/loadzone/run_loadzone.sh.in b/src/bin/loadzone/run_loadzone.sh.in
old mode 100644
new mode 100755
index b7ac19f..95de396
--- a/src/bin/loadzone/run_loadzone.sh.in
+++ b/src/bin/loadzone/run_loadzone.sh.in
@@ -21,6 +21,14 @@ export PYTHON_EXEC
 PYTHONPATH=@abs_top_builddir@/src/lib/python
 export PYTHONPATH
 
+# If necessary (rare cases), explicitly specify paths to dynamic libraries
+# required by loadable python modules.
+SET_ENV_LIBRARY_PATH=@SET_ENV_LIBRARY_PATH@
+if test $SET_ENV_LIBRARY_PATH = yes; then
+	@ENV_LIBRARY_PATH@=@abs_top_builddir@/src/lib/dns/.libs:@abs_top_builddir@/src/lib/cryptolink/.libs:@abs_top_builddir@/src/lib/cc/.libs:@abs_top_builddir@/src/lib/config/.libs:@abs_top_builddir@/src/lib/log/.libs:@abs_top_builddir@/src/lib/util/.libs:@abs_top_builddir@/src/lib/util/io/.libs:@abs_top_builddir@/src/lib/exceptions/.libs:$@ENV_LIBRARY_PATH@
+	export @ENV_LIBRARY_PATH@
+fi
+
 BIND10_MSGQ_SOCKET_FILE=@abs_top_builddir@/msgq_socket
 export BIND10_MSGQ_SOCKET_FILE
 
diff --git a/src/bin/loadzone/tests/correct/Makefile.am b/src/bin/loadzone/tests/correct/Makefile.am
index a90cab2..3507bfa 100644
--- a/src/bin/loadzone/tests/correct/Makefile.am
+++ b/src/bin/loadzone/tests/correct/Makefile.am
@@ -13,8 +13,15 @@ EXTRA_DIST += ttl2.db
 EXTRA_DIST += ttlext.db
 EXTRA_DIST += example.db
 
+# If necessary (rare cases), explicitly specify paths to dynamic libraries
+# required by loadable python modules.
+LIBRARY_PATH_PLACEHOLDER =
+if SET_ENV_LIBRARY_PATH
+LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/cc/.libs:$(abs_top_builddir)/src/lib/config/.libs:$(abs_top_builddir)/src/lib/log/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$$$(ENV_LIBRARY_PATH)
+endif
+
 # TODO: maybe use TESTS?
 # test using command-line arguments, so use check-local target instead of TESTS
 check-local:
 	echo Running test: correct_test.sh 
-	$(SHELL) $(abs_builddir)/correct_test.sh
+	$(LIBRARY_PATH_PLACEHOLDER) $(SHELL) $(abs_builddir)/correct_test.sh
diff --git a/src/bin/loadzone/tests/error/Makefile.am b/src/bin/loadzone/tests/error/Makefile.am
index bbeec07..87bb1cf 100644
--- a/src/bin/loadzone/tests/error/Makefile.am
+++ b/src/bin/loadzone/tests/error/Makefile.am
@@ -12,8 +12,15 @@ EXTRA_DIST += keyerror3.db
 EXTRA_DIST += originerr1.db
 EXTRA_DIST += originerr2.db
 
+# If necessary (rare cases), explicitly specify paths to dynamic libraries
+# required by loadable python modules.
+LIBRARY_PATH_PLACEHOLDER =
+if SET_ENV_LIBRARY_PATH
+LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/cc/.libs:$(abs_top_builddir)/src/lib/config/.libs:$(abs_top_builddir)/src/lib/log/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$$$(ENV_LIBRARY_PATH)
+endif
+
 # TODO: use TESTS ?
 # test using command-line arguments, so use check-local target instead of TESTS
 check-local:
 	echo Running test: error_test.sh
-	$(SHELL) $(abs_builddir)/error_test.sh
+	$(LIBRARY_PATH_PLACEHOLDER) $(SHELL) $(abs_builddir)/error_test.sh
diff --git a/src/bin/msgq/tests/Makefile.am b/src/bin/msgq/tests/Makefile.am
index 0bbb964..50c1e6e 100644
--- a/src/bin/msgq/tests/Makefile.am
+++ b/src/bin/msgq/tests/Makefile.am
@@ -2,6 +2,13 @@ PYCOVERAGE_RUN = @PYCOVERAGE_RUN@
 PYTESTS = msgq_test.py
 EXTRA_DIST = $(PYTESTS)
 
+# If necessary (rare cases), explicitly specify paths to dynamic libraries
+# required by loadable python modules.
+LIBRARY_PATH_PLACEHOLDER =
+if SET_ENV_LIBRARY_PATH
+LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/cc/.libs:$(abs_top_builddir)/src/lib/config/.libs:$(abs_top_builddir)/src/lib/log/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$$$(ENV_LIBRARY_PATH)
+endif
+
 # test using command-line arguments, so use check-local target instead of TESTS
 check-local:
 if ENABLE_PYTHON_COVERAGE
@@ -11,6 +18,7 @@ if ENABLE_PYTHON_COVERAGE
 endif
 	for pytest in $(PYTESTS) ; do \
 	echo Running test: $$pytest ; \
+	$(LIBRARY_PATH_PLACEHOLDER) \
 	env PYTHONPATH=$(abs_top_builddir)/src/bin/msgq:$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python \
 	BIND10_TEST_SOCKET_FILE=$(builddir)/test_msgq_socket.sock \
 	$(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
diff --git a/src/bin/tests/Makefile.am b/src/bin/tests/Makefile.am
index 4340c64..b5bcea2 100644
--- a/src/bin/tests/Makefile.am
+++ b/src/bin/tests/Makefile.am
@@ -3,6 +3,13 @@ PYTESTS = process_rename_test.py
 # .py will be generated by configure, so we don't have to include it
 # in EXTRA_DIST.
 
+# If necessary (rare cases), explicitly specify paths to dynamic libraries
+# required by loadable python modules.
+LIBRARY_PATH_PLACEHOLDER =
+if SET_ENV_LIBRARY_PATH
+LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/cc/.libs:$(abs_top_builddir)/src/lib/config/.libs:$(abs_top_builddir)/src/lib/log/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$$$(ENV_LIBRARY_PATH)
+endif
+
 # test using command-line arguments, so use check-local target instead of TESTS
 check-local:
 if ENABLE_PYTHON_COVERAGE
@@ -12,6 +19,7 @@ if ENABLE_PYTHON_COVERAGE
 endif
 	for pytest in $(PYTESTS) ; do \
 	echo Running test: $$pytest ; \
+	$(LIBRARY_PATH_PLACEHOLDER) \
 	env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/lib/dns/python/.libs \
 	$(PYCOVERAGE_RUN) $(abs_builddir)/$$pytest || exit ; \
 	done
diff --git a/src/bin/xfrin/tests/Makefile.am b/src/bin/xfrin/tests/Makefile.am
index d4efbc7..0f485aa 100644
--- a/src/bin/xfrin/tests/Makefile.am
+++ b/src/bin/xfrin/tests/Makefile.am
@@ -6,7 +6,7 @@ EXTRA_DIST = $(PYTESTS)
 # required by loadable python modules.
 LIBRARY_PATH_PLACEHOLDER =
 if SET_ENV_LIBRARY_PATH
-LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/cryptolink/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$(abs_top_builddir)/src/lib/xfr/.libs:$$$(ENV_LIBRARY_PATH)
+LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/cc/.libs:$(abs_top_builddir)/src/lib/config/.libs:$(abs_top_builddir)/src/lib/log/.libs:$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/cryptolink/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$(abs_top_builddir)/src/lib/xfr/.libs:$$$(ENV_LIBRARY_PATH)
 endif
 
 # test using command-line arguments, so use check-local target instead of TESTS
@@ -18,7 +18,7 @@ if ENABLE_PYTHON_COVERAGE
 endif
 	for pytest in $(PYTESTS) ; do \
 	echo Running test: $$pytest ; \
-	env PYTHONPATH=$(abs_top_builddir)/src/lib/dns/python/.libs:$(abs_top_builddir)/src/bin/xfrin:$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python \
 	$(LIBRARY_PATH_PLACEHOLDER) \
+	env PYTHONPATH=$(abs_top_builddir)/src/lib/dns/python/.libs:$(abs_top_builddir)/src/bin/xfrin:$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python \
 	$(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
 	done
diff --git a/src/bin/xfrout/tests/Makefile.am b/src/bin/xfrout/tests/Makefile.am
index 18503e7..6ca2b42 100644
--- a/src/bin/xfrout/tests/Makefile.am
+++ b/src/bin/xfrout/tests/Makefile.am
@@ -6,7 +6,7 @@ EXTRA_DIST = $(PYTESTS)
 # required by loadable python modules.
 LIBRARY_PATH_PLACEHOLDER =
 if SET_ENV_LIBRARY_PATH
-LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/cryptolink/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$(abs_top_builddir)/src/lib/util/io/.libs:$$$(ENV_LIBRARY_PATH)
+LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/cc/.libs:$(abs_top_builddir)/src/lib/config/.libs:$(abs_top_builddir)/src/lib/log/.libs:$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/cryptolink/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$(abs_top_builddir)/src/lib/util/io/.libs:$$$(ENV_LIBRARY_PATH)
 endif
 
 # test using command-line arguments, so use check-local target instead of TESTS
@@ -18,7 +18,7 @@ if ENABLE_PYTHON_COVERAGE
 endif
 	for pytest in $(PYTESTS) ; do \
 	echo Running test: $$pytest ; \
-	env PYTHONPATH=$(abs_top_builddir)/src/bin/xfrout:$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/lib/dns/python/.libs:$(abs_top_builddir)/src/lib/util/io/.libs \
 	$(LIBRARY_PATH_PLACEHOLDER) \
+	env PYTHONPATH=$(abs_top_builddir)/src/bin/xfrout:$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/lib/dns/python/.libs:$(abs_top_builddir)/src/lib/util/io/.libs \
 	$(PYCOVERAGE_RUN) $(abs_builddir)/$$pytest || exit ; \
 	done
diff --git a/src/bin/xfrout/xfrout.py.in b/src/bin/xfrout/xfrout.py.in
index 40bad85..ac22fe4 100755
--- a/src/bin/xfrout/xfrout.py.in
+++ b/src/bin/xfrout/xfrout.py.in
@@ -559,7 +559,7 @@ class XfroutServer:
         #self._log = None
         self._listen_sock_file = UNIX_SOCKET_FILE
         self._shutdown_event = threading.Event()
-        self._cc = isc.config.ModuleCCSession(SPECFILE_LOCATION, self.config_handler, self.command_handler)
+        self._cc = isc.config.ModuleCCSession(SPECFILE_LOCATION, self.config_handler, self.command_handler, None, True)
         self._config_data = self._cc.get_full_config()
         self._cc.start()
         self._cc.add_remote_config(AUTH_SPECFILE_LOCATION);
diff --git a/src/bin/zonemgr/tests/Makefile.am b/src/bin/zonemgr/tests/Makefile.am
index 496c1a4..97f9b5e 100644
--- a/src/bin/zonemgr/tests/Makefile.am
+++ b/src/bin/zonemgr/tests/Makefile.am
@@ -3,6 +3,13 @@ PYTESTS = zonemgr_test.py
 EXTRA_DIST = $(PYTESTS)
 CLEANFILES = initdb.file
 
+# If necessary (rare cases), explicitly specify paths to dynamic libraries
+# required by loadable python modules.
+LIBRARY_PATH_PLACEHOLDER =
+if SET_ENV_LIBRARY_PATH
+LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/cc/.libs:$(abs_top_builddir)/src/lib/config/.libs:$(abs_top_builddir)/src/lib/log/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$$$(ENV_LIBRARY_PATH)
+endif
+
 # test using command-line arguments, so use check-local target instead of TESTS
 check-local:
 if ENABLE_PYTHON_COVERAGE
@@ -12,6 +19,7 @@ if ENABLE_PYTHON_COVERAGE
 endif
 	for pytest in $(PYTESTS) ; do \
 	echo Running test: $$pytest ; \
+	$(LIBRARY_PATH_PLACEHOLDER) \
 	env PYTHONPATH=$(abs_top_builddir)/src/bin/zonemgr:$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/dns/python/.libs:$(abs_top_builddir)/src/lib/xfr/.libs \
 	$(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
 	done
diff --git a/src/lib/acl/Makefile.am b/src/lib/acl/Makefile.am
index b063289..890851e 100644
--- a/src/lib/acl/Makefile.am
+++ b/src/lib/acl/Makefile.am
@@ -1,6 +1,24 @@
-SUBDIRS = tests
+SUBDIRS = . tests
 
-EXTRA_DIST = check.h acl.h
+AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
+AM_CPPFLAGS += $(BOOST_INCLUDES)
 
-# TODO: Once we have some cc file we are able to compile, create the library.
-# For now, we have only header files, not creating empty library.
+AM_CXXFLAGS = $(B10_CXXFLAGS)
+
+# The core library
+lib_LTLIBRARIES = libacl.la
+libacl_la_SOURCES = check.h acl.h
+libacl_la_SOURCES += loader.h loader.cc
+
+libacl_la_LIBADD = $(top_builddir)/src/lib/exceptions/libexceptions.la
+libacl_la_LIBADD += $(top_builddir)/src/lib/cc/libcc.la
+
+# DNS specialized one
+lib_LTLIBRARIES += libdnsacl.la
+
+libdnsacl_la_SOURCES = dns.h dns.cc
+
+libdnsacl_la_LIBADD = libacl.la
+libdnsacl_la_LIBADD += $(top_builddir)/src/lib/dns/libdns++.la
+
+CLEANFILES = *.gcno *.gcda
diff --git a/src/lib/acl/dns.cc b/src/lib/acl/dns.cc
new file mode 100644
index 0000000..16f1bf5
--- /dev/null
+++ b/src/lib/acl/dns.cc
@@ -0,0 +1,34 @@
+// 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 "dns.h"
+
+namespace isc {
+namespace acl {
+namespace dns {
+
+Loader&
+getLoader() {
+    static Loader* loader(NULL);
+    if (loader == NULL) {
+        loader = new Loader(REJECT);
+        // TODO: This is the place where we register default check creators
+        // like IP check, etc, once we have them.
+    }
+    return (*loader);
+}
+
+}
+}
+}
diff --git a/src/lib/acl/dns.h b/src/lib/acl/dns.h
new file mode 100644
index 0000000..6f36e51
--- /dev/null
+++ b/src/lib/acl/dns.h
@@ -0,0 +1,89 @@
+// 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 ACL_DNS_H
+#define ACL_DNS_H
+
+#include "loader.h"
+
+#include <asiolink/io_address.h>
+#include <dns/message.h>
+
+namespace isc {
+namespace acl {
+namespace dns {
+
+/**
+ * \brief DNS request to be checked.
+ *
+ * This plays the role of Context of the generic template ACLs (in namespace
+ * isc::acl).
+ *
+ * It is simple structure holding just the bunch of information. Therefore
+ * the names don't end up with a slash, there are no methods so they can't be
+ * confused with local variables.
+ *
+ * \todo Do we want a constructor to set this in a shorter manner? So we can
+ *     call the ACLs directly?
+ */
+struct RequestContext {
+    /// \brief The DNS message (payload).
+    isc::dns::ConstMessagePtr message;
+    /// \brief The remote IP address (eg. the client).
+    asiolink::IOAddress remote_address;
+    /// \brief The local IP address (ours, of the interface where we received).
+    asiolink::IOAddress local_address;
+    /// \brief The remote port.
+    uint16_t remote_port;
+    /// \brief The local port.
+    uint16_t local_port;
+    /**
+     * \brief Name of the TSIG key the message is signed with.
+     *
+     * This will be either the name of the TSIG key the message is signed with,
+     * or empty string, if the message is not signed. It is true we could get
+     * the information from the message itself, but because at the time when
+     * the ACL is checked, the signature has been verified already, so passing
+     * it around is probably cheaper.
+     *
+     * It is expected that messages with invalid signatures are handled before
+     * ACL.
+     */
+    std::string tsig_key_name;
+};
+
+/// \brief DNS based check.
+typedef acl::Check<RequestContext> Check;
+/// \brief DNS based compound check.
+typedef acl::CompoundCheck<RequestContext> CompoundCheck;
+/// \brief DNS based ACL.
+typedef acl::ACL<RequestContext> ACL;
+/// \brief DNS based ACL loader.
+typedef acl::Loader<RequestContext> Loader;
+
+/**
+ * \brief Loader singleton access function.
+ *
+ * This function returns a loader of ACLs. It is expected applications
+ * will use this function instead of creating their own loaders, because
+ * one is enough, this one will have registered default checks and it
+ * is known one, so any plugins can registrer additional checks as well.
+ */
+Loader& getLoader();
+
+}
+}
+}
+
+#endif
diff --git a/src/lib/acl/loader.cc b/src/lib/acl/loader.cc
new file mode 100644
index 0000000..8ca7e28
--- /dev/null
+++ b/src/lib/acl/loader.cc
@@ -0,0 +1,46 @@
+// 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 "loader.h"
+
+using namespace std;
+
+namespace isc {
+namespace acl {
+
+BasicAction defaultActionLoader(data::ConstElementPtr actionEl) {
+    try {
+        const string action(actionEl->stringValue());
+        if (action == "ACCEPT") {
+            return (ACCEPT);
+        } else if (action == "REJECT") {
+            return (REJECT);
+        } else if (action == "DROP") {
+            return (DROP);
+        } else {
+            throw LoaderError(__FILE__, __LINE__,
+                              string("Unknown action '" + action + "'").
+                                  c_str(),
+                              actionEl);
+        }
+    }
+    catch (const data::TypeError&) {
+        throw LoaderError(__FILE__, __LINE__,
+                          "Invalid element type for action, must be string",
+                          actionEl);
+    }
+}
+
+}
+}
diff --git a/src/lib/acl/loader.h b/src/lib/acl/loader.h
new file mode 100644
index 0000000..11e7ebc
--- /dev/null
+++ b/src/lib/acl/loader.h
@@ -0,0 +1,404 @@
+// 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 ACL_LOADER_H
+#define ACL_LOADER_H
+
+#include "acl.h"
+#include <cc/data.h>
+#include <boost/function.hpp>
+#include <boost/shared_ptr.hpp>
+#include <map>
+
+namespace isc {
+namespace acl {
+
+/**
+ * \brief Exception for bad ACL specifications.
+ *
+ * This will be thrown by the Loader if the ACL description is malformed
+ * in some way.
+ *
+ * It also can hold optional JSON element where was the error detected, so
+ * it can be examined.
+ *
+ * Checks may subclass this exception for similar errors if they see it fit.
+ */
+class LoaderError : public BadValue {
+private:
+    const data::ConstElementPtr element_;
+public:
+    /**
+     * \brief Constructor.
+     *
+     * Should be used with isc_throw if the fourth argument isn't used.
+     *
+     * \param file The file where the throw happened.
+     * \param line Similar as file, just for the line number.
+     * \param what Human readable description of what happened.
+     * \param element This might be passed to hold the JSON element where
+     *     the error was detected.
+     */
+    LoaderError(const char* file, size_t line, const char* what,
+                data::ConstElementPtr element = data::ConstElementPtr()) :
+        BadValue(file, line, what),
+        element_(element)
+    {}
+    ~ LoaderError() throw() {}
+    /**
+     * \brief Get the element.
+     *
+     * This returns the element where the error was detected. Note that it
+     * might be NULL in some situations.
+     */
+    const data::ConstElementPtr& element() const {
+        return (element_);
+    }
+};
+
+/**
+ * \brief Loader of the default actions of ACLs.
+ *
+ * Declared outside the Loader class, as this one does not need to be
+ * templated. This will throw LoaderError if the parameter isn't string
+ * or if it doesn't contain one of the accepted values.
+ *
+ * \param action The JSON representation of the action. It must be a string
+ *     and contain one of "ACCEPT", "REJECT" or "DENY".
+ * \note We could define different names or add aliases if needed.
+ */
+BasicAction defaultActionLoader(data::ConstElementPtr action);
+
+/**
+ * \brief Loader of ACLs.
+ *
+ * The goal of this class is to convert JSON description of an ACL to object
+ * of the ACL class (including the checks inside it).
+ *
+ * The class can be used to load the checks only. This is supposed to be used
+ * by compound checks to create the subexpressions.
+ *
+ * To allow any kind of checks to exist in the application, creators are
+ * registered for the names of the checks.
+ *
+ * An ACL definition looks like this:
+ * \verbatim
+ * [
+ *   {
+ *      "action": "ACCEPT",
+ *      "match-type": <parameter>
+ *   },
+ *   {
+ *      "action": "REJECT",
+ *      "match-type": <parameter>
+ *      "another-match-type": [<parameter1>, <parameter2>]
+*    },
+*    {
+*       "action": "DROP"
+*    }
+ * ]
+ * \endverbatim
+ *
+ * This is a list of elements. Each element must have an "action"
+ * entry/keyword. That one specifies which action is returned if this
+ * element matches (the value of the key is passed to the action loader
+ * (see the constructor). It may be any piece of JSON which the action
+ * loader expects.
+ *
+ * The rest of the element are matches. The left side is the name of the
+ * match type (for example match for source IP address or match for message
+ * size). The <parameter> is whatever is needed to describe the match and
+ * depends on the match type, the loader passes it verbatim to creator
+ * of that match type.
+ *
+ * There may be multiple match types in single element. In such case, all
+ * of the matches must match for the element to take action (so, in the second
+ * element, both "match-type" and "another-match-type" must be satisfied).
+ * If there's no match in the element, the action is taken/returned without
+ * conditions, every time (makes sense as the last entry, as the ACL will
+ * never get past it).
+ *
+ * The second entry shows another thing - if there's a list as the value
+ * for some match and the match itself is not expecting a list, it is taken
+ * as an "or" - a match for at last one of the choices in the list must match.
+ * So, for the second entry, both "match-type" and "another-match-type" must
+ * be satisfied, but the another one is satisfied by either parameter1 or
+ * parameter2.
+ */
+template<typename Context, typename Action = BasicAction> class Loader {
+public:
+    /**
+     * \brief Constructor.
+     *
+     * \param default_action The default action for created ACLs.
+     * \param actionLoader is the loader which will be used to convert actions
+     *     from their JSON representation. The default value is suitable for
+     *     the BasicAction enum. If you did not specify the second
+     *     template argument, you don't need to specify this loader.
+     */
+    Loader(const Action& defaultAction,
+           const boost::function1<Action, data::ConstElementPtr>
+               &actionLoader = &defaultActionLoader) :
+        default_action_(defaultAction),
+        action_loader_(actionLoader)
+    {}
+    /**
+     * \brief Creator of the checks.
+     *
+     * This can be registered within the Loader and will be used to create the
+     * checks. It is expected multiple creators (for multiple types, one can
+     * handle even multiple names) will be created and registered to support
+     * range of things we could check. This allows for customizing/extending
+     * the loader.
+     */
+    class CheckCreator {
+    public:
+        /**
+         * \brief List of names supported by this loader.
+         *
+         * List of all names for which this loader is able to create the
+         * checks. There can be multiple names, to support both aliases
+         * to the same checks and creators capable of creating multiple
+         * types of checks.
+         */
+        virtual std::vector<std::string> names() const = 0;
+        /**
+         * \brief Creates the check.
+         *
+         * This function does the actual creation. It is passed all the
+         * relevant data and is supposed to return shared pointer to the
+         * check.
+         *
+         * It is expected to throw the LoaderError exception when the
+         * definition is invalid.
+         *
+         * \param name The type name of the check. If the creator creates
+         *     only one type of check, it can safely ignore this parameter.
+         * \param definition The part of JSON describing the parameters of
+         *     check. As there's no way for the loader to know how the
+         *     parameters might look like, they are not checked in any way.
+         *     Therefore it's up to the creator (or the check being created)
+         *     to validate the data and throw if it is bad.
+         * \param Current loader calling this creator. This can be used
+         *     to load subexpressions in case of compound check.
+         */
+        virtual boost::shared_ptr<Check<Context> > create(
+            const std::string& name, data::ConstElementPtr definition,
+            const Loader<Context, Action>& loader) = 0;
+        /**
+         * \brief Is list or-abbreviation allowed?
+         *
+         * If this returns true and the parameter (eg. the value we check
+         * against, the one that is passed as the second parameter of create)
+         * is list, the loader will call the create method with each element of
+         * the list and aggregate all the results in OR compound check. If it
+         * is false, the parameter is passed verbatim no matter if it is or
+         * isn't a list. For example, IP check will have this as true (so
+         * multiple IP addresses can be passed as options), but AND operator
+         * will return false and handle the list of subexpressions itself.
+         *
+         * The rationale behind this is that it is common to specify list of
+         * something that matches (eg. list of IP addresses).
+         */
+        virtual bool allowListAbbreviation() const {
+            return (true);
+        }
+    };
+    /**
+     * \brief Register another check creator.
+     *
+     * Adds a creator to the list of known ones. The creator's list of names
+     * must be disjoint with the names already known to the creator or the
+     * LoaderError exception is thrown. In such case, the creator is not
+     * registered under any of the names. In case of other exceptions, like
+     * bad_alloc, only weak exception safety is guaranteed.
+     *
+     * \param creator Shared pointer to the creator.
+     * \note We don't support deregistration yet, but it is expected it will
+     *     be needed in future, when we have some kind of plugins. These
+     *     plugins might want to unload, in which case they would need to
+     *     deregister their creators. It is expected they would pass the same
+     *     pointer to such method as they pass here.
+     */
+    void registerCreator(boost::shared_ptr<CheckCreator> creator) {
+        // First check we can insert all the names
+        typedef std::vector<std::string> Strings;
+        const Strings names(creator->names());
+        for (Strings::const_iterator i(names.begin()); i != names.end();
+             ++i) {
+            if (creators_.find(*i) != creators_.end()) {
+                isc_throw(LoaderError, "The loader already contains creator "
+                          "named " << *i);
+            }
+        }
+        // Now insert them
+        for (Strings::const_iterator i(names.begin()); i != names.end();
+             ++i) {
+            creators_[*i] = creator;
+        }
+    }
+    /**
+     * \brief Load a check.
+     *
+     * This parses a check dict (block, the one element of ACL) and calls a
+     * creator (or creators, if more than one check is found inside) for it. It
+     * ignores the "action" key, as it is a reserved keyword used to specify
+     * actions inside the ACL.
+     *
+     * This may throw LoaderError if it is not a dict or if some of the type
+     * names is not known (there's no creator registered for it). The
+     * exceptions from creators aren't caught.
+     *
+     * \param description The JSON description of the check.
+     */
+    boost::shared_ptr<Check<Context> > loadCheck(const data::ConstElementPtr&
+                                                 description)
+    {
+        // Get the description as a map
+        typedef std::map<std::string, data::ConstElementPtr> Map;
+        Map map;
+        try {
+            map = description->mapValue();
+        }
+        catch (const data::TypeError&) {
+            isc_throw_1(LoaderError, "Check description is not a map",
+                        description);
+        }
+        // Call the internal part with extracted map
+        return (loadCheck(description, map));
+    }
+    /**
+     * \brief Load an ACL.
+     *
+     * This parses an ACL list, creates the checks and actions of each element
+     * and returns it. It may throw LoaderError if it isn't a list or the
+     * "action" key is missing in some element. Also, no exceptions from
+     * loadCheck (therefore from whatever creator is used) and from the
+     * actionLoader passed to constructor are not caught.
+     *
+     * \param description The JSON list of ACL.
+     */
+    boost::shared_ptr<ACL<Context, Action> > load(const data::ConstElementPtr&
+                                                  description)
+    {
+        // We first check it's a list, so we can use the list reference
+        // (the list may be huge)
+        if (description->getType() != data::Element::list) {
+            isc_throw_1(LoaderError, "ACL not a list", description);
+        }
+        // First create an empty ACL
+        const List &list(description->listValue());
+        boost::shared_ptr<ACL<Context, Action> > result(
+            new ACL<Context, Action>(default_action_));
+        // Run trough the list of elements
+        for (List::const_iterator i(list.begin()); i != list.end(); ++i) {
+            Map map;
+            try {
+                map = (*i)->mapValue();
+            }
+            catch (const data::TypeError&) {
+                isc_throw_1(LoaderError, "ACL element not a map", *i);
+            }
+            // Create an action for the element
+            const Map::const_iterator action(map.find("action"));
+            if (action == map.end()) {
+                isc_throw_1(LoaderError, "No action in ACL element", *i);
+            }
+            const Action acValue(action_loader_(action->second));
+            // Now create the check if there's one
+            if (map.size() >= 2) { // One is the action, another one the check
+                result->append(loadCheck(*i, map), acValue);
+            } else {
+                // In case there's no check, this matches every time. We
+                // simulate it by our own private "True" check.
+                result->append(boost::shared_ptr<Check<Context> >(new True()),
+                               acValue);
+            }
+        }
+        return (result);
+    }
+private:
+    // Some type aliases to save typing
+    typedef std::map<std::string, boost::shared_ptr<CheckCreator> > Creators;
+    typedef std::map<std::string, data::ConstElementPtr> Map;
+    typedef std::vector<data::ConstElementPtr> List;
+    // Private members
+    Creators creators_;
+    const Action default_action_;
+    const boost::function1<Action, data::ConstElementPtr> action_loader_;
+    /**
+     * \brief Internal version of loadCheck.
+     *
+     * This is the internal part, shared between load and loadCheck.
+     * \param description The bit of JSON (used in exceptions).
+     * \param map The extracted map describing the check. It does change
+     *     the map.
+     */
+    boost::shared_ptr<Check<Context> > loadCheck(const data::ConstElementPtr&
+                                                 description, Map& map)
+    {
+        // Remove the action keyword
+        map.erase("action");
+        // Now, do we have any definition? Or is it and abbreviation?
+        switch (map.size()) {
+            case 0:
+                isc_throw_1(LoaderError, "Check description is empty",
+                            description);
+            case 1: {
+                // Get the first and only item
+                const Map::const_iterator checkDesc(map.begin());
+                const std::string& name(checkDesc->first);
+                const typename Creators::const_iterator
+                    creatorIt(creators_.find(name));
+                if (creatorIt == creators_.end()) {
+                    isc_throw_1(LoaderError, "No creator for ACL check " <<
+                                name, description);
+                }
+                if (creatorIt->second->allowListAbbreviation() &&
+                    checkDesc->second->getType() == data::Element::list) {
+                    isc_throw_1(LoaderError,
+                                "Not implemented (OR-abbreviated form)",
+                                checkDesc->second);
+                }
+                // Create the check and return it
+                return (creatorIt->second->create(name, checkDesc->second,
+                                                  *this));
+            }
+            default:
+                isc_throw_1(LoaderError,
+                            "Not implemented (AND-abbreviated form)",
+                            description);
+        }
+    }
+    /**
+     * \brief Check that always matches.
+     *
+     * This one is used internally for ACL elements without condition. We may
+     * want to make this publicly accesible sometime maybe, but for now,
+     * there's no need.
+     */
+    class True : public Check<Context> {
+    public:
+        virtual bool matches(const Context&) const { return (true); };
+        virtual unsigned cost() const { return (1); }
+        // We don't write "true" here, as this one was created using empty
+        // input
+        virtual std::string toText() const { return ""; }
+    };
+};
+
+}
+}
+
+#endif
diff --git a/src/lib/acl/tests/Makefile.am b/src/lib/acl/tests/Makefile.am
index a6e90f7..9328c68 100644
--- a/src/lib/acl/tests/Makefile.am
+++ b/src/lib/acl/tests/Makefile.am
@@ -5,12 +5,18 @@ TESTS =
 if HAVE_GTEST
 TESTS += run_unittests
 run_unittests_SOURCES = run_unittests.cc
-run_unittests_SOURCES += check_test.cc acl_test.cc
+run_unittests_SOURCES += check_test.cc acl_test.cc loader_test.cc
+run_unittests_SOURCES += logcheck.h
+run_unittests_SOURCES += dns_test.cc
 run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
 run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
 
 run_unittests_LDADD = $(GTEST_LDADD)
 run_unittests_LDADD += $(top_builddir)/src/lib/util/unittests/libutil_unittests.la
+run_unittests_LDADD += $(top_builddir)/src/lib/acl/libacl.la
+run_unittests_LDADD += $(top_builddir)/src/lib/cc/libcc.la
+run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
+run_unittests_LDADD += $(top_builddir)/src/lib/acl/libdnsacl.la
 endif
 
 noinst_PROGRAMS = $(TESTS)
diff --git a/src/lib/acl/tests/acl_test.cc b/src/lib/acl/tests/acl_test.cc
index 36baff6..5829fe7 100644
--- a/src/lib/acl/tests/acl_test.cc
+++ b/src/lib/acl/tests/acl_test.cc
@@ -12,75 +12,11 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
-#include <gtest/gtest.h>
-#include <acl/acl.h>
-#include <cassert>
-
-using namespace isc::acl;
-using boost::shared_ptr;
+#include "logcheck.h"
 
 namespace {
 
-// This is arbitrary guess of size for the log. If it's too small for your
-// test, just make it bigger.
-const size_t LOG_SIZE = 10;
-
-// This will remember which checks did run already.
-struct Log {
-    // The actual log cells, if i-th check did run
-    mutable bool run[LOG_SIZE];
-    Log() {
-        // Nothing run yet
-        for (size_t i(0); i < LOG_SIZE; ++i) {
-            run[i] = false;
-        }
-    }
-    // Checks that the first amount of checks did run and the rest didn't.
-    void checkFirst(size_t amount) const {
-        ASSERT_LE(amount, LOG_SIZE) << "Wrong test: amount bigger than size "
-            "of log";
-        {
-            SCOPED_TRACE("Checking that the first amount of checks did run");
-            for (size_t i(0); i < amount; ++i) {
-                EXPECT_TRUE(run[i]) << "Check #" << i << " did not run.";
-            }
-        }
-
-        {
-            SCOPED_TRACE("Checking that the rest did not run");
-            for (size_t i(amount); i < LOG_SIZE; ++i) {
-                EXPECT_FALSE(run[i]) << "Check #" << i << "did run.";
-            }
-        }
-    }
-};
-
-// This returns true or false every time, no matter what is passed to it.
-// But it logs that it did run.
-class ConstCheck : public Check<Log> {
-public:
-    ConstCheck(bool accepts, size_t log_num) :
-        log_num_(log_num),
-        accepts_(accepts)
-    {
-        assert(log_num < LOG_SIZE); // If this fails, the LOG_SIZE is too small
-    }
-    /*
-     * This use of mutable log context is abuse for testing purposes.
-     * It is expected that the context will not be modified in the real
-     * applications of ACLs, but we want to know which checks were called
-     * and this is an easy way.
-     */
-    virtual bool matches(const Log& log) const {
-        log.run[log_num_] = true;
-        return (accepts_);
-    }
-private:
-    size_t log_num_;
-    bool accepts_;
-};
-
-// Test version of the ACL class. It adds few methods to examine the protected
+// Test version of the Acl class. It adds few methods to examine the protected
 // data, but does not change the implementation.
 class TestACL : public ACL<Log> {
 public:
diff --git a/src/lib/acl/tests/dns_test.cc b/src/lib/acl/tests/dns_test.cc
new file mode 100644
index 0000000..e5e0f3a
--- /dev/null
+++ b/src/lib/acl/tests/dns_test.cc
@@ -0,0 +1,35 @@
+// 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 <acl/dns.h>
+#include <gtest/gtest.h>
+
+using namespace isc::acl::dns;
+
+namespace {
+
+// Tests that the getLoader actually returns something, returns the same every
+// time and the returned value can be used to anything. It is not much of a
+// test, but the getLoader is not much of a function.
+TEST(DNSACL, getLoader) {
+    Loader* l(&getLoader());
+    ASSERT_TRUE(l != NULL);
+    EXPECT_EQ(l, &getLoader());
+    EXPECT_NO_THROW(l->load(isc::data::Element::fromJSON(
+        "[{\"action\": \"DROP\"}]")));
+    // TODO Test that the things we should register by default, like IP based
+    // check, are loaded.
+}
+
+}
diff --git a/src/lib/acl/tests/loader_test.cc b/src/lib/acl/tests/loader_test.cc
new file mode 100644
index 0000000..92d40a8
--- /dev/null
+++ b/src/lib/acl/tests/loader_test.cc
@@ -0,0 +1,426 @@
+// 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 "logcheck.h"
+#include <acl/loader.h>
+#include <string>
+#include <gtest/gtest.h>
+
+using namespace std;
+using namespace boost;
+using isc::data::ConstElementPtr;
+
+namespace {
+
+// Just for convenience, create JSON objects from JSON string
+ConstElementPtr el(const string& JSON) {
+    return (isc::data::Element::fromJSON(JSON));
+}
+
+// We don't use the EXPECT_THROW macro, as it doesn't allow us
+// to examine the exception. We want to check the element is stored
+// there as well.
+void testActionLoaderException(const string& JSON) {
+    SCOPED_TRACE("Should throw with input: " + JSON);
+    ConstElementPtr elem(el(JSON));
+    try {
+        defaultActionLoader(elem);
+        FAIL() << "It did not throw";
+    }
+    catch (const LoaderError& error) {
+        // Yes, comparing for pointer equality, that is enough, it
+        // should return the exact instance of the JSON object
+        EXPECT_EQ(elem, error.element());
+    }
+}
+
+// Test the defaultActionLoader function
+TEST(LoaderHelpers, DefaultActionLoader) {
+    // First the three valid inputs
+    EXPECT_EQ(ACCEPT, defaultActionLoader(el("\"ACCEPT\"")));
+    EXPECT_EQ(REJECT, defaultActionLoader(el("\"REJECT\"")));
+    EXPECT_EQ(DROP, defaultActionLoader(el("\"DROP\"")));
+    // Now few invalid ones
+    // String, but unknown one
+    testActionLoaderException("\"UNKNOWN\"");
+    testActionLoaderException("42");
+    testActionLoaderException("true");
+    testActionLoaderException("null");
+    testActionLoaderException("[]");
+    testActionLoaderException("{}");
+}
+
+// A check that doesn't check anything but remembers it's own name
+// and data
+class NamedCheck : public Check<Log> {
+public:
+    NamedCheck(const string& name, ConstElementPtr data) :
+        name_(name),
+        data_(data)
+    {}
+    virtual bool matches(const Log&) const { return (true); }
+    const string name_;
+    const ConstElementPtr data_;
+};
+
+// The creator of NamedCheck
+class NamedCreator : public Loader<Log>::CheckCreator {
+public:
+    NamedCreator(const string& name, bool abbreviatedList = true) :
+        abbreviated_list_(abbreviatedList)
+    {
+        names_.push_back(name);
+    }
+    NamedCreator(const vector<string>& names) :
+        names_(names),
+        abbreviated_list_(true)
+    {}
+    vector<string> names() const {
+        return (names_);
+    }
+    shared_ptr<Check<Log> > create(const string& name, ConstElementPtr data,
+                                   const Loader<Log>&)
+    {
+        bool found(false);
+        for (vector<string>::const_iterator i(names_.begin());
+             i != names_.end(); ++i) {
+            if (*i == name) {
+                found = true;
+                break;
+            }
+        }
+        EXPECT_TRUE(found) << "Name " << name << " passed to creator which "
+            "doesn't handle it.";
+        return (shared_ptr<Check<Log> >(new NamedCheck(name, data)));
+    }
+    bool allowListAbbreviation() const {
+        return (abbreviated_list_);
+    }
+private:
+    vector<string> names_;
+    const bool abbreviated_list_;
+};
+
+// To be thrown in tests internally
+class TestCreatorError {};
+
+// This will throw every time it should create something
+class ThrowCreator : public Loader<Log>::CheckCreator {
+public:
+    vector<string> names() const {
+        vector<string> result;
+        result.push_back("throw");
+        return (result);
+    }
+    shared_ptr<Check<Log> > create(const string&, ConstElementPtr,
+                                   const Loader<Log>&)
+    {
+        throw TestCreatorError();
+    }
+};
+
+// This throws whenever the match is called on it
+class ThrowCheck : public Check<Log> {
+public:
+    virtual bool matches(const Log&) const {
+        throw TestCreatorError();
+    }
+};
+
+// And creator for it
+class ThrowCheckCreator : public Loader<Log>::CheckCreator {
+public:
+    vector<string> names() const {
+        vector<string> result;
+        result.push_back("throwcheck");
+        return (result);
+    }
+    shared_ptr<Check<Log> > create(const string&, ConstElementPtr,
+                                   const Loader<Log>&)
+    {
+        return (shared_ptr<Check<Log> >(new ThrowCheck()));
+    }
+};
+
+class LogCreator : public Loader<Log>::CheckCreator {
+public:
+    vector<string> names() const {
+        vector<string> result;
+        result.push_back("logcheck");
+        return (result);
+    }
+    /*
+     * For simplicity, we just take two values as a list, first is the
+     * logging cell used, the second is result of the check. No error checking
+     * is done, if there's bug in the test, it will throw TypeError for us.
+     */
+    shared_ptr<Check<Log> > create(const string&, ConstElementPtr definition,
+                                   const Loader<Log>&)
+    {
+        vector<ConstElementPtr> list(definition->listValue());
+        int logpos(list[0]->intValue());
+        bool accept(list[1]->boolValue());
+        return (shared_ptr<ConstCheck>(new ConstCheck(accept, logpos)));
+    }
+    // We take a list, so don't interpret it for us
+    virtual bool allowListAbbreviation() const { return (false); }
+};
+
+class LoaderTest : public ::testing::Test {
+public:
+    LoaderTest() :
+        loader_(REJECT)
+    {}
+    Loader<Log> loader_;
+    Log log_;
+    // Some convenience functions to set up
+
+    // Create a NamedCreator, convert to shared pointer
+    shared_ptr<NamedCreator> namedCreator(const string& name,
+                                          bool abbreviatedList = true)
+    {
+        return (shared_ptr<NamedCreator>(new NamedCreator(name,
+                                                          abbreviatedList)));
+    }
+    // Create and add a NamedCreator
+    void addNamed(const string& name, bool abbreviatedList = true) {
+        EXPECT_NO_THROW(loader_.registerCreator(
+            namedCreator(name, abbreviatedList)));
+    }
+    // Load a check and convert it to named check to examine it
+    shared_ptr<NamedCheck> loadCheck(const string& definition) {
+        SCOPED_TRACE("Loading check " + definition);
+        shared_ptr<Check<Log> > loaded;
+        EXPECT_NO_THROW(loaded = loader_.loadCheck(el(definition)));
+        shared_ptr<NamedCheck> result(dynamic_pointer_cast<NamedCheck>(
+            loaded));
+        EXPECT_TRUE(result);
+        return (result);
+    }
+    // The loadCheck throws an exception
+    void checkException(const string& JSON) {
+        SCOPED_TRACE("Loading check exception: " + JSON);
+        ConstElementPtr input(el(JSON));
+        // Not using EXPECT_THROW, we want to examine the exception
+        try {
+            loader_.loadCheck(input);
+            FAIL() << "Should have thrown";
+        }
+        catch (const LoaderError& e) {
+            // It should be identical copy, so checking pointers
+            EXPECT_EQ(input, e.element());
+        }
+    }
+    // Insert the throw, throwcheck and logcheck checks into the loader
+    void aclSetup() {
+        try {
+            loader_.registerCreator(shared_ptr<ThrowCreator>(new
+                                                             ThrowCreator()));
+            loader_.registerCreator(shared_ptr<ThrowCheckCreator>(
+                new ThrowCheckCreator()));
+            loader_.registerCreator(shared_ptr<LogCreator>(new LogCreator()));
+        }
+        // We ignore this exception here, because it happens when we try to
+        // insert the creators multiple times. This is harmless.
+        catch (const LoaderError&) {}
+    }
+    // Create an ACL, run it, check it's result and how many first
+    // log items it marked
+    //
+    // Works with preset names throw and logcheck
+    void aclRun(const string& JSON, BasicAction expectedResult,
+                size_t logged)
+    {
+        SCOPED_TRACE("Running ACL for " + JSON);
+        aclSetup();
+        shared_ptr<ACL<Log> > acl;
+        EXPECT_NO_THROW(acl = loader_.load(el(JSON)));
+        EXPECT_EQ(expectedResult, acl->execute(log_));
+        log_.checkFirst(logged);
+    }
+    // Check it throws an error when creating the ACL
+    void aclException(const string& JSON) {
+        SCOPED_TRACE("Trying to load bad " + JSON);
+        aclSetup();
+        EXPECT_THROW(loader_.load(el(JSON)), LoaderError);
+    }
+};
+
+// Test that it does not accept duplicate creator
+TEST_F(LoaderTest, CreatorDuplicity) {
+    addNamed("name");
+    EXPECT_THROW(loader_.registerCreator(namedCreator("name")), LoaderError);
+}
+
+// Test that when it does not accept a duplicate, nothing is inserted
+TEST_F(LoaderTest, CreatorDuplicateUnchanged) {
+    addNamed("name1");
+    vector<string> names;
+    names.push_back("name2");
+    names.push_back("name1");
+    names.push_back("name3");
+    EXPECT_THROW(loader_.registerCreator(
+        shared_ptr<NamedCreator>(new NamedCreator(names))), LoaderError);
+    // It should now reject both name2 and name3 as not known
+    checkException("{\"name2\": null}");
+    checkException("{\"name3\": null}");
+}
+
+// Test that we can register a creator and load a check with the name
+TEST_F(LoaderTest, SimpleCheckLoad) {
+    addNamed("name");
+    shared_ptr<NamedCheck> check(loadCheck("{\"name\": 42}"));
+    EXPECT_EQ("name", check->name_);
+    EXPECT_TRUE(check->data_->equals(*el("42")));
+}
+
+// As above, but there are multiple creators registered within the loader
+TEST_F(LoaderTest, MultiCreatorCheckLoad) {
+    addNamed("name1");
+    addNamed("name2");
+    shared_ptr<NamedCheck> check(loadCheck("{\"name2\": 42}"));
+    EXPECT_EQ("name2", check->name_);
+    EXPECT_TRUE(check->data_->equals(*el("42")));
+}
+
+// Similar to above, but there's a creator with multiple names
+TEST_F(LoaderTest, MultiNameCheckLoad) {
+    addNamed("name1");
+    vector<string> names;
+    names.push_back("name2");
+    names.push_back("name3");
+    EXPECT_NO_THROW(loader_.registerCreator(shared_ptr<NamedCreator>(
+        new NamedCreator(names))));
+    shared_ptr<NamedCheck> check(loadCheck("{\"name3\": 42}"));
+    EXPECT_EQ("name3", check->name_);
+    EXPECT_TRUE(check->data_->equals(*el("42")));
+}
+
+// Invalid format is rejected
+TEST_F(LoaderTest, InvalidFormatCheck) {
+    checkException("[]");
+    checkException("42");
+    checkException("\"hello\"");
+    checkException("null");
+}
+
+// Empty check is rejected
+TEST_F(LoaderTest, EmptyCheck) {
+    checkException("{}");
+}
+
+// The name isn't known
+TEST_F(LoaderTest, UnkownName) {
+    checkException("{\"unknown\": null}");
+}
+
+// Exception from the creator is propagated
+TEST_F(LoaderTest, CheckPropagate) {
+    loader_.registerCreator(shared_ptr<ThrowCreator>(new ThrowCreator()));
+    EXPECT_THROW(loader_.loadCheck(el("{\"throw\": null}")), TestCreatorError);
+}
+
+// The abbreviated form is not yet implemented
+// (we need the operators to be implemented)
+TEST_F(LoaderTest, AndAbbrev) {
+    addNamed("name1");
+    addNamed("name2");
+    EXPECT_THROW(loader_.loadCheck(el("{\"name1\": 1, \"name2\": 2}")),
+                 LoaderError);
+}
+
+TEST_F(LoaderTest, OrAbbrev) {
+    addNamed("name1");
+    EXPECT_THROW(loader_.loadCheck(el("{\"name1\": [1, 2]}")),
+                 LoaderError);
+}
+
+// But this is not abbreviated form, this should be passed directly to the
+// creator
+TEST_F(LoaderTest, ListCheck) {
+    addNamed("name1", false);
+    shared_ptr<NamedCheck> check(loadCheck("{\"name1\": [1, 2]}"));
+    EXPECT_EQ("name1", check->name_);
+    EXPECT_TRUE(check->data_->equals(*el("[1, 2]")));
+}
+
+// Check the action key is ignored as it should be
+TEST_F(LoaderTest, CheckNoAction) {
+    addNamed("name1");
+    shared_ptr<NamedCheck> check(loadCheck("{\"name1\": 1, \"action\": 2}"));
+    EXPECT_EQ("name1", check->name_);
+    EXPECT_TRUE(check->data_->equals(*el("1")));
+}
+
+// The empty ACL can be created and run, providing the default action
+TEST_F(LoaderTest, EmptyACL) {
+    aclRun("[]", REJECT, 0);
+}
+
+// We can create a simple ACL, which will return the correct default
+// action
+TEST_F(LoaderTest, NoMatchACL) {
+    aclRun("[{\"logcheck\": [0, false], \"action\": \"ACCEPT\"}]",
+           REJECT, 1);
+}
+
+// We can created more complicated ACL, it will match at the second
+// check
+TEST_F(LoaderTest, MatchACL) {
+    aclRun("["
+           "  {\"logcheck\": [0, false], \"action\": \"DROP\"},"
+           "  {\"logcheck\": [1, true], \"action\": \"ACCEPT\"}"
+           "]", ACCEPT, 2);
+}
+
+// ACL without a check (matches unconditionally)
+// We add another one check after it, to make sure it is really not run
+TEST_F(LoaderTest, NoCheckACL) {
+    aclRun("["
+           "  {\"action\": \"DROP\"},"
+           "  {\"throwcheck\": 1, \"action\": \"ACCEPT\"}"
+           "]", DROP, 0);
+}
+
+// Malformed things are rejected
+TEST_F(LoaderTest, InvalidACLFormat) {
+    // Not a list
+    aclException("{}");
+    aclException("42");
+    aclException("true");
+    aclException("null");
+    aclException("\"hello\"");
+    // Malformed element
+    aclException("[42]");
+    aclException("[\"hello\"]");
+    aclException("[[]]");
+    aclException("[true]");
+    aclException("[null]");
+}
+
+// If there's no action keyword, it is rejected
+TEST_F(LoaderTest, NoAction) {
+    aclException("[{}]");
+    aclException("[{\"logcheck\": [0, true]}]");
+}
+
+// Exceptions from check creation is propagated
+TEST_F(LoaderTest, ACLPropagate) {
+    aclSetup();
+    EXPECT_THROW(loader_.load(el("[{\"action\": \"ACCEPT\", \"throw\": 1}]")),
+                 TestCreatorError);
+
+}
+
+}
diff --git a/src/lib/acl/tests/logcheck.h b/src/lib/acl/tests/logcheck.h
new file mode 100644
index 0000000..c5e1bb1
--- /dev/null
+++ b/src/lib/acl/tests/logcheck.h
@@ -0,0 +1,86 @@
+// 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 <acl/acl.h>
+#include <cassert>
+
+// This is not a public header, it is used only inside the tests. Therefore
+// we lower the standards a bit and use anonymous namespace in the header
+// and "using", just for convenience. This is just to share little bit of code
+// between multiple tests.
+using namespace isc::acl;
+using boost::shared_ptr;
+
+namespace {
+
+// This is arbitrary guess of size for the log. If it's too small for your
+// test, just make it bigger.
+const size_t LOG_SIZE = 10;
+
+// This will remember which checks did run already.
+struct Log {
+    // The actual log cells, if i-th check did run
+    mutable bool run[LOG_SIZE];
+    Log() {
+        // Nothing run yet
+        for (size_t i(0); i < LOG_SIZE; ++ i) {
+            run[i] = false;
+        }
+    }
+    // Checks that the first amount of checks did run and the rest didn't.
+    void checkFirst(size_t amount) const {
+        ASSERT_LE(amount, LOG_SIZE) << "Wrong test: amount bigger than size "
+            "of log";
+        {
+            SCOPED_TRACE("Checking that the first amount of checks did run");
+            for (size_t i(0); i < amount; ++ i) {
+                EXPECT_TRUE(run[i]) << "Check #" << i << " did not run.";
+            }
+        }
+
+        {
+            SCOPED_TRACE("Checking that the rest did not run");
+            for (size_t i(amount); i < LOG_SIZE; ++ i) {
+                EXPECT_FALSE(run[i]) << "Check #" << i << "did run.";
+            }
+        }
+    }
+};
+
+// This returns true or false every time, no matter what is passed to it.
+// But it logs that it did run.
+class ConstCheck : public Check<Log> {
+public:
+    ConstCheck(bool accepts, size_t logNum) :
+        logNum_(logNum),
+        accepts_(accepts)
+    {
+        assert(logNum < LOG_SIZE); // If this fails, the LOG_SIZE is too small
+    }
+    virtual bool matches(const Log& log) const {
+        /*
+         * This is abuse of the context. It is designed to carry the
+         * information to check, not to modify it. However, this is the
+         * easiest way to do the test, so we go against the design.
+         */
+        log.run[logNum_] = true;
+        return (accepts_);
+    }
+private:
+    size_t logNum_;
+    bool accepts_;
+};
+
+}
diff --git a/src/lib/asiodns/asiodef.mes b/src/lib/asiodns/asiodef.mes
index 3f2e80c..4f4090d 100644
--- a/src/lib/asiodns/asiodef.mes
+++ b/src/lib/asiodns/asiodef.mes
@@ -16,7 +16,7 @@ $PREFIX ASIODNS_
 $NAMESPACE isc::asiodns
 
 % FETCHCOMP   upstream fetch to %1(%2) has now completed
-A debug message, this records the the upstream fetch (a query made by the
+A debug message, this records that the upstream fetch (a query made by the
 resolver on behalf of its client) to the specified address has completed.
 
 % FETCHSTOP   upstream fetch to %1(%2) has been stopped
@@ -27,12 +27,12 @@ enabled.
 % OPENSOCK    error %1 opening %2 socket to %3(%4)
 The asynchronous I/O code encountered an error when trying to open a socket
 of the specified protocol in order to send a message to the target address.
-The the number of the system error that cause the problem is given in the
+The number of the system error that cause the problem is given in the
 message.
 
 % RECVSOCK    error %1 reading %2 data from %3(%4)
-The asynchronous I/O code encountered an error when trying read data from
-the specified address on the given protocol.  The the number of the system
+The asynchronous I/O code encountered an error when trying to read data from
+the specified address on the given protocol.  The number of the system
 error that cause the problem is given in the message.
 
 % SENDSOCK    error %1 sending data using %2 to %3(%4)
diff --git a/src/lib/config/ccsession.cc b/src/lib/config/ccsession.cc
index 857de63..dd2be3d 100644
--- a/src/lib/config/ccsession.cc
+++ b/src/lib/config/ccsession.cc
@@ -247,7 +247,9 @@ readLoggersConf(std::vector<isc::log::LoggerSpecification>& specs,
 } // end anonymous namespace
 
 void
-my_logconfig_handler(const std::string&n, ConstElementPtr new_config, const ConfigData& config_data) {
+default_logconfig_handler(const std::string& module_name,
+                          ConstElementPtr new_config,
+                          const ConfigData& config_data) {
     config_data.getModuleSpec().validateConfig(new_config, true);
 
     std::vector<isc::log::LoggerSpecification> specs;
@@ -353,7 +355,7 @@ ModuleCCSession::ModuleCCSession(
 
     // Keep track of logging settings automatically
     if (handle_logging) {
-        addRemoteConfig("Logging", my_logconfig_handler, false);
+        addRemoteConfig("Logging", default_logconfig_handler, false);
     }
 
     if (start_immediately) {
diff --git a/src/lib/config/ccsession.h b/src/lib/config/ccsession.h
index 53aab78..0d4b7f3 100644
--- a/src/lib/config/ccsession.h
+++ b/src/lib/config/ccsession.h
@@ -354,6 +354,25 @@ private:
     ModuleSpec fetchRemoteSpec(const std::string& module, bool is_filename);
 };
 
+/// \brief Default handler for logging config updates
+///
+/// When CCSession is initialized with handle_logging set to true,
+/// this callback will be used to update the logger when a configuration
+/// change comes in.
+///
+/// This function updates the (global) loggers by initializing a
+/// LoggerManager and passing the settings as specified in the given
+/// configuration update.
+///
+/// \param module_name The name of the module
+/// \param new_config The modified configuration values
+/// \param config_data The full config data for the (remote) logging
+///                    module.
+void
+default_logconfig_handler(const std::string& module_name,
+                          isc::data::ConstElementPtr new_config,
+                          const ConfigData& config_data);
+
 }
 }
 #endif // __CCSESSION_H
diff --git a/src/lib/datasrc/cache.cc b/src/lib/datasrc/cache.cc
index 8e9487d..9082a6b 100644
--- a/src/lib/datasrc/cache.cc
+++ b/src/lib/datasrc/cache.cc
@@ -100,6 +100,19 @@ public:
     /// \return \c RRsetPtr
     RRsetPtr getRRset() const { return (entry->rrset); }
 
+    /// \brief Returns name associated with cached node
+    ///
+    /// This is the name associated with the RRset if it is a positive
+    /// entry, and the associated question name if the RRSet is NULL
+    /// and this is a negative entry (together with an indication that
+    /// this is a negative entry).
+    string getNodeName() const {
+        if (getRRset()) {
+            return (getRRset()->getName().toText());
+        }
+        return (std::string("negative entry for ") + question.toText());
+    }
+
     /// \brief Returns the query response flags associated with the data.
     ///
     /// \return \c uint32_t
@@ -213,7 +226,7 @@ HotCacheImpl::HotCacheImpl(int slots, bool enabled) :
 inline void
 HotCacheImpl::insert(const CacheNodePtr node) {
     LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_CACHE_INSERT).
-        arg(node->getRRset()->getName());
+        arg(node->getNodeName());
     std::map<Question, CacheNodePtr>::const_iterator iter;
     iter = map_.find(node->question);
     if (iter != map_.end()) {
@@ -253,7 +266,7 @@ HotCacheImpl::promote(CacheNodePtr node) {
 void
 HotCacheImpl::remove(ConstCacheNodePtr node) {
     LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_CACHE_REMOVE).
-        arg(node->getRRset()->getName());
+        arg(node->getNodeName());
     lru_.erase(node->lru_entry_);
     map_.erase(node->question);
     --count_;
diff --git a/src/lib/datasrc/messagedef.mes b/src/lib/datasrc/messagedef.mes
index 0374306..dedd2ad 100644
--- a/src/lib/datasrc/messagedef.mes
+++ b/src/lib/datasrc/messagedef.mes
@@ -88,13 +88,13 @@ and put it into the additional section.
 Debug information. The domain is a CNAME (or a DNAME and we created a CNAME
 for it already), so it's being followed.
 
-% QUERY_EMPTY_CNAME cNAME at '%1' is empty
+% QUERY_EMPTY_CNAME CNAME at '%1' is empty
 There was an CNAME and it was being followed. But it contains no records,
 so there's nowhere to go. There will be no answer. This indicates a problem
 with supplied data.
 We tried to follow
 
-% QUERY_TOO_MANY_CNAMES cNAME chain limit exceeded at '%1'
+% QUERY_TOO_MANY_CNAMES CNAME chain limit exceeded at '%1'
 A CNAME led to another CNAME and it led to another, and so on. After 16
 CNAMEs, the software gave up. Long CNAME chains are discouraged, and this
 might possibly be a loop as well. Note that some of the CNAMEs might have
@@ -283,9 +283,9 @@ some other data. But the protocol forbids coexistence of CNAME with anything
 
 % MEM_CNAME_COEXIST can't add data to CNAME in domain '%1'
 This is the same problem as in MEM_CNAME_TO_NONEMPTY, but it happened the
-other way around -- adding some outher data to CNAME.
+other way around -- adding some other data to CNAME.
 
-% MEM_DNAME_NS dNAME and NS can't coexist in non-apex domain '%1'
+% MEM_DNAME_NS DNAME and NS can't coexist in non-apex domain '%1'
 It was requested for DNAME and NS records to be put into the same domain
 which is not the apex (the top of the zone). This is forbidden by RFC
 2672, section 3. This indicates a problem with provided data.
@@ -299,13 +299,13 @@ It was attempted to add the domain into a zone that shouldn't have it
 (eg. the domain is not subdomain of the zone origin). This indicates a
 problem with provided data.
 
-% MEM_WILDCARD_NS nS record in wildcard domain '%1'
+% MEM_WILDCARD_NS NS record in wildcard domain '%1'
 The software refuses to load NS records into a wildcard domain.  It isn't
 explicitly forbidden, but the protocol is ambiguous about how this should
 behave and BIND 9 refuses that as well. Please describe your intention using
 different tools.
 
-% MEM_WILDCARD_DNAME dNAME record in wildcard domain '%1'
+% MEM_WILDCARD_DNAME DNAME record in wildcard domain '%1'
 The software refuses to load DNAME records into a wildcard domain.  It isn't
 explicitly forbidden, but the protocol is ambiguous about how this should
 behave and BIND 9 refuses that as well. Please describe your intention using
@@ -421,11 +421,11 @@ Debug information. The SQLite data source is looking up records of given name
 and type in the database.
 
 % SQLITE_ENCLOSURE looking for zone containing '%1'
-Debug information. The SQLite data source is trying to identify, which zone
+Debug information. The SQLite data source is trying to identify which zone
 should hold this domain.
 
 % SQLITE_ENCLOSURE_NOTFOUND no zone contains it
-Debug information. The last SQLITE_ENCLOSURE query was unsuccessful, there's
+Debug information. The last SQLITE_ENCLOSURE query was unsuccessful; there's
 no such zone in our data.
 
 % SQLITE_PREVIOUS looking for name previous to '%1'
@@ -472,13 +472,13 @@ Debug information. The SQLite data source is identifying if this domain is
 a referral and where it goes.
 
 % SQLITE_FINDREF_BAD_CLASS class mismatch looking for referral ('%1' and '%2')
-The SQLite data source was trying to identify, if there's a referral. But
+The SQLite data source was trying to identify if there's a referral. But
 it contains different class than the query was for.
 
-% SQLITE_CREATE sQLite data source created
+% SQLITE_CREATE SQLite data source created
 Debug information. An instance of SQLite data source is being created.
 
-% SQLITE_DESTROY sQLite data source destroyed
+% SQLITE_DESTROY SQLite data source destroyed
 Debug information. An instance of SQLite data source is being destroyed.
 
 % SQLITE_SETUP setting up SQLite database
diff --git a/src/lib/exceptions/exceptions.h b/src/lib/exceptions/exceptions.h
index a42037b..d0f1d74 100644
--- a/src/lib/exceptions/exceptions.h
+++ b/src/lib/exceptions/exceptions.h
@@ -163,6 +163,17 @@ public:
         oss__ << stream; \
         throw type(__FILE__, __LINE__, oss__.str().c_str()); \
     } while (1)
+
+///
+/// Similar as isc_throw, but allows the exception to have one additional
+/// parameter (the stream/text goes first)
+#define isc_throw_1(type, stream, param1) \
+    do { \
+        std::ostringstream oss__; \
+        oss__ << stream; \
+        throw type(__FILE__, __LINE__, oss__.str().c_str(), param1); \
+    } while (1)
+
 }
 #endif // __EXCEPTIONS_H
 
diff --git a/src/lib/log/logger.cc b/src/lib/log/logger.cc
index 5a35d36..d10e979 100644
--- a/src/lib/log/logger.cc
+++ b/src/lib/log/logger.cc
@@ -18,6 +18,7 @@
 #include <log/logger.h>
 #include <log/logger_impl.h>
 #include <log/logger_name.h>
+#include <log/logger_support.h>
 #include <log/message_dictionary.h>
 #include <log/message_types.h>
 
@@ -28,9 +29,14 @@ using namespace std;
 namespace isc {
 namespace log {
 
-// Initialize Logger.
+// Initialize underlying logger, but only if logging has been initialized.
 void Logger::initLoggerImpl() {
-    loggerptr_ = new LoggerImpl(name_);
+    if (isLoggingInitialized()) {
+        loggerptr_ = new LoggerImpl(name_);
+    } else {
+        isc_throw(LoggingNotInitialized, "attempt to access logging function "
+                  "before logging has been initialized");
+    }
 }
 
 // Destructor.
diff --git a/src/lib/log/logger.h b/src/lib/log/logger.h
index 378db10..96168c0 100644
--- a/src/lib/log/logger.h
+++ b/src/lib/log/logger.h
@@ -18,6 +18,7 @@
 #include <cstdlib>
 #include <string>
 
+#include <exceptions/exceptions.h>
 #include <log/logger_level.h>
 #include <log/message_types.h>
 #include <log/log_formatter.h>
@@ -73,6 +74,17 @@ namespace log {
 
 class LoggerImpl;   // Forward declaration of the implementation class
 
+/// \brief Logging Not Initialized
+///
+/// Exception thrown if an attempt is made to access a logging function
+/// if the logging system has not been initialized.
+class LoggingNotInitialized : public isc::Exception {
+public:
+    LoggingNotInitialized(const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what)
+    {}
+};
+
 /// \brief Logger Class
 ///
 /// This class is the main class used for logging.  Use comprises:
@@ -224,15 +236,14 @@ private:
 
     /// \brief Initialize Implementation
     ///
-    /// Returns the logger pointer.  If not yet set, the underlying
-    /// implementation class is initialized.\n
-    /// \n
-    /// The reason for this indirection is to avoid the "static initialization
-    /// fiacso", whereby we cannot rely on the order of static initializations.
-    /// The main problem is the root logger name - declared statically - which
-    /// is referenced by various loggers.  By deferring a reference to it until
-    /// after the program starts executing - by which time the root name object
-    /// will be initialized - we avoid this problem.
+    /// Returns the logger pointer.  If not yet set, the implementation class is
+    /// initialized.
+    ///
+    /// The main reason for this is to allow loggers to be declared statically
+    /// before the underlying logging system is initialized.  However, any
+    /// attempt to access a logging method on any logger before initialization -
+    /// regardless of whether is is statically or automatically declared -  will
+    /// cause a "LoggingNotInitialized" exception to be thrown.
     ///
     /// \return Returns pointer to implementation
     LoggerImpl* getLoggerPtr() {
diff --git a/src/lib/log/logger_impl.cc b/src/lib/log/logger_impl.cc
index cbf2f1f..046da13 100644
--- a/src/lib/log/logger_impl.cc
+++ b/src/lib/log/logger_impl.cc
@@ -98,7 +98,7 @@ LoggerImpl::getEffectiveDebugLevel() {
 // Output a general message
 string*
 LoggerImpl::lookupMessage(const MessageID& ident) {
-    return (new string(string(ident) + ", " +
+    return (new string(string(ident) + " " +
                        MessageDictionary::globalDictionary().getText(ident)));
 }
 
diff --git a/src/lib/log/logger_manager.cc b/src/lib/log/logger_manager.cc
index 9955a83..4d56e4b 100644
--- a/src/lib/log/logger_manager.cc
+++ b/src/lib/log/logger_manager.cc
@@ -15,10 +15,11 @@
 #include <algorithm>
 #include <vector>
 
-#include <log/logger.h>
+#include <log/logger_level.h>
 #include <log/logger_manager_impl.h>
 #include <log/logger_manager.h>
 #include <log/logger_name.h>
+#include <log/logger_support.h>
 #include <log/messagedef.h>
 #include <log/message_dictionary.h>
 #include <log/message_exception.h>
@@ -110,6 +111,7 @@ LoggerManager::init(const std::string& root, isc::log::Severity severity,
     // Initialize the implementation logging.  After this point, some basic
     // logging has been set up and messages can be logged.
     LoggerManagerImpl::init(severity, dbglevel);
+    setLoggingInitialized();
 
     // Check if there were any duplicate message IDs in the default dictionary
     // and if so, log them.  Log using the logging facility logger.
diff --git a/src/lib/log/logger_support.cc b/src/lib/log/logger_support.cc
index 78e28f3..73323a0 100644
--- a/src/lib/log/logger_support.cc
+++ b/src/lib/log/logger_support.cc
@@ -29,20 +29,37 @@
 #include <iostream>
 #include <string>
 
-#include <log/logger.h>
+#include <log/logger_level.h>
 #include <log/logger_manager.h>
 #include <log/logger_support.h>
 
+using namespace std;
+
+namespace {
+
+// Flag to hold logging initialization state.
+bool logging_init_state = false;
+
+} // Anonymous namespace
+
 namespace isc {
 namespace log {
 
-using namespace std;
+// Return initialization state.
+bool
+isLoggingInitialized() {
+    return (logging_init_state);
+}
 
-// Declare a logger for the logging subsystem.  This is a sub-logger of the
-// root logger and is used in all functions in this file.
-Logger logger("log");
+// Set initialization state.  (Note: as logging can be initialized via a direct
+// call to LoggerManager::init(), this function is called from there, not from
+// the initialization functions in this file.
+void
+setLoggingInitialized(bool state) {
+    logging_init_state = state;
+}
 
-/// Logger Run-Time Initialization
+// Logger Run-Time Initialization.
 
 void
 initLogger(const string& root, isc::log::Severity severity, int dbglevel,
@@ -50,7 +67,7 @@ initLogger(const string& root, isc::log::Severity severity, int dbglevel,
     LoggerManager::init(root, severity, dbglevel, file);
 }
 
-/// Logger Run-Time Initialization via Environment Variables
+// Logger Run-Time Initialization via Environment Variables
 void initLogger(isc::log::Severity severity, int dbglevel) {
 
     // Root logger name is defined by the environment variable B10_LOGGER_ROOT.
@@ -79,20 +96,20 @@ void initLogger(isc::log::Severity severity, int dbglevel) {
             try {
                 level = boost::lexical_cast<int>(dbg_char);
                 if (level < MIN_DEBUG_LEVEL) {
-                    std::cerr << "**ERROR** debug level of " << level
-                              << " is invalid - a value of " << MIN_DEBUG_LEVEL
-                              << " will be used\n";
+                    cerr << "**ERROR** debug level of " << level
+                         << " is invalid - a value of " << MIN_DEBUG_LEVEL
+                         << " will be used\n";
                     level = MIN_DEBUG_LEVEL;
                 } else if (level > MAX_DEBUG_LEVEL) {
-                    std::cerr << "**ERROR** debug level of " << level
-                              << " is invalid - a value of " << MAX_DEBUG_LEVEL
-                              << " will be used\n";
+                    cerr << "**ERROR** debug level of " << level
+                         << " is invalid - a value of " << MAX_DEBUG_LEVEL
+                         << " will be used\n";
                     level = MAX_DEBUG_LEVEL;
                 }
             } catch (...) {
                 // Error, but not fatal to the test
-                std::cerr << "**ERROR** Unable to translate "
-                             "B10_LOGGER_DBGLEVEL - a value of 0 will be used\n";
+                cerr << "**ERROR** Unable to translate "
+                        "B10_LOGGER_DBGLEVEL - a value of 0 will be used\n";
             }
             dbglevel = level;
         }
diff --git a/src/lib/log/logger_support.h b/src/lib/log/logger_support.h
index 5d574d3..4bc8acc 100644
--- a/src/lib/log/logger_support.h
+++ b/src/lib/log/logger_support.h
@@ -23,6 +23,26 @@
 namespace isc {
 namespace log {
 
+/// \brief Is logging initialized?
+///
+/// As some underlying logging implementations can behave unpredictably if they
+/// have not been initialized when a logging function is called, their
+/// initialization state is tracked.  The logger functions will check this flag
+/// and throw an exception if logging is not initialized at that point.
+///
+/// \return true if logging has been initialized, false if not
+bool isLoggingInitialized();
+
+/// \brief Set "logging initialized" flag
+///
+/// Sets the state of the "logging initialized" flag.
+///
+/// \param state State to set the flag to. (This is expected to be "true" - the
+///        default - for all code apart from specific unit tests.)
+void setLoggingInitialized(bool state = true);
+
+
+
 /// \brief Run-Time Initialization
 ///
 /// Performs run-time initialization of the logger in particular supplying:
@@ -70,7 +90,9 @@ void initLogger(const std::string& root,
 ///
 /// Any errors in the settings cause messages to be output to stderr.
 ///
-/// This function is most likely to be called from unit test programs.
+/// This function is aimed at test programs, allowing the default settings to
+/// be overridden by the tester.  It is not intended for use in production
+/// code.
 
 void initLogger(isc::log::Severity severity = isc::log::INFO,
                 int dbglevel = 0);
diff --git a/src/lib/log/tests/Makefile.am b/src/lib/log/tests/Makefile.am
index 93703c1..cd2ae29 100644
--- a/src/lib/log/tests/Makefile.am
+++ b/src/lib/log/tests/Makefile.am
@@ -19,6 +19,7 @@ run_unittests_SOURCES += logger_level_impl_unittest.cc
 run_unittests_SOURCES += logger_level_unittest.cc
 run_unittests_SOURCES += logger_manager_unittest.cc
 run_unittests_SOURCES += logger_name_unittest.cc
+run_unittests_SOURCES += logger_support_unittest.cc
 run_unittests_SOURCES += logger_unittest.cc
 run_unittests_SOURCES += logger_specification_unittest.cc
 run_unittests_SOURCES += message_dictionary_unittest.cc
diff --git a/src/lib/log/tests/destination_test.sh.in b/src/lib/log/tests/destination_test.sh.in
index ff2d3fb..e02141d 100755
--- a/src/lib/log/tests/destination_test.sh.in
+++ b/src/lib/log/tests/destination_test.sh.in
@@ -37,10 +37,10 @@ passfail() {
 
 echo "1. One logger, multiple destinations:"
 cat > $tempfile << .
-FATAL [example] MSG_WRITERR, error writing to test1: 42
-ERROR [example] MSG_RDLOCMES, reading local message file dummy/file
-FATAL [example.beta] MSG_BADSEVERITY, unrecognized log severity: beta_fatal
-ERROR [example.beta] MSG_BADDESTINATION, unrecognized log destination: beta_error
+FATAL [example] MSG_WRITERR error writing to test1: 42
+ERROR [example] MSG_RDLOCMES reading local message file dummy/file
+FATAL [example.beta] MSG_BADSEVERITY unrecognized log severity: beta_fatal
+ERROR [example.beta] MSG_BADDESTINATION unrecognized log destination: beta_error
 .
 rm -f $destfile1 $destfile2
 ./logger_example -s error -f $destfile1 -f $destfile2
@@ -61,13 +61,13 @@ rm -f $destfile1 $destfile2
 # Output for example.alpha should have done to destfile2.
 
 cat > $tempfile << .
-FATAL [example] MSG_WRITERR, error writing to test1: 42
-ERROR [example] MSG_RDLOCMES, reading local message file dummy/file
-WARN  [example] MSG_BADSTREAM, bad log console output stream: example
-FATAL [example.beta] MSG_BADSEVERITY, unrecognized log severity: beta_fatal
-ERROR [example.beta] MSG_BADDESTINATION, unrecognized log destination: beta_error
-WARN  [example.beta] MSG_BADSTREAM, bad log console output stream: beta_warn
-INFO  [example.beta] MSG_READERR, error reading from message file beta: info
+FATAL [example] MSG_WRITERR error writing to test1: 42
+ERROR [example] MSG_RDLOCMES reading local message file dummy/file
+WARN  [example] MSG_BADSTREAM bad log console output stream: example
+FATAL [example.beta] MSG_BADSEVERITY unrecognized log severity: beta_fatal
+ERROR [example.beta] MSG_BADDESTINATION unrecognized log destination: beta_error
+WARN  [example.beta] MSG_BADSTREAM bad log console output stream: beta_warn
+INFO  [example.beta] MSG_READERR error reading from message file beta: info
 .
 echo -n  "   - destination 1:"
 cut -d' ' -f3- $destfile1 | diff $tempfile -
@@ -75,7 +75,7 @@ passfail $?
 
 echo -n  "   - destination 2:"
 cat > $tempfile << .
-WARN  [example.alpha] MSG_READERR, error reading from message file a.txt: dummy reason
+WARN  [example.alpha] MSG_READERR error reading from message file a.txt: dummy reason
 .
 cut -d' ' -f3- $destfile2 | diff $tempfile -
 passfail $?
diff --git a/src/lib/log/tests/local_file_test.sh.in b/src/lib/log/tests/local_file_test.sh.in
index 53b0c2f..4308f96 100755
--- a/src/lib/log/tests/local_file_test.sh.in
+++ b/src/lib/log/tests/local_file_test.sh.in
@@ -37,36 +37,35 @@ passfail() {
 # Create the local message file for testing
 
 cat > $localmes << .
-\$PREFIX MSG_
-% NOTHERE     this message is not in the global dictionary
-% READERR     replacement read error, parameters: '%1' and '%2'
-% RDLOCMES    replacement read local message file, parameter is '%1'
+% MSG_NOTHERE     this message is not in the global dictionary
+% MSG_READERR     replacement read error, parameters: '%1' and '%2'
+% MSG_RDLOCMES    replacement read local message file, parameter is '%1'
 .
 
 echo -n "1. Local message replacement:"
 cat > $tempfile << .
-WARN  [example.log] MSG_IDNOTFND, could not replace message text for 'MSG_NOTHERE': no such message
-FATAL [example] MSG_WRITERR, error writing to test1: 42
-ERROR [example] MSG_RDLOCMES, replacement read local message file, parameter is 'dummy/file'
-WARN  [example] MSG_BADSTREAM, bad log console output stream: example
-WARN  [example.alpha] MSG_READERR, replacement read error, parameters: 'a.txt' and 'dummy reason'
-FATAL [example.beta] MSG_BADSEVERITY, unrecognized log severity: beta_fatal
-ERROR [example.beta] MSG_BADDESTINATION, unrecognized log destination: beta_error
-WARN  [example.beta] MSG_BADSTREAM, bad log console output stream: beta_warn
+WARN  [example.log] MSG_IDNOTFND could not replace message text for 'MSG_NOTHERE': no such message
+FATAL [example] MSG_WRITERR error writing to test1: 42
+ERROR [example] MSG_RDLOCMES replacement read local message file, parameter is 'dummy/file'
+WARN  [example] MSG_BADSTREAM bad log console output stream: example
+WARN  [example.alpha] MSG_READERR replacement read error, parameters: 'a.txt' and 'dummy reason'
+FATAL [example.beta] MSG_BADSEVERITY unrecognized log severity: beta_fatal
+ERROR [example.beta] MSG_BADDESTINATION unrecognized log destination: beta_error
+WARN  [example.beta] MSG_BADSTREAM bad log console output stream: beta_warn
 .
 ./logger_example -c stdout -s warn $localmes | cut -d' ' -f3- | diff $tempfile -
 passfail $?
 
 echo -n "2. Report error if unable to read local message file:"
 cat > $tempfile << .
-ERROR [example.log] MSG_OPENIN, unable to open message file $localmes for input: No such file or directory
-FATAL [example] MSG_WRITERR, error writing to test1: 42
-ERROR [example] MSG_RDLOCMES, reading local message file dummy/file
-WARN  [example] MSG_BADSTREAM, bad log console output stream: example
-WARN  [example.alpha] MSG_READERR, error reading from message file a.txt: dummy reason
-FATAL [example.beta] MSG_BADSEVERITY, unrecognized log severity: beta_fatal
-ERROR [example.beta] MSG_BADDESTINATION, unrecognized log destination: beta_error
-WARN  [example.beta] MSG_BADSTREAM, bad log console output stream: beta_warn
+ERROR [example.log] MSG_OPENIN unable to open message file $localmes for input: No such file or directory
+FATAL [example] MSG_WRITERR error writing to test1: 42
+ERROR [example] MSG_RDLOCMES reading local message file dummy/file
+WARN  [example] MSG_BADSTREAM bad log console output stream: example
+WARN  [example.alpha] MSG_READERR error reading from message file a.txt: dummy reason
+FATAL [example.beta] MSG_BADSEVERITY unrecognized log severity: beta_fatal
+ERROR [example.beta] MSG_BADDESTINATION unrecognized log destination: beta_error
+WARN  [example.beta] MSG_BADSTREAM bad log console output stream: beta_warn
 .
 rm -f $localmes
 ./logger_example -c stdout -s warn $localmes | cut -d' ' -f3- | diff $tempfile -
diff --git a/src/lib/log/tests/logger_support_unittest.cc b/src/lib/log/tests/logger_support_unittest.cc
new file mode 100644
index 0000000..7e5d23a
--- /dev/null
+++ b/src/lib/log/tests/logger_support_unittest.cc
@@ -0,0 +1,72 @@
+// 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>
+#include <log/messagedef.h>
+
+using namespace isc::log;
+
+// Check that the initialized flag can be manipulated.  This is a bit chicken-
+// -and-egg: we want to reset to the flag to the original value at the end
+// of the test, so use the functions to do that.  But we are trying to check
+// that these functions in fact work.
+
+TEST(LoggerSupportTest, InitializedFlag) {
+    bool current_flag = isLoggingInitialized();
+
+    // check we can flip the flag.
+    setLoggingInitialized(!current_flag);
+    EXPECT_NE(current_flag, isLoggingInitialized());
+    setLoggingInitialized(!isLoggingInitialized());
+    EXPECT_EQ(current_flag, isLoggingInitialized());
+
+    // Check we can set it to explicit values (tests that a call to the "set"
+    // function does not just flip the flag).
+    setLoggingInitialized(false);
+    EXPECT_FALSE(isLoggingInitialized());
+    setLoggingInitialized(false);
+    EXPECT_FALSE(isLoggingInitialized());
+
+    setLoggingInitialized(true);
+    EXPECT_TRUE(isLoggingInitialized());
+    setLoggingInitialized(true);
+    EXPECT_TRUE(isLoggingInitialized());
+
+    // Reset to original value
+    setLoggingInitialized(current_flag);
+}
+
+// Check that a logger will throw an exception if logging has not been
+// initialized.
+
+TEST(LoggerSupportTest, LoggingInitializationCheck) {
+
+    // Assert that logging has been initialized (it should be in main()).
+    bool current_flag = isLoggingInitialized();
+    EXPECT_TRUE(current_flag);
+
+    // Flag that it has not been initialized and declare a logger. Any logging
+    // operation should then throw.
+    setLoggingInitialized(false);
+    isc::log::Logger test_logger("test");
+
+    EXPECT_THROW(test_logger.isDebugEnabled(), LoggingNotInitialized);
+    EXPECT_THROW(test_logger.info(MSG_OPENIN), LoggingNotInitialized);
+
+    // ... and check that they work when logging is initialized.
+    setLoggingInitialized(true);
+    EXPECT_NO_THROW(test_logger.isDebugEnabled());
+    EXPECT_NO_THROW(test_logger.info(MSG_OPENIN));
+}
diff --git a/src/lib/log/tests/severity_test.sh.in b/src/lib/log/tests/severity_test.sh.in
index 6f4d27a..0a304e0 100755
--- a/src/lib/log/tests/severity_test.sh.in
+++ b/src/lib/log/tests/severity_test.sh.in
@@ -35,44 +35,44 @@ passfail() {
 
 echo -n "1. runInitTest default parameters:"
 cat > $tempfile << .
-FATAL [example] MSG_WRITERR, error writing to test1: 42
-ERROR [example] MSG_RDLOCMES, reading local message file dummy/file
-WARN  [example] MSG_BADSTREAM, bad log console output stream: example
-WARN  [example.alpha] MSG_READERR, error reading from message file a.txt: dummy reason
-INFO  [example.alpha] MSG_OPENIN, unable to open message file example.msg for input: dummy reason
-FATAL [example.beta] MSG_BADSEVERITY, unrecognized log severity: beta_fatal
-ERROR [example.beta] MSG_BADDESTINATION, unrecognized log destination: beta_error
-WARN  [example.beta] MSG_BADSTREAM, bad log console output stream: beta_warn
-INFO  [example.beta] MSG_READERR, error reading from message file beta: info
+FATAL [example] MSG_WRITERR error writing to test1: 42
+ERROR [example] MSG_RDLOCMES reading local message file dummy/file
+WARN  [example] MSG_BADSTREAM bad log console output stream: example
+WARN  [example.alpha] MSG_READERR error reading from message file a.txt: dummy reason
+INFO  [example.alpha] MSG_OPENIN unable to open message file example.msg for input: dummy reason
+FATAL [example.beta] MSG_BADSEVERITY unrecognized log severity: beta_fatal
+ERROR [example.beta] MSG_BADDESTINATION unrecognized log destination: beta_error
+WARN  [example.beta] MSG_BADSTREAM bad log console output stream: beta_warn
+INFO  [example.beta] MSG_READERR error reading from message file beta: info
 .
 ./logger_example -c stdout | cut -d' ' -f3- | diff $tempfile -
 passfail $?
 
 echo -n "2. Severity filter:"
 cat > $tempfile << .
-FATAL [example] MSG_WRITERR, error writing to test1: 42
-ERROR [example] MSG_RDLOCMES, reading local message file dummy/file
-FATAL [example.beta] MSG_BADSEVERITY, unrecognized log severity: beta_fatal
-ERROR [example.beta] MSG_BADDESTINATION, unrecognized log destination: beta_error
+FATAL [example] MSG_WRITERR error writing to test1: 42
+ERROR [example] MSG_RDLOCMES reading local message file dummy/file
+FATAL [example.beta] MSG_BADSEVERITY unrecognized log severity: beta_fatal
+ERROR [example.beta] MSG_BADDESTINATION unrecognized log destination: beta_error
 .
 ./logger_example -c stdout -s error | cut -d' ' -f3- | diff $tempfile -
 passfail $?
 
 echo -n "3. Debug level:"
 cat > $tempfile << .
-FATAL [example] MSG_WRITERR, error writing to test1: 42
-ERROR [example] MSG_RDLOCMES, reading local message file dummy/file
-WARN  [example] MSG_BADSTREAM, bad log console output stream: example
-WARN  [example.alpha] MSG_READERR, error reading from message file a.txt: dummy reason
-INFO  [example.alpha] MSG_OPENIN, unable to open message file example.msg for input: dummy reason
-DEBUG [example] MSG_RDLOCMES, reading local message file example/0
-DEBUG [example] MSG_RDLOCMES, reading local message file example/24
-DEBUG [example] MSG_RDLOCMES, reading local message file example/25
-FATAL [example.beta] MSG_BADSEVERITY, unrecognized log severity: beta_fatal
-ERROR [example.beta] MSG_BADDESTINATION, unrecognized log destination: beta_error
-WARN  [example.beta] MSG_BADSTREAM, bad log console output stream: beta_warn
-INFO  [example.beta] MSG_READERR, error reading from message file beta: info
-DEBUG [example.beta] MSG_BADSEVERITY, unrecognized log severity: beta/25
+FATAL [example] MSG_WRITERR error writing to test1: 42
+ERROR [example] MSG_RDLOCMES reading local message file dummy/file
+WARN  [example] MSG_BADSTREAM bad log console output stream: example
+WARN  [example.alpha] MSG_READERR error reading from message file a.txt: dummy reason
+INFO  [example.alpha] MSG_OPENIN unable to open message file example.msg for input: dummy reason
+DEBUG [example] MSG_RDLOCMES reading local message file example/0
+DEBUG [example] MSG_RDLOCMES reading local message file example/24
+DEBUG [example] MSG_RDLOCMES reading local message file example/25
+FATAL [example.beta] MSG_BADSEVERITY unrecognized log severity: beta_fatal
+ERROR [example.beta] MSG_BADDESTINATION unrecognized log destination: beta_error
+WARN  [example.beta] MSG_BADSTREAM bad log console output stream: beta_warn
+INFO  [example.beta] MSG_READERR error reading from message file beta: info
+DEBUG [example.beta] MSG_BADSEVERITY unrecognized log severity: beta/25
 .
 ./logger_example -c stdout -s debug -d 25 | cut -d' ' -f3- | diff $tempfile -
 passfail $?
diff --git a/src/lib/python/isc/cc/tests/Makefile.am b/src/lib/python/isc/cc/tests/Makefile.am
index dc19758..4e49501 100644
--- a/src/lib/python/isc/cc/tests/Makefile.am
+++ b/src/lib/python/isc/cc/tests/Makefile.am
@@ -6,6 +6,13 @@ EXTRA_DIST = $(PYTESTS)
 EXTRA_DIST += sendcmd.py
 EXTRA_DIST += test_session.py
 
+# If necessary (rare cases), explicitly specify paths to dynamic libraries
+# required by loadable python modules.
+LIBRARY_PATH_PLACEHOLDER =
+if SET_ENV_LIBRARY_PATH
+LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/cc/.libs:$(abs_top_builddir)/src/lib/config/.libs:$(abs_top_builddir)/src/lib/log/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$$$(ENV_LIBRARY_PATH)
+endif
+
 # test using command-line arguments, so use check-local target instead of TESTS
 check-local:
 if ENABLE_PYTHON_COVERAGE
@@ -15,6 +22,7 @@ if ENABLE_PYTHON_COVERAGE
 endif
 	for pytest in $(PYTESTS) ; do \
 	echo Running test: $$pytest ; \
+	$(LIBRARY_PATH_PLACEHOLDER) \
 	env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python \
 	BIND10_TEST_SOCKET_FILE=$(builddir)/test_socket.sock \
 	$(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
diff --git a/src/lib/python/isc/config/ccsession.py b/src/lib/python/isc/config/ccsession.py
index 84809f1..0869160 100644
--- a/src/lib/python/isc/config/ccsession.py
+++ b/src/lib/python/isc/config/ccsession.py
@@ -39,6 +39,10 @@
 from isc.cc import Session
 from isc.config.config_data import ConfigData, MultiConfigData, BIND10_CONFIG_DATA_VERSION
 import isc
+from isc.util.file import path_search
+import bind10_config
+from isc.log import log_config_update
+import json
 
 class ModuleCCSessionError(Exception): pass
 
@@ -116,6 +120,18 @@ def create_command(command_name, params = None):
     msg = { 'command': cmd }
     return msg
 
+def default_logconfig_handler(new_config, config_data):
+    errors = []
+
+    if config_data.get_module_spec().validate_config(False, new_config, errors):
+        isc.log.log_config_update(json.dumps(new_config),
+            json.dumps(config_data.get_module_spec().get_full_spec()))
+    else:
+        # no logging here yet, TODO: log these errors
+        print("Error in logging configuration, ignoring config update: ")
+        for err in errors:
+            print(err)
+
 class ModuleCCSession(ConfigData):
     """This class maintains a connection to the command channel, as
        well as configuration options for modules. The module provides
@@ -126,7 +142,7 @@ 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):
+    def __init__(self, spec_file_name, config_handler, command_handler, cc_session = None, handle_logging_config = False):
         """Initialize a ModuleCCSession. This does *NOT* send the
            specification and request the configuration yet. Use start()
            for that once the ModuleCCSession has been initialized.
@@ -149,6 +165,11 @@ class ModuleCCSession(ConfigData):
         self._session.group_subscribe(self._module_name, "*")
 
         self._remote_module_configs = {}
+        self._remote_module_callbacks = {}
+
+        if handle_logging_config:
+            self.add_remote_config(path_search('logging.spec', bind10_config.PLUGIN_PATHS),
+                                   default_logconfig_handler)
 
     def __del__(self):
         # If the CC Session obejct has been closed, it returns
@@ -218,6 +239,9 @@ class ModuleCCSession(ConfigData):
                             newc = self._remote_module_configs[module_name].get_local_config()
                             isc.cc.data.merge(newc, new_config)
                             self._remote_module_configs[module_name].set_local_config(newc)
+                            if self._remote_module_callbacks[module_name] != None:
+                                self._remote_module_callbacks[module_name](new_config,
+                                                                           self._remote_module_configs[module_name])
                         # For other modules, we're not supposed to answer
                         return
 
@@ -260,7 +284,7 @@ class ModuleCCSession(ConfigData):
            and return an answer created with create_answer()"""
         self._command_handler = command_handler
 
-    def add_remote_config(self, spec_file_name):
+    def add_remote_config(self, spec_file_name, config_update_callback = None):
         """Gives access to the configuration of a different module.
            These remote module options can at this moment only be
            accessed through get_remote_config_value(). This function
@@ -289,9 +313,12 @@ class ModuleCCSession(ConfigData):
             if rcode == 0:
                 if value != None and module_spec.validate_config(False, value):
                     module_cfg.set_local_config(value);
+                    if config_update_callback is not None:
+                        config_update_callback(value, module_cfg)
 
         # all done, add it
         self._remote_module_configs[module_name] = module_cfg
+        self._remote_module_callbacks[module_name] = config_update_callback
         return module_name
         
     def remove_remote_config(self, module_name):
@@ -299,6 +326,7 @@ class ModuleCCSession(ConfigData):
         if module_name in self._remote_module_configs:
             self._session.group_unsubscribe(module_name)
             del self._remote_module_configs[module_name]
+            del self._remote_module_callbacks[module_name]
 
     def get_remote_config_value(self, module_name, identifier):
         """Returns the current setting for the given identifier at the
diff --git a/src/lib/python/isc/config/tests/Makefile.am b/src/lib/python/isc/config/tests/Makefile.am
index 60da781..b5f5501 100644
--- a/src/lib/python/isc/config/tests/Makefile.am
+++ b/src/lib/python/isc/config/tests/Makefile.am
@@ -4,6 +4,13 @@ PYTESTS += module_spec_test.py
 EXTRA_DIST = $(PYTESTS)
 EXTRA_DIST += unittest_fakesession.py
 
+# If necessary (rare cases), explicitly specify paths to dynamic libraries
+# required by loadable python modules.
+LIBRARY_PATH_PLACEHOLDER =
+if SET_ENV_LIBRARY_PATH
+LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/cc/.libs:$(abs_top_builddir)/src/lib/config/.libs:$(abs_top_builddir)/src/lib/log/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$$$(ENV_LIBRARY_PATH)
+endif
+
 # test using command-line arguments, so use check-local target instead of TESTS
 check-local:
 if ENABLE_PYTHON_COVERAGE
@@ -13,7 +20,9 @@ if ENABLE_PYTHON_COVERAGE
 endif
 	for pytest in $(PYTESTS) ; do \
 	echo Running test: $$pytest ; \
+	$(LIBRARY_PATH_PLACEHOLDER) \
 	env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python \
+	B10_TEST_PLUGIN_DIR=$(abs_top_srcdir)/src/bin/cfgmgr/plugins \
 	CONFIG_TESTDATA_PATH=$(abs_top_srcdir)/src/lib/config/tests/testdata \
 	CONFIG_WR_TESTDATA_PATH=$(abs_top_builddir)/src/lib/config/tests/testdata \
 	$(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
diff --git a/src/lib/python/isc/config/tests/ccsession_test.py b/src/lib/python/isc/config/tests/ccsession_test.py
index a0cafd6..830cbd7 100644
--- a/src/lib/python/isc/config/tests/ccsession_test.py
+++ b/src/lib/python/isc/config/tests/ccsession_test.py
@@ -22,6 +22,7 @@ import os
 from isc.config.ccsession import *
 from isc.config.config_data import BIND10_CONFIG_DATA_VERSION
 from unittest_fakesession import FakeModuleCCSession, WouldBlockForever
+import bind10_config
 
 class TestHelperFunctions(unittest.TestCase):
     def test_parse_answer(self):
@@ -604,7 +605,43 @@ class TestModuleCCSession(unittest.TestCase):
         self.assertEqual(len(fake_session.message_queue), 1)
         mccs.check_command()
         self.assertEqual(len(fake_session.message_queue), 0)
-        
+
+    def test_logconfig_handler(self):
+        # test whether default_logconfig_handler reacts nicely to
+        # bad data. We assume the actual logger output is tested
+        # elsewhere
+        self.assertRaises(TypeError, default_logconfig_handler);
+        self.assertRaises(TypeError, default_logconfig_handler, 1);
+
+        spec = isc.config.module_spec_from_file(
+            path_search('logging.spec', bind10_config.PLUGIN_PATHS))
+        config_data = ConfigData(spec)
+
+        self.assertRaises(TypeError, default_logconfig_handler, 1, config_data)
+
+        default_logconfig_handler({}, config_data)
+
+        # Wrong data should not raise, but simply not be accepted
+        # This would log a lot of errors, so we may want to suppress that later
+        default_logconfig_handler({ "bad_data": "indeed" }, config_data)
+        default_logconfig_handler({ "bad_data": 1}, config_data)
+        default_logconfig_handler({ "bad_data": 1123 }, config_data)
+        default_logconfig_handler({ "bad_data": True }, config_data)
+        default_logconfig_handler({ "bad_data": False }, config_data)
+        default_logconfig_handler({ "bad_data": 1.1 }, config_data)
+        default_logconfig_handler({ "bad_data": [] }, config_data)
+        default_logconfig_handler({ "bad_data": [[],[],[[1, 3, False, "foo" ]]] },
+                                  config_data)
+        default_logconfig_handler({ "bad_data": [ 1, 2, { "b": { "c": "d" } } ] },
+                                  config_data)
+
+        # Try a correct config
+        log_conf = {"loggers":
+                       [{"name": "b10-xfrout", "output_options":
+                           [{"output": "/tmp/bind10.log",
+                                       "destination": "file",
+                                       "flush": True}]}]}
+        default_logconfig_handler(log_conf, config_data)
 
 class fakeData:
     def decode(self):
diff --git a/src/lib/python/isc/datasrc/tests/Makefile.am b/src/lib/python/isc/datasrc/tests/Makefile.am
index a6c5c58..6f6d157 100644
--- a/src/lib/python/isc/datasrc/tests/Makefile.am
+++ b/src/lib/python/isc/datasrc/tests/Makefile.am
@@ -6,6 +6,13 @@ EXTRA_DIST += testdata/brokendb.sqlite3
 EXTRA_DIST += testdata/example.com.sqlite3
 CLEANFILES = $(abs_builddir)/example.com.out.sqlite3
 
+# If necessary (rare cases), explicitly specify paths to dynamic libraries
+# required by loadable python modules.
+LIBRARY_PATH_PLACEHOLDER =
+if SET_ENV_LIBRARY_PATH
+LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/cc/.libs:$(abs_top_builddir)/src/lib/config/.libs:$(abs_top_builddir)/src/lib/log/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$$$(ENV_LIBRARY_PATH)
+endif
+
 # test using command-line arguments, so use check-local target instead of TESTS
 check-local:
 if ENABLE_PYTHON_COVERAGE
@@ -15,6 +22,7 @@ if ENABLE_PYTHON_COVERAGE
 endif
 	for pytest in $(PYTESTS) ; do \
 	echo Running test: $$pytest ; \
+	$(LIBRARY_PATH_PLACEHOLDER) \
 	env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/lib/python/isc/log \
 	TESTDATA_PATH=$(abs_srcdir)/testdata \
 	TESTDATA_WRITE_PATH=$(abs_builddir) \
diff --git a/src/lib/python/isc/log/Makefile.am b/src/lib/python/isc/log/Makefile.am
index 26735e7..b228caf 100644
--- a/src/lib/python/isc/log/Makefile.am
+++ b/src/lib/python/isc/log/Makefile.am
@@ -15,6 +15,9 @@ log_la_CXXFLAGS = $(AM_CXXFLAGS) $(PYTHON_CXXFLAGS)
 log_la_LDFLAGS = $(PYTHON_LDFLAGS)
 log_la_LDFLAGS += -module
 log_la_LIBADD = $(top_builddir)/src/lib/log/liblog.la
+log_la_LIBADD += $(top_builddir)/src/lib/cc/libcc.la
+log_la_LIBADD += $(top_builddir)/src/lib/config/libcfgclient.la
+log_la_LIBADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
 log_la_LIBADD += $(PYTHON_LIB)
 
 # This is not installed, it helps locate the module during tests
diff --git a/src/lib/python/isc/log/__init__.py b/src/lib/python/isc/log/__init__.py
index ad77dff..641cf79 100644
--- a/src/lib/python/isc/log/__init__.py
+++ b/src/lib/python/isc/log/__init__.py
@@ -23,7 +23,11 @@
 # Should we look there? Or define something in bind10_config?
 
 import os
-cwd = os.getcwd()
-pos = cwd.rfind('/src/')
-import sys; sys.path.insert(0, cwd[:pos] + '/src/lib/python/isc/log/.libs')
+import sys
+
+for base in sys.path[:]:
+    loglibdir = os.path.join(base, 'isc/log/.libs')
+    if os.path.exists(loglibdir):
+        sys.path.insert(0, loglibdir)
+
 from log import *
diff --git a/src/lib/python/isc/log/log.cc b/src/lib/python/isc/log/log.cc
index b29c005..484151f 100644
--- a/src/lib/python/isc/log/log.cc
+++ b/src/lib/python/isc/log/log.cc
@@ -22,6 +22,8 @@
 #include <log/logger_manager.h>
 #include <log/logger.h>
 
+#include <config/ccsession.h>
+
 #include <string>
 #include <boost/bind.hpp>
 
@@ -39,7 +41,12 @@ using boost::bind;
 // to solve this issue.
 namespace clang_unnamed_namespace_workaround {
     // To propagate python exceptions through our code
-    class InternalError {};
+    // This exception is used to signal to the calling function that a
+    // proper Python Exception has already been set, and the caller
+    // should now return NULL.
+    // Since it is only used internally, and should not pass any
+    // information itself, is is not derived from std::exception
+    class InternalError : public std::exception {};
 }
 using namespace clang_unnamed_namespace_workaround;
 
@@ -177,6 +184,47 @@ init(PyObject*, PyObject* args) {
     Py_RETURN_NONE;
 }
 
+PyObject*
+logConfigUpdate(PyObject*, PyObject* args) {
+    // we have no wrappers for ElementPtr and ConfigData,
+    // So we expect JSON strings and convert them.
+    // The new_config object is assumed to have been validated.
+
+    const char* new_config_json;
+    const char* mod_spec_json;
+    if (!PyArg_ParseTuple(args, "ss",
+                          &new_config_json, &mod_spec_json)) {
+        return (NULL);
+    }
+
+    try {
+        isc::data::ConstElementPtr new_config =
+            isc::data::Element::fromJSON(new_config_json);
+        isc::data::ConstElementPtr mod_spec_e =
+            isc::data::Element::fromJSON(mod_spec_json);
+        isc::config::ModuleSpec mod_spec(mod_spec_e);
+        isc::config::ConfigData config_data(mod_spec);
+        isc::config::default_logconfig_handler("logging", new_config,
+                                               config_data);
+
+        Py_RETURN_NONE;
+    } catch (const isc::data::JSONError& je) {
+        std::string error_msg = std::string("JSON format error: ") + je.what();
+        PyErr_SetString(PyExc_TypeError, error_msg.c_str());
+    } catch (const isc::data::TypeError& de) {
+        PyErr_SetString(PyExc_TypeError, "argument 1 of log_config_update "
+                                         "is not a map of config data");
+    } catch (const isc::config::ModuleSpecError& mse) {
+        PyErr_SetString(PyExc_TypeError, "argument 2 of log_config_update "
+                                         "is not a correct module specification");
+    } catch (const std::exception& e) {
+        PyErr_SetString(PyExc_RuntimeError, e.what());
+    } catch (...) {
+        PyErr_SetString(PyExc_RuntimeError, "Unknown C++ exception");
+    }
+    return (NULL);
+}
+
 PyMethodDef methods[] = {
     {"set_test_dictionary", setTestDictionary, METH_VARARGS,
         "Set or unset testing mode for message dictionary. In testing, "
@@ -198,6 +246,19 @@ PyMethodDef methods[] = {
         "logging severity (one of 'DEBUG', 'INFO', 'WARN', 'ERROR' or "
         "'FATAL'), a debug level (integer in the range 0-99) and a file name "
         "of a dictionary with message text translations."},
+    {"log_config_update", logConfigUpdate, METH_VARARGS,
+        "Update logger settings. This method is automatically used when "
+        "ModuleCCSession is initialized with handle_logging_config set "
+        "to True. When called, the first argument is the new logging "
+        "configuration (in JSON format). The second argument is "
+        "the raw specification (as returned from "
+        "ConfigData.get_module_spec().get_full_spec(), and converted to "
+        "JSON format).\n"
+        "Raises a TypeError if either argument is not a (correct) JSON "
+        "string, or if the spec is not a correct spec.\n"
+        "If this call succeeds, the global logger settings have "
+        "been updated."
+    },
     {NULL, NULL, 0, NULL}
 };
 
diff --git a/src/lib/python/isc/log/tests/Makefile.am b/src/lib/python/isc/log/tests/Makefile.am
index 0eacbb1..6bb67de 100644
--- a/src/lib/python/isc/log/tests/Makefile.am
+++ b/src/lib/python/isc/log/tests/Makefile.am
@@ -6,7 +6,7 @@ EXTRA_DIST = $(PYTESTS) log_console.py.in console.out check_output.sh
 # required by loadable python modules.
 LIBRARY_PATH_PLACEHOLDER =
 if SET_ENV_LIBRARY_PATH
-LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/log/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$$$(ENV_LIBRARY_PATH)
+LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/cc/.libs:$(abs_top_builddir)/src/lib/config/.libs:$(abs_top_builddir)/src/lib/log/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$$$(ENV_LIBRARY_PATH)
 endif
 
 # test using command-line arguments, so use check-local target instead of TESTS
@@ -23,5 +23,6 @@ endif
 	echo Running test: $$pytest ; \
 	$(LIBRARY_PATH_PLACEHOLDER) \
 	env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/lib/python/isc/log:$(abs_top_builddir)/src/lib/log/python/.libs \
+	B10_TEST_PLUGIN_DIR=$(abs_top_srcdir)/src/bin/cfgmgr/plugins \
 	$(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
 	done
diff --git a/src/lib/python/isc/log/tests/console.out b/src/lib/python/isc/log/tests/console.out
index d3c6770..fbb1bb9 100644
--- a/src/lib/python/isc/log/tests/console.out
+++ b/src/lib/python/isc/log/tests/console.out
@@ -1,4 +1,4 @@
-INFO  [test.output] MSG_ID, Message with list [1, 2, 3, 4]
-WARN  [test.output] DIFFERENT, Different message
-FATAL [test.output] MSG_ID, Message with 2 1
-DEBUG [test.output] MSG_ID, Message with 3 2
+INFO  [test.output] MSG_ID Message with list [1, 2, 3, 4]
+WARN  [test.output] DIFFERENT Different message
+FATAL [test.output] MSG_ID Message with 2 1
+DEBUG [test.output] MSG_ID Message with 3 2
diff --git a/src/lib/python/isc/log/tests/log_test.py b/src/lib/python/isc/log/tests/log_test.py
index a463d59..4292b6c 100644
--- a/src/lib/python/isc/log/tests/log_test.py
+++ b/src/lib/python/isc/log/tests/log_test.py
@@ -16,6 +16,9 @@
 # This tests it can be loaded, nothing more yet
 import isc.log
 import unittest
+import json
+import bind10_config
+from isc.config.ccsession import path_search
 
 class LogDict(unittest.TestCase):
     def setUp(self):
@@ -52,6 +55,33 @@ class Manager(unittest.TestCase):
         # ignore errors like missing file?
         isc.log.init("root", "INFO", 0, "/no/such/file");
 
+    def test_log_config_update(self):
+        log_spec = json.dumps(isc.config.module_spec_from_file(path_search('logging.spec', bind10_config.PLUGIN_PATHS)).get_full_spec())
+
+        self.assertRaises(TypeError, isc.log.log_config_update)
+        self.assertRaises(TypeError, isc.log.log_config_update, 1)
+        self.assertRaises(TypeError, isc.log.log_config_update, 1, 1)
+        self.assertRaises(TypeError, isc.log.log_config_update, 1, 1, 1)
+
+        self.assertRaises(TypeError, isc.log.log_config_update, 1, log_spec)
+        self.assertRaises(TypeError, isc.log.log_config_update, [], log_spec)
+        self.assertRaises(TypeError, isc.log.log_config_update, "foo", log_spec)
+        self.assertRaises(TypeError, isc.log.log_config_update, "{ '", log_spec)
+
+        # empty should pass
+        isc.log.log_config_update("{}", log_spec)
+
+        # bad spec
+        self.assertRaises(TypeError, isc.log.log_config_update, "{}", json.dumps({"foo": "bar"}))
+
+        # Try a correct one
+        log_conf = json.dumps({"loggers":
+                                [{"name": "b10-xfrout", "output_options":
+                                    [{"output": "/tmp/bind10.log",
+                                       "destination": "file",
+                                       "flush": True}]}]})
+        isc.log.log_config_update(log_conf, log_spec)
+
 class Logger(unittest.TestCase):
     def tearDown(self):
         isc.log.reset()
diff --git a/src/lib/python/isc/net/tests/Makefile.am b/src/lib/python/isc/net/tests/Makefile.am
index 73528d2..3a04f17 100644
--- a/src/lib/python/isc/net/tests/Makefile.am
+++ b/src/lib/python/isc/net/tests/Makefile.am
@@ -2,6 +2,13 @@ PYCOVERAGE_RUN = @PYCOVERAGE_RUN@
 PYTESTS = addr_test.py parse_test.py
 EXTRA_DIST = $(PYTESTS)
 
+# If necessary (rare cases), explicitly specify paths to dynamic libraries
+# required by loadable python modules.
+LIBRARY_PATH_PLACEHOLDER =
+if SET_ENV_LIBRARY_PATH
+LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/cc/.libs:$(abs_top_builddir)/src/lib/config/.libs:$(abs_top_builddir)/src/lib/log/.libs:$(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/cryptolink/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$(abs_top_builddir)/src/lib/util/io/.libs:$$$(ENV_LIBRARY_PATH)
+endif
+
 # test using command-line arguments, so use check-local target instead of TESTS
 check-local:
 if ENABLE_PYTHON_COVERAGE
@@ -11,6 +18,7 @@ if ENABLE_PYTHON_COVERAGE
 endif
 	for pytest in $(PYTESTS) ; do \
 	echo Running test: $$pytest ; \
+	$(LIBRARY_PATH_PLACEHOLDER) \
 	env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/lib/dns/python/.libs \
 	$(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
 	done
diff --git a/src/lib/python/isc/notify/tests/Makefile.am b/src/lib/python/isc/notify/tests/Makefile.am
index a83ff86..1427d93 100644
--- a/src/lib/python/isc/notify/tests/Makefile.am
+++ b/src/lib/python/isc/notify/tests/Makefile.am
@@ -6,7 +6,7 @@ EXTRA_DIST = $(PYTESTS)
 # required by loadable python modules.
 LIBRARY_PATH_PLACEHOLDER =
 if SET_ENV_LIBRARY_PATH
-LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/cryptolink/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$$$(ENV_LIBRARY_PATH)
+LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/cc/.libs:$(abs_top_builddir)/src/lib/config/.libs:$(abs_top_builddir)/src/lib/log/.libs:$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/cryptolink/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$$$(ENV_LIBRARY_PATH)
 endif
 
 # test using command-line arguments, so use check-local target instead of TESTS
diff --git a/src/lib/python/isc/util/tests/Makefile.am b/src/lib/python/isc/util/tests/Makefile.am
index 0ce96de..c3d35c2 100644
--- a/src/lib/python/isc/util/tests/Makefile.am
+++ b/src/lib/python/isc/util/tests/Makefile.am
@@ -2,6 +2,13 @@ PYCOVERAGE_RUN = @PYCOVERAGE_RUN@
 PYTESTS = process_test.py socketserver_mixin_test.py file_test.py
 EXTRA_DIST = $(PYTESTS)
 
+# If necessary (rare cases), explicitly specify paths to dynamic libraries
+# required by loadable python modules.
+LIBRARY_PATH_PLACEHOLDER =
+if SET_ENV_LIBRARY_PATH
+LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/cc/.libs:$(abs_top_builddir)/src/lib/config/.libs:$(abs_top_builddir)/src/lib/log/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$$$(ENV_LIBRARY_PATH)
+endif
+
 # test using command-line arguments, so use check-local target instead of TESTS
 check-local:
 if ENABLE_PYTHON_COVERAGE
@@ -11,6 +18,7 @@ if ENABLE_PYTHON_COVERAGE
 endif
 	for pytest in $(PYTESTS) ; do \
 	echo Running test: $$pytest ; \
+	$(LIBRARY_PATH_PLACEHOLDER) \
 	env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/lib/dns/python/.libs \
 	$(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
 	done




More information about the bind10-changes mailing list