BIND 10 experiments/stephen-bind9log, updated. a31f9ccb9b7c2f2ddd4bbd1df4fb087211cf0392 [experiments/stephen-bind9log] Add BIND 9 logging initialization

BIND 10 source code commits bind10-changes at lists.isc.org
Thu Apr 21 17:37:56 UTC 2011


The branch, experiments/stephen-bind9log has been updated
       via  a31f9ccb9b7c2f2ddd4bbd1df4fb087211cf0392 (commit)
       via  c292495a6fb2e6e32c1a89899da9a44b4c992d9c (commit)
      from  823fa0556364ad5bdcd26cb7a42999d502f3af02 (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 a31f9ccb9b7c2f2ddd4bbd1df4fb087211cf0392
Author: Stephen Morris <stephen at isc.org>
Date:   Thu Apr 21 18:36:24 2011 +0100

    [experiments/stephen-bind9log] Add BIND 9 logging initialization
    
    Added some basic BIND 9 logging initialization to the LoggerImpl class.

commit c292495a6fb2e6e32c1a89899da9a44b4c992d9c
Author: Stephen Morris <stephen at isc.org>
Date:   Thu Apr 21 15:58:15 2011 +0100

    [experiments/stephen-bind9log] Added libisc to directory tree
    
    ... and created Makefile.am to build it.  Note that some options
    have been statically set instead of being generated by configure.
    (This is an experimental branch and other than including the
     bind9 library in the build, configure.ac has not been altered.)

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

Summary of changes:
 configure.ac                                    |    1 +
 src/lib/Makefile.am                             |    2 +-
 src/lib/bind9/Makefile.am                       |  109 +
 src/lib/bind9/alpha/include/isc/atomic.h        |  184 +
 src/lib/bind9/app_api.c                         |  136 +
 src/lib/bind9/assertions.c                      |  139 +
 src/lib/bind9/backtrace-emptytbl.c              |   34 +
 src/lib/bind9/backtrace.c                       |  285 ++
 src/lib/bind9/base32.c                          |  373 ++
 src/lib/bind9/base64.c                          |  252 +
 src/lib/bind9/bitstring.c                       |  127 +
 src/lib/bind9/buffer.c                          |  489 ++
 src/lib/bind9/bufferlist.c                      |   64 +
 src/lib/bind9/commandline.c                     |  225 +
 src/lib/bind9/entropy.c                         | 1277 +++++
 src/lib/bind9/error.c                           |  106 +
 src/lib/bind9/event.c                           |   88 +
 src/lib/bind9/fsaccess.c                        |  102 +
 src/lib/bind9/hash.c                            |  404 ++
 src/lib/bind9/heap.c                            |  265 +
 src/lib/bind9/hex.c                             |  201 +
 src/lib/bind9/hmacmd5.c                         |  149 +
 src/lib/bind9/hmacsha.c                         |  599 +++
 src/lib/bind9/httpd.c                           | 1028 ++++
 src/lib/bind9/ia64/include/isc/atomic.h         |  100 +
 src/lib/bind9/include/isc/app.h                 |  375 ++
 src/lib/bind9/include/isc/assertions.h          |  126 +
 src/lib/bind9/include/isc/backtrace.h           |  131 +
 src/lib/bind9/include/isc/base32.h              |  128 +
 src/lib/bind9/include/isc/base64.h              |   99 +
 src/lib/bind9/include/isc/bind9.h               |   30 +
 src/lib/bind9/include/isc/bitstring.h           |  157 +
 src/lib/bind9/include/isc/boolean.h             |   31 +
 src/lib/bind9/include/isc/buffer.h              |  904 ++++
 src/lib/bind9/include/isc/bufferlist.h          |   86 +
 src/lib/bind9/include/isc/commandline.h         |   50 +
 src/lib/bind9/include/isc/entropy.h             |  314 ++
 src/lib/bind9/include/isc/error.h               |   63 +
 src/lib/bind9/include/isc/event.h               |  121 +
 src/lib/bind9/include/isc/eventclass.h          |   53 +
 src/lib/bind9/include/isc/file.h                |  304 ++
 src/lib/bind9/include/isc/formatcheck.h         |   40 +
 src/lib/bind9/include/isc/fsaccess.h            |  178 +
 src/lib/bind9/include/isc/hash.h                |  185 +
 src/lib/bind9/include/isc/heap.h                |  170 +
 src/lib/bind9/include/isc/hex.h                 |   98 +
 src/lib/bind9/include/isc/hmacmd5.h             |   72 +
 src/lib/bind9/include/isc/hmacsha.h             |  169 +
 src/lib/bind9/include/isc/httpd.h               |   64 +
 src/lib/bind9/include/isc/interfaceiter.h       |  133 +
 src/lib/bind9/include/isc/ipv6.h                |  148 +
 src/lib/bind9/include/isc/iterated_hash.h       |   47 +
 src/lib/bind9/include/isc/lang.h                |   33 +
 src/lib/bind9/include/isc/lex.h                 |  431 ++
 src/lib/bind9/include/isc/lfsr.h                |  130 +
 src/lib/bind9/include/isc/lib.h                 |   50 +
 src/lib/bind9/include/isc/list.h                |  184 +
 src/lib/bind9/include/isc/log.h                 |  914 ++++
 src/lib/bind9/include/isc/magic.h               |   41 +
 src/lib/bind9/include/isc/md5.h                 |   83 +
 src/lib/bind9/include/isc/mem.h                 |  750 +++
 src/lib/bind9/include/isc/msgcat.h              |  131 +
 src/lib/bind9/include/isc/msgs.h                |  194 +
 src/lib/bind9/include/isc/mutexblock.h          |   71 +
 src/lib/bind9/include/isc/namespace.h           |  164 +
 src/lib/bind9/include/isc/netaddr.h             |  180 +
 src/lib/bind9/include/isc/netscope.h            |   43 +
 src/lib/bind9/include/isc/ondestroy.h           |  116 +
 src/lib/bind9/include/isc/os.h                  |   38 +
 src/lib/bind9/include/isc/parseint.h            |   64 +
 src/lib/bind9/include/isc/platform.h            |  370 ++
 src/lib/bind9/include/isc/portset.h             |  141 +
 src/lib/bind9/include/isc/print.h               |   87 +
 src/lib/bind9/include/isc/quota.h               |  119 +
 src/lib/bind9/include/isc/radix.h               |  240 +
 src/lib/bind9/include/isc/random.h              |   62 +
 src/lib/bind9/include/isc/ratelimiter.h         |  134 +
 src/lib/bind9/include/isc/refcount.h            |  233 +
 src/lib/bind9/include/isc/region.h              |   99 +
 src/lib/bind9/include/isc/resource.h            |   97 +
 src/lib/bind9/include/isc/result.h              |  108 +
 src/lib/bind9/include/isc/resultclass.h         |   51 +
 src/lib/bind9/include/isc/rwlock.h              |  135 +
 src/lib/bind9/include/isc/serial.h              |   75 +
 src/lib/bind9/include/isc/sha1.h                |   68 +
 src/lib/bind9/include/isc/sha2.h                |  145 +
 src/lib/bind9/include/isc/sockaddr.h            |  241 +
 src/lib/bind9/include/isc/socket.h              | 1154 +++++
 src/lib/bind9/include/isc/stats.h               |  121 +
 src/lib/bind9/include/isc/stdio.h               |   77 +
 src/lib/bind9/include/isc/stdlib.h              |   40 +
 src/lib/bind9/include/isc/string.h              |  231 +
 src/lib/bind9/include/isc/symtab.h              |  131 +
 src/lib/bind9/include/isc/task.h                |  734 +++
 src/lib/bind9/include/isc/taskpool.h            |  105 +
 src/lib/bind9/include/isc/timer.h               |  431 ++
 src/lib/bind9/include/isc/types.h               |  129 +
 src/lib/bind9/include/isc/util.h                |  248 +
 src/lib/bind9/include/isc/version.h             |   28 +
 src/lib/bind9/include/isc/xml.h                 |   41 +
 src/lib/bind9/inet_aton.c                       |  196 +
 src/lib/bind9/inet_ntop.c                       |  199 +
 src/lib/bind9/inet_pton.c                       |  214 +
 src/lib/bind9/iterated_hash.c                   |   48 +
 src/lib/bind9/lex.c                             |  959 ++++
 src/lib/bind9/lfsr.c                            |  161 +
 src/lib/bind9/lib.c                             |  103 +
 src/lib/bind9/log.c                             | 1763 +++++++
 src/lib/bind9/md5.c                             |  277 ++
 src/lib/bind9/mem.c                             | 2477 ++++++++++
 src/lib/bind9/mem_api.c                         |  303 ++
 src/lib/bind9/mips/include/isc/atomic.h         |   98 +
 src/lib/bind9/mutexblock.c                      |   59 +
 src/lib/bind9/netaddr.c                         |  434 ++
 src/lib/bind9/netscope.c                        |   76 +
 src/lib/bind9/nls/msgcat.c                      |  131 +
 src/lib/bind9/noatomic/include/isc/atomic.h     |   24 +
 src/lib/bind9/nothreads/condition.c             |   24 +
 src/lib/bind9/nothreads/include/isc/condition.h |   59 +
 src/lib/bind9/nothreads/include/isc/mutex.h     |   39 +
 src/lib/bind9/nothreads/include/isc/once.h      |   32 +
 src/lib/bind9/nothreads/include/isc/thread.h    |   35 +
 src/lib/bind9/nothreads/mutex.c                 |   25 +
 src/lib/bind9/nothreads/thread.c                |   28 +
 src/lib/bind9/ondestroy.c                       |   85 +
 src/lib/bind9/parseint.c                        |   72 +
 src/lib/bind9/portset.c                         |  143 +
 src/lib/bind9/powerpc/include/isc/atomic.h      |  197 +
 src/lib/bind9/print.c                           |  624 +++
 src/lib/bind9/pthreads/condition.c              |   74 +
 src/lib/bind9/pthreads/include/isc/condition.h  |   65 +
 src/lib/bind9/pthreads/include/isc/mutex.h      |  145 +
 src/lib/bind9/pthreads/include/isc/once.h       |   50 +
 src/lib/bind9/pthreads/include/isc/thread.h     |   60 +
 src/lib/bind9/pthreads/mutex.c                  |  275 ++
 src/lib/bind9/pthreads/thread.c                 |   76 +
 src/lib/bind9/quota.c                           |  101 +
 src/lib/bind9/radix.c                           |  706 +++
 src/lib/bind9/random.c                          |  113 +
 src/lib/bind9/ratelimiter.c                     |  328 ++
 src/lib/bind9/refcount.c                        |   37 +
 src/lib/bind9/region.c                          |   45 +
 src/lib/bind9/result.c                          |  213 +
 src/lib/bind9/rwlock.c                          |  809 ++++
 src/lib/bind9/serial.c                          |   59 +
 src/lib/bind9/sha1.c                            |  354 ++
 src/lib/bind9/sha2.c                            | 1449 ++++++
 src/lib/bind9/sockaddr.c                        |  506 ++
 src/lib/bind9/socket_api.c                      |  216 +
 src/lib/bind9/sparc64/include/isc/atomic.h      |  127 +
 src/lib/bind9/stats.c                           |  326 ++
 src/lib/bind9/string.c                          |  271 ++
 src/lib/bind9/strtoul.c                         |  129 +
 src/lib/bind9/symtab.c                          |  252 +
 src/lib/bind9/task.c                            | 1578 ++++++
 src/lib/bind9/task_api.c                        |  216 +
 src/lib/bind9/task_p.h                          |   31 +
 src/lib/bind9/taskpool.c                        |   96 +
 src/lib/bind9/timer.c                           | 1072 ++++
 src/lib/bind9/timer_api.c                       |  144 +
 src/lib/bind9/timer_p.h                         |   31 +
 src/lib/bind9/unix/app.c                        |  946 ++++
 src/lib/bind9/unix/dir.c                        |  251 +
 src/lib/bind9/unix/entropy.c                    |  605 +++
 src/lib/bind9/unix/errno2result.c               |  123 +
 src/lib/bind9/unix/errno2result.h               |   39 +
 src/lib/bind9/unix/file.c                       |  541 +++
 src/lib/bind9/unix/fsaccess.c                   |   93 +
 src/lib/bind9/unix/ifiter_getifaddrs.c          |  234 +
 src/lib/bind9/unix/ifiter_ioctl.c               |  931 ++++
 src/lib/bind9/unix/ifiter_sysctl.c              |  302 ++
 src/lib/bind9/unix/include/isc/dir.h            |   94 +
 src/lib/bind9/unix/include/isc/int.h            |   55 +
 src/lib/bind9/unix/include/isc/keyboard.h       |   52 +
 src/lib/bind9/unix/include/isc/net.h            |  364 ++
 src/lib/bind9/unix/include/isc/netdb.h          |   57 +
 src/lib/bind9/unix/include/isc/offset.h         |   46 +
 src/lib/bind9/unix/include/isc/stat.h           |   52 +
 src/lib/bind9/unix/include/isc/stdtime.h        |   64 +
 src/lib/bind9/unix/include/isc/strerror.h       |   45 +
 src/lib/bind9/unix/include/isc/syslog.h         |   47 +
 src/lib/bind9/unix/include/isc/time.h           |  334 ++
 src/lib/bind9/unix/interfaceiter.c              |  312 ++
 src/lib/bind9/unix/ipv6.c                       |   27 +
 src/lib/bind9/unix/keyboard.c                   |  126 +
 src/lib/bind9/unix/net.c                        |  524 ++
 src/lib/bind9/unix/os.c                         |   94 +
 src/lib/bind9/unix/resource.c                   |  231 +
 src/lib/bind9/unix/socket.c                     | 5902 +++++++++++++++++++++++
 src/lib/bind9/unix/socket_p.h                   |   33 +
 src/lib/bind9/unix/stdio.c                      |  118 +
 src/lib/bind9/unix/stdtime.c                    |   86 +
 src/lib/bind9/unix/strerror.c                   |   74 +
 src/lib/bind9/unix/syslog.c                     |   84 +
 src/lib/bind9/unix/time.c                       |  438 ++
 src/lib/bind9/version.c                         |   28 +
 src/lib/bind9/win32/DLLMain.c                   |   58 +
 src/lib/bind9/win32/app.c                       |  260 +
 src/lib/bind9/win32/condition.c                 |  258 +
 src/lib/bind9/win32/dir.c                       |  312 ++
 src/lib/bind9/win32/entropy.c                   |  307 ++
 src/lib/bind9/win32/errno2result.c              |  113 +
 src/lib/bind9/win32/errno2result.h              |   40 +
 src/lib/bind9/win32/file.c                      |  619 +++
 src/lib/bind9/win32/fsaccess.c                  |  375 ++
 src/lib/bind9/win32/include/isc/bind_registry.h |   50 +
 src/lib/bind9/win32/include/isc/bindevt.h       |   91 +
 src/lib/bind9/win32/include/isc/condition.h     |   67 +
 src/lib/bind9/win32/include/isc/dir.h           |   83 +
 src/lib/bind9/win32/include/isc/int.h           |   56 +
 src/lib/bind9/win32/include/isc/ipv6.h          |  124 +
 src/lib/bind9/win32/include/isc/keyboard.h      |   47 +
 src/lib/bind9/win32/include/isc/mutex.h         |   55 +
 src/lib/bind9/win32/include/isc/net.h           |  344 ++
 src/lib/bind9/win32/include/isc/netdb.h         |   54 +
 src/lib/bind9/win32/include/isc/ntgroups.h      |   35 +
 src/lib/bind9/win32/include/isc/ntpaths.h       |   72 +
 src/lib/bind9/win32/include/isc/offset.h        |   44 +
 src/lib/bind9/win32/include/isc/once.h          |   43 +
 src/lib/bind9/win32/include/isc/platform.h      |  106 +
 src/lib/bind9/win32/include/isc/stat.h          |   59 +
 src/lib/bind9/win32/include/isc/stdtime.h       |   62 +
 src/lib/bind9/win32/include/isc/strerror.h      |   42 +
 src/lib/bind9/win32/include/isc/syslog.h        |   45 +
 src/lib/bind9/win32/include/isc/thread.h        |  100 +
 src/lib/bind9/win32/include/isc/time.h          |  291 ++
 src/lib/bind9/win32/include/isc/win32os.h       |   71 +
 src/lib/bind9/win32/interfaceiter.c             |  500 ++
 src/lib/bind9/win32/ipv6.c                      |   27 +
 src/lib/bind9/win32/keyboard.c                  |   89 +
 src/lib/bind9/win32/libgen.h                    |   25 +
 src/lib/bind9/win32/net.c                       |  332 ++
 src/lib/bind9/win32/netdb.h                     |  187 +
 src/lib/bind9/win32/ntgroups.c                  |  186 +
 src/lib/bind9/win32/ntpaths.c                   |  147 +
 src/lib/bind9/win32/once.c                      |   54 +
 src/lib/bind9/win32/os.c                        |   45 +
 src/lib/bind9/win32/resource.c                  |   72 +
 src/lib/bind9/win32/socket.c                    | 3911 +++++++++++++++
 src/lib/bind9/win32/stdio.c                     |  117 +
 src/lib/bind9/win32/stdtime.c                   |   37 +
 src/lib/bind9/win32/strerror.c                  |  459 ++
 src/lib/bind9/win32/syslog.c                    |  181 +
 src/lib/bind9/win32/syslog.h                    |   76 +
 src/lib/bind9/win32/thread.c                    |   90 +
 src/lib/bind9/win32/time.c                      |  320 ++
 src/lib/bind9/win32/unistd.h                    |   60 +
 src/lib/bind9/win32/version.c                   |   28 +
 src/lib/bind9/win32/win32os.c                   |  101 +
 src/lib/bind9/x86_32/include/isc/atomic.h       |  176 +
 src/lib/bind9/x86_64/include/isc/atomic.h       |  123 +
 src/lib/log/Makefile.am                         |   11 +-
 src/lib/log/logger_impl.cc                      |   69 +-
 src/lib/log/logger_impl.h                       |   22 +-
 254 files changed, 64421 insertions(+), 5 deletions(-)
 create mode 100644 src/lib/bind9/Makefile.am
 create mode 100644 src/lib/bind9/alpha/include/isc/atomic.h
 create mode 100644 src/lib/bind9/app_api.c
 create mode 100644 src/lib/bind9/assertions.c
 create mode 100644 src/lib/bind9/backtrace-emptytbl.c
 create mode 100644 src/lib/bind9/backtrace.c
 create mode 100644 src/lib/bind9/base32.c
 create mode 100644 src/lib/bind9/base64.c
 create mode 100644 src/lib/bind9/bitstring.c
 create mode 100644 src/lib/bind9/buffer.c
 create mode 100644 src/lib/bind9/bufferlist.c
 create mode 100644 src/lib/bind9/commandline.c
 create mode 100644 src/lib/bind9/entropy.c
 create mode 100644 src/lib/bind9/error.c
 create mode 100644 src/lib/bind9/event.c
 create mode 100644 src/lib/bind9/fsaccess.c
 create mode 100644 src/lib/bind9/hash.c
 create mode 100644 src/lib/bind9/heap.c
 create mode 100644 src/lib/bind9/hex.c
 create mode 100644 src/lib/bind9/hmacmd5.c
 create mode 100644 src/lib/bind9/hmacsha.c
 create mode 100644 src/lib/bind9/httpd.c
 create mode 100644 src/lib/bind9/ia64/include/isc/atomic.h
 create mode 100644 src/lib/bind9/include/isc/app.h
 create mode 100644 src/lib/bind9/include/isc/assertions.h
 create mode 100644 src/lib/bind9/include/isc/backtrace.h
 create mode 100644 src/lib/bind9/include/isc/base32.h
 create mode 100644 src/lib/bind9/include/isc/base64.h
 create mode 100644 src/lib/bind9/include/isc/bind9.h
 create mode 100644 src/lib/bind9/include/isc/bitstring.h
 create mode 100644 src/lib/bind9/include/isc/boolean.h
 create mode 100644 src/lib/bind9/include/isc/buffer.h
 create mode 100644 src/lib/bind9/include/isc/bufferlist.h
 create mode 100644 src/lib/bind9/include/isc/commandline.h
 create mode 100644 src/lib/bind9/include/isc/entropy.h
 create mode 100644 src/lib/bind9/include/isc/error.h
 create mode 100644 src/lib/bind9/include/isc/event.h
 create mode 100644 src/lib/bind9/include/isc/eventclass.h
 create mode 100644 src/lib/bind9/include/isc/file.h
 create mode 100644 src/lib/bind9/include/isc/formatcheck.h
 create mode 100644 src/lib/bind9/include/isc/fsaccess.h
 create mode 100644 src/lib/bind9/include/isc/hash.h
 create mode 100644 src/lib/bind9/include/isc/heap.h
 create mode 100644 src/lib/bind9/include/isc/hex.h
 create mode 100644 src/lib/bind9/include/isc/hmacmd5.h
 create mode 100644 src/lib/bind9/include/isc/hmacsha.h
 create mode 100644 src/lib/bind9/include/isc/httpd.h
 create mode 100644 src/lib/bind9/include/isc/interfaceiter.h
 create mode 100644 src/lib/bind9/include/isc/ipv6.h
 create mode 100644 src/lib/bind9/include/isc/iterated_hash.h
 create mode 100644 src/lib/bind9/include/isc/lang.h
 create mode 100644 src/lib/bind9/include/isc/lex.h
 create mode 100644 src/lib/bind9/include/isc/lfsr.h
 create mode 100644 src/lib/bind9/include/isc/lib.h
 create mode 100644 src/lib/bind9/include/isc/list.h
 create mode 100644 src/lib/bind9/include/isc/log.h
 create mode 100644 src/lib/bind9/include/isc/magic.h
 create mode 100644 src/lib/bind9/include/isc/md5.h
 create mode 100644 src/lib/bind9/include/isc/mem.h
 create mode 100644 src/lib/bind9/include/isc/msgcat.h
 create mode 100644 src/lib/bind9/include/isc/msgs.h
 create mode 100644 src/lib/bind9/include/isc/mutexblock.h
 create mode 100644 src/lib/bind9/include/isc/namespace.h
 create mode 100644 src/lib/bind9/include/isc/netaddr.h
 create mode 100644 src/lib/bind9/include/isc/netscope.h
 create mode 100644 src/lib/bind9/include/isc/ondestroy.h
 create mode 100644 src/lib/bind9/include/isc/os.h
 create mode 100644 src/lib/bind9/include/isc/parseint.h
 create mode 100644 src/lib/bind9/include/isc/platform.h
 create mode 100644 src/lib/bind9/include/isc/portset.h
 create mode 100644 src/lib/bind9/include/isc/print.h
 create mode 100644 src/lib/bind9/include/isc/quota.h
 create mode 100644 src/lib/bind9/include/isc/radix.h
 create mode 100644 src/lib/bind9/include/isc/random.h
 create mode 100644 src/lib/bind9/include/isc/ratelimiter.h
 create mode 100644 src/lib/bind9/include/isc/refcount.h
 create mode 100644 src/lib/bind9/include/isc/region.h
 create mode 100644 src/lib/bind9/include/isc/resource.h
 create mode 100644 src/lib/bind9/include/isc/result.h
 create mode 100644 src/lib/bind9/include/isc/resultclass.h
 create mode 100644 src/lib/bind9/include/isc/rwlock.h
 create mode 100644 src/lib/bind9/include/isc/serial.h
 create mode 100644 src/lib/bind9/include/isc/sha1.h
 create mode 100644 src/lib/bind9/include/isc/sha2.h
 create mode 100644 src/lib/bind9/include/isc/sockaddr.h
 create mode 100644 src/lib/bind9/include/isc/socket.h
 create mode 100644 src/lib/bind9/include/isc/stats.h
 create mode 100644 src/lib/bind9/include/isc/stdio.h
 create mode 100644 src/lib/bind9/include/isc/stdlib.h
 create mode 100644 src/lib/bind9/include/isc/string.h
 create mode 100644 src/lib/bind9/include/isc/symtab.h
 create mode 100644 src/lib/bind9/include/isc/task.h
 create mode 100644 src/lib/bind9/include/isc/taskpool.h
 create mode 100644 src/lib/bind9/include/isc/timer.h
 create mode 100644 src/lib/bind9/include/isc/types.h
 create mode 100644 src/lib/bind9/include/isc/util.h
 create mode 100644 src/lib/bind9/include/isc/version.h
 create mode 100644 src/lib/bind9/include/isc/xml.h
 create mode 100644 src/lib/bind9/inet_aton.c
 create mode 100644 src/lib/bind9/inet_ntop.c
 create mode 100644 src/lib/bind9/inet_pton.c
 create mode 100644 src/lib/bind9/iterated_hash.c
 create mode 100644 src/lib/bind9/lex.c
 create mode 100644 src/lib/bind9/lfsr.c
 create mode 100644 src/lib/bind9/lib.c
 create mode 100644 src/lib/bind9/log.c
 create mode 100644 src/lib/bind9/md5.c
 create mode 100644 src/lib/bind9/mem.c
 create mode 100644 src/lib/bind9/mem_api.c
 create mode 100644 src/lib/bind9/mips/include/isc/atomic.h
 create mode 100644 src/lib/bind9/mutexblock.c
 create mode 100644 src/lib/bind9/netaddr.c
 create mode 100644 src/lib/bind9/netscope.c
 create mode 100644 src/lib/bind9/nls/msgcat.c
 create mode 100644 src/lib/bind9/noatomic/include/isc/atomic.h
 create mode 100644 src/lib/bind9/nothreads/condition.c
 create mode 100644 src/lib/bind9/nothreads/include/isc/condition.h
 create mode 100644 src/lib/bind9/nothreads/include/isc/mutex.h
 create mode 100644 src/lib/bind9/nothreads/include/isc/once.h
 create mode 100644 src/lib/bind9/nothreads/include/isc/thread.h
 create mode 100644 src/lib/bind9/nothreads/mutex.c
 create mode 100644 src/lib/bind9/nothreads/thread.c
 create mode 100644 src/lib/bind9/ondestroy.c
 create mode 100644 src/lib/bind9/parseint.c
 create mode 100644 src/lib/bind9/portset.c
 create mode 100644 src/lib/bind9/powerpc/include/isc/atomic.h
 create mode 100644 src/lib/bind9/print.c
 create mode 100644 src/lib/bind9/pthreads/condition.c
 create mode 100644 src/lib/bind9/pthreads/include/isc/condition.h
 create mode 100644 src/lib/bind9/pthreads/include/isc/mutex.h
 create mode 100644 src/lib/bind9/pthreads/include/isc/once.h
 create mode 100644 src/lib/bind9/pthreads/include/isc/thread.h
 create mode 100644 src/lib/bind9/pthreads/mutex.c
 create mode 100644 src/lib/bind9/pthreads/thread.c
 create mode 100644 src/lib/bind9/quota.c
 create mode 100644 src/lib/bind9/radix.c
 create mode 100644 src/lib/bind9/random.c
 create mode 100644 src/lib/bind9/ratelimiter.c
 create mode 100644 src/lib/bind9/refcount.c
 create mode 100644 src/lib/bind9/region.c
 create mode 100644 src/lib/bind9/result.c
 create mode 100644 src/lib/bind9/rwlock.c
 create mode 100644 src/lib/bind9/serial.c
 create mode 100644 src/lib/bind9/sha1.c
 create mode 100644 src/lib/bind9/sha2.c
 create mode 100644 src/lib/bind9/sockaddr.c
 create mode 100644 src/lib/bind9/socket_api.c
 create mode 100644 src/lib/bind9/sparc64/include/isc/atomic.h
 create mode 100644 src/lib/bind9/stats.c
 create mode 100644 src/lib/bind9/string.c
 create mode 100644 src/lib/bind9/strtoul.c
 create mode 100644 src/lib/bind9/symtab.c
 create mode 100644 src/lib/bind9/task.c
 create mode 100644 src/lib/bind9/task_api.c
 create mode 100644 src/lib/bind9/task_p.h
 create mode 100644 src/lib/bind9/taskpool.c
 create mode 100644 src/lib/bind9/timer.c
 create mode 100644 src/lib/bind9/timer_api.c
 create mode 100644 src/lib/bind9/timer_p.h
 create mode 100644 src/lib/bind9/unix/app.c
 create mode 100644 src/lib/bind9/unix/dir.c
 create mode 100644 src/lib/bind9/unix/entropy.c
 create mode 100644 src/lib/bind9/unix/errno2result.c
 create mode 100644 src/lib/bind9/unix/errno2result.h
 create mode 100644 src/lib/bind9/unix/file.c
 create mode 100644 src/lib/bind9/unix/fsaccess.c
 create mode 100644 src/lib/bind9/unix/ifiter_getifaddrs.c
 create mode 100644 src/lib/bind9/unix/ifiter_ioctl.c
 create mode 100644 src/lib/bind9/unix/ifiter_sysctl.c
 create mode 100644 src/lib/bind9/unix/include/isc/dir.h
 create mode 100644 src/lib/bind9/unix/include/isc/int.h
 create mode 100644 src/lib/bind9/unix/include/isc/keyboard.h
 create mode 100644 src/lib/bind9/unix/include/isc/net.h
 create mode 100644 src/lib/bind9/unix/include/isc/netdb.h
 create mode 100644 src/lib/bind9/unix/include/isc/offset.h
 create mode 100644 src/lib/bind9/unix/include/isc/stat.h
 create mode 100644 src/lib/bind9/unix/include/isc/stdtime.h
 create mode 100644 src/lib/bind9/unix/include/isc/strerror.h
 create mode 100644 src/lib/bind9/unix/include/isc/syslog.h
 create mode 100644 src/lib/bind9/unix/include/isc/time.h
 create mode 100644 src/lib/bind9/unix/interfaceiter.c
 create mode 100644 src/lib/bind9/unix/ipv6.c
 create mode 100644 src/lib/bind9/unix/keyboard.c
 create mode 100644 src/lib/bind9/unix/net.c
 create mode 100644 src/lib/bind9/unix/os.c
 create mode 100644 src/lib/bind9/unix/resource.c
 create mode 100644 src/lib/bind9/unix/socket.c
 create mode 100644 src/lib/bind9/unix/socket_p.h
 create mode 100644 src/lib/bind9/unix/stdio.c
 create mode 100644 src/lib/bind9/unix/stdtime.c
 create mode 100644 src/lib/bind9/unix/strerror.c
 create mode 100644 src/lib/bind9/unix/syslog.c
 create mode 100644 src/lib/bind9/unix/time.c
 create mode 100644 src/lib/bind9/version.c
 create mode 100644 src/lib/bind9/win32/DLLMain.c
 create mode 100644 src/lib/bind9/win32/app.c
 create mode 100644 src/lib/bind9/win32/condition.c
 create mode 100644 src/lib/bind9/win32/dir.c
 create mode 100644 src/lib/bind9/win32/entropy.c
 create mode 100644 src/lib/bind9/win32/errno2result.c
 create mode 100644 src/lib/bind9/win32/errno2result.h
 create mode 100644 src/lib/bind9/win32/file.c
 create mode 100644 src/lib/bind9/win32/fsaccess.c
 create mode 100644 src/lib/bind9/win32/include/isc/bind_registry.h
 create mode 100644 src/lib/bind9/win32/include/isc/bindevt.h
 create mode 100644 src/lib/bind9/win32/include/isc/condition.h
 create mode 100644 src/lib/bind9/win32/include/isc/dir.h
 create mode 100644 src/lib/bind9/win32/include/isc/int.h
 create mode 100644 src/lib/bind9/win32/include/isc/ipv6.h
 create mode 100644 src/lib/bind9/win32/include/isc/keyboard.h
 create mode 100644 src/lib/bind9/win32/include/isc/mutex.h
 create mode 100644 src/lib/bind9/win32/include/isc/net.h
 create mode 100644 src/lib/bind9/win32/include/isc/netdb.h
 create mode 100644 src/lib/bind9/win32/include/isc/ntgroups.h
 create mode 100644 src/lib/bind9/win32/include/isc/ntpaths.h
 create mode 100644 src/lib/bind9/win32/include/isc/offset.h
 create mode 100644 src/lib/bind9/win32/include/isc/once.h
 create mode 100644 src/lib/bind9/win32/include/isc/platform.h
 create mode 100644 src/lib/bind9/win32/include/isc/stat.h
 create mode 100644 src/lib/bind9/win32/include/isc/stdtime.h
 create mode 100644 src/lib/bind9/win32/include/isc/strerror.h
 create mode 100644 src/lib/bind9/win32/include/isc/syslog.h
 create mode 100644 src/lib/bind9/win32/include/isc/thread.h
 create mode 100644 src/lib/bind9/win32/include/isc/time.h
 create mode 100644 src/lib/bind9/win32/include/isc/win32os.h
 create mode 100644 src/lib/bind9/win32/interfaceiter.c
 create mode 100644 src/lib/bind9/win32/ipv6.c
 create mode 100644 src/lib/bind9/win32/keyboard.c
 create mode 100644 src/lib/bind9/win32/libgen.h
 create mode 100644 src/lib/bind9/win32/net.c
 create mode 100644 src/lib/bind9/win32/netdb.h
 create mode 100644 src/lib/bind9/win32/ntgroups.c
 create mode 100644 src/lib/bind9/win32/ntpaths.c
 create mode 100644 src/lib/bind9/win32/once.c
 create mode 100644 src/lib/bind9/win32/os.c
 create mode 100644 src/lib/bind9/win32/resource.c
 create mode 100644 src/lib/bind9/win32/socket.c
 create mode 100644 src/lib/bind9/win32/stdio.c
 create mode 100644 src/lib/bind9/win32/stdtime.c
 create mode 100644 src/lib/bind9/win32/strerror.c
 create mode 100644 src/lib/bind9/win32/syslog.c
 create mode 100644 src/lib/bind9/win32/syslog.h
 create mode 100644 src/lib/bind9/win32/thread.c
 create mode 100644 src/lib/bind9/win32/time.c
 create mode 100644 src/lib/bind9/win32/unistd.h
 create mode 100644 src/lib/bind9/win32/version.c
 create mode 100644 src/lib/bind9/win32/win32os.c
 create mode 100644 src/lib/bind9/x86_32/include/isc/atomic.h
 create mode 100644 src/lib/bind9/x86_64/include/isc/atomic.h

-----------------------------------------------------------------------
diff --git a/configure.ac b/configure.ac
index 81df476..e575f3f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -706,6 +706,7 @@ AC_CONFIG_FILES([Makefile
                  tests/tools/Makefile
                  tests/tools/badpacket/Makefile
                  tests/tools/badpacket/tests/Makefile
+                 src/lib/bind9/Makefile
                ])
 AC_OUTPUT([doc/version.ent
            src/bin/cfgmgr/b10-cfgmgr.py
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index 81455c4..2260ca0 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -1,2 +1,2 @@
-SUBDIRS = exceptions util dns cc config python xfr bench log asiolink \
+SUBDIRS = bind9 exceptions util dns cc config python xfr bench log asiolink \
           asiodns nsas cache resolve testutils datasrc server_common
diff --git a/src/lib/bind9/Makefile.am b/src/lib/bind9/Makefile.am
new file mode 100644
index 0000000..871efee
--- /dev/null
+++ b/src/lib/bind9/Makefile.am
@@ -0,0 +1,109 @@
+SUBDIRS = . 
+
+AM_CFLAGS   = -I$(top_srcdir)/src/lib/bind9
+AM_CFLAGS  += -I$(top_srcdir)/src/lib/bind9/include
+AM_CFLAGS  += -I$(top_srcdir)/src/lib/bind9/unix/include
+AM_CFLAGS  += -I$(top_srcdir)/src/lib/bind9/nothreads/include
+AM_CFLAGS  += -I$(top_srcdir)/src/lib/bind9/x86_32/include
+AM_CFLAGS  += -Wformat -Wpointer-arith -Wmissing-prototypes
+
+CLEANFILES = *.gcno *.gcda
+
+lib_LTLIBRARIES = libbind9.la
+libbind9_la_SOURCES  =
+# libbind9_la_SOURCES += app_api.c
+libbind9_la_SOURCES += assertions.c
+libbind9_la_SOURCES += backtrace.c
+libbind9_la_SOURCES += backtrace-emptytbl.c
+libbind9_la_SOURCES += base32.c
+libbind9_la_SOURCES += base64.c
+libbind9_la_SOURCES += bitstring.c
+libbind9_la_SOURCES += buffer.c
+libbind9_la_SOURCES += bufferlist.c
+libbind9_la_SOURCES += commandline.c
+# libbind9_la_SOURCES += entropy.c
+libbind9_la_SOURCES += error.c
+libbind9_la_SOURCES += event.c
+# libbind9_la_SOURCES += fsaccess.c
+libbind9_la_SOURCES += hash.c
+libbind9_la_SOURCES += heap.c
+libbind9_la_SOURCES += hex.c
+libbind9_la_SOURCES += hmacmd5.c
+libbind9_la_SOURCES += hmacsha.c
+libbind9_la_SOURCES += httpd.c
+libbind9_la_SOURCES += inet_aton.c
+# libbind9_la_SOURCES += inet_ntop.c
+# libbind9_la_SOURCES += inet_pton.c
+libbind9_la_SOURCES += iterated_hash.c
+libbind9_la_SOURCES += lex.c
+# libbind9_la_SOURCES += lfsr.c
+libbind9_la_SOURCES += lib.c
+libbind9_la_SOURCES += log.c
+libbind9_la_SOURCES += md5.c
+# libbind9_la_SOURCES += mem_api.c
+libbind9_la_SOURCES += mem.c
+libbind9_la_SOURCES += mutexblock.c
+libbind9_la_SOURCES += netaddr.c
+libbind9_la_SOURCES += netscope.c
+libbind9_la_SOURCES += ondestroy.c
+libbind9_la_SOURCES += parseint.c
+libbind9_la_SOURCES += portset.c
+libbind9_la_SOURCES += print.c
+libbind9_la_SOURCES += quota.c
+libbind9_la_SOURCES += radix.c
+libbind9_la_SOURCES += random.c
+libbind9_la_SOURCES += ratelimiter.c
+libbind9_la_SOURCES += refcount.c
+libbind9_la_SOURCES += region.c
+libbind9_la_SOURCES += result.c
+libbind9_la_SOURCES += rwlock.c
+libbind9_la_SOURCES += serial.c
+libbind9_la_SOURCES += sha1.c
+libbind9_la_SOURCES += sha2.c
+libbind9_la_SOURCES += sockaddr.c
+# libbind9_la_SOURCES += socket_api.c
+libbind9_la_SOURCES += stats.c
+libbind9_la_SOURCES += string.c
+libbind9_la_SOURCES += strtoul.c
+libbind9_la_SOURCES += symtab.c
+# libbind9_la_SOURCES += task_api.c
+libbind9_la_SOURCES += task.c
+libbind9_la_SOURCES += taskpool.c
+# libbind9_la_SOURCES += timer_api.c
+libbind9_la_SOURCES += timer.c
+libbind9_la_SOURCES += version.c
+libbind9_la_SOURCES += unix/app.c
+libbind9_la_SOURCES += unix/dir.c
+libbind9_la_SOURCES += unix/entropy.c
+libbind9_la_SOURCES += unix/errno2result.c
+libbind9_la_SOURCES += unix/file.c
+libbind9_la_SOURCES += unix/fsaccess.c
+# libbind9_la_SOURCES += unix/ifiter_getifaddrs.c
+# libbind9_la_SOURCES += unix/ifiter_ioctl.c
+# libbind9_la_SOURCES += unix/ifiter_sysctl.c
+libbind9_la_SOURCES += unix/interfaceiter.c
+# libbind9_la_SOURCES += unix/ipv6.c
+libbind9_la_SOURCES += unix/keyboard.c
+libbind9_la_SOURCES += unix/net.c
+libbind9_la_SOURCES += unix/os.c
+libbind9_la_SOURCES += unix/resource.c
+libbind9_la_SOURCES += unix/socket.c
+libbind9_la_SOURCES += unix/stdio.c
+libbind9_la_SOURCES += unix/stdtime.c
+libbind9_la_SOURCES += unix/strerror.c
+libbind9_la_SOURCES += unix/syslog.c
+libbind9_la_SOURCES += unix/time.c
+libbind9_la_SOURCES += nls/msgcat.c
+
+# Note: the ordering matters: -Wno-... must follow -Wextra (defined in
+# B10_CXXFLAGS)
+liblog_la_CXXFLAGS = $(AM_CXXFLAGS)
+if USE_GXX
+liblog_la_CXXFLAGS += -Wno-unused-parameter
+endif
+if USE_CLANGPP
+# Same for clang++, but we need to turn off -Werror completely.
+liblog_la_CXXFLAGS += -Wno-error
+endif
+libbind9_la_CPPFLAGS = $(AM_CPPFLAGS)
+libbind9_la_CFLAGS = $(AM_CFLAGS)
diff --git a/src/lib/bind9/alpha/include/isc/atomic.h b/src/lib/bind9/alpha/include/isc/atomic.h
new file mode 100644
index 0000000..40d0917
--- /dev/null
+++ b/src/lib/bind9/alpha/include/isc/atomic.h
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2005, 2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: atomic.h,v 1.7 2009-04-08 06:48:23 tbox Exp $ */
+
+/*
+ * This code was written based on FreeBSD's kernel source whose copyright
+ * follows:
+ */
+
+/*-
+ * Copyright (c) 1998 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/alpha/include/atomic.h,v 1.18.6.1 2004/09/13 21:52:04 wilko Exp $
+ */
+
+#ifndef ISC_ATOMIC_H
+#define ISC_ATOMIC_H 1
+
+#include <isc/platform.h>
+#include <isc/types.h>
+
+#ifdef ISC_PLATFORM_USEOSFASM
+#include <c_asm.h>
+
+#pragma intrinsic(asm)
+
+/*
+ * This routine atomically increments the value stored in 'p' by 'val', and
+ * returns the previous value.  Memory access ordering around this function
+ * can be critical, so we add explicit memory block instructions at the
+ * beginning and the end of it (same for other functions).
+ */
+static inline isc_int32_t
+isc_atomic_xadd(isc_int32_t *p, isc_int32_t val) {
+	return (asm("mb;"
+		    "1:"
+		    "ldl_l %t0, 0(%a0);"	/* load old value */
+		    "mov %t0, %v0;"		/* copy the old value */
+		    "addl %t0, %a1, %t0;"	/* calculate new value */
+		    "stl_c %t0, 0(%a0);"	/* attempt to store */
+		    "beq %t0, 1b;"		/* spin if failed */
+		    "mb;",
+		    p, val));
+}
+
+/*
+ * This routine atomically stores the value 'val' in 'p'.
+ */
+static inline void
+isc_atomic_store(isc_int32_t *p, isc_int32_t val) {
+	(void)asm("mb;"
+		  "1:"
+		  "ldl_l %t0, 0(%a0);"		/* load old value */
+		  "mov %a1, %t0;"		/* value to store */
+		  "stl_c %t0, 0(%a0);"		/* attempt to store */
+		  "beq %t0, 1b;"		/* spin if failed */
+		  "mb;",
+		  p, val);
+}
+
+/*
+ * This routine atomically replaces the value in 'p' with 'val', if the
+ * original value is equal to 'cmpval'.  The original value is returned in any
+ * case.
+ */
+static inline isc_int32_t
+isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) {
+
+	return(asm("mb;"
+		   "1:"
+		   "ldl_l %t0, 0(%a0);"		/* load old value */
+		   "mov %t0, %v0;"		/* copy the old value */
+		   "cmpeq %t0, %a1, %t0;"	/* compare */
+		   "beq %t0, 2f;"		/* exit if not equal */
+		   "mov %a2, %t0;"		/* value to store */
+		   "stl_c %t0, 0(%a0);"		/* attempt to store */
+		   "beq %t0, 1b;"		/* if it failed, spin */
+		   "2:"
+		   "mb;",
+		   p, cmpval, val));
+}
+#elif defined (ISC_PLATFORM_USEGCCASM)
+static inline isc_int32_t
+isc_atomic_xadd(isc_int32_t *p, isc_int32_t val) {
+	isc_int32_t temp, prev;
+
+	__asm__ volatile(
+		"mb;"
+		"1:"
+		"ldl_l %0, %1;"			/* load old value */
+		"mov %0, %2;"			/* copy the old value */
+		"addl %0, %3, %0;"		/* calculate new value */
+		"stl_c %0, %1;"			/* attempt to store */
+		"beq %0, 1b;"			/* spin if failed */
+		"mb;"
+		: "=&r"(temp), "+m"(*p), "=&r"(prev)
+		: "r"(val)
+		: "memory");
+
+	return (prev);
+}
+
+static inline void
+isc_atomic_store(isc_int32_t *p, isc_int32_t val) {
+	isc_int32_t temp;
+
+	__asm__ volatile(
+		"mb;"
+		"1:"
+		"ldl_l %0, %1;"			/* load old value */
+		"mov %2, %0;"			/* value to store */
+		"stl_c %0, %1;"			/* attempt to store */
+		"beq %0, 1b;"			/* if it failed, spin */
+		"mb;"
+		: "=&r"(temp), "+m"(*p)
+		: "r"(val)
+		: "memory");
+}
+
+static inline isc_int32_t
+isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) {
+	isc_int32_t temp, prev;
+
+	__asm__ volatile(
+		"mb;"
+		"1:"
+		"ldl_l %0, %1;"			/* load old value */
+		"mov %0, %2;"			/* copy the old value */
+		"cmpeq %0, %3, %0;"		/* compare */
+		"beq %0, 2f;"			/* exit if not equal */
+		"mov %4, %0;"			/* value to store */
+		"stl_c %0, %1;"			/* attempt to store */
+		"beq %0, 1b;"			/* if it failed, spin */
+		"2:"
+		"mb;"
+		: "=&r"(temp), "+m"(*p), "=&r"(prev)
+		: "r"(cmpval), "r"(val)
+		: "memory");
+
+	return (prev);
+}
+#else
+
+#error "unsupported compiler.  disable atomic ops by --disable-atomic"
+
+#endif
+
+#endif /* ISC_ATOMIC_H */
diff --git a/src/lib/bind9/app_api.c b/src/lib/bind9/app_api.c
new file mode 100644
index 0000000..b2a2f14
--- /dev/null
+++ b/src/lib/bind9/app_api.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2009  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: app_api.c,v 1.5 2009-09-02 23:48:02 tbox Exp $ */
+
+#include <config.h>
+
+#include <unistd.h>
+
+#include <isc/app.h>
+#include <isc/magic.h>
+#include <isc/mutex.h>
+#include <isc/once.h>
+#include <isc/util.h>
+
+static isc_mutex_t createlock;
+static isc_once_t once = ISC_ONCE_INIT;
+static isc_appctxcreatefunc_t appctx_createfunc = NULL;
+
+#define ISCAPI_APPMETHODS_VALID(m) ISC_MAGIC_VALID(m, ISCAPI_APPMETHODS_MAGIC)
+
+static void
+initialize(void) {
+	RUNTIME_CHECK(isc_mutex_init(&createlock) == ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_app_register(isc_appctxcreatefunc_t createfunc) {
+	isc_result_t result = ISC_R_SUCCESS;
+
+	RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
+
+	LOCK(&createlock);
+	if (appctx_createfunc == NULL)
+		appctx_createfunc = createfunc;
+	else
+		result = ISC_R_EXISTS;
+	UNLOCK(&createlock);
+
+	return (result);
+}
+
+isc_result_t
+isc_appctx_create(isc_mem_t *mctx, isc_appctx_t **ctxp) {
+	isc_result_t result;
+
+	LOCK(&createlock);
+
+	REQUIRE(appctx_createfunc != NULL);
+	result = (*appctx_createfunc)(mctx, ctxp);
+
+	UNLOCK(&createlock);
+
+	return (result);
+}
+
+void
+isc_appctx_destroy(isc_appctx_t **ctxp) {
+	REQUIRE(ctxp != NULL && ISCAPI_APPCTX_VALID(*ctxp));
+
+	(*ctxp)->methods->ctxdestroy(ctxp);
+
+	ENSURE(*ctxp == NULL);
+}
+
+isc_result_t
+isc_app_ctxstart(isc_appctx_t *ctx) {
+	REQUIRE(ISCAPI_APPCTX_VALID(ctx));
+
+	return (ctx->methods->ctxstart(ctx));
+}
+
+isc_result_t
+isc_app_ctxrun(isc_appctx_t *ctx) {
+	REQUIRE(ISCAPI_APPCTX_VALID(ctx));
+
+	return (ctx->methods->ctxrun(ctx));
+}
+
+isc_result_t
+isc_app_ctxsuspend(isc_appctx_t *ctx) {
+	REQUIRE(ISCAPI_APPCTX_VALID(ctx));
+
+	return (ctx->methods->ctxsuspend(ctx));
+}
+
+isc_result_t
+isc_app_ctxshutdown(isc_appctx_t *ctx) {
+	REQUIRE(ISCAPI_APPCTX_VALID(ctx));
+
+	return (ctx->methods->ctxshutdown(ctx));
+}
+
+void
+isc_app_ctxfinish(isc_appctx_t *ctx) {
+	REQUIRE(ISCAPI_APPCTX_VALID(ctx));
+
+	ctx->methods->ctxfinish(ctx);
+}
+
+void
+isc_appctx_settaskmgr(isc_appctx_t *ctx, isc_taskmgr_t *taskmgr) {
+	REQUIRE(ISCAPI_APPCTX_VALID(ctx));
+	REQUIRE(taskmgr != NULL);
+
+	ctx->methods->settaskmgr(ctx, taskmgr);
+}
+
+void
+isc_appctx_setsocketmgr(isc_appctx_t *ctx, isc_socketmgr_t *socketmgr) {
+	REQUIRE(ISCAPI_APPCTX_VALID(ctx));
+	REQUIRE(socketmgr != NULL);
+
+	ctx->methods->setsocketmgr(ctx, socketmgr);
+}
+
+void
+isc_appctx_settimermgr(isc_appctx_t *ctx, isc_timermgr_t *timermgr) {
+	REQUIRE(ISCAPI_APPCTX_VALID(ctx));
+	REQUIRE(timermgr != NULL);
+
+	ctx->methods->settimermgr(ctx, timermgr);
+}
diff --git a/src/lib/bind9/assertions.c b/src/lib/bind9/assertions.c
new file mode 100644
index 0000000..fe082b7
--- /dev/null
+++ b/src/lib/bind9/assertions.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2004, 2005, 2007-2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1997-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: assertions.c,v 1.26 2009-09-29 15:06:07 fdupont Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <isc/assertions.h>
+#include <isc/backtrace.h>
+#include <isc/msgs.h>
+#include <isc/result.h>
+
+/*
+ * The maximum number of stack frames to dump on assertion failure.
+ */
+#ifndef BACKTRACE_MAXFRAME
+#define BACKTRACE_MAXFRAME 128
+#endif
+
+/*%
+ * Forward.
+ */
+static void
+default_callback(const char *, int, isc_assertiontype_t, const char *);
+
+static isc_assertioncallback_t isc_assertion_failed_cb = default_callback;
+
+/*%
+ * Public.
+ */
+
+/*% assertion failed handler */
+/* coverity[+kill] */
+void
+isc_assertion_failed(const char *file, int line, isc_assertiontype_t type,
+		     const char *cond)
+{
+	isc_assertion_failed_cb(file, line, type, cond);
+	abort();
+	/* NOTREACHED */
+}
+
+/*% Set callback. */
+void
+isc_assertion_setcallback(isc_assertioncallback_t cb) {
+	if (cb == NULL)
+		isc_assertion_failed_cb = default_callback;
+	else
+		isc_assertion_failed_cb = cb;
+}
+
+/*% Type to Text */
+const char *
+isc_assertion_typetotext(isc_assertiontype_t type) {
+	const char *result;
+
+	/*
+	 * These strings have purposefully not been internationalized
+	 * because they are considered to essentially be keywords of
+	 * the ISC development environment.
+	 */
+	switch (type) {
+	case isc_assertiontype_require:
+		result = "REQUIRE";
+		break;
+	case isc_assertiontype_ensure:
+		result = "ENSURE";
+		break;
+	case isc_assertiontype_insist:
+		result = "INSIST";
+		break;
+	case isc_assertiontype_invariant:
+		result = "INVARIANT";
+		break;
+	default:
+		result = NULL;
+	}
+	return (result);
+}
+
+/*
+ * Private.
+ */
+
+static void
+default_callback(const char *file, int line, isc_assertiontype_t type,
+		 const char *cond)
+{
+	void *tracebuf[BACKTRACE_MAXFRAME];
+	int i, nframes;
+	const char *logsuffix = ".";
+	const char *fname;
+	isc_result_t result;
+
+	result = isc_backtrace_gettrace(tracebuf, BACKTRACE_MAXFRAME, &nframes);
+		if (result == ISC_R_SUCCESS && nframes > 0)
+			logsuffix = ", back trace";
+
+	fprintf(stderr, "%s:%d: %s(%s) %s%s\n",
+		file, line, isc_assertion_typetotext(type), cond,
+		isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+			       ISC_MSG_FAILED, "failed"), logsuffix);
+	if (result == ISC_R_SUCCESS) {
+		for (i = 0; i < nframes; i++) {
+			unsigned long offset;
+
+			fname = NULL;
+			result = isc_backtrace_getsymbol(tracebuf[i], &fname,
+							 &offset);
+			if (result == ISC_R_SUCCESS) {
+				fprintf(stderr, "#%d %p in %s()+0x%lx\n", i,
+					tracebuf[i], fname, offset);
+			} else {
+				fprintf(stderr, "#%d %p in ??\n", i,
+					tracebuf[i]);
+			}
+		}
+	}
+	fflush(stderr);
+}
diff --git a/src/lib/bind9/backtrace-emptytbl.c b/src/lib/bind9/backtrace-emptytbl.c
new file mode 100644
index 0000000..2743030
--- /dev/null
+++ b/src/lib/bind9/backtrace-emptytbl.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2009  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: backtrace-emptytbl.c,v 1.3 2009-09-01 20:13:44 each Exp $ */
+
+/*! \file */
+
+/*
+ * This file defines an empty (default) symbol table used in backtrace.c
+ * If the application wants to have a complete symbol table, it should redefine
+ * isc__backtrace_symtable with the complete table in some way, and link the
+ * version of the library not including this definition
+ * (e.g. libisc-nosymbol.a).
+ */
+
+#include <config.h>
+
+#include <isc/backtrace.h>
+
+const int isc__backtrace_nsymbols = 0;
+const isc_backtrace_symmap_t isc__backtrace_symtable[] = { { NULL, "" } };
diff --git a/src/lib/bind9/backtrace.c b/src/lib/bind9/backtrace.c
new file mode 100644
index 0000000..7b5ddfe
--- /dev/null
+++ b/src/lib/bind9/backtrace.c
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2009  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: backtrace.c,v 1.3 2009-09-02 23:48:02 tbox Exp $ */
+
+/*! \file */
+
+#include "config.h"
+
+#include <string.h>
+#include <stdlib.h>
+#ifdef HAVE_LIBCTRACE
+#include <execinfo.h>
+#endif
+
+#include <isc/backtrace.h>
+#include <isc/result.h>
+#include <isc/util.h>
+
+#ifdef ISC_PLATFORM_USEBACKTRACE
+/*
+ * Getting a back trace of a running process is tricky and highly platform
+ * dependent.  Our current approach is as follows:
+ * 1. If the system library supports the "backtrace()" function, use it.
+ * 2. Otherwise, if the compiler is gcc and the architecture is x86_64 or IA64,
+ *    then use gcc's (hidden) Unwind_Backtrace() function.  Note that this
+ *    function doesn't work for C programs on many other architectures.
+ * 3. Otherwise, if the architecture x86 or x86_64, try to unwind the stack
+ *    frame following frame pointers.  This assumes the executable binary
+ *    compiled with frame pointers; this is not always true for x86_64 (rather,
+ *    compiler optimizations often disable frame pointers).  The validation
+ *    checks in getnextframeptr() hopefully rejects bogus values stored in
+ *    the RBP register in such a case.  If the backtrace function itself crashes
+ *    due to this problem, the whole package should be rebuilt with
+ *    --disable-backtrace.
+ */
+#ifdef HAVE_LIBCTRACE
+#define BACKTRACE_LIBC
+#elif defined(__GNUC__) && (defined(__x86_64__) || defined(__ia64__))
+#define BACKTRACE_GCC
+#elif defined(__x86_64__) || defined(__i386__)
+#define BACKTRACE_X86STACK
+#else
+#define BACKTRACE_DISABLED
+#endif  /* HAVE_LIBCTRACE */
+#else	/* !ISC_PLATFORM_USEBACKTRACE */
+#define BACKTRACE_DISABLED
+#endif	/* ISC_PLATFORM_USEBACKTRACE */
+
+#ifdef BACKTRACE_LIBC
+isc_result_t
+isc_backtrace_gettrace(void **addrs, int maxaddrs, int *nframes) {
+	int n;
+
+	/*
+	 * Validate the arguments: intentionally avoid using REQUIRE().
+	 * See notes in backtrace.h.
+	 */
+	if (addrs == NULL || nframes == NULL)
+		return (ISC_R_FAILURE);
+
+	/*
+	 * backtrace(3) includes this function itself in the address array,
+	 * which should be eliminated from the returned sequence.
+	 */
+	n = backtrace(addrs, maxaddrs);
+	if (n < 2)
+		return (ISC_R_NOTFOUND);
+	n--;
+	memmove(addrs, &addrs[1], sizeof(void *) * n);
+	*nframes = n;
+	return (ISC_R_SUCCESS);
+}
+#elif defined(BACKTRACE_GCC)
+extern int _Unwind_Backtrace(void* fn, void* a);
+extern void* _Unwind_GetIP(void* ctx);
+
+typedef struct {
+	void **result;
+	int max_depth;
+	int skip_count;
+	int count;
+} trace_arg_t;
+
+static int
+btcallback(void *uc, void *opq) {
+	trace_arg_t *arg = (trace_arg_t *)opq;
+
+	if (arg->skip_count > 0)
+		arg->skip_count--;
+	else
+		arg->result[arg->count++] = (void *)_Unwind_GetIP(uc);
+	if (arg->count == arg->max_depth)
+		return (5); /* _URC_END_OF_STACK */
+
+	return (0); /* _URC_NO_REASON */
+}
+
+isc_result_t
+isc_backtrace_gettrace(void **addrs, int maxaddrs, int *nframes) {
+	trace_arg_t arg;
+
+	/* Argument validation: see above. */
+	if (addrs == NULL || nframes == NULL)
+		return (ISC_R_FAILURE);
+
+	arg.skip_count = 1;
+	arg.result = addrs;
+	arg.max_depth = maxaddrs;
+	arg.count = 0;
+	_Unwind_Backtrace(btcallback, &arg);
+
+	*nframes = arg.count;
+
+	return (ISC_R_SUCCESS);
+}
+#elif defined(BACKTRACE_X86STACK)
+#ifdef __x86_64__
+static unsigned long
+getrbp() {
+	__asm("movq %rbp, %rax\n");
+}
+#endif
+
+static void **
+getnextframeptr(void **sp) {
+	void **newsp = (void **)*sp;
+
+	/*
+	 * Perform sanity check for the new frame pointer, derived from
+	 * google glog.  This can actually be bogus depending on compiler.
+	 */
+
+	/* prohibit the stack frames from growing downwards */
+	if (newsp <= sp)
+		return (NULL);
+
+	/* A heuristics to reject "too large" frame: this actually happened. */
+	if ((char *)newsp - (char *)sp > 100000)
+		return (NULL);
+
+	/*
+	 * Not sure if other checks used in glog are needed at this moment.
+	 * For our purposes we don't have to consider non-contiguous frames,
+	 * for example.
+	 */
+
+	return (newsp);
+}
+
+isc_result_t
+isc_backtrace_gettrace(void **addrs, int maxaddrs, int *nframes) {
+	int i = 0;
+	void **sp;
+
+	/* Argument validation: see above. */
+	if (addrs == NULL || nframes == NULL)
+		return (ISC_R_FAILURE);
+
+#ifdef __x86_64__
+	sp = (void **)getrbp();
+	if (sp == NULL)
+		return (ISC_R_NOTFOUND);
+	/*
+	 * sp is the frame ptr of this function itself due to the call to
+	 * getrbp(), so need to unwind one frame for consistency.
+	 */
+	sp = getnextframeptr(sp);
+#else
+	/*
+	 * i386: the frame pointer is stored 2 words below the address for the
+	 * first argument.  Note that the body of this function cannot be
+	 * inlined since it depends on the address of the function argument.
+	 */
+	sp = (void **)&addrs - 2;
+#endif
+
+	while (sp != NULL && i < maxaddrs) {
+		addrs[i++] = *(sp + 1);
+		sp = getnextframeptr(sp);
+	}
+
+	*nframes = i;
+
+	return (ISC_R_SUCCESS);
+}
+#elif defined(BACKTRACE_DISABLED)
+isc_result_t
+isc_backtrace_gettrace(void **addrs, int maxaddrs, int *nframes) {
+	/* Argument validation: see above. */
+	if (addrs == NULL || nframes == NULL)
+		return (ISC_R_FAILURE);
+
+	UNUSED(maxaddrs);
+
+	return (ISC_R_NOTIMPLEMENTED);
+}
+#endif
+
+isc_result_t
+isc_backtrace_getsymbolfromindex(int index, const void **addrp,
+				 const char **symbolp)
+{
+	REQUIRE(addrp != NULL && *addrp == NULL);
+	REQUIRE(symbolp != NULL && *symbolp == NULL);
+
+	if (index < 0 || index >= isc__backtrace_nsymbols)
+		return (ISC_R_RANGE);
+
+	*addrp = isc__backtrace_symtable[index].addr;
+	*symbolp = isc__backtrace_symtable[index].symbol;
+	return (ISC_R_SUCCESS);
+}
+
+static int
+symtbl_compare(const void *addr, const void *entryarg) {
+	const isc_backtrace_symmap_t *entry = entryarg;
+	const isc_backtrace_symmap_t *end =
+		&isc__backtrace_symtable[isc__backtrace_nsymbols - 1];
+
+	if (isc__backtrace_nsymbols == 1 || entry == end) {
+		if (addr >= entry->addr) {
+			/*
+			 * If addr is equal to or larger than that of the last
+			 * entry of the table, we cannot be sure if this is
+			 * within a valid range so we consider it valid.
+			 */
+			return (0);
+		}
+		return (-1);
+	}
+
+	/* entry + 1 is a valid entry from now on. */
+	if (addr < entry->addr)
+		return (-1);
+	else if (addr >= (entry + 1)->addr)
+		return (1);
+	return (0);
+}
+
+isc_result_t
+isc_backtrace_getsymbol(const void *addr, const char **symbolp,
+			unsigned long *offsetp)
+{
+	isc_result_t result = ISC_R_SUCCESS;
+	isc_backtrace_symmap_t *found;
+
+	/*
+	 * Validate the arguments: intentionally avoid using REQUIRE().
+	 * See notes in backtrace.h.
+	 */
+	if (symbolp == NULL || *symbolp != NULL || offsetp == NULL)
+		return (ISC_R_FAILURE);
+
+	if (isc__backtrace_nsymbols < 1)
+		return (ISC_R_NOTFOUND);
+
+	/*
+	 * Search the table for the entry that meets:
+	 * entry.addr <= addr < next_entry.addr.
+	 */
+	found = bsearch(addr, isc__backtrace_symtable, isc__backtrace_nsymbols,
+			sizeof(isc__backtrace_symtable[0]), symtbl_compare);
+	if (found == NULL)
+		result = ISC_R_NOTFOUND;
+	else {
+		*symbolp = found->symbol;
+		*offsetp = (const char *)addr - (char *)found->addr;
+	}
+
+	return (result);
+}
diff --git a/src/lib/bind9/base32.c b/src/lib/bind9/base32.c
new file mode 100644
index 0000000..7621920
--- /dev/null
+++ b/src/lib/bind9/base32.c
@@ -0,0 +1,373 @@
+/*
+ * Copyright (C) 2008, 2009  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: base32.c,v 1.6 2009-10-21 01:22:29 each Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/base32.h>
+#include <isc/buffer.h>
+#include <isc/lex.h>
+#include <isc/region.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#define RETERR(x) do { \
+	isc_result_t _r = (x); \
+	if (_r != ISC_R_SUCCESS) \
+		return (_r); \
+	} while (0)
+
+
+/*@{*/
+/*!
+ * These static functions are also present in lib/dns/rdata.c.  I'm not
+ * sure where they should go. -- bwelling
+ */
+static isc_result_t
+str_totext(const char *source, isc_buffer_t *target);
+
+static isc_result_t
+mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length);
+
+/*@}*/
+
+static const char base32[] =
+	 "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=abcdefghijklmnopqrstuvwxyz234567";
+static const char base32hex[] =
+	"0123456789ABCDEFGHIJKLMNOPQRSTUV=0123456789abcdefghijklmnopqrstuv";
+
+static isc_result_t
+base32_totext(isc_region_t *source, int wordlength, const char *wordbreak,
+	      isc_buffer_t *target, const char base[])
+{
+	char buf[9];
+	unsigned int loops = 0;
+
+	if (wordlength >= 0 && wordlength < 8)
+		wordlength = 8;
+
+	memset(buf, 0, sizeof(buf));
+	while (source->length > 0) {
+		buf[0] = base[((source->base[0]>>3)&0x1f)];	/* 5 + */
+		if (source->length == 1) {
+			buf[1] = base[(source->base[0]<<2)&0x1c];
+			buf[2] = buf[3] = buf[4] = '=';
+			buf[5] = buf[6] = buf[7] = '=';
+			RETERR(str_totext(buf, target));
+			break;
+		}
+		buf[1] = base[((source->base[0]<<2)&0x1c)|	/* 3 = 8 */
+			      ((source->base[1]>>6)&0x03)];	/* 2 + */
+		buf[2] = base[((source->base[1]>>1)&0x1f)];	/* 5 + */
+		if (source->length == 2) {
+			buf[3] = base[(source->base[1]<<4)&0x10];
+			buf[4] = buf[5] = buf[6] = buf[7] = '=';
+			RETERR(str_totext(buf, target));
+			break;
+		}
+		buf[3] = base[((source->base[1]<<4)&0x10)|	/* 1 = 8 */
+			      ((source->base[2]>>4)&0x0f)];	/* 4 + */
+		if (source->length == 3) {
+			buf[4] = base[(source->base[2]<<1)&0x1e];
+			buf[5] = buf[6] = buf[7] = '=';
+			RETERR(str_totext(buf, target));
+			break;
+		}
+		buf[4] = base[((source->base[2]<<1)&0x1e)|	/* 4 = 8 */
+			      ((source->base[3]>>7)&0x01)];	/* 1 + */
+		buf[5] = base[((source->base[3]>>2)&0x1f)];	/* 5 + */
+		if (source->length == 4) {
+			buf[6] = base[(source->base[3]<<3)&0x18];
+			buf[7] = '=';
+			RETERR(str_totext(buf, target));
+			break;
+		}
+		buf[6] = base[((source->base[3]<<3)&0x18)|	/* 2 = 8 */
+			      ((source->base[4]>>5)&0x07)];	/* 3 + */
+		buf[7] = base[source->base[4]&0x1f];		/* 5 = 8 */
+		RETERR(str_totext(buf, target));
+		isc_region_consume(source, 5);
+
+		loops++;
+		if (source->length != 0 && wordlength >= 0 &&
+		    (int)((loops + 1) * 8) >= wordlength)
+		{
+			loops = 0;
+			RETERR(str_totext(wordbreak, target));
+		}
+	}
+	if (source->length > 0)
+		isc_region_consume(source, source->length);
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_base32_totext(isc_region_t *source, int wordlength,
+		  const char *wordbreak, isc_buffer_t *target)
+{
+	return (base32_totext(source, wordlength, wordbreak, target, base32));
+}
+
+isc_result_t
+isc_base32hex_totext(isc_region_t *source, int wordlength,
+		     const char *wordbreak, isc_buffer_t *target)
+{
+	return (base32_totext(source, wordlength, wordbreak, target,
+			      base32hex));
+}
+
+/*%
+ * State of a base32 decoding process in progress.
+ */
+typedef struct {
+	int length;		/*%< Desired length of binary data or -1 */
+	isc_buffer_t *target;	/*%< Buffer for resulting binary data */
+	int digits;		/*%< Number of buffered base32 digits */
+	isc_boolean_t seen_end;	/*%< True if "=" end marker seen */
+	int val[8];
+	const char *base;	/*%< Which encoding we are using */
+	int seen_32;		/*%< Number of significant bytes if non zero */
+} base32_decode_ctx_t;
+
+static inline void
+base32_decode_init(base32_decode_ctx_t *ctx, int length,
+		   const char base[], isc_buffer_t *target)
+{
+	ctx->digits = 0;
+	ctx->seen_end = ISC_FALSE;
+	ctx->seen_32 = 0;
+	ctx->length = length;
+	ctx->target = target;
+	ctx->base = base;
+}
+
+static inline isc_result_t
+base32_decode_char(base32_decode_ctx_t *ctx, int c) {
+	char *s;
+	unsigned int last;
+
+	if (ctx->seen_end)
+		return (ISC_R_BADBASE32);
+	if ((s = strchr(ctx->base, c)) == NULL)
+		return (ISC_R_BADBASE32);
+	last = s - ctx->base;
+	/*
+	 * Handle lower case.
+	 */
+	if (last > 32)
+		last -= 33;
+	/*
+	 * Check that padding is contiguous.
+	 */
+	if (last != 32 && ctx->seen_32 != 0)
+		return (ISC_R_BADBASE32);
+	/*
+	 * Check that padding starts at the right place and that
+	 * bits that should be zero are.
+	 * Record how many significant bytes in answer (seen_32).
+	 */
+	if (last == 32 && ctx->seen_32 == 0)
+		switch (ctx->digits) {
+		case 0:
+		case 1:
+			return (ISC_R_BADBASE32);
+		case 2:
+			if ((ctx->val[1]&0x03) != 0)
+				return (ISC_R_BADBASE32);
+			ctx->seen_32 = 1;
+			break;
+		case 3:
+			return (ISC_R_BADBASE32);
+		case 4:
+			if ((ctx->val[3]&0x0f) != 0)
+				return (ISC_R_BADBASE32);
+			ctx->seen_32 = 3;
+			break;
+		case 5:
+			if ((ctx->val[4]&0x01) != 0)
+				return (ISC_R_BADBASE32);
+			ctx->seen_32 = 3;
+			break;
+		case 6:
+			return (ISC_R_BADBASE32);
+		case 7:
+			if ((ctx->val[6]&0x07) != 0)
+				return (ISC_R_BADBASE32);
+			ctx->seen_32 = 4;
+			break;
+		}
+	/*
+	 * Zero fill pad values.
+	 */
+	ctx->val[ctx->digits++] = (last == 32) ? 0 : last;
+
+	if (ctx->digits == 8) {
+		int n = 5;
+		unsigned char buf[5];
+
+		if (ctx->seen_32 != 0) {
+			ctx->seen_end = ISC_TRUE;
+			n = ctx->seen_32;
+		}
+		buf[0] = (ctx->val[0]<<3)|(ctx->val[1]>>2);
+		buf[1] = (ctx->val[1]<<6)|(ctx->val[2]<<1)|(ctx->val[3]>>4);
+		buf[2] = (ctx->val[3]<<4)|(ctx->val[4]>>1);
+		buf[3] = (ctx->val[4]<<7)|(ctx->val[5]<<2)|(ctx->val[6]>>3);
+		buf[4] = (ctx->val[6]<<5)|(ctx->val[7]);
+		RETERR(mem_tobuffer(ctx->target, buf, n));
+		if (ctx->length >= 0) {
+			if (n > ctx->length)
+				return (ISC_R_BADBASE32);
+			else
+				ctx->length -= n;
+		}
+		ctx->digits = 0;
+	}
+	return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+base32_decode_finish(base32_decode_ctx_t *ctx) {
+	if (ctx->length > 0)
+		return (ISC_R_UNEXPECTEDEND);
+	if (ctx->digits != 0)
+		return (ISC_R_BADBASE32);
+	return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+base32_tobuffer(isc_lex_t *lexer, const char base[], isc_buffer_t *target,
+		int length)
+{
+	base32_decode_ctx_t ctx;
+	isc_textregion_t *tr;
+	isc_token_t token;
+	isc_boolean_t eol;
+
+	base32_decode_init(&ctx, length, base, target);
+
+	while (!ctx.seen_end && (ctx.length != 0)) {
+		unsigned int i;
+
+		if (length > 0)
+			eol = ISC_FALSE;
+		else
+			eol = ISC_TRUE;
+		RETERR(isc_lex_getmastertoken(lexer, &token,
+					      isc_tokentype_string, eol));
+		if (token.type != isc_tokentype_string)
+			break;
+		tr = &token.value.as_textregion;
+		for (i = 0; i < tr->length; i++)
+			RETERR(base32_decode_char(&ctx, tr->base[i]));
+	}
+	if (ctx.length < 0 && !ctx.seen_end)
+		isc_lex_ungettoken(lexer, &token);
+	RETERR(base32_decode_finish(&ctx));
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_base32_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length) {
+	return (base32_tobuffer(lexer, base32, target, length));
+}
+
+isc_result_t
+isc_base32hex_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length) {
+	return (base32_tobuffer(lexer, base32hex, target, length));
+}
+
+static isc_result_t
+base32_decodestring(const char *cstr, const char base[], isc_buffer_t *target) {
+	base32_decode_ctx_t ctx;
+
+	base32_decode_init(&ctx, -1, base, target);
+	for (;;) {
+		int c = *cstr++;
+		if (c == '\0')
+			break;
+		if (c == ' ' || c == '\t' || c == '\n' || c== '\r')
+			continue;
+		RETERR(base32_decode_char(&ctx, c));
+	}
+	RETERR(base32_decode_finish(&ctx));
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_base32_decodestring(const char *cstr, isc_buffer_t *target) {
+	return (base32_decodestring(cstr, base32, target));
+}
+
+isc_result_t
+isc_base32hex_decodestring(const char *cstr, isc_buffer_t *target) {
+	return (base32_decodestring(cstr, base32hex, target));
+}
+
+static isc_result_t
+base32_decoderegion(isc_region_t *source, const char base[], isc_buffer_t *target) {
+	base32_decode_ctx_t ctx;
+
+	base32_decode_init(&ctx, -1, base, target);
+	while (source->length != 0) {
+		int c = *source->base;
+		RETERR(base32_decode_char(&ctx, c));
+		isc_region_consume(source, 1);
+	}
+	RETERR(base32_decode_finish(&ctx));
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_base32_decoderegion(isc_region_t *source, isc_buffer_t *target) {
+	return (base32_decoderegion(source, base32, target));
+}
+
+isc_result_t
+isc_base32hex_decoderegion(isc_region_t *source, isc_buffer_t *target) {
+	return (base32_decoderegion(source, base32hex, target));
+}
+
+static isc_result_t
+str_totext(const char *source, isc_buffer_t *target) {
+	unsigned int l;
+	isc_region_t region;
+
+	isc_buffer_availableregion(target, &region);
+	l = strlen(source);
+
+	if (l > region.length)
+		return (ISC_R_NOSPACE);
+
+	memcpy(region.base, source, l);
+	isc_buffer_add(target, l);
+	return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length) {
+	isc_region_t tr;
+
+	isc_buffer_availableregion(target, &tr);
+	if (length > tr.length)
+		return (ISC_R_NOSPACE);
+	memcpy(tr.base, base, length);
+	isc_buffer_add(target, length);
+	return (ISC_R_SUCCESS);
+}
diff --git a/src/lib/bind9/base64.c b/src/lib/bind9/base64.c
new file mode 100644
index 0000000..ee34c3c
--- /dev/null
+++ b/src/lib/bind9/base64.c
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2001, 2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: base64.c,v 1.34 2009-10-21 23:48:05 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/base64.h>
+#include <isc/buffer.h>
+#include <isc/lex.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#define RETERR(x) do { \
+	isc_result_t _r = (x); \
+	if (_r != ISC_R_SUCCESS) \
+		return (_r); \
+	} while (0)
+
+
+/*@{*/
+/*!
+ * These static functions are also present in lib/dns/rdata.c.  I'm not
+ * sure where they should go. -- bwelling
+ */
+static isc_result_t
+str_totext(const char *source, isc_buffer_t *target);
+
+static isc_result_t
+mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length);
+
+static const char base64[] =
+	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+/*@}*/
+
+isc_result_t
+isc_base64_totext(isc_region_t *source, int wordlength,
+		  const char *wordbreak, isc_buffer_t *target)
+{
+	char buf[5];
+	unsigned int loops = 0;
+
+	if (wordlength < 4)
+		wordlength = 4;
+
+	memset(buf, 0, sizeof(buf));
+	while (source->length > 2) {
+		buf[0] = base64[(source->base[0]>>2)&0x3f];
+		buf[1] = base64[((source->base[0]<<4)&0x30)|
+				((source->base[1]>>4)&0x0f)];
+		buf[2] = base64[((source->base[1]<<2)&0x3c)|
+				((source->base[2]>>6)&0x03)];
+		buf[3] = base64[source->base[2]&0x3f];
+		RETERR(str_totext(buf, target));
+		isc_region_consume(source, 3);
+
+		loops++;
+		if (source->length != 0 &&
+		    (int)((loops + 1) * 4) >= wordlength)
+		{
+			loops = 0;
+			RETERR(str_totext(wordbreak, target));
+		}
+	}
+	if (source->length == 2) {
+		buf[0] = base64[(source->base[0]>>2)&0x3f];
+		buf[1] = base64[((source->base[0]<<4)&0x30)|
+				((source->base[1]>>4)&0x0f)];
+		buf[2] = base64[((source->base[1]<<2)&0x3c)];
+		buf[3] = '=';
+		RETERR(str_totext(buf, target));
+		isc_region_consume(source, 2);
+	} else if (source->length == 1) {
+		buf[0] = base64[(source->base[0]>>2)&0x3f];
+		buf[1] = base64[((source->base[0]<<4)&0x30)];
+		buf[2] = buf[3] = '=';
+		RETERR(str_totext(buf, target));
+		isc_region_consume(source, 1);
+	}
+	return (ISC_R_SUCCESS);
+}
+
+/*%
+ * State of a base64 decoding process in progress.
+ */
+typedef struct {
+	int length;		/*%< Desired length of binary data or -1 */
+	isc_buffer_t *target;	/*%< Buffer for resulting binary data */
+	int digits;		/*%< Number of buffered base64 digits */
+	isc_boolean_t seen_end;	/*%< True if "=" end marker seen */
+	int val[4];
+} base64_decode_ctx_t;
+
+static inline void
+base64_decode_init(base64_decode_ctx_t *ctx, int length, isc_buffer_t *target)
+{
+	ctx->digits = 0;
+	ctx->seen_end = ISC_FALSE;
+	ctx->length = length;
+	ctx->target = target;
+}
+
+static inline isc_result_t
+base64_decode_char(base64_decode_ctx_t *ctx, int c) {
+	char *s;
+
+	if (ctx->seen_end)
+		return (ISC_R_BADBASE64);
+	if ((s = strchr(base64, c)) == NULL)
+		return (ISC_R_BADBASE64);
+	ctx->val[ctx->digits++] = s - base64;
+	if (ctx->digits == 4) {
+		int n;
+		unsigned char buf[3];
+		if (ctx->val[0] == 64 || ctx->val[1] == 64)
+			return (ISC_R_BADBASE64);
+		if (ctx->val[2] == 64 && ctx->val[3] != 64)
+			return (ISC_R_BADBASE64);
+		/*
+		 * Check that bits that should be zero are.
+		 */
+		if (ctx->val[2] == 64 && (ctx->val[1] & 0xf) != 0)
+			return (ISC_R_BADBASE64);
+		/*
+		 * We don't need to test for ctx->val[2] != 64 as
+		 * the bottom two bits of 64 are zero.
+		 */
+		if (ctx->val[3] == 64 && (ctx->val[2] & 0x3) != 0)
+			return (ISC_R_BADBASE64);
+		n = (ctx->val[2] == 64) ? 1 :
+			(ctx->val[3] == 64) ? 2 : 3;
+		if (n != 3) {
+			ctx->seen_end = ISC_TRUE;
+			if (ctx->val[2] == 64)
+				ctx->val[2] = 0;
+			if (ctx->val[3] == 64)
+				ctx->val[3] = 0;
+		}
+		buf[0] = (ctx->val[0]<<2)|(ctx->val[1]>>4);
+		buf[1] = (ctx->val[1]<<4)|(ctx->val[2]>>2);
+		buf[2] = (ctx->val[2]<<6)|(ctx->val[3]);
+		RETERR(mem_tobuffer(ctx->target, buf, n));
+		if (ctx->length >= 0) {
+			if (n > ctx->length)
+				return (ISC_R_BADBASE64);
+			else
+				ctx->length -= n;
+		}
+		ctx->digits = 0;
+	}
+	return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+base64_decode_finish(base64_decode_ctx_t *ctx) {
+	if (ctx->length > 0)
+		return (ISC_R_UNEXPECTEDEND);
+	if (ctx->digits != 0)
+		return (ISC_R_BADBASE64);
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_base64_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length) {
+	base64_decode_ctx_t ctx;
+	isc_textregion_t *tr;
+	isc_token_t token;
+	isc_boolean_t eol;
+
+	base64_decode_init(&ctx, length, target);
+
+	while (!ctx.seen_end && (ctx.length != 0)) {
+		unsigned int i;
+
+		if (length > 0)
+			eol = ISC_FALSE;
+		else
+			eol = ISC_TRUE;
+		RETERR(isc_lex_getmastertoken(lexer, &token,
+					      isc_tokentype_string, eol));
+		if (token.type != isc_tokentype_string)
+			break;
+		tr = &token.value.as_textregion;
+		for (i = 0; i < tr->length; i++)
+			RETERR(base64_decode_char(&ctx, tr->base[i]));
+	}
+	if (ctx.length < 0 && !ctx.seen_end)
+		isc_lex_ungettoken(lexer, &token);
+	RETERR(base64_decode_finish(&ctx));
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_base64_decodestring(const char *cstr, isc_buffer_t *target) {
+	base64_decode_ctx_t ctx;
+
+	base64_decode_init(&ctx, -1, target);
+	for (;;) {
+		int c = *cstr++;
+		if (c == '\0')
+			break;
+		if (c == ' ' || c == '\t' || c == '\n' || c== '\r')
+			continue;
+		RETERR(base64_decode_char(&ctx, c));
+	}
+	RETERR(base64_decode_finish(&ctx));
+	return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+str_totext(const char *source, isc_buffer_t *target) {
+	unsigned int l;
+	isc_region_t region;
+
+	isc_buffer_availableregion(target, &region);
+	l = strlen(source);
+
+	if (l > region.length)
+		return (ISC_R_NOSPACE);
+
+	memcpy(region.base, source, l);
+	isc_buffer_add(target, l);
+	return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length) {
+	isc_region_t tr;
+
+	isc_buffer_availableregion(target, &tr);
+	if (length > tr.length)
+		return (ISC_R_NOSPACE);
+	memcpy(tr.base, base, length);
+	isc_buffer_add(target, length);
+	return (ISC_R_SUCCESS);
+}
diff --git a/src/lib/bind9/bitstring.c b/src/lib/bind9/bitstring.c
new file mode 100644
index 0000000..3171150
--- /dev/null
+++ b/src/lib/bind9/bitstring.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: bitstring.c,v 1.17 2007-06-19 23:47:17 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stddef.h>
+
+#include <isc/magic.h>
+#include <isc/bitstring.h>
+#include <isc/util.h>
+
+#define DIV8(x)			((x) >> 3)
+#define MOD8(x)			((x) & 0x00000007U)
+#define OCTETS(n)		(((n) + 7) >> 3)
+#define PADDED(n)		((((n) + 7) >> 3) << 3)
+#define BITSET(bs, n) 		(((bs)->data[DIV8(n)] & \
+				 (1 << (7 - MOD8(n)))) != 0)
+#define SETBIT(bs, n)		(bs)->data[DIV8(n)] |= (1 << (7 - MOD8(n)))
+#define CLEARBIT(bs, n)		(bs)->data[DIV8(n)] &= ~(1 << (7 - MOD8(n)))
+
+#define BITSTRING_MAGIC		ISC_MAGIC('B', 'S', 't', 'r')
+#define VALID_BITSTRING(b)	ISC_MAGIC_VALID(b, BITSTRING_MAGIC)
+
+void
+isc_bitstring_init(isc_bitstring_t *bitstring, unsigned char *data,
+		   unsigned int length, unsigned int size, isc_boolean_t lsb0)
+{
+	/*
+	 * Make 'bitstring' refer to the bitstring of 'size' bits starting
+	 * at 'data'.  'length' bits of the bitstring are valid.  If 'lsb0'
+	 * is set then, bit 0 refers to the least significant bit of the
+	 * bitstring.  Otherwise bit 0 is the most significant bit.
+	 */
+
+	REQUIRE(bitstring != NULL);
+	REQUIRE(data != NULL);
+	REQUIRE(length <= size);
+
+	bitstring->magic = BITSTRING_MAGIC;
+	bitstring->data = data;
+	bitstring->length = length;
+	bitstring->size = size;
+	bitstring->lsb0 = lsb0;
+}
+
+void
+isc_bitstring_invalidate(isc_bitstring_t *bitstring) {
+
+	/*
+	 * Invalidate 'bitstring'.
+	 */
+
+	REQUIRE(VALID_BITSTRING(bitstring));
+
+	bitstring->magic = 0;
+	bitstring->data = NULL;
+	bitstring->length = 0;
+	bitstring->size = 0;
+	bitstring->lsb0 = ISC_FALSE;
+}
+
+void
+isc_bitstring_copy(isc_bitstring_t *source, unsigned int sbitpos,
+		   isc_bitstring_t *target, unsigned int tbitpos,
+		   unsigned int n)
+{
+	unsigned int tlast;
+
+	/*
+	 * Starting at bit 'sbitpos', copy 'n' bits from 'source' to
+	 * the 'n' bits of 'target' starting at 'tbitpos'.
+	 */
+
+	REQUIRE(VALID_BITSTRING(source));
+	REQUIRE(VALID_BITSTRING(target));
+	REQUIRE(source->lsb0 == target->lsb0);
+	if (source->lsb0) {
+		REQUIRE(sbitpos <= source->length);
+		sbitpos = PADDED(source->size) - sbitpos;
+		REQUIRE(sbitpos >= n);
+		sbitpos -= n;
+	} else
+		REQUIRE(sbitpos + n <= source->length);
+	tlast = tbitpos + n;
+	if (target->lsb0) {
+		REQUIRE(tbitpos <= target->length);
+		tbitpos = PADDED(target->size) - tbitpos;
+		REQUIRE(tbitpos >= n);
+		tbitpos -= n;
+	} else
+		REQUIRE(tlast <= target->size);
+
+	if (tlast > target->length)
+		target->length = tlast;
+
+	/*
+	 * This is far from optimal...
+	 */
+
+	while (n > 0) {
+		if (BITSET(source, sbitpos))
+			SETBIT(target, tbitpos);
+		else
+			CLEARBIT(target, tbitpos);
+		sbitpos++;
+		tbitpos++;
+		n--;
+	}
+}
diff --git a/src/lib/bind9/buffer.c b/src/lib/bind9/buffer.c
new file mode 100644
index 0000000..141487b
--- /dev/null
+++ b/src/lib/bind9/buffer.c
@@ -0,0 +1,489 @@
+/*
+ * Copyright (C) 2004-2008  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2002  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: buffer.c,v 1.49 2008-09-25 04:02:39 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/buffer.h>
+#include <isc/mem.h>
+#include <isc/region.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+void
+isc__buffer_init(isc_buffer_t *b, const void *base, unsigned int length) {
+	/*
+	 * Make 'b' refer to the 'length'-byte region starting at 'base'.
+	 * XXXDCL see the comment in buffer.h about base being const.
+	 */
+
+	REQUIRE(b != NULL);
+
+	ISC__BUFFER_INIT(b, base, length);
+}
+
+void
+isc__buffer_initnull(isc_buffer_t *b) {
+	/*
+	 * Initialize a new buffer which has no backing store.  This can
+	 * later be grown as needed and swapped in place.
+	 */
+
+	ISC__BUFFER_INIT(b, NULL, 0);
+}
+
+void
+isc_buffer_reinit(isc_buffer_t *b, void *base, unsigned int length) {
+	/*
+	 * Re-initialize the buffer enough to reconfigure the base of the
+	 * buffer.  We will swap in the new buffer, after copying any
+	 * data we contain into the new buffer and adjusting all of our
+	 * internal pointers.
+	 *
+	 * The buffer must not be smaller than the length of the original
+	 * buffer.
+	 */
+	REQUIRE(b->length <= length);
+	REQUIRE(base != NULL);
+
+	(void)memmove(base, b->base, b->length);
+	b->base = base;
+	b->length = length;
+}
+
+void
+isc__buffer_invalidate(isc_buffer_t *b) {
+	/*
+	 * Make 'b' an invalid buffer.
+	 */
+
+	REQUIRE(ISC_BUFFER_VALID(b));
+	REQUIRE(!ISC_LINK_LINKED(b, link));
+	REQUIRE(b->mctx == NULL);
+
+	ISC__BUFFER_INVALIDATE(b);
+}
+
+void
+isc__buffer_region(isc_buffer_t *b, isc_region_t *r) {
+	/*
+	 * Make 'r' refer to the region of 'b'.
+	 */
+
+	REQUIRE(ISC_BUFFER_VALID(b));
+	REQUIRE(r != NULL);
+
+	ISC__BUFFER_REGION(b, r);
+}
+
+void
+isc__buffer_usedregion(isc_buffer_t *b, isc_region_t *r) {
+	/*
+	 * Make 'r' refer to the used region of 'b'.
+	 */
+
+	REQUIRE(ISC_BUFFER_VALID(b));
+	REQUIRE(r != NULL);
+
+	ISC__BUFFER_USEDREGION(b, r);
+}
+
+void
+isc__buffer_availableregion(isc_buffer_t *b, isc_region_t *r) {
+	/*
+	 * Make 'r' refer to the available region of 'b'.
+	 */
+
+	REQUIRE(ISC_BUFFER_VALID(b));
+	REQUIRE(r != NULL);
+
+	ISC__BUFFER_AVAILABLEREGION(b, r);
+}
+
+void
+isc__buffer_add(isc_buffer_t *b, unsigned int n) {
+	/*
+	 * Increase the 'used' region of 'b' by 'n' bytes.
+	 */
+
+	REQUIRE(ISC_BUFFER_VALID(b));
+	REQUIRE(b->used + n <= b->length);
+
+	ISC__BUFFER_ADD(b, n);
+}
+
+void
+isc__buffer_subtract(isc_buffer_t *b, unsigned int n) {
+	/*
+	 * Decrease the 'used' region of 'b' by 'n' bytes.
+	 */
+
+	REQUIRE(ISC_BUFFER_VALID(b));
+	REQUIRE(b->used >= n);
+
+	ISC__BUFFER_SUBTRACT(b, n);
+}
+
+void
+isc__buffer_clear(isc_buffer_t *b) {
+	/*
+	 * Make the used region empty.
+	 */
+
+	REQUIRE(ISC_BUFFER_VALID(b));
+
+	ISC__BUFFER_CLEAR(b);
+}
+
+void
+isc__buffer_consumedregion(isc_buffer_t *b, isc_region_t *r) {
+	/*
+	 * Make 'r' refer to the consumed region of 'b'.
+	 */
+
+	REQUIRE(ISC_BUFFER_VALID(b));
+	REQUIRE(r != NULL);
+
+	ISC__BUFFER_CONSUMEDREGION(b, r);
+}
+
+void
+isc__buffer_remainingregion(isc_buffer_t *b, isc_region_t *r) {
+	/*
+	 * Make 'r' refer to the remaining region of 'b'.
+	 */
+
+	REQUIRE(ISC_BUFFER_VALID(b));
+	REQUIRE(r != NULL);
+
+	ISC__BUFFER_REMAININGREGION(b, r);
+}
+
+void
+isc__buffer_activeregion(isc_buffer_t *b, isc_region_t *r) {
+	/*
+	 * Make 'r' refer to the active region of 'b'.
+	 */
+
+	REQUIRE(ISC_BUFFER_VALID(b));
+	REQUIRE(r != NULL);
+
+	ISC__BUFFER_ACTIVEREGION(b, r);
+}
+
+void
+isc__buffer_setactive(isc_buffer_t *b, unsigned int n) {
+	/*
+	 * Sets the end of the active region 'n' bytes after current.
+	 */
+
+	REQUIRE(ISC_BUFFER_VALID(b));
+	REQUIRE(b->current + n <= b->used);
+
+	ISC__BUFFER_SETACTIVE(b, n);
+}
+
+void
+isc__buffer_first(isc_buffer_t *b) {
+	/*
+	 * Make the consumed region empty.
+	 */
+
+	REQUIRE(ISC_BUFFER_VALID(b));
+
+	ISC__BUFFER_FIRST(b);
+}
+
+void
+isc__buffer_forward(isc_buffer_t *b, unsigned int n) {
+	/*
+	 * Increase the 'consumed' region of 'b' by 'n' bytes.
+	 */
+
+	REQUIRE(ISC_BUFFER_VALID(b));
+	REQUIRE(b->current + n <= b->used);
+
+	ISC__BUFFER_FORWARD(b, n);
+}
+
+void
+isc__buffer_back(isc_buffer_t *b, unsigned int n) {
+	/*
+	 * Decrease the 'consumed' region of 'b' by 'n' bytes.
+	 */
+
+	REQUIRE(ISC_BUFFER_VALID(b));
+	REQUIRE(n <= b->current);
+
+	ISC__BUFFER_BACK(b, n);
+}
+
+void
+isc_buffer_compact(isc_buffer_t *b) {
+	unsigned int length;
+	void *src;
+
+	/*
+	 * Compact the used region by moving the remaining region so it occurs
+	 * at the start of the buffer.  The used region is shrunk by the size
+	 * of the consumed region, and the consumed region is then made empty.
+	 */
+
+	REQUIRE(ISC_BUFFER_VALID(b));
+
+	src = isc_buffer_current(b);
+	length = isc_buffer_remaininglength(b);
+	(void)memmove(b->base, src, (size_t)length);
+
+	if (b->active > b->current)
+		b->active -= b->current;
+	else
+		b->active = 0;
+	b->current = 0;
+	b->used = length;
+}
+
+isc_uint8_t
+isc_buffer_getuint8(isc_buffer_t *b) {
+	unsigned char *cp;
+	isc_uint8_t result;
+
+	/*
+	 * Read an unsigned 8-bit integer from 'b' and return it.
+	 */
+
+	REQUIRE(ISC_BUFFER_VALID(b));
+	REQUIRE(b->used - b->current >= 1);
+
+	cp = isc_buffer_current(b);
+	b->current += 1;
+	result = ((isc_uint8_t)(cp[0]));
+
+	return (result);
+}
+
+void
+isc__buffer_putuint8(isc_buffer_t *b, isc_uint8_t val) {
+	REQUIRE(ISC_BUFFER_VALID(b));
+	REQUIRE(b->used + 1 <= b->length);
+
+	ISC__BUFFER_PUTUINT8(b, val);
+}
+
+isc_uint16_t
+isc_buffer_getuint16(isc_buffer_t *b) {
+	unsigned char *cp;
+	isc_uint16_t result;
+
+	/*
+	 * Read an unsigned 16-bit integer in network byte order from 'b',
+	 * convert it to host byte order, and return it.
+	 */
+
+	REQUIRE(ISC_BUFFER_VALID(b));
+	REQUIRE(b->used - b->current >= 2);
+
+	cp = isc_buffer_current(b);
+	b->current += 2;
+	result = ((unsigned int)(cp[0])) << 8;
+	result |= ((unsigned int)(cp[1]));
+
+	return (result);
+}
+
+void
+isc__buffer_putuint16(isc_buffer_t *b, isc_uint16_t val) {
+	REQUIRE(ISC_BUFFER_VALID(b));
+	REQUIRE(b->used + 2 <= b->length);
+
+	ISC__BUFFER_PUTUINT16(b, val);
+}
+
+void
+isc__buffer_putuint24(isc_buffer_t *b, isc_uint32_t val) {
+	REQUIRE(ISC_BUFFER_VALID(b));
+	REQUIRE(b->used + 3 <= b->length);
+
+	ISC__BUFFER_PUTUINT24(b, val);
+}
+
+isc_uint32_t
+isc_buffer_getuint32(isc_buffer_t *b) {
+	unsigned char *cp;
+	isc_uint32_t result;
+
+	/*
+	 * Read an unsigned 32-bit integer in network byte order from 'b',
+	 * convert it to host byte order, and return it.
+	 */
+
+	REQUIRE(ISC_BUFFER_VALID(b));
+	REQUIRE(b->used - b->current >= 4);
+
+	cp = isc_buffer_current(b);
+	b->current += 4;
+	result = ((unsigned int)(cp[0])) << 24;
+	result |= ((unsigned int)(cp[1])) << 16;
+	result |= ((unsigned int)(cp[2])) << 8;
+	result |= ((unsigned int)(cp[3]));
+
+	return (result);
+}
+
+void
+isc__buffer_putuint32(isc_buffer_t *b, isc_uint32_t val) {
+	REQUIRE(ISC_BUFFER_VALID(b));
+	REQUIRE(b->used + 4 <= b->length);
+
+	ISC__BUFFER_PUTUINT32(b, val);
+}
+
+isc_uint64_t
+isc_buffer_getuint48(isc_buffer_t *b) {
+	unsigned char *cp;
+	isc_uint64_t result;
+
+	/*
+	 * Read an unsigned 48-bit integer in network byte order from 'b',
+	 * convert it to host byte order, and return it.
+	 */
+
+	REQUIRE(ISC_BUFFER_VALID(b));
+	REQUIRE(b->used - b->current >= 6);
+
+	cp = isc_buffer_current(b);
+	b->current += 6;
+	result = ((isc_int64_t)(cp[0])) << 40;
+	result |= ((isc_int64_t)(cp[1])) << 32;
+	result |= ((isc_int64_t)(cp[2])) << 24;
+	result |= ((isc_int64_t)(cp[3])) << 16;
+	result |= ((isc_int64_t)(cp[4])) << 8;
+	result |= ((isc_int64_t)(cp[5]));
+
+	return (result);
+}
+
+void
+isc__buffer_putuint48(isc_buffer_t *b, isc_uint64_t val) {
+	isc_uint16_t valhi;
+	isc_uint32_t vallo;
+
+	REQUIRE(ISC_BUFFER_VALID(b));
+	REQUIRE(b->used + 6 <= b->length);
+
+	valhi = (isc_uint16_t)(val >> 32);
+	vallo = (isc_uint32_t)(val & 0xFFFFFFFF);
+	ISC__BUFFER_PUTUINT16(b, valhi);
+	ISC__BUFFER_PUTUINT32(b, vallo);
+}
+
+void
+isc__buffer_putmem(isc_buffer_t *b, const unsigned char *base,
+		   unsigned int length)
+{
+	REQUIRE(ISC_BUFFER_VALID(b));
+	REQUIRE(b->used + length <= b->length);
+
+	ISC__BUFFER_PUTMEM(b, base, length);
+}
+
+void
+isc__buffer_putstr(isc_buffer_t *b, const char *source) {
+	unsigned int l;
+	unsigned char *cp;
+
+	REQUIRE(ISC_BUFFER_VALID(b));
+	REQUIRE(source != NULL);
+
+	/*
+	 * Do not use ISC__BUFFER_PUTSTR(), so strlen is only done once.
+	 */
+	l = strlen(source);
+
+	REQUIRE(l <= isc_buffer_availablelength(b));
+
+	cp = isc_buffer_used(b);
+	memcpy(cp, source, l);
+	b->used += l;
+}
+
+isc_result_t
+isc_buffer_copyregion(isc_buffer_t *b, const isc_region_t *r) {
+	unsigned char *base;
+	unsigned int available;
+
+	REQUIRE(ISC_BUFFER_VALID(b));
+	REQUIRE(r != NULL);
+
+	/*
+	 * XXXDCL
+	 */
+	base = isc_buffer_used(b);
+	available = isc_buffer_availablelength(b);
+	if (r->length > available)
+		return (ISC_R_NOSPACE);
+	memcpy(base, r->base, r->length);
+	b->used += r->length;
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_buffer_allocate(isc_mem_t *mctx, isc_buffer_t **dynbuffer,
+		    unsigned int length)
+{
+	isc_buffer_t *dbuf;
+
+	REQUIRE(dynbuffer != NULL);
+	REQUIRE(*dynbuffer == NULL);
+
+	dbuf = isc_mem_get(mctx, length + sizeof(isc_buffer_t));
+	if (dbuf == NULL)
+		return (ISC_R_NOMEMORY);
+
+	isc_buffer_init(dbuf, ((unsigned char *)dbuf) + sizeof(isc_buffer_t),
+			length);
+	dbuf->mctx = mctx;
+
+	*dynbuffer = dbuf;
+
+	return (ISC_R_SUCCESS);
+}
+
+void
+isc_buffer_free(isc_buffer_t **dynbuffer) {
+	unsigned int real_length;
+	isc_buffer_t *dbuf;
+	isc_mem_t *mctx;
+
+	REQUIRE(dynbuffer != NULL);
+	REQUIRE(ISC_BUFFER_VALID(*dynbuffer));
+	REQUIRE((*dynbuffer)->mctx != NULL);
+
+	dbuf = *dynbuffer;
+	*dynbuffer = NULL;	/* destroy external reference */
+
+	real_length = dbuf->length + sizeof(isc_buffer_t);
+	mctx = dbuf->mctx;
+	dbuf->mctx = NULL;
+	isc_buffer_invalidate(dbuf);
+
+	isc_mem_put(mctx, dbuf, real_length);
+}
diff --git a/src/lib/bind9/bufferlist.c b/src/lib/bind9/bufferlist.c
new file mode 100644
index 0000000..c7376bb
--- /dev/null
+++ b/src/lib/bind9/bufferlist.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: bufferlist.c,v 1.17 2007-06-19 23:47:17 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stddef.h>
+
+#include <isc/buffer.h>
+#include <isc/bufferlist.h>
+#include <isc/util.h>
+
+unsigned int
+isc_bufferlist_usedcount(isc_bufferlist_t *bl) {
+	isc_buffer_t *buffer;
+	unsigned int length;
+
+	REQUIRE(bl != NULL);
+
+	length = 0;
+	buffer = ISC_LIST_HEAD(*bl);
+	while (buffer != NULL) {
+		REQUIRE(ISC_BUFFER_VALID(buffer));
+		length += isc_buffer_usedlength(buffer);
+		buffer = ISC_LIST_NEXT(buffer, link);
+	}
+
+	return (length);
+}
+
+unsigned int
+isc_bufferlist_availablecount(isc_bufferlist_t *bl) {
+	isc_buffer_t *buffer;
+	unsigned int length;
+
+	REQUIRE(bl != NULL);
+
+	length = 0;
+	buffer = ISC_LIST_HEAD(*bl);
+	while (buffer != NULL) {
+		REQUIRE(ISC_BUFFER_VALID(buffer));
+		length += isc_buffer_availablelength(buffer);
+		buffer = ISC_LIST_NEXT(buffer, link);
+	}
+
+	return (length);
+}
diff --git a/src/lib/bind9/commandline.c b/src/lib/bind9/commandline.c
new file mode 100644
index 0000000..1f98c7b
--- /dev/null
+++ b/src/lib/bind9/commandline.c
@@ -0,0 +1,225 @@
+/*
+ * Portions Copyright (C) 2004, 2005, 2007, 2008  Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Copyright (c) 1987, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $Id: commandline.c,v 1.22 2008-09-25 04:02:39 tbox Exp $ */
+
+/*! \file
+ * This file was adapted from the NetBSD project's source tree, RCS ID:
+ *    NetBSD: getopt.c,v 1.15 1999/09/20 04:39:37 lukem Exp
+ *
+ * The primary change has been to rename items to the ISC namespace
+ * and format in the ISC coding style.
+ */
+
+/*
+ * \author Principal Authors: Computer Systems Research Group at UC Berkeley
+ * \author Principal ISC caretaker: DCL
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+
+#include <isc/commandline.h>
+#include <isc/msgs.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+/*% Index into parent argv vector. */
+LIBISC_EXTERNAL_DATA int isc_commandline_index = 1;
+/*% Character checked for validity. */
+LIBISC_EXTERNAL_DATA int isc_commandline_option;
+/*% Argument associated with option. */
+LIBISC_EXTERNAL_DATA char *isc_commandline_argument;
+/*% For printing error messages. */
+LIBISC_EXTERNAL_DATA char *isc_commandline_progname;
+/*% Print error messages. */
+LIBISC_EXTERNAL_DATA isc_boolean_t isc_commandline_errprint = ISC_TRUE;
+/*% Reset processing. */
+LIBISC_EXTERNAL_DATA isc_boolean_t isc_commandline_reset = ISC_TRUE;
+
+static char endopt = '\0';
+
+#define	BADOPT	'?'
+#define	BADARG	':'
+#define ENDOPT  &endopt
+
+/*!
+ * getopt --
+ *	Parse argc/argv argument vector.
+ */
+int
+isc_commandline_parse(int argc, char * const *argv, const char *options) {
+	static char *place = ENDOPT;
+	char *option;			/* Index into *options of option. */
+
+	REQUIRE(argc >= 0 && argv != NULL && options != NULL);
+
+	/*
+	 * Update scanning pointer, either because a reset was requested or
+	 * the previous argv was finished.
+	 */
+	if (isc_commandline_reset || *place == '\0') {
+		if (isc_commandline_reset) {
+			isc_commandline_index = 1;
+			isc_commandline_reset = ISC_FALSE;
+		}
+
+		if (isc_commandline_progname == NULL)
+			isc_commandline_progname = argv[0];
+
+		if (isc_commandline_index >= argc ||
+		    *(place = argv[isc_commandline_index]) != '-') {
+			/*
+			 * Index out of range or points to non-option.
+			 */
+			place = ENDOPT;
+			return (-1);
+		}
+
+		if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
+			/*
+			 * Found '--' to signal end of options.  Advance
+			 * index to next argv, the first non-option.
+			 */
+			isc_commandline_index++;
+			place = ENDOPT;
+			return (-1);
+		}
+	}
+
+	isc_commandline_option = *place++;
+	option = strchr(options, isc_commandline_option);
+
+	/*
+	 * Ensure valid option has been passed as specified by options string.
+	 * '-:' is never a valid command line option because it could not
+	 * distinguish ':' from the argument specifier in the options string.
+	 */
+	if (isc_commandline_option == ':' || option == NULL) {
+		if (*place == '\0')
+			isc_commandline_index++;
+
+		if (isc_commandline_errprint && *options != ':')
+			fprintf(stderr, "%s: %s -- %c\n",
+				isc_commandline_progname,
+				isc_msgcat_get(isc_msgcat,
+					       ISC_MSGSET_COMMANDLINE,
+					       ISC_MSG_ILLEGALOPT,
+					       "illegal option"),
+				isc_commandline_option);
+
+		return (BADOPT);
+	}
+
+	if (*++option != ':') {
+		/*
+		 * Option does not take an argument.
+		 */
+		isc_commandline_argument = NULL;
+
+		/*
+		 * Skip to next argv if at the end of the current argv.
+		 */
+		if (*place == '\0')
+			++isc_commandline_index;
+
+	} else {
+		/*
+		 * Option needs an argument.
+		 */
+		if (*place != '\0')
+			/*
+			 * Option is in this argv, -D1 style.
+			 */
+			isc_commandline_argument = place;
+
+		else if (argc > ++isc_commandline_index)
+			/*
+			 * Option is next argv, -D 1 style.
+			 */
+			isc_commandline_argument = argv[isc_commandline_index];
+
+		else {
+			/*
+			 * Argument needed, but no more argv.
+			 */
+			place = ENDOPT;
+
+			/*
+			 * Silent failure with "missing argument" return
+			 * when ':' starts options string, per historical spec.
+			 */
+			if (*options == ':')
+				return (BADARG);
+
+			if (isc_commandline_errprint)
+				fprintf(stderr, "%s: %s -- %c\n",
+					isc_commandline_progname,
+					isc_msgcat_get(isc_msgcat,
+						       ISC_MSGSET_COMMANDLINE,
+						       ISC_MSG_OPTNEEDARG,
+						       "option requires "
+						       "an argument"),
+					isc_commandline_option);
+
+			return (BADOPT);
+		}
+
+		place = ENDOPT;
+
+		/*
+		 * Point to argv that follows argument.
+		 */
+		isc_commandline_index++;
+	}
+
+	return (isc_commandline_option);
+}
diff --git a/src/lib/bind9/entropy.c b/src/lib/bind9/entropy.c
new file mode 100644
index 0000000..8d273d2
--- /dev/null
+++ b/src/lib/bind9/entropy.c
@@ -0,0 +1,1277 @@
+/*
+ * Copyright (C) 2004-2007, 2009, 2010  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: entropy.c,v 1.22 2010-08-10 23:48:19 tbox Exp $ */
+
+/*! \file
+ * \brief
+ * This is the system independent part of the entropy module.  It is
+ * compiled via inclusion from the relevant OS source file, ie,
+ * \link unix/entropy.c unix/entropy.c \endlink or win32/entropy.c.
+ *
+ * \author Much of this code is modeled after the NetBSD /dev/random implementation,
+ * written by Michael Graff <explorer at netbsd.org>.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+
+#include <isc/buffer.h>
+#include <isc/entropy.h>
+#include <isc/keyboard.h>
+#include <isc/list.h>
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/msgs.h>
+#include <isc/mutex.h>
+#include <isc/platform.h>
+#include <isc/region.h>
+#include <isc/sha1.h>
+#include <isc/string.h>
+#include <isc/time.h>
+#include <isc/util.h>
+
+
+#define ENTROPY_MAGIC		ISC_MAGIC('E', 'n', 't', 'e')
+#define SOURCE_MAGIC		ISC_MAGIC('E', 'n', 't', 's')
+
+#define VALID_ENTROPY(e)	ISC_MAGIC_VALID(e, ENTROPY_MAGIC)
+#define VALID_SOURCE(s)		ISC_MAGIC_VALID(s, SOURCE_MAGIC)
+
+/***
+ *** "constants."  Do not change these unless you _really_ know what
+ *** you are doing.
+ ***/
+
+/*%
+ * Size of entropy pool in 32-bit words.  This _MUST_ be a power of 2.
+ */
+#define RND_POOLWORDS	128
+/*% Pool in bytes. */
+#define RND_POOLBYTES	(RND_POOLWORDS * 4)
+/*% Pool in bits. */
+#define RND_POOLBITS	(RND_POOLWORDS * 32)
+
+/*%
+ * Number of bytes returned per hash.  This must be true:
+ *	threshold * 2 <= digest_size_in_bytes
+ */
+#define RND_ENTROPY_THRESHOLD	10
+#define THRESHOLD_BITS		(RND_ENTROPY_THRESHOLD * 8)
+
+/*%
+ * Size of the input event queue in samples.
+ */
+#define RND_EVENTQSIZE	32
+
+/*%
+ * The number of times we'll "reseed" for pseudorandom seeds.  This is an
+ * extremely weak pseudorandom seed.  If the caller is using lots of
+ * pseudorandom data and they cannot provide a stronger random source,
+ * there is little we can do other than hope they're smart enough to
+ * call _adddata() with something better than we can come up with.
+ */
+#define RND_INITIALIZE	128
+
+/*% Entropy Pool */
+typedef struct {
+	isc_uint32_t	cursor;		/*%< current add point in the pool */
+	isc_uint32_t	entropy;	/*%< current entropy estimate in bits */
+	isc_uint32_t	pseudo;		/*%< bits extracted in pseudorandom */
+	isc_uint32_t	rotate;		/*%< how many bits to rotate by */
+	isc_uint32_t	pool[RND_POOLWORDS];	/*%< random pool data */
+} isc_entropypool_t;
+
+struct isc_entropy {
+	unsigned int			magic;
+	isc_mem_t		       *mctx;
+	isc_mutex_t			lock;
+	unsigned int			refcnt;
+	isc_uint32_t			initialized;
+	isc_uint32_t			initcount;
+	isc_entropypool_t		pool;
+	unsigned int			nsources;
+	isc_entropysource_t	       *nextsource;
+	ISC_LIST(isc_entropysource_t)	sources;
+};
+
+/*% Sample Queue */
+typedef struct {
+	isc_uint32_t	last_time;	/*%< last time recorded */
+	isc_uint32_t	last_delta;	/*%< last delta value */
+	isc_uint32_t	last_delta2;	/*%< last delta2 value */
+	isc_uint32_t	nsamples;	/*%< number of samples filled in */
+	isc_uint32_t   *samples;	/*%< the samples */
+	isc_uint32_t   *extra;		/*%< extra samples added in */
+} sample_queue_t;
+
+typedef struct {
+	sample_queue_t	samplequeue;
+} isc_entropysamplesource_t;
+
+typedef struct {
+	isc_boolean_t		start_called;
+	isc_entropystart_t	startfunc;
+	isc_entropyget_t	getfunc;
+	isc_entropystop_t	stopfunc;
+	void		       *arg;
+	sample_queue_t		samplequeue;
+} isc_cbsource_t;
+
+typedef struct {
+	FILESOURCE_HANDLE_TYPE handle;
+} isc_entropyfilesource_t;
+
+struct isc_entropysource {
+	unsigned int	magic;
+	unsigned int	type;
+	isc_entropy_t  *ent;
+	isc_uint32_t	total;		/*%< entropy from this source */
+	ISC_LINK(isc_entropysource_t)	link;
+	char		name[32];
+	isc_boolean_t	bad;
+	isc_boolean_t	warn_keyboard;
+	isc_keyboard_t	kbd;
+	union {
+		isc_entropysamplesource_t	sample;
+		isc_entropyfilesource_t		file;
+		isc_cbsource_t			callback;
+		isc_entropyusocketsource_t	usocket;
+	} sources;
+};
+
+#define ENTROPY_SOURCETYPE_SAMPLE	1	/*%< Type is a sample source */
+#define ENTROPY_SOURCETYPE_FILE		2	/*%< Type is a file source */
+#define ENTROPY_SOURCETYPE_CALLBACK	3	/*%< Type is a callback source */
+#define ENTROPY_SOURCETYPE_USOCKET	4	/*%< Type is a Unix socket source */
+
+/*@{*/
+/*%
+ * The random pool "taps"
+ */
+#define TAP1	99
+#define TAP2	59
+#define TAP3	31
+#define TAP4	 9
+#define TAP5	 7
+/*@}*/
+
+/*@{*/
+/*%
+ * Declarations for function provided by the system dependent sources that
+ * include this file.
+ */
+static void
+fillpool(isc_entropy_t *, unsigned int, isc_boolean_t);
+
+static int
+wait_for_sources(isc_entropy_t *);
+
+static void
+destroyfilesource(isc_entropyfilesource_t *source);
+
+static void
+destroyusocketsource(isc_entropyusocketsource_t *source);
+
+/*@}*/
+
+static void
+samplequeue_release(isc_entropy_t *ent, sample_queue_t *sq) {
+	REQUIRE(sq->samples != NULL);
+	REQUIRE(sq->extra != NULL);
+
+	isc_mem_put(ent->mctx, sq->samples, RND_EVENTQSIZE * 4);
+	isc_mem_put(ent->mctx, sq->extra, RND_EVENTQSIZE * 4);
+	sq->samples = NULL;
+	sq->extra = NULL;
+}
+
+static isc_result_t
+samplesource_allocate(isc_entropy_t *ent, sample_queue_t *sq) {
+	sq->samples = isc_mem_get(ent->mctx, RND_EVENTQSIZE * 4);
+	if (sq->samples == NULL)
+		return (ISC_R_NOMEMORY);
+
+	sq->extra = isc_mem_get(ent->mctx, RND_EVENTQSIZE * 4);
+	if (sq->extra == NULL) {
+		isc_mem_put(ent->mctx, sq->samples, RND_EVENTQSIZE * 4);
+		sq->samples = NULL;
+		return (ISC_R_NOMEMORY);
+	}
+
+	sq->nsamples = 0;
+
+	return (ISC_R_SUCCESS);
+}
+
+/*%
+ * Add in entropy, even when the value we're adding in could be
+ * very large.
+ */
+static inline void
+add_entropy(isc_entropy_t *ent, isc_uint32_t entropy) {
+	/* clamp input.  Yes, this must be done. */
+	entropy = ISC_MIN(entropy, RND_POOLBITS);
+	/* Add in the entropy we already have. */
+	entropy += ent->pool.entropy;
+	/* Clamp. */
+	ent->pool.entropy = ISC_MIN(entropy, RND_POOLBITS);
+}
+
+/*%
+ * Decrement the amount of entropy the pool has.
+ */
+static inline void
+subtract_entropy(isc_entropy_t *ent, isc_uint32_t entropy) {
+	entropy = ISC_MIN(entropy, ent->pool.entropy);
+	ent->pool.entropy -= entropy;
+}
+
+/*!
+ * Add in entropy, even when the value we're adding in could be
+ * very large.
+ */
+static inline void
+add_pseudo(isc_entropy_t *ent, isc_uint32_t pseudo) {
+	/* clamp input.  Yes, this must be done. */
+	pseudo = ISC_MIN(pseudo, RND_POOLBITS * 8);
+	/* Add in the pseudo we already have. */
+	pseudo += ent->pool.pseudo;
+	/* Clamp. */
+	ent->pool.pseudo = ISC_MIN(pseudo, RND_POOLBITS * 8);
+}
+
+/*!
+ * Decrement the amount of pseudo the pool has.
+ */
+static inline void
+subtract_pseudo(isc_entropy_t *ent, isc_uint32_t pseudo) {
+	pseudo = ISC_MIN(pseudo, ent->pool.pseudo);
+	ent->pool.pseudo -= pseudo;
+}
+
+/*!
+ * Add one word to the pool, rotating the input as needed.
+ */
+static inline void
+entropypool_add_word(isc_entropypool_t *rp, isc_uint32_t val) {
+	/*
+	 * Steal some values out of the pool, and xor them into the
+	 * word we were given.
+	 *
+	 * Mix the new value into the pool using xor.  This will
+	 * prevent the actual values from being known to the caller
+	 * since the previous values are assumed to be unknown as well.
+	 */
+	val ^= rp->pool[(rp->cursor + TAP1) & (RND_POOLWORDS - 1)];
+	val ^= rp->pool[(rp->cursor + TAP2) & (RND_POOLWORDS - 1)];
+	val ^= rp->pool[(rp->cursor + TAP3) & (RND_POOLWORDS - 1)];
+	val ^= rp->pool[(rp->cursor + TAP4) & (RND_POOLWORDS - 1)];
+	val ^= rp->pool[(rp->cursor + TAP5) & (RND_POOLWORDS - 1)];
+	if (rp->rotate == 0)
+		rp->pool[rp->cursor++] ^= val;
+	else
+		rp->pool[rp->cursor++] ^=
+		  ((val << rp->rotate) | (val >> (32 - rp->rotate)));
+
+	/*
+	 * If we have looped around the pool, increment the rotate
+	 * variable so the next value will get xored in rotated to
+	 * a different position.
+	 * Increment by a value that is relatively prime to the word size
+	 * to try to spread the bits throughout the pool quickly when the
+	 * pool is empty.
+	 */
+	if (rp->cursor == RND_POOLWORDS) {
+		rp->cursor = 0;
+		rp->rotate = (rp->rotate + 7) & 31;
+	}
+}
+
+/*!
+ * Add a buffer's worth of data to the pool.
+ *
+ * Requires that the lock is held on the entropy pool.
+ */
+static void
+entropypool_adddata(isc_entropy_t *ent, void *p, unsigned int len,
+		    isc_uint32_t entropy)
+{
+	isc_uint32_t val;
+	unsigned long addr;
+	isc_uint8_t *buf;
+
+	addr = (unsigned long)p;
+	buf = p;
+
+	if ((addr & 0x03U) != 0U) {
+		val = 0;
+		switch (len) {
+		case 3:
+			val = *buf++;
+			len--;
+		case 2:
+			val = val << 8 | *buf++;
+			len--;
+		case 1:
+			val = val << 8 | *buf++;
+			len--;
+		}
+
+		entropypool_add_word(&ent->pool, val);
+	}
+
+	for (; len > 3; len -= 4) {
+		val = *((isc_uint32_t *)buf);
+
+		entropypool_add_word(&ent->pool, val);
+		buf += 4;
+	}
+
+	if (len != 0) {
+		val = 0;
+		switch (len) {
+		case 3:
+			val = *buf++;
+		case 2:
+			val = val << 8 | *buf++;
+		case 1:
+			val = val << 8 | *buf++;
+		}
+
+		entropypool_add_word(&ent->pool, val);
+	}
+
+	add_entropy(ent, entropy);
+	subtract_pseudo(ent, entropy);
+}
+
+static inline void
+reseed(isc_entropy_t *ent) {
+	isc_time_t t;
+	pid_t pid;
+
+	if (ent->initcount == 0) {
+		pid = getpid();
+		entropypool_adddata(ent, &pid, sizeof(pid), 0);
+		pid = getppid();
+		entropypool_adddata(ent, &pid, sizeof(pid), 0);
+	}
+
+	/*!
+	 * After we've reseeded 100 times, only add new timing info every
+	 * 50 requests.  This will keep us from using lots and lots of
+	 * CPU just to return bad pseudorandom data anyway.
+	 */
+	if (ent->initcount > 100)
+		if ((ent->initcount % 50) != 0)
+			return;
+
+	TIME_NOW(&t);
+	entropypool_adddata(ent, &t, sizeof(t), 0);
+	ent->initcount++;
+}
+
+static inline unsigned int
+estimate_entropy(sample_queue_t *sq, isc_uint32_t t) {
+	isc_int32_t		delta;
+	isc_int32_t		delta2;
+	isc_int32_t		delta3;
+
+	/*!
+	 * If the time counter has overflowed, calculate the real difference.
+	 * If it has not, it is simpler.
+	 */
+	if (t < sq->last_time)
+		delta = UINT_MAX - sq->last_time + t;
+	else
+		delta = sq->last_time - t;
+
+	if (delta < 0)
+		delta = -delta;
+
+	/*
+	 * Calculate the second and third order differentials
+	 */
+	delta2 = sq->last_delta - delta;
+	if (delta2 < 0)
+		delta2 = -delta2;
+
+	delta3 = sq->last_delta2 - delta2;
+	if (delta3 < 0)
+		delta3 = -delta3;
+
+	sq->last_time = t;
+	sq->last_delta = delta;
+	sq->last_delta2 = delta2;
+
+	/*
+	 * If any delta is 0, we got no entropy.  If all are non-zero, we
+	 * might have something.
+	 */
+	if (delta == 0 || delta2 == 0 || delta3 == 0)
+		return 0;
+
+	/*
+	 * We could find the smallest delta and claim we got log2(delta)
+	 * bits, but for now return that we found 1 bit.
+	 */
+	return 1;
+}
+
+static unsigned int
+crunchsamples(isc_entropy_t *ent, sample_queue_t *sq) {
+	unsigned int ns;
+	unsigned int added;
+
+	if (sq->nsamples < 6)
+		return (0);
+
+	added = 0;
+	sq->last_time = sq->samples[0];
+	sq->last_delta = 0;
+	sq->last_delta2 = 0;
+
+	/*
+	 * Prime the values by adding in the first 4 samples in.  This
+	 * should completely initialize the delta calculations.
+	 */
+	for (ns = 0; ns < 4; ns++)
+		(void)estimate_entropy(sq, sq->samples[ns]);
+
+	for (ns = 4; ns < sq->nsamples; ns++)
+		added += estimate_entropy(sq, sq->samples[ns]);
+
+	entropypool_adddata(ent, sq->samples, sq->nsamples * 4, added);
+	entropypool_adddata(ent, sq->extra, sq->nsamples * 4, 0);
+
+	/*
+	 * Move the last 4 samples into the first 4 positions, and start
+	 * adding new samples from that point.
+	 */
+	for (ns = 0; ns < 4; ns++) {
+		sq->samples[ns] = sq->samples[sq->nsamples - 4 + ns];
+		sq->extra[ns] = sq->extra[sq->nsamples - 4 + ns];
+	}
+
+	sq->nsamples = 4;
+
+	return (added);
+}
+
+static unsigned int
+get_from_callback(isc_entropysource_t *source, unsigned int desired,
+		  isc_boolean_t blocking)
+{
+	isc_entropy_t *ent = source->ent;
+	isc_cbsource_t *cbs = &source->sources.callback;
+	unsigned int added;
+	unsigned int got;
+	isc_result_t result;
+
+	if (desired == 0)
+		return (0);
+
+	if (source->bad)
+		return (0);
+
+	if (!cbs->start_called && cbs->startfunc != NULL) {
+		result = cbs->startfunc(source, cbs->arg, blocking);
+		if (result != ISC_R_SUCCESS)
+			return (0);
+		cbs->start_called = ISC_TRUE;
+	}
+
+	added = 0;
+	result = ISC_R_SUCCESS;
+	while (desired > 0 && result == ISC_R_SUCCESS) {
+		result = cbs->getfunc(source, cbs->arg, blocking);
+		if (result == ISC_R_QUEUEFULL) {
+			got = crunchsamples(ent, &cbs->samplequeue);
+			added += got;
+			desired -= ISC_MIN(got, desired);
+			result = ISC_R_SUCCESS;
+		} else if (result != ISC_R_SUCCESS &&
+			   result != ISC_R_NOTBLOCKING)
+			source->bad = ISC_TRUE;
+
+	}
+
+	return (added);
+}
+
+/*
+ * Extract some number of bytes from the random pool, decreasing the
+ * estimate of randomness as each byte is extracted.
+ *
+ * Do this by stiring the pool and returning a part of hash as randomness.
+ * Note that no secrets are given away here since parts of the hash are
+ * xored together before returned.
+ *
+ * Honor the request from the caller to only return good data, any data,
+ * etc.
+ */
+isc_result_t
+isc_entropy_getdata(isc_entropy_t *ent, void *data, unsigned int length,
+		    unsigned int *returned, unsigned int flags)
+{
+	unsigned int i;
+	isc_sha1_t hash;
+	unsigned char digest[ISC_SHA1_DIGESTLENGTH];
+	isc_uint32_t remain, deltae, count, total;
+	isc_uint8_t *buf;
+	isc_boolean_t goodonly, partial, blocking;
+
+	REQUIRE(VALID_ENTROPY(ent));
+	REQUIRE(data != NULL);
+	REQUIRE(length > 0);
+
+	goodonly = ISC_TF((flags & ISC_ENTROPY_GOODONLY) != 0);
+	partial = ISC_TF((flags & ISC_ENTROPY_PARTIAL) != 0);
+	blocking = ISC_TF((flags & ISC_ENTROPY_BLOCKING) != 0);
+
+	REQUIRE(!partial || returned != NULL);
+
+	LOCK(&ent->lock);
+
+	remain = length;
+	buf = data;
+	total = 0;
+	while (remain != 0) {
+		count = ISC_MIN(remain, RND_ENTROPY_THRESHOLD);
+
+		/*
+		 * If we are extracting good data only, make certain we
+		 * have enough data in our pool for this pass.  If we don't,
+		 * get some, and fail if we can't, and partial returns
+		 * are not ok.
+		 */
+		if (goodonly) {
+			unsigned int fillcount;
+
+			fillcount = ISC_MAX(remain * 8, count * 8);
+
+			/*
+			 * If, however, we have at least THRESHOLD_BITS
+			 * of entropy in the pool, don't block here.  It is
+			 * better to drain the pool once in a while and
+			 * then refill it than it is to constantly keep the
+			 * pool full.
+			 */
+			if (ent->pool.entropy >= THRESHOLD_BITS)
+				fillpool(ent, fillcount, ISC_FALSE);
+			else
+				fillpool(ent, fillcount, blocking);
+
+			/*
+			 * Verify that we got enough entropy to do one
+			 * extraction.  If we didn't, bail.
+			 */
+			if (ent->pool.entropy < THRESHOLD_BITS) {
+				if (!partial)
+					goto zeroize;
+				else
+					goto partial_output;
+			}
+		} else {
+			/*
+			 * If we've extracted half our pool size in bits
+			 * since the last refresh, try to refresh here.
+			 */
+			if (ent->initialized < THRESHOLD_BITS)
+				fillpool(ent, THRESHOLD_BITS, blocking);
+			else
+				fillpool(ent, 0, ISC_FALSE);
+
+			/*
+			 * If we've not initialized with enough good random
+			 * data, seed with our crappy code.
+			 */
+			if (ent->initialized < THRESHOLD_BITS)
+				reseed(ent);
+		}
+
+		isc_sha1_init(&hash);
+		isc_sha1_update(&hash, (void *)(ent->pool.pool),
+				RND_POOLBYTES);
+		isc_sha1_final(&hash, digest);
+
+		/*
+		 * Stir the extracted data (all of it) back into the pool.
+		 */
+		entropypool_adddata(ent, digest, ISC_SHA1_DIGESTLENGTH, 0);
+
+		for (i = 0; i < count; i++)
+			buf[i] = digest[i] ^ digest[i + RND_ENTROPY_THRESHOLD];
+
+		buf += count;
+		remain -= count;
+
+		deltae = count * 8;
+		deltae = ISC_MIN(deltae, ent->pool.entropy);
+		total += deltae;
+		subtract_entropy(ent, deltae);
+		add_pseudo(ent, count * 8);
+	}
+
+ partial_output:
+	memset(digest, 0, sizeof(digest));
+
+	if (returned != NULL)
+		*returned = (length - remain);
+
+	UNLOCK(&ent->lock);
+
+	return (ISC_R_SUCCESS);
+
+ zeroize:
+	/* put the entropy we almost extracted back */
+	add_entropy(ent, total);
+	memset(data, 0, length);
+	memset(digest, 0, sizeof(digest));
+	if (returned != NULL)
+		*returned = 0;
+
+	UNLOCK(&ent->lock);
+
+	return (ISC_R_NOENTROPY);
+}
+
+static void
+isc_entropypool_init(isc_entropypool_t *pool) {
+	pool->cursor = RND_POOLWORDS - 1;
+	pool->entropy = 0;
+	pool->pseudo = 0;
+	pool->rotate = 0;
+	memset(pool->pool, 0, RND_POOLBYTES);
+}
+
+static void
+isc_entropypool_invalidate(isc_entropypool_t *pool) {
+	pool->cursor = 0;
+	pool->entropy = 0;
+	pool->pseudo = 0;
+	pool->rotate = 0;
+	memset(pool->pool, 0, RND_POOLBYTES);
+}
+
+isc_result_t
+isc_entropy_create(isc_mem_t *mctx, isc_entropy_t **entp) {
+	isc_result_t result;
+	isc_entropy_t *ent;
+
+	REQUIRE(mctx != NULL);
+	REQUIRE(entp != NULL && *entp == NULL);
+
+	ent = isc_mem_get(mctx, sizeof(isc_entropy_t));
+	if (ent == NULL)
+		return (ISC_R_NOMEMORY);
+
+	/*
+	 * We need a lock.
+	 */
+	result = isc_mutex_init(&ent->lock);
+	if (result != ISC_R_SUCCESS)
+		goto errout;
+
+	/*
+	 * From here down, no failures will/can occur.
+	 */
+	ISC_LIST_INIT(ent->sources);
+	ent->nextsource = NULL;
+	ent->nsources = 0;
+	ent->mctx = NULL;
+	isc_mem_attach(mctx, &ent->mctx);
+	ent->refcnt = 1;
+	ent->initialized = 0;
+	ent->initcount = 0;
+	ent->magic = ENTROPY_MAGIC;
+
+	isc_entropypool_init(&ent->pool);
+
+	*entp = ent;
+	return (ISC_R_SUCCESS);
+
+ errout:
+	isc_mem_put(mctx, ent, sizeof(isc_entropy_t));
+
+	return (result);
+}
+
+/*!
+ * Requires "ent" be locked.
+ */
+static void
+destroysource(isc_entropysource_t **sourcep) {
+	isc_entropysource_t *source;
+	isc_entropy_t *ent;
+	isc_cbsource_t *cbs;
+
+	source = *sourcep;
+	*sourcep = NULL;
+	ent = source->ent;
+
+	ISC_LIST_UNLINK(ent->sources, source, link);
+	ent->nextsource = NULL;
+	REQUIRE(ent->nsources > 0);
+	ent->nsources--;
+
+	switch (source->type) {
+	case ENTROPY_SOURCETYPE_FILE:
+		if (! source->bad)
+			destroyfilesource(&source->sources.file);
+		break;
+	case ENTROPY_SOURCETYPE_USOCKET:
+		if (! source->bad)
+			destroyusocketsource(&source->sources.usocket);
+		break;
+	case ENTROPY_SOURCETYPE_SAMPLE:
+		samplequeue_release(ent, &source->sources.sample.samplequeue);
+		break;
+	case ENTROPY_SOURCETYPE_CALLBACK:
+		cbs = &source->sources.callback;
+		if (cbs->start_called && cbs->stopfunc != NULL) {
+			cbs->stopfunc(source, cbs->arg);
+			cbs->start_called = ISC_FALSE;
+		}
+		samplequeue_release(ent, &cbs->samplequeue);
+		break;
+	}
+
+	memset(source, 0, sizeof(isc_entropysource_t));
+
+	isc_mem_put(ent->mctx, source, sizeof(isc_entropysource_t));
+}
+
+static inline isc_boolean_t
+destroy_check(isc_entropy_t *ent) {
+	isc_entropysource_t *source;
+
+	if (ent->refcnt > 0)
+		return (ISC_FALSE);
+
+	source = ISC_LIST_HEAD(ent->sources);
+	while (source != NULL) {
+		switch (source->type) {
+		case ENTROPY_SOURCETYPE_FILE:
+		case ENTROPY_SOURCETYPE_USOCKET:
+			break;
+		default:
+			return (ISC_FALSE);
+		}
+		source = ISC_LIST_NEXT(source, link);
+	}
+
+	return (ISC_TRUE);
+}
+
+static void
+destroy(isc_entropy_t **entp) {
+	isc_entropy_t *ent;
+	isc_entropysource_t *source;
+	isc_mem_t *mctx;
+
+	REQUIRE(entp != NULL && *entp != NULL);
+	ent = *entp;
+	*entp = NULL;
+
+	LOCK(&ent->lock);
+
+	REQUIRE(ent->refcnt == 0);
+
+	/*
+	 * Here, detach non-sample sources.
+	 */
+	source = ISC_LIST_HEAD(ent->sources);
+	while (source != NULL) {
+		switch(source->type) {
+		case ENTROPY_SOURCETYPE_FILE:
+		case ENTROPY_SOURCETYPE_USOCKET:
+			destroysource(&source);
+			break;
+		}
+		source = ISC_LIST_HEAD(ent->sources);
+	}
+
+	/*
+	 * If there are other types of sources, we've found a bug.
+	 */
+	REQUIRE(ISC_LIST_EMPTY(ent->sources));
+
+	mctx = ent->mctx;
+
+	isc_entropypool_invalidate(&ent->pool);
+
+	UNLOCK(&ent->lock);
+
+	DESTROYLOCK(&ent->lock);
+
+	memset(ent, 0, sizeof(isc_entropy_t));
+	isc_mem_put(mctx, ent, sizeof(isc_entropy_t));
+	isc_mem_detach(&mctx);
+}
+
+void
+isc_entropy_destroysource(isc_entropysource_t **sourcep) {
+	isc_entropysource_t *source;
+	isc_entropy_t *ent;
+	isc_boolean_t killit;
+
+	REQUIRE(sourcep != NULL);
+	REQUIRE(VALID_SOURCE(*sourcep));
+
+	source = *sourcep;
+	*sourcep = NULL;
+
+	ent = source->ent;
+	REQUIRE(VALID_ENTROPY(ent));
+
+	LOCK(&ent->lock);
+
+	destroysource(&source);
+
+	killit = destroy_check(ent);
+
+	UNLOCK(&ent->lock);
+
+	if (killit)
+		destroy(&ent);
+}
+
+isc_result_t
+isc_entropy_createcallbacksource(isc_entropy_t *ent,
+				 isc_entropystart_t start,
+				 isc_entropyget_t get,
+				 isc_entropystop_t stop,
+				 void *arg,
+				 isc_entropysource_t **sourcep)
+{
+	isc_result_t result;
+	isc_entropysource_t *source;
+	isc_cbsource_t *cbs;
+
+	REQUIRE(VALID_ENTROPY(ent));
+	REQUIRE(get != NULL);
+	REQUIRE(sourcep != NULL && *sourcep == NULL);
+
+	LOCK(&ent->lock);
+
+	source = isc_mem_get(ent->mctx, sizeof(isc_entropysource_t));
+	if (source == NULL) {
+		result = ISC_R_NOMEMORY;
+		goto errout;
+	}
+	source->bad = ISC_FALSE;
+
+	cbs = &source->sources.callback;
+
+	result = samplesource_allocate(ent, &cbs->samplequeue);
+	if (result != ISC_R_SUCCESS)
+		goto errout;
+
+	cbs->start_called = ISC_FALSE;
+	cbs->startfunc = start;
+	cbs->getfunc = get;
+	cbs->stopfunc = stop;
+	cbs->arg = arg;
+
+	/*
+	 * From here down, no failures can occur.
+	 */
+	source->magic = SOURCE_MAGIC;
+	source->type = ENTROPY_SOURCETYPE_CALLBACK;
+	source->ent = ent;
+	source->total = 0;
+	memset(source->name, 0, sizeof(source->name));
+	ISC_LINK_INIT(source, link);
+
+	/*
+	 * Hook it into the entropy system.
+	 */
+	ISC_LIST_APPEND(ent->sources, source, link);
+	ent->nsources++;
+
+	*sourcep = source;
+
+	UNLOCK(&ent->lock);
+	return (ISC_R_SUCCESS);
+
+ errout:
+	if (source != NULL)
+		isc_mem_put(ent->mctx, source, sizeof(isc_entropysource_t));
+
+	UNLOCK(&ent->lock);
+
+	return (result);
+}
+
+void
+isc_entropy_stopcallbacksources(isc_entropy_t *ent) {
+	isc_entropysource_t *source;
+	isc_cbsource_t *cbs;
+
+	REQUIRE(VALID_ENTROPY(ent));
+
+	LOCK(&ent->lock);
+
+	source = ISC_LIST_HEAD(ent->sources);
+	while (source != NULL) {
+		if (source->type == ENTROPY_SOURCETYPE_CALLBACK) {
+			cbs = &source->sources.callback;
+			if (cbs->start_called && cbs->stopfunc != NULL) {
+				cbs->stopfunc(source, cbs->arg);
+				cbs->start_called = ISC_FALSE;
+			}
+		}
+
+		source = ISC_LIST_NEXT(source, link);
+	}
+
+	UNLOCK(&ent->lock);
+}
+
+isc_result_t
+isc_entropy_createsamplesource(isc_entropy_t *ent,
+			       isc_entropysource_t **sourcep)
+{
+	isc_result_t result;
+	isc_entropysource_t *source;
+	sample_queue_t *sq;
+
+	REQUIRE(VALID_ENTROPY(ent));
+	REQUIRE(sourcep != NULL && *sourcep == NULL);
+
+	LOCK(&ent->lock);
+
+	source = isc_mem_get(ent->mctx, sizeof(isc_entropysource_t));
+	if (source == NULL) {
+		result = ISC_R_NOMEMORY;
+		goto errout;
+	}
+
+	sq = &source->sources.sample.samplequeue;
+	result = samplesource_allocate(ent, sq);
+	if (result != ISC_R_SUCCESS)
+		goto errout;
+
+	/*
+	 * From here down, no failures can occur.
+	 */
+	source->magic = SOURCE_MAGIC;
+	source->type = ENTROPY_SOURCETYPE_SAMPLE;
+	source->ent = ent;
+	source->total = 0;
+	memset(source->name, 0, sizeof(source->name));
+	ISC_LINK_INIT(source, link);
+
+	/*
+	 * Hook it into the entropy system.
+	 */
+	ISC_LIST_APPEND(ent->sources, source, link);
+	ent->nsources++;
+
+	*sourcep = source;
+
+	UNLOCK(&ent->lock);
+	return (ISC_R_SUCCESS);
+
+ errout:
+	if (source != NULL)
+		isc_mem_put(ent->mctx, source, sizeof(isc_entropysource_t));
+
+	UNLOCK(&ent->lock);
+
+	return (result);
+}
+
+/*!
+ * Add a sample, and return ISC_R_SUCCESS if the queue has become full,
+ * ISC_R_NOENTROPY if it has space remaining, and ISC_R_NOMORE if the
+ * queue was full when this function was called.
+ */
+static isc_result_t
+addsample(sample_queue_t *sq, isc_uint32_t sample, isc_uint32_t extra) {
+	if (sq->nsamples >= RND_EVENTQSIZE)
+		return (ISC_R_NOMORE);
+
+	sq->samples[sq->nsamples] = sample;
+	sq->extra[sq->nsamples] = extra;
+	sq->nsamples++;
+
+	if (sq->nsamples >= RND_EVENTQSIZE)
+		return (ISC_R_QUEUEFULL);
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_entropy_addsample(isc_entropysource_t *source, isc_uint32_t sample,
+		      isc_uint32_t extra)
+{
+	isc_entropy_t *ent;
+	sample_queue_t *sq;
+	unsigned int entropy;
+	isc_result_t result;
+
+	REQUIRE(VALID_SOURCE(source));
+
+	ent = source->ent;
+
+	LOCK(&ent->lock);
+
+	sq = &source->sources.sample.samplequeue;
+	result = addsample(sq, sample, extra);
+	if (result == ISC_R_QUEUEFULL) {
+		entropy = crunchsamples(ent, sq);
+		add_entropy(ent, entropy);
+	}
+
+	UNLOCK(&ent->lock);
+
+	return (result);
+}
+
+isc_result_t
+isc_entropy_addcallbacksample(isc_entropysource_t *source, isc_uint32_t sample,
+			      isc_uint32_t extra)
+{
+	sample_queue_t *sq;
+	isc_result_t result;
+
+	REQUIRE(VALID_SOURCE(source));
+	REQUIRE(source->type == ENTROPY_SOURCETYPE_CALLBACK);
+
+	sq = &source->sources.callback.samplequeue;
+	result = addsample(sq, sample, extra);
+
+	return (result);
+}
+
+void
+isc_entropy_putdata(isc_entropy_t *ent, void *data, unsigned int length,
+		    isc_uint32_t entropy)
+{
+	REQUIRE(VALID_ENTROPY(ent));
+
+	LOCK(&ent->lock);
+
+	entropypool_adddata(ent, data, length, entropy);
+
+	if (ent->initialized < THRESHOLD_BITS)
+		ent->initialized = THRESHOLD_BITS;
+
+	UNLOCK(&ent->lock);
+}
+
+static void
+dumpstats(isc_entropy_t *ent, FILE *out) {
+	fprintf(out,
+		isc_msgcat_get(isc_msgcat, ISC_MSGSET_ENTROPY,
+			       ISC_MSG_ENTROPYSTATS,
+			       "Entropy pool %p:  refcnt %u cursor %u,"
+			       " rotate %u entropy %u pseudo %u nsources %u"
+			       " nextsource %p initialized %u initcount %u\n"),
+		ent, ent->refcnt,
+		ent->pool.cursor, ent->pool.rotate,
+		ent->pool.entropy, ent->pool.pseudo,
+		ent->nsources, ent->nextsource, ent->initialized,
+		ent->initcount);
+}
+
+/*
+ * This function ignores locking.  Use at your own risk.
+ */
+void
+isc_entropy_stats(isc_entropy_t *ent, FILE *out) {
+	REQUIRE(VALID_ENTROPY(ent));
+
+	LOCK(&ent->lock);
+	dumpstats(ent, out);
+	UNLOCK(&ent->lock);
+}
+
+unsigned int
+isc_entropy_status(isc_entropy_t *ent) {
+	unsigned int estimate;
+
+	LOCK(&ent->lock);
+	estimate = ent->pool.entropy;
+	UNLOCK(&ent->lock);
+
+	return estimate;
+}
+
+void
+isc_entropy_attach(isc_entropy_t *ent, isc_entropy_t **entp) {
+	REQUIRE(VALID_ENTROPY(ent));
+	REQUIRE(entp != NULL && *entp == NULL);
+
+	LOCK(&ent->lock);
+
+	ent->refcnt++;
+	*entp = ent;
+
+	UNLOCK(&ent->lock);
+}
+
+void
+isc_entropy_detach(isc_entropy_t **entp) {
+	isc_entropy_t *ent;
+	isc_boolean_t killit;
+
+	REQUIRE(entp != NULL && VALID_ENTROPY(*entp));
+	ent = *entp;
+	*entp = NULL;
+
+	LOCK(&ent->lock);
+
+	REQUIRE(ent->refcnt > 0);
+	ent->refcnt--;
+
+	killit = destroy_check(ent);
+
+	UNLOCK(&ent->lock);
+
+	if (killit)
+		destroy(&ent);
+}
+
+static isc_result_t
+kbdstart(isc_entropysource_t *source, void *arg, isc_boolean_t blocking) {
+	/*
+	 * The intent of "first" is to provide a warning message only once
+	 * during the run of a program that might try to gather keyboard
+	 * entropy multiple times.
+	 */
+	static isc_boolean_t first = ISC_TRUE;
+
+	UNUSED(arg);
+
+	if (! blocking)
+		return (ISC_R_NOENTROPY);
+
+	if (first) {
+		if (source->warn_keyboard)
+			fprintf(stderr, "You must use the keyboard to create "
+				"entropy, since your system is lacking\n"
+				"/dev/random (or equivalent)\n\n");
+		first = ISC_FALSE;
+	}
+	fprintf(stderr, "start typing:\n");
+
+	return (isc_keyboard_open(&source->kbd));
+}
+
+static void
+kbdstop(isc_entropysource_t *source, void *arg) {
+
+	UNUSED(arg);
+
+	if (! isc_keyboard_canceled(&source->kbd))
+		fprintf(stderr, "stop typing.\r\n");
+
+	(void)isc_keyboard_close(&source->kbd, 3);
+}
+
+static isc_result_t
+kbdget(isc_entropysource_t *source, void *arg, isc_boolean_t blocking) {
+	isc_result_t result;
+	isc_time_t t;
+	isc_uint32_t sample;
+	isc_uint32_t extra;
+	unsigned char c;
+
+	UNUSED(arg);
+
+	if (!blocking)
+		return (ISC_R_NOTBLOCKING);
+
+	result = isc_keyboard_getchar(&source->kbd, &c);
+	if (result != ISC_R_SUCCESS)
+		return (result);
+
+	TIME_NOW(&t);
+
+	sample = isc_time_nanoseconds(&t);
+	extra = c;
+
+	result = isc_entropy_addcallbacksample(source, sample, extra);
+	if (result != ISC_R_SUCCESS) {
+		fprintf(stderr, "\r\n");
+		return (result);
+	}
+
+	fprintf(stderr, ".");
+	fflush(stderr);
+
+	return (result);
+}
+
+isc_result_t
+isc_entropy_usebestsource(isc_entropy_t *ectx, isc_entropysource_t **source,
+			  const char *randomfile, int use_keyboard)
+{
+	isc_result_t result;
+	isc_result_t final_result = ISC_R_NOENTROPY;
+	isc_boolean_t userfile = ISC_TRUE;
+
+	REQUIRE(VALID_ENTROPY(ectx));
+	REQUIRE(source != NULL && *source == NULL);
+	REQUIRE(use_keyboard == ISC_ENTROPY_KEYBOARDYES ||
+		use_keyboard == ISC_ENTROPY_KEYBOARDNO  ||
+		use_keyboard == ISC_ENTROPY_KEYBOARDMAYBE);
+
+#ifdef PATH_RANDOMDEV
+	if (randomfile == NULL) {
+		randomfile = PATH_RANDOMDEV;
+		userfile = ISC_FALSE;
+	}
+#endif
+
+	if (randomfile != NULL && use_keyboard != ISC_ENTROPY_KEYBOARDYES) {
+		result = isc_entropy_createfilesource(ectx, randomfile);
+		if (result == ISC_R_SUCCESS &&
+		    use_keyboard == ISC_ENTROPY_KEYBOARDMAYBE)
+			use_keyboard = ISC_ENTROPY_KEYBOARDNO;
+		if (result != ISC_R_SUCCESS && userfile)
+			return (result);
+
+		final_result = result;
+	}
+
+	if (use_keyboard != ISC_ENTROPY_KEYBOARDNO) {
+		result = isc_entropy_createcallbacksource(ectx, kbdstart,
+							  kbdget, kbdstop,
+							  NULL, source);
+		if (result == ISC_R_SUCCESS)
+			(*source)->warn_keyboard =
+				ISC_TF(use_keyboard ==
+				       ISC_ENTROPY_KEYBOARDMAYBE);
+
+		if (final_result != ISC_R_SUCCESS)
+			final_result = result;
+	}
+
+	/*
+	 * final_result is ISC_R_SUCCESS if at least one source of entropy
+	 * could be started, otherwise it is the error from the most recently
+	 * failed operation (or ISC_R_NOENTROPY if PATH_RANDOMDEV is not
+	 * defined and use_keyboard is ISC_ENTROPY_KEYBOARDNO).
+	 */
+	return (final_result);
+}
diff --git a/src/lib/bind9/error.c b/src/lib/bind9/error.c
new file mode 100644
index 0000000..f5239f9
--- /dev/null
+++ b/src/lib/bind9/error.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: error.c,v 1.21 2007-06-19 23:47:17 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <isc/error.h>
+#include <isc/msgs.h>
+
+/*% Default unexpected callback. */
+static void
+default_unexpected_callback(const char *, int, const char *, va_list)
+     ISC_FORMAT_PRINTF(3, 0);
+
+/*% Default fatal callback. */
+static void
+default_fatal_callback(const char *, int, const char *, va_list)
+     ISC_FORMAT_PRINTF(3, 0);
+
+/*% unexpected_callback */
+static isc_errorcallback_t unexpected_callback = default_unexpected_callback;
+static isc_errorcallback_t fatal_callback = default_fatal_callback;
+
+void
+isc_error_setunexpected(isc_errorcallback_t cb) {
+	if (cb == NULL)
+		unexpected_callback = default_unexpected_callback;
+	else
+		unexpected_callback = cb;
+}
+
+void
+isc_error_setfatal(isc_errorcallback_t cb) {
+	if (cb == NULL)
+		fatal_callback = default_fatal_callback;
+	else
+		fatal_callback = cb;
+}
+
+void
+isc_error_unexpected(const char *file, int line, const char *format, ...) {
+	va_list args;
+
+	va_start(args, format);
+	(unexpected_callback)(file, line, format, args);
+	va_end(args);
+}
+
+void
+isc_error_fatal(const char *file, int line, const char *format, ...) {
+	va_list args;
+
+	va_start(args, format);
+	(fatal_callback)(file, line, format, args);
+	va_end(args);
+	abort();
+}
+
+void
+isc_error_runtimecheck(const char *file, int line, const char *expression) {
+	isc_error_fatal(file, line, "RUNTIME_CHECK(%s) %s", expression,
+			isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+				       ISC_MSG_FAILED, "failed"));
+}
+
+static void
+default_unexpected_callback(const char *file, int line, const char *format,
+			    va_list args)
+{
+	fprintf(stderr, "%s:%d: ", file, line);
+	vfprintf(stderr, format, args);
+	fprintf(stderr, "\n");
+	fflush(stderr);
+}
+
+static void
+default_fatal_callback(const char *file, int line, const char *format,
+		       va_list args)
+{
+	fprintf(stderr, "%s:%d: %s: ", file, line,
+		isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+			       ISC_MSG_FATALERROR, "fatal error"));
+	vfprintf(stderr, format, args);
+	fprintf(stderr, "\n");
+	fflush(stderr);
+}
diff --git a/src/lib/bind9/event.c b/src/lib/bind9/event.c
new file mode 100644
index 0000000..8665160
--- /dev/null
+++ b/src/lib/bind9/event.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: event.c,v 1.21 2007-06-19 23:47:17 tbox Exp $ */
+
+/*!
+ * \file
+ * \author Principal Author: Bob Halley
+ */
+
+#include <config.h>
+
+#include <isc/event.h>
+#include <isc/mem.h>
+#include <isc/util.h>
+
+/***
+ *** Events.
+ ***/
+
+static void
+destroy(isc_event_t *event) {
+	isc_mem_t *mctx = event->ev_destroy_arg;
+
+	isc_mem_put(mctx, event, event->ev_size);
+}
+
+isc_event_t *
+isc_event_allocate(isc_mem_t *mctx, void *sender, isc_eventtype_t type,
+		   isc_taskaction_t action, const void *arg, size_t size)
+{
+	isc_event_t *event;
+	void *deconst_arg;
+
+	REQUIRE(size >= sizeof(struct isc_event));
+	REQUIRE(action != NULL);
+
+	event = isc_mem_get(mctx, size);
+	if (event == NULL)
+		return (NULL);
+
+	/*
+	 * Removing the const attribute from "arg" is the best of two
+	 * evils here.  If the event->ev_arg member is made const, then
+	 * it affects a great many users of the task/event subsystem
+	 * which are not passing in an "arg" which starts its life as
+	 * const.  Changing isc_event_allocate() and isc_task_onshutdown()
+	 * to not have "arg" prototyped as const (which is quite legitimate,
+	 * because neither of those functions modify arg) can cause
+	 * compiler whining anytime someone does want to use a const
+	 * arg that they themselves never modify, such as with
+	 * gcc -Wwrite-strings and using a string "arg".
+	 */
+	DE_CONST(arg, deconst_arg);
+
+	ISC_EVENT_INIT(event, size, 0, NULL, type, action, deconst_arg,
+		       sender, destroy, mctx);
+
+	return (event);
+}
+
+void
+isc_event_free(isc_event_t **eventp) {
+	isc_event_t *event;
+
+	REQUIRE(eventp != NULL);
+	event = *eventp;
+	REQUIRE(event != NULL);
+
+	if (event->ev_destroy != NULL)
+		(event->ev_destroy)(event);
+
+	*eventp = NULL;
+}
diff --git a/src/lib/bind9/fsaccess.c b/src/lib/bind9/fsaccess.c
new file mode 100644
index 0000000..2ddd3db
--- /dev/null
+++ b/src/lib/bind9/fsaccess.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: fsaccess.c,v 1.10 2007-06-19 23:47:17 tbox Exp $ */
+
+/*! \file
+ * \brief
+ * This file contains the OS-independent functionality of the API.
+ */
+#include <isc/fsaccess.h>
+#include <isc/result.h>
+#include <isc/util.h>
+
+/*!
+ * Shorthand.  Maybe ISC__FSACCESS_PERMISSIONBITS should not even be in
+ * <isc/fsaccess.h>.  Could check consistency with sizeof(isc_fsaccess_t)
+ * and the number of bits in each function.
+ */
+#define STEP		(ISC__FSACCESS_PERMISSIONBITS)
+#define GROUP		(STEP)
+#define OTHER		(STEP * 2)
+
+void
+isc_fsaccess_add(int trustee, int permission, isc_fsaccess_t *access) {
+	REQUIRE(trustee <= 0x7);
+	REQUIRE(permission <= 0xFF);
+
+	if ((trustee & ISC_FSACCESS_OWNER) != 0)
+		*access |= permission;
+
+	if ((trustee & ISC_FSACCESS_GROUP) != 0)
+		*access |= (permission << GROUP);
+
+	if ((trustee & ISC_FSACCESS_OTHER) != 0)
+		*access |= (permission << OTHER);
+}
+
+void
+isc_fsaccess_remove(int trustee, int permission, isc_fsaccess_t *access) {
+	REQUIRE(trustee <= 0x7);
+	REQUIRE(permission <= 0xFF);
+
+
+	if ((trustee & ISC_FSACCESS_OWNER) != 0)
+		*access &= ~permission;
+
+	if ((trustee & ISC_FSACCESS_GROUP) != 0)
+		*access &= ~(permission << GROUP);
+
+	if ((trustee & ISC_FSACCESS_OTHER) != 0)
+		*access &= ~(permission << OTHER);
+}
+
+static isc_result_t
+check_bad_bits(isc_fsaccess_t access, isc_boolean_t is_dir) {
+	isc_fsaccess_t bits;
+
+	/*
+	 * Check for disallowed user bits.
+	 */
+	if (is_dir)
+		bits = ISC_FSACCESS_READ |
+		       ISC_FSACCESS_WRITE |
+		       ISC_FSACCESS_EXECUTE;
+	else
+		bits = ISC_FSACCESS_CREATECHILD |
+		       ISC_FSACCESS_ACCESSCHILD |
+		       ISC_FSACCESS_DELETECHILD |
+		       ISC_FSACCESS_LISTDIRECTORY;
+
+	/*
+	 * Set group bad bits.
+	 */
+	bits |= bits << STEP;
+	/*
+	 * Set other bad bits.
+	 */
+	bits |= bits << STEP;
+
+	if ((access & bits) != 0) {
+		if (is_dir)
+			return (ISC_R_NOTFILE);
+		else
+			return (ISC_R_NOTDIRECTORY);
+	}
+
+	return (ISC_R_SUCCESS);
+}
diff --git a/src/lib/bind9/hash.c b/src/lib/bind9/hash.c
new file mode 100644
index 0000000..44975e7
--- /dev/null
+++ b/src/lib/bind9/hash.c
@@ -0,0 +1,404 @@
+/*
+ * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: hash.c,v 1.16 2009-09-01 00:22:28 jinmei Exp $ */
+
+/*! \file
+ * Some portion of this code was derived from universal hash function
+ * libraries of Rice University.
+\section license UH Universal Hashing Library
+
+Copyright ((c)) 2002, Rice University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+    copyright notice, this list of conditions and the following
+    disclaimer in the documentation and/or other materials provided
+    with the distribution.
+
+    * Neither the name of Rice University (RICE) nor the names of its
+    contributors may be used to endorse or promote products derived
+    from this software without specific prior written permission.
+
+
+This software is provided by RICE and the contributors on an "as is"
+basis, without any representations or warranties of any kind, express
+or implied including, but not limited to, representations or
+warranties of non-infringement, merchantability or fitness for a
+particular purpose. In no event shall RICE or contributors be liable
+for any direct, indirect, incidental, special, exemplary, or
+consequential damages (including, but not limited to, procurement of
+substitute goods or services; loss of use, data, or profits; or
+business interruption) however caused and on any theory of liability,
+whether in contract, strict liability, or tort (including negligence
+or otherwise) arising in any way out of the use of this software, even
+if advised of the possibility of such damage.
+*/
+
+#include <config.h>
+
+#include <isc/entropy.h>
+#include <isc/hash.h>
+#include <isc/mem.h>
+#include <isc/magic.h>
+#include <isc/mutex.h>
+#include <isc/once.h>
+#include <isc/random.h>
+#include <isc/refcount.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#define HASH_MAGIC		ISC_MAGIC('H', 'a', 's', 'h')
+#define VALID_HASH(h)		ISC_MAGIC_VALID((h), HASH_MAGIC)
+
+/*%
+ * A large 32-bit prime number that specifies the range of the hash output.
+ */
+#define PRIME32 0xFFFFFFFB              /* 2^32 -  5 */
+
+/*@{*/
+/*%
+ * Types of random seed and hash accumulator.  Perhaps they can be system
+ * dependent.
+ */
+typedef isc_uint32_t hash_accum_t;
+typedef isc_uint16_t hash_random_t;
+/*@}*/
+
+/*% isc hash structure */
+struct isc_hash {
+	unsigned int	magic;
+	isc_mem_t	*mctx;
+	isc_mutex_t	lock;
+	isc_boolean_t	initialized;
+	isc_refcount_t	refcnt;
+	isc_entropy_t	*entropy; /*%< entropy source */
+	unsigned int	limit;	/*%< upper limit of key length */
+	size_t		vectorlen; /*%< size of the vector below */
+	hash_random_t	*rndvector; /*%< random vector for universal hashing */
+};
+
+static isc_mutex_t createlock;
+static isc_once_t once = ISC_ONCE_INIT;
+static isc_hash_t *hash = NULL;
+
+static unsigned char maptolower[] = {
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+	0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+	0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+	0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+	0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+	0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+	0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+	0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+	0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+	0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+	0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+	0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+	0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+	0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+	0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+	0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+	0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+	0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+	0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+	0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+	0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+};
+
+isc_result_t
+isc_hash_ctxcreate(isc_mem_t *mctx, isc_entropy_t *entropy,
+		   unsigned int limit, isc_hash_t **hctxp)
+{
+	isc_result_t result;
+	isc_hash_t *hctx;
+	size_t vlen;
+	hash_random_t *rv;
+	hash_accum_t overflow_limit;
+
+	REQUIRE(mctx != NULL);
+	REQUIRE(hctxp != NULL && *hctxp == NULL);
+
+	/*
+	 * Overflow check.  Since our implementation only does a modulo
+	 * operation at the last stage of hash calculation, the accumulator
+	 * must not overflow.
+	 */
+	overflow_limit =
+		1 << (((sizeof(hash_accum_t) - sizeof(hash_random_t))) * 8);
+	if (overflow_limit < (limit + 1) * 0xff)
+		return (ISC_R_RANGE);
+
+	hctx = isc_mem_get(mctx, sizeof(isc_hash_t));
+	if (hctx == NULL)
+		return (ISC_R_NOMEMORY);
+
+	vlen = sizeof(hash_random_t) * (limit + 1);
+	rv = isc_mem_get(mctx, vlen);
+	if (rv == NULL) {
+		result = ISC_R_NOMEMORY;
+		goto errout;
+	}
+
+	/*
+	 * We need a lock.
+	 */
+	result = isc_mutex_init(&hctx->lock);
+	if (result != ISC_R_SUCCESS)
+		goto errout;
+
+	/*
+	 * From here down, no failures will/can occur.
+	 */
+	hctx->magic = HASH_MAGIC;
+	hctx->mctx = NULL;
+	isc_mem_attach(mctx, &hctx->mctx);
+	hctx->initialized = ISC_FALSE;
+	result = isc_refcount_init(&hctx->refcnt, 1);
+	if (result != ISC_R_SUCCESS)
+		goto cleanup_lock;
+	hctx->entropy = NULL;
+	hctx->limit = limit;
+	hctx->vectorlen = vlen;
+	hctx->rndvector = rv;
+
+#ifdef BIND9
+	if (entropy != NULL)
+		isc_entropy_attach(entropy, &hctx->entropy);
+#else
+	UNUSED(entropy);
+#endif
+
+	*hctxp = hctx;
+	return (ISC_R_SUCCESS);
+
+ cleanup_lock:
+	DESTROYLOCK(&hctx->lock);
+ errout:
+	isc_mem_put(mctx, hctx, sizeof(isc_hash_t));
+	if (rv != NULL)
+		isc_mem_put(mctx, rv, vlen);
+
+	return (result);
+}
+
+static void
+initialize_lock(void) {
+	RUNTIME_CHECK(isc_mutex_init(&createlock) == ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_hash_create(isc_mem_t *mctx, isc_entropy_t *entropy, size_t limit) {
+	isc_result_t result = ISC_R_SUCCESS;
+
+	REQUIRE(mctx != NULL);
+	INSIST(hash == NULL);
+
+	RUNTIME_CHECK(isc_once_do(&once, initialize_lock) == ISC_R_SUCCESS);
+
+	LOCK(&createlock);
+
+	if (hash == NULL)
+		result = isc_hash_ctxcreate(mctx, entropy, limit, &hash);
+
+	UNLOCK(&createlock);
+
+	return (result);
+}
+
+void
+isc_hash_ctxinit(isc_hash_t *hctx) {
+	LOCK(&hctx->lock);
+
+	if (hctx->initialized == ISC_TRUE)
+		goto out;
+
+	if (hctx->entropy) {
+#ifdef BIND9
+		isc_result_t result;
+
+		result = isc_entropy_getdata(hctx->entropy,
+					     hctx->rndvector, hctx->vectorlen,
+					     NULL, 0);
+		INSIST(result == ISC_R_SUCCESS);
+#else
+		INSIST(0);
+#endif
+	} else {
+		isc_uint32_t pr;
+		unsigned int i, copylen;
+		unsigned char *p;
+
+		p = (unsigned char *)hctx->rndvector;
+		for (i = 0; i < hctx->vectorlen; i += copylen, p += copylen) {
+			isc_random_get(&pr);
+			if (i + sizeof(pr) <= hctx->vectorlen)
+				copylen = sizeof(pr);
+			else
+				copylen = hctx->vectorlen - i;
+
+			memcpy(p, &pr, copylen);
+		}
+		INSIST(p == (unsigned char *)hctx->rndvector +
+		       hctx->vectorlen);
+	}
+
+	hctx->initialized = ISC_TRUE;
+
+ out:
+	UNLOCK(&hctx->lock);
+}
+
+void
+isc_hash_init() {
+	INSIST(hash != NULL && VALID_HASH(hash));
+
+	isc_hash_ctxinit(hash);
+}
+
+void
+isc_hash_ctxattach(isc_hash_t *hctx, isc_hash_t **hctxp) {
+	REQUIRE(VALID_HASH(hctx));
+	REQUIRE(hctxp != NULL && *hctxp == NULL);
+
+	isc_refcount_increment(&hctx->refcnt, NULL);
+	*hctxp = hctx;
+}
+
+static void
+destroy(isc_hash_t **hctxp) {
+	isc_hash_t *hctx;
+	isc_mem_t *mctx;
+	unsigned char canary0[4], canary1[4];
+
+	REQUIRE(hctxp != NULL && *hctxp != NULL);
+	hctx = *hctxp;
+	*hctxp = NULL;
+
+	LOCK(&hctx->lock);
+
+	isc_refcount_destroy(&hctx->refcnt);
+
+	mctx = hctx->mctx;
+#ifdef BIND9
+	if (hctx->entropy != NULL)
+		isc_entropy_detach(&hctx->entropy);
+#endif
+	if (hctx->rndvector != NULL)
+		isc_mem_put(mctx, hctx->rndvector, hctx->vectorlen);
+
+	UNLOCK(&hctx->lock);
+
+	DESTROYLOCK(&hctx->lock);
+
+	memcpy(canary0, hctx + 1, sizeof(canary0));
+	memset(hctx, 0, sizeof(isc_hash_t));
+	memcpy(canary1, hctx + 1, sizeof(canary1));
+	INSIST(memcmp(canary0, canary1, sizeof(canary0)) == 0);
+	isc_mem_put(mctx, hctx, sizeof(isc_hash_t));
+	isc_mem_detach(&mctx);
+}
+
+void
+isc_hash_ctxdetach(isc_hash_t **hctxp) {
+	isc_hash_t *hctx;
+	unsigned int refs;
+
+	REQUIRE(hctxp != NULL && VALID_HASH(*hctxp));
+	hctx = *hctxp;
+
+	isc_refcount_decrement(&hctx->refcnt, &refs);
+	if (refs == 0)
+		destroy(&hctx);
+
+	*hctxp = NULL;
+}
+
+void
+isc_hash_destroy() {
+	unsigned int refs;
+
+	INSIST(hash != NULL && VALID_HASH(hash));
+
+	isc_refcount_decrement(&hash->refcnt, &refs);
+	INSIST(refs == 0);
+
+	destroy(&hash);
+}
+
+static inline unsigned int
+hash_calc(isc_hash_t *hctx, const unsigned char *key, unsigned int keylen,
+	  isc_boolean_t case_sensitive)
+{
+	hash_accum_t partial_sum = 0;
+	hash_random_t *p = hctx->rndvector;
+	unsigned int i = 0;
+
+	/* Make it sure that the hash context is initialized. */
+	if (hctx->initialized == ISC_FALSE)
+		isc_hash_ctxinit(hctx);
+
+	if (case_sensitive) {
+		for (i = 0; i < keylen; i++)
+			partial_sum += key[i] * (hash_accum_t)p[i];
+	} else {
+		for (i = 0; i < keylen; i++)
+			partial_sum += maptolower[key[i]] * (hash_accum_t)p[i];
+	}
+
+	partial_sum += p[i];
+
+	return ((unsigned int)(partial_sum % PRIME32));
+}
+
+unsigned int
+isc_hash_ctxcalc(isc_hash_t *hctx, const unsigned char *key,
+		 unsigned int keylen, isc_boolean_t case_sensitive)
+{
+	REQUIRE(hctx != NULL && VALID_HASH(hctx));
+	REQUIRE(keylen <= hctx->limit);
+
+	return (hash_calc(hctx, key, keylen, case_sensitive));
+}
+
+unsigned int
+isc_hash_calc(const unsigned char *key, unsigned int keylen,
+	      isc_boolean_t case_sensitive)
+{
+	INSIST(hash != NULL && VALID_HASH(hash));
+	REQUIRE(keylen <= hash->limit);
+
+	return (hash_calc(hash, key, keylen, case_sensitive));
+}
diff --git a/src/lib/bind9/heap.c b/src/lib/bind9/heap.c
new file mode 100644
index 0000000..eeef7f7
--- /dev/null
+++ b/src/lib/bind9/heap.c
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2004-2007, 2010, 2011  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1997-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: heap.c,v 1.39.150.2 2011-03-03 23:47:09 tbox Exp $ */
+
+/*! \file
+ * Heap implementation of priority queues adapted from the following:
+ *
+ *	\li "Introduction to Algorithms," Cormen, Leiserson, and Rivest,
+ *	MIT Press / McGraw Hill, 1990, ISBN 0-262-03141-8, chapter 7.
+ *
+ *	\li "Algorithms," Second Edition, Sedgewick, Addison-Wesley, 1988,
+ *	ISBN 0-201-06673-4, chapter 11.
+ */
+
+#include <config.h>
+
+#include <isc/heap.h>
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/string.h>		/* Required for memcpy. */
+#include <isc/util.h>
+
+/*@{*/
+/*%
+ * Note: to make heap_parent and heap_left easy to compute, the first
+ * element of the heap array is not used; i.e. heap subscripts are 1-based,
+ * not 0-based.  The parent is index/2, and the left-child is index*2.
+ * The right child is index*2+1.
+ */
+#define heap_parent(i)			((i) >> 1)
+#define heap_left(i)			((i) << 1)
+/*@}*/
+
+#define SIZE_INCREMENT			1024
+
+#define HEAP_MAGIC			ISC_MAGIC('H', 'E', 'A', 'P')
+#define VALID_HEAP(h)			ISC_MAGIC_VALID(h, HEAP_MAGIC)
+
+/*%
+ * When the heap is in a consistent state, the following invariant
+ * holds true: for every element i > 1, heap_parent(i) has a priority
+ * higher than or equal to that of i.
+ */
+#define HEAPCONDITION(i) ((i) == 1 || \
+			  ! heap->compare(heap->array[(i)], \
+					  heap->array[heap_parent(i)]))
+
+/*% ISC heap structure. */
+struct isc_heap {
+	unsigned int			magic;
+	isc_mem_t *			mctx;
+	unsigned int			size;
+	unsigned int			size_increment;
+	unsigned int			last;
+	void				**array;
+	isc_heapcompare_t		compare;
+	isc_heapindex_t			index;
+};
+
+isc_result_t
+isc_heap_create(isc_mem_t *mctx, isc_heapcompare_t compare,
+		isc_heapindex_t index, unsigned int size_increment,
+		isc_heap_t **heapp)
+{
+	isc_heap_t *heap;
+
+	REQUIRE(heapp != NULL && *heapp == NULL);
+	REQUIRE(compare != NULL);
+
+	heap = isc_mem_get(mctx, sizeof(*heap));
+	if (heap == NULL)
+		return (ISC_R_NOMEMORY);
+	heap->magic = HEAP_MAGIC;
+	heap->size = 0;
+	heap->mctx = NULL;
+	isc_mem_attach(mctx, &heap->mctx);
+	if (size_increment == 0)
+		heap->size_increment = SIZE_INCREMENT;
+	else
+		heap->size_increment = size_increment;
+	heap->last = 0;
+	heap->array = NULL;
+	heap->compare = compare;
+	heap->index = index;
+
+	*heapp = heap;
+
+	return (ISC_R_SUCCESS);
+}
+
+void
+isc_heap_destroy(isc_heap_t **heapp) {
+	isc_heap_t *heap;
+
+	REQUIRE(heapp != NULL);
+	heap = *heapp;
+	REQUIRE(VALID_HEAP(heap));
+
+	if (heap->array != NULL)
+		isc_mem_put(heap->mctx, heap->array,
+			    heap->size * sizeof(void *));
+	heap->magic = 0;
+	isc_mem_putanddetach(&heap->mctx, heap, sizeof(*heap));
+
+	*heapp = NULL;
+}
+
+static isc_boolean_t
+resize(isc_heap_t *heap) {
+	void **new_array;
+	size_t new_size;
+
+	REQUIRE(VALID_HEAP(heap));
+
+	new_size = heap->size + heap->size_increment;
+	new_array = isc_mem_get(heap->mctx, new_size * sizeof(void *));
+	if (new_array == NULL)
+		return (ISC_FALSE);
+	if (heap->array != NULL) {
+		memcpy(new_array, heap->array, heap->size * sizeof(void *));
+		isc_mem_put(heap->mctx, heap->array,
+			    heap->size * sizeof(void *));
+	}
+	heap->size = new_size;
+	heap->array = new_array;
+
+	return (ISC_TRUE);
+}
+
+static void
+float_up(isc_heap_t *heap, unsigned int i, void *elt) {
+	unsigned int p;
+
+	for (p = heap_parent(i) ;
+	     i > 1 && heap->compare(elt, heap->array[p]) ;
+	     i = p, p = heap_parent(i)) {
+		heap->array[i] = heap->array[p];
+		if (heap->index != NULL)
+			(heap->index)(heap->array[i], i);
+	}
+	heap->array[i] = elt;
+	if (heap->index != NULL)
+		(heap->index)(heap->array[i], i);
+
+	INSIST(HEAPCONDITION(i));
+}
+
+static void
+sink_down(isc_heap_t *heap, unsigned int i, void *elt) {
+	unsigned int j, size, half_size;
+	size = heap->last;
+	half_size = size / 2;
+	while (i <= half_size) {
+		/* Find the smallest of the (at most) two children. */
+		j = heap_left(i);
+		if (j < size && heap->compare(heap->array[j+1],
+					      heap->array[j]))
+			j++;
+		if (heap->compare(elt, heap->array[j]))
+			break;
+		heap->array[i] = heap->array[j];
+		if (heap->index != NULL)
+			(heap->index)(heap->array[i], i);
+		i = j;
+	}
+	heap->array[i] = elt;
+	if (heap->index != NULL)
+		(heap->index)(heap->array[i], i);
+
+	INSIST(HEAPCONDITION(i));
+}
+
+isc_result_t
+isc_heap_insert(isc_heap_t *heap, void *elt) {
+	unsigned int new_last;
+
+	REQUIRE(VALID_HEAP(heap));
+
+	new_last = heap->last + 1;
+	RUNTIME_CHECK(new_last > 0); /* overflow check */
+	if (new_last >= heap->size && !resize(heap))
+		return (ISC_R_NOMEMORY);
+	heap->last = new_last;
+
+	float_up(heap, new_last, elt);
+
+	return (ISC_R_SUCCESS);
+}
+
+void
+isc_heap_delete(isc_heap_t *heap, unsigned int index) {
+	void *elt;
+	isc_boolean_t less;
+
+	REQUIRE(VALID_HEAP(heap));
+	REQUIRE(index >= 1 && index <= heap->last);
+
+	if (index == heap->last) {
+		heap->array[heap->last] = NULL;
+		heap->last--;
+	} else {
+		elt = heap->array[heap->last];
+		heap->array[heap->last] = NULL;
+		heap->last--;
+
+		less = heap->compare(elt, heap->array[index]);
+		heap->array[index] = elt;
+		if (less)
+			float_up(heap, index, heap->array[index]);
+		else
+			sink_down(heap, index, heap->array[index]);
+	}
+}
+
+void
+isc_heap_increased(isc_heap_t *heap, unsigned int index) {
+	REQUIRE(VALID_HEAP(heap));
+	REQUIRE(index >= 1 && index <= heap->last);
+
+	float_up(heap, index, heap->array[index]);
+}
+
+void
+isc_heap_decreased(isc_heap_t *heap, unsigned int index) {
+	REQUIRE(VALID_HEAP(heap));
+	REQUIRE(index >= 1 && index <= heap->last);
+
+	sink_down(heap, index, heap->array[index]);
+}
+
+void *
+isc_heap_element(isc_heap_t *heap, unsigned int index) {
+	REQUIRE(VALID_HEAP(heap));
+	REQUIRE(index >= 1);
+
+	if (index <= heap->last)
+		return (heap->array[index]);
+	return (NULL);
+}
+
+void
+isc_heap_foreach(isc_heap_t *heap, isc_heapaction_t action, void *uap) {
+	unsigned int i;
+
+	REQUIRE(VALID_HEAP(heap));
+	REQUIRE(action != NULL);
+
+	for (i = 1 ; i <= heap->last ; i++)
+		(action)(heap->array[i], uap);
+}
diff --git a/src/lib/bind9/hex.c b/src/lib/bind9/hex.c
new file mode 100644
index 0000000..3e01013
--- /dev/null
+++ b/src/lib/bind9/hex.c
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2008  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: hex.c,v 1.20 2008-09-25 04:02:39 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <ctype.h>
+
+#include <isc/buffer.h>
+#include <isc/hex.h>
+#include <isc/lex.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#define RETERR(x) do { \
+	isc_result_t _r = (x); \
+	if (_r != ISC_R_SUCCESS) \
+		return (_r); \
+	} while (0)
+
+
+/*
+ * BEW: These static functions are copied from lib/dns/rdata.c.
+ */
+static isc_result_t
+str_totext(const char *source, isc_buffer_t *target);
+
+static isc_result_t
+mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length);
+
+static const char hex[] = "0123456789ABCDEF";
+
+isc_result_t
+isc_hex_totext(isc_region_t *source, int wordlength,
+	       const char *wordbreak, isc_buffer_t *target)
+{
+	char buf[3];
+	unsigned int loops = 0;
+
+	if (wordlength < 2)
+		wordlength = 2;
+
+	memset(buf, 0, sizeof(buf));
+	while (source->length > 0) {
+		buf[0] = hex[(source->base[0] >> 4) & 0xf];
+		buf[1] = hex[(source->base[0]) & 0xf];
+		RETERR(str_totext(buf, target));
+		isc_region_consume(source, 1);
+
+		loops++;
+		if (source->length != 0 &&
+		    (int)((loops + 1) * 2) >= wordlength)
+		{
+			loops = 0;
+			RETERR(str_totext(wordbreak, target));
+		}
+	}
+	return (ISC_R_SUCCESS);
+}
+
+/*%
+ * State of a hex decoding process in progress.
+ */
+typedef struct {
+	int length;		/*%< Desired length of binary data or -1 */
+	isc_buffer_t *target;	/*%< Buffer for resulting binary data */
+	int digits;		/*%< Number of buffered hex digits */
+	int val[2];
+} hex_decode_ctx_t;
+
+static inline void
+hex_decode_init(hex_decode_ctx_t *ctx, int length, isc_buffer_t *target)
+{
+	ctx->digits = 0;
+	ctx->length = length;
+	ctx->target = target;
+}
+
+static inline isc_result_t
+hex_decode_char(hex_decode_ctx_t *ctx, int c) {
+	char *s;
+
+	if ((s = strchr(hex, toupper(c))) == NULL)
+		return (ISC_R_BADHEX);
+	ctx->val[ctx->digits++] = s - hex;
+	if (ctx->digits == 2) {
+		unsigned char num;
+
+		num = (ctx->val[0] << 4) + (ctx->val[1]);
+		RETERR(mem_tobuffer(ctx->target, &num, 1));
+		if (ctx->length >= 0) {
+			if (ctx->length == 0)
+				return (ISC_R_BADHEX);
+			else
+				ctx->length -= 1;
+		}
+		ctx->digits = 0;
+	}
+	return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+hex_decode_finish(hex_decode_ctx_t *ctx) {
+	if (ctx->length > 0)
+		return (ISC_R_UNEXPECTEDEND);
+	if (ctx->digits != 0)
+		return (ISC_R_BADHEX);
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_hex_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length) {
+	hex_decode_ctx_t ctx;
+	isc_textregion_t *tr;
+	isc_token_t token;
+	isc_boolean_t eol;
+
+	hex_decode_init(&ctx, length, target);
+
+	while (ctx.length != 0) {
+		unsigned int i;
+
+		if (length > 0)
+			eol = ISC_FALSE;
+		else
+			eol = ISC_TRUE;
+		RETERR(isc_lex_getmastertoken(lexer, &token,
+					      isc_tokentype_string, eol));
+		if (token.type != isc_tokentype_string)
+			break;
+		tr = &token.value.as_textregion;
+		for (i = 0; i < tr->length; i++)
+			RETERR(hex_decode_char(&ctx, tr->base[i]));
+	}
+	if (ctx.length < 0)
+		isc_lex_ungettoken(lexer, &token);
+	RETERR(hex_decode_finish(&ctx));
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_hex_decodestring(const char *cstr, isc_buffer_t *target) {
+	hex_decode_ctx_t ctx;
+
+	hex_decode_init(&ctx, -1, target);
+	for (;;) {
+		int c = *cstr++;
+		if (c == '\0')
+			break;
+		if (c == ' ' || c == '\t' || c == '\n' || c== '\r')
+			continue;
+		RETERR(hex_decode_char(&ctx, c));
+	}
+	RETERR(hex_decode_finish(&ctx));
+	return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+str_totext(const char *source, isc_buffer_t *target) {
+	unsigned int l;
+	isc_region_t region;
+
+	isc_buffer_availableregion(target, &region);
+	l = strlen(source);
+
+	if (l > region.length)
+		return (ISC_R_NOSPACE);
+
+	memcpy(region.base, source, l);
+	isc_buffer_add(target, l);
+	return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length) {
+	isc_region_t tr;
+
+	isc_buffer_availableregion(target, &tr);
+	if (length > tr.length)
+		return (ISC_R_NOSPACE);
+	memcpy(tr.base, base, length);
+	isc_buffer_add(target, length);
+	return (ISC_R_SUCCESS);
+}
diff --git a/src/lib/bind9/hmacmd5.c b/src/lib/bind9/hmacmd5.c
new file mode 100644
index 0000000..10e87c9
--- /dev/null
+++ b/src/lib/bind9/hmacmd5.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: hmacmd5.c,v 1.16 2009-02-06 23:47:42 tbox Exp $ */
+
+/*! \file
+ * This code implements the HMAC-MD5 keyed hash algorithm
+ * described in RFC2104.
+ */
+
+#include "config.h"
+
+#include <isc/assertions.h>
+#include <isc/hmacmd5.h>
+#include <isc/md5.h>
+#include <isc/platform.h>
+#include <isc/string.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#ifdef ISC_PLATFORM_OPENSSLHASH
+
+void
+isc_hmacmd5_init(isc_hmacmd5_t *ctx, const unsigned char *key,
+		 unsigned int len)
+{
+	HMAC_Init(ctx, (const void *) key, (int) len, EVP_md5());
+}
+
+void
+isc_hmacmd5_invalidate(isc_hmacmd5_t *ctx) {
+	HMAC_CTX_cleanup(ctx);
+}
+
+void
+isc_hmacmd5_update(isc_hmacmd5_t *ctx, const unsigned char *buf,
+		   unsigned int len)
+{
+	HMAC_Update(ctx, buf, (int) len);
+}
+
+void
+isc_hmacmd5_sign(isc_hmacmd5_t *ctx, unsigned char *digest) {
+	HMAC_Final(ctx, digest, NULL);
+	HMAC_CTX_cleanup(ctx);
+}
+
+#else
+
+#define PADLEN 64
+#define IPAD 0x36
+#define OPAD 0x5C
+
+/*!
+ * Start HMAC-MD5 process.  Initialize an md5 context and digest the key.
+ */
+void
+isc_hmacmd5_init(isc_hmacmd5_t *ctx, const unsigned char *key,
+		 unsigned int len)
+{
+	unsigned char ipad[PADLEN];
+	int i;
+
+	memset(ctx->key, 0, sizeof(ctx->key));
+	if (len > sizeof(ctx->key)) {
+		isc_md5_t md5ctx;
+		isc_md5_init(&md5ctx);
+		isc_md5_update(&md5ctx, key, len);
+		isc_md5_final(&md5ctx, ctx->key);
+	} else
+		memcpy(ctx->key, key, len);
+
+	isc_md5_init(&ctx->md5ctx);
+	memset(ipad, IPAD, sizeof(ipad));
+	for (i = 0; i < PADLEN; i++)
+		ipad[i] ^= ctx->key[i];
+	isc_md5_update(&ctx->md5ctx, ipad, sizeof(ipad));
+}
+
+void
+isc_hmacmd5_invalidate(isc_hmacmd5_t *ctx) {
+	isc_md5_invalidate(&ctx->md5ctx);
+	memset(ctx->key, 0, sizeof(ctx->key));
+}
+
+/*!
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void
+isc_hmacmd5_update(isc_hmacmd5_t *ctx, const unsigned char *buf,
+		   unsigned int len)
+{
+	isc_md5_update(&ctx->md5ctx, buf, len);
+}
+
+/*!
+ * Compute signature - finalize MD5 operation and reapply MD5.
+ */
+void
+isc_hmacmd5_sign(isc_hmacmd5_t *ctx, unsigned char *digest) {
+	unsigned char opad[PADLEN];
+	int i;
+
+	isc_md5_final(&ctx->md5ctx, digest);
+
+	memset(opad, OPAD, sizeof(opad));
+	for (i = 0; i < PADLEN; i++)
+		opad[i] ^= ctx->key[i];
+
+	isc_md5_init(&ctx->md5ctx);
+	isc_md5_update(&ctx->md5ctx, opad, sizeof(opad));
+	isc_md5_update(&ctx->md5ctx, digest, ISC_MD5_DIGESTLENGTH);
+	isc_md5_final(&ctx->md5ctx, digest);
+	isc_hmacmd5_invalidate(ctx);
+}
+#endif /* !ISC_PLATFORM_OPENSSLHASH */
+
+/*!
+ * Verify signature - finalize MD5 operation and reapply MD5, then
+ * compare to the supplied digest.
+ */
+isc_boolean_t
+isc_hmacmd5_verify(isc_hmacmd5_t *ctx, unsigned char *digest) {
+	return (isc_hmacmd5_verify2(ctx, digest, ISC_MD5_DIGESTLENGTH));
+}
+
+isc_boolean_t
+isc_hmacmd5_verify2(isc_hmacmd5_t *ctx, unsigned char *digest, size_t len) {
+	unsigned char newdigest[ISC_MD5_DIGESTLENGTH];
+
+	REQUIRE(len <= ISC_MD5_DIGESTLENGTH);
+	isc_hmacmd5_sign(ctx, newdigest);
+	return (ISC_TF(memcmp(digest, newdigest, len) == 0));
+}
diff --git a/src/lib/bind9/hmacsha.c b/src/lib/bind9/hmacsha.c
new file mode 100644
index 0000000..125672d
--- /dev/null
+++ b/src/lib/bind9/hmacsha.c
@@ -0,0 +1,599 @@
+/*
+ * Copyright (C) 2005-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: hmacsha.c,v 1.10 2009-02-06 23:47:42 tbox Exp $ */
+
+/*
+ * This code implements the HMAC-SHA1, HMAC-SHA224, HMAC-SHA256, HMAC-SHA384
+ * and HMAC-SHA512 keyed hash algorithm described in RFC 2104 and
+ * draft-ietf-dnsext-tsig-sha-01.txt.
+ */
+
+#include "config.h"
+
+#include <isc/assertions.h>
+#include <isc/hmacsha.h>
+#include <isc/platform.h>
+#include <isc/sha1.h>
+#include <isc/sha2.h>
+#include <isc/string.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#ifdef ISC_PLATFORM_OPENSSLHASH
+
+void
+isc_hmacsha1_init(isc_hmacsha1_t *ctx, const unsigned char *key,
+		  unsigned int len)
+{
+	HMAC_Init(ctx, (const void *) key, (int) len, EVP_sha1());
+}
+
+void
+isc_hmacsha1_invalidate(isc_hmacsha1_t *ctx) {
+	HMAC_CTX_cleanup(ctx);
+}
+
+void
+isc_hmacsha1_update(isc_hmacsha1_t *ctx, const unsigned char *buf,
+		   unsigned int len)
+{
+	HMAC_Update(ctx, buf, (int) len);
+}
+
+void
+isc_hmacsha1_sign(isc_hmacsha1_t *ctx, unsigned char *digest, size_t len) {
+	unsigned char newdigest[ISC_SHA1_DIGESTLENGTH];
+
+	REQUIRE(len <= ISC_SHA1_DIGESTLENGTH);
+
+	HMAC_Final(ctx, newdigest, NULL);
+	HMAC_CTX_cleanup(ctx);
+	memcpy(digest, newdigest, len);
+	memset(newdigest, 0, sizeof(newdigest));
+}
+
+void
+isc_hmacsha224_init(isc_hmacsha224_t *ctx, const unsigned char *key,
+		    unsigned int len)
+{
+	HMAC_Init(ctx, (const void *) key, (int) len, EVP_sha224());
+}
+
+void
+isc_hmacsha224_invalidate(isc_hmacsha224_t *ctx) {
+	HMAC_CTX_cleanup(ctx);
+}
+
+void
+isc_hmacsha224_update(isc_hmacsha224_t *ctx, const unsigned char *buf,
+		   unsigned int len)
+{
+	HMAC_Update(ctx, buf, (int) len);
+}
+
+void
+isc_hmacsha224_sign(isc_hmacsha224_t *ctx, unsigned char *digest, size_t len) {
+	unsigned char newdigest[ISC_SHA224_DIGESTLENGTH];
+
+	REQUIRE(len <= ISC_SHA224_DIGESTLENGTH);
+
+	HMAC_Final(ctx, newdigest, NULL);
+	HMAC_CTX_cleanup(ctx);
+	memcpy(digest, newdigest, len);
+	memset(newdigest, 0, sizeof(newdigest));
+}
+
+void
+isc_hmacsha256_init(isc_hmacsha256_t *ctx, const unsigned char *key,
+		    unsigned int len)
+{
+	HMAC_Init(ctx, (const void *) key, (int) len, EVP_sha256());
+}
+
+void
+isc_hmacsha256_invalidate(isc_hmacsha256_t *ctx) {
+	HMAC_CTX_cleanup(ctx);
+}
+
+void
+isc_hmacsha256_update(isc_hmacsha256_t *ctx, const unsigned char *buf,
+		   unsigned int len)
+{
+	HMAC_Update(ctx, buf, (int) len);
+}
+
+void
+isc_hmacsha256_sign(isc_hmacsha256_t *ctx, unsigned char *digest, size_t len) {
+	unsigned char newdigest[ISC_SHA256_DIGESTLENGTH];
+
+	REQUIRE(len <= ISC_SHA256_DIGESTLENGTH);
+
+	HMAC_Final(ctx, newdigest, NULL);
+	HMAC_CTX_cleanup(ctx);
+	memcpy(digest, newdigest, len);
+	memset(newdigest, 0, sizeof(newdigest));
+}
+
+void
+isc_hmacsha384_init(isc_hmacsha384_t *ctx, const unsigned char *key,
+		    unsigned int len)
+{
+	HMAC_Init(ctx, (const void *) key, (int) len, EVP_sha384());
+}
+
+void
+isc_hmacsha384_invalidate(isc_hmacsha384_t *ctx) {
+	HMAC_CTX_cleanup(ctx);
+}
+
+void
+isc_hmacsha384_update(isc_hmacsha384_t *ctx, const unsigned char *buf,
+		   unsigned int len)
+{
+	HMAC_Update(ctx, buf, (int) len);
+}
+
+void
+isc_hmacsha384_sign(isc_hmacsha384_t *ctx, unsigned char *digest, size_t len) {
+	unsigned char newdigest[ISC_SHA384_DIGESTLENGTH];
+
+	REQUIRE(len <= ISC_SHA384_DIGESTLENGTH);
+
+	HMAC_Final(ctx, newdigest, NULL);
+	HMAC_CTX_cleanup(ctx);
+	memcpy(digest, newdigest, len);
+	memset(newdigest, 0, sizeof(newdigest));
+}
+
+void
+isc_hmacsha512_init(isc_hmacsha512_t *ctx, const unsigned char *key,
+		    unsigned int len)
+{
+	HMAC_Init(ctx, (const void *) key, (int) len, EVP_sha512());
+}
+
+void
+isc_hmacsha512_invalidate(isc_hmacsha512_t *ctx) {
+	HMAC_CTX_cleanup(ctx);
+}
+
+void
+isc_hmacsha512_update(isc_hmacsha512_t *ctx, const unsigned char *buf,
+		   unsigned int len)
+{
+	HMAC_Update(ctx, buf, (int) len);
+}
+
+void
+isc_hmacsha512_sign(isc_hmacsha512_t *ctx, unsigned char *digest, size_t len) {
+	unsigned char newdigest[ISC_SHA512_DIGESTLENGTH];
+
+	REQUIRE(len <= ISC_SHA512_DIGESTLENGTH);
+
+	HMAC_Final(ctx, newdigest, NULL);
+	HMAC_CTX_cleanup(ctx);
+	memcpy(digest, newdigest, len);
+	memset(newdigest, 0, sizeof(newdigest));
+}
+
+#else
+
+#define IPAD 0x36
+#define OPAD 0x5C
+
+/*
+ * Start HMAC-SHA1 process.  Initialize an sha1 context and digest the key.
+ */
+void
+isc_hmacsha1_init(isc_hmacsha1_t *ctx, const unsigned char *key,
+		  unsigned int len)
+{
+	unsigned char ipad[ISC_SHA1_BLOCK_LENGTH];
+	unsigned int i;
+
+	memset(ctx->key, 0, sizeof(ctx->key));
+	if (len > sizeof(ctx->key)) {
+		isc_sha1_t sha1ctx;
+		isc_sha1_init(&sha1ctx);
+		isc_sha1_update(&sha1ctx, key, len);
+		isc_sha1_final(&sha1ctx, ctx->key);
+	} else
+		memcpy(ctx->key, key, len);
+
+	isc_sha1_init(&ctx->sha1ctx);
+	memset(ipad, IPAD, sizeof(ipad));
+	for (i = 0; i < ISC_SHA1_BLOCK_LENGTH; i++)
+		ipad[i] ^= ctx->key[i];
+	isc_sha1_update(&ctx->sha1ctx, ipad, sizeof(ipad));
+}
+
+void
+isc_hmacsha1_invalidate(isc_hmacsha1_t *ctx) {
+	isc_sha1_invalidate(&ctx->sha1ctx);
+	memset(ctx->key, 0, sizeof(ctx->key));
+	memset(ctx, 0, sizeof(ctx));
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void
+isc_hmacsha1_update(isc_hmacsha1_t *ctx, const unsigned char *buf,
+		   unsigned int len)
+{
+	isc_sha1_update(&ctx->sha1ctx, buf, len);
+}
+
+/*
+ * Compute signature - finalize SHA1 operation and reapply SHA1.
+ */
+void
+isc_hmacsha1_sign(isc_hmacsha1_t *ctx, unsigned char *digest, size_t len) {
+	unsigned char opad[ISC_SHA1_BLOCK_LENGTH];
+	unsigned char newdigest[ISC_SHA1_DIGESTLENGTH];
+	unsigned int i;
+
+	REQUIRE(len <= ISC_SHA1_DIGESTLENGTH);
+	isc_sha1_final(&ctx->sha1ctx, newdigest);
+
+	memset(opad, OPAD, sizeof(opad));
+	for (i = 0; i < ISC_SHA1_BLOCK_LENGTH; i++)
+		opad[i] ^= ctx->key[i];
+
+	isc_sha1_init(&ctx->sha1ctx);
+	isc_sha1_update(&ctx->sha1ctx, opad, sizeof(opad));
+	isc_sha1_update(&ctx->sha1ctx, newdigest, ISC_SHA1_DIGESTLENGTH);
+	isc_sha1_final(&ctx->sha1ctx, newdigest);
+	isc_hmacsha1_invalidate(ctx);
+	memcpy(digest, newdigest, len);
+	memset(newdigest, 0, sizeof(newdigest));
+}
+
+/*
+ * Start HMAC-SHA224 process.  Initialize an sha224 context and digest the key.
+ */
+void
+isc_hmacsha224_init(isc_hmacsha224_t *ctx, const unsigned char *key,
+		    unsigned int len)
+{
+	unsigned char ipad[ISC_SHA224_BLOCK_LENGTH];
+	unsigned int i;
+
+	memset(ctx->key, 0, sizeof(ctx->key));
+	if (len > sizeof(ctx->key)) {
+		isc_sha224_t sha224ctx;
+		isc_sha224_init(&sha224ctx);
+		isc_sha224_update(&sha224ctx, key, len);
+		isc_sha224_final(ctx->key, &sha224ctx);
+	} else
+		memcpy(ctx->key, key, len);
+
+	isc_sha224_init(&ctx->sha224ctx);
+	memset(ipad, IPAD, sizeof(ipad));
+	for (i = 0; i < ISC_SHA224_BLOCK_LENGTH; i++)
+		ipad[i] ^= ctx->key[i];
+	isc_sha224_update(&ctx->sha224ctx, ipad, sizeof(ipad));
+}
+
+void
+isc_hmacsha224_invalidate(isc_hmacsha224_t *ctx) {
+	memset(ctx->key, 0, sizeof(ctx->key));
+	memset(ctx, 0, sizeof(ctx));
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void
+isc_hmacsha224_update(isc_hmacsha224_t *ctx, const unsigned char *buf,
+		   unsigned int len)
+{
+	isc_sha224_update(&ctx->sha224ctx, buf, len);
+}
+
+/*
+ * Compute signature - finalize SHA224 operation and reapply SHA224.
+ */
+void
+isc_hmacsha224_sign(isc_hmacsha224_t *ctx, unsigned char *digest, size_t len) {
+	unsigned char opad[ISC_SHA224_BLOCK_LENGTH];
+	unsigned char newdigest[ISC_SHA224_DIGESTLENGTH];
+	unsigned int i;
+
+	REQUIRE(len <= ISC_SHA224_DIGESTLENGTH);
+	isc_sha224_final(newdigest, &ctx->sha224ctx);
+
+	memset(opad, OPAD, sizeof(opad));
+	for (i = 0; i < ISC_SHA224_BLOCK_LENGTH; i++)
+		opad[i] ^= ctx->key[i];
+
+	isc_sha224_init(&ctx->sha224ctx);
+	isc_sha224_update(&ctx->sha224ctx, opad, sizeof(opad));
+	isc_sha224_update(&ctx->sha224ctx, newdigest, ISC_SHA224_DIGESTLENGTH);
+	isc_sha224_final(newdigest, &ctx->sha224ctx);
+	memcpy(digest, newdigest, len);
+	memset(newdigest, 0, sizeof(newdigest));
+}
+
+/*
+ * Start HMAC-SHA256 process.  Initialize an sha256 context and digest the key.
+ */
+void
+isc_hmacsha256_init(isc_hmacsha256_t *ctx, const unsigned char *key,
+		    unsigned int len)
+{
+	unsigned char ipad[ISC_SHA256_BLOCK_LENGTH];
+	unsigned int i;
+
+	memset(ctx->key, 0, sizeof(ctx->key));
+	if (len > sizeof(ctx->key)) {
+		isc_sha256_t sha256ctx;
+		isc_sha256_init(&sha256ctx);
+		isc_sha256_update(&sha256ctx, key, len);
+		isc_sha256_final(ctx->key, &sha256ctx);
+	} else
+		memcpy(ctx->key, key, len);
+
+	isc_sha256_init(&ctx->sha256ctx);
+	memset(ipad, IPAD, sizeof(ipad));
+	for (i = 0; i < ISC_SHA256_BLOCK_LENGTH; i++)
+		ipad[i] ^= ctx->key[i];
+	isc_sha256_update(&ctx->sha256ctx, ipad, sizeof(ipad));
+}
+
+void
+isc_hmacsha256_invalidate(isc_hmacsha256_t *ctx) {
+	memset(ctx->key, 0, sizeof(ctx->key));
+	memset(ctx, 0, sizeof(ctx));
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void
+isc_hmacsha256_update(isc_hmacsha256_t *ctx, const unsigned char *buf,
+		   unsigned int len)
+{
+	isc_sha256_update(&ctx->sha256ctx, buf, len);
+}
+
+/*
+ * Compute signature - finalize SHA256 operation and reapply SHA256.
+ */
+void
+isc_hmacsha256_sign(isc_hmacsha256_t *ctx, unsigned char *digest, size_t len) {
+	unsigned char opad[ISC_SHA256_BLOCK_LENGTH];
+	unsigned char newdigest[ISC_SHA256_DIGESTLENGTH];
+	unsigned int i;
+
+	REQUIRE(len <= ISC_SHA256_DIGESTLENGTH);
+	isc_sha256_final(newdigest, &ctx->sha256ctx);
+
+	memset(opad, OPAD, sizeof(opad));
+	for (i = 0; i < ISC_SHA256_BLOCK_LENGTH; i++)
+		opad[i] ^= ctx->key[i];
+
+	isc_sha256_init(&ctx->sha256ctx);
+	isc_sha256_update(&ctx->sha256ctx, opad, sizeof(opad));
+	isc_sha256_update(&ctx->sha256ctx, newdigest, ISC_SHA256_DIGESTLENGTH);
+	isc_sha256_final(newdigest, &ctx->sha256ctx);
+	memcpy(digest, newdigest, len);
+	memset(newdigest, 0, sizeof(newdigest));
+}
+
+/*
+ * Start HMAC-SHA384 process.  Initialize an sha384 context and digest the key.
+ */
+void
+isc_hmacsha384_init(isc_hmacsha384_t *ctx, const unsigned char *key,
+		    unsigned int len)
+{
+	unsigned char ipad[ISC_SHA384_BLOCK_LENGTH];
+	unsigned int i;
+
+	memset(ctx->key, 0, sizeof(ctx->key));
+	if (len > sizeof(ctx->key)) {
+		isc_sha384_t sha384ctx;
+		isc_sha384_init(&sha384ctx);
+		isc_sha384_update(&sha384ctx, key, len);
+		isc_sha384_final(ctx->key, &sha384ctx);
+	} else
+		memcpy(ctx->key, key, len);
+
+	isc_sha384_init(&ctx->sha384ctx);
+	memset(ipad, IPAD, sizeof(ipad));
+	for (i = 0; i < ISC_SHA384_BLOCK_LENGTH; i++)
+		ipad[i] ^= ctx->key[i];
+	isc_sha384_update(&ctx->sha384ctx, ipad, sizeof(ipad));
+}
+
+void
+isc_hmacsha384_invalidate(isc_hmacsha384_t *ctx) {
+	memset(ctx->key, 0, sizeof(ctx->key));
+	memset(ctx, 0, sizeof(ctx));
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void
+isc_hmacsha384_update(isc_hmacsha384_t *ctx, const unsigned char *buf,
+		   unsigned int len)
+{
+	isc_sha384_update(&ctx->sha384ctx, buf, len);
+}
+
+/*
+ * Compute signature - finalize SHA384 operation and reapply SHA384.
+ */
+void
+isc_hmacsha384_sign(isc_hmacsha384_t *ctx, unsigned char *digest, size_t len) {
+	unsigned char opad[ISC_SHA384_BLOCK_LENGTH];
+	unsigned char newdigest[ISC_SHA384_DIGESTLENGTH];
+	unsigned int i;
+
+	REQUIRE(len <= ISC_SHA384_DIGESTLENGTH);
+	isc_sha384_final(newdigest, &ctx->sha384ctx);
+
+	memset(opad, OPAD, sizeof(opad));
+	for (i = 0; i < ISC_SHA384_BLOCK_LENGTH; i++)
+		opad[i] ^= ctx->key[i];
+
+	isc_sha384_init(&ctx->sha384ctx);
+	isc_sha384_update(&ctx->sha384ctx, opad, sizeof(opad));
+	isc_sha384_update(&ctx->sha384ctx, newdigest, ISC_SHA384_DIGESTLENGTH);
+	isc_sha384_final(newdigest, &ctx->sha384ctx);
+	memcpy(digest, newdigest, len);
+	memset(newdigest, 0, sizeof(newdigest));
+}
+
+/*
+ * Start HMAC-SHA512 process.  Initialize an sha512 context and digest the key.
+ */
+void
+isc_hmacsha512_init(isc_hmacsha512_t *ctx, const unsigned char *key,
+		    unsigned int len)
+{
+	unsigned char ipad[ISC_SHA512_BLOCK_LENGTH];
+	unsigned int i;
+
+	memset(ctx->key, 0, sizeof(ctx->key));
+	if (len > sizeof(ctx->key)) {
+		isc_sha512_t sha512ctx;
+		isc_sha512_init(&sha512ctx);
+		isc_sha512_update(&sha512ctx, key, len);
+		isc_sha512_final(ctx->key, &sha512ctx);
+	} else
+		memcpy(ctx->key, key, len);
+
+	isc_sha512_init(&ctx->sha512ctx);
+	memset(ipad, IPAD, sizeof(ipad));
+	for (i = 0; i < ISC_SHA512_BLOCK_LENGTH; i++)
+		ipad[i] ^= ctx->key[i];
+	isc_sha512_update(&ctx->sha512ctx, ipad, sizeof(ipad));
+}
+
+void
+isc_hmacsha512_invalidate(isc_hmacsha512_t *ctx) {
+	memset(ctx->key, 0, sizeof(ctx->key));
+	memset(ctx, 0, sizeof(ctx));
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void
+isc_hmacsha512_update(isc_hmacsha512_t *ctx, const unsigned char *buf,
+		   unsigned int len)
+{
+	isc_sha512_update(&ctx->sha512ctx, buf, len);
+}
+
+/*
+ * Compute signature - finalize SHA512 operation and reapply SHA512.
+ */
+void
+isc_hmacsha512_sign(isc_hmacsha512_t *ctx, unsigned char *digest, size_t len) {
+	unsigned char opad[ISC_SHA512_BLOCK_LENGTH];
+	unsigned char newdigest[ISC_SHA512_DIGESTLENGTH];
+	unsigned int i;
+
+	REQUIRE(len <= ISC_SHA512_DIGESTLENGTH);
+	isc_sha512_final(newdigest, &ctx->sha512ctx);
+
+	memset(opad, OPAD, sizeof(opad));
+	for (i = 0; i < ISC_SHA512_BLOCK_LENGTH; i++)
+		opad[i] ^= ctx->key[i];
+
+	isc_sha512_init(&ctx->sha512ctx);
+	isc_sha512_update(&ctx->sha512ctx, opad, sizeof(opad));
+	isc_sha512_update(&ctx->sha512ctx, newdigest, ISC_SHA512_DIGESTLENGTH);
+	isc_sha512_final(newdigest, &ctx->sha512ctx);
+	memcpy(digest, newdigest, len);
+	memset(newdigest, 0, sizeof(newdigest));
+}
+#endif /* !ISC_PLATFORM_OPENSSLHASH */
+
+/*
+ * Verify signature - finalize SHA1 operation and reapply SHA1, then
+ * compare to the supplied digest.
+ */
+isc_boolean_t
+isc_hmacsha1_verify(isc_hmacsha1_t *ctx, unsigned char *digest, size_t len) {
+	unsigned char newdigest[ISC_SHA1_DIGESTLENGTH];
+
+	REQUIRE(len <= ISC_SHA1_DIGESTLENGTH);
+	isc_hmacsha1_sign(ctx, newdigest, ISC_SHA1_DIGESTLENGTH);
+	return (ISC_TF(memcmp(digest, newdigest, len) == 0));
+}
+
+/*
+ * Verify signature - finalize SHA224 operation and reapply SHA224, then
+ * compare to the supplied digest.
+ */
+isc_boolean_t
+isc_hmacsha224_verify(isc_hmacsha224_t *ctx, unsigned char *digest, size_t len) {
+	unsigned char newdigest[ISC_SHA224_DIGESTLENGTH];
+
+	REQUIRE(len <= ISC_SHA224_DIGESTLENGTH);
+	isc_hmacsha224_sign(ctx, newdigest, ISC_SHA224_DIGESTLENGTH);
+	return (ISC_TF(memcmp(digest, newdigest, len) == 0));
+}
+
+/*
+ * Verify signature - finalize SHA256 operation and reapply SHA256, then
+ * compare to the supplied digest.
+ */
+isc_boolean_t
+isc_hmacsha256_verify(isc_hmacsha256_t *ctx, unsigned char *digest, size_t len) {
+	unsigned char newdigest[ISC_SHA256_DIGESTLENGTH];
+
+	REQUIRE(len <= ISC_SHA256_DIGESTLENGTH);
+	isc_hmacsha256_sign(ctx, newdigest, ISC_SHA256_DIGESTLENGTH);
+	return (ISC_TF(memcmp(digest, newdigest, len) == 0));
+}
+
+/*
+ * Verify signature - finalize SHA384 operation and reapply SHA384, then
+ * compare to the supplied digest.
+ */
+isc_boolean_t
+isc_hmacsha384_verify(isc_hmacsha384_t *ctx, unsigned char *digest, size_t len) {
+	unsigned char newdigest[ISC_SHA384_DIGESTLENGTH];
+
+	REQUIRE(len <= ISC_SHA384_DIGESTLENGTH);
+	isc_hmacsha384_sign(ctx, newdigest, ISC_SHA384_DIGESTLENGTH);
+	return (ISC_TF(memcmp(digest, newdigest, len) == 0));
+}
+
+/*
+ * Verify signature - finalize SHA512 operation and reapply SHA512, then
+ * compare to the supplied digest.
+ */
+isc_boolean_t
+isc_hmacsha512_verify(isc_hmacsha512_t *ctx, unsigned char *digest, size_t len) {
+	unsigned char newdigest[ISC_SHA512_DIGESTLENGTH];
+
+	REQUIRE(len <= ISC_SHA512_DIGESTLENGTH);
+	isc_hmacsha512_sign(ctx, newdigest, ISC_SHA512_DIGESTLENGTH);
+	return (ISC_TF(memcmp(digest, newdigest, len) == 0));
+}
diff --git a/src/lib/bind9/httpd.c b/src/lib/bind9/httpd.c
new file mode 100644
index 0000000..4402647
--- /dev/null
+++ b/src/lib/bind9/httpd.c
@@ -0,0 +1,1028 @@
+/*
+ * Copyright (C) 2006-2008, 2010, 2011  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: httpd.c,v 1.20.40.3 2011-03-11 06:47:07 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/buffer.h>
+#include <isc/httpd.h>
+#include <isc/mem.h>
+#include <isc/socket.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/util.h>
+
+#include <string.h>
+
+/*%
+ * TODO:
+ *
+ *  o  Put in better checks to make certain things are passed in correctly.
+ *     This includes a magic number for externally-visible structures,
+ *     checking for NULL-ness before dereferencing, etc.
+ *  o  Make the URL processing external functions which will fill-in a buffer
+ *     structure we provide, or return an error and we will render a generic
+ *     page and close the client.
+ */
+
+#define MSHUTTINGDOWN(cm) ((cm->flags & ISC_HTTPDMGR_FLAGSHUTTINGDOWN) != 0)
+#define MSETSHUTTINGDOWN(cm) (cm->flags |= ISC_HTTPDMGR_FLAGSHUTTINGDOWN)
+
+#ifdef DEBUG_HTTPD
+#define ENTER(x) do { fprintf(stderr, "ENTER %s\n", (x)); } while (0)
+#define EXIT(x) do { fprintf(stderr, "EXIT %s\n", (x)); } while (0)
+#define NOTICE(x) do { fprintf(stderr, "NOTICE %s\n", (x)); } while (0)
+#else
+#define ENTER(x) do { } while(0)
+#define EXIT(x) do { } while(0)
+#define NOTICE(x) do { } while(0)
+#endif
+
+#define HTTP_RECVLEN			1024
+#define HTTP_SENDGROW			1024
+#define HTTP_SEND_MAXLEN		10240
+
+/*%
+ * HTTP urls.  These are the URLs we manage, and the function to call to
+ * provide the data for it.  We pass in the base url (so the same function
+ * can handle multiple requests), and a structure to fill in to return a
+ * result to the client.  We also pass in a pointer to be filled in for
+ * the data cleanup function.
+ */
+struct isc_httpdurl {
+	char			       *url;
+	isc_httpdaction_t	       *action;
+	void			       *action_arg;
+	ISC_LINK(isc_httpdurl_t)	link;
+};
+
+#define HTTPD_CLOSE		0x0001 /* Got a Connection: close header */
+#define HTTPD_FOUNDHOST		0x0002 /* Got a Host: header */
+
+/*% http client */
+struct isc_httpd {
+	isc_httpdmgr_t	       *mgr;		/*%< our parent */
+	ISC_LINK(isc_httpd_t)	link;
+	unsigned int		state;
+	isc_socket_t		*sock;
+
+	/*%
+	 * Received data state.
+	 */
+	char			recvbuf[HTTP_RECVLEN]; /*%< receive buffer */
+	isc_uint32_t		recvlen;	/*%< length recv'd */
+	unsigned int		method;
+	char		       *url;
+	char		       *querystring;
+	char		       *protocol;
+
+	/*
+	 * Flags on the httpd client.
+	 */
+	int			flags;
+
+	/*%
+	 * Transmit data state.
+	 *
+	 * This is the data buffer we will transmit.
+	 *
+	 * This free function pointer is filled in by the rendering function
+	 * we call.  The free function is called after the data is transmitted
+	 * to the client.
+	 *
+	 * The bufflist is the list of buffers we are currently transmitting.
+	 * The headerdata is where we render our headers to.  If we run out of
+	 * space when rendering a header, we will change the size of our
+	 * buffer.  We will not free it until we are finished, and will
+	 * allocate an additional HTTP_SENDGROW bytes per header space grow.
+	 *
+	 * We currently use two buffers total, one for the headers (which
+	 * we manage) and another for the client to fill in (which it manages,
+	 * it provides the space for it, etc) -- we will pass that buffer
+	 * structure back to the caller, who is responsible for managing the
+	 * space it may have allocated as backing store for it.  This second
+	 * buffer is bodybuffer, and we only allocate the buffer itself, not
+	 * the backing store.
+	 */
+	isc_bufferlist_t	bufflist;
+	char		       *headerdata; /*%< send header buf */
+	unsigned int		headerlen;  /*%< current header buffer size */
+	isc_buffer_t		headerbuffer;
+
+	const char	       *mimetype;
+	unsigned int		retcode;
+	const char	       *retmsg;
+	isc_buffer_t		bodybuffer;
+	isc_httpdfree_t	       *freecb;
+	void		       *freecb_arg;
+};
+
+/*% lightweight socket manager for httpd output */
+struct isc_httpdmgr {
+	isc_mem_t	       *mctx;
+	isc_socket_t	       *sock;		/*%< listening socket */
+	isc_task_t	       *task;		/*%< owning task */
+	isc_timermgr_t	       *timermgr;
+
+	isc_httpdclientok_t    *client_ok;	/*%< client validator */
+	isc_httpdondestroy_t   *ondestroy;	/*%< cleanup callback */
+	void		       *cb_arg;		/*%< argument for the above */
+
+	unsigned int		flags;
+	ISC_LIST(isc_httpd_t)	running;	/*%< running clients */
+
+	isc_mutex_t		lock;
+
+	ISC_LIST(isc_httpdurl_t) urls;		/*%< urls we manage */
+	isc_httpdaction_t      *render_404;
+	isc_httpdaction_t      *render_500;
+};
+
+/*%
+ * HTTP methods.
+ */
+#define ISC_HTTPD_METHODUNKNOWN	0
+#define ISC_HTTPD_METHODGET	1
+#define ISC_HTTPD_METHODPOST	2
+
+/*%
+ * Client states.
+ *
+ * _IDLE	The client is not doing anything at all.  This state should
+ *		only occur just after creation, and just before being
+ *		destroyed.
+ *
+ * _RECV	The client is waiting for data after issuing a socket recv().
+ *
+ * _RECVDONE	Data has been received, and is being processed.
+ *
+ * _SEND	All data for a response has completed, and a reply was
+ *		sent via a socket send() call.
+ *
+ * _SENDDONE	Send is completed.
+ *
+ * Badly formatted state table:
+ *
+ *	IDLE -> RECV when client has a recv() queued.
+ *
+ *	RECV -> RECVDONE when recvdone event received.
+ *
+ *	RECVDONE -> SEND if the data for a reply is at hand.
+ *
+ *	SEND -> RECV when a senddone event was received.
+ *
+ *	At any time -> RECV on error.  If RECV fails, the client will
+ *	self-destroy, closing the socket and freeing memory.
+ */
+#define ISC_HTTPD_STATEIDLE	0
+#define ISC_HTTPD_STATERECV	1
+#define ISC_HTTPD_STATERECVDONE	2
+#define ISC_HTTPD_STATESEND	3
+#define ISC_HTTPD_STATESENDDONE	4
+
+#define ISC_HTTPD_ISRECV(c)	((c)->state == ISC_HTTPD_STATERECV)
+#define ISC_HTTPD_ISRECVDONE(c)	((c)->state == ISC_HTTPD_STATERECVDONE)
+#define ISC_HTTPD_ISSEND(c)	((c)->state == ISC_HTTPD_STATESEND)
+#define ISC_HTTPD_ISSENDDONE(c)	((c)->state == ISC_HTTPD_STATESENDDONE)
+
+/*%
+ * Overall magic test that means we're not idle.
+ */
+#define ISC_HTTPD_SETRECV(c)	((c)->state = ISC_HTTPD_STATERECV)
+#define ISC_HTTPD_SETRECVDONE(c)	((c)->state = ISC_HTTPD_STATERECVDONE)
+#define ISC_HTTPD_SETSEND(c)	((c)->state = ISC_HTTPD_STATESEND)
+#define ISC_HTTPD_SETSENDDONE(c)	((c)->state = ISC_HTTPD_STATESENDDONE)
+
+static void isc_httpd_accept(isc_task_t *, isc_event_t *);
+static void isc_httpd_recvdone(isc_task_t *, isc_event_t *);
+static void isc_httpd_senddone(isc_task_t *, isc_event_t *);
+static void destroy_client(isc_httpd_t **);
+static isc_result_t process_request(isc_httpd_t *, int);
+static void httpdmgr_destroy(isc_httpdmgr_t *);
+static isc_result_t grow_headerspace(isc_httpd_t *);
+static void reset_client(isc_httpd_t *httpd);
+static isc_result_t render_404(const char *, const char *,
+			       void *,
+			       unsigned int *, const char **,
+			       const char **, isc_buffer_t *,
+			       isc_httpdfree_t **, void **);
+static isc_result_t render_500(const char *, const char *,
+			       void *,
+			       unsigned int *, const char **,
+			       const char **, isc_buffer_t *,
+			       isc_httpdfree_t **, void **);
+
+static void
+destroy_client(isc_httpd_t **httpdp)
+{
+	isc_httpd_t *httpd = *httpdp;
+	isc_httpdmgr_t *httpdmgr = httpd->mgr;
+
+	*httpdp = NULL;
+
+	LOCK(&httpdmgr->lock);
+
+	isc_socket_detach(&httpd->sock);
+	ISC_LIST_UNLINK(httpdmgr->running, httpd, link);
+
+	if (httpd->headerlen > 0)
+		isc_mem_put(httpdmgr->mctx, httpd->headerdata,
+			    httpd->headerlen);
+
+	isc_mem_put(httpdmgr->mctx, httpd, sizeof(isc_httpd_t));
+
+	UNLOCK(&httpdmgr->lock);
+
+	httpdmgr_destroy(httpdmgr);
+}
+
+isc_result_t
+isc_httpdmgr_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
+		    isc_httpdclientok_t *client_ok,
+		    isc_httpdondestroy_t *ondestroy, void *cb_arg,
+		    isc_timermgr_t *tmgr, isc_httpdmgr_t **httpdp)
+{
+	isc_result_t result;
+	isc_httpdmgr_t *httpd;
+
+	REQUIRE(mctx != NULL);
+	REQUIRE(sock != NULL);
+	REQUIRE(task != NULL);
+	REQUIRE(tmgr != NULL);
+	REQUIRE(httpdp != NULL && *httpdp == NULL);
+
+	httpd = isc_mem_get(mctx, sizeof(isc_httpdmgr_t));
+	if (httpd == NULL)
+		return (ISC_R_NOMEMORY);
+
+	result = isc_mutex_init(&httpd->lock);
+	if (result != ISC_R_SUCCESS) {
+		isc_mem_put(mctx, httpd, sizeof(isc_httpdmgr_t));
+		return (result);
+	}
+	httpd->mctx = NULL;
+	isc_mem_attach(mctx, &httpd->mctx);
+	httpd->sock = NULL;
+	isc_socket_attach(sock, &httpd->sock);
+	httpd->task = NULL;
+	isc_task_attach(task, &httpd->task);
+	httpd->timermgr = tmgr; /* XXXMLG no attach function? */
+	httpd->client_ok = client_ok;
+	httpd->ondestroy = ondestroy;
+	httpd->cb_arg = cb_arg;
+
+	ISC_LIST_INIT(httpd->running);
+	ISC_LIST_INIT(httpd->urls);
+
+	/* XXXMLG ignore errors on isc_socket_listen() */
+	result = isc_socket_listen(sock, SOMAXCONN);
+	if (result != ISC_R_SUCCESS) {
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "isc_socket_listen() failed: %s",
+				 isc_result_totext(result));
+		goto cleanup;
+	}
+
+	(void)isc_socket_filter(sock, "httpready");
+
+	result = isc_socket_accept(sock, task, isc_httpd_accept, httpd);
+	if (result != ISC_R_SUCCESS)
+		goto cleanup;
+
+	httpd->render_404 = render_404;
+	httpd->render_500 = render_500;
+
+	*httpdp = httpd;
+	return (ISC_R_SUCCESS);
+
+  cleanup:
+	isc_task_detach(&httpd->task);
+	isc_socket_detach(&httpd->sock);
+	isc_mem_detach(&httpd->mctx);
+	(void)isc_mutex_destroy(&httpd->lock);
+	isc_mem_put(mctx, httpd, sizeof(isc_httpdmgr_t));
+	return (result);
+}
+
+static void
+httpdmgr_destroy(isc_httpdmgr_t *httpdmgr)
+{
+	isc_mem_t *mctx;
+	isc_httpdurl_t *url;
+
+	ENTER("httpdmgr_destroy");
+
+	LOCK(&httpdmgr->lock);
+
+	if (!MSHUTTINGDOWN(httpdmgr)) {
+		NOTICE("httpdmgr_destroy not shutting down yet");
+		UNLOCK(&httpdmgr->lock);
+		return;
+	}
+
+	/*
+	 * If all clients are not shut down, don't do anything yet.
+	 */
+	if (!ISC_LIST_EMPTY(httpdmgr->running)) {
+		NOTICE("httpdmgr_destroy clients still active");
+		UNLOCK(&httpdmgr->lock);
+		return;
+	}
+
+	NOTICE("httpdmgr_destroy detaching socket, task, and timermgr");
+
+	isc_socket_detach(&httpdmgr->sock);
+	isc_task_detach(&httpdmgr->task);
+	httpdmgr->timermgr = NULL;
+
+	/*
+	 * Clear out the list of all actions we know about.  Just free the
+	 * memory.
+	 */
+	url = ISC_LIST_HEAD(httpdmgr->urls);
+	while (url != NULL) {
+		isc_mem_free(httpdmgr->mctx, url->url);
+		ISC_LIST_UNLINK(httpdmgr->urls, url, link);
+		isc_mem_put(httpdmgr->mctx, url, sizeof(isc_httpdurl_t));
+		url = ISC_LIST_HEAD(httpdmgr->urls);
+	}
+
+	UNLOCK(&httpdmgr->lock);
+	(void)isc_mutex_destroy(&httpdmgr->lock);
+
+	if (httpdmgr->ondestroy != NULL)
+		(httpdmgr->ondestroy)(httpdmgr->cb_arg);
+
+	mctx = httpdmgr->mctx;
+	isc_mem_putanddetach(&mctx, httpdmgr, sizeof(isc_httpdmgr_t));
+
+	EXIT("httpdmgr_destroy");
+}
+
+#define LENGTHOK(s) (httpd->recvbuf - (s) < (int)httpd->recvlen)
+#define BUFLENOK(s) (httpd->recvbuf - (s) < HTTP_RECVLEN)
+
+static isc_result_t
+process_request(isc_httpd_t *httpd, int length)
+{
+	char *s;
+	char *p;
+	int delim;
+
+	ENTER("request");
+
+	httpd->recvlen += length;
+
+	httpd->recvbuf[httpd->recvlen] = 0;
+
+	/*
+	 * If we don't find a blank line in our buffer, return that we need
+	 * more data.
+	 */
+	s = strstr(httpd->recvbuf, "\r\n\r\n");
+	delim = 1;
+	if (s == NULL) {
+		s = strstr(httpd->recvbuf, "\n\n");
+		delim = 2;
+	}
+	if (s == NULL)
+		return (ISC_R_NOTFOUND);
+
+	/*
+	 * Determine if this is a POST or GET method.  Any other values will
+	 * cause an error to be returned.
+	 */
+	if (strncmp(httpd->recvbuf, "GET ", 4) == 0) {
+		httpd->method = ISC_HTTPD_METHODGET;
+		p = httpd->recvbuf + 4;
+	} else if (strncmp(httpd->recvbuf, "POST ", 5) == 0) {
+		httpd->method = ISC_HTTPD_METHODPOST;
+		p = httpd->recvbuf + 5;
+	} else {
+		return (ISC_R_RANGE);
+	}
+
+	/*
+	 * From now on, p is the start of our buffer.
+	 */
+
+	/*
+	 * Extract the URL.
+	 */
+	s = p;
+	while (LENGTHOK(s) && BUFLENOK(s) &&
+	       (*s != '\n' && *s != '\r' && *s != '\0' && *s != ' '))
+		s++;
+	if (!LENGTHOK(s))
+		return (ISC_R_NOTFOUND);
+	if (!BUFLENOK(s))
+		return (ISC_R_NOMEMORY);
+	*s = 0;
+
+	/*
+	 * Make the URL relative.
+	 */
+	if ((strncmp(p, "http:/", 6) == 0)
+	    || (strncmp(p, "https:/", 7) == 0)) {
+		/* Skip first / */
+		while (*p != '/' && *p != 0)
+			p++;
+		if (*p == 0)
+			return (ISC_R_RANGE);
+		p++;
+		/* Skip second / */
+		while (*p != '/' && *p != 0)
+			p++;
+		if (*p == 0)
+			return (ISC_R_RANGE);
+		p++;
+		/* Find third / */
+		while (*p != '/' && *p != 0)
+			p++;
+		if (*p == 0) {
+			p--;
+			*p = '/';
+		}
+	}
+
+	httpd->url = p;
+	p = s + delim;
+	s = p;
+
+	/*
+	 * Now, see if there is a ? mark in the URL.  If so, this is
+	 * part of the query string, and we will split it from the URL.
+	 */
+	httpd->querystring = strchr(httpd->url, '?');
+	if (httpd->querystring != NULL) {
+		*(httpd->querystring) = 0;
+		httpd->querystring++;
+	}
+
+	/*
+	 * Extract the HTTP/1.X protocol.  We will bounce on anything but
+	 * HTTP/1.1 for now.
+	 */
+	while (LENGTHOK(s) && BUFLENOK(s) &&
+	       (*s != '\n' && *s != '\r' && *s != '\0'))
+		s++;
+	if (!LENGTHOK(s))
+		return (ISC_R_NOTFOUND);
+	if (!BUFLENOK(s))
+		return (ISC_R_NOMEMORY);
+	*s = 0;
+	if ((strncmp(p, "HTTP/1.0", 8) != 0)
+	    && (strncmp(p, "HTTP/1.1", 8) != 0))
+		return (ISC_R_RANGE);
+	httpd->protocol = p;
+	p = s + 1;
+	s = p;
+
+	if (strstr(s, "Connection: close") != NULL)
+		httpd->flags |= HTTPD_CLOSE;
+
+	if (strstr(s, "Host: ") != NULL)
+		httpd->flags |= HTTPD_FOUNDHOST;
+
+	/*
+	 * Standards compliance hooks here.
+	 */
+	if (strcmp(httpd->protocol, "HTTP/1.1") == 0
+	    && ((httpd->flags & HTTPD_FOUNDHOST) == 0))
+		return (ISC_R_RANGE);
+
+	EXIT("request");
+
+	return (ISC_R_SUCCESS);
+}
+
+static void
+isc_httpd_accept(isc_task_t *task, isc_event_t *ev)
+{
+	isc_result_t result;
+	isc_httpdmgr_t *httpdmgr = ev->ev_arg;
+	isc_httpd_t *httpd;
+	isc_region_t r;
+	isc_socket_newconnev_t *nev = (isc_socket_newconnev_t *)ev;
+	isc_sockaddr_t peeraddr;
+
+	ENTER("accept");
+
+	LOCK(&httpdmgr->lock);
+	if (MSHUTTINGDOWN(httpdmgr)) {
+		NOTICE("accept shutting down, goto out");
+		goto out;
+	}
+
+	if (nev->result == ISC_R_CANCELED) {
+		NOTICE("accept canceled, goto out");
+		goto out;
+	}
+
+	if (nev->result != ISC_R_SUCCESS) {
+		/* XXXMLG log failure */
+		NOTICE("accept returned failure, goto requeue");
+		goto requeue;
+	}
+
+	(void)isc_socket_getpeername(nev->newsocket, &peeraddr);
+	if (httpdmgr->client_ok != NULL &&
+	    !(httpdmgr->client_ok)(&peeraddr, httpdmgr->cb_arg)) {
+		isc_socket_detach(&nev->newsocket);
+		goto requeue;
+	}
+
+	httpd = isc_mem_get(httpdmgr->mctx, sizeof(isc_httpd_t));
+	if (httpd == NULL) {
+		/* XXXMLG log failure */
+		NOTICE("accept failed to allocate memory, goto requeue");
+		isc_socket_detach(&nev->newsocket);
+		goto requeue;
+	}
+
+	httpd->mgr = httpdmgr;
+	ISC_LINK_INIT(httpd, link);
+	ISC_LIST_APPEND(httpdmgr->running, httpd, link);
+	ISC_HTTPD_SETRECV(httpd);
+	httpd->sock = nev->newsocket;
+	isc_socket_setname(httpd->sock, "httpd", NULL);
+	httpd->flags = 0;
+
+	/*
+	 * Initialize the buffer for our headers.
+	 */
+	httpd->headerdata = isc_mem_get(httpdmgr->mctx, HTTP_SENDGROW);
+	if (httpd->headerdata == NULL) {
+		isc_mem_put(httpdmgr->mctx, httpd, sizeof(isc_httpd_t));
+		isc_socket_detach(&nev->newsocket);
+		goto requeue;
+	}
+	httpd->headerlen = HTTP_SENDGROW;
+	isc_buffer_init(&httpd->headerbuffer, httpd->headerdata,
+			httpd->headerlen);
+
+	ISC_LIST_INIT(httpd->bufflist);
+
+	isc_buffer_initnull(&httpd->bodybuffer);
+	reset_client(httpd);
+
+	r.base = (unsigned char *)httpd->recvbuf;
+	r.length = HTTP_RECVLEN - 1;
+	result = isc_socket_recv(httpd->sock, &r, 1, task, isc_httpd_recvdone,
+				 httpd);
+	/* FIXME!!! */
+	POST(result);
+	NOTICE("accept queued recv on socket");
+
+ requeue:
+	result = isc_socket_accept(httpdmgr->sock, task, isc_httpd_accept,
+				   httpdmgr);
+	if (result != ISC_R_SUCCESS) {
+		/* XXXMLG what to do?  Log failure... */
+		NOTICE("accept could not reaccept due to failure");
+	}
+
+ out:
+	UNLOCK(&httpdmgr->lock);
+
+	httpdmgr_destroy(httpdmgr);
+
+	isc_event_free(&ev);
+
+	EXIT("accept");
+}
+
+static isc_result_t
+render_404(const char *url, const char *querystring,
+	   void *arg,
+	   unsigned int *retcode, const char **retmsg,
+	   const char **mimetype, isc_buffer_t *b,
+	   isc_httpdfree_t **freecb, void **freecb_args)
+{
+	static char msg[] = "No such URL.";
+
+	UNUSED(url);
+	UNUSED(querystring);
+	UNUSED(arg);
+
+	*retcode = 404;
+	*retmsg = "No such URL";
+	*mimetype = "text/plain";
+	isc_buffer_reinit(b, msg, strlen(msg));
+	isc_buffer_add(b, strlen(msg));
+	*freecb = NULL;
+	*freecb_args = NULL;
+
+	return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+render_500(const char *url, const char *querystring,
+	   void *arg,
+	   unsigned int *retcode, const char **retmsg,
+	   const char **mimetype, isc_buffer_t *b,
+	   isc_httpdfree_t **freecb, void **freecb_args)
+{
+	static char msg[] = "Internal server failure.";
+
+	UNUSED(url);
+	UNUSED(querystring);
+	UNUSED(arg);
+
+	*retcode = 500;
+	*retmsg = "Internal server failure";
+	*mimetype = "text/plain";
+	isc_buffer_reinit(b, msg, strlen(msg));
+	isc_buffer_add(b, strlen(msg));
+	*freecb = NULL;
+	*freecb_args = NULL;
+
+	return (ISC_R_SUCCESS);
+}
+
+static void
+isc_httpd_recvdone(isc_task_t *task, isc_event_t *ev)
+{
+	isc_region_t r;
+	isc_result_t result;
+	isc_httpd_t *httpd = ev->ev_arg;
+	isc_socketevent_t *sev = (isc_socketevent_t *)ev;
+	isc_httpdurl_t *url;
+	isc_time_t now;
+	char datebuf[32];  /* Only need 30, but safety first */
+
+	ENTER("recv");
+
+	INSIST(ISC_HTTPD_ISRECV(httpd));
+
+	if (sev->result != ISC_R_SUCCESS) {
+		NOTICE("recv destroying client");
+		destroy_client(&httpd);
+		goto out;
+	}
+
+	result = process_request(httpd, sev->n);
+	if (result == ISC_R_NOTFOUND) {
+		if (httpd->recvlen >= HTTP_RECVLEN - 1) {
+			destroy_client(&httpd);
+			goto out;
+		}
+		r.base = (unsigned char *)httpd->recvbuf + httpd->recvlen;
+		r.length = HTTP_RECVLEN - httpd->recvlen - 1;
+		/* check return code? */
+		(void)isc_socket_recv(httpd->sock, &r, 1, task,
+				      isc_httpd_recvdone, httpd);
+		goto out;
+	} else if (result != ISC_R_SUCCESS) {
+		destroy_client(&httpd);
+		goto out;
+	}
+
+	ISC_HTTPD_SETSEND(httpd);
+
+	/*
+	 * XXXMLG Call function here.  Provide an add-header function
+	 * which will append the common headers to a response we generate.
+	 */
+	isc_buffer_initnull(&httpd->bodybuffer);
+	isc_time_now(&now);
+	isc_time_formathttptimestamp(&now, datebuf, sizeof(datebuf));
+	url = ISC_LIST_HEAD(httpd->mgr->urls);
+	while (url != NULL) {
+		if (strcmp(httpd->url, url->url) == 0)
+			break;
+		url = ISC_LIST_NEXT(url, link);
+	}
+	if (url == NULL)
+		result = httpd->mgr->render_404(httpd->url, httpd->querystring,
+						NULL,
+						&httpd->retcode,
+						&httpd->retmsg,
+						&httpd->mimetype,
+						&httpd->bodybuffer,
+						&httpd->freecb,
+						&httpd->freecb_arg);
+	else
+		result = url->action(httpd->url, httpd->querystring,
+				     url->action_arg,
+				     &httpd->retcode, &httpd->retmsg,
+				     &httpd->mimetype, &httpd->bodybuffer,
+				     &httpd->freecb, &httpd->freecb_arg);
+	if (result != ISC_R_SUCCESS) {
+		result = httpd->mgr->render_500(httpd->url, httpd->querystring,
+						NULL, &httpd->retcode,
+						&httpd->retmsg,
+						&httpd->mimetype,
+						&httpd->bodybuffer,
+						&httpd->freecb,
+						&httpd->freecb_arg);
+		RUNTIME_CHECK(result == ISC_R_SUCCESS);
+	}
+
+	isc_httpd_response(httpd);
+	isc_httpd_addheader(httpd, "Content-Type", httpd->mimetype);
+	isc_httpd_addheader(httpd, "Date", datebuf);
+	isc_httpd_addheader(httpd, "Expires", datebuf);
+	isc_httpd_addheader(httpd, "Last-Modified", datebuf);
+	isc_httpd_addheader(httpd, "Pragma: no-cache", NULL);
+	isc_httpd_addheader(httpd, "Cache-Control: no-cache", NULL);
+	isc_httpd_addheader(httpd, "Server: libisc", NULL);
+	isc_httpd_addheaderuint(httpd, "Content-Length",
+				isc_buffer_usedlength(&httpd->bodybuffer));
+	isc_httpd_endheaders(httpd);  /* done */
+
+	ISC_LIST_APPEND(httpd->bufflist, &httpd->headerbuffer, link);
+	/*
+	 * Link the data buffer into our send queue, should we have any data
+	 * rendered into it.  If no data is present, we won't do anything
+	 * with the buffer.
+	 */
+	if (isc_buffer_length(&httpd->bodybuffer) > 0)
+		ISC_LIST_APPEND(httpd->bufflist, &httpd->bodybuffer, link);
+
+	/* check return code? */
+	(void)isc_socket_sendv(httpd->sock, &httpd->bufflist, task,
+			       isc_httpd_senddone, httpd);
+
+ out:
+	isc_event_free(&ev);
+	EXIT("recv");
+}
+
+void
+isc_httpdmgr_shutdown(isc_httpdmgr_t **httpdmgrp)
+{
+	isc_httpdmgr_t *httpdmgr;
+	isc_httpd_t *httpd;
+	httpdmgr = *httpdmgrp;
+	*httpdmgrp = NULL;
+
+	ENTER("isc_httpdmgr_shutdown");
+
+	LOCK(&httpdmgr->lock);
+
+	MSETSHUTTINGDOWN(httpdmgr);
+
+	isc_socket_cancel(httpdmgr->sock, httpdmgr->task, ISC_SOCKCANCEL_ALL);
+
+	httpd = ISC_LIST_HEAD(httpdmgr->running);
+	while (httpd != NULL) {
+		isc_socket_cancel(httpd->sock, httpdmgr->task,
+				  ISC_SOCKCANCEL_ALL);
+		httpd = ISC_LIST_NEXT(httpd, link);
+	}
+
+	UNLOCK(&httpdmgr->lock);
+
+	EXIT("isc_httpdmgr_shutdown");
+}
+
+static isc_result_t
+grow_headerspace(isc_httpd_t *httpd)
+{
+	char *newspace;
+	unsigned int newlen;
+	isc_region_t r;
+
+	newlen = httpd->headerlen + HTTP_SENDGROW;
+	if (newlen > HTTP_SEND_MAXLEN)
+		return (ISC_R_NOSPACE);
+
+	newspace = isc_mem_get(httpd->mgr->mctx, newlen);
+	if (newspace == NULL)
+		return (ISC_R_NOMEMORY);
+	isc_buffer_region(&httpd->headerbuffer, &r);
+	isc_buffer_reinit(&httpd->headerbuffer, newspace, newlen);
+
+	isc_mem_put(httpd->mgr->mctx, r.base, r.length);
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_httpd_response(isc_httpd_t *httpd)
+{
+	isc_result_t result;
+	unsigned int needlen;
+
+	needlen = strlen(httpd->protocol) + 1; /* protocol + space */
+	needlen += 3 + 1;  /* room for response code, always 3 bytes */
+	needlen += strlen(httpd->retmsg) + 2;  /* return msg + CRLF */
+
+	while (isc_buffer_availablelength(&httpd->headerbuffer) < needlen) {
+		result = grow_headerspace(httpd);
+		if (result != ISC_R_SUCCESS)
+			return (result);
+	}
+
+	sprintf(isc_buffer_used(&httpd->headerbuffer), "%s %03d %s\r\n",
+		httpd->protocol, httpd->retcode, httpd->retmsg);
+	isc_buffer_add(&httpd->headerbuffer, needlen);
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_httpd_addheader(isc_httpd_t *httpd, const char *name,
+		    const char *val)
+{
+	isc_result_t result;
+	unsigned int needlen;
+
+	needlen = strlen(name); /* name itself */
+	if (val != NULL)
+		needlen += 2 + strlen(val); /* :<space> and val */
+	needlen += 2; /* CRLF */
+
+	while (isc_buffer_availablelength(&httpd->headerbuffer) < needlen) {
+		result = grow_headerspace(httpd);
+		if (result != ISC_R_SUCCESS)
+			return (result);
+	}
+
+	if (val != NULL)
+		sprintf(isc_buffer_used(&httpd->headerbuffer),
+			"%s: %s\r\n", name, val);
+	else
+		sprintf(isc_buffer_used(&httpd->headerbuffer),
+			"%s\r\n", name);
+
+	isc_buffer_add(&httpd->headerbuffer, needlen);
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_httpd_endheaders(isc_httpd_t *httpd)
+{
+	isc_result_t result;
+
+	while (isc_buffer_availablelength(&httpd->headerbuffer) < 2) {
+		result = grow_headerspace(httpd);
+		if (result != ISC_R_SUCCESS)
+			return (result);
+	}
+
+	sprintf(isc_buffer_used(&httpd->headerbuffer), "\r\n");
+	isc_buffer_add(&httpd->headerbuffer, 2);
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_httpd_addheaderuint(isc_httpd_t *httpd, const char *name, int val) {
+	isc_result_t result;
+	unsigned int needlen;
+	char buf[sizeof "18446744073709551616"];
+
+	sprintf(buf, "%d", val);
+
+	needlen = strlen(name); /* name itself */
+	needlen += 2 + strlen(buf); /* :<space> and val */
+	needlen += 2; /* CRLF */
+
+	while (isc_buffer_availablelength(&httpd->headerbuffer) < needlen) {
+		result = grow_headerspace(httpd);
+		if (result != ISC_R_SUCCESS)
+			return (result);
+	}
+
+	sprintf(isc_buffer_used(&httpd->headerbuffer),
+		"%s: %s\r\n", name, buf);
+
+	isc_buffer_add(&httpd->headerbuffer, needlen);
+
+	return (ISC_R_SUCCESS);
+}
+
+static void
+isc_httpd_senddone(isc_task_t *task, isc_event_t *ev)
+{
+	isc_httpd_t *httpd = ev->ev_arg;
+	isc_region_t r;
+	isc_socketevent_t *sev = (isc_socketevent_t *)ev;
+
+	ENTER("senddone");
+	INSIST(ISC_HTTPD_ISSEND(httpd));
+
+	/*
+	 * First, unlink our header buffer from the socket's bufflist.  This
+	 * is sort of an evil hack, since we know our buffer will be there,
+	 * and we know it's address, so we can just remove it directly.
+	 */
+	NOTICE("senddone unlinked header");
+	ISC_LIST_UNLINK(sev->bufferlist, &httpd->headerbuffer, link);
+
+	/*
+	 * We will always want to clean up our receive buffer, even if we
+	 * got an error on send or we are shutting down.
+	 *
+	 * We will pass in the buffer only if there is data in it.  If
+	 * there is no data, we will pass in a NULL.
+	 */
+	if (httpd->freecb != NULL) {
+		isc_buffer_t *b = NULL;
+		if (isc_buffer_length(&httpd->bodybuffer) > 0)
+			b = &httpd->bodybuffer;
+		httpd->freecb(b, httpd->freecb_arg);
+		NOTICE("senddone free callback performed");
+	}
+	if (ISC_LINK_LINKED(&httpd->bodybuffer, link)) {
+		ISC_LIST_UNLINK(sev->bufferlist, &httpd->bodybuffer, link);
+		NOTICE("senddone body buffer unlinked");
+	}
+
+	if (sev->result != ISC_R_SUCCESS) {
+		destroy_client(&httpd);
+		goto out;
+	}
+
+	if ((httpd->flags & HTTPD_CLOSE) != 0) {
+		destroy_client(&httpd);
+		goto out;
+	}
+
+	ISC_HTTPD_SETRECV(httpd);
+
+	NOTICE("senddone restarting recv on socket");
+
+	reset_client(httpd);
+
+	r.base = (unsigned char *)httpd->recvbuf;
+	r.length = HTTP_RECVLEN - 1;
+	/* check return code? */
+	(void)isc_socket_recv(httpd->sock, &r, 1, task,
+			      isc_httpd_recvdone, httpd);
+
+out:
+	isc_event_free(&ev);
+	EXIT("senddone");
+}
+
+static void
+reset_client(isc_httpd_t *httpd)
+{
+	/*
+	 * Catch errors here.  We MUST be in RECV mode, and we MUST NOT have
+	 * any outstanding buffers.  If we have buffers, we have a leak.
+	 */
+	INSIST(ISC_HTTPD_ISRECV(httpd));
+	INSIST(!ISC_LINK_LINKED(&httpd->headerbuffer, link));
+	INSIST(!ISC_LINK_LINKED(&httpd->bodybuffer, link));
+
+	httpd->recvbuf[0] = 0;
+	httpd->recvlen = 0;
+	httpd->method = ISC_HTTPD_METHODUNKNOWN;
+	httpd->url = NULL;
+	httpd->querystring = NULL;
+	httpd->protocol = NULL;
+	httpd->flags = 0;
+
+	isc_buffer_clear(&httpd->headerbuffer);
+	isc_buffer_invalidate(&httpd->bodybuffer);
+}
+
+isc_result_t
+isc_httpdmgr_addurl(isc_httpdmgr_t *httpdmgr, const char *url,
+		    isc_httpdaction_t *func, void *arg)
+{
+	isc_httpdurl_t *item;
+
+	if (url == NULL) {
+		httpdmgr->render_404 = func;
+		return (ISC_R_SUCCESS);
+	}
+
+	item = isc_mem_get(httpdmgr->mctx, sizeof(isc_httpdurl_t));
+	if (item == NULL)
+		return (ISC_R_NOMEMORY);
+
+	item->url = isc_mem_strdup(httpdmgr->mctx, url);
+	if (item->url == NULL) {
+		isc_mem_put(httpdmgr->mctx, item, sizeof(isc_httpdurl_t));
+		return (ISC_R_NOMEMORY);
+	}
+
+	item->action = func;
+	item->action_arg = arg;
+	ISC_LINK_INIT(item, link);
+	ISC_LIST_APPEND(httpdmgr->urls, item, link);
+
+	return (ISC_R_SUCCESS);
+}
diff --git a/src/lib/bind9/ia64/include/isc/atomic.h b/src/lib/bind9/ia64/include/isc/atomic.h
new file mode 100644
index 0000000..11c9706
--- /dev/null
+++ b/src/lib/bind9/ia64/include/isc/atomic.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2006, 2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: atomic.h,v 1.7 2009-06-24 02:22:50 marka Exp $ */
+
+#ifndef ISC_ATOMIC_H
+#define ISC_ATOMIC_H 1
+
+#include <isc/platform.h>
+#include <isc/types.h>
+
+#ifdef ISC_PLATFORM_USEGCCASM
+/*
+ * This routine atomically increments the value stored in 'p' by 'val', and
+ * returns the previous value.
+ *
+ * Open issue: can 'fetchadd' make the code faster for some particular values
+ * (e.g., 1 and -1)?
+ */
+static inline isc_int32_t
+#ifdef __GNUC__
+__attribute__ ((unused))
+#endif
+isc_atomic_xadd(isc_int32_t *p, isc_int32_t val)
+{
+	isc_int32_t prev, swapped;
+
+	for (prev = *(volatile isc_int32_t *)p; ; prev = swapped) {
+		swapped = prev + val;
+		__asm__ volatile(
+			"mov ar.ccv=%2;"
+			"cmpxchg4.acq %0=%4,%3,ar.ccv"
+			: "=r" (swapped), "=m" (*p)
+			: "r" (prev), "r" (swapped), "m" (*p)
+			: "memory");
+		if (swapped == prev)
+			break;
+	}
+
+	return (prev);
+}
+
+/*
+ * This routine atomically stores the value 'val' in 'p'.
+ */
+static inline void
+#ifdef __GNUC__
+__attribute__ ((unused))
+#endif
+isc_atomic_store(isc_int32_t *p, isc_int32_t val)
+{
+	__asm__ volatile(
+		"st4.rel %0=%1"
+		: "=m" (*p)
+		: "r" (val)
+		: "memory"
+		);
+}
+
+/*
+ * This routine atomically replaces the value in 'p' with 'val', if the
+ * original value is equal to 'cmpval'.  The original value is returned in any
+ * case.
+ */
+static inline isc_int32_t
+#ifdef __GNUC__
+__attribute__ ((unused))
+#endif
+isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val)
+{
+	isc_int32_t ret;
+
+	__asm__ volatile(
+		"mov ar.ccv=%2;"
+		"cmpxchg4.acq %0=%4,%3,ar.ccv"
+		: "=r" (ret), "=m" (*p)
+		: "r" (cmpval), "r" (val), "m" (*p)
+		: "memory");
+
+	return (ret);
+}
+#else /* !ISC_PLATFORM_USEGCCASM */
+
+#error "unsupported compiler.  disable atomic ops by --disable-atomic"
+
+#endif
+#endif /* ISC_ATOMIC_H */
diff --git a/src/lib/bind9/include/isc/app.h b/src/lib/bind9/include/isc/app.h
new file mode 100644
index 0000000..ac8669f
--- /dev/null
+++ b/src/lib/bind9/include/isc/app.h
@@ -0,0 +1,375 @@
+/*
+ * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: app.h,v 1.11 2009-09-02 23:48:03 tbox Exp $ */
+
+#ifndef ISC_APP_H
+#define ISC_APP_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file isc/app.h
+ * \brief ISC Application Support
+ *
+ * Dealing with program termination can be difficult, especially in a
+ * multithreaded program.  The routines in this module help coordinate
+ * the shutdown process.  They are used as follows by the initial (main)
+ * thread of the application:
+ *
+ *\li		isc_app_start();	Call very early in main(), before
+ *					any other threads have been created.
+ *
+ *\li		isc_app_run();		This will post any on-run events,
+ *					and then block until application
+ *					shutdown is requested.  A shutdown
+ *					request is made by calling
+ *					isc_app_shutdown(), or by sending
+ *					SIGINT or SIGTERM to the process.
+ *					After isc_app_run() returns, the
+ *					application should shutdown itself.
+ *
+ *\li		isc_app_finish();	Call very late in main().
+ *
+ * Applications that want to use SIGHUP/isc_app_reload() to trigger reloading
+ * should check the result of isc_app_run() and call the reload routine if
+ * the result is ISC_R_RELOAD.  They should then call isc_app_run() again
+ * to resume waiting for reload or termination.
+ *
+ * Use of this module is not required.  In particular, isc_app_start() is
+ * NOT an ISC library initialization routine.
+ *
+ * This module also supports per-thread 'application contexts'.  With this
+ * mode, a thread-based application will have a separate context, in which
+ * it uses other ISC library services such as tasks or timers.  Signals are
+ * not caught in this mode, so that the application can handle the signals
+ * in its preferred way.
+ *
+ * \li MP:
+ *	Clients must ensure that isc_app_start(), isc_app_run(), and
+ *	isc_app_finish() are called at most once.  isc_app_shutdown()
+ *	is safe to use by any thread (provided isc_app_start() has been
+ *	called previously).
+ *
+ *	The same note applies to isc_app_ctxXXX() functions, but in this case
+ *	it's a per-thread restriction.  For example, a thread with an
+ *	application context must ensure that isc_app_ctxstart() with the
+ *	context is called at most once.
+ *
+ * \li Reliability:
+ *	No anticipated impact.
+ *
+ * \li Resources:
+ *	None.
+ *
+ * \li Security:
+ *	No anticipated impact.
+ *
+ * \li Standards:
+ *	None.
+ */
+
+#include <isc/eventclass.h>
+#include <isc/lang.h>
+#include <isc/magic.h>
+#include <isc/result.h>
+
+/***
+ *** Types
+ ***/
+
+typedef isc_event_t isc_appevent_t;
+
+#define ISC_APPEVENT_FIRSTEVENT		(ISC_EVENTCLASS_APP + 0)
+#define ISC_APPEVENT_SHUTDOWN		(ISC_EVENTCLASS_APP + 1)
+#define ISC_APPEVENT_LASTEVENT		(ISC_EVENTCLASS_APP + 65535)
+
+/*%
+ * app module methods.  Only app driver implementations use this structure.
+ * Other clients should use the top-level interfaces (i.e., isc_app_xxx
+ * functions).  magic must be ISCAPI_APPMETHODS_MAGIC.
+ */
+typedef struct isc_appmethods {
+	void		(*ctxdestroy)(isc_appctx_t **ctxp);
+	isc_result_t	(*ctxstart)(isc_appctx_t *ctx);
+	isc_result_t	(*ctxrun)(isc_appctx_t *ctx);
+	isc_result_t	(*ctxsuspend)(isc_appctx_t *ctx);
+	isc_result_t	(*ctxshutdown)(isc_appctx_t *ctx);
+	void		(*ctxfinish)(isc_appctx_t *ctx);
+	void		(*settaskmgr)(isc_appctx_t *ctx,
+				      isc_taskmgr_t *timermgr);
+	void		(*setsocketmgr)(isc_appctx_t *ctx,
+					isc_socketmgr_t *timermgr);
+	void		(*settimermgr)(isc_appctx_t *ctx,
+				       isc_timermgr_t *timermgr);
+} isc_appmethods_t;
+
+/*%
+ * This structure is actually just the common prefix of an application context
+ * implementation's version of an isc_appctx_t.
+ * \brief
+ * Direct use of this structure by clients is forbidden.  app implementations
+ * may change the structure.  'magic' must be ISCAPI_APPCTX_MAGIC for any
+ * of the isc_app_ routines to work.  app implementations must maintain
+ * all app context invariants.
+ */
+struct isc_appctx {
+	unsigned int		impmagic;
+	unsigned int		magic;
+	isc_appmethods_t	*methods;
+};
+
+#define ISCAPI_APPCTX_MAGIC		ISC_MAGIC('A','a','p','c')
+#define ISCAPI_APPCTX_VALID(c)		((c) != NULL && \
+					 (c)->magic == ISCAPI_APPCTX_MAGIC)
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_app_ctxstart(isc_appctx_t *ctx);
+
+isc_result_t
+isc_app_start(void);
+/*!<
+ * \brief Start an ISC library application.
+ *
+ * Notes:
+ *	This call should be made before any other ISC library call, and as
+ *	close to the beginning of the application as possible.
+ *
+ * Requires:
+ *	'ctx' is a valid application context (for app_ctxstart()).
+ */
+
+isc_result_t
+isc_app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action,
+	      void *arg);
+/*!<
+ * \brief Request delivery of an event when the application is run.
+ *
+ * Requires:
+ *\li	isc_app_start() has been called.
+ *
+ * Returns:
+ *	ISC_R_SUCCESS
+ *	ISC_R_NOMEMORY
+ */
+
+isc_result_t
+isc_app_ctxrun(isc_appctx_t *ctx);
+
+isc_result_t
+isc_app_run(void);
+/*!<
+ * \brief Run an ISC library application.
+ *
+ * Notes:
+ *\li	The caller (typically the initial thread of an application) will
+ *	block until shutdown is requested.  When the call returns, the
+ *	caller should start shutting down the application.
+ *
+ * Requires:
+ *\li	isc_app_[ctx]start() has been called.
+ *
+ * Ensures:
+ *\li	Any events requested via isc_app_onrun() will have been posted (in
+ *	FIFO order) before isc_app_run() blocks.
+ *\li	'ctx' is a valid application context (for app_ctxrun()).
+ *
+ * Returns:
+ *\li	ISC_R_SUCCESS			Shutdown has been requested.
+ *\li	ISC_R_RELOAD			Reload has been requested.
+ */
+
+isc_result_t
+isc_app_ctxshutdown(isc_appctx_t *ctx);
+
+isc_result_t
+isc_app_shutdown(void);
+/*!<
+ * \brief Request application shutdown.
+ *
+ * Notes:
+ *\li	It is safe to call isc_app_shutdown() multiple times.  Shutdown will
+ *	only be triggered once.
+ *
+ * Requires:
+ *\li	isc_app_[ctx]run() has been called.
+ *\li	'ctx' is a valid application context (for app_ctxshutdown()).
+ *
+ * Returns:
+ *\li	ISC_R_SUCCESS
+ *\li	ISC_R_UNEXPECTED
+ */
+
+isc_result_t
+isc_app_ctxsuspend(isc_appctx_t *ctx);
+/*!<
+ * \brief This has the same behavior as isc_app_ctxsuspend().
+ */
+
+isc_result_t
+isc_app_reload(void);
+/*!<
+ * \brief Request application reload.
+ *
+ * Requires:
+ *\li	isc_app_run() has been called.
+ *
+ * Returns:
+ *\li	ISC_R_SUCCESS
+ *\li	ISC_R_UNEXPECTED
+ */
+
+void
+isc_app_ctxfinish(isc_appctx_t *ctx);
+
+void
+isc_app_finish(void);
+/*!<
+ * \brief Finish an ISC library application.
+ *
+ * Notes:
+ *\li	This call should be made at or near the end of main().
+ *
+ * Requires:
+ *\li	isc_app_start() has been called.
+ *\li	'ctx' is a valid application context (for app_ctxfinish()).
+ *
+ * Ensures:
+ *\li	Any resources allocated by isc_app_start() have been released.
+ */
+
+void
+isc_app_block(void);
+/*!<
+ * \brief Indicate that a blocking operation will be performed.
+ *
+ * Notes:
+ *\li	If a blocking operation is in process, a call to isc_app_shutdown()
+ *	or an external signal will abort the program, rather than allowing
+ *	clean shutdown.  This is primarily useful for reading user input.
+ *
+ * Requires:
+ * \li	isc_app_start() has been called.
+ * \li	No other blocking operations are in progress.
+ */
+
+void
+isc_app_unblock(void);
+/*!<
+ * \brief Indicate that a blocking operation is complete.
+ *
+ * Notes:
+ * \li	When a blocking operation has completed, return the program to a
+ * 	state where a call to isc_app_shutdown() or an external signal will
+ * 	shutdown normally.
+ *
+ * Requires:
+ * \li	isc_app_start() has been called.
+ * \li	isc_app_block() has been called by the same thread.
+ */
+
+isc_result_t
+isc_appctx_create(isc_mem_t *mctx, isc_appctx_t **ctxp);
+/*!<
+ * \brief Create an application context.
+ *
+ * Requires:
+ *\li	'mctx' is a valid memory context.
+ *\li	'ctxp' != NULL && *ctxp == NULL.
+ */
+
+void
+isc_appctx_destroy(isc_appctx_t **ctxp);
+/*!<
+ * \brief Destroy an application context.
+ *
+ * Requires:
+ *\li	'*ctxp' is a valid application context.
+ *
+ * Ensures:
+ *\li	*ctxp == NULL.
+ */
+
+void
+isc_appctx_settaskmgr(isc_appctx_t *ctx, isc_taskmgr_t *taskmgr);
+/*!<
+ * \brief Associate a task manager with an application context.
+ *
+ * This must be done before running tasks within the application context.
+ *
+ * Requires:
+ *\li	'ctx' is a valid application context.
+ *\li	'taskmgr' is a valid task manager.
+ */
+
+void
+isc_appctx_setsocketmgr(isc_appctx_t *ctx, isc_socketmgr_t *socketmgr);
+/*!<
+ * \brief Associate a socket manager with an application context.
+ *
+ * This must be done before handling socket events within the application
+ * context.
+ *
+ * Requires:
+ *\li	'ctx' is a valid application context.
+ *\li	'socketmgr' is a valid socket manager.
+ */
+
+void
+isc_appctx_settimermgr(isc_appctx_t *ctx, isc_timermgr_t *timermgr);
+/*!<
+ * \brief Associate a socket timer with an application context.
+ *
+ * This must be done before handling timer events within the application
+ * context.
+ *
+ * Requires:
+ *\li	'ctx' is a valid application context.
+ *\li	'timermgr' is a valid timer manager.
+ */
+
+#ifdef USE_APPIMPREGISTER
+/*%<
+ * See isc_appctx_create() above.
+ */
+typedef isc_result_t
+(*isc_appctxcreatefunc_t)(isc_mem_t *mctx, isc_appctx_t **ctxp);
+
+isc_result_t
+isc_app_register(isc_appctxcreatefunc_t createfunc);
+/*%<
+ * Register a new application implementation and add it to the list of
+ * supported implementations.  This function must be called when a different
+ * event library is used than the one contained in the ISC library.
+ */
+
+isc_result_t
+isc__app_register(void);
+/*%<
+ * A short cut function that specifies the application module in the ISC
+ * library for isc_app_register().  An application that uses the ISC library
+ * usually do not have to care about this function: it would call
+ * isc_lib_register(), which internally calls this function.
+ */
+#endif /* USE_APPIMPREGISTER */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_APP_H */
diff --git a/src/lib/bind9/include/isc/assertions.h b/src/lib/bind9/include/isc/assertions.h
new file mode 100644
index 0000000..91217b8
--- /dev/null
+++ b/src/lib/bind9/include/isc/assertions.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2004-2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1997-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * $Id: assertions.h,v 1.28 2009-09-29 23:48:04 tbox Exp $
+ */
+/*! \file isc/assertions.h
+ */
+
+#ifndef ISC_ASSERTIONS_H
+#define ISC_ASSERTIONS_H 1
+
+#include <isc/lang.h>
+#include <isc/platform.h>
+
+ISC_LANG_BEGINDECLS
+
+/*% isc assertion type */
+typedef enum {
+	isc_assertiontype_require,
+	isc_assertiontype_ensure,
+	isc_assertiontype_insist,
+	isc_assertiontype_invariant
+} isc_assertiontype_t;
+
+typedef void (*isc_assertioncallback_t)(const char *, int, isc_assertiontype_t,
+					const char *);
+
+/* coverity[+kill] */
+ISC_PLATFORM_NORETURN_PRE
+void isc_assertion_failed(const char *, int, isc_assertiontype_t,
+			  const char *) ISC_PLATFORM_NORETURN_POST;
+
+void
+isc_assertion_setcallback(isc_assertioncallback_t);
+
+const char *
+isc_assertion_typetotext(isc_assertiontype_t type);
+
+#if defined(ISC_CHECK_ALL) || defined(__COVERITY__)
+#define ISC_CHECK_REQUIRE		1
+#define ISC_CHECK_ENSURE		1
+#define ISC_CHECK_INSIST		1
+#define ISC_CHECK_INVARIANT		1
+#endif
+
+#if defined(ISC_CHECK_NONE) && !defined(__COVERITY__)
+#define ISC_CHECK_REQUIRE		0
+#define ISC_CHECK_ENSURE		0
+#define ISC_CHECK_INSIST		0
+#define ISC_CHECK_INVARIANT		0
+#endif
+
+#ifndef ISC_CHECK_REQUIRE
+#define ISC_CHECK_REQUIRE		1
+#endif
+
+#ifndef ISC_CHECK_ENSURE
+#define ISC_CHECK_ENSURE		1
+#endif
+
+#ifndef ISC_CHECK_INSIST
+#define ISC_CHECK_INSIST		1
+#endif
+
+#ifndef ISC_CHECK_INVARIANT
+#define ISC_CHECK_INVARIANT		1
+#endif
+
+#if ISC_CHECK_REQUIRE != 0
+#define ISC_REQUIRE(cond) \
+	((void) ((cond) || \
+		 ((isc_assertion_failed)(__FILE__, __LINE__, \
+					 isc_assertiontype_require, \
+					 #cond), 0)))
+#else
+#define ISC_REQUIRE(cond)	((void) 0)
+#endif /* ISC_CHECK_REQUIRE */
+
+#if ISC_CHECK_ENSURE != 0
+#define ISC_ENSURE(cond) \
+	((void) ((cond) || \
+		 ((isc_assertion_failed)(__FILE__, __LINE__, \
+					 isc_assertiontype_ensure, \
+					 #cond), 0)))
+#else
+#define ISC_ENSURE(cond)	((void) 0)
+#endif /* ISC_CHECK_ENSURE */
+
+#if ISC_CHECK_INSIST != 0
+#define ISC_INSIST(cond) \
+	((void) ((cond) || \
+		 ((isc_assertion_failed)(__FILE__, __LINE__, \
+					 isc_assertiontype_insist, \
+					 #cond), 0)))
+#else
+#define ISC_INSIST(cond)	((void) 0)
+#endif /* ISC_CHECK_INSIST */
+
+#if ISC_CHECK_INVARIANT != 0
+#define ISC_INVARIANT(cond) \
+	((void) ((cond) || \
+		 ((isc_assertion_failed)(__FILE__, __LINE__, \
+					 isc_assertiontype_invariant, \
+					 #cond), 0)))
+#else
+#define ISC_INVARIANT(cond)	((void) 0)
+#endif /* ISC_CHECK_INVARIANT */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_ASSERTIONS_H */
diff --git a/src/lib/bind9/include/isc/backtrace.h b/src/lib/bind9/include/isc/backtrace.h
new file mode 100644
index 0000000..94fee61
--- /dev/null
+++ b/src/lib/bind9/include/isc/backtrace.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2009  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: backtrace.h,v 1.2 2009-09-01 18:40:25 jinmei Exp $ */
+
+/*! \file isc/backtrace.h
+ * \brief provide a back trace of the running process to help debug problems.
+ *
+ * This module tries to get a back trace of the process using some platform
+ * dependent way when available.  It also manages an internal symbol table
+ * that maps function addresses used in the process to their textual symbols.
+ * This module is expected to be used to help debug when some fatal error
+ * happens.
+ *
+ * IMPORTANT NOTE: since the (major) intended use case of this module is
+ * dumping a back trace on a fatal error, normally followed by self termination,
+ * functions defined in this module generally doesn't employ assertion checks
+ * (if it did, a program bug could cause infinite recursive calls to a
+ * backtrace function).  These functions still perform minimal checks and return
+ * ISC_R_FAILURE if they detect an error, but the caller should therefore be
+ * very careful about the use of these functions, and generally discouraged to
+ * use them except in an exit path.  The exception is
+ * isc_backtrace_getsymbolfromindex(), which is expected to be used in a
+ * non-error-handling context and validates arguments with assertion checks.
+ */
+
+#ifndef ISC_BACKTRACE_H
+#define ISC_BACKTRACE_H 1
+
+/***
+ ***	Imports
+ ***/
+
+#include <isc/types.h>
+
+/***
+ *** Types
+ ***/
+struct isc_backtrace_symmap {
+	void		*addr;
+	const char	*symbol;
+};
+
+extern const int isc__backtrace_nsymbols;
+extern const isc_backtrace_symmap_t isc__backtrace_symtable[];
+
+/***
+ *** Functions
+ ***/
+
+ISC_LANG_BEGINDECLS
+isc_result_t
+isc_backtrace_gettrace(void **addrs, int maxaddrs, int *nframes);
+/*%<
+ * Get a back trace of the running process above this function itself.  On
+ * success, addrs[i] will store the address of the call point of the i-th
+ * stack frame (addrs[0] is the caller of this function).  *nframes will store
+ * the total number of frames.
+ *
+ * Requires (note that these are not ensured by assertion checks, see above):
+ *
+ *\li	'addrs' is a valid array containing at least 'maxaddrs' void * entries.
+ *
+ *\li	'nframes' must be non NULL.
+ *
+ * Returns:
+ *
+ *\li	#ISC_R_SUCCESS
+ *\li	#ISC_R_FAILURE
+ *\li	#ISC_R_NOTFOUND
+ *\li	#ISC_R_NOTIMPLEMENTED
+ */
+
+isc_result_t
+isc_backtrace_getsymbolfromindex(int index, const void **addrp,
+				 const char **symbolp);
+/*%<
+ * Returns the content of the internal symbol table of the given index.
+ * On success, *addrsp and *symbolp point to the address and the symbol of
+ * the 'index'th entry of the table, respectively.  If 'index' is not in the
+ * range of the symbol table, ISC_R_RANGE will be returned.
+ *
+ * Requires
+ *
+ *\li	'addrp' must be non NULL && '*addrp' == NULL.
+ *
+ *\li	'symbolp' must be non NULL && '*symbolp' == NULL.
+ *
+ * Returns:
+ *
+ *\li	#ISC_R_SUCCESS
+ *\li	#ISC_R_RANGE
+ */
+
+isc_result_t
+isc_backtrace_getsymbol(const void *addr, const char **symbolp,
+			unsigned long *offsetp);
+/*%<
+ * Searches the internal symbol table for the symbol that most matches the
+ * given 'addr'.  On success, '*symbolp' will point to the name of function
+ * to which the address 'addr' belong, and '*offsetp' will store the offset
+ * from the function's entry address to 'addr'.
+ *
+ * Requires (note that these are not ensured by assertion checks, see above):
+ *
+ *\li	'symbolp' must be non NULL && '*symbolp' == NULL.
+ *
+ *\li	'offsetp' must be non NULL.
+ *
+ * Returns:
+ *
+ *\li	#ISC_R_SUCCESS
+ *\li	#ISC_R_FAILURE
+ *\li	#ISC_R_NOTFOUND
+ */
+ISC_LANG_ENDDECLS
+
+#endif	/* ISC_BACKTRACE_H */
diff --git a/src/lib/bind9/include/isc/base32.h b/src/lib/bind9/include/isc/base32.h
new file mode 100644
index 0000000..884c724
--- /dev/null
+++ b/src/lib/bind9/include/isc/base32.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2008  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: base32.h,v 1.3 2008-09-25 04:02:39 tbox Exp $ */
+
+#ifndef ISC_BASE32_H
+#define ISC_BASE32_H 1
+
+/*! \file */
+
+/*
+ * Routines for manipulating base 32 and base 32 hex encoded data.
+ * Based on RFC 4648.
+ *
+ * Base 32 hex preserves the sort order of data when it is encoded /
+ * decoded.
+ */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/***
+ *** Functions
+ ***/
+
+isc_result_t
+isc_base32_totext(isc_region_t *source, int wordlength,
+		  const char *wordbreak, isc_buffer_t *target);
+isc_result_t
+isc_base32hex_totext(isc_region_t *source, int wordlength,
+		     const char *wordbreak, isc_buffer_t *target);
+/*!<
+ * \brief Convert data into base32 encoded text.
+ *
+ * Notes:
+ *\li	The base32 encoded text in 'target' will be divided into
+ *	words of at most 'wordlength' characters, separated by
+ * 	the 'wordbreak' string.  No parentheses will surround
+ *	the text.
+ *
+ * Requires:
+ *\li	'source' is a region containing binary data
+ *\li	'target' is a text buffer containing available space
+ *\li	'wordbreak' points to a null-terminated string of
+ *		zero or more whitespace characters
+ *
+ * Ensures:
+ *\li	target will contain the base32 encoded version of the data
+ *	in source.  The 'used' pointer in target will be advanced as
+ *	necessary.
+ */
+
+isc_result_t
+isc_base32_decodestring(const char *cstr, isc_buffer_t *target);
+isc_result_t
+isc_base32hex_decodestring(const char *cstr, isc_buffer_t *target);
+/*!<
+ * \brief Decode a null-terminated base32 string.
+ *
+ * Requires:
+ *\li	'cstr' is non-null.
+ *\li	'target' is a valid buffer.
+ *
+ * Returns:
+ *\li	#ISC_R_SUCCESS	-- the entire decoded representation of 'cstring'
+ *			   fit in 'target'.
+ *\li	#ISC_R_BADBASE32 -- 'cstr' is not a valid base32 encoding.
+ *
+ * 	Other error returns are any possible error code from:
+ *\li		isc_lex_create(),
+ *\li		isc_lex_openbuffer(),
+ *\li		isc_base32_tobuffer().
+ */
+
+isc_result_t
+isc_base32_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length);
+isc_result_t
+isc_base32hex_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length);
+/*!<
+ * \brief Convert base32 encoded text from a lexer context into data.
+ *
+ * Requires:
+ *\li	'lex' is a valid lexer context
+ *\li	'target' is a buffer containing binary data
+ *\li	'length' is an integer
+ *
+ * Ensures:
+ *\li	target will contain the data represented by the base32 encoded
+ *	string parsed by the lexer.  No more than length bytes will be read,
+ *	if length is positive.  The 'used' pointer in target will be
+ *	advanced as necessary.
+ */
+
+isc_result_t
+isc_base32_decoderegion(isc_region_t *source, isc_buffer_t *target);
+isc_result_t
+isc_base32hex_decoderegion(isc_region_t *source, isc_buffer_t *target);
+/*!<
+ * \brief Decode a packed (no white space permitted) base32 region.
+ *
+ * Requires:
+ *\li   'source' is a valid region.
+ *\li   'target' is a valid buffer.
+ *
+ * Returns:
+ *\li   #ISC_R_SUCCESS  -- the entire decoded representation of 'cstring'
+ *                         fit in 'target'.
+ *\li   #ISC_R_BADBASE32 -- 'source' is not a valid base32 encoding.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_BASE32_H */
diff --git a/src/lib/bind9/include/isc/base64.h b/src/lib/bind9/include/isc/base64.h
new file mode 100644
index 0000000..574e57d
--- /dev/null
+++ b/src/lib/bind9/include/isc/base64.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: base64.h,v 1.22 2007-06-19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_BASE64_H
+#define ISC_BASE64_H 1
+
+/*! \file isc/base64.h */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/***
+ *** Functions
+ ***/
+
+isc_result_t
+isc_base64_totext(isc_region_t *source, int wordlength,
+		  const char *wordbreak, isc_buffer_t *target);
+/*!<
+ * \brief Convert data into base64 encoded text.
+ *
+ * Notes:
+ *\li	The base64 encoded text in 'target' will be divided into
+ *	words of at most 'wordlength' characters, separated by
+ * 	the 'wordbreak' string.  No parentheses will surround
+ *	the text.
+ *
+ * Requires:
+ *\li	'source' is a region containing binary data
+ *\li	'target' is a text buffer containing available space
+ *\li	'wordbreak' points to a null-terminated string of
+ *		zero or more whitespace characters
+ *
+ * Ensures:
+ *\li	target will contain the base64 encoded version of the data
+ *	in source.  The 'used' pointer in target will be advanced as
+ *	necessary.
+ */
+
+isc_result_t
+isc_base64_decodestring(const char *cstr, isc_buffer_t *target);
+/*!<
+ * \brief Decode a null-terminated base64 string.
+ *
+ * Requires:
+ *\li	'cstr' is non-null.
+ *\li	'target' is a valid buffer.
+ *
+ * Returns:
+ *\li	#ISC_R_SUCCESS	-- the entire decoded representation of 'cstring'
+ *			   fit in 'target'.
+ *\li	#ISC_R_BADBASE64 -- 'cstr' is not a valid base64 encoding.
+ *
+ * 	Other error returns are any possible error code from:
+ *\li		isc_lex_create(),
+ *\li		isc_lex_openbuffer(),
+ *\li		isc_base64_tobuffer().
+ */
+
+isc_result_t
+isc_base64_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length);
+/*!<
+ * \brief Convert base64 encoded text from a lexer context into data.
+ *
+ * Requires:
+ *\li	'lex' is a valid lexer context
+ *\li	'target' is a buffer containing binary data
+ *\li	'length' is an integer
+ *
+ * Ensures:
+ *\li	target will contain the data represented by the base64 encoded
+ *	string parsed by the lexer.  No more than length bytes will be read,
+ *	if length is positive.  The 'used' pointer in target will be
+ *	advanced as necessary.
+ */
+
+
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_BASE64_H */
diff --git a/src/lib/bind9/include/isc/bind9.h b/src/lib/bind9/include/isc/bind9.h
new file mode 100644
index 0000000..dd75e91
--- /dev/null
+++ b/src/lib/bind9/include/isc/bind9.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2009  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: bind9.h,v 1.2 2009-12-05 23:31:41 each Exp $ */
+
+#ifndef ISC_BIND9_H
+#define ISC_BIND9_H 1
+
+/*
+ * This determines whether we are building BIND9 or using the exported
+ * libisc/libdns libraries.  The version of this file included in the
+ * standard BIND9 build defines BIND9; the version included with the
+ * exportable libraries does not.
+ */
+#define BIND9 1
+
+#endif /* ISC_BIND9_H */
diff --git a/src/lib/bind9/include/isc/bitstring.h b/src/lib/bind9/include/isc/bitstring.h
new file mode 100644
index 0000000..e280bc0
--- /dev/null
+++ b/src/lib/bind9/include/isc/bitstring.h
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: bitstring.h,v 1.14 2007-06-19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_BITSTRING_H
+#define ISC_BITSTRING_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file isc/bitstring.h
+ *
+ * \brief Bitstring manipulation functions.
+ *
+ * A bitstring is a packed array of bits, stored in a contiguous
+ * sequence of octets.  The "most significant bit" (msb) of a bitstring
+ * is the high bit of the first octet.  The "least significant bit" of a
+ * bitstring is the low bit of the last octet.
+ *
+ * Two bit numbering schemes are supported, "msb0" and "lsb0".
+ *
+ * In the "msb0" scheme, bit number 0 designates the most significant bit,
+ * and any padding bits required to make the bitstring a multiple of 8 bits
+ * long are added to the least significant end of the last octet.
+ *
+ * In the "lsb0" scheme, bit number 0 designates the least significant bit,
+ * and any padding bits required to make the bitstring a multiple of 8 bits
+ * long are added to the most significant end of the first octet.
+ *
+ * E.g., consider the bitstring "11010001111".  This bitstring is 11 bits
+ * long and will take two octets.  Let "p" denote a pad bit.  In the msb0
+ * encoding, it would be
+ *
+ * \verbatim
+ *             Octet 0           Octet 1
+ *                         |
+ *         1 1 0 1 0 0 0 1 | 1 1 1 p p p p p
+ *         ^               |               ^
+ *         |                               |
+ *         bit 0                           bit 15
+ * \endverbatim
+ *
+ * In the lsb0 encoding, it would be
+ *
+ * \verbatim
+ *             Octet 0           Octet 1
+ *                         |
+ *         p p p p p 1 1 0 | 1 0 0 0 1 1 1 1 
+ *         ^               |               ^
+ *         |                               |
+ *         bit 15                          bit 0
+ * \endverbatim
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/***
+ *** Types
+ ***/
+
+struct isc_bitstring {
+	unsigned int		magic;
+	unsigned char *		data;
+	unsigned int		length;
+	unsigned int		size;
+	isc_boolean_t		lsb0;
+};
+
+/***
+ *** Functions
+ ***/
+
+void
+isc_bitstring_init(isc_bitstring_t *bitstring, unsigned char *data,
+		   unsigned int length, unsigned int size, isc_boolean_t lsb0);
+/*!<
+ * \brief Make 'bitstring' refer to the bitstring of 'size' bits starting
+ * at 'data'.  'length' bits of the bitstring are valid.  If 'lsb0'
+ * is set then, bit 0 refers to the least significant bit of the
+ * bitstring.  Otherwise bit 0 is the most significant bit.
+ *
+ * Requires:
+ *
+ *\li	'bitstring' points to a isc_bitstring_t.
+ *
+ *\li	'data' points to an array of unsigned char large enough to hold
+ *	'size' bits.
+ *
+ *\li	'length' <= 'size'.
+ *
+ * Ensures:
+ *
+ *\li	'bitstring' is a valid bitstring.
+ */
+
+void
+isc_bitstring_invalidate(isc_bitstring_t *bitstring);
+/*!<
+ * \brief Invalidate 'bitstring'.
+ *
+ * Requires:
+ *
+ *\li	'bitstring' is a valid bitstring.
+ *
+ * Ensures:
+ *
+ *\li	'bitstring' is not a valid bitstring.
+ */
+
+void
+isc_bitstring_copy(isc_bitstring_t *source, unsigned int sbitpos,
+		   isc_bitstring_t *target, unsigned int tbitpos,
+		   unsigned int n);
+/*!<
+ * \brief Starting at bit 'sbitpos', copy 'n' bits from 'source' to
+ * the 'n' bits of 'target' starting at 'tbitpos'.
+ *
+ * Requires:
+ *
+ *\li	'source' and target are valid bitstrings with the same lsb0 setting.
+ *
+ *\li	'sbitpos' + 'n' is less than or equal to the length of 'source'.
+ *
+ *\li	'tbitpos' + 'n' is less than or equal to the size of 'target'.
+ *
+ * Ensures:
+ *
+ *\li	The specified bits have been copied, and the length of 'target'
+ *	adjusted (if required).
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_BITSTRING_H */
diff --git a/src/lib/bind9/include/isc/boolean.h b/src/lib/bind9/include/isc/boolean.h
new file mode 100644
index 0000000..45a0e57
--- /dev/null
+++ b/src/lib/bind9/include/isc/boolean.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: boolean.h,v 1.19 2007-06-19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_BOOLEAN_H
+#define ISC_BOOLEAN_H 1
+
+/*! \file isc/boolean.h */
+
+typedef enum { isc_boolean_false = 0, isc_boolean_true = 1 } isc_boolean_t;
+
+#define ISC_FALSE isc_boolean_false
+#define ISC_TRUE isc_boolean_true
+#define ISC_TF(x) ((x) ? ISC_TRUE : ISC_FALSE)
+
+#endif /* ISC_BOOLEAN_H */
diff --git a/src/lib/bind9/include/isc/buffer.h b/src/lib/bind9/include/isc/buffer.h
new file mode 100644
index 0000000..30a6e39
--- /dev/null
+++ b/src/lib/bind9/include/isc/buffer.h
@@ -0,0 +1,904 @@
+/*
+ * Copyright (C) 2004-2008, 2010  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2002  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: buffer.h,v 1.55 2010-12-20 23:47:21 tbox Exp $ */
+
+#ifndef ISC_BUFFER_H
+#define ISC_BUFFER_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file isc/buffer.h
+ *
+ * \brief A buffer is a region of memory, together with a set of related subregions.
+ * Buffers are used for parsing and I/O operations.
+ *
+ * The 'used region' and the 'available' region are disjoint, and their
+ * union is the buffer's region.  The used region extends from the beginning
+ * of the buffer region to the last used byte.  The available region
+ * extends from one byte greater than the last used byte to the end of the
+ * buffer's region.  The size of the used region can be changed using various
+ * buffer commands.  Initially, the used region is empty.
+ *
+ * The used region is further subdivided into two disjoint regions: the
+ * 'consumed region' and the 'remaining region'.  The union of these two
+ * regions is the used region.  The consumed region extends from the beginning
+ * of the used region to the byte before the 'current' offset (if any).  The
+ * 'remaining' region the current pointer to the end of the used
+ * region.  The size of the consumed region can be changed using various
+ * buffer commands.  Initially, the consumed region is empty.
+ *
+ * The 'active region' is an (optional) subregion of the remaining region.
+ * It extends from the current offset to an offset in the remaining region
+ * that is selected with isc_buffer_setactive().  Initially, the active region
+ * is empty.  If the current offset advances beyond the chosen offset, the
+ * active region will also be empty.
+ *
+ * \verbatim
+ *  /------------entire length---------------\
+ *  /----- used region -----\/-- available --\
+ *  +----------------------------------------+
+ *  | consumed  | remaining |                |
+ *  +----------------------------------------+
+ *  a           b     c     d                e
+ *
+ * a == base of buffer.
+ * b == current pointer.  Can be anywhere between a and d.
+ * c == active pointer.  Meaningful between b and d.
+ * d == used pointer.
+ * e == length of buffer.
+ *
+ * a-e == entire length of buffer.
+ * a-d == used region.
+ * a-b == consumed region.
+ * b-d == remaining region.
+ * b-c == optional active region.
+ *\endverbatim
+ *
+ * The following invariants are maintained by all routines:
+ *
+ *\code
+ *	length > 0
+ *
+ *	base is a valid pointer to length bytes of memory
+ *
+ *	0 <= used <= length
+ *
+ *	0 <= current <= used
+ *
+ *	0 <= active <= used
+ *	(although active < current implies empty active region)
+ *\endcode
+ *
+ * \li MP:
+ *	Buffers have no synchronization.  Clients must ensure exclusive
+ *	access.
+ *
+ * \li Reliability:
+ *	No anticipated impact.
+ *
+ * \li Resources:
+ *	Memory: 1 pointer + 6 unsigned integers per buffer.
+ *
+ * \li Security:
+ *	No anticipated impact.
+ *
+ * \li Standards:
+ *	None.
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/lang.h>
+#include <isc/magic.h>
+#include <isc/types.h>
+
+/*!
+ * To make many functions be inline macros (via \#define) define this.
+ * If it is undefined, a function will be used.
+ */
+/* #define ISC_BUFFER_USEINLINE */
+
+ISC_LANG_BEGINDECLS
+
+/*@{*/
+/*!
+ *** Magic numbers
+ ***/
+#define ISC_BUFFER_MAGIC		0x42756621U	/* Buf!. */
+#define ISC_BUFFER_VALID(b)		ISC_MAGIC_VALID(b, ISC_BUFFER_MAGIC)
+/*@}*/
+
+/*
+ * The following macros MUST be used only on valid buffers.  It is the
+ * caller's responsibility to ensure this by using the ISC_BUFFER_VALID
+ * check above, or by calling another isc_buffer_*() function (rather than
+ * another macro.)
+ */
+
+/*@{*/
+/*!
+ * Fundamental buffer elements.  (A through E in the introductory comment.)
+ */
+#define isc_buffer_base(b)    ((void *)(b)->base)			  /*a*/
+#define isc_buffer_current(b) \
+		((void *)((unsigned char *)(b)->base + (b)->current))     /*b*/
+#define isc_buffer_active(b)  \
+		((void *)((unsigned char *)(b)->base + (b)->active))      /*c*/
+#define isc_buffer_used(b)    \
+		((void *)((unsigned char *)(b)->base + (b)->used))        /*d*/
+#define isc_buffer_length(b)  ((b)->length)				  /*e*/
+/*@}*/
+
+/*@{*/
+/*!
+ * Derived lengths.  (Described in the introductory comment.)
+ */
+#define isc_buffer_usedlength(b)	((b)->used)		      /* d-a */
+#define isc_buffer_consumedlength(b)	((b)->current)		      /* b-a */
+#define isc_buffer_remaininglength(b)	((b)->used - (b)->current)    /* d-b */
+#define isc_buffer_activelength(b)	((b)->active - (b)->current)  /* c-b */
+#define isc_buffer_availablelength(b)	((b)->length - (b)->used)     /* e-d */
+/*@}*/
+
+/*!
+ * Note that the buffer structure is public.  This is principally so buffer
+ * operations can be implemented using macros.  Applications are strongly
+ * discouraged from directly manipulating the structure.
+ */
+
+struct isc_buffer {
+	unsigned int		magic;
+	void		       *base;
+	/*@{*/
+	/*! The following integers are byte offsets from 'base'. */
+	unsigned int		length;
+	unsigned int		used;
+	unsigned int 		current;
+	unsigned int 		active;
+	/*@}*/
+	/*! linkable */
+	ISC_LINK(isc_buffer_t)	link;
+	/*! private internal elements */
+	isc_mem_t	       *mctx;
+};
+
+/***
+ *** Functions
+ ***/
+
+isc_result_t
+isc_buffer_allocate(isc_mem_t *mctx, isc_buffer_t **dynbuffer,
+		    unsigned int length);
+/*!<
+ * \brief Allocate a dynamic linkable buffer which has "length" bytes in the
+ * data region.
+ *
+ * Requires:
+ *\li	"mctx" is valid.
+ *
+ *\li	"dynbuffer" is non-NULL, and "*dynbuffer" is NULL.
+ *
+ * Returns:
+ *\li	ISC_R_SUCCESS		- success
+ *\li	ISC_R_NOMEMORY		- no memory available
+ *
+ * Note:
+ *\li	Changing the buffer's length field is not permitted.
+ */
+
+void
+isc_buffer_free(isc_buffer_t **dynbuffer);
+/*!<
+ * \brief Release resources allocated for a dynamic buffer.
+ *
+ * Requires:
+ *\li	"dynbuffer" is not NULL.
+ *
+ *\li	"*dynbuffer" is a valid dynamic buffer.
+ *
+ * Ensures:
+ *\li	"*dynbuffer" will be NULL on return, and all memory associated with
+ *	the dynamic buffer is returned to the memory context used in
+ *	isc_buffer_allocate().
+ */
+
+void
+isc__buffer_init(isc_buffer_t *b, const void *base, unsigned int length);
+/*!<
+ * \brief Make 'b' refer to the 'length'-byte region starting at base.
+ *
+ * Requires:
+ *
+ *\li	'length' > 0
+ *
+ *\li	'base' is a pointer to a sequence of 'length' bytes.
+ *
+ */
+
+void
+isc__buffer_initnull(isc_buffer_t *b);
+/*!<
+ *\brief Initialize a buffer 'b' with a null data and zero length/
+ */
+
+void
+isc_buffer_reinit(isc_buffer_t *b, void *base, unsigned int length);
+/*!<
+ * \brief Make 'b' refer to the 'length'-byte region starting at base.
+ * Any existing data will be copied.
+ *
+ * Requires:
+ *
+ *\li	'length' > 0 AND length >= previous length
+ *
+ *\li	'base' is a pointer to a sequence of 'length' bytes.
+ *
+ */
+
+void
+isc__buffer_invalidate(isc_buffer_t *b);
+/*!<
+ * \brief Make 'b' an invalid buffer.
+ *
+ * Requires:
+ *\li	'b' is a valid buffer.
+ *
+ * Ensures:
+ *\li	If assertion checking is enabled, future attempts to use 'b' without
+ *	calling isc_buffer_init() on it will cause an assertion failure.
+ */
+
+void
+isc__buffer_region(isc_buffer_t *b, isc_region_t *r);
+/*!<
+ * \brief Make 'r' refer to the region of 'b'.
+ *
+ * Requires:
+ *
+ *\li	'b' is a valid buffer.
+ *
+ *\li	'r' points to a region structure.
+ */
+
+void
+isc__buffer_usedregion(isc_buffer_t *b, isc_region_t *r);
+/*!<
+ * \brief Make 'r' refer to the used region of 'b'.
+ *
+ * Requires:
+ *
+ *\li	'b' is a valid buffer.
+ *
+ *\li	'r' points to a region structure.
+ */
+
+void
+isc__buffer_availableregion(isc_buffer_t *b, isc_region_t *r);
+/*!<
+ * \brief Make 'r' refer to the available region of 'b'.
+ *
+ * Requires:
+ *
+ *\li	'b' is a valid buffer.
+ *
+ *\li	'r' points to a region structure.
+ */
+
+void
+isc__buffer_add(isc_buffer_t *b, unsigned int n);
+/*!<
+ * \brief Increase the 'used' region of 'b' by 'n' bytes.
+ *
+ * Requires:
+ *
+ *\li	'b' is a valid buffer
+ *
+ *\li	used + n <= length
+ *
+ */
+
+void
+isc__buffer_subtract(isc_buffer_t *b, unsigned int n);
+/*!<
+ * \brief Decrease the 'used' region of 'b' by 'n' bytes.
+ *
+ * Requires:
+ *
+ *\li	'b' is a valid buffer
+ *
+ *\li	used >= n
+ *
+ */
+
+void
+isc__buffer_clear(isc_buffer_t *b);
+/*!<
+ * \brief Make the used region empty.
+ *
+ * Requires:
+ *
+ *\li	'b' is a valid buffer
+ *
+ * Ensures:
+ *
+ *\li	used = 0
+ *
+ */
+
+void
+isc__buffer_consumedregion(isc_buffer_t *b, isc_region_t *r);
+/*!<
+ * \brief Make 'r' refer to the consumed region of 'b'.
+ *
+ * Requires:
+ *
+ *\li	'b' is a valid buffer.
+ *
+ *\li	'r' points to a region structure.
+ */
+
+void
+isc__buffer_remainingregion(isc_buffer_t *b, isc_region_t *r);
+/*!<
+ * \brief Make 'r' refer to the remaining region of 'b'.
+ *
+ * Requires:
+ *
+ *\li	'b' is a valid buffer.
+ *
+ *\li	'r' points to a region structure.
+ */
+
+void
+isc__buffer_activeregion(isc_buffer_t *b, isc_region_t *r);
+/*!<
+ * \brief Make 'r' refer to the active region of 'b'.
+ *
+ * Requires:
+ *
+ *\li	'b' is a valid buffer.
+ *
+ *\li	'r' points to a region structure.
+ */
+
+void
+isc__buffer_setactive(isc_buffer_t *b, unsigned int n);
+/*!<
+ * \brief Sets the end of the active region 'n' bytes after current.
+ *
+ * Requires:
+ *
+ *\li	'b' is a valid buffer.
+ *
+ *\li	current + n <= used
+ */
+
+void
+isc__buffer_first(isc_buffer_t *b);
+/*!<
+ * \brief Make the consumed region empty.
+ *
+ * Requires:
+ *
+ *\li	'b' is a valid buffer
+ *
+ * Ensures:
+ *
+ *\li	current == 0
+ *
+ */
+
+void
+isc__buffer_forward(isc_buffer_t *b, unsigned int n);
+/*!<
+ * \brief Increase the 'consumed' region of 'b' by 'n' bytes.
+ *
+ * Requires:
+ *
+ *\li	'b' is a valid buffer
+ *
+ *\li	current + n <= used
+ *
+ */
+
+void
+isc__buffer_back(isc_buffer_t *b, unsigned int n);
+/*!<
+ * \brief Decrease the 'consumed' region of 'b' by 'n' bytes.
+ *
+ * Requires:
+ *
+ *\li	'b' is a valid buffer
+ *
+ *\li	n <= current
+ *
+ */
+
+void
+isc_buffer_compact(isc_buffer_t *b);
+/*!<
+ * \brief Compact the used region by moving the remaining region so it occurs
+ * at the start of the buffer.  The used region is shrunk by the size of
+ * the consumed region, and the consumed region is then made empty.
+ *
+ * Requires:
+ *
+ *\li	'b' is a valid buffer
+ *
+ * Ensures:
+ *
+ *\li	current == 0
+ *
+ *\li	The size of the used region is now equal to the size of the remaining
+ *	region (as it was before the call).  The contents of the used region
+ *	are those of the remaining region (as it was before the call).
+ */
+
+isc_uint8_t
+isc_buffer_getuint8(isc_buffer_t *b);
+/*!<
+ * \brief Read an unsigned 8-bit integer from 'b' and return it.
+ *
+ * Requires:
+ *
+ *\li	'b' is a valid buffer.
+ *
+ *\li	The length of the available region of 'b' is at least 1.
+ *
+ * Ensures:
+ *
+ *\li	The current pointer in 'b' is advanced by 1.
+ *
+ * Returns:
+ *
+ *\li	A 8-bit unsigned integer.
+ */
+
+void
+isc__buffer_putuint8(isc_buffer_t *b, isc_uint8_t val);
+/*!<
+ * \brief Store an unsigned 8-bit integer from 'val' into 'b'.
+ *
+ * Requires:
+ *\li	'b' is a valid buffer.
+ *
+ *\li	The length of the unused region of 'b' is at least 1.
+ *
+ * Ensures:
+ *\li	The used pointer in 'b' is advanced by 1.
+ */
+
+isc_uint16_t
+isc_buffer_getuint16(isc_buffer_t *b);
+/*!<
+ * \brief Read an unsigned 16-bit integer in network byte order from 'b', convert
+ * it to host byte order, and return it.
+ *
+ * Requires:
+ *
+ *\li	'b' is a valid buffer.
+ *
+ *\li	The length of the available region of 'b' is at least 2.
+ *
+ * Ensures:
+ *
+ *\li	The current pointer in 'b' is advanced by 2.
+ *
+ * Returns:
+ *
+ *\li	A 16-bit unsigned integer.
+ */
+
+void
+isc__buffer_putuint16(isc_buffer_t *b, isc_uint16_t val);
+/*!<
+ * \brief Store an unsigned 16-bit integer in host byte order from 'val'
+ * into 'b' in network byte order.
+ *
+ * Requires:
+ *\li	'b' is a valid buffer.
+ *
+ *\li	The length of the unused region of 'b' is at least 2.
+ *
+ * Ensures:
+ *\li	The used pointer in 'b' is advanced by 2.
+ */
+
+isc_uint32_t
+isc_buffer_getuint32(isc_buffer_t *b);
+/*!<
+ * \brief Read an unsigned 32-bit integer in network byte order from 'b', convert
+ * it to host byte order, and return it.
+ *
+ * Requires:
+ *
+ *\li	'b' is a valid buffer.
+ *
+ *\li	The length of the available region of 'b' is at least 4.
+ *
+ * Ensures:
+ *
+ *\li	The current pointer in 'b' is advanced by 4.
+ *
+ * Returns:
+ *
+ *\li	A 32-bit unsigned integer.
+ */
+
+void
+isc__buffer_putuint32(isc_buffer_t *b, isc_uint32_t val);
+/*!<
+ * \brief Store an unsigned 32-bit integer in host byte order from 'val'
+ * into 'b' in network byte order.
+ *
+ * Requires:
+ *\li	'b' is a valid buffer.
+ *
+ *\li	The length of the unused region of 'b' is at least 4.
+ *
+ * Ensures:
+ *\li	The used pointer in 'b' is advanced by 4.
+ */
+
+isc_uint64_t
+isc_buffer_getuint48(isc_buffer_t *b);
+/*!<
+ * \brief Read an unsigned 48-bit integer in network byte order from 'b',
+ * convert it to host byte order, and return it.
+ *
+ * Requires:
+ *
+ *\li	'b' is a valid buffer.
+ *
+ *\li	The length of the available region of 'b' is at least 6.
+ *
+ * Ensures:
+ *
+ *\li	The current pointer in 'b' is advanced by 6.
+ *
+ * Returns:
+ *
+ *\li	A 48-bit unsigned integer (stored in a 64-bit integer).
+ */
+
+void
+isc__buffer_putuint48(isc_buffer_t *b, isc_uint64_t val);
+/*!<
+ * \brief Store an unsigned 48-bit integer in host byte order from 'val'
+ * into 'b' in network byte order.
+ *
+ * Requires:
+ *\li	'b' is a valid buffer.
+ *
+ *\li	The length of the unused region of 'b' is at least 6.
+ *
+ * Ensures:
+ *\li	The used pointer in 'b' is advanced by 6.
+ */
+
+void
+isc__buffer_putuint24(isc_buffer_t *b, isc_uint32_t val);
+/*!<
+ * Store an unsigned 24-bit integer in host byte order from 'val'
+ * into 'b' in network byte order.
+ *
+ * Requires:
+ *\li	'b' is a valid buffer.
+ *
+ *	The length of the unused region of 'b' is at least 3.
+ *
+ * Ensures:
+ *\li	The used pointer in 'b' is advanced by 3.
+ */
+
+void
+isc__buffer_putmem(isc_buffer_t *b, const unsigned char *base,
+		   unsigned int length);
+/*!<
+ * \brief Copy 'length' bytes of memory at 'base' into 'b'.
+ *
+ * Requires:
+ *\li	'b' is a valid buffer.
+ *
+ *\li	'base' points to 'length' bytes of valid memory.
+ *
+ */
+
+void
+isc__buffer_putstr(isc_buffer_t *b, const char *source);
+/*!<
+ * \brief Copy 'source' into 'b', not including terminating NUL.
+ *
+ * Requires:
+ *\li	'b' is a valid buffer.
+ *
+ *\li	'source' to be a valid NULL terminated string.
+ *
+ *\li	strlen(source) <= isc_buffer_available(b)
+ */
+
+isc_result_t
+isc_buffer_copyregion(isc_buffer_t *b, const isc_region_t *r);
+/*!<
+ * \brief Copy the contents of 'r' into 'b'.
+ *
+ * Requires:
+ *\li	'b' is a valid buffer.
+ *
+ *\li	'r' is a valid region.
+ *
+ * Returns:
+ *
+ *\li	ISC_R_SUCCESS
+ *\li	ISC_R_NOSPACE			The available region of 'b' is not
+ *					big enough.
+ */
+
+ISC_LANG_ENDDECLS
+
+/*
+ * Inline macro versions of the functions.  These should never be called
+ * directly by an application, but will be used by the functions within
+ * buffer.c.  The callers should always use "isc_buffer_*()" names, never
+ * ones beginning with "isc__"
+ */
+
+/*! \note
+ * XXXDCL Something more could be done with initializing buffers that
+ * point to const data.  For example, a new function, isc_buffer_initconst,
+ * could be used, and a new boolean flag in the buffer structure could
+ * indicate whether the buffer was initialized with that function.
+ * (isc_bufer_init itself would be reprototyped to *not* have its "base"
+ * parameter be const.)  Then if the boolean were true, the isc_buffer_put*
+ * functions could assert a contractual requirement for a non-const buffer.
+ * One drawback is that the isc_buffer_* functions (macros) that return
+ * pointers would still need to return non-const pointers to avoid compiler
+ * warnings, so it would be up to code that uses them to have to deal
+ * with the possibility that the buffer was initialized as const --
+ * a problem that they *already* have to deal with but have absolutely
+ * no ability to.  With a new isc_buffer_isconst() function returning
+ * true/false, they could at least assert a contractual requirement for
+ * non-const buffers when needed.
+ */
+#define ISC__BUFFER_INIT(_b, _base, _length) \
+	do { \
+		union { \
+			const void *	konst; \
+			void *		var; \
+		} _u; \
+		_u.konst = (_base); \
+		(_b)->base = _u.var; \
+		(_b)->length = (_length); \
+		(_b)->used = 0; \
+		(_b)->current = 0; \
+		(_b)->active = 0; \
+		(_b)->mctx = NULL; \
+		ISC_LINK_INIT(_b, link); \
+		(_b)->magic = ISC_BUFFER_MAGIC; \
+	} while (0)
+
+#define ISC__BUFFER_INITNULL(_b) ISC__BUFFER_INIT(_b, NULL, 0)
+
+#define ISC__BUFFER_INVALIDATE(_b) \
+	do { \
+		(_b)->magic = 0; \
+		(_b)->base = NULL; \
+		(_b)->length = 0; \
+		(_b)->used = 0; \
+		(_b)->current = 0; \
+		(_b)->active = 0; \
+	} while (0)
+
+#define ISC__BUFFER_REGION(_b, _r) \
+	do { \
+		(_r)->base = (_b)->base; \
+		(_r)->length = (_b)->length; \
+	} while (0)
+
+#define ISC__BUFFER_USEDREGION(_b, _r) \
+	do { \
+		(_r)->base = (_b)->base; \
+		(_r)->length = (_b)->used; \
+	} while (0)
+
+#define ISC__BUFFER_AVAILABLEREGION(_b, _r) \
+	do { \
+		(_r)->base = isc_buffer_used(_b); \
+		(_r)->length = isc_buffer_availablelength(_b); \
+	} while (0)
+
+#define ISC__BUFFER_ADD(_b, _n) \
+	do { \
+		(_b)->used += (_n); \
+	} while (0)
+
+#define ISC__BUFFER_SUBTRACT(_b, _n) \
+	do { \
+		(_b)->used -= (_n); \
+		if ((_b)->current > (_b)->used) \
+			(_b)->current = (_b)->used; \
+		if ((_b)->active > (_b)->used) \
+			(_b)->active = (_b)->used; \
+	} while (0)
+
+#define ISC__BUFFER_CLEAR(_b) \
+	do { \
+		(_b)->used = 0; \
+		(_b)->current = 0; \
+		(_b)->active = 0; \
+	} while (0)
+
+#define ISC__BUFFER_CONSUMEDREGION(_b, _r) \
+	do { \
+		(_r)->base = (_b)->base; \
+		(_r)->length = (_b)->current; \
+	} while (0)
+
+#define ISC__BUFFER_REMAININGREGION(_b, _r) \
+	do { \
+		(_r)->base = isc_buffer_current(_b); \
+		(_r)->length = isc_buffer_remaininglength(_b); \
+	} while (0)
+
+#define ISC__BUFFER_ACTIVEREGION(_b, _r) \
+	do { \
+		if ((_b)->current < (_b)->active) { \
+			(_r)->base = isc_buffer_current(_b); \
+			(_r)->length = isc_buffer_activelength(_b); \
+		} else { \
+			(_r)->base = NULL; \
+			(_r)->length = 0; \
+		} \
+	} while (0)
+
+#define ISC__BUFFER_SETACTIVE(_b, _n) \
+	do { \
+		(_b)->active = (_b)->current + (_n); \
+	} while (0)
+
+#define ISC__BUFFER_FIRST(_b) \
+	do { \
+		(_b)->current = 0; \
+	} while (0)
+
+#define ISC__BUFFER_FORWARD(_b, _n) \
+	do { \
+		(_b)->current += (_n); \
+	} while (0)
+
+#define ISC__BUFFER_BACK(_b, _n) \
+	do { \
+		(_b)->current -= (_n); \
+	} while (0)
+
+#define ISC__BUFFER_PUTMEM(_b, _base, _length) \
+	do { \
+		memcpy(isc_buffer_used(_b), (_base), (_length)); \
+		(_b)->used += (_length); \
+	} while (0)
+
+#define ISC__BUFFER_PUTSTR(_b, _source) \
+	do { \
+		unsigned int _length; \
+		unsigned char *_cp; \
+		_length = strlen(_source); \
+		_cp = isc_buffer_used(_b); \
+		memcpy(_cp, (_source), _length); \
+		(_b)->used += (_length); \
+	} while (0)
+
+#define ISC__BUFFER_PUTUINT8(_b, _val) \
+	do { \
+		unsigned char *_cp; \
+		isc_uint8_t _val2 = (_val); \
+		_cp = isc_buffer_used(_b); \
+		(_b)->used++; \
+		_cp[0] = _val2 & 0x00ff; \
+	} while (0)
+
+#define ISC__BUFFER_PUTUINT16(_b, _val) \
+	do { \
+		unsigned char *_cp; \
+		isc_uint16_t _val2 = (_val); \
+		_cp = isc_buffer_used(_b); \
+		(_b)->used += 2; \
+		_cp[0] = (unsigned char)((_val2 & 0xff00U) >> 8); \
+		_cp[1] = (unsigned char)(_val2 & 0x00ffU); \
+	} while (0)
+
+#define ISC__BUFFER_PUTUINT24(_b, _val) \
+	do { \
+		unsigned char *_cp; \
+		isc_uint32_t _val2 = (_val); \
+		_cp = isc_buffer_used(_b); \
+		(_b)->used += 3; \
+		_cp[0] = (unsigned char)((_val2 & 0xff0000U) >> 16); \
+		_cp[1] = (unsigned char)((_val2 & 0xff00U) >> 8); \
+		_cp[2] = (unsigned char)(_val2 & 0x00ffU); \
+	} while (0)
+
+#define ISC__BUFFER_PUTUINT32(_b, _val) \
+	do { \
+		unsigned char *_cp; \
+		isc_uint32_t _val2 = (_val); \
+		_cp = isc_buffer_used(_b); \
+		(_b)->used += 4; \
+		_cp[0] = (unsigned char)((_val2 & 0xff000000) >> 24); \
+		_cp[1] = (unsigned char)((_val2 & 0x00ff0000) >> 16); \
+		_cp[2] = (unsigned char)((_val2 & 0x0000ff00) >> 8); \
+		_cp[3] = (unsigned char)((_val2 & 0x000000ff)); \
+	} while (0)
+
+#if defined(ISC_BUFFER_USEINLINE)
+#define isc_buffer_init			ISC__BUFFER_INIT
+#define isc_buffer_initnull		ISC__BUFFER_INITNULL
+#define isc_buffer_invalidate		ISC__BUFFER_INVALIDATE
+#define isc_buffer_region		ISC__BUFFER_REGION
+#define isc_buffer_usedregion		ISC__BUFFER_USEDREGION
+#define isc_buffer_availableregion	ISC__BUFFER_AVAILABLEREGION
+#define isc_buffer_add			ISC__BUFFER_ADD
+#define isc_buffer_subtract		ISC__BUFFER_SUBTRACT
+#define isc_buffer_clear		ISC__BUFFER_CLEAR
+#define isc_buffer_consumedregion	ISC__BUFFER_CONSUMEDREGION
+#define isc_buffer_remainingregion	ISC__BUFFER_REMAININGREGION
+#define isc_buffer_activeregion		ISC__BUFFER_ACTIVEREGION
+#define isc_buffer_setactive		ISC__BUFFER_SETACTIVE
+#define isc_buffer_first		ISC__BUFFER_FIRST
+#define isc_buffer_forward		ISC__BUFFER_FORWARD
+#define isc_buffer_back			ISC__BUFFER_BACK
+#define isc_buffer_putmem		ISC__BUFFER_PUTMEM
+#define isc_buffer_putstr		ISC__BUFFER_PUTSTR
+#define isc_buffer_putuint8		ISC__BUFFER_PUTUINT8
+#define isc_buffer_putuint16		ISC__BUFFER_PUTUINT16
+#define isc_buffer_putuint24		ISC__BUFFER_PUTUINT24
+#define isc_buffer_putuint32		ISC__BUFFER_PUTUINT32
+#else
+#define isc_buffer_init			isc__buffer_init
+#define isc_buffer_initnull		isc__buffer_initnull
+#define isc_buffer_invalidate		isc__buffer_invalidate
+#define isc_buffer_region		isc__buffer_region
+#define isc_buffer_usedregion		isc__buffer_usedregion
+#define isc_buffer_availableregion	isc__buffer_availableregion
+#define isc_buffer_add			isc__buffer_add
+#define isc_buffer_subtract		isc__buffer_subtract
+#define isc_buffer_clear		isc__buffer_clear
+#define isc_buffer_consumedregion	isc__buffer_consumedregion
+#define isc_buffer_remainingregion	isc__buffer_remainingregion
+#define isc_buffer_activeregion		isc__buffer_activeregion
+#define isc_buffer_setactive		isc__buffer_setactive
+#define isc_buffer_first		isc__buffer_first
+#define isc_buffer_forward		isc__buffer_forward
+#define isc_buffer_back			isc__buffer_back
+#define isc_buffer_putmem		isc__buffer_putmem
+#define isc_buffer_putstr		isc__buffer_putstr
+#define isc_buffer_putuint8		isc__buffer_putuint8
+#define isc_buffer_putuint16		isc__buffer_putuint16
+#define isc_buffer_putuint24		isc__buffer_putuint24
+#define isc_buffer_putuint32		isc__buffer_putuint32
+#endif
+
+/*
+ * No inline method for this one (yet).
+ */
+#define isc_buffer_putuint48		isc__buffer_putuint48
+
+#endif /* ISC_BUFFER_H */
diff --git a/src/lib/bind9/include/isc/bufferlist.h b/src/lib/bind9/include/isc/bufferlist.h
new file mode 100644
index 0000000..99b0c8d
--- /dev/null
+++ b/src/lib/bind9/include/isc/bufferlist.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: bufferlist.h,v 1.17 2007-06-19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_BUFFERLIST_H
+#define ISC_BUFFERLIST_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file isc/bufferlist.h
+ *
+ *
+ *\brief	Buffer lists have no synchronization.  Clients must ensure exclusive
+ *	access.
+ *
+ * \li Reliability:
+ *	No anticipated impact.
+
+ * \li Security:
+ *	No anticipated impact.
+ *
+ * \li Standards:
+ *	None.
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/***
+ *** Functions
+ ***/
+
+unsigned int
+isc_bufferlist_usedcount(isc_bufferlist_t *bl);
+/*!<
+ * \brief Return the length of the sum of all used regions of all buffers in
+ * the buffer list 'bl'
+ *
+ * Requires:
+ *
+ *\li	'bl' is not NULL.
+ *
+ * Returns:
+ *\li	sum of all used regions' lengths.
+ */
+
+unsigned int
+isc_bufferlist_availablecount(isc_bufferlist_t *bl);
+/*!<
+ * \brief Return the length of the sum of all available regions of all buffers in
+ * the buffer list 'bl'
+ *
+ * Requires:
+ *
+ *\li	'bl' is not NULL.
+ *
+ * Returns:
+ *\li	sum of all available regions' lengths.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_BUFFERLIST_H */
diff --git a/src/lib/bind9/include/isc/commandline.h b/src/lib/bind9/include/isc/commandline.h
new file mode 100644
index 0000000..21ae1e5
--- /dev/null
+++ b/src/lib/bind9/include/isc/commandline.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: commandline.h,v 1.16 2007-06-19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_COMMANDLINE_H
+#define ISC_COMMANDLINE_H 1
+
+/*! \file isc/commandline.h */
+
+#include <isc/boolean.h>
+#include <isc/lang.h>
+#include <isc/platform.h>
+
+/*% Index into parent argv vector. */
+LIBISC_EXTERNAL_DATA extern int isc_commandline_index;
+/*% Character checked for validity. */
+LIBISC_EXTERNAL_DATA extern int isc_commandline_option;
+/*% Argument associated with option. */
+LIBISC_EXTERNAL_DATA extern char *isc_commandline_argument;
+/*% For printing error messages. */
+LIBISC_EXTERNAL_DATA extern char *isc_commandline_progname;
+/*% Print error message. */
+LIBISC_EXTERNAL_DATA extern isc_boolean_t isc_commandline_errprint;
+/*% Reset getopt. */
+LIBISC_EXTERNAL_DATA extern isc_boolean_t isc_commandline_reset;
+
+ISC_LANG_BEGINDECLS
+
+/*% parse command line */
+int
+isc_commandline_parse(int argc, char * const *argv, const char *options);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_COMMANDLINE_H */
diff --git a/src/lib/bind9/include/isc/entropy.h b/src/lib/bind9/include/isc/entropy.h
new file mode 100644
index 0000000..e115906
--- /dev/null
+++ b/src/lib/bind9/include/isc/entropy.h
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: entropy.h,v 1.35 2009-10-19 02:37:08 marka Exp $ */
+
+#ifndef ISC_ENTROPY_H
+#define ISC_ENTROPY_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file isc/entropy.h
+ * \brief The entropy API
+ *
+ * \li MP:
+ *	The entropy object is locked internally.  All callbacks into
+ *	application-provided functions (for setup, gathering, and
+ *	shutdown of sources) are guaranteed to be called with the
+ *	entropy API lock held.  This means these functions are
+ *	not permitted to call back into the entropy API.
+ *
+ * \li Reliability:
+ *	No anticipated impact.
+ *
+ * \li Resources:
+ *	A buffer, used as an entropy pool.
+ *
+ * \li Security:
+ *	While this code is believed to implement good entropy gathering
+ *	and distribution, it has not been reviewed by a cryptographic
+ *	expert.
+ *	Since the added entropy is only as good as the sources used,
+ *	this module could hand out bad data and never know it.
+ *
+ * \li Standards:
+ *	None.
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <stdio.h>
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+/*@{*/
+/*% Entropy callback function. */
+typedef isc_result_t (*isc_entropystart_t)(isc_entropysource_t *source,
+					   void *arg, isc_boolean_t blocking);
+typedef isc_result_t (*isc_entropyget_t)(isc_entropysource_t *source,
+					 void *arg, isc_boolean_t blocking);
+typedef void (*isc_entropystop_t)(isc_entropysource_t *source, void *arg);
+/*@}*/
+
+/***
+ *** Flags.
+ ***/
+
+/*!
+ * \brief
+ *	Extract only "good" data; return failure if there is not enough
+ *	data available and there are no sources which we can poll to get
+ *	data, or those sources are empty.
+ *
+ *
+ */
+#define ISC_ENTROPY_GOODONLY	0x00000001U
+/*!
+ * \brief
+ *	Extract as much good data as possible, but if there isn't enough
+ *	at hand, return what is available.  This flag only makes sense
+ *	when used with _GOODONLY.
+ */
+#define ISC_ENTROPY_PARTIAL	0x00000002U
+/*!
+ * \brief
+ *	Block the task until data is available.  This is contrary to the
+ *	ISC task system, where tasks should never block.  However, if
+ *	this is a special purpose application where blocking a task is
+ *	acceptable (say, an offline zone signer) this flag may be set.
+ *	This flag only makes sense when used with _GOODONLY, and will
+ *	block regardless of the setting for _PARTIAL.
+ */
+#define ISC_ENTROPY_BLOCKING	0x00000004U
+
+/*!
+ * \brief
+ *	Estimate the amount of entropy contained in the sample pool.
+ *	If this is not set, the source will be gathered and periodically
+ *	mixed into the entropy pool, but no increment in contained entropy
+ *	will be assumed.  This flag only makes sense on sample sources.
+ */
+#define ISC_ENTROPYSOURCE_ESTIMATE	0x00000001U
+
+/*
+ * For use with isc_entropy_usebestsource().
+ */
+/*!
+ * \brief
+ *	Use the keyboard as the only entropy source.
+ */
+#define ISC_ENTROPY_KEYBOARDYES		1
+/*!
+ * \brief
+ *	Never use the keyboard as an entropy source.
+ */
+#define ISC_ENTROPY_KEYBOARDNO		2
+/*!
+ * \brief
+ *	Use the keyboard as an entropy source only if opening the
+ *	random device fails.
+ */
+#define ISC_ENTROPY_KEYBOARDMAYBE	3
+
+ISC_LANG_BEGINDECLS
+
+/***
+ *** Functions
+ ***/
+
+isc_result_t
+isc_entropy_create(isc_mem_t *mctx, isc_entropy_t **entp);
+/*!<
+ * \brief Create a new entropy object.
+ */
+
+void
+isc_entropy_attach(isc_entropy_t *ent, isc_entropy_t **entp);
+/*!<
+ * Attaches to an entropy object.
+ */
+
+void
+isc_entropy_detach(isc_entropy_t **entp);
+/*!<
+ * \brief Detaches from an entropy object.
+ */
+
+isc_result_t
+isc_entropy_createfilesource(isc_entropy_t *ent, const char *fname);
+/*!<
+ * \brief Create a new entropy source from a file.
+ *
+ * The file is assumed to contain good randomness, and will be mixed directly
+ * into the pool with every byte adding 8 bits of entropy.
+ *
+ * The file will be put into non-blocking mode, so it may be a device file,
+ * such as /dev/random.  /dev/urandom should not be used here if it can
+ * be avoided, since it will always provide data even if it isn't good.
+ * We will make as much pseudorandom data as we need internally if our
+ * caller asks for it.
+ *
+ * If we hit end-of-file, we will stop reading from this source.  Callers
+ * who require strong random data will get failure when our pool drains.
+ * The file will never be opened/read again once EOF is reached.
+ */
+
+void
+isc_entropy_destroysource(isc_entropysource_t **sourcep);
+/*!<
+ * \brief Removes an entropy source from the entropy system.
+ */
+
+isc_result_t
+isc_entropy_createsamplesource(isc_entropy_t *ent,
+			       isc_entropysource_t **sourcep);
+/*!<
+ * \brief Create an entropy source that consists of samples.  Each sample is
+ * added to the source via isc_entropy_addsamples(), below.
+ */
+
+isc_result_t
+isc_entropy_createcallbacksource(isc_entropy_t *ent,
+				 isc_entropystart_t start,
+				 isc_entropyget_t get,
+				 isc_entropystop_t stop,
+				 void *arg,
+				 isc_entropysource_t **sourcep);
+/*!<
+ * \brief Create an entropy source that is polled via a callback.
+ *
+ * This would
+ * be used when keyboard input is used, or a GUI input method.  It can
+ * also be used to hook in any external entropy source.
+ *
+ * Samples are added via isc_entropy_addcallbacksample(), below.
+ * _addcallbacksample() is the only function which may be called from
+ * within an entropy API callback function.
+ */
+
+void
+isc_entropy_stopcallbacksources(isc_entropy_t *ent);
+/*!<
+ * \brief Call the stop functions for callback sources that have had their
+ * start functions called.
+ */
+
+/*@{*/
+isc_result_t
+isc_entropy_addcallbacksample(isc_entropysource_t *source, isc_uint32_t sample,
+			      isc_uint32_t extra);
+isc_result_t
+isc_entropy_addsample(isc_entropysource_t *source, isc_uint32_t sample,
+		      isc_uint32_t extra);
+/*!<
+ * \brief Add a sample to the sample source.
+ *
+ * The sample MUST be a timestamp
+ * that increases over time, with the exception of wrap-around for
+ * extremely high resolution timers which will quickly wrap-around
+ * a 32-bit integer.
+ *
+ * The "extra" parameter is used only to add a bit more unpredictable
+ * data.  It is not used other than included in the hash of samples.
+ *
+ * When in an entropy API callback function, _addcallbacksource() must be
+ * used.  At all other times, _addsample() must be used.
+ */
+/*@}*/
+
+isc_result_t
+isc_entropy_getdata(isc_entropy_t *ent, void *data, unsigned int length,
+		    unsigned int *returned, unsigned int flags);
+/*!<
+ * \brief Extract data from the entropy pool.  This may load the pool from various
+ * sources.
+ *
+ * Do this by stiring the pool and returning a part of hash as randomness.
+ * Note that no secrets are given away here since parts of the hash are
+ * xored together before returned.
+ *
+ * Honor the request from the caller to only return good data, any data,
+ * etc.
+ */
+
+void
+isc_entropy_putdata(isc_entropy_t *ent, void *data, unsigned int length,
+		    isc_uint32_t entropy);
+/*!<
+ * \brief Add "length" bytes in "data" to the entropy pool, incrementing the
+ * pool's entropy count by "entropy."
+ *
+ * These bytes will prime the pseudorandom portion even if no entropy is
+ * actually added.
+ */
+
+void
+isc_entropy_stats(isc_entropy_t *ent, FILE *out);
+/*!<
+ * \brief Dump some (trivial) stats to the stdio stream "out".
+ */
+
+unsigned int
+isc_entropy_status(isc_entropy_t *end);
+/*
+ * Returns the number of bits the pool currently contains.  This is just
+ * an estimate.
+ */
+
+isc_result_t
+isc_entropy_usebestsource(isc_entropy_t *ectx, isc_entropysource_t **source,
+			  const char *randomfile, int use_keyboard);
+/*!<
+ * \brief Use whatever source of entropy is best.
+ *
+ * Notes:
+ *\li	If "randomfile" is not NULL, open it with
+ *	isc_entropy_createfilesource().
+ *
+ *\li	If "randomfile" is NULL and the system's random device was detected
+ *	when the program was configured and built, open that device with
+ *	isc_entropy_createfilesource().
+ *
+ *\li	If "use_keyboard" is #ISC_ENTROPY_KEYBOARDYES, then always open
+ *	the keyboard as an entropy source (possibly in addition to
+ *	"randomfile" or the random device).
+ *
+ *\li	If "use_keyboard" is #ISC_ENTROPY_KEYBOARDMAYBE, open the keyboard only
+ *	if opening the random file/device fails.  A message will be
+ *	printed describing the need for keyboard input.
+ *
+ *\li	If "use_keyboard" is #ISC_ENTROPY_KEYBOARDNO, the keyboard will
+ *	never be opened.
+ *
+ * Returns:
+ *\li	#ISC_R_SUCCESS if at least one source of entropy could be started.
+ *
+ *\li	#ISC_R_NOENTROPY if use_keyboard is #ISC_ENTROPY_KEYBOARDNO and
+ *	there is no random device pathname compiled into the program.
+ *
+ *\li	A return code from isc_entropy_createfilesource() or
+ *	isc_entropy_createcallbacksource().
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_ENTROPY_H */
diff --git a/src/lib/bind9/include/isc/error.h b/src/lib/bind9/include/isc/error.h
new file mode 100644
index 0000000..d3dcc8b
--- /dev/null
+++ b/src/lib/bind9/include/isc/error.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: error.h,v 1.22 2009-09-29 23:48:04 tbox Exp $ */
+
+#ifndef ISC_ERROR_H
+#define ISC_ERROR_H 1
+
+/*! \file isc/error.h */
+
+#include <stdarg.h>
+
+#include <isc/formatcheck.h>
+#include <isc/lang.h>
+#include <isc/platform.h>
+
+ISC_LANG_BEGINDECLS
+
+typedef void (*isc_errorcallback_t)(const char *, int, const char *, va_list);
+
+/*% set unexpected error */
+void
+isc_error_setunexpected(isc_errorcallback_t);
+
+/*% set fatal error */
+void
+isc_error_setfatal(isc_errorcallback_t);
+
+/*% unexpected error */
+void
+isc_error_unexpected(const char *, int, const char *, ...)
+     ISC_FORMAT_PRINTF(3, 4);
+
+/*% fatal error */
+ISC_PLATFORM_NORETURN_PRE void
+isc_error_fatal(const char *, int, const char *, ...)
+ISC_FORMAT_PRINTF(3, 4) ISC_PLATFORM_NORETURN_POST;
+
+/*% runtimecheck error */
+void
+isc_error_runtimecheck(const char *, int, const char *);
+
+#define ISC_ERROR_RUNTIMECHECK(cond) \
+	((void) ((cond) || \
+		 ((isc_error_runtimecheck)(__FILE__, __LINE__, #cond), 0)))
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_ERROR_H */
diff --git a/src/lib/bind9/include/isc/event.h b/src/lib/bind9/include/isc/event.h
new file mode 100644
index 0000000..621edd8
--- /dev/null
+++ b/src/lib/bind9/include/isc/event.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2002  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: event.h,v 1.34 2007-06-19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_EVENT_H
+#define ISC_EVENT_H 1
+
+/*! \file isc/event.h */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+/*****
+ ***** Events.
+ *****/
+
+typedef void (*isc_eventdestructor_t)(isc_event_t *);
+
+#define ISC_EVENT_COMMON(ltype)		\
+	size_t				ev_size; \
+	unsigned int			ev_attributes; \
+	void *				ev_tag; \
+	isc_eventtype_t			ev_type; \
+	isc_taskaction_t		ev_action; \
+	void *				ev_arg; \
+	void *				ev_sender; \
+	isc_eventdestructor_t		ev_destroy; \
+	void *				ev_destroy_arg; \
+	ISC_LINK(ltype)			ev_link
+
+/*%
+ * Attributes matching a mask of 0x000000ff are reserved for the task library's
+ * definition.  Attributes of 0xffffff00 may be used by the application
+ * or non-ISC libraries.
+ */
+#define ISC_EVENTATTR_NOPURGE		0x00000001
+
+/*%
+ * The ISC_EVENTATTR_CANCELED attribute is intended to indicate
+ * that an event is delivered as a result of a canceled operation
+ * rather than successful completion, by mutual agreement
+ * between the sender and receiver.  It is not set or used by
+ * the task system.
+ */
+#define ISC_EVENTATTR_CANCELED		0x00000002
+
+#define ISC_EVENT_INIT(event, sz, at, ta, ty, ac, ar, sn, df, da) \
+do { \
+	(event)->ev_size = (sz); \
+	(event)->ev_attributes = (at); \
+	(event)->ev_tag = (ta); \
+	(event)->ev_type = (ty); \
+	(event)->ev_action = (ac); \
+	(event)->ev_arg = (ar); \
+	(event)->ev_sender = (sn); \
+	(event)->ev_destroy = (df); \
+	(event)->ev_destroy_arg = (da); \
+	ISC_LINK_INIT((event), ev_link); \
+} while (0)
+
+/*%
+ * This structure is public because "subclassing" it may be useful when
+ * defining new event types.
+ */
+struct isc_event {
+	ISC_EVENT_COMMON(struct isc_event);
+};
+
+#define ISC_EVENTTYPE_FIRSTEVENT	0x00000000
+#define ISC_EVENTTYPE_LASTEVENT		0xffffffff
+
+#define ISC_EVENT_PTR(p) ((isc_event_t **)(void *)(p))
+
+ISC_LANG_BEGINDECLS
+
+isc_event_t *
+isc_event_allocate(isc_mem_t *mctx, void *sender, isc_eventtype_t type,
+		   isc_taskaction_t action, const void *arg, size_t size);
+/*%<
+ * Allocate an event structure. 
+ *
+ * Allocate and initialize in a structure with initial elements
+ * defined by:
+ *
+ * \code
+ *	struct {
+ *		ISC_EVENT_COMMON(struct isc_event);
+ *		...
+ *	};
+ * \endcode
+ *	
+ * Requires:
+ *\li	'size' >= sizeof(struct isc_event)
+ *\li	'action' to be non NULL
+ *
+ * Returns:
+ *\li	a pointer to a initialized structure of the requested size.
+ *\li	NULL if unable to allocate memory.
+ */
+
+void
+isc_event_free(isc_event_t **);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_EVENT_H */
diff --git a/src/lib/bind9/include/isc/eventclass.h b/src/lib/bind9/include/isc/eventclass.h
new file mode 100644
index 0000000..97aed78
--- /dev/null
+++ b/src/lib/bind9/include/isc/eventclass.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: eventclass.h,v 1.18 2007-06-19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_EVENTCLASS_H
+#define ISC_EVENTCLASS_H 1
+
+/*! \file isc/eventclass.h
+ ***** Registry of Predefined Event Type Classes
+ *****/
+
+/*%
+ * An event class is an unsigned 16 bit number.  Each class may contain up
+ * to 65536 events.  An event type is formed by adding the event number
+ * within the class to the class number.
+ *
+ */
+
+#define ISC_EVENTCLASS(eclass)		((eclass) << 16)
+
+/*@{*/
+/*!
+ * Classes < 1024 are reserved for ISC use.
+ * Event classes >= 1024 and <= 65535 are reserved for application use.
+ */
+
+#define	ISC_EVENTCLASS_TASK		ISC_EVENTCLASS(0)
+#define	ISC_EVENTCLASS_TIMER		ISC_EVENTCLASS(1)
+#define	ISC_EVENTCLASS_SOCKET		ISC_EVENTCLASS(2)
+#define	ISC_EVENTCLASS_FILE		ISC_EVENTCLASS(3)
+#define	ISC_EVENTCLASS_DNS		ISC_EVENTCLASS(4)
+#define	ISC_EVENTCLASS_APP		ISC_EVENTCLASS(5)
+#define	ISC_EVENTCLASS_OMAPI		ISC_EVENTCLASS(6)
+#define	ISC_EVENTCLASS_RATELIMITER	ISC_EVENTCLASS(7)
+#define	ISC_EVENTCLASS_ISCCC		ISC_EVENTCLASS(8)
+/*@}*/
+
+#endif /* ISC_EVENTCLASS_H */
diff --git a/src/lib/bind9/include/isc/file.h b/src/lib/bind9/include/isc/file.h
new file mode 100644
index 0000000..9087990
--- /dev/null
+++ b/src/lib/bind9/include/isc/file.h
@@ -0,0 +1,304 @@
+/*
+ * Copyright (C) 2004-2007, 2009, 2011  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: file.h,v 1.39.10.2 2011-03-04 23:47:28 tbox Exp $ */
+
+#ifndef ISC_FILE_H
+#define ISC_FILE_H 1
+
+/*! \file isc/file.h */
+
+#include <stdio.h>
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_file_settime(const char *file, isc_time_t *time);
+
+isc_result_t
+isc_file_getmodtime(const char *file, isc_time_t *time);
+/*!<
+ * \brief Get the time of last modification of a file.
+ *
+ * Notes:
+ *\li	The time that is set is relative to the (OS-specific) epoch, as are
+ *	all isc_time_t structures.
+ *
+ * Requires:
+ *\li	file != NULL.
+ *\li	time != NULL.
+ *
+ * Ensures:
+ *\li	If the file could not be accessed, 'time' is unchanged.
+ *
+ * Returns:
+ *\li	#ISC_R_SUCCESS
+ *		Success.
+ *\li	#ISC_R_NOTFOUND
+ *		No such file exists.
+ *\li	#ISC_R_INVALIDFILE
+ *		The path specified was not usable by the operating system.
+ *\li	#ISC_R_NOPERM
+ *		The file's metainformation could not be retrieved because
+ *		permission was denied to some part of the file's path.
+ *\li	#ISC_R_EIO
+ *		Hardware error interacting with the filesystem.
+ *\li	#ISC_R_UNEXPECTED
+ *		Something totally unexpected happened.
+ *
+ */
+
+isc_result_t
+isc_file_mktemplate(const char *path, char *buf, size_t buflen);
+/*!<
+ * \brief Generate a template string suitable for use with isc_file_openunique().
+ *
+ * Notes:
+ *\li	This function is intended to make creating temporary files
+ *	portable between different operating systems.
+ *
+ *\li	The path is prepended to an implementation-defined string and
+ *	placed into buf.  The string has no path characters in it,
+ *	and its maximum length is 14 characters plus a NUL.  Thus
+ *	buflen should be at least strlen(path) + 15 characters or
+ *	an error will be returned.
+ *
+ * Requires:
+ *\li	buf != NULL.
+ *
+ * Ensures:
+ *\li	If result == #ISC_R_SUCCESS:
+ *		buf contains a string suitable for use as the template argument
+ *		to isc_file_openunique().
+ *
+ *\li	If result != #ISC_R_SUCCESS:
+ *		buf is unchanged.
+ *
+ * Returns:
+ *\li	#ISC_R_SUCCESS 	Success.
+ *\li	#ISC_R_NOSPACE	buflen indicates buf is too small for the catenation
+ *				of the path with the internal template string.
+ */
+
+
+isc_result_t
+isc_file_openunique(char *templet, FILE **fp);
+isc_result_t
+isc_file_openuniqueprivate(char *templet, FILE **fp);
+isc_result_t
+isc_file_openuniquemode(char *templet, int mode, FILE **fp);
+/*!<
+ * \brief Create and open a file with a unique name based on 'templet'.
+ *
+ * Notes:
+ *\li	'template' is a reserved work in C++.  If you want to complain
+ *	about the spelling of 'templet', first look it up in the
+ *	Merriam-Webster English dictionary. (http://www.m-w.com/)
+ *
+ *\li	This function works by using the template to generate file names.
+ *	The template must be a writable string, as it is modified in place.
+ *	Trailing X characters in the file name (full file name on Unix,
+ *	basename on Win32 -- eg, tmp-XXXXXX vs XXXXXX.tmp, respectively)
+ *	are replaced with ASCII characters until a non-existent filename
+ *	is found.  If the template does not include pathname information,
+ *	the files in the working directory of the program are searched.
+ *
+ *\li	isc_file_mktemplate is a good, portable way to get a template.
+ *
+ * Requires:
+ *\li	'fp' is non-NULL and '*fp' is NULL.
+ *
+ *\li	'template' is non-NULL, and of a form suitable for use by
+ *	the system as described above.
+ *
+ * Ensures:
+ *\li	If result is #ISC_R_SUCCESS:
+ *		*fp points to an stream opening in stdio's "w+" mode.
+ *
+ *\li	If result is not #ISC_R_SUCCESS:
+ *		*fp is NULL.
+ *
+ *		No file is open.  Even if one was created (but unable
+ *		to be reopened as a stdio FILE pointer) then it has been
+ *		removed.
+ *
+ *\li	This function does *not* ensure that the template string has not been
+ *	modified, even if the operation was unsuccessful.
+ *
+ * Returns:
+ *\li	#ISC_R_SUCCESS
+ *		Success.
+ *\li	#ISC_R_EXISTS
+ *		No file with a unique name could be created based on the
+ *		template.
+ *\li	#ISC_R_INVALIDFILE
+ *		The path specified was not usable by the operating system.
+ *\li	#ISC_R_NOPERM
+ *		The file could not be created because permission was denied
+ *		to some part of the file's path.
+ *\li	#ISC_R_IOERROR
+ *		Hardware error interacting with the filesystem.
+ *\li	#ISC_R_UNEXPECTED
+ *		Something totally unexpected happened.
+ */
+
+isc_result_t
+isc_file_remove(const char *filename);
+/*!<
+ * \brief Remove the file named by 'filename'.
+ */
+
+isc_result_t
+isc_file_rename(const char *oldname, const char *newname);
+/*!<
+ * \brief Rename the file 'oldname' to 'newname'.
+ */
+
+isc_boolean_t
+isc_file_exists(const char *pathname);
+/*!<
+ * \brief Return #ISC_TRUE if the calling process can tell that the given file exists.
+ * Will not return true if the calling process has insufficient privileges
+ * to search the entire path.
+ */
+
+isc_boolean_t
+isc_file_isabsolute(const char *filename);
+/*!<
+ * \brief Return #ISC_TRUE if the given file name is absolute.
+ */
+
+isc_result_t
+isc_file_isplainfile(const char *name);
+/*!<
+ * \brief Check that the file is a plain file
+ *
+ * Returns:
+ *\li	#ISC_R_SUCCESS
+ *		Success. The file is a plain file.
+ *\li	#ISC_R_INVALIDFILE
+ *		The path specified was not usable by the operating system.
+ *\li	#ISC_R_FILENOTFOUND
+ *		The file does not exist. This return code comes from
+ *		errno=ENOENT when stat returns -1. This code is mentioned
+ *		here, because in logconf.c, it is the one rcode that is
+ *		permitted in addition to ISC_R_SUCCESS. This is done since
+ *		the next call in logconf.c is to isc_stdio_open(), which
+ *		will create the file if it can.
+ *\li	#other ISC_R_* errors translated from errno
+ *		These occur when stat returns -1 and an errno.
+ */
+
+isc_boolean_t
+isc_file_iscurrentdir(const char *filename);
+/*!<
+ * \brief Return #ISC_TRUE if the given file name is the current directory (".").
+ */
+
+isc_boolean_t
+isc_file_ischdiridempotent(const char *filename);
+/*%<
+ * Return #ISC_TRUE if calling chdir(filename) multiple times will give
+ * the same result as calling it once.
+ */
+
+const char *
+isc_file_basename(const char *filename);
+/*%<
+ * Return the final component of the path in the file name.
+ */
+
+isc_result_t
+isc_file_progname(const char *filename, char *buf, size_t buflen);
+/*!<
+ * \brief Given an operating system specific file name "filename"
+ * referring to a program, return the canonical program name.
+ *
+ *
+ * Any directory prefix or executable file name extension (if
+ * used on the OS in case) is stripped.  On systems where program
+ * names are case insensitive, the name is canonicalized to all
+ * lower case.  The name is written to 'buf', an array of 'buflen'
+ * chars, and null terminated.
+ *
+ * Returns:
+ *\li	#ISC_R_SUCCESS
+ *\li	#ISC_R_NOSPACE 	The name did not fit in 'buf'.
+ */
+
+isc_result_t
+isc_file_template(const char *path, const char *templet, char *buf,
+		  size_t buflen);
+/*%<
+ * Create an OS specific template using 'path' to define the directory
+ * 'templet' to describe the filename and store the result in 'buf'
+ * such that path can be renamed to buf atomically.
+ */
+
+isc_result_t
+isc_file_renameunique(const char *file, char *templet);
+/*%<
+ * Rename 'file' using 'templet' as a template for the new file name.
+ */
+
+isc_result_t
+isc_file_absolutepath(const char *filename, char *path, size_t pathlen);
+/*%<
+ * Given a file name, return the fully qualified path to the file.
+ */
+
+/*
+ * XXX We should also have a isc_file_writeeopen() function
+ * for safely open a file in a publicly writable directory
+ * (see write_open() in BIND 8's ns_config.c).
+ */
+
+isc_result_t
+isc_file_truncate(const char *filename, isc_offset_t size);
+/*%<
+ * Truncate/extend the file specified to 'size' bytes.
+ */
+
+isc_result_t
+isc_file_safecreate(const char *filename, FILE **fp);
+/*%<
+ * Open 'filename' for writing, truncating if necessary.  Ensure that
+ * if it existed it was a normal file.  If creating the file, ensure
+ * that only the owner can read/write it.
+ */
+
+isc_result_t
+isc_file_splitpath(isc_mem_t *mctx, char *path,
+		   char **dirname, char **basename);
+/*%<
+ * Split a path into dirname and basename.  If 'path' contains no slash
+ * (or, on windows, backslash), then '*dirname' is set to ".".
+ *
+ * Allocates memory for '*dirname', which can be freed with isc_mem_free().
+ *
+ * Returns:
+ * - ISC_R_SUCCESS on success
+ * - ISC_R_INVALIDFILE if 'path' is empty or ends with '/'
+ * - ISC_R_NOMEMORY if unable to allocate memory
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_FILE_H */
diff --git a/src/lib/bind9/include/isc/formatcheck.h b/src/lib/bind9/include/isc/formatcheck.h
new file mode 100644
index 0000000..213374e
--- /dev/null
+++ b/src/lib/bind9/include/isc/formatcheck.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: formatcheck.h,v 1.13 2007-06-19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_FORMATCHECK_H
+#define ISC_FORMATCHECK_H 1
+
+/*! \file isc/formatcheck.h */
+
+/*%
+ * ISC_FORMAT_PRINTF().
+ *
+ * \li fmt is the location of the format string parameter.
+ * \li args is the location of the first argument (or 0 for no argument checking).
+ * 
+ * Note:
+ * \li The first parameter is 1, not 0.
+ */
+#ifdef __GNUC__
+#define ISC_FORMAT_PRINTF(fmt, args) __attribute__((__format__(__printf__, fmt, args)))
+#else
+#define ISC_FORMAT_PRINTF(fmt, args)
+#endif
+
+#endif /* ISC_FORMATCHECK_H */
diff --git a/src/lib/bind9/include/isc/fsaccess.h b/src/lib/bind9/include/isc/fsaccess.h
new file mode 100644
index 0000000..9758242
--- /dev/null
+++ b/src/lib/bind9/include/isc/fsaccess.h
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: fsaccess.h,v 1.16 2009-01-17 23:47:43 tbox Exp $ */
+
+#ifndef ISC_FSACCESS_H
+#define ISC_FSACCESS_H 1
+
+/*! \file isc/fsaccess.h
+ * \brief The ISC filesystem access module encapsulates the setting of file
+ * and directory access permissions into one API that is meant to be
+ * portable to multiple operating systems.
+ *
+ * The two primary operating system flavors that are initially accommodated
+ * are POSIX and Windows NT 4.0 and later.  The Windows NT access model is
+ * considerable more flexible than POSIX's model (as much as I am loathe to
+ * admit it), and so the ISC API has a higher degree of complexity than would
+ * be needed to simply address POSIX's needs.
+ *
+ * The full breadth of NT's flexibility is not available either, for the
+ * present time.  Much of it is to provide compatibility with what Unix
+ * programmers are expecting.  This is also due to not yet really needing all
+ * of the functionality of an NT system (or, for that matter, a POSIX system)
+ * in BIND9, and so resolving how to handle the various incompatibilities has
+ * been a purely theoretical exercise with no operational experience to
+ * indicate how flawed the thinking may be.
+ *
+ * Some of the more notable dumbing down of NT for this API includes:
+ *
+ *\li   Each of FILE_READ_DATA and FILE_READ_EA are set with #ISC_FSACCESS_READ.
+ *
+ * \li  All of FILE_WRITE_DATA, FILE_WRITE_EA and FILE_APPEND_DATA are
+ *     set with #ISC_FSACCESS_WRITE.  FILE_WRITE_ATTRIBUTES is not set
+ *     so as to be consistent with Unix, where only the owner of the file
+ *     or the superuser can change the attributes/mode of a file.
+ *
+ * \li  Both of FILE_ADD_FILE and FILE_ADD_SUBDIRECTORY are set with
+ *     #ISC_FSACCESS_CREATECHILD.  This is similar to setting the WRITE
+ *     permission on a Unix directory.
+ *
+ * \li  SYNCHRONIZE is always set for files and directories, unless someone
+ *     can give me a reason why this is a bad idea.
+ *
+ * \li  READ_CONTROL and FILE_READ_ATTRIBUTES are always set; this is
+ *     consistent with Unix, where any file or directory can be stat()'d
+ *     unless the directory path disallows complete access somewhere along
+ *     the way.
+ *
+ * \li  WRITE_DAC is only set for the owner.  This too is consistent with
+ *     Unix, and is tighter security than allowing anyone else to be
+ *     able to set permissions.
+ *
+ * \li  DELETE is only set for the owner.  On Unix the ability to delete
+ *     a file is controlled by the directory permissions, but it isn't
+ *     currently clear to me what happens on NT if the directory has
+ *     FILE_DELETE_CHILD set but a file within it does not have DELETE
+ *     set.  Always setting DELETE on the file/directory for the owner
+ *     gives maximum flexibility to the owner without exposing the
+ *     file to deletion by others.
+ *
+ * \li  WRITE_OWNER is never set.  This too is consistent with Unix,
+ *     and is also tighter security than allowing anyone to change the
+ *     ownership of the file apart from the superu..ahem, Administrator.
+ *
+ * \li  Inheritance is set to NO_INHERITANCE.
+ *
+ * Unix's dumbing down includes:
+ *
+ * \li  The sticky bit cannot be set.
+ *
+ * \li  setuid and setgid cannot be set.
+ *
+ * \li  Only regular files and directories can be set.
+ *
+ * The rest of this comment discusses a few of the incompatibilities
+ * between the two systems that need more thought if this API is to
+ * be extended to accommodate them.
+ *
+ * The Windows standard access right "DELETE" doesn't have a direct
+ * equivalent in the Unix world, so it isn't clear what should be done
+ * with it.
+ *
+ * The Unix sticky bit is not supported.  While NT does have a concept
+ * of allowing users to create files in a directory but not delete or
+ * rename them, it does not have a concept of allowing them to be deleted
+ * if they are owned by the user trying to delete/rename.  While it is
+ * probable that something could be cobbled together in NT 5 with inheritance,
+ * it can't really be done in NT 4 as a single property that you could
+ * set on a directory.  You'd need to coordinate something with file creation
+ * so that every file created had DELETE set for the owner but noone else.
+ *
+ * On Unix systems, setting #ISC_FSACCESS_LISTDIRECTORY sets READ.
+ * ... setting either #ISC_FSACCESS_CREATECHILD or #ISC_FSACCESS_DELETECHILD
+ *      sets WRITE.
+ * ... setting #ISC_FSACCESS_ACCESSCHILD sets EXECUTE.
+ *
+ * On NT systems, setting #ISC_FSACCESS_LISTDIRECTORY sets FILE_LIST_DIRECTORY.
+ * ... setting #ISC_FSACCESS_CREATECHILD sets FILE_CREATE_CHILD independently.
+ * ... setting #ISC_FSACCESS_DELETECHILD sets FILE_DELETE_CHILD independently.
+ * ... setting #ISC_FSACCESS_ACCESSCHILD sets FILE_TRAVERSE.
+ *
+ * Unresolved:							XXXDCL
+ * \li  What NT access right controls the ability to rename a file?
+ * \li  How does DELETE work?  If a directory has FILE_DELETE_CHILD but a
+ *      file or directory within it does not have DELETE, is that file
+ *	or directory deletable?
+ * \li  To implement isc_fsaccess_get(), mapping an existing Unix permission
+ * 	mode_t back to an isc_fsaccess_t is pretty trivial; however, mapping
+ *	an NT DACL could be impossible to do in a responsible way.
+ * \li  Similarly, trying to implement the functionality of being able to
+ *	say "add group writability to whatever permissions already exist"
+ *	could be tricky on NT because of the order-of-entry issue combined
+ *	with possibly having one or more matching ACEs already explicitly
+ *	granting or denying access.  Because this functionality is
+ *	not yet needed by the ISC, no code has been written to try to
+ * 	solve this problem.
+ */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+/*
+ * Trustees.
+ */
+#define ISC_FSACCESS_OWNER	0x1 /*%< User account. */
+#define ISC_FSACCESS_GROUP	0x2 /*%< Primary group owner. */
+#define ISC_FSACCESS_OTHER	0x4 /*%< Not the owner or the group owner. */
+#define ISC_FSACCESS_WORLD	0x7 /*%< User, Group, Other. */
+
+/*
+ * Types of permission.
+ */
+#define ISC_FSACCESS_READ		0x00000001 /*%< File only. */
+#define ISC_FSACCESS_WRITE		0x00000002 /*%< File only. */
+#define ISC_FSACCESS_EXECUTE		0x00000004 /*%< File only. */
+#define ISC_FSACCESS_CREATECHILD	0x00000008 /*%< Dir only. */
+#define ISC_FSACCESS_DELETECHILD	0x00000010 /*%< Dir only. */
+#define ISC_FSACCESS_LISTDIRECTORY	0x00000020 /*%< Dir only. */
+#define ISC_FSACCESS_ACCESSCHILD	0x00000040 /*%< Dir only. */
+
+/*%
+ * Adding any permission bits beyond 0x200 would mean typedef'ing
+ * isc_fsaccess_t as isc_uint64_t, and redefining this value to
+ * reflect the new range of permission types, Probably to 21 for
+ * maximum flexibility.  The number of bits has to accommodate all of
+ * the permission types, and three full sets of them have to fit
+ * within an isc_fsaccess_t.
+ */
+#define ISC__FSACCESS_PERMISSIONBITS 10
+
+ISC_LANG_BEGINDECLS
+
+void
+isc_fsaccess_add(int trustee, int permission, isc_fsaccess_t *access);
+
+void
+isc_fsaccess_remove(int trustee, int permission, isc_fsaccess_t *access);
+
+isc_result_t
+isc_fsaccess_set(const char *path, isc_fsaccess_t access);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_FSACCESS_H */
diff --git a/src/lib/bind9/include/isc/hash.h b/src/lib/bind9/include/isc/hash.h
new file mode 100644
index 0000000..543e5fd
--- /dev/null
+++ b/src/lib/bind9/include/isc/hash.h
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: hash.h,v 1.12 2009-01-17 23:47:43 tbox Exp $ */
+
+#ifndef ISC_HASH_H
+#define ISC_HASH_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file isc/hash.h
+ *
+ * \brief The hash API
+ *	provides an unpredictable hash value for variable length data.
+ *	A hash object contains a random vector (which is hidden from clients
+ *	of this API) to make the actual hash value unpredictable.
+ *
+ *	The algorithm used in the API guarantees the probability of hash
+ *	collision; in the current implementation, as long as the values stored
+ *	in the random vector are unpredictable, the probability of hash
+ *	collision between arbitrary two different values is at most 1/2^16.
+ *
+ *	Although the API is generic about the hash keys, it mainly expects
+ *	DNS names (and sometimes IPv4/v6 addresses) as inputs.  It has an
+ *	upper limit of the input length, and may run slow to calculate the
+ *	hash values for large inputs.
+ *
+ *	This API is designed to be general so that it can provide multiple
+ *	different hash contexts that have different random vectors.  However,
+ *	it should be typical to have a single context for an entire system.
+ *	To support such cases, the API also provides a single-context mode.
+ *
+ * \li MP:
+ *	The hash object is almost read-only.  Once the internal random vector
+ *	is initialized, no write operation will occur, and there will be no
+ *	need to lock the object to calculate actual hash values.
+ *
+ * \li Reliability:
+ *	In some cases this module uses low-level data copy to initialize the
+ *	random vector.  Errors in this part are likely to crash the server or
+ *	corrupt memory.
+ *
+ * \li Resources:
+ *	A buffer, used as a random vector for calculating hash values.
+ *
+ * \li Security:
+ *	This module intends to provide unpredictable hash values in
+ *	adversarial environments in order to avoid denial of service attacks
+ *	to hash buckets.
+ *	Its unpredictability relies on the quality of entropy to build the
+ *	random vector.
+ *
+ * \li Standards:
+ *	None.
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/types.h>
+
+/***
+ *** Functions
+ ***/
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_hash_ctxcreate(isc_mem_t *mctx, isc_entropy_t *entropy, unsigned int limit,
+		   isc_hash_t **hctx);
+isc_result_t
+isc_hash_create(isc_mem_t *mctx, isc_entropy_t *entropy, size_t limit);
+/*!<
+ * \brief Create a new hash object.
+ *
+ * isc_hash_ctxcreate() creates a different object.
+ *
+ * isc_hash_create() creates a module-internal object to support the
+ * single-context mode.  It should be called only once.
+ *
+ * 'entropy' must be NULL or a valid entropy object.  If 'entropy' is NULL,
+ * pseudo random values will be used to build the random vector, which may
+ * weaken security.
+ *
+ * 'limit' specifies the maximum number of hash keys.  If it is too large,
+ * these functions may fail.
+ */
+
+void
+isc_hash_ctxattach(isc_hash_t *hctx, isc_hash_t **hctxp);
+/*!<
+ * \brief Attach to a hash object.
+ *
+ * This function is only necessary for the multiple-context mode.
+ */
+
+void
+isc_hash_ctxdetach(isc_hash_t **hctxp);
+/*!<
+ * \brief Detach from a hash object.
+ *
+ * This function  is for the multiple-context mode, and takes a valid
+ * hash object as an argument.
+ */
+
+void
+isc_hash_destroy(void);
+/*!<
+ * \brief This function is for the single-context mode, and is expected to be used
+ * as a counterpart of isc_hash_create().
+ *
+ * A valid module-internal hash object must have been created, and this
+ * function should be called only once.
+ */
+
+/*@{*/
+void
+isc_hash_ctxinit(isc_hash_t *hctx);
+void
+isc_hash_init(void);
+/*!<
+ * \brief Initialize a hash object.
+ *
+ * It fills in the random vector with a proper
+ * source of entropy, which is typically from the entropy object specified
+ * at the creation.  Thus, it is desirable to call these functions after
+ * initializing the entropy object with some good entropy sources.
+ *
+ * These functions should be called before the first hash calculation.
+ *
+ * isc_hash_ctxinit() is for the multiple-context mode, and takes a valid hash
+ * object as an argument.
+ *
+ * isc_hash_init() is for the single-context mode.  A valid module-internal
+ * hash object must have been created, and this function should be called only
+ * once.
+ */
+/*@}*/
+
+/*@{*/
+unsigned int
+isc_hash_ctxcalc(isc_hash_t *hctx, const unsigned char *key,
+		 unsigned int keylen, isc_boolean_t case_sensitive);
+unsigned int
+isc_hash_calc(const unsigned char *key, unsigned int keylen,
+	      isc_boolean_t case_sensitive);
+/*!<
+ * \brief Calculate a hash value.
+ *
+ * isc_hash_ctxinit() is for the multiple-context mode, and takes a valid hash
+ * object as an argument.
+ *
+ * isc_hash_init() is for the single-context mode.  A valid module-internal
+ * hash object must have been created.
+ *
+ * 'key' is the hash key, which is a variable length buffer.
+ *
+ * 'keylen' specifies the key length, which must not be larger than the limit
+ * specified for the corresponding hash object.
+ *
+ * 'case_sensitive' specifies whether the hash key should be treated as
+ * case_sensitive values.  It should typically be ISC_FALSE if the hash key
+ * is a DNS name.
+ */
+/*@}*/
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_HASH_H */
diff --git a/src/lib/bind9/include/isc/heap.h b/src/lib/bind9/include/isc/heap.h
new file mode 100644
index 0000000..943ace3
--- /dev/null
+++ b/src/lib/bind9/include/isc/heap.h
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1997-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: heap.h,v 1.26 2009-01-17 23:47:43 tbox Exp $ */
+
+#ifndef ISC_HEAP_H
+#define ISC_HEAP_H 1
+
+/*! \file isc/heap.h */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/*%
+ * The comparison function returns ISC_TRUE if the first argument has
+ * higher priority than the second argument, and ISC_FALSE otherwise.
+ */
+typedef isc_boolean_t (*isc_heapcompare_t)(void *, void *);
+
+/*%
+ * The index function allows the client of the heap to receive a callback
+ * when an item's index number changes.  This allows it to maintain
+ * sync with its external state, but still delete itself, since deletions
+ * from the heap require the index be provided.
+ */
+typedef void (*isc_heapindex_t)(void *, unsigned int);
+
+/*%
+ * The heapaction function is used when iterating over the heap.
+ *
+ * NOTE:  The heap structure CANNOT BE MODIFIED during the call to
+ * isc_heap_foreach().
+ */
+typedef void (*isc_heapaction_t)(void *, void *);
+
+typedef struct isc_heap isc_heap_t;
+
+isc_result_t
+isc_heap_create(isc_mem_t *mctx, isc_heapcompare_t compare,
+		isc_heapindex_t index, unsigned int size_increment,
+		isc_heap_t **heapp);
+/*!<
+ * \brief Create a new heap.  The heap is implemented using a space-efficient
+ * storage method.  When the heap elements are deleted space is not freed
+ * but will be reused when new elements are inserted.
+ *
+ * Requires:
+ *\li	"mctx" is valid.
+ *\li	"compare" is a function which takes two void * arguments and
+ *	returns ISC_TRUE if the first argument has a higher priority than
+ *	the second, and ISC_FALSE otherwise.
+ *\li	"index" is a function which takes a void *, and an unsigned int
+ *	argument.  This function will be called whenever an element's
+ *	index value changes, so it may continue to delete itself from the
+ *	heap.  This option may be NULL if this functionality is unneeded.
+ *\li	"size_increment" is a hint about how large the heap should grow
+ *	when resizing is needed.  If this is 0, a default size will be
+ *	used, which is currently 1024, allowing space for an additional 1024
+ *	heap elements to be inserted before adding more space.
+ *\li	"heapp" is not NULL, and "*heap" is NULL.
+ *
+ * Returns:
+ *\li	ISC_R_SUCCESS		- success
+ *\li	ISC_R_NOMEMORY		- insufficient memory
+ */
+
+void
+isc_heap_destroy(isc_heap_t **heapp);
+/*!<
+ * \brief Destroys a heap.
+ *
+ * Requires:
+ *\li	"heapp" is not NULL and "*heap" points to a valid isc_heap_t.
+ */
+
+isc_result_t
+isc_heap_insert(isc_heap_t *heap, void *elt);
+/*!<
+ * \brief Inserts a new element into a heap.
+ *
+ * Requires:
+ *\li	"heapp" is not NULL and "*heap" points to a valid isc_heap_t.
+ */
+
+void
+isc_heap_delete(isc_heap_t *heap, unsigned int index);
+/*!<
+ * \brief Deletes an element from a heap, by element index.
+ *
+ * Requires:
+ *\li	"heapp" is not NULL and "*heap" points to a valid isc_heap_t.
+ *\li	"index" is a valid element index, as provided by the "index" callback
+ *	provided during heap creation.
+ */
+
+void
+isc_heap_increased(isc_heap_t *heap, unsigned int index);
+/*!<
+ * \brief Indicates to the heap that an element's priority has increased.
+ * This function MUST be called whenever an element has increased in priority.
+ *
+ * Requires:
+ *\li	"heapp" is not NULL and "*heap" points to a valid isc_heap_t.
+ *\li	"index" is a valid element index, as provided by the "index" callback
+ *	provided during heap creation.
+ */
+
+void
+isc_heap_decreased(isc_heap_t *heap, unsigned int index);
+/*!<
+ * \brief Indicates to the heap that an element's priority has decreased.
+ * This function MUST be called whenever an element has decreased in priority.
+ *
+ * Requires:
+ *\li	"heapp" is not NULL and "*heap" points to a valid isc_heap_t.
+ *\li	"index" is a valid element index, as provided by the "index" callback
+ *	provided during heap creation.
+ */
+
+void *
+isc_heap_element(isc_heap_t *heap, unsigned int index);
+/*!<
+ * \brief Returns the element for a specific element index.
+ *
+ * Requires:
+ *\li	"heapp" is not NULL and "*heap" points to a valid isc_heap_t.
+ *\li	"index" is a valid element index, as provided by the "index" callback
+ *	provided during heap creation.
+ *
+ * Returns:
+ *\li	A pointer to the element for the element index.
+ */
+
+void
+isc_heap_foreach(isc_heap_t *heap, isc_heapaction_t action, void *uap);
+/*!<
+ * \brief Iterate over the heap, calling an action for each element.  The
+ * order of iteration is not sorted.
+ *
+ * Requires:
+ *\li	"heapp" is not NULL and "*heap" points to a valid isc_heap_t.
+ *\li	"action" is not NULL, and is a function which takes two arguments.
+ *	The first is a void *, representing the element, and the second is
+ *	"uap" as provided to isc_heap_foreach.
+ *\li	"uap" is a caller-provided argument, and may be NULL.
+ *
+ * Note:
+ *\li	The heap structure CANNOT be modified during this iteration.  The only
+ *	safe function to call while iterating the heap is isc_heap_element().
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_HEAP_H */
diff --git a/src/lib/bind9/include/isc/hex.h b/src/lib/bind9/include/isc/hex.h
new file mode 100644
index 0000000..d19e825
--- /dev/null
+++ b/src/lib/bind9/include/isc/hex.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2004-2008  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: hex.h,v 1.13 2008-09-25 04:02:39 tbox Exp $ */
+
+#ifndef ISC_HEX_H
+#define ISC_HEX_H 1
+
+/*! \file isc/hex.h */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/***
+ *** Functions
+ ***/
+
+isc_result_t
+isc_hex_totext(isc_region_t *source, int wordlength,
+	       const char *wordbreak, isc_buffer_t *target);
+/*!<
+ * \brief Convert data into hex encoded text.
+ *
+ * Notes:
+ *\li	The hex encoded text in 'target' will be divided into
+ *	words of at most 'wordlength' characters, separated by
+ * 	the 'wordbreak' string.  No parentheses will surround
+ *	the text.
+ *
+ * Requires:
+ *\li	'source' is a region containing binary data
+ *\li	'target' is a text buffer containing available space
+ *\li	'wordbreak' points to a null-terminated string of
+ *		zero or more whitespace characters
+ *
+ * Ensures:
+ *\li	target will contain the hex encoded version of the data
+ *	in source.  The 'used' pointer in target will be advanced as
+ *	necessary.
+ */
+
+isc_result_t
+isc_hex_decodestring(const char *cstr, isc_buffer_t *target);
+/*!<
+ * \brief Decode a null-terminated hex string.
+ *
+ * Requires:
+ *\li	'cstr' is non-null.
+ *\li	'target' is a valid buffer.
+ *
+ * Returns:
+ *\li	#ISC_R_SUCCESS	-- the entire decoded representation of 'cstring'
+ *			   fit in 'target'.
+ *\li	#ISC_R_BADHEX -- 'cstr' is not a valid hex encoding.
+ *
+ * 	Other error returns are any possible error code from:
+ *		isc_lex_create(),
+ *		isc_lex_openbuffer(),
+ *		isc_hex_tobuffer().
+ */
+
+isc_result_t
+isc_hex_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length);
+/*!<
+ * \brief Convert hex encoded text from a lexer context into data.
+ *
+ * Requires:
+ *\li	'lex' is a valid lexer context
+ *\li	'target' is a buffer containing binary data
+ *\li	'length' is an integer
+ *
+ * Ensures:
+ *\li	target will contain the data represented by the hex encoded
+ *	string parsed by the lexer.  No more than length bytes will be read,
+ *	if length is positive.  The 'used' pointer in target will be
+ *	advanced as necessary.
+ */
+
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_HEX_H */
diff --git a/src/lib/bind9/include/isc/hmacmd5.h b/src/lib/bind9/include/isc/hmacmd5.h
new file mode 100644
index 0000000..c7d7fff
--- /dev/null
+++ b/src/lib/bind9/include/isc/hmacmd5.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: hmacmd5.h,v 1.14 2009-02-06 23:47:42 tbox Exp $ */
+
+/*! \file isc/hmacmd5.h
+ * \brief This is the header file for the HMAC-MD5 keyed hash algorithm
+ * described in RFC2104.
+ */
+
+#ifndef ISC_HMACMD5_H
+#define ISC_HMACMD5_H 1
+
+#include <isc/lang.h>
+#include <isc/md5.h>
+#include <isc/platform.h>
+#include <isc/types.h>
+
+#define ISC_HMACMD5_KEYLENGTH 64
+
+#ifdef ISC_PLATFORM_OPENSSLHASH
+#include <openssl/hmac.h>
+
+typedef HMAC_CTX isc_hmacmd5_t;
+
+#else
+
+typedef struct {
+	isc_md5_t md5ctx;
+	unsigned char key[ISC_HMACMD5_KEYLENGTH];
+} isc_hmacmd5_t;
+#endif
+
+ISC_LANG_BEGINDECLS
+
+void
+isc_hmacmd5_init(isc_hmacmd5_t *ctx, const unsigned char *key,
+		 unsigned int len);
+
+void
+isc_hmacmd5_invalidate(isc_hmacmd5_t *ctx);
+
+void
+isc_hmacmd5_update(isc_hmacmd5_t *ctx, const unsigned char *buf,
+		   unsigned int len);
+
+void
+isc_hmacmd5_sign(isc_hmacmd5_t *ctx, unsigned char *digest);
+
+isc_boolean_t
+isc_hmacmd5_verify(isc_hmacmd5_t *ctx, unsigned char *digest);
+
+isc_boolean_t
+isc_hmacmd5_verify2(isc_hmacmd5_t *ctx, unsigned char *digest, size_t len);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_HMACMD5_H */
diff --git a/src/lib/bind9/include/isc/hmacsha.h b/src/lib/bind9/include/isc/hmacsha.h
new file mode 100644
index 0000000..286cafc
--- /dev/null
+++ b/src/lib/bind9/include/isc/hmacsha.h
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2005-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: hmacsha.h,v 1.9 2009-02-06 23:47:42 tbox Exp $ */
+
+/*! \file isc/hmacsha.h
+ * This is the header file for the HMAC-SHA1, HMAC-SHA224, HMAC-SHA256,
+ * HMAC-SHA334 and HMAC-SHA512 hash algorithm described in RFC 2104.
+ */
+
+#ifndef ISC_HMACSHA_H
+#define ISC_HMACSHA_H 1
+
+#include <isc/lang.h>
+#include <isc/platform.h>
+#include <isc/sha1.h>
+#include <isc/sha2.h>
+#include <isc/types.h>
+
+#define ISC_HMACSHA1_KEYLENGTH ISC_SHA1_BLOCK_LENGTH
+#define ISC_HMACSHA224_KEYLENGTH ISC_SHA224_BLOCK_LENGTH
+#define ISC_HMACSHA256_KEYLENGTH ISC_SHA256_BLOCK_LENGTH
+#define ISC_HMACSHA384_KEYLENGTH ISC_SHA384_BLOCK_LENGTH
+#define ISC_HMACSHA512_KEYLENGTH ISC_SHA512_BLOCK_LENGTH
+
+#ifdef ISC_PLATFORM_OPENSSLHASH
+#include <openssl/hmac.h>
+
+typedef HMAC_CTX isc_hmacsha1_t;
+typedef HMAC_CTX isc_hmacsha224_t;
+typedef HMAC_CTX isc_hmacsha256_t;
+typedef HMAC_CTX isc_hmacsha384_t;
+typedef HMAC_CTX isc_hmacsha512_t;
+
+#else
+
+typedef struct {
+	isc_sha1_t sha1ctx;
+	unsigned char key[ISC_HMACSHA1_KEYLENGTH];
+} isc_hmacsha1_t;
+
+typedef struct {
+	isc_sha224_t sha224ctx;
+	unsigned char key[ISC_HMACSHA224_KEYLENGTH];
+} isc_hmacsha224_t;
+
+typedef struct {
+	isc_sha256_t sha256ctx;
+	unsigned char key[ISC_HMACSHA256_KEYLENGTH];
+} isc_hmacsha256_t;
+
+typedef struct {
+	isc_sha384_t sha384ctx;
+	unsigned char key[ISC_HMACSHA384_KEYLENGTH];
+} isc_hmacsha384_t;
+
+typedef struct {
+	isc_sha512_t sha512ctx;
+	unsigned char key[ISC_HMACSHA512_KEYLENGTH];
+} isc_hmacsha512_t;
+#endif
+
+ISC_LANG_BEGINDECLS
+
+void
+isc_hmacsha1_init(isc_hmacsha1_t *ctx, const unsigned char *key,
+		  unsigned int len);
+
+void
+isc_hmacsha1_invalidate(isc_hmacsha1_t *ctx);
+
+void
+isc_hmacsha1_update(isc_hmacsha1_t *ctx, const unsigned char *buf,
+		    unsigned int len);
+
+void
+isc_hmacsha1_sign(isc_hmacsha1_t *ctx, unsigned char *digest, size_t len);
+
+isc_boolean_t
+isc_hmacsha1_verify(isc_hmacsha1_t *ctx, unsigned char *digest, size_t len);
+
+
+void
+isc_hmacsha224_init(isc_hmacsha224_t *ctx, const unsigned char *key,
+		    unsigned int len);
+
+void
+isc_hmacsha224_invalidate(isc_hmacsha224_t *ctx);
+
+void
+isc_hmacsha224_update(isc_hmacsha224_t *ctx, const unsigned char *buf,
+		      unsigned int len);
+
+void
+isc_hmacsha224_sign(isc_hmacsha224_t *ctx, unsigned char *digest, size_t len);
+
+isc_boolean_t
+isc_hmacsha224_verify(isc_hmacsha224_t *ctx, unsigned char *digest, size_t len);
+
+
+void
+isc_hmacsha256_init(isc_hmacsha256_t *ctx, const unsigned char *key,
+		    unsigned int len);
+
+void
+isc_hmacsha256_invalidate(isc_hmacsha256_t *ctx);
+
+void
+isc_hmacsha256_update(isc_hmacsha256_t *ctx, const unsigned char *buf,
+		      unsigned int len);
+
+void
+isc_hmacsha256_sign(isc_hmacsha256_t *ctx, unsigned char *digest, size_t len);
+
+isc_boolean_t
+isc_hmacsha256_verify(isc_hmacsha256_t *ctx, unsigned char *digest, size_t len);
+
+
+void
+isc_hmacsha384_init(isc_hmacsha384_t *ctx, const unsigned char *key,
+		    unsigned int len);
+
+void
+isc_hmacsha384_invalidate(isc_hmacsha384_t *ctx);
+
+void
+isc_hmacsha384_update(isc_hmacsha384_t *ctx, const unsigned char *buf,
+		      unsigned int len);
+
+void
+isc_hmacsha384_sign(isc_hmacsha384_t *ctx, unsigned char *digest, size_t len);
+
+isc_boolean_t
+isc_hmacsha384_verify(isc_hmacsha384_t *ctx, unsigned char *digest, size_t len);
+
+
+void
+isc_hmacsha512_init(isc_hmacsha512_t *ctx, const unsigned char *key,
+		    unsigned int len);
+
+void
+isc_hmacsha512_invalidate(isc_hmacsha512_t *ctx);
+
+void
+isc_hmacsha512_update(isc_hmacsha512_t *ctx, const unsigned char *buf,
+		      unsigned int len);
+
+void
+isc_hmacsha512_sign(isc_hmacsha512_t *ctx, unsigned char *digest, size_t len);
+
+isc_boolean_t
+isc_hmacsha512_verify(isc_hmacsha512_t *ctx, unsigned char *digest, size_t len);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_HMACSHA_H */
diff --git a/src/lib/bind9/include/isc/httpd.h b/src/lib/bind9/include/isc/httpd.h
new file mode 100644
index 0000000..aff9856
--- /dev/null
+++ b/src/lib/bind9/include/isc/httpd.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2006-2008  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: httpd.h,v 1.9 2008-08-08 05:06:49 marka Exp $ */
+
+#ifndef ISC_HTTPD_H
+#define ISC_HTTPD_H 1
+
+/*! \file */
+
+#include <isc/event.h>
+#include <isc/eventclass.h>
+#include <isc/types.h>
+#include <isc/mutex.h>
+#include <isc/task.h>
+
+#define HTTPD_EVENTCLASS		ISC_EVENTCLASS(4300)
+#define HTTPD_SHUTDOWN			(HTTPD_EVENTCLASS + 0x0001)
+
+#define ISC_HTTPDMGR_FLAGSHUTTINGDOWN	0x00000001
+
+/*
+ * Create a new http daemon which will send, once every time period,
+ * a http-like header followed by HTTP data.
+ */
+isc_result_t
+isc_httpdmgr_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
+		    isc_httpdclientok_t *client_ok,
+		    isc_httpdondestroy_t *ondestory, void *cb_arg,
+		    isc_timermgr_t *tmgr, isc_httpdmgr_t **httpdp);
+
+void
+isc_httpdmgr_shutdown(isc_httpdmgr_t **httpdp);
+
+isc_result_t
+isc_httpdmgr_addurl(isc_httpdmgr_t *httpdmgr, const char *url,
+		    isc_httpdaction_t *func, void *arg);
+
+isc_result_t
+isc_httpd_response(isc_httpd_t *httpd);
+
+isc_result_t
+isc_httpd_addheader(isc_httpd_t *httpd, const char *name,
+		    const char *val);
+
+isc_result_t
+isc_httpd_addheaderuint(isc_httpd_t *httpd, const char *name, int val);
+
+isc_result_t isc_httpd_endheaders(isc_httpd_t *httpd);
+
+#endif /* ISC_HTTPD_H */
diff --git a/src/lib/bind9/include/isc/interfaceiter.h b/src/lib/bind9/include/isc/interfaceiter.h
new file mode 100644
index 0000000..3abf957
--- /dev/null
+++ b/src/lib/bind9/include/isc/interfaceiter.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: interfaceiter.h,v 1.17 2007-06-19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_INTERFACEITER_H
+#define ISC_INTERFACEITER_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file isc/interfaceiter.h
+ * \brief Iterates over the list of network interfaces.
+ *
+ * Interfaces whose address family is not supported are ignored and never
+ * returned by the iterator.  Interfaces whose netmask, interface flags,
+ * or similar cannot be obtained are also ignored, and the failure is logged.
+ *
+ * Standards:
+ *	The API for scanning varies greatly among operating systems.
+ *	This module attempts to hide the differences.
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/lang.h>
+#include <isc/netaddr.h>
+#include <isc/types.h>
+
+/*!
+ * \brief Public structure describing a network interface.
+ */
+
+struct isc_interface {
+	char name[32];			/*%< Interface name, null-terminated. */
+	unsigned int af;		/*%< Address family. */
+	isc_netaddr_t address;		/*%< Local address. */
+	isc_netaddr_t netmask;		/*%< Network mask. */
+	isc_netaddr_t dstaddress; 	/*%< Destination address (point-to-point only). */
+	isc_uint32_t flags;		/*%< Flags; see INTERFACE flags. */
+};
+
+/*@{*/
+/*! Interface flags. */
+
+#define INTERFACE_F_UP			0x00000001U
+#define INTERFACE_F_POINTTOPOINT	0x00000002U
+#define INTERFACE_F_LOOPBACK		0x00000004U
+/*@}*/
+
+/***
+ *** Functions
+ ***/
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp);
+/*!<
+ * \brief Create an iterator for traversing the operating system's list
+ * of network interfaces.
+ *
+ * Returns:
+ *\li	#ISC_R_SUCCESS
+ * \li	#ISC_R_NOMEMORY
+ *\li	Various network-related errors
+ */
+
+isc_result_t
+isc_interfaceiter_first(isc_interfaceiter_t *iter);
+/*!<
+ * \brief Position the iterator on the first interface.
+ *
+ * Returns:
+ *\li	#ISC_R_SUCCESS		Success.
+ *\li	#ISC_R_NOMORE		There are no interfaces.
+ */
+
+isc_result_t
+isc_interfaceiter_current(isc_interfaceiter_t *iter,
+			  isc_interface_t *ifdata);
+/*!<
+ * \brief Get information about the interface the iterator is currently
+ * positioned at and store it at *ifdata.
+ *
+ * Requires:
+ *\li 	The iterator has been successfully positioned using
+ * 	isc_interface_iter_first() / isc_interface_iter_next().
+ *
+ * Returns:
+ *\li	#ISC_R_SUCCESS		Success.
+ */
+
+isc_result_t
+isc_interfaceiter_next(isc_interfaceiter_t *iter);
+/*!<
+ * \brief Position the iterator on the next interface.
+ *
+ * Requires:
+ * \li	The iterator has been successfully positioned using
+ * 	isc_interface_iter_first() / isc_interface_iter_next().
+ *
+ * Returns:
+ *\li	#ISC_R_SUCCESS		Success.
+ *\li	#ISC_R_NOMORE		There are no more interfaces.
+ */
+
+void
+isc_interfaceiter_destroy(isc_interfaceiter_t **iterp);
+/*!<
+ * \brief Destroy the iterator.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_INTERFACEITER_H */
diff --git a/src/lib/bind9/include/isc/ipv6.h b/src/lib/bind9/include/isc/ipv6.h
new file mode 100644
index 0000000..b9c30cd
--- /dev/null
+++ b/src/lib/bind9/include/isc/ipv6.h
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: ipv6.h,v 1.24 2007-06-19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_IPV6_H
+#define ISC_IPV6_H 1
+
+/*!
+ * Also define LWRES_IPV6_H to keep it from being included if liblwres is
+ * being used, or redefinition errors will occur.
+ */
+#define LWRES_IPV6_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file isc/ipv6.h
+ * \brief IPv6 definitions for systems which do not support IPv6.
+ *
+ * \li MP:
+ *	No impact.
+ *
+ * \li Reliability:
+ *	No anticipated impact.
+ *
+ * \li Resources:
+ *	N/A.
+ *
+ * \li Security:
+ *	No anticipated impact.
+ *
+ * \li Standards:
+ *	RFC2553.
+ */
+
+/***
+ *** Imports.
+ ***/
+
+#include <isc/int.h>
+#include <isc/platform.h>
+
+/***
+ *** Types.
+ ***/
+
+struct in6_addr {
+        union {
+		isc_uint8_t	_S6_u8[16];
+		isc_uint16_t	_S6_u16[8];
+		isc_uint32_t	_S6_u32[4];
+        } _S6_un;
+};
+#define s6_addr		_S6_un._S6_u8
+#define s6_addr8	_S6_un._S6_u8
+#define s6_addr16	_S6_un._S6_u16
+#define s6_addr32	_S6_un._S6_u32
+
+#define IN6ADDR_ANY_INIT 	{{{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }}}
+#define IN6ADDR_LOOPBACK_INIT 	{{{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 }}}
+
+LIBISC_EXTERNAL_DATA extern const struct in6_addr in6addr_any;
+LIBISC_EXTERNAL_DATA extern const struct in6_addr in6addr_loopback;
+
+struct sockaddr_in6 {
+#ifdef ISC_PLATFORM_HAVESALEN
+	isc_uint8_t		sin6_len;
+	isc_uint8_t		sin6_family;
+#else
+	isc_uint16_t		sin6_family;
+#endif
+	isc_uint16_t		sin6_port;
+	isc_uint32_t		sin6_flowinfo;
+	struct in6_addr		sin6_addr;
+	isc_uint32_t		sin6_scope_id;
+};
+
+#ifdef ISC_PLATFORM_HAVESALEN
+#define SIN6_LEN 1
+#endif
+
+/*%
+ * Unspecified
+ */
+#define IN6_IS_ADDR_UNSPECIFIED(a)      \
+        (((a)->s6_addr32[0] == 0) &&    \
+         ((a)->s6_addr32[1] == 0) &&    \
+         ((a)->s6_addr32[2] == 0) &&    \
+         ((a)->s6_addr32[3] == 0))
+
+/*%
+ * Loopback
+ */
+#define IN6_IS_ADDR_LOOPBACK(a)         \
+        (((a)->s6_addr32[0] == 0) &&    \
+         ((a)->s6_addr32[1] == 0) &&    \
+         ((a)->s6_addr32[2] == 0) &&    \
+         ((a)->s6_addr32[3] == htonl(1)))
+
+/*%
+ * IPv4 compatible
+ */
+#define IN6_IS_ADDR_V4COMPAT(a)         \
+        (((a)->s6_addr32[0] == 0) &&    \
+         ((a)->s6_addr32[1] == 0) &&    \
+         ((a)->s6_addr32[2] == 0) &&    \
+         ((a)->s6_addr32[3] != 0) &&    \
+         ((a)->s6_addr32[3] != htonl(1)))
+
+/*%
+ * Mapped
+ */
+#define IN6_IS_ADDR_V4MAPPED(a)               \
+        (((a)->s6_addr32[0] == 0) &&          \
+         ((a)->s6_addr32[1] == 0) &&          \
+         ((a)->s6_addr32[2] == htonl(0x0000ffff)))
+
+/*%
+ * Multicast
+ */
+#define IN6_IS_ADDR_MULTICAST(a)	\
+	((a)->s6_addr8[0] == 0xffU)
+
+/*%
+ * Unicast link / site local.
+ */
+#define IN6_IS_ADDR_LINKLOCAL(a)	\
+	(((a)->s6_addr[0] == 0xfe) && (((a)->s6_addr[1] & 0xc0) == 0x80))
+#define IN6_IS_ADDR_SITELOCAL(a)	\
+	(((a)->s6_addr[0] == 0xfe) && (((a)->s6_addr[1] & 0xc0) == 0xc0))
+
+#endif /* ISC_IPV6_H */
diff --git a/src/lib/bind9/include/isc/iterated_hash.h b/src/lib/bind9/include/isc/iterated_hash.h
new file mode 100644
index 0000000..a6de8fc
--- /dev/null
+++ b/src/lib/bind9/include/isc/iterated_hash.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2008  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: iterated_hash.h,v 1.3 2008-09-25 04:02:39 tbox Exp $ */
+
+#ifndef ISC_ITERATED_HASH_H
+#define ISC_ITERATED_HASH_H 1
+
+#include <isc/lang.h>
+#include <isc/sha1.h>
+
+/*
+ * The maximal hash length that can be encoded it a name
+ * using base32hex.  floor(255/8)*5
+ */
+#define NSEC3_MAX_HASH_LENGTH 155
+
+/*
+ * The maximum has that can be encoded in a single label using
+ * base32hex.  floor(63/8)*5
+ */
+#define NSEC3_MAX_LABEL_HASH 35
+
+ISC_LANG_BEGINDECLS
+
+int isc_iterated_hash(unsigned char out[NSEC3_MAX_HASH_LENGTH],
+		      unsigned int hashalg, int iterations,
+		      const unsigned char *salt, int saltlength,
+		      const unsigned char *in, int inlength);
+
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_ITERATED_HASH_H */
diff --git a/src/lib/bind9/include/isc/lang.h b/src/lib/bind9/include/isc/lang.h
new file mode 100644
index 0000000..5e1c61e
--- /dev/null
+++ b/src/lib/bind9/include/isc/lang.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: lang.h,v 1.13 2007-06-19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_LANG_H
+#define ISC_LANG_H 1
+
+/*! \file isc/lang.h */
+
+#ifdef __cplusplus
+#define ISC_LANG_BEGINDECLS	extern "C" {
+#define ISC_LANG_ENDDECLS	}
+#else
+#define ISC_LANG_BEGINDECLS
+#define ISC_LANG_ENDDECLS
+#endif
+
+#endif /* ISC_LANG_H */
diff --git a/src/lib/bind9/include/isc/lex.h b/src/lib/bind9/include/isc/lex.h
new file mode 100644
index 0000000..e260a5b
--- /dev/null
+++ b/src/lib/bind9/include/isc/lex.h
@@ -0,0 +1,431 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2008  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2002  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: lex.h,v 1.37 2008-05-30 23:47:01 tbox Exp $ */
+
+#ifndef ISC_LEX_H
+#define ISC_LEX_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file isc/lex.h
+ * \brief The "lex" module provides a lightweight tokenizer.  It can operate
+ * on files or buffers, and can handle "include".  It is designed for
+ * parsing of DNS master files and the BIND configuration file, but
+ * should be general enough to tokenize other things, e.g. HTTP.
+ *
+ * \li MP:
+ *	No synchronization is provided.  Clients must ensure exclusive
+ *	access.
+ *
+ * \li Reliability:
+ *	No anticipated impact.
+ *
+ * \li Resources:
+ *	TBS
+ *
+ * \li Security:
+ *	No anticipated impact.
+ *
+ * \li Standards:
+ * 	None.
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <stdio.h>
+
+#include <isc/lang.h>
+#include <isc/region.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/***
+ *** Options
+ ***/
+
+/*@{*/
+/*!
+ * Various options for isc_lex_gettoken().
+ */
+
+#define ISC_LEXOPT_EOL			0x01	/*%< Want end-of-line token. */
+#define ISC_LEXOPT_EOF			0x02	/*%< Want end-of-file token. */
+#define ISC_LEXOPT_INITIALWS		0x04	/*%< Want initial whitespace. */
+#define ISC_LEXOPT_NUMBER		0x08	/*%< Recognize numbers. */
+#define ISC_LEXOPT_QSTRING		0x10	/*%< Recognize qstrings. */
+/*@}*/
+
+/*@{*/
+/*!
+ * The ISC_LEXOPT_DNSMULTILINE option handles the processing of '(' and ')' in
+ * the DNS master file format.  If this option is set, then the
+ * ISC_LEXOPT_INITIALWS and ISC_LEXOPT_EOL options will be ignored when
+ * the paren count is > 0.  To use this option, '(' and ')' must be special
+ * characters.
+ */
+#define ISC_LEXOPT_DNSMULTILINE		0x20	/*%< Handle '(' and ')'. */
+#define ISC_LEXOPT_NOMORE		0x40	/*%< Want "no more" token. */
+
+#define ISC_LEXOPT_CNUMBER		0x80    /*%< Recognize octal and hex. */
+#define ISC_LEXOPT_ESCAPE		0x100	/*%< Recognize escapes. */
+#define ISC_LEXOPT_QSTRINGMULTILINE	0x200	/*%< Allow multiline "" strings */
+#define ISC_LEXOPT_OCTAL		0x400	/*%< Expect a octal number. */
+/*@}*/
+/*@{*/
+/*!
+ * Various commenting styles, which may be changed at any time with
+ * isc_lex_setcomments().
+ */
+
+#define ISC_LEXCOMMENT_C		0x01
+#define ISC_LEXCOMMENT_CPLUSPLUS	0x02
+#define ISC_LEXCOMMENT_SHELL		0x04
+#define ISC_LEXCOMMENT_DNSMASTERFILE	0x08
+/*@}*/
+
+/***
+ *** Types
+ ***/
+
+/*! Lex */
+
+typedef char isc_lexspecials_t[256];
+
+/* Tokens */
+
+typedef enum {
+	isc_tokentype_unknown = 0,
+	isc_tokentype_string = 1,
+	isc_tokentype_number = 2,
+	isc_tokentype_qstring = 3,
+	isc_tokentype_eol = 4,
+	isc_tokentype_eof = 5,
+	isc_tokentype_initialws = 6,
+	isc_tokentype_special = 7,
+	isc_tokentype_nomore = 8
+} isc_tokentype_t;
+
+typedef union {
+	char				as_char;
+	unsigned long			as_ulong;
+	isc_region_t			as_region;
+	isc_textregion_t		as_textregion;
+	void *				as_pointer;
+} isc_tokenvalue_t;
+
+typedef struct isc_token {
+	isc_tokentype_t			type;
+	isc_tokenvalue_t		value;
+} isc_token_t;
+
+/***
+ *** Functions
+ ***/
+
+isc_result_t
+isc_lex_create(isc_mem_t *mctx, size_t max_token, isc_lex_t **lexp);
+/*%<
+ * Create a lexer.
+ *
+ * 'max_token' is a hint of the number of bytes in the largest token.
+ *
+ * Requires:
+ *\li	'*lexp' is a valid lexer.
+ *
+ *\li	max_token > 0.
+ *
+ * Ensures:
+ *\li	On success, *lexp is attached to the newly created lexer.
+ *
+ * Returns:
+ *\li	#ISC_R_SUCCESS
+ *\li	#ISC_R_NOMEMORY
+ */
+
+void
+isc_lex_destroy(isc_lex_t **lexp);
+/*%<
+ * Destroy the lexer.
+ *
+ * Requires:
+ *\li	'*lexp' is a valid lexer.
+ *
+ * Ensures:
+ *\li	*lexp == NULL
+ */
+
+unsigned int
+isc_lex_getcomments(isc_lex_t *lex);
+/*%<
+ * Return the current lexer commenting styles.
+ *
+ * Requires:
+ *\li	'lex' is a valid lexer.
+ *
+ * Returns:
+ *\li	The commenting sytles which are currently allowed.
+ */
+
+void
+isc_lex_setcomments(isc_lex_t *lex, unsigned int comments);
+/*%<
+ * Set allowed lexer commenting styles.
+ *
+ * Requires:
+ *\li	'lex' is a valid lexer.
+ *
+ *\li	'comments' has meaningful values.
+ */
+
+void
+isc_lex_getspecials(isc_lex_t *lex, isc_lexspecials_t specials);
+/*%<
+ * Put the current list of specials into 'specials'.
+ *
+ * Requires:
+ *\li	'lex' is a valid lexer.
+ */
+
+void
+isc_lex_setspecials(isc_lex_t *lex, isc_lexspecials_t specials);
+/*!<
+ * The characters in 'specials' are returned as tokens.  Along with
+ * whitespace, they delimit strings and numbers.
+ *
+ * Note:
+ *\li	Comment processing takes precedence over special character
+ *	recognition.
+ *
+ * Requires:
+ *\li	'lex' is a valid lexer.
+ */
+
+isc_result_t
+isc_lex_openfile(isc_lex_t *lex, const char *filename);
+/*%<
+ * Open 'filename' and make it the current input source for 'lex'.
+ *
+ * Requires:
+ *\li	'lex' is a valid lexer.
+ *
+ *\li	filename is a valid C string.
+ *
+ * Returns:
+ *\li	#ISC_R_SUCCESS
+ *\li	#ISC_R_NOMEMORY			Out of memory
+ *\li	#ISC_R_NOTFOUND			File not found
+ *\li	#ISC_R_NOPERM			No permission to open file
+ *\li	#ISC_R_FAILURE			Couldn't open file, not sure why
+ *\li	#ISC_R_UNEXPECTED
+ */
+
+isc_result_t
+isc_lex_openstream(isc_lex_t *lex, FILE *stream);
+/*%<
+ * Make 'stream' the current input source for 'lex'.
+ *
+ * Requires:
+ *\li	'lex' is a valid lexer.
+ *
+ *\li	'stream' is a valid C stream.
+ *
+ * Returns:
+ *\li	#ISC_R_SUCCESS
+ *\li	#ISC_R_NOMEMORY			Out of memory
+ */
+
+isc_result_t
+isc_lex_openbuffer(isc_lex_t *lex, isc_buffer_t *buffer);
+/*%<
+ * Make 'buffer' the current input source for 'lex'.
+ *
+ * Requires:
+ *\li	'lex' is a valid lexer.
+ *
+ *\li	'buffer' is a valid buffer.
+ *
+ * Returns:
+ *\li	#ISC_R_SUCCESS
+ *\li	#ISC_R_NOMEMORY			Out of memory
+ */
+
+isc_result_t
+isc_lex_close(isc_lex_t *lex);
+/*%<
+ * Close the most recently opened object (i.e. file or buffer).
+ *
+ * Returns:
+ *\li	#ISC_R_SUCCESS
+ *\li	#ISC_R_NOMORE			No more input sources
+ */
+
+isc_result_t
+isc_lex_gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *tokenp);
+/*%<
+ * Get the next token.
+ *
+ * Requires:
+ *\li	'lex' is a valid lexer.
+ *
+ *\li	'lex' has an input source.
+ *
+ *\li	'options' contains valid options.
+ *
+ *\li	'*tokenp' is a valid pointer.
+ *
+ * Returns:
+ *\li	#ISC_R_SUCCESS
+ *\li	#ISC_R_UNEXPECTEDEND
+ *\li	#ISC_R_NOMEMORY
+ *
+ *	These two results are returned only if their corresponding lexer
+ *	options are not set.
+ *
+ *\li	#ISC_R_EOF			End of input source
+ *\li	#ISC_R_NOMORE			No more input sources
+ */
+
+isc_result_t
+isc_lex_getmastertoken(isc_lex_t *lex, isc_token_t *token,
+		       isc_tokentype_t expect, isc_boolean_t eol);
+/*%<
+ * Get the next token from a DNS master file type stream.  This is a
+ * convenience function that sets appropriate options and handles quoted
+ * strings and end of line correctly for master files.  It also ungets
+ * unexpected tokens.
+ *
+ * Requires:
+ *\li	'lex' is a valid lexer.
+ *
+ *\li	'token' is a valid pointer
+ *
+ * Returns:
+ *
+ * \li	any return code from isc_lex_gettoken().
+ */
+
+isc_result_t
+isc_lex_getoctaltoken(isc_lex_t *lex, isc_token_t *token, isc_boolean_t eol);
+/*%<
+ * Get the next token from a DNS master file type stream.  This is a
+ * convenience function that sets appropriate options and handles end
+ * of line correctly for master files.  It also ungets unexpected tokens.
+ *
+ * Requires:
+ *\li	'lex' is a valid lexer.
+ *
+ *\li	'token' is a valid pointer
+ *
+ * Returns:
+ *
+ * \li	any return code from isc_lex_gettoken().
+ */
+
+void
+isc_lex_ungettoken(isc_lex_t *lex, isc_token_t *tokenp);
+/*%<
+ * Unget the current token.
+ *
+ * Requires:
+ *\li	'lex' is a valid lexer.
+ *
+ *\li	'lex' has an input source.
+ *
+ *\li	'tokenp' points to a valid token.
+ *
+ *\li	There is no ungotten token already.
+ */
+
+void
+isc_lex_getlasttokentext(isc_lex_t *lex, isc_token_t *tokenp, isc_region_t *r);
+/*%<
+ * Returns a region containing the text of the last token returned.
+ *
+ * Requires:
+ *\li	'lex' is a valid lexer.
+ *
+ *\li	'lex' has an input source.
+ *
+ *\li	'tokenp' points to a valid token.
+ *
+ *\li	A token has been gotten and not ungotten.
+ */
+
+char *
+isc_lex_getsourcename(isc_lex_t *lex);
+/*%<
+ * Return the input source name.
+ *
+ * Requires:
+ *\li	'lex' is a valid lexer.
+ *
+ * Returns:
+ * \li	source name or NULL if no current source.
+ *\li	result valid while current input source exists.
+ */
+
+
+unsigned long
+isc_lex_getsourceline(isc_lex_t *lex);
+/*%<
+ * Return the input source line number.
+ *
+ * Requires:
+ *\li	'lex' is a valid lexer.
+ *
+ * Returns:
+ *\li 	Current line number or 0 if no current source.
+ */
+
+isc_result_t
+isc_lex_setsourcename(isc_lex_t *lex, const char *name);
+/*%<
+ * Assigns a new name to the input source.
+ *
+ * Requires:
+ *
+ * \li	'lex' is a valid lexer.
+ *
+ * Returns:
+ * \li	#ISC_R_SUCCESS
+ * \li	#ISC_R_NOMEMORY
+ * \li	#ISC_R_NOTFOUND - there are no sources.
+ */
+
+isc_boolean_t
+isc_lex_isfile(isc_lex_t *lex);
+/*%<
+ * Return whether the current input source is a file.
+ *
+ * Requires:
+ *\li	'lex' is a valid lexer.
+ *
+ * Returns:
+ * \li	#ISC_TRUE if the current input is a file,
+ *\li	#ISC_FALSE otherwise.
+ */
+
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_LEX_H */
diff --git a/src/lib/bind9/include/isc/lfsr.h b/src/lib/bind9/include/isc/lfsr.h
new file mode 100644
index 0000000..c9ad13d
--- /dev/null
+++ b/src/lib/bind9/include/isc/lfsr.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: lfsr.h,v 1.17 2007-06-19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_LFSR_H
+#define ISC_LFSR_H 1
+
+/*! \file isc/lfsr.h */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+typedef struct isc_lfsr isc_lfsr_t;
+
+/*%
+ * This function is called when reseeding is needed.  It is allowed to
+ * modify any state in the LFSR in any way it sees fit OTHER THAN "bits".
+ *
+ * It MUST set "count" to a new value or the lfsr will never reseed again.
+ *
+ * Also, a reseed will never occur in the middle of an extraction.  This
+ * is purely an optimization, and is probably what one would want.
+ */
+typedef void (*isc_lfsrreseed_t)(isc_lfsr_t *, void *);
+
+/*%
+ * The members of this structure can be used by the application, but care
+ * needs to be taken to not change state once the lfsr is in operation.
+ */
+struct isc_lfsr {
+	isc_uint32_t		state;	/*%< previous state */
+	unsigned int		bits;	/*%< length */
+	isc_uint32_t		tap;	/*%< bit taps */
+	unsigned int		count;	/*%< reseed count (in BITS!) */
+	isc_lfsrreseed_t	reseed;	/*%< reseed function */
+	void		       *arg;	/*%< reseed function argument */
+};
+
+ISC_LANG_BEGINDECLS
+
+
+void 
+isc_lfsr_init(isc_lfsr_t *lfsr, isc_uint32_t state, unsigned int bits,
+		   isc_uint32_t tap, unsigned int count,
+		   isc_lfsrreseed_t reseed, void *arg);
+/*%<
+ * Initialize an LFSR.
+ *
+ * Note:
+ *
+ *\li	Putting untrusted values into this function will cause the LFSR to
+ *	generate (perhaps) non-maximal length sequences.
+ *
+ * Requires:
+ *
+ *\li	lfsr != NULL
+ *
+ *\li	8 <= bits <= 32
+ *
+ *\li	tap != 0
+ */
+
+void 
+isc_lfsr_generate(isc_lfsr_t *lfsr, void *data, unsigned int count);
+/*%<
+ * Returns "count" bytes of data from the LFSR.
+ *
+ * Requires:
+ *
+ *\li	lfsr be valid.
+ *
+ *\li	data != NULL.
+ *
+ *\li	count > 0.
+ */
+
+void 
+isc_lfsr_skip(isc_lfsr_t *lfsr, unsigned int skip);
+/*%<
+ * Skip "skip" states.
+ *
+ * Requires:
+ *
+ *\li	lfsr be valid.
+ */
+
+isc_uint32_t 
+isc_lfsr_generate32(isc_lfsr_t *lfsr1, isc_lfsr_t *lfsr2);
+/*%<
+ * Given two LFSRs, use the current state from each to skip entries in the
+ * other.  The next states are then xor'd together and returned.
+ *
+ * WARNING:
+ *
+ *\li	This function is used only for very, very low security data, such
+ *	as DNS message IDs where it is desired to have an unpredictable
+ *	stream of bytes that are harder to predict than a simple flooding
+ *	attack.
+ *
+ * Notes:
+ *
+ *\li	Since the current state from each of the LFSRs is used to skip
+ *	state in the other, it is important that no state be leaked
+ *	from either LFSR.
+ *
+ * Requires:
+ *
+ *\li	lfsr1 and lfsr2 be valid.
+ *
+ *\li	1 <= skipbits <= 31
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_LFSR_H */
diff --git a/src/lib/bind9/include/isc/lib.h b/src/lib/bind9/include/isc/lib.h
new file mode 100644
index 0000000..c8bdbc6
--- /dev/null
+++ b/src/lib/bind9/include/isc/lib.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: lib.h,v 1.16 2009-09-02 23:48:03 tbox Exp $ */
+
+#ifndef ISC_LIB_H
+#define ISC_LIB_H 1
+
+/*! \file isc/lib.h */
+
+#include <isc/types.h>
+#include <isc/lang.h>
+
+ISC_LANG_BEGINDECLS
+
+LIBISC_EXTERNAL_DATA extern isc_msgcat_t *isc_msgcat;
+
+void
+isc_lib_initmsgcat(void);
+/*!<
+ * \brief Initialize the ISC library's message catalog, isc_msgcat, if it
+ * has not already been initialized.
+ */
+
+void
+isc_lib_register(void);
+/*!<
+ * \brief Register the ISC library implementations for some base services
+ * such as memory or event management and handling socket or timer events.
+ * An external application that wants to use the ISC library must call this
+ * function very early in main().
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_LIB_H */
diff --git a/src/lib/bind9/include/isc/list.h b/src/lib/bind9/include/isc/list.h
new file mode 100644
index 0000000..69ba1c6
--- /dev/null
+++ b/src/lib/bind9/include/isc/list.h
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2004, 2006, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1997-2002  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: list.h,v 1.24 2007-06-19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_LIST_H
+#define ISC_LIST_H 1
+#include <isc/boolean.h>
+#include <isc/assertions.h>
+
+#ifdef ISC_LIST_CHECKINIT
+#define ISC_LINK_INSIST(x) ISC_INSIST(x)
+#else
+#define ISC_LINK_INSIST(x)
+#endif
+
+#define ISC_LIST(type) struct { type *head, *tail; }
+#define ISC_LIST_INIT(list) \
+	do { (list).head = NULL; (list).tail = NULL; } while (0)
+
+#define ISC_LINK(type) struct { type *prev, *next; }
+#define ISC_LINK_INIT_TYPE(elt, link, type) \
+	do { \
+		(elt)->link.prev = (type *)(-1); \
+		(elt)->link.next = (type *)(-1); \
+	} while (0)
+#define ISC_LINK_INIT(elt, link) \
+	ISC_LINK_INIT_TYPE(elt, link, void)
+#define ISC_LINK_LINKED(elt, link) ((void *)((elt)->link.prev) != (void *)(-1))
+
+#define ISC_LIST_HEAD(list) ((list).head)
+#define ISC_LIST_TAIL(list) ((list).tail)
+#define ISC_LIST_EMPTY(list) ISC_TF((list).head == NULL)
+
+#define __ISC_LIST_PREPENDUNSAFE(list, elt, link) \
+	do { \
+		if ((list).head != NULL) \
+			(list).head->link.prev = (elt); \
+		else \
+			(list).tail = (elt); \
+		(elt)->link.prev = NULL; \
+		(elt)->link.next = (list).head; \
+		(list).head = (elt); \
+	} while (0)
+
+#define ISC_LIST_PREPEND(list, elt, link) \
+	do { \
+		ISC_LINK_INSIST(!ISC_LINK_LINKED(elt, link)); \
+		__ISC_LIST_PREPENDUNSAFE(list, elt, link); \
+	} while (0)
+
+#define ISC_LIST_INITANDPREPEND(list, elt, link) \
+		__ISC_LIST_PREPENDUNSAFE(list, elt, link)
+
+#define __ISC_LIST_APPENDUNSAFE(list, elt, link) \
+	do { \
+		if ((list).tail != NULL) \
+			(list).tail->link.next = (elt); \
+		else \
+			(list).head = (elt); \
+		(elt)->link.prev = (list).tail; \
+		(elt)->link.next = NULL; \
+		(list).tail = (elt); \
+	} while (0)
+
+#define ISC_LIST_APPEND(list, elt, link) \
+	do { \
+		ISC_LINK_INSIST(!ISC_LINK_LINKED(elt, link)); \
+		__ISC_LIST_APPENDUNSAFE(list, elt, link); \
+	} while (0)
+
+#define ISC_LIST_INITANDAPPEND(list, elt, link) \
+		__ISC_LIST_APPENDUNSAFE(list, elt, link)
+
+#define __ISC_LIST_UNLINKUNSAFE_TYPE(list, elt, link, type) \
+	do { \
+		if ((elt)->link.next != NULL) \
+			(elt)->link.next->link.prev = (elt)->link.prev; \
+		else { \
+			ISC_INSIST((list).tail == (elt)); \
+			(list).tail = (elt)->link.prev; \
+		} \
+		if ((elt)->link.prev != NULL) \
+			(elt)->link.prev->link.next = (elt)->link.next; \
+		else { \
+			ISC_INSIST((list).head == (elt)); \
+			(list).head = (elt)->link.next; \
+		} \
+		(elt)->link.prev = (type *)(-1); \
+		(elt)->link.next = (type *)(-1); \
+	} while (0)
+
+#define __ISC_LIST_UNLINKUNSAFE(list, elt, link) \
+	__ISC_LIST_UNLINKUNSAFE_TYPE(list, elt, link, void)
+
+#define ISC_LIST_UNLINK_TYPE(list, elt, link, type) \
+	do { \
+		ISC_LINK_INSIST(ISC_LINK_LINKED(elt, link)); \
+		__ISC_LIST_UNLINKUNSAFE_TYPE(list, elt, link, type); \
+	} while (0)
+#define ISC_LIST_UNLINK(list, elt, link) \
+	ISC_LIST_UNLINK_TYPE(list, elt, link, void)
+
+#define ISC_LIST_PREV(elt, link) ((elt)->link.prev)
+#define ISC_LIST_NEXT(elt, link) ((elt)->link.next)
+
+#define __ISC_LIST_INSERTBEFOREUNSAFE(list, before, elt, link) \
+	do { \
+		if ((before)->link.prev == NULL) \
+			ISC_LIST_PREPEND(list, elt, link); \
+		else { \
+			(elt)->link.prev = (before)->link.prev; \
+			(before)->link.prev = (elt); \
+			(elt)->link.prev->link.next = (elt); \
+			(elt)->link.next = (before); \
+		} \
+	} while (0)
+
+#define ISC_LIST_INSERTBEFORE(list, before, elt, link) \
+	do { \
+		ISC_LINK_INSIST(ISC_LINK_LINKED(before, link)); \
+		ISC_LINK_INSIST(!ISC_LINK_LINKED(elt, link)); \
+		__ISC_LIST_INSERTBEFOREUNSAFE(list, before, elt, link); \
+	} while (0)
+
+#define __ISC_LIST_INSERTAFTERUNSAFE(list, after, elt, link) \
+	do { \
+		if ((after)->link.next == NULL) \
+			ISC_LIST_APPEND(list, elt, link); \
+		else { \
+			(elt)->link.next = (after)->link.next; \
+			(after)->link.next = (elt); \
+			(elt)->link.next->link.prev = (elt); \
+			(elt)->link.prev = (after); \
+		} \
+	} while (0)
+
+#define ISC_LIST_INSERTAFTER(list, after, elt, link) \
+	do { \
+		ISC_LINK_INSIST(ISC_LINK_LINKED(after, link)); \
+		ISC_LINK_INSIST(!ISC_LINK_LINKED(elt, link)); \
+		__ISC_LIST_INSERTAFTERUNSAFE(list, after, elt, link); \
+	} while (0)
+
+#define ISC_LIST_APPENDLIST(list1, list2, link) \
+	do { \
+		if (ISC_LIST_EMPTY(list1)) \
+			(list1) = (list2); \
+		else if (!ISC_LIST_EMPTY(list2)) { \
+			(list1).tail->link.next = (list2).head; \
+			(list2).head->link.prev = (list1).tail; \
+			(list1).tail = (list2).tail; \
+		} \
+		(list2).head = NULL; \
+		(list2).tail = NULL; \
+	} while (0)
+
+#define ISC_LIST_ENQUEUE(list, elt, link) ISC_LIST_APPEND(list, elt, link)
+#define __ISC_LIST_ENQUEUEUNSAFE(list, elt, link) \
+	__ISC_LIST_APPENDUNSAFE(list, elt, link)
+#define ISC_LIST_DEQUEUE(list, elt, link) \
+	 ISC_LIST_UNLINK_TYPE(list, elt, link, void)
+#define ISC_LIST_DEQUEUE_TYPE(list, elt, link, type) \
+	 ISC_LIST_UNLINK_TYPE(list, elt, link, type)
+#define __ISC_LIST_DEQUEUEUNSAFE(list, elt, link) \
+	__ISC_LIST_UNLINKUNSAFE_TYPE(list, elt, link, void)
+#define __ISC_LIST_DEQUEUEUNSAFE_TYPE(list, elt, link, type) \
+	__ISC_LIST_UNLINKUNSAFE_TYPE(list, elt, link, type)
+
+#endif /* ISC_LIST_H */
diff --git a/src/lib/bind9/include/isc/log.h b/src/lib/bind9/include/isc/log.h
new file mode 100644
index 0000000..eac5755
--- /dev/null
+++ b/src/lib/bind9/include/isc/log.h
@@ -0,0 +1,914 @@
+/*
+ * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: log.h,v 1.59 2009-02-16 02:01:16 marka Exp $ */
+
+#ifndef ISC_LOG_H
+#define ISC_LOG_H 1
+
+/*! \file isc/log.h */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <syslog.h> /* XXXDCL NT */
+
+#include <isc/formatcheck.h>
+#include <isc/lang.h>
+#include <isc/platform.h>
+#include <isc/types.h>
+
+/*@{*/
+/*!
+ * \brief Severity levels, patterned after Unix's syslog levels.
+ *
+ */
+#define ISC_LOG_DEBUG(level)	(level)
+/*!
+ * #ISC_LOG_DYNAMIC can only be used for defining channels with
+ * isc_log_createchannel(), not to specify a level in isc_log_write().
+ */
+#define ISC_LOG_DYNAMIC	  	  0
+#define ISC_LOG_INFO		(-1)
+#define ISC_LOG_NOTICE		(-2)
+#define ISC_LOG_WARNING 	(-3)
+#define ISC_LOG_ERROR		(-4)
+#define ISC_LOG_CRITICAL	(-5)
+/*@}*/
+
+/*@{*/
+/*!
+ * \brief Destinations.
+ */
+#define ISC_LOG_TONULL		1
+#define ISC_LOG_TOSYSLOG	2
+#define ISC_LOG_TOFILE		3
+#define ISC_LOG_TOFILEDESC	4
+/*@}*/
+
+/*@{*/
+/*%
+ * Channel flags.
+ */
+#define ISC_LOG_PRINTTIME	0x0001
+#define ISC_LOG_PRINTLEVEL	0x0002
+#define ISC_LOG_PRINTCATEGORY	0x0004
+#define ISC_LOG_PRINTMODULE	0x0008
+#define ISC_LOG_PRINTTAG	0x0010
+#define ISC_LOG_PRINTALL	0x001F
+#define ISC_LOG_DEBUGONLY	0x1000
+#define ISC_LOG_OPENERR		0x8000		/* internal */
+/*@}*/
+
+/*@{*/
+/*!
+ * \brief Other options.
+ *
+ * XXXDCL INFINITE doesn't yet work.  Arguably it isn't needed, but
+ *   since I am intend to make large number of versions work efficiently,
+ *   INFINITE is going to be trivial to add to that.
+ */
+#define ISC_LOG_ROLLINFINITE	(-1)
+#define ISC_LOG_ROLLNEVER	(-2)
+/*@}*/
+
+/*!
+ * \brief Used to name the categories used by a library.
+ *
+ * An array of isc_logcategory
+ * structures names each category, and the id value is initialized by calling
+ * isc_log_registercategories.
+ */
+struct isc_logcategory {
+	const char *name;
+	unsigned int id;
+};
+
+/*%
+ * Similar to isc_logcategory, but for all the modules a library defines.
+ */
+struct isc_logmodule {
+	const char *name;
+	unsigned int id;
+};
+
+/*%
+ * The isc_logfile structure is initialized as part of an isc_logdestination
+ * before calling isc_log_createchannel().
+ *
+ * When defining an #ISC_LOG_TOFILE
+ * channel the name, versions and maximum_size should be set before calling
+ * isc_log_createchannel().  To define an #ISC_LOG_TOFILEDESC channel set only
+ * the stream before the call.
+ *
+ * Setting maximum_size to zero implies no maximum.
+ */
+typedef struct isc_logfile {
+	FILE *stream;		/*%< Initialized to NULL for #ISC_LOG_TOFILE. */
+	const char *name;	/*%< NULL for #ISC_LOG_TOFILEDESC. */
+	int versions;	/* >= 0, #ISC_LOG_ROLLNEVER, #ISC_LOG_ROLLINFINITE. */
+	/*%
+	 * stdio's ftell is standardized to return a long, which may well not
+	 * be big enough for the largest file supportable by the operating
+	 * system (though it is _probably_ big enough for the largest log
+	 * anyone would want).  st_size returned by fstat should be typedef'd
+	 * to a size large enough for the largest possible file on a system.
+	 */
+	isc_offset_t maximum_size;
+	isc_boolean_t maximum_reached; /*%< Private. */
+} isc_logfile_t;
+
+/*%
+ * Passed to isc_log_createchannel to define the attributes of either
+ * a stdio or a syslog log.
+ */
+typedef union isc_logdestination {
+	isc_logfile_t file;
+	int facility;		/* XXXDCL NT */
+} isc_logdestination_t;
+
+/*@{*/
+/*%
+ * The built-in categories of libisc.
+ *
+ * Each library registering categories should provide library_LOGCATEGORY_name
+ * definitions with indexes into its isc_logcategory structure corresponding to
+ * the order of the names.
+ */
+LIBISC_EXTERNAL_DATA extern isc_logcategory_t isc_categories[];
+LIBISC_EXTERNAL_DATA extern isc_log_t *isc_lctx;
+LIBISC_EXTERNAL_DATA extern isc_logmodule_t isc_modules[];
+/*@}*/
+
+/*@{*/
+/*%
+ * Do not log directly to DEFAULT.  Use another category.  When in doubt,
+ * use GENERAL.
+ */
+#define ISC_LOGCATEGORY_DEFAULT	(&isc_categories[0])
+#define ISC_LOGCATEGORY_GENERAL	(&isc_categories[1])
+/*@}*/
+
+#define ISC_LOGMODULE_SOCKET (&isc_modules[0])
+#define ISC_LOGMODULE_TIME (&isc_modules[1])
+#define ISC_LOGMODULE_INTERFACE (&isc_modules[2])
+#define ISC_LOGMODULE_TIMER (&isc_modules[3])
+#define ISC_LOGMODULE_FILE (&isc_modules[4])
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_log_create(isc_mem_t *mctx, isc_log_t **lctxp, isc_logconfig_t **lcfgp);
+/*%<
+ * Establish a new logging context, with default channels.
+ *
+ * Notes:
+ *\li	isc_log_create() calls isc_logconfig_create(), so see its comment
+ *	below for more information.
+ *
+ * Requires:
+ *\li	mctx is a valid memory context.
+ *\li	lctxp is not null and *lctxp is null.
+ *\li	lcfgp is null or lcfgp is not null and *lcfgp is null.
+ *
+ * Ensures:
+ *\li	*lctxp will point to a valid logging context if all of the necessary
+ *	memory was allocated, or NULL otherwise.
+ *\li	*lcfgp will point to a valid logging configuration if all of the
+ *	necessary memory was allocated, or NULL otherwise.
+ *\li	On failure, no additional memory is allocated.
+ *
+ * Returns:
+ *\li	#ISC_R_SUCCESS		Success
+ *\li	#ISC_R_NOMEMORY		Resource limit: Out of memory
+ */
+
+isc_result_t
+isc_logconfig_create(isc_log_t *lctx, isc_logconfig_t **lcfgp);
+/*%<
+ * Create the data structure that holds all of the configurable information
+ * about where messages are actually supposed to be sent -- the information
+ * that could changed based on some configuration file, as opposed to the
+ * the category/module specification of isc_log_[v]write[1] that is compiled
+ * into a program, or the debug_level which is dynamic state information.
+ *
+ * Notes:
+ *\li	It is necessary to specify the logging context the configuration
+ * 	will be used with because the number of categories and modules
+ *	needs to be known in order to set the configuration.  However,
+ *	the configuration is not used by the logging context until the
+ *	isc_logconfig_use function is called.
+ *
+ *\li	The memory context used for operations that allocate memory for
+ *	the configuration is that of the logging context, as specified
+ *	in the isc_log_create call.
+ *
+ *\li	Four default channels are established:
+ *\verbatim
+ *	    	default_syslog
+ *		 - log to syslog's daemon facility #ISC_LOG_INFO or higher
+ *		default_stderr
+ *		 - log to stderr #ISC_LOG_INFO or higher
+ *		default_debug
+ *		 - log to stderr #ISC_LOG_DEBUG dynamically
+ *		null
+ *		 - log nothing
+ *\endverbatim
+ *
+ * Requires:
+ *\li 	lctx is a valid logging context.
+ *\li	lcftp is not null and *lcfgp is null.
+ *
+ * Ensures:
+ *\li	*lcfgp will point to a valid logging context if all of the necessary
+ *	memory was allocated, or NULL otherwise.
+ *\li	On failure, no additional memory is allocated.
+ *
+ * Returns:
+ *\li	#ISC_R_SUCCESS		Success
+ *\li	#ISC_R_NOMEMORY		Resource limit: Out of memory
+ */
+
+isc_logconfig_t *
+isc_logconfig_get(isc_log_t *lctx);
+/*%<
+ * Returns a pointer to the configuration currently in use by the log context.
+ *
+ * Requires:
+ *\li	lctx is a valid context.
+ *
+ * Ensures:
+ *\li	The configuration pointer is non-null.
+ *
+ * Returns:
+ *\li	The configuration pointer.
+ */
+
+isc_result_t
+isc_logconfig_use(isc_log_t *lctx, isc_logconfig_t *lcfg);
+/*%<
+ * Associate a new configuration with a logging context.
+ *
+ * Notes:
+ *\li	This is thread safe.  The logging context will lock a mutex
+ *	before attempting to swap in the new configuration, and isc_log_doit
+ *	(the internal function used by all of isc_log_[v]write[1]) locks
+ *	the same lock for the duration of its use of the configuration.
+ *
+ * Requires:
+ *\li	lctx is a valid logging context.
+ *\li	lcfg is a valid logging configuration.
+ *\li	lctx is the same configuration given to isc_logconfig_create
+ *		when the configuration was created.
+ *
+ * Ensures:
+ *\li	Future calls to isc_log_write will use the new configuration.
+ *
+ * Returns:
+ *\li	#ISC_R_SUCCESS		Success
+ *\li	#ISC_R_NOMEMORY		Resource limit: Out of memory
+ */
+
+void
+isc_log_destroy(isc_log_t **lctxp);
+/*%<
+ * Deallocate the memory associated with a logging context.
+ *
+ * Requires:
+ *\li	*lctx is a valid logging context.
+ *
+ * Ensures:
+ *\li	All of the memory associated with the logging context is returned
+ *	to the free memory pool.
+ *
+ *\li	Any open files are closed.
+ *
+ *\li	The logging context is marked as invalid.
+ */
+
+void
+isc_logconfig_destroy(isc_logconfig_t **lcfgp);
+/*%<
+ * Destroy a logging configuration.
+ *
+ * Notes:
+ *\li	This function cannot be used directly with the return value of
+ *	isc_logconfig_get, because a logging context must always have
+ *	a valid configuration associated with it.
+ *
+ * Requires:
+ *\li	lcfgp is not null and *lcfgp is a valid logging configuration.
+ *\li	The logging configuration is not in use by an existing logging context.
+ *
+ * Ensures:
+ *\li	All memory allocated for the configuration is freed.
+ *
+ *\li	The configuration is marked as invalid.
+ */
+
+void
+isc_log_registercategories(isc_log_t *lctx, isc_logcategory_t categories[]);
+/*%<
+ * Identify logging categories a library will use.
+ *
+ * Notes:
+ *\li	A category should only be registered once, but no mechanism enforces
+ *	this rule.
+ *
+ *\li	The end of the categories array is identified by a NULL name.
+ *
+ *\li	Because the name is used by #ISC_LOG_PRINTCATEGORY, it should not
+ *	be altered or destroyed after isc_log_registercategories().
+ *
+ *\li	Because each element of the categories array is used by
+ *	isc_log_categorybyname, it should not be altered or destroyed
+ *	after registration.
+ *
+ *\li	The value of the id integer in each structure is overwritten
+ *	by this function, and so id need not be initialized to any particular
+ *	value prior to the function call.
+ *
+ *\li	A subsequent call to isc_log_registercategories with the same
+ *	logging context (but new categories) will cause the last
+ *	element of the categories array from the prior call to have
+ *	its "name" member changed from NULL to point to the new
+ *	categories array, and its "id" member set to UINT_MAX.
+ *
+ * Requires:
+ *\li	lctx is a valid logging context.
+ *\li	categories != NULL.
+ *\li	categories[0].name != NULL.
+ *
+ * Ensures:
+ * \li	There are references to each category in the logging context,
+ * 	so they can be used with isc_log_usechannel() and isc_log_write().
+ */
+
+void
+isc_log_registermodules(isc_log_t *lctx, isc_logmodule_t modules[]);
+/*%<
+ * Identify logging categories a library will use.
+ *
+ * Notes:
+ *\li	A module should only be registered once, but no mechanism enforces
+ *	this rule.
+ *
+ *\li	The end of the modules array is identified by a NULL name.
+ *
+ *\li	Because the name is used by #ISC_LOG_PRINTMODULE, it should not
+ *	be altered or destroyed after isc_log_registermodules().
+ *
+ *\li	Because each element of the modules array is used by
+ *	isc_log_modulebyname, it should not be altered or destroyed
+ *	after registration.
+ *
+ *\li	The value of the id integer in each structure is overwritten
+ *	by this function, and so id need not be initialized to any particular
+ *	value prior to the function call.
+ *
+ *\li	A subsequent call to isc_log_registermodules with the same
+ *	logging context (but new modules) will cause the last
+ *	element of the modules array from the prior call to have
+ *	its "name" member changed from NULL to point to the new
+ *	modules array, and its "id" member set to UINT_MAX.
+ *
+ * Requires:
+ *\li	lctx is a valid logging context.
+ *\li	modules != NULL.
+ *\li	modules[0].name != NULL;
+ *
+ * Ensures:
+ *\li	Each module has a reference in the logging context, so they can be
+ *	used with isc_log_usechannel() and isc_log_write().
+ */
+
+isc_result_t
+isc_log_createchannel(isc_logconfig_t *lcfg, const char *name,
+		      unsigned int type, int level,
+		      const isc_logdestination_t *destination,
+		      unsigned int flags);
+/*%<
+ * Specify the parameters of a logging channel.
+ *
+ * Notes:
+ *\li	The name argument is copied to memory in the logging context, so
+ *	it can be altered or destroyed after isc_log_createchannel().
+ *
+ *\li	Defining a very large number of channels will have a performance
+ *	impact on isc_log_usechannel(), since the names are searched
+ *	linearly until a match is made.  This same issue does not affect
+ *	isc_log_write, however.
+ *
+ *\li	Channel names can be redefined; this is primarily useful for programs
+ *	that want their own definition of default_syslog, default_debug
+ *	and default_stderr.
+ *
+ *\li	Any channel that is redefined will not affect logging that was
+ *	already directed to its original definition, _except_ for the
+ *	default_stderr channel.  This case is handled specially so that
+ *	the default logging category can be changed by redefining
+ *	default_stderr.  (XXXDCL Though now that I think of it, the default
+ *	logging category can be changed with only one additional function
+ *	call by defining a new channel and then calling isc_log_usechannel()
+ *	for #ISC_LOGCATEGORY_DEFAULT.)
+ *
+ *\li	Specifying #ISC_LOG_PRINTTIME or #ISC_LOG_PRINTTAG for syslog is allowed,
+ *	but probably not what you wanted to do.
+ *
+ *	#ISC_LOG_DEBUGONLY will mark the channel as usable only when the
+ *	debug level of the logging context (see isc_log_setdebuglevel)
+ *	is non-zero.
+ *
+ * Requires:
+ *\li	lcfg is a valid logging configuration.
+ *
+ *\li	name is not NULL.
+ *
+ *\li	type is #ISC_LOG_TOSYSLOG, #ISC_LOG_TOFILE, #ISC_LOG_TOFILEDESC or
+ *		#ISC_LOG_TONULL.
+ *
+ *\li	destination is not NULL unless type is #ISC_LOG_TONULL.
+ *
+ *\li	level is >= #ISC_LOG_CRITICAL (the most negative logging level).
+ *
+ *\li	flags does not include any bits aside from the ISC_LOG_PRINT* bits
+ *	or #ISC_LOG_DEBUGONLY.
+ *
+ * Ensures:
+ *\li	#ISC_R_SUCCESS
+ *		A channel with the given name is usable with
+ *		isc_log_usechannel().
+ *
+ *\li	#ISC_R_NOMEMORY or #ISC_R_UNEXPECTED
+ *		No additional memory is being used by the logging context.
+ *		Any channel that previously existed with the given name
+ *		is not redefined.
+ *
+ * Returns:
+ *\li	#ISC_R_SUCCESS		Success
+ *\li	#ISC_R_NOMEMORY		Resource limit: Out of memory
+ *\li	#ISC_R_UNEXPECTED	type was out of range and REQUIRE()
+ *					was disabled.
+ */
+
+isc_result_t
+isc_log_usechannel(isc_logconfig_t *lcfg, const char *name,
+		   const isc_logcategory_t *category,
+		   const isc_logmodule_t *module);
+/*%<
+ * Associate a named logging channel with a category and module that
+ * will use it.
+ *
+ * Notes:
+ *\li	The name is searched for linearly in the set of known channel names
+ *	until a match is found.  (Note the performance impact of a very large
+ *	number of named channels.)  When multiple channels of the same
+ *	name are defined, the most recent definition is found.
+ *
+ *\li	Specifying a very large number of channels for a category will have
+ *	a moderate impact on performance in isc_log_write(), as each
+ *	call looks up the category for the start of a linked list, which
+ *	it follows all the way to the end to find matching modules.  The
+ *	test for matching modules is  integral, though.
+ *
+ *\li	If category is NULL, then the channel is associated with the indicated
+ *	module for all known categories (including the "default" category).
+ *
+ *\li	If module is NULL, then the channel is associated with every module
+ *	that uses that category.
+ *
+ *\li	Passing both category and module as NULL would make every log message
+ *	use the indicated channel.
+ *
+ * \li	Specifying a channel that is #ISC_LOG_TONULL for a category/module pair
+ *	has no effect on any other channels associated with that pair,
+ *	regardless of ordering.  Thus you cannot use it to "mask out" one
+ *	category/module pair when you have specified some other channel that
+ * 	is also used by that category/module pair.
+ *
+ * Requires:
+ *\li	lcfg is a valid logging configuration.
+ *
+ *\li	category is NULL or has an id that is in the range of known ids.
+ *
+ *	module is NULL or has an id that is in the range of known ids.
+ *
+ * Ensures:
+ *\li	#ISC_R_SUCCESS
+ *		The channel will be used by the indicated category/module
+ *		arguments.
+ *
+ *\li	#ISC_R_NOMEMORY
+ *		If assignment for a specific category has been requested,
+ *		the channel has not been associated with the indicated
+ *		category/module arguments and no additional memory is
+ *		used by the logging context.
+ *		If assignment for all categories has been requested
+ *		then _some_ may have succeeded (starting with category
+ *		"default" and progressing through the order of categories
+ *		passed to isc_log_registercategories()) and additional memory
+ *		is being used by whatever assignments succeeded.
+ *
+ * Returns:
+ *\li	#ISC_R_SUCCESS	Success
+ *\li	#ISC_R_NOMEMORY	Resource limit: Out of memory
+ */
+
+/* Attention: next four comments PRECEED code */
+/*!
+ *   \brief
+ * Write a message to the log channels.
+ *
+ * Notes:
+ *\li	Log messages containing natural language text should be logged with
+ *	isc_log_iwrite() to allow for localization.
+ *
+ *\li	lctx can be NULL; this is allowed so that programs which use
+ *	libraries that use the ISC logging system are not required to
+ *	also use it.
+ *
+ *\li	The format argument is a printf(3) string, with additional arguments
+ *	as necessary.
+ *
+ * Requires:
+ *\li	lctx is a valid logging context.
+ *
+ *\li	The category and module arguments must have ids that are in the
+ *	range of known ids, as established by isc_log_registercategories()
+ *	and isc_log_registermodules().
+ *
+ *\li	level != #ISC_LOG_DYNAMIC.  ISC_LOG_DYNAMIC is used only to define
+ *	channels, and explicit debugging level must be identified for
+ *	isc_log_write() via ISC_LOG_DEBUG(level).
+ *
+ *\li	format != NULL.
+ *
+ * Ensures:
+ *\li	The log message is written to every channel associated with the
+ *	indicated category/module pair.
+ *
+ * Returns:
+ *\li	Nothing.  Failure to log a message is not construed as a
+ *	meaningful error.
+ */
+void
+isc_log_write(isc_log_t *lctx, isc_logcategory_t *category,
+	       isc_logmodule_t *module, int level,
+	      const char *format, ...)
+
+ISC_FORMAT_PRINTF(5, 6);
+
+/*%
+ * Write a message to the log channels.
+ *
+ * Notes:
+ *\li	lctx can be NULL; this is allowed so that programs which use
+ *	libraries that use the ISC logging system are not required to
+ *	also use it.
+ *
+ *\li	The format argument is a printf(3) string, with additional arguments
+ *	as necessary.
+ *
+ * Requires:
+ *\li	lctx is a valid logging context.
+ *
+ *\li	The category and module arguments must have ids that are in the
+ *	range of known ids, as established by isc_log_registercategories()
+ *	and isc_log_registermodules().
+ *
+ *\li	level != #ISC_LOG_DYNAMIC.  ISC_LOG_DYNAMIC is used only to define
+ *	channels, and explicit debugging level must be identified for
+ *	isc_log_write() via ISC_LOG_DEBUG(level).
+ *
+ *\li	format != NULL.
+ *
+ * Ensures:
+ *\li	The log message is written to every channel associated with the
+ *	indicated category/module pair.
+ *
+ * Returns:
+ *\li	Nothing.  Failure to log a message is not construed as a
+ *	meaningful error.
+ */
+void
+isc_log_vwrite(isc_log_t *lctx, isc_logcategory_t *category,
+	       isc_logmodule_t *module, int level,
+	       const char *format, va_list args)
+
+ISC_FORMAT_PRINTF(5, 0);
+
+/*%
+ * Write a message to the log channels, pruning duplicates that occur within
+ * a configurable amount of seconds (see isc_log_[sg]etduplicateinterval).
+ * This function is otherwise identical to isc_log_write().
+ */
+void
+isc_log_write1(isc_log_t *lctx, isc_logcategory_t *category,
+	       isc_logmodule_t *module, int level, const char *format, ...)
+
+ISC_FORMAT_PRINTF(5, 6);
+
+/*%
+ * Write a message to the log channels, pruning duplicates that occur within
+ * a configurable amount of seconds (see isc_log_[sg]etduplicateinterval).
+ * This function is otherwise identical to isc_log_vwrite().
+ */
+void
+isc_log_vwrite1(isc_log_t *lctx, isc_logcategory_t *category,
+		isc_logmodule_t *module, int level, const char *format,
+		va_list args)
+
+ISC_FORMAT_PRINTF(5, 0);
+
+/*%
+ * These are four internationalized versions of the isc_log_[v]write[1]
+ * functions.
+ *
+ * The only difference is that they take arguments for a message
+ * catalog, message set, and message number, all immediately preceding the
+ * format argument.  The format argument becomes the default text, a la
+ * isc_msgcat_get.  If the message catalog is NULL, no lookup is attempted
+ * for a message -- which makes the message set and message number irrelevant,
+ * and the non-internationalized call should have probably been used instead.
+ *
+ * Yes, that means there are now *eight* interfaces to logging a message.
+ * Sheesh.   Make the madness stop!
+ */
+/*@{*/
+void
+isc_log_iwrite(isc_log_t *lctx, isc_logcategory_t *category,
+	      isc_logmodule_t *module, int level,
+	      isc_msgcat_t *msgcat, int msgset, int message,
+	      const char *format, ...)
+ISC_FORMAT_PRINTF(8, 9);
+
+void
+isc_log_ivwrite(isc_log_t *lctx, isc_logcategory_t *category,
+		isc_logmodule_t *module, int level,
+		isc_msgcat_t *msgcat, int msgset, int message,
+		const char *format, va_list args)
+ISC_FORMAT_PRINTF(8, 0);
+
+void
+isc_log_iwrite1(isc_log_t *lctx, isc_logcategory_t *category,
+		isc_logmodule_t *module, int level,
+		isc_msgcat_t *msgcat, int msgset, int message,
+		const char *format, ...)
+ISC_FORMAT_PRINTF(8, 9);
+
+void
+isc_log_ivwrite1(isc_log_t *lctx, isc_logcategory_t *category,
+		 isc_logmodule_t *module, int level,
+		 isc_msgcat_t *msgcat, int msgset, int message,
+		 const char *format, va_list args)
+ISC_FORMAT_PRINTF(8, 0);
+/*@}*/
+
+void
+isc_log_setdebuglevel(isc_log_t *lctx, unsigned int level);
+/*%<
+ * Set the debugging level used for logging.
+ *
+ * Notes:
+ *\li	Setting the debugging level to 0 disables debugging log messages.
+ *
+ * Requires:
+ *\li	lctx is a valid logging context.
+ *
+ * Ensures:
+ *\li	The debugging level is set to the requested value.
+ */
+
+unsigned int
+isc_log_getdebuglevel(isc_log_t *lctx);
+/*%<
+ * Get the current debugging level.
+ *
+ * Notes:
+ *\li	This is provided so that a program can have a notion of
+ *	"increment debugging level" or "decrement debugging level"
+ *	without needing to keep track of what the current level is.
+ *
+ *\li	A return value of 0 indicates that debugging messages are disabled.
+ *
+ * Requires:
+ *\li	lctx is a valid logging context.
+ *
+ * Ensures:
+ *\li	The current logging debugging level is returned.
+ */
+
+isc_boolean_t
+isc_log_wouldlog(isc_log_t *lctx, int level);
+/*%<
+ * Determine whether logging something to 'lctx' at 'level' would
+ * actually cause something to be logged somewhere.
+ *
+ * If #ISC_FALSE is returned, it is guaranteed that nothing would
+ * be logged, allowing the caller to omit unnecessary
+ * isc_log_write() calls and possible message preformatting.
+ */
+
+void
+isc_log_setduplicateinterval(isc_logconfig_t *lcfg, unsigned int interval);
+/*%<
+ * Set the interval over which duplicate log messages will be ignored
+ * by isc_log_[v]write1(), in seconds.
+ *
+ * Notes:
+ *\li	Increasing the duplicate interval from X to Y will not necessarily
+ *	filter out duplicates of messages logged in Y - X seconds since the
+ *	increase.  (Example: Message1 is logged at midnight.  Message2
+ *	is logged at 00:01:00, when the interval is only 30 seconds, causing
+ *	Message1 to be expired from the log message history.  Then the interval
+ *	is increased to 3000 (five minutes) and at 00:04:00 Message1 is logged
+ *	again.  It will appear the second time even though less than five
+ *	passed since the first occurrence.
+ *
+ * Requires:
+ *\li	lctx is a valid logging context.
+ */
+
+unsigned int
+isc_log_getduplicateinterval(isc_logconfig_t *lcfg);
+/*%<
+ * Get the current duplicate filtering interval.
+ *
+ * Requires:
+ *\li	lctx is a valid logging context.
+ *
+ * Returns:
+ *\li	The current duplicate filtering interval.
+ */
+
+isc_result_t
+isc_log_settag(isc_logconfig_t *lcfg, const char *tag);
+/*%<
+ * Set the program name or other identifier for #ISC_LOG_PRINTTAG.
+ *
+ * Requires:
+ *\li	lcfg is a valid logging configuration.
+ *
+ * Notes:
+ *\li	If this function has not set the tag to a non-NULL, non-empty value,
+ *	then the #ISC_LOG_PRINTTAG channel flag will not print anything.
+ *	Unlike some implementations of syslog on Unix systems, you *must* set
+ *	the tag in order to get it logged.  It is not implicitly derived from
+ *	the program name (which is pretty impossible to infer portably).
+ *
+ *\li	Setting the tag to NULL or the empty string will also cause the
+ *	#ISC_LOG_PRINTTAG channel flag to not print anything.  If tag equals the
+ *	empty string, calls to isc_log_gettag will return NULL.
+ *
+ * Returns:
+ *\li	#ISC_R_SUCCESS	Success
+ *\li	#ISC_R_NOMEMORY  Resource Limit: Out of memory
+ *
+ * XXXDCL when creating a new isc_logconfig_t, it might be nice if the tag
+ * of the currently active isc_logconfig_t was inherited.  this does not
+ * currently happen.
+ */
+
+char *
+isc_log_gettag(isc_logconfig_t *lcfg);
+/*%<
+ * Get the current identifier printed with #ISC_LOG_PRINTTAG.
+ *
+ * Requires:
+ *\li	lcfg is a valid logging configuration.
+ *
+ * Notes:
+ *\li	Since isc_log_settag() will not associate a zero-length string
+ *	with the logging configuration, attempts to do so will cause
+ *	this function to return NULL.  However, a determined programmer
+ *	will observe that (currently) a tag of length greater than zero
+ *	could be set, and then modified to be zero length.
+ *
+ * Returns:
+ *\li	A pointer to the current identifier, or NULL if none has been set.
+ */
+
+void
+isc_log_opensyslog(const char *tag, int options, int facility);
+/*%<
+ * Initialize syslog logging.
+ *
+ * Notes:
+ *\li	XXXDCL NT
+ *	This is currently equivalent to openlog(), but is not going to remain
+ *	that way.  In the meantime, the arguments are all identical to
+ *	those used by openlog(3), as follows:
+ *
+ * \code
+ *		tag: The string to use in the position of the program
+ *			name in syslog messages.  Most (all?) syslogs
+ *			will use basename(argv[0]) if tag is NULL.
+ *
+ *		options: LOG_CONS, LOG_PID, LOG_NDELAY ... whatever your
+ *			syslog supports.
+ *
+ *		facility: The default syslog facility.  This is irrelevant
+ *			since isc_log_write will ALWAYS use the channel's
+ *			declared facility.
+ * \endcode
+ *
+ *\li	Zero effort has been made (yet) to accommodate systems with openlog()
+ *	that only takes two arguments, or to identify valid syslog
+ *	facilities or options for any given architecture.
+ *
+ *\li	It is necessary to call isc_log_opensyslog() to initialize
+ *	syslogging on machines which do not support network connections to
+ *	syslogd because they require a Unix domain socket to be used.  Since
+ *	this is a chore to determine at run-time, it is suggested that it
+ *	always be called by programs using the ISC logging system.
+ *
+ * Requires:
+ *\li	Nothing.
+ *
+ * Ensures:
+ *\li	openlog() is called to initialize the syslog system.
+ */
+
+void
+isc_log_closefilelogs(isc_log_t *lctx);
+/*%<
+ * Close all open files used by #ISC_LOG_TOFILE channels.
+ *
+ * Notes:
+ *\li	This function is provided for programs that want to use their own
+ *	log rolling mechanism rather than the one provided internally.
+ *	For example, a program that wanted to keep daily logs would define
+ *	a channel which used #ISC_LOG_ROLLNEVER, then once a day would
+ *	rename the log file and call isc_log_closefilelogs().
+ *
+ *\li	#ISC_LOG_TOFILEDESC channels are unaffected.
+ *
+ * Requires:
+ *\li	lctx is a valid context.
+ *
+ * Ensures:
+ *\li	The open files are closed and will be reopened when they are
+ *	next needed.
+ */
+
+isc_logcategory_t *
+isc_log_categorybyname(isc_log_t *lctx, const char *name);
+/*%<
+ * Find a category by its name.
+ *
+ * Notes:
+ *\li	The string name of a category is not required to be unique.
+ *
+ * Requires:
+ *\li	lctx is a valid context.
+ *\li	name is not NULL.
+ *
+ * Returns:
+ *\li	A pointer to the _first_ isc_logcategory_t structure used by "name".
+ *
+ *\li	NULL if no category exists by that name.
+ */
+
+isc_logmodule_t *
+isc_log_modulebyname(isc_log_t *lctx, const char *name);
+/*%<
+ * Find a module by its name.
+ *
+ * Notes:
+ *\li	The string name of a module is not required to be unique.
+ *
+ * Requires:
+ *\li	lctx is a valid context.
+ *\li	name is not NULL.
+ *
+ * Returns:
+ *\li	A pointer to the _first_ isc_logmodule_t structure used by "name".
+ *
+ *\li	NULL if no module exists by that name.
+ */
+
+void
+isc_log_setcontext(isc_log_t *lctx);
+/*%<
+ * Sets the context used by the libisc for logging.
+ *
+ * Requires:
+ *\li	lctx be a valid context.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_LOG_H */
diff --git a/src/lib/bind9/include/isc/magic.h b/src/lib/bind9/include/isc/magic.h
new file mode 100644
index 0000000..0a864ea
--- /dev/null
+++ b/src/lib/bind9/include/isc/magic.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: magic.h,v 1.18 2007-06-19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_MAGIC_H
+#define ISC_MAGIC_H 1
+
+/*! \file isc/magic.h */
+
+typedef struct {
+	unsigned int magic;
+} isc__magic_t;
+
+
+/*%
+ * To use this macro the magic number MUST be the first thing in the
+ * structure, and MUST be of type "unsigned int".
+ * The intent of this is to allow magic numbers to be checked even though
+ * the object is otherwise opaque.
+ */
+#define ISC_MAGIC_VALID(a,b)	(((a) != NULL) && \
+				 (((const isc__magic_t *)(a))->magic == (b)))
+
+#define ISC_MAGIC(a, b, c, d)	((a) << 24 | (b) << 16 | (c) << 8 | (d))
+
+#endif /* ISC_MAGIC_H */
diff --git a/src/lib/bind9/include/isc/md5.h b/src/lib/bind9/include/isc/md5.h
new file mode 100644
index 0000000..9017115
--- /dev/null
+++ b/src/lib/bind9/include/isc/md5.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2004-2007, 2009, 2010  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: md5.h,v 1.20 2010-01-07 23:48:54 tbox Exp $ */
+
+/*! \file isc/md5.h
+ * \brief This is the header file for the MD5 message-digest algorithm.
+ *
+ * The algorithm is due to Ron Rivest.  This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ *
+ * Changed so as no longer to depend on Colin Plumb's `usual.h'
+ * header definitions; now uses stuff from dpkg's config.h
+ *  - Ian Jackson <ijackson at nyx.cs.du.edu>.
+ * Still in the public domain.
+ */
+
+#ifndef ISC_MD5_H
+#define ISC_MD5_H 1
+
+#include <isc/lang.h>
+#include <isc/platform.h>
+#include <isc/types.h>
+
+#define ISC_MD5_DIGESTLENGTH 16U
+#define ISC_MD5_BLOCK_LENGTH 64U
+
+#ifdef ISC_PLATFORM_OPENSSLHASH
+#include <openssl/evp.h>
+
+typedef EVP_MD_CTX isc_md5_t;
+
+#else
+
+typedef struct {
+	isc_uint32_t buf[4];
+	isc_uint32_t bytes[2];
+	isc_uint32_t in[16];
+} isc_md5_t;
+#endif
+
+ISC_LANG_BEGINDECLS
+
+void
+isc_md5_init(isc_md5_t *ctx);
+
+void
+isc_md5_invalidate(isc_md5_t *ctx);
+
+void
+isc_md5_update(isc_md5_t *ctx, const unsigned char *buf, unsigned int len);
+
+void
+isc_md5_final(isc_md5_t *ctx, unsigned char *digest);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_MD5_H */
diff --git a/src/lib/bind9/include/isc/mem.h b/src/lib/bind9/include/isc/mem.h
new file mode 100644
index 0000000..e0a7fe5
--- /dev/null
+++ b/src/lib/bind9/include/isc/mem.h
@@ -0,0 +1,750 @@
+/*
+ * Copyright (C) 2004-2010  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1997-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: mem.h,v 1.89 2010-08-11 22:54:58 jinmei Exp $ */
+
+#ifndef ISC_MEM_H
+#define ISC_MEM_H 1
+
+/*! \file isc/mem.h */
+
+#include <stdio.h>
+
+#include <isc/lang.h>
+#include <isc/mutex.h>
+#include <isc/platform.h>
+#include <isc/types.h>
+#include <isc/xml.h>
+
+ISC_LANG_BEGINDECLS
+
+#define ISC_MEM_LOWATER 0
+#define ISC_MEM_HIWATER 1
+typedef void (*isc_mem_water_t)(void *, int);
+
+typedef void * (*isc_memalloc_t)(void *, size_t);
+typedef void (*isc_memfree_t)(void *, void *);
+
+/*%
+ * Define ISC_MEM_DEBUG=1 to make all functions that free memory
+ * set the pointer being freed to NULL after being freed.
+ * This is the default; set ISC_MEM_DEBUG=0 to disable it.
+ */
+#ifndef ISC_MEM_DEBUG
+#define ISC_MEM_DEBUG 1
+#endif
+
+/*%
+ * Define ISC_MEM_TRACKLINES=1 to turn on detailed tracing of memory
+ * allocation and freeing by file and line number.
+ */
+#ifndef ISC_MEM_TRACKLINES
+#define ISC_MEM_TRACKLINES 1
+#endif
+
+/*%
+ * Define ISC_MEM_CHECKOVERRUN=1 to turn on checks for using memory outside
+ * the requested space.  This will increase the size of each allocation.
+ */
+#ifndef ISC_MEM_CHECKOVERRUN
+#define ISC_MEM_CHECKOVERRUN 1
+#endif
+
+/*%
+ * Define ISC_MEM_FILL=1 to fill each block of memory returned to the system
+ * with the byte string '0xbe'.  This helps track down uninitialized pointers
+ * and the like.  On freeing memory, the space is filled with '0xde' for
+ * the same reasons.
+ */
+#ifndef ISC_MEM_FILL
+#define ISC_MEM_FILL 1
+#endif
+
+/*%
+ * Define ISC_MEMPOOL_NAMES=1 to make memory pools store a symbolic
+ * name so that the leaking pool can be more readily identified in
+ * case of a memory leak.
+ */
+#ifndef ISC_MEMPOOL_NAMES
+#define ISC_MEMPOOL_NAMES 1
+#endif
+
+LIBISC_EXTERNAL_DATA extern unsigned int isc_mem_debugging;
+/*@{*/
+#define ISC_MEM_DEBUGTRACE		0x00000001U
+#define ISC_MEM_DEBUGRECORD		0x00000002U
+#define ISC_MEM_DEBUGUSAGE		0x00000004U
+#define ISC_MEM_DEBUGSIZE		0x00000008U
+#define ISC_MEM_DEBUGCTX		0x00000010U
+#define ISC_MEM_DEBUGALL		0x0000001FU
+/*!<
+ * The variable isc_mem_debugging holds a set of flags for
+ * turning certain memory debugging options on or off at
+ * runtime.  It is initialized to the value ISC_MEM_DEGBUGGING,
+ * which is 0 by default but may be overridden at compile time.
+ * The following flags can be specified:
+ *
+ * \li #ISC_MEM_DEBUGTRACE
+ *	Log each allocation and free to isc_lctx.
+ *
+ * \li #ISC_MEM_DEBUGRECORD
+ *	Remember each allocation, and match them up on free.
+ *	Crash if a free doesn't match an allocation.
+ *
+ * \li #ISC_MEM_DEBUGUSAGE
+ *	If a hi_water mark is set, print the maximum inuse memory
+ *	every time it is raised once it exceeds the hi_water mark.
+ *
+ * \li #ISC_MEM_DEBUGSIZE
+ *	Check the size argument being passed to isc_mem_put() matches
+ *	that passed to isc_mem_get().
+ *
+ * \li #ISC_MEM_DEBUGCTX
+ *	Check the mctx argument being passed to isc_mem_put() matches
+ *	that passed to isc_mem_get().
+ */
+/*@}*/
+
+#if ISC_MEM_TRACKLINES
+#define _ISC_MEM_FILELINE	, __FILE__, __LINE__
+#define _ISC_MEM_FLARG		, const char *, unsigned int
+#else
+#define _ISC_MEM_FILELINE
+#define _ISC_MEM_FLARG
+#endif
+
+/*!
+ * Define ISC_MEM_USE_INTERNAL_MALLOC=1 to use the internal malloc()
+ * implementation in preference to the system one.  The internal malloc()
+ * is very space-efficient, and quite fast on uniprocessor systems.  It
+ * performs poorly on multiprocessor machines.
+ * JT: we can overcome the performance issue on multiprocessor machines
+ * by carefully separating memory contexts.
+ */
+
+#ifndef ISC_MEM_USE_INTERNAL_MALLOC
+#define ISC_MEM_USE_INTERNAL_MALLOC 1
+#endif
+
+/*
+ * Flags for isc_mem_create2()calls.
+ */
+#define ISC_MEMFLAG_NOLOCK	0x00000001	 /* no lock is necessary */
+#define ISC_MEMFLAG_INTERNAL	0x00000002	 /* use internal malloc */
+#if ISC_MEM_USE_INTERNAL_MALLOC
+#define ISC_MEMFLAG_DEFAULT 	ISC_MEMFLAG_INTERNAL
+#else
+#define ISC_MEMFLAG_DEFAULT 	0
+#endif
+
+
+/*%<
+ * We use either isc___mem (three underscores) or isc__mem (two) depending on
+ * whether it's for BIND9's internal purpose (with -DBIND9) or generic export
+ * library.  This condition is generally handled in isc/namespace.h, but for
+ * Windows it doesn't work if it involves multiple times of macro expansion
+ * (such as isc_mem to isc__mem then to isc___mem).  The following definitions
+ * are used to work around this portability issue.  Right now, we don't support
+ * the export library for Windows, so we always use the three-underscore
+ * version.
+ */
+#ifdef WIN32
+#define ISCMEMFUNC(sfx) isc___mem_ ## sfx
+#define ISCMEMPOOLFUNC(sfx) isc___mempool_ ## sfx
+#else
+#define ISCMEMFUNC(sfx) isc__mem_ ## sfx
+#define ISCMEMPOOLFUNC(sfx) isc__mempool_ ## sfx
+#endif
+
+#define isc_mem_get(c, s)	ISCMEMFUNC(get)((c), (s) _ISC_MEM_FILELINE)
+#define isc_mem_allocate(c, s)	ISCMEMFUNC(allocate)((c), (s) _ISC_MEM_FILELINE)
+#define isc_mem_reallocate(c, p, s) ISCMEMFUNC(reallocate)((c), (p), (s) _ISC_MEM_FILELINE)
+#define isc_mem_strdup(c, p)	ISCMEMFUNC(strdup)((c), (p) _ISC_MEM_FILELINE)
+#define isc_mempool_get(c)	ISCMEMPOOLFUNC(get)((c) _ISC_MEM_FILELINE)
+
+/*%
+ * isc_mem_putanddetach() is a convenience function for use where you
+ * have a structure with an attached memory context.
+ *
+ * Given:
+ *
+ * \code
+ * struct {
+ *	...
+ *	isc_mem_t *mctx;
+ *	...
+ * } *ptr;
+ *
+ * isc_mem_t *mctx;
+ *
+ * isc_mem_putanddetach(&ptr->mctx, ptr, sizeof(*ptr));
+ * \endcode
+ *
+ * is the equivalent of:
+ *
+ * \code
+ * mctx = NULL;
+ * isc_mem_attach(ptr->mctx, &mctx);
+ * isc_mem_detach(&ptr->mctx);
+ * isc_mem_put(mctx, ptr, sizeof(*ptr));
+ * isc_mem_detach(&mctx);
+ * \endcode
+ */
+
+/*% memory and memory pool methods */
+typedef struct isc_memmethods {
+	void (*attach)(isc_mem_t *source, isc_mem_t **targetp);
+	void (*detach)(isc_mem_t **mctxp);
+	void (*destroy)(isc_mem_t **mctxp);
+	void *(*memget)(isc_mem_t *mctx, size_t size _ISC_MEM_FLARG);
+	void (*memput)(isc_mem_t *mctx, void *ptr, size_t size _ISC_MEM_FLARG);
+	void (*memputanddetach)(isc_mem_t **mctxp, void *ptr,
+				size_t size _ISC_MEM_FLARG);
+	void *(*memallocate)(isc_mem_t *mctx, size_t size _ISC_MEM_FLARG);
+	void *(*memreallocate)(isc_mem_t *mctx, void *ptr,
+			       size_t size _ISC_MEM_FLARG);
+	char *(*memstrdup)(isc_mem_t *mctx, const char *s _ISC_MEM_FLARG);
+	void (*memfree)(isc_mem_t *mctx, void *ptr _ISC_MEM_FLARG);
+	void (*setdestroycheck)(isc_mem_t *mctx, isc_boolean_t flag);
+	void (*setwater)(isc_mem_t *ctx, isc_mem_water_t water,
+			 void *water_arg, size_t hiwater, size_t lowater);
+	void (*waterack)(isc_mem_t *ctx, int flag);
+	size_t (*inuse)(isc_mem_t *mctx);
+	isc_boolean_t (*isovermem)(isc_mem_t *mctx);
+	isc_result_t (*mpcreate)(isc_mem_t *mctx, size_t size,
+				 isc_mempool_t **mpctxp);
+} isc_memmethods_t;
+
+typedef struct isc_mempoolmethods {
+	void (*destroy)(isc_mempool_t **mpctxp);
+	void *(*get)(isc_mempool_t *mpctx _ISC_MEM_FLARG);
+	void (*put)(isc_mempool_t *mpctx, void *mem _ISC_MEM_FLARG);
+	unsigned int (*getallocated)(isc_mempool_t *mpctx);
+	void (*setmaxalloc)(isc_mempool_t *mpctx, unsigned int limit);
+	void (*setfreemax)(isc_mempool_t *mpctx, unsigned int limit);
+	void (*setname)(isc_mempool_t *mpctx, const char *name);
+	void (*associatelock)(isc_mempool_t *mpctx, isc_mutex_t *lock);
+	void (*setfillcount)(isc_mempool_t *mpctx, unsigned int limit);
+} isc_mempoolmethods_t;
+
+/*%
+ * This structure is actually just the common prefix of a memory context
+ * implementation's version of an isc_mem_t.
+ * \brief
+ * Direct use of this structure by clients is forbidden.  mctx implementations
+ * may change the structure.  'magic' must be ISCAPI_MCTX_MAGIC for any of the
+ * isc_mem_ routines to work.  mctx implementations must maintain all mctx
+ * invariants.
+ */
+struct isc_mem {
+	unsigned int		impmagic;
+	unsigned int		magic;
+	isc_memmethods_t	*methods;
+};
+
+#define ISCAPI_MCTX_MAGIC	ISC_MAGIC('A','m','c','x')
+#define ISCAPI_MCTX_VALID(m)	((m) != NULL && \
+				 (m)->magic == ISCAPI_MCTX_MAGIC)
+
+/*%
+ * This is the common prefix of a memory pool context.  The same note as
+ * that for the mem structure applies.
+ */
+struct isc_mempool {
+	unsigned int		impmagic;
+	unsigned int		magic;
+	isc_mempoolmethods_t	*methods;
+};
+
+#define ISCAPI_MPOOL_MAGIC	ISC_MAGIC('A','m','p','l')
+#define ISCAPI_MPOOL_VALID(mp)	((mp) != NULL && \
+				 (mp)->magic == ISCAPI_MPOOL_MAGIC)
+
+#if ISC_MEM_DEBUG
+#define isc_mem_put(c, p, s) \
+	do { \
+		ISCMEMFUNC(put)((c), (p), (s) _ISC_MEM_FILELINE);	\
+		(p) = NULL; \
+	} while (0)
+#define isc_mem_putanddetach(c, p, s) \
+	do { \
+		ISCMEMFUNC(putanddetach)((c), (p), (s) _ISC_MEM_FILELINE); \
+		(p) = NULL; \
+	} while (0)
+#define isc_mem_free(c, p) \
+	do { \
+		ISCMEMFUNC(free)((c), (p) _ISC_MEM_FILELINE);	\
+		(p) = NULL; \
+	} while (0)
+#define isc_mempool_put(c, p) \
+	do { \
+		ISCMEMPOOLFUNC(put)((c), (p) _ISC_MEM_FILELINE);	\
+		(p) = NULL; \
+	} while (0)
+#else
+#define isc_mem_put(c, p, s)	ISCMEMFUNC(put)((c), (p), (s) _ISC_MEM_FILELINE)
+#define isc_mem_putanddetach(c, p, s) \
+	ISCMEMFUNC(putanddetach)((c), (p), (s) _ISC_MEM_FILELINE)
+#define isc_mem_free(c, p)	ISCMEMFUNC(free)((c), (p) _ISC_MEM_FILELINE)
+#define isc_mempool_put(c, p)	ISCMEMPOOLFUNC(put)((c), (p) _ISC_MEM_FILELINE)
+#endif
+
+/*@{*/
+isc_result_t
+isc_mem_create(size_t max_size, size_t target_size,
+	       isc_mem_t **mctxp);
+
+isc_result_t
+isc_mem_create2(size_t max_size, size_t target_size,
+		isc_mem_t **mctxp, unsigned int flags);
+
+isc_result_t
+isc_mem_createx(size_t max_size, size_t target_size,
+		isc_memalloc_t memalloc, isc_memfree_t memfree,
+		void *arg, isc_mem_t **mctxp);
+
+isc_result_t
+isc_mem_createx2(size_t max_size, size_t target_size,
+		 isc_memalloc_t memalloc, isc_memfree_t memfree,
+		 void *arg, isc_mem_t **mctxp, unsigned int flags);
+
+/*!<
+ * \brief Create a memory context.
+ *
+ * 'max_size' and 'target_size' are tuning parameters.  When
+ * ISC_MEMFLAG_INTERNAL is set, allocations smaller than 'max_size'
+ * will be satisfied by getting blocks of size 'target_size' from the
+ * system allocator and breaking them up into pieces; larger allocations
+ * will use the system allocator directly. If 'max_size' and/or
+ * 'target_size' are zero, default values will be * used.  When
+ * ISC_MEMFLAG_INTERNAL is not set, 'target_size' is ignored.
+ *
+ * 'max_size' is also used to size the statistics arrays and the array
+ * used to record active memory when ISC_MEM_DEBUGRECORD is set.  Settin
+ * 'max_size' too low can have detrimental effects on performance.
+ *
+ * A memory context created using isc_mem_createx() will obtain
+ * memory from the system by calling 'memalloc' and 'memfree',
+ * passing them the argument 'arg'.  A memory context created
+ * using isc_mem_create() will use the standard library malloc()
+ * and free().
+ *
+ * If ISC_MEMFLAG_NOLOCK is set in 'flags', the corresponding memory context
+ * will be accessed without locking.  The user who creates the context must
+ * ensure there be no race.  Since this can be a source of bug, it is generally
+ * inadvisable to use this flag unless the user is very sure about the race
+ * condition and the access to the object is highly performance sensitive.
+ *
+ * Requires:
+ * mctxp != NULL && *mctxp == NULL */
+/*@}*/
+
+/*@{*/
+void
+isc_mem_attach(isc_mem_t *, isc_mem_t **);
+void
+isc_mem_detach(isc_mem_t **);
+/*!<
+ * \brief Attach to / detach from a memory context.
+ *
+ * This is intended for applications that use multiple memory contexts
+ * in such a way that it is not obvious when the last allocations from
+ * a given context has been freed and destroying the context is safe.
+ *
+ * Most applications do not need to call these functions as they can
+ * simply create a single memory context at the beginning of main()
+ * and destroy it at the end of main(), thereby guaranteeing that it
+ * is not destroyed while there are outstanding allocations.
+ */
+/*@}*/
+
+void
+isc_mem_destroy(isc_mem_t **);
+/*%<
+ * Destroy a memory context.
+ */
+
+isc_result_t
+isc_mem_ondestroy(isc_mem_t *ctx,
+		  isc_task_t *task,
+		  isc_event_t **event);
+/*%<
+ * Request to be notified with an event when a memory context has
+ * been successfully destroyed.
+ */
+
+void
+isc_mem_stats(isc_mem_t *mctx, FILE *out);
+/*%<
+ * Print memory usage statistics for 'mctx' on the stream 'out'.
+ */
+
+void
+isc_mem_setdestroycheck(isc_mem_t *mctx,
+			isc_boolean_t on);
+/*%<
+ * If 'on' is ISC_TRUE, 'mctx' will check for memory leaks when
+ * destroyed and abort the program if any are present.
+ */
+
+/*@{*/
+void
+isc_mem_setquota(isc_mem_t *, size_t);
+size_t
+isc_mem_getquota(isc_mem_t *);
+/*%<
+ * Set/get the memory quota of 'mctx'.  This is a hard limit
+ * on the amount of memory that may be allocated from mctx;
+ * if it is exceeded, allocations will fail.
+ */
+/*@}*/
+
+size_t
+isc_mem_inuse(isc_mem_t *mctx);
+/*%<
+ * Get an estimate of the number of memory in use in 'mctx', in bytes.
+ * This includes quantization overhead, but does not include memory
+ * allocated from the system but not yet used.
+ */
+
+isc_boolean_t
+isc_mem_isovermem(isc_mem_t *mctx);
+/*%<
+ * Return true iff the memory context is in "over memory" state, i.e.,
+ * a hiwater mark has been set and the used amount of memory has exceeds
+ * the mark.
+ */
+
+void
+isc_mem_setwater(isc_mem_t *mctx, isc_mem_water_t water, void *water_arg,
+		 size_t hiwater, size_t lowater);
+/*%<
+ * Set high and low water marks for this memory context.
+ *
+ * When the memory usage of 'mctx' exceeds 'hiwater',
+ * '(water)(water_arg, #ISC_MEM_HIWATER)' will be called.  'water' needs to
+ * call isc_mem_waterack() with #ISC_MEM_HIWATER to acknowledge the state
+ * change.  'water' may be called multiple times.
+ *
+ * When the usage drops below 'lowater', 'water' will again be called, this
+ * time with #ISC_MEM_LOWATER.  'water' need to calls isc_mem_waterack() with
+ * #ISC_MEM_LOWATER to acknowledge the change.
+ *
+ *	static void
+ *	water(void *arg, int mark) {
+ *		struct foo *foo = arg;
+ *
+ *		LOCK(&foo->marklock);
+ *		if (foo->mark != mark) {
+ * 			foo->mark = mark;
+ *			....
+ *			isc_mem_waterack(foo->mctx, mark);
+ *		}
+ *		UNLOCK(&foo->marklock);
+ *	}
+ *
+ * If 'water' is NULL then 'water_arg', 'hi_water' and 'lo_water' are
+ * ignored and the state is reset.
+ *
+ * Requires:
+ *
+ *	'water' is not NULL.
+ *	hi_water >= lo_water
+ */
+
+void
+isc_mem_waterack(isc_mem_t *ctx, int mark);
+/*%<
+ * Called to acknowledge changes in signaled by calls to 'water'.
+ */
+
+void
+isc_mem_printactive(isc_mem_t *mctx, FILE *file);
+/*%<
+ * Print to 'file' all active memory in 'mctx'.
+ *
+ * Requires ISC_MEM_DEBUGRECORD to have been set.
+ */
+
+void
+isc_mem_printallactive(FILE *file);
+/*%<
+ * Print to 'file' all active memory in all contexts.
+ *
+ * Requires ISC_MEM_DEBUGRECORD to have been set.
+ */
+
+void
+isc_mem_checkdestroyed(FILE *file);
+/*%<
+ * Check that all memory contexts have been destroyed.
+ * Prints out those that have not been.
+ * Fatally fails if there are still active contexts.
+ */
+
+unsigned int
+isc_mem_references(isc_mem_t *ctx);
+/*%<
+ * Return the current reference count.
+ */
+
+void
+isc_mem_setname(isc_mem_t *ctx, const char *name, void *tag);
+/*%<
+ * Name 'ctx'.
+ *
+ * Notes:
+ *
+ *\li	Only the first 15 characters of 'name' will be copied.
+ *
+ *\li	'tag' is for debugging purposes only.
+ *
+ * Requires:
+ *
+ *\li	'ctx' is a valid ctx.
+ */
+
+const char *
+isc_mem_getname(isc_mem_t *ctx);
+/*%<
+ * Get the name of 'ctx', as previously set using isc_mem_setname().
+ *
+ * Requires:
+ *\li	'ctx' is a valid ctx.
+ *
+ * Returns:
+ *\li	A non-NULL pointer to a null-terminated string.
+ * 	If the ctx has not been named, the string is
+ * 	empty.
+ */
+
+void *
+isc_mem_gettag(isc_mem_t *ctx);
+/*%<
+ * Get the tag value for  'task', as previously set using isc_mem_setname().
+ *
+ * Requires:
+ *\li	'ctx' is a valid ctx.
+ *
+ * Notes:
+ *\li	This function is for debugging purposes only.
+ *
+ * Requires:
+ *\li	'ctx' is a valid task.
+ */
+
+#ifdef HAVE_LIBXML2
+void
+isc_mem_renderxml(xmlTextWriterPtr writer);
+/*%<
+ * Render all contexts' statistics and status in XML for writer.
+ */
+#endif /* HAVE_LIBXML2 */
+
+/*
+ * Memory pools
+ */
+
+isc_result_t
+isc_mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp);
+/*%<
+ * Create a memory pool.
+ *
+ * Requires:
+ *\li	mctx is a valid memory context.
+ *\li	size > 0
+ *\li	mpctxp != NULL and *mpctxp == NULL
+ *
+ * Defaults:
+ *\li	maxalloc = UINT_MAX
+ *\li	freemax = 1
+ *\li	fillcount = 1
+ *
+ * Returns:
+ *\li	#ISC_R_NOMEMORY		-- not enough memory to create pool
+ *\li	#ISC_R_SUCCESS		-- all is well.
+ */
+
+void
+isc_mempool_destroy(isc_mempool_t **mpctxp);
+/*%<
+ * Destroy a memory pool.
+ *
+ * Requires:
+ *\li	mpctxp != NULL && *mpctxp is a valid pool.
+ *\li	The pool has no un"put" allocations outstanding
+ */
+
+void
+isc_mempool_setname(isc_mempool_t *mpctx, const char *name);
+/*%<
+ * Associate a name with a memory pool.  At most 15 characters may be used.
+ *
+ * Requires:
+ *\li	mpctx is a valid pool.
+ *\li	name != NULL;
+ */
+
+void
+isc_mempool_associatelock(isc_mempool_t *mpctx, isc_mutex_t *lock);
+/*%<
+ * Associate a lock with this memory pool.
+ *
+ * This lock is used when getting or putting items using this memory pool,
+ * and it is also used to set or get internal state via the isc_mempool_get*()
+ * and isc_mempool_set*() set of functions.
+ *
+ * Multiple pools can each share a single lock.  For instance, if "manager"
+ * type object contained pools for various sizes of events, and each of
+ * these pools used a common lock.  Note that this lock must NEVER be used
+ * by other than mempool routines once it is given to a pool, since that can
+ * easily cause double locking.
+ *
+ * Requires:
+ *
+ *\li	mpctpx is a valid pool.
+ *
+ *\li	lock != NULL.
+ *
+ *\li	No previous lock is assigned to this pool.
+ *
+ *\li	The lock is initialized before calling this function via the normal
+ *	means of doing that.
+ */
+
+/*
+ * The following functions get/set various parameters.  Note that due to
+ * the unlocked nature of pools these are potentially random values unless
+ * the imposed externally provided locking protocols are followed.
+ *
+ * Also note that the quota limits will not always take immediate effect.
+ * For instance, setting "maxalloc" to a number smaller than the currently
+ * allocated count is permitted.  New allocations will be refused until
+ * the count drops below this threshold.
+ *
+ * All functions require (in addition to other requirements):
+ *	mpctx is a valid memory pool
+ */
+
+unsigned int
+isc_mempool_getfreemax(isc_mempool_t *mpctx);
+/*%<
+ * Returns the maximum allowed size of the free list.
+ */
+
+void
+isc_mempool_setfreemax(isc_mempool_t *mpctx, unsigned int limit);
+/*%<
+ * Sets the maximum allowed size of the free list.
+ */
+
+unsigned int
+isc_mempool_getfreecount(isc_mempool_t *mpctx);
+/*%<
+ * Returns current size of the free list.
+ */
+
+unsigned int
+isc_mempool_getmaxalloc(isc_mempool_t *mpctx);
+/*!<
+ * Returns the maximum allowed number of allocations.
+ */
+
+void
+isc_mempool_setmaxalloc(isc_mempool_t *mpctx, unsigned int limit);
+/*%<
+ * Sets the maximum allowed number of allocations.
+ *
+ * Additional requirements:
+ *\li	limit > 0
+ */
+
+unsigned int
+isc_mempool_getallocated(isc_mempool_t *mpctx);
+/*%<
+ * Returns the number of items allocated from this pool.
+ */
+
+unsigned int
+isc_mempool_getfillcount(isc_mempool_t *mpctx);
+/*%<
+ * Returns the number of items allocated as a block from the parent memory
+ * context when the free list is empty.
+ */
+
+void
+isc_mempool_setfillcount(isc_mempool_t *mpctx, unsigned int limit);
+/*%<
+ * Sets the fillcount.
+ *
+ * Additional requirements:
+ *\li	limit > 0
+ */
+
+
+/*
+ * Pseudo-private functions for use via macros.  Do not call directly.
+ */
+void *
+ISCMEMFUNC(get)(isc_mem_t *, size_t _ISC_MEM_FLARG);
+void
+ISCMEMFUNC(putanddetach)(isc_mem_t **, void *, size_t _ISC_MEM_FLARG);
+void
+ISCMEMFUNC(put)(isc_mem_t *, void *, size_t _ISC_MEM_FLARG);
+void *
+ISCMEMFUNC(allocate)(isc_mem_t *, size_t _ISC_MEM_FLARG);
+void *
+ISCMEMFUNC(reallocate)(isc_mem_t *, void *, size_t _ISC_MEM_FLARG);
+void
+ISCMEMFUNC(free)(isc_mem_t *, void * _ISC_MEM_FLARG);
+char *
+ISCMEMFUNC(strdup)(isc_mem_t *, const char *_ISC_MEM_FLARG);
+void *
+ISCMEMPOOLFUNC(get)(isc_mempool_t * _ISC_MEM_FLARG);
+void
+ISCMEMPOOLFUNC(put)(isc_mempool_t *, void * _ISC_MEM_FLARG);
+
+#ifdef USE_MEMIMPREGISTER
+
+/*%<
+ * See isc_mem_create2() above.
+ */
+typedef isc_result_t
+(*isc_memcreatefunc_t)(size_t init_max_size, size_t target_size,
+		       isc_mem_t **ctxp, unsigned int flags);
+
+isc_result_t
+isc_mem_register(isc_memcreatefunc_t createfunc);
+/*%<
+ * Register a new memory management implementation and add it to the list of
+ * supported implementations.  This function must be called when a different
+ * memory management library is used than the one contained in the ISC library.
+ */
+
+isc_result_t
+isc__mem_register(void);
+/*%<
+ * A short cut function that specifies the memory management module in the ISC
+ * library for isc_mem_register().  An application that uses the ISC library
+ * usually do not have to care about this function: it would call
+ * isc_lib_register(), which internally calls this function.
+ */
+#endif /* USE_MEMIMPREGISTER */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_MEM_H */
diff --git a/src/lib/bind9/include/isc/msgcat.h b/src/lib/bind9/include/isc/msgcat.h
new file mode 100644
index 0000000..e4bdf52
--- /dev/null
+++ b/src/lib/bind9/include/isc/msgcat.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: msgcat.h,v 1.13 2007-06-19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_MSGCAT_H
+#define ISC_MSGCAT_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file isc/msgcat.h
+ * \brief The ISC Message Catalog
+ * aids internationalization of applications by allowing
+ * messages to be retrieved from locale-specific files instead of
+ * hardwiring them into the application.  This allows translations of
+ * messages appropriate to the locale to be supplied without recompiling
+ * the application.
+ *
+ * Notes:
+ *\li	It's very important that message catalogs work, even if only the
+ *	default_text can be used.
+ *
+ * MP:
+ *\li	The caller must ensure appropriate synchronization of
+ *	isc_msgcat_open() and isc_msgcat_close().  isc_msgcat_get()
+ *	ensures appropriate synchronization.
+ *
+ * Reliability:
+ *\li	No anticipated impact.
+ *
+ * Resources:
+ *\li	TBS
+ *
+ * \li Security:
+ *	No anticipated impact.
+ *
+ * \li Standards:
+ *	None.
+ */
+
+/*****
+ ***** Imports
+ *****/
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/*****
+ ***** Methods
+ *****/
+
+void
+isc_msgcat_open(const char *name, isc_msgcat_t **msgcatp);
+/*%<
+ * Open a message catalog.
+ *
+ * Notes:
+ *
+ *\li	If memory cannot be allocated or other failures occur, *msgcatp
+ *	will be set to NULL.  If a NULL msgcat is given to isc_msgcat_get(),
+ *	the default_text will be returned, ensuring that some message text
+ *	will be available, no matter what's going wrong.
+ *
+ * Requires:
+ *
+ *\li	'name' is a valid string.
+ *
+ *\li	msgcatp != NULL && *msgcatp == NULL
+ */
+
+void
+isc_msgcat_close(isc_msgcat_t **msgcatp);
+/*%<
+ * Close a message catalog.
+ *
+ * Notes:
+ *
+ *\li	Any string pointers returned by prior calls to isc_msgcat_get() are
+ *	invalid after isc_msgcat_close() has been called and must not be
+ *	used.
+ *
+ * Requires:
+ *
+ *\li	*msgcatp is a valid message catalog or is NULL.
+ *
+ * Ensures:
+ *
+ *\li	All resources associated with the message catalog are released.
+ *
+ *\li	*msgcatp == NULL
+ */
+
+const char *
+isc_msgcat_get(isc_msgcat_t *msgcat, int set, int message,
+	       const char *default_text);
+/*%<
+ * Get message 'message' from message set 'set' in 'msgcat'.  If it
+ * is not available, use 'default_text'.
+ *
+ * Requires:
+ *
+ *\li	'msgcat' is a valid message catalog or is NULL.
+ *
+ *\li	set > 0
+ *
+ *\li	message > 0
+ *
+ *\li	'default_text' is a valid string.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_MSGCAT_H */
diff --git a/src/lib/bind9/include/isc/msgs.h b/src/lib/bind9/include/isc/msgs.h
new file mode 100644
index 0000000..22dfde2
--- /dev/null
+++ b/src/lib/bind9/include/isc/msgs.h
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2004-2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: msgs.h,v 1.19 2009-10-01 23:48:08 tbox Exp $ */
+
+#ifndef ISC_MSGS_H
+#define ISC_MSGS_H 1
+
+/*! \file isc/msgs.h */
+
+#include <isc/lib.h>		/* Provide isc_msgcat global variable. */
+#include <isc/msgcat.h>		/* Provide isc_msgcat_*() functions. */
+
+/*@{*/
+/*!
+ * \brief Message sets, named per source file, excepting "GENERAL".
+ *
+ * IMPORTANT: The original list is alphabetical, but any new sets must
+ * be added to the end.
+ */
+#define ISC_MSGSET_GENERAL	1
+/*	ISC_RESULT_RESULTSET    2 */     /* XXX */
+/*	ISC_RESULT_UNAVAILABLESET 3 */   /* XXX */
+#define ISC_MSGSET_APP		4
+#define ISC_MSGSET_COMMANDLINE	5
+#define ISC_MSGSET_ENTROPY	6
+#define ISC_MSGSET_IFITERIOCTL	7
+#define ISC_MSGSET_IFITERSYSCTL	8
+#define ISC_MSGSET_LEX		9
+#define ISC_MSGSET_LOG		10
+#define ISC_MSGSET_MEM		11
+#define ISC_MSGSET_NETADDR	12
+#define ISC_MSGSET_PRINT	13
+#define ISC_MSGSET_RESULT	14
+#define ISC_MSGSET_RWLOCK	15
+#define ISC_MSGSET_SOCKADDR	16
+#define ISC_MSGSET_SOCKET	17
+#define ISC_MSGSET_TASK		18
+#define ISC_MSGSET_TIMER	19
+#define ISC_MSGSET_UTIL		20
+#define ISC_MSGSET_IFITERGETIFADDRS 21
+/*@}*/
+
+/*@{*/
+/*!
+ * Message numbers
+ * are only required to be unique per message set,
+ * but are unique throughout the entire catalog to not be as confusing when
+ * debugging.
+ *
+ * The initial numbering was done by multiply by 100 the set number the
+ * message appears in then adding the incremental message number.
+ */
+#define ISC_MSG_FAILED		101 /*%< "failed" */
+#define ISC_MSG_SUCCEEDED	102 /*%< Compatible with "failed" */
+#define ISC_MSG_SUCCESS		103 /*%< More usual way to say "success" */
+#define ISC_MSG_STARTING	104 /*%< As in "daemon: starting" */
+#define ISC_MSG_STOPING		105 /*%< As in "daemon: stopping" */
+#define ISC_MSG_ENTERING	106 /*%< As in "some_subr: entering" */
+#define ISC_MSG_EXITING		107 /*%< As in "some_subr: exiting" */
+#define ISC_MSG_CALLING		108 /*%< As in "calling some_subr()" */
+#define ISC_MSG_RETURNED	109 /*%< As in "some_subr: returned <foo>" */
+#define ISC_MSG_FATALERROR	110 /*%< "fatal error" */
+#define ISC_MSG_SHUTTINGDOWN	111 /*%< "shutting down" */
+#define ISC_MSG_RUNNING		112 /*%< "running" */
+#define ISC_MSG_WAIT		113 /*%< "wait" */
+#define ISC_MSG_WAITUNTIL	114 /*%< "waituntil" */
+
+#define ISC_MSG_SIGNALSETUP	201 /*%< "handle_signal() %d setup: %s" */
+
+#define ISC_MSG_ILLEGALOPT	301 /*%< "illegal option" */
+#define ISC_MSG_OPTNEEDARG	302 /*%< "option requires an argument" */
+
+#define ISC_MSG_ENTROPYSTATS	401 /*%< "Entropy pool %p:  refcnt %u ..." */
+
+#define ISC_MSG_MAKESCANSOCKET	501 /*%< "making interface scan socket: %s" */
+#define ISC_MSG_GETIFCONFIG	502 /*%< "get interface configuration: %s" */
+#define ISC_MSG_BUFFERMAX	503 /*%< "... maximum buffer size exceeded" */
+#define ISC_MSG_GETDESTADDR	504 /*%< "%s: getting destination address: %s" */
+#define ISC_MSG_GETNETMASK	505 /*%< "%s: getting netmask: %s" */
+
+#define ISC_MSG_GETIFLISTSIZE	601 /*%< "getting interface list size: ..." */
+#define ISC_MSG_GETIFLIST	602 /*%< "getting interface list: ..." */
+#define ISC_MSG_UNEXPECTEDTYPE	603 /*%< "... unexpected ... message type" */
+
+#define ISC_MSG_UNEXPECTEDSTATE	701 /*%< "Unexpected state %d" */
+
+#define ISC_MSG_BADTIME		801 /*%< "Bad 00 99:99:99.999 " */
+#define ISC_MSG_LEVEL		802 /*%< "level %d: " */
+
+#define ISC_MSG_ADDTRACE	901 /*%< "add %p size %u " */
+#define ISC_MSG_DELTRACE	902 /*%< "del %p size %u " */
+#define ISC_MSG_POOLSTATS	903 /*%< "[Pool statistics]\n" */
+#define ISC_MSG_POOLNAME	904 /*%< "name" */
+#define ISC_MSG_POOLSIZE	905 /*%< "size" */
+#define ISC_MSG_POOLMAXALLOC	906 /*%< "maxalloc" */
+#define ISC_MSG_POOLALLOCATED	907 /*%< "allocated" */
+#define ISC_MSG_POOLFREECOUNT	908 /*%< "freecount" */
+#define ISC_MSG_POOLFREEMAX	909 /*%< "freemax" */
+#define ISC_MSG_POOLFILLCOUNT	910 /*%< "fillcount" */
+#define ISC_MSG_POOLGETS	911 /*%< "gets" */
+#define ISC_MSG_DUMPALLOC	912 /*%< "DUMP OF ALL OUTSTANDING MEMORY ..." */
+#define ISC_MSG_NONE		913 /*%< "\tNone.\n" */
+#define ISC_MSG_PTRFILELINE	914 /*%< "\tptr %p file %s line %u\n" */
+
+#define ISC_MSG_UNKNOWNADDR    1001 /*%< "<unknown address, family %u>" */
+
+#define ISC_MSG_NOLONGDBL      1104 /*%< "long doubles are not supported" */
+
+#define ISC_MSG_PRINTLOCK      1201 /*%< "rwlock %p thread %lu ..." */
+#define ISC_MSG_READ	       1202 /*%< "read" */
+#define ISC_MSG_WRITE	       1203 /*%< "write" */
+#define ISC_MSG_READING	       1204 /*%< "reading" */
+#define ISC_MSG_WRITING	       1205 /*%< "writing" */
+#define ISC_MSG_PRELOCK	       1206 /*%< "prelock" */
+#define ISC_MSG_POSTLOCK       1207 /*%< "postlock" */
+#define ISC_MSG_PREUNLOCK      1208 /*%< "preunlock" */
+#define ISC_MSG_POSTUNLOCK     1209 /*%< "postunlock" */
+
+#define ISC_MSG_UNKNOWNFAMILY  1301 /*%< "unknown address family: %d" */
+
+#define ISC_MSG_WRITEFAILED    1401 /*%< "write() failed during watcher ..." */
+#define ISC_MSG_READFAILED     1402 /*%< "read() failed during watcher ... " */
+#define ISC_MSG_PROCESSCMSG    1403 /*%< "processing cmsg %p" */
+#define ISC_MSG_IFRECEIVED     1404 /*%< "interface received on ifindex %u" */
+#define ISC_MSG_SENDTODATA     1405 /*%< "sendto pktinfo data, ifindex %u" */
+#define ISC_MSG_DOIORECV       1406 /*%< "doio_recv: recvmsg(%d) %d bytes ..." */
+#define ISC_MSG_PKTRECV	       1407 /*%< "packet received correctly" */
+#define ISC_MSG_DESTROYING     1408 /*%< "destroying" */
+#define ISC_MSG_CREATED	       1409 /*%< "created" */
+#define ISC_MSG_ACCEPTLOCK     1410 /*%< "internal_accept called, locked ..." */
+#define ISC_MSG_ACCEPTEDCXN    1411 /*%< "accepted connection, new socket %p" */
+#define ISC_MSG_INTERNALRECV   1412 /*%< "internal_recv: task %p got event %p" */
+#define ISC_MSG_INTERNALSEND   1413 /*%< "internal_send: task %p got event %p" */
+#define ISC_MSG_WATCHERMSG     1414 /*%< "watcher got message %d" */
+#define ISC_MSG_SOCKETSREMAIN  1415 /*%< "sockets exist" */
+#define ISC_MSG_PKTINFOPROVIDED	1416 /*%< "pktinfo structure provided, ..." */
+#define ISC_MSG_BOUND	       1417 /*%< "bound" */
+#define ISC_MSG_ACCEPTRETURNED 1418 /*%< accept() returned %d/%s */
+#define ISC_MSG_TOOMANYFDS     1419 /*%< %s: too many open file descriptors */
+#define ISC_MSG_ZEROPORT       1420 /*%< dropping source port zero packet */
+#define ISC_MSG_FILTER	       1421 /*%< setsockopt(SO_ACCEPTFILTER): %s */
+
+#define ISC_MSG_TOOMANYHANDLES 1422 /*%< %s: too many open WSA event handles: %s */
+#define ISC_MSG_POKED          1423 /*%< "poked flags: %d" */
+
+#define ISC_MSG_AWAKE	       1502 /*%< "awake" */
+#define ISC_MSG_WORKING	       1503 /*%< "working" */
+#define ISC_MSG_EXECUTE	       1504 /*%< "execute action" */
+#define ISC_MSG_EMPTY	       1505 /*%< "empty" */
+#define ISC_MSG_DONE	       1506 /*%< "done" */
+#define ISC_MSG_QUANTUM	       1507 /*%< "quantum" */
+
+#define ISC_MSG_SCHEDULE       1601 /*%< "schedule" */
+#define ISC_MSG_SIGNALSCHED    1602 /*%< "signal (schedule)" */
+#define ISC_MSG_SIGNALDESCHED  1603 /*%< "signal (deschedule)" */
+#define ISC_MSG_SIGNALDESTROY  1604 /*%< "signal (destroy)" */
+#define ISC_MSG_IDLERESCHED    1605 /*%< "idle reschedule" */
+#define ISC_MSG_EVENTNOTALLOC  1606 /*%< "couldn't allocate event" */
+#define ISC_MSG_SCHEDFAIL      1607 /*%< "couldn't schedule timer: %u" */
+#define ISC_MSG_POSTING	       1608 /*%< "posting" */
+#define ISC_MSG_WAKEUP	       1609 /*%< "wakeup" */
+
+#define ISC_MSG_LOCK	       1701 /*%< "LOCK" */
+#define ISC_MSG_LOCKING	       1702 /*%< "LOCKING" */
+#define ISC_MSG_LOCKED	       1703 /*%< "LOCKED" */
+#define ISC_MSG_UNLOCKED       1704 /*%< "UNLOCKED" */
+#define ISC_MSG_RWLOCK	       1705 /*%< "RWLOCK" */
+#define ISC_MSG_RWLOCKED       1706 /*%< "RWLOCKED" */
+#define ISC_MSG_RWUNLOCK       1707 /*%< "RWUNLOCK" */
+#define ISC_MSG_BROADCAST      1708 /*%< "BROADCAST" */
+#define ISC_MSG_SIGNAL	       1709 /*%< "SIGNAL" */
+#define ISC_MSG_UTILWAIT       1710 /*%< "WAIT" */
+#define ISC_MSG_WAITED	       1711 /*%< "WAITED" */
+
+#define ISC_MSG_GETIFADDRS     1801 /*%< "getting interface addresses: ..." */
+
+/*@}*/
+
+#endif /* ISC_MSGS_H */
diff --git a/src/lib/bind9/include/isc/mutexblock.h b/src/lib/bind9/include/isc/mutexblock.h
new file mode 100644
index 0000000..b08ece7
--- /dev/null
+++ b/src/lib/bind9/include/isc/mutexblock.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: mutexblock.h,v 1.17 2007-06-19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_MUTEXBLOCK_H
+#define ISC_MUTEXBLOCK_H 1
+
+/*! \file isc/mutexblock.h */
+
+#include <isc/lang.h>
+#include <isc/mutex.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_mutexblock_init(isc_mutex_t *block, unsigned int count);
+/*%<
+ * Initialize a block of locks.  If an error occurs all initialized locks
+ * will be destroyed, if possible.
+ *
+ * Requires:
+ *
+ *\li	block != NULL
+ *
+ *\li	count > 0
+ *
+ * Returns:
+ *
+ *\li	Any code isc_mutex_init() can return is a valid return for this
+ *	function.
+ */
+
+isc_result_t
+isc_mutexblock_destroy(isc_mutex_t *block, unsigned int count);
+/*%<
+ * Destroy a block of locks.
+ *
+ * Requires:
+ *
+ *\li	block != NULL
+ *
+ *\li	count > 0
+ *
+ *\li	Each lock in the block be initialized via isc_mutex_init() or
+ * 	the whole block was initialized via isc_mutex_initblock().
+ *
+ * Returns:
+ *
+ *\li	Any code isc_mutex_init() can return is a valid return for this
+ *	function.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_MUTEXBLOCK_H */
diff --git a/src/lib/bind9/include/isc/namespace.h b/src/lib/bind9/include/isc/namespace.h
new file mode 100644
index 0000000..05a8b2c
--- /dev/null
+++ b/src/lib/bind9/include/isc/namespace.h
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2009, 2010  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: namespace.h,v 1.9 2010-12-04 13:25:59 marka Exp $ */
+
+#ifndef ISCAPI_NAMESPACE_H
+#define ISCAPI_NAMESPACE_H 1
+
+/*%
+ * name space conversions
+ */
+
+#ifdef BIND9
+
+#define isc_app_start isc__app_start
+#define isc_app_ctxstart isc__app_ctxstart
+#define isc_app_onrun isc__app_onrun
+#define isc_app_run isc__app_run
+#define isc_app_ctxrun isc__app_ctxrun
+#define isc_app_shutdown isc__app_shutdown
+#define isc_app_ctxshutdown isc__app_ctxshutdown
+#define isc_app_ctxsuspend isc__app_ctxsuspend
+#define isc_app_reload isc__app_reload
+#define isc_app_finish isc__app_finish
+#define isc_app_block isc__app_block
+#define isc_app_unblock isc__app_unblock
+#define isc_appctx_create isc__appctx_create
+#define isc_appctx_destroy isc__appctx_destroy
+#define isc_appctx_settaskmgr isc__appctx_settaskmgr
+#define isc_appctx_setsocketmgr isc__appctx_setsocketmgr
+#define isc_appctx_settimermgr isc__appctx_settimermgr
+
+#define isc_mem_checkdestroyed isc__mem_checkdestroyed
+#define isc_mem_createx isc__mem_createx
+#define isc_mem_createx2 isc__mem_createx2
+#define isc_mem_create isc__mem_create
+#define isc_mem_create2 isc__mem_create2
+#define isc_mem_attach isc__mem_attach
+#define isc_mem_detach isc__mem_detach
+#define isc__mem_putanddetach isc___mem_putanddetach
+#define isc_mem_destroy isc__mem_destroy
+#define isc_mem_ondestroy isc__mem_ondestroy
+#define isc__mem_get isc___mem_get
+#define isc__mem_put isc___mem_put
+#define isc_mem_stats isc__mem_stats
+#define isc__mem_allocate isc___mem_allocate
+#define isc__mem_free isc___mem_free
+#define isc__mem_strdup isc___mem_strdup
+#define isc__mem_reallocate isc___mem_reallocate
+#define isc_mem_references isc__mem_references
+#define isc_mem_setdestroycheck isc__mem_setdestroycheck
+#define isc_mem_setquota isc__mem_setquota
+#define isc_mem_getname isc__mem_getname
+#define isc_mem_getquota isc__mem_getquota
+#define isc_mem_gettag isc__mem_gettag
+#define isc_mem_inuse isc__mem_inuse
+#define isc_mem_isovermem isc__mem_isovermem
+#define isc_mem_setname isc__mem_setname
+#define isc_mem_setwater isc__mem_setwater
+#define isc_mem_printallactive isc__mem_printallactive
+#define isc_mem_waterack isc__mem_waterack
+#define isc_mempool_create isc__mempool_create
+#define isc_mempool_setname isc__mempool_setname
+#define isc_mempool_destroy isc__mempool_destroy
+#define isc_mempool_associatelock isc__mempool_associatelock
+#define isc__mempool_get isc___mempool_get
+#define isc__mempool_put isc___mempool_put
+#define isc_mempool_setfreemax isc__mempool_setfreemax
+#define isc_mempool_getfreemax isc__mempool_getfreemax
+#define isc_mempool_getfreecount isc__mempool_getfreecount
+#define isc_mempool_setmaxalloc isc__mempool_setmaxalloc
+#define isc_mempool_getmaxalloc isc__mempool_getmaxalloc
+#define isc_mempool_getallocated isc__mempool_getallocated
+#define isc_mempool_setfillcount isc__mempool_setfillcount
+#define isc_mempool_getfillcount isc__mempool_getfillcount
+
+#define isc_socket_create isc__socket_create
+#define isc_socket_attach isc__socket_attach
+#define isc_socket_detach isc__socket_detach
+#define isc_socketmgr_create isc__socketmgr_create
+#define isc_socketmgr_create2 isc__socketmgr_create2
+#define isc_socketmgr_destroy isc__socketmgr_destroy
+#define isc_socket_open isc__socket_open
+#define isc_socket_close isc__socket_close
+#define isc_socket_recvv isc__socket_recvv
+#define isc_socket_recv isc__socket_recv
+#define isc_socket_recv2 isc__socket_recv2
+#define isc_socket_send isc__socket_send
+#define isc_socket_sendto isc__socket_sendto
+#define isc_socket_sendv isc__socket_sendv
+#define isc_socket_sendtov isc__socket_sendtov
+#define isc_socket_sendto2 isc__socket_sendto2
+#define isc_socket_cleanunix isc__socket_cleanunix
+#define isc_socket_permunix isc__socket_permunix
+#define isc_socket_bind isc__socket_bind
+#define isc_socket_filter isc__socket_filter
+#define isc_socket_listen isc__socket_listen
+#define isc_socket_accept isc__socket_accept
+#define isc_socket_connect isc__socket_connect
+#define isc_socket_getname isc__socket_getname
+#define isc_socket_gettag isc__socket_gettag
+#define isc_socket_getpeername isc__socket_getpeername
+#define isc_socket_getsockname isc__socket_getsockname
+#define isc_socket_cancel isc__socket_cancel
+#define isc_socket_gettype isc__socket_gettype
+#define isc_socket_isbound isc__socket_isbound
+#define isc_socket_ipv6only isc__socket_ipv6only
+#define isc_socket_setname isc__socket_setname
+#define isc_socketmgr_getmaxsockets isc__socketmgr_getmaxsockets
+#define isc_socketmgr_setstats isc__socketmgr_setstats
+#define isc_socketmgr_setreserved isc__socketmgr_setreserved
+#define isc__socketmgr_maxudp isc___socketmgr_maxudp
+#define isc_socket_fdwatchcreate isc__socket_fdwatchcreate
+#define isc_socket_fdwatchpoke isc__socket_fdwatchpoke
+
+#define isc_task_create isc__task_create
+#define isc_task_attach isc__task_attach
+#define isc_task_detach isc__task_detach
+/* #define isc_task_exiting isc__task_exiting XXXMPA */
+#define isc_task_send isc__task_send
+#define isc_task_sendanddetach isc__task_sendanddetach
+#define isc_task_purgerange isc__task_purgerange
+#define isc_task_purge isc__task_purge
+#define isc_task_purgeevent isc__task_purgeevent
+#define isc_task_unsendrange isc__task_unsendrange
+#define isc_task_unsend isc__task_unsend
+#define isc_task_onshutdown isc__task_onshutdown
+#define isc_task_shutdown isc__task_shutdown
+#define isc_task_destroy isc__task_destroy
+#define isc_task_setname isc__task_setname
+#define isc_task_getname isc__task_getname
+#define isc_task_gettag isc__task_gettag
+#define isc_task_getcurrenttime isc__task_getcurrenttime
+#define isc_taskmgr_create isc__taskmgr_create
+#define isc_taskmgr_destroy isc__taskmgr_destroy
+#define isc_task_beginexclusive isc__task_beginexclusive
+#define isc_task_endexclusive isc__task_endexclusive
+
+#define isc_timer_create isc__timer_create
+#define isc_timer_reset isc__timer_reset
+#define isc_timer_gettype isc__timer_gettype
+#define isc_timer_touch isc__timer_touch
+#define isc_timer_attach isc__timer_attach
+#define isc_timer_detach isc__timer_detach
+#define isc_timermgr_create isc__timermgr_create
+#define isc_timermgr_poke isc__timermgr_poke
+#define isc_timermgr_destroy isc__timermgr_destroy
+
+#endif /* BIND9 */
+
+#endif /* ISCAPI_NAMESPACE_H */
diff --git a/src/lib/bind9/include/isc/netaddr.h b/src/lib/bind9/include/isc/netaddr.h
new file mode 100644
index 0000000..04b7ec1
--- /dev/null
+++ b/src/lib/bind9/include/isc/netaddr.h
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2002  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: netaddr.h,v 1.37 2009-01-17 23:47:43 tbox Exp $ */
+
+#ifndef ISC_NETADDR_H
+#define ISC_NETADDR_H 1
+
+/*! \file isc/netaddr.h */
+
+#include <isc/lang.h>
+#include <isc/net.h>
+#include <isc/types.h>
+
+#ifdef ISC_PLATFORM_HAVESYSUNH
+#include <sys/types.h>
+#include <sys/un.h>
+#endif
+
+ISC_LANG_BEGINDECLS
+
+struct isc_netaddr {
+	unsigned int family;
+	union {
+		struct in_addr in;
+		struct in6_addr in6;
+#ifdef ISC_PLATFORM_HAVESYSUNH
+		char un[sizeof(((struct sockaddr_un *)0)->sun_path)];
+#endif
+	} type;
+	isc_uint32_t zone;
+};
+
+isc_boolean_t
+isc_netaddr_equal(const isc_netaddr_t *a, const isc_netaddr_t *b);
+
+/*%<
+ * Compare network addresses 'a' and 'b'.  Return #ISC_TRUE if
+ * they are equal, #ISC_FALSE if not.
+ */
+
+isc_boolean_t
+isc_netaddr_eqprefix(const isc_netaddr_t *a, const isc_netaddr_t *b,
+		     unsigned int prefixlen);
+/*%<
+ * Compare the 'prefixlen' most significant bits of the network
+ * addresses 'a' and 'b'.  If 'b''s scope is zero then 'a''s scope is
+ * ignored.  Return #ISC_TRUE if they are equal, #ISC_FALSE if not.
+ */
+
+isc_result_t
+isc_netaddr_masktoprefixlen(const isc_netaddr_t *s, unsigned int *lenp);
+/*%<
+ * Convert a netmask in 's' into a prefix length in '*lenp'.
+ * The mask should consist of zero or more '1' bits in the most
+ * most significant part of the address, followed by '0' bits.
+ * If this is not the case, #ISC_R_MASKNONCONTIG is returned.
+ *
+ * Returns:
+ *\li	#ISC_R_SUCCESS
+ *\li	#ISC_R_MASKNONCONTIG
+ */
+
+isc_result_t
+isc_netaddr_totext(const isc_netaddr_t *netaddr, isc_buffer_t *target);
+/*%<
+ * Append a text representation of 'sockaddr' to the buffer 'target'.
+ * The text is NOT null terminated.  Handles IPv4 and IPv6 addresses.
+ *
+ * Returns:
+ *\li	#ISC_R_SUCCESS
+ *\li	#ISC_R_NOSPACE	The text or the null termination did not fit.
+ *\li	#ISC_R_FAILURE	Unspecified failure
+ */
+
+void
+isc_netaddr_format(const isc_netaddr_t *na, char *array, unsigned int size);
+/*%<
+ * Format a human-readable representation of the network address '*na'
+ * into the character array 'array', which is of size 'size'.
+ * The resulting string is guaranteed to be null-terminated.
+ */
+
+#define ISC_NETADDR_FORMATSIZE \
+	sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:XXX.XXX.XXX.XXX%SSSSSSSSSS")
+/*%<
+ * Minimum size of array to pass to isc_netaddr_format().
+ */
+
+void
+isc_netaddr_fromsockaddr(isc_netaddr_t *netaddr, const isc_sockaddr_t *source);
+
+void
+isc_netaddr_fromin(isc_netaddr_t *netaddr, const struct in_addr *ina);
+
+void
+isc_netaddr_fromin6(isc_netaddr_t *netaddr, const struct in6_addr *ina6);
+
+isc_result_t
+isc_netaddr_frompath(isc_netaddr_t *netaddr, const char *path);
+
+void
+isc_netaddr_setzone(isc_netaddr_t *netaddr, isc_uint32_t zone);
+
+isc_uint32_t
+isc_netaddr_getzone(const isc_netaddr_t *netaddr);
+
+void
+isc_netaddr_any(isc_netaddr_t *netaddr);
+/*%<
+ * Return the IPv4 wildcard address.
+ */
+
+void
+isc_netaddr_any6(isc_netaddr_t *netaddr);
+/*%<
+ * Return the IPv6 wildcard address.
+ */
+
+isc_boolean_t
+isc_netaddr_ismulticast(isc_netaddr_t *na);
+/*%<
+ * Returns ISC_TRUE if the address is a multicast address.
+ */
+
+isc_boolean_t
+isc_netaddr_isexperimental(isc_netaddr_t *na);
+/*%<
+ * Returns ISC_TRUE if the address is a experimental (CLASS E) address.
+ */
+
+isc_boolean_t
+isc_netaddr_islinklocal(isc_netaddr_t *na);
+/*%<
+ * Returns #ISC_TRUE if the address is a link local address.
+ */
+
+isc_boolean_t
+isc_netaddr_issitelocal(isc_netaddr_t *na);
+/*%<
+ * Returns #ISC_TRUE if the address is a site local address.
+ */
+
+void
+isc_netaddr_fromv4mapped(isc_netaddr_t *t, const isc_netaddr_t *s);
+/*%<
+ * Convert an IPv6 v4mapped address into an IPv4 address.
+ */
+
+isc_result_t
+isc_netaddr_prefixok(const isc_netaddr_t *na, unsigned int prefixlen);
+/*
+ * Test whether the netaddr 'na' and 'prefixlen' are consistant.
+ * e.g. prefixlen within range.
+ *      na does not have bits set which are not covered by the prefixlen.
+ *
+ * Returns:
+ *	ISC_R_SUCCESS
+ *	ISC_R_RANGE		prefixlen out of range
+ *	ISC_R_NOTIMPLEMENTED	unsupported family
+ *	ISC_R_FAILURE		extra bits.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_NETADDR_H */
diff --git a/src/lib/bind9/include/isc/netscope.h b/src/lib/bind9/include/isc/netscope.h
new file mode 100644
index 0000000..1a50816
--- /dev/null
+++ b/src/lib/bind9/include/isc/netscope.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2002  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: netscope.h,v 1.13 2009-06-25 23:48:02 tbox Exp $ */
+
+#ifndef ISC_NETSCOPE_H
+#define ISC_NETSCOPE_H 1
+
+/*! \file isc/netscope.h */
+
+ISC_LANG_BEGINDECLS
+
+/*%
+ * Convert a string of an IPv6 scope zone to zone index.  If the conversion
+ * succeeds, 'zoneid' will store the index value.
+ *
+ * XXXJT: when a standard interface for this purpose is defined,
+ * we should use it.
+ *
+ * Returns:
+ * \li	ISC_R_SUCCESS: conversion succeeds
+ * \li	ISC_R_FAILURE: conversion fails
+ */
+isc_result_t
+isc_netscope_pton(int af, char *scopename, void *addr, isc_uint32_t *zoneid);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_NETSCOPE_H */
diff --git a/src/lib/bind9/include/isc/ondestroy.h b/src/lib/bind9/include/isc/ondestroy.h
new file mode 100644
index 0000000..8fe5b27
--- /dev/null
+++ b/src/lib/bind9/include/isc/ondestroy.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: ondestroy.h,v 1.14 2007-06-19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_ONDESTROY_H
+#define ISC_ONDESTROY_H 1
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/*! \file isc/ondestroy.h
+ * ondestroy handling.
+ *
+ * Any class ``X'' of objects that wants to send out notifications
+ * on its destruction should declare a field of type isc_ondestroy_t
+ * (call it 'ondest').
+ *
+ * \code
+ * 	typedef struct {
+ * 		...
+ * 		isc_ondestroy_t	ondest;
+ * 		...
+ * 	} X;
+ * \endcode
+ *
+ * When an object ``A'' of type X is created
+ * it must initialize the field ondest with a call to
+ *
+ * \code
+ * 	isc_ondestroy_init(&A->ondest).
+ * \endcode
+ *
+ * X should also provide a registration function for third-party
+ * objects to call to register their interest in being told about
+ * the destruction of a particular instance of X.
+ *
+ * \code
+ *	isc_result_t
+ * 	X_ondestroy(X *instance, isc_task_t *task,
+ * 		     isc_event_t **eventp) {
+ * 		return(isc_ondestroy_register(&instance->ondest, task,eventp));
+ * 	}
+ * \endcode
+ *
+ *	Note: locking of the ondestory structure embedded inside of X, is
+ * 	X's responsibility.
+ *
+ * When an instance of X is destroyed, a call to  isc_ondestroy_notify()
+ * sends the notifications:
+ *
+ * \code
+ *	X *instance;
+ *	isc_ondestroy_t ondest = instance->ondest;
+ *
+ *	... completely cleanup 'instance' here...
+ *
+ * 	isc_ondestroy_notify(&ondest, instance);
+ * \endcode
+ *
+ *
+ * see lib/dns/zone.c for an ifdef'd-out example.
+ */
+
+struct isc_ondestroy {
+	unsigned int magic;
+	isc_eventlist_t events;
+};
+
+void
+isc_ondestroy_init(isc_ondestroy_t *ondest);
+/*%<
+ * Initialize the on ondest structure. *must* be called before first call
+ * to isc_ondestroy_register().
+ */
+
+isc_result_t
+isc_ondestroy_register(isc_ondestroy_t *ondest, isc_task_t *task,
+		       isc_event_t **eventp);
+
+/*%<
+ * Stores task and *eventp away inside *ondest.  Ownership of **event is
+ * taken from the caller (and *eventp is set to NULL). The task is attached
+ * to.
+ */
+
+void
+isc_ondestroy_notify(isc_ondestroy_t *ondest, void *sender);
+/*%<
+ * Dispatches the event(s) to the task(s) that were given in
+ * isc_ondestroy_register call(s) (done via calls to
+ * isc_task_sendanddetach()).  Before dispatch, the sender value of each
+ * event structure is set to the value of the sender paramater. The
+ * internal structures of the ondest parameter are cleaned out, so no other
+ * cleanup is needed.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_ONDESTROY_H */
diff --git a/src/lib/bind9/include/isc/os.h b/src/lib/bind9/include/isc/os.h
new file mode 100644
index 0000000..5ebdd76
--- /dev/null
+++ b/src/lib/bind9/include/isc/os.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: os.h,v 1.12 2007-06-19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_OS_H
+#define ISC_OS_H 1
+
+/*! \file isc/os.h */
+
+#include <isc/lang.h>
+
+ISC_LANG_BEGINDECLS
+
+unsigned int
+isc_os_ncpus(void);
+/*%<
+ * Return the number of CPUs available on the system, or 1 if this cannot
+ * be determined.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_OS_H */
diff --git a/src/lib/bind9/include/isc/parseint.h b/src/lib/bind9/include/isc/parseint.h
new file mode 100644
index 0000000..a92b215
--- /dev/null
+++ b/src/lib/bind9/include/isc/parseint.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2001, 2002  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: parseint.h,v 1.9 2007-06-19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_PARSEINT_H
+#define ISC_PARSEINT_H 1
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+/*! \file isc/parseint.h
+ * \brief Parse integers, in a saner way than atoi() or strtoul() do.
+ */
+
+/***
+ ***	Functions
+ ***/
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_parse_uint32(isc_uint32_t *uip, const char *string, int base);
+
+isc_result_t
+isc_parse_uint16(isc_uint16_t *uip, const char *string, int base);
+
+isc_result_t
+isc_parse_uint8(isc_uint8_t *uip, const char *string, int base);
+/*%<
+ * Parse the null-terminated string 'string' containing a base 'base'
+ * integer, storing the result in '*uip'.  
+ * The base is interpreted
+ * as in strtoul().  Unlike strtoul(), leading whitespace, minus or
+ * plus signs are not accepted, and all errors (including overflow)
+ * are reported uniformly through the return value.
+ *
+ * Requires:
+ *\li	'string' points to a null-terminated string
+ *\li	0 <= 'base' <= 36
+ *
+ * Returns:
+ *\li	#ISC_R_SUCCESS
+ *\li	#ISC_R_BADNUMBER   The string is not numeric (in the given base)
+ *\li	#ISC_R_RANGE	  The number is not representable as the requested type.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_PARSEINT_H */
diff --git a/src/lib/bind9/include/isc/platform.h b/src/lib/bind9/include/isc/platform.h
new file mode 100644
index 0000000..add3cd7
--- /dev/null
+++ b/src/lib/bind9/include/isc/platform.h
@@ -0,0 +1,370 @@
+/*
+ * Copyright (C) 2004-2010  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: platform.h.in,v 1.56 2010-12-18 01:56:23 each Exp $ */
+
+#ifndef ISC_PLATFORM_H
+#define ISC_PLATFORM_H 1
+
+/*! \file */
+
+/*****
+ ***** Platform-dependent defines.
+ *****/
+
+/***
+ *** Network.
+ ***/
+
+/*! \brief
+ * Define if this system needs the <netinet/in6.h> header file included
+ * for full IPv6 support (pretty much only UnixWare).
+ */
+#undef ISC_PLATFORM_NEEDNETINETIN6H
+
+/*! \brief
+ * Define if this system needs the <netinet6/in6.h> header file included
+ * to support in6_pkinfo (pretty much only BSD/OS).
+ */
+#undef ISC_PLATFORM_NEEDNETINET6IN6H
+
+/*! \brief
+ * If sockaddrs on this system have an sa_len field, ISC_PLATFORM_HAVESALEN
+ * will be defined.
+ */
+#undef ISC_PLATFORM_HAVESALEN
+
+/*! \brief
+ * If this system has the IPv6 structure definitions, ISC_PLATFORM_HAVEIPV6
+ * will be defined.
+ */
+#define ISC_PLATFORM_HAVEIPV6 1
+
+/*! \brief
+ * If this system is missing in6addr_any, ISC_PLATFORM_NEEDIN6ADDRANY will
+ * be defined.
+ */
+#undef ISC_PLATFORM_NEEDIN6ADDRANY
+
+/*! \brief
+ * If this system is missing in6addr_loopback, ISC_PLATFORM_NEEDIN6ADDRLOOPBACK
+ * will be defined.
+ */
+#undef ISC_PLATFORM_NEEDIN6ADDRLOOPBACK
+
+/*! \brief
+ * If this system has in6_pktinfo, ISC_PLATFORM_HAVEIN6PKTINFO will be
+ * defined.
+ */
+#undef ISC_PLATFORM_HAVEIN6PKTINFO
+
+/*! \brief
+ * If this system has in_addr6, rather than in6_addr, ISC_PLATFORM_HAVEINADDR6
+ * will be defined.
+ */
+#undef ISC_PLATFORM_HAVEINADDR6
+
+/*! \brief
+ * If this system has sin6_scope_id, ISC_PLATFORM_HAVESCOPEID will be defined.
+ */
+#define ISC_PLATFORM_HAVESCOPEID 1
+
+/*! \brief
+ * If this system needs inet_ntop(), ISC_PLATFORM_NEEDNTOP will be defined.
+ */
+#undef ISC_PLATFORM_NEEDNTOP
+
+/*! \brief
+ * If this system needs inet_pton(), ISC_PLATFORM_NEEDPTON will be defined.
+ */
+#undef ISC_PLATFORM_NEEDPTON
+
+/*! \brief
+ * If this system needs in_port_t, ISC_PLATFORM_NEEDPORTT will be defined.
+ */
+#undef ISC_PLATFORM_NEEDPORTT
+
+/*! \brief
+ * Define if the system has struct lifconf which is a extended struct ifconf
+ * for IPv6.
+ */
+#undef ISC_PLATFORM_HAVELIFCONF
+
+/*! \brief
+ * Define if the system has struct if_laddrconf which is a extended struct
+ * ifconf for IPv6.
+ */
+#undef ISC_PLATFORM_HAVEIF_LADDRCONF
+
+/*! \brief
+ * Define if the system has struct if_laddrreq.
+ */
+#undef ISC_PLATFORM_HAVEIF_LADDRREQ
+
+/*! \brief
+ * Define either ISC_PLATFORM_BSD44MSGHDR or ISC_PLATFORM_BSD43MSGHDR.
+ */
+#define ISC_NET_BSD44MSGHDR 1
+
+/*! \brief
+ * Define if the system supports if_nametoindex.
+ */
+#define ISC_PLATFORM_HAVEIFNAMETOINDEX 1
+
+/*! \brief
+ * Define on some UnixWare systems to fix erroneous definitions of various
+ * IN6_IS_ADDR_* macros.
+ */
+#undef ISC_PLATFORM_FIXIN6ISADDR
+
+/*! \brief
+ * Define if the system supports kqueue multiplexing
+ */
+#undef ISC_PLATFORM_HAVEKQUEUE
+
+/*! \brief
+ * Define if the system supports epoll multiplexing
+ */
+#define ISC_PLATFORM_HAVEEPOLL 1
+
+/*! \brief
+ * Define if the system supports /dev/poll multiplexing
+ */
+#undef ISC_PLATFORM_HAVEDEVPOLL
+
+/*! \brief
+ * Define if we want to log backtrace
+ */
+#define ISC_PLATFORM_USEBACKTRACE 1
+
+/*
+ *** Printing.
+ ***/
+
+/*! \brief
+ * If this system needs vsnprintf() and snprintf(), ISC_PLATFORM_NEEDVSNPRINTF
+ * will be defined.
+ */
+#undef ISC_PLATFORM_NEEDVSNPRINTF
+
+/*! \brief
+ * If this system need a modern sprintf() that returns (int) not (char*).
+ */
+#undef ISC_PLATFORM_NEEDSPRINTF
+
+/*! \brief
+ * The printf format string modifier to use with isc_uint64_t values.
+ */
+#define ISC_PLATFORM_QUADFORMAT "ll"
+
+/***
+ *** String functions.
+ ***/
+/*
+ * If the system needs strsep(), ISC_PLATFORM_NEEDSTRSEP will be defined.
+ */
+#undef ISC_PLATFORM_NEEDSTRSEP
+
+/*
+ * If the system needs strlcpy(), ISC_PLATFORM_NEEDSTRLCPY will be defined.
+ */
+#define ISC_PLATFORM_NEEDSTRLCPY 1
+
+/*
+ * If the system needs strlcat(), ISC_PLATFORM_NEEDSTRLCAT will be defined.
+ */
+#define ISC_PLATFORM_NEEDSTRLCAT 1
+
+/*
+ * Define if this system needs strtoul.
+ */
+#undef ISC_PLATFORM_NEEDSTRTOUL
+
+/*
+ * Define if this system needs memmove.
+ */
+#undef ISC_PLATFORM_NEEDMEMMOVE
+
+/***
+ *** Miscellaneous.
+ ***/
+
+/*
+ * Defined if we are using threads.
+ */
+#undef ISC_PLATFORM_USETHREADS
+
+/*
+ * Defined if unistd.h does not cause fd_set to be delared.
+ */
+#undef ISC_PLATFORM_NEEDSYSSELECTH
+
+/*
+ * Defined to <gssapi.h> or <gssapi/gssapi.h> for how to include
+ * the GSSAPI header.
+ */
+
+
+/*
+ * Defined to <gssapi_krb5.h> or <gssapi/gssapi_krb5.h> for how to
+ * include the GSSAPI KRB5 header.
+ */
+
+
+/*
+ * Defined to <krb5.h> or <krb5/krb5.h> for how to include
+ * the KRB5 header.
+ */
+
+
+/*
+ * Type used for resource limits.
+ */
+#define ISC_PLATFORM_RLIMITTYPE rlim_t
+
+/*
+ * Define if your compiler supports "long long int".
+ */
+#define ISC_PLATFORM_HAVELONGLONG 1
+
+/*
+ * Define if PTHREAD_ONCE_INIT should be surrounded by braces to
+ * prevent compiler warnings (such as with gcc on Solaris 2.8).
+ */
+#undef ISC_PLATFORM_BRACEPTHREADONCEINIT
+
+/*
+ * Used to control how extern data is linked; needed for Win32 platforms.
+ */
+#undef ISC_PLATFORM_USEDECLSPEC
+
+/*
+ * Define if the platform has <sys/un.h>.
+ */
+#define ISC_PLATFORM_HAVESYSUNH 1
+
+/*
+ * If the "xadd" operation is available on this architecture,
+ * ISC_PLATFORM_HAVEXADD will be defined.
+ */
+#define ISC_PLATFORM_HAVEXADD 1
+
+/*
+ * If the "xaddq" operation (64bit xadd) is available on this architecture,
+ * ISC_PLATFORM_HAVEXADDQ will be defined.
+ */
+#undef ISC_PLATFORM_HAVEXADDQ
+
+/*
+ * If the "atomic swap" operation is available on this architecture,
+ * ISC_PLATFORM_HAVEATOMICSTORE" will be defined.
+ */
+#define ISC_PLATFORM_HAVEATOMICSTORE 1
+
+/*
+ * If the "compare-and-exchange" operation is available on this architecture,
+ * ISC_PLATFORM_HAVECMPXCHG will be defined.
+ */
+#define ISC_PLATFORM_HAVECMPXCHG 1
+
+/*
+ * Define if gcc ASM extension is available
+ */
+#define ISC_PLATFORM_USEGCCASM 1
+
+/*
+ * Define if Tru64 style ASM syntax must be used.
+ */
+#undef ISC_PLATFORM_USEOSFASM
+
+/*
+ * Define if the standard __asm function must be used.
+ */
+
+
+/*
+ * Define if the platform has <strings.h>.
+ */
+#define ISC_PLATFORM_HAVESTRINGSH 1
+
+/*
+ * Define if the hash functions must be provided by OpenSSL.
+ */
+#undef ISC_PLATFORM_OPENSSLHASH
+
+/*
+ * Defines for the noreturn attribute.
+ */
+#define ISC_PLATFORM_NORETURN_PRE
+#define ISC_PLATFORM_NORETURN_POST __attribute__((noreturn))
+
+/***
+ ***	Windows dll support.
+ ***/
+
+/*
+ * Define if MacOS style of PPC assembly must be used.
+ * e.g. "r6", not "6", for register six.
+ */
+
+
+#ifndef ISC_PLATFORM_USEDECLSPEC
+#define LIBISC_EXTERNAL_DATA
+#define LIBDNS_EXTERNAL_DATA
+#define LIBISCCC_EXTERNAL_DATA
+#define LIBISCCFG_EXTERNAL_DATA
+#define LIBBIND9_EXTERNAL_DATA
+#else /*! \brief ISC_PLATFORM_USEDECLSPEC */
+#ifdef LIBISC_EXPORTS
+#define LIBISC_EXTERNAL_DATA __declspec(dllexport)
+#else
+#define LIBISC_EXTERNAL_DATA __declspec(dllimport)
+#endif
+#ifdef LIBDNS_EXPORTS
+#define LIBDNS_EXTERNAL_DATA __declspec(dllexport)
+#else
+#define LIBDNS_EXTERNAL_DATA __declspec(dllimport)
+#endif
+#ifdef LIBISCCC_EXPORTS
+#define LIBISCCC_EXTERNAL_DATA __declspec(dllexport)
+#else
+#define LIBISCCC_EXTERNAL_DATA __declspec(dllimport)
+#endif
+#ifdef LIBISCCFG_EXPORTS
+#define LIBISCCFG_EXTERNAL_DATA __declspec(dllexport)
+#else
+#define LIBISCCFG_EXTERNAL_DATA __declspec(dllimport)
+#endif
+#ifdef LIBBIND9_EXPORTS
+#define LIBBIND9_EXTERNAL_DATA __declspec(dllexport)
+#else
+#define LIBBIND9_EXTERNAL_DATA __declspec(dllimport)
+#endif
+#endif /*! \brief ISC_PLATFORM_USEDECLSPEC */
+
+/*
+ * Tell emacs to use C mode for this file.
+ *
+ * Local Variables:
+ * mode: c
+ * End:
+ */
+
+#define PORT_NONBLOCK O_NONBLOCK
+#define HAVE_STRERROR
+
+#endif /* ISC_PLATFORM_H */
diff --git a/src/lib/bind9/include/isc/portset.h b/src/lib/bind9/include/isc/portset.h
new file mode 100644
index 0000000..2e27467
--- /dev/null
+++ b/src/lib/bind9/include/isc/portset.h
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2008, 2009  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: portset.h,v 1.6 2009-06-25 05:28:34 marka Exp $ */
+
+/*! \file isc/portset.h
+ * \brief Transport Protocol Port Manipulation Module
+ *
+ * This module provides simple utilities to handle a set of transport protocol
+ * (UDP or TCP) port numbers, e.g., for creating an ACL list.  An isc_portset_t
+ * object is an opaque instance of a port set, for which the user can add or
+ * remove a specific port or a range of consecutive ports.  This object is
+ * expected to be used as a temporary work space only, and does not protect
+ * simultaneous access from multiple threads.  Therefore it must not be stored
+ * in a place that can be accessed from multiple threads.
+ */
+
+#ifndef ISC_PORTSET_H
+#define ISC_PORTSET_H 1
+
+/***
+ ***	Imports
+ ***/
+
+#include <isc/net.h>
+
+/***
+ *** Functions
+ ***/
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_portset_create(isc_mem_t *mctx, isc_portset_t **portsetp);
+/*%<
+ * Create a port set and initialize it as an empty set.
+ *
+ * Requires:
+ *\li	'mctx' to be valid.
+ *\li	'portsetp' to be non NULL and '*portsetp' to be NULL;
+ *
+ * Returns:
+ *\li	#ISC_R_SUCCESS
+ *\li	#ISC_R_NOMEMORY
+ */
+
+void
+isc_portset_destroy(isc_mem_t *mctx, isc_portset_t **portsetp);
+/*%<
+ * Destroy a port set.
+ *
+ * Requires:
+ *\li	'mctx' to be valid and must be the same context given when the port set
+ *       was created.
+ *\li	'*portsetp' to be a valid set.
+ */
+
+isc_boolean_t
+isc_portset_isset(isc_portset_t *portset, in_port_t port);
+/*%<
+ * Test whether the given port is stored in the portset.
+ *
+ * Requires:
+ *\li	'portset' to be a valid set.
+ *
+ * Returns
+ * \li	#ISC_TRUE if the port is found, ISC_FALSE otherwise.
+ */
+
+unsigned int
+isc_portset_nports(isc_portset_t *portset);
+/*%<
+ * Provides the number of ports stored in the given portset.
+ *
+ * Requires:
+ *\li	'portset' to be a valid set.
+ *
+ * Returns
+ * \li	the number of ports stored in portset.
+ */
+
+void
+isc_portset_add(isc_portset_t *portset, in_port_t port);
+/*%<
+ * Add the given port to the portset.  The port may or may not be stored in
+ * the portset.
+ *
+ * Requires:
+ *\li	'portlist' to be valid.
+ */
+
+void
+isc_portset_remove(isc_portset_t *portset, in_port_t port);
+/*%<
+ * Remove the given port to the portset.  The port may or may not be stored in
+ * the portset.
+ *
+ * Requires:
+ *\li	'portlist' to be valid.
+ */
+
+void
+isc_portset_addrange(isc_portset_t *portset, in_port_t port_lo,
+		     in_port_t port_hi);
+/*%<
+ * Add a subset of [port_lo, port_hi] (inclusive) to the portset.  Ports in the
+ * subset may or may not be stored in portset.
+ *
+ * Requires:
+ *\li	'portlist' to be valid.
+ *\li	port_lo <= port_hi
+ */
+
+void
+isc_portset_removerange(isc_portset_t *portset, in_port_t port_lo,
+			in_port_t port_hi);
+/*%<
+ * Subtract a subset of [port_lo, port_hi] (inclusive) from the portset.  Ports
+ * in the subset may or may not be stored in portset.
+ *
+ * Requires:
+ *\li	'portlist' to be valid.
+ *\li	port_lo <= port_hi
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif	/* ISC_PORTSET_H */
diff --git a/src/lib/bind9/include/isc/print.h b/src/lib/bind9/include/isc/print.h
new file mode 100644
index 0000000..bf77ac7
--- /dev/null
+++ b/src/lib/bind9/include/isc/print.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001, 2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: print.h,v 1.26 2007-06-19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_PRINT_H
+#define ISC_PRINT_H 1
+
+/*! \file isc/print.h */
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/formatcheck.h>    /* Required for ISC_FORMAT_PRINTF() macro. */
+#include <isc/lang.h>
+#include <isc/platform.h>
+
+/*!
+ * This block allows lib/isc/print.c to be cleanly compiled even if
+ * the platform does not need it.  The standard Makefile will still
+ * not compile print.c or archive print.o, so this is just to make test
+ * compilation ("make print.o") easier.
+ */
+#if !defined(ISC_PLATFORM_NEEDVSNPRINTF) && defined(ISC__PRINT_SOURCE)
+#define ISC_PLATFORM_NEEDVSNPRINTF
+#endif
+
+#if !defined(ISC_PLATFORM_NEEDSPRINTF) && defined(ISC__PRINT_SOURCE)
+#define ISC_PLATFORM_NEEDSPRINTF
+#endif
+
+/***
+ *** Macros
+ ***/
+#define ISC_PRINT_QUADFORMAT ISC_PLATFORM_QUADFORMAT
+
+/***
+ *** Functions
+ ***/
+
+#ifdef ISC_PLATFORM_NEEDVSNPRINTF
+#include <stdarg.h>
+#include <stddef.h>
+#endif
+#ifdef ISC_PLATFORM_NEEDSPRINTF
+#include <stdio.h>
+#endif
+
+
+ISC_LANG_BEGINDECLS
+
+#ifdef ISC_PLATFORM_NEEDVSNPRINTF
+int
+isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap)
+     ISC_FORMAT_PRINTF(3, 0);
+#define vsnprintf isc_print_vsnprintf
+
+int
+isc_print_snprintf(char *str, size_t size, const char *format, ...)
+     ISC_FORMAT_PRINTF(3, 4);
+#define snprintf isc_print_snprintf
+#endif /* ISC_PLATFORM_NEEDVSNPRINTF */
+
+#ifdef ISC_PLATFORM_NEEDSPRINTF
+int
+isc_print_sprintf(char *str, const char *format, ...) ISC_FORMAT_PRINTF(2, 3);
+#define sprintf isc_print_sprintf
+#endif
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_PRINT_H */
diff --git a/src/lib/bind9/include/isc/quota.h b/src/lib/bind9/include/isc/quota.h
new file mode 100644
index 0000000..93f63fe
--- /dev/null
+++ b/src/lib/bind9/include/isc/quota.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: quota.h,v 1.16 2007-06-19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_QUOTA_H
+#define ISC_QUOTA_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file isc/quota.h
+ *
+ * \brief The isc_quota_t object is a simple helper object for implementing
+ * quotas on things like the number of simultaneous connections to
+ * a server.  It keeps track of the amount of quota in use, and
+ * encapsulates the locking necessary to allow multiple tasks to
+ * share a quota.
+ */
+
+/***
+ *** Imports.
+ ***/
+
+#include <isc/lang.h>
+#include <isc/mutex.h>
+#include <isc/types.h>
+
+/*****
+ ***** Types.
+ *****/
+
+ISC_LANG_BEGINDECLS
+
+/*% isc_quota structure */
+struct isc_quota {
+	isc_mutex_t	lock; /*%< Locked by lock. */
+	int 		max;
+	int 		used;
+	int		soft;
+};
+
+isc_result_t
+isc_quota_init(isc_quota_t *quota, int max);
+/*%<
+ * Initialize a quota object.
+ *
+ * Returns:
+ * 	ISC_R_SUCCESS
+ *	Other error	Lock creation failed.
+ */
+
+void
+isc_quota_destroy(isc_quota_t *quota);
+/*%<
+ * Destroy a quota object.
+ */
+
+void
+isc_quota_soft(isc_quota_t *quota, int soft);
+/*%<
+ * Set a soft quota.
+ */
+
+void
+isc_quota_max(isc_quota_t *quota, int max);
+/*%<
+ * Re-set a maximum quota.
+ */
+
+isc_result_t
+isc_quota_reserve(isc_quota_t *quota);
+/*%<
+ * Attempt to reserve one unit of 'quota'.
+ *
+ * Returns:
+ * \li 	#ISC_R_SUCCESS		Success
+ * \li	#ISC_R_SOFTQUOTA	Success soft quota reached
+ * \li	#ISC_R_QUOTA		Quota is full
+ */
+
+void
+isc_quota_release(isc_quota_t *quota);
+/*%<
+ * Release one unit of quota.
+ */
+
+isc_result_t
+isc_quota_attach(isc_quota_t *quota, isc_quota_t **p);
+/*%<
+ * Like isc_quota_reserve, and also attaches '*p' to the
+ * quota if successful (ISC_R_SUCCESS or ISC_R_SOFTQUOTA).
+ */
+
+void
+isc_quota_detach(isc_quota_t **p);
+/*%<
+ * Like isc_quota_release, and also detaches '*p' from the
+ * quota.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_QUOTA_H */
diff --git a/src/lib/bind9/include/isc/radix.h b/src/lib/bind9/include/isc/radix.h
new file mode 100644
index 0000000..ed8aaf2
--- /dev/null
+++ b/src/lib/bind9/include/isc/radix.h
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) 2007, 2008  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: radix.h,v 1.13 2008-12-01 23:47:45 tbox Exp $ */
+
+/*
+ * This source was adapted from MRT's RCS Ids:
+ * Id: radix.h,v 1.6 1999/08/03 03:32:53 masaki Exp
+ * Id: mrt.h,v 1.57.2.6 1999/12/28 23:41:27 labovit Exp
+ * Id: defs.h,v 1.5.2.2 2000/01/15 14:19:16 masaki Exp
+ */
+
+#include <isc/magic.h>
+#include <isc/types.h>
+#include <isc/mutex.h>
+#include <isc/net.h>
+#include <isc/refcount.h>
+
+#include <string.h>
+
+#ifndef _RADIX_H
+#define _RADIX_H
+
+#define NETADDR_TO_PREFIX_T(na,pt,bits) \
+	do { \
+		memset(&(pt), 0, sizeof(pt)); \
+		if((na) != NULL) { \
+			(pt).family = (na)->family; \
+			(pt).bitlen = (bits); \
+			if ((pt).family == AF_INET6) { \
+				memcpy(&(pt).add.sin6, &(na)->type.in6, \
+				       ((bits)+7)/8); \
+			} else \
+				memcpy(&(pt).add.sin, &(na)->type.in, \
+				       ((bits)+7)/8); \
+		} else { \
+			(pt).family = AF_UNSPEC; \
+			(pt).bitlen = 0; \
+		} \
+		isc_refcount_init(&(pt).refcount, 0); \
+	} while(0)
+
+typedef struct isc_prefix {
+    unsigned int family;	/* AF_INET | AF_INET6, or AF_UNSPEC for "any" */
+    unsigned int bitlen;	/* 0 for "any" */
+    isc_refcount_t refcount;
+    union {
+		struct in_addr sin;
+		struct in6_addr sin6;
+    } add;
+} isc_prefix_t;
+
+typedef void (*isc_radix_destroyfunc_t)(void *);
+typedef void (*isc_radix_processfunc_t)(isc_prefix_t *, void **);
+
+#define isc_prefix_tochar(prefix) ((char *)&(prefix)->add.sin)
+#define isc_prefix_touchar(prefix) ((u_char *)&(prefix)->add.sin)
+
+#define BIT_TEST(f, b)  ((f) & (b))
+
+/*
+ * We need "first match" when we search the radix tree to preserve
+ * compatibility with the existing ACL implementation. Radix trees
+ * naturally lend themselves to "best match". In order to get "first match"
+ * behavior, we keep track of the order in which entries are added to the
+ * tree--and when a search is made, we find all matching entries, and
+ * return the one that was added first.
+ *
+ * An IPv4 prefix and an IPv6 prefix may share a radix tree node if they
+ * have the same length and bit pattern (e.g., 127/8 and 7f::/8).  To
+ * disambiguate between them, node_num and data are two-element arrays;
+ * node_num[0] and data[0] are used for IPv4 addresses, node_num[1]
+ * and data[1] for IPv6 addresses.  The only exception is a prefix of
+ * 0/0 (aka "any" or "none"), which is always stored as IPv4 but matches
+ * IPv6 addresses too.
+ */
+
+#define ISC_IS6(family) ((family) == AF_INET6 ? 1 : 0)
+typedef struct isc_radix_node {
+   isc_uint32_t bit;			/* bit length of the prefix */
+   isc_prefix_t *prefix;		/* who we are in radix tree */
+   struct isc_radix_node *l, *r;	/* left and right children */
+   struct isc_radix_node *parent;	/* may be used */
+   void *data[2];			/* pointers to IPv4 and IPV6 data */
+   int node_num[2];			/* which node this was in the tree,
+					   or -1 for glue nodes */
+} isc_radix_node_t;
+
+#define RADIX_TREE_MAGIC         ISC_MAGIC('R','d','x','T');
+#define RADIX_TREE_VALID(a)      ISC_MAGIC_VALID(a, RADIX_TREE_MAGIC);
+
+typedef struct isc_radix_tree {
+   unsigned int		magic;
+   isc_mem_t		*mctx;
+   isc_radix_node_t 	*head;
+   isc_uint32_t		maxbits;	/* for IP, 32 bit addresses */
+   int num_active_node;			/* for debugging purposes */
+   int num_added_node;			/* total number of nodes */
+} isc_radix_tree_t;
+
+isc_result_t
+isc_radix_search(isc_radix_tree_t *radix, isc_radix_node_t **target,
+		 isc_prefix_t *prefix);
+/*%<
+ * Search 'radix' for the best match to 'prefix'.
+ * Return the node found in '*target'.
+ *
+ * Requires:
+ * \li	'radix' to be valid.
+ * \li	'target' is not NULL and "*target" is NULL.
+ * \li	'prefix' to be valid.
+ *
+ * Returns:
+ * \li	ISC_R_NOTFOUND
+ * \li	ISC_R_SUCCESS
+ */
+
+isc_result_t
+isc_radix_insert(isc_radix_tree_t *radix, isc_radix_node_t **target,
+		 isc_radix_node_t *source, isc_prefix_t *prefix);
+/*%<
+ * Insert 'source' or 'prefix' into the radix tree 'radix'.
+ * Return the node added in 'target'.
+ *
+ * Requires:
+ * \li	'radix' to be valid.
+ * \li	'target' is not NULL and "*target" is NULL.
+ * \li	'prefix' to be valid or 'source' to be non NULL and contain
+ *	a valid prefix.
+ *
+ * Returns:
+ * \li	ISC_R_NOMEMORY
+ * \li	ISC_R_SUCCESS
+ */
+
+void
+isc_radix_remove(isc_radix_tree_t *radix, isc_radix_node_t *node);
+/*%<
+ * Remove the node 'node' from the radix tree 'radix'.
+ *
+ * Requires:
+ * \li	'radix' to be valid.
+ * \li	'node' to be valid.
+ */
+
+isc_result_t
+isc_radix_create(isc_mem_t *mctx, isc_radix_tree_t **target, int maxbits);
+/*%<
+ * Create a radix tree with a maximum depth of 'maxbits';
+ *
+ * Requires:
+ * \li	'mctx' to be valid.
+ * \li	'target' to be non NULL and '*target' to be NULL.
+ * \li	'maxbits' to be less than or equal to RADIX_MAXBITS.
+ *
+ * Returns:
+ * \li	ISC_R_NOMEMORY
+ * \li	ISC_R_SUCCESS
+ */
+
+void
+isc_radix_destroy(isc_radix_tree_t *radix, isc_radix_destroyfunc_t func);
+/*%<
+ * Destroy a radix tree optionally calling 'func' to clean up node data.
+ *
+ * Requires:
+ * \li	'radix' to be valid.
+ */
+
+void
+isc_radix_process(isc_radix_tree_t *radix, isc_radix_processfunc_t func);
+/*%<
+ * Walk a radix tree calling 'func' to process node data.
+ *
+ * Requires:
+ * \li	'radix' to be valid.
+ * \li	'func' to point to a function.
+ */
+
+#define RADIX_MAXBITS 128
+#define RADIX_NBIT(x)        (0x80 >> ((x) & 0x7f))
+#define RADIX_NBYTE(x)       ((x) >> 3)
+
+#define RADIX_DATA_GET(node, type) (type *)((node)->data)
+#define RADIX_DATA_SET(node, value) ((node)->data = (void *)(value))
+
+#define RADIX_WALK(Xhead, Xnode) \
+    do { \
+	isc_radix_node_t *Xstack[RADIX_MAXBITS+1]; \
+	isc_radix_node_t **Xsp = Xstack; \
+	isc_radix_node_t *Xrn = (Xhead); \
+	while ((Xnode = Xrn)) { \
+	    if (Xnode->prefix)
+
+#define RADIX_WALK_ALL(Xhead, Xnode) \
+do { \
+	isc_radix_node_t *Xstack[RADIX_MAXBITS+1]; \
+	isc_radix_node_t **Xsp = Xstack; \
+	isc_radix_node_t *Xrn = (Xhead); \
+	while ((Xnode = Xrn)) { \
+	    if (1)
+
+#define RADIX_WALK_BREAK { \
+	    if (Xsp != Xstack) { \
+		Xrn = *(--Xsp); \
+	     } else { \
+		Xrn = (radix_node_t *) 0; \
+	    } \
+	    continue; }
+
+#define RADIX_WALK_END \
+	    if (Xrn->l) { \
+		if (Xrn->r) { \
+		    *Xsp++ = Xrn->r; \
+		} \
+		Xrn = Xrn->l; \
+	    } else if (Xrn->r) { \
+		Xrn = Xrn->r; \
+	    } else if (Xsp != Xstack) { \
+		Xrn = *(--Xsp); \
+	    } else { \
+		Xrn = (isc_radix_node_t *) 0; \
+	    } \
+	} \
+    } while (0)
+
+#endif /* _RADIX_H */
diff --git a/src/lib/bind9/include/isc/random.h b/src/lib/bind9/include/isc/random.h
new file mode 100644
index 0000000..e05b204
--- /dev/null
+++ b/src/lib/bind9/include/isc/random.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: random.h,v 1.20 2009-01-17 23:47:43 tbox Exp $ */
+
+#ifndef ISC_RANDOM_H
+#define ISC_RANDOM_H 1
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+/*! \file isc/random.h
+ * \brief Implements a random state pool which will let the caller return a
+ * series of possibly non-reproducible random values.
+ *
+ * Note that the
+ * strength of these numbers is not all that high, and should not be
+ * used in cryptography functions.  It is useful for jittering values
+ * a bit here and there, such as timeouts, etc.
+ */
+
+ISC_LANG_BEGINDECLS
+
+void
+isc_random_seed(isc_uint32_t seed);
+/*%<
+ * Set the initial seed of the random state.
+ */
+
+void
+isc_random_get(isc_uint32_t *val);
+/*%<
+ * Get a random value.
+ *
+ * Requires:
+ *	val != NULL.
+ */
+
+isc_uint32_t
+isc_random_jitter(isc_uint32_t max, isc_uint32_t jitter);
+/*%<
+ * Get a random value between (max - jitter) and (max).
+ * This is useful for jittering timer values.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_RANDOM_H */
diff --git a/src/lib/bind9/include/isc/ratelimiter.h b/src/lib/bind9/include/isc/ratelimiter.h
new file mode 100644
index 0000000..f8a9819
--- /dev/null
+++ b/src/lib/bind9/include/isc/ratelimiter.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: ratelimiter.h,v 1.23 2009-01-18 23:48:14 tbox Exp $ */
+
+#ifndef ISC_RATELIMITER_H
+#define ISC_RATELIMITER_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file isc/ratelimiter.h
+ * \brief A rate limiter is a mechanism for dispatching events at a limited
+ * rate.  This is intended to be used when sending zone maintenance
+ * SOA queries, NOTIFY messages, etc.
+ */
+
+/***
+ *** Imports.
+ ***/
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/*****
+ ***** Functions.
+ *****/
+
+isc_result_t
+isc_ratelimiter_create(isc_mem_t *mctx, isc_timermgr_t *timermgr,
+		       isc_task_t *task, isc_ratelimiter_t **ratelimiterp);
+/*%<
+ * Create a rate limiter.  The execution interval is initially undefined.
+ */
+
+isc_result_t
+isc_ratelimiter_setinterval(isc_ratelimiter_t *rl, isc_interval_t *interval);
+/*!<
+ * Set the minimum interval between event executions.
+ * The interval value is copied, so the caller need not preserve it.
+ *
+ * Requires:
+ *	'*interval' is a nonzero interval.
+ */
+
+void
+isc_ratelimiter_setpertic(isc_ratelimiter_t *rl, isc_uint32_t perint);
+/*%<
+ * Set the number of events processed per interval timer tick.
+ * If 'perint' is zero it is treated as 1.
+ */
+
+isc_result_t
+isc_ratelimiter_enqueue(isc_ratelimiter_t *rl, isc_task_t *task,
+			isc_event_t **eventp);
+/*%<
+ * Queue an event for rate-limited execution.
+ *
+ * This is similar
+ * to doing an isc_task_send() to the 'task', except that the
+ * execution may be delayed to achieve the desired rate of
+ * execution.
+ *
+ * '(*eventp)->ev_sender' is used to hold the task.  The caller
+ * must ensure that the task exists until the event is delivered.
+ *
+ * Requires:
+ *\li	An interval has been set by calling
+ *	isc_ratelimiter_setinterval().
+ *
+ *\li	'task' to be non NULL.
+ *\li	'(*eventp)->ev_sender' to be NULL.
+ */
+
+void
+isc_ratelimiter_shutdown(isc_ratelimiter_t *ratelimiter);
+/*%<
+ * Shut down a rate limiter.
+ *
+ * Ensures:
+ *\li	All events that have not yet been
+ * 	dispatched to the task are dispatched immediately with
+ *	the #ISC_EVENTATTR_CANCELED bit set in ev_attributes.
+ *
+ *\li	Further attempts to enqueue events will fail with
+ * 	#ISC_R_SHUTTINGDOWN.
+ *
+ *\li	The rate limiter is no longer attached to its task.
+ */
+
+void
+isc_ratelimiter_attach(isc_ratelimiter_t *source, isc_ratelimiter_t **target);
+/*%<
+ * Attach to a rate limiter.
+ */
+
+void
+isc_ratelimiter_detach(isc_ratelimiter_t **ratelimiterp);
+/*%<
+ * Detach from a rate limiter.
+ */
+
+isc_result_t
+isc_ratelimiter_stall(isc_ratelimiter_t *rl);
+/*%<
+ * Stall event processing.
+ */
+
+isc_result_t
+isc_ratelimiter_release(isc_ratelimiter_t *rl);
+/*%<
+ * Release a stalled rate limiter.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_RATELIMITER_H */
diff --git a/src/lib/bind9/include/isc/refcount.h b/src/lib/bind9/include/isc/refcount.h
new file mode 100644
index 0000000..71f35f1
--- /dev/null
+++ b/src/lib/bind9/include/isc/refcount.h
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2001, 2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: refcount.h,v 1.17 2009-09-29 23:48:04 tbox Exp $ */
+
+#ifndef ISC_REFCOUNT_H
+#define ISC_REFCOUNT_H 1
+
+#include <isc/atomic.h>
+#include <isc/lang.h>
+#include <isc/mutex.h>
+#include <isc/platform.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+/*! \file isc/refcount.h
+ * \brief Implements a locked reference counter.
+ *
+ * These functions may actually be
+ * implemented using macros, and implementations of these macros are below.
+ * The isc_refcount_t type should not be accessed directly, as its contents
+ * depend on the implementation.
+ */
+
+ISC_LANG_BEGINDECLS
+
+/*
+ * Function prototypes
+ */
+
+/*
+ * isc_result_t
+ * isc_refcount_init(isc_refcount_t *ref, unsigned int n);
+ *
+ * Initialize the reference counter.  There will be 'n' initial references.
+ *
+ * Requires:
+ *	ref != NULL
+ */
+
+/*
+ * void
+ * isc_refcount_destroy(isc_refcount_t *ref);
+ *
+ * Destroys a reference counter.
+ *
+ * Requires:
+ *	ref != NULL
+ *	The number of references is 0.
+ */
+
+/*
+ * void
+ * isc_refcount_increment(isc_refcount_t *ref, unsigned int *targetp);
+ * isc_refcount_increment0(isc_refcount_t *ref, unsigned int *targetp);
+ *
+ * Increments the reference count, returning the new value in targetp if it's
+ * not NULL.  The reference counter typically begins with the initial counter
+ * of 1, and will be destroyed once the counter reaches 0.  Thus,
+ * isc_refcount_increment() additionally requires the previous counter be
+ * larger than 0 so that an error which violates the usage can be easily
+ * caught.  isc_refcount_increment0() does not have this restriction.
+ *
+ * Requires:
+ *	ref != NULL.
+ */
+
+/*
+ * void
+ * isc_refcount_decrement(isc_refcount_t *ref, unsigned int *targetp);
+ *
+ * Decrements the reference count,  returning the new value in targetp if it's
+ * not NULL.
+ *
+ * Requires:
+ *	ref != NULL.
+ */
+
+
+/*
+ * Sample implementations
+ */
+#ifdef ISC_PLATFORM_USETHREADS
+#ifdef ISC_PLATFORM_HAVEXADD
+
+#define ISC_REFCOUNT_HAVEATOMIC 1
+
+typedef struct isc_refcount {
+	isc_int32_t refs;
+} isc_refcount_t;
+
+#define isc_refcount_destroy(rp) REQUIRE((rp)->refs == 0)
+#define isc_refcount_current(rp) ((unsigned int)((rp)->refs))
+
+#define isc_refcount_increment0(rp, tp)				\
+	do {							\
+		unsigned int *_tmp = (unsigned int *)(tp);	\
+		isc_int32_t prev;				\
+		prev = isc_atomic_xadd(&(rp)->refs, 1);		\
+		if (_tmp != NULL)				\
+			*_tmp = prev + 1;			\
+	} while (0)
+
+#define isc_refcount_increment(rp, tp)				\
+	do {							\
+		unsigned int *_tmp = (unsigned int *)(tp);	\
+		isc_int32_t prev;				\
+		prev = isc_atomic_xadd(&(rp)->refs, 1);		\
+		REQUIRE(prev > 0);				\
+		if (_tmp != NULL)				\
+			*_tmp = prev + 1;			\
+	} while (0)
+
+#define isc_refcount_decrement(rp, tp)				\
+	do {							\
+		unsigned int *_tmp = (unsigned int *)(tp);	\
+		isc_int32_t prev;				\
+		prev = isc_atomic_xadd(&(rp)->refs, -1);	\
+		REQUIRE(prev > 0);				\
+		if (_tmp != NULL)				\
+			*_tmp = prev - 1;			\
+	} while (0)
+
+#else  /* ISC_PLATFORM_HAVEXADD */
+
+typedef struct isc_refcount {
+	int refs;
+	isc_mutex_t lock;
+} isc_refcount_t;
+
+/*% Destroys a reference counter. */
+#define isc_refcount_destroy(rp)			\
+	do {						\
+		REQUIRE((rp)->refs == 0);		\
+		DESTROYLOCK(&(rp)->lock);		\
+	} while (0)
+
+#define isc_refcount_current(rp) ((unsigned int)((rp)->refs))
+
+/*% Increments the reference count, returning the new value in targetp if it's not NULL. */
+#define isc_refcount_increment0(rp, tp)				\
+	do {							\
+		unsigned int *_tmp = (unsigned int *)(tp);	\
+		LOCK(&(rp)->lock);				\
+		++((rp)->refs);					\
+		if (_tmp != NULL)				\
+			*_tmp = ((rp)->refs);			\
+		UNLOCK(&(rp)->lock);				\
+	} while (0)
+
+#define isc_refcount_increment(rp, tp)				\
+	do {							\
+		unsigned int *_tmp = (unsigned int *)(tp);	\
+		LOCK(&(rp)->lock);				\
+		REQUIRE((rp)->refs > 0);			\
+		++((rp)->refs);					\
+		if (_tmp != NULL)				\
+			*_tmp = ((rp)->refs);			\
+		UNLOCK(&(rp)->lock);				\
+	} while (0)
+
+/*% Decrements the reference count,  returning the new value in targetp if it's not NULL. */
+#define isc_refcount_decrement(rp, tp)				\
+	do {							\
+		unsigned int *_tmp = (unsigned int *)(tp);	\
+		LOCK(&(rp)->lock);				\
+		REQUIRE((rp)->refs > 0);			\
+		--((rp)->refs);					\
+		if (_tmp != NULL)				\
+			*_tmp = ((rp)->refs);			\
+		UNLOCK(&(rp)->lock);				\
+	} while (0)
+
+#endif /* ISC_PLATFORM_HAVEXADD */
+#else  /* ISC_PLATFORM_USETHREADS */
+
+typedef struct isc_refcount {
+	int refs;
+} isc_refcount_t;
+
+#define isc_refcount_destroy(rp) REQUIRE((rp)->refs == 0)
+#define isc_refcount_current(rp) ((unsigned int)((rp)->refs))
+
+#define isc_refcount_increment0(rp, tp)					\
+	do {								\
+		unsigned int *_tmp = (unsigned int *)(tp);		\
+		int _n = ++(rp)->refs;					\
+		if (_tmp != NULL)					\
+			*_tmp = _n;					\
+	} while (0)
+
+#define isc_refcount_increment(rp, tp)					\
+	do {								\
+		unsigned int *_tmp = (unsigned int *)(tp);		\
+		int _n;							\
+		REQUIRE((rp)->refs > 0);				\
+		_n = ++(rp)->refs;					\
+		if (_tmp != NULL)					\
+			*_tmp = _n;					\
+	} while (0)
+
+#define isc_refcount_decrement(rp, tp)					\
+	do {								\
+		unsigned int *_tmp = (unsigned int *)(tp);		\
+		int _n;							\
+		REQUIRE((rp)->refs > 0);				\
+		_n = --(rp)->refs;					\
+		if (_tmp != NULL)					\
+			*_tmp = _n;					\
+	} while (0)
+
+#endif /* ISC_PLATFORM_USETHREADS */
+
+isc_result_t
+isc_refcount_init(isc_refcount_t *ref, unsigned int n);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_REFCOUNT_H */
diff --git a/src/lib/bind9/include/isc/region.h b/src/lib/bind9/include/isc/region.h
new file mode 100644
index 0000000..4d4f677
--- /dev/null
+++ b/src/lib/bind9/include/isc/region.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2002  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: region.h,v 1.25 2007-06-19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_REGION_H
+#define ISC_REGION_H 1
+
+/*! \file isc/region.h */
+
+#include <isc/types.h>
+
+struct isc_region {
+	unsigned char *	base;
+	unsigned int	length;
+};
+
+struct isc_textregion {
+	char *		base;
+	unsigned int	length;
+};
+
+/* XXXDCL questionable ... bears discussion.  we have been putting off
+ * discussing the region api.
+ */
+struct isc_constregion {
+	const void *	base;
+	unsigned int	length;
+};
+
+struct isc_consttextregion {
+	const char *	base;
+	unsigned int	length;
+};
+
+/*@{*/
+/*!
+ * The region structure is not opaque, and is usually directly manipulated.
+ * Some macros are defined below for convenience.
+ */
+
+#define isc_region_consume(r,l) \
+	do { \
+		isc_region_t *_r = (r); \
+		unsigned int _l = (l); \
+		INSIST(_r->length >= _l); \
+		_r->base += _l; \
+		_r->length -= _l; \
+	} while (0)
+
+#define isc_textregion_consume(r,l) \
+	do { \
+		isc_textregion_t *_r = (r); \
+		unsigned int _l = (l); \
+		INSIST(_r->length >= _l); \
+		_r->base += _l; \
+		_r->length -= _l; \
+	} while (0)
+
+#define isc_constregion_consume(r,l) \
+	do { \
+		isc_constregion_t *_r = (r); \
+		unsigned int _l = (l); \
+		INSIST(_r->length >= _l); \
+		_r->base += _l; \
+		_r->length -= _l; \
+	} while (0)
+/*@}*/
+
+int
+isc_region_compare(isc_region_t *r1, isc_region_t *r2);
+/*%<
+ * Compares the contents of two regions 
+ *
+ * Requires: 
+ *\li	'r1' is a valid region
+ *\li	'r2' is a valid region
+ *
+ * Returns:
+ *\li	 < 0 if r1 is lexicographically less than r2
+ *\li	 = 0 if r1 is lexicographically identical to r2
+ *\li	 > 0 if r1 is lexicographically greater than r2
+ */
+
+#endif /* ISC_REGION_H */
diff --git a/src/lib/bind9/include/isc/resource.h b/src/lib/bind9/include/isc/resource.h
new file mode 100644
index 0000000..2e2e73c
--- /dev/null
+++ b/src/lib/bind9/include/isc/resource.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2004-2008  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: resource.h,v 1.13 2008-07-11 23:47:09 tbox Exp $ */
+
+#ifndef ISC_RESOURCE_H
+#define ISC_RESOURCE_H 1
+
+/*! \file isc/resource.h */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+#define ISC_RESOURCE_UNLIMITED ((isc_resourcevalue_t)ISC_UINT64_MAX)
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_resource_setlimit(isc_resource_t resource, isc_resourcevalue_t value);
+/*%<
+ * Set the maximum limit for a system resource.
+ *
+ * Notes:
+ *\li	If 'value' exceeds the maximum possible on the operating system,
+ *	it is silently limited to that maximum -- or to "infinity", if
+ *	the operating system has that concept.  #ISC_RESOURCE_UNLIMITED
+ *	can be used to explicitly ask for the maximum.
+ *
+ * Requires:
+ *\li	'resource' is a valid member of the isc_resource_t enumeration.
+ *
+ * Returns:
+ *\li	#ISC_R_SUCCESS	Success.
+ *\li	#ISC_R_NOTIMPLEMENTED	'resource' is not a type known by the OS.
+ *\li	#ISC_R_NOPERM	The calling process did not have adequate permission
+ *			to change the resource limit.
+ */
+
+isc_result_t
+isc_resource_getlimit(isc_resource_t resource, isc_resourcevalue_t *value);
+/*%<
+ * Get the maximum limit for a system resource.
+ *
+ * Notes:
+ *\li	'value' is set to the maximum limit.
+ *
+ *\li	#ISC_RESOURCE_UNLIMITED is the maximum value of isc_resourcevalue_t.
+ *
+ *\li	On many (all?) Unix systems, RLIM_INFINITY is a valid value that is
+ *	significantly less than #ISC_RESOURCE_UNLIMITED, but which in practice
+ *	behaves the same.
+ *
+ *\li	The current ISC libdns configuration file parser assigns a value
+ *	of ISC_UINT32_MAX for a size_spec of "unlimited" and ISC_UNIT32_MAX - 1
+ *	for "default", the latter of which is supposed to represent "the
+ *	limit that was in force when the server started".  Since these are
+ *	valid values in the middle of the range of isc_resourcevalue_t,
+ *	there is the possibility for confusion over what exactly those
+ *	particular values are supposed to represent in a particular context --
+ *	discrete integral values or generalized concepts.
+ *
+ * Requires:
+ *\li	'resource' is a valid member of the isc_resource_t enumeration.
+ *
+ * Returns:
+ *\li	#ISC_R_SUCCESS		Success.
+ *\li	#ISC_R_NOTIMPLEMENTED	'resource' is not a type known by the OS.
+ */
+
+isc_result_t
+isc_resource_getcurlimit(isc_resource_t resource, isc_resourcevalue_t *value);
+/*%<
+ * Same as isc_resource_getlimit(), but returns the current (soft) limit.
+ *
+ * Returns:
+ *\li	#ISC_R_SUCCESS		Success.
+ *\li	#ISC_R_NOTIMPLEMENTED	'resource' is not a type known by the OS.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_RESOURCE_H */
+
diff --git a/src/lib/bind9/include/isc/result.h b/src/lib/bind9/include/isc/result.h
new file mode 100644
index 0000000..cc591dc
--- /dev/null
+++ b/src/lib/bind9/include/isc/result.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2004-2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2001, 2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: result.h,v 1.73 2009-09-02 23:48:03 tbox Exp $ */
+
+#ifndef ISC_RESULT_H
+#define ISC_RESULT_H 1
+
+/*! \file isc/result.h */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+#define ISC_R_SUCCESS			0	/*%< success */
+#define ISC_R_NOMEMORY			1	/*%< out of memory */
+#define ISC_R_TIMEDOUT			2	/*%< timed out */
+#define ISC_R_NOTHREADS			3	/*%< no available threads */
+#define ISC_R_ADDRNOTAVAIL		4	/*%< address not available */
+#define ISC_R_ADDRINUSE			5	/*%< address in use */
+#define ISC_R_NOPERM			6	/*%< permission denied */
+#define ISC_R_NOCONN			7	/*%< no pending connections */
+#define ISC_R_NETUNREACH		8	/*%< network unreachable */
+#define ISC_R_HOSTUNREACH		9	/*%< host unreachable */
+#define ISC_R_NETDOWN			10	/*%< network down */
+#define ISC_R_HOSTDOWN			11	/*%< host down */
+#define ISC_R_CONNREFUSED		12	/*%< connection refused */
+#define ISC_R_NORESOURCES		13	/*%< not enough free resources */
+#define ISC_R_EOF			14	/*%< end of file */
+#define ISC_R_BOUND			15	/*%< socket already bound */
+#define ISC_R_RELOAD			16	/*%< reload */
+#define ISC_R_SUSPEND	      ISC_R_RELOAD	/*%< alias of 'reload' */
+#define ISC_R_LOCKBUSY			17	/*%< lock busy */
+#define ISC_R_EXISTS			18	/*%< already exists */
+#define ISC_R_NOSPACE			19	/*%< ran out of space */
+#define ISC_R_CANCELED			20	/*%< operation canceled */
+#define ISC_R_NOTBOUND			21	/*%< socket is not bound */
+#define ISC_R_SHUTTINGDOWN		22	/*%< shutting down */
+#define ISC_R_NOTFOUND			23	/*%< not found */
+#define ISC_R_UNEXPECTEDEND		24	/*%< unexpected end of input */
+#define ISC_R_FAILURE			25	/*%< generic failure */
+#define ISC_R_IOERROR			26	/*%< I/O error */
+#define ISC_R_NOTIMPLEMENTED		27	/*%< not implemented */
+#define ISC_R_UNBALANCED		28	/*%< unbalanced parentheses */
+#define ISC_R_NOMORE			29	/*%< no more */
+#define ISC_R_INVALIDFILE		30	/*%< invalid file */
+#define ISC_R_BADBASE64			31	/*%< bad base64 encoding */
+#define ISC_R_UNEXPECTEDTOKEN		32	/*%< unexpected token */
+#define ISC_R_QUOTA			33	/*%< quota reached */
+#define ISC_R_UNEXPECTED		34	/*%< unexpected error */
+#define ISC_R_ALREADYRUNNING		35	/*%< already running */
+#define ISC_R_IGNORE			36	/*%< ignore */
+#define ISC_R_MASKNONCONTIG             37	/*%< addr mask not contiguous */
+#define ISC_R_FILENOTFOUND		38	/*%< file not found */
+#define ISC_R_FILEEXISTS		39	/*%< file already exists */
+#define ISC_R_NOTCONNECTED		40	/*%< socket is not connected */
+#define ISC_R_RANGE			41	/*%< out of range */
+#define ISC_R_NOENTROPY			42	/*%< out of entropy */
+#define ISC_R_MULTICAST			43	/*%< invalid use of multicast */
+#define ISC_R_NOTFILE			44	/*%< not a file */
+#define ISC_R_NOTDIRECTORY		45	/*%< not a directory */
+#define ISC_R_QUEUEFULL			46	/*%< queue is full */
+#define ISC_R_FAMILYMISMATCH		47	/*%< address family mismatch */
+#define ISC_R_FAMILYNOSUPPORT		48	/*%< AF not supported */
+#define ISC_R_BADHEX			49	/*%< bad hex encoding */
+#define ISC_R_TOOMANYOPENFILES		50	/*%< too many open files */
+#define ISC_R_NOTBLOCKING		51	/*%< not blocking */
+#define ISC_R_UNBALANCEDQUOTES		52	/*%< unbalanced quotes */
+#define ISC_R_INPROGRESS		53	/*%< operation in progress */
+#define ISC_R_CONNECTIONRESET		54	/*%< connection reset */
+#define ISC_R_SOFTQUOTA			55	/*%< soft quota reached */
+#define ISC_R_BADNUMBER			56	/*%< not a valid number */
+#define ISC_R_DISABLED			57	/*%< disabled */
+#define ISC_R_MAXSIZE			58	/*%< max size */
+#define ISC_R_BADADDRESSFORM		59	/*%< invalid address format */
+#define ISC_R_BADBASE32			60	/*%< bad base32 encoding */
+
+/*% Not a result code: the number of results. */
+#define ISC_R_NRESULTS 			61
+
+ISC_LANG_BEGINDECLS
+
+const char *
+isc_result_totext(isc_result_t);
+/*%<
+ * Convert an isc_result_t into a string message describing the result.
+ */
+
+isc_result_t
+isc_result_register(unsigned int base, unsigned int nresults,
+		    const char **text, isc_msgcat_t *msgcat, int set);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_RESULT_H */
diff --git a/src/lib/bind9/include/isc/resultclass.h b/src/lib/bind9/include/isc/resultclass.h
new file mode 100644
index 0000000..84f6c64
--- /dev/null
+++ b/src/lib/bind9/include/isc/resultclass.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: resultclass.h,v 1.20 2009-09-02 23:48:03 tbox Exp $ */
+
+#ifndef ISC_RESULTCLASS_H
+#define ISC_RESULTCLASS_H 1
+
+
+/*! \file isc/resultclass.h
+ * \brief Registry of Predefined Result Type Classes
+ *
+ * A result class number is an unsigned 16 bit number.  Each class may
+ * contain up to 65536 results.  A result code is formed by adding the
+ * result number within the class to the class number multiplied by 65536.
+ *
+ * Classes < 1024 are reserved for ISC use.
+ * Result classes >= 1024 and <= 65535 are reserved for application use.
+ */
+
+#define ISC_RESULTCLASS_FROMNUM(num)		((num) << 16)
+#define ISC_RESULTCLASS_TONUM(rclass)		((rclass) >> 16)
+#define ISC_RESULTCLASS_SIZE			65536
+#define ISC_RESULTCLASS_INCLASS(rclass, result) \
+	((rclass) == ((result) & 0xFFFF0000))
+
+
+#define	ISC_RESULTCLASS_ISC		ISC_RESULTCLASS_FROMNUM(0)
+#define	ISC_RESULTCLASS_DNS		ISC_RESULTCLASS_FROMNUM(1)
+#define	ISC_RESULTCLASS_DST		ISC_RESULTCLASS_FROMNUM(2)
+#define	ISC_RESULTCLASS_DNSRCODE	ISC_RESULTCLASS_FROMNUM(3)
+#define	ISC_RESULTCLASS_OMAPI		ISC_RESULTCLASS_FROMNUM(4)
+#define	ISC_RESULTCLASS_ISCCC		ISC_RESULTCLASS_FROMNUM(5)
+#define	ISC_RESULTCLASS_DHCP		ISC_RESULTCLASS_FROMNUM(6)
+
+
+#endif /* ISC_RESULTCLASS_H */
diff --git a/src/lib/bind9/include/isc/rwlock.h b/src/lib/bind9/include/isc/rwlock.h
new file mode 100644
index 0000000..57cc16c
--- /dev/null
+++ b/src/lib/bind9/include/isc/rwlock.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2001, 2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: rwlock.h,v 1.28 2007-06-19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_RWLOCK_H
+#define ISC_RWLOCK_H 1
+
+/*! \file isc/rwlock.h */
+
+#include <isc/condition.h>
+#include <isc/lang.h>
+#include <isc/platform.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+typedef enum {
+	isc_rwlocktype_none = 0,
+	isc_rwlocktype_read,
+	isc_rwlocktype_write
+} isc_rwlocktype_t;
+
+#ifdef ISC_PLATFORM_USETHREADS
+#if defined(ISC_PLATFORM_HAVEXADD) && defined(ISC_PLATFORM_HAVECMPXCHG)
+#define ISC_RWLOCK_USEATOMIC 1
+#endif
+
+struct isc_rwlock {
+	/* Unlocked. */
+	unsigned int		magic;
+	isc_mutex_t		lock;
+
+#if defined(ISC_PLATFORM_HAVEXADD) && defined(ISC_PLATFORM_HAVECMPXCHG)
+	/*
+	 * When some atomic instructions with hardware assistance are
+	 * available, rwlock will use those so that concurrent readers do not
+	 * interfere with each other through mutex as long as no writers
+	 * appear, massively reducing the lock overhead in the typical case.
+	 *
+	 * The basic algorithm of this approach is the "simple
+	 * writer-preference lock" shown in the following URL:
+	 * http://www.cs.rochester.edu/u/scott/synchronization/pseudocode/rw.html
+	 * but our implementation does not rely on the spin lock unlike the
+	 * original algorithm to be more portable as a user space application.
+	 */
+
+	/* Read or modified atomically. */
+	isc_int32_t		write_requests;
+	isc_int32_t		write_completions;
+	isc_int32_t		cnt_and_flag;
+
+	/* Locked by lock. */
+	isc_condition_t		readable;
+	isc_condition_t		writeable;
+	unsigned int		readers_waiting;
+
+	/* Locked by rwlock itself. */
+	unsigned int		write_granted;
+
+	/* Unlocked. */
+	unsigned int		write_quota;
+
+#else  /* ISC_PLATFORM_HAVEXADD && ISC_PLATFORM_HAVECMPXCHG */
+
+	/*%< Locked by lock. */
+	isc_condition_t		readable;
+	isc_condition_t		writeable;
+	isc_rwlocktype_t	type;
+
+	/*% The number of threads that have the lock. */
+	unsigned int		active;
+
+	/*%
+	 * The number of lock grants made since the lock was last switched
+	 * from reading to writing or vice versa; used in determining
+	 * when the quota is reached and it is time to switch.
+	 */
+	unsigned int		granted;
+	
+	unsigned int		readers_waiting;
+	unsigned int		writers_waiting;
+	unsigned int		read_quota;
+	unsigned int		write_quota;
+	isc_rwlocktype_t	original;
+#endif  /* ISC_PLATFORM_HAVEXADD && ISC_PLATFORM_HAVECMPXCHG */
+};
+#else /* ISC_PLATFORM_USETHREADS */
+struct isc_rwlock {
+	unsigned int		magic;
+	isc_rwlocktype_t	type;
+	unsigned int		active;
+};
+#endif /* ISC_PLATFORM_USETHREADS */
+
+
+isc_result_t
+isc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota,
+		unsigned int write_quota);
+
+isc_result_t
+isc_rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type);
+
+isc_result_t
+isc_rwlock_trylock(isc_rwlock_t *rwl, isc_rwlocktype_t type);
+
+isc_result_t
+isc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type);
+
+isc_result_t
+isc_rwlock_tryupgrade(isc_rwlock_t *rwl);
+
+void
+isc_rwlock_downgrade(isc_rwlock_t *rwl);
+
+void
+isc_rwlock_destroy(isc_rwlock_t *rwl);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_RWLOCK_H */
diff --git a/src/lib/bind9/include/isc/serial.h b/src/lib/bind9/include/isc/serial.h
new file mode 100644
index 0000000..332709d
--- /dev/null
+++ b/src/lib/bind9/include/isc/serial.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: serial.h,v 1.18 2009-01-18 23:48:14 tbox Exp $ */
+
+#ifndef ISC_SERIAL_H
+#define ISC_SERIAL_H 1
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+/*! \file isc/serial.h
+ *	\brief Implement 32 bit serial space arithmetic comparison functions.
+ *	Note: Undefined results are returned as ISC_FALSE.
+ */
+
+/***
+ ***	Functions
+ ***/
+
+ISC_LANG_BEGINDECLS
+
+isc_boolean_t
+isc_serial_lt(isc_uint32_t a, isc_uint32_t b);
+/*%<
+ *	Return true if 'a' < 'b' otherwise false.
+ */
+
+isc_boolean_t
+isc_serial_gt(isc_uint32_t a, isc_uint32_t b);
+/*%<
+ *	Return true if 'a' > 'b' otherwise false.
+ */
+
+isc_boolean_t
+isc_serial_le(isc_uint32_t a, isc_uint32_t b);
+/*%<
+ *	Return true if 'a' <= 'b' otherwise false.
+ */
+
+isc_boolean_t
+isc_serial_ge(isc_uint32_t a, isc_uint32_t b);
+/*%<
+ *	Return true if 'a' >= 'b' otherwise false.
+ */
+
+isc_boolean_t
+isc_serial_eq(isc_uint32_t a, isc_uint32_t b);
+/*%<
+ *	Return true if 'a' == 'b' otherwise false.
+ */
+
+isc_boolean_t
+isc_serial_ne(isc_uint32_t a, isc_uint32_t b);
+/*%<
+ *	Return true if 'a' != 'b' otherwise false.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_SERIAL_H */
diff --git a/src/lib/bind9/include/isc/sha1.h b/src/lib/bind9/include/isc/sha1.h
new file mode 100644
index 0000000..a9d08b9
--- /dev/null
+++ b/src/lib/bind9/include/isc/sha1.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ISC_SHA1_H
+#define ISC_SHA1_H 1
+
+/* $Id: sha1.h,v 1.19 2009-02-06 23:47:42 tbox Exp $ */
+
+/*	$NetBSD: sha1.h,v 1.2 1998/05/29 22:55:44 thorpej Exp $	*/
+
+/*! \file isc/sha1.h
+ * \brief SHA-1 in C
+ * \author By Steve Reid <steve at edmweb.com>
+ * \note 100% Public Domain
+ */
+
+#include <isc/lang.h>
+#include <isc/platform.h>
+#include <isc/types.h>
+
+#define ISC_SHA1_DIGESTLENGTH 20U
+#define ISC_SHA1_BLOCK_LENGTH 64U
+
+#ifdef ISC_PLATFORM_OPENSSLHASH
+#include <openssl/evp.h>
+
+typedef EVP_MD_CTX isc_sha1_t;
+
+#else
+
+typedef struct {
+	isc_uint32_t state[5];
+	isc_uint32_t count[2];
+	unsigned char buffer[ISC_SHA1_BLOCK_LENGTH];
+} isc_sha1_t;
+#endif
+
+ISC_LANG_BEGINDECLS
+
+void
+isc_sha1_init(isc_sha1_t *ctx);
+
+void
+isc_sha1_invalidate(isc_sha1_t *ctx);
+
+void
+isc_sha1_update(isc_sha1_t *ctx, const unsigned char *data, unsigned int len);
+
+void
+isc_sha1_final(isc_sha1_t *ctx, unsigned char *digest);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_SHA1_H */
diff --git a/src/lib/bind9/include/isc/sha2.h b/src/lib/bind9/include/isc/sha2.h
new file mode 100644
index 0000000..bce4845
--- /dev/null
+++ b/src/lib/bind9/include/isc/sha2.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2005-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: sha2.h,v 1.12 2009-10-22 02:21:31 each Exp $ */
+
+/*	$FreeBSD: src/sys/crypto/sha2/sha2.h,v 1.1.2.1 2001/07/03 11:01:36 ume Exp $	*/
+/*	$KAME: sha2.h,v 1.3 2001/03/12 08:27:48 itojun Exp $	*/
+
+/*
+ * sha2.h
+ *
+ * Version 1.0.0beta1
+ *
+ * Written by Aaron D. Gifford <me at aarongifford.com>
+ *
+ * Copyright 2000 Aaron D. Gifford.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTOR(S) ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTOR(S) BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef ISC_SHA2_H
+#define ISC_SHA2_H
+
+#include <isc/lang.h>
+#include <isc/platform.h>
+#include <isc/types.h>
+
+/*** SHA-224/256/384/512 Various Length Definitions ***********************/
+
+#define ISC_SHA224_BLOCK_LENGTH		64U
+#define ISC_SHA224_DIGESTLENGTH	28U
+#define ISC_SHA224_DIGESTSTRINGLENGTH	(ISC_SHA224_DIGESTLENGTH * 2 + 1)
+#define ISC_SHA256_BLOCK_LENGTH		64U
+#define ISC_SHA256_DIGESTLENGTH	32U
+#define ISC_SHA256_DIGESTSTRINGLENGTH	(ISC_SHA256_DIGESTLENGTH * 2 + 1)
+#define ISC_SHA384_BLOCK_LENGTH		128
+#define ISC_SHA384_DIGESTLENGTH	48U
+#define ISC_SHA384_DIGESTSTRINGLENGTH	(ISC_SHA384_DIGESTLENGTH * 2 + 1)
+#define ISC_SHA512_BLOCK_LENGTH		128U
+#define ISC_SHA512_DIGESTLENGTH	64U
+#define ISC_SHA512_DIGESTSTRINGLENGTH	(ISC_SHA512_DIGESTLENGTH * 2 + 1)
+
+/*** SHA-256/384/512 Context Structures *******************************/
+
+#ifdef ISC_PLATFORM_OPENSSLHASH
+#include <openssl/evp.h>
+
+typedef EVP_MD_CTX isc_sha256_t;
+typedef EVP_MD_CTX isc_sha512_t;
+
+#else
+
+/*
+ * Keep buffer immediately after bitcount to preserve alignment.
+ */
+typedef struct {
+	isc_uint32_t	state[8];
+	isc_uint64_t	bitcount;
+	isc_uint8_t	buffer[ISC_SHA256_BLOCK_LENGTH];
+} isc_sha256_t;
+
+/*
+ * Keep buffer immediately after bitcount to preserve alignment.
+ */
+typedef struct {
+	isc_uint64_t	state[8];
+	isc_uint64_t	bitcount[2];
+	isc_uint8_t	buffer[ISC_SHA512_BLOCK_LENGTH];
+} isc_sha512_t;
+#endif
+
+typedef isc_sha256_t isc_sha224_t;
+typedef isc_sha512_t isc_sha384_t;
+
+ISC_LANG_BEGINDECLS
+
+/*** SHA-224/256/384/512 Function Prototypes ******************************/
+
+void isc_sha224_init (isc_sha224_t *);
+void isc_sha224_invalidate (isc_sha224_t *);
+void isc_sha224_update (isc_sha224_t *, const isc_uint8_t *, size_t);
+void isc_sha224_final (isc_uint8_t[ISC_SHA224_DIGESTLENGTH], isc_sha224_t *);
+char *isc_sha224_end (isc_sha224_t *, char[ISC_SHA224_DIGESTSTRINGLENGTH]);
+char *isc_sha224_data (const isc_uint8_t *, size_t, char[ISC_SHA224_DIGESTSTRINGLENGTH]);
+
+void isc_sha256_init (isc_sha256_t *);
+void isc_sha256_invalidate (isc_sha256_t *);
+void isc_sha256_update (isc_sha256_t *, const isc_uint8_t *, size_t);
+void isc_sha256_final (isc_uint8_t[ISC_SHA256_DIGESTLENGTH], isc_sha256_t *);
+char *isc_sha256_end (isc_sha256_t *, char[ISC_SHA256_DIGESTSTRINGLENGTH]);
+char *isc_sha256_data (const isc_uint8_t *, size_t, char[ISC_SHA256_DIGESTSTRINGLENGTH]);
+
+void isc_sha384_init (isc_sha384_t *);
+void isc_sha384_invalidate (isc_sha384_t *);
+void isc_sha384_update (isc_sha384_t *, const isc_uint8_t *, size_t);
+void isc_sha384_final (isc_uint8_t[ISC_SHA384_DIGESTLENGTH], isc_sha384_t *);
+char *isc_sha384_end (isc_sha384_t *, char[ISC_SHA384_DIGESTSTRINGLENGTH]);
+char *isc_sha384_data (const isc_uint8_t *, size_t, char[ISC_SHA384_DIGESTSTRINGLENGTH]);
+
+void isc_sha512_init (isc_sha512_t *);
+void isc_sha512_invalidate (isc_sha512_t *);
+void isc_sha512_update (isc_sha512_t *, const isc_uint8_t *, size_t);
+void isc_sha512_final (isc_uint8_t[ISC_SHA512_DIGESTLENGTH], isc_sha512_t *);
+char *isc_sha512_end (isc_sha512_t *, char[ISC_SHA512_DIGESTSTRINGLENGTH]);
+char *isc_sha512_data (const isc_uint8_t *, size_t, char[ISC_SHA512_DIGESTSTRINGLENGTH]);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_SHA2_H */
diff --git a/src/lib/bind9/include/isc/sockaddr.h b/src/lib/bind9/include/isc/sockaddr.h
new file mode 100644
index 0000000..c83655e
--- /dev/null
+++ b/src/lib/bind9/include/isc/sockaddr.h
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: sockaddr.h,v 1.57 2009-01-18 23:48:14 tbox Exp $ */
+
+#ifndef ISC_SOCKADDR_H
+#define ISC_SOCKADDR_H 1
+
+/*! \file isc/sockaddr.h */
+
+#include <isc/lang.h>
+#include <isc/net.h>
+#include <isc/types.h>
+#ifdef ISC_PLATFORM_HAVESYSUNH
+#include <sys/un.h>
+#endif
+
+struct isc_sockaddr {
+	union {
+		struct sockaddr		sa;
+		struct sockaddr_in	sin;
+		struct sockaddr_in6	sin6;
+#ifdef ISC_PLATFORM_HAVESYSUNH
+		struct sockaddr_un	sunix;
+#endif
+	}				type;
+	unsigned int			length;		/* XXXRTH beginning? */
+	ISC_LINK(struct isc_sockaddr)	link;
+};
+
+typedef ISC_LIST(struct isc_sockaddr)	isc_sockaddrlist_t;
+
+#define ISC_SOCKADDR_CMPADDR	  0x0001	/*%< compare the address
+						 *   sin_addr/sin6_addr */
+#define ISC_SOCKADDR_CMPPORT 	  0x0002	/*%< compare the port
+						 *   sin_port/sin6_port */
+#define ISC_SOCKADDR_CMPSCOPE     0x0004	/*%< compare the scope
+						 *   sin6_scope */
+#define ISC_SOCKADDR_CMPSCOPEZERO 0x0008	/*%< when comparing scopes
+						 *   zero scopes always match */
+
+ISC_LANG_BEGINDECLS
+
+isc_boolean_t
+isc_sockaddr_compare(const isc_sockaddr_t *a, const isc_sockaddr_t *b,
+		     unsigned int flags);
+/*%<
+ * Compare the elements of the two address ('a' and 'b') as specified
+ * by 'flags' and report if they are equal or not.
+ *
+ * 'flags' is set from ISC_SOCKADDR_CMP*.
+ */
+
+isc_boolean_t
+isc_sockaddr_equal(const isc_sockaddr_t *a, const isc_sockaddr_t *b);
+/*%<
+ * Return ISC_TRUE iff the socket addresses 'a' and 'b' are equal.
+ */
+
+isc_boolean_t
+isc_sockaddr_eqaddr(const isc_sockaddr_t *a, const isc_sockaddr_t *b);
+/*%<
+ * Return ISC_TRUE iff the address parts of the socket addresses
+ * 'a' and 'b' are equal, ignoring the ports.
+ */
+
+isc_boolean_t
+isc_sockaddr_eqaddrprefix(const isc_sockaddr_t *a, const isc_sockaddr_t *b,
+			  unsigned int prefixlen);
+/*%<
+ * Return ISC_TRUE iff the most significant 'prefixlen' bits of the
+ * socket addresses 'a' and 'b' are equal, ignoring the ports.
+ * If 'b''s scope is zero then 'a''s scope will be ignored.
+ */
+
+unsigned int
+isc_sockaddr_hash(const isc_sockaddr_t *sockaddr, isc_boolean_t address_only);
+/*%<
+ * Return a hash value for the socket address 'sockaddr'.  If 'address_only'
+ * is ISC_TRUE, the hash value will not depend on the port.
+ *
+ * IPv6 addresses containing mapped IPv4 addresses generate the same hash
+ * value as the equivalent IPv4 address.
+ */
+
+void
+isc_sockaddr_any(isc_sockaddr_t *sockaddr);
+/*%<
+ * Return the IPv4 wildcard address.
+ */
+
+void
+isc_sockaddr_any6(isc_sockaddr_t *sockaddr);
+/*%<
+ * Return the IPv6 wildcard address.
+ */
+
+void
+isc_sockaddr_anyofpf(isc_sockaddr_t *sockaddr, int family);
+/*%<
+ * Set '*sockaddr' to the wildcard address of protocol family
+ * 'family'.
+ *
+ * Requires:
+ * \li	'family' is AF_INET or AF_INET6.
+ */
+
+void
+isc_sockaddr_fromin(isc_sockaddr_t *sockaddr, const struct in_addr *ina,
+		    in_port_t port);
+/*%<
+ * Construct an isc_sockaddr_t from an IPv4 address and port.
+ */
+
+void
+isc_sockaddr_fromin6(isc_sockaddr_t *sockaddr, const struct in6_addr *ina6,
+		     in_port_t port);
+/*%<
+ * Construct an isc_sockaddr_t from an IPv6 address and port.
+ */
+
+void
+isc_sockaddr_v6fromin(isc_sockaddr_t *sockaddr, const struct in_addr *ina,
+		      in_port_t port);
+/*%<
+ * Construct an IPv6 isc_sockaddr_t representing a mapped IPv4 address.
+ */
+
+void
+isc_sockaddr_fromnetaddr(isc_sockaddr_t *sockaddr, const isc_netaddr_t *na,
+			 in_port_t port);
+/*%<
+ * Construct an isc_sockaddr_t from an isc_netaddr_t and port.
+ */
+
+int
+isc_sockaddr_pf(const isc_sockaddr_t *sockaddr);
+/*%<
+ * Get the protocol family of 'sockaddr'.
+ *
+ * Requires:
+ *
+ *\li	'sockaddr' is a valid sockaddr with an address family of AF_INET
+ *	or AF_INET6.
+ *
+ * Returns:
+ *
+ *\li	The protocol family of 'sockaddr', e.g. PF_INET or PF_INET6.
+ */
+
+void
+isc_sockaddr_setport(isc_sockaddr_t *sockaddr, in_port_t port);
+/*%<
+ * Set the port of 'sockaddr' to 'port'.
+ */
+
+in_port_t
+isc_sockaddr_getport(const isc_sockaddr_t *sockaddr);
+/*%<
+ * Get the port stored in 'sockaddr'.
+ */
+
+isc_result_t
+isc_sockaddr_totext(const isc_sockaddr_t *sockaddr, isc_buffer_t *target);
+/*%<
+ * Append a text representation of 'sockaddr' to the buffer 'target'.
+ * The text will include both the IP address (v4 or v6) and the port.
+ * The text is null terminated, but the terminating null is not
+ * part of the buffer's used region.
+ *
+ * Returns:
+ * \li	ISC_R_SUCCESS
+ * \li	ISC_R_NOSPACE	The text or the null termination did not fit.
+ */
+
+void
+isc_sockaddr_format(const isc_sockaddr_t *sa, char *array, unsigned int size);
+/*%<
+ * Format a human-readable representation of the socket address '*sa'
+ * into the character array 'array', which is of size 'size'.
+ * The resulting string is guaranteed to be null-terminated.
+ */
+
+isc_boolean_t
+isc_sockaddr_ismulticast(const isc_sockaddr_t *sa);
+/*%<
+ * Returns #ISC_TRUE if the address is a multicast address.
+ */
+
+isc_boolean_t
+isc_sockaddr_isexperimental(const isc_sockaddr_t *sa);
+/*
+ * Returns ISC_TRUE if the address is a experimental (CLASS E) address.
+ */
+
+isc_boolean_t
+isc_sockaddr_islinklocal(const isc_sockaddr_t *sa);
+/*%<
+ * Returns ISC_TRUE if the address is a link local address.
+ */
+
+isc_boolean_t
+isc_sockaddr_issitelocal(const isc_sockaddr_t *sa);
+/*%<
+ * Returns ISC_TRUE if the address is a sitelocal address.
+ */
+
+isc_result_t
+isc_sockaddr_frompath(isc_sockaddr_t *sockaddr, const char *path);
+/*
+ *  Create a UNIX domain sockaddr that refers to path.
+ *
+ * Returns:
+ * \li	ISC_R_NOSPACE
+ * \li	ISC_R_NOTIMPLEMENTED
+ * \li	ISC_R_SUCCESS
+ */
+
+#define ISC_SOCKADDR_FORMATSIZE \
+	sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:XXX.XXX.XXX.XXX%SSSSSSSSSS#YYYYY")
+/*%<
+ * Minimum size of array to pass to isc_sockaddr_format().
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_SOCKADDR_H */
diff --git a/src/lib/bind9/include/isc/socket.h b/src/lib/bind9/include/isc/socket.h
new file mode 100644
index 0000000..0aa71da
--- /dev/null
+++ b/src/lib/bind9/include/isc/socket.h
@@ -0,0 +1,1154 @@
+/*
+ * Copyright (C) 2004-2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2002  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: socket.h,v 1.94 2009-10-01 01:30:01 sar Exp $ */
+
+#ifndef ISC_SOCKET_H
+#define ISC_SOCKET_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file isc/socket.h
+ * \brief Provides TCP and UDP sockets for network I/O.  The sockets are event
+ * sources in the task system.
+ *
+ * When I/O completes, a completion event for the socket is posted to the
+ * event queue of the task which requested the I/O.
+ *
+ * \li MP:
+ *	The module ensures appropriate synchronization of data structures it
+ *	creates and manipulates.
+ *	Clients of this module must not be holding a socket's task's lock when
+ *	making a call that affects that socket.  Failure to follow this rule
+ *	can result in deadlock.
+ *	The caller must ensure that isc_socketmgr_destroy() is called only
+ *	once for a given manager.
+ *
+ * \li Reliability:
+ *	No anticipated impact.
+ *
+ * \li Resources:
+ *	TBS
+ *
+ * \li Security:
+ *	No anticipated impact.
+ *
+ * \li Standards:
+ *	None.
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/lang.h>
+#include <isc/types.h>
+#include <isc/event.h>
+#include <isc/eventclass.h>
+#include <isc/time.h>
+#include <isc/region.h>
+#include <isc/sockaddr.h>
+#include <isc/xml.h>
+
+ISC_LANG_BEGINDECLS
+
+/***
+ *** Constants
+ ***/
+
+/*%
+ * Maximum number of buffers in a scatter/gather read/write.  The operating
+ * system in use must support at least this number (plus one on some.)
+ */
+#define ISC_SOCKET_MAXSCATTERGATHER	8
+
+/*%
+ * In isc_socket_bind() set socket option SO_REUSEADDR prior to calling
+ * bind() if a non zero port is specified (AF_INET and AF_INET6).
+ */
+#define ISC_SOCKET_REUSEADDRESS		0x01U
+
+/*%
+ * Statistics counters.  Used as isc_statscounter_t values.
+ */
+enum {
+	isc_sockstatscounter_udp4open = 0,
+	isc_sockstatscounter_udp6open = 1,
+	isc_sockstatscounter_tcp4open = 2,
+	isc_sockstatscounter_tcp6open = 3,
+	isc_sockstatscounter_unixopen = 4,
+
+	isc_sockstatscounter_udp4openfail = 5,
+	isc_sockstatscounter_udp6openfail = 6,
+	isc_sockstatscounter_tcp4openfail = 7,
+	isc_sockstatscounter_tcp6openfail = 8,
+	isc_sockstatscounter_unixopenfail = 9,
+
+	isc_sockstatscounter_udp4close = 10,
+	isc_sockstatscounter_udp6close = 11,
+	isc_sockstatscounter_tcp4close = 12,
+	isc_sockstatscounter_tcp6close = 13,
+	isc_sockstatscounter_unixclose = 14,
+	isc_sockstatscounter_fdwatchclose = 15,
+
+	isc_sockstatscounter_udp4bindfail = 16,
+	isc_sockstatscounter_udp6bindfail = 17,
+	isc_sockstatscounter_tcp4bindfail = 18,
+	isc_sockstatscounter_tcp6bindfail = 19,
+	isc_sockstatscounter_unixbindfail = 20,
+	isc_sockstatscounter_fdwatchbindfail = 21,
+
+	isc_sockstatscounter_udp4connect = 22,
+	isc_sockstatscounter_udp6connect = 23,
+	isc_sockstatscounter_tcp4connect = 24,
+	isc_sockstatscounter_tcp6connect = 25,
+	isc_sockstatscounter_unixconnect = 26,
+	isc_sockstatscounter_fdwatchconnect = 27,
+
+	isc_sockstatscounter_udp4connectfail = 28,
+	isc_sockstatscounter_udp6connectfail = 29,
+	isc_sockstatscounter_tcp4connectfail = 30,
+	isc_sockstatscounter_tcp6connectfail = 31,
+	isc_sockstatscounter_unixconnectfail = 32,
+	isc_sockstatscounter_fdwatchconnectfail = 33,
+
+	isc_sockstatscounter_tcp4accept = 34,
+	isc_sockstatscounter_tcp6accept = 35,
+	isc_sockstatscounter_unixaccept = 36,
+
+	isc_sockstatscounter_tcp4acceptfail = 37,
+	isc_sockstatscounter_tcp6acceptfail = 38,
+	isc_sockstatscounter_unixacceptfail = 39,
+
+	isc_sockstatscounter_udp4sendfail = 40,
+	isc_sockstatscounter_udp6sendfail = 41,
+	isc_sockstatscounter_tcp4sendfail = 42,
+	isc_sockstatscounter_tcp6sendfail = 43,
+	isc_sockstatscounter_unixsendfail = 44,
+	isc_sockstatscounter_fdwatchsendfail = 45,
+
+	isc_sockstatscounter_udp4recvfail = 46,
+	isc_sockstatscounter_udp6recvfail = 47,
+	isc_sockstatscounter_tcp4recvfail = 48,
+	isc_sockstatscounter_tcp6recvfail = 49,
+	isc_sockstatscounter_unixrecvfail = 50,
+	isc_sockstatscounter_fdwatchrecvfail = 51,
+
+	isc_sockstatscounter_max = 52
+};
+
+/***
+ *** Types
+ ***/
+
+struct isc_socketevent {
+	ISC_EVENT_COMMON(isc_socketevent_t);
+	isc_result_t		result;		/*%< OK, EOF, whatever else */
+	unsigned int		minimum;	/*%< minimum i/o for event */
+	unsigned int		n;		/*%< bytes read or written */
+	unsigned int		offset;		/*%< offset into buffer list */
+	isc_region_t		region;		/*%< for single-buffer i/o */
+	isc_bufferlist_t	bufferlist;	/*%< list of buffers */
+	isc_sockaddr_t		address;	/*%< source address */
+	isc_time_t		timestamp;	/*%< timestamp of packet recv */
+	struct in6_pktinfo	pktinfo;	/*%< ipv6 pktinfo */
+	isc_uint32_t		attributes;	/*%< see below */
+	isc_eventdestructor_t   destroy;	/*%< original destructor */
+};
+
+typedef struct isc_socket_newconnev isc_socket_newconnev_t;
+struct isc_socket_newconnev {
+	ISC_EVENT_COMMON(isc_socket_newconnev_t);
+	isc_socket_t *		newsocket;
+	isc_result_t		result;		/*%< OK, EOF, whatever else */
+	isc_sockaddr_t		address;	/*%< source address */
+};
+
+typedef struct isc_socket_connev isc_socket_connev_t;
+struct isc_socket_connev {
+	ISC_EVENT_COMMON(isc_socket_connev_t);
+	isc_result_t		result;		/*%< OK, EOF, whatever else */
+};
+
+/*@{*/
+/*!
+ * _ATTACHED:	Internal use only.
+ * _TRUNC:	Packet was truncated on receive.
+ * _CTRUNC:	Packet control information was truncated.  This can
+ *		indicate that the packet is not complete, even though
+ *		all the data is valid.
+ * _TIMESTAMP:	The timestamp member is valid.
+ * _PKTINFO:	The pktinfo member is valid.
+ * _MULTICAST:	The UDP packet was received via a multicast transmission.
+ */
+#define ISC_SOCKEVENTATTR_ATTACHED		0x80000000U /* internal */
+#define ISC_SOCKEVENTATTR_TRUNC			0x00800000U /* public */
+#define ISC_SOCKEVENTATTR_CTRUNC		0x00400000U /* public */
+#define ISC_SOCKEVENTATTR_TIMESTAMP		0x00200000U /* public */
+#define ISC_SOCKEVENTATTR_PKTINFO		0x00100000U /* public */
+#define ISC_SOCKEVENTATTR_MULTICAST		0x00080000U /* public */
+/*@}*/
+
+#define ISC_SOCKEVENT_ANYEVENT  (0)
+#define ISC_SOCKEVENT_RECVDONE	(ISC_EVENTCLASS_SOCKET + 1)
+#define ISC_SOCKEVENT_SENDDONE	(ISC_EVENTCLASS_SOCKET + 2)
+#define ISC_SOCKEVENT_NEWCONN	(ISC_EVENTCLASS_SOCKET + 3)
+#define ISC_SOCKEVENT_CONNECT	(ISC_EVENTCLASS_SOCKET + 4)
+
+/*
+ * Internal events.
+ */
+#define ISC_SOCKEVENT_INTR	(ISC_EVENTCLASS_SOCKET + 256)
+#define ISC_SOCKEVENT_INTW	(ISC_EVENTCLASS_SOCKET + 257)
+
+typedef enum {
+	isc_sockettype_udp = 1,
+	isc_sockettype_tcp = 2,
+	isc_sockettype_unix = 3,
+	isc_sockettype_fdwatch = 4
+} isc_sockettype_t;
+
+/*@{*/
+/*!
+ * How a socket should be shutdown in isc_socket_shutdown() calls.
+ */
+#define ISC_SOCKSHUT_RECV	0x00000001	/*%< close read side */
+#define ISC_SOCKSHUT_SEND	0x00000002	/*%< close write side */
+#define ISC_SOCKSHUT_ALL	0x00000003	/*%< close them all */
+/*@}*/
+
+/*@{*/
+/*!
+ * What I/O events to cancel in isc_socket_cancel() calls.
+ */
+#define ISC_SOCKCANCEL_RECV	0x00000001	/*%< cancel recv */
+#define ISC_SOCKCANCEL_SEND	0x00000002	/*%< cancel send */
+#define ISC_SOCKCANCEL_ACCEPT	0x00000004	/*%< cancel accept */
+#define ISC_SOCKCANCEL_CONNECT	0x00000008	/*%< cancel connect */
+#define ISC_SOCKCANCEL_ALL	0x0000000f	/*%< cancel everything */
+/*@}*/
+
+/*@{*/
+/*!
+ * Flags for isc_socket_send() and isc_socket_recv() calls.
+ */
+#define ISC_SOCKFLAG_IMMEDIATE	0x00000001	/*%< send event only if needed */
+#define ISC_SOCKFLAG_NORETRY	0x00000002	/*%< drop failed UDP sends */
+/*@}*/
+
+/*@{*/
+/*!
+ * Flags for fdwatchcreate.
+ */
+#define ISC_SOCKFDWATCH_READ	0x00000001	/*%< watch for readable */
+#define ISC_SOCKFDWATCH_WRITE	0x00000002	/*%< watch for writable */
+/*@}*/
+
+/*% Socket and socket manager methods */
+typedef struct isc_socketmgrmethods {
+	void		(*destroy)(isc_socketmgr_t **managerp);
+	isc_result_t	(*socketcreate)(isc_socketmgr_t *manager, int pf,
+					isc_sockettype_t type,
+					isc_socket_t **socketp);
+	isc_result_t    (*fdwatchcreate)(isc_socketmgr_t *manager, int fd,
+					 int flags,
+					 isc_sockfdwatch_t callback,
+					 void *cbarg, isc_task_t *task,
+					 isc_socket_t **socketp);
+} isc_socketmgrmethods_t;
+
+typedef struct isc_socketmethods {
+	void		(*attach)(isc_socket_t *socket,
+				  isc_socket_t **socketp);
+	void		(*detach)(isc_socket_t **socketp);
+	isc_result_t	(*bind)(isc_socket_t *sock, isc_sockaddr_t *sockaddr,
+				unsigned int options);
+	isc_result_t	(*sendto)(isc_socket_t *sock, isc_region_t *region,
+				  isc_task_t *task, isc_taskaction_t action,
+				  const void *arg, isc_sockaddr_t *address,
+				  struct in6_pktinfo *pktinfo);
+	isc_result_t	(*connect)(isc_socket_t *sock, isc_sockaddr_t *addr,
+				   isc_task_t *task, isc_taskaction_t action,
+				   const void *arg);
+	isc_result_t	(*recv)(isc_socket_t *sock, isc_region_t *region,
+				unsigned int minimum, isc_task_t *task,
+				isc_taskaction_t action, const void *arg);
+	void		(*cancel)(isc_socket_t *sock, isc_task_t *task,
+				  unsigned int how);
+	isc_result_t	(*getsockname)(isc_socket_t *sock,
+				       isc_sockaddr_t *addressp);
+	isc_sockettype_t (*gettype)(isc_socket_t *sock);
+	void		(*ipv6only)(isc_socket_t *sock, isc_boolean_t yes);
+	isc_result_t    (*fdwatchpoke)(isc_socket_t *sock, int flags);
+} isc_socketmethods_t;
+
+/*%
+ * This structure is actually just the common prefix of a socket manager
+ * object implementation's version of an isc_socketmgr_t.
+ * \brief
+ * Direct use of this structure by clients is forbidden.  socket implementations
+ * may change the structure.  'magic' must be ISCAPI_SOCKETMGR_MAGIC for any
+ * of the isc_socket_ routines to work.  socket implementations must maintain
+ * all socket invariants.
+ * In effect, this definition is used only for non-BIND9 version ("export")
+ * of the library, and the export version does not work for win32.  So, to avoid
+ * the definition conflict with win32/socket.c, we enable this definition only
+ * for non-Win32 (i.e. Unix) platforms.
+ */
+#ifndef WIN32
+struct isc_socketmgr {
+	unsigned int		impmagic;
+	unsigned int		magic;
+	isc_socketmgrmethods_t	*methods;
+};
+#endif
+
+#define ISCAPI_SOCKETMGR_MAGIC		ISC_MAGIC('A','s','m','g')
+#define ISCAPI_SOCKETMGR_VALID(m)	((m) != NULL && \
+					 (m)->magic == ISCAPI_SOCKETMGR_MAGIC)
+
+/*%
+ * This is the common prefix of a socket object.  The same note as
+ * that for the socketmgr structure applies.
+ */
+#ifndef WIN32
+struct isc_socket {
+	unsigned int		impmagic;
+	unsigned int		magic;
+	isc_socketmethods_t	*methods;
+};
+#endif
+
+#define ISCAPI_SOCKET_MAGIC	ISC_MAGIC('A','s','c','t')
+#define ISCAPI_SOCKET_VALID(s)	((s) != NULL && \
+				 (s)->magic == ISCAPI_SOCKET_MAGIC)
+
+/***
+ *** Socket and Socket Manager Functions
+ ***
+ *** Note: all Ensures conditions apply only if the result is success for
+ *** those functions which return an isc_result.
+ ***/
+
+isc_result_t
+isc_socket_fdwatchcreate(isc_socketmgr_t *manager,
+			 int fd,
+			 int flags,
+			 isc_sockfdwatch_t callback,
+			 void *cbarg,
+			 isc_task_t *task,
+			 isc_socket_t **socketp);
+/*%<
+ * Create a new file descriptor watch socket managed by 'manager'.
+ *
+ * Note:
+ *
+ *\li   'fd' is the already-opened file descriptor.
+ *\li	This function is not available on Windows.
+ *\li	The callback function is called "in-line" - this means the function
+ *	needs to return as fast as possible, as all other I/O will be suspended
+ *	until the callback completes.
+ *
+ * Requires:
+ *
+ *\li	'manager' is a valid manager
+ *
+ *\li	'socketp' is a valid pointer, and *socketp == NULL
+ *
+ *\li	'fd' be opened.
+ *
+ * Ensures:
+ *
+ *	'*socketp' is attached to the newly created fdwatch socket
+ *
+ * Returns:
+ *
+ *\li	#ISC_R_SUCCESS
+ *\li	#ISC_R_NOMEMORY
+ *\li	#ISC_R_NORESOURCES
+ *\li	#ISC_R_UNEXPECTED
+ */
+
+isc_result_t
+isc_socket_fdwatchpoke(isc_socket_t *sock,
+		       int flags);
+/*%<
+ * Poke a file descriptor watch socket informing the manager that it
+ * should restart watching the socket
+ *
+ * Note:
+ *
+ *\li   'sock' is the socket returned by isc_socket_fdwatchcreate
+ *
+ *\li   'flags' indicates what the manager should watch for on the socket
+ *      in addition to what it may already be watching.  It can be one or
+ *      both of ISC_SOCKFDWATCH_READ and ISC_SOCKFDWATCH_WRITE.  To
+ *      temporarily disable watching on a socket the value indicating
+ *      no more data should be returned from the call back routine.
+ *
+ *\li	This function is not available on Windows.
+ *
+ * Requires:
+ *
+ *\li	'sock' is a valid isc socket
+ *
+ *
+ * Returns:
+ *
+ *\li	#ISC_R_SUCCESS
+ */
+
+isc_result_t
+isc_socket_create(isc_socketmgr_t *manager,
+		  int pf,
+		  isc_sockettype_t type,
+		  isc_socket_t **socketp);
+/*%<
+ * Create a new 'type' socket managed by 'manager'.
+ *
+ * For isc_sockettype_fdwatch sockets you should use isc_socket_fdwatchcreate()
+ * rather than isc_socket_create().
+ *
+ * Note:
+ *
+ *\li	'pf' is the desired protocol family, e.g. PF_INET or PF_INET6.
+ *
+ * Requires:
+ *
+ *\li	'manager' is a valid manager
+ *
+ *\li	'socketp' is a valid pointer, and *socketp == NULL
+ *
+ *\li	'type' is not isc_sockettype_fdwatch
+ *
+ * Ensures:
+ *
+ *	'*socketp' is attached to the newly created socket
+ *
+ * Returns:
+ *
+ *\li	#ISC_R_SUCCESS
+ *\li	#ISC_R_NOMEMORY
+ *\li	#ISC_R_NORESOURCES
+ *\li	#ISC_R_UNEXPECTED
+ */
+
+void
+isc_socket_cancel(isc_socket_t *sock, isc_task_t *task,
+		  unsigned int how);
+/*%<
+ * Cancel pending I/O of the type specified by "how".
+ *
+ * Note: if "task" is NULL, then the cancel applies to all tasks using the
+ * socket.
+ *
+ * Requires:
+ *
+ * \li	"socket" is a valid socket
+ *
+ * \li	"task" is NULL or a valid task
+ *
+ * "how" is a bitmask describing the type of cancelation to perform.
+ * The type ISC_SOCKCANCEL_ALL will cancel all pending I/O on this
+ * socket.
+ *
+ * \li ISC_SOCKCANCEL_RECV:
+ *	Cancel pending isc_socket_recv() calls.
+ *
+ * \li ISC_SOCKCANCEL_SEND:
+ *	Cancel pending isc_socket_send() and isc_socket_sendto() calls.
+ *
+ * \li ISC_SOCKCANCEL_ACCEPT:
+ *	Cancel pending isc_socket_accept() calls.
+ *
+ * \li ISC_SOCKCANCEL_CONNECT:
+ *	Cancel pending isc_socket_connect() call.
+ */
+
+void
+isc_socket_shutdown(isc_socket_t *sock, unsigned int how);
+/*%<
+ * Shutdown 'socket' according to 'how'.
+ *
+ * Requires:
+ *
+ * \li	'socket' is a valid socket.
+ *
+ * \li	'task' is NULL or is a valid task.
+ *
+ * \li	If 'how' is 'ISC_SOCKSHUT_RECV' or 'ISC_SOCKSHUT_ALL' then
+ *
+ *		The read queue must be empty.
+ *
+ *		No further read requests may be made.
+ *
+ * \li	If 'how' is 'ISC_SOCKSHUT_SEND' or 'ISC_SOCKSHUT_ALL' then
+ *
+ *		The write queue must be empty.
+ *
+ *		No further write requests may be made.
+ */
+
+void
+isc_socket_attach(isc_socket_t *sock, isc_socket_t **socketp);
+/*%<
+ * Attach *socketp to socket.
+ *
+ * Requires:
+ *
+ * \li	'socket' is a valid socket.
+ *
+ * \li	'socketp' points to a NULL socket.
+ *
+ * Ensures:
+ *
+ * \li	*socketp is attached to socket.
+ */
+
+void
+isc_socket_detach(isc_socket_t **socketp);
+/*%<
+ * Detach *socketp from its socket.
+ *
+ * Requires:
+ *
+ * \li	'socketp' points to a valid socket.
+ *
+ * \li	If '*socketp' is the last reference to the socket,
+ *	then:
+ *
+ *		There must be no pending I/O requests.
+ *
+ * Ensures:
+ *
+ * \li	*socketp is NULL.
+ *
+ * \li	If '*socketp' is the last reference to the socket,
+ *	then:
+ *
+ *		The socket will be shutdown (both reading and writing)
+ *		for all tasks.
+ *
+ *		All resources used by the socket have been freed
+ */
+
+isc_result_t
+isc_socket_open(isc_socket_t *sock);
+/*%<
+ * Open a new socket file descriptor of the given socket structure.  It simply
+ * opens a new descriptor; all of the other parameters including the socket
+ * type are inherited from the existing socket.  This function is provided to
+ * avoid overhead of destroying and creating sockets when many short-lived
+ * sockets are frequently opened and closed.  When the efficiency is not an
+ * issue, it should be safer to detach the unused socket and re-create a new
+ * one.  This optimization may not be available for some systems, in which
+ * case this function will return ISC_R_NOTIMPLEMENTED and must not be used.
+ *
+ * isc_socket_open() should not be called on sockets created by
+ * isc_socket_fdwatchcreate().
+ *
+ * Requires:
+ *
+ * \li	there must be no other reference to this socket.
+ *
+ * \li	'socket' is a valid and previously closed by isc_socket_close()
+ *
+ * \li  'sock->type' is not isc_sockettype_fdwatch
+ *
+ * Returns:
+ *	Same as isc_socket_create().
+ * \li	ISC_R_NOTIMPLEMENTED
+ */
+
+isc_result_t
+isc_socket_close(isc_socket_t *sock);
+/*%<
+ * Close a socket file descriptor of the given socket structure.  This function
+ * is provided as an alternative to destroying an unused socket when overhead
+ * destroying/re-creating sockets can be significant, and is expected to be
+ * used with isc_socket_open().  This optimization may not be available for some
+ * systems, in which case this function will return ISC_R_NOTIMPLEMENTED and
+ * must not be used.
+ *
+ * isc_socket_close() should not be called on sockets created by
+ * isc_socket_fdwatchcreate().
+ *
+ * Requires:
+ *
+ * \li	The socket must have a valid descriptor.
+ *
+ * \li	There must be no other reference to this socket.
+ *
+ * \li	There must be no pending I/O requests.
+ *
+ * \li  'sock->type' is not isc_sockettype_fdwatch
+ *
+ * Returns:
+ * \li	#ISC_R_NOTIMPLEMENTED
+ */
+
+isc_result_t
+isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *addressp,
+		unsigned int options);
+/*%<
+ * Bind 'socket' to '*addressp'.
+ *
+ * Requires:
+ *
+ * \li	'socket' is a valid socket
+ *
+ * \li	'addressp' points to a valid isc_sockaddr.
+ *
+ * Returns:
+ *
+ * \li	ISC_R_SUCCESS
+ * \li	ISC_R_NOPERM
+ * \li	ISC_R_ADDRNOTAVAIL
+ * \li	ISC_R_ADDRINUSE
+ * \li	ISC_R_BOUND
+ * \li	ISC_R_UNEXPECTED
+ */
+
+isc_result_t
+isc_socket_filter(isc_socket_t *sock, const char *filter);
+/*%<
+ * Inform the kernel that it should perform accept filtering.
+ * If filter is NULL the current filter will be removed.:w
+ */
+
+isc_result_t
+isc_socket_listen(isc_socket_t *sock, unsigned int backlog);
+/*%<
+ * Set listen mode on the socket.  After this call, the only function that
+ * can be used (other than attach and detach) is isc_socket_accept().
+ *
+ * Notes:
+ *
+ * \li	'backlog' is as in the UNIX system call listen() and may be
+ *	ignored by non-UNIX implementations.
+ *
+ * \li	If 'backlog' is zero, a reasonable system default is used, usually
+ *	SOMAXCONN.
+ *
+ * Requires:
+ *
+ * \li	'socket' is a valid, bound TCP socket or a valid, bound UNIX socket.
+ *
+ * Returns:
+ *
+ * \li	ISC_R_SUCCESS
+ * \li	ISC_R_UNEXPECTED
+ */
+
+isc_result_t
+isc_socket_accept(isc_socket_t *sock,
+		  isc_task_t *task, isc_taskaction_t action, const void *arg);
+/*%<
+ * Queue accept event.  When a new connection is received, the task will
+ * get an ISC_SOCKEVENT_NEWCONN event with the sender set to the listen
+ * socket.  The new socket structure is sent inside the isc_socket_newconnev_t
+ * event type, and is attached to the task 'task'.
+ *
+ * REQUIRES:
+ * \li	'socket' is a valid TCP socket that isc_socket_listen() was called
+ *	on.
+ *
+ * \li	'task' is a valid task
+ *
+ * \li	'action' is a valid action
+ *
+ * RETURNS:
+ * \li	ISC_R_SUCCESS
+ * \li	ISC_R_NOMEMORY
+ * \li	ISC_R_UNEXPECTED
+ */
+
+isc_result_t
+isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addressp,
+		   isc_task_t *task, isc_taskaction_t action,
+		   const void *arg);
+/*%<
+ * Connect 'socket' to peer with address *saddr.  When the connection
+ * succeeds, or when an error occurs, a CONNECT event with action 'action'
+ * and arg 'arg' will be posted to the event queue for 'task'.
+ *
+ * Requires:
+ *
+ * \li	'socket' is a valid TCP socket
+ *
+ * \li	'addressp' points to a valid isc_sockaddr
+ *
+ * \li	'task' is a valid task
+ *
+ * \li	'action' is a valid action
+ *
+ * Returns:
+ *
+ * \li	ISC_R_SUCCESS
+ * \li	ISC_R_NOMEMORY
+ * \li	ISC_R_UNEXPECTED
+ *
+ * Posted event's result code:
+ *
+ * \li	ISC_R_SUCCESS
+ * \li	ISC_R_TIMEDOUT
+ * \li	ISC_R_CONNREFUSED
+ * \li	ISC_R_NETUNREACH
+ * \li	ISC_R_UNEXPECTED
+ */
+
+isc_result_t
+isc_socket_getpeername(isc_socket_t *sock, isc_sockaddr_t *addressp);
+/*%<
+ * Get the name of the peer connected to 'socket'.
+ *
+ * Requires:
+ *
+ * \li	'socket' is a valid TCP socket.
+ *
+ * Returns:
+ *
+ * \li	ISC_R_SUCCESS
+ * \li	ISC_R_TOOSMALL
+ * \li	ISC_R_UNEXPECTED
+ */
+
+isc_result_t
+isc_socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp);
+/*%<
+ * Get the name of 'socket'.
+ *
+ * Requires:
+ *
+ * \li	'socket' is a valid socket.
+ *
+ * Returns:
+ *
+ * \li	ISC_R_SUCCESS
+ * \li	ISC_R_TOOSMALL
+ * \li	ISC_R_UNEXPECTED
+ */
+
+/*@{*/
+isc_result_t
+isc_socket_recv(isc_socket_t *sock, isc_region_t *region,
+		unsigned int minimum,
+		isc_task_t *task, isc_taskaction_t action, const void *arg);
+isc_result_t
+isc_socket_recvv(isc_socket_t *sock, isc_bufferlist_t *buflist,
+		 unsigned int minimum,
+		 isc_task_t *task, isc_taskaction_t action, const void *arg);
+
+isc_result_t
+isc_socket_recv2(isc_socket_t *sock, isc_region_t *region,
+		 unsigned int minimum, isc_task_t *task,
+		 isc_socketevent_t *event, unsigned int flags);
+
+/*!
+ * Receive from 'socket', storing the results in region.
+ *
+ * Notes:
+ *
+ *\li	Let 'length' refer to the length of 'region' or to the sum of all
+ *	available regions in the list of buffers '*buflist'.
+ *
+ *\li	If 'minimum' is non-zero and at least that many bytes are read,
+ *	the completion event will be posted to the task 'task.'  If minimum
+ *	is zero, the exact number of bytes requested in the region must
+ * 	be read for an event to be posted.  This only makes sense for TCP
+ *	connections, and is always set to 1 byte for UDP.
+ *
+ *\li	The read will complete when the desired number of bytes have been
+ *	read, if end-of-input occurs, or if an error occurs.  A read done
+ *	event with the given 'action' and 'arg' will be posted to the
+ *	event queue of 'task'.
+ *
+ *\li	The caller may not modify 'region', the buffers which are passed
+ *	into this function, or any data they refer to until the completion
+ *	event is received.
+ *
+ *\li	For isc_socket_recvv():
+ *	On successful completion, '*buflist' will be empty, and the list of
+ *	all buffers will be returned in the done event's 'bufferlist'
+ *	member.  On error return, '*buflist' will be unchanged.
+ *
+ *\li	For isc_socket_recv2():
+ *	'event' is not NULL, and the non-socket specific fields are
+ *	expected to be initialized.
+ *
+ *\li	For isc_socket_recv2():
+ *	The only defined value for 'flags' is ISC_SOCKFLAG_IMMEDIATE.  If
+ *	set and the operation completes, the return value will be
+ *	ISC_R_SUCCESS and the event will be filled in and not sent.  If the
+ *	operation does not complete, the return value will be
+ *	ISC_R_INPROGRESS and the event will be sent when the operation
+ *	completes.
+ *
+ * Requires:
+ *
+ *\li	'socket' is a valid, bound socket.
+ *
+ *\li	For isc_socket_recv():
+ *	'region' is a valid region
+ *
+ *\li	For isc_socket_recvv():
+ *	'buflist' is non-NULL, and '*buflist' contain at least one buffer.
+ *
+ *\li	'task' is a valid task
+ *
+ *\li	For isc_socket_recv() and isc_socket_recvv():
+ *	action != NULL and is a valid action
+ *
+ *\li	For isc_socket_recv2():
+ *	event != NULL
+ *
+ * Returns:
+ *
+ *\li	#ISC_R_SUCCESS
+ *\li	#ISC_R_INPROGRESS
+ *\li	#ISC_R_NOMEMORY
+ *\li	#ISC_R_UNEXPECTED
+ *
+ * Event results:
+ *
+ *\li	#ISC_R_SUCCESS
+ *\li	#ISC_R_UNEXPECTED
+ *\li	XXX needs other net-type errors
+ */
+/*@}*/
+
+/*@{*/
+isc_result_t
+isc_socket_send(isc_socket_t *sock, isc_region_t *region,
+		isc_task_t *task, isc_taskaction_t action, const void *arg);
+isc_result_t
+isc_socket_sendto(isc_socket_t *sock, isc_region_t *region,
+		  isc_task_t *task, isc_taskaction_t action, const void *arg,
+		  isc_sockaddr_t *address, struct in6_pktinfo *pktinfo);
+isc_result_t
+isc_socket_sendv(isc_socket_t *sock, isc_bufferlist_t *buflist,
+		 isc_task_t *task, isc_taskaction_t action, const void *arg);
+isc_result_t
+isc_socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist,
+		   isc_task_t *task, isc_taskaction_t action, const void *arg,
+		   isc_sockaddr_t *address, struct in6_pktinfo *pktinfo);
+isc_result_t
+isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region,
+		   isc_task_t *task,
+		   isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
+		   isc_socketevent_t *event, unsigned int flags);
+
+/*!
+ * Send the contents of 'region' to the socket's peer.
+ *
+ * Notes:
+ *
+ *\li	Shutting down the requestor's task *may* result in any
+ *	still pending writes being dropped or completed, depending on the
+ *	underlying OS implementation.
+ *
+ *\li	If 'action' is NULL, then no completion event will be posted.
+ *
+ *\li	The caller may not modify 'region', the buffers which are passed
+ *	into this function, or any data they refer to until the completion
+ *	event is received.
+ *
+ *\li	For isc_socket_sendv() and isc_socket_sendtov():
+ *	On successful completion, '*buflist' will be empty, and the list of
+ *	all buffers will be returned in the done event's 'bufferlist'
+ *	member.  On error return, '*buflist' will be unchanged.
+ *
+ *\li	For isc_socket_sendto2():
+ *	'event' is not NULL, and the non-socket specific fields are
+ *	expected to be initialized.
+ *
+ *\li	For isc_socket_sendto2():
+ *	The only defined values for 'flags' are ISC_SOCKFLAG_IMMEDIATE
+ *	and ISC_SOCKFLAG_NORETRY.
+ *
+ *\li	If ISC_SOCKFLAG_IMMEDIATE is set and the operation completes, the
+ *	return value will be ISC_R_SUCCESS and the event will be filled
+ *	in and not sent.  If the operation does not complete, the return
+ *	value will be ISC_R_INPROGRESS and the event will be sent when
+ *	the operation completes.
+ *
+ *\li	ISC_SOCKFLAG_NORETRY can only be set for UDP sockets.  If set
+ *	and the send operation fails due to a transient error, the send
+ *	will not be retried and the error will be indicated in the event.
+ *	Using this option along with ISC_SOCKFLAG_IMMEDIATE allows the caller
+ *	to specify a region that is allocated on the stack.
+ *
+ * Requires:
+ *
+ *\li	'socket' is a valid, bound socket.
+ *
+ *\li	For isc_socket_send():
+ *	'region' is a valid region
+ *
+ *\li	For isc_socket_sendv() and isc_socket_sendtov():
+ *	'buflist' is non-NULL, and '*buflist' contain at least one buffer.
+ *
+ *\li	'task' is a valid task
+ *
+ *\li	For isc_socket_sendv(), isc_socket_sendtov(), isc_socket_send(), and
+ *	isc_socket_sendto():
+ *	action == NULL or is a valid action
+ *
+ *\li	For isc_socket_sendto2():
+ *	event != NULL
+ *
+ * Returns:
+ *
+ *\li	#ISC_R_SUCCESS
+ *\li	#ISC_R_INPROGRESS
+ *\li	#ISC_R_NOMEMORY
+ *\li	#ISC_R_UNEXPECTED
+ *
+ * Event results:
+ *
+ *\li	#ISC_R_SUCCESS
+ *\li	#ISC_R_UNEXPECTED
+ *\li	XXX needs other net-type errors
+ */
+/*@}*/
+
+isc_result_t
+isc_socketmgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx,
+			  isc_socketmgr_t **managerp);
+
+isc_result_t
+isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp);
+
+isc_result_t
+isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
+		      unsigned int maxsocks);
+/*%<
+ * Create a socket manager.  If "maxsocks" is non-zero, it specifies the
+ * maximum number of sockets that the created manager should handle.
+ * isc_socketmgr_create() is equivalent of isc_socketmgr_create2() with
+ * "maxsocks" being zero.
+ * isc_socketmgr_createinctx() also associates the new manager with the
+ * specified application context.
+ *
+ * Notes:
+ *
+ *\li	All memory will be allocated in memory context 'mctx'.
+ *
+ * Requires:
+ *
+ *\li	'mctx' is a valid memory context.
+ *
+ *\li	'managerp' points to a NULL isc_socketmgr_t.
+ *
+ *\li	'actx' is a valid application context (for createinctx()).
+ *
+ * Ensures:
+ *
+ *\li	'*managerp' is a valid isc_socketmgr_t.
+ *
+ * Returns:
+ *
+ *\li	#ISC_R_SUCCESS
+ *\li	#ISC_R_NOMEMORY
+ *\li	#ISC_R_UNEXPECTED
+ *\li	#ISC_R_NOTIMPLEMENTED
+ */
+
+isc_result_t
+isc_socketmgr_getmaxsockets(isc_socketmgr_t *manager, unsigned int *nsockp);
+/*%<
+ * Returns in "*nsockp" the maximum number of sockets this manager may open.
+ *
+ * Requires:
+ *
+ *\li	'*manager' is a valid isc_socketmgr_t.
+ *\li	'nsockp' is not NULL.
+ *
+ * Returns:
+ *
+ *\li	#ISC_R_SUCCESS
+ *\li	#ISC_R_NOTIMPLEMENTED
+ */
+
+void
+isc_socketmgr_setstats(isc_socketmgr_t *manager, isc_stats_t *stats);
+/*%<
+ * Set a general socket statistics counter set 'stats' for 'manager'.
+ *
+ * Requires:
+ * \li	'manager' is valid, hasn't opened any socket, and doesn't have
+ *	stats already set.
+ *
+ *\li	stats is a valid statistics supporting socket statistics counters
+ *	(see above).
+ */
+
+void
+isc_socketmgr_destroy(isc_socketmgr_t **managerp);
+/*%<
+ * Destroy a socket manager.
+ *
+ * Notes:
+ *
+ *\li	This routine blocks until there are no sockets left in the manager,
+ *	so if the caller holds any socket references using the manager, it
+ *	must detach them before calling isc_socketmgr_destroy() or it will
+ *	block forever.
+ *
+ * Requires:
+ *
+ *\li	'*managerp' is a valid isc_socketmgr_t.
+ *
+ *\li	All sockets managed by this manager are fully detached.
+ *
+ * Ensures:
+ *
+ *\li	*managerp == NULL
+ *
+ *\li	All resources used by the manager have been freed.
+ */
+
+isc_sockettype_t
+isc_socket_gettype(isc_socket_t *sock);
+/*%<
+ * Returns the socket type for "sock."
+ *
+ * Requires:
+ *
+ *\li	"sock" is a valid socket.
+ */
+
+/*@{*/
+isc_boolean_t
+isc_socket_isbound(isc_socket_t *sock);
+
+void
+isc_socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes);
+/*%<
+ * If the socket is an IPv6 socket set/clear the IPV6_IPV6ONLY socket
+ * option if the host OS supports this option.
+ *
+ * Requires:
+ *\li	'sock' is a valid socket.
+ */
+/*@}*/
+
+void
+isc_socket_cleanunix(isc_sockaddr_t *addr, isc_boolean_t active);
+
+/*%<
+ * Cleanup UNIX domain sockets in the file-system.  If 'active' is true
+ * then just unlink the socket.  If 'active' is false try to determine
+ * if there is a listener of the socket or not.  If no listener is found
+ * then unlink socket.
+ *
+ * Prior to unlinking the path is tested to see if it a socket.
+ *
+ * Note: there are a number of race conditions which cannot be avoided
+ *       both in the filesystem and any application using UNIX domain
+ *	 sockets (e.g. socket is tested between bind() and listen(),
+ *	 the socket is deleted and replaced in the file-system between
+ *	 stat() and unlink()).
+ */
+
+isc_result_t
+isc_socket_permunix(isc_sockaddr_t *sockaddr, isc_uint32_t perm,
+		    isc_uint32_t owner, isc_uint32_t group);
+/*%<
+ * Set ownership and file permissions on the UNIX domain socket.
+ *
+ * Note: On Solaris and SunOS this secures the directory containing
+ *       the socket as Solaris and SunOS do not honour the filesystem
+ *	 permissions on the socket.
+ *
+ * Requires:
+ * \li	'sockaddr' to be a valid UNIX domain sockaddr.
+ *
+ * Returns:
+ * \li	#ISC_R_SUCCESS
+ * \li	#ISC_R_FAILURE
+ */
+
+void isc_socket_setname(isc_socket_t *socket, const char *name, void *tag);
+/*%<
+ * Set the name and optional tag for a socket.  This allows tracking of the
+ * owner or purpose for this socket, and is useful for tracing and statistics
+ * reporting.
+ */
+
+const char *isc_socket_getname(isc_socket_t *socket);
+/*%<
+ * Get the name associated with a socket, if any.
+ */
+
+void *isc_socket_gettag(isc_socket_t *socket);
+/*%<
+ * Get the tag associated with a socket, if any.
+ */
+
+void
+isc__socketmgr_setreserved(isc_socketmgr_t *mgr, isc_uint32_t);
+/*%<
+ * Temporary.  For use by named only.
+ */
+
+void
+isc__socketmgr_maxudp(isc_socketmgr_t *mgr, int maxudp);
+/*%<
+ * Test interface. Drop UDP packet > 'maxudp'.
+ */
+
+#ifdef HAVE_LIBXML2
+
+void
+isc_socketmgr_renderxml(isc_socketmgr_t *mgr, xmlTextWriterPtr writer);
+/*%<
+ * Render internal statistics and other state into the XML document.
+ */
+
+#endif /* HAVE_LIBXML2 */
+
+#ifdef USE_SOCKETIMPREGISTER
+/*%<
+ * See isc_socketmgr_create() above.
+ */
+typedef isc_result_t
+(*isc_socketmgrcreatefunc_t)(isc_mem_t *mctx, isc_socketmgr_t **managerp);
+
+isc_result_t
+isc_socket_register(isc_socketmgrcreatefunc_t createfunc);
+/*%<
+ * Register a new socket I/O implementation and add it to the list of
+ * supported implementations.  This function must be called when a different
+ * event library is used than the one contained in the ISC library.
+ */
+
+isc_result_t
+isc__socket_register(void);
+/*%<
+ * A short cut function that specifies the socket I/O module in the ISC
+ * library for isc_socket_register().  An application that uses the ISC library
+ * usually do not have to care about this function: it would call
+ * isc_lib_register(), which internally calls this function.
+ */
+#endif /* USE_SOCKETIMPREGISTER */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_SOCKET_H */
diff --git a/src/lib/bind9/include/isc/stats.h b/src/lib/bind9/include/isc/stats.h
new file mode 100644
index 0000000..226bc08
--- /dev/null
+++ b/src/lib/bind9/include/isc/stats.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2009  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: stats.h,v 1.4 2009-01-29 01:03:56 jinmei Exp $ */
+
+#ifndef ISC_STATS_H
+#define ISC_STATS_H 1
+
+/*! \file isc/stats.h */
+
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/*%<
+ * Flag(s) for isc_stats_dump().
+ */
+#define ISC_STATSDUMP_VERBOSE	0x00000001 /*%< dump 0-value counters */
+
+/*%<
+ * Dump callback type.
+ */
+typedef void (*isc_stats_dumper_t)(isc_statscounter_t, isc_uint64_t, void *);
+
+isc_result_t
+isc_stats_create(isc_mem_t *mctx, isc_stats_t **statsp, int ncounters);
+/*%<
+ * Create a statistics counter structure of general type.  It counts a general
+ * set of counters indexed by an ID between 0 and ncounters -1.
+ *
+ * Requires:
+ *\li	'mctx' must be a valid memory context.
+ *
+ *\li	'statsp' != NULL && '*statsp' == NULL.
+ *
+ * Returns:
+ *\li	ISC_R_SUCCESS	-- all ok
+ *
+ *\li	anything else	-- failure
+ */
+
+void
+isc_stats_attach(isc_stats_t *stats, isc_stats_t **statsp);
+/*%<
+ * Attach to a statistics set.
+ *
+ * Requires:
+ *\li	'stats' is a valid isc_stats_t.
+ *
+ *\li	'statsp' != NULL && '*statsp' == NULL
+ */
+
+void
+isc_stats_detach(isc_stats_t **statsp);
+/*%<
+ * Detaches from the statistics set.
+ *
+ * Requires:
+ *\li	'statsp' != NULL and '*statsp' is a valid isc_stats_t.
+ */
+
+int
+isc_stats_ncounters(isc_stats_t *stats);
+/*%<
+ * Returns the number of counters contained in stats.
+ *
+ * Requires:
+ *\li	'stats' is a valid isc_stats_t.
+ *
+ */
+
+void
+isc_stats_increment(isc_stats_t *stats, isc_statscounter_t counter);
+/*%<
+ * Increment the counter-th counter of stats.
+ *
+ * Requires:
+ *\li	'stats' is a valid isc_stats_t.
+ *
+ *\li	counter is less than the maximum available ID for the stats specified
+ *	on creation.
+ */
+
+void
+isc_stats_decrement(isc_stats_t *stats, isc_statscounter_t counter);
+/*%<
+ * Decrement the counter-th counter of stats.
+ *
+ * Requires:
+ *\li	'stats' is a valid isc_stats_t.
+ */
+
+void
+isc_stats_dump(isc_stats_t *stats, isc_stats_dumper_t dump_fn, void *arg,
+	       unsigned int options);
+/*%<
+ * Dump the current statistics counters in a specified way.  For each counter
+ * in stats, dump_fn is called with its current value and the given argument
+ * arg.  By default counters that have a value of 0 is skipped; if options has
+ * the ISC_STATSDUMP_VERBOSE flag, even such counters are dumped.
+ *
+ * Requires:
+ *\li	'stats' is a valid isc_stats_t.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_STATS_H */
diff --git a/src/lib/bind9/include/isc/stdio.h b/src/lib/bind9/include/isc/stdio.h
new file mode 100644
index 0000000..6a1de5d
--- /dev/null
+++ b/src/lib/bind9/include/isc/stdio.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: stdio.h,v 1.13 2007-06-19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_STDIO_H
+#define ISC_STDIO_H 1
+
+/*! \file isc/stdio.h */
+
+/*% 
+ * These functions are wrappers around the corresponding stdio functions.
+ *
+ * They return a detailed error code in the form of an an isc_result_t.  ANSI C
+ * does not guarantee that stdio functions set errno, hence these functions
+ * must use platform dependent methods (e.g., the POSIX errno) to construct the
+ * error code.
+ */
+
+#include <stdio.h>
+
+#include <isc/lang.h>
+#include <isc/result.h>
+
+ISC_LANG_BEGINDECLS
+
+/*% Open */
+isc_result_t
+isc_stdio_open(const char *filename, const char *mode, FILE **fp);
+
+/*% Close */
+isc_result_t
+isc_stdio_close(FILE *f);
+
+/*% Seek */
+isc_result_t
+isc_stdio_seek(FILE *f, long offset, int whence);
+
+/*% Read */
+isc_result_t
+isc_stdio_read(void *ptr, size_t size, size_t nmemb, FILE *f,
+	       size_t *nret);
+
+/*% Write */
+isc_result_t
+isc_stdio_write(const void *ptr, size_t size, size_t nmemb, FILE *f,
+		size_t *nret);
+
+/*% Flush */
+isc_result_t
+isc_stdio_flush(FILE *f);
+
+isc_result_t
+isc_stdio_sync(FILE *f);
+/*%<
+ * Invoke fsync() on the file descriptor underlying an stdio stream, or an
+ * equivalent system-dependent operation.  Note that this function has no
+ * direct counterpart in the stdio library.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_STDIO_H */
diff --git a/src/lib/bind9/include/isc/stdlib.h b/src/lib/bind9/include/isc/stdlib.h
new file mode 100644
index 0000000..3198d48
--- /dev/null
+++ b/src/lib/bind9/include/isc/stdlib.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: stdlib.h,v 1.8 2007-06-19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_STDLIB_H
+#define ISC_STDLIB_H 1
+
+/*! \file isc/stdlib.h */
+
+#include <stdlib.h>
+
+#include <isc/lang.h>
+#include <isc/platform.h>
+
+#ifdef ISC_PLATFORM_NEEDSTRTOUL
+#define strtoul isc_strtoul
+#endif
+
+ISC_LANG_BEGINDECLS
+
+unsigned long isc_strtoul(const char *, char **, int);
+
+ISC_LANG_ENDDECLS
+
+#endif
diff --git a/src/lib/bind9/include/isc/string.h b/src/lib/bind9/include/isc/string.h
new file mode 100644
index 0000000..e8c6834
--- /dev/null
+++ b/src/lib/bind9/include/isc/string.h
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001, 2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: string.h,v 1.23 2007-09-13 04:48:16 each Exp $ */
+
+#ifndef ISC_STRING_H
+#define ISC_STRING_H 1
+
+/*! \file isc/string.h */
+
+#include <isc/formatcheck.h>
+#include <isc/int.h>
+#include <isc/lang.h>
+#include <isc/platform.h>
+#include <isc/types.h>
+
+#include <string.h>
+
+#ifdef ISC_PLATFORM_HAVESTRINGSH
+#include <strings.h>
+#endif
+
+#define ISC_STRING_MAGIC 0x5e
+
+ISC_LANG_BEGINDECLS
+
+isc_uint64_t
+isc_string_touint64(char *source, char **endp, int base);
+/*%<
+ * Convert the string pointed to by 'source' to isc_uint64_t.
+ *
+ * On successful conversion 'endp' points to the first character
+ * after conversion is complete.
+ *
+ * 'base': 0 or 2..36
+ *
+ * If base is 0 the base is computed from the string type.
+ *
+ * On error 'endp' points to 'source'.
+ */
+
+isc_result_t
+isc_string_copy(char *target, size_t size, const char *source);
+/*
+ * Copy the string pointed to by 'source' to 'target' which is a
+ * pointer to a string of at least 'size' bytes.
+ *
+ * Requires:
+ *	'target' is a pointer to a char[] of at least 'size' bytes.
+ *	'size' an integer > 0.
+ *	'source' == NULL or points to a NUL terminated string.
+ *
+ * Ensures:
+ *	If result == ISC_R_SUCCESS
+ *		'target' will be a NUL terminated string of no more
+ *		than 'size' bytes (including NUL).
+ *
+ *	If result == ISC_R_NOSPACE
+ *		'target' is undefined.
+ *
+ * Returns:
+ *	ISC_R_SUCCESS  -- 'source' was successfully copied to 'target'.
+ *	ISC_R_NOSPACE  -- 'source' could not be copied since 'target'
+ *	                  is too small.
+ */
+
+void
+isc_string_copy_truncate(char *target, size_t size, const char *source);
+/*
+ * Copy the string pointed to by 'source' to 'target' which is a
+ * pointer to a string of at least 'size' bytes.
+ *
+ * Requires:
+ *	'target' is a pointer to a char[] of at least 'size' bytes.
+ *	'size' an integer > 0.
+ *	'source' == NULL or points to a NUL terminated string.
+ *
+ * Ensures:
+ *	'target' will be a NUL terminated string of no more
+ *	than 'size' bytes (including NUL).
+ */
+
+isc_result_t
+isc_string_append(char *target, size_t size, const char *source);
+/*
+ * Append the string pointed to by 'source' to 'target' which is a
+ * pointer to a NUL terminated string of at least 'size' bytes.
+ *
+ * Requires:
+ *	'target' is a pointer to a NUL terminated char[] of at
+ *	least 'size' bytes.
+ *	'size' an integer > 0.
+ *	'source' == NULL or points to a NUL terminated string.
+ *
+ * Ensures:
+ *	If result == ISC_R_SUCCESS
+ *		'target' will be a NUL terminated string of no more
+ *		than 'size' bytes (including NUL).
+ *
+ *	If result == ISC_R_NOSPACE
+ *		'target' is undefined.
+ *
+ * Returns:
+ *	ISC_R_SUCCESS  -- 'source' was successfully appended to 'target'.
+ *	ISC_R_NOSPACE  -- 'source' could not be appended since 'target'
+ *	                  is too small.
+ */
+
+void
+isc_string_append_truncate(char *target, size_t size, const char *source);
+/*
+ * Append the string pointed to by 'source' to 'target' which is a
+ * pointer to a NUL terminated string of at least 'size' bytes.
+ *
+ * Requires:
+ *	'target' is a pointer to a NUL terminated char[] of at
+ *	least 'size' bytes.
+ *	'size' an integer > 0.
+ *	'source' == NULL or points to a NUL terminated string.
+ *
+ * Ensures:
+ *	'target' will be a NUL terminated string of no more
+ *	than 'size' bytes (including NUL).
+ */
+
+isc_result_t
+isc_string_printf(char *target, size_t size, const char *format, ...)
+	ISC_FORMAT_PRINTF(3, 4);
+/*
+ * Print 'format' to 'target' which is a pointer to a string of at least
+ * 'size' bytes.
+ *
+ * Requires:
+ *	'target' is a pointer to a char[] of at least 'size' bytes.
+ *	'size' an integer > 0.
+ *	'format' == NULL or points to a NUL terminated string.
+ *
+ * Ensures:
+ *	If result == ISC_R_SUCCESS
+ *		'target' will be a NUL terminated string of no more
+ *		than 'size' bytes (including NUL).
+ *
+ *	If result == ISC_R_NOSPACE
+ *		'target' is undefined.
+ *
+ * Returns:
+ *	ISC_R_SUCCESS  -- 'format' was successfully printed to 'target'.
+ *	ISC_R_NOSPACE  -- 'format' could not be printed to 'target' since it
+ *	                  is too small.
+ */
+
+void
+isc_string_printf_truncate(char *target, size_t size, const char *format, ...)
+	ISC_FORMAT_PRINTF(3, 4);
+/*
+ * Print 'format' to 'target' which is a pointer to a string of at least
+ * 'size' bytes.
+ *
+ * Requires:
+ *	'target' is a pointer to a char[] of at least 'size' bytes.
+ *	'size' an integer > 0.
+ *	'format' == NULL or points to a NUL terminated string.
+ *
+ * Ensures:
+ *	'target' will be a NUL terminated string of no more
+ *	than 'size' bytes (including NUL).
+ */
+
+
+char *
+isc_string_regiondup(isc_mem_t *mctx, const isc_region_t *source);
+/*
+ * Copy the region pointed to by r to a NUL terminated string
+ * allocated from the memory context pointed to by mctx.
+ *
+ * The result should be deallocated using isc_mem_free()
+ *
+ * Requires:
+ *	'mctx' is a point to a valid memory context.
+ *	'source' is a pointer to a valid region.
+ *
+ * Returns:
+ *	a pointer to a NUL terminated string or
+ *	NULL if memory for the copy could not be allocated
+ *
+ */
+
+char *
+isc_string_separate(char **stringp, const char *delim);
+
+#ifdef ISC_PLATFORM_NEEDSTRSEP
+#define strsep isc_string_separate
+#endif
+
+#ifdef ISC_PLATFORM_NEEDMEMMOVE
+#define memmove(a,b,c) bcopy(b,a,c)
+#endif
+
+size_t
+isc_string_strlcpy(char *dst, const char *src, size_t size);
+
+
+#ifdef ISC_PLATFORM_NEEDSTRLCPY
+#define strlcpy isc_string_strlcpy
+#endif
+
+
+size_t
+isc_string_strlcat(char *dst, const char *src, size_t size);
+
+#ifdef ISC_PLATFORM_NEEDSTRLCAT
+#define strlcat isc_string_strlcat
+#endif
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_STRING_H */
diff --git a/src/lib/bind9/include/isc/symtab.h b/src/lib/bind9/include/isc/symtab.h
new file mode 100644
index 0000000..c61d0ea
--- /dev/null
+++ b/src/lib/bind9/include/isc/symtab.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1996-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: symtab.h,v 1.26 2009-01-18 23:48:14 tbox Exp $ */
+
+#ifndef ISC_SYMTAB_H
+#define ISC_SYMTAB_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file isc/symtab.h
+ * \brief Provides a simple memory-based symbol table.
+ *
+ * Keys are C strings, and key comparisons are case-insensitive.  A type may
+ * be specified when looking up, defining, or undefining.  A type value of
+ * 0 means "match any type"; any other value will only match the given
+ * type.
+ *
+ * It's possible that a client will attempt to define a <key, type, value>
+ * tuple when a tuple with the given key and type already exists in the table.
+ * What to do in this case is specified by the client.  Possible policies are:
+ *
+ *\li	#isc_symexists_reject	Disallow the define, returning #ISC_R_EXISTS
+ *\li	#isc_symexists_replace	Replace the old value with the new.  The
+ *				undefine action (if provided) will be called
+ *				with the old <key, type, value> tuple.
+ *\li	#isc_symexists_add	Add the new tuple, leaving the old tuple in
+ *				the table.  Subsequent lookups will retrieve
+ *				the most-recently-defined tuple.
+ *
+ * A lookup of a key using type 0 will return the most-recently defined
+ * symbol with that key.  An undefine of a key using type 0 will undefine the
+ * most-recently defined symbol with that key.  Trying to define a key with
+ * type 0 is illegal.
+ *
+ * The symbol table library does not make a copy the key field, so the
+ * caller must ensure that any key it passes to isc_symtab_define() will not
+ * change until it calls isc_symtab_undefine() or isc_symtab_destroy().
+ *
+ * A user-specified action will be called (if provided) when a symbol is
+ * undefined.  It can be used to free memory associated with keys and/or
+ * values.
+ *
+ * \li MP:
+ *	The callers of this module must ensure any required synchronization.
+ *
+ * \li Reliability:
+ *	No anticipated impact.
+ *
+ * \li Resources:
+ *	TBS
+ *
+ * \li Security:
+ *	No anticipated impact.
+ *
+ * \li Standards:
+ *	None.
+ */
+
+/***
+ *** Imports.
+ ***/
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+/*
+ *** Symbol Tables.
+ ***/
+/*% Symbol table value. */
+typedef union isc_symvalue {
+	void *				as_pointer;
+	const void *			as_cpointer;
+	int				as_integer;
+	unsigned int			as_uinteger;
+} isc_symvalue_t;
+
+typedef void (*isc_symtabaction_t)(char *key, unsigned int type,
+				   isc_symvalue_t value, void *userarg);
+/*% Symbol table exists. */
+typedef enum {
+	isc_symexists_reject = 0,	/*%< Disallow the define */
+	isc_symexists_replace = 1,	/*%< Replace the old value with the new */
+	isc_symexists_add = 2		/*%< Add the new tuple */
+} isc_symexists_t;
+
+ISC_LANG_BEGINDECLS
+
+/*% Create a symbol table. */
+isc_result_t
+isc_symtab_create(isc_mem_t *mctx, unsigned int size,
+		  isc_symtabaction_t undefine_action, void *undefine_arg,
+		  isc_boolean_t case_sensitive, isc_symtab_t **symtabp);
+
+/*% Destroy a symbol table. */
+void
+isc_symtab_destroy(isc_symtab_t **symtabp);
+
+/*% Lookup a symbol table. */
+isc_result_t
+isc_symtab_lookup(isc_symtab_t *symtab, const char *key, unsigned int type,
+		  isc_symvalue_t *value);
+
+/*% Define a symbol table. */
+isc_result_t
+isc_symtab_define(isc_symtab_t *symtab, const char *key, unsigned int type,
+		  isc_symvalue_t value, isc_symexists_t exists_policy);
+
+/*% Undefine a symbol table. */
+isc_result_t
+isc_symtab_undefine(isc_symtab_t *symtab, const char *key, unsigned int type);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_SYMTAB_H */
diff --git a/src/lib/bind9/include/isc/task.h b/src/lib/bind9/include/isc/task.h
new file mode 100644
index 0000000..b3cdbb6
--- /dev/null
+++ b/src/lib/bind9/include/isc/task.h
@@ -0,0 +1,734 @@
+/*
+ * Copyright (C) 2004-2007, 2009-2011  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2001, 2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: task.h,v 1.69.14.2 2011-02-28 01:20:04 tbox Exp $ */
+
+#ifndef ISC_TASK_H
+#define ISC_TASK_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file isc/task.h
+ * \brief The task system provides a lightweight execution context, which is
+ * basically an event queue.
+
+ * When a task's event queue is non-empty, the
+ * task is runnable.  A small work crew of threads, typically one per CPU,
+ * execute runnable tasks by dispatching the events on the tasks' event
+ * queues.  Context switching between tasks is fast.
+ *
+ * \li MP:
+ *	The module ensures appropriate synchronization of data structures it
+ *	creates and manipulates.
+ *	The caller must ensure that isc_taskmgr_destroy() is called only
+ *	once for a given manager.
+ *
+ * \li Reliability:
+ *	No anticipated impact.
+ *
+ * \li Resources:
+ *	TBS
+ *
+ * \li Security:
+ *	No anticipated impact.
+ *
+ * \li Standards:
+ *	None.
+ *
+ * \section purge Purging and Unsending
+ *
+ * Events which have been queued for a task but not delivered may be removed
+ * from the task's event queue by purging or unsending.
+ *
+ * With both types, the caller specifies a matching pattern that selects
+ * events based upon their sender, type, and tag.
+ *
+ * Purging calls isc_event_free() on the matching events.
+ *
+ * Unsending returns a list of events that matched the pattern.
+ * The caller is then responsible for them.
+ *
+ * Consumers of events should purge, not unsend.
+ *
+ * Producers of events often want to remove events when the caller indicates
+ * it is no longer interested in the object, e.g. by canceling a timer.
+ * Sometimes this can be done by purging, but for some event types, the
+ * calls to isc_event_free() cause deadlock because the event free routine
+ * wants to acquire a lock the caller is already holding.  Unsending instead
+ * of purging solves this problem.  As a general rule, producers should only
+ * unsend events which they have sent.
+ */
+
+
+/***
+ *** Imports.
+ ***/
+
+#include <isc/eventclass.h>
+#include <isc/lang.h>
+#include <isc/stdtime.h>
+#include <isc/types.h>
+#include <isc/xml.h>
+
+#define ISC_TASKEVENT_FIRSTEVENT	(ISC_EVENTCLASS_TASK + 0)
+#define ISC_TASKEVENT_SHUTDOWN		(ISC_EVENTCLASS_TASK + 1)
+#define ISC_TASKEVENT_LASTEVENT		(ISC_EVENTCLASS_TASK + 65535)
+
+/*****
+ ***** Tasks.
+ *****/
+
+ISC_LANG_BEGINDECLS
+
+/***
+ *** Types
+ ***/
+
+/*% Task and task manager methods */
+typedef struct isc_taskmgrmethods {
+	void		(*destroy)(isc_taskmgr_t **managerp);
+	isc_result_t	(*taskcreate)(isc_taskmgr_t *manager,
+				      unsigned int quantum,
+				      isc_task_t **taskp);
+} isc_taskmgrmethods_t;
+
+typedef struct isc_taskmethods {
+	void (*attach)(isc_task_t *source, isc_task_t **targetp);
+	void (*detach)(isc_task_t **taskp);
+	void (*destroy)(isc_task_t **taskp);
+	void (*send)(isc_task_t *task, isc_event_t **eventp);
+	void (*sendanddetach)(isc_task_t **taskp, isc_event_t **eventp);
+	unsigned int (*unsend)(isc_task_t *task, void *sender, isc_eventtype_t type,
+			       void *tag, isc_eventlist_t *events);
+	isc_result_t (*onshutdown)(isc_task_t *task, isc_taskaction_t action,
+				   const void *arg);
+	void (*shutdown)(isc_task_t *task);
+	void (*setname)(isc_task_t *task, const char *name, void *tag);
+	unsigned int (*purgeevents)(isc_task_t *task, void *sender,
+				    isc_eventtype_t type, void *tag);
+	unsigned int (*purgerange)(isc_task_t *task, void *sender,
+				   isc_eventtype_t first, isc_eventtype_t last,
+				   void *tag);
+	isc_result_t (*beginexclusive)(isc_task_t *task);
+	void (*endexclusive)(isc_task_t *task);
+} isc_taskmethods_t;
+
+/*%
+ * This structure is actually just the common prefix of a task manager
+ * object implementation's version of an isc_taskmgr_t.
+ * \brief
+ * Direct use of this structure by clients is forbidden.  task implementations
+ * may change the structure.  'magic' must be ISCAPI_TASKMGR_MAGIC for any
+ * of the isc_task_ routines to work.  task implementations must maintain
+ * all task invariants.
+ */
+struct isc_taskmgr {
+	unsigned int		impmagic;
+	unsigned int		magic;
+	isc_taskmgrmethods_t	*methods;
+};
+
+#define ISCAPI_TASKMGR_MAGIC	ISC_MAGIC('A','t','m','g')
+#define ISCAPI_TASKMGR_VALID(m)	((m) != NULL && \
+				 (m)->magic == ISCAPI_TASKMGR_MAGIC)
+
+/*%
+ * This is the common prefix of a task object.  The same note as
+ * that for the taskmgr structure applies.
+ */
+struct isc_task {
+	unsigned int		impmagic;
+	unsigned int		magic;
+	isc_taskmethods_t	*methods;
+};
+
+#define ISCAPI_TASK_MAGIC	ISC_MAGIC('A','t','s','t')
+#define ISCAPI_TASK_VALID(s)	((s) != NULL && \
+				 (s)->magic == ISCAPI_TASK_MAGIC)
+
+isc_result_t
+isc_task_create(isc_taskmgr_t *manager, unsigned int quantum,
+		isc_task_t **taskp);
+/*%<
+ * Create a task.
+ *
+ * Notes:
+ *
+ *\li	If 'quantum' is non-zero, then only that many events can be dispatched
+ *	before the task must yield to other tasks waiting to execute.  If
+ *	quantum is zero, then the default quantum of the task manager will
+ *	be used.
+ *
+ *\li	The 'quantum' option may be removed from isc_task_create() in the
+ *	future.  If this happens, isc_task_getquantum() and
+ *	isc_task_setquantum() will be provided.
+ *
+ * Requires:
+ *
+ *\li	'manager' is a valid task manager.
+ *
+ *\li	taskp != NULL && *taskp == NULL
+ *
+ * Ensures:
+ *
+ *\li	On success, '*taskp' is bound to the new task.
+ *
+ * Returns:
+ *
+ *\li   #ISC_R_SUCCESS
+ *\li	#ISC_R_NOMEMORY
+ *\li	#ISC_R_UNEXPECTED
+ *\li	#ISC_R_SHUTTINGDOWN
+ */
+
+void
+isc_task_attach(isc_task_t *source, isc_task_t **targetp);
+/*%<
+ * Attach *targetp to source.
+ *
+ * Requires:
+ *
+ *\li	'source' is a valid task.
+ *
+ *\li	'targetp' points to a NULL isc_task_t *.
+ *
+ * Ensures:
+ *
+ *\li	*targetp is attached to source.
+ */
+
+void
+isc_task_detach(isc_task_t **taskp);
+/*%<
+ * Detach *taskp from its task.
+ *
+ * Requires:
+ *
+ *\li	'*taskp' is a valid task.
+ *
+ * Ensures:
+ *
+ *\li	*taskp is NULL.
+ *
+ *\li	If '*taskp' is the last reference to the task, the task is idle (has
+ *	an empty event queue), and has not been shutdown, the task will be
+ *	shutdown.
+ *
+ *\li	If '*taskp' is the last reference to the task and
+ *	the task has been shutdown,
+ *		all resources used by the task will be freed.
+ */
+
+void
+isc_task_send(isc_task_t *task, isc_event_t **eventp);
+/*%<
+ * Send '*event' to 'task'.
+ *
+ * Requires:
+ *
+ *\li	'task' is a valid task.
+ *\li	eventp != NULL && *eventp != NULL.
+ *
+ * Ensures:
+ *
+ *\li	*eventp == NULL.
+ */
+
+void
+isc_task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp);
+/*%<
+ * Send '*event' to '*taskp' and then detach '*taskp' from its
+ * task.
+ *
+ * Requires:
+ *
+ *\li	'*taskp' is a valid task.
+ *\li	eventp != NULL && *eventp != NULL.
+ *
+ * Ensures:
+ *
+ *\li	*eventp == NULL.
+ *
+ *\li	*taskp == NULL.
+ *
+ *\li	If '*taskp' is the last reference to the task, the task is
+ *	idle (has an empty event queue), and has not been shutdown,
+ *	the task will be shutdown.
+ *
+ *\li	If '*taskp' is the last reference to the task and
+ *	the task has been shutdown,
+ *		all resources used by the task will be freed.
+ */
+
+
+unsigned int
+isc_task_purgerange(isc_task_t *task, void *sender, isc_eventtype_t first,
+		    isc_eventtype_t last, void *tag);
+/*%<
+ * Purge events from a task's event queue.
+ *
+ * Requires:
+ *
+ *\li	'task' is a valid task.
+ *
+ *\li	last >= first
+ *
+ * Ensures:
+ *
+ *\li	Events in the event queue of 'task' whose sender is 'sender', whose
+ *	type is >= first and <= last, and whose tag is 'tag' will be purged,
+ *	unless they are marked as unpurgable.
+ *
+ *\li	A sender of NULL will match any sender.  A NULL tag matches any
+ *	tag.
+ *
+ * Returns:
+ *
+ *\li	The number of events purged.
+ */
+
+unsigned int
+isc_task_purge(isc_task_t *task, void *sender, isc_eventtype_t type,
+	       void *tag);
+/*%<
+ * Purge events from a task's event queue.
+ *
+ * Notes:
+ *
+ *\li	This function is equivalent to
+ *
+ *\code
+ *		isc_task_purgerange(task, sender, type, type, tag);
+ *\endcode
+ *
+ * Requires:
+ *
+ *\li	'task' is a valid task.
+ *
+ * Ensures:
+ *
+ *\li	Events in the event queue of 'task' whose sender is 'sender', whose
+ *	type is 'type', and whose tag is 'tag' will be purged, unless they
+ *	are marked as unpurgable.
+ *
+ *\li	A sender of NULL will match any sender.  A NULL tag matches any
+ *	tag.
+ *
+ * Returns:
+ *
+ *\li	The number of events purged.
+ */
+
+isc_boolean_t
+isc_task_purgeevent(isc_task_t *task, isc_event_t *event);
+/*%<
+ * Purge 'event' from a task's event queue.
+ *
+ * XXXRTH:  WARNING:  This method may be removed before beta.
+ *
+ * Notes:
+ *
+ *\li	If 'event' is on the task's event queue, it will be purged,
+ * 	unless it is marked as unpurgeable.  'event' does not have to be
+ *	on the task's event queue; in fact, it can even be an invalid
+ *	pointer.  Purging only occurs if the event is actually on the task's
+ *	event queue.
+ *
+ * \li	Purging never changes the state of the task.
+ *
+ * Requires:
+ *
+ *\li	'task' is a valid task.
+ *
+ * Ensures:
+ *
+ *\li	'event' is not in the event queue for 'task'.
+ *
+ * Returns:
+ *
+ *\li	#ISC_TRUE			The event was purged.
+ *\li	#ISC_FALSE			The event was not in the event queue,
+ *					or was marked unpurgeable.
+ */
+
+unsigned int
+isc_task_unsendrange(isc_task_t *task, void *sender, isc_eventtype_t first,
+		     isc_eventtype_t last, void *tag, isc_eventlist_t *events);
+/*%<
+ * Remove events from a task's event queue.
+ *
+ * Requires:
+ *
+ *\li	'task' is a valid task.
+ *
+ *\li	last >= first.
+ *
+ *\li	*events is a valid list.
+ *
+ * Ensures:
+ *
+ *\li	Events in the event queue of 'task' whose sender is 'sender', whose
+ *	type is >= first and <= last, and whose tag is 'tag' will be dequeued
+ *	and appended to *events.
+ *
+ *\li	A sender of NULL will match any sender.  A NULL tag matches any
+ *	tag.
+ *
+ * Returns:
+ *
+ *\li	The number of events unsent.
+ */
+
+unsigned int
+isc_task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type,
+		void *tag, isc_eventlist_t *events);
+/*%<
+ * Remove events from a task's event queue.
+ *
+ * Notes:
+ *
+ *\li	This function is equivalent to
+ *
+ *\code
+ *		isc_task_unsendrange(task, sender, type, type, tag, events);
+ *\endcode
+ *
+ * Requires:
+ *
+ *\li	'task' is a valid task.
+ *
+ *\li	*events is a valid list.
+ *
+ * Ensures:
+ *
+ *\li	Events in the event queue of 'task' whose sender is 'sender', whose
+ *	type is 'type', and whose tag is 'tag' will be dequeued and appended
+ *	to *events.
+ *
+ * Returns:
+ *
+ *\li	The number of events unsent.
+ */
+
+isc_result_t
+isc_task_onshutdown(isc_task_t *task, isc_taskaction_t action,
+		    const void *arg);
+/*%<
+ * Send a shutdown event with action 'action' and argument 'arg' when
+ * 'task' is shutdown.
+ *
+ * Notes:
+ *
+ *\li	Shutdown events are posted in LIFO order.
+ *
+ * Requires:
+ *
+ *\li	'task' is a valid task.
+ *
+ *\li	'action' is a valid task action.
+ *
+ * Ensures:
+ *
+ *\li	When the task is shutdown, shutdown events requested with
+ *	isc_task_onshutdown() will be appended to the task's event queue.
+ *
+
+ * Returns:
+ *
+ *\li	#ISC_R_SUCCESS
+ *\li	#ISC_R_NOMEMORY
+ *\li	#ISC_R_TASKSHUTTINGDOWN			Task is shutting down.
+ */
+
+void
+isc_task_shutdown(isc_task_t *task);
+/*%<
+ * Shutdown 'task'.
+ *
+ * Notes:
+ *
+ *\li	Shutting down a task causes any shutdown events requested with
+ *	isc_task_onshutdown() to be posted (in LIFO order).  The task
+ *	moves into a "shutting down" mode which prevents further calls
+ *	to isc_task_onshutdown().
+ *
+ *\li	Trying to shutdown a task that has already been shutdown has no
+ *	effect.
+ *
+ * Requires:
+ *
+ *\li	'task' is a valid task.
+ *
+ * Ensures:
+ *
+ *\li	Any shutdown events requested with isc_task_onshutdown() have been
+ *	posted (in LIFO order).
+ */
+
+void
+isc_task_destroy(isc_task_t **taskp);
+/*%<
+ * Destroy '*taskp'.
+ *
+ * Notes:
+ *
+ *\li	This call is equivalent to:
+ *
+ *\code
+ *		isc_task_shutdown(*taskp);
+ *		isc_task_detach(taskp);
+ *\endcode
+ *
+ * Requires:
+ *
+ *	'*taskp' is a valid task.
+ *
+ * Ensures:
+ *
+ *\li	Any shutdown events requested with isc_task_onshutdown() have been
+ *	posted (in LIFO order).
+ *
+ *\li	*taskp == NULL
+ *
+ *\li	If '*taskp' is the last reference to the task,
+ *		all resources used by the task will be freed.
+ */
+
+void
+isc_task_setname(isc_task_t *task, const char *name, void *tag);
+/*%<
+ * Name 'task'.
+ *
+ * Notes:
+ *
+ *\li	Only the first 15 characters of 'name' will be copied.
+ *
+ *\li	Naming a task is currently only useful for debugging purposes.
+ *
+ * Requires:
+ *
+ *\li	'task' is a valid task.
+ */
+
+const char *
+isc_task_getname(isc_task_t *task);
+/*%<
+ * Get the name of 'task', as previously set using isc_task_setname().
+ *
+ * Notes:
+ *\li	This function is for debugging purposes only.
+ *
+ * Requires:
+ *\li	'task' is a valid task.
+ *
+ * Returns:
+ *\li	A non-NULL pointer to a null-terminated string.
+ * 	If the task has not been named, the string is
+ * 	empty.
+ *
+ */
+
+void *
+isc_task_gettag(isc_task_t *task);
+/*%<
+ * Get the tag value for  'task', as previously set using isc_task_settag().
+ *
+ * Notes:
+ *\li	This function is for debugging purposes only.
+ *
+ * Requires:
+ *\li	'task' is a valid task.
+ */
+
+isc_result_t
+isc_task_beginexclusive(isc_task_t *task);
+/*%<
+ * Request exclusive access for 'task', which must be the calling
+ * task.  Waits for any other concurrently executing tasks to finish their
+ * current event, and prevents any new events from executing in any of the
+ * tasks sharing a task manager with 'task'.
+ *
+ * The exclusive access must be relinquished by calling
+ * isc_task_endexclusive() before returning from the current event handler.
+ *
+ * Requires:
+ *\li	'task' is the calling task.
+ *
+ * Returns:
+ *\li	#ISC_R_SUCCESS		The current task now has exclusive access.
+ *\li	#ISC_R_LOCKBUSY		Another task has already requested exclusive
+ *				access.
+ */
+
+void
+isc_task_endexclusive(isc_task_t *task);
+/*%<
+ * Relinquish the exclusive access obtained by isc_task_beginexclusive(),
+ * allowing other tasks to execute.
+ *
+ * Requires:
+ *\li	'task' is the calling task, and has obtained
+ *		exclusive access by calling isc_task_spl().
+ */
+
+void
+isc_task_getcurrenttime(isc_task_t *task, isc_stdtime_t *t);
+/*%<
+ * Provide the most recent timestamp on the task.  The timestamp is considered
+ * as the "current time" in the second-order granularity.
+ *
+ * Requires:
+ *\li	'task' is a valid task.
+ *\li	't' is a valid non NULL pointer.
+ *
+ * Ensures:
+ *\li	'*t' has the "current time".
+ */
+
+isc_boolean_t
+isc_task_exiting(isc_task_t *t);
+/*%<
+ * Returns ISC_TRUE if the task is in the process of shutting down,
+ * ISC_FALSE otherwise.
+ *
+ * Requires:
+ *\li	'task' is a valid task.
+ */
+
+/*****
+ ***** Task Manager.
+ *****/
+
+isc_result_t
+isc_taskmgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx,
+			unsigned int workers, unsigned int default_quantum,
+			isc_taskmgr_t **managerp);
+isc_result_t
+isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
+		   unsigned int default_quantum, isc_taskmgr_t **managerp);
+/*%<
+ * Create a new task manager.  isc_taskmgr_createinctx() also associates
+ * the new manager with the specified application context.
+ *
+ * Notes:
+ *
+ *\li	'workers' in the number of worker threads to create.  In general,
+ *	the value should be close to the number of processors in the system.
+ *	The 'workers' value is advisory only.  An attempt will be made to
+ *	create 'workers' threads, but if at least one thread creation
+ *	succeeds, isc_taskmgr_create() may return ISC_R_SUCCESS.
+ *
+ *\li	If 'default_quantum' is non-zero, then it will be used as the default
+ *	quantum value when tasks are created.  If zero, then an implementation
+ *	defined default quantum will be used.
+ *
+ * Requires:
+ *
+ *\li      'mctx' is a valid memory context.
+ *
+ *\li	workers > 0
+ *
+ *\li	managerp != NULL && *managerp == NULL
+ *
+ *\li	'actx' is a valid application context (for createinctx()).
+ *
+ * Ensures:
+ *
+ *\li	On success, '*managerp' will be attached to the newly created task
+ *	manager.
+ *
+ * Returns:
+ *
+ *\li	#ISC_R_SUCCESS
+ *\li	#ISC_R_NOMEMORY
+ *\li	#ISC_R_NOTHREADS		No threads could be created.
+ *\li	#ISC_R_UNEXPECTED		An unexpected error occurred.
+ *\li	#ISC_R_SHUTTINGDOWN      	The non-threaded, shared, task
+ *					manager shutting down.
+ */
+
+void
+isc_taskmgr_destroy(isc_taskmgr_t **managerp);
+/*%<
+ * Destroy '*managerp'.
+ *
+ * Notes:
+ *
+ *\li	Calling isc_taskmgr_destroy() will shutdown all tasks managed by
+ *	*managerp that haven't already been shutdown.  The call will block
+ *	until all tasks have entered the done state.
+ *
+ *\li	isc_taskmgr_destroy() must not be called by a task event action,
+ *	because it would block forever waiting for the event action to
+ *	complete.  An event action that wants to cause task manager shutdown
+ *	should request some non-event action thread of execution to do the
+ *	shutdown, e.g. by signaling a condition variable or using
+ *	isc_app_shutdown().
+ *
+ *\li	Task manager references are not reference counted, so the caller
+ *	must ensure that no attempt will be made to use the manager after
+ *	isc_taskmgr_destroy() returns.
+ *
+ * Requires:
+ *
+ *\li	'*managerp' is a valid task manager.
+ *
+ *\li	isc_taskmgr_destroy() has not be called previously on '*managerp'.
+ *
+ * Ensures:
+ *
+ *\li	All resources used by the task manager, and any tasks it managed,
+ *	have been freed.
+ */
+
+#ifdef HAVE_LIBXML2
+
+void
+isc_taskmgr_renderxml(isc_taskmgr_t *mgr, xmlTextWriterPtr writer);
+
+#endif
+
+/*%<
+ * See isc_taskmgr_create() above.
+ */
+typedef isc_result_t
+(*isc_taskmgrcreatefunc_t)(isc_mem_t *mctx, unsigned int workers,
+			   unsigned int default_quantum,
+			   isc_taskmgr_t **managerp);
+
+isc_result_t
+isc_task_register(isc_taskmgrcreatefunc_t createfunc);
+/*%<
+ * Register a new task management implementation and add it to the list of
+ * supported implementations.  This function must be called when a different
+ * event library is used than the one contained in the ISC library.
+ */
+
+isc_result_t
+isc__task_register(void);
+/*%<
+ * A short cut function that specifies the task management module in the ISC
+ * library for isc_task_register().  An application that uses the ISC library
+ * usually do not have to care about this function: it would call
+ * isc_lib_register(), which internally calls this function.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_TASK_H */
diff --git a/src/lib/bind9/include/isc/taskpool.h b/src/lib/bind9/include/isc/taskpool.h
new file mode 100644
index 0000000..07aba70
--- /dev/null
+++ b/src/lib/bind9/include/isc/taskpool.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: taskpool.h,v 1.15 2007-06-19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_TASKPOOL_H
+#define ISC_TASKPOOL_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file isc/taskpool.h
+ * \brief A task pool is a mechanism for sharing a small number of tasks
+ * among a large number of objects such that each object is
+ * assigned a unique task, but each task may be shared by several
+ * objects.
+ *
+ * Task pools are used to let objects that can exist in large
+ * numbers (e.g., zones) use tasks for synchronization without
+ * the memory overhead and unfair scheduling competition that
+ * could result from creating a separate task for each object.
+ */
+
+
+/***
+ *** Imports.
+ ***/
+
+#include <isc/lang.h>
+#include <isc/task.h>
+
+ISC_LANG_BEGINDECLS
+
+/*****
+ ***** Types.
+ *****/
+
+typedef struct isc_taskpool isc_taskpool_t;
+
+/*****
+ ***** Functions.
+ *****/
+
+isc_result_t
+isc_taskpool_create(isc_taskmgr_t *tmgr, isc_mem_t *mctx,
+		    unsigned int ntasks, unsigned int quantum,
+		    isc_taskpool_t **poolp);
+/*%<
+ * Create a task pool of "ntasks" tasks, each with quantum
+ * "quantum".
+ *
+ * Requires:
+ *
+ *\li	'tmgr' is a valid task manager.
+ *
+ *\li	'mctx' is a valid memory context.
+ *
+ *\li	poolp != NULL && *poolp == NULL
+ *
+ * Ensures:
+ *
+ *\li	On success, '*taskp' points to the new task pool.
+ *
+ * Returns:
+ *
+ *\li	#ISC_R_SUCCESS
+ *\li	#ISC_R_NOMEMORY
+ *\li	#ISC_R_UNEXPECTED
+ */
+
+void 
+isc_taskpool_gettask(isc_taskpool_t *pool, unsigned int hash,
+			  isc_task_t **targetp);
+/*%<
+ * Attach to the task corresponding to the hash value "hash".
+ */
+
+void
+isc_taskpool_destroy(isc_taskpool_t **poolp);
+/*%<
+ * Destroy a task pool.  The tasks in the pool are detached but not
+ * shut down.
+ *
+ * Requires:
+ * \li	'*poolp' is a valid task pool.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_TASKPOOL_H */
diff --git a/src/lib/bind9/include/isc/timer.h b/src/lib/bind9/include/isc/timer.h
new file mode 100644
index 0000000..a54e73b
--- /dev/null
+++ b/src/lib/bind9/include/isc/timer.h
@@ -0,0 +1,431 @@
+/*
+ * Copyright (C) 2004-2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2002  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: timer.h,v 1.43 2009-09-02 23:48:03 tbox Exp $ */
+
+#ifndef ISC_TIMER_H
+#define ISC_TIMER_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file isc/timer.h
+ * \brief Provides timers which are event sources in the task system.
+ *
+ * Three types of timers are supported:
+ *
+ *\li	'ticker' timers generate a periodic tick event.
+ *
+ *\li	'once' timers generate an idle timeout event if they are idle for too
+ *	long, and generate a life timeout event if their lifetime expires.
+ *	They are used to implement both (possibly expiring) idle timers and
+ *	'one-shot' timers.
+ *
+ *\li	'limited' timers generate a periodic tick event until they reach
+ *	their lifetime when they generate a life timeout event.
+ *
+ *\li	'inactive' timers generate no events.
+ *
+ * Timers can change type.  It is typical to create a timer as
+ * an 'inactive' timer and then change it into a 'ticker' or
+ * 'once' timer.
+ *
+ *\li MP:
+ *	The module ensures appropriate synchronization of data structures it
+ *	creates and manipulates.
+ *	Clients of this module must not be holding a timer's task's lock when
+ *	making a call that affects that timer.  Failure to follow this rule
+ *	can result in deadlock.
+ *	The caller must ensure that isc_timermgr_destroy() is called only
+ *	once for a given manager.
+ *
+ * \li Reliability:
+ *	No anticipated impact.
+ *
+ * \li Resources:
+ *	TBS
+ *
+ * \li Security:
+ *	No anticipated impact.
+ *
+ * \li Standards:
+ *	None.
+ */
+
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/types.h>
+#include <isc/event.h>
+#include <isc/eventclass.h>
+#include <isc/lang.h>
+#include <isc/time.h>
+
+ISC_LANG_BEGINDECLS
+
+/***
+ *** Types
+ ***/
+
+/*% Timer Type */
+typedef enum {
+	isc_timertype_ticker = 0, 	/*%< Ticker */
+	isc_timertype_once = 1, 	/*%< Once */
+	isc_timertype_limited = 2, 	/*%< Limited */
+	isc_timertype_inactive = 3 	/*%< Inactive */
+} isc_timertype_t;
+
+typedef struct isc_timerevent {
+	struct isc_event	common;
+	isc_time_t		due;
+} isc_timerevent_t;
+
+#define ISC_TIMEREVENT_FIRSTEVENT	(ISC_EVENTCLASS_TIMER + 0)
+#define ISC_TIMEREVENT_TICK		(ISC_EVENTCLASS_TIMER + 1)
+#define ISC_TIMEREVENT_IDLE		(ISC_EVENTCLASS_TIMER + 2)
+#define ISC_TIMEREVENT_LIFE		(ISC_EVENTCLASS_TIMER + 3)
+#define ISC_TIMEREVENT_LASTEVENT	(ISC_EVENTCLASS_TIMER + 65535)
+
+/*% Timer and timer manager methods */
+typedef struct {
+	void		(*destroy)(isc_timermgr_t **managerp);
+	isc_result_t	(*timercreate)(isc_timermgr_t *manager,
+				       isc_timertype_t type,
+				       isc_time_t *expires,
+				       isc_interval_t *interval,
+				       isc_task_t *task,
+				       isc_taskaction_t action,
+				       const void *arg,
+				       isc_timer_t **timerp);
+} isc_timermgrmethods_t;
+
+typedef struct {
+	void		(*attach)(isc_timer_t *timer, isc_timer_t **timerp);
+	void		(*detach)(isc_timer_t **timerp);
+	isc_result_t	(*reset)(isc_timer_t *timer, isc_timertype_t type,
+				 isc_time_t *expires, isc_interval_t *interval,
+				 isc_boolean_t purge);
+	isc_result_t	(*touch)(isc_timer_t *timer);
+} isc_timermethods_t;
+
+/*%
+ * This structure is actually just the common prefix of a timer manager
+ * object implementation's version of an isc_timermgr_t.
+ * \brief
+ * Direct use of this structure by clients is forbidden.  timer implementations
+ * may change the structure.  'magic' must be ISCAPI_TIMERMGR_MAGIC for any
+ * of the isc_timer_ routines to work.  timer implementations must maintain
+ * all timer invariants.
+ */
+struct isc_timermgr {
+	unsigned int		impmagic;
+	unsigned int		magic;
+	isc_timermgrmethods_t	*methods;
+};
+
+#define ISCAPI_TIMERMGR_MAGIC		ISC_MAGIC('A','t','m','g')
+#define ISCAPI_TIMERMGR_VALID(m)	((m) != NULL && \
+					 (m)->magic == ISCAPI_TIMERMGR_MAGIC)
+
+/*%
+ * This is the common prefix of a timer object.  The same note as
+ * that for the timermgr structure applies.
+ */
+struct isc_timer {
+	unsigned int		impmagic;
+	unsigned int		magic;
+	isc_timermethods_t	*methods;
+};
+
+#define ISCAPI_TIMER_MAGIC	ISC_MAGIC('A','t','m','r')
+#define ISCAPI_TIMER_VALID(s)	((s) != NULL && \
+				 (s)->magic == ISCAPI_TIMER_MAGIC)
+
+/***
+ *** Timer and Timer Manager Functions
+ ***
+ *** Note: all Ensures conditions apply only if the result is success for
+ *** those functions which return an isc_result_t.
+ ***/
+
+isc_result_t
+isc_timer_create(isc_timermgr_t *manager,
+		 isc_timertype_t type,
+		 isc_time_t *expires,
+		 isc_interval_t *interval,
+		 isc_task_t *task,
+		 isc_taskaction_t action,
+		 const void *arg,
+		 isc_timer_t **timerp);
+/*%<
+ * Create a new 'type' timer managed by 'manager'.  The timers parameters
+ * are specified by 'expires' and 'interval'.  Events will be posted to
+ * 'task' and when dispatched 'action' will be called with 'arg' as the
+ * arg value.  The new timer is returned in 'timerp'.
+ *
+ * Notes:
+ *
+ *\li	For ticker timers, the timer will generate a 'tick' event every
+ *	'interval' seconds.  The value of 'expires' is ignored.
+ *
+ *\li	For once timers, 'expires' specifies the time when a life timeout
+ *	event should be generated.  If 'expires' is 0 (the epoch), then no life
+ *	timeout will be generated.  'interval' specifies how long the timer
+ *	can be idle before it generates an idle timeout.  If 0, then no
+ *	idle timeout will be generated.
+ *
+ *\li	If 'expires' is NULL, the epoch will be used.
+ *
+ *	If 'interval' is NULL, the zero interval will be used.
+ *
+ * Requires:
+ *
+ *\li	'manager' is a valid manager
+ *
+ *\li	'task' is a valid task
+ *
+ *\li	'action' is a valid action
+ *
+ *\li	'expires' points to a valid time, or is NULL.
+ *
+ *\li	'interval' points to a valid interval, or is NULL.
+ *
+ *\li	type == isc_timertype_inactive ||
+ *	('expires' and 'interval' are not both 0)
+ *
+ *\li	'timerp' is a valid pointer, and *timerp == NULL
+ *
+ * Ensures:
+ *
+ *\li	'*timerp' is attached to the newly created timer
+ *
+ *\li	The timer is attached to the task
+ *
+ *\li	An idle timeout will not be generated until at least Now + the
+ *	timer's interval if 'timer' is a once timer with a non-zero
+ *	interval.
+ *
+ * Returns:
+ *
+ *\li	Success
+ *\li	No memory
+ *\li	Unexpected error
+ */
+
+isc_result_t
+isc_timer_reset(isc_timer_t *timer,
+		isc_timertype_t type,
+		isc_time_t *expires,
+		isc_interval_t *interval,
+		isc_boolean_t purge);
+/*%<
+ * Change the timer's type, expires, and interval values to the given
+ * values.  If 'purge' is TRUE, any pending events from this timer
+ * are purged from its task's event queue.
+ *
+ * Notes:
+ *
+ *\li	If 'expires' is NULL, the epoch will be used.
+ *
+ *\li	If 'interval' is NULL, the zero interval will be used.
+ *
+ * Requires:
+ *
+ *\li	'timer' is a valid timer
+ *
+ *\li	The same requirements that isc_timer_create() imposes on 'type',
+ *	'expires' and 'interval' apply.
+ *
+ * Ensures:
+ *
+ *\li	An idle timeout will not be generated until at least Now + the
+ *	timer's interval if 'timer' is a once timer with a non-zero
+ *	interval.
+ *
+ * Returns:
+ *
+ *\li	Success
+ *\li	No memory
+ *\li	Unexpected error
+ */
+
+isc_result_t
+isc_timer_touch(isc_timer_t *timer);
+/*%<
+ * Set the last-touched time of 'timer' to the current time.
+ *
+ * Requires:
+ *
+ *\li	'timer' is a valid once timer.
+ *
+ * Ensures:
+ *
+ *\li	An idle timeout will not be generated until at least Now + the
+ *	timer's interval if 'timer' is a once timer with a non-zero
+ *	interval.
+ *
+ * Returns:
+ *
+ *\li	Success
+ *\li	Unexpected error
+ */
+
+void
+isc_timer_attach(isc_timer_t *timer, isc_timer_t **timerp);
+/*%<
+ * Attach *timerp to timer.
+ *
+ * Requires:
+ *
+ *\li	'timer' is a valid timer.
+ *
+ *\li	'timerp' points to a NULL timer.
+ *
+ * Ensures:
+ *
+ *\li	*timerp is attached to timer.
+ */
+
+void
+isc_timer_detach(isc_timer_t **timerp);
+/*%<
+ * Detach *timerp from its timer.
+ *
+ * Requires:
+ *
+ *\li	'timerp' points to a valid timer.
+ *
+ * Ensures:
+ *
+ *\li	*timerp is NULL.
+ *
+ *\li	If '*timerp' is the last reference to the timer,
+ *	then:
+ *
+ *\code
+ *		The timer will be shutdown
+ *
+ *		The timer will detach from its task
+ *
+ *		All resources used by the timer have been freed
+ *
+ *		Any events already posted by the timer will be purged.
+ *		Therefore, if isc_timer_detach() is called in the context
+ *		of the timer's task, it is guaranteed that no more
+ *		timer event callbacks will run after the call.
+ *\endcode
+ */
+
+isc_timertype_t
+isc_timer_gettype(isc_timer_t *timer);
+/*%<
+ * Return the timer type.
+ *
+ * Requires:
+ *
+ *\li	'timer' to be a valid timer.
+ */
+
+isc_result_t
+isc_timermgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx,
+			 isc_timermgr_t **managerp);
+
+isc_result_t
+isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp);
+/*%<
+ * Create a timer manager.  isc_timermgr_createinctx() also associates
+ * the new manager with the specified application context.
+ *
+ * Notes:
+ *
+ *\li	All memory will be allocated in memory context 'mctx'.
+ *
+ * Requires:
+ *
+ *\li	'mctx' is a valid memory context.
+ *
+ *\li	'managerp' points to a NULL isc_timermgr_t.
+ *
+ *\li	'actx' is a valid application context (for createinctx()).
+ *
+ * Ensures:
+ *
+ *\li	'*managerp' is a valid isc_timermgr_t.
+ *
+ * Returns:
+ *
+ *\li	Success
+ *\li	No memory
+ *\li	Unexpected error
+ */
+
+void
+isc_timermgr_destroy(isc_timermgr_t **managerp);
+/*%<
+ * Destroy a timer manager.
+ *
+ * Notes:
+ *
+ *\li	This routine blocks until there are no timers left in the manager,
+ *	so if the caller holds any timer references using the manager, it
+ *	must detach them before calling isc_timermgr_destroy() or it will
+ *	block forever.
+ *
+ * Requires:
+ *
+ *\li	'*managerp' is a valid isc_timermgr_t.
+ *
+ * Ensures:
+ *
+ *\li	*managerp == NULL
+ *
+ *\li	All resources used by the manager have been freed.
+ */
+
+void isc_timermgr_poke(isc_timermgr_t *m);
+
+#ifdef USE_TIMERIMPREGISTER
+/*%<
+ * See isc_timermgr_create() above.
+ */
+typedef isc_result_t
+(*isc_timermgrcreatefunc_t)(isc_mem_t *mctx, isc_timermgr_t **managerp);
+
+isc_result_t
+isc__timer_register(void);
+/*%<
+ * Register a new timer management implementation and add it to the list of
+ * supported implementations.  This function must be called when a different
+ * event library is used than the one contained in the ISC library.
+ */
+
+isc_result_t
+isc_timer_register(isc_timermgrcreatefunc_t createfunc);
+/*%<
+ * A short cut function that specifies the timer management module in the ISC
+ * library for isc_timer_register().  An application that uses the ISC library
+ * usually do not have to care about this function: it would call
+ * isc_lib_register(), which internally calls this function.
+ */
+#endif /* USE_TIMERIMPREGISTER */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_TIMER_H */
diff --git a/src/lib/bind9/include/isc/types.h b/src/lib/bind9/include/isc/types.h
new file mode 100644
index 0000000..10da62b
--- /dev/null
+++ b/src/lib/bind9/include/isc/types.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2004-2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: types.h,v 1.52 2009-12-05 23:31:41 each Exp $ */
+
+#ifndef ISC_TYPES_H
+#define ISC_TYPES_H 1
+
+#include <isc/bind9.h>
+#include <isc/namespace.h>
+
+/*! \file isc/types.h
+ * \brief
+ * OS-specific types, from the OS-specific include directories.
+ */
+#include <isc/int.h>
+#include <isc/offset.h>
+
+/*
+ * XXXDCL should isc_boolean_t be moved here, requiring an explicit include
+ * of <isc/boolean.h> when ISC_TRUE/ISC_FALSE/ISC_TF() are desired?
+ */
+#include <isc/boolean.h>
+/*
+ * XXXDCL This is just for ISC_LIST and ISC_LINK, but gets all of the other
+ * list macros too.
+ */
+#include <isc/list.h>
+
+/* Core Types.  Alphabetized by defined type. */
+
+typedef struct isc_appctx		isc_appctx_t;	 	/*%< Application context */
+typedef struct isc_backtrace_symmap	isc_backtrace_symmap_t; /*%< Symbol Table Entry */
+typedef struct isc_bitstring		isc_bitstring_t; 	/*%< Bitstring */
+typedef struct isc_buffer		isc_buffer_t;		/*%< Buffer */
+typedef ISC_LIST(isc_buffer_t)		isc_bufferlist_t;	/*%< Buffer List */
+typedef struct isc_constregion		isc_constregion_t;	/*%< Const region */
+typedef struct isc_consttextregion	isc_consttextregion_t;	/*%< Const Text Region */
+typedef struct isc_entropy		isc_entropy_t;		/*%< Entropy */
+typedef struct isc_entropysource	isc_entropysource_t;	/*%< Entropy Source */
+typedef struct isc_event		isc_event_t;		/*%< Event */
+typedef ISC_LIST(isc_event_t)		isc_eventlist_t;	/*%< Event List */
+typedef unsigned int			isc_eventtype_t;	/*%< Event Type */
+typedef isc_uint32_t			isc_fsaccess_t;		/*%< FS Access */
+typedef struct isc_hash			isc_hash_t;		/*%< Hash */
+typedef struct isc_httpd		isc_httpd_t;		/*%< HTTP client */
+typedef void (isc_httpdfree_t)(isc_buffer_t *, void *);		/*%< HTTP free function */
+typedef struct isc_httpdmgr		isc_httpdmgr_t;		/*%< HTTP manager */
+typedef struct isc_httpdurl		isc_httpdurl_t;		/*%< HTTP URL */
+typedef void (isc_httpdondestroy_t)(void *);			/*%< Callback on destroying httpd */
+typedef struct isc_interface		isc_interface_t;	/*%< Interface */
+typedef struct isc_interfaceiter	isc_interfaceiter_t;	/*%< Interface Iterator */
+typedef struct isc_interval		isc_interval_t;		/*%< Interval */
+typedef struct isc_lex			isc_lex_t;		/*%< Lex */
+typedef struct isc_log 			isc_log_t;		/*%< Log */
+typedef struct isc_logcategory		isc_logcategory_t;	/*%< Log Category */
+typedef struct isc_logconfig		isc_logconfig_t;	/*%< Log Configuration */
+typedef struct isc_logmodule		isc_logmodule_t;	/*%< Log Module */
+typedef struct isc_mem			isc_mem_t;		/*%< Memory */
+typedef struct isc_mempool		isc_mempool_t;		/*%< Memory Pool */
+typedef struct isc_msgcat		isc_msgcat_t;		/*%< Message Catalog */
+typedef struct isc_ondestroy		isc_ondestroy_t;	/*%< On Destroy */
+typedef struct isc_netaddr		isc_netaddr_t;		/*%< Net Address */
+typedef struct isc_portset		isc_portset_t;		/*%< Port Set */
+typedef struct isc_quota		isc_quota_t;		/*%< Quota */
+typedef struct isc_random		isc_random_t;		/*%< Random */
+typedef struct isc_ratelimiter		isc_ratelimiter_t;	/*%< Rate Limiter */
+typedef struct isc_region		isc_region_t;		/*%< Region */
+typedef isc_uint64_t			isc_resourcevalue_t;	/*%< Resource Value */
+typedef unsigned int			isc_result_t;		/*%< Result */
+typedef struct isc_rwlock		isc_rwlock_t;		/*%< Read Write Lock */
+typedef struct isc_sockaddr		isc_sockaddr_t;		/*%< Socket Address */
+typedef struct isc_socket		isc_socket_t;		/*%< Socket */
+typedef struct isc_socketevent		isc_socketevent_t;	/*%< Socket Event */
+typedef struct isc_socketmgr		isc_socketmgr_t;	/*%< Socket Manager */
+typedef struct isc_stats		isc_stats_t;		/*%< Statistics */
+typedef int				isc_statscounter_t;	/*%< Statistics Counter */
+typedef struct isc_symtab		isc_symtab_t;		/*%< Symbol Table */
+typedef struct isc_task			isc_task_t;		/*%< Task */
+typedef ISC_LIST(isc_task_t)		isc_tasklist_t;		/*%< Task List */
+typedef struct isc_taskmgr		isc_taskmgr_t;		/*%< Task Manager */
+typedef struct isc_textregion		isc_textregion_t;	/*%< Text Region */
+typedef struct isc_time			isc_time_t;		/*%< Time */
+typedef struct isc_timer		isc_timer_t;		/*%< Timer */
+typedef struct isc_timermgr		isc_timermgr_t;		/*%< Timer Manager */
+
+typedef void (*isc_taskaction_t)(isc_task_t *, isc_event_t *);
+typedef int (*isc_sockfdwatch_t)(isc_task_t *, isc_socket_t *, void *, int);
+
+/* The following cannot be listed alphabetically due to forward reference */
+typedef isc_result_t (isc_httpdaction_t)(const char *url,
+					 const char *querystring,
+					 void *arg,
+					 unsigned int *retcode,
+					 const char **retmsg,
+					 const char **mimetype,
+					 isc_buffer_t *body,
+					 isc_httpdfree_t **freecb,
+					 void **freecb_args);
+typedef isc_boolean_t (isc_httpdclientok_t)(const isc_sockaddr_t *, void *);
+
+/*% Resource */
+typedef enum {
+	isc_resource_coresize = 1,
+	isc_resource_cputime,
+	isc_resource_datasize,
+	isc_resource_filesize,
+	isc_resource_lockedmemory,
+	isc_resource_openfiles,
+	isc_resource_processes,
+	isc_resource_residentsize,
+	isc_resource_stacksize
+} isc_resource_t;
+
+#endif /* ISC_TYPES_H */
diff --git a/src/lib/bind9/include/isc/util.h b/src/lib/bind9/include/isc/util.h
new file mode 100644
index 0000000..6e7da3a
--- /dev/null
+++ b/src/lib/bind9/include/isc/util.h
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) 2004-2007, 2010, 2011  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: util.h,v 1.32.170.2 2011-03-12 04:59:19 tbox Exp $ */
+
+#ifndef ISC_UTIL_H
+#define ISC_UTIL_H 1
+
+/*! \file isc/util.h
+ * NOTE:
+ *
+ * This file is not to be included from any <isc/???.h> (or other) library
+ * files.
+ *
+ * \brief
+ * Including this file puts several macros in your name space that are
+ * not protected (as all the other ISC functions/macros do) by prepending
+ * ISC_ or isc_ to the name.
+ */
+
+/***
+ *** General Macros.
+ ***/
+
+/*%
+ * Use this to hide unused function arguments.
+ * \code
+ * int
+ * foo(char *bar)
+ * {
+ *	UNUSED(bar);
+ * }
+ * \endcode
+ */
+#define UNUSED(x)      (void)(x)
+
+/*%
+ * The opposite: silent warnings about stored values which are never read.
+ */
+#define POST(x)        (void)(x)
+
+#define ISC_MAX(a, b)  ((a) > (b) ? (a) : (b))
+#define ISC_MIN(a, b)  ((a) < (b) ? (a) : (b))
+
+/*%
+ * Use this to remove the const qualifier of a variable to assign it to
+ * a non-const variable or pass it as a non-const function argument ...
+ * but only when you are sure it won't then be changed!
+ * This is necessary to sometimes shut up some compilers
+ * (as with gcc -Wcast-qual) when there is just no other good way to avoid the
+ * situation.
+ */
+#define DE_CONST(konst, var) \
+	do { \
+		union { const void *k; void *v; } _u; \
+		_u.k = konst; \
+		var = _u.v; \
+	} while (0)
+
+/*%
+ * Use this in translation units that would otherwise be empty, to
+ * suppress compiler warnings.
+ */
+#define EMPTY_TRANSLATION_UNIT static void isc__empty(void) { isc__empty(); }
+
+/*%
+ * We use macros instead of calling the routines directly because
+ * the capital letters make the locking stand out.
+ * We RUNTIME_CHECK for success since in general there's no way
+ * for us to continue if they fail.
+ */
+
+#ifdef ISC_UTIL_TRACEON
+#define ISC_UTIL_TRACE(a) a
+#include <stdio.h>		/* Required for fprintf/stderr when tracing. */
+#include <isc/msgs.h>		/* Required for isc_msgcat when tracing. */
+#else
+#define ISC_UTIL_TRACE(a)
+#endif
+
+#include <isc/result.h>		/* Contractual promise. */
+
+#define LOCK(lp) do { \
+	ISC_UTIL_TRACE(fprintf(stderr, "%s %p %s %d\n", \
+			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
+					      ISC_MSG_LOCKING, "LOCKING"), \
+			       (lp), __FILE__, __LINE__)); \
+	RUNTIME_CHECK(isc_mutex_lock((lp)) == ISC_R_SUCCESS); \
+	ISC_UTIL_TRACE(fprintf(stderr, "%s %p %s %d\n", \
+			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
+					      ISC_MSG_LOCKED, "LOCKED"), \
+			       (lp), __FILE__, __LINE__)); \
+	} while (0)
+#define UNLOCK(lp) do { \
+	RUNTIME_CHECK(isc_mutex_unlock((lp)) == ISC_R_SUCCESS); \
+	ISC_UTIL_TRACE(fprintf(stderr, "%s %p %s %d\n", \
+			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
+					      ISC_MSG_UNLOCKED, "UNLOCKED"), \
+			       (lp), __FILE__, __LINE__)); \
+	} while (0)
+#define ISLOCKED(lp) (1)
+#define DESTROYLOCK(lp) \
+	RUNTIME_CHECK(isc_mutex_destroy((lp)) == ISC_R_SUCCESS)
+
+
+#define BROADCAST(cvp) do { \
+	ISC_UTIL_TRACE(fprintf(stderr, "%s %p %s %d\n", \
+			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
+					      ISC_MSG_BROADCAST, "BROADCAST"),\
+			       (cvp), __FILE__, __LINE__)); \
+	RUNTIME_CHECK(isc_condition_broadcast((cvp)) == ISC_R_SUCCESS); \
+	} while (0)
+#define SIGNAL(cvp) do { \
+	ISC_UTIL_TRACE(fprintf(stderr, "%s %p %s %d\n", \
+			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
+					      ISC_MSG_SIGNAL, "SIGNAL"), \
+			       (cvp), __FILE__, __LINE__)); \
+	RUNTIME_CHECK(isc_condition_signal((cvp)) == ISC_R_SUCCESS); \
+	} while (0)
+#define WAIT(cvp, lp) do { \
+	ISC_UTIL_TRACE(fprintf(stderr, "%s %p %s %p %s %d\n", \
+			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
+					      ISC_MSG_UTILWAIT, "WAIT"), \
+			       (cvp), \
+			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
+					      ISC_MSG_LOCK, "LOCK"), \
+			       (lp), __FILE__, __LINE__)); \
+	RUNTIME_CHECK(isc_condition_wait((cvp), (lp)) == ISC_R_SUCCESS); \
+	ISC_UTIL_TRACE(fprintf(stderr, "%s %p %s %p %s %d\n", \
+			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
+					      ISC_MSG_WAITED, "WAITED"), \
+			       (cvp), \
+			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
+					      ISC_MSG_LOCKED, "LOCKED"), \
+			       (lp), __FILE__, __LINE__)); \
+	} while (0)
+
+/*
+ * isc_condition_waituntil can return ISC_R_TIMEDOUT, so we
+ * don't RUNTIME_CHECK the result.
+ *
+ *  XXX Also, can't really debug this then...
+ */
+
+#define WAITUNTIL(cvp, lp, tp) \
+	isc_condition_waituntil((cvp), (lp), (tp))
+
+#define RWLOCK(lp, t) do { \
+	ISC_UTIL_TRACE(fprintf(stderr, "%s %p, %d %s %d\n", \
+			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
+					      ISC_MSG_RWLOCK, "RWLOCK"), \
+			       (lp), (t), __FILE__, __LINE__)); \
+	RUNTIME_CHECK(isc_rwlock_lock((lp), (t)) == ISC_R_SUCCESS); \
+	ISC_UTIL_TRACE(fprintf(stderr, "%s %p, %d %s %d\n", \
+			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
+					      ISC_MSG_RWLOCKED, "RWLOCKED"), \
+			       (lp), (t), __FILE__, __LINE__)); \
+	} while (0)
+#define RWUNLOCK(lp, t) do { \
+	ISC_UTIL_TRACE(fprintf(stderr, "%s %p, %d %s %d\n", \
+			       isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
+					      ISC_MSG_RWUNLOCK, "RWUNLOCK"), \
+			       (lp), (t), __FILE__, __LINE__)); \
+	RUNTIME_CHECK(isc_rwlock_unlock((lp), (t)) == ISC_R_SUCCESS); \
+	} while (0)
+
+#define DESTROYMUTEXBLOCK(bp, n) \
+	RUNTIME_CHECK(isc_mutexblock_destroy((bp), (n)) == ISC_R_SUCCESS)
+
+/*
+ * List Macros.
+ */
+#include <isc/list.h>		/* Contractual promise. */
+
+#define LIST(type)			ISC_LIST(type)
+#define INIT_LIST(type)			ISC_LIST_INIT(type)
+#define LINK(type)			ISC_LINK(type)
+#define INIT_LINK(elt, link)		ISC_LINK_INIT(elt, link)
+#define HEAD(list)			ISC_LIST_HEAD(list)
+#define TAIL(list)			ISC_LIST_TAIL(list)
+#define EMPTY(list)			ISC_LIST_EMPTY(list)
+#define PREV(elt, link)			ISC_LIST_PREV(elt, link)
+#define NEXT(elt, link)			ISC_LIST_NEXT(elt, link)
+#define APPEND(list, elt, link)		ISC_LIST_APPEND(list, elt, link)
+#define PREPEND(list, elt, link)	ISC_LIST_PREPEND(list, elt, link)
+#define UNLINK(list, elt, link)		ISC_LIST_UNLINK(list, elt, link)
+#define ENQUEUE(list, elt, link)	ISC_LIST_APPEND(list, elt, link)
+#define DEQUEUE(list, elt, link)	ISC_LIST_UNLINK(list, elt, link)
+#define INSERTBEFORE(li, b, e, ln)	ISC_LIST_INSERTBEFORE(li, b, e, ln)
+#define INSERTAFTER(li, a, e, ln)	ISC_LIST_INSERTAFTER(li, a, e, ln)
+#define APPENDLIST(list1, list2, link)	ISC_LIST_APPENDLIST(list1, list2, link)
+
+/*
+ * Assertions
+ */
+#include <isc/assertions.h>	/* Contractual promise. */
+
+/*% Require Assertion */
+#define REQUIRE(e)			ISC_REQUIRE(e)
+/*% Ensure Assertion */
+#define ENSURE(e)			ISC_ENSURE(e)
+/*% Insist Assertion */
+#define INSIST(e)			ISC_INSIST(e)
+/*% Invariant Assertion */
+#define INVARIANT(e)			ISC_INVARIANT(e)
+
+/*
+ * Errors
+ */
+#include <isc/error.h>		/* Contractual promise. */
+
+/*% Unexpected Error */
+#define UNEXPECTED_ERROR		isc_error_unexpected
+/*% Fatal Error */
+#define FATAL_ERROR			isc_error_fatal
+/*% Runtime Check */
+#define RUNTIME_CHECK(cond)		ISC_ERROR_RUNTIMECHECK(cond)
+
+/*%
+ * Time
+ */
+#define TIME_NOW(tp) 	RUNTIME_CHECK(isc_time_now((tp)) == ISC_R_SUCCESS)
+
+/*%
+ * Prevent Linux spurious warnings
+ */
+#if defined(__GNUC__) && (__GNUC__ > 3)
+#define isc_util_fwrite(a, b, c, d)	\
+	__builtin_expect(fwrite((a), (b), (c), (d)), (c))
+#else
+#define isc_util_fwrite(a, b, c, d)	fwrite((a), (b), (c), (d))
+#endif
+
+#endif /* ISC_UTIL_H */
diff --git a/src/lib/bind9/include/isc/version.h b/src/lib/bind9/include/isc/version.h
new file mode 100644
index 0000000..1be37b6
--- /dev/null
+++ b/src/lib/bind9/include/isc/version.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: version.h,v 1.9 2007-06-19 23:47:18 tbox Exp $ */
+
+/*! \file isc/version.h */
+
+#include <isc/platform.h>
+
+LIBISC_EXTERNAL_DATA extern const char isc_version[];
+
+LIBISC_EXTERNAL_DATA extern const unsigned int isc_libinterface;
+LIBISC_EXTERNAL_DATA extern const unsigned int isc_librevision;
+LIBISC_EXTERNAL_DATA extern const unsigned int isc_libage;
diff --git a/src/lib/bind9/include/isc/xml.h b/src/lib/bind9/include/isc/xml.h
new file mode 100644
index 0000000..afbfa2b
--- /dev/null
+++ b/src/lib/bind9/include/isc/xml.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2006, 2007  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: xml.h,v 1.4 2007-06-19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_XML_H
+#define ISC_XML_H 1
+
+/*
+ * This file is here mostly to make it easy to add additional libxml header
+ * files as needed across all the users of this file.  Rather than place
+ * these libxml includes in each file, one include makes it easy to handle
+ * the ifdef as well as adding the ability to add additional functions
+ * which may be useful.
+ */
+
+#ifdef HAVE_LIBXML2
+#include <libxml/encoding.h>
+#include <libxml/xmlwriter.h>
+#endif
+
+#define ISC_XMLCHAR (const xmlChar *)
+
+#define ISC_XML_RENDERCONFIG		0x00000001 /* render config data */
+#define ISC_XML_RENDERSTATS		0x00000002 /* render stats */
+#define ISC_XML_RENDERALL		0x000000ff /* render everything */
+
+#endif /* ISC_XML_H */
diff --git a/src/lib/bind9/inet_aton.c b/src/lib/bind9/inet_aton.c
new file mode 100644
index 0000000..9e35a36
--- /dev/null
+++ b/src/lib/bind9/inet_aton.c
@@ -0,0 +1,196 @@
+/*
+ * Portions Copyright (C) 2004, 2005, 2007, 2008  Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 1996-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Copyright (c) 1983, 1990, 1993
+ *    The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ * 	This product includes software developed by the University of
+ * 	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+/*! \file */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)inet_addr.c	8.1 (Berkeley) 6/17/93";
+static char rcsid[] = "$Id: inet_aton.c,v 1.23 2008-12-01 23:47:45 tbox Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <config.h>
+
+#include <ctype.h>
+#include <stddef.h>		/* Required for NULL. */
+
+#include <isc/types.h>
+#include <isc/net.h>
+
+/*%
+ * Check whether "cp" is a valid ascii representation
+ * of an Internet address and convert to a binary address.
+ * Returns 1 if the address is valid, 0 if not.
+ * This replaces inet_addr, the return value from which
+ * cannot distinguish between failure and a local broadcast address.
+ */
+int
+isc_net_aton(const char *cp, struct in_addr *addr) {
+	unsigned long val;
+	int base, n;
+	unsigned char c;
+	isc_uint8_t parts[4];
+	isc_uint8_t *pp = parts;
+	int digit;
+
+	c = *cp;
+	for (;;) {
+		/*
+		 * Collect number up to ``.''.
+		 * Values are specified as for C:
+		 * 0x=hex, 0=octal, isdigit=decimal.
+		 */
+		if (!isdigit(c & 0xff))
+			return (0);
+		val = 0; base = 10; digit = 0;
+		if (c == '0') {
+			c = *++cp;
+			if (c == 'x' || c == 'X')
+				base = 16, c = *++cp;
+			else {
+				base = 8;
+				digit = 1;
+			}
+		}
+		for (;;) {
+			/*
+			 * isascii() is valid for all integer values, and
+			 * when it is true, c is known to be in scope
+			 * for isdigit().  No cast necessary.  Similar
+			 * comment applies for later ctype uses.
+			 */
+			if (isascii(c) && isdigit(c)) {
+				if (base == 8 && (c == '8' || c == '9'))
+					return (0);
+				val = (val * base) + (c - '0');
+				c = *++cp;
+				digit = 1;
+			} else if (base == 16 && isascii(c) && isxdigit(c)) {
+				val = (val << 4) |
+					(c + 10 - (islower(c) ? 'a' : 'A'));
+				c = *++cp;
+				digit = 1;
+			} else
+				break;
+		}
+		if (c == '.') {
+			/*
+			 * Internet format:
+			 *	a.b.c.d
+			 *	a.b.c	(with c treated as 16 bits)
+			 *	a.b	(with b treated as 24 bits)
+			 */
+			if (pp >= parts + 3 || val > 0xffU)
+				return (0);
+			*pp++ = (isc_uint8_t)val;
+			c = *++cp;
+		} else
+			break;
+	}
+	/*
+	 * Check for trailing characters.
+	 */
+	if (c != '\0' && (!isascii(c) || !isspace(c)))
+		return (0);
+	/*
+	 * Did we get a valid digit?
+	 */
+	if (!digit)
+		return (0);
+	/*
+	 * Concoct the address according to
+	 * the number of parts specified.
+	 */
+	n = pp - parts + 1;
+	switch (n) {
+	case 1:				/* a -- 32 bits */
+		break;
+
+	case 2:				/* a.b -- 8.24 bits */
+		if (val > 0xffffffU)
+			return (0);
+		val |= parts[0] << 24;
+		break;
+
+	case 3:				/* a.b.c -- 8.8.16 bits */
+		if (val > 0xffffU)
+			return (0);
+		val |= (parts[0] << 24) | (parts[1] << 16);
+		break;
+
+	case 4:				/* a.b.c.d -- 8.8.8.8 bits */
+		if (val > 0xffU)
+			return (0);
+		val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
+		break;
+	}
+	if (addr != NULL)
+		addr->s_addr = htonl(val);
+
+	return (1);
+}
diff --git a/src/lib/bind9/inet_ntop.c b/src/lib/bind9/inet_ntop.c
new file mode 100644
index 0000000..581ebe8
--- /dev/null
+++ b/src/lib/bind9/inet_ntop.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1996-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*! \file */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char rcsid[] =
+	"$Id: inet_ntop.c,v 1.21 2009-07-17 23:47:41 tbox Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <config.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <isc/net.h>
+#include <isc/print.h>
+
+#define NS_INT16SZ	 2
+#define NS_IN6ADDRSZ	16
+
+/*
+ * WARNING: Don't even consider trying to compile this on a system where
+ * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
+ */
+
+static const char *inet_ntop4(const unsigned char *src, char *dst,
+			      size_t size);
+
+#ifdef AF_INET6
+static const char *inet_ntop6(const unsigned char *src, char *dst,
+			      size_t size);
+#endif
+
+/*! char *
+ * isc_net_ntop(af, src, dst, size)
+ *	convert a network format address to presentation format.
+ * \return
+ *	pointer to presentation format address (`dst'), or NULL (see errno).
+ * \author
+ *	Paul Vixie, 1996.
+ */
+const char *
+isc_net_ntop(int af, const void *src, char *dst, size_t size)
+{
+	switch (af) {
+	case AF_INET:
+		return (inet_ntop4(src, dst, size));
+#ifdef AF_INET6
+	case AF_INET6:
+		return (inet_ntop6(src, dst, size));
+#endif
+	default:
+		errno = EAFNOSUPPORT;
+		return (NULL);
+	}
+	/* NOTREACHED */
+}
+
+/*! const char *
+ * inet_ntop4(src, dst, size)
+ *	format an IPv4 address
+ * \return
+ *	`dst' (as a const)
+ * \note
+ *	(1) uses no statics
+ * \note
+ *	(2) takes a unsigned char* not an in_addr as input
+ * \author
+ *	Paul Vixie, 1996.
+ */
+static const char *
+inet_ntop4(const unsigned char *src, char *dst, size_t size)
+{
+	static const char *fmt = "%u.%u.%u.%u";
+	char tmp[sizeof("255.255.255.255")];
+
+	if ((size_t)sprintf(tmp, fmt, src[0], src[1], src[2], src[3]) >= size)
+	{
+		errno = ENOSPC;
+		return (NULL);
+	}
+	strcpy(dst, tmp);
+
+	return (dst);
+}
+
+/*! const char *
+ * isc_inet_ntop6(src, dst, size)
+ *	convert IPv6 binary address into presentation (printable) format
+ * \author
+ *	Paul Vixie, 1996.
+ */
+#ifdef AF_INET6
+static const char *
+inet_ntop6(const unsigned char *src, char *dst, size_t size)
+{
+	/*
+	 * Note that int32_t and int16_t need only be "at least" large enough
+	 * to contain a value of the specified size.  On some systems, like
+	 * Crays, there is no such thing as an integer variable with 16 bits.
+	 * Keep this in mind if you think this function should have been coded
+	 * to use pointer overlays.  All the world's not a VAX.
+	 */
+	char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")], *tp;
+	struct { int base, len; } best, cur;
+	unsigned int words[NS_IN6ADDRSZ / NS_INT16SZ];
+	int i;
+
+	/*
+	 * Preprocess:
+	 *	Copy the input (bytewise) array into a wordwise array.
+	 *	Find the longest run of 0x00's in src[] for :: shorthanding.
+	 */
+	memset(words, '\0', sizeof(words));
+	for (i = 0; i < NS_IN6ADDRSZ; i++)
+		words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
+	best.base = -1;
+	cur.base = -1;
+	for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
+		if (words[i] == 0) {
+			if (cur.base == -1)
+				cur.base = i, cur.len = 1;
+			else
+				cur.len++;
+		} else {
+			if (cur.base != -1) {
+				if (best.base == -1 || cur.len > best.len)
+					best = cur;
+				cur.base = -1;
+			}
+		}
+	}
+	if (cur.base != -1) {
+		if (best.base == -1 || cur.len > best.len)
+			best = cur;
+	}
+	if (best.base != -1 && best.len < 2)
+		best.base = -1;
+
+	/*
+	 * Format the result.
+	 */
+	tp = tmp;
+	for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
+		/* Are we inside the best run of 0x00's? */
+		if (best.base != -1 && i >= best.base &&
+		    i < (best.base + best.len)) {
+			if (i == best.base)
+				*tp++ = ':';
+			continue;
+		}
+		/* Are we following an initial run of 0x00s or any real hex? */
+		if (i != 0)
+			*tp++ = ':';
+		/* Is this address an encapsulated IPv4? */
+		if (i == 6 && best.base == 0 && (best.len == 6 ||
+		    (best.len == 7 && words[7] != 0x0001) ||
+		    (best.len == 5 && words[5] == 0xffff))) {
+			if (!inet_ntop4(src+12, tp,
+					sizeof(tmp) - (tp - tmp)))
+				return (NULL);
+			tp += strlen(tp);
+			break;
+		}
+		tp += sprintf(tp, "%x", words[i]);
+	}
+	/* Was it a trailing run of 0x00's? */
+	if (best.base != -1 && (best.base + best.len) ==
+	    (NS_IN6ADDRSZ / NS_INT16SZ))
+		*tp++ = ':';
+	*tp++ = '\0';
+
+	/*
+	 * Check for overflow, copy, and we're done.
+	 */
+	if ((size_t)(tp - tmp) > size) {
+		errno = ENOSPC;
+		return (NULL);
+	}
+	strcpy(dst, tmp);
+	return (dst);
+}
+#endif /* AF_INET6 */
diff --git a/src/lib/bind9/inet_pton.c b/src/lib/bind9/inet_pton.c
new file mode 100644
index 0000000..65901ba
--- /dev/null
+++ b/src/lib/bind9/inet_pton.c
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1996-2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*! \file */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char rcsid[] =
+	"$Id: inet_pton.c,v 1.19 2007-06-19 23:47:17 tbox Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <config.h>
+
+#include <errno.h>
+#include <string.h>
+
+#include <isc/net.h>
+
+/*% INT16 Size */
+#define NS_INT16SZ	 2
+/*% IPv4 Address Size */
+#define NS_INADDRSZ	 4
+/*% IPv6 Address Size */
+#define NS_IN6ADDRSZ	16
+
+/*
+ * WARNING: Don't even consider trying to compile this on a system where
+ * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
+ */
+
+static int inet_pton4(const char *src, unsigned char *dst);
+static int inet_pton6(const char *src, unsigned char *dst);
+
+/*% 
+ *	convert from presentation format (which usually means ASCII printable)
+ *	to network format (which is usually some kind of binary format).
+ * \return
+ *	1 if the address was valid for the specified address family
+ *	0 if the address wasn't valid (`dst' is untouched in this case)
+ *	-1 if some other error occurred (`dst' is untouched in this case, too)
+ * \author
+ *	Paul Vixie, 1996.
+ */
+int
+isc_net_pton(int af, const char *src, void *dst) {
+	switch (af) {
+	case AF_INET:
+		return (inet_pton4(src, dst));
+	case AF_INET6:
+		return (inet_pton6(src, dst));
+	default:
+		errno = EAFNOSUPPORT;
+		return (-1);
+	}
+	/* NOTREACHED */
+}
+
+/*!\fn static int inet_pton4(const char *src, unsigned char *dst)
+ * \brief
+ *	like inet_aton() but without all the hexadecimal and shorthand.
+ * \return
+ *	1 if `src' is a valid dotted quad, else 0.
+ * \note
+ *	does not touch `dst' unless it's returning 1.
+ * \author
+ *	Paul Vixie, 1996.
+ */
+static int
+inet_pton4(const char *src, unsigned char *dst) {
+	static const char digits[] = "0123456789";
+	int saw_digit, octets, ch;
+	unsigned char tmp[NS_INADDRSZ], *tp;
+
+	saw_digit = 0;
+	octets = 0;
+	*(tp = tmp) = 0;
+	while ((ch = *src++) != '\0') {
+		const char *pch;
+
+		if ((pch = strchr(digits, ch)) != NULL) {
+			unsigned int new = *tp * 10 + (pch - digits);
+
+			if (saw_digit && *tp == 0)
+				return (0);
+			if (new > 255)
+				return (0);
+			*tp = new;
+			if (!saw_digit) {
+				if (++octets > 4)
+					return (0);
+				saw_digit = 1;
+			}
+		} else if (ch == '.' && saw_digit) {
+			if (octets == 4)
+				return (0);
+			*++tp = 0;
+			saw_digit = 0;
+		} else
+			return (0);
+	}
+	if (octets < 4)
+		return (0);
+	memcpy(dst, tmp, NS_INADDRSZ);
+	return (1);
+}
+
+/*%
+ *	convert presentation level address to network order binary form.
+ * \return
+ *	1 if `src' is a valid [RFC1884 2.2] address, else 0.
+ * \note
+ *	(1) does not touch `dst' unless it's returning 1.
+ * \note
+ *	(2) :: in a full address is silently ignored.
+ * \author
+ *	inspired by Mark Andrews.
+ * \author
+ *	Paul Vixie, 1996.
+ */
+static int
+inet_pton6(const char *src, unsigned char *dst) {
+	static const char xdigits_l[] = "0123456789abcdef",
+			  xdigits_u[] = "0123456789ABCDEF";
+	unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
+	const char *xdigits, *curtok;
+	int ch, seen_xdigits;
+	unsigned int val;
+
+	memset((tp = tmp), '\0', NS_IN6ADDRSZ);
+	endp = tp + NS_IN6ADDRSZ;
+	colonp = NULL;
+	/* Leading :: requires some special handling. */
+	if (*src == ':')
+		if (*++src != ':')
+			return (0);
+	curtok = src;
+	seen_xdigits = 0;
+	val = 0;
+	while ((ch = *src++) != '\0') {
+		const char *pch;
+
+		if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
+			pch = strchr((xdigits = xdigits_u), ch);
+		if (pch != NULL) {
+			val <<= 4;
+			val |= (pch - xdigits);
+			if (++seen_xdigits > 4)
+				return (0);
+			continue;
+		}
+		if (ch == ':') {
+			curtok = src;
+			if (!seen_xdigits) {
+				if (colonp)
+					return (0);
+				colonp = tp;
+				continue;
+			}
+			if (tp + NS_INT16SZ > endp)
+				return (0);
+			*tp++ = (unsigned char) (val >> 8) & 0xff;
+			*tp++ = (unsigned char) val & 0xff;
+			seen_xdigits = 0;
+			val = 0;
+			continue;
+		}
+		if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
+		    inet_pton4(curtok, tp) > 0) {
+			tp += NS_INADDRSZ;
+			seen_xdigits = 0;
+			break;	/* '\0' was seen by inet_pton4(). */
+		}
+		return (0);
+	}
+	if (seen_xdigits) {
+		if (tp + NS_INT16SZ > endp)
+			return (0);
+		*tp++ = (unsigned char) (val >> 8) & 0xff;
+		*tp++ = (unsigned char) val & 0xff;
+	}
+	if (colonp != NULL) {
+		/*
+		 * Since some memmove()'s erroneously fail to handle
+		 * overlapping regions, we'll do the shift by hand.
+		 */
+		const int n = tp - colonp;
+		int i;
+
+		if (tp == endp)
+			return (0);
+		for (i = 1; i <= n; i++) {
+			endp[- i] = colonp[n - i];
+			colonp[n - i] = 0;
+		}
+		tp = endp;
+	}
+	if (tp != endp)
+		return (0);
+	memcpy(dst, tmp, NS_IN6ADDRSZ);
+	return (1);
+}
diff --git a/src/lib/bind9/iterated_hash.c b/src/lib/bind9/iterated_hash.c
new file mode 100644
index 0000000..7185075
--- /dev/null
+++ b/src/lib/bind9/iterated_hash.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2006, 2008, 2009  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: iterated_hash.c,v 1.6 2009-02-18 23:47:48 tbox Exp $ */
+
+#include "config.h"
+
+#include <stdio.h>
+
+#include <isc/sha1.h>
+#include <isc/iterated_hash.h>
+
+int
+isc_iterated_hash(unsigned char out[ISC_SHA1_DIGESTLENGTH],
+		  unsigned int hashalg, int iterations,
+		  const unsigned char *salt, int saltlength,
+		  const unsigned char *in, int inlength)
+{
+	isc_sha1_t ctx;
+	int n = 0;
+
+	if (hashalg != 1)
+		return (0);
+
+	do {
+		isc_sha1_init(&ctx);
+		isc_sha1_update(&ctx, in, inlength);
+		isc_sha1_update(&ctx, salt, saltlength);
+		isc_sha1_final(&ctx, out);
+		in = out;
+		inlength = ISC_SHA1_DIGESTLENGTH;
+	} while (n++ < iterations);
+
+	return (ISC_SHA1_DIGESTLENGTH);
+}
diff --git a/src/lib/bind9/lex.c b/src/lib/bind9/lex.c
new file mode 100644
index 0000000..41db5fe
--- /dev/null
+++ b/src/lib/bind9/lex.c
@@ -0,0 +1,959 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: lex.c,v 1.86 2007-09-17 09:56:29 shane Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include <isc/buffer.h>
+#include <isc/file.h>
+#include <isc/lex.h>
+#include <isc/mem.h>
+#include <isc/msgs.h>
+#include <isc/parseint.h>
+#include <isc/print.h>
+#include <isc/stdio.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+typedef struct inputsource {
+	isc_result_t			result;
+	isc_boolean_t			is_file;
+	isc_boolean_t			need_close;
+	isc_boolean_t			at_eof;
+	isc_buffer_t *			pushback;
+	unsigned int			ignored;
+	void *				input;
+	char *				name;
+	unsigned long			line;
+	unsigned long			saved_line;
+	ISC_LINK(struct inputsource)	link;
+} inputsource;
+
+#define LEX_MAGIC			ISC_MAGIC('L', 'e', 'x', '!')
+#define VALID_LEX(l)			ISC_MAGIC_VALID(l, LEX_MAGIC)
+
+struct isc_lex {
+	/* Unlocked. */
+	unsigned int			magic;
+	isc_mem_t *			mctx;
+	size_t				max_token;
+	char *				data;
+	unsigned int			comments;
+	isc_boolean_t			comment_ok;
+	isc_boolean_t			last_was_eol;
+	unsigned int			paren_count;
+	unsigned int			saved_paren_count;
+	isc_lexspecials_t		specials;
+	LIST(struct inputsource)	sources;
+};
+
+static inline isc_result_t
+grow_data(isc_lex_t *lex, size_t *remainingp, char **currp, char **prevp) {
+	char *new;
+
+	new = isc_mem_get(lex->mctx, lex->max_token * 2 + 1);
+	if (new == NULL)
+		return (ISC_R_NOMEMORY);
+	memcpy(new, lex->data, lex->max_token + 1);
+	*currp = new + (*currp - lex->data);
+	if (*prevp != NULL)
+		*prevp = new + (*prevp - lex->data);
+	isc_mem_put(lex->mctx, lex->data, lex->max_token + 1);
+	lex->data = new;
+	*remainingp += lex->max_token;
+	lex->max_token *= 2;
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_lex_create(isc_mem_t *mctx, size_t max_token, isc_lex_t **lexp) {
+	isc_lex_t *lex;
+
+	/*
+	 * Create a lexer.
+	 */
+
+	REQUIRE(lexp != NULL && *lexp == NULL);
+	REQUIRE(max_token > 0U);
+
+	lex = isc_mem_get(mctx, sizeof(*lex));
+	if (lex == NULL)
+		return (ISC_R_NOMEMORY);
+	lex->data = isc_mem_get(mctx, max_token + 1);
+	if (lex->data == NULL) {
+		isc_mem_put(mctx, lex, sizeof(*lex));
+		return (ISC_R_NOMEMORY);
+	}
+	lex->mctx = mctx;
+	lex->max_token = max_token;
+	lex->comments = 0;
+	lex->comment_ok = ISC_TRUE;
+	lex->last_was_eol = ISC_TRUE;
+	lex->paren_count = 0;
+	lex->saved_paren_count = 0;
+	memset(lex->specials, 0, 256);
+	INIT_LIST(lex->sources);
+	lex->magic = LEX_MAGIC;
+
+	*lexp = lex;
+
+	return (ISC_R_SUCCESS);
+}
+
+void
+isc_lex_destroy(isc_lex_t **lexp) {
+	isc_lex_t *lex;
+
+	/*
+	 * Destroy the lexer.
+	 */
+
+	REQUIRE(lexp != NULL);
+	lex = *lexp;
+	REQUIRE(VALID_LEX(lex));
+
+	while (!EMPTY(lex->sources))
+		RUNTIME_CHECK(isc_lex_close(lex) == ISC_R_SUCCESS);
+	if (lex->data != NULL)
+		isc_mem_put(lex->mctx, lex->data, lex->max_token + 1);
+	lex->magic = 0;
+	isc_mem_put(lex->mctx, lex, sizeof(*lex));
+
+	*lexp = NULL;
+}
+
+unsigned int
+isc_lex_getcomments(isc_lex_t *lex) {
+	/*
+	 * Return the current lexer commenting styles.
+	 */
+
+	REQUIRE(VALID_LEX(lex));
+
+	return (lex->comments);
+}
+
+void
+isc_lex_setcomments(isc_lex_t *lex, unsigned int comments) {
+	/*
+	 * Set allowed lexer commenting styles.
+	 */
+
+	REQUIRE(VALID_LEX(lex));
+
+	lex->comments = comments;
+}
+
+void
+isc_lex_getspecials(isc_lex_t *lex, isc_lexspecials_t specials) {
+	/*
+	 * Put the current list of specials into 'specials'.
+	 */
+
+	REQUIRE(VALID_LEX(lex));
+
+	memcpy(specials, lex->specials, 256);
+}
+
+void
+isc_lex_setspecials(isc_lex_t *lex, isc_lexspecials_t specials) {
+	/*
+	 * The characters in 'specials' are returned as tokens.  Along with
+	 * whitespace, they delimit strings and numbers.
+	 */
+
+	REQUIRE(VALID_LEX(lex));
+
+	memcpy(lex->specials, specials, 256);
+}
+
+static inline isc_result_t
+new_source(isc_lex_t *lex, isc_boolean_t is_file, isc_boolean_t need_close,
+	   void *input, const char *name)
+{
+	inputsource *source;
+	isc_result_t result;
+
+	source = isc_mem_get(lex->mctx, sizeof(*source));
+	if (source == NULL)
+		return (ISC_R_NOMEMORY);
+	source->result = ISC_R_SUCCESS;
+	source->is_file = is_file;
+	source->need_close = need_close;
+	source->at_eof = ISC_FALSE;
+	source->input = input;
+	source->name = isc_mem_strdup(lex->mctx, name);
+	if (source->name == NULL) {
+		isc_mem_put(lex->mctx, source, sizeof(*source));
+		return (ISC_R_NOMEMORY);
+	}
+	source->pushback = NULL;
+	result = isc_buffer_allocate(lex->mctx, &source->pushback,
+				     lex->max_token);
+	if (result != ISC_R_SUCCESS) {
+		isc_mem_free(lex->mctx, source->name);
+		isc_mem_put(lex->mctx, source, sizeof(*source));
+		return (result);
+	}
+	source->ignored = 0;
+	source->line = 1;
+	ISC_LIST_INITANDPREPEND(lex->sources, source, link);
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_lex_openfile(isc_lex_t *lex, const char *filename) {
+	isc_result_t result;
+	FILE *stream = NULL;
+
+	/*
+	 * Open 'filename' and make it the current input source for 'lex'.
+	 */
+
+	REQUIRE(VALID_LEX(lex));
+
+	result = isc_stdio_open(filename, "r", &stream);
+	if (result != ISC_R_SUCCESS)
+		return (result);
+
+	result = new_source(lex, ISC_TRUE, ISC_TRUE, stream, filename);
+	if (result != ISC_R_SUCCESS)
+		(void)fclose(stream);
+	return (result);
+}
+
+isc_result_t
+isc_lex_openstream(isc_lex_t *lex, FILE *stream) {
+	char name[128];
+
+	/*
+	 * Make 'stream' the current input source for 'lex'.
+	 */
+
+	REQUIRE(VALID_LEX(lex));
+
+	snprintf(name, sizeof(name), "stream-%p", stream);
+
+	return (new_source(lex, ISC_TRUE, ISC_FALSE, stream, name));
+}
+
+isc_result_t
+isc_lex_openbuffer(isc_lex_t *lex, isc_buffer_t *buffer) {
+	char name[128];
+
+	/*
+	 * Make 'buffer' the current input source for 'lex'.
+	 */
+
+	REQUIRE(VALID_LEX(lex));
+
+	snprintf(name, sizeof(name), "buffer-%p", buffer);
+
+	return (new_source(lex, ISC_FALSE, ISC_FALSE, buffer, name));
+}
+
+isc_result_t
+isc_lex_close(isc_lex_t *lex) {
+	inputsource *source;
+
+	/*
+	 * Close the most recently opened object (i.e. file or buffer).
+	 */
+
+	REQUIRE(VALID_LEX(lex));
+
+	source = HEAD(lex->sources);
+	if (source == NULL)
+		return (ISC_R_NOMORE);
+
+	ISC_LIST_UNLINK(lex->sources, source, link);
+	if (source->is_file) {
+		if (source->need_close)
+			(void)fclose((FILE *)(source->input));
+	}
+	isc_mem_free(lex->mctx, source->name);
+	isc_buffer_free(&source->pushback);
+	isc_mem_put(lex->mctx, source, sizeof(*source));
+
+	return (ISC_R_SUCCESS);
+}
+
+typedef enum {
+	lexstate_start,
+	lexstate_crlf,
+	lexstate_string,
+	lexstate_number,
+	lexstate_maybecomment,
+	lexstate_ccomment,
+	lexstate_ccommentend,
+	lexstate_eatline,
+	lexstate_qstring
+} lexstate;
+
+#define IWSEOL (ISC_LEXOPT_INITIALWS | ISC_LEXOPT_EOL)
+
+static void
+pushback(inputsource *source, int c) {
+	REQUIRE(source->pushback->current > 0);
+	if (c == EOF) {
+		source->at_eof = ISC_FALSE;
+		return;
+	}
+	source->pushback->current--;
+	if (c == '\n')
+		source->line--;
+}
+
+static isc_result_t
+pushandgrow(isc_lex_t *lex, inputsource *source, int c) {
+	if (isc_buffer_availablelength(source->pushback) == 0) {
+		isc_buffer_t *tbuf = NULL;
+		unsigned int oldlen;
+		isc_region_t used;
+		isc_result_t result;
+
+		oldlen = isc_buffer_length(source->pushback);
+		result = isc_buffer_allocate(lex->mctx, &tbuf, oldlen * 2);
+		if (result != ISC_R_SUCCESS)
+			return (result);
+		isc_buffer_usedregion(source->pushback, &used);
+		result = isc_buffer_copyregion(tbuf, &used);
+		INSIST(result == ISC_R_SUCCESS);
+		tbuf->current = source->pushback->current;
+		isc_buffer_free(&source->pushback);
+		source->pushback = tbuf;
+	}
+	isc_buffer_putuint8(source->pushback, (isc_uint8_t)c);
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_lex_gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *tokenp) {
+	inputsource *source;
+	int c;
+	isc_boolean_t done = ISC_FALSE;
+	isc_boolean_t no_comments = ISC_FALSE;
+	isc_boolean_t escaped = ISC_FALSE;
+	lexstate state = lexstate_start;
+	lexstate saved_state = lexstate_start;
+	isc_buffer_t *buffer;
+	FILE *stream;
+	char *curr, *prev;
+	size_t remaining;
+	isc_uint32_t as_ulong;
+	unsigned int saved_options;
+	isc_result_t result;
+
+	/*
+	 * Get the next token.
+	 */
+
+	REQUIRE(VALID_LEX(lex));
+	source = HEAD(lex->sources);
+	REQUIRE(tokenp != NULL);
+
+	if (source == NULL) {
+		if ((options & ISC_LEXOPT_NOMORE) != 0) {
+			tokenp->type = isc_tokentype_nomore;
+			return (ISC_R_SUCCESS);
+		}
+		return (ISC_R_NOMORE);
+	}
+
+	if (source->result != ISC_R_SUCCESS)
+		return (source->result);
+
+	lex->saved_paren_count = lex->paren_count;
+	source->saved_line = source->line;
+
+	if (isc_buffer_remaininglength(source->pushback) == 0 &&
+	    source->at_eof)
+	{
+		if ((options & ISC_LEXOPT_DNSMULTILINE) != 0 &&
+		    lex->paren_count != 0) {
+			lex->paren_count = 0;
+			return (ISC_R_UNBALANCED);
+		}
+		if ((options & ISC_LEXOPT_EOF) != 0) {
+			tokenp->type = isc_tokentype_eof;
+			return (ISC_R_SUCCESS);
+		}
+		return (ISC_R_EOF);
+	}
+
+	isc_buffer_compact(source->pushback);
+
+	saved_options = options;
+	if ((options & ISC_LEXOPT_DNSMULTILINE) != 0 && lex->paren_count > 0)
+		options &= ~IWSEOL;
+
+	curr = lex->data;
+	*curr = '\0';
+
+	prev = NULL;
+	remaining = lex->max_token;
+
+#ifdef HAVE_FLOCKFILE
+	if (source->is_file)
+		flockfile(source->input);
+#endif
+
+	do {
+		if (isc_buffer_remaininglength(source->pushback) == 0) {
+			if (source->is_file) {
+				stream = source->input;
+
+#if defined(HAVE_FLOCKFILE) && defined(HAVE_GETCUNLOCKED)
+				c = getc_unlocked(stream);
+#else
+				c = getc(stream);
+#endif
+				if (c == EOF) {
+					if (ferror(stream)) {
+						source->result = ISC_R_IOERROR;
+						result = source->result;
+						goto done;
+					}
+					source->at_eof = ISC_TRUE;
+				}
+			} else {
+				buffer = source->input;
+
+				if (buffer->current == buffer->used) {
+					c = EOF;
+					source->at_eof = ISC_TRUE;
+				} else {
+					c = *((char *)buffer->base +
+					      buffer->current);
+					buffer->current++;
+				}
+			}
+			if (c != EOF) {
+				source->result = pushandgrow(lex, source, c);
+				if (source->result != ISC_R_SUCCESS) {
+					result = source->result;
+					goto done;
+				}
+			}
+		}
+
+		if (!source->at_eof) {
+			if (state == lexstate_start)
+				/* Token has not started yet. */
+				source->ignored =
+				   isc_buffer_consumedlength(source->pushback);
+			c = isc_buffer_getuint8(source->pushback);
+		} else {
+			c = EOF;
+		}
+
+		if (c == '\n')
+			source->line++;
+
+		if (lex->comment_ok && !no_comments) {
+			if (!escaped && c == ';' &&
+			    ((lex->comments & ISC_LEXCOMMENT_DNSMASTERFILE)
+			     != 0)) {
+				saved_state = state;
+				state = lexstate_eatline;
+				no_comments = ISC_TRUE;
+				continue;
+			} else if (c == '/' &&
+				   (lex->comments &
+				    (ISC_LEXCOMMENT_C|
+				     ISC_LEXCOMMENT_CPLUSPLUS)) != 0) {
+				saved_state = state;
+				state = lexstate_maybecomment;
+				no_comments = ISC_TRUE;
+				continue;
+			} else if (c == '#' &&
+				   ((lex->comments & ISC_LEXCOMMENT_SHELL)
+				    != 0)) {
+				saved_state = state;
+				state = lexstate_eatline;
+				no_comments = ISC_TRUE;
+				continue;
+			}
+		}
+
+	no_read:
+		/* INSIST(c == EOF || (c >= 0 && c <= 255)); */
+		switch (state) {
+		case lexstate_start:
+			if (c == EOF) {
+				lex->last_was_eol = ISC_FALSE;
+				if ((options & ISC_LEXOPT_DNSMULTILINE) != 0 &&
+				    lex->paren_count != 0) {
+					lex->paren_count = 0;
+					result = ISC_R_UNBALANCED;
+					goto done;
+				}
+				if ((options & ISC_LEXOPT_EOF) == 0) {
+					result = ISC_R_EOF;
+					goto done;
+				}
+				tokenp->type = isc_tokentype_eof;
+				done = ISC_TRUE;
+			} else if (c == ' ' || c == '\t') {
+				if (lex->last_was_eol &&
+				    (options & ISC_LEXOPT_INITIALWS)
+				    != 0) {
+					lex->last_was_eol = ISC_FALSE;
+					tokenp->type = isc_tokentype_initialws;
+ 					tokenp->value.as_char = c;
+					done = ISC_TRUE;
+				}
+			} else if (c == '\n') {
+				if ((options & ISC_LEXOPT_EOL) != 0) {
+					tokenp->type = isc_tokentype_eol;
+					done = ISC_TRUE;
+				}
+				lex->last_was_eol = ISC_TRUE;
+			} else if (c == '\r') {
+				if ((options & ISC_LEXOPT_EOL) != 0)
+					state = lexstate_crlf;
+			} else if (c == '"' &&
+				   (options & ISC_LEXOPT_QSTRING) != 0) {
+				lex->last_was_eol = ISC_FALSE;
+				no_comments = ISC_TRUE;
+				state = lexstate_qstring;
+			} else if (lex->specials[c]) {
+				lex->last_was_eol = ISC_FALSE;
+				if ((c == '(' || c == ')') &&
+				    (options & ISC_LEXOPT_DNSMULTILINE) != 0) {
+					if (c == '(') {
+						if (lex->paren_count == 0)
+							options &= ~IWSEOL;
+						lex->paren_count++;
+					} else {
+						if (lex->paren_count == 0) {
+						    result = ISC_R_UNBALANCED;
+						    goto done;
+						}
+						lex->paren_count--;
+						if (lex->paren_count == 0)
+							options =
+								saved_options;
+					}
+					continue;
+				}
+				tokenp->type = isc_tokentype_special;
+				tokenp->value.as_char = c;
+				done = ISC_TRUE;
+			} else if (isdigit((unsigned char)c) &&
+				   (options & ISC_LEXOPT_NUMBER) != 0) {
+				lex->last_was_eol = ISC_FALSE;
+				if ((options & ISC_LEXOPT_OCTAL) != 0 &&
+				    (c == '8' || c == '9'))
+					state = lexstate_string;
+				else
+					state = lexstate_number;
+				goto no_read;
+			} else {
+				lex->last_was_eol = ISC_FALSE;
+				state = lexstate_string;
+				goto no_read;
+			}
+			break;
+		case lexstate_crlf:
+			if (c != '\n')
+				pushback(source, c);
+			tokenp->type = isc_tokentype_eol;
+			done = ISC_TRUE;
+			lex->last_was_eol = ISC_TRUE;
+			break;
+		case lexstate_number:
+			if (c == EOF || !isdigit((unsigned char)c)) {
+				if (c == ' ' || c == '\t' || c == '\r' ||
+				    c == '\n' || c == EOF ||
+				    lex->specials[c]) {
+					int base;
+					if ((options & ISC_LEXOPT_OCTAL) != 0)
+						base = 8;
+					else if ((options & ISC_LEXOPT_CNUMBER) != 0)
+						base = 0;
+					else
+						base = 10;
+					pushback(source, c);
+
+					result = isc_parse_uint32(&as_ulong,
+								  lex->data,
+								  base);
+					if (result == ISC_R_SUCCESS) {
+						tokenp->type =
+							isc_tokentype_number;
+						tokenp->value.as_ulong =
+							as_ulong;
+					} else if (result == ISC_R_BADNUMBER) {
+						isc_tokenvalue_t *v;
+
+						tokenp->type =
+							isc_tokentype_string;
+						v = &(tokenp->value);
+						v->as_textregion.base =
+							lex->data;
+						v->as_textregion.length =
+							lex->max_token -
+							remaining;
+					} else
+						goto done;
+					done = ISC_TRUE;
+					continue;
+				} else if (!(options & ISC_LEXOPT_CNUMBER) ||
+					   ((c != 'x' && c != 'X') ||
+					   (curr != &lex->data[1]) ||
+					   (lex->data[0] != '0'))) {
+					/* Above test supports hex numbers */
+					state = lexstate_string;
+				}
+			} else if ((options & ISC_LEXOPT_OCTAL) != 0 &&
+				   (c == '8' || c == '9')) {
+				state = lexstate_string;
+			}
+			if (remaining == 0U) {
+				result = grow_data(lex, &remaining,
+						   &curr, &prev);
+				if (result != ISC_R_SUCCESS)
+					goto done;
+			}
+			INSIST(remaining > 0U);
+			*curr++ = c;
+			*curr = '\0';
+			remaining--;
+			break;
+		case lexstate_string:
+			/*
+			 * EOF needs to be checked before lex->specials[c]
+			 * as lex->specials[EOF] is not a good idea.
+			 */
+			if (c == '\r' || c == '\n' || c == EOF ||
+			    (!escaped &&
+			     (c == ' ' || c == '\t' || lex->specials[c]))) {
+				pushback(source, c);
+				if (source->result != ISC_R_SUCCESS) {
+					result = source->result;
+					goto done;
+				}
+				tokenp->type = isc_tokentype_string;
+				tokenp->value.as_textregion.base = lex->data;
+				tokenp->value.as_textregion.length =
+					lex->max_token - remaining;
+				done = ISC_TRUE;
+				continue;
+			}
+			if ((options & ISC_LEXOPT_ESCAPE) != 0)
+				escaped = (!escaped && c == '\\') ?
+						ISC_TRUE : ISC_FALSE;
+			if (remaining == 0U) {
+				result = grow_data(lex, &remaining,
+						   &curr, &prev);
+				if (result != ISC_R_SUCCESS)
+					goto done;
+			}
+			INSIST(remaining > 0U);
+			*curr++ = c;
+			*curr = '\0';
+			remaining--;
+			break;
+		case lexstate_maybecomment:
+			if (c == '*' &&
+			    (lex->comments & ISC_LEXCOMMENT_C) != 0) {
+				state = lexstate_ccomment;
+				continue;
+			} else if (c == '/' &&
+			    (lex->comments & ISC_LEXCOMMENT_CPLUSPLUS) != 0) {
+				state = lexstate_eatline;
+				continue;
+			}
+			pushback(source, c);
+			c = '/';
+			no_comments = ISC_FALSE;
+			state = saved_state;
+			goto no_read;
+		case lexstate_ccomment:
+			if (c == EOF) {
+				result = ISC_R_UNEXPECTEDEND;
+				goto done;
+			}
+			if (c == '*')
+				state = lexstate_ccommentend;
+			break;
+		case lexstate_ccommentend:
+			if (c == EOF) {
+				result = ISC_R_UNEXPECTEDEND;
+				goto done;
+			}
+			if (c == '/') {
+				/*
+				 * C-style comments become a single space.
+				 * We do this to ensure that a comment will
+				 * act as a delimiter for strings and
+				 * numbers.
+				 */
+				c = ' ';
+				no_comments = ISC_FALSE;
+				state = saved_state;
+				goto no_read;
+			} else if (c != '*')
+				state = lexstate_ccomment;
+			break;
+		case lexstate_eatline:
+			if ((c == '\n') || (c == EOF)) {
+				no_comments = ISC_FALSE;
+				state = saved_state;
+				goto no_read;
+			}
+			break;
+		case lexstate_qstring:
+			if (c == EOF) {
+				result = ISC_R_UNEXPECTEDEND;
+				goto done;
+			}
+			if (c == '"') {
+				if (escaped) {
+					escaped = ISC_FALSE;
+					/*
+					 * Overwrite the preceding backslash.
+					 */
+					INSIST(prev != NULL);
+					*prev = '"';
+				} else {
+					tokenp->type = isc_tokentype_qstring;
+					tokenp->value.as_textregion.base =
+						lex->data;
+					tokenp->value.as_textregion.length =
+						lex->max_token - remaining;
+					no_comments = ISC_FALSE;
+					done = ISC_TRUE;
+				}
+			} else {
+				if (c == '\n' && !escaped &&
+			    (options & ISC_LEXOPT_QSTRINGMULTILINE) == 0) {
+					pushback(source, c);
+					result = ISC_R_UNBALANCEDQUOTES;
+					goto done;
+				}
+				if (c == '\\' && !escaped)
+					escaped = ISC_TRUE;
+				else
+					escaped = ISC_FALSE;
+				if (remaining == 0U) {
+					result = grow_data(lex, &remaining,
+							   &curr, &prev);
+					if (result != ISC_R_SUCCESS)
+						goto done;
+				}
+				INSIST(remaining > 0U);
+				prev = curr;
+				*curr++ = c;
+				*curr = '\0';
+				remaining--;
+			}
+			break;
+		default:
+			FATAL_ERROR(__FILE__, __LINE__,
+				    isc_msgcat_get(isc_msgcat, ISC_MSGSET_LEX,
+						   ISC_MSG_UNEXPECTEDSTATE,
+						   "Unexpected state %d"),
+				    state);
+			/* Does not return. */
+		}
+
+	} while (!done);
+
+	result = ISC_R_SUCCESS;
+ done:
+#ifdef HAVE_FLOCKFILE
+	if (source->is_file)
+		funlockfile(source->input);
+#endif
+	return (result);
+}
+
+isc_result_t
+isc_lex_getmastertoken(isc_lex_t *lex, isc_token_t *token,
+		       isc_tokentype_t expect, isc_boolean_t eol)
+{
+	unsigned int options = ISC_LEXOPT_EOL | ISC_LEXOPT_EOF |
+			       ISC_LEXOPT_DNSMULTILINE | ISC_LEXOPT_ESCAPE;
+	isc_result_t result;
+
+	if (expect == isc_tokentype_qstring)
+		options |= ISC_LEXOPT_QSTRING;
+	else if (expect == isc_tokentype_number)
+		options |= ISC_LEXOPT_NUMBER;
+	result = isc_lex_gettoken(lex, options, token);
+	if (result == ISC_R_RANGE)
+		isc_lex_ungettoken(lex, token);
+	if (result != ISC_R_SUCCESS)
+		return (result);
+
+	if (eol && ((token->type == isc_tokentype_eol) ||
+		    (token->type == isc_tokentype_eof)))
+		return (ISC_R_SUCCESS);
+	if (token->type == isc_tokentype_string &&
+	    expect == isc_tokentype_qstring)
+		return (ISC_R_SUCCESS);
+	if (token->type != expect) {
+		isc_lex_ungettoken(lex, token);
+		if (token->type == isc_tokentype_eol ||
+		    token->type == isc_tokentype_eof)
+			return (ISC_R_UNEXPECTEDEND);
+		if (expect == isc_tokentype_number)
+			return (ISC_R_BADNUMBER);
+		return (ISC_R_UNEXPECTEDTOKEN);
+	}
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_lex_getoctaltoken(isc_lex_t *lex, isc_token_t *token, isc_boolean_t eol)
+{
+	unsigned int options = ISC_LEXOPT_EOL | ISC_LEXOPT_EOF |
+			       ISC_LEXOPT_DNSMULTILINE | ISC_LEXOPT_ESCAPE|
+			       ISC_LEXOPT_NUMBER | ISC_LEXOPT_OCTAL;
+	isc_result_t result;
+
+	result = isc_lex_gettoken(lex, options, token);
+	if (result == ISC_R_RANGE)
+		isc_lex_ungettoken(lex, token);
+	if (result != ISC_R_SUCCESS)
+		return (result);
+
+	if (eol && ((token->type == isc_tokentype_eol) ||
+		    (token->type == isc_tokentype_eof)))
+		return (ISC_R_SUCCESS);
+	if (token->type != isc_tokentype_number) {
+		isc_lex_ungettoken(lex, token);
+		if (token->type == isc_tokentype_eol ||
+		    token->type == isc_tokentype_eof)
+			return (ISC_R_UNEXPECTEDEND);
+		return (ISC_R_BADNUMBER);
+	}
+	return (ISC_R_SUCCESS);
+}
+
+void
+isc_lex_ungettoken(isc_lex_t *lex, isc_token_t *tokenp) {
+	inputsource *source;
+	/*
+	 * Unget the current token.
+	 */
+
+	REQUIRE(VALID_LEX(lex));
+	source = HEAD(lex->sources);
+	REQUIRE(source != NULL);
+	REQUIRE(tokenp != NULL);
+	REQUIRE(isc_buffer_consumedlength(source->pushback) != 0 ||
+		tokenp->type == isc_tokentype_eof);
+
+	UNUSED(tokenp);
+
+	isc_buffer_first(source->pushback);
+	lex->paren_count = lex->saved_paren_count;
+	source->line = source->saved_line;
+	source->at_eof = ISC_FALSE;
+}
+
+void
+isc_lex_getlasttokentext(isc_lex_t *lex, isc_token_t *tokenp, isc_region_t *r)
+{
+	inputsource *source;
+
+	REQUIRE(VALID_LEX(lex));
+	source = HEAD(lex->sources);
+	REQUIRE(source != NULL);
+	REQUIRE(tokenp != NULL);
+	REQUIRE(isc_buffer_consumedlength(source->pushback) != 0 ||
+		tokenp->type == isc_tokentype_eof);
+
+	UNUSED(tokenp);
+
+	INSIST(source->ignored <= isc_buffer_consumedlength(source->pushback));
+	r->base = (unsigned char *)isc_buffer_base(source->pushback) +
+		  source->ignored;
+	r->length = isc_buffer_consumedlength(source->pushback) -
+		    source->ignored;
+}
+
+
+char *
+isc_lex_getsourcename(isc_lex_t *lex) {
+	inputsource *source;
+
+	REQUIRE(VALID_LEX(lex));
+	source = HEAD(lex->sources);
+
+	if (source == NULL)
+		return (NULL);
+
+	return (source->name);
+}
+
+unsigned long
+isc_lex_getsourceline(isc_lex_t *lex) {
+	inputsource *source;
+
+	REQUIRE(VALID_LEX(lex));
+	source = HEAD(lex->sources);
+
+	if (source == NULL)
+		return (0);
+
+	return (source->line);
+}
+
+
+isc_result_t
+isc_lex_setsourcename(isc_lex_t *lex, const char *name) {
+	inputsource *source;
+	char *newname;
+
+	REQUIRE(VALID_LEX(lex));
+	source = HEAD(lex->sources);
+
+	if (source == NULL)
+		return(ISC_R_NOTFOUND);
+	newname = isc_mem_strdup(lex->mctx, name);
+	if (newname == NULL)
+		return (ISC_R_NOMEMORY);
+	isc_mem_free(lex->mctx, source->name);
+	source->name = newname;
+	return (ISC_R_SUCCESS);
+}
+
+isc_boolean_t
+isc_lex_isfile(isc_lex_t *lex) {
+	inputsource *source;
+
+	REQUIRE(VALID_LEX(lex));
+
+	source = HEAD(lex->sources);
+
+	if (source == NULL)
+		return (ISC_FALSE);
+
+	return (source->is_file);
+}
diff --git a/src/lib/bind9/lfsr.c b/src/lib/bind9/lfsr.c
new file mode 100644
index 0000000..7c56634
--- /dev/null
+++ b/src/lib/bind9/lfsr.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: lfsr.c,v 1.20 2007-06-19 23:47:17 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#include <isc/assertions.h>
+#include <isc/lfsr.h>
+#include <isc/util.h>
+
+#define VALID_LFSR(x)	(x != NULL)
+
+void
+isc_lfsr_init(isc_lfsr_t *lfsr, isc_uint32_t state, unsigned int bits,
+	      isc_uint32_t tap, unsigned int count,
+	      isc_lfsrreseed_t reseed, void *arg)
+{
+	REQUIRE(VALID_LFSR(lfsr));
+	REQUIRE(8 <= bits && bits <= 32);
+	REQUIRE(tap != 0);
+
+	lfsr->state = state;
+	lfsr->bits = bits;
+	lfsr->tap = tap;
+	lfsr->count = count;
+	lfsr->reseed = reseed;
+	lfsr->arg = arg;
+
+	if (count == 0 && reseed != NULL)
+		reseed(lfsr, arg);
+	if (lfsr->state == 0)
+		lfsr->state = 0xffffffffU >> (32 - lfsr->bits);
+}
+
+/*!
+ * Return the next state of the lfsr.
+ */
+static inline isc_uint32_t
+lfsr_generate(isc_lfsr_t *lfsr)
+{
+
+	/*
+	 * If the previous state is zero, we must fill it with something
+	 * here, or we will begin to generate an extremely predictable output.
+	 *
+	 * First, give the reseed function a crack at it.  If the state is
+	 * still 0, set it to all ones.
+	 */
+	if (lfsr->state == 0) {
+		if (lfsr->reseed != NULL)
+			lfsr->reseed(lfsr, lfsr->arg);
+		if (lfsr->state == 0)
+			lfsr->state = 0xffffffffU >> (32 - lfsr->bits);
+	}
+
+	if (lfsr->state & 0x01) {
+		lfsr->state = (lfsr->state >> 1) ^ lfsr->tap;
+		return (1);
+	} else {
+		lfsr->state >>= 1;
+		return (0);
+	}
+}
+
+void
+isc_lfsr_generate(isc_lfsr_t *lfsr, void *data, unsigned int count)
+{
+	unsigned char *p;
+	unsigned int bit;
+	unsigned int byte;
+
+	REQUIRE(VALID_LFSR(lfsr));
+	REQUIRE(data != NULL);
+	REQUIRE(count > 0);
+
+	p = data;
+	byte = count;
+
+	while (byte--) {
+		*p = 0;
+		for (bit = 0; bit < 7; bit++) {
+			*p |= lfsr_generate(lfsr);
+			*p <<= 1;
+		}
+		*p |= lfsr_generate(lfsr);
+		p++;
+	}
+
+	if (lfsr->count != 0 && lfsr->reseed != NULL) {
+		if (lfsr->count <= count * 8)
+			lfsr->reseed(lfsr, lfsr->arg);
+		else
+			lfsr->count -= (count * 8);
+	}
+}
+
+static inline isc_uint32_t
+lfsr_skipgenerate(isc_lfsr_t *lfsr, unsigned int skip)
+{
+	while (skip--)
+		(void)lfsr_generate(lfsr);
+
+	(void)lfsr_generate(lfsr);
+
+	return (lfsr->state);
+}
+
+/*
+ * Skip "skip" states in "lfsr".
+ */
+void
+isc_lfsr_skip(isc_lfsr_t *lfsr, unsigned int skip)
+{
+	REQUIRE(VALID_LFSR(lfsr));
+
+	while (skip--)
+		(void)lfsr_generate(lfsr);
+}
+
+/*
+ * Skip states in lfsr1 and lfsr2 using the other's current state.
+ * Return the final state of lfsr1 ^ lfsr2.
+ */
+isc_uint32_t
+isc_lfsr_generate32(isc_lfsr_t *lfsr1, isc_lfsr_t *lfsr2)
+{
+	isc_uint32_t state1, state2;
+	isc_uint32_t skip1, skip2;
+
+	REQUIRE(VALID_LFSR(lfsr1));
+	REQUIRE(VALID_LFSR(lfsr2));
+
+	skip1 = lfsr1->state & 0x01;
+	skip2 = lfsr2->state & 0x01;
+
+	/* cross-skip. */
+	state1 = lfsr_skipgenerate(lfsr1, skip2);
+	state2 = lfsr_skipgenerate(lfsr2, skip1);
+
+	return (state1 ^ state2);
+}
diff --git a/src/lib/bind9/lib.c b/src/lib/bind9/lib.c
new file mode 100644
index 0000000..1b6ccc0
--- /dev/null
+++ b/src/lib/bind9/lib.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: lib.c,v 1.16 2009-09-02 23:48:02 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <isc/app.h>
+#include <isc/lib.h>
+#include <isc/mem.h>
+#include <isc/msgs.h>
+#include <isc/once.h>
+#include <isc/socket.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+/***
+ *** Globals
+ ***/
+
+LIBISC_EXTERNAL_DATA isc_msgcat_t *		isc_msgcat = NULL;
+
+
+/***
+ *** Private
+ ***/
+
+static isc_once_t		msgcat_once = ISC_ONCE_INIT;
+
+/***
+ *** Functions
+ ***/
+
+static void
+open_msgcat(void) {
+	isc_msgcat_open("libisc.cat", &isc_msgcat);
+}
+
+void
+isc_lib_initmsgcat(void) {
+	isc_result_t result;
+
+	/*!
+	 * Initialize the ISC library's message catalog, isc_msgcat, if it
+	 * has not already been initialized.
+	 */
+
+	result = isc_once_do(&msgcat_once, open_msgcat);
+	if (result != ISC_R_SUCCESS) {
+		/*
+		 * Normally we'd use RUNTIME_CHECK() or FATAL_ERROR(), but
+		 * we can't do that here, since they might call us!
+		 * (Note that the catalog might be open anyway, so we might
+		 * as well try to  provide an internationalized message.)
+		 */
+		fprintf(stderr, "%s:%d: %s: isc_once_do() %s.\n",
+			__FILE__, __LINE__,
+			isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+				       ISC_MSG_FATALERROR, "fatal error"),
+			isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+				       ISC_MSG_FAILED, "failed"));
+		abort();
+	}
+}
+
+#ifndef BIND9
+static isc_once_t		register_once = ISC_ONCE_INIT;
+
+static void
+do_register(void) {
+	RUNTIME_CHECK(isc__mem_register() == ISC_R_SUCCESS);
+	RUNTIME_CHECK(isc__app_register() == ISC_R_SUCCESS);
+	RUNTIME_CHECK(isc__task_register() == ISC_R_SUCCESS);
+	RUNTIME_CHECK(isc__socket_register() == ISC_R_SUCCESS);
+	RUNTIME_CHECK(isc__timer_register() == ISC_R_SUCCESS);
+}
+
+void
+isc_lib_register() {
+	RUNTIME_CHECK(isc_once_do(&register_once, do_register)
+		      == ISC_R_SUCCESS);
+}
+#endif
diff --git a/src/lib/bind9/log.c b/src/lib/bind9/log.c
new file mode 100644
index 0000000..ee71deb
--- /dev/null
+++ b/src/lib/bind9/log.c
@@ -0,0 +1,1763 @@
+/*
+ * Copyright (C) 2004-2007, 2009, 2011  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: log.c,v 1.99.404.2 2011-03-12 04:59:18 tbox Exp $ */
+
+/*! \file
+ * \author  Principal Authors: DCL */
+
+#include <config.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <time.h>
+
+#include <sys/types.h>	/* dev_t FreeBSD 2.1 */
+
+#include <isc/dir.h>
+#include <isc/file.h>
+#include <isc/log.h>
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/msgs.h>
+#include <isc/print.h>
+#include <isc/stat.h>
+#include <isc/stdio.h>
+#include <isc/string.h>
+#include <isc/time.h>
+#include <isc/util.h>
+
+#define LCTX_MAGIC		ISC_MAGIC('L', 'c', 't', 'x')
+#define VALID_CONTEXT(lctx)	ISC_MAGIC_VALID(lctx, LCTX_MAGIC)
+
+#define LCFG_MAGIC		ISC_MAGIC('L', 'c', 'f', 'g')
+#define VALID_CONFIG(lcfg)	ISC_MAGIC_VALID(lcfg, LCFG_MAGIC)
+
+/*
+ * XXXDCL make dynamic?
+ */
+#define LOG_BUFFER_SIZE	(8 * 1024)
+
+#ifndef PATH_MAX
+#define PATH_MAX 1024	/* AIX and others don't define this. */
+#endif
+
+/*!
+ * This is the structure that holds each named channel.  A simple linked
+ * list chains all of the channels together, so an individual channel is
+ * found by doing strcmp()s with the names down the list.  Their should
+ * be no performance penalty from this as it is expected that the number
+ * of named channels will be no more than a dozen or so, and name lookups
+ * from the head of the list are only done when isc_log_usechannel() is
+ * called, which should also be very infrequent.
+ */
+typedef struct isc_logchannel isc_logchannel_t;
+
+struct isc_logchannel {
+	char *				name;
+	unsigned int			type;
+	int 				level;
+	unsigned int			flags;
+	isc_logdestination_t 		destination;
+	ISC_LINK(isc_logchannel_t)	link;
+};
+
+/*!
+ * The logchannellist structure associates categories and modules with
+ * channels.  First the appropriate channellist is found based on the
+ * category, and then each structure in the linked list is checked for
+ * a matching module.  It is expected that the number of channels
+ * associated with any given category will be very short, no more than
+ * three or four in the more unusual cases.
+ */
+typedef struct isc_logchannellist isc_logchannellist_t;
+
+struct isc_logchannellist {
+	const isc_logmodule_t *		module;
+	isc_logchannel_t *		channel;
+	ISC_LINK(isc_logchannellist_t)	link;
+};
+
+/*!
+ * This structure is used to remember messages for pruning via
+ * isc_log_[v]write1().
+ */
+typedef struct isc_logmessage isc_logmessage_t;
+
+struct isc_logmessage {
+	char *				text;
+	isc_time_t			time;
+	ISC_LINK(isc_logmessage_t)	link;
+};
+
+/*!
+ * The isc_logconfig structure is used to store the configurable information
+ * about where messages are actually supposed to be sent -- the information
+ * that could changed based on some configuration file, as opposed to the
+ * the category/module specification of isc_log_[v]write[1] that is compiled
+ * into a program, or the debug_level which is dynamic state information.
+ */
+struct isc_logconfig {
+	unsigned int			magic;
+	isc_log_t *			lctx;
+	ISC_LIST(isc_logchannel_t)	channels;
+	ISC_LIST(isc_logchannellist_t) *channellists;
+	unsigned int			channellist_count;
+	unsigned int			duplicate_interval;
+	int				highest_level;
+	char *				tag;
+	isc_boolean_t			dynamic;
+};
+
+/*!
+ * This isc_log structure provides the context for the isc_log functions.
+ * The log context locks itself in isc_log_doit, the internal backend to
+ * isc_log_write.  The locking is necessary both to provide exclusive access
+ * to the buffer into which the message is formatted and to guard against
+ * competing threads trying to write to the same syslog resource.  (On
+ * some systems, such as BSD/OS, stdio is thread safe but syslog is not.)
+ * Unfortunately, the lock cannot guard against a _different_ logging
+ * context in the same program competing for syslog's attention.  Thus
+ * There Can Be Only One, but this is not enforced.
+ * XXXDCL enforce it?
+ *
+ * Note that the category and module information is not locked.
+ * This is because in the usual case, only one isc_log_t is ever created
+ * in a program, and the category/module registration happens only once.
+ * XXXDCL it might be wise to add more locking overall.
+ */
+struct isc_log {
+	/* Not locked. */
+	unsigned int			magic;
+	isc_mem_t *			mctx;
+	isc_logcategory_t *		categories;
+	unsigned int			category_count;
+	isc_logmodule_t *		modules;
+	unsigned int			module_count;
+	int				debug_level;
+	isc_mutex_t			lock;
+	/* Locked by isc_log lock. */
+	isc_logconfig_t * 		logconfig;
+	char 				buffer[LOG_BUFFER_SIZE];
+	ISC_LIST(isc_logmessage_t)	messages;
+};
+
+/*!
+ * Used when ISC_LOG_PRINTLEVEL is enabled for a channel.
+ */
+static const char *log_level_strings[] = {
+	"debug",
+	"info",
+	"notice",
+	"warning",
+	"error",
+	"critical"
+};
+
+/*!
+ * Used to convert ISC_LOG_* priorities into syslog priorities.
+ * XXXDCL This will need modification for NT.
+ */
+static const int syslog_map[] = {
+	LOG_DEBUG,
+	LOG_INFO,
+	LOG_NOTICE,
+	LOG_WARNING,
+	LOG_ERR,
+	LOG_CRIT
+};
+
+/*!
+ * When adding new categories, a corresponding ISC_LOGCATEGORY_foo
+ * definition needs to be added to <isc/log.h>.
+ *
+ * The default category is provided so that the internal default can
+ * be overridden.  Since the default is always looked up as the first
+ * channellist in the log context, it must come first in isc_categories[].
+ */
+LIBISC_EXTERNAL_DATA isc_logcategory_t isc_categories[] = {
+	{ "default", 0 },	/* "default" must come first. */
+	{ "general", 0 },
+	{ NULL, 0 }
+};
+
+/*!
+ * See above comment for categories on LIBISC_EXTERNAL_DATA, and apply it to modules.
+ */
+LIBISC_EXTERNAL_DATA isc_logmodule_t isc_modules[] = {
+	{ "socket", 0 },
+	{ "time", 0 },
+	{ "interface", 0 },
+	{ "timer", 0 },
+	{ "file", 0 },
+	{ NULL, 0 }
+};
+
+/*!
+ * This essentially constant structure must be filled in at run time,
+ * because its channel member is pointed to a channel that is created
+ * dynamically with isc_log_createchannel.
+ */
+static isc_logchannellist_t default_channel;
+
+/*!
+ * libisc logs to this context.
+ */
+LIBISC_EXTERNAL_DATA isc_log_t *isc_lctx = NULL;
+
+/*!
+ * Forward declarations.
+ */
+static isc_result_t
+assignchannel(isc_logconfig_t *lcfg, unsigned int category_id,
+	      const isc_logmodule_t *module, isc_logchannel_t *channel);
+
+static isc_result_t
+sync_channellist(isc_logconfig_t *lcfg);
+
+static isc_result_t
+greatest_version(isc_logchannel_t *channel, int *greatest);
+
+static isc_result_t
+roll_log(isc_logchannel_t *channel);
+
+static void
+isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category,
+	     isc_logmodule_t *module, int level, isc_boolean_t write_once,
+	     isc_msgcat_t *msgcat, int msgset, int msg,
+	     const char *format, va_list args)
+     ISC_FORMAT_PRINTF(9, 0);
+
+/*@{*/
+/*!
+ * Convenience macros.
+ */
+
+#define FACILITY(channel)	 (channel->destination.facility)
+#define FILE_NAME(channel)	 (channel->destination.file.name)
+#define FILE_STREAM(channel)	 (channel->destination.file.stream)
+#define FILE_VERSIONS(channel)	 (channel->destination.file.versions)
+#define FILE_MAXSIZE(channel)	 (channel->destination.file.maximum_size)
+#define FILE_MAXREACHED(channel) (channel->destination.file.maximum_reached)
+
+/*@}*/
+/****
+ **** Public interfaces.
+ ****/
+
+/*
+ * Establish a new logging context, with default channels.
+ */
+isc_result_t
+isc_log_create(isc_mem_t *mctx, isc_log_t **lctxp, isc_logconfig_t **lcfgp) {
+	isc_log_t *lctx;
+	isc_logconfig_t *lcfg = NULL;
+	isc_result_t result;
+
+	REQUIRE(mctx != NULL);
+	REQUIRE(lctxp != NULL && *lctxp == NULL);
+	REQUIRE(lcfgp == NULL || *lcfgp == NULL);
+
+	lctx = isc_mem_get(mctx, sizeof(*lctx));
+	if (lctx != NULL) {
+		lctx->mctx = mctx;
+		lctx->categories = NULL;
+		lctx->category_count = 0;
+		lctx->modules = NULL;
+		lctx->module_count = 0;
+		lctx->debug_level = 0;
+
+		ISC_LIST_INIT(lctx->messages);
+
+		result = isc_mutex_init(&lctx->lock);
+		if (result != ISC_R_SUCCESS) {
+			isc_mem_put(mctx, lctx, sizeof(*lctx));
+			return (result);
+		}
+
+		/*
+		 * Normally setting the magic number is the last step done
+		 * in a creation function, but a valid log context is needed
+		 * by isc_log_registercategories and isc_logconfig_create.
+		 * If either fails, the lctx is destroyed and not returned
+		 * to the caller.
+		 */
+		lctx->magic = LCTX_MAGIC;
+
+		isc_log_registercategories(lctx, isc_categories);
+		isc_log_registermodules(lctx, isc_modules);
+		result = isc_logconfig_create(lctx, &lcfg);
+
+	} else
+		result = ISC_R_NOMEMORY;
+
+	if (result == ISC_R_SUCCESS)
+		result = sync_channellist(lcfg);
+
+	if (result == ISC_R_SUCCESS) {
+		lctx->logconfig = lcfg;
+
+		*lctxp = lctx;
+		if (lcfgp != NULL)
+			*lcfgp = lcfg;
+
+	} else {
+		if (lcfg != NULL)
+			isc_logconfig_destroy(&lcfg);
+		if (lctx != NULL)
+			isc_log_destroy(&lctx);
+	}
+
+	return (result);
+}
+
+isc_result_t
+isc_logconfig_create(isc_log_t *lctx, isc_logconfig_t **lcfgp) {
+	isc_logconfig_t *lcfg;
+	isc_logdestination_t destination;
+	isc_result_t result = ISC_R_SUCCESS;
+	int level = ISC_LOG_INFO;
+
+	REQUIRE(lcfgp != NULL && *lcfgp == NULL);
+	REQUIRE(VALID_CONTEXT(lctx));
+
+	lcfg = isc_mem_get(lctx->mctx, sizeof(*lcfg));
+
+	if (lcfg != NULL) {
+		lcfg->lctx = lctx;
+		lcfg->channellists = NULL;
+		lcfg->channellist_count = 0;
+		lcfg->duplicate_interval = 0;
+		lcfg->highest_level = level;
+		lcfg->tag = NULL;
+		lcfg->dynamic = ISC_FALSE;
+
+		ISC_LIST_INIT(lcfg->channels);
+
+		/*
+		 * Normally the magic number is the last thing set in the
+		 * structure, but isc_log_createchannel() needs a valid
+		 * config.  If the channel creation fails, the lcfg is not
+		 * returned to the caller.
+		 */
+		lcfg->magic = LCFG_MAGIC;
+
+	} else
+		result = ISC_R_NOMEMORY;
+
+	/*
+	 * Create the default channels:
+	 *   	default_syslog, default_stderr, default_debug and null.
+	 */
+	if (result == ISC_R_SUCCESS) {
+		destination.facility = LOG_DAEMON;
+		result = isc_log_createchannel(lcfg, "default_syslog",
+					       ISC_LOG_TOSYSLOG, level,
+					       &destination, 0);
+	}
+
+	if (result == ISC_R_SUCCESS) {
+		destination.file.stream = stderr;
+		destination.file.name = NULL;
+		destination.file.versions = ISC_LOG_ROLLNEVER;
+		destination.file.maximum_size = 0;
+		result = isc_log_createchannel(lcfg, "default_stderr",
+					       ISC_LOG_TOFILEDESC,
+					       level,
+					       &destination,
+					       ISC_LOG_PRINTTIME);
+	}
+
+	if (result == ISC_R_SUCCESS) {
+		/*
+		 * Set the default category's channel to default_stderr,
+		 * which is at the head of the channels list because it was
+		 * just created.
+		 */
+		default_channel.channel = ISC_LIST_HEAD(lcfg->channels);
+
+		destination.file.stream = stderr;
+		destination.file.name = NULL;
+		destination.file.versions = ISC_LOG_ROLLNEVER;
+		destination.file.maximum_size = 0;
+		result = isc_log_createchannel(lcfg, "default_debug",
+					       ISC_LOG_TOFILEDESC,
+					       ISC_LOG_DYNAMIC,
+					       &destination,
+					       ISC_LOG_PRINTTIME);
+	}
+
+	if (result == ISC_R_SUCCESS)
+		result = isc_log_createchannel(lcfg, "null",
+					       ISC_LOG_TONULL,
+					       ISC_LOG_DYNAMIC,
+					       NULL, 0);
+
+	if (result == ISC_R_SUCCESS)
+		*lcfgp = lcfg;
+
+	else
+		if (lcfg != NULL)
+			isc_logconfig_destroy(&lcfg);
+
+	return (result);
+}
+
+isc_logconfig_t *
+isc_logconfig_get(isc_log_t *lctx) {
+	REQUIRE(VALID_CONTEXT(lctx));
+
+	ENSURE(lctx->logconfig != NULL);
+
+	return (lctx->logconfig);
+}
+
+isc_result_t
+isc_logconfig_use(isc_log_t *lctx, isc_logconfig_t *lcfg) {
+	isc_logconfig_t *old_cfg;
+	isc_result_t result;
+
+	REQUIRE(VALID_CONTEXT(lctx));
+	REQUIRE(VALID_CONFIG(lcfg));
+	REQUIRE(lcfg->lctx == lctx);
+
+	/*
+	 * Ensure that lcfg->channellist_count == lctx->category_count.
+	 * They won't be equal if isc_log_usechannel has not been called
+	 * since any call to isc_log_registercategories.
+	 */
+	result = sync_channellist(lcfg);
+	if (result != ISC_R_SUCCESS)
+		return (result);
+
+	LOCK(&lctx->lock);
+
+	old_cfg = lctx->logconfig;
+	lctx->logconfig = lcfg;
+
+	UNLOCK(&lctx->lock);
+
+	isc_logconfig_destroy(&old_cfg);
+
+	return (ISC_R_SUCCESS);
+}
+
+void
+isc_log_destroy(isc_log_t **lctxp) {
+	isc_log_t *lctx;
+	isc_logconfig_t *lcfg;
+	isc_mem_t *mctx;
+	isc_logmessage_t *message;
+
+	REQUIRE(lctxp != NULL && VALID_CONTEXT(*lctxp));
+
+	lctx = *lctxp;
+	mctx = lctx->mctx;
+
+	if (lctx->logconfig != NULL) {
+		lcfg = lctx->logconfig;
+		lctx->logconfig = NULL;
+		isc_logconfig_destroy(&lcfg);
+	}
+
+	DESTROYLOCK(&lctx->lock);
+
+	while ((message = ISC_LIST_HEAD(lctx->messages)) != NULL) {
+		ISC_LIST_UNLINK(lctx->messages, message, link);
+
+		isc_mem_put(mctx, message,
+			    sizeof(*message) + strlen(message->text) + 1);
+	}
+
+	lctx->buffer[0] = '\0';
+	lctx->debug_level = 0;
+	lctx->categories = NULL;
+	lctx->category_count = 0;
+	lctx->modules = NULL;
+	lctx->module_count = 0;
+	lctx->mctx = NULL;
+	lctx->magic = 0;
+
+	isc_mem_put(mctx, lctx, sizeof(*lctx));
+
+	*lctxp = NULL;
+}
+
+void
+isc_logconfig_destroy(isc_logconfig_t **lcfgp) {
+	isc_logconfig_t *lcfg;
+	isc_mem_t *mctx;
+	isc_logchannel_t *channel;
+	isc_logchannellist_t *item;
+	char *filename;
+	unsigned int i;
+
+	REQUIRE(lcfgp != NULL && VALID_CONFIG(*lcfgp));
+
+	lcfg = *lcfgp;
+
+	/*
+	 * This function cannot be called with a logconfig that is in
+	 * use by a log context.
+	 */
+	REQUIRE(lcfg->lctx != NULL && lcfg->lctx->logconfig != lcfg);
+
+	mctx = lcfg->lctx->mctx;
+
+	while ((channel = ISC_LIST_HEAD(lcfg->channels)) != NULL) {
+		ISC_LIST_UNLINK(lcfg->channels, channel, link);
+
+		if (channel->type == ISC_LOG_TOFILE) {
+			/*
+			 * The filename for the channel may have ultimately
+			 * started its life in user-land as a const string,
+			 * but in isc_log_createchannel it gets copied
+			 * into writable memory and is not longer truly const.
+			 */
+			DE_CONST(FILE_NAME(channel), filename);
+			isc_mem_free(mctx, filename);
+
+			if (FILE_STREAM(channel) != NULL)
+				(void)fclose(FILE_STREAM(channel));
+		}
+
+		isc_mem_free(mctx, channel->name);
+		isc_mem_put(mctx, channel, sizeof(*channel));
+	}
+
+	for (i = 0; i < lcfg->channellist_count; i++)
+		while ((item = ISC_LIST_HEAD(lcfg->channellists[i])) != NULL) {
+			ISC_LIST_UNLINK(lcfg->channellists[i], item, link);
+			isc_mem_put(mctx, item, sizeof(*item));
+		}
+
+	if (lcfg->channellist_count > 0)
+		isc_mem_put(mctx, lcfg->channellists,
+			    lcfg->channellist_count *
+			    sizeof(ISC_LIST(isc_logchannellist_t)));
+
+	lcfg->dynamic = ISC_FALSE;
+	if (lcfg->tag != NULL)
+		isc_mem_free(lcfg->lctx->mctx, lcfg->tag);
+	lcfg->tag = NULL;
+	lcfg->highest_level = 0;
+	lcfg->duplicate_interval = 0;
+	lcfg->magic = 0;
+
+	isc_mem_put(mctx, lcfg, sizeof(*lcfg));
+
+	*lcfgp = NULL;
+}
+
+void
+isc_log_registercategories(isc_log_t *lctx, isc_logcategory_t categories[]) {
+	isc_logcategory_t *catp;
+
+	REQUIRE(VALID_CONTEXT(lctx));
+	REQUIRE(categories != NULL && categories[0].name != NULL);
+
+	/*
+	 * XXXDCL This somewhat sleazy situation of using the last pointer
+	 * in one category array to point to the next array exists because
+	 * this registration function returns void and I didn't want to have
+	 * change everything that used it by making it return an isc_result_t.
+	 * It would need to do that if it had to allocate memory to store
+	 * pointers to each array passed in.
+	 */
+	if (lctx->categories == NULL)
+		lctx->categories = categories;
+
+	else {
+		/*
+		 * Adjust the last (NULL) pointer of the already registered
+		 * categories to point to the incoming array.
+		 */
+		for (catp = lctx->categories; catp->name != NULL; )
+			if (catp->id == UINT_MAX)
+				/*
+				 * The name pointer points to the next array.
+				 * Ick.
+				 */
+				DE_CONST(catp->name, catp);
+			else
+				catp++;
+
+		catp->name = (void *)categories;
+		catp->id = UINT_MAX;
+	}
+
+	/*
+	 * Update the id number of the category with its new global id.
+	 */
+	for (catp = categories; catp->name != NULL; catp++)
+		catp->id = lctx->category_count++;
+}
+
+isc_logcategory_t *
+isc_log_categorybyname(isc_log_t *lctx, const char *name) {
+	isc_logcategory_t *catp;
+
+	REQUIRE(VALID_CONTEXT(lctx));
+	REQUIRE(name != NULL);
+
+	for (catp = lctx->categories; catp->name != NULL; )
+		if (catp->id == UINT_MAX)
+			/*
+			 * catp is neither modified nor returned to the
+			 * caller, so removing its const qualifier is ok.
+			 */
+			DE_CONST(catp->name, catp);
+		else {
+			if (strcmp(catp->name, name) == 0)
+				return (catp);
+			catp++;
+		}
+
+	return (NULL);
+}
+
+void
+isc_log_registermodules(isc_log_t *lctx, isc_logmodule_t modules[]) {
+	isc_logmodule_t *modp;
+
+	REQUIRE(VALID_CONTEXT(lctx));
+	REQUIRE(modules != NULL && modules[0].name != NULL);
+
+	/*
+	 * XXXDCL This somewhat sleazy situation of using the last pointer
+	 * in one category array to point to the next array exists because
+	 * this registration function returns void and I didn't want to have
+	 * change everything that used it by making it return an isc_result_t.
+	 * It would need to do that if it had to allocate memory to store
+	 * pointers to each array passed in.
+	 */
+	if (lctx->modules == NULL)
+		lctx->modules = modules;
+
+	else {
+		/*
+		 * Adjust the last (NULL) pointer of the already registered
+		 * modules to point to the incoming array.
+		 */
+		for (modp = lctx->modules; modp->name != NULL; )
+			if (modp->id == UINT_MAX)
+				/*
+				 * The name pointer points to the next array.
+				 * Ick.
+				 */
+				DE_CONST(modp->name, modp);
+			else
+				modp++;
+
+		modp->name = (void *)modules;
+		modp->id = UINT_MAX;
+	}
+
+	/*
+	 * Update the id number of the module with its new global id.
+	 */
+	for (modp = modules; modp->name != NULL; modp++)
+		modp->id = lctx->module_count++;
+}
+
+isc_logmodule_t *
+isc_log_modulebyname(isc_log_t *lctx, const char *name) {
+	isc_logmodule_t *modp;
+
+	REQUIRE(VALID_CONTEXT(lctx));
+	REQUIRE(name != NULL);
+
+	for (modp = lctx->modules; modp->name != NULL; )
+		if (modp->id == UINT_MAX)
+			/*
+			 * modp is neither modified nor returned to the
+			 * caller, so removing its const qualifier is ok.
+			 */
+			DE_CONST(modp->name, modp);
+		else {
+			if (strcmp(modp->name, name) == 0)
+				return (modp);
+			modp++;
+		}
+
+	return (NULL);
+}
+
+isc_result_t
+isc_log_createchannel(isc_logconfig_t *lcfg, const char *name,
+		      unsigned int type, int level,
+		      const isc_logdestination_t *destination,
+		      unsigned int flags)
+{
+	isc_logchannel_t *channel;
+	isc_mem_t *mctx;
+
+	REQUIRE(VALID_CONFIG(lcfg));
+	REQUIRE(name != NULL);
+	REQUIRE(type == ISC_LOG_TOSYSLOG   || type == ISC_LOG_TOFILE ||
+		type == ISC_LOG_TOFILEDESC || type == ISC_LOG_TONULL);
+	REQUIRE(destination != NULL || type == ISC_LOG_TONULL);
+	REQUIRE(level >= ISC_LOG_CRITICAL);
+	REQUIRE((flags &
+		 (unsigned int)~(ISC_LOG_PRINTALL | ISC_LOG_DEBUGONLY)) == 0);
+
+	/* XXXDCL find duplicate names? */
+
+	mctx = lcfg->lctx->mctx;
+
+	channel = isc_mem_get(mctx, sizeof(*channel));
+	if (channel == NULL)
+		return (ISC_R_NOMEMORY);
+
+	channel->name = isc_mem_strdup(mctx, name);
+	if (channel->name == NULL) {
+		isc_mem_put(mctx, channel, sizeof(*channel));
+		return (ISC_R_NOMEMORY);
+	}
+
+	channel->type = type;
+	channel->level = level;
+	channel->flags = flags;
+	ISC_LINK_INIT(channel, link);
+
+	switch (type) {
+	case ISC_LOG_TOSYSLOG:
+		FACILITY(channel) = destination->facility;
+		break;
+
+	case ISC_LOG_TOFILE:
+		/*
+		 * The file name is copied because greatest_version wants
+		 * to scribble on it, so it needs to be definitely in
+		 * writable memory.
+		 */
+		FILE_NAME(channel) =
+			isc_mem_strdup(mctx, destination->file.name);
+		FILE_STREAM(channel) = NULL;
+		FILE_VERSIONS(channel) = destination->file.versions;
+		FILE_MAXSIZE(channel) = destination->file.maximum_size;
+		FILE_MAXREACHED(channel) = ISC_FALSE;
+		break;
+
+	case ISC_LOG_TOFILEDESC:
+		FILE_NAME(channel) = NULL;
+		FILE_STREAM(channel) = destination->file.stream;
+		FILE_MAXSIZE(channel) = 0;
+		FILE_VERSIONS(channel) = ISC_LOG_ROLLNEVER;
+		break;
+
+	case ISC_LOG_TONULL:
+		/* Nothing. */
+		break;
+
+	default:
+		isc_mem_put(mctx, channel->name, strlen(channel->name) + 1);
+		isc_mem_put(mctx, channel, sizeof(*channel));
+		return (ISC_R_UNEXPECTED);
+	}
+
+	ISC_LIST_PREPEND(lcfg->channels, channel, link);
+
+	/*
+	 * If default_stderr was redefined, make the default category
+	 * point to the new default_stderr.
+	 */
+	if (strcmp(name, "default_stderr") == 0)
+		default_channel.channel = channel;
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_log_usechannel(isc_logconfig_t *lcfg, const char *name,
+		   const isc_logcategory_t *category,
+		   const isc_logmodule_t *module)
+{
+	isc_log_t *lctx;
+	isc_logchannel_t *channel;
+	isc_result_t result = ISC_R_SUCCESS;
+	unsigned int i;
+
+	REQUIRE(VALID_CONFIG(lcfg));
+	REQUIRE(name != NULL);
+
+	lctx = lcfg->lctx;
+
+	REQUIRE(category == NULL || category->id < lctx->category_count);
+	REQUIRE(module == NULL || module->id < lctx->module_count);
+
+	for (channel = ISC_LIST_HEAD(lcfg->channels); channel != NULL;
+	     channel = ISC_LIST_NEXT(channel, link))
+		if (strcmp(name, channel->name) == 0)
+			break;
+
+	if (channel == NULL)
+		return (ISC_R_NOTFOUND);
+
+	if (category != NULL)
+		result = assignchannel(lcfg, category->id, module, channel);
+
+	else
+		/*
+		 * Assign to all categories.  Note that this includes
+		 * the default channel.
+		 */
+		for (i = 0; i < lctx->category_count; i++) {
+			result = assignchannel(lcfg, i, module, channel);
+			if (result != ISC_R_SUCCESS)
+				break;
+		}
+
+	return (result);
+}
+
+void
+isc_log_write(isc_log_t *lctx, isc_logcategory_t *category,
+	      isc_logmodule_t *module, int level, const char *format, ...)
+{
+	va_list args;
+
+	/*
+	 * Contract checking is done in isc_log_doit().
+	 */
+
+	va_start(args, format);
+	isc_log_doit(lctx, category, module, level, ISC_FALSE,
+		     NULL, 0, 0, format, args);
+	va_end(args);
+}
+
+void
+isc_log_vwrite(isc_log_t *lctx, isc_logcategory_t *category,
+	       isc_logmodule_t *module, int level,
+	       const char *format, va_list args)
+{
+	/*
+	 * Contract checking is done in isc_log_doit().
+	 */
+	isc_log_doit(lctx, category, module, level, ISC_FALSE,
+		     NULL, 0, 0, format, args);
+}
+
+void
+isc_log_write1(isc_log_t *lctx, isc_logcategory_t *category,
+	       isc_logmodule_t *module, int level, const char *format, ...)
+{
+	va_list args;
+
+	/*
+	 * Contract checking is done in isc_log_doit().
+	 */
+
+	va_start(args, format);
+	isc_log_doit(lctx, category, module, level, ISC_TRUE,
+		     NULL, 0, 0, format, args);
+	va_end(args);
+}
+
+void
+isc_log_vwrite1(isc_log_t *lctx, isc_logcategory_t *category,
+		isc_logmodule_t *module, int level,
+		const char *format, va_list args)
+{
+	/*
+	 * Contract checking is done in isc_log_doit().
+	 */
+	isc_log_doit(lctx, category, module, level, ISC_TRUE,
+		     NULL, 0, 0, format, args);
+}
+
+void
+isc_log_iwrite(isc_log_t *lctx, isc_logcategory_t *category,
+	       isc_logmodule_t *module, int level,
+	       isc_msgcat_t *msgcat, int msgset, int msg,
+	       const char *format, ...)
+{
+	va_list args;
+
+	/*
+	 * Contract checking is done in isc_log_doit().
+	 */
+
+	va_start(args, format);
+	isc_log_doit(lctx, category, module, level, ISC_FALSE,
+		     msgcat, msgset, msg, format, args);
+	va_end(args);
+}
+
+void
+isc_log_ivwrite(isc_log_t *lctx, isc_logcategory_t *category,
+	       isc_logmodule_t *module, int level,
+	       isc_msgcat_t *msgcat, int msgset, int msg,
+	       const char *format, va_list args)
+{
+	/*
+	 * Contract checking is done in isc_log_doit().
+	 */
+	isc_log_doit(lctx, category, module, level, ISC_FALSE,
+		     msgcat, msgset, msg, format, args);
+}
+
+void
+isc_log_iwrite1(isc_log_t *lctx, isc_logcategory_t *category,
+		isc_logmodule_t *module, int level,
+		isc_msgcat_t *msgcat, int msgset, int msg,
+		const char *format, ...)
+{
+	va_list args;
+
+	/*
+	 * Contract checking is done in isc_log_doit().
+	 */
+
+	va_start(args, format);
+	isc_log_doit(lctx, category, module, level, ISC_TRUE,
+		     msgcat, msgset, msg, format, args);
+	va_end(args);
+}
+
+void
+isc_log_ivwrite1(isc_log_t *lctx, isc_logcategory_t *category,
+		 isc_logmodule_t *module, int level,
+		 isc_msgcat_t *msgcat, int msgset, int msg,
+		 const char *format, va_list args)
+{
+	/*
+	 * Contract checking is done in isc_log_doit().
+	 */
+	isc_log_doit(lctx, category, module, level, ISC_TRUE,
+		     msgcat, msgset, msg, format, args);
+}
+
+void
+isc_log_setcontext(isc_log_t *lctx) {
+	isc_lctx = lctx;
+}
+
+void
+isc_log_setdebuglevel(isc_log_t *lctx, unsigned int level) {
+	isc_logchannel_t *channel;
+
+	REQUIRE(VALID_CONTEXT(lctx));
+
+	LOCK(&lctx->lock);
+
+	lctx->debug_level = level;
+	/*
+	 * Close ISC_LOG_DEBUGONLY channels if level is zero.
+	 */
+	if (lctx->debug_level == 0)
+		for (channel = ISC_LIST_HEAD(lctx->logconfig->channels);
+		     channel != NULL;
+		     channel = ISC_LIST_NEXT(channel, link))
+			if (channel->type == ISC_LOG_TOFILE &&
+			    (channel->flags & ISC_LOG_DEBUGONLY) != 0 &&
+			    FILE_STREAM(channel) != NULL) {
+				(void)fclose(FILE_STREAM(channel));
+				FILE_STREAM(channel) = NULL;
+			}
+	UNLOCK(&lctx->lock);
+}
+
+unsigned int
+isc_log_getdebuglevel(isc_log_t *lctx) {
+	REQUIRE(VALID_CONTEXT(lctx));
+
+	return (lctx->debug_level);
+}
+
+void
+isc_log_setduplicateinterval(isc_logconfig_t *lcfg, unsigned int interval) {
+	REQUIRE(VALID_CONFIG(lcfg));
+
+	lcfg->duplicate_interval = interval;
+}
+
+unsigned int
+isc_log_getduplicateinterval(isc_logconfig_t *lcfg) {
+	REQUIRE(VALID_CONTEXT(lcfg));
+
+	return (lcfg->duplicate_interval);
+}
+
+isc_result_t
+isc_log_settag(isc_logconfig_t *lcfg, const char *tag) {
+	REQUIRE(VALID_CONFIG(lcfg));
+
+	if (tag != NULL && *tag != '\0') {
+		if (lcfg->tag != NULL)
+			isc_mem_free(lcfg->lctx->mctx, lcfg->tag);
+		lcfg->tag = isc_mem_strdup(lcfg->lctx->mctx, tag);
+		if (lcfg->tag == NULL)
+			return (ISC_R_NOMEMORY);
+
+	} else {
+		if (lcfg->tag != NULL)
+			isc_mem_free(lcfg->lctx->mctx, lcfg->tag);
+		lcfg->tag = NULL;
+	}
+
+	return (ISC_R_SUCCESS);
+}
+
+char *
+isc_log_gettag(isc_logconfig_t *lcfg) {
+	REQUIRE(VALID_CONFIG(lcfg));
+
+	return (lcfg->tag);
+}
+
+/* XXXDCL NT  -- This interface will assuredly be changing. */
+void
+isc_log_opensyslog(const char *tag, int options, int facility) {
+	(void)openlog(tag, options, facility);
+}
+
+void
+isc_log_closefilelogs(isc_log_t *lctx) {
+	isc_logchannel_t *channel;
+
+	REQUIRE(VALID_CONTEXT(lctx));
+
+	LOCK(&lctx->lock);
+	for (channel = ISC_LIST_HEAD(lctx->logconfig->channels);
+	     channel != NULL;
+	     channel = ISC_LIST_NEXT(channel, link))
+
+		if (channel->type == ISC_LOG_TOFILE &&
+		    FILE_STREAM(channel) != NULL) {
+			(void)fclose(FILE_STREAM(channel));
+			FILE_STREAM(channel) = NULL;
+		}
+	UNLOCK(&lctx->lock);
+}
+
+/****
+ **** Internal functions
+ ****/
+
+static isc_result_t
+assignchannel(isc_logconfig_t *lcfg, unsigned int category_id,
+	      const isc_logmodule_t *module, isc_logchannel_t *channel)
+{
+	isc_logchannellist_t *new_item;
+	isc_log_t *lctx;
+	isc_result_t result;
+
+	REQUIRE(VALID_CONFIG(lcfg));
+
+	lctx = lcfg->lctx;
+
+	REQUIRE(category_id < lctx->category_count);
+	REQUIRE(module == NULL || module->id < lctx->module_count);
+	REQUIRE(channel != NULL);
+
+	/*
+	 * Ensure lcfg->channellist_count == lctx->category_count.
+	 */
+	result = sync_channellist(lcfg);
+	if (result != ISC_R_SUCCESS)
+		return (result);
+
+	new_item = isc_mem_get(lctx->mctx, sizeof(*new_item));
+	if (new_item == NULL)
+		return (ISC_R_NOMEMORY);
+
+	new_item->channel = channel;
+	new_item->module = module;
+	ISC_LIST_INITANDPREPEND(lcfg->channellists[category_id],
+			       new_item, link);
+
+	/*
+	 * Remember the highest logging level set by any channel in the
+	 * logging config, so isc_log_doit() can quickly return if the
+	 * message is too high to be logged by any channel.
+	 */
+	if (channel->type != ISC_LOG_TONULL) {
+		if (lcfg->highest_level < channel->level)
+			lcfg->highest_level = channel->level;
+		if (channel->level == ISC_LOG_DYNAMIC)
+			lcfg->dynamic = ISC_TRUE;
+	}
+
+	return (ISC_R_SUCCESS);
+}
+
+/*
+ * This would ideally be part of isc_log_registercategories(), except then
+ * that function would have to return isc_result_t instead of void.
+ */
+static isc_result_t
+sync_channellist(isc_logconfig_t *lcfg) {
+	unsigned int bytes;
+	isc_log_t *lctx;
+	void *lists;
+
+	REQUIRE(VALID_CONFIG(lcfg));
+
+	lctx = lcfg->lctx;
+
+	REQUIRE(lctx->category_count != 0);
+
+	if (lctx->category_count == lcfg->channellist_count)
+		return (ISC_R_SUCCESS);
+
+	bytes = lctx->category_count * sizeof(ISC_LIST(isc_logchannellist_t));
+
+	lists = isc_mem_get(lctx->mctx, bytes);
+
+	if (lists == NULL)
+		return (ISC_R_NOMEMORY);
+
+	memset(lists, 0, bytes);
+
+	if (lcfg->channellist_count != 0) {
+		bytes = lcfg->channellist_count *
+			sizeof(ISC_LIST(isc_logchannellist_t));
+		memcpy(lists, lcfg->channellists, bytes);
+		isc_mem_put(lctx->mctx, lcfg->channellists, bytes);
+	}
+
+	lcfg->channellists = lists;
+	lcfg->channellist_count = lctx->category_count;
+
+	return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+greatest_version(isc_logchannel_t *channel, int *greatestp) {
+	/* XXXDCL HIGHLY NT */
+	char *basename, *digit_end;
+	const char *dirname;
+	int version, greatest = -1;
+	unsigned int basenamelen;
+	isc_dir_t dir;
+	isc_result_t result;
+	char sep = '/';
+#ifdef _WIN32
+	char *basename2;
+#endif
+
+	REQUIRE(channel->type == ISC_LOG_TOFILE);
+
+	/*
+	 * It is safe to DE_CONST the file.name because it was copied
+	 * with isc_mem_strdup in isc_log_createchannel.
+	 */
+	basename = strrchr(FILE_NAME(channel), sep);
+#ifdef _WIN32
+	basename2 = strrchr(FILE_NAME(channel), '\\');
+	if ((basename != NULL && basename2 != NULL && basename2 > basename) ||
+	    (basename == NULL && basename2 != NULL)) {
+		basename = basename2;
+		sep = '\\';
+	}
+#endif
+	if (basename != NULL) {
+		*basename++ = '\0';
+		dirname = FILE_NAME(channel);
+	} else {
+		DE_CONST(FILE_NAME(channel), basename);
+		dirname = ".";
+	}
+	basenamelen = strlen(basename);
+
+	isc_dir_init(&dir);
+	result = isc_dir_open(&dir, dirname);
+
+	/*
+	 * Replace the file separator if it was taken out.
+	 */
+	if (basename != FILE_NAME(channel))
+		*(basename - 1) = sep;
+
+	/*
+	 * Return if the directory open failed.
+	 */
+	if (result != ISC_R_SUCCESS)
+		return (result);
+
+	while (isc_dir_read(&dir) == ISC_R_SUCCESS) {
+		if (dir.entry.length > basenamelen &&
+		    strncmp(dir.entry.name, basename, basenamelen) == 0 &&
+		    dir.entry.name[basenamelen] == '.') {
+
+			version = strtol(&dir.entry.name[basenamelen + 1],
+					 &digit_end, 10);
+			if (*digit_end == '\0' && version > greatest)
+				greatest = version;
+		}
+	}
+	isc_dir_close(&dir);
+
+	*greatestp = ++greatest;
+
+	return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+roll_log(isc_logchannel_t *channel) {
+	int i, n, greatest;
+	char current[PATH_MAX + 1];
+	char new[PATH_MAX + 1];
+	const char *path;
+	isc_result_t result;
+
+	/*
+	 * Do nothing (not even excess version trimming) if ISC_LOG_ROLLNEVER
+	 * is specified.  Apparently complete external control over the log
+	 * files is desired.
+	 */
+	if (FILE_VERSIONS(channel) == ISC_LOG_ROLLNEVER)
+		return (ISC_R_SUCCESS);
+
+	path = FILE_NAME(channel);
+
+	/*
+	 * Set greatest_version to the greatest existing version
+	 * (not the maximum requested version).  This is 1 based even
+	 * though the file names are 0 based, so an oldest log of log.1
+	 * is a greatest_version of 2.
+	 */
+	result = greatest_version(channel, &greatest);
+	if (result != ISC_R_SUCCESS)
+		return (result);
+
+	/*
+	 * Now greatest should be set to the highest version number desired.
+	 * Since the highest number is one less than FILE_VERSIONS(channel)
+	 * when not doing infinite log rolling, greatest will need to be
+	 * decremented when it is equal to -- or greater than --
+	 * FILE_VERSIONS(channel).  When greatest is less than
+	 * FILE_VERSIONS(channel), it is already suitable for use as
+	 * the maximum version number.
+	 */
+
+	if (FILE_VERSIONS(channel) == ISC_LOG_ROLLINFINITE ||
+	    FILE_VERSIONS(channel) > greatest)
+		;		/* Do nothing. */
+	else
+		/*
+		 * When greatest is >= FILE_VERSIONS(channel), it needs to
+		 * be reduced until it is FILE_VERSIONS(channel) - 1.
+		 * Remove any excess logs on the way to that value.
+		 */
+		while (--greatest >= FILE_VERSIONS(channel)) {
+			n = snprintf(current, sizeof(current), "%s.%d",
+				     path, greatest);
+			if (n >= (int)sizeof(current) || n < 0)
+				result = ISC_R_NOSPACE;
+			else
+				result = isc_file_remove(current);
+			if (result != ISC_R_SUCCESS &&
+			    result != ISC_R_FILENOTFOUND)
+				syslog(LOG_ERR,
+				       "unable to remove log file '%s.%d': %s",
+				       path, greatest,
+				       isc_result_totext(result));
+		}
+
+	for (i = greatest; i > 0; i--) {
+		result = ISC_R_SUCCESS;
+		n = snprintf(current, sizeof(current), "%s.%d", path, i - 1);
+		if (n >= (int)sizeof(current) || n < 0)
+			result = ISC_R_NOSPACE;
+		if (result == ISC_R_SUCCESS) {
+			n = snprintf(new, sizeof(new), "%s.%d", path, i);
+			if (n >= (int)sizeof(new) || n < 0)
+				result = ISC_R_NOSPACE;
+		}
+		if (result == ISC_R_SUCCESS)
+			result = isc_file_rename(current, new);
+		if (result != ISC_R_SUCCESS &&
+		    result != ISC_R_FILENOTFOUND)
+			syslog(LOG_ERR,
+			       "unable to rename log file '%s.%d' to "
+			       "'%s.%d': %s", path, i - 1, path, i,
+			       isc_result_totext(result));
+	}
+
+	if (FILE_VERSIONS(channel) != 0) {
+		n = snprintf(new, sizeof(new), "%s.0", path);
+		if (n >= (int)sizeof(new) || n < 0)
+			result = ISC_R_NOSPACE;
+		else
+			result = isc_file_rename(path, new);
+		if (result != ISC_R_SUCCESS &&
+		    result != ISC_R_FILENOTFOUND)
+			syslog(LOG_ERR,
+			       "unable to rename log file '%s' to '%s.0': %s",
+			       path, path, isc_result_totext(result));
+	} else {
+		result = isc_file_remove(path);
+		if (result != ISC_R_SUCCESS &&
+		    result != ISC_R_FILENOTFOUND)
+			syslog(LOG_ERR, "unable to remove log file '%s': %s",
+			       path, isc_result_totext(result));
+	}
+
+	return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+isc_log_open(isc_logchannel_t *channel) {
+	struct stat statbuf;
+	isc_boolean_t regular_file;
+	isc_boolean_t roll = ISC_FALSE;
+	isc_result_t result = ISC_R_SUCCESS;
+	const char *path;
+
+	REQUIRE(channel->type == ISC_LOG_TOFILE);
+	REQUIRE(FILE_STREAM(channel) == NULL);
+
+	path = FILE_NAME(channel);
+
+	REQUIRE(path != NULL && *path != '\0');
+
+	/*
+	 * Determine type of file; only regular files will be
+	 * version renamed, and only if the base file exists
+	 * and either has no size limit or has reached its size limit.
+	 */
+	if (stat(path, &statbuf) == 0) {
+		regular_file = S_ISREG(statbuf.st_mode) ? ISC_TRUE : ISC_FALSE;
+		/* XXXDCL if not regular_file complain? */
+		if ((FILE_MAXSIZE(channel) == 0 &&
+		     FILE_VERSIONS(channel) != ISC_LOG_ROLLNEVER) ||
+		    (FILE_MAXSIZE(channel) > 0 &&
+		     statbuf.st_size >= FILE_MAXSIZE(channel)))
+			roll = regular_file;
+	} else if (errno == ENOENT) {
+		regular_file = ISC_TRUE;
+		POST(regular_file);
+	} else
+		result = ISC_R_INVALIDFILE;
+
+	/*
+	 * Version control.
+	 */
+	if (result == ISC_R_SUCCESS && roll) {
+		if (FILE_VERSIONS(channel) == ISC_LOG_ROLLNEVER)
+			return (ISC_R_MAXSIZE);
+		result = roll_log(channel);
+		if (result != ISC_R_SUCCESS) {
+			if ((channel->flags & ISC_LOG_OPENERR) == 0) {
+				syslog(LOG_ERR,
+				       "isc_log_open: roll_log '%s' "
+				       "failed: %s",
+				       FILE_NAME(channel),
+				       isc_result_totext(result));
+				channel->flags |= ISC_LOG_OPENERR;
+			}
+			return (result);
+		}
+	}
+
+	result = isc_stdio_open(path, "a", &FILE_STREAM(channel));
+
+	return (result);
+}
+
+isc_boolean_t
+isc_log_wouldlog(isc_log_t *lctx, int level) {
+	/*
+	 * Try to avoid locking the mutex for messages which can't
+	 * possibly be logged to any channels -- primarily debugging
+	 * messages that the debug level is not high enough to print.
+	 *
+	 * If the level is (mathematically) less than or equal to the
+	 * highest_level, or if there is a dynamic channel and the level is
+	 * less than or equal to the debug level, the main loop must be
+	 * entered to see if the message should really be output.
+	 *
+	 * NOTE: this is UNLOCKED access to the logconfig.  However,
+	 * the worst thing that can happen is that a bad decision is made
+	 * about returning without logging, and that's not a big concern,
+	 * because that's a risk anyway if the logconfig is being
+	 * dynamically changed.
+	 */
+
+	if (lctx == NULL || lctx->logconfig == NULL)
+		return (ISC_FALSE);
+
+	return (ISC_TF(level <= lctx->logconfig->highest_level ||
+		       (lctx->logconfig->dynamic &&
+			level <= lctx->debug_level)));
+}
+
+static void
+isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category,
+	     isc_logmodule_t *module, int level, isc_boolean_t write_once,
+	     isc_msgcat_t *msgcat, int msgset, int msg,
+	     const char *format, va_list args)
+{
+	int syslog_level;
+	char time_string[64];
+	char level_string[24];
+	const char *iformat;
+	struct stat statbuf;
+	isc_boolean_t matched = ISC_FALSE;
+	isc_boolean_t printtime, printtag;
+	isc_boolean_t printcategory, printmodule, printlevel;
+	isc_logconfig_t *lcfg;
+	isc_logchannel_t *channel;
+	isc_logchannellist_t *category_channels;
+	isc_result_t result;
+
+	REQUIRE(lctx == NULL || VALID_CONTEXT(lctx));
+	REQUIRE(category != NULL);
+	REQUIRE(module != NULL);
+	REQUIRE(level != ISC_LOG_DYNAMIC);
+	REQUIRE(format != NULL);
+
+	/*
+	 * Programs can use libraries that use this logging code without
+	 * wanting to do any logging, thus the log context is allowed to
+	 * be non-existent.
+	 */
+	if (lctx == NULL)
+		return;
+
+	REQUIRE(category->id < lctx->category_count);
+	REQUIRE(module->id < lctx->module_count);
+
+	if (! isc_log_wouldlog(lctx, level))
+		return;
+
+	if (msgcat != NULL)
+		iformat = isc_msgcat_get(msgcat, msgset, msg, format);
+	else
+		iformat = format;
+
+	time_string[0]  = '\0';
+	level_string[0] = '\0';
+
+	LOCK(&lctx->lock);
+
+	lctx->buffer[0] = '\0';
+
+	lcfg = lctx->logconfig;
+
+	category_channels = ISC_LIST_HEAD(lcfg->channellists[category->id]);
+
+	/*
+	 * XXXDCL add duplicate filtering? (To not write multiple times to
+	 * the same source via various channels).
+	 */
+	do {
+		/*
+		 * If the channel list end was reached and a match was made,
+		 * everything is finished.
+		 */
+		if (category_channels == NULL && matched)
+			break;
+
+		if (category_channels == NULL && ! matched &&
+		    category_channels != ISC_LIST_HEAD(lcfg->channellists[0]))
+			/*
+			 * No category/module pair was explicitly configured.
+			 * Try the category named "default".
+			 */
+			category_channels =
+				ISC_LIST_HEAD(lcfg->channellists[0]);
+
+		if (category_channels == NULL && ! matched)
+			/*
+			 * No matching module was explicitly configured
+			 * for the category named "default".  Use the internal
+			 * default channel.
+			 */
+			category_channels = &default_channel;
+
+		if (category_channels->module != NULL &&
+		    category_channels->module != module) {
+			category_channels = ISC_LIST_NEXT(category_channels,
+							  link);
+			continue;
+		}
+
+		matched = ISC_TRUE;
+
+		channel = category_channels->channel;
+		category_channels = ISC_LIST_NEXT(category_channels, link);
+
+		if (((channel->flags & ISC_LOG_DEBUGONLY) != 0) &&
+		    lctx->debug_level == 0)
+			continue;
+
+		if (channel->level == ISC_LOG_DYNAMIC) {
+			if (lctx->debug_level < level)
+				continue;
+		} else if (channel->level < level)
+			continue;
+
+		if ((channel->flags & ISC_LOG_PRINTTIME) != 0 &&
+		    time_string[0] == '\0') {
+			isc_time_t isctime;
+
+			TIME_NOW(&isctime);
+			isc_time_formattimestamp(&isctime, time_string,
+						 sizeof(time_string));
+		}
+
+		if ((channel->flags & ISC_LOG_PRINTLEVEL) != 0 &&
+		    level_string[0] == '\0') {
+			if (level < ISC_LOG_CRITICAL)
+				snprintf(level_string, sizeof(level_string),
+					 isc_msgcat_get(isc_msgcat,
+							ISC_MSGSET_LOG,
+							ISC_MSG_LEVEL,
+							"level %d: "),
+					 level);
+			else if (level > ISC_LOG_DYNAMIC)
+				snprintf(level_string, sizeof(level_string),
+					 "%s %d: ", log_level_strings[0],
+					 level);
+			else
+				snprintf(level_string, sizeof(level_string),
+					 "%s: ", log_level_strings[-level]);
+		}
+
+		/*
+		 * Only format the message once.
+		 */
+		if (lctx->buffer[0] == '\0') {
+			(void)vsnprintf(lctx->buffer, sizeof(lctx->buffer),
+					iformat, args);
+
+			/*
+			 * Check for duplicates.
+			 */
+			if (write_once) {
+				isc_logmessage_t *message, *new;
+				isc_time_t oldest;
+				isc_interval_t interval;
+
+				isc_interval_set(&interval,
+						 lcfg->duplicate_interval, 0);
+
+				/*
+				 * 'oldest' is the age of the oldest messages
+				 * which fall within the duplicate_interval
+				 * range.
+				 */
+				TIME_NOW(&oldest);
+				if (isc_time_subtract(&oldest, &interval, &oldest)
+				    != ISC_R_SUCCESS)
+					/*
+					 * Can't effectively do the checking
+					 * without having a valid time.
+					 */
+					message = NULL;
+				else
+					message =ISC_LIST_HEAD(lctx->messages);
+
+				while (message != NULL) {
+					if (isc_time_compare(&message->time,
+							     &oldest) < 0) {
+						/*
+						 * This message is older
+						 * than the duplicate_interval,
+						 * so it should be dropped from
+						 * the history.
+						 *
+						 * Setting the interval to be
+						 * to be longer will obviously
+						 * not cause the expired
+						 * message to spring back into
+						 * existence.
+						 */
+						new = ISC_LIST_NEXT(message,
+								    link);
+
+						ISC_LIST_UNLINK(lctx->messages,
+								message, link);
+
+						isc_mem_put(lctx->mctx,
+							message,
+							sizeof(*message) + 1 +
+							strlen(message->text));
+
+						message = new;
+						continue;
+					}
+
+					/*
+					 * This message is in the duplicate
+					 * filtering interval ...
+					 */
+					if (strcmp(lctx->buffer, message->text)
+					    == 0) {
+						/*
+						 * ... and it is a duplicate.
+						 * Unlock the mutex and
+						 * get the hell out of Dodge.
+						 */
+						UNLOCK(&lctx->lock);
+						return;
+					}
+
+					message = ISC_LIST_NEXT(message, link);
+				}
+
+				/*
+				 * It wasn't in the duplicate interval,
+				 * so add it to the message list.
+				 */
+				new = isc_mem_get(lctx->mctx,
+						  sizeof(isc_logmessage_t) +
+						  strlen(lctx->buffer) + 1);
+				if (new != NULL) {
+					/*
+					 * Put the text immediately after
+					 * the struct.  The strcpy is safe.
+					 */
+					new->text = (char *)(new + 1);
+					strcpy(new->text, lctx->buffer);
+
+					TIME_NOW(&new->time);
+
+					ISC_LIST_APPEND(lctx->messages,
+							new, link);
+				}
+			}
+		}
+
+		printtime     = ISC_TF((channel->flags & ISC_LOG_PRINTTIME)
+				       != 0);
+		printtag      = ISC_TF((channel->flags & ISC_LOG_PRINTTAG)
+				       != 0 && lcfg->tag != NULL);
+		printcategory = ISC_TF((channel->flags & ISC_LOG_PRINTCATEGORY)
+				       != 0);
+		printmodule   = ISC_TF((channel->flags & ISC_LOG_PRINTMODULE)
+				       != 0);
+		printlevel    = ISC_TF((channel->flags & ISC_LOG_PRINTLEVEL)
+				       != 0);
+
+		switch (channel->type) {
+		case ISC_LOG_TOFILE:
+			if (FILE_MAXREACHED(channel)) {
+				/*
+				 * If the file can be rolled, OR
+				 * If the file no longer exists, OR
+				 * If the file is less than the maximum size,
+				 *    (such as if it had been renamed and
+				 *     a new one touched, or it was truncated
+				 *     in place)
+				 * ... then close it to trigger reopening.
+				 */
+				if (FILE_VERSIONS(channel) !=
+				    ISC_LOG_ROLLNEVER ||
+				    (stat(FILE_NAME(channel), &statbuf) != 0 &&
+				     errno == ENOENT) ||
+				    statbuf.st_size < FILE_MAXSIZE(channel)) {
+					(void)fclose(FILE_STREAM(channel));
+					FILE_STREAM(channel) = NULL;
+					FILE_MAXREACHED(channel) = ISC_FALSE;
+				} else
+					/*
+					 * Eh, skip it.
+					 */
+					break;
+			}
+
+			if (FILE_STREAM(channel) == NULL) {
+				result = isc_log_open(channel);
+				if (result != ISC_R_SUCCESS &&
+				    result != ISC_R_MAXSIZE &&
+				    (channel->flags & ISC_LOG_OPENERR) == 0) {
+					syslog(LOG_ERR,
+					       "isc_log_open '%s' failed: %s",
+					       FILE_NAME(channel),
+					       isc_result_totext(result));
+					channel->flags |= ISC_LOG_OPENERR;
+				}
+				if (result != ISC_R_SUCCESS)
+					break;
+				channel->flags &= ~ISC_LOG_OPENERR;
+			}
+			/* FALLTHROUGH */
+
+		case ISC_LOG_TOFILEDESC:
+			fprintf(FILE_STREAM(channel), "%s%s%s%s%s%s%s%s%s%s\n",
+				printtime     ? time_string	: "",
+				printtime     ? " "		: "",
+				printtag      ? lcfg->tag	: "",
+				printtag      ? ": "		: "",
+				printcategory ? category->name	: "",
+				printcategory ? ": "		: "",
+				printmodule   ? (module != NULL ? module->name
+								: "no_module")
+								: "",
+				printmodule   ? ": "		: "",
+				printlevel    ? level_string	: "",
+				lctx->buffer);
+
+			fflush(FILE_STREAM(channel));
+
+			/*
+			 * If the file now exceeds its maximum size
+			 * threshold, note it so that it will not be logged
+			 * to any more.
+			 */
+			if (FILE_MAXSIZE(channel) > 0) {
+				INSIST(channel->type == ISC_LOG_TOFILE);
+
+				/* XXXDCL NT fstat/fileno */
+				/* XXXDCL complain if fstat fails? */
+				if (fstat(fileno(FILE_STREAM(channel)),
+					  &statbuf) >= 0 &&
+				    statbuf.st_size > FILE_MAXSIZE(channel))
+					FILE_MAXREACHED(channel) = ISC_TRUE;
+			}
+
+			break;
+
+		case ISC_LOG_TOSYSLOG:
+			if (level > 0)
+				syslog_level = LOG_DEBUG;
+			else if (level < ISC_LOG_CRITICAL)
+				syslog_level = LOG_CRIT;
+			else
+				syslog_level = syslog_map[-level];
+
+			(void)syslog(FACILITY(channel) | syslog_level,
+			       "%s%s%s%s%s%s%s%s%s%s",
+			       printtime     ? time_string	: "",
+			       printtime     ? " "		: "",
+			       printtag      ? lcfg->tag	: "",
+			       printtag      ? ": "		: "",
+			       printcategory ? category->name	: "",
+			       printcategory ? ": "		: "",
+			       printmodule   ? (module != NULL	? module->name
+								: "no_module")
+								: "",
+			       printmodule   ? ": "		: "",
+			       printlevel    ? level_string	: "",
+			       lctx->buffer);
+			break;
+
+		case ISC_LOG_TONULL:
+			break;
+
+		}
+
+	} while (1);
+
+	UNLOCK(&lctx->lock);
+}
diff --git a/src/lib/bind9/md5.c b/src/lib/bind9/md5.c
new file mode 100644
index 0000000..b778177
--- /dev/null
+++ b/src/lib/bind9/md5.c
@@ -0,0 +1,277 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: md5.c,v 1.16 2009-02-06 23:47:42 tbox Exp $ */
+
+/*! \file
+ * This code implements the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest.  This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ */
+
+#include "config.h"
+
+#include <isc/assertions.h>
+#include <isc/md5.h>
+#include <isc/platform.h>
+#include <isc/string.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#ifdef ISC_PLATFORM_OPENSSLHASH
+
+void
+isc_md5_init(isc_md5_t *ctx) {
+	EVP_DigestInit(ctx, EVP_md5());
+}
+
+void
+isc_md5_invalidate(isc_md5_t *ctx) {
+	EVP_MD_CTX_cleanup(ctx);
+}
+
+void
+isc_md5_update(isc_md5_t *ctx, const unsigned char *buf, unsigned int len) {
+	EVP_DigestUpdate(ctx, (const void *) buf, (size_t) len);
+}
+
+void
+isc_md5_final(isc_md5_t *ctx, unsigned char *digest) {
+	EVP_DigestFinal(ctx, digest, NULL);
+}
+
+#else
+
+static void
+byteSwap(isc_uint32_t *buf, unsigned words)
+{
+	unsigned char *p = (unsigned char *)buf;
+
+	do {
+		*buf++ = (isc_uint32_t)((unsigned)p[3] << 8 | p[2]) << 16 |
+			((unsigned)p[1] << 8 | p[0]);
+		p += 4;
+	} while (--words);
+}
+
+/*!
+ * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+void
+isc_md5_init(isc_md5_t *ctx) {
+	ctx->buf[0] = 0x67452301;
+	ctx->buf[1] = 0xefcdab89;
+	ctx->buf[2] = 0x98badcfe;
+	ctx->buf[3] = 0x10325476;
+
+	ctx->bytes[0] = 0;
+	ctx->bytes[1] = 0;
+}
+
+void
+isc_md5_invalidate(isc_md5_t *ctx) {
+	memset(ctx, 0, sizeof(isc_md5_t));
+}
+
+/*@{*/
+/*! The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+/*@}*/
+
+/*! This is the central step in the MD5 algorithm. */
+#define MD5STEP(f,w,x,y,z,in,s) \
+	 (w += f(x,y,z) + in, w = (w<<s | w>>(32-s)) + x)
+
+/*!
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data.  MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+static void
+transform(isc_uint32_t buf[4], isc_uint32_t const in[16]) {
+	register isc_uint32_t a, b, c, d;
+
+	a = buf[0];
+	b = buf[1];
+	c = buf[2];
+	d = buf[3];
+
+	MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+	MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+	MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+	MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+	MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+	MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+	MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+	MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+	MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+	MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+	MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+	MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+	MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+	MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+	MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+	MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+	MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+	MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+	MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+	MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+	MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+	MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+	MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+	MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+	MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+	MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+	MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+	MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+	MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+	MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+	MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+	MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+	MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+	MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+	MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+	MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+	MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+	MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+	MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+	MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+	MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+	MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+	MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+	MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+	MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+	MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+	MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+	MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+
+	MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+	MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+	MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+	MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+	MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+	MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+	MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+	MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+	MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+	MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+	MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+	MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+	MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+	MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+	MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+	MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+
+	buf[0] += a;
+	buf[1] += b;
+	buf[2] += c;
+	buf[3] += d;
+}
+
+/*!
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void
+isc_md5_update(isc_md5_t *ctx, const unsigned char *buf, unsigned int len) {
+	isc_uint32_t t;
+
+	/* Update byte count */
+
+	t = ctx->bytes[0];
+	if ((ctx->bytes[0] = t + len) < t)
+		ctx->bytes[1]++;	/* Carry from low to high */
+
+	t = 64 - (t & 0x3f);	/* Space available in ctx->in (at least 1) */
+	if (t > len) {
+		memcpy((unsigned char *)ctx->in + 64 - t, buf, len);
+		return;
+	}
+	/* First chunk is an odd size */
+	memcpy((unsigned char *)ctx->in + 64 - t, buf, t);
+	byteSwap(ctx->in, 16);
+	transform(ctx->buf, ctx->in);
+	buf += t;
+	len -= t;
+
+	/* Process data in 64-byte chunks */
+	while (len >= 64) {
+		memcpy(ctx->in, buf, 64);
+		byteSwap(ctx->in, 16);
+		transform(ctx->buf, ctx->in);
+		buf += 64;
+		len -= 64;
+	}
+
+	/* Handle any remaining bytes of data. */
+	memcpy(ctx->in, buf, len);
+}
+
+/*!
+ * Final wrapup - pad to 64-byte boundary with the bit pattern
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+void
+isc_md5_final(isc_md5_t *ctx, unsigned char *digest) {
+	int count = ctx->bytes[0] & 0x3f;    /* Number of bytes in ctx->in */
+	unsigned char *p = (unsigned char *)ctx->in + count;
+
+	/* Set the first char of padding to 0x80.  There is always room. */
+	*p++ = 0x80;
+
+	/* Bytes of padding needed to make 56 bytes (-8..55) */
+	count = 56 - 1 - count;
+
+	if (count < 0) {	/* Padding forces an extra block */
+		memset(p, 0, count + 8);
+		byteSwap(ctx->in, 16);
+		transform(ctx->buf, ctx->in);
+		p = (unsigned char *)ctx->in;
+		count = 56;
+	}
+	memset(p, 0, count);
+	byteSwap(ctx->in, 14);
+
+	/* Append length in bits and transform */
+	ctx->in[14] = ctx->bytes[0] << 3;
+	ctx->in[15] = ctx->bytes[1] << 3 | ctx->bytes[0] >> 29;
+	transform(ctx->buf, ctx->in);
+
+	byteSwap(ctx->buf, 4);
+	memcpy(digest, ctx->buf, 16);
+	memset(ctx, 0, sizeof(isc_md5_t));	/* In case it's sensitive */
+}
+#endif
diff --git a/src/lib/bind9/mem.c b/src/lib/bind9/mem.c
new file mode 100644
index 0000000..8311569
--- /dev/null
+++ b/src/lib/bind9/mem.c
@@ -0,0 +1,2477 @@
+/*
+ * Copyright (C) 2004-2010  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1997-2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: mem.c,v 1.160 2010-12-08 02:46:16 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+
+#include <limits.h>
+
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/msgs.h>
+#include <isc/once.h>
+#include <isc/ondestroy.h>
+#include <isc/string.h>
+#include <isc/mutex.h>
+#include <isc/print.h>
+#include <isc/util.h>
+#include <isc/xml.h>
+
+#define MCTXLOCK(m, l) if (((m)->flags & ISC_MEMFLAG_NOLOCK) == 0) LOCK(l)
+#define MCTXUNLOCK(m, l) if (((m)->flags & ISC_MEMFLAG_NOLOCK) == 0) UNLOCK(l)
+
+#ifndef ISC_MEM_DEBUGGING
+#define ISC_MEM_DEBUGGING 0
+#endif
+LIBISC_EXTERNAL_DATA unsigned int isc_mem_debugging = ISC_MEM_DEBUGGING;
+
+/*
+ * Constants.
+ */
+
+#define DEF_MAX_SIZE		1100
+#define DEF_MEM_TARGET		4096
+#define ALIGNMENT_SIZE		8U		/*%< must be a power of 2 */
+#define NUM_BASIC_BLOCKS	64		/*%< must be > 1 */
+#define TABLE_INCREMENT		1024
+#define DEBUGLIST_COUNT		1024
+
+/*
+ * Types.
+ */
+typedef struct isc__mem isc__mem_t;
+typedef struct isc__mempool isc__mempool_t;
+
+#if ISC_MEM_TRACKLINES
+typedef struct debuglink debuglink_t;
+struct debuglink {
+	ISC_LINK(debuglink_t)	link;
+	const void	       *ptr[DEBUGLIST_COUNT];
+	unsigned int		size[DEBUGLIST_COUNT];
+	const char	       *file[DEBUGLIST_COUNT];
+	unsigned int		line[DEBUGLIST_COUNT];
+	unsigned int		count;
+};
+
+#define FLARG_PASS	, file, line
+#define FLARG		, const char *file, unsigned int line
+#else
+#define FLARG_PASS
+#define FLARG
+#endif
+
+typedef struct element element;
+struct element {
+	element *		next;
+};
+
+typedef struct {
+	/*!
+	 * This structure must be ALIGNMENT_SIZE bytes.
+	 */
+	union {
+		size_t		size;
+		isc__mem_t	*ctx;
+		char		bytes[ALIGNMENT_SIZE];
+	} u;
+} size_info;
+
+struct stats {
+	unsigned long		gets;
+	unsigned long		totalgets;
+	unsigned long		blocks;
+	unsigned long		freefrags;
+};
+
+#define MEM_MAGIC		ISC_MAGIC('M', 'e', 'm', 'C')
+#define VALID_CONTEXT(c)	ISC_MAGIC_VALID(c, MEM_MAGIC)
+
+#if ISC_MEM_TRACKLINES
+typedef ISC_LIST(debuglink_t)	debuglist_t;
+#endif
+
+/* List of all active memory contexts. */
+
+static ISC_LIST(isc__mem_t)	contexts;
+static isc_once_t		once = ISC_ONCE_INIT;
+static isc_mutex_t		lock;
+
+/*%
+ * Total size of lost memory due to a bug of external library.
+ * Locked by the global lock.
+ */
+static isc_uint64_t		totallost;
+
+struct isc__mem {
+	isc_mem_t		common;
+	isc_ondestroy_t		ondestroy;
+	unsigned int		flags;
+	isc_mutex_t		lock;
+	isc_memalloc_t		memalloc;
+	isc_memfree_t		memfree;
+	void *			arg;
+	size_t			max_size;
+	isc_boolean_t		checkfree;
+	struct stats *		stats;
+	unsigned int		references;
+	char			name[16];
+	void *			tag;
+	size_t			quota;
+	size_t			total;
+	size_t			inuse;
+	size_t			maxinuse;
+	size_t			hi_water;
+	size_t			lo_water;
+	isc_boolean_t		hi_called;
+	isc_boolean_t		is_overmem;
+	isc_mem_water_t		water;
+	void *			water_arg;
+	ISC_LIST(isc__mempool_t) pools;
+	unsigned int		poolcnt;
+
+	/*  ISC_MEMFLAG_INTERNAL */
+	size_t			mem_target;
+	element **		freelists;
+	element *		basic_blocks;
+	unsigned char **	basic_table;
+	unsigned int		basic_table_count;
+	unsigned int		basic_table_size;
+	unsigned char *		lowest;
+	unsigned char *		highest;
+
+#if ISC_MEM_TRACKLINES
+	debuglist_t *	 	debuglist;
+	unsigned int		debuglistcnt;
+#endif
+
+	unsigned int		memalloc_failures;
+	ISC_LINK(isc__mem_t)	link;
+};
+
+#define MEMPOOL_MAGIC		ISC_MAGIC('M', 'E', 'M', 'p')
+#define VALID_MEMPOOL(c)	ISC_MAGIC_VALID(c, MEMPOOL_MAGIC)
+
+struct isc__mempool {
+	/* always unlocked */
+	isc_mempool_t	common;		/*%< common header of mempool's */
+	isc_mutex_t    *lock;		/*%< optional lock */
+	isc__mem_t      *mctx;		/*%< our memory context */
+	/*%< locked via the memory context's lock */
+	ISC_LINK(isc__mempool_t)	link;	/*%< next pool in this mem context */
+	/*%< optionally locked from here down */
+	element	       *items;		/*%< low water item list */
+	size_t		size;		/*%< size of each item on this pool */
+	unsigned int	maxalloc;	/*%< max number of items allowed */
+	unsigned int	allocated;	/*%< # of items currently given out */
+	unsigned int	freecount;	/*%< # of items on reserved list */
+	unsigned int	freemax;	/*%< # of items allowed on free list */
+	unsigned int	fillcount;	/*%< # of items to fetch on each fill */
+	/*%< Stats only. */
+	unsigned int	gets;		/*%< # of requests to this pool */
+	/*%< Debugging only. */
+#if ISC_MEMPOOL_NAMES
+	char		name[16];	/*%< printed name in stats reports */
+#endif
+};
+
+/*
+ * Private Inline-able.
+ */
+
+#if ! ISC_MEM_TRACKLINES
+#define ADD_TRACE(a, b, c, d, e)
+#define DELETE_TRACE(a, b, c, d, e)
+#else
+#define ADD_TRACE(a, b, c, d, e) \
+	do { \
+		if ((isc_mem_debugging & (ISC_MEM_DEBUGTRACE | \
+					  ISC_MEM_DEBUGRECORD)) != 0 && \
+		     b != NULL) \
+			 add_trace_entry(a, b, c, d, e); \
+	} while (0)
+#define DELETE_TRACE(a, b, c, d, e)	delete_trace_entry(a, b, c, d, e)
+
+static void
+print_active(isc__mem_t *ctx, FILE *out);
+
+/*%
+ * The following can be either static or public, depending on build environment.
+ */
+
+#ifdef BIND9
+#define ISC_MEMFUNC_SCOPE
+#else
+#define ISC_MEMFUNC_SCOPE static
+#endif
+
+ISC_MEMFUNC_SCOPE isc_result_t
+isc__mem_createx(size_t init_max_size, size_t target_size,
+		 isc_memalloc_t memalloc, isc_memfree_t memfree, void *arg,
+		 isc_mem_t **ctxp);
+ISC_MEMFUNC_SCOPE isc_result_t
+isc__mem_createx2(size_t init_max_size, size_t target_size,
+		  isc_memalloc_t memalloc, isc_memfree_t memfree, void *arg,
+		  isc_mem_t **ctxp, unsigned int flags);
+ISC_MEMFUNC_SCOPE isc_result_t
+isc__mem_create(size_t init_max_size, size_t target_size, isc_mem_t **ctxp);
+ISC_MEMFUNC_SCOPE isc_result_t
+isc__mem_create2(size_t init_max_size, size_t target_size,
+		 isc_mem_t **ctxp, unsigned int flags);
+ISC_MEMFUNC_SCOPE void
+isc__mem_attach(isc_mem_t *source, isc_mem_t **targetp);
+ISC_MEMFUNC_SCOPE void
+isc__mem_detach(isc_mem_t **ctxp);
+ISC_MEMFUNC_SCOPE void
+isc___mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG);
+ISC_MEMFUNC_SCOPE void
+isc__mem_destroy(isc_mem_t **ctxp);
+ISC_MEMFUNC_SCOPE isc_result_t
+isc__mem_ondestroy(isc_mem_t *ctx, isc_task_t *task, isc_event_t **event);
+ISC_MEMFUNC_SCOPE void *
+isc___mem_get(isc_mem_t *ctx, size_t size FLARG);
+ISC_MEMFUNC_SCOPE void
+isc___mem_put(isc_mem_t *ctx, void *ptr, size_t size FLARG);
+ISC_MEMFUNC_SCOPE void
+isc__mem_stats(isc_mem_t *ctx, FILE *out);
+ISC_MEMFUNC_SCOPE void *
+isc___mem_allocate(isc_mem_t *ctx, size_t size FLARG);
+ISC_MEMFUNC_SCOPE void *
+isc___mem_reallocate(isc_mem_t *ctx, void *ptr, size_t size FLARG);
+ISC_MEMFUNC_SCOPE void
+isc___mem_free(isc_mem_t *ctx, void *ptr FLARG);
+ISC_MEMFUNC_SCOPE char *
+isc___mem_strdup(isc_mem_t *mctx, const char *s FLARG);
+ISC_MEMFUNC_SCOPE void
+isc__mem_setdestroycheck(isc_mem_t *ctx, isc_boolean_t flag);
+ISC_MEMFUNC_SCOPE void
+isc__mem_setquota(isc_mem_t *ctx, size_t quota);
+ISC_MEMFUNC_SCOPE size_t
+isc__mem_getquota(isc_mem_t *ctx);
+ISC_MEMFUNC_SCOPE size_t
+isc__mem_inuse(isc_mem_t *ctx);
+ISC_MEMFUNC_SCOPE isc_boolean_t
+isc__mem_isovermem(isc_mem_t *ctx);
+ISC_MEMFUNC_SCOPE void
+isc__mem_setwater(isc_mem_t *ctx, isc_mem_water_t water, void *water_arg,
+		  size_t hiwater, size_t lowater);
+ISC_MEMFUNC_SCOPE void
+isc__mem_waterack(isc_mem_t *ctx0, int flag);
+ISC_MEMFUNC_SCOPE void
+isc__mem_setname(isc_mem_t *ctx, const char *name, void *tag);
+ISC_MEMFUNC_SCOPE const char *
+isc__mem_getname(isc_mem_t *ctx);
+ISC_MEMFUNC_SCOPE void *
+isc__mem_gettag(isc_mem_t *ctx);
+ISC_MEMFUNC_SCOPE isc_result_t
+isc__mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp);
+ISC_MEMFUNC_SCOPE void
+isc__mempool_setname(isc_mempool_t *mpctx, const char *name);
+ISC_MEMFUNC_SCOPE void
+isc__mempool_destroy(isc_mempool_t **mpctxp);
+ISC_MEMFUNC_SCOPE void
+isc__mempool_associatelock(isc_mempool_t *mpctx, isc_mutex_t *lock);
+ISC_MEMFUNC_SCOPE void *
+isc___mempool_get(isc_mempool_t *mpctx FLARG);
+ISC_MEMFUNC_SCOPE void
+isc___mempool_put(isc_mempool_t *mpctx, void *mem FLARG);
+ISC_MEMFUNC_SCOPE void
+isc__mempool_setfreemax(isc_mempool_t *mpctx, unsigned int limit);
+ISC_MEMFUNC_SCOPE unsigned int
+isc__mempool_getfreemax(isc_mempool_t *mpctx);
+ISC_MEMFUNC_SCOPE unsigned int
+isc__mempool_getfreecount(isc_mempool_t *mpctx);
+ISC_MEMFUNC_SCOPE void
+isc__mempool_setmaxalloc(isc_mempool_t *mpctx, unsigned int limit);
+ISC_MEMFUNC_SCOPE unsigned int
+isc__mempool_getmaxalloc(isc_mempool_t *mpctx);
+ISC_MEMFUNC_SCOPE unsigned int
+isc__mempool_getallocated(isc_mempool_t *mpctx);
+ISC_MEMFUNC_SCOPE void
+isc__mempool_setfillcount(isc_mempool_t *mpctx, unsigned int limit);
+ISC_MEMFUNC_SCOPE unsigned int
+isc__mempool_getfillcount(isc_mempool_t *mpctx);
+#ifdef BIND9
+ISC_MEMFUNC_SCOPE void
+isc__mem_printactive(isc_mem_t *ctx0, FILE *file);
+ISC_MEMFUNC_SCOPE void
+isc__mem_printallactive(FILE *file);
+ISC_MEMFUNC_SCOPE void
+isc__mem_checkdestroyed(FILE *file);
+ISC_MEMFUNC_SCOPE unsigned int
+isc__mem_references(isc_mem_t *ctx0);
+#endif
+
+static struct isc__memmethods {
+	isc_memmethods_t methods;
+
+	/*%
+	 * The following are defined just for avoiding unused static functions.
+	 */
+#ifndef BIND9
+	void *createx, *create, *create2, *ondestroy, *stats,
+		*setquota, *getquota, *setname, *getname, *gettag;
+#endif
+} memmethods = {
+	{
+		isc__mem_attach,
+		isc__mem_detach,
+		isc__mem_destroy,
+		isc___mem_get,
+		isc___mem_put,
+		isc___mem_putanddetach,
+		isc___mem_allocate,
+		isc___mem_reallocate,
+		isc___mem_strdup,
+		isc___mem_free,
+		isc__mem_setdestroycheck,
+		isc__mem_setwater,
+		isc__mem_waterack,
+		isc__mem_inuse,
+		isc__mem_isovermem,
+		isc__mempool_create
+	}
+#ifndef BIND9
+	,
+	(void *)isc__mem_createx, (void *)isc__mem_create,
+	(void *)isc__mem_create2, (void *)isc__mem_ondestroy,
+	(void *)isc__mem_stats, (void *)isc__mem_setquota,
+	(void *)isc__mem_getquota, (void *)isc__mem_setname,
+	(void *)isc__mem_getname, (void *)isc__mem_gettag
+#endif
+};
+
+static struct isc__mempoolmethods {
+	isc_mempoolmethods_t methods;
+
+	/*%
+	 * The following are defined just for avoiding unused static functions.
+	 */
+#ifndef BIND9
+	void *getfreemax, *getfreecount, *getmaxalloc, *getfillcount;
+#endif
+} mempoolmethods = {
+	{
+		isc__mempool_destroy,
+		isc___mempool_get,
+		isc___mempool_put,
+		isc__mempool_getallocated,
+		isc__mempool_setmaxalloc,
+		isc__mempool_setfreemax,
+		isc__mempool_setname,
+		isc__mempool_associatelock,
+		isc__mempool_setfillcount
+	}
+#ifndef BIND9
+	,
+	(void *)isc__mempool_getfreemax, (void *)isc__mempool_getfreecount,
+	(void *)isc__mempool_getmaxalloc, (void *)isc__mempool_getfillcount
+#endif
+};
+
+/*!
+ * mctx must be locked.
+ */
+static inline void
+add_trace_entry(isc__mem_t *mctx, const void *ptr, unsigned int size
+		FLARG)
+{
+	debuglink_t *dl;
+	unsigned int i;
+	unsigned int mysize = size;
+
+	if ((isc_mem_debugging & ISC_MEM_DEBUGTRACE) != 0)
+		fprintf(stderr, isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
+					       ISC_MSG_ADDTRACE,
+					       "add %p size %u "
+					       "file %s line %u mctx %p\n"),
+			ptr, size, file, line, mctx);
+
+	if (mctx->debuglist == NULL)
+		return;
+
+	if (mysize > mctx->max_size)
+		mysize = mctx->max_size;
+
+	dl = ISC_LIST_HEAD(mctx->debuglist[mysize]);
+	while (dl != NULL) {
+		if (dl->count == DEBUGLIST_COUNT)
+			goto next;
+		for (i = 0; i < DEBUGLIST_COUNT; i++) {
+			if (dl->ptr[i] == NULL) {
+				dl->ptr[i] = ptr;
+				dl->size[i] = size;
+				dl->file[i] = file;
+				dl->line[i] = line;
+				dl->count++;
+				return;
+			}
+		}
+	next:
+		dl = ISC_LIST_NEXT(dl, link);
+	}
+
+	dl = malloc(sizeof(debuglink_t));
+	INSIST(dl != NULL);
+
+	ISC_LINK_INIT(dl, link);
+	for (i = 1; i < DEBUGLIST_COUNT; i++) {
+		dl->ptr[i] = NULL;
+		dl->size[i] = 0;
+		dl->file[i] = NULL;
+		dl->line[i] = 0;
+	}
+
+	dl->ptr[0] = ptr;
+	dl->size[0] = size;
+	dl->file[0] = file;
+	dl->line[0] = line;
+	dl->count = 1;
+
+	ISC_LIST_PREPEND(mctx->debuglist[mysize], dl, link);
+	mctx->debuglistcnt++;
+}
+
+static inline void
+delete_trace_entry(isc__mem_t *mctx, const void *ptr, unsigned int size,
+		   const char *file, unsigned int line)
+{
+	debuglink_t *dl;
+	unsigned int i;
+
+	if ((isc_mem_debugging & ISC_MEM_DEBUGTRACE) != 0)
+		fprintf(stderr, isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
+					       ISC_MSG_DELTRACE,
+					       "del %p size %u "
+					       "file %s line %u mctx %p\n"),
+			ptr, size, file, line, mctx);
+
+	if (mctx->debuglist == NULL)
+		return;
+
+	if (size > mctx->max_size)
+		size = mctx->max_size;
+
+	dl = ISC_LIST_HEAD(mctx->debuglist[size]);
+	while (dl != NULL) {
+		for (i = 0; i < DEBUGLIST_COUNT; i++) {
+			if (dl->ptr[i] == ptr) {
+				dl->ptr[i] = NULL;
+				dl->size[i] = 0;
+				dl->file[i] = NULL;
+				dl->line[i] = 0;
+
+				INSIST(dl->count > 0);
+				dl->count--;
+				if (dl->count == 0) {
+					ISC_LIST_UNLINK(mctx->debuglist[size],
+							dl, link);
+					free(dl);
+				}
+				return;
+			}
+		}
+		dl = ISC_LIST_NEXT(dl, link);
+	}
+
+	/*
+	 * If we get here, we didn't find the item on the list.  We're
+	 * screwed.
+	 */
+	INSIST(dl != NULL);
+}
+#endif /* ISC_MEM_TRACKLINES */
+
+static inline size_t
+rmsize(size_t size) {
+	/*
+	 * round down to ALIGNMENT_SIZE
+	 */
+	return (size & (~(ALIGNMENT_SIZE - 1)));
+}
+
+static inline size_t
+quantize(size_t size) {
+	/*!
+	 * Round up the result in order to get a size big
+	 * enough to satisfy the request and be aligned on ALIGNMENT_SIZE
+	 * byte boundaries.
+	 */
+
+	if (size == 0U)
+		return (ALIGNMENT_SIZE);
+	return ((size + ALIGNMENT_SIZE - 1) & (~(ALIGNMENT_SIZE - 1)));
+}
+
+static inline isc_boolean_t
+more_basic_blocks(isc__mem_t *ctx) {
+	void *new;
+	unsigned char *curr, *next;
+	unsigned char *first, *last;
+	unsigned char **table;
+	unsigned int table_size;
+	size_t increment;
+	int i;
+
+	/* Require: we hold the context lock. */
+
+	/*
+	 * Did we hit the quota for this context?
+	 */
+	increment = NUM_BASIC_BLOCKS * ctx->mem_target;
+	if (ctx->quota != 0U && ctx->total + increment > ctx->quota)
+		return (ISC_FALSE);
+
+	INSIST(ctx->basic_table_count <= ctx->basic_table_size);
+	if (ctx->basic_table_count == ctx->basic_table_size) {
+		table_size = ctx->basic_table_size + TABLE_INCREMENT;
+		table = (ctx->memalloc)(ctx->arg,
+					table_size * sizeof(unsigned char *));
+		if (table == NULL) {
+			ctx->memalloc_failures++;
+			return (ISC_FALSE);
+		}
+		if (ctx->basic_table_size != 0) {
+			memcpy(table, ctx->basic_table,
+			       ctx->basic_table_size *
+			       sizeof(unsigned char *));
+			(ctx->memfree)(ctx->arg, ctx->basic_table);
+		}
+		ctx->basic_table = table;
+		ctx->basic_table_size = table_size;
+	}
+
+	new = (ctx->memalloc)(ctx->arg, NUM_BASIC_BLOCKS * ctx->mem_target);
+	if (new == NULL) {
+		ctx->memalloc_failures++;
+		return (ISC_FALSE);
+	}
+	ctx->total += increment;
+	ctx->basic_table[ctx->basic_table_count] = new;
+	ctx->basic_table_count++;
+
+	curr = new;
+	next = curr + ctx->mem_target;
+	for (i = 0; i < (NUM_BASIC_BLOCKS - 1); i++) {
+		((element *)curr)->next = (element *)next;
+		curr = next;
+		next += ctx->mem_target;
+	}
+	/*
+	 * curr is now pointing at the last block in the
+	 * array.
+	 */
+	((element *)curr)->next = NULL;
+	first = new;
+	last = first + NUM_BASIC_BLOCKS * ctx->mem_target - 1;
+	if (first < ctx->lowest || ctx->lowest == NULL)
+		ctx->lowest = first;
+	if (last > ctx->highest)
+		ctx->highest = last;
+	ctx->basic_blocks = new;
+
+	return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+more_frags(isc__mem_t *ctx, size_t new_size) {
+	int i, frags;
+	size_t total_size;
+	void *new;
+	unsigned char *curr, *next;
+
+	/*!
+	 * Try to get more fragments by chopping up a basic block.
+	 */
+
+	if (ctx->basic_blocks == NULL) {
+		if (!more_basic_blocks(ctx)) {
+			/*
+			 * We can't get more memory from the OS, or we've
+			 * hit the quota for this context.
+			 */
+			/*
+			 * XXXRTH  "At quota" notification here.
+			 */
+			return (ISC_FALSE);
+		}
+	}
+
+	total_size = ctx->mem_target;
+	new = ctx->basic_blocks;
+	ctx->basic_blocks = ctx->basic_blocks->next;
+	frags = total_size / new_size;
+	ctx->stats[new_size].blocks++;
+	ctx->stats[new_size].freefrags += frags;
+	/*
+	 * Set up a linked-list of blocks of size
+	 * "new_size".
+	 */
+	curr = new;
+	next = curr + new_size;
+	total_size -= new_size;
+	for (i = 0; i < (frags - 1); i++) {
+		((element *)curr)->next = (element *)next;
+		curr = next;
+		next += new_size;
+		total_size -= new_size;
+	}
+	/*
+	 * Add the remaining fragment of the basic block to a free list.
+	 */
+	total_size = rmsize(total_size);
+	if (total_size > 0U) {
+		((element *)next)->next = ctx->freelists[total_size];
+		ctx->freelists[total_size] = (element *)next;
+		ctx->stats[total_size].freefrags++;
+	}
+	/*
+	 * curr is now pointing at the last block in the
+	 * array.
+	 */
+	((element *)curr)->next = NULL;
+	ctx->freelists[new_size] = new;
+
+	return (ISC_TRUE);
+}
+
+static inline void *
+mem_getunlocked(isc__mem_t *ctx, size_t size) {
+	size_t new_size = quantize(size);
+	void *ret;
+
+	if (size >= ctx->max_size || new_size >= ctx->max_size) {
+		/*
+		 * memget() was called on something beyond our upper limit.
+		 */
+		if (ctx->quota != 0U && ctx->total + size > ctx->quota) {
+			ret = NULL;
+			goto done;
+		}
+		ret = (ctx->memalloc)(ctx->arg, size);
+		if (ret == NULL) {
+			ctx->memalloc_failures++;
+			goto done;
+		}
+		ctx->total += size;
+		ctx->inuse += size;
+		ctx->stats[ctx->max_size].gets++;
+		ctx->stats[ctx->max_size].totalgets++;
+		/*
+		 * If we don't set new_size to size, then the
+		 * ISC_MEM_FILL code might write over bytes we
+		 * don't own.
+		 */
+		new_size = size;
+		goto done;
+	}
+
+	/*
+	 * If there are no blocks in the free list for this size, get a chunk
+	 * of memory and then break it up into "new_size"-sized blocks, adding
+	 * them to the free list.
+	 */
+	if (ctx->freelists[new_size] == NULL && !more_frags(ctx, new_size))
+		return (NULL);
+
+	/*
+	 * The free list uses the "rounded-up" size "new_size".
+	 */
+	ret = ctx->freelists[new_size];
+	ctx->freelists[new_size] = ctx->freelists[new_size]->next;
+
+	/*
+	 * The stats[] uses the _actual_ "size" requested by the
+	 * caller, with the caveat (in the code above) that "size" >= the
+	 * max. size (max_size) ends up getting recorded as a call to
+	 * max_size.
+	 */
+	ctx->stats[size].gets++;
+	ctx->stats[size].totalgets++;
+	ctx->stats[new_size].freefrags--;
+	ctx->inuse += new_size;
+
+ done:
+
+#if ISC_MEM_FILL
+	if (ret != NULL)
+		memset(ret, 0xbe, new_size); /* Mnemonic for "beef". */
+#endif
+
+	return (ret);
+}
+
+#if ISC_MEM_FILL && ISC_MEM_CHECKOVERRUN
+static inline void
+check_overrun(void *mem, size_t size, size_t new_size) {
+	unsigned char *cp;
+
+	cp = (unsigned char *)mem;
+	cp += size;
+	while (size < new_size) {
+		INSIST(*cp == 0xbe);
+		cp++;
+		size++;
+	}
+}
+#endif
+
+static inline void
+mem_putunlocked(isc__mem_t *ctx, void *mem, size_t size) {
+	size_t new_size = quantize(size);
+
+	if (size == ctx->max_size || new_size >= ctx->max_size) {
+		/*
+		 * memput() called on something beyond our upper limit.
+		 */
+#if ISC_MEM_FILL
+		memset(mem, 0xde, size); /* Mnemonic for "dead". */
+#endif
+		(ctx->memfree)(ctx->arg, mem);
+		INSIST(ctx->stats[ctx->max_size].gets != 0U);
+		ctx->stats[ctx->max_size].gets--;
+		INSIST(size <= ctx->total);
+		ctx->inuse -= size;
+		ctx->total -= size;
+		return;
+	}
+
+#if ISC_MEM_FILL
+#if ISC_MEM_CHECKOVERRUN
+	check_overrun(mem, size, new_size);
+#endif
+	memset(mem, 0xde, new_size); /* Mnemonic for "dead". */
+#endif
+
+	/*
+	 * The free list uses the "rounded-up" size "new_size".
+	 */
+	((element *)mem)->next = ctx->freelists[new_size];
+	ctx->freelists[new_size] = (element *)mem;
+
+	/*
+	 * The stats[] uses the _actual_ "size" requested by the
+	 * caller, with the caveat (in the code above) that "size" >= the
+	 * max. size (max_size) ends up getting recorded as a call to
+	 * max_size.
+	 */
+	INSIST(ctx->stats[size].gets != 0U);
+	ctx->stats[size].gets--;
+	ctx->stats[new_size].freefrags++;
+	ctx->inuse -= new_size;
+}
+
+/*!
+ * Perform a malloc, doing memory filling and overrun detection as necessary.
+ */
+static inline void *
+mem_get(isc__mem_t *ctx, size_t size) {
+	char *ret;
+
+#if ISC_MEM_CHECKOVERRUN
+	size += 1;
+#endif
+
+	ret = (ctx->memalloc)(ctx->arg, size);
+	if (ret == NULL)
+		ctx->memalloc_failures++;
+
+#if ISC_MEM_FILL
+	if (ret != NULL)
+		memset(ret, 0xbe, size); /* Mnemonic for "beef". */
+#else
+#  if ISC_MEM_CHECKOVERRUN
+	if (ret != NULL)
+		ret[size-1] = 0xbe;
+#  endif
+#endif
+
+	return (ret);
+}
+
+/*!
+ * Perform a free, doing memory filling and overrun detection as necessary.
+ */
+static inline void
+mem_put(isc__mem_t *ctx, void *mem, size_t size) {
+#if ISC_MEM_CHECKOVERRUN
+	INSIST(((unsigned char *)mem)[size] == 0xbe);
+#endif
+#if ISC_MEM_FILL
+	memset(mem, 0xde, size); /* Mnemonic for "dead". */
+#else
+	UNUSED(size);
+#endif
+	(ctx->memfree)(ctx->arg, mem);
+}
+
+/*!
+ * Update internal counters after a memory get.
+ */
+static inline void
+mem_getstats(isc__mem_t *ctx, size_t size) {
+	ctx->total += size;
+	ctx->inuse += size;
+
+	if (size > ctx->max_size) {
+		ctx->stats[ctx->max_size].gets++;
+		ctx->stats[ctx->max_size].totalgets++;
+	} else {
+		ctx->stats[size].gets++;
+		ctx->stats[size].totalgets++;
+	}
+}
+
+/*!
+ * Update internal counters after a memory put.
+ */
+static inline void
+mem_putstats(isc__mem_t *ctx, void *ptr, size_t size) {
+	UNUSED(ptr);
+
+	INSIST(ctx->inuse >= size);
+	ctx->inuse -= size;
+
+	if (size > ctx->max_size) {
+		INSIST(ctx->stats[ctx->max_size].gets > 0U);
+		ctx->stats[ctx->max_size].gets--;
+	} else {
+		INSIST(ctx->stats[size].gets > 0U);
+		ctx->stats[size].gets--;
+	}
+}
+
+/*
+ * Private.
+ */
+
+static void *
+default_memalloc(void *arg, size_t size) {
+	UNUSED(arg);
+	if (size == 0U)
+		size = 1;
+	return (malloc(size));
+}
+
+static void
+default_memfree(void *arg, void *ptr) {
+	UNUSED(arg);
+	free(ptr);
+}
+
+static void
+initialize_action(void) {
+	RUNTIME_CHECK(isc_mutex_init(&lock) == ISC_R_SUCCESS);
+	ISC_LIST_INIT(contexts);
+	totallost = 0;
+}
+
+/*
+ * Public.
+ */
+
+ISC_MEMFUNC_SCOPE isc_result_t
+isc__mem_createx(size_t init_max_size, size_t target_size,
+		 isc_memalloc_t memalloc, isc_memfree_t memfree, void *arg,
+		 isc_mem_t **ctxp)
+{
+	return (isc__mem_createx2(init_max_size, target_size, memalloc, memfree,
+				  arg, ctxp, ISC_MEMFLAG_DEFAULT));
+
+}
+
+ISC_MEMFUNC_SCOPE isc_result_t
+isc__mem_createx2(size_t init_max_size, size_t target_size,
+		  isc_memalloc_t memalloc, isc_memfree_t memfree, void *arg,
+		  isc_mem_t **ctxp, unsigned int flags)
+{
+	isc__mem_t *ctx;
+	isc_result_t result;
+
+	REQUIRE(ctxp != NULL && *ctxp == NULL);
+	REQUIRE(memalloc != NULL);
+	REQUIRE(memfree != NULL);
+
+	INSIST((ALIGNMENT_SIZE & (ALIGNMENT_SIZE - 1)) == 0);
+
+	RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
+
+	ctx = (memalloc)(arg, sizeof(*ctx));
+	if (ctx == NULL)
+		return (ISC_R_NOMEMORY);
+
+	if ((flags & ISC_MEMFLAG_NOLOCK) == 0) {
+		result = isc_mutex_init(&ctx->lock);
+		if (result != ISC_R_SUCCESS) {
+			(memfree)(arg, ctx);
+			return (result);
+		}
+	}
+
+	if (init_max_size == 0U)
+		ctx->max_size = DEF_MAX_SIZE;
+	else
+		ctx->max_size = init_max_size;
+	ctx->flags = flags;
+	ctx->references = 1;
+	memset(ctx->name, 0, sizeof(ctx->name));
+	ctx->tag = NULL;
+	ctx->quota = 0;
+	ctx->total = 0;
+	ctx->inuse = 0;
+	ctx->maxinuse = 0;
+	ctx->hi_water = 0;
+	ctx->lo_water = 0;
+	ctx->hi_called = ISC_FALSE;
+	ctx->is_overmem = ISC_FALSE;
+	ctx->water = NULL;
+	ctx->water_arg = NULL;
+	ctx->common.impmagic = MEM_MAGIC;
+	ctx->common.magic = ISCAPI_MCTX_MAGIC;
+	ctx->common.methods = (isc_memmethods_t *)&memmethods;
+	isc_ondestroy_init(&ctx->ondestroy);
+	ctx->memalloc = memalloc;
+	ctx->memfree = memfree;
+	ctx->arg = arg;
+	ctx->stats = NULL;
+	ctx->checkfree = ISC_TRUE;
+#if ISC_MEM_TRACKLINES
+	ctx->debuglist = NULL;
+	ctx->debuglistcnt = 0;
+#endif
+	ISC_LIST_INIT(ctx->pools);
+	ctx->poolcnt = 0;
+	ctx->freelists = NULL;
+	ctx->basic_blocks = NULL;
+	ctx->basic_table = NULL;
+	ctx->basic_table_count = 0;
+	ctx->basic_table_size = 0;
+	ctx->lowest = NULL;
+	ctx->highest = NULL;
+
+	ctx->stats = (memalloc)(arg,
+				(ctx->max_size+1) * sizeof(struct stats));
+	if (ctx->stats == NULL) {
+		result = ISC_R_NOMEMORY;
+		goto error;
+	}
+	memset(ctx->stats, 0, (ctx->max_size + 1) * sizeof(struct stats));
+
+	if ((flags & ISC_MEMFLAG_INTERNAL) != 0) {
+		if (target_size == 0U)
+			ctx->mem_target = DEF_MEM_TARGET;
+		else
+			ctx->mem_target = target_size;
+		ctx->freelists = (memalloc)(arg, ctx->max_size *
+						 sizeof(element *));
+		if (ctx->freelists == NULL) {
+			result = ISC_R_NOMEMORY;
+			goto error;
+		}
+		memset(ctx->freelists, 0,
+		       ctx->max_size * sizeof(element *));
+	}
+
+#if ISC_MEM_TRACKLINES
+	if ((isc_mem_debugging & ISC_MEM_DEBUGRECORD) != 0) {
+		unsigned int i;
+
+		ctx->debuglist = (memalloc)(arg,
+				      (ctx->max_size+1) * sizeof(debuglist_t));
+		if (ctx->debuglist == NULL) {
+			result = ISC_R_NOMEMORY;
+			goto error;
+		}
+		for (i = 0; i <= ctx->max_size; i++)
+			ISC_LIST_INIT(ctx->debuglist[i]);
+	}
+#endif
+
+	ctx->memalloc_failures = 0;
+
+	LOCK(&lock);
+	ISC_LIST_INITANDAPPEND(contexts, ctx, link);
+	UNLOCK(&lock);
+
+	*ctxp = (isc_mem_t *)ctx;
+	return (ISC_R_SUCCESS);
+
+  error:
+	if (ctx != NULL) {
+		if (ctx->stats != NULL)
+			(memfree)(arg, ctx->stats);
+		if (ctx->freelists != NULL)
+			(memfree)(arg, ctx->freelists);
+#if ISC_MEM_TRACKLINES
+		if (ctx->debuglist != NULL)
+			(ctx->memfree)(ctx->arg, ctx->debuglist);
+#endif /* ISC_MEM_TRACKLINES */
+		if ((ctx->flags & ISC_MEMFLAG_NOLOCK) == 0)
+			DESTROYLOCK(&ctx->lock);
+		(memfree)(arg, ctx);
+	}
+
+	return (result);
+}
+
+ISC_MEMFUNC_SCOPE isc_result_t
+isc__mem_create(size_t init_max_size, size_t target_size, isc_mem_t **ctxp) {
+	return (isc__mem_createx2(init_max_size, target_size,
+				  default_memalloc, default_memfree, NULL,
+				  ctxp, ISC_MEMFLAG_DEFAULT));
+}
+
+ISC_MEMFUNC_SCOPE isc_result_t
+isc__mem_create2(size_t init_max_size, size_t target_size,
+		 isc_mem_t **ctxp, unsigned int flags)
+{
+	return (isc__mem_createx2(init_max_size, target_size,
+				  default_memalloc, default_memfree, NULL,
+				  ctxp, flags));
+}
+
+static void
+destroy(isc__mem_t *ctx) {
+	unsigned int i;
+	isc_ondestroy_t ondest;
+
+	LOCK(&lock);
+	ISC_LIST_UNLINK(contexts, ctx, link);
+	totallost += ctx->inuse;
+	UNLOCK(&lock);
+
+	ctx->common.impmagic = 0;
+	ctx->common.magic = 0;
+
+	INSIST(ISC_LIST_EMPTY(ctx->pools));
+
+#if ISC_MEM_TRACKLINES
+	if (ctx->debuglist != NULL) {
+		if (ctx->checkfree) {
+			for (i = 0; i <= ctx->max_size; i++) {
+				if (!ISC_LIST_EMPTY(ctx->debuglist[i]))
+					print_active(ctx, stderr);
+				INSIST(ISC_LIST_EMPTY(ctx->debuglist[i]));
+			}
+		} else {
+			debuglink_t *dl;
+
+			for (i = 0; i <= ctx->max_size; i++)
+				for (dl = ISC_LIST_HEAD(ctx->debuglist[i]);
+				     dl != NULL;
+				     dl = ISC_LIST_HEAD(ctx->debuglist[i])) {
+					ISC_LIST_UNLINK(ctx->debuglist[i],
+							dl, link);
+					free(dl);
+				}
+		}
+		(ctx->memfree)(ctx->arg, ctx->debuglist);
+	}
+#endif
+	INSIST(ctx->references == 0);
+
+	if (ctx->checkfree) {
+		for (i = 0; i <= ctx->max_size; i++) {
+#if ISC_MEM_TRACKLINES
+			if (ctx->stats[i].gets != 0U)
+				print_active(ctx, stderr);
+#endif
+			INSIST(ctx->stats[i].gets == 0U);
+		}
+	}
+
+	(ctx->memfree)(ctx->arg, ctx->stats);
+
+	if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
+		for (i = 0; i < ctx->basic_table_count; i++)
+			(ctx->memfree)(ctx->arg, ctx->basic_table[i]);
+		(ctx->memfree)(ctx->arg, ctx->freelists);
+		if (ctx->basic_table != NULL)
+			(ctx->memfree)(ctx->arg, ctx->basic_table);
+	}
+
+	ondest = ctx->ondestroy;
+
+	if ((ctx->flags & ISC_MEMFLAG_NOLOCK) == 0)
+		DESTROYLOCK(&ctx->lock);
+	(ctx->memfree)(ctx->arg, ctx);
+
+	isc_ondestroy_notify(&ondest, ctx);
+}
+
+ISC_MEMFUNC_SCOPE void
+isc__mem_attach(isc_mem_t *source0, isc_mem_t **targetp) {
+	isc__mem_t *source = (isc__mem_t *)source0;
+
+	REQUIRE(VALID_CONTEXT(source));
+	REQUIRE(targetp != NULL && *targetp == NULL);
+
+	MCTXLOCK(source, &source->lock);
+	source->references++;
+	MCTXUNLOCK(source, &source->lock);
+
+	*targetp = (isc_mem_t *)source;
+}
+
+ISC_MEMFUNC_SCOPE void
+isc__mem_detach(isc_mem_t **ctxp) {
+	isc__mem_t *ctx;
+	isc_boolean_t want_destroy = ISC_FALSE;
+
+	REQUIRE(ctxp != NULL);
+	ctx = (isc__mem_t *)*ctxp;
+	REQUIRE(VALID_CONTEXT(ctx));
+
+	MCTXLOCK(ctx, &ctx->lock);
+	INSIST(ctx->references > 0);
+	ctx->references--;
+	if (ctx->references == 0)
+		want_destroy = ISC_TRUE;
+	MCTXUNLOCK(ctx, &ctx->lock);
+
+	if (want_destroy)
+		destroy(ctx);
+
+	*ctxp = NULL;
+}
+
+/*
+ * isc_mem_putanddetach() is the equivalent of:
+ *
+ * mctx = NULL;
+ * isc_mem_attach(ptr->mctx, &mctx);
+ * isc_mem_detach(&ptr->mctx);
+ * isc_mem_put(mctx, ptr, sizeof(*ptr);
+ * isc_mem_detach(&mctx);
+ */
+
+ISC_MEMFUNC_SCOPE void
+isc___mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG) {
+	isc__mem_t *ctx;
+	isc_boolean_t want_destroy = ISC_FALSE;
+	size_info *si;
+	size_t oldsize;
+
+	REQUIRE(ctxp != NULL);
+	ctx = (isc__mem_t *)*ctxp;
+	REQUIRE(VALID_CONTEXT(ctx));
+	REQUIRE(ptr != NULL);
+
+	/*
+	 * Must be before mem_putunlocked() as ctxp is usually within
+	 * [ptr..ptr+size).
+	 */
+	*ctxp = NULL;
+
+	if ((isc_mem_debugging & (ISC_MEM_DEBUGSIZE|ISC_MEM_DEBUGCTX)) != 0) {
+		if ((isc_mem_debugging & ISC_MEM_DEBUGSIZE) != 0) {
+			si = &(((size_info *)ptr)[-1]);
+			oldsize = si->u.size - ALIGNMENT_SIZE;
+			if ((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0)
+				oldsize -= ALIGNMENT_SIZE;
+			INSIST(oldsize == size);
+		}
+		isc_mem_free((isc_mem_t *)ctx, ptr);
+
+		MCTXLOCK(ctx, &ctx->lock);
+		ctx->references--;
+		if (ctx->references == 0)
+			want_destroy = ISC_TRUE;
+		MCTXUNLOCK(ctx, &ctx->lock);
+		if (want_destroy)
+			destroy(ctx);
+
+		return;
+	}
+
+	if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
+		MCTXLOCK(ctx, &ctx->lock);
+		mem_putunlocked(ctx, ptr, size);
+	} else {
+		mem_put(ctx, ptr, size);
+		MCTXLOCK(ctx, &ctx->lock);
+		mem_putstats(ctx, ptr, size);
+	}
+
+	DELETE_TRACE(ctx, ptr, size, file, line);
+	INSIST(ctx->references > 0);
+	ctx->references--;
+	if (ctx->references == 0)
+		want_destroy = ISC_TRUE;
+
+	MCTXUNLOCK(ctx, &ctx->lock);
+
+	if (want_destroy)
+		destroy(ctx);
+}
+
+ISC_MEMFUNC_SCOPE void
+isc__mem_destroy(isc_mem_t **ctxp) {
+	isc__mem_t *ctx;
+
+	/*
+	 * This routine provides legacy support for callers who use mctxs
+	 * without attaching/detaching.
+	 */
+
+	REQUIRE(ctxp != NULL);
+	ctx = (isc__mem_t *)*ctxp;
+	REQUIRE(VALID_CONTEXT(ctx));
+
+	MCTXLOCK(ctx, &ctx->lock);
+#if ISC_MEM_TRACKLINES
+	if (ctx->references != 1)
+		print_active(ctx, stderr);
+#endif
+	REQUIRE(ctx->references == 1);
+	ctx->references--;
+	MCTXUNLOCK(ctx, &ctx->lock);
+
+	destroy(ctx);
+
+	*ctxp = NULL;
+}
+
+ISC_MEMFUNC_SCOPE isc_result_t
+isc__mem_ondestroy(isc_mem_t *ctx0, isc_task_t *task, isc_event_t **event) {
+	isc__mem_t *ctx = (isc__mem_t *)ctx0;
+	isc_result_t res;
+
+	MCTXLOCK(ctx, &ctx->lock);
+	res = isc_ondestroy_register(&ctx->ondestroy, task, event);
+	MCTXUNLOCK(ctx, &ctx->lock);
+
+	return (res);
+}
+
+ISC_MEMFUNC_SCOPE void *
+isc___mem_get(isc_mem_t *ctx0, size_t size FLARG) {
+	isc__mem_t *ctx = (isc__mem_t *)ctx0;
+	void *ptr;
+	isc_boolean_t call_water = ISC_FALSE;
+
+	REQUIRE(VALID_CONTEXT(ctx));
+
+	if ((isc_mem_debugging & (ISC_MEM_DEBUGSIZE|ISC_MEM_DEBUGCTX)) != 0)
+		return (isc__mem_allocate(ctx0, size FLARG_PASS));
+
+	if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
+		MCTXLOCK(ctx, &ctx->lock);
+		ptr = mem_getunlocked(ctx, size);
+	} else {
+		ptr = mem_get(ctx, size);
+		MCTXLOCK(ctx, &ctx->lock);
+		if (ptr != NULL)
+			mem_getstats(ctx, size);
+	}
+
+	ADD_TRACE(ctx, ptr, size, file, line);
+	if (ctx->hi_water != 0U && ctx->inuse > ctx->hi_water &&
+	    !ctx->is_overmem) {
+		ctx->is_overmem = ISC_TRUE;
+	}
+	if (ctx->hi_water != 0U && !ctx->hi_called &&
+	    ctx->inuse > ctx->hi_water) {
+		call_water = ISC_TRUE;
+	}
+	if (ctx->inuse > ctx->maxinuse) {
+		ctx->maxinuse = ctx->inuse;
+		if (ctx->hi_water != 0U && ctx->inuse > ctx->hi_water &&
+		    (isc_mem_debugging & ISC_MEM_DEBUGUSAGE) != 0)
+			fprintf(stderr, "maxinuse = %lu\n",
+				(unsigned long)ctx->inuse);
+	}
+	MCTXUNLOCK(ctx, &ctx->lock);
+
+	if (call_water)
+		(ctx->water)(ctx->water_arg, ISC_MEM_HIWATER);
+
+	return (ptr);
+}
+
+ISC_MEMFUNC_SCOPE void
+isc___mem_put(isc_mem_t *ctx0, void *ptr, size_t size FLARG) {
+	isc__mem_t *ctx = (isc__mem_t *)ctx0;
+	isc_boolean_t call_water = ISC_FALSE;
+	size_info *si;
+	size_t oldsize;
+
+	REQUIRE(VALID_CONTEXT(ctx));
+	REQUIRE(ptr != NULL);
+
+	if ((isc_mem_debugging & (ISC_MEM_DEBUGSIZE|ISC_MEM_DEBUGCTX)) != 0) {
+		if ((isc_mem_debugging & ISC_MEM_DEBUGSIZE) != 0) {
+			si = &(((size_info *)ptr)[-1]);
+			oldsize = si->u.size - ALIGNMENT_SIZE;
+			if ((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0)
+				oldsize -= ALIGNMENT_SIZE;
+			INSIST(oldsize == size);
+		}
+		isc_mem_free((isc_mem_t *)ctx, ptr);
+		return;
+	}
+
+	if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
+		MCTXLOCK(ctx, &ctx->lock);
+		mem_putunlocked(ctx, ptr, size);
+	} else {
+		mem_put(ctx, ptr, size);
+		MCTXLOCK(ctx, &ctx->lock);
+		mem_putstats(ctx, ptr, size);
+	}
+
+	DELETE_TRACE(ctx, ptr, size, file, line);
+
+	/*
+	 * The check against ctx->lo_water == 0 is for the condition
+	 * when the context was pushed over hi_water but then had
+	 * isc_mem_setwater() called with 0 for hi_water and lo_water.
+	 */
+	if (ctx->is_overmem &&
+	    (ctx->inuse < ctx->lo_water || ctx->lo_water == 0U)) {
+		ctx->is_overmem = ISC_FALSE;
+	}
+	if (ctx->hi_called &&
+	    (ctx->inuse < ctx->lo_water || ctx->lo_water == 0U)) {
+		if (ctx->water != NULL)
+			call_water = ISC_TRUE;
+	}
+	MCTXUNLOCK(ctx, &ctx->lock);
+
+	if (call_water)
+		(ctx->water)(ctx->water_arg, ISC_MEM_LOWATER);
+}
+
+ISC_MEMFUNC_SCOPE void
+isc__mem_waterack(isc_mem_t *ctx0, int flag) {
+	isc__mem_t *ctx = (isc__mem_t *)ctx0;
+
+	REQUIRE(VALID_CONTEXT(ctx));
+
+	MCTXLOCK(ctx, &ctx->lock);
+	if (flag == ISC_MEM_LOWATER)
+		ctx->hi_called = ISC_FALSE;
+	else if (flag == ISC_MEM_HIWATER)
+		ctx->hi_called = ISC_TRUE;
+	MCTXUNLOCK(ctx, &ctx->lock);
+}
+
+#if ISC_MEM_TRACKLINES
+static void
+print_active(isc__mem_t *mctx, FILE *out) {
+	if (mctx->debuglist != NULL) {
+		debuglink_t *dl;
+		unsigned int i, j;
+		const char *format;
+		isc_boolean_t found;
+
+		fprintf(out, "%s", isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
+					    ISC_MSG_DUMPALLOC,
+					    "Dump of all outstanding "
+					    "memory allocations:\n"));
+		found = ISC_FALSE;
+		format = isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
+					ISC_MSG_PTRFILELINE,
+					"\tptr %p size %u file %s line %u\n");
+		for (i = 0; i <= mctx->max_size; i++) {
+			dl = ISC_LIST_HEAD(mctx->debuglist[i]);
+
+			if (dl != NULL)
+				found = ISC_TRUE;
+
+			while (dl != NULL) {
+				for (j = 0; j < DEBUGLIST_COUNT; j++)
+					if (dl->ptr[j] != NULL)
+						fprintf(out, format,
+							dl->ptr[j],
+							dl->size[j],
+							dl->file[j],
+							dl->line[j]);
+				dl = ISC_LIST_NEXT(dl, link);
+			}
+		}
+		if (!found)
+			fprintf(out, "%s", isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
+						    ISC_MSG_NONE, "\tNone.\n"));
+	}
+}
+#endif
+
+/*
+ * Print the stats[] on the stream "out" with suitable formatting.
+ */
+ISC_MEMFUNC_SCOPE void
+isc__mem_stats(isc_mem_t *ctx0, FILE *out) {
+	isc__mem_t *ctx = (isc__mem_t *)ctx0;
+	size_t i;
+	const struct stats *s;
+	const isc__mempool_t *pool;
+
+	REQUIRE(VALID_CONTEXT(ctx));
+	MCTXLOCK(ctx, &ctx->lock);
+
+	for (i = 0; i <= ctx->max_size; i++) {
+		s = &ctx->stats[i];
+
+		if (s->totalgets == 0U && s->gets == 0U)
+			continue;
+		fprintf(out, "%s%5lu: %11lu gets, %11lu rem",
+			(i == ctx->max_size) ? ">=" : "  ",
+			(unsigned long) i, s->totalgets, s->gets);
+		if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0 &&
+		    (s->blocks != 0U || s->freefrags != 0U))
+			fprintf(out, " (%lu bl, %lu ff)",
+				s->blocks, s->freefrags);
+		fputc('\n', out);
+	}
+
+	/*
+	 * Note that since a pool can be locked now, these stats might be
+	 * somewhat off if the pool is in active use at the time the stats
+	 * are dumped.  The link fields are protected by the isc_mem_t's
+	 * lock, however, so walking this list and extracting integers from
+	 * stats fields is always safe.
+	 */
+	pool = ISC_LIST_HEAD(ctx->pools);
+	if (pool != NULL) {
+		fprintf(out, "%s", isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
+					    ISC_MSG_POOLSTATS,
+					    "[Pool statistics]\n"));
+		fprintf(out, "%15s %10s %10s %10s %10s %10s %10s %10s %1s\n",
+			isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
+				       ISC_MSG_POOLNAME, "name"),
+			isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
+				       ISC_MSG_POOLSIZE, "size"),
+			isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
+				       ISC_MSG_POOLMAXALLOC, "maxalloc"),
+			isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
+				       ISC_MSG_POOLALLOCATED, "allocated"),
+			isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
+				       ISC_MSG_POOLFREECOUNT, "freecount"),
+			isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
+				       ISC_MSG_POOLFREEMAX, "freemax"),
+			isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
+				       ISC_MSG_POOLFILLCOUNT, "fillcount"),
+			isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
+				       ISC_MSG_POOLGETS, "gets"),
+			"L");
+	}
+	while (pool != NULL) {
+		fprintf(out, "%15s %10lu %10u %10u %10u %10u %10u %10u %s\n",
+			pool->name, (unsigned long) pool->size, pool->maxalloc,
+			pool->allocated, pool->freecount, pool->freemax,
+			pool->fillcount, pool->gets,
+			(pool->lock == NULL ? "N" : "Y"));
+		pool = ISC_LIST_NEXT(pool, link);
+	}
+
+#if ISC_MEM_TRACKLINES
+	print_active(ctx, out);
+#endif
+
+	MCTXUNLOCK(ctx, &ctx->lock);
+}
+
+/*
+ * Replacements for malloc() and free() -- they implicitly remember the
+ * size of the object allocated (with some additional overhead).
+ */
+
+static void *
+isc__mem_allocateunlocked(isc_mem_t *ctx0, size_t size) {
+	isc__mem_t *ctx = (isc__mem_t *)ctx0;
+	size_info *si;
+
+	size += ALIGNMENT_SIZE;
+	if ((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0)
+		size += ALIGNMENT_SIZE;
+
+	if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0)
+		si = mem_getunlocked(ctx, size);
+	else
+		si = mem_get(ctx, size);
+
+	if (si == NULL)
+		return (NULL);
+	if ((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0) {
+		si->u.ctx = ctx;
+		si++;
+	}
+	si->u.size = size;
+	return (&si[1]);
+}
+
+ISC_MEMFUNC_SCOPE void *
+isc___mem_allocate(isc_mem_t *ctx0, size_t size FLARG) {
+	isc__mem_t *ctx = (isc__mem_t *)ctx0;
+	size_info *si;
+	isc_boolean_t call_water = ISC_FALSE;
+
+	REQUIRE(VALID_CONTEXT(ctx));
+
+	if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
+		MCTXLOCK(ctx, &ctx->lock);
+		si = isc__mem_allocateunlocked((isc_mem_t *)ctx, size);
+	} else {
+		si = isc__mem_allocateunlocked((isc_mem_t *)ctx, size);
+		MCTXLOCK(ctx, &ctx->lock);
+		if (si != NULL)
+			mem_getstats(ctx, si[-1].u.size);
+	}
+
+#if ISC_MEM_TRACKLINES
+	ADD_TRACE(ctx, si, si[-1].u.size, file, line);
+#endif
+	if (ctx->hi_water != 0U && ctx->inuse > ctx->hi_water &&
+	    !ctx->is_overmem) {
+		ctx->is_overmem = ISC_TRUE;
+	}
+
+	if (ctx->hi_water != 0U && !ctx->hi_called &&
+	    ctx->inuse > ctx->hi_water) {
+		ctx->hi_called = ISC_TRUE;
+		call_water = ISC_TRUE;
+	}
+	if (ctx->inuse > ctx->maxinuse) {
+		ctx->maxinuse = ctx->inuse;
+		if (ctx->hi_water != 0U && ctx->inuse > ctx->hi_water &&
+		    (isc_mem_debugging & ISC_MEM_DEBUGUSAGE) != 0)
+			fprintf(stderr, "maxinuse = %lu\n",
+				(unsigned long)ctx->inuse);
+	}
+	MCTXUNLOCK(ctx, &ctx->lock);
+
+	if (call_water)
+		(ctx->water)(ctx->water_arg, ISC_MEM_HIWATER);
+
+	return (si);
+}
+
+ISC_MEMFUNC_SCOPE void *
+isc___mem_reallocate(isc_mem_t *ctx0, void *ptr, size_t size FLARG) {
+	isc__mem_t *ctx = (isc__mem_t *)ctx0;
+	void *new_ptr = NULL;
+	size_t oldsize, copysize;
+
+	REQUIRE(VALID_CONTEXT(ctx));
+
+	/*
+	 * This function emulates the realloc(3) standard library function:
+	 * - if size > 0, allocate new memory; and if ptr is non NULL, copy
+	 *   as much of the old contents to the new buffer and free the old one.
+	 *   Note that when allocation fails the original pointer is intact;
+	 *   the caller must free it.
+	 * - if size is 0 and ptr is non NULL, simply free the given ptr.
+	 * - this function returns:
+	 *     pointer to the newly allocated memory, or
+	 *     NULL if allocation fails or doesn't happen.
+	 */
+	if (size > 0U) {
+		new_ptr = isc__mem_allocate(ctx0, size FLARG_PASS);
+		if (new_ptr != NULL && ptr != NULL) {
+			oldsize = (((size_info *)ptr)[-1]).u.size;
+			INSIST(oldsize >= ALIGNMENT_SIZE);
+			oldsize -= ALIGNMENT_SIZE;
+			copysize = oldsize > size ? size : oldsize;
+			memcpy(new_ptr, ptr, copysize);
+			isc__mem_free(ctx0, ptr FLARG_PASS);
+		}
+	} else if (ptr != NULL)
+		isc__mem_free(ctx0, ptr FLARG_PASS);
+
+	return (new_ptr);
+}
+
+ISC_MEMFUNC_SCOPE void
+isc___mem_free(isc_mem_t *ctx0, void *ptr FLARG) {
+	isc__mem_t *ctx = (isc__mem_t *)ctx0;
+	size_info *si;
+	size_t size;
+	isc_boolean_t call_water= ISC_FALSE;
+
+	REQUIRE(VALID_CONTEXT(ctx));
+	REQUIRE(ptr != NULL);
+
+	if ((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0) {
+		si = &(((size_info *)ptr)[-2]);
+		REQUIRE(si->u.ctx == ctx);
+		size = si[1].u.size;
+	} else {
+		si = &(((size_info *)ptr)[-1]);
+		size = si->u.size;
+	}
+
+	if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
+		MCTXLOCK(ctx, &ctx->lock);
+		mem_putunlocked(ctx, si, size);
+	} else {
+		mem_put(ctx, si, size);
+		MCTXLOCK(ctx, &ctx->lock);
+		mem_putstats(ctx, si, size);
+	}
+
+	DELETE_TRACE(ctx, ptr, size, file, line);
+
+	/*
+	 * The check against ctx->lo_water == 0 is for the condition
+	 * when the context was pushed over hi_water but then had
+	 * isc_mem_setwater() called with 0 for hi_water and lo_water.
+	 */
+	if (ctx->is_overmem &&
+	    (ctx->inuse < ctx->lo_water || ctx->lo_water == 0U)) {
+		ctx->is_overmem = ISC_FALSE;
+	}
+
+	if (ctx->hi_called &&
+	    (ctx->inuse < ctx->lo_water || ctx->lo_water == 0U)) {
+		ctx->hi_called = ISC_FALSE;
+
+		if (ctx->water != NULL)
+			call_water = ISC_TRUE;
+	}
+	MCTXUNLOCK(ctx, &ctx->lock);
+
+	if (call_water)
+		(ctx->water)(ctx->water_arg, ISC_MEM_LOWATER);
+}
+
+
+/*
+ * Other useful things.
+ */
+
+ISC_MEMFUNC_SCOPE char *
+isc___mem_strdup(isc_mem_t *mctx0, const char *s FLARG) {
+	isc__mem_t *mctx = (isc__mem_t *)mctx0;
+	size_t len;
+	char *ns;
+
+	REQUIRE(VALID_CONTEXT(mctx));
+	REQUIRE(s != NULL);
+
+	len = strlen(s);
+
+	ns = isc___mem_allocate((isc_mem_t *)mctx, len + 1 FLARG_PASS);
+
+	if (ns != NULL)
+		strncpy(ns, s, len + 1);
+
+	return (ns);
+}
+
+ISC_MEMFUNC_SCOPE void
+isc__mem_setdestroycheck(isc_mem_t *ctx0, isc_boolean_t flag) {
+	isc__mem_t *ctx = (isc__mem_t *)ctx0;
+
+	REQUIRE(VALID_CONTEXT(ctx));
+	MCTXLOCK(ctx, &ctx->lock);
+
+	ctx->checkfree = flag;
+
+	MCTXUNLOCK(ctx, &ctx->lock);
+}
+
+/*
+ * Quotas
+ */
+
+ISC_MEMFUNC_SCOPE void
+isc__mem_setquota(isc_mem_t *ctx0, size_t quota) {
+	isc__mem_t *ctx = (isc__mem_t *)ctx0;
+
+	REQUIRE(VALID_CONTEXT(ctx));
+	MCTXLOCK(ctx, &ctx->lock);
+
+	ctx->quota = quota;
+
+	MCTXUNLOCK(ctx, &ctx->lock);
+}
+
+ISC_MEMFUNC_SCOPE size_t
+isc__mem_getquota(isc_mem_t *ctx0) {
+	isc__mem_t *ctx = (isc__mem_t *)ctx0;
+	size_t quota;
+
+	REQUIRE(VALID_CONTEXT(ctx));
+	MCTXLOCK(ctx, &ctx->lock);
+
+	quota = ctx->quota;
+
+	MCTXUNLOCK(ctx, &ctx->lock);
+
+	return (quota);
+}
+
+ISC_MEMFUNC_SCOPE size_t
+isc__mem_inuse(isc_mem_t *ctx0) {
+	isc__mem_t *ctx = (isc__mem_t *)ctx0;
+	size_t inuse;
+
+	REQUIRE(VALID_CONTEXT(ctx));
+	MCTXLOCK(ctx, &ctx->lock);
+
+	inuse = ctx->inuse;
+
+	MCTXUNLOCK(ctx, &ctx->lock);
+
+	return (inuse);
+}
+
+ISC_MEMFUNC_SCOPE void
+isc__mem_setwater(isc_mem_t *ctx0, isc_mem_water_t water, void *water_arg,
+		 size_t hiwater, size_t lowater)
+{
+	isc__mem_t *ctx = (isc__mem_t *)ctx0;
+	isc_boolean_t callwater = ISC_FALSE;
+	isc_mem_water_t oldwater;
+	void *oldwater_arg;
+
+	REQUIRE(VALID_CONTEXT(ctx));
+	REQUIRE(hiwater >= lowater);
+
+	MCTXLOCK(ctx, &ctx->lock);
+	oldwater = ctx->water;
+	oldwater_arg = ctx->water_arg;
+	if (water == NULL) {
+		callwater = ctx->hi_called;
+		ctx->water = NULL;
+		ctx->water_arg = NULL;
+		ctx->hi_water = 0;
+		ctx->lo_water = 0;
+		ctx->hi_called = ISC_FALSE;
+	} else {
+		if (ctx->hi_called &&
+		    (ctx->water != water || ctx->water_arg != water_arg ||
+		     ctx->inuse < lowater || lowater == 0U))
+			callwater = ISC_TRUE;
+		ctx->water = water;
+		ctx->water_arg = water_arg;
+		ctx->hi_water = hiwater;
+		ctx->lo_water = lowater;
+		ctx->hi_called = ISC_FALSE;
+	}
+	MCTXUNLOCK(ctx, &ctx->lock);
+
+	if (callwater && oldwater != NULL)
+		(oldwater)(oldwater_arg, ISC_MEM_LOWATER);
+}
+
+ISC_MEMFUNC_SCOPE isc_boolean_t
+isc__mem_isovermem(isc_mem_t *ctx0) {
+	isc__mem_t *ctx = (isc__mem_t *)ctx0;
+
+	REQUIRE(VALID_CONTEXT(ctx));
+
+	/*
+	 * We don't bother to lock the context because 100% accuracy isn't
+	 * necessary (and even if we locked the context the returned value
+	 * could be different from the actual state when it's used anyway)
+	 */
+	return (ctx->is_overmem);
+}
+
+ISC_MEMFUNC_SCOPE void
+isc__mem_setname(isc_mem_t *ctx0, const char *name, void *tag) {
+	isc__mem_t *ctx = (isc__mem_t *)ctx0;
+
+	REQUIRE(VALID_CONTEXT(ctx));
+
+	LOCK(&ctx->lock);
+	memset(ctx->name, 0, sizeof(ctx->name));
+	strncpy(ctx->name, name, sizeof(ctx->name) - 1);
+	ctx->tag = tag;
+	UNLOCK(&ctx->lock);
+}
+
+ISC_MEMFUNC_SCOPE const char *
+isc__mem_getname(isc_mem_t *ctx0) {
+	isc__mem_t *ctx = (isc__mem_t *)ctx0;
+
+	REQUIRE(VALID_CONTEXT(ctx));
+
+	return (ctx->name);
+}
+
+ISC_MEMFUNC_SCOPE void *
+isc__mem_gettag(isc_mem_t *ctx0) {
+	isc__mem_t *ctx = (isc__mem_t *)ctx0;
+
+	REQUIRE(VALID_CONTEXT(ctx));
+
+	return (ctx->tag);
+}
+
+/*
+ * Memory pool stuff
+ */
+
+ISC_MEMFUNC_SCOPE isc_result_t
+isc__mempool_create(isc_mem_t *mctx0, size_t size, isc_mempool_t **mpctxp) {
+	isc__mem_t *mctx = (isc__mem_t *)mctx0;
+	isc__mempool_t *mpctx;
+
+	REQUIRE(VALID_CONTEXT(mctx));
+	REQUIRE(size > 0U);
+	REQUIRE(mpctxp != NULL && *mpctxp == NULL);
+
+	/*
+	 * Allocate space for this pool, initialize values, and if all works
+	 * well, attach to the memory context.
+	 */
+	mpctx = isc_mem_get((isc_mem_t *)mctx, sizeof(isc__mempool_t));
+	if (mpctx == NULL)
+		return (ISC_R_NOMEMORY);
+
+	mpctx->common.methods = (isc_mempoolmethods_t *)&mempoolmethods;
+	mpctx->common.impmagic = MEMPOOL_MAGIC;
+	mpctx->common.magic = ISCAPI_MPOOL_MAGIC;
+	mpctx->lock = NULL;
+	mpctx->mctx = mctx;
+	mpctx->size = size;
+	mpctx->maxalloc = UINT_MAX;
+	mpctx->allocated = 0;
+	mpctx->freecount = 0;
+	mpctx->freemax = 1;
+	mpctx->fillcount = 1;
+	mpctx->gets = 0;
+#if ISC_MEMPOOL_NAMES
+	mpctx->name[0] = 0;
+#endif
+	mpctx->items = NULL;
+
+	*mpctxp = (isc_mempool_t *)mpctx;
+
+	MCTXLOCK(mctx, &mctx->lock);
+	ISC_LIST_INITANDAPPEND(mctx->pools, mpctx, link);
+	mctx->poolcnt++;
+	MCTXUNLOCK(mctx, &mctx->lock);
+
+	return (ISC_R_SUCCESS);
+}
+
+ISC_MEMFUNC_SCOPE void
+isc__mempool_setname(isc_mempool_t *mpctx0, const char *name) {
+	isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
+
+	REQUIRE(name != NULL);
+	REQUIRE(VALID_MEMPOOL(mpctx));
+
+#if ISC_MEMPOOL_NAMES
+	if (mpctx->lock != NULL)
+		LOCK(mpctx->lock);
+
+	strncpy(mpctx->name, name, sizeof(mpctx->name) - 1);
+	mpctx->name[sizeof(mpctx->name) - 1] = '\0';
+
+	if (mpctx->lock != NULL)
+		UNLOCK(mpctx->lock);
+#else
+	UNUSED(mpctx);
+	UNUSED(name);
+#endif
+}
+
+ISC_MEMFUNC_SCOPE void
+isc__mempool_destroy(isc_mempool_t **mpctxp) {
+	isc__mempool_t *mpctx;
+	isc__mem_t *mctx;
+	isc_mutex_t *lock;
+	element *item;
+
+	REQUIRE(mpctxp != NULL);
+	mpctx = (isc__mempool_t *)*mpctxp;
+	REQUIRE(VALID_MEMPOOL(mpctx));
+#if ISC_MEMPOOL_NAMES
+	if (mpctx->allocated > 0)
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "isc__mempool_destroy(): mempool %s "
+				 "leaked memory",
+				 mpctx->name);
+#endif
+	REQUIRE(mpctx->allocated == 0);
+
+	mctx = mpctx->mctx;
+
+	lock = mpctx->lock;
+
+	if (lock != NULL)
+		LOCK(lock);
+
+	/*
+	 * Return any items on the free list
+	 */
+	MCTXLOCK(mctx, &mctx->lock);
+	while (mpctx->items != NULL) {
+		INSIST(mpctx->freecount > 0);
+		mpctx->freecount--;
+		item = mpctx->items;
+		mpctx->items = item->next;
+
+		if ((mctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
+			mem_putunlocked(mctx, item, mpctx->size);
+		} else {
+			mem_put(mctx, item, mpctx->size);
+			mem_putstats(mctx, item, mpctx->size);
+		}
+	}
+	MCTXUNLOCK(mctx, &mctx->lock);
+
+	/*
+	 * Remove our linked list entry from the memory context.
+	 */
+	MCTXLOCK(mctx, &mctx->lock);
+	ISC_LIST_UNLINK(mctx->pools, mpctx, link);
+	mctx->poolcnt--;
+	MCTXUNLOCK(mctx, &mctx->lock);
+
+	mpctx->common.impmagic = 0;
+	mpctx->common.magic = 0;
+
+	isc_mem_put((isc_mem_t *)mpctx->mctx, mpctx, sizeof(isc__mempool_t));
+
+	if (lock != NULL)
+		UNLOCK(lock);
+
+	*mpctxp = NULL;
+}
+
+ISC_MEMFUNC_SCOPE void
+isc__mempool_associatelock(isc_mempool_t *mpctx0, isc_mutex_t *lock) {
+	isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
+
+	REQUIRE(VALID_MEMPOOL(mpctx));
+	REQUIRE(mpctx->lock == NULL);
+	REQUIRE(lock != NULL);
+
+	mpctx->lock = lock;
+}
+
+ISC_MEMFUNC_SCOPE void *
+isc___mempool_get(isc_mempool_t *mpctx0 FLARG) {
+	isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
+	element *item;
+	isc__mem_t *mctx;
+	unsigned int i;
+
+	REQUIRE(VALID_MEMPOOL(mpctx));
+
+	mctx = mpctx->mctx;
+
+	if (mpctx->lock != NULL)
+		LOCK(mpctx->lock);
+
+	/*
+	 * Don't let the caller go over quota
+	 */
+	if (mpctx->allocated >= mpctx->maxalloc) {
+		item = NULL;
+		goto out;
+	}
+
+	/*
+	 * if we have a free list item, return the first here
+	 */
+	item = mpctx->items;
+	if (item != NULL) {
+		mpctx->items = item->next;
+		INSIST(mpctx->freecount > 0);
+		mpctx->freecount--;
+		mpctx->gets++;
+		mpctx->allocated++;
+		goto out;
+	}
+
+	/*
+	 * We need to dip into the well.  Lock the memory context here and
+	 * fill up our free list.
+	 */
+	MCTXLOCK(mctx, &mctx->lock);
+	for (i = 0; i < mpctx->fillcount; i++) {
+		if ((mctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
+			item = mem_getunlocked(mctx, mpctx->size);
+		} else {
+			item = mem_get(mctx, mpctx->size);
+			if (item != NULL)
+				mem_getstats(mctx, mpctx->size);
+		}
+		if (item == NULL)
+			break;
+		item->next = mpctx->items;
+		mpctx->items = item;
+		mpctx->freecount++;
+	}
+	MCTXUNLOCK(mctx, &mctx->lock);
+
+	/*
+	 * If we didn't get any items, return NULL.
+	 */
+	item = mpctx->items;
+	if (item == NULL)
+		goto out;
+
+	mpctx->items = item->next;
+	mpctx->freecount--;
+	mpctx->gets++;
+	mpctx->allocated++;
+
+ out:
+	if (mpctx->lock != NULL)
+		UNLOCK(mpctx->lock);
+
+#if ISC_MEM_TRACKLINES
+	if (item != NULL) {
+		MCTXLOCK(mctx, &mctx->lock);
+		ADD_TRACE(mctx, item, mpctx->size, file, line);
+		MCTXUNLOCK(mctx, &mctx->lock);
+	}
+#endif /* ISC_MEM_TRACKLINES */
+
+	return (item);
+}
+
+ISC_MEMFUNC_SCOPE void
+isc___mempool_put(isc_mempool_t *mpctx0, void *mem FLARG) {
+	isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
+	isc__mem_t *mctx;
+	element *item;
+
+	REQUIRE(VALID_MEMPOOL(mpctx));
+	REQUIRE(mem != NULL);
+
+	mctx = mpctx->mctx;
+
+	if (mpctx->lock != NULL)
+		LOCK(mpctx->lock);
+
+	INSIST(mpctx->allocated > 0);
+	mpctx->allocated--;
+
+#if ISC_MEM_TRACKLINES
+	MCTXLOCK(mctx, &mctx->lock);
+	DELETE_TRACE(mctx, mem, mpctx->size, file, line);
+	MCTXUNLOCK(mctx, &mctx->lock);
+#endif /* ISC_MEM_TRACKLINES */
+
+	/*
+	 * If our free list is full, return this to the mctx directly.
+	 */
+	if (mpctx->freecount >= mpctx->freemax) {
+		if ((mctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
+			MCTXLOCK(mctx, &mctx->lock);
+			mem_putunlocked(mctx, mem, mpctx->size);
+			MCTXUNLOCK(mctx, &mctx->lock);
+		} else {
+			mem_put(mctx, mem, mpctx->size);
+			MCTXLOCK(mctx, &mctx->lock);
+			mem_putstats(mctx, mem, mpctx->size);
+			MCTXUNLOCK(mctx, &mctx->lock);
+		}
+		if (mpctx->lock != NULL)
+			UNLOCK(mpctx->lock);
+		return;
+	}
+
+	/*
+	 * Otherwise, attach it to our free list and bump the counter.
+	 */
+	mpctx->freecount++;
+	item = (element *)mem;
+	item->next = mpctx->items;
+	mpctx->items = item;
+
+	if (mpctx->lock != NULL)
+		UNLOCK(mpctx->lock);
+}
+
+/*
+ * Quotas
+ */
+
+ISC_MEMFUNC_SCOPE void
+isc__mempool_setfreemax(isc_mempool_t *mpctx0, unsigned int limit) {
+	isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
+
+	REQUIRE(VALID_MEMPOOL(mpctx));
+
+	if (mpctx->lock != NULL)
+		LOCK(mpctx->lock);
+
+	mpctx->freemax = limit;
+
+	if (mpctx->lock != NULL)
+		UNLOCK(mpctx->lock);
+}
+
+ISC_MEMFUNC_SCOPE unsigned int
+isc__mempool_getfreemax(isc_mempool_t *mpctx0) {
+	isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
+	unsigned int freemax;
+
+	REQUIRE(VALID_MEMPOOL(mpctx));
+
+	if (mpctx->lock != NULL)
+		LOCK(mpctx->lock);
+
+	freemax = mpctx->freemax;
+
+	if (mpctx->lock != NULL)
+		UNLOCK(mpctx->lock);
+
+	return (freemax);
+}
+
+ISC_MEMFUNC_SCOPE unsigned int
+isc__mempool_getfreecount(isc_mempool_t *mpctx0) {
+	isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
+	unsigned int freecount;
+
+	REQUIRE(VALID_MEMPOOL(mpctx));
+
+	if (mpctx->lock != NULL)
+		LOCK(mpctx->lock);
+
+	freecount = mpctx->freecount;
+
+	if (mpctx->lock != NULL)
+		UNLOCK(mpctx->lock);
+
+	return (freecount);
+}
+
+ISC_MEMFUNC_SCOPE void
+isc__mempool_setmaxalloc(isc_mempool_t *mpctx0, unsigned int limit) {
+	isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
+
+	REQUIRE(limit > 0);
+
+	REQUIRE(VALID_MEMPOOL(mpctx));
+
+	if (mpctx->lock != NULL)
+		LOCK(mpctx->lock);
+
+	mpctx->maxalloc = limit;
+
+	if (mpctx->lock != NULL)
+		UNLOCK(mpctx->lock);
+}
+
+ISC_MEMFUNC_SCOPE unsigned int
+isc__mempool_getmaxalloc(isc_mempool_t *mpctx0) {
+	isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
+	unsigned int maxalloc;
+
+	REQUIRE(VALID_MEMPOOL(mpctx));
+
+	if (mpctx->lock != NULL)
+		LOCK(mpctx->lock);
+
+	maxalloc = mpctx->maxalloc;
+
+	if (mpctx->lock != NULL)
+		UNLOCK(mpctx->lock);
+
+	return (maxalloc);
+}
+
+ISC_MEMFUNC_SCOPE unsigned int
+isc__mempool_getallocated(isc_mempool_t *mpctx0) {
+	isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
+	unsigned int allocated;
+
+	REQUIRE(VALID_MEMPOOL(mpctx));
+
+	if (mpctx->lock != NULL)
+		LOCK(mpctx->lock);
+
+	allocated = mpctx->allocated;
+
+	if (mpctx->lock != NULL)
+		UNLOCK(mpctx->lock);
+
+	return (allocated);
+}
+
+ISC_MEMFUNC_SCOPE void
+isc__mempool_setfillcount(isc_mempool_t *mpctx0, unsigned int limit) {
+	isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
+
+	REQUIRE(limit > 0);
+	REQUIRE(VALID_MEMPOOL(mpctx));
+
+	if (mpctx->lock != NULL)
+		LOCK(mpctx->lock);
+
+	mpctx->fillcount = limit;
+
+	if (mpctx->lock != NULL)
+		UNLOCK(mpctx->lock);
+}
+
+ISC_MEMFUNC_SCOPE unsigned int
+isc__mempool_getfillcount(isc_mempool_t *mpctx0) {
+	isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
+
+	unsigned int fillcount;
+
+	REQUIRE(VALID_MEMPOOL(mpctx));
+
+	if (mpctx->lock != NULL)
+		LOCK(mpctx->lock);
+
+	fillcount = mpctx->fillcount;
+
+	if (mpctx->lock != NULL)
+		UNLOCK(mpctx->lock);
+
+	return (fillcount);
+}
+
+#ifdef USE_MEMIMPREGISTER
+isc_result_t
+isc__mem_register() {
+	return (isc_mem_register(isc__mem_create2));
+}
+#endif
+
+#ifdef BIND9
+ISC_MEMFUNC_SCOPE void
+isc__mem_printactive(isc_mem_t *ctx0, FILE *file) {
+	isc__mem_t *ctx = (isc__mem_t *)ctx0;
+
+	REQUIRE(VALID_CONTEXT(ctx));
+	REQUIRE(file != NULL);
+
+#if !ISC_MEM_TRACKLINES
+	UNUSED(ctx);
+	UNUSED(file);
+#else
+	print_active(ctx, file);
+#endif
+}
+
+ISC_MEMFUNC_SCOPE void
+isc__mem_printallactive(FILE *file) {
+#if !ISC_MEM_TRACKLINES
+	UNUSED(file);
+#else
+	isc__mem_t *ctx;
+
+	RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
+
+	LOCK(&lock);
+	for (ctx = ISC_LIST_HEAD(contexts);
+	     ctx != NULL;
+	     ctx = ISC_LIST_NEXT(ctx, link)) {
+		fprintf(file, "context: %p\n", ctx);
+		print_active(ctx, file);
+	}
+	UNLOCK(&lock);
+#endif
+}
+
+ISC_MEMFUNC_SCOPE void
+isc__mem_checkdestroyed(FILE *file) {
+
+	RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
+
+	LOCK(&lock);
+	if (!ISC_LIST_EMPTY(contexts))  {
+#if ISC_MEM_TRACKLINES
+		isc__mem_t *ctx;
+
+		for (ctx = ISC_LIST_HEAD(contexts);
+		     ctx != NULL;
+		     ctx = ISC_LIST_NEXT(ctx, link)) {
+			fprintf(file, "context: %p\n", ctx);
+			print_active(ctx, file);
+		}
+		fflush(file);
+#endif
+		INSIST(0);
+	}
+	UNLOCK(&lock);
+}
+
+ISC_MEMFUNC_SCOPE unsigned int
+isc_mem_references(isc_mem_t *ctx0) {
+	isc__mem_t *ctx = (isc__mem_t *)ctx0;
+	unsigned int references;
+
+	REQUIRE(VALID_CONTEXT(ctx));
+
+	MCTXLOCK(ctx, &ctx->lock);
+	references = ctx->references;
+	MCTXUNLOCK(ctx, &ctx->lock);
+
+	return (references);
+}
+
+#ifdef HAVE_LIBXML2
+
+typedef struct summarystat {
+	isc_uint64_t	total;
+	isc_uint64_t	inuse;
+	isc_uint64_t	blocksize;
+	isc_uint64_t	contextsize;
+} summarystat_t;
+
+static void
+renderctx(isc__mem_t *ctx, summarystat_t *summary, xmlTextWriterPtr writer) {
+	REQUIRE(VALID_CONTEXT(ctx));
+
+	xmlTextWriterStartElement(writer, ISC_XMLCHAR "context");
+
+	xmlTextWriterStartElement(writer, ISC_XMLCHAR "id");
+	xmlTextWriterWriteFormatString(writer, "%p", ctx);
+	xmlTextWriterEndElement(writer); /* id */
+
+	if (ctx->name[0] != 0) {
+		xmlTextWriterStartElement(writer, ISC_XMLCHAR "name");
+		xmlTextWriterWriteFormatString(writer, "%s", ctx->name);
+		xmlTextWriterEndElement(writer); /* name */
+	}
+
+	REQUIRE(VALID_CONTEXT(ctx));
+	MCTXLOCK(ctx, &ctx->lock);
+
+	summary->contextsize += sizeof(*ctx) +
+		(ctx->max_size + 1) * sizeof(struct stats) +
+		ctx->max_size * sizeof(element *) +
+		ctx->basic_table_count * sizeof(char *);
+#if ISC_MEM_TRACKLINES
+	if (ctx->debuglist != NULL) {
+		summary->contextsize +=
+			(ctx->max_size + 1) * sizeof(debuglist_t) +
+			ctx->debuglistcnt * sizeof(debuglink_t);
+	}
+#endif
+	xmlTextWriterStartElement(writer, ISC_XMLCHAR "references");
+	xmlTextWriterWriteFormatString(writer, "%d", ctx->references);
+	xmlTextWriterEndElement(writer); /* references */
+
+	summary->total += ctx->total;
+	xmlTextWriterStartElement(writer, ISC_XMLCHAR "total");
+	xmlTextWriterWriteFormatString(writer, "%" ISC_PRINT_QUADFORMAT "u",
+				       (isc_uint64_t)ctx->total);
+	xmlTextWriterEndElement(writer); /* total */
+
+	summary->inuse += ctx->inuse;
+	xmlTextWriterStartElement(writer, ISC_XMLCHAR "inuse");
+	xmlTextWriterWriteFormatString(writer, "%" ISC_PRINT_QUADFORMAT "u",
+				       (isc_uint64_t)ctx->inuse);
+	xmlTextWriterEndElement(writer); /* inuse */
+
+	xmlTextWriterStartElement(writer, ISC_XMLCHAR "maxinuse");
+	xmlTextWriterWriteFormatString(writer, "%" ISC_PRINT_QUADFORMAT "u",
+				       (isc_uint64_t)ctx->maxinuse);
+	xmlTextWriterEndElement(writer); /* maxinuse */
+
+	xmlTextWriterStartElement(writer, ISC_XMLCHAR "blocksize");
+	if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
+		summary->blocksize += ctx->basic_table_count *
+			NUM_BASIC_BLOCKS * ctx->mem_target;
+		xmlTextWriterWriteFormatString(writer,
+					       "%" ISC_PRINT_QUADFORMAT "u",
+					       (isc_uint64_t)
+					       ctx->basic_table_count *
+					       NUM_BASIC_BLOCKS *
+					       ctx->mem_target);
+	} else
+		xmlTextWriterWriteFormatString(writer, "%s", "-");
+	xmlTextWriterEndElement(writer); /* blocksize */
+
+	xmlTextWriterStartElement(writer, ISC_XMLCHAR "pools");
+	xmlTextWriterWriteFormatString(writer, "%u", ctx->poolcnt);
+	xmlTextWriterEndElement(writer); /* pools */
+	summary->contextsize += ctx->poolcnt * sizeof(isc_mempool_t);
+
+	xmlTextWriterStartElement(writer, ISC_XMLCHAR "hiwater");
+	xmlTextWriterWriteFormatString(writer, "%" ISC_PRINT_QUADFORMAT "u",
+				       (isc_uint64_t)ctx->hi_water);
+	xmlTextWriterEndElement(writer); /* hiwater */
+
+	xmlTextWriterStartElement(writer, ISC_XMLCHAR "lowater");
+	xmlTextWriterWriteFormatString(writer, "%" ISC_PRINT_QUADFORMAT "u",
+				       (isc_uint64_t)ctx->lo_water);
+	xmlTextWriterEndElement(writer); /* lowater */
+
+	MCTXUNLOCK(ctx, &ctx->lock);
+
+	xmlTextWriterEndElement(writer); /* context */
+}
+
+void
+isc_mem_renderxml(xmlTextWriterPtr writer) {
+	isc__mem_t *ctx;
+	summarystat_t summary;
+	isc_uint64_t lost;
+
+	memset(&summary, 0, sizeof(summary));
+
+	xmlTextWriterStartElement(writer, ISC_XMLCHAR "contexts");
+
+	RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
+
+	LOCK(&lock);
+	lost = totallost;
+	for (ctx = ISC_LIST_HEAD(contexts);
+	     ctx != NULL;
+	     ctx = ISC_LIST_NEXT(ctx, link)) {
+		renderctx(ctx, &summary, writer);
+	}
+	UNLOCK(&lock);
+
+	xmlTextWriterEndElement(writer); /* contexts */
+
+	xmlTextWriterStartElement(writer, ISC_XMLCHAR "summary");
+
+	xmlTextWriterStartElement(writer, ISC_XMLCHAR "TotalUse");
+	xmlTextWriterWriteFormatString(writer, "%" ISC_PRINT_QUADFORMAT "u",
+				       summary.total);
+	xmlTextWriterEndElement(writer); /* TotalUse */
+
+	xmlTextWriterStartElement(writer, ISC_XMLCHAR "InUse");
+	xmlTextWriterWriteFormatString(writer, "%" ISC_PRINT_QUADFORMAT "u",
+				       summary.inuse);
+	xmlTextWriterEndElement(writer); /* InUse */
+
+	xmlTextWriterStartElement(writer, ISC_XMLCHAR "BlockSize");
+	xmlTextWriterWriteFormatString(writer, "%" ISC_PRINT_QUADFORMAT "u",
+				       summary.blocksize);
+	xmlTextWriterEndElement(writer); /* BlockSize */
+
+	xmlTextWriterStartElement(writer, ISC_XMLCHAR "ContextSize");
+	xmlTextWriterWriteFormatString(writer, "%" ISC_PRINT_QUADFORMAT "u",
+				       summary.contextsize);
+	xmlTextWriterEndElement(writer); /* ContextSize */
+
+	xmlTextWriterStartElement(writer, ISC_XMLCHAR "Lost");
+	xmlTextWriterWriteFormatString(writer, "%" ISC_PRINT_QUADFORMAT "u",
+				       lost);
+	xmlTextWriterEndElement(writer); /* Lost */
+
+	xmlTextWriterEndElement(writer); /* summary */
+}
+
+#endif /* HAVE_LIBXML2 */
+#endif /* BIND9 */
diff --git a/src/lib/bind9/mem_api.c b/src/lib/bind9/mem_api.c
new file mode 100644
index 0000000..638efcd
--- /dev/null
+++ b/src/lib/bind9/mem_api.c
@@ -0,0 +1,303 @@
+/*
+ * Copyright (C) 2009, 2010  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: mem_api.c,v 1.8 2010-08-12 21:30:26 jinmei Exp $ */
+
+#include <config.h>
+
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/once.h>
+#include <isc/util.h>
+
+#if ISC_MEM_TRACKLINES
+#define FLARG_PASS	, file, line
+#define FLARG		, const char *file, unsigned int line
+#else
+#define FLARG_PASS
+#define FLARG
+#endif
+
+static isc_mutex_t createlock;
+static isc_once_t once = ISC_ONCE_INIT;
+static isc_memcreatefunc_t mem_createfunc = NULL;
+
+static void
+initialize(void) {
+	RUNTIME_CHECK(isc_mutex_init(&createlock) == ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_mem_register(isc_memcreatefunc_t createfunc) {
+	isc_result_t result = ISC_R_SUCCESS;
+
+	RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
+
+	LOCK(&createlock);
+	if (mem_createfunc == NULL)
+		mem_createfunc = createfunc;
+	else
+		result = ISC_R_EXISTS;
+	UNLOCK(&createlock);
+
+	return (result);
+}
+
+isc_result_t
+isc_mem_create(size_t init_max_size, size_t target_size, isc_mem_t **mctxp) {
+	isc_result_t result;
+
+	LOCK(&createlock);
+
+	REQUIRE(mem_createfunc != NULL);
+	result = (*mem_createfunc)(init_max_size, target_size, mctxp,
+				   ISC_MEMFLAG_DEFAULT);
+
+	UNLOCK(&createlock);
+
+	return (result);
+}
+
+isc_result_t
+isc_mem_create2(size_t init_max_size, size_t target_size, isc_mem_t **mctxp,
+		unsigned int flags)
+{
+	isc_result_t result;
+
+	LOCK(&createlock);
+
+	REQUIRE(mem_createfunc != NULL);
+	result = (*mem_createfunc)(init_max_size, target_size, mctxp, flags);
+
+	UNLOCK(&createlock);
+
+	return (result);
+}
+
+void
+isc_mem_attach(isc_mem_t *source, isc_mem_t **targetp) {
+	REQUIRE(ISCAPI_MCTX_VALID(source));
+	REQUIRE(targetp != NULL && *targetp == NULL);
+
+	source->methods->attach(source, targetp);
+
+	ENSURE(*targetp == source);
+}
+
+void
+isc_mem_detach(isc_mem_t **mctxp) {
+	REQUIRE(mctxp != NULL && ISCAPI_MCTX_VALID(*mctxp));
+
+	(*mctxp)->methods->detach(mctxp);
+
+	ENSURE(*mctxp == NULL);
+}
+
+void
+isc_mem_destroy(isc_mem_t **mctxp) {
+	REQUIRE(mctxp != NULL && ISCAPI_MCTX_VALID(*mctxp));
+
+	(*mctxp)->methods->destroy(mctxp);
+
+	ENSURE(*mctxp == NULL);
+}
+
+void *
+isc__mem_get(isc_mem_t *mctx, size_t size FLARG) {
+	REQUIRE(ISCAPI_MCTX_VALID(mctx));
+
+	return (mctx->methods->memget(mctx, size FLARG_PASS));
+}
+
+void
+isc__mem_put(isc_mem_t *mctx, void *ptr, size_t size FLARG) {
+	REQUIRE(ISCAPI_MCTX_VALID(mctx));
+
+	mctx->methods->memput(mctx, ptr, size FLARG_PASS);
+}
+
+void
+isc__mem_putanddetach(isc_mem_t **mctxp, void *ptr, size_t size FLARG) {
+	REQUIRE(mctxp != NULL && ISCAPI_MCTX_VALID(*mctxp));
+
+	(*mctxp)->methods->memputanddetach(mctxp, ptr, size FLARG_PASS);
+
+	/*
+	 * XXX: We cannot always ensure *mctxp == NULL here
+	 * (see lib/isc/mem.c).
+	 */
+}
+
+void *
+isc__mem_allocate(isc_mem_t *mctx, size_t size FLARG) {
+	REQUIRE(ISCAPI_MCTX_VALID(mctx));
+
+	return (mctx->methods->memallocate(mctx, size FLARG_PASS));
+}
+
+void *
+isc__mem_reallocate(isc_mem_t *mctx, void *ptr, size_t size FLARG) {
+	REQUIRE(ISCAPI_MCTX_VALID(mctx));
+
+	return (mctx->methods->memreallocate(mctx, ptr, size FLARG_PASS));
+}
+
+char *
+isc__mem_strdup(isc_mem_t *mctx, const char *s FLARG) {
+	REQUIRE(ISCAPI_MCTX_VALID(mctx));
+
+	return (mctx->methods->memstrdup(mctx, s FLARG_PASS));
+}
+
+void
+isc__mem_free(isc_mem_t *mctx, void *ptr FLARG) {
+	REQUIRE(ISCAPI_MCTX_VALID(mctx));
+
+	mctx->methods->memfree(mctx, ptr FLARG_PASS);
+}
+
+void
+isc_mem_setdestroycheck(isc_mem_t *mctx, isc_boolean_t flag) {
+	REQUIRE(ISCAPI_MCTX_VALID(mctx));
+
+	mctx->methods->setdestroycheck(mctx, flag);
+}
+
+void
+isc_mem_setwater(isc_mem_t *ctx, isc_mem_water_t water, void *water_arg,
+		 size_t hiwater, size_t lowater)
+{
+	REQUIRE(ISCAPI_MCTX_VALID(ctx));
+
+	ctx->methods->setwater(ctx, water, water_arg, hiwater, lowater);
+}
+
+void
+isc_mem_waterack(isc_mem_t *ctx, int flag) {
+	REQUIRE(ISCAPI_MCTX_VALID(ctx));
+
+	ctx->methods->waterack(ctx, flag);
+}
+
+size_t
+isc_mem_inuse(isc_mem_t *mctx) {
+	REQUIRE(ISCAPI_MCTX_VALID(mctx));
+
+	return (mctx->methods->inuse(mctx));
+}
+
+isc_boolean_t
+isc_mem_isovermem(isc_mem_t *mctx) {
+	REQUIRE(ISCAPI_MCTX_VALID(mctx));
+
+	return (mctx->methods->isovermem(mctx));
+}
+
+void
+isc_mem_setname(isc_mem_t *mctx, const char *name, void *tag) {
+	REQUIRE(ISCAPI_MCTX_VALID(mctx));
+
+	UNUSED(name);
+	UNUSED(tag);
+
+	return;
+}
+
+const char *
+isc_mem_getname(isc_mem_t *mctx) {
+	REQUIRE(ISCAPI_MCTX_VALID(mctx));
+
+	return ("");
+}
+
+void *
+isc_mem_gettag(isc_mem_t *mctx) {
+	REQUIRE(ISCAPI_MCTX_VALID(mctx));
+
+	return (NULL);
+}
+
+isc_result_t
+isc_mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp) {
+	REQUIRE(ISCAPI_MCTX_VALID(mctx));
+
+	return (mctx->methods->mpcreate(mctx, size, mpctxp));
+}
+
+void
+isc_mempool_destroy(isc_mempool_t **mpctxp) {
+	REQUIRE(mpctxp != NULL && ISCAPI_MPOOL_VALID(*mpctxp));
+
+	(*mpctxp)->methods->destroy(mpctxp);
+
+	ENSURE(*mpctxp == NULL);
+}
+
+void *
+isc__mempool_get(isc_mempool_t *mpctx FLARG) {
+	REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
+
+	return (mpctx->methods->get(mpctx FLARG_PASS));
+}
+
+void
+isc__mempool_put(isc_mempool_t *mpctx, void *mem FLARG) {
+	REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
+
+	mpctx->methods->put(mpctx, mem FLARG_PASS);
+}
+
+unsigned int
+isc_mempool_getallocated(isc_mempool_t *mpctx) {
+	REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
+
+	return (mpctx->methods->getallocated(mpctx));
+}
+
+void
+isc_mempool_setmaxalloc(isc_mempool_t *mpctx, unsigned int limit) {
+	REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
+
+	mpctx->methods->setmaxalloc(mpctx, limit);
+}
+
+void
+isc_mempool_setfreemax(isc_mempool_t *mpctx, unsigned int limit) {
+	REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
+
+	mpctx->methods->setfreemax(mpctx, limit);
+}
+
+void
+isc_mempool_setname(isc_mempool_t *mpctx, const char *name) {
+	REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
+
+	mpctx->methods->setname(mpctx, name);
+}
+
+void
+isc_mempool_associatelock(isc_mempool_t *mpctx, isc_mutex_t *lock) {
+	REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
+
+	mpctx->methods->associatelock(mpctx, lock);
+}
+
+void
+isc_mempool_setfillcount(isc_mempool_t *mpctx, unsigned int limit) {
+	REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
+
+	mpctx->methods->setfillcount(mpctx, limit);
+}
diff --git a/src/lib/bind9/mips/include/isc/atomic.h b/src/lib/bind9/mips/include/isc/atomic.h
new file mode 100644
index 0000000..1c2f23d
--- /dev/null
+++ b/src/lib/bind9/mips/include/isc/atomic.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: atomic.h,v 1.3 2007-06-19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_ATOMIC_H
+#define ISC_ATOMIC_H 1
+
+#include <isc/platform.h>
+#include <isc/types.h>
+
+#ifdef ISC_PLATFORM_USEGCCASM
+/*
+ * This routine atomically increments the value stored in 'p' by 'val', and
+ * returns the previous value.
+ */
+static inline isc_int32_t
+isc_atomic_xadd(isc_int32_t *p, int val) {
+	isc_int32_t orig;
+
+	/* add is a cheat, since MIPS has no mov instruction */
+	__asm__ volatile (
+	    "1:"
+	    "ll $3, %1\n"
+	    "add %0, $0, $3\n"
+	    "add $3, $3, %2\n"
+	    "sc $3, %1\n"
+	    "beq $3, 0, 1b"
+	    : "=&r"(orig)
+	    : "m"(*p), "r"(val)
+	    : "memory", "$3"
+		);
+
+	return (orig);
+}
+
+/*
+ * This routine atomically stores the value 'val' in 'p'.
+ */
+static inline void
+isc_atomic_store(isc_int32_t *p, isc_int32_t val) {
+	__asm__ volatile (
+	    "1:"
+	    "ll $3, %0\n"
+	    "add $3, $0, %1\n"
+	    "sc $3, %0\n"
+	    "beq $3, 0, 1b"
+	    :
+	    : "m"(*p), "r"(val)
+	    : "memory", "$3"
+		);
+}
+
+/*
+ * This routine atomically replaces the value in 'p' with 'val', if the
+ * original value is equal to 'cmpval'.  The original value is returned in any
+ * case.
+ */
+static inline isc_int32_t
+isc_atomic_cmpxchg(isc_int32_t *p, int cmpval, int val) {
+	isc_int32_t orig;
+
+	__asm__ volatile(
+	    "1:"
+	    "ll $3, %1\n"
+	    "add %0, $0, $3\n"
+	    "bne $3, %2, 2f\n"
+	    "add $3, $0, %3\n"
+	    "sc $3, %1\n"
+	    "beq $3, 0, 1b\n"
+	    "2:"
+	    : "=&r"(orig)
+	    : "m"(*p), "r"(cmpval), "r"(val)
+	    : "memory", "$3"
+		);
+
+	return (orig);
+}
+
+#else /* !ISC_PLATFORM_USEGCCASM */
+
+#error "unsupported compiler.  disable atomic ops by --disable-atomic"
+
+#endif
+#endif /* ISC_ATOMIC_H */
diff --git a/src/lib/bind9/mutexblock.c b/src/lib/bind9/mutexblock.c
new file mode 100644
index 0000000..38f423a
--- /dev/null
+++ b/src/lib/bind9/mutexblock.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: mutexblock.c,v 1.20 2007-06-19 23:47:17 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/mutexblock.h>
+#include <isc/util.h>
+
+isc_result_t
+isc_mutexblock_init(isc_mutex_t *block, unsigned int count) {
+	isc_result_t result;
+	unsigned int i;
+
+	for (i = 0; i < count; i++) {
+		result = isc_mutex_init(&block[i]);
+		if (result != ISC_R_SUCCESS) {
+			i--;
+			while (i > 0) {
+				DESTROYLOCK(&block[i]);
+				i--;
+			}
+			return (result);
+		}
+	}
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_mutexblock_destroy(isc_mutex_t *block, unsigned int count) {
+	isc_result_t result;
+	unsigned int i;
+
+	for (i = 0; i < count; i++) {
+		result = isc_mutex_destroy(&block[i]);
+		if (result != ISC_R_SUCCESS)
+			return (result);
+	}
+
+	return (ISC_R_SUCCESS);
+}
diff --git a/src/lib/bind9/netaddr.c b/src/lib/bind9/netaddr.c
new file mode 100644
index 0000000..690141b
--- /dev/null
+++ b/src/lib/bind9/netaddr.c
@@ -0,0 +1,434 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2010, 2011  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: netaddr.c,v 1.41.38.3 2011-03-11 06:47:07 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+
+#include <isc/buffer.h>
+#include <isc/msgs.h>
+#include <isc/net.h>
+#include <isc/netaddr.h>
+#include <isc/print.h>
+#include <isc/sockaddr.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+isc_boolean_t
+isc_netaddr_equal(const isc_netaddr_t *a, const isc_netaddr_t *b) {
+	REQUIRE(a != NULL && b != NULL);
+
+	if (a->family != b->family)
+		return (ISC_FALSE);
+
+	if (a->zone != b->zone)
+		return (ISC_FALSE);
+
+	switch (a->family) {
+	case AF_INET:
+		if (a->type.in.s_addr != b->type.in.s_addr)
+			return (ISC_FALSE);
+		break;
+	case AF_INET6:
+		if (memcmp(&a->type.in6, &b->type.in6,
+			   sizeof(a->type.in6)) != 0 ||
+		    a->zone != b->zone)
+			return (ISC_FALSE);
+		break;
+#ifdef ISC_PLATFORM_HAVESYSUNH
+	case AF_UNIX:
+		if (strcmp(a->type.un, b->type.un) != 0)
+			return (ISC_FALSE);
+		break;
+#endif
+	default:
+		return (ISC_FALSE);
+	}
+	return (ISC_TRUE);
+}
+
+isc_boolean_t
+isc_netaddr_eqprefix(const isc_netaddr_t *a, const isc_netaddr_t *b,
+		     unsigned int prefixlen)
+{
+	const unsigned char *pa = NULL, *pb = NULL;
+	unsigned int ipabytes = 0; /* Length of whole IP address in bytes */
+	unsigned int nbytes;       /* Number of significant whole bytes */
+	unsigned int nbits;        /* Number of significant leftover bits */
+
+	REQUIRE(a != NULL && b != NULL);
+
+	if (a->family != b->family)
+		return (ISC_FALSE);
+
+	if (a->zone != b->zone && b->zone != 0)
+		return (ISC_FALSE);
+
+	switch (a->family) {
+	case AF_INET:
+		pa = (const unsigned char *) &a->type.in;
+		pb = (const unsigned char *) &b->type.in;
+		ipabytes = 4;
+		break;
+	case AF_INET6:
+		pa = (const unsigned char *) &a->type.in6;
+		pb = (const unsigned char *) &b->type.in6;
+		ipabytes = 16;
+		break;
+	default:
+		return (ISC_FALSE);
+	}
+
+	/*
+	 * Don't crash if we get a pattern like 10.0.0.1/9999999.
+	 */
+	if (prefixlen > ipabytes * 8)
+		prefixlen = ipabytes * 8;
+
+	nbytes = prefixlen / 8;
+	nbits = prefixlen % 8;
+
+	if (nbytes > 0) {
+		if (memcmp(pa, pb, nbytes) != 0)
+			return (ISC_FALSE);
+	}
+	if (nbits > 0) {
+		unsigned int bytea, byteb, mask;
+		INSIST(nbytes < ipabytes);
+		INSIST(nbits < 8);
+		bytea = pa[nbytes];
+		byteb = pb[nbytes];
+		mask = (0xFF << (8-nbits)) & 0xFF;
+		if ((bytea & mask) != (byteb & mask))
+			return (ISC_FALSE);
+	}
+	return (ISC_TRUE);
+}
+
+isc_result_t
+isc_netaddr_totext(const isc_netaddr_t *netaddr, isc_buffer_t *target) {
+	char abuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")];
+	char zbuf[sizeof("%4294967295")];
+	unsigned int alen;
+	int zlen;
+	const char *r;
+	const void *type;
+
+	REQUIRE(netaddr != NULL);
+
+	switch (netaddr->family) {
+	case AF_INET:
+		type = &netaddr->type.in;
+		break;
+	case AF_INET6:
+		type = &netaddr->type.in6;
+		break;
+#ifdef ISC_PLATFORM_HAVESYSUNH
+	case AF_UNIX:
+		alen = strlen(netaddr->type.un);
+		if (alen > isc_buffer_availablelength(target))
+			return (ISC_R_NOSPACE);
+		isc_buffer_putmem(target,
+				  (const unsigned char *)(netaddr->type.un),
+				  alen);
+		return (ISC_R_SUCCESS);
+#endif
+	default:
+		return (ISC_R_FAILURE);
+	}
+	r = inet_ntop(netaddr->family, type, abuf, sizeof(abuf));
+	if (r == NULL)
+		return (ISC_R_FAILURE);
+
+	alen = strlen(abuf);
+	INSIST(alen < sizeof(abuf));
+
+	zlen = 0;
+	if (netaddr->family == AF_INET6 && netaddr->zone != 0) {
+		zlen = snprintf(zbuf, sizeof(zbuf), "%%%u", netaddr->zone);
+		if (zlen < 0)
+			return (ISC_R_FAILURE);
+		INSIST((unsigned int)zlen < sizeof(zbuf));
+	}
+
+	if (alen + zlen > isc_buffer_availablelength(target))
+		return (ISC_R_NOSPACE);
+
+	isc_buffer_putmem(target, (unsigned char *)abuf, alen);
+	isc_buffer_putmem(target, (unsigned char *)zbuf, zlen);
+
+	return (ISC_R_SUCCESS);
+}
+
+void
+isc_netaddr_format(const isc_netaddr_t *na, char *array, unsigned int size) {
+	isc_result_t result;
+	isc_buffer_t buf;
+
+	isc_buffer_init(&buf, array, size);
+	result = isc_netaddr_totext(na, &buf);
+
+	if (size == 0)
+		return;
+
+	/*
+	 * Null terminate.
+	 */
+	if (result == ISC_R_SUCCESS) {
+		if (isc_buffer_availablelength(&buf) >= 1)
+			isc_buffer_putuint8(&buf, 0);
+		else
+			result = ISC_R_NOSPACE;
+	}
+
+	if (result != ISC_R_SUCCESS) {
+		snprintf(array, size,
+			 isc_msgcat_get(isc_msgcat, ISC_MSGSET_NETADDR,
+					ISC_MSG_UNKNOWNADDR,
+					"<unknown address, family %u>"),
+			 na->family);
+		array[size - 1] = '\0';
+	}
+}
+
+
+isc_result_t
+isc_netaddr_prefixok(const isc_netaddr_t *na, unsigned int prefixlen) {
+	static const unsigned char zeros[16];
+	unsigned int nbits, nbytes, ipbytes = 0;
+	const unsigned char *p;
+
+	switch (na->family) {
+	case AF_INET:
+		p = (const unsigned char *) &na->type.in;
+		ipbytes = 4;
+		if (prefixlen > 32)
+			return (ISC_R_RANGE);
+		break;
+	case AF_INET6:
+		p = (const unsigned char *) &na->type.in6;
+		ipbytes = 16;
+		if (prefixlen > 128)
+			return (ISC_R_RANGE);
+		break;
+	default:
+		return (ISC_R_NOTIMPLEMENTED);
+	}
+	nbytes = prefixlen / 8;
+	nbits = prefixlen % 8;
+	if (nbits != 0) {
+		if ((p[nbytes] & (0xff>>nbits)) != 0U)
+			return (ISC_R_FAILURE);
+		nbytes++;
+	}
+	if (memcmp(p + nbytes, zeros, ipbytes - nbytes) != 0)
+		return (ISC_R_FAILURE);
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_netaddr_masktoprefixlen(const isc_netaddr_t *s, unsigned int *lenp) {
+	unsigned int nbits = 0, nbytes = 0, ipbytes = 0, i;
+	const unsigned char *p;
+
+	switch (s->family) {
+	case AF_INET:
+		p = (const unsigned char *) &s->type.in;
+		ipbytes = 4;
+		break;
+	case AF_INET6:
+		p = (const unsigned char *) &s->type.in6;
+		ipbytes = 16;
+		break;
+	default:
+		return (ISC_R_NOTIMPLEMENTED);
+	}
+	for (i = 0; i < ipbytes; i++) {
+		if (p[i] != 0xFF)
+			break;
+	}
+	nbytes = i;
+	if (i < ipbytes) {
+		unsigned int c = p[nbytes];
+		while ((c & 0x80) != 0 && nbits < 8) {
+			c <<= 1; nbits++;
+		}
+		if ((c & 0xFF) != 0)
+			return (ISC_R_MASKNONCONTIG);
+		i++;
+	}
+	for (; i < ipbytes; i++) {
+		if (p[i] != 0)
+			return (ISC_R_MASKNONCONTIG);
+		i++;
+	}
+	*lenp = nbytes * 8 + nbits;
+	return (ISC_R_SUCCESS);
+}
+
+void
+isc_netaddr_fromin(isc_netaddr_t *netaddr, const struct in_addr *ina) {
+	memset(netaddr, 0, sizeof(*netaddr));
+	netaddr->family = AF_INET;
+	netaddr->type.in = *ina;
+}
+
+void
+isc_netaddr_fromin6(isc_netaddr_t *netaddr, const struct in6_addr *ina6) {
+	memset(netaddr, 0, sizeof(*netaddr));
+	netaddr->family = AF_INET6;
+	netaddr->type.in6 = *ina6;
+}
+
+isc_result_t
+isc_netaddr_frompath(isc_netaddr_t *netaddr, const char *path) {
+#ifdef ISC_PLATFORM_HAVESYSUNH
+	if (strlen(path) > sizeof(netaddr->type.un) - 1)
+		return (ISC_R_NOSPACE);
+
+	memset(netaddr, 0, sizeof(*netaddr));
+	netaddr->family = AF_UNIX;
+	strcpy(netaddr->type.un, path);
+	netaddr->zone = 0;
+	return (ISC_R_SUCCESS);
+#else
+	UNUSED(netaddr);
+	UNUSED(path);
+	return (ISC_R_NOTIMPLEMENTED);
+#endif
+}
+
+
+void
+isc_netaddr_setzone(isc_netaddr_t *netaddr, isc_uint32_t zone) {
+	/* we currently only support AF_INET6. */
+	REQUIRE(netaddr->family == AF_INET6);
+
+	netaddr->zone = zone;
+}
+
+isc_uint32_t
+isc_netaddr_getzone(const isc_netaddr_t *netaddr) {
+	return (netaddr->zone);
+}
+
+void
+isc_netaddr_fromsockaddr(isc_netaddr_t *t, const isc_sockaddr_t *s) {
+	int family = s->type.sa.sa_family;
+	t->family = family;
+	switch (family) {
+	case AF_INET:
+		t->type.in = s->type.sin.sin_addr;
+		t->zone = 0;
+		break;
+	case AF_INET6:
+		memcpy(&t->type.in6, &s->type.sin6.sin6_addr, 16);
+#ifdef ISC_PLATFORM_HAVESCOPEID
+		t->zone = s->type.sin6.sin6_scope_id;
+#else
+		t->zone = 0;
+#endif
+		break;
+#ifdef ISC_PLATFORM_HAVESYSUNH
+	case AF_UNIX:
+		memcpy(t->type.un, s->type.sunix.sun_path, sizeof(t->type.un));
+		t->zone = 0;
+		break;
+#endif
+	default:
+		INSIST(0);
+	}
+}
+
+void
+isc_netaddr_any(isc_netaddr_t *netaddr) {
+	memset(netaddr, 0, sizeof(*netaddr));
+	netaddr->family = AF_INET;
+	netaddr->type.in.s_addr = INADDR_ANY;
+}
+
+void
+isc_netaddr_any6(isc_netaddr_t *netaddr) {
+	memset(netaddr, 0, sizeof(*netaddr));
+	netaddr->family = AF_INET6;
+	netaddr->type.in6 = in6addr_any;
+}
+
+isc_boolean_t
+isc_netaddr_ismulticast(isc_netaddr_t *na) {
+	switch (na->family) {
+	case AF_INET:
+		return (ISC_TF(ISC_IPADDR_ISMULTICAST(na->type.in.s_addr)));
+	case AF_INET6:
+		return (ISC_TF(IN6_IS_ADDR_MULTICAST(&na->type.in6)));
+	default:
+		return (ISC_FALSE);  /* XXXMLG ? */
+	}
+}
+
+isc_boolean_t
+isc_netaddr_isexperimental(isc_netaddr_t *na) {
+	switch (na->family) {
+	case AF_INET:
+		return (ISC_TF(ISC_IPADDR_ISEXPERIMENTAL(na->type.in.s_addr)));
+	default:
+		return (ISC_FALSE);  /* XXXMLG ? */
+	}
+}
+
+isc_boolean_t
+isc_netaddr_islinklocal(isc_netaddr_t *na) {
+	switch (na->family) {
+	case AF_INET:
+		return (ISC_FALSE);
+	case AF_INET6:
+		return (ISC_TF(IN6_IS_ADDR_LINKLOCAL(&na->type.in6)));
+	default:
+		return (ISC_FALSE);
+	}
+}
+
+isc_boolean_t
+isc_netaddr_issitelocal(isc_netaddr_t *na) {
+	switch (na->family) {
+	case AF_INET:
+		return (ISC_FALSE);
+	case AF_INET6:
+		return (ISC_TF(IN6_IS_ADDR_SITELOCAL(&na->type.in6)));
+	default:
+		return (ISC_FALSE);
+	}
+}
+
+void
+isc_netaddr_fromv4mapped(isc_netaddr_t *t, const isc_netaddr_t *s) {
+	isc_netaddr_t *src;
+
+	DE_CONST(s, src);	/* Must come before IN6_IS_ADDR_V4MAPPED. */
+
+	REQUIRE(s->family == AF_INET6);
+	REQUIRE(IN6_IS_ADDR_V4MAPPED(&src->type.in6));
+
+	memset(t, 0, sizeof(*t));
+	t->family = AF_INET;
+	memcpy(&t->type.in, (char *)&src->type.in6 + 12, 4);
+	return;
+}
diff --git a/src/lib/bind9/netscope.c b/src/lib/bind9/netscope.c
new file mode 100644
index 0000000..c34b8d3
--- /dev/null
+++ b/src/lib/bind9/netscope.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2002  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*! \file */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char rcsid[] =
+	"$Id: netscope.c,v 1.13 2007-06-19 23:47:17 tbox Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <config.h>
+
+#include <isc/string.h>
+#include <isc/net.h>
+#include <isc/netscope.h>
+#include <isc/result.h>
+
+isc_result_t
+isc_netscope_pton(int af, char *scopename, void *addr, isc_uint32_t *zoneid) {
+	char *ep;
+#ifdef ISC_PLATFORM_HAVEIFNAMETOINDEX
+	unsigned int ifid;
+#endif
+	struct in6_addr *in6;
+	isc_uint32_t zone;
+	isc_uint64_t llz;
+
+	/* at this moment, we only support AF_INET6 */
+	if (af != AF_INET6)
+		return (ISC_R_FAILURE);
+
+	in6 = (struct in6_addr *)addr;
+
+	/*
+	 * Basically, "names" are more stable than numeric IDs in terms of
+	 * renumbering, and are more preferred.  However, since there is no
+	 * standard naming convention and APIs to deal with the names.  Thus,
+	 * we only handle the case of link-local addresses, for which we use
+	 * interface names as link names, assuming one to one mapping between
+	 * interfaces and links.
+	 */
+#ifdef ISC_PLATFORM_HAVEIFNAMETOINDEX
+	if (IN6_IS_ADDR_LINKLOCAL(in6) &&
+	    (ifid = if_nametoindex((const char *)scopename)) != 0)
+		zone = (isc_uint32_t)ifid;
+	else {
+#endif
+		llz = isc_string_touint64(scopename, &ep, 10);
+		if (ep == scopename)
+			return (ISC_R_FAILURE);
+
+		/* check overflow */
+		zone = (isc_uint32_t)(llz & 0xffffffffUL);
+		if (zone != llz)
+			return (ISC_R_FAILURE);
+#ifdef ISC_PLATFORM_HAVEIFNAMETOINDEX
+	}
+#endif
+
+	*zoneid = zone;
+	return (ISC_R_SUCCESS);
+}
diff --git a/src/lib/bind9/nls/msgcat.c b/src/lib/bind9/nls/msgcat.c
new file mode 100644
index 0000000..e9bb9e1
--- /dev/null
+++ b/src/lib/bind9/nls/msgcat.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: msgcat.c,v 1.18 2007-06-19 23:47:18 tbox Exp $ */
+
+/*! \file msgcat.c
+ *
+ * \author Principal Author: Bob Halley
+ */
+
+#include <config.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#include <isc/magic.h>
+#include <isc/msgcat.h>
+#include <isc/util.h>
+
+#ifdef HAVE_CATGETS
+#include <nl_types.h>		/* Required for nl_catd. */
+#endif
+
+/*
+ * Implementation Notes:
+ *
+ *	We use malloc() and free() instead of isc_mem_get() and isc_mem_put()
+ *	because we don't want to require a memory context to be specified
+ *	in order to use a message catalog.
+ */
+
+struct isc_msgcat {
+	unsigned int	magic;
+#ifdef HAVE_CATGETS
+	nl_catd		catalog;
+#endif
+};
+
+#define MSGCAT_MAGIC			ISC_MAGIC('M', 'C', 'a', 't')
+#define VALID_MSGCAT(m)			ISC_MAGIC_VALID(m, MSGCAT_MAGIC)
+
+void
+isc_msgcat_open(const char *name, isc_msgcat_t **msgcatp) {
+	isc_msgcat_t *msgcat;
+
+	/*
+	 * Open a message catalog.
+	 */
+
+	REQUIRE(name != NULL);
+	REQUIRE(msgcatp != NULL && *msgcatp == NULL);
+
+	msgcat = malloc(sizeof(*msgcat));
+	if (msgcat == NULL) {
+		*msgcatp = NULL;
+		return;
+	}
+
+#ifdef HAVE_CATGETS
+	/*
+	 * We don't check if catopen() fails because we don't care.
+	 * If it does fail, then when we call catgets(), it will use
+	 * the default string.
+	 */
+	msgcat->catalog = catopen(name, 0);
+#endif
+	msgcat->magic = MSGCAT_MAGIC;
+
+	*msgcatp = msgcat;
+}
+
+void
+isc_msgcat_close(isc_msgcat_t **msgcatp) {
+	isc_msgcat_t *msgcat;
+
+	/*
+	 * Close a message catalog.
+	 */
+
+	REQUIRE(msgcatp != NULL);
+	msgcat = *msgcatp;
+	REQUIRE(VALID_MSGCAT(msgcat) || msgcat == NULL);
+
+	if (msgcat != NULL) {
+#ifdef HAVE_CATGETS
+		if (msgcat->catalog != (nl_catd)(-1))
+			(void)catclose(msgcat->catalog);
+#endif
+		msgcat->magic = 0;
+		free(msgcat);
+	}
+
+	*msgcatp = NULL;
+}
+
+const char *
+isc_msgcat_get(isc_msgcat_t *msgcat, int set, int message,
+	       const char *default_text)
+{
+	/*
+	 * Get message 'message' from message set 'set' in 'msgcat'.  If it
+	 * is not available, use 'default'.
+	 */
+
+	REQUIRE(VALID_MSGCAT(msgcat) || msgcat == NULL);
+	REQUIRE(set > 0);
+	REQUIRE(message > 0);
+	REQUIRE(default_text != NULL);
+
+#ifdef HAVE_CATGETS
+	if (msgcat == NULL)
+		return (default_text);
+	return (catgets(msgcat->catalog, set, message, default_text));
+#else
+	return (default_text);
+#endif
+}
diff --git a/src/lib/bind9/noatomic/include/isc/atomic.h b/src/lib/bind9/noatomic/include/isc/atomic.h
new file mode 100644
index 0000000..453952e
--- /dev/null
+++ b/src/lib/bind9/noatomic/include/isc/atomic.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: atomic.h,v 1.4 2007-06-19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_ATOMIC_H
+#define ISC_ATOMIC_H 1
+
+/* This file is inherently empty. */
+
+#endif /* ISC_ATOMIC_H */
diff --git a/src/lib/bind9/nothreads/condition.c b/src/lib/bind9/nothreads/condition.c
new file mode 100644
index 0000000..86ca487
--- /dev/null
+++ b/src/lib/bind9/nothreads/condition.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2004, 2006, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: condition.c,v 1.10 2007-06-19 23:47:18 tbox Exp $ */
+
+#include <config.h>
+
+#include <isc/util.h>
+
+EMPTY_TRANSLATION_UNIT
diff --git a/src/lib/bind9/nothreads/include/isc/condition.h b/src/lib/bind9/nothreads/include/isc/condition.h
new file mode 100644
index 0000000..9fef02a
--- /dev/null
+++ b/src/lib/bind9/nothreads/include/isc/condition.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2004, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: condition.h,v 1.6 2007-06-19 23:47:18 tbox Exp $ */
+
+/*
+ * This provides a limited subset of the isc_condition_t
+ * functionality for use by single-threaded programs that
+ * need to block waiting for events.   Only a single
+ * call to isc_condition_wait() may be blocked at any given
+ * time, and the _waituntil and _broadcast functions are not
+ * supported.  This is intended primarily for use by the omapi
+ * library, and may go away once omapi goes away.  Use for
+ * other purposes is strongly discouraged.
+ */
+
+#ifndef ISC_CONDITION_H
+#define ISC_CONDITION_H 1
+
+#include <isc/mutex.h>
+
+typedef int isc_condition_t;
+
+isc_result_t isc__nothread_wait_hack(isc_condition_t *cp, isc_mutex_t *mp);
+isc_result_t isc__nothread_signal_hack(isc_condition_t *cp);
+
+#define isc_condition_init(cp) \
+	(*(cp) = 0, ISC_R_SUCCESS)
+
+#define isc_condition_wait(cp, mp) \
+	isc__nothread_wait_hack(cp, mp)
+
+#define isc_condition_waituntil(cp, mp, tp) \
+	((void)(cp), (void)(mp), (void)(tp), ISC_R_NOTIMPLEMENTED)
+
+#define isc_condition_signal(cp) \
+	isc__nothread_signal_hack(cp)
+
+#define isc_condition_broadcast(cp) \
+	((void)(cp), ISC_R_NOTIMPLEMENTED)
+
+#define isc_condition_destroy(cp) \
+	(*(cp) == 0 ? (*(cp) = -1, ISC_R_SUCCESS) : ISC_R_UNEXPECTED)
+
+#endif /* ISC_CONDITION_H */
diff --git a/src/lib/bind9/nothreads/include/isc/mutex.h b/src/lib/bind9/nothreads/include/isc/mutex.h
new file mode 100644
index 0000000..7355f43
--- /dev/null
+++ b/src/lib/bind9/nothreads/include/isc/mutex.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2004, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: mutex.h,v 1.6 2007-06-19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_MUTEX_H
+#define ISC_MUTEX_H 1
+
+#include <isc/result.h>		/* for ISC_R_ codes */
+
+typedef int isc_mutex_t;
+
+#define isc_mutex_init(mp) \
+	(*(mp) = 0, ISC_R_SUCCESS)
+#define isc_mutex_lock(mp) \
+	((*(mp))++ == 0 ? ISC_R_SUCCESS : ISC_R_UNEXPECTED)
+#define isc_mutex_unlock(mp) \
+	(--(*(mp)) == 0 ? ISC_R_SUCCESS : ISC_R_UNEXPECTED)
+#define isc_mutex_trylock(mp) \
+	(*(mp) == 0 ? ((*(mp))++, ISC_R_SUCCESS) : ISC_R_LOCKBUSY)
+#define isc_mutex_destroy(mp) \
+	(*(mp) == 0 ? (*(mp) = -1, ISC_R_SUCCESS) : ISC_R_UNEXPECTED)
+#define isc_mutex_stats(fp)
+
+#endif /* ISC_MUTEX_H */
diff --git a/src/lib/bind9/nothreads/include/isc/once.h b/src/lib/bind9/nothreads/include/isc/once.h
new file mode 100644
index 0000000..21319d1
--- /dev/null
+++ b/src/lib/bind9/nothreads/include/isc/once.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2004, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: once.h,v 1.6 2007-06-19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_ONCE_H
+#define ISC_ONCE_H 1
+
+#include <isc/result.h>
+
+typedef isc_boolean_t isc_once_t;
+
+#define ISC_ONCE_INIT ISC_FALSE
+
+#define isc_once_do(op, f) \
+	(!*(op) ? (f(), *(op) = ISC_TRUE, ISC_R_SUCCESS) : ISC_R_SUCCESS)
+
+#endif /* ISC_ONCE_H */
diff --git a/src/lib/bind9/nothreads/include/isc/thread.h b/src/lib/bind9/nothreads/include/isc/thread.h
new file mode 100644
index 0000000..5746c99
--- /dev/null
+++ b/src/lib/bind9/nothreads/include/isc/thread.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2004, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: thread.h,v 1.6 2007-06-19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_THREAD_H
+#define ISC_THREAD_H 1
+
+#include <isc/lang.h>
+#include <isc/result.h>
+
+ISC_LANG_BEGINDECLS
+
+void
+isc_thread_setconcurrency(unsigned int level);
+
+#define isc_thread_self() ((unsigned long)0)
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_THREAD_H */
diff --git a/src/lib/bind9/nothreads/mutex.c b/src/lib/bind9/nothreads/mutex.c
new file mode 100644
index 0000000..fb6a1db
--- /dev/null
+++ b/src/lib/bind9/nothreads/mutex.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2004, 2006, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: mutex.c,v 1.10 2007-06-19 23:47:18 tbox Exp $ */
+
+#include <config.h>
+
+#include <isc/util.h>
+
+EMPTY_TRANSLATION_UNIT
+
diff --git a/src/lib/bind9/nothreads/thread.c b/src/lib/bind9/nothreads/thread.c
new file mode 100644
index 0000000..3e61b49
--- /dev/null
+++ b/src/lib/bind9/nothreads/thread.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2004, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: thread.c,v 1.5 2007-06-19 23:47:18 tbox Exp $ */
+
+#include <config.h>
+
+#include <isc/thread.h>
+#include <isc/util.h>
+
+void
+isc_thread_setconcurrency(unsigned int level) {
+	UNUSED(level);
+}
diff --git a/src/lib/bind9/ondestroy.c b/src/lib/bind9/ondestroy.c
new file mode 100644
index 0000000..0326557
--- /dev/null
+++ b/src/lib/bind9/ondestroy.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: ondestroy.c,v 1.16 2007-06-19 23:47:17 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stddef.h>
+
+#include <isc/event.h>
+#include <isc/magic.h>
+#include <isc/ondestroy.h>
+#include <isc/task.h>
+#include <isc/util.h>
+
+#define ONDESTROY_MAGIC		ISC_MAGIC('D', 'e', 'S', 't')
+#define VALID_ONDESTROY(s)	ISC_MAGIC_VALID(s, ONDESTROY_MAGIC)
+
+void
+isc_ondestroy_init(isc_ondestroy_t *ondest) {
+	ondest->magic = ONDESTROY_MAGIC;
+	ISC_LIST_INIT(ondest->events);
+}
+
+isc_result_t
+isc_ondestroy_register(isc_ondestroy_t *ondest, isc_task_t *task,
+		       isc_event_t **eventp)
+{
+	isc_event_t *theevent;
+	isc_task_t *thetask = NULL;
+
+	REQUIRE(VALID_ONDESTROY(ondest));
+	REQUIRE(task != NULL);
+	REQUIRE(eventp != NULL);
+
+	theevent = *eventp;
+
+	REQUIRE(theevent != NULL);
+
+	isc_task_attach(task, &thetask);
+
+	theevent->ev_sender = thetask;
+
+	ISC_LIST_APPEND(ondest->events, theevent, ev_link);
+
+	return (ISC_R_SUCCESS);
+}
+
+void
+isc_ondestroy_notify(isc_ondestroy_t *ondest, void *sender) {
+	isc_event_t *eventp;
+	isc_task_t *task;
+
+	REQUIRE(VALID_ONDESTROY(ondest));
+
+	eventp = ISC_LIST_HEAD(ondest->events);
+	while (eventp != NULL) {
+		ISC_LIST_UNLINK(ondest->events, eventp, ev_link);
+
+		task = eventp->ev_sender;
+		eventp->ev_sender = sender;
+
+		isc_task_sendanddetach(&task, &eventp);
+
+		eventp = ISC_LIST_HEAD(ondest->events);
+	}
+}
+
+
diff --git a/src/lib/bind9/parseint.c b/src/lib/bind9/parseint.c
new file mode 100644
index 0000000..a7fe84f
--- /dev/null
+++ b/src/lib/bind9/parseint.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2001-2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: parseint.c,v 1.8 2007-06-19 23:47:17 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+
+#include <isc/parseint.h>
+#include <isc/result.h>
+#include <isc/stdlib.h>
+
+isc_result_t
+isc_parse_uint32(isc_uint32_t *uip, const char *string, int base) {
+	unsigned long n;
+	char *e;
+	if (! isalnum((unsigned char)(string[0])))
+		return (ISC_R_BADNUMBER);
+	errno = 0;
+	n = strtoul(string, &e, base);
+	if (*e != '\0')
+		return (ISC_R_BADNUMBER);
+	if (n == ULONG_MAX && errno == ERANGE)
+		return (ISC_R_RANGE);
+	*uip = n;
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_parse_uint16(isc_uint16_t *uip, const char *string, int base) {
+	isc_uint32_t val;
+	isc_result_t result;
+	result = isc_parse_uint32(&val, string, base);
+	if (result != ISC_R_SUCCESS)
+		return (result);
+	if (val > 0xFFFF)
+		return (ISC_R_RANGE);
+	*uip = (isc_uint16_t) val;
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_parse_uint8(isc_uint8_t *uip, const char *string, int base) {
+	isc_uint32_t val;
+	isc_result_t result;
+	result = isc_parse_uint32(&val, string, base);
+	if (result != ISC_R_SUCCESS)
+		return (result);
+	if (val > 0xFF)
+		return (ISC_R_RANGE);
+	*uip = (isc_uint8_t) val;
+	return (ISC_R_SUCCESS);
+}
diff --git a/src/lib/bind9/portset.c b/src/lib/bind9/portset.c
new file mode 100644
index 0000000..07fb0cb
--- /dev/null
+++ b/src/lib/bind9/portset.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2008  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: portset.c,v 1.4 2008-06-24 23:24:35 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/mem.h>
+#include <isc/portset.h>
+#include <isc/string.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#define ISC_PORTSET_BUFSIZE (65536 / (sizeof(isc_uint32_t) * 8))
+
+/*%
+ * Internal representation of portset.  It's an array of 32-bit integers, each
+ * bit corresponding to a single port in the ascending order.  For example,
+ * the second most significant bit of buf[0] corresponds to port 1.
+ */
+struct isc_portset {
+	unsigned int nports;	/*%< number of ports in the set */
+	isc_uint32_t buf[ISC_PORTSET_BUFSIZE];
+};
+
+static inline isc_boolean_t
+portset_isset(isc_portset_t *portset, in_port_t port) {
+	return (ISC_TF((portset->buf[port >> 5] & (1 << (port & 31))) != 0));
+}
+
+static inline void
+portset_add(isc_portset_t *portset, in_port_t port) {
+	if (!portset_isset(portset, port)) {
+		portset->nports++;
+		portset->buf[port >> 5] |= (1 << (port & 31));
+	}
+}
+
+static inline void
+portset_remove(isc_portset_t *portset, in_port_t port) {
+	if (portset_isset(portset, port)) {
+		portset->nports--;
+		portset->buf[port >> 5] &= ~(1 << (port & 31));
+	}
+}
+
+isc_result_t
+isc_portset_create(isc_mem_t *mctx, isc_portset_t **portsetp) {
+	isc_portset_t *portset;
+
+	REQUIRE(portsetp != NULL && *portsetp == NULL);
+
+	portset = isc_mem_get(mctx, sizeof(*portset));
+	if (portset == NULL)
+		return (ISC_R_NOMEMORY);
+
+	/* Make the set 'empty' by default */
+	memset(portset, 0, sizeof(*portset));
+	*portsetp = portset;
+
+	return (ISC_R_SUCCESS);
+}
+
+void
+isc_portset_destroy(isc_mem_t *mctx, isc_portset_t **portsetp) {
+	isc_portset_t *portset;
+
+	REQUIRE(portsetp != NULL);
+	portset = *portsetp;
+
+	isc_mem_put(mctx, portset, sizeof(*portset));
+}
+
+isc_boolean_t
+isc_portset_isset(isc_portset_t *portset, in_port_t port) {
+	REQUIRE(portset != NULL);
+
+	return (portset_isset(portset, port));
+}
+
+unsigned int
+isc_portset_nports(isc_portset_t *portset) {
+	REQUIRE(portset != NULL);
+
+	return (portset->nports);
+}
+
+void
+isc_portset_add(isc_portset_t *portset, in_port_t port) {
+	REQUIRE(portset != NULL);
+
+	portset_add(portset, port);
+}
+
+void
+isc_portset_remove(isc_portset_t *portset, in_port_t port) {
+	portset_remove(portset, port);
+}
+
+void
+isc_portset_addrange(isc_portset_t *portset, in_port_t port_lo,
+		     in_port_t port_hi)
+{
+	in_port_t p;
+
+	REQUIRE(portset != NULL);
+	REQUIRE(port_lo <= port_hi);
+
+	p = port_lo;
+	do {
+		portset_add(portset, p);
+	} while (p++ < port_hi);
+}
+
+void
+isc_portset_removerange(isc_portset_t *portset, in_port_t port_lo,
+			in_port_t port_hi)
+{
+	in_port_t p;
+
+	REQUIRE(portset != NULL);
+	REQUIRE(port_lo <= port_hi);
+
+	p = port_lo;
+	do {
+		portset_remove(portset, p);
+	} while (p++ < port_hi);
+}
diff --git a/src/lib/bind9/powerpc/include/isc/atomic.h b/src/lib/bind9/powerpc/include/isc/atomic.h
new file mode 100644
index 0000000..4404bed
--- /dev/null
+++ b/src/lib/bind9/powerpc/include/isc/atomic.h
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2005, 2007, 2009, 2011  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: atomic.h,v 1.8.284.3 2011-03-08 00:52:21 marka Exp $ */
+
+#ifndef ISC_ATOMIC_H
+#define ISC_ATOMIC_H 1
+
+#include <isc/platform.h>
+#include <isc/types.h>
+
+/*!\file
+ * static inline isc_int32_t
+ * isc_atomic_xadd(isc_int32_t *p, isc_int32_t val);
+ *
+ * This routine atomically increments the value stored in 'p' by 'val', and
+ * returns the previous value.
+ *
+ * static inline void
+ * isc_atomic_store(void *p, isc_int32_t val);
+ *
+ * This routine atomically stores the value 'val' in 'p'.
+ *
+ * static inline isc_int32_t
+ * isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val);
+ *
+ * This routine atomically replaces the value in 'p' with 'val', if the
+ * original value is equal to 'cmpval'.  The original value is returned in any
+ * case.
+ */
+
+#if defined(_AIX)
+
+#include <sys/atomic_op.h>
+
+#define isc_atomic_store(p, v) _clear_lock(p, v)
+
+#ifdef __GNUC__
+static inline isc_int32_t
+#else
+static isc_int32_t
+#endif
+isc_atomic_xadd(isc_int32_t *p, isc_int32_t val) {
+	int ret;
+
+#ifdef __GNUC__
+	asm("ics");
+#else
+	 __isync();
+#endif
+
+	ret = fetch_and_add((atomic_p)p, (int)val);
+
+#ifdef __GNUC__
+	asm("ics");
+#else
+	 __isync();
+#endif
+
+	 return (ret);
+}
+
+#ifdef __GNUC__
+static inline int
+#else
+static int
+#endif
+isc_atomic_cmpxchg(atomic_p p, int old, int new) {
+	int orig = old;
+
+#ifdef __GNUC__
+	asm("ics");
+#else
+	 __isync();
+#endif
+	if (compare_and_swap(p, &orig, new))
+		orig = old;
+
+#ifdef __GNUC__
+	asm("ics");
+#else
+	 __isync();
+#endif
+
+	return (orig);
+}
+
+#elif defined(ISC_PLATFORM_USEGCCASM) || defined(ISC_PLATFORM_USEMACASM)
+static inline isc_int32_t
+isc_atomic_xadd(isc_int32_t *p, isc_int32_t val) {
+	isc_int32_t orig;
+
+	__asm__ volatile (
+#ifdef ISC_PLATFORM_USEMACASM
+		"1:"
+		"lwarx r6, 0, %1\n"
+		"mr %0, r6\n"
+		"add r6, r6, %2\n"
+		"stwcx. r6, 0, %1\n"
+		"bne- 1b\n"
+		"sync"
+#else
+		"1:"
+		"lwarx 6, 0, %1\n"
+		"mr %0, 6\n"
+		"add 6, 6, %2\n"
+		"stwcx. 6, 0, %1\n"
+		"bne- 1b\n"
+		"sync"
+#endif
+		: "=&r"(orig)
+		: "r"(p), "r"(val)
+		: "r6", "memory"
+		);
+
+	return (orig);
+}
+
+static inline void
+isc_atomic_store(void *p, isc_int32_t val) {
+	__asm__ volatile (
+#ifdef ISC_PLATFORM_USEMACASM
+		"1:"
+		"lwarx r6, 0, %0\n"
+		"lwz r6, %1\n"
+		"stwcx. r6, 0, %0\n"
+		"bne- 1b\n"
+		"sync"
+#else
+		"1:"
+		"lwarx 6, 0, %0\n"
+		"lwz 6, %1\n"
+		"stwcx. 6, 0, %0\n"
+		"bne- 1b\n"
+		"sync"
+#endif
+		:
+		: "r"(p), "m"(val)
+		: "r6", "memory"
+		);
+}
+
+static inline isc_int32_t
+isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) {
+	isc_int32_t orig;
+
+	__asm__ volatile (
+#ifdef ISC_PLATFORM_USEMACASM
+		"1:"
+		"lwarx r6, 0, %1\n"
+		"mr %0,r6\n"
+		"cmpw r6, %2\n"
+		"bne 2f\n"
+		"mr r6, %3\n"
+		"stwcx. r6, 0, %1\n"
+		"bne- 1b\n"
+		"2:\n"
+		"sync"
+#else
+		"1:"
+		"lwarx 6, 0, %1\n"
+		"mr %0,6\n"
+		"cmpw 6, %2\n"
+		"bne 2f\n"
+		"mr 6, %3\n"
+		"stwcx. 6, 0, %1\n"
+		"bne- 1b\n"
+		"2:\n"
+		"sync"
+#endif
+		: "=&r" (orig)
+		: "r"(p), "r"(cmpval), "r"(val)
+		: "r6", "memory"
+		);
+
+	return (orig);
+}
+
+#else
+
+#error "unsupported compiler.  disable atomic ops by --disable-atomic"
+
+#endif
+#endif /* ISC_ATOMIC_H */
diff --git a/src/lib/bind9/print.c b/src/lib/bind9/print.c
new file mode 100644
index 0000000..bd7b580
--- /dev/null
+++ b/src/lib/bind9/print.c
@@ -0,0 +1,624 @@
+/*
+ * Copyright (C) 2004-2008, 2010  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001, 2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: print.c,v 1.37 2010-10-18 23:47:08 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <ctype.h>
+#include <stdio.h>		/* for sprintf() */
+#include <string.h>		/* for strlen() */
+
+#define	ISC__PRINT_SOURCE	/* Used to get the isc_print_* prototypes. */
+
+#include <isc/assertions.h>
+#include <isc/int.h>
+#include <isc/msgs.h>
+#include <isc/print.h>
+#include <isc/stdlib.h>
+#include <isc/util.h>
+
+int
+isc_print_sprintf(char *str, const char *format, ...) {
+	va_list ap;
+
+	va_start(ap, format);
+	vsprintf(str, format, ap);
+	va_end(ap);
+	return (strlen(str));
+}
+
+/*!
+ * Return length of string that would have been written if not truncated.
+ */
+
+int
+isc_print_snprintf(char *str, size_t size, const char *format, ...) {
+	va_list ap;
+	int ret;
+
+	va_start(ap, format);
+	ret = vsnprintf(str, size, format, ap);
+	va_end(ap);
+	return (ret);
+
+}
+
+/*!
+ * Return length of string that would have been written if not truncated.
+ */
+
+int
+isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
+	int h;
+	int l;
+	int q;
+	int alt;
+	int zero;
+	int left;
+	int plus;
+	int space;
+	int neg;
+	isc_int64_t tmpi;
+	isc_uint64_t tmpui;
+	unsigned long width;
+	unsigned long precision;
+	unsigned int length;
+	char buf[1024];
+	char c;
+	void *v;
+	char *save = str;
+	const char *cp;
+	const char *head;
+	int count = 0;
+	int pad;
+	int zeropad;
+	int dot;
+	double dbl;
+#ifdef HAVE_LONG_DOUBLE
+	long double ldbl;
+#endif
+	char fmt[32];
+
+	INSIST(str != NULL);
+	INSIST(format != NULL);
+
+	while (*format != '\0') {
+		if (*format != '%') {
+			if (size > 1) {
+				*str++ = *format;
+				size--;
+			}
+			count++;
+			format++;
+			continue;
+		}
+		format++;
+
+		/*
+		 * Reset flags.
+		 */
+		dot = neg = space = plus = left = zero = alt = h = l = q = 0;
+		width = precision = 0;
+		head = "";
+		length = pad = zeropad = 0;
+
+		do {
+			if (*format == '#') {
+				alt = 1;
+				format++;
+			} else if (*format == '-') {
+				left = 1;
+				zero = 0;
+				format++;
+			} else if (*format == ' ') {
+				if (!plus)
+					space = 1;
+				format++;
+			} else if (*format == '+') {
+				plus = 1;
+				space = 0;
+				format++;
+			} else if (*format == '0') {
+				if (!left)
+					zero = 1;
+				format++;
+			} else
+				break;
+		} while (1);
+
+		/*
+		 * Width.
+		 */
+		if (*format == '*') {
+			width = va_arg(ap, int);
+			format++;
+		} else if (isdigit((unsigned char)*format)) {
+			char *e;
+			width = strtoul(format, &e, 10);
+			format = e;
+		}
+
+		/*
+		 * Precision.
+		 */
+		if (*format == '.') {
+			format++;
+			dot = 1;
+			if (*format == '*') {
+				precision = va_arg(ap, int);
+				format++;
+			} else if (isdigit((unsigned char)*format)) {
+				char *e;
+				precision = strtoul(format, &e, 10);
+				format = e;
+			}
+		}
+
+		switch (*format) {
+		case '\0':
+			continue;
+		case '%':
+			if (size > 1) {
+				*str++ = *format;
+				size--;
+			}
+			count++;
+			break;
+		case 'q':
+			q = 1;
+			format++;
+			goto doint;
+		case 'h':
+			h = 1;
+			format++;
+			goto doint;
+		case 'l':
+			l = 1;
+			format++;
+			if (*format == 'l') {
+				q = 1;
+				format++;
+			}
+			goto doint;
+		case 'n':
+		case 'i':
+		case 'd':
+		case 'o':
+		case 'u':
+		case 'x':
+		case 'X':
+		doint:
+			if (precision != 0)
+				zero = 0;
+			switch (*format) {
+			case 'n':
+				if (h) {
+					short int *p;
+					p = va_arg(ap, short *);
+					REQUIRE(p != NULL);
+					*p = str - save;
+				} else if (l) {
+					long int *p;
+					p = va_arg(ap, long *);
+					REQUIRE(p != NULL);
+					*p = str - save;
+				} else {
+					int *p;
+					p = va_arg(ap, int *);
+					REQUIRE(p != NULL);
+					*p = str - save;
+				}
+				break;
+			case 'i':
+			case 'd':
+				if (q)
+					tmpi = va_arg(ap, isc_int64_t);
+				else if (l)
+					tmpi = va_arg(ap, long int);
+				else
+					tmpi = va_arg(ap, int);
+				if (tmpi < 0) {
+					head = "-";
+					tmpui = -tmpi;
+				} else {
+					if (plus)
+						head = "+";
+					else if (space)
+						head = " ";
+					else
+						head = "";
+					tmpui = tmpi;
+				}
+				if (tmpui <= 0xffffffffU)
+					sprintf(buf, "%lu",
+						(unsigned long)tmpui);
+				else {
+					unsigned long mid;
+					unsigned long lo;
+					unsigned long hi;
+					lo = tmpui % 1000000000;
+					tmpui /= 1000000000;
+					mid = tmpui % 1000000000;
+					hi = tmpui / 1000000000;
+					if (hi != 0)
+						sprintf(buf, "%lu", hi);
+					else
+						buf[0] = '\n';
+					sprintf(buf + strlen(buf), "%lu", mid);
+					sprintf(buf + strlen(buf), "%lu", lo);
+				}
+				goto printint;
+			case 'o':
+				if (q)
+					tmpui = va_arg(ap, isc_uint64_t);
+				else if (l)
+					tmpui = va_arg(ap, long int);
+				else
+					tmpui = va_arg(ap, int);
+				if (tmpui <= 0xffffffffU)
+					sprintf(buf, alt ?  "%#lo" : "%lo",
+						(unsigned long)tmpui);
+				else {
+					unsigned long mid;
+					unsigned long lo;
+					unsigned long hi;
+					lo = tmpui % 010000000000;
+					tmpui /= 010000000000;
+					mid = tmpui % 010000000000;
+					hi = tmpui / 010000000000;
+					if (hi != 0) {
+						sprintf(buf,
+							alt ?  "%#lo" : "%lo",
+							hi);
+						sprintf(buf + strlen(buf),
+							"%lo", mid);
+					} else
+						sprintf(buf,
+							alt ?  "%#lo" : "%lo",
+							mid);
+					sprintf(buf + strlen(buf), "%lo", lo);
+				}
+				goto printint;
+			case 'u':
+				if (q)
+					tmpui = va_arg(ap, isc_uint64_t);
+				else if (l)
+					tmpui = va_arg(ap, unsigned long int);
+				else
+					tmpui = va_arg(ap, unsigned int);
+				if (tmpui <= 0xffffffffU)
+					sprintf(buf, "%lu",
+						(unsigned long)tmpui);
+				else {
+					unsigned long mid;
+					unsigned long lo;
+					unsigned long hi;
+					lo = tmpui % 1000000000;
+					tmpui /= 1000000000;
+					mid = tmpui % 1000000000;
+					hi = tmpui / 1000000000;
+					if (hi != 0)
+						sprintf(buf, "%lu", hi);
+					else
+						buf[0] = '\n';
+					sprintf(buf + strlen(buf), "%lu", mid);
+					sprintf(buf + strlen(buf), "%lu", lo);
+				}
+				goto printint;
+			case 'x':
+				if (q)
+					tmpui = va_arg(ap, isc_uint64_t);
+				else if (l)
+					tmpui = va_arg(ap, unsigned long int);
+				else
+					tmpui = va_arg(ap, unsigned int);
+				if (alt) {
+					head = "0x";
+					if (precision > 2)
+						precision -= 2;
+				}
+				if (tmpui <= 0xffffffffU)
+					sprintf(buf, "%lx",
+						(unsigned long)tmpui);
+				else {
+					unsigned long hi = tmpui>>32;
+					unsigned long lo = tmpui & 0xffffffff;
+					sprintf(buf, "%lx", hi);
+					sprintf(buf + strlen(buf), "%lx", lo);
+				}
+				goto printint;
+			case 'X':
+				if (q)
+					tmpui = va_arg(ap, isc_uint64_t);
+				else if (l)
+					tmpui = va_arg(ap, unsigned long int);
+				else
+					tmpui = va_arg(ap, unsigned int);
+				if (alt) {
+					head = "0X";
+					if (precision > 2)
+						precision -= 2;
+				}
+				if (tmpui <= 0xffffffffU)
+					sprintf(buf, "%lX",
+						(unsigned long)tmpui);
+				else  {
+					unsigned long hi = tmpui>>32;
+					unsigned long lo = tmpui & 0xffffffff;
+					sprintf(buf, "%lX", hi);
+					sprintf(buf + strlen(buf), "%lX", lo);
+				}
+				goto printint;
+			printint:
+				if (precision != 0 || width != 0) {
+					length = strlen(buf);
+					if (length < precision)
+						zeropad = precision - length;
+					else if (length < width && zero)
+						zeropad = width - length;
+					if (width != 0) {
+						pad = width - length -
+						      zeropad - strlen(head);
+						if (pad < 0)
+							pad = 0;
+					}
+				}
+				count += strlen(head) + strlen(buf) + pad +
+					 zeropad;
+				if (!left) {
+					while (pad > 0 && size > 1) {
+						*str++ = ' ';
+						size--;
+						pad--;
+					}
+				}
+				cp = head;
+				while (*cp != '\0' && size > 1) {
+					*str++ = *cp++;
+					size--;
+				}
+				while (zeropad > 0 && size > 1) {
+					*str++ = '0';
+					size--;
+					zeropad--;
+				}
+				cp = buf;
+				while (*cp != '\0' && size > 1) {
+					*str++ = *cp++;
+					size--;
+				}
+				while (pad > 0 && size > 1) {
+					*str++ = ' ';
+					size--;
+					pad--;
+				}
+				break;
+			default:
+				break;
+			}
+			break;
+		case 's':
+			cp = va_arg(ap, char *);
+			REQUIRE(cp != NULL);
+
+			if (precision != 0) {
+				/*
+				 * cp need not be NULL terminated.
+				 */
+				const char *tp;
+				unsigned long n;
+
+				n = precision;
+				tp = cp;
+				while (n != 0 && *tp != '\0')
+					n--, tp++;
+				length = precision - n;
+			} else {
+				length = strlen(cp);
+			}
+			if (width != 0) {
+				pad = width - length;
+				if (pad < 0)
+					pad = 0;
+			}
+			count += pad + length;
+			if (!left)
+				while (pad > 0 && size > 1) {
+					*str++ = ' ';
+					size--;
+					pad--;
+				}
+			if (precision != 0)
+				while (precision > 0 && *cp != '\0' &&
+				       size > 1) {
+					*str++ = *cp++;
+					size--;
+					precision--;
+				}
+			else
+				while (*cp != '\0' && size > 1) {
+					*str++ = *cp++;
+					size--;
+				}
+			while (pad > 0 && size > 1) {
+				*str++ = ' ';
+				size--;
+				pad--;
+			}
+			break;
+		case 'c':
+			c = va_arg(ap, int);
+			if (width > 0) {
+				count += width;
+				width--;
+				if (left && size > 1) {
+					*str++ = c;
+					size--;
+				}
+				while (width-- > 0 && size > 1) {
+					*str++ = ' ';
+					size--;
+				}
+				if (!left && size > 1) {
+					*str++ = c;
+					size--;
+				}
+			} else {
+				count++;
+				if (size > 1) {
+					*str++ = c;
+					size--;
+				}
+			}
+			break;
+		case 'p':
+			v = va_arg(ap, void *);
+			sprintf(buf, "%p", v);
+			length = strlen(buf);
+			if (precision > length)
+				zeropad = precision - length;
+			if (width > 0) {
+				pad = width - length - zeropad;
+				if (pad < 0)
+					pad = 0;
+			}
+			count += length + pad + zeropad;
+			if (!left)
+				while (pad > 0 && size > 1) {
+					*str++ = ' ';
+					size--;
+					pad--;
+				}
+			cp = buf;
+			if (zeropad > 0 && buf[0] == '0' &&
+			    (buf[1] == 'x' || buf[1] == 'X')) {
+				if (size > 1) {
+					*str++ = *cp++;
+					size--;
+				}
+				if (size > 1) {
+					*str++ = *cp++;
+					size--;
+				}
+				while (zeropad > 0 && size > 1) {
+					*str++ = '0';
+					size--;
+					zeropad--;
+				}
+			}
+			while (*cp != '\0' && size > 1) {
+				*str++ = *cp++;
+				size--;
+			}
+			while (pad > 0 && size > 1) {
+				*str++ = ' ';
+				size--;
+				pad--;
+			}
+			break;
+		case 'D':	/*deprecated*/
+			INSIST("use %ld instead of %D" == NULL);
+		case 'O':	/*deprecated*/
+			INSIST("use %lo instead of %O" == NULL);
+		case 'U':	/*deprecated*/
+			INSIST("use %lu instead of %U" == NULL);
+
+		case 'L':
+#ifdef HAVE_LONG_DOUBLE
+			l = 1;
+#else
+			INSIST("long doubles are not supported" == NULL);
+#endif
+			/*FALLTHROUGH*/
+		case 'e':
+		case 'E':
+		case 'f':
+		case 'g':
+		case 'G':
+			if (!dot)
+				precision = 6;
+			/*
+			 * IEEE floating point.
+			 * MIN 2.2250738585072014E-308
+			 * MAX 1.7976931348623157E+308
+			 * VAX floating point has a smaller range than IEEE.
+			 *
+			 * precisions > 324 don't make much sense.
+			 * if we cap the precision at 512 we will not
+			 * overflow buf.
+			 */
+			if (precision > 512)
+				precision = 512;
+			sprintf(fmt, "%%%s%s.%lu%s%c", alt ? "#" : "",
+				plus ? "+" : space ? " " : "",
+				precision, l ? "L" : "", *format);
+			switch (*format) {
+			case 'e':
+			case 'E':
+			case 'f':
+			case 'g':
+			case 'G':
+#ifdef HAVE_LONG_DOUBLE
+				if (l) {
+					ldbl = va_arg(ap, long double);
+					sprintf(buf, fmt, ldbl);
+				} else
+#endif
+				{
+					dbl = va_arg(ap, double);
+					sprintf(buf, fmt, dbl);
+				}
+				length = strlen(buf);
+				if (width > 0) {
+					pad = width - length;
+					if (pad < 0)
+						pad = 0;
+				}
+				count += length + pad;
+				if (!left)
+					while (pad > 0 && size > 1) {
+						*str++ = ' ';
+						size--;
+						pad--;
+					}
+				cp = buf;
+				while (*cp != ' ' && size > 1) {
+					*str++ = *cp++;
+					size--;
+				}
+				while (pad > 0 && size > 1) {
+					*str++ = ' ';
+					size--;
+					pad--;
+				}
+				break;
+			default:
+				continue;
+			}
+			break;
+		default:
+			continue;
+		}
+		format++;
+	}
+	if (size > 0)
+		*str = '\0';
+	return (count);
+}
diff --git a/src/lib/bind9/pthreads/condition.c b/src/lib/bind9/pthreads/condition.c
new file mode 100644
index 0000000..f19ab6d
--- /dev/null
+++ b/src/lib/bind9/pthreads/condition.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: condition.c,v 1.36 2007-06-19 23:47:18 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <errno.h>
+
+#include <isc/condition.h>
+#include <isc/msgs.h>
+#include <isc/strerror.h>
+#include <isc/string.h>
+#include <isc/time.h>
+#include <isc/util.h>
+
+isc_result_t
+isc_condition_waituntil(isc_condition_t *c, isc_mutex_t *m, isc_time_t *t) {
+	int presult;
+	isc_result_t result;
+	struct timespec ts;
+	char strbuf[ISC_STRERRORSIZE];
+
+	REQUIRE(c != NULL && m != NULL && t != NULL);
+
+	/*
+	 * POSIX defines a timespec's tv_sec as time_t.
+	 */
+	result = isc_time_secondsastimet(t, &ts.tv_sec);
+	if (result != ISC_R_SUCCESS)
+		return (result);
+
+	/*!
+	 * POSIX defines a timespec's tv_nsec as long.  isc_time_nanoseconds
+	 * ensures its return value is < 1 billion, which will fit in a long.
+	 */
+	ts.tv_nsec = (long)isc_time_nanoseconds(t);
+
+	do {
+#if ISC_MUTEX_PROFILE
+		presult = pthread_cond_timedwait(c, &m->mutex, &ts);
+#else
+		presult = pthread_cond_timedwait(c, m, &ts);
+#endif
+		if (presult == 0)
+			return (ISC_R_SUCCESS);
+		if (presult == ETIMEDOUT)
+			return (ISC_R_TIMEDOUT);
+	} while (presult == EINTR);
+
+	isc__strerror(presult, strbuf, sizeof(strbuf));
+	UNEXPECTED_ERROR(__FILE__, __LINE__,
+			 "pthread_cond_timedwait() %s %s",
+			 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+					ISC_MSG_RETURNED, "returned"),
+			 strbuf);
+	return (ISC_R_UNEXPECTED);
+}
diff --git a/src/lib/bind9/pthreads/include/isc/condition.h b/src/lib/bind9/pthreads/include/isc/condition.h
new file mode 100644
index 0000000..b216657
--- /dev/null
+++ b/src/lib/bind9/pthreads/include/isc/condition.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: condition.h,v 1.26 2007-06-19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_CONDITION_H
+#define ISC_CONDITION_H 1
+
+/*! \file */
+
+#include <isc/lang.h>
+#include <isc/mutex.h>
+#include <isc/result.h>
+#include <isc/types.h>
+
+typedef pthread_cond_t isc_condition_t;
+
+#define isc_condition_init(cp) \
+	((pthread_cond_init((cp), NULL) == 0) ? \
+	 ISC_R_SUCCESS : ISC_R_UNEXPECTED)
+
+#if ISC_MUTEX_PROFILE
+#define isc_condition_wait(cp, mp) \
+	((pthread_cond_wait((cp), &((mp)->mutex)) == 0) ? \
+	 ISC_R_SUCCESS : ISC_R_UNEXPECTED)
+#else
+#define isc_condition_wait(cp, mp) \
+	((pthread_cond_wait((cp), (mp)) == 0) ? \
+	 ISC_R_SUCCESS : ISC_R_UNEXPECTED)
+#endif
+
+#define isc_condition_signal(cp) \
+	((pthread_cond_signal((cp)) == 0) ? \
+	 ISC_R_SUCCESS : ISC_R_UNEXPECTED)
+
+#define isc_condition_broadcast(cp) \
+	((pthread_cond_broadcast((cp)) == 0) ? \
+	 ISC_R_SUCCESS : ISC_R_UNEXPECTED)
+
+#define isc_condition_destroy(cp) \
+	((pthread_cond_destroy((cp)) == 0) ? \
+	 ISC_R_SUCCESS : ISC_R_UNEXPECTED)
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_condition_waituntil(isc_condition_t *, isc_mutex_t *, isc_time_t *);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_CONDITION_H */
diff --git a/src/lib/bind9/pthreads/include/isc/mutex.h b/src/lib/bind9/pthreads/include/isc/mutex.h
new file mode 100644
index 0000000..71bb430
--- /dev/null
+++ b/src/lib/bind9/pthreads/include/isc/mutex.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2002  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: mutex.h,v 1.30 2007-06-19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_MUTEX_H
+#define ISC_MUTEX_H 1
+
+/*! \file */
+
+#include <pthread.h>
+#include <stdio.h>
+
+#include <isc/lang.h>
+#include <isc/result.h>		/* for ISC_R_ codes */
+
+ISC_LANG_BEGINDECLS
+
+/*!
+ * Supply mutex attributes that enable deadlock detection
+ * (helpful when debugging).  This is system dependent and
+ * currently only supported on NetBSD.
+ */
+#if ISC_MUTEX_DEBUG && defined(__NetBSD__) && defined(PTHREAD_MUTEX_ERRORCHECK)
+extern pthread_mutexattr_t isc__mutex_attrs;
+#define ISC__MUTEX_ATTRS &isc__mutex_attrs
+#else
+#define ISC__MUTEX_ATTRS NULL
+#endif
+
+/* XXX We could do fancier error handling... */
+
+/*!
+ * Define ISC_MUTEX_PROFILE to turn on profiling of mutexes by line.  When
+ * enabled, isc_mutex_stats() can be used to print a table showing the
+ * number of times each type of mutex was locked and the amount of time
+ * waiting to obtain the lock.
+ */
+#ifndef ISC_MUTEX_PROFILE
+#define ISC_MUTEX_PROFILE 0
+#endif
+
+#if ISC_MUTEX_PROFILE
+typedef struct isc_mutexstats isc_mutexstats_t;
+
+typedef struct {
+	pthread_mutex_t		mutex;	/*%< The actual mutex. */
+	isc_mutexstats_t *	stats;	/*%< Mutex statistics. */
+} isc_mutex_t;
+#else
+typedef pthread_mutex_t	isc_mutex_t;
+#endif
+
+
+#if ISC_MUTEX_PROFILE
+#define isc_mutex_init(mp) \
+	isc_mutex_init_profile((mp), __FILE__, __LINE__)
+#else
+#if ISC_MUTEX_DEBUG && defined(PTHREAD_MUTEX_ERRORCHECK)
+#define isc_mutex_init(mp) \
+        isc_mutex_init_errcheck((mp))
+#else
+#define isc_mutex_init(mp) \
+	isc__mutex_init((mp), __FILE__, __LINE__)
+isc_result_t isc__mutex_init(isc_mutex_t *mp, const char *file, unsigned int line);
+#endif
+#endif
+
+#if ISC_MUTEX_PROFILE
+#define isc_mutex_lock(mp) \
+	isc_mutex_lock_profile((mp), __FILE__, __LINE__)
+#else
+#define isc_mutex_lock(mp) \
+	((pthread_mutex_lock((mp)) == 0) ? \
+	 ISC_R_SUCCESS : ISC_R_UNEXPECTED)
+#endif
+
+#if ISC_MUTEX_PROFILE
+#define isc_mutex_unlock(mp) \
+	isc_mutex_unlock_profile((mp), __FILE__, __LINE__)
+#else
+#define isc_mutex_unlock(mp) \
+	((pthread_mutex_unlock((mp)) == 0) ? \
+	 ISC_R_SUCCESS : ISC_R_UNEXPECTED)
+#endif
+
+#if ISC_MUTEX_PROFILE
+#define isc_mutex_trylock(mp) \
+	((pthread_mutex_trylock((&(mp)->mutex)) == 0) ? \
+	 ISC_R_SUCCESS : ISC_R_LOCKBUSY)
+#else
+#define isc_mutex_trylock(mp) \
+	((pthread_mutex_trylock((mp)) == 0) ? \
+	 ISC_R_SUCCESS : ISC_R_LOCKBUSY)
+#endif
+
+#if ISC_MUTEX_PROFILE
+#define isc_mutex_destroy(mp) \
+	((pthread_mutex_destroy((&(mp)->mutex)) == 0) ? \
+	 ISC_R_SUCCESS : ISC_R_UNEXPECTED)
+#else
+#define isc_mutex_destroy(mp) \
+	((pthread_mutex_destroy((mp)) == 0) ? \
+	 ISC_R_SUCCESS : ISC_R_UNEXPECTED)
+#endif
+
+#if ISC_MUTEX_PROFILE
+#define isc_mutex_stats(fp) isc_mutex_statsprofile(fp);
+#else
+#define isc_mutex_stats(fp)
+#endif
+
+#if ISC_MUTEX_PROFILE
+
+isc_result_t
+isc_mutex_init_profile(isc_mutex_t *mp, const char * _file, int _line);
+isc_result_t
+isc_mutex_lock_profile(isc_mutex_t *mp, const char * _file, int _line);
+isc_result_t
+isc_mutex_unlock_profile(isc_mutex_t *mp, const char * _file, int _line);
+
+void
+isc_mutex_statsprofile(FILE *fp);
+
+isc_result_t
+isc_mutex_init_errcheck(isc_mutex_t *mp);
+
+#endif /* ISC_MUTEX_PROFILE */
+
+ISC_LANG_ENDDECLS
+#endif /* ISC_MUTEX_H */
diff --git a/src/lib/bind9/pthreads/include/isc/once.h b/src/lib/bind9/pthreads/include/isc/once.h
new file mode 100644
index 0000000..dd580f1
--- /dev/null
+++ b/src/lib/bind9/pthreads/include/isc/once.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: once.h,v 1.13 2007-06-19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_ONCE_H
+#define ISC_ONCE_H 1
+
+/*! \file */
+
+#include <pthread.h>
+
+#include <isc/platform.h>
+#include <isc/result.h>
+
+typedef pthread_once_t isc_once_t;
+
+#ifdef ISC_PLATFORM_BRACEPTHREADONCEINIT
+/*!
+ * This accomodates systems that define PTHRAD_ONCE_INIT improperly.
+ */
+#define ISC_ONCE_INIT { PTHREAD_ONCE_INIT }
+#else
+/*!
+ * This is the usual case.
+ */
+#define ISC_ONCE_INIT PTHREAD_ONCE_INIT
+#endif
+
+/* XXX We could do fancier error handling... */
+
+#define isc_once_do(op, f) \
+	((pthread_once((op), (f)) == 0) ? \
+	 ISC_R_SUCCESS : ISC_R_UNEXPECTED)
+
+#endif /* ISC_ONCE_H */
diff --git a/src/lib/bind9/pthreads/include/isc/thread.h b/src/lib/bind9/pthreads/include/isc/thread.h
new file mode 100644
index 0000000..390ca73
--- /dev/null
+++ b/src/lib/bind9/pthreads/include/isc/thread.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: thread.h,v 1.26 2007-06-19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_THREAD_H
+#define ISC_THREAD_H 1
+
+/*! \file */
+
+#include <pthread.h>
+
+#include <isc/lang.h>
+#include <isc/result.h>
+
+ISC_LANG_BEGINDECLS
+
+typedef pthread_t isc_thread_t;
+typedef void * isc_threadresult_t;
+typedef void * isc_threadarg_t;
+typedef isc_threadresult_t (*isc_threadfunc_t)(isc_threadarg_t);
+typedef pthread_key_t isc_thread_key_t;
+
+isc_result_t
+isc_thread_create(isc_threadfunc_t, isc_threadarg_t, isc_thread_t *);
+
+void
+isc_thread_setconcurrency(unsigned int level);
+
+/* XXX We could do fancier error handling... */
+
+#define isc_thread_join(t, rp) \
+	((pthread_join((t), (rp)) == 0) ? \
+	 ISC_R_SUCCESS : ISC_R_UNEXPECTED)
+
+#define isc_thread_self \
+	(unsigned long)pthread_self
+
+#define isc_thread_key_create pthread_key_create
+#define isc_thread_key_getspecific pthread_getspecific
+#define isc_thread_key_setspecific pthread_setspecific
+#define isc_thread_key_delete pthread_key_delete
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_THREAD_H */
diff --git a/src/lib/bind9/pthreads/mutex.c b/src/lib/bind9/pthreads/mutex.c
new file mode 100644
index 0000000..fa5a701
--- /dev/null
+++ b/src/lib/bind9/pthreads/mutex.c
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2008, 2011  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2002  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: mutex.c,v 1.18 2011-01-04 23:47:14 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <time.h>
+#include <sys/time.h>
+#include <errno.h>
+
+#include <isc/mutex.h>
+#include <isc/util.h>
+#include <isc/strerror.h>
+
+#if ISC_MUTEX_PROFILE
+
+/*@{*/
+/*% Operations on timevals; adapted from FreeBSD's sys/time.h */
+#define timevalclear(tvp)      ((tvp)->tv_sec = (tvp)->tv_usec = 0)
+#define timevaladd(vvp, uvp)                                            \
+	do {                                                            \
+		(vvp)->tv_sec += (uvp)->tv_sec;                         \
+		(vvp)->tv_usec += (uvp)->tv_usec;                       \
+		if ((vvp)->tv_usec >= 1000000) {                        \
+			(vvp)->tv_sec++;                                \
+			(vvp)->tv_usec -= 1000000;                      \
+		}                                                       \
+	} while (0)
+#define timevalsub(vvp, uvp)                                            \
+	do {                                                            \
+		(vvp)->tv_sec -= (uvp)->tv_sec;                         \
+		(vvp)->tv_usec -= (uvp)->tv_usec;                       \
+		if ((vvp)->tv_usec < 0) {                               \
+			(vvp)->tv_sec--;                                \
+			(vvp)->tv_usec += 1000000;                      \
+		}                                                       \
+	} while (0)
+
+/*@}*/
+
+#define ISC_MUTEX_MAX_LOCKERS 32
+
+typedef struct {
+	const char *		file;
+	int			line;
+	unsigned		count;
+	struct timeval		locked_total;
+	struct timeval		wait_total;
+} isc_mutexlocker_t;
+
+struct isc_mutexstats {
+	const char *		file;	/*%< File mutex was created in. */
+	int 			line;	/*%< Line mutex was created on. */
+	unsigned		count;
+	struct timeval		lock_t;
+	struct timeval		locked_total;
+	struct timeval		wait_total;
+	isc_mutexlocker_t *	cur_locker;
+	isc_mutexlocker_t	lockers[ISC_MUTEX_MAX_LOCKERS];
+};
+
+#ifndef ISC_MUTEX_PROFTABLESIZE
+#define ISC_MUTEX_PROFTABLESIZE (16 * 1024)
+#endif
+static isc_mutexstats_t stats[ISC_MUTEX_PROFTABLESIZE];
+static int stats_next = 0;
+static isc_boolean_t stats_init = ISC_FALSE;
+static pthread_mutex_t statslock = PTHREAD_MUTEX_INITIALIZER;
+
+
+isc_result_t
+isc_mutex_init_profile(isc_mutex_t *mp, const char *file, int line) {
+	int i, err;
+
+	err = pthread_mutex_init(&mp->mutex, NULL);
+	if (err == ENOMEM)
+		return (ISC_R_NOMEMORY);
+	if (err != 0)
+		return (ISC_R_UNEXPECTED);
+
+	RUNTIME_CHECK(pthread_mutex_lock(&statslock) == 0);
+
+	if (stats_init == ISC_FALSE)
+		stats_init = ISC_TRUE;
+
+	/*
+	 * If all statistics entries have been used, give up and trigger an
+	 * assertion failure.  There would be no other way to deal with this
+	 * because we'd like to keep record of all locks for the purpose of
+	 * debugging and the number of necessary locks is unpredictable.
+	 * If this failure is triggered while debugging, named should be
+	 * rebuilt with an increased ISC_MUTEX_PROFTABLESIZE.
+	 */
+	RUNTIME_CHECK(stats_next < ISC_MUTEX_PROFTABLESIZE);
+	mp->stats = &stats[stats_next++];
+
+	RUNTIME_CHECK(pthread_mutex_unlock(&statslock) == 0);
+
+	mp->stats->file = file;
+	mp->stats->line = line;
+	mp->stats->count = 0;
+	timevalclear(&mp->stats->locked_total);
+	timevalclear(&mp->stats->wait_total);
+	for (i = 0; i < ISC_MUTEX_MAX_LOCKERS; i++) {
+		mp->stats->lockers[i].file = NULL;
+		mp->stats->lockers[i].line = 0;
+		mp->stats->lockers[i].count = 0;
+		timevalclear(&mp->stats->lockers[i].locked_total);
+		timevalclear(&mp->stats->lockers[i].wait_total);
+	}
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_mutex_lock_profile(isc_mutex_t *mp, const char *file, int line) {
+	struct timeval prelock_t;
+	struct timeval postlock_t;
+	isc_mutexlocker_t *locker = NULL;
+	int i;
+
+	gettimeofday(&prelock_t, NULL);
+
+	if (pthread_mutex_lock(&mp->mutex) != 0)
+		return (ISC_R_UNEXPECTED);
+
+	gettimeofday(&postlock_t, NULL);
+	mp->stats->lock_t = postlock_t;
+
+	timevalsub(&postlock_t, &prelock_t);
+
+	mp->stats->count++;
+	timevaladd(&mp->stats->wait_total, &postlock_t);
+
+	for (i = 0; i < ISC_MUTEX_MAX_LOCKERS; i++) {
+		if (mp->stats->lockers[i].file == NULL) {
+			locker = &mp->stats->lockers[i];
+			locker->file = file;
+			locker->line = line;
+			break;
+		} else if (mp->stats->lockers[i].file == file &&
+			   mp->stats->lockers[i].line == line) {
+			locker = &mp->stats->lockers[i];
+			break;
+		}
+	}
+
+	if (locker != NULL) {
+		locker->count++;
+		timevaladd(&locker->wait_total, &postlock_t);
+	}
+
+	mp->stats->cur_locker = locker;
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_mutex_unlock_profile(isc_mutex_t *mp, const char *file, int line) {
+	struct timeval unlock_t;
+
+	UNUSED(file);
+	UNUSED(line);
+
+	if (mp->stats->cur_locker != NULL) {
+		gettimeofday(&unlock_t, NULL);
+		timevalsub(&unlock_t, &mp->stats->lock_t);
+		timevaladd(&mp->stats->locked_total, &unlock_t);
+		timevaladd(&mp->stats->cur_locker->locked_total, &unlock_t);
+		mp->stats->cur_locker = NULL;
+	}
+
+	return ((pthread_mutex_unlock((&mp->mutex)) == 0) ? \
+		ISC_R_SUCCESS : ISC_R_UNEXPECTED);
+}
+
+
+void
+isc_mutex_statsprofile(FILE *fp) {
+	isc_mutexlocker_t *locker;
+	int i, j;
+
+	fprintf(fp, "Mutex stats (in us)\n");
+	for (i = 0; i < stats_next; i++) {
+		fprintf(fp, "%-12s %4d: %10u  %lu.%06lu %lu.%06lu\n",
+			stats[i].file, stats[i].line, stats[i].count,
+			stats[i].locked_total.tv_sec,
+			stats[i].locked_total.tv_usec,
+			stats[i].wait_total.tv_sec,
+			stats[i].wait_total.tv_usec
+			);
+		for (j = 0; j < ISC_MUTEX_MAX_LOCKERS; j++) {
+			locker = &stats[i].lockers[j];
+			if (locker->file == NULL)
+				continue;
+			fprintf(fp, " %-11s %4d: %10u  %lu.%06lu %lu.%06lu\n",
+				locker->file, locker->line, locker->count,
+				locker->locked_total.tv_sec,
+				locker->locked_total.tv_usec,
+				locker->wait_total.tv_sec,
+				locker->wait_total.tv_usec
+				);
+		}
+	}
+}
+
+#endif /* ISC_MUTEX_PROFILE */
+
+#if ISC_MUTEX_DEBUG && defined(PTHREAD_MUTEX_ERRORCHECK)
+isc_result_t
+isc_mutex_init_errcheck(isc_mutex_t *mp)
+{
+	pthread_mutexattr_t attr;
+	int err;
+
+	if (pthread_mutexattr_init(&attr) != 0)
+		return (ISC_R_UNEXPECTED);
+
+	if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK) != 0) {
+		pthread_mutexattr_destroy(&attr);
+		return (ISC_R_UNEXPECTED);
+	}
+
+	err = pthread_mutex_init(mp, &attr) != 0)
+	pthread_mutexattr_destroy(&attr);
+	if (err == ENOMEM)
+		return (ISC_R_NOMEMORY);
+	return ((err == 0) ? ISC_R_SUCCESS : ISC_R_UNEXPECTED);
+}
+#endif
+
+#if ISC_MUTEX_DEBUG && defined(__NetBSD__) && defined(PTHREAD_MUTEX_ERRORCHECK)
+pthread_mutexattr_t isc__mutex_attrs = {
+	PTHREAD_MUTEX_ERRORCHECK,	/* m_type */
+	0				/* m_flags, which appears to be unused. */
+};
+#endif
+
+#if !(ISC_MUTEX_DEBUG && defined(PTHREAD_MUTEX_ERRORCHECK)) && !ISC_MUTEX_PROFILE
+isc_result_t
+isc__mutex_init(isc_mutex_t *mp, const char *file, unsigned int line) {
+	char strbuf[ISC_STRERRORSIZE];
+	isc_result_t result = ISC_R_SUCCESS;
+	int err;
+
+	err = pthread_mutex_init(mp, ISC__MUTEX_ATTRS);
+	if (err == ENOMEM)
+		return (ISC_R_NOMEMORY);
+	if (err != 0) {
+		isc__strerror(errno, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(file, line, "isc_mutex_init() failed: %s",
+				 strbuf);
+		result = ISC_R_UNEXPECTED;
+	}
+	return (result);
+}
+#endif
diff --git a/src/lib/bind9/pthreads/thread.c b/src/lib/bind9/pthreads/thread.c
new file mode 100644
index 0000000..663ca8c
--- /dev/null
+++ b/src/lib/bind9/pthreads/thread.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001, 2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: thread.c,v 1.17 2007-06-19 23:47:18 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/thread.h>
+#include <isc/util.h>
+
+#ifndef THREAD_MINSTACKSIZE
+#define THREAD_MINSTACKSIZE		(64U * 1024)
+#endif
+
+isc_result_t
+isc_thread_create(isc_threadfunc_t func, isc_threadarg_t arg,
+		  isc_thread_t *thread)
+{
+	pthread_attr_t attr;
+	size_t stacksize;
+	int ret;
+
+	pthread_attr_init(&attr);
+
+#if defined(HAVE_PTHREAD_ATTR_GETSTACKSIZE) && \
+    defined(HAVE_PTHREAD_ATTR_SETSTACKSIZE)
+	ret = pthread_attr_getstacksize(&attr, &stacksize);
+	if (ret != 0)
+		return (ISC_R_UNEXPECTED);
+
+	if (stacksize < THREAD_MINSTACKSIZE) {
+		ret = pthread_attr_setstacksize(&attr, THREAD_MINSTACKSIZE);
+		if (ret != 0)
+			return (ISC_R_UNEXPECTED);
+	}
+#endif
+
+#if defined(PTHREAD_SCOPE_SYSTEM) && defined(NEED_PTHREAD_SCOPE_SYSTEM)
+	ret = pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
+	if (ret != 0)
+		return (ISC_R_UNEXPECTED);
+#endif
+
+	ret = pthread_create(thread, &attr, func, arg);
+	if (ret != 0)
+		return (ISC_R_UNEXPECTED);
+
+	pthread_attr_destroy(&attr);
+
+	return (ISC_R_SUCCESS);
+}
+
+void
+isc_thread_setconcurrency(unsigned int level) {
+#if defined(CALL_PTHREAD_SETCONCURRENCY)
+	(void)pthread_setconcurrency(level);
+#else
+	UNUSED(level);
+#endif
+}
diff --git a/src/lib/bind9/quota.c b/src/lib/bind9/quota.c
new file mode 100644
index 0000000..f977fb5
--- /dev/null
+++ b/src/lib/bind9/quota.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: quota.c,v 1.18 2007-06-19 23:47:17 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stddef.h>
+
+#include <isc/quota.h>
+#include <isc/util.h>
+
+isc_result_t
+isc_quota_init(isc_quota_t *quota, int max) {
+	quota->max = max;
+	quota->used = 0;
+	quota->soft = 0;
+	return (isc_mutex_init(&quota->lock));
+}
+
+void
+isc_quota_destroy(isc_quota_t *quota) {
+	INSIST(quota->used == 0);
+	quota->max = 0;
+	quota->used = 0;
+	quota->soft = 0;
+	DESTROYLOCK(&quota->lock);
+}
+
+void
+isc_quota_soft(isc_quota_t *quota, int soft) {
+	LOCK(&quota->lock);
+	quota->soft = soft;
+	UNLOCK(&quota->lock);
+}
+
+void
+isc_quota_max(isc_quota_t *quota, int max) {
+	LOCK(&quota->lock);
+	quota->max = max;
+	UNLOCK(&quota->lock);
+}
+
+isc_result_t
+isc_quota_reserve(isc_quota_t *quota) {
+	isc_result_t result;
+	LOCK(&quota->lock);
+	if (quota->max == 0 || quota->used < quota->max) {
+		if (quota->soft == 0 || quota->used < quota->soft)
+			result = ISC_R_SUCCESS;
+		else
+			result = ISC_R_SOFTQUOTA;
+		quota->used++;
+	} else
+		result = ISC_R_QUOTA;
+	UNLOCK(&quota->lock);
+	return (result);
+}
+
+void
+isc_quota_release(isc_quota_t *quota) {
+	LOCK(&quota->lock);
+	INSIST(quota->used > 0);
+	quota->used--;
+	UNLOCK(&quota->lock);
+}
+
+isc_result_t
+isc_quota_attach(isc_quota_t *quota, isc_quota_t **p)
+{
+	isc_result_t result;
+	INSIST(p != NULL && *p == NULL);
+	result = isc_quota_reserve(quota);
+	if (result == ISC_R_SUCCESS || result == ISC_R_SOFTQUOTA)
+		*p = quota;
+	return (result);
+}
+
+void
+isc_quota_detach(isc_quota_t **p)
+{
+	INSIST(p != NULL && *p != NULL);
+	isc_quota_release(*p);
+	*p = NULL;
+}
diff --git a/src/lib/bind9/radix.c b/src/lib/bind9/radix.c
new file mode 100644
index 0000000..641620c
--- /dev/null
+++ b/src/lib/bind9/radix.c
@@ -0,0 +1,706 @@
+/*
+ * Copyright (C) 2007-2009, 2011  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: radix.c,v 1.23.426.2 2011-03-12 04:59:18 tbox Exp $ */
+
+/*
+ * This source was adapted from MRT's RCS Ids:
+ * Id: radix.c,v 1.10.2.1 1999/11/29 05:16:24 masaki Exp
+ * Id: prefix.c,v 1.37.2.9 2000/03/10 02:53:19 labovit Exp
+ */
+
+#include <config.h>
+
+#include <isc/mem.h>
+#include <isc/types.h>
+#include <isc/util.h>
+#include <isc/radix.h>
+
+static isc_result_t
+_new_prefix(isc_mem_t *mctx, isc_prefix_t **target, int family,
+	    void *dest, int bitlen);
+
+static void
+_deref_prefix(isc_mem_t *mctx, isc_prefix_t *prefix);
+
+static isc_result_t
+_ref_prefix(isc_mem_t *mctx, isc_prefix_t **target, isc_prefix_t *prefix);
+
+static int
+_comp_with_mask(void *addr, void *dest, u_int mask);
+
+static void
+_clear_radix(isc_radix_tree_t *radix, isc_radix_destroyfunc_t func);
+
+static isc_result_t
+_new_prefix(isc_mem_t *mctx, isc_prefix_t **target, int family, void *dest,
+	    int bitlen)
+{
+	isc_prefix_t *prefix;
+
+	REQUIRE(target != NULL);
+
+	if (family != AF_INET6 && family != AF_INET && family != AF_UNSPEC)
+		return (ISC_R_NOTIMPLEMENTED);
+
+	prefix = isc_mem_get(mctx, sizeof(isc_prefix_t));
+	if (prefix == NULL)
+		return (ISC_R_NOMEMORY);
+
+	if (family == AF_INET6) {
+		prefix->bitlen = (bitlen >= 0) ? bitlen : 128;
+		memcpy(&prefix->add.sin6, dest, 16);
+	} else {
+		/* AF_UNSPEC is "any" or "none"--treat it as AF_INET */
+		prefix->bitlen = (bitlen >= 0) ? bitlen : 32;
+		memcpy(&prefix->add.sin, dest, 4);
+	}
+
+	prefix->family = family;
+
+	isc_refcount_init(&prefix->refcount, 1);
+
+	*target = prefix;
+	return (ISC_R_SUCCESS);
+}
+
+static void
+_deref_prefix(isc_mem_t *mctx, isc_prefix_t *prefix) {
+	int refs;
+
+	if (prefix == NULL)
+		return;
+
+	isc_refcount_decrement(&prefix->refcount, &refs);
+
+	if (refs <= 0) {
+		isc_refcount_destroy(&prefix->refcount);
+		isc_mem_put(mctx, prefix, sizeof(isc_prefix_t));
+	}
+}
+
+static isc_result_t
+_ref_prefix(isc_mem_t *mctx, isc_prefix_t **target, isc_prefix_t *prefix) {
+	INSIST(prefix != NULL);
+	INSIST((prefix->family == AF_INET && prefix->bitlen <= 32) ||
+	       (prefix->family == AF_INET6 && prefix->bitlen <= 128) ||
+	       (prefix->family == AF_UNSPEC && prefix->bitlen == 0));
+	REQUIRE(target != NULL && *target == NULL);
+
+	/*
+	 * If this prefix is a static allocation, copy it into new memory.
+	 * (Note, the refcount still has to be destroyed by the calling
+	 * routine.)
+	 */
+	if (isc_refcount_current(&prefix->refcount) == 0) {
+		isc_result_t ret;
+		ret = _new_prefix(mctx, target, prefix->family,
+				  &prefix->add, prefix->bitlen);
+		return ret;
+	}
+
+	isc_refcount_increment(&prefix->refcount, NULL);
+
+	*target = prefix;
+	return (ISC_R_SUCCESS);
+}
+
+static int
+_comp_with_mask(void *addr, void *dest, u_int mask) {
+
+	/* Mask length of zero matches everything */
+	if (mask == 0)
+		return (1);
+
+	if (memcmp(addr, dest, mask / 8) == 0) {
+		int n = mask / 8;
+		int m = ((~0) << (8 - (mask % 8)));
+
+		if ((mask % 8) == 0 ||
+		    (((u_char *)addr)[n] & m) == (((u_char *)dest)[n] & m))
+			return (1);
+	}
+	return (0);
+}
+
+isc_result_t
+isc_radix_create(isc_mem_t *mctx, isc_radix_tree_t **target, int maxbits) {
+	isc_radix_tree_t *radix;
+
+	REQUIRE(target != NULL && *target == NULL);
+
+	radix = isc_mem_get(mctx, sizeof(isc_radix_tree_t));
+	if (radix == NULL)
+		return (ISC_R_NOMEMORY);
+
+	radix->mctx = mctx;
+	radix->maxbits = maxbits;
+	radix->head = NULL;
+	radix->num_active_node = 0;
+	radix->num_added_node = 0;
+	RUNTIME_CHECK(maxbits <= RADIX_MAXBITS); /* XXX */
+	radix->magic = RADIX_TREE_MAGIC;
+	*target = radix;
+	return (ISC_R_SUCCESS);
+}
+
+/*
+ * if func is supplied, it will be called as func(node->data)
+ * before deleting the node
+ */
+
+static void
+_clear_radix(isc_radix_tree_t *radix, isc_radix_destroyfunc_t func) {
+
+	REQUIRE(radix != NULL);
+
+	if (radix->head != NULL) {
+
+		isc_radix_node_t *Xstack[RADIX_MAXBITS+1];
+		isc_radix_node_t **Xsp = Xstack;
+		isc_radix_node_t *Xrn = radix->head;
+
+		while (Xrn != NULL) {
+			isc_radix_node_t *l = Xrn->l;
+			isc_radix_node_t *r = Xrn->r;
+
+			if (Xrn->prefix != NULL) {
+				_deref_prefix(radix->mctx, Xrn->prefix);
+				if (func != NULL && (Xrn->data[0] != NULL ||
+						     Xrn->data[1] != NULL))
+					func(Xrn->data);
+			} else {
+				INSIST(Xrn->data[0] == NULL &&
+				       Xrn->data[1] == NULL);
+			}
+
+			isc_mem_put(radix->mctx, Xrn, sizeof(*Xrn));
+			radix->num_active_node--;
+
+			if (l != NULL) {
+				if (r != NULL) {
+					*Xsp++ = r;
+				}
+				Xrn = l;
+			} else if (r != NULL) {
+				Xrn = r;
+			} else if (Xsp != Xstack) {
+				Xrn = *(--Xsp);
+			} else {
+				Xrn = NULL;
+			}
+		}
+	}
+	RUNTIME_CHECK(radix->num_active_node == 0);
+}
+
+
+void
+isc_radix_destroy(isc_radix_tree_t *radix, isc_radix_destroyfunc_t func)
+{
+	REQUIRE(radix != NULL);
+	_clear_radix(radix, func);
+	isc_mem_put(radix->mctx, radix, sizeof(*radix));
+}
+
+
+/*
+ * func will be called as func(node->prefix, node->data)
+ */
+void
+isc_radix_process(isc_radix_tree_t *radix, isc_radix_processfunc_t func)
+{
+	isc_radix_node_t *node;
+
+	REQUIRE(func != NULL);
+
+	RADIX_WALK(radix->head, node) {
+		func(node->prefix, node->data);
+	} RADIX_WALK_END;
+}
+
+
+isc_result_t
+isc_radix_search(isc_radix_tree_t *radix, isc_radix_node_t **target,
+		 isc_prefix_t *prefix)
+{
+	isc_radix_node_t *node;
+	isc_radix_node_t *stack[RADIX_MAXBITS + 1];
+	u_char *addr;
+	isc_uint32_t bitlen;
+	int tfamily = -1;
+	int cnt = 0;
+
+	REQUIRE(radix != NULL);
+	REQUIRE(prefix != NULL);
+	REQUIRE(target != NULL && *target == NULL);
+	RUNTIME_CHECK(prefix->bitlen <= radix->maxbits);
+
+	*target = NULL;
+
+	if (radix->head == NULL) {
+		return (ISC_R_NOTFOUND);
+	}
+
+	node = radix->head;
+	addr = isc_prefix_touchar(prefix);
+	bitlen = prefix->bitlen;
+
+	while (node->bit < bitlen) {
+		if (node->prefix)
+			stack[cnt++] = node;
+
+		if (BIT_TEST(addr[node->bit >> 3], 0x80 >> (node->bit & 0x07)))
+			node = node->r;
+		else
+			node = node->l;
+
+		if (node == NULL)
+			break;
+	}
+
+	if (node && node->prefix)
+		stack[cnt++] = node;
+
+	while (cnt-- > 0) {
+		node = stack[cnt];
+
+		if (_comp_with_mask(isc_prefix_tochar(node->prefix),
+				    isc_prefix_tochar(prefix),
+				    node->prefix->bitlen)) {
+			if (node->node_num[ISC_IS6(prefix->family)] != -1 &&
+				 ((*target == NULL) ||
+				  (*target)->node_num[ISC_IS6(tfamily)] >
+				   node->node_num[ISC_IS6(prefix->family)])) {
+				*target = node;
+				tfamily = prefix->family;
+			}
+		}
+	}
+
+	if (*target == NULL) {
+		return (ISC_R_NOTFOUND);
+	} else {
+		return (ISC_R_SUCCESS);
+	}
+}
+
+isc_result_t
+isc_radix_insert(isc_radix_tree_t *radix, isc_radix_node_t **target,
+		 isc_radix_node_t *source, isc_prefix_t *prefix)
+{
+	isc_radix_node_t *node, *new_node, *parent, *glue = NULL;
+	u_char *addr, *test_addr;
+	isc_uint32_t bitlen, fam, check_bit, differ_bit;
+	isc_uint32_t i, j, r;
+	isc_result_t result;
+
+	REQUIRE(radix != NULL);
+	REQUIRE(target != NULL && *target == NULL);
+	REQUIRE(prefix != NULL || (source != NULL && source->prefix != NULL));
+	RUNTIME_CHECK(prefix == NULL || prefix->bitlen <= radix->maxbits);
+
+	if (prefix == NULL)
+		prefix = source->prefix;
+
+	INSIST(prefix != NULL);
+
+	bitlen = prefix->bitlen;
+	fam = prefix->family;
+
+	if (radix->head == NULL) {
+		node = isc_mem_get(radix->mctx, sizeof(isc_radix_node_t));
+		if (node == NULL)
+			return (ISC_R_NOMEMORY);
+		node->bit = bitlen;
+		node->node_num[0] = node->node_num[1] = -1;
+		node->prefix = NULL;
+		result = _ref_prefix(radix->mctx, &node->prefix, prefix);
+		if (result != ISC_R_SUCCESS) {
+			isc_mem_put(radix->mctx, node,
+				    sizeof(isc_radix_node_t));
+			return (result);
+		}
+		node->parent = NULL;
+		node->l = node->r = NULL;
+		if (source != NULL) {
+			/*
+			 * If source is non-NULL, then we're merging in a
+			 * node from an existing radix tree.  To keep
+			 * the node_num values consistent, the calling
+			 * function will add the total number of nodes
+			 * added to num_added_node at the end of
+			 * the merge operation--we don't do it here.
+			 */
+			if (source->node_num[0] != -1)
+				node->node_num[0] = radix->num_added_node +
+						    source->node_num[0];
+			if (source->node_num[1] != -1)
+				node->node_num[1] = radix->num_added_node +
+						    source->node_num[1];
+			node->data[0] = source->data[0];
+			node->data[1] = source->data[1];
+		} else {
+			if (fam == AF_UNSPEC) {
+				/* "any" or "none" */
+				node->node_num[0] = node->node_num[1] =
+					++radix->num_added_node;
+			} else {
+				node->node_num[ISC_IS6(fam)] =
+					++radix->num_added_node;
+			}
+			node->data[0] = NULL;
+			node->data[1] = NULL;
+		}
+		radix->head = node;
+		radix->num_active_node++;
+		*target = node;
+		return (ISC_R_SUCCESS);
+	}
+
+	addr = isc_prefix_touchar(prefix);
+	node = radix->head;
+
+	while (node->bit < bitlen || node->prefix == NULL) {
+		if (node->bit < radix->maxbits &&
+		    BIT_TEST(addr[node->bit >> 3], 0x80 >> (node->bit & 0x07)))
+		{
+			if (node->r == NULL)
+				break;
+			node = node->r;
+		} else {
+			if (node->l == NULL)
+				break;
+			node = node->l;
+		}
+
+		INSIST(node != NULL);
+	}
+
+	INSIST(node->prefix != NULL);
+
+	test_addr = isc_prefix_touchar(node->prefix);
+	/* Find the first bit different. */
+	check_bit = (node->bit < bitlen) ? node->bit : bitlen;
+	differ_bit = 0;
+	for (i = 0; i*8 < check_bit; i++) {
+		if ((r = (addr[i] ^ test_addr[i])) == 0) {
+			differ_bit = (i + 1) * 8;
+			continue;
+		}
+		/* I know the better way, but for now. */
+		for (j = 0; j < 8; j++) {
+			if (BIT_TEST (r, (0x80 >> j)))
+				break;
+		}
+		/* Must be found. */
+		INSIST(j < 8);
+		differ_bit = i * 8 + j;
+		break;
+	}
+
+	if (differ_bit > check_bit)
+		differ_bit = check_bit;
+
+	parent = node->parent;
+	while (parent != NULL && parent->bit >= differ_bit) {
+		node = parent;
+		parent = node->parent;
+	}
+
+	if (differ_bit == bitlen && node->bit == bitlen) {
+		if (node->prefix != NULL) {
+			/* Set node_num only if it hasn't been set before */
+			if (source != NULL) {
+				/* Merging node */
+				if (node->node_num[0] == -1 &&
+				    source->node_num[0] != -1) {
+					node->node_num[0] =
+						radix->num_added_node +
+						source->node_num[0];
+					node->data[0] = source->data[0];
+				}
+				if (node->node_num[1] == -1 &&
+				    source->node_num[0] != -1) {
+					node->node_num[1] =
+						radix->num_added_node +
+						source->node_num[1];
+					node->data[1] = source->data[1];
+				}
+			} else {
+				if (fam == AF_UNSPEC) {
+					/* "any" or "none" */
+					int next = radix->num_added_node + 1;
+					if (node->node_num[0] == -1) {
+						node->node_num[0] = next;
+						radix->num_added_node = next;
+					}
+					if (node->node_num[1] == -1) {
+						node->node_num[1] = next;
+						radix->num_added_node = next;
+					}
+				} else {
+					if (node->node_num[ISC_IS6(fam)] == -1)
+						node->node_num[ISC_IS6(fam)]
+						   = ++radix->num_added_node;
+				}
+			}
+			*target = node;
+			return (ISC_R_SUCCESS);
+		} else {
+			result =
+				_ref_prefix(radix->mctx, &node->prefix, prefix);
+			if (result != ISC_R_SUCCESS)
+				return (result);
+		}
+		INSIST(node->data[0] == NULL && node->node_num[0] == -1 &&
+		       node->data[1] == NULL && node->node_num[1] == -1);
+		if (source != NULL) {
+			/* Merging node */
+			if (source->node_num[0] != -1) {
+				node->node_num[0] = radix->num_added_node +
+						    source->node_num[0];
+				node->data[0] = source->data[0];
+			}
+			if (source->node_num[1] != -1) {
+				node->node_num[1] = radix->num_added_node +
+						    source->node_num[1];
+				node->data[1] = source->data[1];
+			}
+		} else {
+			if (fam == AF_UNSPEC) {
+				/* "any" or "none" */
+				node->node_num[0] = node->node_num[1] =
+					++radix->num_added_node;
+			} else {
+				node->node_num[ISC_IS6(fam)] =
+					++radix->num_added_node;
+			}
+		}
+		*target = node;
+		return (ISC_R_SUCCESS);
+	}
+
+	new_node = isc_mem_get(radix->mctx, sizeof(isc_radix_node_t));
+	if (new_node == NULL)
+		return (ISC_R_NOMEMORY);
+	if (node->bit != differ_bit && bitlen != differ_bit) {
+		glue = isc_mem_get(radix->mctx, sizeof(isc_radix_node_t));
+		if (glue == NULL) {
+			isc_mem_put(radix->mctx, new_node,
+				    sizeof(isc_radix_node_t));
+			return (ISC_R_NOMEMORY);
+		}
+	}
+	new_node->bit = bitlen;
+	new_node->prefix = NULL;
+	result = _ref_prefix(radix->mctx, &new_node->prefix, prefix);
+	if (result != ISC_R_SUCCESS) {
+		isc_mem_put(radix->mctx, new_node, sizeof(isc_radix_node_t));
+		if (glue != NULL)
+			isc_mem_put(radix->mctx, glue,
+				    sizeof(isc_radix_node_t));
+		return (result);
+	}
+	new_node->parent = NULL;
+	new_node->l = new_node->r = NULL;
+	new_node->node_num[0] = new_node->node_num[1] = -1;
+	radix->num_active_node++;
+
+	if (source != NULL) {
+		/* Merging node */
+		if (source->node_num[0] != -1)
+			new_node->node_num[0] = radix->num_added_node +
+						source->node_num[0];
+		if (source->node_num[1] != -1)
+			new_node->node_num[1] = radix->num_added_node +
+						source->node_num[1];
+		new_node->data[0] = source->data[0];
+		new_node->data[1] = source->data[1];
+	} else {
+		if (fam == AF_UNSPEC) {
+			/* "any" or "none" */
+			new_node->node_num[0] = new_node->node_num[1] =
+				++radix->num_added_node;
+		} else {
+			new_node->node_num[ISC_IS6(fam)] =
+				++radix->num_added_node;
+		}
+		new_node->data[0] = NULL;
+		new_node->data[1] = NULL;
+	}
+
+	if (node->bit == differ_bit) {
+		INSIST(glue == NULL);
+		new_node->parent = node;
+		if (node->bit < radix->maxbits &&
+		    BIT_TEST(addr[node->bit >> 3], 0x80 >> (node->bit & 0x07)))
+		{
+			INSIST(node->r == NULL);
+			node->r = new_node;
+		} else {
+			INSIST(node->l == NULL);
+			node->l = new_node;
+		}
+		*target = new_node;
+		return (ISC_R_SUCCESS);
+	}
+
+	if (bitlen == differ_bit) {
+		INSIST(glue == NULL);
+		if (bitlen < radix->maxbits &&
+		    BIT_TEST(test_addr[bitlen >> 3], 0x80 >> (bitlen & 0x07))) {
+			new_node->r = node;
+		} else {
+			new_node->l = node;
+		}
+		new_node->parent = node->parent;
+		if (node->parent == NULL) {
+			INSIST(radix->head == node);
+			radix->head = new_node;
+		} else if (node->parent->r == node) {
+			node->parent->r = new_node;
+		} else {
+			node->parent->l = new_node;
+		}
+		node->parent = new_node;
+	} else {
+		INSIST(glue != NULL);
+		glue->bit = differ_bit;
+		glue->prefix = NULL;
+		glue->parent = node->parent;
+		glue->data[0] = glue->data[1] = NULL;
+		glue->node_num[0] = glue->node_num[1] = -1;
+		radix->num_active_node++;
+		if (differ_bit < radix->maxbits &&
+		    BIT_TEST(addr[differ_bit>>3], 0x80 >> (differ_bit & 07))) {
+			glue->r = new_node;
+			glue->l = node;
+		} else {
+			glue->r = node;
+			glue->l = new_node;
+		}
+		new_node->parent = glue;
+
+		if (node->parent == NULL) {
+			INSIST(radix->head == node);
+			radix->head = glue;
+		} else if (node->parent->r == node) {
+			node->parent->r = glue;
+		} else {
+			node->parent->l = glue;
+		}
+		node->parent = glue;
+	}
+
+	*target = new_node;
+	return (ISC_R_SUCCESS);
+}
+
+void
+isc_radix_remove(isc_radix_tree_t *radix, isc_radix_node_t *node) {
+	isc_radix_node_t *parent, *child;
+
+	REQUIRE(radix != NULL);
+	REQUIRE(node != NULL);
+
+	if (node->r && node->l) {
+		/*
+		 * This might be a placeholder node -- have to check and
+		 * make sure there is a prefix associated with it!
+		 */
+		if (node->prefix != NULL)
+			_deref_prefix(radix->mctx, node->prefix);
+
+		node->prefix = NULL;
+		node->data[0] = node->data[1] = NULL;
+		return;
+	}
+
+	if (node->r == NULL && node->l == NULL) {
+		parent = node->parent;
+		_deref_prefix(radix->mctx, node->prefix);
+		isc_mem_put(radix->mctx, node, sizeof(*node));
+		radix->num_active_node--;
+
+		if (parent == NULL) {
+			INSIST(radix->head == node);
+			radix->head = NULL;
+			return;
+		}
+
+		if (parent->r == node) {
+			parent->r = NULL;
+			child = parent->l;
+		} else {
+			INSIST(parent->l == node);
+			parent->l = NULL;
+			child = parent->r;
+		}
+
+		if (parent->prefix)
+			return;
+
+		/* We need to remove parent too. */
+
+		if (parent->parent == NULL) {
+			INSIST(radix->head == parent);
+			radix->head = child;
+		} else if (parent->parent->r == parent) {
+			parent->parent->r = child;
+		} else {
+			INSIST(parent->parent->l == parent);
+			parent->parent->l = child;
+		}
+		child->parent = parent->parent;
+		isc_mem_put(radix->mctx, parent, sizeof(*parent));
+		radix->num_active_node--;
+		return;
+	}
+
+	if (node->r) {
+		child = node->r;
+	} else {
+		INSIST(node->l != NULL);
+		child = node->l;
+	}
+	parent = node->parent;
+	child->parent = parent;
+
+	_deref_prefix(radix->mctx, node->prefix);
+	isc_mem_put(radix->mctx, node, sizeof(*node));
+	radix->num_active_node--;
+
+	if (parent == NULL) {
+		INSIST(radix->head == node);
+		radix->head = child;
+		return;
+	}
+
+	if (parent->r == node) {
+		parent->r = child;
+	} else {
+		INSIST(parent->l == node);
+		parent->l = child;
+	}
+}
+
+/*
+Local Variables:
+c-basic-offset: 4
+indent-tabs-mode: t
+End:
+*/
diff --git a/src/lib/bind9/random.c b/src/lib/bind9/random.c
new file mode 100644
index 0000000..f082fe6
--- /dev/null
+++ b/src/lib/bind9/random.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: random.c,v 1.28 2009-07-16 05:52:46 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <time.h>		/* Required for time(). */
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <isc/mutex.h>
+#include <isc/once.h>
+#include <isc/random.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+static isc_once_t once = ISC_ONCE_INIT;
+
+static void
+initialize_rand(void)
+{
+#ifndef HAVE_ARC4RANDOM
+	unsigned int pid = getpid();
+
+	/*
+	 * The low bits of pid generally change faster.
+	 * Xor them with the high bits of time which change slowly.
+	 */
+	pid = ((pid << 16) & 0xffff0000) | ((pid >> 16) & 0xffff);
+
+	srand(time(NULL) ^ pid);
+#endif
+}
+
+static void
+initialize(void)
+{
+	RUNTIME_CHECK(isc_once_do(&once, initialize_rand) == ISC_R_SUCCESS);
+}
+
+void
+isc_random_seed(isc_uint32_t seed)
+{
+	initialize();
+
+#ifndef HAVE_ARC4RANDOM
+	srand(seed);
+#else
+	arc4random_addrandom((u_char *) &seed, sizeof(isc_uint32_t));
+#endif
+}
+
+void
+isc_random_get(isc_uint32_t *val)
+{
+	REQUIRE(val != NULL);
+
+	initialize();
+
+#ifndef HAVE_ARC4RANDOM
+	/*
+	 * rand()'s lower bits are not random.
+	 * rand()'s upper bit is zero.
+	 */
+#if RAND_MAX >= 0xfffff
+	/* We have at least 20 bits.  Use lower 16 excluding lower most 4 */
+	*val = ((rand() >> 4) & 0xffff) | ((rand() << 12) & 0xffff0000);
+#elif RAND_MAX >= 0x7fff
+	/* We have at least 15 bits.  Use lower 10/11 excluding lower most 4 */
+	*val = ((rand() >> 4) & 0x000007ff) | ((rand() << 7) & 0x003ff800) |
+		((rand() << 18) & 0xffc00000);
+#else
+#error RAND_MAX is too small
+#endif
+#else
+	*val = arc4random();
+#endif
+}
+
+isc_uint32_t
+isc_random_jitter(isc_uint32_t max, isc_uint32_t jitter) {
+	isc_uint32_t rnd;
+
+	REQUIRE(jitter < max || (jitter == 0 && max == 0));
+
+	if (jitter == 0)
+		return (max);
+
+	isc_random_get(&rnd);
+	return (max - rnd % jitter);
+}
diff --git a/src/lib/bind9/ratelimiter.c b/src/lib/bind9/ratelimiter.c
new file mode 100644
index 0000000..2bd3c9c
--- /dev/null
+++ b/src/lib/bind9/ratelimiter.c
@@ -0,0 +1,328 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: ratelimiter.c,v 1.25 2007-06-19 23:47:17 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/mem.h>
+#include <isc/ratelimiter.h>
+#include <isc/task.h>
+#include <isc/time.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+typedef enum {
+	isc_ratelimiter_stalled = 0,
+	isc_ratelimiter_ratelimited = 1,
+	isc_ratelimiter_idle = 2,
+	isc_ratelimiter_shuttingdown = 3
+} isc_ratelimiter_state_t;
+
+struct isc_ratelimiter {
+	isc_mem_t *		mctx;
+	isc_mutex_t		lock;
+	int			refs;
+	isc_task_t *		task;
+	isc_timer_t *		timer;
+	isc_interval_t		interval;
+	isc_uint32_t		pertic;
+	isc_ratelimiter_state_t	state;
+	isc_event_t		shutdownevent;
+	ISC_LIST(isc_event_t)	pending;
+};
+
+#define ISC_RATELIMITEREVENT_SHUTDOWN (ISC_EVENTCLASS_RATELIMITER + 1)
+
+static void
+ratelimiter_tick(isc_task_t *task, isc_event_t *event);
+
+static void
+ratelimiter_shutdowncomplete(isc_task_t *task, isc_event_t *event);
+
+isc_result_t
+isc_ratelimiter_create(isc_mem_t *mctx, isc_timermgr_t *timermgr,
+		       isc_task_t *task, isc_ratelimiter_t **ratelimiterp)
+{
+	isc_result_t result;
+	isc_ratelimiter_t *rl;
+	INSIST(ratelimiterp != NULL && *ratelimiterp == NULL);
+
+	rl = isc_mem_get(mctx, sizeof(*rl));
+	if (rl == NULL)
+		return ISC_R_NOMEMORY;
+	rl->mctx = mctx;
+	rl->refs = 1;
+	rl->task = task;
+	isc_interval_set(&rl->interval, 0, 0);
+	rl->timer = NULL;
+	rl->pertic = 1;
+	rl->state = isc_ratelimiter_idle;
+	ISC_LIST_INIT(rl->pending);
+
+	result = isc_mutex_init(&rl->lock);
+	if (result != ISC_R_SUCCESS)
+		goto free_mem;
+	result = isc_timer_create(timermgr, isc_timertype_inactive,
+				  NULL, NULL, rl->task, ratelimiter_tick,
+				  rl, &rl->timer);
+	if (result != ISC_R_SUCCESS)
+		goto free_mutex;
+
+	/*
+	 * Increment the reference count to indicate that we may
+	 * (soon) have events outstanding.
+	 */
+	rl->refs++;
+
+	ISC_EVENT_INIT(&rl->shutdownevent,
+		       sizeof(isc_event_t),
+		       0, NULL, ISC_RATELIMITEREVENT_SHUTDOWN,
+		       ratelimiter_shutdowncomplete, rl, rl, NULL, NULL);
+
+	*ratelimiterp = rl;
+	return (ISC_R_SUCCESS);
+
+free_mutex:
+	DESTROYLOCK(&rl->lock);
+free_mem:
+	isc_mem_put(mctx, rl, sizeof(*rl));
+	return (result);
+}
+
+isc_result_t
+isc_ratelimiter_setinterval(isc_ratelimiter_t *rl, isc_interval_t *interval) {
+	isc_result_t result = ISC_R_SUCCESS;
+	LOCK(&rl->lock);
+	rl->interval = *interval;
+	/*
+	 * If the timer is currently running, change its rate.
+	 */
+        if (rl->state == isc_ratelimiter_ratelimited) {
+		result = isc_timer_reset(rl->timer, isc_timertype_ticker, NULL,
+					 &rl->interval, ISC_FALSE);
+	}
+	UNLOCK(&rl->lock);
+	return (result);
+}
+
+void
+isc_ratelimiter_setpertic(isc_ratelimiter_t *rl, isc_uint32_t pertic) {
+	if (pertic == 0)
+		pertic = 1;
+	rl->pertic = pertic;
+}
+
+isc_result_t
+isc_ratelimiter_enqueue(isc_ratelimiter_t *rl, isc_task_t *task,
+			isc_event_t **eventp)
+{
+	isc_result_t result = ISC_R_SUCCESS;
+	isc_event_t *ev;
+
+	REQUIRE(eventp != NULL && *eventp != NULL);
+	REQUIRE(task != NULL);
+	ev = *eventp;
+	REQUIRE(ev->ev_sender == NULL);
+
+	LOCK(&rl->lock);
+        if (rl->state == isc_ratelimiter_ratelimited ||
+	    rl->state == isc_ratelimiter_stalled) {
+		isc_event_t *ev = *eventp;
+		ev->ev_sender = task;
+                ISC_LIST_APPEND(rl->pending, ev, ev_link);
+		*eventp = NULL;
+        } else if (rl->state == isc_ratelimiter_idle) {
+		result = isc_timer_reset(rl->timer, isc_timertype_ticker, NULL,
+					 &rl->interval, ISC_FALSE);
+		if (result == ISC_R_SUCCESS) {
+			ev->ev_sender = task;
+			rl->state = isc_ratelimiter_ratelimited;
+		}
+	} else {
+		INSIST(rl->state == isc_ratelimiter_shuttingdown);
+		result = ISC_R_SHUTTINGDOWN;
+	}
+	UNLOCK(&rl->lock);
+	if (*eventp != NULL && result == ISC_R_SUCCESS)
+		isc_task_send(task, eventp);
+	return (result);
+}
+
+static void
+ratelimiter_tick(isc_task_t *task, isc_event_t *event) {
+	isc_result_t result = ISC_R_SUCCESS;
+	isc_ratelimiter_t *rl = (isc_ratelimiter_t *)event->ev_arg;
+	isc_event_t *p;
+	isc_uint32_t pertic;
+
+	UNUSED(task);
+
+	isc_event_free(&event);
+
+	pertic = rl->pertic;
+        while (pertic != 0) {
+		pertic--;
+		LOCK(&rl->lock);
+		p = ISC_LIST_HEAD(rl->pending);
+		if (p != NULL) {
+			/*
+			 * There is work to do.  Let's do it after unlocking.
+			 */
+			ISC_LIST_UNLINK(rl->pending, p, ev_link);
+		} else {
+			/*
+			 * No work left to do.  Stop the timer so that we don't
+			 * waste resources by having it fire periodically.
+			 */
+			result = isc_timer_reset(rl->timer,
+						 isc_timertype_inactive,
+						 NULL, NULL, ISC_FALSE);
+			RUNTIME_CHECK(result == ISC_R_SUCCESS);
+			rl->state = isc_ratelimiter_idle;
+			pertic = 0;	/* Force the loop to exit. */
+		}
+		UNLOCK(&rl->lock);
+		if (p != NULL) {
+			isc_task_t *evtask = p->ev_sender;
+			isc_task_send(evtask, &p);
+		}
+		INSIST(p == NULL);
+	}
+}
+
+void
+isc_ratelimiter_shutdown(isc_ratelimiter_t *rl) {
+	isc_event_t *ev;
+	isc_task_t *task;
+	LOCK(&rl->lock);
+	rl->state = isc_ratelimiter_shuttingdown;
+	(void)isc_timer_reset(rl->timer, isc_timertype_inactive,
+			      NULL, NULL, ISC_FALSE);
+	while ((ev = ISC_LIST_HEAD(rl->pending)) != NULL) {
+		ISC_LIST_UNLINK(rl->pending, ev, ev_link);
+		ev->ev_attributes |= ISC_EVENTATTR_CANCELED;
+		task = ev->ev_sender;
+		isc_task_send(task, &ev);
+	}
+	isc_timer_detach(&rl->timer);
+	/*
+	 * Send an event to our task.  The delivery of this event
+	 * indicates that no more timer events will be delivered.
+	 */
+	ev = &rl->shutdownevent;
+	isc_task_send(rl->task, &ev);
+
+	UNLOCK(&rl->lock);
+}
+
+static void
+ratelimiter_shutdowncomplete(isc_task_t *task, isc_event_t *event) {
+	isc_ratelimiter_t *rl = (isc_ratelimiter_t *)event->ev_arg;
+
+	UNUSED(task);
+
+	isc_ratelimiter_detach(&rl);
+}
+
+static void
+ratelimiter_free(isc_ratelimiter_t *rl) {
+	DESTROYLOCK(&rl->lock);
+	isc_mem_put(rl->mctx, rl, sizeof(*rl));
+}
+
+void
+isc_ratelimiter_attach(isc_ratelimiter_t *source, isc_ratelimiter_t **target) {
+	REQUIRE(source != NULL);
+	REQUIRE(target != NULL && *target == NULL);
+
+	LOCK(&source->lock);
+	REQUIRE(source->refs > 0);
+	source->refs++;
+	INSIST(source->refs > 0);
+	UNLOCK(&source->lock);
+	*target = source;
+}
+
+void
+isc_ratelimiter_detach(isc_ratelimiter_t **rlp) {
+	isc_ratelimiter_t *rl = *rlp;
+	isc_boolean_t free_now = ISC_FALSE;
+
+	LOCK(&rl->lock);
+	REQUIRE(rl->refs > 0);
+	rl->refs--;
+	if (rl->refs == 0)
+		free_now = ISC_TRUE;
+	UNLOCK(&rl->lock);
+
+	if (free_now)
+		ratelimiter_free(rl);
+
+	*rlp = NULL;
+}
+
+isc_result_t
+isc_ratelimiter_stall(isc_ratelimiter_t *rl) {
+	isc_result_t result = ISC_R_SUCCESS;
+
+	LOCK(&rl->lock);
+	switch (rl->state) {
+	case isc_ratelimiter_shuttingdown:
+		result = ISC_R_SHUTTINGDOWN;
+		break;
+	case isc_ratelimiter_ratelimited:
+		result = isc_timer_reset(rl->timer, isc_timertype_inactive,
+				 	 NULL, NULL, ISC_FALSE);
+		RUNTIME_CHECK(result == ISC_R_SUCCESS);
+	case isc_ratelimiter_idle:
+	case isc_ratelimiter_stalled:
+		rl->state = isc_ratelimiter_stalled;
+		break;
+	}
+	UNLOCK(&rl->lock);
+	return (result);
+}
+
+isc_result_t
+isc_ratelimiter_release(isc_ratelimiter_t *rl) {
+	isc_result_t result = ISC_R_SUCCESS;
+
+	LOCK(&rl->lock);
+	switch (rl->state) {
+	case isc_ratelimiter_shuttingdown:
+		result = ISC_R_SHUTTINGDOWN;
+		break;
+	case isc_ratelimiter_stalled:
+		if (!ISC_LIST_EMPTY(rl->pending)) {
+			result = isc_timer_reset(rl->timer,
+						 isc_timertype_ticker, NULL,
+						 &rl->interval, ISC_FALSE);
+			if (result == ISC_R_SUCCESS)
+				rl->state = isc_ratelimiter_ratelimited;
+		} else 
+			rl->state = isc_ratelimiter_idle;
+		break;
+	case isc_ratelimiter_ratelimited:
+	case isc_ratelimiter_idle:
+		break;
+	}
+	UNLOCK(&rl->lock);
+	return (result);
+}
diff --git a/src/lib/bind9/refcount.c b/src/lib/bind9/refcount.c
new file mode 100644
index 0000000..3bef1be
--- /dev/null
+++ b/src/lib/bind9/refcount.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: refcount.c,v 1.5 2007-06-19 23:47:17 tbox Exp $ */
+
+#include <config.h>
+
+#include <stddef.h>
+
+#include <isc/mutex.h>
+#include <isc/refcount.h>
+#include <isc/result.h>
+
+isc_result_t
+isc_refcount_init(isc_refcount_t *ref, unsigned int n) {
+	REQUIRE(ref != NULL);
+
+	ref->refs = n;
+#if defined(ISC_PLATFORM_USETHREADS) && !defined(ISC_PLATFORM_HAVEXADD)
+	return (isc_mutex_init(&ref->lock));
+#else
+	return (ISC_R_SUCCESS);
+#endif
+}
diff --git a/src/lib/bind9/region.c b/src/lib/bind9/region.c
new file mode 100644
index 0000000..72973be
--- /dev/null
+++ b/src/lib/bind9/region.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2002  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: region.c,v 1.7 2007-06-19 23:47:17 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/region.h>
+#include <isc/util.h>
+
+int
+isc_region_compare(isc_region_t *r1, isc_region_t *r2) {
+	unsigned int l;
+	int result;
+
+	REQUIRE(r1 != NULL);
+	REQUIRE(r2 != NULL);
+	       
+	l = (r1->length < r2->length) ? r1->length : r2->length;
+
+	if ((result = memcmp(r1->base, r2->base, l)) != 0)
+		return ((result < 0) ? -1 : 1);
+	else
+		return ((r1->length == r2->length) ? 0 :
+			(r1->length < r2->length) ? -1 : 1);
+}
diff --git a/src/lib/bind9/result.c b/src/lib/bind9/result.c
new file mode 100644
index 0000000..fcb5295
--- /dev/null
+++ b/src/lib/bind9/result.c
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2008  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2001, 2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: result.c,v 1.71 2008-09-25 04:02:39 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#include <isc/lib.h>
+#include <isc/msgs.h>
+#include <isc/mutex.h>
+#include <isc/once.h>
+#include <isc/resultclass.h>
+#include <isc/util.h>
+
+typedef struct resulttable {
+	unsigned int				base;
+	unsigned int				last;
+	const char **				text;
+	isc_msgcat_t *				msgcat;
+	int					set;
+	ISC_LINK(struct resulttable)		link;
+} resulttable;
+
+static const char *text[ISC_R_NRESULTS] = {
+	"success",				/*%< 0 */
+	"out of memory",			/*%< 1 */
+	"timed out",				/*%< 2 */
+	"no available threads",			/*%< 3 */
+	"address not available",		/*%< 4 */
+	"address in use",			/*%< 5 */
+	"permission denied",			/*%< 6 */
+	"no pending connections",		/*%< 7 */
+	"network unreachable",			/*%< 8 */
+	"host unreachable",			/*%< 9 */
+	"network down",				/*%< 10 */
+	"host down",				/*%< 11 */
+	"connection refused",			/*%< 12 */
+	"not enough free resources",		/*%< 13 */
+	"end of file",				/*%< 14 */
+	"socket already bound",			/*%< 15 */
+	"reload",				/*%< 16 */
+	"lock busy",				/*%< 17 */
+	"already exists",			/*%< 18 */
+	"ran out of space",			/*%< 19 */
+	"operation canceled",			/*%< 20 */
+	"socket is not bound",			/*%< 21 */
+	"shutting down",			/*%< 22 */
+	"not found",				/*%< 23 */
+	"unexpected end of input",		/*%< 24 */
+	"failure",				/*%< 25 */
+	"I/O error",				/*%< 26 */
+	"not implemented",			/*%< 27 */
+	"unbalanced parentheses",		/*%< 28 */
+	"no more",				/*%< 29 */
+	"invalid file",				/*%< 30 */
+	"bad base64 encoding",			/*%< 31 */
+	"unexpected token",			/*%< 32 */
+	"quota reached",			/*%< 33 */
+	"unexpected error",			/*%< 34 */
+	"already running",			/*%< 35 */
+	"ignore",				/*%< 36 */
+	"address mask not contiguous",		/*%< 37 */
+	"file not found",			/*%< 38 */
+	"file already exists",			/*%< 39 */
+	"socket is not connected",		/*%< 40 */
+	"out of range",				/*%< 41 */
+	"out of entropy",			/*%< 42 */
+	"invalid use of multicast address",	/*%< 43 */
+	"not a file",				/*%< 44 */
+	"not a directory",			/*%< 45 */
+	"queue is full",			/*%< 46 */
+	"address family mismatch",		/*%< 47 */
+	"address family not supported",		/*%< 48 */
+	"bad hex encoding",			/*%< 49 */
+	"too many open files",			/*%< 50 */
+	"not blocking",				/*%< 51 */
+	"unbalanced quotes",			/*%< 52 */
+	"operation in progress",		/*%< 53 */
+	"connection reset",			/*%< 54 */
+	"soft quota reached",			/*%< 55 */
+	"not a valid number",			/*%< 56 */
+	"disabled",				/*%< 57 */
+	"max size",				/*%< 58 */
+	"invalid address format",		/*%< 59 */
+	"bad base32 encoding",			/*%< 60 */
+};
+
+#define ISC_RESULT_RESULTSET			2
+#define ISC_RESULT_UNAVAILABLESET		3
+
+static isc_once_t 				once = ISC_ONCE_INIT;
+static ISC_LIST(resulttable)			tables;
+static isc_mutex_t				lock;
+
+static isc_result_t
+register_table(unsigned int base, unsigned int nresults, const char **text,
+	       isc_msgcat_t *msgcat, int set)
+{
+	resulttable *table;
+
+	REQUIRE(base % ISC_RESULTCLASS_SIZE == 0);
+	REQUIRE(nresults <= ISC_RESULTCLASS_SIZE);
+	REQUIRE(text != NULL);
+
+	/*
+	 * We use malloc() here because we we want to be able to use
+	 * isc_result_totext() even if there is no memory context.
+	 */
+	table = malloc(sizeof(*table));
+	if (table == NULL)
+		return (ISC_R_NOMEMORY);
+	table->base = base;
+	table->last = base + nresults - 1;
+	table->text = text;
+	table->msgcat = msgcat;
+	table->set = set;
+	ISC_LINK_INIT(table, link);
+
+	LOCK(&lock);
+
+	ISC_LIST_APPEND(tables, table, link);
+
+	UNLOCK(&lock);
+
+	return (ISC_R_SUCCESS);
+}
+
+static void
+initialize_action(void) {
+	isc_result_t result;
+
+	RUNTIME_CHECK(isc_mutex_init(&lock) == ISC_R_SUCCESS);
+	ISC_LIST_INIT(tables);
+
+	result = register_table(ISC_RESULTCLASS_ISC, ISC_R_NRESULTS, text,
+				isc_msgcat, ISC_RESULT_RESULTSET);
+	if (result != ISC_R_SUCCESS)
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "register_table() %s: %u",
+				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+						ISC_MSG_FAILED, "failed"),
+				 result);
+}
+
+static void
+initialize(void) {
+	isc_lib_initmsgcat();
+	RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
+}
+
+const char *
+isc_result_totext(isc_result_t result) {
+	resulttable *table;
+	const char *text, *default_text;
+	int index;
+
+	initialize();
+
+	LOCK(&lock);
+
+	text = NULL;
+	for (table = ISC_LIST_HEAD(tables);
+	     table != NULL;
+	     table = ISC_LIST_NEXT(table, link)) {
+		if (result >= table->base && result <= table->last) {
+			index = (int)(result - table->base);
+			default_text = table->text[index];
+			/*
+			 * Note: we use 'index + 1' as the message number
+			 * instead of index because isc_msgcat_get() requires
+			 * the message number to be > 0.
+			 */
+			text = isc_msgcat_get(table->msgcat, table->set,
+					      index + 1, default_text);
+			break;
+		}
+	}
+	if (text == NULL)
+		text = isc_msgcat_get(isc_msgcat, ISC_RESULT_UNAVAILABLESET,
+				      1, "(result code text not available)");
+
+	UNLOCK(&lock);
+
+	return (text);
+}
+
+isc_result_t
+isc_result_register(unsigned int base, unsigned int nresults,
+		    const char **text, isc_msgcat_t *msgcat, int set)
+{
+	initialize();
+
+	return (register_table(base, nresults, text, msgcat, set));
+}
diff --git a/src/lib/bind9/rwlock.c b/src/lib/bind9/rwlock.c
new file mode 100644
index 0000000..5b37f9c
--- /dev/null
+++ b/src/lib/bind9/rwlock.c
@@ -0,0 +1,809 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2009, 2011  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2001, 2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: rwlock.c,v 1.46.426.2 2011-03-12 04:59:18 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stddef.h>
+
+#include <isc/atomic.h>
+#include <isc/magic.h>
+#include <isc/msgs.h>
+#include <isc/platform.h>
+#include <isc/rwlock.h>
+#include <isc/util.h>
+
+#define RWLOCK_MAGIC		ISC_MAGIC('R', 'W', 'L', 'k')
+#define VALID_RWLOCK(rwl)	ISC_MAGIC_VALID(rwl, RWLOCK_MAGIC)
+
+#ifdef ISC_PLATFORM_USETHREADS
+
+#ifndef RWLOCK_DEFAULT_READ_QUOTA
+#define RWLOCK_DEFAULT_READ_QUOTA 4
+#endif
+
+#ifndef RWLOCK_DEFAULT_WRITE_QUOTA
+#define RWLOCK_DEFAULT_WRITE_QUOTA 4
+#endif
+
+#ifdef ISC_RWLOCK_TRACE
+#include <stdio.h>		/* Required for fprintf/stderr. */
+#include <isc/thread.h>		/* Required for isc_thread_self(). */
+
+static void
+print_lock(const char *operation, isc_rwlock_t *rwl, isc_rwlocktype_t type) {
+	fprintf(stderr,
+		isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
+			       ISC_MSG_PRINTLOCK,
+			       "rwlock %p thread %lu %s(%s): %s, %u active, "
+			       "%u granted, %u rwaiting, %u wwaiting\n"),
+		rwl, isc_thread_self(), operation,
+		(type == isc_rwlocktype_read ?
+		 isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
+				ISC_MSG_READ, "read") :
+		 isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
+				ISC_MSG_WRITE, "write")),
+		(rwl->type == isc_rwlocktype_read ?
+		 isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
+				ISC_MSG_READING, "reading") :
+		 isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
+				ISC_MSG_WRITING, "writing")),
+		rwl->active, rwl->granted, rwl->readers_waiting,
+		rwl->writers_waiting);
+}
+#endif
+
+isc_result_t
+isc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota,
+		unsigned int write_quota)
+{
+	isc_result_t result;
+
+	REQUIRE(rwl != NULL);
+
+	/*
+	 * In case there's trouble initializing, we zero magic now.  If all
+	 * goes well, we'll set it to RWLOCK_MAGIC.
+	 */
+	rwl->magic = 0;
+
+#if defined(ISC_PLATFORM_HAVEXADD) && defined(ISC_PLATFORM_HAVECMPXCHG)
+	rwl->write_requests = 0;
+	rwl->write_completions = 0;
+	rwl->cnt_and_flag = 0;
+	rwl->readers_waiting = 0;
+	rwl->write_granted = 0;
+	if (read_quota != 0) {
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "read quota is not supported");
+	}
+	if (write_quota == 0)
+		write_quota = RWLOCK_DEFAULT_WRITE_QUOTA;
+	rwl->write_quota = write_quota;
+#else
+	rwl->type = isc_rwlocktype_read;
+	rwl->original = isc_rwlocktype_none;
+	rwl->active = 0;
+	rwl->granted = 0;
+	rwl->readers_waiting = 0;
+	rwl->writers_waiting = 0;
+	if (read_quota == 0)
+		read_quota = RWLOCK_DEFAULT_READ_QUOTA;
+	rwl->read_quota = read_quota;
+	if (write_quota == 0)
+		write_quota = RWLOCK_DEFAULT_WRITE_QUOTA;
+	rwl->write_quota = write_quota;
+#endif
+
+	result = isc_mutex_init(&rwl->lock);
+	if (result != ISC_R_SUCCESS)
+		return (result);
+
+	result = isc_condition_init(&rwl->readable);
+	if (result != ISC_R_SUCCESS) {
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "isc_condition_init(readable) %s: %s",
+				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+						ISC_MSG_FAILED, "failed"),
+				 isc_result_totext(result));
+		result = ISC_R_UNEXPECTED;
+		goto destroy_lock;
+	}
+	result = isc_condition_init(&rwl->writeable);
+	if (result != ISC_R_SUCCESS) {
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "isc_condition_init(writeable) %s: %s",
+				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+						ISC_MSG_FAILED, "failed"),
+				 isc_result_totext(result));
+		result = ISC_R_UNEXPECTED;
+		goto destroy_rcond;
+	}
+
+	rwl->magic = RWLOCK_MAGIC;
+
+	return (ISC_R_SUCCESS);
+
+  destroy_rcond:
+	(void)isc_condition_destroy(&rwl->readable);
+  destroy_lock:
+	DESTROYLOCK(&rwl->lock);
+
+	return (result);
+}
+
+void
+isc_rwlock_destroy(isc_rwlock_t *rwl) {
+	REQUIRE(VALID_RWLOCK(rwl));
+
+#if defined(ISC_PLATFORM_HAVEXADD) && defined(ISC_PLATFORM_HAVECMPXCHG)
+	REQUIRE(rwl->write_requests == rwl->write_completions &&
+		rwl->cnt_and_flag == 0 && rwl->readers_waiting == 0);
+#else
+	LOCK(&rwl->lock);
+	REQUIRE(rwl->active == 0 &&
+		rwl->readers_waiting == 0 &&
+		rwl->writers_waiting == 0);
+	UNLOCK(&rwl->lock);
+#endif
+
+	rwl->magic = 0;
+	(void)isc_condition_destroy(&rwl->readable);
+	(void)isc_condition_destroy(&rwl->writeable);
+	DESTROYLOCK(&rwl->lock);
+}
+
+#if defined(ISC_PLATFORM_HAVEXADD) && defined(ISC_PLATFORM_HAVECMPXCHG)
+
+/*
+ * When some architecture-dependent atomic operations are available,
+ * rwlock can be more efficient than the generic algorithm defined below.
+ * The basic algorithm is described in the following URL:
+ *   http://www.cs.rochester.edu/u/scott/synchronization/pseudocode/rw.html
+ *
+ * The key is to use the following integer variables modified atomically:
+ *   write_requests, write_completions, and cnt_and_flag.
+ *
+ * write_requests and write_completions act as a waiting queue for writers
+ * in order to ensure the FIFO order.  Both variables begin with the initial
+ * value of 0.  When a new writer tries to get a write lock, it increments
+ * write_requests and gets the previous value of the variable as a "ticket".
+ * When write_completions reaches the ticket number, the new writer can start
+ * writing.  When the writer completes its work, it increments
+ * write_completions so that another new writer can start working.  If the
+ * write_requests is not equal to write_completions, it means a writer is now
+ * working or waiting.  In this case, a new readers cannot start reading, or
+ * in other words, this algorithm basically prefers writers.
+ *
+ * cnt_and_flag is a "lock" shared by all readers and writers.  This integer
+ * variable is a kind of structure with two members: writer_flag (1 bit) and
+ * reader_count (31 bits).  The writer_flag shows whether a writer is working,
+ * and the reader_count shows the number of readers currently working or almost
+ * ready for working.  A writer who has the current "ticket" tries to get the
+ * lock by exclusively setting the writer_flag to 1, provided that the whole
+ * 32-bit is 0 (meaning no readers or writers working).  On the other hand,
+ * a new reader tries to increment the "reader_count" field provided that
+ * the writer_flag is 0 (meaning there is no writer working).
+ *
+ * If some of the above operations fail, the reader or the writer sleeps
+ * until the related condition changes.  When a working reader or writer
+ * completes its work, some readers or writers are sleeping, and the condition
+ * that suspended the reader or writer has changed, it wakes up the sleeping
+ * readers or writers.
+ *
+ * As already noted, this algorithm basically prefers writers.  In order to
+ * prevent readers from starving, however, the algorithm also introduces the
+ * "writer quota" (Q).  When Q consecutive writers have completed their work,
+ * suspending readers, the last writer will wake up the readers, even if a new
+ * writer is waiting.
+ *
+ * Implementation specific note: due to the combination of atomic operations
+ * and a mutex lock, ordering between the atomic operation and locks can be
+ * very sensitive in some cases.  In particular, it is generally very important
+ * to check the atomic variable that requires a reader or writer to sleep after
+ * locking the mutex and before actually sleeping; otherwise, it could be very
+ * likely to cause a deadlock.  For example, assume "var" is a variable
+ * atomically modified, then the corresponding code would be:
+ *	if (var == need_sleep) {
+ *		LOCK(lock);
+ *		if (var == need_sleep)
+ *			WAIT(cond, lock);
+ *		UNLOCK(lock);
+ *	}
+ * The second check is important, since "var" is protected by the atomic
+ * operation, not by the mutex, and can be changed just before sleeping.
+ * (The first "if" could be omitted, but this is also important in order to
+ * make the code efficient by avoiding the use of the mutex unless it is
+ * really necessary.)
+ */
+
+#define WRITER_ACTIVE	0x1
+#define READER_INCR	0x2
+
+isc_result_t
+isc_rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
+	isc_int32_t cntflag;
+
+	REQUIRE(VALID_RWLOCK(rwl));
+
+#ifdef ISC_RWLOCK_TRACE
+	print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
+				  ISC_MSG_PRELOCK, "prelock"), rwl, type);
+#endif
+
+	if (type == isc_rwlocktype_read) {
+		if (rwl->write_requests != rwl->write_completions) {
+			/* there is a waiting or active writer */
+			LOCK(&rwl->lock);
+			if (rwl->write_requests != rwl->write_completions) {
+				rwl->readers_waiting++;
+				WAIT(&rwl->readable, &rwl->lock);
+				rwl->readers_waiting--;
+			}
+			UNLOCK(&rwl->lock);
+		}
+
+		cntflag = isc_atomic_xadd(&rwl->cnt_and_flag, READER_INCR);
+		POST(cntflag);
+		while (1) {
+			if ((rwl->cnt_and_flag & WRITER_ACTIVE) == 0)
+				break;
+
+			/* A writer is still working */
+			LOCK(&rwl->lock);
+			rwl->readers_waiting++;
+			if ((rwl->cnt_and_flag & WRITER_ACTIVE) != 0)
+				WAIT(&rwl->readable, &rwl->lock);
+			rwl->readers_waiting--;
+			UNLOCK(&rwl->lock);
+
+			/*
+			 * Typically, the reader should be able to get a lock
+			 * at this stage:
+			 *   (1) there should have been no pending writer when
+			 *       the reader was trying to increment the
+			 *       counter; otherwise, the writer should be in
+			 *       the waiting queue, preventing the reader from
+			 *       proceeding to this point.
+			 *   (2) once the reader increments the counter, no
+			 *       more writer can get a lock.
+			 * Still, it is possible another writer can work at
+			 * this point, e.g. in the following scenario:
+			 *   A previous writer unlocks the writer lock.
+			 *   This reader proceeds to point (1).
+			 *   A new writer appears, and gets a new lock before
+			 *   the reader increments the counter.
+			 *   The reader then increments the counter.
+			 *   The previous writer notices there is a waiting
+			 *   reader who is almost ready, and wakes it up.
+			 * So, the reader needs to confirm whether it can now
+			 * read explicitly (thus we loop).  Note that this is
+			 * not an infinite process, since the reader has
+			 * incremented the counter at this point.
+			 */
+		}
+
+		/*
+		 * If we are temporarily preferred to writers due to the writer
+		 * quota, reset the condition (race among readers doesn't
+		 * matter).
+		 */
+		rwl->write_granted = 0;
+	} else {
+		isc_int32_t prev_writer;
+
+		/* enter the waiting queue, and wait for our turn */
+		prev_writer = isc_atomic_xadd(&rwl->write_requests, 1);
+		while (rwl->write_completions != prev_writer) {
+			LOCK(&rwl->lock);
+			if (rwl->write_completions != prev_writer) {
+				WAIT(&rwl->writeable, &rwl->lock);
+				UNLOCK(&rwl->lock);
+				continue;
+			}
+			UNLOCK(&rwl->lock);
+			break;
+		}
+
+		while (1) {
+			cntflag = isc_atomic_cmpxchg(&rwl->cnt_and_flag, 0,
+						     WRITER_ACTIVE);
+			if (cntflag == 0)
+				break;
+
+			/* Another active reader or writer is working. */
+			LOCK(&rwl->lock);
+			if (rwl->cnt_and_flag != 0)
+				WAIT(&rwl->writeable, &rwl->lock);
+			UNLOCK(&rwl->lock);
+		}
+
+		INSIST((rwl->cnt_and_flag & WRITER_ACTIVE) != 0);
+		rwl->write_granted++;
+	}
+
+#ifdef ISC_RWLOCK_TRACE
+	print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
+				  ISC_MSG_POSTLOCK, "postlock"), rwl, type);
+#endif
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_rwlock_trylock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
+	isc_int32_t cntflag;
+
+	REQUIRE(VALID_RWLOCK(rwl));
+
+#ifdef ISC_RWLOCK_TRACE
+	print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
+				  ISC_MSG_PRELOCK, "prelock"), rwl, type);
+#endif
+
+	if (type == isc_rwlocktype_read) {
+		/* If a writer is waiting or working, we fail. */
+		if (rwl->write_requests != rwl->write_completions)
+			return (ISC_R_LOCKBUSY);
+
+		/* Otherwise, be ready for reading. */
+		cntflag = isc_atomic_xadd(&rwl->cnt_and_flag, READER_INCR);
+		if ((cntflag & WRITER_ACTIVE) != 0) {
+			/*
+			 * A writer is working.  We lose, and cancel the read
+			 * request.
+			 */
+			cntflag = isc_atomic_xadd(&rwl->cnt_and_flag,
+						  -READER_INCR);
+			/*
+			 * If no other readers are waiting and we've suspended
+			 * new writers in this short period, wake them up.
+			 */
+			if (cntflag == READER_INCR &&
+			    rwl->write_completions != rwl->write_requests) {
+				LOCK(&rwl->lock);
+				BROADCAST(&rwl->writeable);
+				UNLOCK(&rwl->lock);
+			}
+
+			return (ISC_R_LOCKBUSY);
+		}
+	} else {
+		/* Try locking without entering the waiting queue. */
+		cntflag = isc_atomic_cmpxchg(&rwl->cnt_and_flag, 0,
+					     WRITER_ACTIVE);
+		if (cntflag != 0)
+			return (ISC_R_LOCKBUSY);
+
+		/*
+		 * XXXJT: jump into the queue, possibly breaking the writer
+		 * order.
+		 */
+		(void)isc_atomic_xadd(&rwl->write_completions, -1);
+
+		rwl->write_granted++;
+	}
+
+#ifdef ISC_RWLOCK_TRACE
+	print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
+				  ISC_MSG_POSTLOCK, "postlock"), rwl, type);
+#endif
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_rwlock_tryupgrade(isc_rwlock_t *rwl) {
+	isc_int32_t prevcnt;
+
+	REQUIRE(VALID_RWLOCK(rwl));
+
+	/* Try to acquire write access. */
+	prevcnt = isc_atomic_cmpxchg(&rwl->cnt_and_flag,
+				     READER_INCR, WRITER_ACTIVE);
+	/*
+	 * There must have been no writer, and there must have been at least
+	 * one reader.
+	 */
+	INSIST((prevcnt & WRITER_ACTIVE) == 0 &&
+	       (prevcnt & ~WRITER_ACTIVE) != 0);
+
+	if (prevcnt == READER_INCR) {
+		/*
+		 * We are the only reader and have been upgraded.
+		 * Now jump into the head of the writer waiting queue.
+		 */
+		(void)isc_atomic_xadd(&rwl->write_completions, -1);
+	} else
+		return (ISC_R_LOCKBUSY);
+
+	return (ISC_R_SUCCESS);
+
+}
+
+void
+isc_rwlock_downgrade(isc_rwlock_t *rwl) {
+	isc_int32_t prev_readers;
+
+	REQUIRE(VALID_RWLOCK(rwl));
+
+	/* Become an active reader. */
+	prev_readers = isc_atomic_xadd(&rwl->cnt_and_flag, READER_INCR);
+	/* We must have been a writer. */
+	INSIST((prev_readers & WRITER_ACTIVE) != 0);
+
+	/* Complete write */
+	(void)isc_atomic_xadd(&rwl->cnt_and_flag, -WRITER_ACTIVE);
+	(void)isc_atomic_xadd(&rwl->write_completions, 1);
+
+	/* Resume other readers */
+	LOCK(&rwl->lock);
+	if (rwl->readers_waiting > 0)
+		BROADCAST(&rwl->readable);
+	UNLOCK(&rwl->lock);
+}
+
+isc_result_t
+isc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
+	isc_int32_t prev_cnt;
+
+	REQUIRE(VALID_RWLOCK(rwl));
+
+#ifdef ISC_RWLOCK_TRACE
+	print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
+				  ISC_MSG_PREUNLOCK, "preunlock"), rwl, type);
+#endif
+
+	if (type == isc_rwlocktype_read) {
+		prev_cnt = isc_atomic_xadd(&rwl->cnt_and_flag, -READER_INCR);
+
+		/*
+		 * If we're the last reader and any writers are waiting, wake
+		 * them up.  We need to wake up all of them to ensure the
+		 * FIFO order.
+		 */
+		if (prev_cnt == READER_INCR &&
+		    rwl->write_completions != rwl->write_requests) {
+			LOCK(&rwl->lock);
+			BROADCAST(&rwl->writeable);
+			UNLOCK(&rwl->lock);
+		}
+	} else {
+		isc_boolean_t wakeup_writers = ISC_TRUE;
+
+		/*
+		 * Reset the flag, and (implicitly) tell other writers
+		 * we are done.
+		 */
+		(void)isc_atomic_xadd(&rwl->cnt_and_flag, -WRITER_ACTIVE);
+		(void)isc_atomic_xadd(&rwl->write_completions, 1);
+
+		if (rwl->write_granted >= rwl->write_quota ||
+		    rwl->write_requests == rwl->write_completions ||
+		    (rwl->cnt_and_flag & ~WRITER_ACTIVE) != 0) {
+			/*
+			 * We have passed the write quota, no writer is
+			 * waiting, or some readers are almost ready, pending
+			 * possible writers.  Note that the last case can
+			 * happen even if write_requests != write_completions
+			 * (which means a new writer in the queue), so we need
+			 * to catch the case explicitly.
+			 */
+			LOCK(&rwl->lock);
+			if (rwl->readers_waiting > 0) {
+				wakeup_writers = ISC_FALSE;
+				BROADCAST(&rwl->readable);
+			}
+			UNLOCK(&rwl->lock);
+		}
+
+		if (rwl->write_requests != rwl->write_completions &&
+		    wakeup_writers) {
+			LOCK(&rwl->lock);
+			BROADCAST(&rwl->writeable);
+			UNLOCK(&rwl->lock);
+		}
+	}
+
+#ifdef ISC_RWLOCK_TRACE
+	print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
+				  ISC_MSG_POSTUNLOCK, "postunlock"),
+		   rwl, type);
+#endif
+
+	return (ISC_R_SUCCESS);
+}
+
+#else /* ISC_PLATFORM_HAVEXADD && ISC_PLATFORM_HAVECMPXCHG */
+
+static isc_result_t
+doit(isc_rwlock_t *rwl, isc_rwlocktype_t type, isc_boolean_t nonblock) {
+	isc_boolean_t skip = ISC_FALSE;
+	isc_boolean_t done = ISC_FALSE;
+	isc_result_t result = ISC_R_SUCCESS;
+
+	REQUIRE(VALID_RWLOCK(rwl));
+
+	LOCK(&rwl->lock);
+
+#ifdef ISC_RWLOCK_TRACE
+	print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
+				  ISC_MSG_PRELOCK, "prelock"), rwl, type);
+#endif
+
+	if (type == isc_rwlocktype_read) {
+		if (rwl->readers_waiting != 0)
+			skip = ISC_TRUE;
+		while (!done) {
+			if (!skip &&
+			    ((rwl->active == 0 ||
+			      (rwl->type == isc_rwlocktype_read &&
+			       (rwl->writers_waiting == 0 ||
+				rwl->granted < rwl->read_quota)))))
+			{
+				rwl->type = isc_rwlocktype_read;
+				rwl->active++;
+				rwl->granted++;
+				done = ISC_TRUE;
+			} else if (nonblock) {
+				result = ISC_R_LOCKBUSY;
+				done = ISC_TRUE;
+			} else {
+				skip = ISC_FALSE;
+				rwl->readers_waiting++;
+				WAIT(&rwl->readable, &rwl->lock);
+				rwl->readers_waiting--;
+			}
+		}
+	} else {
+		if (rwl->writers_waiting != 0)
+			skip = ISC_TRUE;
+		while (!done) {
+			if (!skip && rwl->active == 0) {
+				rwl->type = isc_rwlocktype_write;
+				rwl->active = 1;
+				rwl->granted++;
+				done = ISC_TRUE;
+			} else if (nonblock) {
+				result = ISC_R_LOCKBUSY;
+				done = ISC_TRUE;
+			} else {
+				skip = ISC_FALSE;
+				rwl->writers_waiting++;
+				WAIT(&rwl->writeable, &rwl->lock);
+				rwl->writers_waiting--;
+			}
+		}
+	}
+
+#ifdef ISC_RWLOCK_TRACE
+	print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
+				  ISC_MSG_POSTLOCK, "postlock"), rwl, type);
+#endif
+
+	UNLOCK(&rwl->lock);
+
+	return (result);
+}
+
+isc_result_t
+isc_rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
+	return (doit(rwl, type, ISC_FALSE));
+}
+
+isc_result_t
+isc_rwlock_trylock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
+	return (doit(rwl, type, ISC_TRUE));
+}
+
+isc_result_t
+isc_rwlock_tryupgrade(isc_rwlock_t *rwl) {
+	isc_result_t result = ISC_R_SUCCESS;
+
+	REQUIRE(VALID_RWLOCK(rwl));
+	LOCK(&rwl->lock);
+	REQUIRE(rwl->type == isc_rwlocktype_read);
+	REQUIRE(rwl->active != 0);
+
+	/* If we are the only reader then succeed. */
+	if (rwl->active == 1) {
+		rwl->original = (rwl->original == isc_rwlocktype_none) ?
+				isc_rwlocktype_read : isc_rwlocktype_none;
+		rwl->type = isc_rwlocktype_write;
+	} else
+		result = ISC_R_LOCKBUSY;
+
+	UNLOCK(&rwl->lock);
+	return (result);
+}
+
+void
+isc_rwlock_downgrade(isc_rwlock_t *rwl) {
+
+	REQUIRE(VALID_RWLOCK(rwl));
+	LOCK(&rwl->lock);
+	REQUIRE(rwl->type == isc_rwlocktype_write);
+	REQUIRE(rwl->active == 1);
+
+	rwl->type = isc_rwlocktype_read;
+	rwl->original = (rwl->original == isc_rwlocktype_none) ?
+			isc_rwlocktype_write : isc_rwlocktype_none;
+	/*
+	 * Resume processing any read request that were blocked when
+	 * we upgraded.
+	 */
+	if (rwl->original == isc_rwlocktype_none &&
+	    (rwl->writers_waiting == 0 || rwl->granted < rwl->read_quota) &&
+	    rwl->readers_waiting > 0)
+		BROADCAST(&rwl->readable);
+
+	UNLOCK(&rwl->lock);
+}
+
+isc_result_t
+isc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
+
+	REQUIRE(VALID_RWLOCK(rwl));
+	LOCK(&rwl->lock);
+	REQUIRE(rwl->type == type);
+
+	UNUSED(type);
+
+#ifdef ISC_RWLOCK_TRACE
+	print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
+				  ISC_MSG_PREUNLOCK, "preunlock"), rwl, type);
+#endif
+
+	INSIST(rwl->active > 0);
+	rwl->active--;
+	if (rwl->active == 0) {
+		if (rwl->original != isc_rwlocktype_none) {
+			rwl->type = rwl->original;
+			rwl->original = isc_rwlocktype_none;
+		}
+		if (rwl->type == isc_rwlocktype_read) {
+			rwl->granted = 0;
+			if (rwl->writers_waiting > 0) {
+				rwl->type = isc_rwlocktype_write;
+				SIGNAL(&rwl->writeable);
+			} else if (rwl->readers_waiting > 0) {
+				/* Does this case ever happen? */
+				BROADCAST(&rwl->readable);
+			}
+		} else {
+			if (rwl->readers_waiting > 0) {
+				if (rwl->writers_waiting > 0 &&
+				    rwl->granted < rwl->write_quota) {
+					SIGNAL(&rwl->writeable);
+				} else {
+					rwl->granted = 0;
+					rwl->type = isc_rwlocktype_read;
+					BROADCAST(&rwl->readable);
+				}
+			} else if (rwl->writers_waiting > 0) {
+				rwl->granted = 0;
+				SIGNAL(&rwl->writeable);
+			} else {
+				rwl->granted = 0;
+			}
+		}
+	}
+	INSIST(rwl->original == isc_rwlocktype_none);
+
+#ifdef ISC_RWLOCK_TRACE
+	print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
+				  ISC_MSG_POSTUNLOCK, "postunlock"),
+		   rwl, type);
+#endif
+
+	UNLOCK(&rwl->lock);
+
+	return (ISC_R_SUCCESS);
+}
+
+#endif /* ISC_PLATFORM_HAVEXADD && ISC_PLATFORM_HAVECMPXCHG */
+#else /* ISC_PLATFORM_USETHREADS */
+
+isc_result_t
+isc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota,
+		unsigned int write_quota)
+{
+	REQUIRE(rwl != NULL);
+
+	UNUSED(read_quota);
+	UNUSED(write_quota);
+
+	rwl->type = isc_rwlocktype_read;
+	rwl->active = 0;
+	rwl->magic = RWLOCK_MAGIC;
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
+	REQUIRE(VALID_RWLOCK(rwl));
+
+	if (type == isc_rwlocktype_read) {
+		if (rwl->type != isc_rwlocktype_read && rwl->active != 0)
+			return (ISC_R_LOCKBUSY);
+		rwl->type = isc_rwlocktype_read;
+		rwl->active++;
+	} else {
+		if (rwl->active != 0)
+			return (ISC_R_LOCKBUSY);
+		rwl->type = isc_rwlocktype_write;
+		rwl->active = 1;
+	}
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_rwlock_trylock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
+	return (isc_rwlock_lock(rwl, type));
+}
+
+isc_result_t
+isc_rwlock_tryupgrade(isc_rwlock_t *rwl) {
+	isc_result_t result = ISC_R_SUCCESS;
+
+	REQUIRE(VALID_RWLOCK(rwl));
+	REQUIRE(rwl->type == isc_rwlocktype_read);
+	REQUIRE(rwl->active != 0);
+
+	/* If we are the only reader then succeed. */
+	if (rwl->active == 1)
+		rwl->type = isc_rwlocktype_write;
+	else
+		result = ISC_R_LOCKBUSY;
+	return (result);
+}
+
+void
+isc_rwlock_downgrade(isc_rwlock_t *rwl) {
+
+	REQUIRE(VALID_RWLOCK(rwl));
+	REQUIRE(rwl->type == isc_rwlocktype_write);
+	REQUIRE(rwl->active == 1);
+
+	rwl->type = isc_rwlocktype_read;
+}
+
+isc_result_t
+isc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
+	REQUIRE(VALID_RWLOCK(rwl));
+	REQUIRE(rwl->type == type);
+
+	UNUSED(type);
+
+	INSIST(rwl->active > 0);
+	rwl->active--;
+
+	return (ISC_R_SUCCESS);
+}
+
+void
+isc_rwlock_destroy(isc_rwlock_t *rwl) {
+	REQUIRE(rwl != NULL);
+	REQUIRE(rwl->active == 0);
+	rwl->magic = 0;
+}
+
+#endif /* ISC_PLATFORM_USETHREADS */
diff --git a/src/lib/bind9/serial.c b/src/lib/bind9/serial.c
new file mode 100644
index 0000000..0126d02
--- /dev/null
+++ b/src/lib/bind9/serial.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: serial.c,v 1.12 2007-06-19 23:47:17 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/serial.h>
+
+isc_boolean_t
+isc_serial_lt(isc_uint32_t a, isc_uint32_t b) {
+	/*
+	 * Undefined => ISC_FALSE
+	 */
+	if (a == (b ^ 0x80000000U))
+		return (ISC_FALSE);
+	return (((isc_int32_t)(a - b) < 0) ? ISC_TRUE : ISC_FALSE);
+}
+
+isc_boolean_t
+isc_serial_gt(isc_uint32_t a, isc_uint32_t b) {
+	return (((isc_int32_t)(a - b) > 0) ? ISC_TRUE : ISC_FALSE);
+}
+
+isc_boolean_t
+isc_serial_le(isc_uint32_t a, isc_uint32_t b) {
+	return ((a == b) ? ISC_TRUE : isc_serial_lt(a, b));
+}
+
+isc_boolean_t
+isc_serial_ge(isc_uint32_t a, isc_uint32_t b) {
+	return ((a == b) ? ISC_TRUE : isc_serial_gt(a, b));
+}
+
+isc_boolean_t
+isc_serial_eq(isc_uint32_t a, isc_uint32_t b) {
+	return ((a == b) ? ISC_TRUE : ISC_FALSE);
+}
+
+isc_boolean_t
+isc_serial_ne(isc_uint32_t a, isc_uint32_t b) {
+	return ((a != b) ? ISC_TRUE : ISC_FALSE);
+}
diff --git a/src/lib/bind9/sha1.c b/src/lib/bind9/sha1.c
new file mode 100644
index 0000000..72e6b0a
--- /dev/null
+++ b/src/lib/bind9/sha1.c
@@ -0,0 +1,354 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2009, 2011  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001, 2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: sha1.c,v 1.20.408.2 2011-03-12 04:59:18 tbox Exp $ */
+
+/*	$NetBSD: sha1.c,v 1.5 2000/01/22 22:19:14 mycroft Exp $	*/
+/*	$OpenBSD: sha1.c,v 1.9 1997/07/23 21:12:32 kstailey Exp $	*/
+
+/*! \file
+ * SHA-1 in C
+ * \author By Steve Reid <steve at edmweb.com>
+ * 100% Public Domain
+ * \verbatim
+ * Test Vectors (from FIPS PUB 180-1)
+ * "abc"
+ *   A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
+ * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+ *   84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
+ * A million repetitions of "a"
+ *   34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
+ * \endverbatim
+ */
+
+#include "config.h"
+
+#include <isc/assertions.h>
+#include <isc/platform.h>
+#include <isc/sha1.h>
+#include <isc/string.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#ifdef ISC_PLATFORM_OPENSSLHASH
+
+void
+isc_sha1_init(isc_sha1_t *context)
+{
+	INSIST(context != NULL);
+
+	EVP_DigestInit(context, EVP_sha1());
+}
+
+void
+isc_sha1_invalidate(isc_sha1_t *context) {
+	EVP_MD_CTX_cleanup(context);
+}
+
+void
+isc_sha1_update(isc_sha1_t *context, const unsigned char *data,
+		unsigned int len)
+{
+	INSIST(context != 0);
+	INSIST(data != 0);
+
+	EVP_DigestUpdate(context, (const void *) data, (size_t) len);
+}
+
+void
+isc_sha1_final(isc_sha1_t *context, unsigned char *digest) {
+	INSIST(digest != 0);
+	INSIST(context != 0);
+
+	EVP_DigestFinal(context, digest, NULL);
+}
+
+#else
+
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+/*@{*/
+/*!
+ * blk0() and blk() perform the initial expand.
+ * I got the idea of expanding during the round function from SSLeay
+ */
+#if !defined(WORDS_BIGENDIAN)
+# define blk0(i) \
+	(block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) \
+	 | (rol(block->l[i], 8) & 0x00FF00FF))
+#else
+# define blk0(i) block->l[i]
+#endif
+#define blk(i) \
+	(block->l[i & 15] = rol(block->l[(i + 13) & 15] \
+				^ block->l[(i + 8) & 15] \
+				^ block->l[(i + 2) & 15] \
+				^ block->l[i & 15], 1))
+
+/*@}*/
+/*@{*/
+/*!
+ * (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1
+ */
+#define R0(v,w,x,y,z,i) \
+	z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5); \
+	w = rol(w, 30);
+#define R1(v,w,x,y,z,i) \
+	z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \
+	w = rol(w, 30);
+#define R2(v,w,x,y,z,i) \
+	z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); \
+	w = rol(w, 30);
+#define R3(v,w,x,y,z,i) \
+	z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \
+	w = rol(w, 30);
+#define R4(v,w,x,y,z,i) \
+	z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \
+	w = rol(w, 30);
+
+/*@}*/
+
+typedef union {
+	unsigned char c[64];
+	unsigned int l[16];
+} CHAR64LONG16;
+
+#ifdef __sparc_v9__
+static void do_R01(isc_uint32_t *a, isc_uint32_t *b, isc_uint32_t *c,
+		   isc_uint32_t *d, isc_uint32_t *e, CHAR64LONG16 *);
+static void do_R2(isc_uint32_t *a, isc_uint32_t *b, isc_uint32_t *c,
+		  isc_uint32_t *d, isc_uint32_t *e, CHAR64LONG16 *);
+static void do_R3(isc_uint32_t *a, isc_uint32_t *b, isc_uint32_t *c,
+		  isc_uint32_t *d, isc_uint32_t *e, CHAR64LONG16 *);
+static void do_R4(isc_uint32_t *a, isc_uint32_t *b, isc_uint32_t *c,
+		  isc_uint32_t *d, isc_uint32_t *e, CHAR64LONG16 *);
+
+#define nR0(v,w,x,y,z,i) R0(*v,*w,*x,*y,*z,i)
+#define nR1(v,w,x,y,z,i) R1(*v,*w,*x,*y,*z,i)
+#define nR2(v,w,x,y,z,i) R2(*v,*w,*x,*y,*z,i)
+#define nR3(v,w,x,y,z,i) R3(*v,*w,*x,*y,*z,i)
+#define nR4(v,w,x,y,z,i) R4(*v,*w,*x,*y,*z,i)
+
+static void
+do_R01(isc_uint32_t *a, isc_uint32_t *b, isc_uint32_t *c, isc_uint32_t *d,
+       isc_uint32_t *e, CHAR64LONG16 *block)
+{
+	nR0(a,b,c,d,e, 0); nR0(e,a,b,c,d, 1); nR0(d,e,a,b,c, 2);
+	nR0(c,d,e,a,b, 3); nR0(b,c,d,e,a, 4); nR0(a,b,c,d,e, 5);
+	nR0(e,a,b,c,d, 6); nR0(d,e,a,b,c, 7); nR0(c,d,e,a,b, 8);
+	nR0(b,c,d,e,a, 9); nR0(a,b,c,d,e,10); nR0(e,a,b,c,d,11);
+	nR0(d,e,a,b,c,12); nR0(c,d,e,a,b,13); nR0(b,c,d,e,a,14);
+	nR0(a,b,c,d,e,15); nR1(e,a,b,c,d,16); nR1(d,e,a,b,c,17);
+	nR1(c,d,e,a,b,18); nR1(b,c,d,e,a,19);
+}
+
+static void
+do_R2(isc_uint32_t *a, isc_uint32_t *b, isc_uint32_t *c, isc_uint32_t *d,
+      isc_uint32_t *e, CHAR64LONG16 *block)
+{
+	nR2(a,b,c,d,e,20); nR2(e,a,b,c,d,21); nR2(d,e,a,b,c,22);
+	nR2(c,d,e,a,b,23); nR2(b,c,d,e,a,24); nR2(a,b,c,d,e,25);
+	nR2(e,a,b,c,d,26); nR2(d,e,a,b,c,27); nR2(c,d,e,a,b,28);
+	nR2(b,c,d,e,a,29); nR2(a,b,c,d,e,30); nR2(e,a,b,c,d,31);
+	nR2(d,e,a,b,c,32); nR2(c,d,e,a,b,33); nR2(b,c,d,e,a,34);
+	nR2(a,b,c,d,e,35); nR2(e,a,b,c,d,36); nR2(d,e,a,b,c,37);
+	nR2(c,d,e,a,b,38); nR2(b,c,d,e,a,39);
+}
+
+static void
+do_R3(isc_uint32_t *a, isc_uint32_t *b, isc_uint32_t *c, isc_uint32_t *d,
+      isc_uint32_t *e, CHAR64LONG16 *block)
+{
+	nR3(a,b,c,d,e,40); nR3(e,a,b,c,d,41); nR3(d,e,a,b,c,42);
+	nR3(c,d,e,a,b,43); nR3(b,c,d,e,a,44); nR3(a,b,c,d,e,45);
+	nR3(e,a,b,c,d,46); nR3(d,e,a,b,c,47); nR3(c,d,e,a,b,48);
+	nR3(b,c,d,e,a,49); nR3(a,b,c,d,e,50); nR3(e,a,b,c,d,51);
+	nR3(d,e,a,b,c,52); nR3(c,d,e,a,b,53); nR3(b,c,d,e,a,54);
+	nR3(a,b,c,d,e,55); nR3(e,a,b,c,d,56); nR3(d,e,a,b,c,57);
+	nR3(c,d,e,a,b,58); nR3(b,c,d,e,a,59);
+}
+
+static void
+do_R4(isc_uint32_t *a, isc_uint32_t *b, isc_uint32_t *c, isc_uint32_t *d,
+      isc_uint32_t *e, CHAR64LONG16 *block)
+{
+	nR4(a,b,c,d,e,60); nR4(e,a,b,c,d,61); nR4(d,e,a,b,c,62);
+	nR4(c,d,e,a,b,63); nR4(b,c,d,e,a,64); nR4(a,b,c,d,e,65);
+	nR4(e,a,b,c,d,66); nR4(d,e,a,b,c,67); nR4(c,d,e,a,b,68);
+	nR4(b,c,d,e,a,69); nR4(a,b,c,d,e,70); nR4(e,a,b,c,d,71);
+	nR4(d,e,a,b,c,72); nR4(c,d,e,a,b,73); nR4(b,c,d,e,a,74);
+	nR4(a,b,c,d,e,75); nR4(e,a,b,c,d,76); nR4(d,e,a,b,c,77);
+	nR4(c,d,e,a,b,78); nR4(b,c,d,e,a,79);
+}
+#endif
+
+/*!
+ * Hash a single 512-bit block. This is the core of the algorithm.
+ */
+static void
+transform(isc_uint32_t state[5], const unsigned char buffer[64]) {
+	isc_uint32_t a, b, c, d, e;
+	CHAR64LONG16 *block;
+	CHAR64LONG16 workspace;
+
+	INSIST(buffer != NULL);
+	INSIST(state != NULL);
+
+	block = &workspace;
+	(void)memcpy(block, buffer, 64);
+
+	/* Copy context->state[] to working vars */
+	a = state[0];
+	b = state[1];
+	c = state[2];
+	d = state[3];
+	e = state[4];
+
+#ifdef __sparc_v9__
+	do_R01(&a, &b, &c, &d, &e, block);
+	do_R2(&a, &b, &c, &d, &e, block);
+	do_R3(&a, &b, &c, &d, &e, block);
+	do_R4(&a, &b, &c, &d, &e, block);
+#else
+	/* 4 rounds of 20 operations each. Loop unrolled. */
+	R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+	R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+	R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+	R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+	R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+	R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+	R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+	R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+	R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+	R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+	R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+	R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+	R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+	R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+	R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+	R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+	R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+	R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+	R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+	R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+#endif
+
+	/* Add the working vars back into context.state[] */
+	state[0] += a;
+	state[1] += b;
+	state[2] += c;
+	state[3] += d;
+	state[4] += e;
+
+	/* Wipe variables */
+	a = b = c = d = e = 0;
+	/* Avoid compiler warnings */
+	POST(a); POST(b); POST(c); POST(d); POST(e);
+}
+
+
+/*!
+ * isc_sha1_init - Initialize new context
+ */
+void
+isc_sha1_init(isc_sha1_t *context)
+{
+	INSIST(context != NULL);
+
+	/* SHA1 initialization constants */
+	context->state[0] = 0x67452301;
+	context->state[1] = 0xEFCDAB89;
+	context->state[2] = 0x98BADCFE;
+	context->state[3] = 0x10325476;
+	context->state[4] = 0xC3D2E1F0;
+	context->count[0] = 0;
+	context->count[1] = 0;
+}
+
+void
+isc_sha1_invalidate(isc_sha1_t *context) {
+	memset(context, 0, sizeof(isc_sha1_t));
+}
+
+/*!
+ * Run your data through this.
+ */
+void
+isc_sha1_update(isc_sha1_t *context, const unsigned char *data,
+		unsigned int len)
+{
+	unsigned int i, j;
+
+	INSIST(context != 0);
+	INSIST(data != 0);
+
+	j = context->count[0];
+	if ((context->count[0] += len << 3) < j)
+		context->count[1] += (len >> 29) + 1;
+	j = (j >> 3) & 63;
+	if ((j + len) > 63) {
+		(void)memcpy(&context->buffer[j], data, (i = 64 - j));
+		transform(context->state, context->buffer);
+		for (; i + 63 < len; i += 64)
+			transform(context->state, &data[i]);
+		j = 0;
+	} else {
+		i = 0;
+	}
+
+	(void)memcpy(&context->buffer[j], &data[i], len - i);
+}
+
+
+/*!
+ * Add padding and return the message digest.
+ */
+
+static const unsigned char final_200 = 128;
+static const unsigned char final_0 = 0;
+
+void
+isc_sha1_final(isc_sha1_t *context, unsigned char *digest) {
+	unsigned int i;
+	unsigned char finalcount[8];
+
+	INSIST(digest != 0);
+	INSIST(context != 0);
+
+	for (i = 0; i < 8; i++) {
+		/* Endian independent */
+		finalcount[i] = (unsigned char)
+			((context->count[(i >= 4 ? 0 : 1)]
+			  >> ((3 - (i & 3)) * 8)) & 255);
+	}
+
+	isc_sha1_update(context, &final_200, 1);
+	while ((context->count[0] & 504) != 448)
+		isc_sha1_update(context, &final_0, 1);
+	/* The next Update should cause a transform() */
+	isc_sha1_update(context, finalcount, 8);
+
+	if (digest) {
+		for (i = 0; i < 20; i++)
+			digest[i] = (unsigned char)
+				((context->state[i >> 2]
+				  >> ((3 - (i & 3)) * 8)) & 255);
+	}
+
+	memset(context, 0, sizeof(isc_sha1_t));
+}
+#endif
diff --git a/src/lib/bind9/sha2.c b/src/lib/bind9/sha2.c
new file mode 100644
index 0000000..2c9fe33
--- /dev/null
+++ b/src/lib/bind9/sha2.c
@@ -0,0 +1,1449 @@
+/*
+ * Copyright (C) 2005-2007, 2009, 2011  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: sha2.c,v 1.18.280.2 2011-03-12 04:59:18 tbox Exp $ */
+
+/*	$FreeBSD: src/sys/crypto/sha2/sha2.c,v 1.2.2.2 2002/03/05 08:36:47 ume Exp $	*/
+/*	$KAME: sha2.c,v 1.8 2001/11/08 01:07:52 itojun Exp $	*/
+
+/*
+ * sha2.c
+ *
+ * Version 1.0.0beta1
+ *
+ * Written by Aaron D. Gifford <me at aarongifford.com>
+ *
+ * Copyright 2000 Aaron D. Gifford.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTOR(S) ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTOR(S) BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+
+#include <config.h>
+
+#include <isc/assertions.h>
+#include <isc/platform.h>
+#include <isc/sha2.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#ifdef ISC_PLATFORM_OPENSSLHASH
+
+void
+isc_sha224_init(isc_sha224_t *context) {
+	if (context == (isc_sha224_t *)0) {
+		return;
+	}
+	EVP_DigestInit(context, EVP_sha224());
+}
+
+void
+isc_sha224_invalidate(isc_sha224_t *context) {
+	EVP_MD_CTX_cleanup(context);
+}
+
+void
+isc_sha224_update(isc_sha224_t *context, const isc_uint8_t* data, size_t len) {
+	if (len == 0U) {
+		/* Calling with no data is valid - we do nothing */
+		return;
+	}
+
+	/* Sanity check: */
+	REQUIRE(context != (isc_sha224_t *)0 && data != (isc_uint8_t*)0);
+
+	EVP_DigestUpdate(context, (const void *) data, len);
+}
+
+void
+isc_sha224_final(isc_uint8_t digest[], isc_sha224_t *context) {
+	/* Sanity check: */
+	REQUIRE(context != (isc_sha224_t *)0);
+
+	/* If no digest buffer is passed, we don't bother doing this: */
+	if (digest != (isc_uint8_t*)0) {
+		EVP_DigestFinal(context, digest, NULL);
+	} else {
+		EVP_MD_CTX_cleanup(context);
+	}
+}
+
+void
+isc_sha256_init(isc_sha256_t *context) {
+	if (context == (isc_sha256_t *)0) {
+		return;
+	}
+	EVP_DigestInit(context, EVP_sha256());
+}
+
+void
+isc_sha256_invalidate(isc_sha256_t *context) {
+	EVP_MD_CTX_cleanup(context);
+}
+
+void
+isc_sha256_update(isc_sha256_t *context, const isc_uint8_t *data, size_t len) {
+	if (len == 0U) {
+		/* Calling with no data is valid - we do nothing */
+		return;
+	}
+
+	/* Sanity check: */
+	REQUIRE(context != (isc_sha256_t *)0 && data != (isc_uint8_t*)0);
+
+	EVP_DigestUpdate(context, (const void *) data, len);
+}
+
+void
+isc_sha256_final(isc_uint8_t digest[], isc_sha256_t *context) {
+	/* Sanity check: */
+	REQUIRE(context != (isc_sha256_t *)0);
+
+	/* If no digest buffer is passed, we don't bother doing this: */
+	if (digest != (isc_uint8_t*)0) {
+		EVP_DigestFinal(context, digest, NULL);
+	} else {
+		EVP_MD_CTX_cleanup(context);
+	}
+}
+
+void
+isc_sha512_init(isc_sha512_t *context) {
+	if (context == (isc_sha512_t *)0) {
+		return;
+	}
+	EVP_DigestInit(context, EVP_sha512());
+}
+
+void
+isc_sha512_invalidate(isc_sha512_t *context) {
+	EVP_MD_CTX_cleanup(context);
+}
+
+void isc_sha512_update(isc_sha512_t *context, const isc_uint8_t *data, size_t len) {
+	if (len == 0U) {
+		/* Calling with no data is valid - we do nothing */
+		return;
+	}
+
+	/* Sanity check: */
+	REQUIRE(context != (isc_sha512_t *)0 && data != (isc_uint8_t*)0);
+
+	EVP_DigestUpdate(context, (const void *) data, len);
+}
+
+void isc_sha512_final(isc_uint8_t digest[], isc_sha512_t *context) {
+	/* Sanity check: */
+	REQUIRE(context != (isc_sha512_t *)0);
+
+	/* If no digest buffer is passed, we don't bother doing this: */
+	if (digest != (isc_uint8_t*)0) {
+		EVP_DigestFinal(context, digest, NULL);
+	} else {
+		EVP_MD_CTX_cleanup(context);
+	}
+}
+
+void
+isc_sha384_init(isc_sha384_t *context) {
+	if (context == (isc_sha384_t *)0) {
+		return;
+	}
+	EVP_DigestInit(context, EVP_sha384());
+}
+
+void
+isc_sha384_invalidate(isc_sha384_t *context) {
+	EVP_MD_CTX_cleanup(context);
+}
+
+void
+isc_sha384_update(isc_sha384_t *context, const isc_uint8_t* data, size_t len) {
+	if (len == 0U) {
+		/* Calling with no data is valid - we do nothing */
+		return;
+	}
+
+	/* Sanity check: */
+	REQUIRE(context != (isc_sha512_t *)0 && data != (isc_uint8_t*)0);
+
+	EVP_DigestUpdate(context, (const void *) data, len);
+}
+
+void
+isc_sha384_final(isc_uint8_t digest[], isc_sha384_t *context) {
+	/* Sanity check: */
+	REQUIRE(context != (isc_sha384_t *)0);
+
+	/* If no digest buffer is passed, we don't bother doing this: */
+	if (digest != (isc_uint8_t*)0) {
+		EVP_DigestFinal(context, digest, NULL);
+	} else {
+		EVP_MD_CTX_cleanup(context);
+	}
+}
+
+#else
+
+/*
+ * UNROLLED TRANSFORM LOOP NOTE:
+ * You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform
+ * loop version for the hash transform rounds (defined using macros
+ * later in this file).  Either define on the command line, for example:
+ *
+ *   cc -DISC_SHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c
+ *
+ * or define below:
+ *
+ *   \#define ISC_SHA2_UNROLL_TRANSFORM
+ *
+ */
+
+/*** SHA-256/384/512 Machine Architecture Definitions *****************/
+/*
+ * BYTE_ORDER NOTE:
+ *
+ * Please make sure that your system defines BYTE_ORDER.  If your
+ * architecture is little-endian, make sure it also defines
+ * LITTLE_ENDIAN and that the two (BYTE_ORDER and LITTLE_ENDIAN) are
+ * equivalent.
+ *
+ * If your system does not define the above, then you can do so by
+ * hand like this:
+ *
+ *   \#define LITTLE_ENDIAN 1234
+ *   \#define BIG_ENDIAN    4321
+ *
+ * And for little-endian machines, add:
+ *
+ *   \#define BYTE_ORDER LITTLE_ENDIAN
+ *
+ * Or for big-endian machines:
+ *
+ *   \#define BYTE_ORDER BIG_ENDIAN
+ *
+ * The FreeBSD machine this was written on defines BYTE_ORDER
+ * appropriately by including <sys/types.h> (which in turn includes
+ * <machine/endian.h> where the appropriate definitions are actually
+ * made).
+ */
+#if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN)
+#ifndef BYTE_ORDER
+#ifndef BIG_ENDIAN
+#define BIG_ENDIAN 4321
+#endif
+#ifndef LITTLE_ENDIAN
+#define LITTLE_ENDIAN 1234
+#endif
+#ifdef WORDS_BIGENDIAN
+#define BYTE_ORDER BIG_ENDIAN
+#else
+#define BYTE_ORDER LITTLE_ENDIAN
+#endif
+#else
+#error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN
+#endif
+#endif
+
+/*** SHA-256/384/512 Various Length Definitions ***********************/
+/* NOTE: Most of these are in sha2.h */
+#define ISC_SHA256_SHORT_BLOCK_LENGTH	(ISC_SHA256_BLOCK_LENGTH - 8)
+#define ISC_SHA384_SHORT_BLOCK_LENGTH	(ISC_SHA384_BLOCK_LENGTH - 16)
+#define ISC_SHA512_SHORT_BLOCK_LENGTH	(ISC_SHA512_BLOCK_LENGTH - 16)
+
+
+/*** ENDIAN REVERSAL MACROS *******************************************/
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define REVERSE32(w,x)	{ \
+	isc_uint32_t tmp = (w); \
+	tmp = (tmp >> 16) | (tmp << 16); \
+	(x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \
+}
+#ifdef WIN32
+#define REVERSE64(w,x)	{ \
+	isc_uint64_t tmp = (w); \
+	tmp = (tmp >> 32) | (tmp << 32); \
+	tmp = ((tmp & 0xff00ff00ff00ff00UL) >> 8) | \
+	      ((tmp & 0x00ff00ff00ff00ffUL) << 8); \
+	(x) = ((tmp & 0xffff0000ffff0000UL) >> 16) | \
+	      ((tmp & 0x0000ffff0000ffffUL) << 16); \
+}
+#else
+#define REVERSE64(w,x)	{ \
+	isc_uint64_t tmp = (w); \
+	tmp = (tmp >> 32) | (tmp << 32); \
+	tmp = ((tmp & 0xff00ff00ff00ff00ULL) >> 8) | \
+	      ((tmp & 0x00ff00ff00ff00ffULL) << 8); \
+	(x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \
+	      ((tmp & 0x0000ffff0000ffffULL) << 16); \
+}
+#endif
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+
+/*
+ * Macro for incrementally adding the unsigned 64-bit integer n to the
+ * unsigned 128-bit integer (represented using a two-element array of
+ * 64-bit words):
+ */
+#define ADDINC128(w,n)	{ \
+	(w)[0] += (isc_uint64_t)(n); \
+	if ((w)[0] < (n)) { \
+		(w)[1]++; \
+	} \
+}
+
+/*** THE SIX LOGICAL FUNCTIONS ****************************************/
+/*
+ * Bit shifting and rotation (used by the six SHA-XYZ logical functions:
+ *
+ *   NOTE:  The naming of R and S appears backwards here (R is a SHIFT and
+ *   S is a ROTATION) because the SHA-256/384/512 description document
+ *   (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this
+ *   same "backwards" definition.
+ */
+/* Shift-right (used in SHA-256, SHA-384, and SHA-512): */
+#define R(b,x) 		((x) >> (b))
+/* 32-bit Rotate-right (used in SHA-256): */
+#define S32(b,x)	(((x) >> (b)) | ((x) << (32 - (b))))
+/* 64-bit Rotate-right (used in SHA-384 and SHA-512): */
+#define S64(b,x)	(((x) >> (b)) | ((x) << (64 - (b))))
+
+/* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */
+#define Ch(x,y,z)	(((x) & (y)) ^ ((~(x)) & (z)))
+#define Maj(x,y,z)	(((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
+
+/* Four of six logical functions used in SHA-256: */
+#define Sigma0_256(x)	(S32(2,  (x)) ^ S32(13, (x)) ^ S32(22, (x)))
+#define Sigma1_256(x)	(S32(6,  (x)) ^ S32(11, (x)) ^ S32(25, (x)))
+#define sigma0_256(x)	(S32(7,  (x)) ^ S32(18, (x)) ^ R(3 ,   (x)))
+#define sigma1_256(x)	(S32(17, (x)) ^ S32(19, (x)) ^ R(10,   (x)))
+
+/* Four of six logical functions used in SHA-384 and SHA-512: */
+#define Sigma0_512(x)	(S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x)))
+#define Sigma1_512(x)	(S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x)))
+#define sigma0_512(x)	(S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7,   (x)))
+#define sigma1_512(x)	(S64(19, (x)) ^ S64(61, (x)) ^ R( 6,   (x)))
+
+/*** INTERNAL FUNCTION PROTOTYPES *************************************/
+/* NOTE: These should not be accessed directly from outside this
+ * library -- they are intended for private internal visibility/use
+ * only.
+ */
+void isc_sha512_last(isc_sha512_t *);
+void isc_sha256_transform(isc_sha256_t *, const isc_uint32_t*);
+void isc_sha512_transform(isc_sha512_t *, const isc_uint64_t*);
+
+
+/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/
+/* Hash constant words K for SHA-224 and SHA-256: */
+static const isc_uint32_t K256[64] = {
+	0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
+	0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
+	0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
+	0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
+	0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
+	0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
+	0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,
+	0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
+	0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,
+	0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
+	0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,
+	0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
+	0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,
+	0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
+	0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
+	0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
+};
+
+/* Initial hash value H for SHA-224: */
+static const isc_uint32_t sha224_initial_hash_value[8] = {
+	0xc1059ed8UL,
+	0x367cd507UL,
+	0x3070dd17UL,
+	0xf70e5939UL,
+	0xffc00b31UL,
+	0x68581511UL,
+	0x64f98fa7UL,
+	0xbefa4fa4UL
+};
+
+/* Initial hash value H for SHA-256: */
+static const isc_uint32_t sha256_initial_hash_value[8] = {
+	0x6a09e667UL,
+	0xbb67ae85UL,
+	0x3c6ef372UL,
+	0xa54ff53aUL,
+	0x510e527fUL,
+	0x9b05688cUL,
+	0x1f83d9abUL,
+	0x5be0cd19UL
+};
+
+#ifdef WIN32
+/* Hash constant words K for SHA-384 and SHA-512: */
+static const isc_uint64_t K512[80] = {
+	0x428a2f98d728ae22UL, 0x7137449123ef65cdUL,
+	0xb5c0fbcfec4d3b2fUL, 0xe9b5dba58189dbbcUL,
+	0x3956c25bf348b538UL, 0x59f111f1b605d019UL,
+	0x923f82a4af194f9bUL, 0xab1c5ed5da6d8118UL,
+	0xd807aa98a3030242UL, 0x12835b0145706fbeUL,
+	0x243185be4ee4b28cUL, 0x550c7dc3d5ffb4e2UL,
+	0x72be5d74f27b896fUL, 0x80deb1fe3b1696b1UL,
+	0x9bdc06a725c71235UL, 0xc19bf174cf692694UL,
+	0xe49b69c19ef14ad2UL, 0xefbe4786384f25e3UL,
+	0x0fc19dc68b8cd5b5UL, 0x240ca1cc77ac9c65UL,
+	0x2de92c6f592b0275UL, 0x4a7484aa6ea6e483UL,
+	0x5cb0a9dcbd41fbd4UL, 0x76f988da831153b5UL,
+	0x983e5152ee66dfabUL, 0xa831c66d2db43210UL,
+	0xb00327c898fb213fUL, 0xbf597fc7beef0ee4UL,
+	0xc6e00bf33da88fc2UL, 0xd5a79147930aa725UL,
+	0x06ca6351e003826fUL, 0x142929670a0e6e70UL,
+	0x27b70a8546d22ffcUL, 0x2e1b21385c26c926UL,
+	0x4d2c6dfc5ac42aedUL, 0x53380d139d95b3dfUL,
+	0x650a73548baf63deUL, 0x766a0abb3c77b2a8UL,
+	0x81c2c92e47edaee6UL, 0x92722c851482353bUL,
+	0xa2bfe8a14cf10364UL, 0xa81a664bbc423001UL,
+	0xc24b8b70d0f89791UL, 0xc76c51a30654be30UL,
+	0xd192e819d6ef5218UL, 0xd69906245565a910UL,
+	0xf40e35855771202aUL, 0x106aa07032bbd1b8UL,
+	0x19a4c116b8d2d0c8UL, 0x1e376c085141ab53UL,
+	0x2748774cdf8eeb99UL, 0x34b0bcb5e19b48a8UL,
+	0x391c0cb3c5c95a63UL, 0x4ed8aa4ae3418acbUL,
+	0x5b9cca4f7763e373UL, 0x682e6ff3d6b2b8a3UL,
+	0x748f82ee5defb2fcUL, 0x78a5636f43172f60UL,
+	0x84c87814a1f0ab72UL, 0x8cc702081a6439ecUL,
+	0x90befffa23631e28UL, 0xa4506cebde82bde9UL,
+	0xbef9a3f7b2c67915UL, 0xc67178f2e372532bUL,
+	0xca273eceea26619cUL, 0xd186b8c721c0c207UL,
+	0xeada7dd6cde0eb1eUL, 0xf57d4f7fee6ed178UL,
+	0x06f067aa72176fbaUL, 0x0a637dc5a2c898a6UL,
+	0x113f9804bef90daeUL, 0x1b710b35131c471bUL,
+	0x28db77f523047d84UL, 0x32caab7b40c72493UL,
+	0x3c9ebe0a15c9bebcUL, 0x431d67c49c100d4cUL,
+	0x4cc5d4becb3e42b6UL, 0x597f299cfc657e2aUL,
+	0x5fcb6fab3ad6faecUL, 0x6c44198c4a475817UL
+};
+
+/* Initial hash value H for SHA-384: */
+static const isc_uint64_t sha384_initial_hash_value[8] = {
+	0xcbbb9d5dc1059ed8UL,
+	0x629a292a367cd507UL,
+	0x9159015a3070dd17UL,
+	0x152fecd8f70e5939UL,
+	0x67332667ffc00b31UL,
+	0x8eb44a8768581511UL,
+	0xdb0c2e0d64f98fa7UL,
+	0x47b5481dbefa4fa4UL
+};
+
+/* Initial hash value H for SHA-512: */
+static const isc_uint64_t sha512_initial_hash_value[8] = {
+	0x6a09e667f3bcc908U,
+	0xbb67ae8584caa73bUL,
+	0x3c6ef372fe94f82bUL,
+	0xa54ff53a5f1d36f1UL,
+	0x510e527fade682d1UL,
+	0x9b05688c2b3e6c1fUL,
+	0x1f83d9abfb41bd6bUL,
+	0x5be0cd19137e2179UL
+};
+#else
+/* Hash constant words K for SHA-384 and SHA-512: */
+static const isc_uint64_t K512[80] = {
+	0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
+	0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
+	0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
+	0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
+	0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
+	0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
+	0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
+	0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
+	0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
+	0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
+	0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
+	0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
+	0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
+	0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
+	0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
+	0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
+	0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
+	0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
+	0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
+	0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
+	0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
+	0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
+	0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
+	0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
+	0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
+	0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
+	0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
+	0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
+	0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
+	0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
+	0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
+	0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
+	0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
+	0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
+	0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
+	0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
+	0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
+	0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
+	0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
+	0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
+};
+
+/* Initial hash value H for SHA-384: */
+static const isc_uint64_t sha384_initial_hash_value[8] = {
+	0xcbbb9d5dc1059ed8ULL,
+	0x629a292a367cd507ULL,
+	0x9159015a3070dd17ULL,
+	0x152fecd8f70e5939ULL,
+	0x67332667ffc00b31ULL,
+	0x8eb44a8768581511ULL,
+	0xdb0c2e0d64f98fa7ULL,
+	0x47b5481dbefa4fa4ULL
+};
+
+/* Initial hash value H for SHA-512: */
+static const isc_uint64_t sha512_initial_hash_value[8] = {
+	0x6a09e667f3bcc908ULL,
+	0xbb67ae8584caa73bULL,
+	0x3c6ef372fe94f82bULL,
+	0xa54ff53a5f1d36f1ULL,
+	0x510e527fade682d1ULL,
+	0x9b05688c2b3e6c1fULL,
+	0x1f83d9abfb41bd6bULL,
+	0x5be0cd19137e2179ULL
+};
+#endif
+
+
+/*** SHA-224: *********************************************************/
+void
+isc_sha224_init(isc_sha224_t *context) {
+	if (context == (isc_sha256_t *)0) {
+		return;
+	}
+	memcpy(context->state, sha224_initial_hash_value,
+	       ISC_SHA256_DIGESTLENGTH);
+	memset(context->buffer, 0, ISC_SHA256_BLOCK_LENGTH);
+	context->bitcount = 0;
+}
+
+void
+isc_sha224_invalidate(isc_sha224_t *context) {
+	memset(context, 0, sizeof(isc_sha224_t));
+}
+
+void
+isc_sha224_update(isc_sha224_t *context, const isc_uint8_t* data, size_t len) {
+	isc_sha256_update((isc_sha256_t *)context, data, len);
+}
+
+void
+isc_sha224_final(isc_uint8_t digest[], isc_sha224_t *context) {
+	isc_uint8_t sha256_digest[ISC_SHA256_DIGESTLENGTH];
+	isc_sha256_final(sha256_digest, (isc_sha256_t *)context);
+	memcpy(digest, sha256_digest, ISC_SHA224_DIGESTLENGTH);
+	memset(sha256_digest, 0, ISC_SHA256_DIGESTLENGTH);
+}
+
+/*** SHA-256: *********************************************************/
+void
+isc_sha256_init(isc_sha256_t *context) {
+	if (context == (isc_sha256_t *)0) {
+		return;
+	}
+	memcpy(context->state, sha256_initial_hash_value,
+	       ISC_SHA256_DIGESTLENGTH);
+	memset(context->buffer, 0, ISC_SHA256_BLOCK_LENGTH);
+	context->bitcount = 0;
+}
+
+void
+isc_sha256_invalidate(isc_sha256_t *context) {
+	memset(context, 0, sizeof(isc_sha256_t));
+}
+
+#ifdef ISC_SHA2_UNROLL_TRANSFORM
+
+/* Unrolled SHA-256 round macros: */
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+
+#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h)	\
+	REVERSE32(*data++, W256[j]); \
+	T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \
+	     K256[j] + W256[j]; \
+	(d) += T1; \
+	(h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
+	j++
+
+
+#else /* BYTE_ORDER == LITTLE_ENDIAN */
+
+#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h)	\
+	T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \
+	     K256[j] + (W256[j] = *data++); \
+	(d) += T1; \
+	(h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
+	j++
+
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+
+#define ROUND256(a,b,c,d,e,f,g,h)	\
+	s0 = W256[(j+1)&0x0f]; \
+	s0 = sigma0_256(s0); \
+	s1 = W256[(j+14)&0x0f]; \
+	s1 = sigma1_256(s1); \
+	T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + K256[j] + \
+	     (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \
+	(d) += T1; \
+	(h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
+	j++
+
+void isc_sha256_transform(isc_sha256_t *context, const isc_uint32_t* data) {
+	isc_uint32_t	a, b, c, d, e, f, g, h, s0, s1;
+	isc_uint32_t	T1, *W256;
+	int		j;
+
+	W256 = (isc_uint32_t*)context->buffer;
+
+	/* Initialize registers with the prev. intermediate value */
+	a = context->state[0];
+	b = context->state[1];
+	c = context->state[2];
+	d = context->state[3];
+	e = context->state[4];
+	f = context->state[5];
+	g = context->state[6];
+	h = context->state[7];
+
+	j = 0;
+	do {
+		/* Rounds 0 to 15 (unrolled): */
+		ROUND256_0_TO_15(a,b,c,d,e,f,g,h);
+		ROUND256_0_TO_15(h,a,b,c,d,e,f,g);
+		ROUND256_0_TO_15(g,h,a,b,c,d,e,f);
+		ROUND256_0_TO_15(f,g,h,a,b,c,d,e);
+		ROUND256_0_TO_15(e,f,g,h,a,b,c,d);
+		ROUND256_0_TO_15(d,e,f,g,h,a,b,c);
+		ROUND256_0_TO_15(c,d,e,f,g,h,a,b);
+		ROUND256_0_TO_15(b,c,d,e,f,g,h,a);
+	} while (j < 16);
+
+	/* Now for the remaining rounds to 64: */
+	do {
+		ROUND256(a,b,c,d,e,f,g,h);
+		ROUND256(h,a,b,c,d,e,f,g);
+		ROUND256(g,h,a,b,c,d,e,f);
+		ROUND256(f,g,h,a,b,c,d,e);
+		ROUND256(e,f,g,h,a,b,c,d);
+		ROUND256(d,e,f,g,h,a,b,c);
+		ROUND256(c,d,e,f,g,h,a,b);
+		ROUND256(b,c,d,e,f,g,h,a);
+	} while (j < 64);
+
+	/* Compute the current intermediate hash value */
+	context->state[0] += a;
+	context->state[1] += b;
+	context->state[2] += c;
+	context->state[3] += d;
+	context->state[4] += e;
+	context->state[5] += f;
+	context->state[6] += g;
+	context->state[7] += h;
+
+	/* Clean up */
+	a = b = c = d = e = f = g = h = T1 = 0;
+	/* Avoid compiler warnings */
+	POST(a); POST(b); POST(c); POST(d); POST(e); POST(f);
+	POST(g); POST(h); POST(T1);
+}
+
+#else /* ISC_SHA2_UNROLL_TRANSFORM */
+
+void
+isc_sha256_transform(isc_sha256_t *context, const isc_uint32_t* data) {
+	isc_uint32_t	a, b, c, d, e, f, g, h, s0, s1;
+	isc_uint32_t	T1, T2, *W256;
+	int		j;
+
+	W256 = (isc_uint32_t*)context->buffer;
+
+	/* Initialize registers with the prev. intermediate value */
+	a = context->state[0];
+	b = context->state[1];
+	c = context->state[2];
+	d = context->state[3];
+	e = context->state[4];
+	f = context->state[5];
+	g = context->state[6];
+	h = context->state[7];
+
+	j = 0;
+	do {
+#if BYTE_ORDER == LITTLE_ENDIAN
+		/* Copy data while converting to host byte order */
+		REVERSE32(*data++,W256[j]);
+		/* Apply the SHA-256 compression function to update a..h */
+		T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j];
+#else /* BYTE_ORDER == LITTLE_ENDIAN */
+		/* Apply the SHA-256 compression function to update a..h with copy */
+		T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j] = *data++);
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+		T2 = Sigma0_256(a) + Maj(a, b, c);
+		h = g;
+		g = f;
+		f = e;
+		e = d + T1;
+		d = c;
+		c = b;
+		b = a;
+		a = T1 + T2;
+
+		j++;
+	} while (j < 16);
+
+	do {
+		/* Part of the message block expansion: */
+		s0 = W256[(j+1)&0x0f];
+		s0 = sigma0_256(s0);
+		s1 = W256[(j+14)&0x0f];
+		s1 = sigma1_256(s1);
+
+		/* Apply the SHA-256 compression function to update a..h */
+		T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] +
+		     (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0);
+		T2 = Sigma0_256(a) + Maj(a, b, c);
+		h = g;
+		g = f;
+		f = e;
+		e = d + T1;
+		d = c;
+		c = b;
+		b = a;
+		a = T1 + T2;
+
+		j++;
+	} while (j < 64);
+
+	/* Compute the current intermediate hash value */
+	context->state[0] += a;
+	context->state[1] += b;
+	context->state[2] += c;
+	context->state[3] += d;
+	context->state[4] += e;
+	context->state[5] += f;
+	context->state[6] += g;
+	context->state[7] += h;
+
+	/* Clean up */
+	a = b = c = d = e = f = g = h = T1 = T2 = 0;
+	/* Avoid compiler warnings */
+	POST(a); POST(b); POST(c); POST(d); POST(e); POST(f);
+	POST(g); POST(h); POST(T1); POST(T2);
+}
+
+#endif /* ISC_SHA2_UNROLL_TRANSFORM */
+
+void
+isc_sha256_update(isc_sha256_t *context, const isc_uint8_t *data, size_t len) {
+	unsigned int	freespace, usedspace;
+
+	if (len == 0U) {
+		/* Calling with no data is valid - we do nothing */
+		return;
+	}
+
+	/* Sanity check: */
+	REQUIRE(context != (isc_sha256_t *)0 && data != (isc_uint8_t*)0);
+
+	usedspace = (unsigned int)((context->bitcount >> 3) %
+				   ISC_SHA256_BLOCK_LENGTH);
+	if (usedspace > 0) {
+		/* Calculate how much free space is available in the buffer */
+		freespace = ISC_SHA256_BLOCK_LENGTH - usedspace;
+
+		if (len >= freespace) {
+			/* Fill the buffer completely and process it */
+			memcpy(&context->buffer[usedspace], data, freespace);
+			context->bitcount += freespace << 3;
+			len -= freespace;
+			data += freespace;
+			isc_sha256_transform(context,
+					     (isc_uint32_t*)context->buffer);
+		} else {
+			/* The buffer is not yet full */
+			memcpy(&context->buffer[usedspace], data, len);
+			context->bitcount += len << 3;
+			/* Clean up: */
+			usedspace = freespace = 0;
+			/* Avoid compiler warnings: */
+			POST(usedspace); POST(freespace);
+			return;
+		}
+	}
+	while (len >= ISC_SHA256_BLOCK_LENGTH) {
+		/* Process as many complete blocks as we can */
+		memcpy(context->buffer, data, ISC_SHA256_BLOCK_LENGTH);
+		isc_sha256_transform(context, (isc_uint32_t*)context->buffer);
+		context->bitcount += ISC_SHA256_BLOCK_LENGTH << 3;
+		len -= ISC_SHA256_BLOCK_LENGTH;
+		data += ISC_SHA256_BLOCK_LENGTH;
+	}
+	if (len > 0U) {
+		/* There's left-overs, so save 'em */
+		memcpy(context->buffer, data, len);
+		context->bitcount += len << 3;
+	}
+	/* Clean up: */
+	usedspace = freespace = 0;
+	/* Avoid compiler warnings: */
+	POST(usedspace); POST(freespace);
+}
+
+void
+isc_sha256_final(isc_uint8_t digest[], isc_sha256_t *context) {
+	isc_uint32_t	*d = (isc_uint32_t*)digest;
+	unsigned int	usedspace;
+
+	/* Sanity check: */
+	REQUIRE(context != (isc_sha256_t *)0);
+
+	/* If no digest buffer is passed, we don't bother doing this: */
+	if (digest != (isc_uint8_t*)0) {
+		usedspace = (unsigned int)((context->bitcount >> 3) %
+					   ISC_SHA256_BLOCK_LENGTH);
+#if BYTE_ORDER == LITTLE_ENDIAN
+		/* Convert FROM host byte order */
+		REVERSE64(context->bitcount,context->bitcount);
+#endif
+		if (usedspace > 0) {
+			/* Begin padding with a 1 bit: */
+			context->buffer[usedspace++] = 0x80;
+
+			if (usedspace <= ISC_SHA256_SHORT_BLOCK_LENGTH) {
+				/* Set-up for the last transform: */
+				memset(&context->buffer[usedspace], 0,
+				       ISC_SHA256_SHORT_BLOCK_LENGTH - usedspace);
+			} else {
+				if (usedspace < ISC_SHA256_BLOCK_LENGTH) {
+					memset(&context->buffer[usedspace], 0,
+					       ISC_SHA256_BLOCK_LENGTH -
+					       usedspace);
+				}
+				/* Do second-to-last transform: */
+				isc_sha256_transform(context,
+					       (isc_uint32_t*)context->buffer);
+
+				/* And set-up for the last transform: */
+				memset(context->buffer, 0,
+				       ISC_SHA256_SHORT_BLOCK_LENGTH);
+			}
+		} else {
+			/* Set-up for the last transform: */
+			memset(context->buffer, 0, ISC_SHA256_SHORT_BLOCK_LENGTH);
+
+			/* Begin padding with a 1 bit: */
+			*context->buffer = 0x80;
+		}
+		/* Set the bit count: */
+		*(isc_uint64_t*)&context->buffer[ISC_SHA256_SHORT_BLOCK_LENGTH] = context->bitcount;
+
+		/* Final transform: */
+		isc_sha256_transform(context, (isc_uint32_t*)context->buffer);
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+		{
+			/* Convert TO host byte order */
+			int	j;
+			for (j = 0; j < 8; j++) {
+				REVERSE32(context->state[j],context->state[j]);
+				*d++ = context->state[j];
+			}
+		}
+#else
+		memcpy(d, context->state, ISC_SHA256_DIGESTLENGTH);
+#endif
+	}
+
+	/* Clean up state data: */
+	memset(context, 0, sizeof(context));
+	usedspace = 0;
+	POST(usedspace);
+}
+
+/*** SHA-512: *********************************************************/
+void
+isc_sha512_init(isc_sha512_t *context) {
+	if (context == (isc_sha512_t *)0) {
+		return;
+	}
+	memcpy(context->state, sha512_initial_hash_value,
+	       ISC_SHA512_DIGESTLENGTH);
+	memset(context->buffer, 0, ISC_SHA512_BLOCK_LENGTH);
+	context->bitcount[0] = context->bitcount[1] =  0;
+}
+
+void
+isc_sha512_invalidate(isc_sha512_t *context) {
+	memset(context, 0, sizeof(isc_sha512_t));
+}
+
+#ifdef ISC_SHA2_UNROLL_TRANSFORM
+
+/* Unrolled SHA-512 round macros: */
+#if BYTE_ORDER == LITTLE_ENDIAN
+
+#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h)	\
+	REVERSE64(*data++, W512[j]); \
+	T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \
+	     K512[j] + W512[j]; \
+	(d) += T1, \
+	(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)), \
+	j++
+
+
+#else /* BYTE_ORDER == LITTLE_ENDIAN */
+
+#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h)	\
+	T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \
+	     K512[j] + (W512[j] = *data++); \
+	(d) += T1; \
+	(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \
+	j++
+
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+
+#define ROUND512(a,b,c,d,e,f,g,h)	\
+	s0 = W512[(j+1)&0x0f]; \
+	s0 = sigma0_512(s0); \
+	s1 = W512[(j+14)&0x0f]; \
+	s1 = sigma1_512(s1); \
+	T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + K512[j] + \
+	     (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); \
+	(d) += T1; \
+	(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \
+	j++
+
+void isc_sha512_transform(isc_sha512_t *context, const isc_uint64_t* data) {
+	isc_uint64_t	a, b, c, d, e, f, g, h, s0, s1;
+	isc_uint64_t	T1, *W512 = (isc_uint64_t*)context->buffer;
+	int		j;
+
+	/* Initialize registers with the prev. intermediate value */
+	a = context->state[0];
+	b = context->state[1];
+	c = context->state[2];
+	d = context->state[3];
+	e = context->state[4];
+	f = context->state[5];
+	g = context->state[6];
+	h = context->state[7];
+
+	j = 0;
+	do {
+		ROUND512_0_TO_15(a,b,c,d,e,f,g,h);
+		ROUND512_0_TO_15(h,a,b,c,d,e,f,g);
+		ROUND512_0_TO_15(g,h,a,b,c,d,e,f);
+		ROUND512_0_TO_15(f,g,h,a,b,c,d,e);
+		ROUND512_0_TO_15(e,f,g,h,a,b,c,d);
+		ROUND512_0_TO_15(d,e,f,g,h,a,b,c);
+		ROUND512_0_TO_15(c,d,e,f,g,h,a,b);
+		ROUND512_0_TO_15(b,c,d,e,f,g,h,a);
+	} while (j < 16);
+
+	/* Now for the remaining rounds up to 79: */
+	do {
+		ROUND512(a,b,c,d,e,f,g,h);
+		ROUND512(h,a,b,c,d,e,f,g);
+		ROUND512(g,h,a,b,c,d,e,f);
+		ROUND512(f,g,h,a,b,c,d,e);
+		ROUND512(e,f,g,h,a,b,c,d);
+		ROUND512(d,e,f,g,h,a,b,c);
+		ROUND512(c,d,e,f,g,h,a,b);
+		ROUND512(b,c,d,e,f,g,h,a);
+	} while (j < 80);
+
+	/* Compute the current intermediate hash value */
+	context->state[0] += a;
+	context->state[1] += b;
+	context->state[2] += c;
+	context->state[3] += d;
+	context->state[4] += e;
+	context->state[5] += f;
+	context->state[6] += g;
+	context->state[7] += h;
+
+	/* Clean up */
+	a = b = c = d = e = f = g = h = T1 = 0;
+	/* Avoid compiler warnings */
+	POST(a); POST(b); POST(c); POST(d); POST(e); POST(f);
+	POST(g); POST(h); POST(T1);
+}
+
+#else /* ISC_SHA2_UNROLL_TRANSFORM */
+
+void
+isc_sha512_transform(isc_sha512_t *context, const isc_uint64_t* data) {
+	isc_uint64_t	a, b, c, d, e, f, g, h, s0, s1;
+	isc_uint64_t	T1, T2, *W512 = (isc_uint64_t*)context->buffer;
+	int		j;
+
+	/* Initialize registers with the prev. intermediate value */
+	a = context->state[0];
+	b = context->state[1];
+	c = context->state[2];
+	d = context->state[3];
+	e = context->state[4];
+	f = context->state[5];
+	g = context->state[6];
+	h = context->state[7];
+
+	j = 0;
+	do {
+#if BYTE_ORDER == LITTLE_ENDIAN
+		/* Convert TO host byte order */
+		REVERSE64(*data++, W512[j]);
+		/* Apply the SHA-512 compression function to update a..h */
+		T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j];
+#else /* BYTE_ORDER == LITTLE_ENDIAN */
+		/* Apply the SHA-512 compression function to update a..h with copy */
+		T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + (W512[j] = *data++);
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+		T2 = Sigma0_512(a) + Maj(a, b, c);
+		h = g;
+		g = f;
+		f = e;
+		e = d + T1;
+		d = c;
+		c = b;
+		b = a;
+		a = T1 + T2;
+
+		j++;
+	} while (j < 16);
+
+	do {
+		/* Part of the message block expansion: */
+		s0 = W512[(j+1)&0x0f];
+		s0 = sigma0_512(s0);
+		s1 = W512[(j+14)&0x0f];
+		s1 =  sigma1_512(s1);
+
+		/* Apply the SHA-512 compression function to update a..h */
+		T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] +
+		     (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0);
+		T2 = Sigma0_512(a) + Maj(a, b, c);
+		h = g;
+		g = f;
+		f = e;
+		e = d + T1;
+		d = c;
+		c = b;
+		b = a;
+		a = T1 + T2;
+
+		j++;
+	} while (j < 80);
+
+	/* Compute the current intermediate hash value */
+	context->state[0] += a;
+	context->state[1] += b;
+	context->state[2] += c;
+	context->state[3] += d;
+	context->state[4] += e;
+	context->state[5] += f;
+	context->state[6] += g;
+	context->state[7] += h;
+
+	/* Clean up */
+	a = b = c = d = e = f = g = h = T1 = T2 = 0;
+	/* Avoid compiler warnings */
+	POST(a); POST(b); POST(c); POST(d); POST(e); POST(f);
+	POST(g); POST(h); POST(T1); POST(T2);
+}
+
+#endif /* ISC_SHA2_UNROLL_TRANSFORM */
+
+void isc_sha512_update(isc_sha512_t *context, const isc_uint8_t *data, size_t len) {
+	unsigned int	freespace, usedspace;
+
+	if (len == 0U) {
+		/* Calling with no data is valid - we do nothing */
+		return;
+	}
+
+	/* Sanity check: */
+	REQUIRE(context != (isc_sha512_t *)0 && data != (isc_uint8_t*)0);
+
+	usedspace = (unsigned int)((context->bitcount[0] >> 3) %
+				   ISC_SHA512_BLOCK_LENGTH);
+	if (usedspace > 0) {
+		/* Calculate how much free space is available in the buffer */
+		freespace = ISC_SHA512_BLOCK_LENGTH - usedspace;
+
+		if (len >= freespace) {
+			/* Fill the buffer completely and process it */
+			memcpy(&context->buffer[usedspace], data, freespace);
+			ADDINC128(context->bitcount, freespace << 3);
+			len -= freespace;
+			data += freespace;
+			isc_sha512_transform(context,
+					     (isc_uint64_t*)context->buffer);
+		} else {
+			/* The buffer is not yet full */
+			memcpy(&context->buffer[usedspace], data, len);
+			ADDINC128(context->bitcount, len << 3);
+			/* Clean up: */
+			usedspace = freespace = 0;
+			/* Avoid compiler warnings: */
+			POST(usedspace); POST(freespace);
+			return;
+		}
+	}
+	while (len >= ISC_SHA512_BLOCK_LENGTH) {
+		/* Process as many complete blocks as we can */
+		memcpy(context->buffer, data, ISC_SHA512_BLOCK_LENGTH);
+		isc_sha512_transform(context, (isc_uint64_t*)context->buffer);
+		ADDINC128(context->bitcount, ISC_SHA512_BLOCK_LENGTH << 3);
+		len -= ISC_SHA512_BLOCK_LENGTH;
+		data += ISC_SHA512_BLOCK_LENGTH;
+	}
+	if (len > 0U) {
+		/* There's left-overs, so save 'em */
+		memcpy(context->buffer, data, len);
+		ADDINC128(context->bitcount, len << 3);
+	}
+	/* Clean up: */
+	usedspace = freespace = 0;
+	/* Avoid compiler warnings: */
+	POST(usedspace); POST(freespace);
+}
+
+void isc_sha512_last(isc_sha512_t *context) {
+	unsigned int	usedspace;
+
+	usedspace = (unsigned int)((context->bitcount[0] >> 3) %
+				    ISC_SHA512_BLOCK_LENGTH);
+#if BYTE_ORDER == LITTLE_ENDIAN
+	/* Convert FROM host byte order */
+	REVERSE64(context->bitcount[0],context->bitcount[0]);
+	REVERSE64(context->bitcount[1],context->bitcount[1]);
+#endif
+	if (usedspace > 0) {
+		/* Begin padding with a 1 bit: */
+		context->buffer[usedspace++] = 0x80;
+
+		if (usedspace <= ISC_SHA512_SHORT_BLOCK_LENGTH) {
+			/* Set-up for the last transform: */
+			memset(&context->buffer[usedspace], 0,
+			       ISC_SHA512_SHORT_BLOCK_LENGTH - usedspace);
+		} else {
+			if (usedspace < ISC_SHA512_BLOCK_LENGTH) {
+				memset(&context->buffer[usedspace], 0,
+				       ISC_SHA512_BLOCK_LENGTH - usedspace);
+			}
+			/* Do second-to-last transform: */
+			isc_sha512_transform(context,
+					    (isc_uint64_t*)context->buffer);
+
+			/* And set-up for the last transform: */
+			memset(context->buffer, 0, ISC_SHA512_BLOCK_LENGTH - 2);
+		}
+	} else {
+		/* Prepare for final transform: */
+		memset(context->buffer, 0, ISC_SHA512_SHORT_BLOCK_LENGTH);
+
+		/* Begin padding with a 1 bit: */
+		*context->buffer = 0x80;
+	}
+	/* Store the length of input data (in bits): */
+	*(isc_uint64_t*)&context->buffer[ISC_SHA512_SHORT_BLOCK_LENGTH] = context->bitcount[1];
+	*(isc_uint64_t*)&context->buffer[ISC_SHA512_SHORT_BLOCK_LENGTH+8] = context->bitcount[0];
+
+	/* Final transform: */
+	isc_sha512_transform(context, (isc_uint64_t*)context->buffer);
+}
+
+void isc_sha512_final(isc_uint8_t digest[], isc_sha512_t *context) {
+	isc_uint64_t	*d = (isc_uint64_t*)digest;
+
+	/* Sanity check: */
+	REQUIRE(context != (isc_sha512_t *)0);
+
+	/* If no digest buffer is passed, we don't bother doing this: */
+	if (digest != (isc_uint8_t*)0) {
+		isc_sha512_last(context);
+
+		/* Save the hash data for output: */
+#if BYTE_ORDER == LITTLE_ENDIAN
+		{
+			/* Convert TO host byte order */
+			int	j;
+			for (j = 0; j < 8; j++) {
+				REVERSE64(context->state[j],context->state[j]);
+				*d++ = context->state[j];
+			}
+		}
+#else
+		memcpy(d, context->state, ISC_SHA512_DIGESTLENGTH);
+#endif
+	}
+
+	/* Zero out state data */
+	memset(context, 0, sizeof(context));
+}
+
+
+/*** SHA-384: *********************************************************/
+void
+isc_sha384_init(isc_sha384_t *context) {
+	if (context == (isc_sha384_t *)0) {
+		return;
+	}
+	memcpy(context->state, sha384_initial_hash_value,
+	       ISC_SHA512_DIGESTLENGTH);
+	memset(context->buffer, 0, ISC_SHA384_BLOCK_LENGTH);
+	context->bitcount[0] = context->bitcount[1] = 0;
+}
+
+void
+isc_sha384_invalidate(isc_sha384_t *context) {
+	memset(context, 0, sizeof(isc_sha384_t));
+}
+
+void
+isc_sha384_update(isc_sha384_t *context, const isc_uint8_t* data, size_t len) {
+	isc_sha512_update((isc_sha512_t *)context, data, len);
+}
+
+void
+isc_sha384_final(isc_uint8_t digest[], isc_sha384_t *context) {
+	isc_uint64_t	*d = (isc_uint64_t*)digest;
+
+	/* Sanity check: */
+	REQUIRE(context != (isc_sha384_t *)0);
+
+	/* If no digest buffer is passed, we don't bother doing this: */
+	if (digest != (isc_uint8_t*)0) {
+		isc_sha512_last((isc_sha512_t *)context);
+
+		/* Save the hash data for output: */
+#if BYTE_ORDER == LITTLE_ENDIAN
+		{
+			/* Convert TO host byte order */
+			int	j;
+			for (j = 0; j < 6; j++) {
+				REVERSE64(context->state[j],context->state[j]);
+				*d++ = context->state[j];
+			}
+		}
+#else
+		memcpy(d, context->state, ISC_SHA384_DIGESTLENGTH);
+#endif
+	}
+
+	/* Zero out state data */
+	memset(context, 0, sizeof(context));
+}
+#endif /* !ISC_PLATFORM_OPENSSLHASH */
+
+/*
+ * Constant used by SHA256/384/512_End() functions for converting the
+ * digest to a readable hexadecimal character string:
+ */
+static const char *sha2_hex_digits = "0123456789abcdef";
+
+char *
+isc_sha224_end(isc_sha224_t *context, char buffer[]) {
+	isc_uint8_t	digest[ISC_SHA224_DIGESTLENGTH], *d = digest;
+	unsigned int	i;
+
+	/* Sanity check: */
+	REQUIRE(context != (isc_sha224_t *)0);
+
+	if (buffer != (char*)0) {
+		isc_sha224_final(digest, context);
+
+		for (i = 0; i < ISC_SHA224_DIGESTLENGTH; i++) {
+			*buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
+			*buffer++ = sha2_hex_digits[*d & 0x0f];
+			d++;
+		}
+		*buffer = (char)0;
+	} else {
+#ifdef ISC_PLATFORM_OPENSSLHASH
+		EVP_MD_CTX_cleanup(context);
+#else
+		memset(context, 0, sizeof(context));
+#endif
+	}
+	memset(digest, 0, ISC_SHA224_DIGESTLENGTH);
+	return buffer;
+}
+
+char *
+isc_sha224_data(const isc_uint8_t *data, size_t len,
+		char digest[ISC_SHA224_DIGESTSTRINGLENGTH])
+{
+	isc_sha224_t context;
+
+	isc_sha224_init(&context);
+	isc_sha224_update(&context, data, len);
+	return (isc_sha224_end(&context, digest));
+}
+
+char *
+isc_sha256_end(isc_sha256_t *context, char buffer[]) {
+	isc_uint8_t	digest[ISC_SHA256_DIGESTLENGTH], *d = digest;
+	unsigned int	i;
+
+	/* Sanity check: */
+	REQUIRE(context != (isc_sha256_t *)0);
+
+	if (buffer != (char*)0) {
+		isc_sha256_final(digest, context);
+
+		for (i = 0; i < ISC_SHA256_DIGESTLENGTH; i++) {
+			*buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
+			*buffer++ = sha2_hex_digits[*d & 0x0f];
+			d++;
+		}
+		*buffer = (char)0;
+	} else {
+#ifdef ISC_PLATFORM_OPENSSLHASH
+		EVP_MD_CTX_cleanup(context);
+#else
+		memset(context, 0, sizeof(context));
+#endif
+	}
+	memset(digest, 0, ISC_SHA256_DIGESTLENGTH);
+	return buffer;
+}
+
+char *
+isc_sha256_data(const isc_uint8_t* data, size_t len,
+		char digest[ISC_SHA256_DIGESTSTRINGLENGTH])
+{
+	isc_sha256_t context;
+
+	isc_sha256_init(&context);
+	isc_sha256_update(&context, data, len);
+	return (isc_sha256_end(&context, digest));
+}
+
+char *
+isc_sha512_end(isc_sha512_t *context, char buffer[]) {
+	isc_uint8_t	digest[ISC_SHA512_DIGESTLENGTH], *d = digest;
+	unsigned int	i;
+
+	/* Sanity check: */
+	REQUIRE(context != (isc_sha512_t *)0);
+
+	if (buffer != (char*)0) {
+		isc_sha512_final(digest, context);
+
+		for (i = 0; i < ISC_SHA512_DIGESTLENGTH; i++) {
+			*buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
+			*buffer++ = sha2_hex_digits[*d & 0x0f];
+			d++;
+		}
+		*buffer = (char)0;
+	} else {
+#ifdef ISC_PLATFORM_OPENSSLHASH
+		EVP_MD_CTX_cleanup(context);
+#else
+		memset(context, 0, sizeof(context));
+#endif
+	}
+	memset(digest, 0, ISC_SHA512_DIGESTLENGTH);
+	return buffer;
+}
+
+char *
+isc_sha512_data(const isc_uint8_t *data, size_t len,
+		char digest[ISC_SHA512_DIGESTSTRINGLENGTH])
+{
+	isc_sha512_t 	context;
+
+	isc_sha512_init(&context);
+	isc_sha512_update(&context, data, len);
+	return (isc_sha512_end(&context, digest));
+}
+
+char *
+isc_sha384_end(isc_sha384_t *context, char buffer[]) {
+	isc_uint8_t	digest[ISC_SHA384_DIGESTLENGTH], *d = digest;
+	unsigned int	i;
+
+	/* Sanity check: */
+	REQUIRE(context != (isc_sha384_t *)0);
+
+	if (buffer != (char*)0) {
+		isc_sha384_final(digest, context);
+
+		for (i = 0; i < ISC_SHA384_DIGESTLENGTH; i++) {
+			*buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
+			*buffer++ = sha2_hex_digits[*d & 0x0f];
+			d++;
+		}
+		*buffer = (char)0;
+	} else {
+#ifdef ISC_PLATFORM_OPENSSLHASH
+		EVP_MD_CTX_cleanup(context);
+#else
+		memset(context, 0, sizeof(context));
+#endif
+	}
+	memset(digest, 0, ISC_SHA384_DIGESTLENGTH);
+	return buffer;
+}
+
+char *
+isc_sha384_data(const isc_uint8_t *data, size_t len,
+		char digest[ISC_SHA384_DIGESTSTRINGLENGTH])
+{
+	isc_sha384_t context;
+
+	isc_sha384_init(&context);
+	isc_sha384_update(&context, data, len);
+	return (isc_sha384_end(&context, digest));
+}
diff --git a/src/lib/bind9/sockaddr.c b/src/lib/bind9/sockaddr.c
new file mode 100644
index 0000000..fe27066
--- /dev/null
+++ b/src/lib/bind9/sockaddr.c
@@ -0,0 +1,506 @@
+/*
+ * Copyright (C) 2004-2007, 2010, 2011  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: sockaddr.c,v 1.73.38.2 2011-02-28 01:20:03 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+
+#include <isc/buffer.h>
+#include <isc/hash.h>
+#include <isc/msgs.h>
+#include <isc/netaddr.h>
+#include <isc/print.h>
+#include <isc/region.h>
+#include <isc/sockaddr.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+isc_boolean_t
+isc_sockaddr_equal(const isc_sockaddr_t *a, const isc_sockaddr_t *b) {
+	return (isc_sockaddr_compare(a, b, ISC_SOCKADDR_CMPADDR|
+					   ISC_SOCKADDR_CMPPORT|
+					   ISC_SOCKADDR_CMPSCOPE));
+}
+
+isc_boolean_t
+isc_sockaddr_eqaddr(const isc_sockaddr_t *a, const isc_sockaddr_t *b) {
+	return (isc_sockaddr_compare(a, b, ISC_SOCKADDR_CMPADDR|
+					   ISC_SOCKADDR_CMPSCOPE));
+}
+
+isc_boolean_t
+isc_sockaddr_compare(const isc_sockaddr_t *a, const isc_sockaddr_t *b,
+		     unsigned int flags)
+{
+	REQUIRE(a != NULL && b != NULL);
+
+	if (a->length != b->length)
+		return (ISC_FALSE);
+
+	/*
+	 * We don't just memcmp because the sin_zero field isn't always
+	 * zero.
+	 */
+
+	if (a->type.sa.sa_family != b->type.sa.sa_family)
+		return (ISC_FALSE);
+	switch (a->type.sa.sa_family) {
+	case AF_INET:
+		if ((flags & ISC_SOCKADDR_CMPADDR) != 0 &&
+		    memcmp(&a->type.sin.sin_addr, &b->type.sin.sin_addr,
+			   sizeof(a->type.sin.sin_addr)) != 0)
+			return (ISC_FALSE);
+		if ((flags & ISC_SOCKADDR_CMPPORT) != 0 &&
+		    a->type.sin.sin_port != b->type.sin.sin_port)
+			return (ISC_FALSE);
+		break;
+	case AF_INET6:
+		if ((flags & ISC_SOCKADDR_CMPADDR) != 0 &&
+		    memcmp(&a->type.sin6.sin6_addr, &b->type.sin6.sin6_addr,
+			   sizeof(a->type.sin6.sin6_addr)) != 0)
+			return (ISC_FALSE);
+#ifdef ISC_PLATFORM_HAVESCOPEID
+		/*
+		 * If ISC_SOCKADDR_CMPSCOPEZERO is set then don't return
+		 * ISC_FALSE if one of the scopes in zero.
+		 */
+		if ((flags & ISC_SOCKADDR_CMPSCOPE) != 0 &&
+		    a->type.sin6.sin6_scope_id != b->type.sin6.sin6_scope_id &&
+		    ((flags & ISC_SOCKADDR_CMPSCOPEZERO) == 0 ||
+		      (a->type.sin6.sin6_scope_id != 0 &&
+		       b->type.sin6.sin6_scope_id != 0)))
+			return (ISC_FALSE);
+#endif
+		if ((flags & ISC_SOCKADDR_CMPPORT) != 0 &&
+		    a->type.sin6.sin6_port != b->type.sin6.sin6_port)
+			return (ISC_FALSE);
+		break;
+	default:
+		if (memcmp(&a->type, &b->type, a->length) != 0)
+			return (ISC_FALSE);
+	}
+	return (ISC_TRUE);
+}
+
+isc_boolean_t
+isc_sockaddr_eqaddrprefix(const isc_sockaddr_t *a, const isc_sockaddr_t *b,
+			  unsigned int prefixlen)
+{
+	isc_netaddr_t na, nb;
+	isc_netaddr_fromsockaddr(&na, a);
+	isc_netaddr_fromsockaddr(&nb, b);
+	return (isc_netaddr_eqprefix(&na, &nb, prefixlen));
+}
+
+isc_result_t
+isc_sockaddr_totext(const isc_sockaddr_t *sockaddr, isc_buffer_t *target) {
+	isc_result_t result;
+	isc_netaddr_t netaddr;
+	char pbuf[sizeof("65000")];
+	unsigned int plen;
+	isc_region_t avail;
+
+	REQUIRE(sockaddr != NULL);
+
+	/*
+	 * Do the port first, giving us the opportunity to check for
+	 * unsupported address families before calling
+	 * isc_netaddr_fromsockaddr().
+	 */
+	switch (sockaddr->type.sa.sa_family) {
+	case AF_INET:
+		snprintf(pbuf, sizeof(pbuf), "%u", ntohs(sockaddr->type.sin.sin_port));
+		break;
+	case AF_INET6:
+		snprintf(pbuf, sizeof(pbuf), "%u", ntohs(sockaddr->type.sin6.sin6_port));
+		break;
+#ifdef ISC_PLAFORM_HAVESYSUNH
+	case AF_UNIX:
+		plen = strlen(sockaddr->type.sunix.sun_path);
+		if (plen >= isc_buffer_availablelength(target))
+			return (ISC_R_NOSPACE);
+
+		isc_buffer_putmem(target, sockaddr->type.sunix.sun_path, plen);
+
+		/*
+		 * Null terminate after used region.
+		 */
+		isc_buffer_availableregion(target, &avail);
+		INSIST(avail.length >= 1);
+		avail.base[0] = '\0';
+
+		return (ISC_R_SUCCESS);
+#endif
+	default:
+		return (ISC_R_FAILURE);
+	}
+
+	plen = strlen(pbuf);
+	INSIST(plen < sizeof(pbuf));
+
+	isc_netaddr_fromsockaddr(&netaddr, sockaddr);
+	result = isc_netaddr_totext(&netaddr, target);
+	if (result != ISC_R_SUCCESS)
+		return (result);
+
+	if (1 + plen + 1 > isc_buffer_availablelength(target))
+		return (ISC_R_NOSPACE);
+
+	isc_buffer_putmem(target, (const unsigned char *)"#", 1);
+	isc_buffer_putmem(target, (const unsigned char *)pbuf, plen);
+
+	/*
+	 * Null terminate after used region.
+	 */
+	isc_buffer_availableregion(target, &avail);
+	INSIST(avail.length >= 1);
+	avail.base[0] = '\0';
+
+	return (ISC_R_SUCCESS);
+}
+
+void
+isc_sockaddr_format(const isc_sockaddr_t *sa, char *array, unsigned int size) {
+	isc_result_t result;
+	isc_buffer_t buf;
+
+	if (size == 0U)
+		return;
+
+	isc_buffer_init(&buf, array, size);
+	result = isc_sockaddr_totext(sa, &buf);
+	if (result != ISC_R_SUCCESS) {
+		/*
+		 * The message is the same as in netaddr.c.
+		 */
+		snprintf(array, size,
+			 isc_msgcat_get(isc_msgcat, ISC_MSGSET_NETADDR,
+					ISC_MSG_UNKNOWNADDR,
+					"<unknown address, family %u>"),
+			 sa->type.sa.sa_family);
+		array[size - 1] = '\0';
+	}
+}
+
+unsigned int
+isc_sockaddr_hash(const isc_sockaddr_t *sockaddr, isc_boolean_t address_only) {
+	unsigned int length = 0;
+	const unsigned char *s = NULL;
+	unsigned int h = 0;
+	unsigned int g;
+	unsigned int p = 0;
+	const struct in6_addr *in6;
+
+	REQUIRE(sockaddr != NULL);
+
+	switch (sockaddr->type.sa.sa_family) {
+	case AF_INET:
+		s = (const unsigned char *)&sockaddr->type.sin.sin_addr;
+		p = ntohs(sockaddr->type.sin.sin_port);
+		length = sizeof(sockaddr->type.sin.sin_addr.s_addr);
+		break;
+	case AF_INET6:
+		in6 = &sockaddr->type.sin6.sin6_addr;
+		if (IN6_IS_ADDR_V4MAPPED(in6)) {
+			s = (const unsigned char *)&in6[12];
+			length = sizeof(sockaddr->type.sin.sin_addr.s_addr);
+		} else {
+			s = (const unsigned char *)in6;
+			length = sizeof(sockaddr->type.sin6.sin6_addr);
+		}
+		p = ntohs(sockaddr->type.sin6.sin6_port);
+		break;
+	default:
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 isc_msgcat_get(isc_msgcat,
+						ISC_MSGSET_SOCKADDR,
+						ISC_MSG_UNKNOWNFAMILY,
+						"unknown address family: %d"),
+					     (int)sockaddr->type.sa.sa_family);
+		s = (const unsigned char *)&sockaddr->type;
+		length = sockaddr->length;
+		p = 0;
+	}
+
+	h = isc_hash_calc(s, length, ISC_TRUE);
+	if (!address_only) {
+		g = isc_hash_calc((const unsigned char *)&p, sizeof(p),
+				  ISC_TRUE);
+		h = h ^ g; /* XXX: we should concatenate h and p first */
+	}
+
+	return (h);
+}
+
+void
+isc_sockaddr_any(isc_sockaddr_t *sockaddr)
+{
+	memset(sockaddr, 0, sizeof(*sockaddr));
+	sockaddr->type.sin.sin_family = AF_INET;
+#ifdef ISC_PLATFORM_HAVESALEN
+	sockaddr->type.sin.sin_len = sizeof(sockaddr->type.sin);
+#endif
+	sockaddr->type.sin.sin_addr.s_addr = INADDR_ANY;
+	sockaddr->type.sin.sin_port = 0;
+	sockaddr->length = sizeof(sockaddr->type.sin);
+	ISC_LINK_INIT(sockaddr, link);
+}
+
+void
+isc_sockaddr_any6(isc_sockaddr_t *sockaddr)
+{
+	memset(sockaddr, 0, sizeof(*sockaddr));
+	sockaddr->type.sin6.sin6_family = AF_INET6;
+#ifdef ISC_PLATFORM_HAVESALEN
+	sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6);
+#endif
+	sockaddr->type.sin6.sin6_addr = in6addr_any;
+	sockaddr->type.sin6.sin6_port = 0;
+	sockaddr->length = sizeof(sockaddr->type.sin6);
+	ISC_LINK_INIT(sockaddr, link);
+}
+
+void
+isc_sockaddr_fromin(isc_sockaddr_t *sockaddr, const struct in_addr *ina,
+		    in_port_t port)
+{
+	memset(sockaddr, 0, sizeof(*sockaddr));
+	sockaddr->type.sin.sin_family = AF_INET;
+#ifdef ISC_PLATFORM_HAVESALEN
+	sockaddr->type.sin.sin_len = sizeof(sockaddr->type.sin);
+#endif
+	sockaddr->type.sin.sin_addr = *ina;
+	sockaddr->type.sin.sin_port = htons(port);
+	sockaddr->length = sizeof(sockaddr->type.sin);
+	ISC_LINK_INIT(sockaddr, link);
+}
+
+void
+isc_sockaddr_anyofpf(isc_sockaddr_t *sockaddr, int pf) {
+     switch (pf) {
+     case AF_INET:
+	     isc_sockaddr_any(sockaddr);
+	     break;
+     case AF_INET6:
+	     isc_sockaddr_any6(sockaddr);
+	     break;
+     default:
+	     INSIST(0);
+     }
+}
+
+void
+isc_sockaddr_fromin6(isc_sockaddr_t *sockaddr, const struct in6_addr *ina6,
+		     in_port_t port)
+{
+	memset(sockaddr, 0, sizeof(*sockaddr));
+	sockaddr->type.sin6.sin6_family = AF_INET6;
+#ifdef ISC_PLATFORM_HAVESALEN
+	sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6);
+#endif
+	sockaddr->type.sin6.sin6_addr = *ina6;
+	sockaddr->type.sin6.sin6_port = htons(port);
+	sockaddr->length = sizeof(sockaddr->type.sin6);
+	ISC_LINK_INIT(sockaddr, link);
+}
+
+void
+isc_sockaddr_v6fromin(isc_sockaddr_t *sockaddr, const struct in_addr *ina,
+		      in_port_t port)
+{
+	memset(sockaddr, 0, sizeof(*sockaddr));
+	sockaddr->type.sin6.sin6_family = AF_INET6;
+#ifdef ISC_PLATFORM_HAVESALEN
+	sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6);
+#endif
+	sockaddr->type.sin6.sin6_addr.s6_addr[10] = 0xff;
+	sockaddr->type.sin6.sin6_addr.s6_addr[11] = 0xff;
+	memcpy(&sockaddr->type.sin6.sin6_addr.s6_addr[12], ina, 4);
+	sockaddr->type.sin6.sin6_port = htons(port);
+	sockaddr->length = sizeof(sockaddr->type.sin6);
+	ISC_LINK_INIT(sockaddr, link);
+}
+
+int
+isc_sockaddr_pf(const isc_sockaddr_t *sockaddr) {
+
+	/*
+	 * Get the protocol family of 'sockaddr'.
+	 */
+
+#if (AF_INET == PF_INET && AF_INET6 == PF_INET6)
+	/*
+	 * Assume that PF_xxx == AF_xxx for all AF and PF.
+	 */
+	return (sockaddr->type.sa.sa_family);
+#else
+	switch (sockaddr->type.sa.sa_family) {
+	case AF_INET:
+		return (PF_INET);
+	case AF_INET6:
+		return (PF_INET6);
+	default:
+		FATAL_ERROR(__FILE__, __LINE__,
+			    isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKADDR,
+					   ISC_MSG_UNKNOWNFAMILY,
+					   "unknown address family: %d"),
+			    (int)sockaddr->type.sa.sa_family);
+	}
+#endif
+}
+
+void
+isc_sockaddr_fromnetaddr(isc_sockaddr_t *sockaddr, const isc_netaddr_t *na,
+		    in_port_t port)
+{
+	memset(sockaddr, 0, sizeof(*sockaddr));
+	sockaddr->type.sin.sin_family = na->family;
+	switch (na->family) {
+	case AF_INET:
+		sockaddr->length = sizeof(sockaddr->type.sin);
+#ifdef ISC_PLATFORM_HAVESALEN
+		sockaddr->type.sin.sin_len = sizeof(sockaddr->type.sin);
+#endif
+		sockaddr->type.sin.sin_addr = na->type.in;
+		sockaddr->type.sin.sin_port = htons(port);
+		break;
+	case AF_INET6:
+		sockaddr->length = sizeof(sockaddr->type.sin6);
+#ifdef ISC_PLATFORM_HAVESALEN
+		sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6);
+#endif
+		memcpy(&sockaddr->type.sin6.sin6_addr, &na->type.in6, 16);
+#ifdef ISC_PLATFORM_HAVESCOPEID
+		sockaddr->type.sin6.sin6_scope_id = isc_netaddr_getzone(na);
+#endif
+		sockaddr->type.sin6.sin6_port = htons(port);
+		break;
+	default:
+		INSIST(0);
+	}
+	ISC_LINK_INIT(sockaddr, link);
+}
+
+void
+isc_sockaddr_setport(isc_sockaddr_t *sockaddr, in_port_t port) {
+	switch (sockaddr->type.sa.sa_family) {
+	case AF_INET:
+		sockaddr->type.sin.sin_port = htons(port);
+		break;
+	case AF_INET6:
+		sockaddr->type.sin6.sin6_port = htons(port);
+		break;
+	default:
+		FATAL_ERROR(__FILE__, __LINE__,
+			    isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKADDR,
+					   ISC_MSG_UNKNOWNFAMILY,
+					   "unknown address family: %d"),
+			    (int)sockaddr->type.sa.sa_family);
+	}
+}
+
+in_port_t
+isc_sockaddr_getport(const isc_sockaddr_t *sockaddr) {
+	in_port_t port = 0;
+
+	switch (sockaddr->type.sa.sa_family) {
+	case AF_INET:
+		port = ntohs(sockaddr->type.sin.sin_port);
+		break;
+	case AF_INET6:
+		port = ntohs(sockaddr->type.sin6.sin6_port);
+		break;
+	default:
+		FATAL_ERROR(__FILE__, __LINE__,
+			    isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKADDR,
+					   ISC_MSG_UNKNOWNFAMILY,
+					   "unknown address family: %d"),
+			    (int)sockaddr->type.sa.sa_family);
+	}
+
+	return (port);
+}
+
+isc_boolean_t
+isc_sockaddr_ismulticast(const isc_sockaddr_t *sockaddr) {
+	isc_netaddr_t netaddr;
+
+	if (sockaddr->type.sa.sa_family == AF_INET ||
+	    sockaddr->type.sa.sa_family == AF_INET6) {
+		isc_netaddr_fromsockaddr(&netaddr, sockaddr);
+		return (isc_netaddr_ismulticast(&netaddr));
+	}
+	return (ISC_FALSE);
+}
+
+isc_boolean_t
+isc_sockaddr_isexperimental(const isc_sockaddr_t *sockaddr) {
+	isc_netaddr_t netaddr;
+
+	if (sockaddr->type.sa.sa_family == AF_INET) {
+		isc_netaddr_fromsockaddr(&netaddr, sockaddr);
+		return (isc_netaddr_isexperimental(&netaddr));
+	}
+	return (ISC_FALSE);
+}
+
+isc_boolean_t
+isc_sockaddr_issitelocal(const isc_sockaddr_t *sockaddr) {
+	isc_netaddr_t netaddr;
+
+	if (sockaddr->type.sa.sa_family == AF_INET6) {
+		isc_netaddr_fromsockaddr(&netaddr, sockaddr);
+		return (isc_netaddr_issitelocal(&netaddr));
+	}
+	return (ISC_FALSE);
+}
+
+isc_boolean_t
+isc_sockaddr_islinklocal(const isc_sockaddr_t *sockaddr) {
+	isc_netaddr_t netaddr;
+
+	if (sockaddr->type.sa.sa_family == AF_INET6) {
+		isc_netaddr_fromsockaddr(&netaddr, sockaddr);
+		return (isc_netaddr_islinklocal(&netaddr));
+	}
+	return (ISC_FALSE);
+}
+
+isc_result_t
+isc_sockaddr_frompath(isc_sockaddr_t *sockaddr, const char *path) {
+#ifdef ISC_PLATFORM_HAVESYSUNH
+	if (strlen(path) >= sizeof(sockaddr->type.sunix.sun_path))
+		return (ISC_R_NOSPACE);
+	memset(sockaddr, 0, sizeof(*sockaddr));
+	sockaddr->length = sizeof(sockaddr->type.sunix);
+	sockaddr->type.sunix.sun_family = AF_UNIX;
+#ifdef ISC_PLATFORM_HAVESALEN
+	sockaddr->type.sunix.sun_len =
+			(unsigned char)sizeof(sockaddr->type.sunix);
+#endif
+	strcpy(sockaddr->type.sunix.sun_path, path);
+	return (ISC_R_SUCCESS);
+#else
+	UNUSED(sockaddr);
+	UNUSED(path);
+	return (ISC_R_NOTIMPLEMENTED);
+#endif
+}
diff --git a/src/lib/bind9/socket_api.c b/src/lib/bind9/socket_api.c
new file mode 100644
index 0000000..c1e5fd4
--- /dev/null
+++ b/src/lib/bind9/socket_api.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2009  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: socket_api.c,v 1.5 2009-10-01 01:30:01 sar Exp $ */
+
+#include <config.h>
+
+#include <isc/app.h>
+#include <isc/magic.h>
+#include <isc/mutex.h>
+#include <isc/once.h>
+#include <isc/socket.h>
+#include <isc/util.h>
+
+static isc_mutex_t createlock;
+static isc_once_t once = ISC_ONCE_INIT;
+static isc_socketmgrcreatefunc_t socketmgr_createfunc = NULL;
+
+static void
+initialize(void) {
+	RUNTIME_CHECK(isc_mutex_init(&createlock) == ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_socket_register(isc_socketmgrcreatefunc_t createfunc) {
+	isc_result_t result = ISC_R_SUCCESS;
+
+	RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
+
+	LOCK(&createlock);
+	if (socketmgr_createfunc == NULL)
+		socketmgr_createfunc = createfunc;
+	else
+		result = ISC_R_EXISTS;
+	UNLOCK(&createlock);
+
+	return (result);
+}
+
+isc_result_t
+isc_socketmgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx,
+			  isc_socketmgr_t **managerp)
+{
+	isc_result_t result;
+
+	LOCK(&createlock);
+
+	REQUIRE(socketmgr_createfunc != NULL);
+	result = (*socketmgr_createfunc)(mctx, managerp);
+
+	UNLOCK(&createlock);
+
+	if (result == ISC_R_SUCCESS)
+		isc_appctx_setsocketmgr(actx, *managerp);
+
+	return (result);
+}
+
+isc_result_t
+isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) {
+	isc_result_t result;
+
+	LOCK(&createlock);
+
+	REQUIRE(socketmgr_createfunc != NULL);
+	result = (*socketmgr_createfunc)(mctx, managerp);
+
+	UNLOCK(&createlock);
+
+	return (result);
+}
+
+void
+isc_socketmgr_destroy(isc_socketmgr_t **managerp) {
+	REQUIRE(managerp != NULL && ISCAPI_SOCKETMGR_VALID(*managerp));
+
+	(*managerp)->methods->destroy(managerp);
+
+	ENSURE(*managerp == NULL);
+}
+
+isc_result_t
+isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
+		  isc_socket_t **socketp)
+{
+	REQUIRE(ISCAPI_SOCKETMGR_VALID(manager));
+
+	return (manager->methods->socketcreate(manager, pf, type, socketp));
+}
+
+void
+isc_socket_attach(isc_socket_t *sock, isc_socket_t **socketp) {
+	REQUIRE(ISCAPI_SOCKET_VALID(sock));
+	REQUIRE(socketp != NULL && *socketp == NULL);
+
+	sock->methods->attach(sock, socketp);
+
+	ENSURE(*socketp == sock);
+}
+
+void
+isc_socket_detach(isc_socket_t **socketp) {
+	REQUIRE(socketp != NULL && ISCAPI_SOCKET_VALID(*socketp));
+
+	(*socketp)->methods->detach(socketp);
+
+	ENSURE(*socketp == NULL);
+}
+
+isc_result_t
+isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr,
+		unsigned int options)
+{
+	REQUIRE(ISCAPI_SOCKET_VALID(sock));
+
+	return (sock->methods->bind(sock, sockaddr, options));
+}
+
+isc_result_t
+isc_socket_sendto(isc_socket_t *sock, isc_region_t *region, isc_task_t *task,
+		  isc_taskaction_t action, const void *arg,
+		  isc_sockaddr_t *address, struct in6_pktinfo *pktinfo)
+{
+	REQUIRE(ISCAPI_SOCKET_VALID(sock));
+
+	return (sock->methods->sendto(sock, region, task, action, arg, address,
+				      pktinfo));
+}
+
+isc_result_t
+isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr, isc_task_t *task,
+		   isc_taskaction_t action, const void *arg)
+{
+	REQUIRE(ISCAPI_SOCKET_VALID(sock));
+
+	return (sock->methods->connect(sock, addr, task, action, arg));
+}
+
+isc_result_t
+isc_socket_recv(isc_socket_t *sock, isc_region_t *region, unsigned int minimum,
+		isc_task_t *task, isc_taskaction_t action, const void *arg)
+{
+	REQUIRE(ISCAPI_SOCKET_VALID(sock));
+
+	return (sock->methods->recv(sock, region, minimum, task, action, arg));
+}
+
+void
+isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) {
+	REQUIRE(ISCAPI_SOCKET_VALID(sock));
+
+	sock->methods->cancel(sock, task, how);
+}
+
+isc_result_t
+isc_socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp) {
+	REQUIRE(ISCAPI_SOCKET_VALID(sock));
+
+	return (sock->methods->getsockname(sock, addressp));
+}
+
+void
+isc_socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes) {
+	REQUIRE(ISCAPI_SOCKET_VALID(sock));
+
+	sock->methods->ipv6only(sock, yes);
+}
+
+isc_sockettype_t
+isc_socket_gettype(isc_socket_t *sock) {
+	REQUIRE(ISCAPI_SOCKET_VALID(sock));
+
+	return (sock->methods->gettype(sock));
+}
+
+void
+isc_socket_setname(isc_socket_t *socket, const char *name, void *tag) {
+	REQUIRE(ISCAPI_SOCKET_VALID(socket));
+
+	UNUSED(socket);		/* in case REQUIRE() is empty */
+	UNUSED(name);
+	UNUSED(tag);
+}
+
+isc_result_t
+isc_socket_fdwatchcreate(isc_socketmgr_t *manager, int fd, int flags,
+			 isc_sockfdwatch_t callback, void *cbarg,
+			 isc_task_t *task, isc_socket_t **socketp)
+{
+	REQUIRE(ISCAPI_SOCKETMGR_VALID(manager));
+
+	return (manager->methods->fdwatchcreate(manager, fd, flags,
+						callback, cbarg, task,
+						socketp));
+}
+
+isc_result_t
+isc_socket_fdwatchpoke(isc_socket_t *sock, int flags)
+{
+	REQUIRE(ISCAPI_SOCKET_VALID(sock));
+
+	return(sock->methods->fdwatchpoke(sock, flags));
+}
diff --git a/src/lib/bind9/sparc64/include/isc/atomic.h b/src/lib/bind9/sparc64/include/isc/atomic.h
new file mode 100644
index 0000000..8d34f76
--- /dev/null
+++ b/src/lib/bind9/sparc64/include/isc/atomic.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: atomic.h,v 1.5 2007-06-19 23:47:18 tbox Exp $ */
+
+/*
+ * This code was written based on FreeBSD's kernel source whose copyright
+ * follows:
+ */
+
+/*-
+ * Copyright (c) 1998 Doug Rabson.
+ * Copyright (c) 2001 Jake Burkholder.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	from: FreeBSD: src/sys/i386/include/atomic.h,v 1.20 2001/02/11
+ * $FreeBSD: src/sys/sparc64/include/atomic.h,v 1.8 2004/05/22 00:52:16 marius Exp $
+ */
+
+#ifndef ISC_ATOMIC_H
+#define ISC_ATOMIC_H 1
+
+#include <isc/platform.h>
+#include <isc/types.h>
+
+#define	ASI_P	0x80		/* Primary Address Space Identifier */
+
+#ifdef ISC_PLATFORM_USEGCCASM
+
+/*
+ * This routine atomically increments the value stored in 'p' by 'val', and
+ * returns the previous value.
+ */
+static inline isc_int32_t
+isc_atomic_xadd(isc_int32_t *p, isc_int32_t val) {
+	isc_int32_t prev, swapped;
+
+	for (prev = *(volatile isc_int32_t *)p; ; prev = swapped) {
+		swapped = prev + val;
+		__asm__ volatile(
+			"casa [%1] %2, %3, %0"
+			: "+r"(swapped)
+			: "r"(p), "n"(ASI_P), "r"(prev));
+		if (swapped == prev)
+			break;
+	}
+
+	return (prev);
+}
+
+/*
+ * This routine atomically stores the value 'val' in 'p'.
+ */
+static inline void
+isc_atomic_store(isc_int32_t *p, isc_int32_t val) {
+	isc_int32_t prev, swapped;
+
+	for (prev = *(volatile isc_int32_t *)p; ; prev = swapped) {
+		swapped = val;
+		__asm__ volatile(
+			"casa [%1] %2, %3, %0"
+			: "+r"(swapped)
+			: "r"(p), "n"(ASI_P), "r"(prev)
+			: "memory");
+		if (swapped == prev)
+			break;
+	}
+}
+
+/*
+ * This routine atomically replaces the value in 'p' with 'val', if the
+ * original value is equal to 'cmpval'.  The original value is returned in any
+ * case.
+ */
+static inline isc_int32_t
+isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) {
+	isc_int32_t temp = val;
+
+	__asm__ volatile(
+		"casa [%1] %2, %3, %0"
+		: "+r"(temp)
+		: "r"(p), "n"(ASI_P), "r"(cmpval));
+
+	return (temp);
+}
+
+#else  /* ISC_PLATFORM_USEGCCASM */
+
+#error "unsupported compiler.  disable atomic ops by --disable-atomic"
+
+#endif /* ISC_PLATFORM_USEGCCASM */
+
+#endif /* ISC_ATOMIC_H */
diff --git a/src/lib/bind9/stats.c b/src/lib/bind9/stats.c
new file mode 100644
index 0000000..e72fb54
--- /dev/null
+++ b/src/lib/bind9/stats.c
@@ -0,0 +1,326 @@
+/*
+ * Copyright (C) 2009  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: stats.c,v 1.3 2009-01-27 23:47:54 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <isc/atomic.h>
+#include <isc/buffer.h>
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/platform.h>
+#include <isc/print.h>
+#include <isc/rwlock.h>
+#include <isc/stats.h>
+#include <isc/util.h>
+
+#define ISC_STATS_MAGIC			ISC_MAGIC('S', 't', 'a', 't')
+#define ISC_STATS_VALID(x)		ISC_MAGIC_VALID(x, ISC_STATS_MAGIC)
+
+#ifndef ISC_STATS_USEMULTIFIELDS
+#if defined(ISC_RWLOCK_USEATOMIC) && defined(ISC_PLATFORM_HAVEXADD) && !defined(ISC_PLATFORM_HAVEXADDQ)
+#define ISC_STATS_USEMULTIFIELDS 1
+#else
+#define ISC_STATS_USEMULTIFIELDS 0
+#endif
+#endif	/* ISC_STATS_USEMULTIFIELDS */
+
+#if ISC_STATS_USEMULTIFIELDS
+typedef struct {
+	isc_uint32_t hi;
+	isc_uint32_t lo;
+} isc_stat_t;
+#else
+typedef isc_uint64_t isc_stat_t;
+#endif
+
+struct isc_stats {
+	/*% Unlocked */
+	unsigned int	magic;
+	isc_mem_t	*mctx;
+	int		ncounters;
+
+	isc_mutex_t	lock;
+	unsigned int	references; /* locked by lock */
+
+	/*%
+	 * Locked by counterlock or unlocked if efficient rwlock is not
+	 * available.
+	 */
+#ifdef ISC_RWLOCK_USEATOMIC
+	isc_rwlock_t	counterlock;
+#endif
+	isc_stat_t	*counters;
+
+	/*%
+	 * We don't want to lock the counters while we are dumping, so we first
+	 * copy the current counter values into a local array.  This buffer
+	 * will be used as the copy destination.  It's allocated on creation
+	 * of the stats structure so that the dump operation won't fail due
+	 * to memory allocation failure.
+	 * XXX: this approach is weird for non-threaded build because the
+	 * additional memory and the copy overhead could be avoided.  We prefer
+	 * simplicity here, however, under the assumption that this function
+	 * should be only rarely called.
+	 */
+	isc_uint64_t	*copiedcounters;
+};
+
+static isc_result_t
+create_stats(isc_mem_t *mctx, int ncounters, isc_stats_t **statsp) {
+	isc_stats_t *stats;
+	isc_result_t result = ISC_R_SUCCESS;
+
+	REQUIRE(statsp != NULL && *statsp == NULL);
+
+	stats = isc_mem_get(mctx, sizeof(*stats));
+	if (stats == NULL)
+		return (ISC_R_NOMEMORY);
+
+	result = isc_mutex_init(&stats->lock);
+	if (result != ISC_R_SUCCESS)
+		goto clean_stats;
+
+	stats->counters = isc_mem_get(mctx, sizeof(isc_stat_t) * ncounters);
+	if (stats->counters == NULL) {
+		result = ISC_R_NOMEMORY;
+		goto clean_mutex;
+	}
+	stats->copiedcounters = isc_mem_get(mctx,
+					    sizeof(isc_uint64_t) * ncounters);
+	if (stats->copiedcounters == NULL) {
+		result = ISC_R_NOMEMORY;
+		goto clean_counters;
+	}
+
+#ifdef ISC_RWLOCK_USEATOMIC
+	result = isc_rwlock_init(&stats->counterlock, 0, 0);
+	if (result != ISC_R_SUCCESS)
+		goto clean_copiedcounters;
+#endif
+
+	stats->references = 1;
+	memset(stats->counters, 0, sizeof(isc_stat_t) * ncounters);
+	stats->mctx = NULL;
+	isc_mem_attach(mctx, &stats->mctx);
+	stats->ncounters = ncounters;
+	stats->magic = ISC_STATS_MAGIC;
+
+	*statsp = stats;
+
+	return (result);
+
+clean_counters:
+	isc_mem_put(mctx, stats->counters, sizeof(isc_stat_t) * ncounters);
+
+#ifdef ISC_RWLOCK_USEATOMIC
+clean_copiedcounters:
+	isc_mem_put(mctx, stats->copiedcounters,
+		    sizeof(isc_stat_t) * ncounters);
+#endif
+
+clean_mutex:
+	DESTROYLOCK(&stats->lock);
+
+clean_stats:
+	isc_mem_put(mctx, stats, sizeof(*stats));
+
+	return (result);
+}
+
+void
+isc_stats_attach(isc_stats_t *stats, isc_stats_t **statsp) {
+	REQUIRE(ISC_STATS_VALID(stats));
+	REQUIRE(statsp != NULL && *statsp == NULL);
+
+	LOCK(&stats->lock);
+	stats->references++;
+	UNLOCK(&stats->lock);
+
+	*statsp = stats;
+}
+
+void
+isc_stats_detach(isc_stats_t **statsp) {
+	isc_stats_t *stats;
+
+	REQUIRE(statsp != NULL && ISC_STATS_VALID(*statsp));
+
+	stats = *statsp;
+	*statsp = NULL;
+
+	LOCK(&stats->lock);
+	stats->references--;
+	UNLOCK(&stats->lock);
+
+	if (stats->references == 0) {
+		isc_mem_put(stats->mctx, stats->copiedcounters,
+			    sizeof(isc_stat_t) * stats->ncounters);
+		isc_mem_put(stats->mctx, stats->counters,
+			    sizeof(isc_stat_t) * stats->ncounters);
+		DESTROYLOCK(&stats->lock);
+#ifdef ISC_RWLOCK_USEATOMIC
+		isc_rwlock_destroy(&stats->counterlock);
+#endif
+		isc_mem_putanddetach(&stats->mctx, stats, sizeof(*stats));
+	}
+}
+
+int
+isc_stats_ncounters(isc_stats_t *stats) {
+	REQUIRE(ISC_STATS_VALID(stats));
+
+	return (stats->ncounters);
+}
+
+static inline void
+incrementcounter(isc_stats_t *stats, int counter) {
+	isc_int32_t prev;
+
+#ifdef ISC_RWLOCK_USEATOMIC
+	/*
+	 * We use a "read" lock to prevent other threads from reading the
+	 * counter while we "writing" a counter field.  The write access itself
+	 * is protected by the atomic operation.
+	 */
+	isc_rwlock_lock(&stats->counterlock, isc_rwlocktype_read);
+#endif
+
+#if ISC_STATS_USEMULTIFIELDS
+	prev = isc_atomic_xadd((isc_int32_t *)&stats->counters[counter].lo, 1);
+	/*
+	 * If the lower 32-bit field overflows, increment the higher field.
+	 * Note that it's *theoretically* possible that the lower field
+	 * overlaps again before the higher field is incremented.  It doesn't
+	 * matter, however, because we don't read the value until
+	 * isc_stats_copy() is called where the whole process is protected
+	 * by the write (exclusive) lock.
+	 */
+	if (prev == (isc_int32_t)0xffffffff)
+		isc_atomic_xadd((isc_int32_t *)&stats->counters[counter].hi, 1);
+#elif defined(ISC_PLATFORM_HAVEXADDQ)
+	UNUSED(prev);
+	isc_atomic_xaddq((isc_int64_t *)&stats->counters[counter], 1);
+#else
+	UNUSED(prev);
+	stats->counters[counter]++;
+#endif
+
+#ifdef ISC_RWLOCK_USEATOMIC
+	isc_rwlock_unlock(&stats->counterlock, isc_rwlocktype_read);
+#endif
+}
+
+static inline void
+decrementcounter(isc_stats_t *stats, int counter) {
+	isc_int32_t prev;
+
+#ifdef ISC_RWLOCK_USEATOMIC
+	isc_rwlock_lock(&stats->counterlock, isc_rwlocktype_read);
+#endif
+
+#if ISC_STATS_USEMULTIFIELDS
+	prev = isc_atomic_xadd((isc_int32_t *)&stats->counters[counter].lo, -1);
+	if (prev == 0)
+		isc_atomic_xadd((isc_int32_t *)&stats->counters[counter].hi,
+				-1);
+#elif defined(ISC_PLATFORM_HAVEXADDQ)
+	UNUSED(prev);
+	isc_atomic_xaddq((isc_int64_t *)&stats->counters[counter], -1);
+#else
+	UNUSED(prev);
+	stats->counters[counter]--;
+#endif
+
+#ifdef ISC_RWLOCK_USEATOMIC
+	isc_rwlock_unlock(&stats->counterlock, isc_rwlocktype_read);
+#endif
+}
+
+static void
+copy_counters(isc_stats_t *stats) {
+	int i;
+
+#ifdef ISC_RWLOCK_USEATOMIC
+	/*
+	 * We use a "write" lock before "reading" the statistics counters as
+	 * an exclusive lock.
+	 */
+	isc_rwlock_lock(&stats->counterlock, isc_rwlocktype_write);
+#endif
+
+#if ISC_STATS_USEMULTIFIELDS
+	for (i = 0; i < stats->ncounters; i++) {
+		stats->copiedcounters[i] =
+				(isc_uint64_t)(stats->counters[i].hi) << 32 |
+				stats->counters[i].lo;
+	}
+#else
+	UNUSED(i);
+	memcpy(stats->copiedcounters, stats->counters,
+	       stats->ncounters * sizeof(isc_stat_t));
+#endif
+
+#ifdef ISC_RWLOCK_USEATOMIC
+	isc_rwlock_unlock(&stats->counterlock, isc_rwlocktype_write);
+#endif
+}
+
+isc_result_t
+isc_stats_create(isc_mem_t *mctx, isc_stats_t **statsp, int ncounters) {
+	REQUIRE(statsp != NULL && *statsp == NULL);
+
+	return (create_stats(mctx, ncounters, statsp));
+}
+
+void
+isc_stats_increment(isc_stats_t *stats, isc_statscounter_t counter) {
+	REQUIRE(ISC_STATS_VALID(stats));
+	REQUIRE(counter < stats->ncounters);
+
+	incrementcounter(stats, (int)counter);
+}
+
+void
+isc_stats_decrement(isc_stats_t *stats, isc_statscounter_t counter) {
+	REQUIRE(ISC_STATS_VALID(stats));
+	REQUIRE(counter < stats->ncounters);
+
+	decrementcounter(stats, (int)counter);
+}
+
+void
+isc_stats_dump(isc_stats_t *stats, isc_stats_dumper_t dump_fn,
+	       void *arg, unsigned int options)
+{
+	int i;
+
+	REQUIRE(ISC_STATS_VALID(stats));
+
+	copy_counters(stats);
+
+	for (i = 0; i < stats->ncounters; i++) {
+		if ((options & ISC_STATSDUMP_VERBOSE) == 0 &&
+		    stats->copiedcounters[i] == 0)
+				continue;
+		dump_fn((isc_statscounter_t)i, stats->copiedcounters[i], arg);
+	}
+}
diff --git a/src/lib/bind9/string.c b/src/lib/bind9/string.c
new file mode 100644
index 0000000..0cad5c7
--- /dev/null
+++ b/src/lib/bind9/string.c
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 2004-2007, 2011  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001, 2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: string.c,v 1.20.814.2 2011-03-12 04:59:18 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <ctype.h>
+
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/region.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+static char digits[] = "0123456789abcdefghijklmnoprstuvwxyz";
+
+isc_uint64_t
+isc_string_touint64(char *source, char **end, int base) {
+	isc_uint64_t tmp;
+	isc_uint64_t overflow;
+	char *s = source;
+	char *o;
+	char c;
+
+	if ((base < 0) || (base == 1) || (base > 36)) {
+		*end = source;
+		return (0);
+	}
+
+	while (*s != 0 && isascii(*s&0xff) && isspace(*s&0xff))
+		s++;
+	if (*s == '+' /* || *s == '-' */)
+		s++;
+	if (base == 0) {
+		if (*s == '0' && (*(s+1) == 'X' || *(s+1) == 'x')) {
+			s += 2;
+			base = 16;
+		} else if (*s == '0')
+			base = 8;
+		else
+			base = 10;
+	}
+	if (*s == 0) {
+		*end = source;
+		return (0);
+	}
+	overflow = ~0;
+	overflow /= base;
+	tmp = 0;
+
+	while ((c = *s) != 0) {
+		c = tolower(c&0xff);
+		/* end ? */
+		if ((o = strchr(digits, c)) == NULL) {
+			*end = s;
+			return (tmp);
+		}
+		/* end ? */
+		if ((o - digits) >= base) {
+			*end = s;
+			return (tmp);
+		}
+		/* overflow ? */
+		if (tmp > overflow) {
+			*end = source;
+			return (0);
+		}
+		tmp *= base;
+		/* overflow ? */
+		if ((tmp + (o - digits)) < tmp) {
+			*end = source;
+			return (0);
+		}
+		tmp += o - digits;
+		s++;
+	}
+	*end = s;
+	return (tmp);
+}
+
+isc_result_t
+isc_string_copy(char *target, size_t size, const char *source) {
+	REQUIRE(size > 0U);
+
+	if (strlcpy(target, source, size) >= size) {
+		memset(target, ISC_STRING_MAGIC, size);
+		return (ISC_R_NOSPACE);
+	}
+
+	ENSURE(strlen(target) < size);
+
+	return (ISC_R_SUCCESS);
+}
+
+void
+isc_string_copy_truncate(char *target, size_t size, const char *source) {
+	REQUIRE(size > 0U);
+
+	strlcpy(target, source, size);
+
+	ENSURE(strlen(target) < size);
+}
+
+isc_result_t
+isc_string_append(char *target, size_t size, const char *source) {
+	REQUIRE(size > 0U);
+	REQUIRE(strlen(target) < size);
+
+	if (strlcat(target, source, size) >= size) {
+		memset(target, ISC_STRING_MAGIC, size);
+		return (ISC_R_NOSPACE);
+	}
+
+	ENSURE(strlen(target) < size);
+
+	return (ISC_R_SUCCESS);
+}
+
+void
+isc_string_append_truncate(char *target, size_t size, const char *source) {
+	REQUIRE(size > 0U);
+	REQUIRE(strlen(target) < size);
+
+	strlcat(target, source, size);
+
+	ENSURE(strlen(target) < size);
+}
+
+isc_result_t
+isc_string_printf(char *target, size_t size, const char *format, ...) {
+	va_list args;
+	size_t n;
+
+	REQUIRE(size > 0U);
+
+	va_start(args, format);
+	n = vsnprintf(target, size, format, args);
+	va_end(args);
+
+	if (n >= size) {
+		memset(target, ISC_STRING_MAGIC, size);
+		return (ISC_R_NOSPACE);
+	}
+
+	ENSURE(strlen(target) < size);
+
+	return (ISC_R_SUCCESS);
+}
+
+void
+isc_string_printf_truncate(char *target, size_t size, const char *format, ...)
+{
+	va_list args;
+
+	REQUIRE(size > 0U);
+
+	va_start(args, format);
+	/* check return code? */
+	(void)vsnprintf(target, size, format, args);
+	va_end(args);
+
+	ENSURE(strlen(target) < size);
+}
+
+char *
+isc_string_regiondup(isc_mem_t *mctx, const isc_region_t *source) {
+	char *target;
+
+	REQUIRE(mctx != NULL);
+	REQUIRE(source != NULL);
+
+	target = (char *) isc_mem_allocate(mctx, source->length + 1);
+	if (target != NULL) {
+		memcpy(source->base, target, source->length);
+		target[source->length] = '\0';
+	}
+
+	return (target);
+}
+
+char *
+isc_string_separate(char **stringp, const char *delim) {
+	char *string = *stringp;
+	char *s;
+	const char *d;
+	char sc, dc;
+
+	if (string == NULL)
+		return (NULL);
+
+	for (s = string; (sc = *s) != '\0'; s++)
+		for (d = delim; (dc = *d) != '\0'; d++)
+			if (sc == dc) {
+				*s++ = '\0';
+				*stringp = s;
+				return (string);
+			}
+	*stringp = NULL;
+	return (string);
+}
+
+size_t
+isc_string_strlcpy(char *dst, const char *src, size_t size)
+{
+	char *d = dst;
+	const char *s = src;
+	size_t n = size;
+
+	/* Copy as many bytes as will fit */
+	if (n != 0U && --n != 0U) {
+		do {
+			if ((*d++ = *s++) == 0)
+				break;
+		} while (--n != 0U);
+	}
+
+	/* Not enough room in dst, add NUL and traverse rest of src */
+	if (n == 0U) {
+		if (size != 0U)
+			*d = '\0';		/* NUL-terminate dst */
+		while (*s++)
+			;
+	}
+
+	return(s - src - 1);	/* count does not include NUL */
+}
+
+size_t
+isc_string_strlcat(char *dst, const char *src, size_t size)
+{
+	char *d = dst;
+	const char *s = src;
+	size_t n = size;
+	size_t dlen;
+
+	/* Find the end of dst and adjust bytes left but don't go past end */
+	while (n-- != 0U && *d != '\0')
+		d++;
+	dlen = d - dst;
+	n = size - dlen;
+
+	if (n == 0U)
+		return(dlen + strlen(s));
+	while (*s != '\0') {
+		if (n != 1U) {
+			*d++ = *s;
+			n--;
+		}
+		s++;
+	}
+	*d = '\0';
+
+	return(dlen + (s - src));	/* count does not include NUL */
+}
diff --git a/src/lib/bind9/strtoul.c b/src/lib/bind9/strtoul.c
new file mode 100644
index 0000000..31a0dde
--- /dev/null
+++ b/src/lib/bind9/strtoul.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*! \file */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strtoul.c	8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+/* $Id: strtoul.c,v 1.7 2007-06-19 23:47:17 tbox Exp $ */
+
+#include <config.h>
+
+#include <limits.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include <isc/stdlib.h>
+#include <isc/util.h>
+
+/*!
+ * Convert a string to an unsigned long integer.
+ *
+ * Ignores `locale' stuff.  Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+unsigned long
+isc_strtoul(const char *nptr, char **endptr, int base) {
+	const char *s = nptr;
+	unsigned long acc;
+	unsigned char c;
+	unsigned long cutoff;
+	int neg = 0, any, cutlim;
+
+	/*
+	 * See strtol for comments as to the logic used.
+	 */
+	do {
+		c = *s++;
+	} while (isspace(c));
+	if (c == '-') {
+		neg = 1;
+		c = *s++;
+	} else if (c == '+')
+		c = *s++;
+	if ((base == 0 || base == 16) &&
+	    c == '0' && (*s == 'x' || *s == 'X')) {
+		c = s[1];
+		s += 2;
+		base = 16;
+	}
+	if (base == 0)
+		base = c == '0' ? 8 : 10;
+	cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
+	cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
+	for (acc = 0, any = 0;; c = *s++) {
+		if (!isascii(c))
+			break;
+		if (isdigit(c))
+			c -= '0';
+		else if (isalpha(c))
+			c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+		else
+			break;
+		if (c >= base)
+			break;
+		if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+			any = -1;
+		else {
+			any = 1;
+			acc *= base;
+			acc += c;
+		}
+	}
+	if (any < 0) {
+		acc = ULONG_MAX;
+		errno = ERANGE;
+	} else if (neg)
+		acc = -acc;
+	if (endptr != 0)
+		DE_CONST(any ? s - 1 : nptr, *endptr);
+	return (acc);
+}
diff --git a/src/lib/bind9/symtab.c b/src/lib/bind9/symtab.c
new file mode 100644
index 0000000..c30054f
--- /dev/null
+++ b/src/lib/bind9/symtab.c
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1996-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: symtab.c,v 1.30 2007-06-19 23:47:17 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <ctype.h>
+
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/string.h>
+#include <isc/symtab.h>
+#include <isc/util.h>
+
+typedef struct elt {
+	char *				key;
+	unsigned int			type;
+	isc_symvalue_t			value;
+	LINK(struct elt)		link;
+} elt_t;
+
+typedef LIST(elt_t)			eltlist_t;
+
+#define SYMTAB_MAGIC			ISC_MAGIC('S', 'y', 'm', 'T')
+#define VALID_SYMTAB(st)		ISC_MAGIC_VALID(st, SYMTAB_MAGIC)
+
+struct isc_symtab {
+	/* Unlocked. */
+	unsigned int			magic;
+	isc_mem_t *			mctx;
+	unsigned int			size;
+	eltlist_t *			table;
+	isc_symtabaction_t		undefine_action;
+	void *				undefine_arg;
+	isc_boolean_t			case_sensitive;
+};
+
+isc_result_t
+isc_symtab_create(isc_mem_t *mctx, unsigned int size,
+		  isc_symtabaction_t undefine_action,
+		  void *undefine_arg,
+		  isc_boolean_t case_sensitive,
+		  isc_symtab_t **symtabp)
+{
+	isc_symtab_t *symtab;
+	unsigned int i;
+
+	REQUIRE(mctx != NULL);
+	REQUIRE(symtabp != NULL && *symtabp == NULL);
+	REQUIRE(size > 0);	/* Should be prime. */
+
+	symtab = (isc_symtab_t *)isc_mem_get(mctx, sizeof(*symtab));
+	if (symtab == NULL)
+		return (ISC_R_NOMEMORY);
+	symtab->table = (eltlist_t *)isc_mem_get(mctx,
+						 size * sizeof(eltlist_t));
+	if (symtab->table == NULL) {
+		isc_mem_put(mctx, symtab, sizeof(*symtab));
+		return (ISC_R_NOMEMORY);
+	}
+	for (i = 0; i < size; i++)
+		INIT_LIST(symtab->table[i]);
+	symtab->mctx = mctx;
+	symtab->size = size;
+	symtab->undefine_action = undefine_action;
+	symtab->undefine_arg = undefine_arg;
+	symtab->case_sensitive = case_sensitive;
+	symtab->magic = SYMTAB_MAGIC;
+
+	*symtabp = symtab;
+
+	return (ISC_R_SUCCESS);
+}
+
+void
+isc_symtab_destroy(isc_symtab_t **symtabp) {
+	isc_symtab_t *symtab;
+	unsigned int i;
+	elt_t *elt, *nelt;
+
+	REQUIRE(symtabp != NULL);
+	symtab = *symtabp;
+	REQUIRE(VALID_SYMTAB(symtab));
+
+	for (i = 0; i < symtab->size; i++) {
+		for (elt = HEAD(symtab->table[i]); elt != NULL; elt = nelt) {
+			nelt = NEXT(elt, link);
+			if (symtab->undefine_action != NULL)
+			       (symtab->undefine_action)(elt->key,
+							 elt->type,
+							 elt->value,
+							 symtab->undefine_arg);
+			isc_mem_put(symtab->mctx, elt, sizeof(*elt));
+		}
+	}
+	isc_mem_put(symtab->mctx, symtab->table,
+		    symtab->size * sizeof(eltlist_t));
+	symtab->magic = 0;
+	isc_mem_put(symtab->mctx, symtab, sizeof(*symtab));
+
+	*symtabp = NULL;
+}
+
+static inline unsigned int
+hash(const char *key, isc_boolean_t case_sensitive) {
+	const char *s;
+	unsigned int h = 0;
+	int c;
+
+	/*
+	 * This hash function is similar to the one Ousterhout
+	 * uses in Tcl.
+	 */
+
+	if (case_sensitive) {
+		for (s = key; *s != '\0'; s++) {
+			h += (h << 3) + *s;
+		}
+	} else {
+		for (s = key; *s != '\0'; s++) {
+			c = *s;
+			c = tolower((unsigned char)c);
+			h += (h << 3) + c;
+		}
+	}
+
+	return (h);
+}
+
+#define FIND(s, k, t, b, e) \
+	b = hash((k), (s)->case_sensitive) % (s)->size; \
+	if ((s)->case_sensitive) { \
+		for (e = HEAD((s)->table[b]); e != NULL; e = NEXT(e, link)) { \
+			if (((t) == 0 || e->type == (t)) && \
+			    strcmp(e->key, (k)) == 0) \
+				break; \
+		} \
+	} else { \
+		for (e = HEAD((s)->table[b]); e != NULL; e = NEXT(e, link)) { \
+			if (((t) == 0 || e->type == (t)) && \
+			    strcasecmp(e->key, (k)) == 0) \
+				break; \
+		} \
+	}
+
+isc_result_t
+isc_symtab_lookup(isc_symtab_t *symtab, const char *key, unsigned int type,
+		  isc_symvalue_t *value)
+{
+	unsigned int bucket;
+	elt_t *elt;
+
+	REQUIRE(VALID_SYMTAB(symtab));
+	REQUIRE(key != NULL);
+
+	FIND(symtab, key, type, bucket, elt);
+
+	if (elt == NULL)
+		return (ISC_R_NOTFOUND);
+
+	if (value != NULL)
+		*value = elt->value;
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_symtab_define(isc_symtab_t *symtab, const char *key, unsigned int type,
+		  isc_symvalue_t value, isc_symexists_t exists_policy)
+{
+	unsigned int bucket;
+	elt_t *elt;
+
+	REQUIRE(VALID_SYMTAB(symtab));
+	REQUIRE(key != NULL);
+	REQUIRE(type != 0);
+
+	FIND(symtab, key, type, bucket, elt);
+
+	if (exists_policy != isc_symexists_add && elt != NULL) {
+		if (exists_policy == isc_symexists_reject)
+			return (ISC_R_EXISTS);
+		INSIST(exists_policy == isc_symexists_replace);
+		UNLINK(symtab->table[bucket], elt, link);
+		if (symtab->undefine_action != NULL)
+			(symtab->undefine_action)(elt->key, elt->type,
+						  elt->value,
+						  symtab->undefine_arg);
+	} else {
+		elt = (elt_t *)isc_mem_get(symtab->mctx, sizeof(*elt));
+		if (elt == NULL)
+			return (ISC_R_NOMEMORY);
+		ISC_LINK_INIT(elt, link);
+	}
+
+	/*
+	 * Though the "key" can be const coming in, it is not stored as const
+	 * so that the calling program can easily have writable access to
+	 * it in its undefine_action function.  In the event that it *was*
+	 * truly const coming in and then the caller modified it anyway ...
+	 * well, don't do that!
+	 */
+	DE_CONST(key, elt->key);
+	elt->type = type;
+	elt->value = value;
+
+	/*
+	 * We prepend so that the most recent definition will be found.
+	 */
+	PREPEND(symtab->table[bucket], elt, link);
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_symtab_undefine(isc_symtab_t *symtab, const char *key, unsigned int type) {
+	unsigned int bucket;
+	elt_t *elt;
+
+	REQUIRE(VALID_SYMTAB(symtab));
+	REQUIRE(key != NULL);
+
+	FIND(symtab, key, type, bucket, elt);
+
+	if (elt == NULL)
+		return (ISC_R_NOTFOUND);
+
+	if (symtab->undefine_action != NULL)
+		(symtab->undefine_action)(elt->key, elt->type,
+					  elt->value, symtab->undefine_arg);
+	UNLINK(symtab->table[bucket], elt, link);
+	isc_mem_put(symtab->mctx, elt, sizeof(*elt));
+
+	return (ISC_R_SUCCESS);
+}
diff --git a/src/lib/bind9/task.c b/src/lib/bind9/task.c
new file mode 100644
index 0000000..913e707
--- /dev/null
+++ b/src/lib/bind9/task.c
@@ -0,0 +1,1578 @@
+/*
+ * Copyright (C) 2004-2011  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: task.c,v 1.115.14.2 2011-02-28 01:20:03 tbox Exp $ */
+
+/*! \file
+ * \author Principal Author: Bob Halley
+ */
+
+/*
+ * XXXRTH  Need to document the states a task can be in, and the rules
+ * for changing states.
+ */
+
+#include <config.h>
+
+#include <isc/condition.h>
+#include <isc/event.h>
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/msgs.h>
+#include <isc/platform.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/thread.h>
+#include <isc/util.h>
+#include <isc/xml.h>
+
+#ifdef OPENSSL_LEAKS
+#include <openssl/err.h>
+#endif
+
+/*%
+ * For BIND9 internal applications:
+ * when built with threads we use multiple worker threads shared by the whole
+ * application.
+ * when built without threads we share a single global task manager and use
+ * an integrated event loop for socket, timer, and other generic task events.
+ * For generic library:
+ * we don't use either of them: an application can have multiple task managers
+ * whether or not it's threaded, and if the application is threaded each thread
+ * is expected to have a separate manager; no "worker threads" are shared by
+ * the application threads.
+ */
+#ifdef BIND9
+#ifdef ISC_PLATFORM_USETHREADS
+#define USE_WORKER_THREADS
+#else
+#define USE_SHARED_MANAGER
+#endif	/* ISC_PLATFORM_USETHREADS */
+#endif	/* BIND9 */
+
+#ifndef USE_WORKER_THREADS
+#include "task_p.h"
+#endif /* USE_WORKER_THREADS */
+
+#ifdef ISC_TASK_TRACE
+#define XTRACE(m)		fprintf(stderr, "task %p thread %lu: %s\n", \
+				       task, isc_thread_self(), (m))
+#define XTTRACE(t, m)		fprintf(stderr, "task %p thread %lu: %s\n", \
+				       (t), isc_thread_self(), (m))
+#define XTHREADTRACE(m)		fprintf(stderr, "thread %lu: %s\n", \
+				       isc_thread_self(), (m))
+#else
+#define XTRACE(m)
+#define XTTRACE(t, m)
+#define XTHREADTRACE(m)
+#endif
+
+/***
+ *** Types.
+ ***/
+
+typedef enum {
+	task_state_idle, task_state_ready, task_state_running,
+	task_state_done
+} task_state_t;
+
+#if defined(HAVE_LIBXML2) && defined(BIND9)
+static const char *statenames[] = {
+	"idle", "ready", "running", "done",
+};
+#endif
+
+#define TASK_MAGIC			ISC_MAGIC('T', 'A', 'S', 'K')
+#define VALID_TASK(t)			ISC_MAGIC_VALID(t, TASK_MAGIC)
+
+typedef struct isc__task isc__task_t;
+typedef struct isc__taskmgr isc__taskmgr_t;
+
+struct isc__task {
+	/* Not locked. */
+	isc_task_t			common;
+	isc__taskmgr_t *		manager;
+	isc_mutex_t			lock;
+	/* Locked by task lock. */
+	task_state_t			state;
+	unsigned int			references;
+	isc_eventlist_t			events;
+	isc_eventlist_t			on_shutdown;
+	unsigned int			quantum;
+	unsigned int			flags;
+	isc_stdtime_t			now;
+	char				name[16];
+	void *				tag;
+	/* Locked by task manager lock. */
+	LINK(isc__task_t)		link;
+	LINK(isc__task_t)		ready_link;
+};
+
+#define TASK_F_SHUTTINGDOWN		0x01
+
+#define TASK_SHUTTINGDOWN(t)		(((t)->flags & TASK_F_SHUTTINGDOWN) \
+					 != 0)
+
+#define TASK_MANAGER_MAGIC		ISC_MAGIC('T', 'S', 'K', 'M')
+#define VALID_MANAGER(m)		ISC_MAGIC_VALID(m, TASK_MANAGER_MAGIC)
+
+typedef ISC_LIST(isc__task_t)	isc__tasklist_t;
+
+struct isc__taskmgr {
+	/* Not locked. */
+	isc_taskmgr_t			common;
+	isc_mem_t *			mctx;
+	isc_mutex_t			lock;
+#ifdef ISC_PLATFORM_USETHREADS
+	unsigned int			workers;
+	isc_thread_t *			threads;
+#endif /* ISC_PLATFORM_USETHREADS */
+	/* Locked by task manager lock. */
+	unsigned int			default_quantum;
+	LIST(isc__task_t)		tasks;
+	isc__tasklist_t			ready_tasks;
+#ifdef ISC_PLATFORM_USETHREADS
+	isc_condition_t			work_available;
+	isc_condition_t			exclusive_granted;
+#endif /* ISC_PLATFORM_USETHREADS */
+	unsigned int			tasks_running;
+	isc_boolean_t			exclusive_requested;
+	isc_boolean_t			exiting;
+#ifdef USE_SHARED_MANAGER
+	unsigned int			refs;
+#endif /* ISC_PLATFORM_USETHREADS */
+};
+
+#define DEFAULT_TASKMGR_QUANTUM		10
+#define DEFAULT_DEFAULT_QUANTUM		5
+#define FINISHED(m)			((m)->exiting && EMPTY((m)->tasks))
+
+#ifdef USE_SHARED_MANAGER
+static isc__taskmgr_t *taskmgr = NULL;
+#endif /* USE_SHARED_MANAGER */
+
+/*%
+ * The following can be either static or public, depending on build environment.
+ */
+
+#ifdef BIND9
+#define ISC_TASKFUNC_SCOPE
+#else
+#define ISC_TASKFUNC_SCOPE static
+#endif
+
+ISC_TASKFUNC_SCOPE isc_result_t
+isc__task_create(isc_taskmgr_t *manager0, unsigned int quantum,
+		 isc_task_t **taskp);
+ISC_TASKFUNC_SCOPE void
+isc__task_attach(isc_task_t *source0, isc_task_t **targetp);
+ISC_TASKFUNC_SCOPE void
+isc__task_detach(isc_task_t **taskp);
+ISC_TASKFUNC_SCOPE void
+isc__task_send(isc_task_t *task0, isc_event_t **eventp);
+ISC_TASKFUNC_SCOPE void
+isc__task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp);
+ISC_TASKFUNC_SCOPE unsigned int
+isc__task_purgerange(isc_task_t *task0, void *sender, isc_eventtype_t first,
+		     isc_eventtype_t last, void *tag);
+ISC_TASKFUNC_SCOPE unsigned int
+isc__task_purge(isc_task_t *task, void *sender, isc_eventtype_t type,
+		void *tag);
+ISC_TASKFUNC_SCOPE isc_boolean_t
+isc__task_purgeevent(isc_task_t *task0, isc_event_t *event);
+ISC_TASKFUNC_SCOPE unsigned int
+isc__task_unsendrange(isc_task_t *task, void *sender, isc_eventtype_t first,
+		      isc_eventtype_t last, void *tag,
+		      isc_eventlist_t *events);
+ISC_TASKFUNC_SCOPE unsigned int
+isc__task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type,
+		 void *tag, isc_eventlist_t *events);
+ISC_TASKFUNC_SCOPE isc_result_t
+isc__task_onshutdown(isc_task_t *task0, isc_taskaction_t action,
+		     const void *arg);
+ISC_TASKFUNC_SCOPE void
+isc__task_shutdown(isc_task_t *task0);
+ISC_TASKFUNC_SCOPE void
+isc__task_destroy(isc_task_t **taskp);
+ISC_TASKFUNC_SCOPE void
+isc__task_setname(isc_task_t *task0, const char *name, void *tag);
+ISC_TASKFUNC_SCOPE const char *
+isc__task_getname(isc_task_t *task0);
+ISC_TASKFUNC_SCOPE void *
+isc__task_gettag(isc_task_t *task0);
+ISC_TASKFUNC_SCOPE void
+isc__task_getcurrenttime(isc_task_t *task0, isc_stdtime_t *t);
+ISC_TASKFUNC_SCOPE isc_result_t
+isc__taskmgr_create(isc_mem_t *mctx, unsigned int workers,
+		    unsigned int default_quantum, isc_taskmgr_t **managerp);
+ISC_TASKFUNC_SCOPE void
+isc__taskmgr_destroy(isc_taskmgr_t **managerp);
+ISC_TASKFUNC_SCOPE isc_result_t
+isc__task_beginexclusive(isc_task_t *task);
+ISC_TASKFUNC_SCOPE void
+isc__task_endexclusive(isc_task_t *task0);
+
+static struct isc__taskmethods {
+	isc_taskmethods_t methods;
+
+	/*%
+	 * The following are defined just for avoiding unused static functions.
+	 */
+#ifndef BIND9
+	void *purgeevent, *unsendrange, *getname, *gettag, *getcurrenttime;
+#endif
+} taskmethods = {
+	{
+		isc__task_attach,
+		isc__task_detach,
+		isc__task_destroy,
+		isc__task_send,
+		isc__task_sendanddetach,
+		isc__task_unsend,
+		isc__task_onshutdown,
+		isc__task_shutdown,
+		isc__task_setname,
+		isc__task_purge,
+		isc__task_purgerange,
+		isc__task_beginexclusive,
+		isc__task_endexclusive
+	}
+#ifndef BIND9
+	,
+	(void *)isc__task_purgeevent, (void *)isc__task_unsendrange,
+	(void *)isc__task_getname, (void *)isc__task_gettag,
+	(void *)isc__task_getcurrenttime
+#endif
+};
+
+static isc_taskmgrmethods_t taskmgrmethods = {
+	isc__taskmgr_destroy,
+	isc__task_create
+};
+
+/***
+ *** Tasks.
+ ***/
+
+static void
+task_finished(isc__task_t *task) {
+	isc__taskmgr_t *manager = task->manager;
+
+	REQUIRE(EMPTY(task->events));
+	REQUIRE(EMPTY(task->on_shutdown));
+	REQUIRE(task->references == 0);
+	REQUIRE(task->state == task_state_done);
+
+	XTRACE("task_finished");
+
+	LOCK(&manager->lock);
+	UNLINK(manager->tasks, task, link);
+#ifdef USE_WORKER_THREADS
+	if (FINISHED(manager)) {
+		/*
+		 * All tasks have completed and the
+		 * task manager is exiting.  Wake up
+		 * any idle worker threads so they
+		 * can exit.
+		 */
+		BROADCAST(&manager->work_available);
+	}
+#endif /* USE_WORKER_THREADS */
+	UNLOCK(&manager->lock);
+
+	DESTROYLOCK(&task->lock);
+	task->common.impmagic = 0;
+	task->common.magic = 0;
+	isc_mem_put(manager->mctx, task, sizeof(*task));
+}
+
+ISC_TASKFUNC_SCOPE isc_result_t
+isc__task_create(isc_taskmgr_t *manager0, unsigned int quantum,
+		 isc_task_t **taskp)
+{
+	isc__taskmgr_t *manager = (isc__taskmgr_t *)manager0;
+	isc__task_t *task;
+	isc_boolean_t exiting;
+	isc_result_t result;
+
+	REQUIRE(VALID_MANAGER(manager));
+	REQUIRE(taskp != NULL && *taskp == NULL);
+
+	task = isc_mem_get(manager->mctx, sizeof(*task));
+	if (task == NULL)
+		return (ISC_R_NOMEMORY);
+	XTRACE("isc_task_create");
+	task->manager = manager;
+	result = isc_mutex_init(&task->lock);
+	if (result != ISC_R_SUCCESS) {
+		isc_mem_put(manager->mctx, task, sizeof(*task));
+		return (result);
+	}
+	task->state = task_state_idle;
+	task->references = 1;
+	INIT_LIST(task->events);
+	INIT_LIST(task->on_shutdown);
+	task->quantum = quantum;
+	task->flags = 0;
+	task->now = 0;
+	memset(task->name, 0, sizeof(task->name));
+	task->tag = NULL;
+	INIT_LINK(task, link);
+	INIT_LINK(task, ready_link);
+
+	exiting = ISC_FALSE;
+	LOCK(&manager->lock);
+	if (!manager->exiting) {
+		if (task->quantum == 0)
+			task->quantum = manager->default_quantum;
+		APPEND(manager->tasks, task, link);
+	} else
+		exiting = ISC_TRUE;
+	UNLOCK(&manager->lock);
+
+	if (exiting) {
+		DESTROYLOCK(&task->lock);
+		isc_mem_put(manager->mctx, task, sizeof(*task));
+		return (ISC_R_SHUTTINGDOWN);
+	}
+
+	task->common.methods = (isc_taskmethods_t *)&taskmethods;
+	task->common.magic = ISCAPI_TASK_MAGIC;
+	task->common.impmagic = TASK_MAGIC;
+	*taskp = (isc_task_t *)task;
+
+	return (ISC_R_SUCCESS);
+}
+
+ISC_TASKFUNC_SCOPE void
+isc__task_attach(isc_task_t *source0, isc_task_t **targetp) {
+	isc__task_t *source = (isc__task_t *)source0;
+
+	/*
+	 * Attach *targetp to source.
+	 */
+
+	REQUIRE(VALID_TASK(source));
+	REQUIRE(targetp != NULL && *targetp == NULL);
+
+	XTTRACE(source, "isc_task_attach");
+
+	LOCK(&source->lock);
+	source->references++;
+	UNLOCK(&source->lock);
+
+	*targetp = (isc_task_t *)source;
+}
+
+static inline isc_boolean_t
+task_shutdown(isc__task_t *task) {
+	isc_boolean_t was_idle = ISC_FALSE;
+	isc_event_t *event, *prev;
+
+	/*
+	 * Caller must be holding the task's lock.
+	 */
+
+	XTRACE("task_shutdown");
+
+	if (! TASK_SHUTTINGDOWN(task)) {
+		XTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+				      ISC_MSG_SHUTTINGDOWN, "shutting down"));
+		task->flags |= TASK_F_SHUTTINGDOWN;
+		if (task->state == task_state_idle) {
+			INSIST(EMPTY(task->events));
+			task->state = task_state_ready;
+			was_idle = ISC_TRUE;
+		}
+		INSIST(task->state == task_state_ready ||
+		       task->state == task_state_running);
+		/*
+		 * Note that we post shutdown events LIFO.
+		 */
+		for (event = TAIL(task->on_shutdown);
+		     event != NULL;
+		     event = prev) {
+			prev = PREV(event, ev_link);
+			DEQUEUE(task->on_shutdown, event, ev_link);
+			ENQUEUE(task->events, event, ev_link);
+		}
+	}
+
+	return (was_idle);
+}
+
+static inline void
+task_ready(isc__task_t *task) {
+	isc__taskmgr_t *manager = task->manager;
+
+	REQUIRE(VALID_MANAGER(manager));
+	REQUIRE(task->state == task_state_ready);
+
+	XTRACE("task_ready");
+
+	LOCK(&manager->lock);
+
+	ENQUEUE(manager->ready_tasks, task, ready_link);
+#ifdef USE_WORKER_THREADS
+	SIGNAL(&manager->work_available);
+#endif /* USE_WORKER_THREADS */
+
+	UNLOCK(&manager->lock);
+}
+
+static inline isc_boolean_t
+task_detach(isc__task_t *task) {
+
+	/*
+	 * Caller must be holding the task lock.
+	 */
+
+	REQUIRE(task->references > 0);
+
+	XTRACE("detach");
+
+	task->references--;
+	if (task->references == 0 && task->state == task_state_idle) {
+		INSIST(EMPTY(task->events));
+		/*
+		 * There are no references to this task, and no
+		 * pending events.  We could try to optimize and
+		 * either initiate shutdown or clean up the task,
+		 * depending on its state, but it's easier to just
+		 * make the task ready and allow run() or the event
+		 * loop to deal with shutting down and termination.
+		 */
+		task->state = task_state_ready;
+		return (ISC_TRUE);
+	}
+
+	return (ISC_FALSE);
+}
+
+ISC_TASKFUNC_SCOPE void
+isc__task_detach(isc_task_t **taskp) {
+	isc__task_t *task;
+	isc_boolean_t was_idle;
+
+	/*
+	 * Detach *taskp from its task.
+	 */
+
+	REQUIRE(taskp != NULL);
+	task = (isc__task_t *)*taskp;
+	REQUIRE(VALID_TASK(task));
+
+	XTRACE("isc_task_detach");
+
+	LOCK(&task->lock);
+	was_idle = task_detach(task);
+	UNLOCK(&task->lock);
+
+	if (was_idle)
+		task_ready(task);
+
+	*taskp = NULL;
+}
+
+static inline isc_boolean_t
+task_send(isc__task_t *task, isc_event_t **eventp) {
+	isc_boolean_t was_idle = ISC_FALSE;
+	isc_event_t *event;
+
+	/*
+	 * Caller must be holding the task lock.
+	 */
+
+	REQUIRE(eventp != NULL);
+	event = *eventp;
+	REQUIRE(event != NULL);
+	REQUIRE(event->ev_type > 0);
+	REQUIRE(task->state != task_state_done);
+
+	XTRACE("task_send");
+
+	if (task->state == task_state_idle) {
+		was_idle = ISC_TRUE;
+		INSIST(EMPTY(task->events));
+		task->state = task_state_ready;
+	}
+	INSIST(task->state == task_state_ready ||
+	       task->state == task_state_running);
+	ENQUEUE(task->events, event, ev_link);
+	*eventp = NULL;
+
+	return (was_idle);
+}
+
+ISC_TASKFUNC_SCOPE void
+isc__task_send(isc_task_t *task0, isc_event_t **eventp) {
+	isc__task_t *task = (isc__task_t *)task0;
+	isc_boolean_t was_idle;
+
+	/*
+	 * Send '*event' to 'task'.
+	 */
+
+	REQUIRE(VALID_TASK(task));
+
+	XTRACE("isc_task_send");
+
+	/*
+	 * We're trying hard to hold locks for as short a time as possible.
+	 * We're also trying to hold as few locks as possible.  This is why
+	 * some processing is deferred until after the lock is released.
+	 */
+	LOCK(&task->lock);
+	was_idle = task_send(task, eventp);
+	UNLOCK(&task->lock);
+
+	if (was_idle) {
+		/*
+		 * We need to add this task to the ready queue.
+		 *
+		 * We've waited until now to do it because making a task
+		 * ready requires locking the manager.  If we tried to do
+		 * this while holding the task lock, we could deadlock.
+		 *
+		 * We've changed the state to ready, so no one else will
+		 * be trying to add this task to the ready queue.  The
+		 * only way to leave the ready state is by executing the
+		 * task.  It thus doesn't matter if events are added,
+		 * removed, or a shutdown is started in the interval
+		 * between the time we released the task lock, and the time
+		 * we add the task to the ready queue.
+		 */
+		task_ready(task);
+	}
+}
+
+ISC_TASKFUNC_SCOPE void
+isc__task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp) {
+	isc_boolean_t idle1, idle2;
+	isc__task_t *task;
+
+	/*
+	 * Send '*event' to '*taskp' and then detach '*taskp' from its
+	 * task.
+	 */
+
+	REQUIRE(taskp != NULL);
+	task = (isc__task_t *)*taskp;
+	REQUIRE(VALID_TASK(task));
+
+	XTRACE("isc_task_sendanddetach");
+
+	LOCK(&task->lock);
+	idle1 = task_send(task, eventp);
+	idle2 = task_detach(task);
+	UNLOCK(&task->lock);
+
+	/*
+	 * If idle1, then idle2 shouldn't be true as well since we're holding
+	 * the task lock, and thus the task cannot switch from ready back to
+	 * idle.
+	 */
+	INSIST(!(idle1 && idle2));
+
+	if (idle1 || idle2)
+		task_ready(task);
+
+	*taskp = NULL;
+}
+
+#define PURGE_OK(event)	(((event)->ev_attributes & ISC_EVENTATTR_NOPURGE) == 0)
+
+static unsigned int
+dequeue_events(isc__task_t *task, void *sender, isc_eventtype_t first,
+	       isc_eventtype_t last, void *tag,
+	       isc_eventlist_t *events, isc_boolean_t purging)
+{
+	isc_event_t *event, *next_event;
+	unsigned int count = 0;
+
+	REQUIRE(VALID_TASK(task));
+	REQUIRE(last >= first);
+
+	XTRACE("dequeue_events");
+
+	/*
+	 * Events matching 'sender', whose type is >= first and <= last, and
+	 * whose tag is 'tag' will be dequeued.  If 'purging', matching events
+	 * which are marked as unpurgable will not be dequeued.
+	 *
+	 * sender == NULL means "any sender", and tag == NULL means "any tag".
+	 */
+
+	LOCK(&task->lock);
+
+	for (event = HEAD(task->events); event != NULL; event = next_event) {
+		next_event = NEXT(event, ev_link);
+		if (event->ev_type >= first && event->ev_type <= last &&
+		    (sender == NULL || event->ev_sender == sender) &&
+		    (tag == NULL || event->ev_tag == tag) &&
+		    (!purging || PURGE_OK(event))) {
+			DEQUEUE(task->events, event, ev_link);
+			ENQUEUE(*events, event, ev_link);
+			count++;
+		}
+	}
+
+	UNLOCK(&task->lock);
+
+	return (count);
+}
+
+ISC_TASKFUNC_SCOPE unsigned int
+isc__task_purgerange(isc_task_t *task0, void *sender, isc_eventtype_t first,
+		     isc_eventtype_t last, void *tag)
+{
+	isc__task_t *task = (isc__task_t *)task0;
+	unsigned int count;
+	isc_eventlist_t events;
+	isc_event_t *event, *next_event;
+
+	/*
+	 * Purge events from a task's event queue.
+	 */
+
+	XTRACE("isc_task_purgerange");
+
+	ISC_LIST_INIT(events);
+
+	count = dequeue_events(task, sender, first, last, tag, &events,
+			       ISC_TRUE);
+
+	for (event = HEAD(events); event != NULL; event = next_event) {
+		next_event = NEXT(event, ev_link);
+		isc_event_free(&event);
+	}
+
+	/*
+	 * Note that purging never changes the state of the task.
+	 */
+
+	return (count);
+}
+
+ISC_TASKFUNC_SCOPE unsigned int
+isc__task_purge(isc_task_t *task, void *sender, isc_eventtype_t type,
+		void *tag)
+{
+	/*
+	 * Purge events from a task's event queue.
+	 */
+
+	XTRACE("isc_task_purge");
+
+	return (isc__task_purgerange(task, sender, type, type, tag));
+}
+
+ISC_TASKFUNC_SCOPE isc_boolean_t
+isc__task_purgeevent(isc_task_t *task0, isc_event_t *event) {
+	isc__task_t *task = (isc__task_t *)task0;
+	isc_event_t *curr_event, *next_event;
+
+	/*
+	 * Purge 'event' from a task's event queue.
+	 *
+	 * XXXRTH:  WARNING:  This method may be removed before beta.
+	 */
+
+	REQUIRE(VALID_TASK(task));
+
+	/*
+	 * If 'event' is on the task's event queue, it will be purged,
+	 * unless it is marked as unpurgeable.  'event' does not have to be
+	 * on the task's event queue; in fact, it can even be an invalid
+	 * pointer.  Purging only occurs if the event is actually on the task's
+	 * event queue.
+	 *
+	 * Purging never changes the state of the task.
+	 */
+
+	LOCK(&task->lock);
+	for (curr_event = HEAD(task->events);
+	     curr_event != NULL;
+	     curr_event = next_event) {
+		next_event = NEXT(curr_event, ev_link);
+		if (curr_event == event && PURGE_OK(event)) {
+			DEQUEUE(task->events, curr_event, ev_link);
+			break;
+		}
+	}
+	UNLOCK(&task->lock);
+
+	if (curr_event == NULL)
+		return (ISC_FALSE);
+
+	isc_event_free(&curr_event);
+
+	return (ISC_TRUE);
+}
+
+ISC_TASKFUNC_SCOPE unsigned int
+isc__task_unsendrange(isc_task_t *task, void *sender, isc_eventtype_t first,
+		      isc_eventtype_t last, void *tag,
+		      isc_eventlist_t *events)
+{
+	/*
+	 * Remove events from a task's event queue.
+	 */
+
+	XTRACE("isc_task_unsendrange");
+
+	return (dequeue_events((isc__task_t *)task, sender, first,
+			       last, tag, events, ISC_FALSE));
+}
+
+ISC_TASKFUNC_SCOPE unsigned int
+isc__task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type,
+		 void *tag, isc_eventlist_t *events)
+{
+	/*
+	 * Remove events from a task's event queue.
+	 */
+
+	XTRACE("isc_task_unsend");
+
+	return (dequeue_events((isc__task_t *)task, sender, type,
+			       type, tag, events, ISC_FALSE));
+}
+
+ISC_TASKFUNC_SCOPE isc_result_t
+isc__task_onshutdown(isc_task_t *task0, isc_taskaction_t action,
+		     const void *arg)
+{
+	isc__task_t *task = (isc__task_t *)task0;
+	isc_boolean_t disallowed = ISC_FALSE;
+	isc_result_t result = ISC_R_SUCCESS;
+	isc_event_t *event;
+
+	/*
+	 * Send a shutdown event with action 'action' and argument 'arg' when
+	 * 'task' is shutdown.
+	 */
+
+	REQUIRE(VALID_TASK(task));
+	REQUIRE(action != NULL);
+
+	event = isc_event_allocate(task->manager->mctx,
+				   NULL,
+				   ISC_TASKEVENT_SHUTDOWN,
+				   action,
+				   arg,
+				   sizeof(*event));
+	if (event == NULL)
+		return (ISC_R_NOMEMORY);
+
+	LOCK(&task->lock);
+	if (TASK_SHUTTINGDOWN(task)) {
+		disallowed = ISC_TRUE;
+		result = ISC_R_SHUTTINGDOWN;
+	} else
+		ENQUEUE(task->on_shutdown, event, ev_link);
+	UNLOCK(&task->lock);
+
+	if (disallowed)
+		isc_mem_put(task->manager->mctx, event, sizeof(*event));
+
+	return (result);
+}
+
+ISC_TASKFUNC_SCOPE void
+isc__task_shutdown(isc_task_t *task0) {
+	isc__task_t *task = (isc__task_t *)task0;
+	isc_boolean_t was_idle;
+
+	/*
+	 * Shutdown 'task'.
+	 */
+
+	REQUIRE(VALID_TASK(task));
+
+	LOCK(&task->lock);
+	was_idle = task_shutdown(task);
+	UNLOCK(&task->lock);
+
+	if (was_idle)
+		task_ready(task);
+}
+
+ISC_TASKFUNC_SCOPE void
+isc__task_destroy(isc_task_t **taskp) {
+
+	/*
+	 * Destroy '*taskp'.
+	 */
+
+	REQUIRE(taskp != NULL);
+
+	isc_task_shutdown(*taskp);
+	isc_task_detach(taskp);
+}
+
+ISC_TASKFUNC_SCOPE void
+isc__task_setname(isc_task_t *task0, const char *name, void *tag) {
+	isc__task_t *task = (isc__task_t *)task0;
+
+	/*
+	 * Name 'task'.
+	 */
+
+	REQUIRE(VALID_TASK(task));
+
+	LOCK(&task->lock);
+	memset(task->name, 0, sizeof(task->name));
+	strncpy(task->name, name, sizeof(task->name) - 1);
+	task->tag = tag;
+	UNLOCK(&task->lock);
+}
+
+ISC_TASKFUNC_SCOPE const char *
+isc__task_getname(isc_task_t *task0) {
+	isc__task_t *task = (isc__task_t *)task0;
+
+	REQUIRE(VALID_TASK(task));
+
+	return (task->name);
+}
+
+ISC_TASKFUNC_SCOPE void *
+isc__task_gettag(isc_task_t *task0) {
+	isc__task_t *task = (isc__task_t *)task0;
+
+	REQUIRE(VALID_TASK(task));
+
+	return (task->tag);
+}
+
+ISC_TASKFUNC_SCOPE void
+isc__task_getcurrenttime(isc_task_t *task0, isc_stdtime_t *t) {
+	isc__task_t *task = (isc__task_t *)task0;
+
+	REQUIRE(VALID_TASK(task));
+	REQUIRE(t != NULL);
+
+	LOCK(&task->lock);
+
+	*t = task->now;
+
+	UNLOCK(&task->lock);
+}
+
+/***
+ *** Task Manager.
+ ***/
+static void
+dispatch(isc__taskmgr_t *manager) {
+	isc__task_t *task;
+#ifndef USE_WORKER_THREADS
+	unsigned int total_dispatch_count = 0;
+	isc__tasklist_t ready_tasks;
+#endif /* USE_WORKER_THREADS */
+
+	REQUIRE(VALID_MANAGER(manager));
+
+	/*
+	 * Again we're trying to hold the lock for as short a time as possible
+	 * and to do as little locking and unlocking as possible.
+	 *
+	 * In both while loops, the appropriate lock must be held before the
+	 * while body starts.  Code which acquired the lock at the top of
+	 * the loop would be more readable, but would result in a lot of
+	 * extra locking.  Compare:
+	 *
+	 * Straightforward:
+	 *
+	 *	LOCK();
+	 *	...
+	 *	UNLOCK();
+	 *	while (expression) {
+	 *		LOCK();
+	 *		...
+	 *		UNLOCK();
+	 *
+	 *	       	Unlocked part here...
+	 *
+	 *		LOCK();
+	 *		...
+	 *		UNLOCK();
+	 *	}
+	 *
+	 * Note how if the loop continues we unlock and then immediately lock.
+	 * For N iterations of the loop, this code does 2N+1 locks and 2N+1
+	 * unlocks.  Also note that the lock is not held when the while
+	 * condition is tested, which may or may not be important, depending
+	 * on the expression.
+	 *
+	 * As written:
+	 *
+	 *	LOCK();
+	 *	while (expression) {
+	 *		...
+	 *		UNLOCK();
+	 *
+	 *	       	Unlocked part here...
+	 *
+	 *		LOCK();
+	 *		...
+	 *	}
+	 *	UNLOCK();
+	 *
+	 * For N iterations of the loop, this code does N+1 locks and N+1
+	 * unlocks.  The while expression is always protected by the lock.
+	 */
+
+#ifndef USE_WORKER_THREADS
+	ISC_LIST_INIT(ready_tasks);
+#endif
+	LOCK(&manager->lock);
+	while (!FINISHED(manager)) {
+#ifdef USE_WORKER_THREADS
+		/*
+		 * For reasons similar to those given in the comment in
+		 * isc_task_send() above, it is safe for us to dequeue
+		 * the task while only holding the manager lock, and then
+		 * change the task to running state while only holding the
+		 * task lock.
+		 */
+		while ((EMPTY(manager->ready_tasks) ||
+			manager->exclusive_requested) &&
+			!FINISHED(manager))
+		{
+			XTHREADTRACE(isc_msgcat_get(isc_msgcat,
+						    ISC_MSGSET_GENERAL,
+						    ISC_MSG_WAIT, "wait"));
+			WAIT(&manager->work_available, &manager->lock);
+			XTHREADTRACE(isc_msgcat_get(isc_msgcat,
+						    ISC_MSGSET_TASK,
+						    ISC_MSG_AWAKE, "awake"));
+		}
+#else /* USE_WORKER_THREADS */
+		if (total_dispatch_count >= DEFAULT_TASKMGR_QUANTUM ||
+		    EMPTY(manager->ready_tasks))
+			break;
+#endif /* USE_WORKER_THREADS */
+		XTHREADTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TASK,
+					    ISC_MSG_WORKING, "working"));
+
+		task = HEAD(manager->ready_tasks);
+		if (task != NULL) {
+			unsigned int dispatch_count = 0;
+			isc_boolean_t done = ISC_FALSE;
+			isc_boolean_t requeue = ISC_FALSE;
+			isc_boolean_t finished = ISC_FALSE;
+			isc_event_t *event;
+
+			INSIST(VALID_TASK(task));
+
+			/*
+			 * Note we only unlock the manager lock if we actually
+			 * have a task to do.  We must reacquire the manager
+			 * lock before exiting the 'if (task != NULL)' block.
+			 */
+			DEQUEUE(manager->ready_tasks, task, ready_link);
+			manager->tasks_running++;
+			UNLOCK(&manager->lock);
+
+			LOCK(&task->lock);
+			INSIST(task->state == task_state_ready);
+			task->state = task_state_running;
+			XTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+					      ISC_MSG_RUNNING, "running"));
+			isc_stdtime_get(&task->now);
+			do {
+				if (!EMPTY(task->events)) {
+					event = HEAD(task->events);
+					DEQUEUE(task->events, event, ev_link);
+
+					/*
+					 * Execute the event action.
+					 */
+					XTRACE(isc_msgcat_get(isc_msgcat,
+							    ISC_MSGSET_TASK,
+							    ISC_MSG_EXECUTE,
+							    "execute action"));
+					if (event->ev_action != NULL) {
+						UNLOCK(&task->lock);
+						(event->ev_action)(
+							(isc_task_t *)task,
+							event);
+						LOCK(&task->lock);
+					}
+					dispatch_count++;
+#ifndef USE_WORKER_THREADS
+					total_dispatch_count++;
+#endif /* USE_WORKER_THREADS */
+				}
+
+				if (task->references == 0 &&
+				    EMPTY(task->events) &&
+				    !TASK_SHUTTINGDOWN(task)) {
+					isc_boolean_t was_idle;
+
+					/*
+					 * There are no references and no
+					 * pending events for this task,
+					 * which means it will not become
+					 * runnable again via an external
+					 * action (such as sending an event
+					 * or detaching).
+					 *
+					 * We initiate shutdown to prevent
+					 * it from becoming a zombie.
+					 *
+					 * We do this here instead of in
+					 * the "if EMPTY(task->events)" block
+					 * below because:
+					 *
+					 *	If we post no shutdown events,
+					 *	we want the task to finish.
+					 *
+					 *	If we did post shutdown events,
+					 *	will still want the task's
+					 *	quantum to be applied.
+					 */
+					was_idle = task_shutdown(task);
+					INSIST(!was_idle);
+				}
+
+				if (EMPTY(task->events)) {
+					/*
+					 * Nothing else to do for this task
+					 * right now.
+					 */
+					XTRACE(isc_msgcat_get(isc_msgcat,
+							      ISC_MSGSET_TASK,
+							      ISC_MSG_EMPTY,
+							      "empty"));
+					if (task->references == 0 &&
+					    TASK_SHUTTINGDOWN(task)) {
+						/*
+						 * The task is done.
+						 */
+						XTRACE(isc_msgcat_get(
+							       isc_msgcat,
+							       ISC_MSGSET_TASK,
+							       ISC_MSG_DONE,
+							       "done"));
+						finished = ISC_TRUE;
+						task->state = task_state_done;
+					} else
+						task->state = task_state_idle;
+					done = ISC_TRUE;
+				} else if (dispatch_count >= task->quantum) {
+					/*
+					 * Our quantum has expired, but
+					 * there is more work to be done.
+					 * We'll requeue it to the ready
+					 * queue later.
+					 *
+					 * We don't check quantum until
+					 * dispatching at least one event,
+					 * so the minimum quantum is one.
+					 */
+					XTRACE(isc_msgcat_get(isc_msgcat,
+							      ISC_MSGSET_TASK,
+							      ISC_MSG_QUANTUM,
+							      "quantum"));
+					task->state = task_state_ready;
+					requeue = ISC_TRUE;
+					done = ISC_TRUE;
+				}
+			} while (!done);
+			UNLOCK(&task->lock);
+
+			if (finished)
+				task_finished(task);
+
+			LOCK(&manager->lock);
+			manager->tasks_running--;
+#ifdef USE_WORKER_THREADS
+			if (manager->exclusive_requested &&
+			    manager->tasks_running == 1) {
+				SIGNAL(&manager->exclusive_granted);
+			}
+#endif /* USE_WORKER_THREADS */
+			if (requeue) {
+				/*
+				 * We know we're awake, so we don't have
+				 * to wakeup any sleeping threads if the
+				 * ready queue is empty before we requeue.
+				 *
+				 * A possible optimization if the queue is
+				 * empty is to 'goto' the 'if (task != NULL)'
+				 * block, avoiding the ENQUEUE of the task
+				 * and the subsequent immediate DEQUEUE
+				 * (since it is the only executable task).
+				 * We don't do this because then we'd be
+				 * skipping the exit_requested check.  The
+				 * cost of ENQUEUE is low anyway, especially
+				 * when you consider that we'd have to do
+				 * an extra EMPTY check to see if we could
+				 * do the optimization.  If the ready queue
+				 * were usually nonempty, the 'optimization'
+				 * might even hurt rather than help.
+				 */
+#ifdef USE_WORKER_THREADS
+				ENQUEUE(manager->ready_tasks, task,
+					ready_link);
+#else
+				ENQUEUE(ready_tasks, task, ready_link);
+#endif
+			}
+		}
+	}
+#ifndef USE_WORKER_THREADS
+	ISC_LIST_APPENDLIST(manager->ready_tasks, ready_tasks, ready_link);
+#endif
+	UNLOCK(&manager->lock);
+}
+
+#ifdef USE_WORKER_THREADS
+static isc_threadresult_t
+#ifdef _WIN32
+WINAPI
+#endif
+run(void *uap) {
+	isc__taskmgr_t *manager = uap;
+
+	XTHREADTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+				    ISC_MSG_STARTING, "starting"));
+
+	dispatch(manager);
+
+	XTHREADTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+				    ISC_MSG_EXITING, "exiting"));
+
+#ifdef OPENSSL_LEAKS
+	ERR_remove_state(0);
+#endif
+
+	return ((isc_threadresult_t)0);
+}
+#endif /* USE_WORKER_THREADS */
+
+static void
+manager_free(isc__taskmgr_t *manager) {
+	isc_mem_t *mctx;
+
+#ifdef USE_WORKER_THREADS
+	(void)isc_condition_destroy(&manager->exclusive_granted);
+	(void)isc_condition_destroy(&manager->work_available);
+	isc_mem_free(manager->mctx, manager->threads);
+#endif /* USE_WORKER_THREADS */
+	DESTROYLOCK(&manager->lock);
+	manager->common.impmagic = 0;
+	manager->common.magic = 0;
+	mctx = manager->mctx;
+	isc_mem_put(mctx, manager, sizeof(*manager));
+	isc_mem_detach(&mctx);
+
+#ifdef USE_SHARED_MANAGER
+	taskmgr = NULL;
+#endif	/* USE_SHARED_MANAGER */
+}
+
+ISC_TASKFUNC_SCOPE isc_result_t
+isc__taskmgr_create(isc_mem_t *mctx, unsigned int workers,
+		    unsigned int default_quantum, isc_taskmgr_t **managerp)
+{
+	isc_result_t result;
+	unsigned int i, started = 0;
+	isc__taskmgr_t *manager;
+
+	/*
+	 * Create a new task manager.
+	 */
+
+	REQUIRE(workers > 0);
+	REQUIRE(managerp != NULL && *managerp == NULL);
+
+#ifndef USE_WORKER_THREADS
+	UNUSED(i);
+	UNUSED(started);
+#endif
+
+#ifdef USE_SHARED_MANAGER
+	if (taskmgr != NULL) {
+		if (taskmgr->refs == 0)
+			return (ISC_R_SHUTTINGDOWN);
+		taskmgr->refs++;
+		*managerp = (isc_taskmgr_t *)taskmgr;
+		return (ISC_R_SUCCESS);
+	}
+#endif /* USE_SHARED_MANAGER */
+
+	manager = isc_mem_get(mctx, sizeof(*manager));
+	if (manager == NULL)
+		return (ISC_R_NOMEMORY);
+	manager->common.methods = &taskmgrmethods;
+	manager->common.impmagic = TASK_MANAGER_MAGIC;
+	manager->common.magic = ISCAPI_TASKMGR_MAGIC;
+	manager->mctx = NULL;
+	result = isc_mutex_init(&manager->lock);
+	if (result != ISC_R_SUCCESS)
+		goto cleanup_mgr;
+
+#ifdef USE_WORKER_THREADS
+	manager->workers = 0;
+	manager->threads = isc_mem_allocate(mctx,
+					    workers * sizeof(isc_thread_t));
+	if (manager->threads == NULL) {
+		result = ISC_R_NOMEMORY;
+		goto cleanup_lock;
+	}
+	if (isc_condition_init(&manager->work_available) != ISC_R_SUCCESS) {
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "isc_condition_init() %s",
+				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+						ISC_MSG_FAILED, "failed"));
+		result = ISC_R_UNEXPECTED;
+		goto cleanup_threads;
+	}
+	if (isc_condition_init(&manager->exclusive_granted) != ISC_R_SUCCESS) {
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "isc_condition_init() %s",
+				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+						ISC_MSG_FAILED, "failed"));
+		result = ISC_R_UNEXPECTED;
+		goto cleanup_workavailable;
+	}
+#endif /* USE_WORKER_THREADS */
+	if (default_quantum == 0)
+		default_quantum = DEFAULT_DEFAULT_QUANTUM;
+	manager->default_quantum = default_quantum;
+	INIT_LIST(manager->tasks);
+	INIT_LIST(manager->ready_tasks);
+	manager->tasks_running = 0;
+	manager->exclusive_requested = ISC_FALSE;
+	manager->exiting = ISC_FALSE;
+
+	isc_mem_attach(mctx, &manager->mctx);
+
+#ifdef USE_WORKER_THREADS
+	LOCK(&manager->lock);
+	/*
+	 * Start workers.
+	 */
+	for (i = 0; i < workers; i++) {
+		if (isc_thread_create(run, manager,
+				      &manager->threads[manager->workers]) ==
+		    ISC_R_SUCCESS) {
+			manager->workers++;
+			started++;
+		}
+	}
+	UNLOCK(&manager->lock);
+
+	if (started == 0) {
+		manager_free(manager);
+		return (ISC_R_NOTHREADS);
+	}
+	isc_thread_setconcurrency(workers);
+#endif /* USE_WORKER_THREADS */
+#ifdef USE_SHARED_MANAGER
+	manager->refs = 1;
+	taskmgr = manager;
+#endif /* USE_SHARED_MANAGER */
+
+	*managerp = (isc_taskmgr_t *)manager;
+
+	return (ISC_R_SUCCESS);
+
+#ifdef USE_WORKER_THREADS
+ cleanup_workavailable:
+	(void)isc_condition_destroy(&manager->work_available);
+ cleanup_threads:
+	isc_mem_free(mctx, manager->threads);
+ cleanup_lock:
+	DESTROYLOCK(&manager->lock);
+#endif
+ cleanup_mgr:
+	isc_mem_put(mctx, manager, sizeof(*manager));
+	return (result);
+}
+
+ISC_TASKFUNC_SCOPE void
+isc__taskmgr_destroy(isc_taskmgr_t **managerp) {
+	isc__taskmgr_t *manager;
+	isc__task_t *task;
+	unsigned int i;
+
+	/*
+	 * Destroy '*managerp'.
+	 */
+
+	REQUIRE(managerp != NULL);
+	manager = (isc__taskmgr_t *)*managerp;
+	REQUIRE(VALID_MANAGER(manager));
+
+#ifndef USE_WORKER_THREADS
+	UNUSED(i);
+#endif /* USE_WORKER_THREADS */
+
+#ifdef USE_SHARED_MANAGER
+	manager->refs--;
+	if (manager->refs > 0) {
+		*managerp = NULL;
+		return;
+	}
+#endif
+
+	XTHREADTRACE("isc_taskmgr_destroy");
+	/*
+	 * Only one non-worker thread may ever call this routine.
+	 * If a worker thread wants to initiate shutdown of the
+	 * task manager, it should ask some non-worker thread to call
+	 * isc_taskmgr_destroy(), e.g. by signalling a condition variable
+	 * that the startup thread is sleeping on.
+	 */
+
+	/*
+	 * Unlike elsewhere, we're going to hold this lock a long time.
+	 * We need to do so, because otherwise the list of tasks could
+	 * change while we were traversing it.
+	 *
+	 * This is also the only function where we will hold both the
+	 * task manager lock and a task lock at the same time.
+	 */
+
+	LOCK(&manager->lock);
+
+	/*
+	 * Make sure we only get called once.
+	 */
+	INSIST(!manager->exiting);
+	manager->exiting = ISC_TRUE;
+
+	/*
+	 * Post shutdown event(s) to every task (if they haven't already been
+	 * posted).
+	 */
+	for (task = HEAD(manager->tasks);
+	     task != NULL;
+	     task = NEXT(task, link)) {
+		LOCK(&task->lock);
+		if (task_shutdown(task))
+			ENQUEUE(manager->ready_tasks, task, ready_link);
+		UNLOCK(&task->lock);
+	}
+#ifdef USE_WORKER_THREADS
+	/*
+	 * Wake up any sleeping workers.  This ensures we get work done if
+	 * there's work left to do, and if there are already no tasks left
+	 * it will cause the workers to see manager->exiting.
+	 */
+	BROADCAST(&manager->work_available);
+	UNLOCK(&manager->lock);
+
+	/*
+	 * Wait for all the worker threads to exit.
+	 */
+	for (i = 0; i < manager->workers; i++)
+		(void)isc_thread_join(manager->threads[i], NULL);
+#else /* USE_WORKER_THREADS */
+	/*
+	 * Dispatch the shutdown events.
+	 */
+	UNLOCK(&manager->lock);
+	while (isc__taskmgr_ready((isc_taskmgr_t *)manager))
+		(void)isc__taskmgr_dispatch((isc_taskmgr_t *)manager);
+#ifdef BIND9
+	if (!ISC_LIST_EMPTY(manager->tasks))
+		isc_mem_printallactive(stderr);
+#endif
+	INSIST(ISC_LIST_EMPTY(manager->tasks));
+#ifdef USE_SHARED_MANAGER
+	taskmgr = NULL;
+#endif
+#endif /* USE_WORKER_THREADS */
+
+	manager_free(manager);
+
+	*managerp = NULL;
+}
+
+#ifndef USE_WORKER_THREADS
+isc_boolean_t
+isc__taskmgr_ready(isc_taskmgr_t *manager0) {
+	isc__taskmgr_t *manager = (isc__taskmgr_t *)manager0;
+
+#ifdef USE_SHARED_MANAGER
+	if (manager == NULL)
+		manager = taskmgr;
+#endif
+	if (manager == NULL)
+		return (ISC_FALSE);
+	return (ISC_TF(!ISC_LIST_EMPTY(manager->ready_tasks)));
+}
+
+isc_result_t
+isc__taskmgr_dispatch(isc_taskmgr_t *manager0) {
+	isc__taskmgr_t *manager = (isc__taskmgr_t *)manager0;
+
+#ifdef USE_SHARED_MANAGER
+	if (manager == NULL)
+		manager = taskmgr;
+#endif
+	if (manager == NULL)
+		return (ISC_R_NOTFOUND);
+
+	dispatch(manager);
+
+	return (ISC_R_SUCCESS);
+}
+
+#endif /* USE_WORKER_THREADS */
+
+ISC_TASKFUNC_SCOPE isc_result_t
+isc__task_beginexclusive(isc_task_t *task0) {
+#ifdef USE_WORKER_THREADS
+	isc__task_t *task = (isc__task_t *)task0;
+	isc__taskmgr_t *manager = task->manager;
+	REQUIRE(task->state == task_state_running);
+	LOCK(&manager->lock);
+	if (manager->exclusive_requested) {
+		UNLOCK(&manager->lock);
+		return (ISC_R_LOCKBUSY);
+	}
+	manager->exclusive_requested = ISC_TRUE;
+	while (manager->tasks_running > 1) {
+		WAIT(&manager->exclusive_granted, &manager->lock);
+	}
+	UNLOCK(&manager->lock);
+#else
+	UNUSED(task0);
+#endif
+	return (ISC_R_SUCCESS);
+}
+
+ISC_TASKFUNC_SCOPE void
+isc__task_endexclusive(isc_task_t *task0) {
+#ifdef USE_WORKER_THREADS
+	isc__task_t *task = (isc__task_t *)task0;
+	isc__taskmgr_t *manager = task->manager;
+
+	REQUIRE(task->state == task_state_running);
+	LOCK(&manager->lock);
+	REQUIRE(manager->exclusive_requested);
+	manager->exclusive_requested = ISC_FALSE;
+	BROADCAST(&manager->work_available);
+	UNLOCK(&manager->lock);
+#else
+	UNUSED(task0);
+#endif
+}
+
+#ifdef USE_SOCKETIMPREGISTER
+isc_result_t
+isc__task_register() {
+	return (isc_task_register(isc__taskmgr_create));
+}
+#endif
+
+isc_boolean_t
+isc_task_exiting(isc_task_t *t) {
+	isc__task_t *task = (isc__task_t *)t;
+
+	REQUIRE(VALID_TASK(task));
+	return (TASK_SHUTTINGDOWN(task));
+}
+
+
+#if defined(HAVE_LIBXML2) && defined(BIND9)
+void
+isc_taskmgr_renderxml(isc_taskmgr_t *mgr0, xmlTextWriterPtr writer) {
+	isc__taskmgr_t *mgr = (isc__taskmgr_t *)mgr0;
+	isc__task_t *task;
+
+	LOCK(&mgr->lock);
+
+	/*
+	 * Write out the thread-model, and some details about each depending
+	 * on which type is enabled.
+	 */
+	xmlTextWriterStartElement(writer, ISC_XMLCHAR "thread-model");
+#ifdef ISC_PLATFORM_USETHREADS
+	xmlTextWriterStartElement(writer, ISC_XMLCHAR "type");
+	xmlTextWriterWriteString(writer, ISC_XMLCHAR "threaded");
+	xmlTextWriterEndElement(writer); /* type */
+
+	xmlTextWriterStartElement(writer, ISC_XMLCHAR "worker-threads");
+	xmlTextWriterWriteFormatString(writer, "%d", mgr->workers);
+	xmlTextWriterEndElement(writer); /* worker-threads */
+#else /* ISC_PLATFORM_USETHREADS */
+	xmlTextWriterStartElement(writer, ISC_XMLCHAR "type");
+	xmlTextWriterWriteString(writer, ISC_XMLCHAR "non-threaded");
+	xmlTextWriterEndElement(writer); /* type */
+
+	xmlTextWriterStartElement(writer, ISC_XMLCHAR "references");
+	xmlTextWriterWriteFormatString(writer, "%d", mgr->refs);
+	xmlTextWriterEndElement(writer); /* references */
+#endif /* ISC_PLATFORM_USETHREADS */
+
+	xmlTextWriterStartElement(writer, ISC_XMLCHAR "default-quantum");
+	xmlTextWriterWriteFormatString(writer, "%d", mgr->default_quantum);
+	xmlTextWriterEndElement(writer); /* default-quantum */
+
+	xmlTextWriterStartElement(writer, ISC_XMLCHAR "tasks-running");
+	xmlTextWriterWriteFormatString(writer, "%d", mgr->tasks_running);
+	xmlTextWriterEndElement(writer); /* tasks-running */
+
+	xmlTextWriterEndElement(writer); /* thread-model */
+
+	xmlTextWriterStartElement(writer, ISC_XMLCHAR "tasks");
+	task = ISC_LIST_HEAD(mgr->tasks);
+	while (task != NULL) {
+		LOCK(&task->lock);
+		xmlTextWriterStartElement(writer, ISC_XMLCHAR "task");
+
+		if (task->name[0] != 0) {
+			xmlTextWriterStartElement(writer, ISC_XMLCHAR "name");
+			xmlTextWriterWriteFormatString(writer, "%s",
+						       task->name);
+			xmlTextWriterEndElement(writer); /* name */
+		}
+
+		xmlTextWriterStartElement(writer, ISC_XMLCHAR "references");
+		xmlTextWriterWriteFormatString(writer, "%d", task->references);
+		xmlTextWriterEndElement(writer); /* references */
+
+		xmlTextWriterStartElement(writer, ISC_XMLCHAR "id");
+		xmlTextWriterWriteFormatString(writer, "%p", task);
+		xmlTextWriterEndElement(writer); /* id */
+
+		xmlTextWriterStartElement(writer, ISC_XMLCHAR "state");
+		xmlTextWriterWriteFormatString(writer, "%s",
+					       statenames[task->state]);
+		xmlTextWriterEndElement(writer); /* state */
+
+		xmlTextWriterStartElement(writer, ISC_XMLCHAR "quantum");
+		xmlTextWriterWriteFormatString(writer, "%d", task->quantum);
+		xmlTextWriterEndElement(writer); /* quantum */
+
+		xmlTextWriterEndElement(writer);
+
+		UNLOCK(&task->lock);
+		task = ISC_LIST_NEXT(task, link);
+	}
+	xmlTextWriterEndElement(writer); /* tasks */
+
+	UNLOCK(&mgr->lock);
+}
+#endif /* HAVE_LIBXML2 && BIND9 */
diff --git a/src/lib/bind9/task_api.c b/src/lib/bind9/task_api.c
new file mode 100644
index 0000000..4e03db2
--- /dev/null
+++ b/src/lib/bind9/task_api.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2009, 2010  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: task_api.c,v 1.7 2010-12-22 23:46:59 tbox Exp $ */
+
+#include <config.h>
+
+#include <unistd.h>
+
+#include <isc/app.h>
+#include <isc/magic.h>
+#include <isc/mutex.h>
+#include <isc/once.h>
+#include <isc/task.h>
+#include <isc/util.h>
+
+static isc_mutex_t createlock;
+static isc_once_t once = ISC_ONCE_INIT;
+static isc_taskmgrcreatefunc_t taskmgr_createfunc = NULL;
+
+static void
+initialize(void) {
+	RUNTIME_CHECK(isc_mutex_init(&createlock) == ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_task_register(isc_taskmgrcreatefunc_t createfunc) {
+	isc_result_t result = ISC_R_SUCCESS;
+
+	RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
+
+	LOCK(&createlock);
+	if (taskmgr_createfunc == NULL)
+		taskmgr_createfunc = createfunc;
+	else
+		result = ISC_R_EXISTS;
+	UNLOCK(&createlock);
+
+	return (result);
+}
+
+isc_result_t
+isc_taskmgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx,
+			unsigned int workers, unsigned int default_quantum,
+			isc_taskmgr_t **managerp)
+{
+	isc_result_t result;
+
+	LOCK(&createlock);
+
+	REQUIRE(taskmgr_createfunc != NULL);
+	result = (*taskmgr_createfunc)(mctx, workers, default_quantum,
+				       managerp);
+
+	UNLOCK(&createlock);
+
+	if (result == ISC_R_SUCCESS)
+		isc_appctx_settaskmgr(actx, *managerp);
+
+	return (result);
+}
+
+isc_result_t
+isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
+		   unsigned int default_quantum, isc_taskmgr_t **managerp)
+{
+	isc_result_t result;
+
+	LOCK(&createlock);
+
+	REQUIRE(taskmgr_createfunc != NULL);
+	result = (*taskmgr_createfunc)(mctx, workers, default_quantum,
+				       managerp);
+
+	UNLOCK(&createlock);
+
+	return (result);
+}
+
+void
+isc_taskmgr_destroy(isc_taskmgr_t **managerp) {
+	REQUIRE(managerp != NULL && ISCAPI_TASKMGR_VALID(*managerp));
+
+	(*managerp)->methods->destroy(managerp);
+
+	ENSURE(*managerp == NULL);
+}
+
+isc_result_t
+isc_task_create(isc_taskmgr_t *manager, unsigned int quantum,
+		isc_task_t **taskp)
+{
+	REQUIRE(ISCAPI_TASKMGR_VALID(manager));
+	REQUIRE(taskp != NULL && *taskp == NULL);
+
+	return (manager->methods->taskcreate(manager, quantum, taskp));
+}
+
+void
+isc_task_attach(isc_task_t *source, isc_task_t **targetp) {
+	REQUIRE(ISCAPI_TASK_VALID(source));
+	REQUIRE(targetp != NULL && *targetp == NULL);
+
+	source->methods->attach(source, targetp);
+
+	ENSURE(*targetp == source);
+}
+
+void
+isc_task_detach(isc_task_t **taskp) {
+	REQUIRE(taskp != NULL && ISCAPI_TASK_VALID(*taskp));
+
+	(*taskp)->methods->detach(taskp);
+
+	ENSURE(*taskp == NULL);
+}
+
+void
+isc_task_send(isc_task_t *task, isc_event_t **eventp) {
+	REQUIRE(ISCAPI_TASK_VALID(task));
+	REQUIRE(eventp != NULL && *eventp != NULL);
+
+	task->methods->send(task, eventp);
+
+	ENSURE(*eventp == NULL);
+}
+
+void
+isc_task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp) {
+	REQUIRE(taskp != NULL && ISCAPI_TASK_VALID(*taskp));
+	REQUIRE(eventp != NULL && *eventp != NULL);
+
+	(*taskp)->methods->sendanddetach(taskp, eventp);
+
+	ENSURE(*taskp == NULL && *eventp == NULL);
+}
+
+unsigned int
+isc_task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type,
+		void *tag, isc_eventlist_t *events)
+{
+	REQUIRE(ISCAPI_TASK_VALID(task));
+
+	return (task->methods->unsend(task, sender, type, tag, events));
+}
+
+isc_result_t
+isc_task_onshutdown(isc_task_t *task, isc_taskaction_t action, const void *arg)
+{
+	REQUIRE(ISCAPI_TASK_VALID(task));
+
+	return (task->methods->onshutdown(task, action, arg));
+}
+
+void
+isc_task_shutdown(isc_task_t *task) {
+	REQUIRE(ISCAPI_TASK_VALID(task));
+
+	task->methods->shutdown(task);
+}
+
+void
+isc_task_setname(isc_task_t *task, const char *name, void *tag) {
+	REQUIRE(ISCAPI_TASK_VALID(task));
+
+	task->methods->setname(task, name, tag);
+}
+
+unsigned int
+isc_task_purge(isc_task_t *task, void *sender, isc_eventtype_t type, void *tag)
+{
+	REQUIRE(ISCAPI_TASK_VALID(task));
+
+	return (task->methods->purgeevents(task, sender, type, tag));
+}
+
+isc_result_t
+isc_task_beginexclusive(isc_task_t *task) {
+	REQUIRE(ISCAPI_TASK_VALID(task));
+
+	return (task->methods->beginexclusive(task));
+}
+
+void
+isc_task_endexclusive(isc_task_t *task) {
+	REQUIRE(ISCAPI_TASK_VALID(task));
+
+	task->methods->endexclusive(task);
+}
+
+
+/*%
+ * This is necessary for libisc's internal timer implementation.  Other
+ * implementation might skip implementing this.
+ */
+unsigned int
+isc_task_purgerange(isc_task_t *task, void *sender, isc_eventtype_t first,
+		    isc_eventtype_t last, void *tag)
+{
+	REQUIRE(ISCAPI_TASK_VALID(task));
+
+	return (task->methods->purgerange(task, sender, first, last, tag));
+}
diff --git a/src/lib/bind9/task_p.h b/src/lib/bind9/task_p.h
new file mode 100644
index 0000000..1bcdca6
--- /dev/null
+++ b/src/lib/bind9/task_p.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: task_p.h,v 1.13 2009-09-02 23:48:02 tbox Exp $ */
+
+#ifndef ISC_TASK_P_H
+#define ISC_TASK_P_H
+
+/*! \file */
+
+isc_boolean_t
+isc__taskmgr_ready(isc_taskmgr_t *taskmgr);
+
+isc_result_t
+isc__taskmgr_dispatch(isc_taskmgr_t *taskmgr);
+
+#endif /* ISC_TASK_P_H */
diff --git a/src/lib/bind9/taskpool.c b/src/lib/bind9/taskpool.c
new file mode 100644
index 0000000..8efbf28
--- /dev/null
+++ b/src/lib/bind9/taskpool.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: taskpool.c,v 1.18 2007-06-18 23:47:44 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/mem.h>
+#include <isc/taskpool.h>
+#include <isc/util.h>
+
+/***
+ *** Types.
+ ***/
+
+struct isc_taskpool {
+	isc_mem_t *			mctx;
+	unsigned int			ntasks;
+	isc_task_t **			tasks;
+};
+/***
+ *** Functions.
+ ***/
+
+isc_result_t
+isc_taskpool_create(isc_taskmgr_t *tmgr, isc_mem_t *mctx,
+		    unsigned int ntasks, unsigned int quantum,
+		    isc_taskpool_t **poolp)
+{
+	unsigned int i;
+	isc_taskpool_t *pool;
+	isc_result_t result;
+
+	INSIST(ntasks > 0);
+	pool = isc_mem_get(mctx, sizeof(*pool));
+	if (pool == NULL)
+		return (ISC_R_NOMEMORY);
+	pool->mctx = mctx;
+	pool->ntasks = ntasks;
+	pool->tasks = isc_mem_get(mctx, ntasks * sizeof(isc_task_t *));
+	if (pool->tasks == NULL) {
+		isc_mem_put(mctx, pool, sizeof(*pool));
+		return (ISC_R_NOMEMORY);
+	}
+	for (i = 0; i < ntasks; i++)
+		pool->tasks[i] = NULL;
+	for (i = 0; i < ntasks; i++) {
+		result = isc_task_create(tmgr, quantum, &pool->tasks[i]);
+		if (result != ISC_R_SUCCESS) {
+			isc_taskpool_destroy(&pool);
+			return (result);
+		}
+		isc_task_setname(pool->tasks[i], "taskpool", NULL);
+	}
+	*poolp = pool;
+	return (ISC_R_SUCCESS);
+}
+
+void isc_taskpool_gettask(isc_taskpool_t *pool, unsigned int hash,
+			  isc_task_t **targetp)
+{
+	isc_task_attach(pool->tasks[hash % pool->ntasks], targetp);
+}
+
+void
+isc_taskpool_destroy(isc_taskpool_t **poolp) {
+	unsigned int i;
+	isc_taskpool_t *pool = *poolp;
+	for (i = 0; i < pool->ntasks; i++) {
+		if (pool->tasks[i] != NULL) {
+			isc_task_detach(&pool->tasks[i]);
+		}
+	}
+	isc_mem_put(pool->mctx, pool->tasks,
+		    pool->ntasks * sizeof(isc_task_t *));
+	isc_mem_put(pool->mctx, pool, sizeof(*pool));
+	*poolp = NULL;
+}
+
+
diff --git a/src/lib/bind9/timer.c b/src/lib/bind9/timer.c
new file mode 100644
index 0000000..71473fb
--- /dev/null
+++ b/src/lib/bind9/timer.c
@@ -0,0 +1,1072 @@
+/*
+ * Copyright (C) 2004, 2005, 2007-2009, 2011  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2002  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: timer.c,v 1.95.302.3 2011-03-11 06:47:08 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/condition.h>
+#include <isc/heap.h>
+#include <isc/log.h>
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/msgs.h>
+#include <isc/platform.h>
+#include <isc/task.h>
+#include <isc/thread.h>
+#include <isc/time.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#ifdef OPENSSL_LEAKS
+#include <openssl/err.h>
+#endif
+
+/* See task.c about the following definition: */
+#ifdef BIND9
+#ifdef ISC_PLATFORM_USETHREADS
+#define USE_TIMER_THREAD
+#else
+#define USE_SHARED_MANAGER
+#endif	/* ISC_PLATFORM_USETHREADS */
+#endif	/* BIND9 */
+
+#ifndef USE_TIMER_THREAD
+#include "timer_p.h"
+#endif /* USE_TIMER_THREAD */
+
+#ifdef ISC_TIMER_TRACE
+#define XTRACE(s)			fprintf(stderr, "%s\n", (s))
+#define XTRACEID(s, t)			fprintf(stderr, "%s %p\n", (s), (t))
+#define XTRACETIME(s, d)		fprintf(stderr, "%s %u.%09u\n", (s), \
+					       (d).seconds, (d).nanoseconds)
+#define XTRACETIME2(s, d, n)		fprintf(stderr, "%s %u.%09u %u.%09u\n", (s), \
+					       (d).seconds, (d).nanoseconds, (n).seconds, (n).nanoseconds)
+#define XTRACETIMER(s, t, d)		fprintf(stderr, "%s %p %u.%09u\n", (s), (t), \
+					       (d).seconds, (d).nanoseconds)
+#else
+#define XTRACE(s)
+#define XTRACEID(s, t)
+#define XTRACETIME(s, d)
+#define XTRACETIME2(s, d, n)
+#define XTRACETIMER(s, t, d)
+#endif /* ISC_TIMER_TRACE */
+
+#define TIMER_MAGIC			ISC_MAGIC('T', 'I', 'M', 'R')
+#define VALID_TIMER(t)			ISC_MAGIC_VALID(t, TIMER_MAGIC)
+
+typedef struct isc__timer isc__timer_t;
+typedef struct isc__timermgr isc__timermgr_t;
+
+struct isc__timer {
+	/*! Not locked. */
+	isc_timer_t			common;
+	isc__timermgr_t *		manager;
+	isc_mutex_t			lock;
+	/*! Locked by timer lock. */
+	unsigned int			references;
+	isc_time_t			idle;
+	/*! Locked by manager lock. */
+	isc_timertype_t			type;
+	isc_time_t			expires;
+	isc_interval_t			interval;
+	isc_task_t *			task;
+	isc_taskaction_t		action;
+	void *				arg;
+	unsigned int			index;
+	isc_time_t			due;
+	LINK(isc__timer_t)		link;
+};
+
+#define TIMER_MANAGER_MAGIC		ISC_MAGIC('T', 'I', 'M', 'M')
+#define VALID_MANAGER(m)		ISC_MAGIC_VALID(m, TIMER_MANAGER_MAGIC)
+
+struct isc__timermgr {
+	/* Not locked. */
+	isc_timermgr_t			common;
+	isc_mem_t *			mctx;
+	isc_mutex_t			lock;
+	/* Locked by manager lock. */
+	isc_boolean_t			done;
+	LIST(isc__timer_t)		timers;
+	unsigned int			nscheduled;
+	isc_time_t			due;
+#ifdef USE_TIMER_THREAD
+	isc_condition_t			wakeup;
+	isc_thread_t			thread;
+#endif	/* USE_TIMER_THREAD */
+#ifdef USE_SHARED_MANAGER
+	unsigned int			refs;
+#endif /* USE_SHARED_MANAGER */
+	isc_heap_t *			heap;
+};
+
+/*%
+ * The followings can be either static or public, depending on build
+ * environment.
+ */
+
+#ifdef BIND9
+#define ISC_TIMERFUNC_SCOPE
+#else
+#define ISC_TIMERFUNC_SCOPE static
+#endif
+
+ISC_TIMERFUNC_SCOPE isc_result_t
+isc__timer_create(isc_timermgr_t *manager, isc_timertype_t type,
+		  isc_time_t *expires, isc_interval_t *interval,
+		  isc_task_t *task, isc_taskaction_t action, const void *arg,
+		  isc_timer_t **timerp);
+ISC_TIMERFUNC_SCOPE isc_result_t
+isc__timer_reset(isc_timer_t *timer, isc_timertype_t type,
+		 isc_time_t *expires, isc_interval_t *interval,
+		 isc_boolean_t purge);
+ISC_TIMERFUNC_SCOPE isc_timertype_t
+isc__timer_gettype(isc_timer_t *timer);
+ISC_TIMERFUNC_SCOPE isc_result_t
+isc__timer_touch(isc_timer_t *timer);
+ISC_TIMERFUNC_SCOPE void
+isc__timer_attach(isc_timer_t *timer0, isc_timer_t **timerp);
+ISC_TIMERFUNC_SCOPE void
+isc__timer_detach(isc_timer_t **timerp);
+ISC_TIMERFUNC_SCOPE isc_result_t
+isc__timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp);
+ISC_TIMERFUNC_SCOPE void
+isc__timermgr_poke(isc_timermgr_t *manager0);
+ISC_TIMERFUNC_SCOPE void
+isc__timermgr_destroy(isc_timermgr_t **managerp);
+
+static struct isc__timermethods {
+	isc_timermethods_t methods;
+
+	/*%
+	 * The following are defined just for avoiding unused static functions.
+	 */
+#ifndef BIND9
+	void *gettype;
+#endif
+} timermethods = {
+	{
+		isc__timer_attach,
+		isc__timer_detach,
+		isc__timer_reset,
+		isc__timer_touch
+	}
+#ifndef BIND9
+	,
+	(void *)isc__timer_gettype
+#endif
+};
+
+static struct isc__timermgrmethods {
+	isc_timermgrmethods_t methods;
+#ifndef BIND9
+	void *poke;		/* see above */
+#endif
+} timermgrmethods = {
+	{
+		isc__timermgr_destroy,
+		isc__timer_create
+	}
+#ifndef BIND9
+	,
+	(void *)isc__timermgr_poke
+#endif
+};
+
+#ifdef USE_SHARED_MANAGER
+/*!
+ * If the manager is supposed to be shared, there can be only one.
+ */
+static isc__timermgr_t *timermgr = NULL;
+#endif /* USE_SHARED_MANAGER */
+
+static inline isc_result_t
+schedule(isc__timer_t *timer, isc_time_t *now, isc_boolean_t signal_ok) {
+	isc_result_t result;
+	isc__timermgr_t *manager;
+	isc_time_t due;
+	int cmp;
+#ifdef USE_TIMER_THREAD
+	isc_boolean_t timedwait;
+#endif
+
+	/*!
+	 * Note: the caller must ensure locking.
+	 */
+
+	REQUIRE(timer->type != isc_timertype_inactive);
+
+#ifndef USE_TIMER_THREAD
+	UNUSED(signal_ok);
+#endif /* USE_TIMER_THREAD */
+
+	manager = timer->manager;
+
+#ifdef USE_TIMER_THREAD
+	/*!
+	 * If the manager was timed wait, we may need to signal the
+	 * manager to force a wakeup.
+	 */
+	timedwait = ISC_TF(manager->nscheduled > 0 &&
+			   isc_time_seconds(&manager->due) != 0);
+#endif
+
+	/*
+	 * Compute the new due time.
+	 */
+	if (timer->type != isc_timertype_once) {
+		result = isc_time_add(now, &timer->interval, &due);
+		if (result != ISC_R_SUCCESS)
+			return (result);
+		if (timer->type == isc_timertype_limited &&
+		    isc_time_compare(&timer->expires, &due) < 0)
+			due = timer->expires;
+	} else {
+		if (isc_time_isepoch(&timer->idle))
+			due = timer->expires;
+		else if (isc_time_isepoch(&timer->expires))
+			due = timer->idle;
+		else if (isc_time_compare(&timer->idle, &timer->expires) < 0)
+			due = timer->idle;
+		else
+			due = timer->expires;
+	}
+
+	/*
+	 * Schedule the timer.
+	 */
+
+	if (timer->index > 0) {
+		/*
+		 * Already scheduled.
+		 */
+		cmp = isc_time_compare(&due, &timer->due);
+		timer->due = due;
+		switch (cmp) {
+		case -1:
+			isc_heap_increased(manager->heap, timer->index);
+			break;
+		case 1:
+			isc_heap_decreased(manager->heap, timer->index);
+			break;
+		case 0:
+			/* Nothing to do. */
+			break;
+		}
+	} else {
+		timer->due = due;
+		result = isc_heap_insert(manager->heap, timer);
+		if (result != ISC_R_SUCCESS) {
+			INSIST(result == ISC_R_NOMEMORY);
+			return (ISC_R_NOMEMORY);
+		}
+		manager->nscheduled++;
+	}
+
+	XTRACETIMER(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TIMER,
+				   ISC_MSG_SCHEDULE, "schedule"), timer, due);
+
+	/*
+	 * If this timer is at the head of the queue, we need to ensure
+	 * that we won't miss it if it has a more recent due time than
+	 * the current "next" timer.  We do this either by waking up the
+	 * run thread, or explicitly setting the value in the manager.
+	 */
+#ifdef USE_TIMER_THREAD
+
+	/*
+	 * This is a temporary (probably) hack to fix a bug on tru64 5.1
+	 * and 5.1a.  Sometimes, pthread_cond_timedwait() doesn't actually
+	 * return when the time expires, so here, we check to see if
+	 * we're 15 seconds or more behind, and if we are, we signal
+	 * the dispatcher.  This isn't such a bad idea as a general purpose
+	 * watchdog, so perhaps we should just leave it in here.
+	 */
+	if (signal_ok && timedwait) {
+		isc_interval_t fifteen;
+		isc_time_t then;
+
+		isc_interval_set(&fifteen, 15, 0);
+		result = isc_time_add(&manager->due, &fifteen, &then);
+
+		if (result == ISC_R_SUCCESS &&
+		    isc_time_compare(&then, now) < 0) {
+			SIGNAL(&manager->wakeup);
+			signal_ok = ISC_FALSE;
+			isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+				      ISC_LOGMODULE_TIMER, ISC_LOG_WARNING,
+				      "*** POKED TIMER ***");
+		}
+	}
+
+	if (timer->index == 1 && signal_ok) {
+		XTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TIMER,
+				      ISC_MSG_SIGNALSCHED,
+				      "signal (schedule)"));
+		SIGNAL(&manager->wakeup);
+	}
+#else /* USE_TIMER_THREAD */
+	if (timer->index == 1 &&
+	    isc_time_compare(&timer->due, &manager->due) < 0)
+		manager->due = timer->due;
+#endif /* USE_TIMER_THREAD */
+
+	return (ISC_R_SUCCESS);
+}
+
+static inline void
+deschedule(isc__timer_t *timer) {
+#ifdef USE_TIMER_THREAD
+	isc_boolean_t need_wakeup = ISC_FALSE;
+#endif
+	isc__timermgr_t *manager;
+
+	/*
+	 * The caller must ensure locking.
+	 */
+
+	manager = timer->manager;
+	if (timer->index > 0) {
+#ifdef USE_TIMER_THREAD
+		if (timer->index == 1)
+			need_wakeup = ISC_TRUE;
+#endif
+		isc_heap_delete(manager->heap, timer->index);
+		timer->index = 0;
+		INSIST(manager->nscheduled > 0);
+		manager->nscheduled--;
+#ifdef USE_TIMER_THREAD
+		if (need_wakeup) {
+			XTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TIMER,
+					      ISC_MSG_SIGNALDESCHED,
+					      "signal (deschedule)"));
+			SIGNAL(&manager->wakeup);
+		}
+#endif /* USE_TIMER_THREAD */
+	}
+}
+
+static void
+destroy(isc__timer_t *timer) {
+	isc__timermgr_t *manager = timer->manager;
+
+	/*
+	 * The caller must ensure it is safe to destroy the timer.
+	 */
+
+	LOCK(&manager->lock);
+
+	(void)isc_task_purgerange(timer->task,
+				  timer,
+				  ISC_TIMEREVENT_FIRSTEVENT,
+				  ISC_TIMEREVENT_LASTEVENT,
+				  NULL);
+	deschedule(timer);
+	UNLINK(manager->timers, timer, link);
+
+	UNLOCK(&manager->lock);
+
+	isc_task_detach(&timer->task);
+	DESTROYLOCK(&timer->lock);
+	timer->common.impmagic = 0;
+	timer->common.magic = 0;
+	isc_mem_put(manager->mctx, timer, sizeof(*timer));
+}
+
+ISC_TIMERFUNC_SCOPE isc_result_t
+isc__timer_create(isc_timermgr_t *manager0, isc_timertype_t type,
+		  isc_time_t *expires, isc_interval_t *interval,
+		  isc_task_t *task, isc_taskaction_t action, const void *arg,
+		  isc_timer_t **timerp)
+{
+	isc__timermgr_t *manager = (isc__timermgr_t *)manager0;
+	isc__timer_t *timer;
+	isc_result_t result;
+	isc_time_t now;
+
+	/*
+	 * Create a new 'type' timer managed by 'manager'.  The timers
+	 * parameters are specified by 'expires' and 'interval'.  Events
+	 * will be posted to 'task' and when dispatched 'action' will be
+	 * called with 'arg' as the arg value.  The new timer is returned
+	 * in 'timerp'.
+	 */
+
+	REQUIRE(VALID_MANAGER(manager));
+	REQUIRE(task != NULL);
+	REQUIRE(action != NULL);
+	if (expires == NULL)
+		expires = isc_time_epoch;
+	if (interval == NULL)
+		interval = isc_interval_zero;
+	REQUIRE(type == isc_timertype_inactive ||
+		!(isc_time_isepoch(expires) && isc_interval_iszero(interval)));
+	REQUIRE(timerp != NULL && *timerp == NULL);
+	REQUIRE(type != isc_timertype_limited ||
+		!(isc_time_isepoch(expires) || isc_interval_iszero(interval)));
+
+	/*
+	 * Get current time.
+	 */
+	if (type != isc_timertype_inactive) {
+		TIME_NOW(&now);
+	} else {
+		/*
+		 * We don't have to do this, but it keeps the compiler from
+		 * complaining about "now" possibly being used without being
+		 * set, even though it will never actually happen.
+		 */
+		isc_time_settoepoch(&now);
+	}
+
+
+	timer = isc_mem_get(manager->mctx, sizeof(*timer));
+	if (timer == NULL)
+		return (ISC_R_NOMEMORY);
+
+	timer->manager = manager;
+	timer->references = 1;
+
+	if (type == isc_timertype_once && !isc_interval_iszero(interval)) {
+		result = isc_time_add(&now, interval, &timer->idle);
+		if (result != ISC_R_SUCCESS) {
+			isc_mem_put(manager->mctx, timer, sizeof(*timer));
+			return (result);
+		}
+	} else
+		isc_time_settoepoch(&timer->idle);
+
+	timer->type = type;
+	timer->expires = *expires;
+	timer->interval = *interval;
+	timer->task = NULL;
+	isc_task_attach(task, &timer->task);
+	timer->action = action;
+	/*
+	 * Removing the const attribute from "arg" is the best of two
+	 * evils here.  If the timer->arg member is made const, then
+	 * it affects a great many recipients of the timer event
+	 * which did not pass in an "arg" that was truly const.
+	 * Changing isc_timer_create() to not have "arg" prototyped as const,
+	 * though, can cause compilers warnings for calls that *do*
+	 * have a truly const arg.  The caller will have to carefully
+	 * keep track of whether arg started as a true const.
+	 */
+	DE_CONST(arg, timer->arg);
+	timer->index = 0;
+	result = isc_mutex_init(&timer->lock);
+	if (result != ISC_R_SUCCESS) {
+		isc_task_detach(&timer->task);
+		isc_mem_put(manager->mctx, timer, sizeof(*timer));
+		return (result);
+	}
+	ISC_LINK_INIT(timer, link);
+	timer->common.impmagic = TIMER_MAGIC;
+	timer->common.magic = ISCAPI_TIMER_MAGIC;
+	timer->common.methods = (isc_timermethods_t *)&timermethods;
+
+	LOCK(&manager->lock);
+
+	/*
+	 * Note we don't have to lock the timer like we normally would because
+	 * there are no external references to it yet.
+	 */
+
+	if (type != isc_timertype_inactive)
+		result = schedule(timer, &now, ISC_TRUE);
+	else
+		result = ISC_R_SUCCESS;
+	if (result == ISC_R_SUCCESS)
+		APPEND(manager->timers, timer, link);
+
+	UNLOCK(&manager->lock);
+
+	if (result != ISC_R_SUCCESS) {
+		timer->common.impmagic = 0;
+		timer->common.magic = 0;
+		DESTROYLOCK(&timer->lock);
+		isc_task_detach(&timer->task);
+		isc_mem_put(manager->mctx, timer, sizeof(*timer));
+		return (result);
+	}
+
+	*timerp = (isc_timer_t *)timer;
+
+	return (ISC_R_SUCCESS);
+}
+
+ISC_TIMERFUNC_SCOPE isc_result_t
+isc__timer_reset(isc_timer_t *timer0, isc_timertype_t type,
+		 isc_time_t *expires, isc_interval_t *interval,
+		 isc_boolean_t purge)
+{
+	isc__timer_t *timer = (isc__timer_t *)timer0;
+	isc_time_t now;
+	isc__timermgr_t *manager;
+	isc_result_t result;
+
+	/*
+	 * Change the timer's type, expires, and interval values to the given
+	 * values.  If 'purge' is ISC_TRUE, any pending events from this timer
+	 * are purged from its task's event queue.
+	 */
+
+	REQUIRE(VALID_TIMER(timer));
+	manager = timer->manager;
+	REQUIRE(VALID_MANAGER(manager));
+
+	if (expires == NULL)
+		expires = isc_time_epoch;
+	if (interval == NULL)
+		interval = isc_interval_zero;
+	REQUIRE(type == isc_timertype_inactive ||
+		!(isc_time_isepoch(expires) && isc_interval_iszero(interval)));
+	REQUIRE(type != isc_timertype_limited ||
+		!(isc_time_isepoch(expires) || isc_interval_iszero(interval)));
+
+	/*
+	 * Get current time.
+	 */
+	if (type != isc_timertype_inactive) {
+		TIME_NOW(&now);
+	} else {
+		/*
+		 * We don't have to do this, but it keeps the compiler from
+		 * complaining about "now" possibly being used without being
+		 * set, even though it will never actually happen.
+		 */
+		isc_time_settoepoch(&now);
+	}
+
+	LOCK(&manager->lock);
+	LOCK(&timer->lock);
+
+	if (purge)
+		(void)isc_task_purgerange(timer->task,
+					  timer,
+					  ISC_TIMEREVENT_FIRSTEVENT,
+					  ISC_TIMEREVENT_LASTEVENT,
+					  NULL);
+	timer->type = type;
+	timer->expires = *expires;
+	timer->interval = *interval;
+	if (type == isc_timertype_once && !isc_interval_iszero(interval)) {
+		result = isc_time_add(&now, interval, &timer->idle);
+	} else {
+		isc_time_settoepoch(&timer->idle);
+		result = ISC_R_SUCCESS;
+	}
+
+	if (result == ISC_R_SUCCESS) {
+		if (type == isc_timertype_inactive) {
+			deschedule(timer);
+			result = ISC_R_SUCCESS;
+		} else
+			result = schedule(timer, &now, ISC_TRUE);
+	}
+
+	UNLOCK(&timer->lock);
+	UNLOCK(&manager->lock);
+
+	return (result);
+}
+
+ISC_TIMERFUNC_SCOPE isc_timertype_t
+isc__timer_gettype(isc_timer_t *timer0) {
+	isc__timer_t *timer = (isc__timer_t *)timer0;
+	isc_timertype_t t;
+
+	REQUIRE(VALID_TIMER(timer));
+
+	LOCK(&timer->lock);
+	t = timer->type;
+	UNLOCK(&timer->lock);
+
+	return (t);
+}
+
+ISC_TIMERFUNC_SCOPE isc_result_t
+isc__timer_touch(isc_timer_t *timer0) {
+	isc__timer_t *timer = (isc__timer_t *)timer0;
+	isc_result_t result;
+	isc_time_t now;
+
+	/*
+	 * Set the last-touched time of 'timer' to the current time.
+	 */
+
+	REQUIRE(VALID_TIMER(timer));
+
+	LOCK(&timer->lock);
+
+	/*
+	 * We'd like to
+	 *
+	 *	REQUIRE(timer->type == isc_timertype_once);
+	 *
+	 * but we cannot without locking the manager lock too, which we
+	 * don't want to do.
+	 */
+
+	TIME_NOW(&now);
+	result = isc_time_add(&now, &timer->interval, &timer->idle);
+
+	UNLOCK(&timer->lock);
+
+	return (result);
+}
+
+ISC_TIMERFUNC_SCOPE void
+isc__timer_attach(isc_timer_t *timer0, isc_timer_t **timerp) {
+	isc__timer_t *timer = (isc__timer_t *)timer0;
+
+	/*
+	 * Attach *timerp to timer.
+	 */
+
+	REQUIRE(VALID_TIMER(timer));
+	REQUIRE(timerp != NULL && *timerp == NULL);
+
+	LOCK(&timer->lock);
+	timer->references++;
+	UNLOCK(&timer->lock);
+
+	*timerp = (isc_timer_t *)timer;
+}
+
+ISC_TIMERFUNC_SCOPE void
+isc__timer_detach(isc_timer_t **timerp) {
+	isc__timer_t *timer;
+	isc_boolean_t free_timer = ISC_FALSE;
+
+	/*
+	 * Detach *timerp from its timer.
+	 */
+
+	REQUIRE(timerp != NULL);
+	timer = (isc__timer_t *)*timerp;
+	REQUIRE(VALID_TIMER(timer));
+
+	LOCK(&timer->lock);
+	REQUIRE(timer->references > 0);
+	timer->references--;
+	if (timer->references == 0)
+		free_timer = ISC_TRUE;
+	UNLOCK(&timer->lock);
+
+	if (free_timer)
+		destroy(timer);
+
+	*timerp = NULL;
+}
+
+static void
+dispatch(isc__timermgr_t *manager, isc_time_t *now) {
+	isc_boolean_t done = ISC_FALSE, post_event, need_schedule;
+	isc_timerevent_t *event;
+	isc_eventtype_t type = 0;
+	isc__timer_t *timer;
+	isc_result_t result;
+	isc_boolean_t idle;
+
+	/*!
+	 * The caller must be holding the manager lock.
+	 */
+
+	while (manager->nscheduled > 0 && !done) {
+		timer = isc_heap_element(manager->heap, 1);
+		INSIST(timer->type != isc_timertype_inactive);
+		if (isc_time_compare(now, &timer->due) >= 0) {
+			if (timer->type == isc_timertype_ticker) {
+				type = ISC_TIMEREVENT_TICK;
+				post_event = ISC_TRUE;
+				need_schedule = ISC_TRUE;
+			} else if (timer->type == isc_timertype_limited) {
+				int cmp;
+				cmp = isc_time_compare(now, &timer->expires);
+				if (cmp >= 0) {
+					type = ISC_TIMEREVENT_LIFE;
+					post_event = ISC_TRUE;
+					need_schedule = ISC_FALSE;
+				} else {
+					type = ISC_TIMEREVENT_TICK;
+					post_event = ISC_TRUE;
+					need_schedule = ISC_TRUE;
+				}
+			} else if (!isc_time_isepoch(&timer->expires) &&
+				   isc_time_compare(now,
+						    &timer->expires) >= 0) {
+				type = ISC_TIMEREVENT_LIFE;
+				post_event = ISC_TRUE;
+				need_schedule = ISC_FALSE;
+			} else {
+				idle = ISC_FALSE;
+
+				LOCK(&timer->lock);
+				if (!isc_time_isepoch(&timer->idle) &&
+				    isc_time_compare(now,
+						     &timer->idle) >= 0) {
+					idle = ISC_TRUE;
+				}
+				UNLOCK(&timer->lock);
+				if (idle) {
+					type = ISC_TIMEREVENT_IDLE;
+					post_event = ISC_TRUE;
+					need_schedule = ISC_FALSE;
+				} else {
+					/*
+					 * Idle timer has been touched;
+					 * reschedule.
+					 */
+					XTRACEID(isc_msgcat_get(isc_msgcat,
+								ISC_MSGSET_TIMER,
+								ISC_MSG_IDLERESCHED,
+								"idle reschedule"),
+						 timer);
+					post_event = ISC_FALSE;
+					need_schedule = ISC_TRUE;
+				}
+			}
+
+			if (post_event) {
+				XTRACEID(isc_msgcat_get(isc_msgcat,
+							ISC_MSGSET_TIMER,
+							ISC_MSG_POSTING,
+							"posting"), timer);
+				/*
+				 * XXX We could preallocate this event.
+				 */
+				event = (isc_timerevent_t *)isc_event_allocate(manager->mctx,
+							   timer,
+							   type,
+							   timer->action,
+							   timer->arg,
+							   sizeof(*event));
+
+				if (event != NULL) {
+					event->due = timer->due;
+					isc_task_send(timer->task,
+						      ISC_EVENT_PTR(&event));
+				} else
+					UNEXPECTED_ERROR(__FILE__, __LINE__, "%s",
+						 isc_msgcat_get(isc_msgcat,
+							 ISC_MSGSET_TIMER,
+							 ISC_MSG_EVENTNOTALLOC,
+							 "couldn't "
+							 "allocate event"));
+			}
+
+			timer->index = 0;
+			isc_heap_delete(manager->heap, 1);
+			manager->nscheduled--;
+
+			if (need_schedule) {
+				result = schedule(timer, now, ISC_FALSE);
+				if (result != ISC_R_SUCCESS)
+					UNEXPECTED_ERROR(__FILE__, __LINE__,
+							 "%s: %u",
+						isc_msgcat_get(isc_msgcat,
+							ISC_MSGSET_TIMER,
+							ISC_MSG_SCHEDFAIL,
+							"couldn't schedule "
+							"timer"),
+							 result);
+			}
+		} else {
+			manager->due = timer->due;
+			done = ISC_TRUE;
+		}
+	}
+}
+
+#ifdef USE_TIMER_THREAD
+static isc_threadresult_t
+#ifdef _WIN32			/* XXXDCL */
+WINAPI
+#endif
+run(void *uap) {
+	isc__timermgr_t *manager = uap;
+	isc_time_t now;
+	isc_result_t result;
+
+	LOCK(&manager->lock);
+	while (!manager->done) {
+		TIME_NOW(&now);
+
+		XTRACETIME(isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+					  ISC_MSG_RUNNING,
+					  "running"), now);
+
+		dispatch(manager, &now);
+
+		if (manager->nscheduled > 0) {
+			XTRACETIME2(isc_msgcat_get(isc_msgcat,
+						   ISC_MSGSET_GENERAL,
+						   ISC_MSG_WAITUNTIL,
+						   "waituntil"),
+				    manager->due, now);
+			result = WAITUNTIL(&manager->wakeup, &manager->lock, &manager->due);
+			INSIST(result == ISC_R_SUCCESS ||
+			       result == ISC_R_TIMEDOUT);
+		} else {
+			XTRACETIME(isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+						  ISC_MSG_WAIT, "wait"), now);
+			WAIT(&manager->wakeup, &manager->lock);
+		}
+		XTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TIMER,
+				      ISC_MSG_WAKEUP, "wakeup"));
+	}
+	UNLOCK(&manager->lock);
+
+#ifdef OPENSSL_LEAKS
+	ERR_remove_state(0);
+#endif
+
+	return ((isc_threadresult_t)0);
+}
+#endif /* USE_TIMER_THREAD */
+
+static isc_boolean_t
+sooner(void *v1, void *v2) {
+	isc__timer_t *t1, *t2;
+
+	t1 = v1;
+	t2 = v2;
+	REQUIRE(VALID_TIMER(t1));
+	REQUIRE(VALID_TIMER(t2));
+
+	if (isc_time_compare(&t1->due, &t2->due) < 0)
+		return (ISC_TRUE);
+	return (ISC_FALSE);
+}
+
+static void
+set_index(void *what, unsigned int index) {
+	isc__timer_t *timer;
+
+	timer = what;
+	REQUIRE(VALID_TIMER(timer));
+
+	timer->index = index;
+}
+
+ISC_TIMERFUNC_SCOPE isc_result_t
+isc__timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp) {
+	isc__timermgr_t *manager;
+	isc_result_t result;
+
+	/*
+	 * Create a timer manager.
+	 */
+
+	REQUIRE(managerp != NULL && *managerp == NULL);
+
+#ifdef USE_SHARED_MANAGER
+	if (timermgr != NULL) {
+		timermgr->refs++;
+		*managerp = (isc_timermgr_t *)timermgr;
+		return (ISC_R_SUCCESS);
+	}
+#endif /* USE_SHARED_MANAGER */
+
+	manager = isc_mem_get(mctx, sizeof(*manager));
+	if (manager == NULL)
+		return (ISC_R_NOMEMORY);
+
+	manager->common.impmagic = TIMER_MANAGER_MAGIC;
+	manager->common.magic = ISCAPI_TIMERMGR_MAGIC;
+	manager->common.methods = (isc_timermgrmethods_t *)&timermgrmethods;
+	manager->mctx = NULL;
+	manager->done = ISC_FALSE;
+	INIT_LIST(manager->timers);
+	manager->nscheduled = 0;
+	isc_time_settoepoch(&manager->due);
+	manager->heap = NULL;
+	result = isc_heap_create(mctx, sooner, set_index, 0, &manager->heap);
+	if (result != ISC_R_SUCCESS) {
+		INSIST(result == ISC_R_NOMEMORY);
+		isc_mem_put(mctx, manager, sizeof(*manager));
+		return (ISC_R_NOMEMORY);
+	}
+	result = isc_mutex_init(&manager->lock);
+	if (result != ISC_R_SUCCESS) {
+		isc_heap_destroy(&manager->heap);
+		isc_mem_put(mctx, manager, sizeof(*manager));
+		return (result);
+	}
+	isc_mem_attach(mctx, &manager->mctx);
+#ifdef USE_TIMER_THREAD
+	if (isc_condition_init(&manager->wakeup) != ISC_R_SUCCESS) {
+		isc_mem_detach(&manager->mctx);
+		DESTROYLOCK(&manager->lock);
+		isc_heap_destroy(&manager->heap);
+		isc_mem_put(mctx, manager, sizeof(*manager));
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "isc_condition_init() %s",
+				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+						ISC_MSG_FAILED, "failed"));
+		return (ISC_R_UNEXPECTED);
+	}
+	if (isc_thread_create(run, manager, &manager->thread) !=
+	    ISC_R_SUCCESS) {
+		isc_mem_detach(&manager->mctx);
+		(void)isc_condition_destroy(&manager->wakeup);
+		DESTROYLOCK(&manager->lock);
+		isc_heap_destroy(&manager->heap);
+		isc_mem_put(mctx, manager, sizeof(*manager));
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "isc_thread_create() %s",
+				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+						ISC_MSG_FAILED, "failed"));
+		return (ISC_R_UNEXPECTED);
+	}
+#endif
+#ifdef USE_SHARED_MANAGER
+	manager->refs = 1;
+	timermgr = manager;
+#endif /* USE_SHARED_MANAGER */
+
+	*managerp = (isc_timermgr_t *)manager;
+
+	return (ISC_R_SUCCESS);
+}
+
+ISC_TIMERFUNC_SCOPE void
+isc__timermgr_poke(isc_timermgr_t *manager0) {
+#ifdef USE_TIMER_THREAD
+	isc__timermgr_t *manager = (isc__timermgr_t *)manager0;
+
+	REQUIRE(VALID_MANAGER(manager));
+
+	SIGNAL(&manager->wakeup);
+#else
+	UNUSED(manager0);
+#endif
+}
+
+ISC_TIMERFUNC_SCOPE void
+isc__timermgr_destroy(isc_timermgr_t **managerp) {
+	isc__timermgr_t *manager;
+	isc_mem_t *mctx;
+
+	/*
+	 * Destroy a timer manager.
+	 */
+
+	REQUIRE(managerp != NULL);
+	manager = (isc__timermgr_t *)*managerp;
+	REQUIRE(VALID_MANAGER(manager));
+
+	LOCK(&manager->lock);
+
+#ifdef USE_SHARED_MANAGER
+	manager->refs--;
+	if (manager->refs > 0) {
+		UNLOCK(&manager->lock);
+		*managerp = NULL;
+		return;
+	}
+	timermgr = NULL;
+#endif /* USE_SHARED_MANAGER */
+
+#ifndef USE_TIMER_THREAD
+	isc__timermgr_dispatch((isc_timermgr_t *)manager);
+#endif
+
+	REQUIRE(EMPTY(manager->timers));
+	manager->done = ISC_TRUE;
+
+#ifdef USE_TIMER_THREAD
+	XTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TIMER,
+			      ISC_MSG_SIGNALDESTROY, "signal (destroy)"));
+	SIGNAL(&manager->wakeup);
+#endif /* USE_TIMER_THREAD */
+
+	UNLOCK(&manager->lock);
+
+#ifdef USE_TIMER_THREAD
+	/*
+	 * Wait for thread to exit.
+	 */
+	if (isc_thread_join(manager->thread, NULL) != ISC_R_SUCCESS)
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "isc_thread_join() %s",
+				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+						ISC_MSG_FAILED, "failed"));
+#endif /* USE_TIMER_THREAD */
+
+	/*
+	 * Clean up.
+	 */
+#ifdef USE_TIMER_THREAD
+	(void)isc_condition_destroy(&manager->wakeup);
+#endif /* USE_TIMER_THREAD */
+	DESTROYLOCK(&manager->lock);
+	isc_heap_destroy(&manager->heap);
+	manager->common.impmagic = 0;
+	manager->common.magic = 0;
+	mctx = manager->mctx;
+	isc_mem_put(mctx, manager, sizeof(*manager));
+	isc_mem_detach(&mctx);
+
+	*managerp = NULL;
+
+#ifdef USE_SHARED_MANAGER
+	timermgr = NULL;
+#endif
+}
+
+#ifndef USE_TIMER_THREAD
+isc_result_t
+isc__timermgr_nextevent(isc_timermgr_t *manager0, isc_time_t *when) {
+	isc__timermgr_t *manager = (isc__timermgr_t *)manager0;
+
+#ifdef USE_SHARED_MANAGER
+	if (manager == NULL)
+		manager = timermgr;
+#endif
+	if (manager == NULL || manager->nscheduled == 0)
+		return (ISC_R_NOTFOUND);
+	*when = manager->due;
+	return (ISC_R_SUCCESS);
+}
+
+void
+isc__timermgr_dispatch(isc_timermgr_t *manager0) {
+	isc__timermgr_t *manager = (isc__timermgr_t *)manager0;
+	isc_time_t now;
+
+#ifdef USE_SHARED_MANAGER
+	if (manager == NULL)
+		manager = timermgr;
+#endif
+	if (manager == NULL)
+		return;
+	TIME_NOW(&now);
+	dispatch(manager, &now);
+}
+#endif /* USE_TIMER_THREAD */
+
+#ifdef USE_TIMERIMPREGISTER
+isc_result_t
+isc__timer_register() {
+	return (isc_timer_register(isc__timermgr_create));
+}
+#endif
diff --git a/src/lib/bind9/timer_api.c b/src/lib/bind9/timer_api.c
new file mode 100644
index 0000000..5a9bf9d
--- /dev/null
+++ b/src/lib/bind9/timer_api.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2009  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: timer_api.c,v 1.4 2009-09-02 23:48:02 tbox Exp $ */
+
+#include <config.h>
+
+#include <unistd.h>
+
+#include <isc/app.h>
+#include <isc/magic.h>
+#include <isc/mutex.h>
+#include <isc/once.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+static isc_mutex_t createlock;
+static isc_once_t once = ISC_ONCE_INIT;
+static isc_timermgrcreatefunc_t timermgr_createfunc = NULL;
+
+static void
+initialize(void) {
+	RUNTIME_CHECK(isc_mutex_init(&createlock) == ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_timer_register(isc_timermgrcreatefunc_t createfunc) {
+	isc_result_t result = ISC_R_SUCCESS;
+
+	RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
+
+	LOCK(&createlock);
+	if (timermgr_createfunc == NULL)
+		timermgr_createfunc = createfunc;
+	else
+		result = ISC_R_EXISTS;
+	UNLOCK(&createlock);
+
+	return (result);
+}
+
+isc_result_t
+isc_timermgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx,
+			 isc_timermgr_t **managerp)
+{
+	isc_result_t result;
+
+	LOCK(&createlock);
+
+	REQUIRE(timermgr_createfunc != NULL);
+	result = (*timermgr_createfunc)(mctx, managerp);
+
+	UNLOCK(&createlock);
+
+	if (result == ISC_R_SUCCESS)
+		isc_appctx_settimermgr(actx, *managerp);
+
+	return (result);
+}
+
+isc_result_t
+isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp) {
+	isc_result_t result;
+
+	LOCK(&createlock);
+
+	REQUIRE(timermgr_createfunc != NULL);
+	result = (*timermgr_createfunc)(mctx, managerp);
+
+	UNLOCK(&createlock);
+
+	return (result);
+}
+
+void
+isc_timermgr_destroy(isc_timermgr_t **managerp) {
+	REQUIRE(*managerp != NULL && ISCAPI_TIMERMGR_VALID(*managerp));
+
+	(*managerp)->methods->destroy(managerp);
+
+	ENSURE(*managerp == NULL);
+}
+
+isc_result_t
+isc_timer_create(isc_timermgr_t *manager, isc_timertype_t type,
+		 isc_time_t *expires, isc_interval_t *interval,
+		 isc_task_t *task, isc_taskaction_t action, const void *arg,
+		 isc_timer_t **timerp)
+{
+	REQUIRE(ISCAPI_TIMERMGR_VALID(manager));
+
+	return (manager->methods->timercreate(manager, type, expires,
+					      interval, task, action, arg,
+					      timerp));
+}
+
+void
+isc_timer_attach(isc_timer_t *timer, isc_timer_t **timerp) {
+	REQUIRE(ISCAPI_TIMER_VALID(timer));
+	REQUIRE(timerp != NULL && *timerp == NULL);
+
+	timer->methods->attach(timer, timerp);
+
+	ENSURE(*timerp == timer);
+}
+
+void
+isc_timer_detach(isc_timer_t **timerp) {
+	REQUIRE(timerp != NULL && ISCAPI_TIMER_VALID(*timerp));
+
+	(*timerp)->methods->detach(timerp);
+
+	ENSURE(*timerp == NULL);
+}
+
+isc_result_t
+isc_timer_reset(isc_timer_t *timer, isc_timertype_t type,
+		isc_time_t *expires, isc_interval_t *interval,
+		isc_boolean_t purge)
+{
+	REQUIRE(ISCAPI_TIMER_VALID(timer));
+
+	return (timer->methods->reset(timer, type, expires, interval, purge));
+}
+
+isc_result_t
+isc_timer_touch(isc_timer_t *timer) {
+	REQUIRE(ISCAPI_TIMER_VALID(timer));
+
+	return (timer->methods->touch(timer));
+}
diff --git a/src/lib/bind9/timer_p.h b/src/lib/bind9/timer_p.h
new file mode 100644
index 0000000..657b695
--- /dev/null
+++ b/src/lib/bind9/timer_p.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: timer_p.h,v 1.12 2009-09-02 23:48:02 tbox Exp $ */
+
+#ifndef ISC_TIMER_P_H
+#define ISC_TIMER_P_H
+
+/*! \file */
+
+isc_result_t
+isc__timermgr_nextevent(isc_timermgr_t *timermgr, isc_time_t *when);
+
+void
+isc__timermgr_dispatch(isc_timermgr_t *timermgr);
+
+#endif /* ISC_TIMER_P_H */
diff --git a/src/lib/bind9/unix/app.c b/src/lib/bind9/unix/app.c
new file mode 100644
index 0000000..4dc5130
--- /dev/null
+++ b/src/lib/bind9/unix/app.c
@@ -0,0 +1,946 @@
+/*
+ * Copyright (C) 2004, 2005, 2007-2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: app.c,v 1.64 2009-11-04 05:58:46 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <sys/param.h>	/* Openserver 5.0.6A and FD_SETSIZE */
+#include <sys/types.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/time.h>
+#ifdef HAVE_EPOLL
+#include <sys/epoll.h>
+#endif
+
+#include <isc/app.h>
+#include <isc/boolean.h>
+#include <isc/condition.h>
+#include <isc/mem.h>
+#include <isc/msgs.h>
+#include <isc/mutex.h>
+#include <isc/event.h>
+#include <isc/platform.h>
+#include <isc/strerror.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/time.h>
+#include <isc/util.h>
+
+/*%
+ * For BIND9 internal applications built with threads, we use a single app
+ * context and let multiple worker, I/O, timer threads do actual jobs.
+ * For other cases (including BIND9 built without threads) an app context acts
+ * as an event loop dispatching various events.
+ */
+#if defined(ISC_PLATFORM_USETHREADS) && defined(BIND9)
+#define USE_THREADS_SINGLECTX
+#endif
+
+#ifdef ISC_PLATFORM_USETHREADS
+#include <pthread.h>
+#endif
+
+#ifndef USE_THREADS_SINGLECTX
+#include "../timer_p.h"
+#include "../task_p.h"
+#include "socket_p.h"
+#endif /* USE_THREADS_SINGLECTX */
+
+#ifdef ISC_PLATFORM_USETHREADS
+static pthread_t		blockedthread;
+#endif /* ISC_PLATFORM_USETHREADS */
+
+/*%
+ * The following can be either static or public, depending on build environment.
+ */
+
+#ifdef BIND9
+#define ISC_APPFUNC_SCOPE
+#else
+#define ISC_APPFUNC_SCOPE static
+#endif
+
+ISC_APPFUNC_SCOPE isc_result_t isc__app_start(void);
+ISC_APPFUNC_SCOPE isc_result_t isc__app_ctxstart(isc_appctx_t *ctx);
+ISC_APPFUNC_SCOPE isc_result_t isc__app_onrun(isc_mem_t *mctx,
+					      isc_task_t *task,
+					      isc_taskaction_t action,
+					      void *arg);
+ISC_APPFUNC_SCOPE isc_result_t isc__app_ctxrun(isc_appctx_t *ctx);
+ISC_APPFUNC_SCOPE isc_result_t isc__app_run(void);
+ISC_APPFUNC_SCOPE isc_result_t isc__app_ctxshutdown(isc_appctx_t *ctx);
+ISC_APPFUNC_SCOPE isc_result_t isc__app_shutdown(void);
+ISC_APPFUNC_SCOPE isc_result_t isc__app_reload(void);
+ISC_APPFUNC_SCOPE isc_result_t isc__app_ctxsuspend(isc_appctx_t *ctx);
+ISC_APPFUNC_SCOPE void isc__app_ctxfinish(isc_appctx_t *ctx);
+ISC_APPFUNC_SCOPE void isc__app_finish(void);
+ISC_APPFUNC_SCOPE void isc__app_block(void);
+ISC_APPFUNC_SCOPE void isc__app_unblock(void);
+ISC_APPFUNC_SCOPE isc_result_t isc__appctx_create(isc_mem_t *mctx,
+						  isc_appctx_t **ctxp);
+ISC_APPFUNC_SCOPE void isc__appctx_destroy(isc_appctx_t **ctxp);
+ISC_APPFUNC_SCOPE void isc__appctx_settaskmgr(isc_appctx_t *ctx,
+					      isc_taskmgr_t *taskmgr);
+ISC_APPFUNC_SCOPE void isc__appctx_setsocketmgr(isc_appctx_t *ctx,
+						isc_socketmgr_t *socketmgr);
+ISC_APPFUNC_SCOPE void isc__appctx_settimermgr(isc_appctx_t *ctx,
+					       isc_timermgr_t *timermgr);
+
+/*
+ * The application context of this module.  This implementation actually
+ * doesn't use it. (This may change in the future).
+ */
+#define APPCTX_MAGIC		ISC_MAGIC('A', 'p', 'c', 'x')
+#define VALID_APPCTX(c)		ISC_MAGIC_VALID(c, APPCTX_MAGIC)
+
+typedef struct isc__appctx {
+	isc_appctx_t		common;
+	isc_mem_t		*mctx;
+	isc_mutex_t		lock;
+	isc_eventlist_t		on_run;
+	isc_boolean_t		shutdown_requested;
+	isc_boolean_t		running;
+
+	/*!
+	 * We assume that 'want_shutdown' can be read and written atomically.
+	 */
+	isc_boolean_t		want_shutdown;
+	/*
+	 * We assume that 'want_reload' can be read and written atomically.
+	 */
+	isc_boolean_t		want_reload;
+
+	isc_boolean_t		blocked;
+
+	isc_taskmgr_t		*taskmgr;
+	isc_socketmgr_t		*socketmgr;
+	isc_timermgr_t		*timermgr;
+} isc__appctx_t;
+
+static isc__appctx_t isc_g_appctx;
+
+static struct {
+	isc_appmethods_t methods;
+
+	/*%
+	 * The following are defined just for avoiding unused static functions.
+	 */
+#ifndef BIND9
+	void *run, *shutdown, *start, *onrun, *reload, *finish,
+		*block, *unblock;
+#endif
+} appmethods = {
+	{
+		isc__appctx_destroy,
+		isc__app_ctxstart,
+		isc__app_ctxrun,
+		isc__app_ctxsuspend,
+		isc__app_ctxshutdown,
+		isc__app_ctxfinish,
+		isc__appctx_settaskmgr,
+		isc__appctx_setsocketmgr,
+		isc__appctx_settimermgr
+	}
+#ifndef BIND9
+	,
+	(void *)isc__app_run, (void *)isc__app_shutdown,
+	(void *)isc__app_start, (void *)isc__app_onrun, (void *)isc__app_reload,
+	(void *)isc__app_finish, (void *)isc__app_block,
+	(void *)isc__app_unblock
+#endif
+};
+
+#ifdef HAVE_LINUXTHREADS
+/*!
+ * Linux has sigwait(), but it appears to prevent signal handlers from
+ * running, even if they're not in the set being waited for.  This makes
+ * it impossible to get the default actions for SIGILL, SIGSEGV, etc.
+ * Instead of messing with it, we just use sigsuspend() instead.
+ */
+#undef HAVE_SIGWAIT
+/*!
+ * We need to remember which thread is the main thread...
+ */
+static pthread_t		main_thread;
+#endif
+
+#ifndef HAVE_SIGWAIT
+static void
+exit_action(int arg) {
+	UNUSED(arg);
+	isc_g_appctx.want_shutdown = ISC_TRUE;
+}
+
+static void
+reload_action(int arg) {
+	UNUSED(arg);
+	isc_g_appctx.want_reload = ISC_TRUE;
+}
+#endif
+
+static isc_result_t
+handle_signal(int sig, void (*handler)(int)) {
+	struct sigaction sa;
+	char strbuf[ISC_STRERRORSIZE];
+
+	memset(&sa, 0, sizeof(sa));
+	sa.sa_handler = handler;
+
+	if (sigfillset(&sa.sa_mask) != 0 ||
+	    sigaction(sig, &sa, NULL) < 0) {
+		isc__strerror(errno, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_APP,
+					       ISC_MSG_SIGNALSETUP,
+					       "handle_signal() %d setup: %s"),
+				 sig, strbuf);
+		return (ISC_R_UNEXPECTED);
+	}
+
+	return (ISC_R_SUCCESS);
+}
+
+ISC_APPFUNC_SCOPE isc_result_t
+isc__app_ctxstart(isc_appctx_t *ctx0) {
+	isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
+	isc_result_t result;
+
+	REQUIRE(VALID_APPCTX(ctx));
+
+	/*
+	 * Start an ISC library application.
+	 */
+
+#ifdef NEED_PTHREAD_INIT
+	/*
+	 * BSDI 3.1 seg faults in pthread_sigmask() if we don't do this.
+	 */
+	presult = pthread_init();
+	if (presult != 0) {
+		isc__strerror(presult, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "isc_app_start() pthread_init: %s", strbuf);
+		return (ISC_R_UNEXPECTED);
+	}
+#endif
+
+#ifdef HAVE_LINUXTHREADS
+	main_thread = pthread_self();
+#endif
+
+	result = isc_mutex_init(&ctx->lock);
+	if (result != ISC_R_SUCCESS)
+		return (result);
+
+	ISC_LIST_INIT(ctx->on_run);
+
+	ctx->shutdown_requested = ISC_FALSE;
+	ctx->running = ISC_FALSE;
+	ctx->want_shutdown = ISC_FALSE;
+	ctx->want_reload = ISC_FALSE;
+	ctx->blocked = ISC_FALSE;
+
+	return (ISC_R_SUCCESS);
+}
+
+ISC_APPFUNC_SCOPE isc_result_t
+isc__app_start(void) {
+	isc_result_t result;
+	int presult;
+	sigset_t sset;
+	char strbuf[ISC_STRERRORSIZE];
+
+	isc_g_appctx.common.impmagic = APPCTX_MAGIC;
+	isc_g_appctx.common.magic = ISCAPI_APPCTX_MAGIC;
+	isc_g_appctx.common.methods = &appmethods.methods;
+	isc_g_appctx.mctx = NULL;
+	/* The remaining members will be initialized in ctxstart() */
+
+	result = isc__app_ctxstart((isc_appctx_t *)&isc_g_appctx);
+	if (result != ISC_R_SUCCESS)
+		return (result);
+
+#ifndef HAVE_SIGWAIT
+	/*
+	 * Install do-nothing handlers for SIGINT and SIGTERM.
+	 *
+	 * We install them now because BSDI 3.1 won't block
+	 * the default actions, regardless of what we do with
+	 * pthread_sigmask().
+	 */
+	result = handle_signal(SIGINT, exit_action);
+	if (result != ISC_R_SUCCESS)
+		return (result);
+	result = handle_signal(SIGTERM, exit_action);
+	if (result != ISC_R_SUCCESS)
+		return (result);
+#endif
+
+	/*
+	 * Always ignore SIGPIPE.
+	 */
+	result = handle_signal(SIGPIPE, SIG_IGN);
+	if (result != ISC_R_SUCCESS)
+		return (result);
+
+	/*
+	 * On Solaris 2, delivery of a signal whose action is SIG_IGN
+	 * will not cause sigwait() to return. We may have inherited
+	 * unexpected actions for SIGHUP, SIGINT, and SIGTERM from our parent
+	 * process (e.g, Solaris cron).  Set an action of SIG_DFL to make
+	 * sure sigwait() works as expected.  Only do this for SIGTERM and
+	 * SIGINT if we don't have sigwait(), since a different handler is
+	 * installed above.
+	 */
+	result = handle_signal(SIGHUP, SIG_DFL);
+	if (result != ISC_R_SUCCESS)
+		return (result);
+
+#ifdef HAVE_SIGWAIT
+	result = handle_signal(SIGTERM, SIG_DFL);
+	if (result != ISC_R_SUCCESS)
+		return (result);
+	result = handle_signal(SIGINT, SIG_DFL);
+	if (result != ISC_R_SUCCESS)
+		return (result);
+#endif
+
+#ifdef ISC_PLATFORM_USETHREADS
+	/*
+	 * Block SIGHUP, SIGINT, SIGTERM.
+	 *
+	 * If isc_app_start() is called from the main thread before any other
+	 * threads have been created, then the pthread_sigmask() call below
+	 * will result in all threads having SIGHUP, SIGINT and SIGTERM
+	 * blocked by default, ensuring that only the thread that calls
+	 * sigwait() for them will get those signals.
+	 */
+	if (sigemptyset(&sset) != 0 ||
+	    sigaddset(&sset, SIGHUP) != 0 ||
+	    sigaddset(&sset, SIGINT) != 0 ||
+	    sigaddset(&sset, SIGTERM) != 0) {
+		isc__strerror(errno, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "isc_app_start() sigsetops: %s", strbuf);
+		return (ISC_R_UNEXPECTED);
+	}
+	presult = pthread_sigmask(SIG_BLOCK, &sset, NULL);
+	if (presult != 0) {
+		isc__strerror(presult, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "isc_app_start() pthread_sigmask: %s",
+				 strbuf);
+		return (ISC_R_UNEXPECTED);
+	}
+#else /* ISC_PLATFORM_USETHREADS */
+	/*
+	 * Unblock SIGHUP, SIGINT, SIGTERM.
+	 *
+	 * If we're not using threads, we need to make sure that SIGHUP,
+	 * SIGINT and SIGTERM are not inherited as blocked from the parent
+	 * process.
+	 */
+	if (sigemptyset(&sset) != 0 ||
+	    sigaddset(&sset, SIGHUP) != 0 ||
+	    sigaddset(&sset, SIGINT) != 0 ||
+	    sigaddset(&sset, SIGTERM) != 0) {
+		isc__strerror(errno, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "isc_app_start() sigsetops: %s", strbuf);
+		return (ISC_R_UNEXPECTED);
+	}
+	presult = sigprocmask(SIG_UNBLOCK, &sset, NULL);
+	if (presult != 0) {
+		isc__strerror(presult, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "isc_app_start() sigprocmask: %s", strbuf);
+		return (ISC_R_UNEXPECTED);
+	}
+#endif /* ISC_PLATFORM_USETHREADS */
+
+	return (ISC_R_SUCCESS);
+}
+
+ISC_APPFUNC_SCOPE isc_result_t
+isc__app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action,
+	      void *arg)
+{
+	isc_event_t *event;
+	isc_task_t *cloned_task = NULL;
+	isc_result_t result;
+
+	LOCK(&isc_g_appctx.lock);
+
+	if (isc_g_appctx.running) {
+		result = ISC_R_ALREADYRUNNING;
+		goto unlock;
+	}
+
+	/*
+	 * Note that we store the task to which we're going to send the event
+	 * in the event's "sender" field.
+	 */
+	isc_task_attach(task, &cloned_task);
+	event = isc_event_allocate(mctx, cloned_task, ISC_APPEVENT_SHUTDOWN,
+				   action, arg, sizeof(*event));
+	if (event == NULL) {
+		result = ISC_R_NOMEMORY;
+		goto unlock;
+	}
+
+	ISC_LIST_APPEND(isc_g_appctx.on_run, event, ev_link);
+
+	result = ISC_R_SUCCESS;
+
+ unlock:
+	UNLOCK(&isc_g_appctx.lock);
+
+	return (result);
+}
+
+#ifndef USE_THREADS_SINGLECTX
+/*!
+ * Event loop for nonthreaded programs.
+ */
+static isc_result_t
+evloop(isc__appctx_t *ctx) {
+	isc_result_t result;
+
+	while (!ctx->want_shutdown) {
+		int n;
+		isc_time_t when, now;
+		struct timeval tv, *tvp;
+		isc_socketwait_t *swait;
+		isc_boolean_t readytasks;
+		isc_boolean_t call_timer_dispatch = ISC_FALSE;
+
+		/*
+		 * Check the reload (or suspend) case first for exiting the
+		 * loop as fast as possible in case:
+		 *   - the direct call to isc__taskmgr_dispatch() in
+		 *     isc__app_ctxrun() completes all the tasks so far,
+		 *   - there is thus currently no active task, and
+		 *   - there is a timer event
+		 */
+		if (ctx->want_reload) {
+			ctx->want_reload = ISC_FALSE;
+			return (ISC_R_RELOAD);
+		}
+
+		readytasks = isc__taskmgr_ready(ctx->taskmgr);
+		if (readytasks) {
+			tv.tv_sec = 0;
+			tv.tv_usec = 0;
+			tvp = &tv;
+			call_timer_dispatch = ISC_TRUE;
+		} else {
+			result = isc__timermgr_nextevent(ctx->timermgr, &when);
+			if (result != ISC_R_SUCCESS)
+				tvp = NULL;
+			else {
+				isc_uint64_t us;
+
+				TIME_NOW(&now);
+				us = isc_time_microdiff(&when, &now);
+				if (us == 0)
+					call_timer_dispatch = ISC_TRUE;
+				tv.tv_sec = us / 1000000;
+				tv.tv_usec = us % 1000000;
+				tvp = &tv;
+			}
+		}
+
+		swait = NULL;
+		n = isc__socketmgr_waitevents(ctx->socketmgr, tvp, &swait);
+
+		if (n == 0 || call_timer_dispatch) {
+			/*
+			 * We call isc__timermgr_dispatch() only when
+			 * necessary, in order to reduce overhead.  If the
+			 * select() call indicates a timeout, we need the
+			 * dispatch.  Even if not, if we set the 0-timeout
+			 * for the select() call, we need to check the timer
+			 * events.  In the 'readytasks' case, there may be no
+			 * timeout event actually, but there is no other way
+			 * to reduce the overhead.
+			 * Note that we do not have to worry about the case
+			 * where a new timer is inserted during the select()
+			 * call, since this loop only runs in the non-thread
+			 * mode.
+			 */
+			isc__timermgr_dispatch(ctx->timermgr);
+		}
+		if (n > 0)
+			(void)isc__socketmgr_dispatch(ctx->socketmgr, swait);
+		(void)isc__taskmgr_dispatch(ctx->taskmgr);
+	}
+	return (ISC_R_SUCCESS);
+}
+#endif	/* USE_THREADS_SINGLECTX */
+
+#ifndef ISC_PLATFORM_USETHREADS
+/*
+ * This is a gross hack to support waiting for condition
+ * variables in nonthreaded programs in a limited way;
+ * see lib/isc/nothreads/include/isc/condition.h.
+ * We implement isc_condition_wait() by entering the
+ * event loop recursively until the want_shutdown flag
+ * is set by isc_condition_signal().
+ */
+
+/*!
+ * \brief True if we are currently executing in the recursive
+ * event loop.
+ */
+static isc_boolean_t in_recursive_evloop = ISC_FALSE;
+
+/*!
+ * \brief True if we are exiting the event loop as the result of
+ * a call to isc_condition_signal() rather than a shutdown
+ * or reload.
+ */
+static isc_boolean_t signalled = ISC_FALSE;
+
+isc_result_t
+isc__nothread_wait_hack(isc_condition_t *cp, isc_mutex_t *mp) {
+	isc_result_t result;
+
+	UNUSED(cp);
+	UNUSED(mp);
+
+	INSIST(!in_recursive_evloop);
+	in_recursive_evloop = ISC_TRUE;
+
+	INSIST(*mp == 1); /* Mutex must be locked on entry. */
+	--*mp;
+
+	result = evloop(&isc_g_appctx);
+	if (result == ISC_R_RELOAD)
+		isc_g_appctx.want_reload = ISC_TRUE;
+	if (signalled) {
+		isc_g_appctx.want_shutdown = ISC_FALSE;
+		signalled = ISC_FALSE;
+	}
+
+	++*mp;
+	in_recursive_evloop = ISC_FALSE;
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc__nothread_signal_hack(isc_condition_t *cp) {
+
+	UNUSED(cp);
+
+	INSIST(in_recursive_evloop);
+
+	isc_g_appctx.want_shutdown = ISC_TRUE;
+	signalled = ISC_TRUE;
+	return (ISC_R_SUCCESS);
+}
+
+#endif /* ISC_PLATFORM_USETHREADS */
+
+ISC_APPFUNC_SCOPE isc_result_t
+isc__app_ctxrun(isc_appctx_t *ctx0) {
+	isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
+	int result;
+	isc_event_t *event, *next_event;
+	isc_task_t *task;
+#ifdef USE_THREADS_SINGLECTX
+	sigset_t sset;
+	char strbuf[ISC_STRERRORSIZE];
+#ifdef HAVE_SIGWAIT
+	int sig;
+#endif
+#endif /* USE_THREADS_SINGLECTX */
+
+	REQUIRE(VALID_APPCTX(ctx));
+
+#ifdef HAVE_LINUXTHREADS
+	REQUIRE(main_thread == pthread_self());
+#endif
+
+	LOCK(&ctx->lock);
+
+	if (!ctx->running) {
+		ctx->running = ISC_TRUE;
+
+		/*
+		 * Post any on-run events (in FIFO order).
+		 */
+		for (event = ISC_LIST_HEAD(ctx->on_run);
+		     event != NULL;
+		     event = next_event) {
+			next_event = ISC_LIST_NEXT(event, ev_link);
+			ISC_LIST_UNLINK(ctx->on_run, event, ev_link);
+			task = event->ev_sender;
+			event->ev_sender = NULL;
+			isc_task_sendanddetach(&task, &event);
+		}
+
+	}
+
+	UNLOCK(&ctx->lock);
+
+#ifndef HAVE_SIGWAIT
+	/*
+	 * Catch SIGHUP.
+	 *
+	 * We do this here to ensure that the signal handler is installed
+	 * (i.e. that it wasn't a "one-shot" handler).
+	 */
+	if (ctx == &isc_g_appctx) {
+		result = handle_signal(SIGHUP, reload_action);
+		if (result != ISC_R_SUCCESS)
+			return (ISC_R_SUCCESS);
+	}
+#endif
+
+#ifdef USE_THREADS_SINGLECTX
+	/*
+	 * When we are using multiple contexts, we don't rely on signals.
+	 */
+	if (ctx != &isc_g_appctx)
+		return (ISC_R_SUCCESS);
+
+	/*
+	 * There is no danger if isc_app_shutdown() is called before we wait
+	 * for signals.  Signals are blocked, so any such signal will simply
+	 * be made pending and we will get it when we call sigwait().
+	 */
+
+	while (!ctx->want_shutdown) {
+#ifdef HAVE_SIGWAIT
+		/*
+		 * Wait for SIGHUP, SIGINT, or SIGTERM.
+		 */
+		if (sigemptyset(&sset) != 0 ||
+		    sigaddset(&sset, SIGHUP) != 0 ||
+		    sigaddset(&sset, SIGINT) != 0 ||
+		    sigaddset(&sset, SIGTERM) != 0) {
+			isc__strerror(errno, strbuf, sizeof(strbuf));
+			UNEXPECTED_ERROR(__FILE__, __LINE__,
+					 "isc_app_run() sigsetops: %s", strbuf);
+			return (ISC_R_UNEXPECTED);
+		}
+
+#ifndef HAVE_UNIXWARE_SIGWAIT
+		result = sigwait(&sset, &sig);
+		if (result == 0) {
+			if (sig == SIGINT || sig == SIGTERM)
+				ctx->want_shutdown = ISC_TRUE;
+			else if (sig == SIGHUP)
+				ctx->want_reload = ISC_TRUE;
+		}
+
+#else /* Using UnixWare sigwait semantics. */
+		sig = sigwait(&sset);
+		if (sig >= 0) {
+			if (sig == SIGINT || sig == SIGTERM)
+				ctx->want_shutdown = ISC_TRUE;
+			else if (sig == SIGHUP)
+				ctx->want_reload = ISC_TRUE;
+		}
+
+#endif /* HAVE_UNIXWARE_SIGWAIT */
+#else  /* Don't have sigwait(). */
+		/*
+		 * Listen for all signals.
+		 */
+		if (sigemptyset(&sset) != 0) {
+			isc__strerror(errno, strbuf, sizeof(strbuf));
+			UNEXPECTED_ERROR(__FILE__, __LINE__,
+					 "isc_app_run() sigsetops: %s",
+					 strbuf);
+			return (ISC_R_UNEXPECTED);
+		}
+		result = sigsuspend(&sset);
+#endif /* HAVE_SIGWAIT */
+
+		if (ctx->want_reload) {
+			ctx->want_reload = ISC_FALSE;
+			return (ISC_R_RELOAD);
+		}
+
+		if (ctx->want_shutdown && ctx->blocked)
+			exit(1);
+	}
+
+#else /* USE_THREADS_SINGLECTX */
+
+	(void)isc__taskmgr_dispatch(ctx->taskmgr);
+
+	result = evloop(ctx);
+	if (result != ISC_R_SUCCESS)
+		return (result);
+
+#endif /* USE_THREADS_SINGLECTX */
+
+	return (ISC_R_SUCCESS);
+}
+
+ISC_APPFUNC_SCOPE isc_result_t
+isc__app_run() {
+	return (isc__app_ctxrun((isc_appctx_t *)&isc_g_appctx));
+}
+
+ISC_APPFUNC_SCOPE isc_result_t
+isc__app_ctxshutdown(isc_appctx_t *ctx0) {
+	isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
+	isc_boolean_t want_kill = ISC_TRUE;
+	char strbuf[ISC_STRERRORSIZE];
+
+	REQUIRE(VALID_APPCTX(ctx));
+
+	LOCK(&ctx->lock);
+
+	REQUIRE(ctx->running);
+
+	if (ctx->shutdown_requested)
+		want_kill = ISC_FALSE;
+	else
+		ctx->shutdown_requested = ISC_TRUE;
+
+	UNLOCK(&ctx->lock);
+
+	if (want_kill) {
+		if (ctx != &isc_g_appctx)
+			ctx->want_shutdown = ISC_TRUE;
+		else {
+#ifdef HAVE_LINUXTHREADS
+			int result;
+
+			result = pthread_kill(main_thread, SIGTERM);
+			if (result != 0) {
+				isc__strerror(result, strbuf, sizeof(strbuf));
+				UNEXPECTED_ERROR(__FILE__, __LINE__,
+						 "isc_app_shutdown() "
+						 "pthread_kill: %s",
+						 strbuf);
+				return (ISC_R_UNEXPECTED);
+			}
+#else
+			if (kill(getpid(), SIGTERM) < 0) {
+				isc__strerror(errno, strbuf, sizeof(strbuf));
+				UNEXPECTED_ERROR(__FILE__, __LINE__,
+						 "isc_app_shutdown() "
+						 "kill: %s", strbuf);
+				return (ISC_R_UNEXPECTED);
+			}
+#endif	/* HAVE_LINUXTHREADS */
+		}
+	}
+
+	return (ISC_R_SUCCESS);
+}
+
+ISC_APPFUNC_SCOPE isc_result_t
+isc__app_shutdown() {
+	return (isc__app_ctxshutdown((isc_appctx_t *)&isc_g_appctx));
+}
+
+ISC_APPFUNC_SCOPE isc_result_t
+isc__app_ctxsuspend(isc_appctx_t *ctx0) {
+	isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
+	isc_boolean_t want_kill = ISC_TRUE;
+	char strbuf[ISC_STRERRORSIZE];
+
+	REQUIRE(VALID_APPCTX(ctx));
+
+	LOCK(&ctx->lock);
+
+	REQUIRE(ctx->running);
+
+	/*
+	 * Don't send the reload signal if we're shutting down.
+	 */
+	if (ctx->shutdown_requested)
+		want_kill = ISC_FALSE;
+
+	UNLOCK(&ctx->lock);
+
+	if (want_kill) {
+		if (ctx != &isc_g_appctx)
+			ctx->want_reload = ISC_TRUE;
+		else {
+#ifdef HAVE_LINUXTHREADS
+			int result;
+
+			result = pthread_kill(main_thread, SIGHUP);
+			if (result != 0) {
+				isc__strerror(result, strbuf, sizeof(strbuf));
+				UNEXPECTED_ERROR(__FILE__, __LINE__,
+						 "isc_app_reload() "
+						 "pthread_kill: %s",
+						 strbuf);
+				return (ISC_R_UNEXPECTED);
+			}
+#else
+			if (kill(getpid(), SIGHUP) < 0) {
+				isc__strerror(errno, strbuf, sizeof(strbuf));
+				UNEXPECTED_ERROR(__FILE__, __LINE__,
+						 "isc_app_reload() "
+						 "kill: %s", strbuf);
+				return (ISC_R_UNEXPECTED);
+			}
+#endif
+		}
+	}
+
+	return (ISC_R_SUCCESS);
+}
+
+ISC_APPFUNC_SCOPE isc_result_t
+isc__app_reload(void) {
+	return (isc__app_ctxsuspend((isc_appctx_t *)&isc_g_appctx));
+}
+
+ISC_APPFUNC_SCOPE void
+isc__app_ctxfinish(isc_appctx_t *ctx0) {
+	isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
+
+	REQUIRE(VALID_APPCTX(ctx));
+
+	DESTROYLOCK(&ctx->lock);
+}
+
+ISC_APPFUNC_SCOPE void
+isc__app_finish(void) {
+	isc__app_ctxfinish((isc_appctx_t *)&isc_g_appctx);
+}
+
+ISC_APPFUNC_SCOPE void
+isc__app_block(void) {
+#ifdef ISC_PLATFORM_USETHREADS
+	sigset_t sset;
+#endif /* ISC_PLATFORM_USETHREADS */
+	REQUIRE(isc_g_appctx.running);
+	REQUIRE(!isc_g_appctx.blocked);
+
+	isc_g_appctx.blocked = ISC_TRUE;
+#ifdef ISC_PLATFORM_USETHREADS
+	blockedthread = pthread_self();
+	RUNTIME_CHECK(sigemptyset(&sset) == 0 &&
+		      sigaddset(&sset, SIGINT) == 0 &&
+		      sigaddset(&sset, SIGTERM) == 0);
+	RUNTIME_CHECK(pthread_sigmask(SIG_UNBLOCK, &sset, NULL) == 0);
+#endif /* ISC_PLATFORM_USETHREADS */
+}
+
+ISC_APPFUNC_SCOPE void
+isc__app_unblock(void) {
+#ifdef ISC_PLATFORM_USETHREADS
+	sigset_t sset;
+#endif /* ISC_PLATFORM_USETHREADS */
+
+	REQUIRE(isc_g_appctx.running);
+	REQUIRE(isc_g_appctx.blocked);
+
+	isc_g_appctx.blocked = ISC_FALSE;
+
+#ifdef ISC_PLATFORM_USETHREADS
+	REQUIRE(blockedthread == pthread_self());
+
+	RUNTIME_CHECK(sigemptyset(&sset) == 0 &&
+		      sigaddset(&sset, SIGINT) == 0 &&
+		      sigaddset(&sset, SIGTERM) == 0);
+	RUNTIME_CHECK(pthread_sigmask(SIG_BLOCK, &sset, NULL) == 0);
+#endif /* ISC_PLATFORM_USETHREADS */
+}
+
+ISC_APPFUNC_SCOPE isc_result_t
+isc__appctx_create(isc_mem_t *mctx, isc_appctx_t **ctxp) {
+	isc__appctx_t *ctx;
+
+	REQUIRE(mctx != NULL);
+	REQUIRE(ctxp != NULL && *ctxp == NULL);
+
+	ctx = isc_mem_get(mctx, sizeof(*ctx));
+	if (ctx == NULL)
+		return (ISC_R_NOMEMORY);
+
+	ctx->common.impmagic = APPCTX_MAGIC;
+	ctx->common.magic = ISCAPI_APPCTX_MAGIC;
+	ctx->common.methods = &appmethods.methods;
+
+	ctx->mctx = NULL;
+	isc_mem_attach(mctx, &ctx->mctx);
+
+	ctx->taskmgr = NULL;
+	ctx->socketmgr = NULL;
+	ctx->timermgr = NULL;
+
+	*ctxp = (isc_appctx_t *)ctx;
+
+	return (ISC_R_SUCCESS);
+}
+
+ISC_APPFUNC_SCOPE void
+isc__appctx_destroy(isc_appctx_t **ctxp) {
+	isc__appctx_t *ctx;
+
+	REQUIRE(ctxp != NULL);
+	ctx = (isc__appctx_t *)*ctxp;
+	REQUIRE(VALID_APPCTX(ctx));
+
+	isc_mem_putanddetach(&ctx->mctx, ctx, sizeof(*ctx));
+
+	*ctxp = NULL;
+}
+
+ISC_APPFUNC_SCOPE void
+isc__appctx_settaskmgr(isc_appctx_t *ctx0, isc_taskmgr_t *taskmgr) {
+	isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
+
+	REQUIRE(VALID_APPCTX(ctx));
+
+	ctx->taskmgr = taskmgr;
+}
+
+ISC_APPFUNC_SCOPE void
+isc__appctx_setsocketmgr(isc_appctx_t *ctx0, isc_socketmgr_t *socketmgr) {
+	isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
+
+	REQUIRE(VALID_APPCTX(ctx));
+
+	ctx->socketmgr = socketmgr;
+}
+
+ISC_APPFUNC_SCOPE void
+isc__appctx_settimermgr(isc_appctx_t *ctx0, isc_timermgr_t *timermgr) {
+	isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
+
+	REQUIRE(VALID_APPCTX(ctx));
+
+	ctx->timermgr = timermgr;
+}
+
+#ifdef USE_APPIMPREGISTER
+isc_result_t
+isc__app_register() {
+	return (isc_app_register(isc__appctx_create));
+}
+#endif
diff --git a/src/lib/bind9/unix/dir.c b/src/lib/bind9/unix/dir.c
new file mode 100644
index 0000000..e670f03
--- /dev/null
+++ b/src/lib/bind9/unix/dir.c
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2004, 2005, 2007-2009, 2011  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: dir.c,v 1.29.404.2 2011-03-12 04:59:19 tbox Exp $ */
+
+/*! \file
+ * \author  Principal Authors: DCL */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <isc/dir.h>
+#include <isc/magic.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include "errno2result.h"
+
+#define ISC_DIR_MAGIC		ISC_MAGIC('D', 'I', 'R', '*')
+#define VALID_DIR(dir)		ISC_MAGIC_VALID(dir, ISC_DIR_MAGIC)
+
+void
+isc_dir_init(isc_dir_t *dir) {
+	REQUIRE(dir != NULL);
+
+	dir->entry.name[0] = '\0';
+	dir->entry.length = 0;
+
+	dir->handle = NULL;
+
+	dir->magic = ISC_DIR_MAGIC;
+}
+
+/*!
+ * \brief Allocate workspace and open directory stream. If either one fails,
+ * NULL will be returned.
+ */
+isc_result_t
+isc_dir_open(isc_dir_t *dir, const char *dirname) {
+	char *p;
+	isc_result_t result = ISC_R_SUCCESS;
+
+	REQUIRE(VALID_DIR(dir));
+	REQUIRE(dirname != NULL);
+
+	/*
+	 * Copy directory name.  Need to have enough space for the name,
+	 * a possible path separator, the wildcard, and the final NUL.
+	 */
+	if (strlen(dirname) + 3 > sizeof(dir->dirname))
+		/* XXXDCL ? */
+		return (ISC_R_NOSPACE);
+	strcpy(dir->dirname, dirname);
+
+	/*
+	 * Append path separator, if needed, and "*".
+	 */
+	p = dir->dirname + strlen(dir->dirname);
+	if (dir->dirname < p && *(p - 1) != '/')
+		*p++ = '/';
+	*p++ = '*';
+	*p = '\0';
+
+	/*
+	 * Open stream.
+	 */
+	dir->handle = opendir(dirname);
+
+	if (dir->handle == NULL)
+		return isc__errno2result(errno);
+
+	return (result);
+}
+
+/*!
+ * \brief Return previously retrieved file or get next one.
+
+ * Unix's dirent has
+ * separate open and read functions, but the Win32 and DOS interfaces open
+ * the dir stream and reads the first file in one operation.
+ */
+isc_result_t
+isc_dir_read(isc_dir_t *dir) {
+	struct dirent *entry;
+
+	REQUIRE(VALID_DIR(dir) && dir->handle != NULL);
+
+	/*
+	 * Fetch next file in directory.
+	 */
+	entry = readdir(dir->handle);
+
+	if (entry == NULL)
+		return (ISC_R_NOMORE);
+
+	/*
+	 * Make sure that the space for the name is long enough.
+	 */
+	if (sizeof(dir->entry.name) <= strlen(entry->d_name))
+	    return (ISC_R_UNEXPECTED);
+
+	strcpy(dir->entry.name, entry->d_name);
+
+	/*
+	 * Some dirents have d_namlen, but it is not portable.
+	 */
+	dir->entry.length = strlen(entry->d_name);
+
+	return (ISC_R_SUCCESS);
+}
+
+/*!
+ * \brief Close directory stream.
+ */
+void
+isc_dir_close(isc_dir_t *dir) {
+       REQUIRE(VALID_DIR(dir) && dir->handle != NULL);
+
+       (void)closedir(dir->handle);
+       dir->handle = NULL;
+}
+
+/*!
+ * \brief Reposition directory stream at start.
+ */
+isc_result_t
+isc_dir_reset(isc_dir_t *dir) {
+	REQUIRE(VALID_DIR(dir) && dir->handle != NULL);
+
+	rewinddir(dir->handle);
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_dir_chdir(const char *dirname) {
+	/*!
+	 * \brief Change the current directory to 'dirname'.
+	 */
+
+	REQUIRE(dirname != NULL);
+
+	if (chdir(dirname) < 0)
+		return (isc__errno2result(errno));
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_dir_chroot(const char *dirname) {
+
+	REQUIRE(dirname != NULL);
+
+#ifdef HAVE_CHROOT
+	if (chroot(dirname) < 0 || chdir("/") < 0)
+		return (isc__errno2result(errno));
+
+	return (ISC_R_SUCCESS);
+#else
+	return (ISC_R_NOTIMPLEMENTED);
+#endif
+}
+
+isc_result_t
+isc_dir_createunique(char *templet) {
+	isc_result_t result;
+	char *x;
+	char *p;
+	int i;
+	int pid;
+
+	REQUIRE(templet != NULL);
+
+	/*!
+	 * \brief mkdtemp is not portable, so this emulates it.
+	 */
+
+	pid = getpid();
+
+	/*
+	 * Replace trailing Xs with the process-id, zero-filled.
+	 */
+	for (x = templet + strlen(templet) - 1; *x == 'X' && x >= templet;
+	     x--, pid /= 10)
+		*x = pid % 10 + '0';
+
+	x++;			/* Set x to start of ex-Xs. */
+
+	do {
+		i = mkdir(templet, 0700);
+		if (i == 0 || errno != EEXIST)
+			break;
+
+		/*
+		 * The BSD algorithm.
+		 */
+		p = x;
+		while (*p != '\0') {
+			if (isdigit(*p & 0xff))
+				*p = 'a';
+			else if (*p != 'z')
+				++*p;
+			else {
+				/*
+				 * Reset character and move to next.
+				 */
+				*p++ = 'a';
+				continue;
+			}
+
+			break;
+		}
+
+		if (*p == '\0') {
+			/*
+			 * Tried all combinations.  errno should already
+			 * be EEXIST, but ensure it is anyway for
+			 * isc__errno2result().
+			 */
+			errno = EEXIST;
+			break;
+		}
+	} while (1);
+
+	if (i == -1)
+		result = isc__errno2result(errno);
+	else
+		result = ISC_R_SUCCESS;
+
+	return (result);
+}
diff --git a/src/lib/bind9/unix/entropy.c b/src/lib/bind9/unix/entropy.c
new file mode 100644
index 0000000..9044632
--- /dev/null
+++ b/src/lib/bind9/unix/entropy.c
@@ -0,0 +1,605 @@
+/*
+ * Copyright (C) 2004-2008  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: entropy.c,v 1.82 2008-12-01 23:47:45 tbox Exp $ */
+
+/* \file unix/entropy.c
+ * \brief
+ * This is the system dependent part of the ISC entropy API.
+ */
+
+#include <config.h>
+
+#include <sys/param.h>	/* Openserver 5.0.6A and FD_SETSIZE */
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#ifdef HAVE_NANOSLEEP
+#include <time.h>
+#endif
+#include <unistd.h>
+
+#include <isc/platform.h>
+#include <isc/strerror.h>
+
+#ifdef ISC_PLATFORM_NEEDSYSSELECTH
+#include <sys/select.h>
+#endif
+
+#include "errno2result.h"
+
+/*%
+ * There is only one variable in the entropy data structures that is not
+ * system independent, but pulling the structure that uses it into this file
+ * ultimately means pulling several other independent structures here also to
+ * resolve their interdependencies.  Thus only the problem variable's type
+ * is defined here.
+ */
+#define FILESOURCE_HANDLE_TYPE	int
+
+typedef struct {
+	int	handle;
+	enum	{
+		isc_usocketsource_disconnected,
+		isc_usocketsource_connecting,
+		isc_usocketsource_connected,
+		isc_usocketsource_ndesired,
+		isc_usocketsource_wrote,
+		isc_usocketsource_reading
+	} status;
+	size_t	sz_to_recv;
+} isc_entropyusocketsource_t;
+
+#include "../entropy.c"
+
+static unsigned int
+get_from_filesource(isc_entropysource_t *source, isc_uint32_t desired) {
+	isc_entropy_t *ent = source->ent;
+	unsigned char buf[128];
+	int fd = source->sources.file.handle;
+	ssize_t n, ndesired;
+	unsigned int added;
+
+	if (source->bad)
+		return (0);
+
+	desired = desired / 8 + (((desired & 0x07) > 0) ? 1 : 0);
+
+	added = 0;
+	while (desired > 0) {
+		ndesired = ISC_MIN(desired, sizeof(buf));
+		n = read(fd, buf, ndesired);
+		if (n < 0) {
+			if (errno == EAGAIN || errno == EINTR)
+				goto out;
+			goto err;
+		}
+		if (n == 0)
+			goto err;
+
+		entropypool_adddata(ent, buf, n, n * 8);
+		added += n * 8;
+		desired -= n;
+	}
+	goto out;
+
+ err:
+	(void)close(fd);
+	source->sources.file.handle = -1;
+	source->bad = ISC_TRUE;
+
+ out:
+	return (added);
+}
+
+static unsigned int
+get_from_usocketsource(isc_entropysource_t *source, isc_uint32_t desired) {
+	isc_entropy_t *ent = source->ent;
+	unsigned char buf[128];
+	int fd = source->sources.usocket.handle;
+	ssize_t n = 0, ndesired;
+	unsigned int added;
+	size_t sz_to_recv = source->sources.usocket.sz_to_recv;
+
+	if (source->bad)
+		return (0);
+
+	desired = desired / 8 + (((desired & 0x07) > 0) ? 1 : 0);
+
+	added = 0;
+	while (desired > 0) {
+		ndesired = ISC_MIN(desired, sizeof(buf));
+ eagain_loop:
+
+		switch ( source->sources.usocket.status ) {
+		case isc_usocketsource_ndesired:
+			buf[0] = ndesired;
+			if ((n = sendto(fd, buf, 1, 0, NULL, 0)) < 0) {
+				if (errno == EWOULDBLOCK || errno == EINTR ||
+				    errno == ECONNRESET)
+					goto out;
+				goto err;
+			}
+			INSIST(n == 1);
+			source->sources.usocket.status =
+						isc_usocketsource_wrote;
+			goto eagain_loop;
+
+		case isc_usocketsource_connecting:
+		case isc_usocketsource_connected:
+			buf[0] = 1;
+			buf[1] = ndesired;
+			if ((n = sendto(fd, buf, 2, 0, NULL, 0)) < 0) {
+				if (errno == EWOULDBLOCK || errno == EINTR ||
+				    errno == ECONNRESET)
+					goto out;
+				goto err;
+			}
+			if (n == 1) {
+				source->sources.usocket.status =
+					isc_usocketsource_ndesired;
+				goto eagain_loop;
+			}
+			INSIST(n == 2);
+			source->sources.usocket.status =
+						isc_usocketsource_wrote;
+			/*FALLTHROUGH*/
+
+		case isc_usocketsource_wrote:
+			if (recvfrom(fd, buf, 1, 0, NULL, NULL) != 1) {
+				if (errno == EAGAIN) {
+					/*
+					 * The problem of EAGAIN (try again
+					 * later) is a major issue on HP-UX.
+					 * Solaris actually tries the recvfrom
+					 * call again, while HP-UX just dies.
+					 * This code is an attempt to let the
+					 * entropy pool fill back up (at least
+					 * that's what I think the problem is.)
+					 * We go to eagain_loop because if we
+					 * just "break", then the "desired"
+					 * amount gets borked.
+					 */
+#ifdef HAVE_NANOSLEEP
+					struct timespec ts;
+
+					ts.tv_sec = 0;
+					ts.tv_nsec = 1000000;
+					nanosleep(&ts, NULL);
+#else
+					usleep(1000);
+#endif
+					goto eagain_loop;
+				}
+				if (errno == EWOULDBLOCK || errno == EINTR)
+					goto out;
+				goto err;
+			}
+			source->sources.usocket.status =
+					isc_usocketsource_reading;
+			sz_to_recv = buf[0];
+			source->sources.usocket.sz_to_recv = sz_to_recv;
+			if (sz_to_recv > sizeof(buf))
+				goto err;
+			/*FALLTHROUGH*/
+
+		case isc_usocketsource_reading:
+			if (sz_to_recv != 0U) {
+				n = recv(fd, buf, sz_to_recv, 0);
+				if (n < 0) {
+					if (errno == EWOULDBLOCK ||
+					    errno == EINTR)
+						goto out;
+					goto err;
+				}
+			} else
+				n = 0;
+			break;
+
+		default:
+			goto err;
+		}
+
+		if ((size_t)n != sz_to_recv)
+			source->sources.usocket.sz_to_recv -= n;
+		else
+			source->sources.usocket.status =
+				isc_usocketsource_connected;
+
+		if (n == 0)
+			goto out;
+
+		entropypool_adddata(ent, buf, n, n * 8);
+		added += n * 8;
+		desired -= n;
+	}
+	goto out;
+
+ err:
+	close(fd);
+	source->bad = ISC_TRUE;
+	source->sources.usocket.status = isc_usocketsource_disconnected;
+	source->sources.usocket.handle = -1;
+
+ out:
+	return (added);
+}
+
+/*
+ * Poll each source, trying to get data from it to stuff into the entropy
+ * pool.
+ */
+static void
+fillpool(isc_entropy_t *ent, unsigned int desired, isc_boolean_t blocking) {
+	unsigned int added;
+	unsigned int remaining;
+	unsigned int needed;
+	unsigned int nsource;
+	isc_entropysource_t *source;
+
+	REQUIRE(VALID_ENTROPY(ent));
+
+	needed = desired;
+
+	/*
+	 * This logic is a little strange, so an explanation is in order.
+	 *
+	 * If needed is 0, it means we are being asked to "fill to whatever
+	 * we think is best."  This means that if we have at least a
+	 * partially full pool (say, > 1/4th of the pool) we probably don't
+	 * need to add anything.
+	 *
+	 * Also, we will check to see if the "pseudo" count is too high.
+	 * If it is, try to mix in better data.  Too high is currently
+	 * defined as 1/4th of the pool.
+	 *
+	 * Next, if we are asked to add a specific bit of entropy, make
+	 * certain that we will do so.  Clamp how much we try to add to
+	 * (DIGEST_SIZE * 8 < needed < POOLBITS - entropy).
+	 *
+	 * Note that if we are in a blocking mode, we will only try to
+	 * get as much data as we need, not as much as we might want
+	 * to build up.
+	 */
+	if (needed == 0) {
+		REQUIRE(!blocking);
+
+		if ((ent->pool.entropy >= RND_POOLBITS / 4)
+		    && (ent->pool.pseudo <= RND_POOLBITS / 4))
+			return;
+
+		needed = THRESHOLD_BITS * 4;
+	} else {
+		needed = ISC_MAX(needed, THRESHOLD_BITS);
+		needed = ISC_MIN(needed, RND_POOLBITS);
+	}
+
+	/*
+	 * In any case, clamp how much we need to how much we can add.
+	 */
+	needed = ISC_MIN(needed, RND_POOLBITS - ent->pool.entropy);
+
+	/*
+	 * But wait!  If we're not yet initialized, we need at least
+	 *	THRESHOLD_BITS
+	 * of randomness.
+	 */
+	if (ent->initialized < THRESHOLD_BITS)
+		needed = ISC_MAX(needed, THRESHOLD_BITS - ent->initialized);
+
+	/*
+	 * Poll each file source to see if we can read anything useful from
+	 * it.  XXXMLG When where are multiple sources, we should keep a
+	 * record of which one we last used so we can start from it (or the
+	 * next one) to avoid letting some sources build up entropy while
+	 * others are always drained.
+	 */
+
+	added = 0;
+	remaining = needed;
+	if (ent->nextsource == NULL) {
+		ent->nextsource = ISC_LIST_HEAD(ent->sources);
+		if (ent->nextsource == NULL)
+			return;
+	}
+	source = ent->nextsource;
+ again_file:
+	for (nsource = 0; nsource < ent->nsources; nsource++) {
+		unsigned int got;
+
+		if (remaining == 0)
+			break;
+
+		got = 0;
+
+		switch ( source->type ) {
+		case ENTROPY_SOURCETYPE_FILE:
+			got = get_from_filesource(source, remaining);
+			break;
+
+		case ENTROPY_SOURCETYPE_USOCKET:
+			got = get_from_usocketsource(source, remaining);
+			break;
+		}
+
+		added += got;
+
+		remaining -= ISC_MIN(remaining, got);
+
+		source = ISC_LIST_NEXT(source, link);
+		if (source == NULL)
+			source = ISC_LIST_HEAD(ent->sources);
+	}
+	ent->nextsource = source;
+
+	if (blocking && remaining != 0) {
+		int fds;
+
+		fds = wait_for_sources(ent);
+		if (fds > 0)
+			goto again_file;
+	}
+
+	/*
+	 * Here, if there are bits remaining to be had and we can block,
+	 * check to see if we have a callback source.  If so, call them.
+	 */
+	source = ISC_LIST_HEAD(ent->sources);
+	while ((remaining != 0) && (source != NULL)) {
+		unsigned int got;
+
+		got = 0;
+
+		if (source->type == ENTROPY_SOURCETYPE_CALLBACK)
+			got = get_from_callback(source, remaining, blocking);
+
+		added += got;
+		remaining -= ISC_MIN(remaining, got);
+
+		if (added >= needed)
+			break;
+
+		source = ISC_LIST_NEXT(source, link);
+	}
+
+	/*
+	 * Mark as initialized if we've added enough data.
+	 */
+	if (ent->initialized < THRESHOLD_BITS)
+		ent->initialized += added;
+}
+
+static int
+wait_for_sources(isc_entropy_t *ent) {
+	isc_entropysource_t *source;
+	int maxfd, fd;
+	int cc;
+	fd_set reads;
+	fd_set writes;
+
+	maxfd = -1;
+	FD_ZERO(&reads);
+	FD_ZERO(&writes);
+
+	source = ISC_LIST_HEAD(ent->sources);
+	while (source != NULL) {
+		if (source->type == ENTROPY_SOURCETYPE_FILE) {
+			fd = source->sources.file.handle;
+			if (fd >= 0) {
+				maxfd = ISC_MAX(maxfd, fd);
+				FD_SET(fd, &reads);
+			}
+		}
+		if (source->type == ENTROPY_SOURCETYPE_USOCKET) {
+			fd = source->sources.usocket.handle;
+			if (fd >= 0) {
+				switch (source->sources.usocket.status) {
+				case isc_usocketsource_disconnected:
+					break;
+				case isc_usocketsource_connecting:
+				case isc_usocketsource_connected:
+				case isc_usocketsource_ndesired:
+					maxfd = ISC_MAX(maxfd, fd);
+					FD_SET(fd, &writes);
+					break;
+				case isc_usocketsource_wrote:
+				case isc_usocketsource_reading:
+					maxfd = ISC_MAX(maxfd, fd);
+					FD_SET(fd, &reads);
+					break;
+				}
+			}
+		}
+		source = ISC_LIST_NEXT(source, link);
+	}
+
+	if (maxfd < 0)
+		return (-1);
+
+	cc = select(maxfd + 1, &reads, &writes, NULL, NULL);
+	if (cc < 0)
+		return (-1);
+
+	return (cc);
+}
+
+static void
+destroyfilesource(isc_entropyfilesource_t *source) {
+	(void)close(source->handle);
+}
+
+static void
+destroyusocketsource(isc_entropyusocketsource_t *source) {
+	close(source->handle);
+}
+
+/*
+ * Make a fd non-blocking
+ */
+static isc_result_t
+make_nonblock(int fd) {
+	int ret;
+	int flags;
+	char strbuf[ISC_STRERRORSIZE];
+#ifdef USE_FIONBIO_IOCTL
+	int on = 1;
+
+	ret = ioctl(fd, FIONBIO, (char *)&on);
+#else
+	flags = fcntl(fd, F_GETFL, 0);
+	flags |= PORT_NONBLOCK;
+	ret = fcntl(fd, F_SETFL, flags);
+#endif
+
+	if (ret == -1) {
+		isc__strerror(errno, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+#ifdef USE_FIONBIO_IOCTL
+				 "ioctl(%d, FIONBIO, &on): %s", fd,
+#else
+				 "fcntl(%d, F_SETFL, %d): %s", fd, flags,
+#endif
+				 strbuf);
+
+		return (ISC_R_UNEXPECTED);
+	}
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_entropy_createfilesource(isc_entropy_t *ent, const char *fname) {
+	int fd;
+	struct stat _stat;
+	isc_boolean_t is_usocket = ISC_FALSE;
+	isc_boolean_t is_connected = ISC_FALSE;
+	isc_result_t ret;
+	isc_entropysource_t *source;
+
+	REQUIRE(VALID_ENTROPY(ent));
+	REQUIRE(fname != NULL);
+
+	LOCK(&ent->lock);
+
+	if (stat(fname, &_stat) < 0) {
+		ret = isc__errno2result(errno);
+		goto errout;
+	}
+	/*
+	 * Solaris 2.5.1 does not have support for sockets (S_IFSOCK),
+	 * but it does return type S_IFIFO (the OS believes that
+	 * the socket is a fifo).  This may be an issue if we tell
+	 * the program to look at an actual FIFO as its source of
+	 * entropy.
+	 */
+#if defined(S_ISSOCK)
+	if (S_ISSOCK(_stat.st_mode))
+		is_usocket = ISC_TRUE;
+#endif
+#if defined(S_ISFIFO) && defined(sun)
+	if (S_ISFIFO(_stat.st_mode))
+		is_usocket = ISC_TRUE;
+#endif
+	if (is_usocket)
+		fd = socket(PF_UNIX, SOCK_STREAM, 0);
+	else
+		fd = open(fname, O_RDONLY | PORT_NONBLOCK, 0);
+
+	if (fd < 0) {
+		ret = isc__errno2result(errno);
+		goto errout;
+	}
+
+	ret = make_nonblock(fd);
+	if (ret != ISC_R_SUCCESS)
+		goto closefd;
+
+	if (is_usocket) {
+		struct sockaddr_un sname;
+
+		memset(&sname, 0, sizeof(sname));
+		sname.sun_family = AF_UNIX;
+		strncpy(sname.sun_path, fname, sizeof(sname.sun_path));
+		sname.sun_path[sizeof(sname.sun_path)-1] = '0';
+#ifdef ISC_PLATFORM_HAVESALEN
+#if !defined(SUN_LEN)
+#define SUN_LEN(su) \
+	(sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
+#endif
+		sname.sun_len = SUN_LEN(&sname);
+#endif
+
+		if (connect(fd, (struct sockaddr *) &sname,
+			    sizeof(struct sockaddr_un)) < 0) {
+			if (errno != EINPROGRESS) {
+				ret = isc__errno2result(errno);
+				goto closefd;
+			}
+		} else
+			is_connected = ISC_TRUE;
+	}
+
+	source = isc_mem_get(ent->mctx, sizeof(isc_entropysource_t));
+	if (source == NULL) {
+		ret = ISC_R_NOMEMORY;
+		goto closefd;
+	}
+
+	/*
+	 * From here down, no failures can occur.
+	 */
+	source->magic = SOURCE_MAGIC;
+	source->ent = ent;
+	source->total = 0;
+	source->bad = ISC_FALSE;
+	memset(source->name, 0, sizeof(source->name));
+	ISC_LINK_INIT(source, link);
+	if (is_usocket) {
+		source->sources.usocket.handle = fd;
+		if (is_connected)
+			source->sources.usocket.status =
+					isc_usocketsource_connected;
+		else
+			source->sources.usocket.status =
+					isc_usocketsource_connecting;
+		source->sources.usocket.sz_to_recv = 0;
+		source->type = ENTROPY_SOURCETYPE_USOCKET;
+	} else {
+		source->sources.file.handle = fd;
+		source->type = ENTROPY_SOURCETYPE_FILE;
+	}
+
+	/*
+	 * Hook it into the entropy system.
+	 */
+	ISC_LIST_APPEND(ent->sources, source, link);
+	ent->nsources++;
+
+	UNLOCK(&ent->lock);
+	return (ISC_R_SUCCESS);
+
+ closefd:
+	(void)close(fd);
+
+ errout:
+	UNLOCK(&ent->lock);
+
+	return (ret);
+}
diff --git a/src/lib/bind9/unix/errno2result.c b/src/lib/bind9/unix/errno2result.c
new file mode 100644
index 0000000..4252de6
--- /dev/null
+++ b/src/lib/bind9/unix/errno2result.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2002  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: errno2result.c,v 1.17 2007-06-19 23:47:18 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/result.h>
+#include <isc/strerror.h>
+#include <isc/util.h>
+
+#include "errno2result.h"
+
+/*%
+ * Convert a POSIX errno value into an isc_result_t.  The
+ * list of supported errno values is not complete; new users
+ * of this function should add any expected errors that are
+ * not already there.
+ */
+isc_result_t
+isc__errno2result(int posixerrno) {
+	char strbuf[ISC_STRERRORSIZE];
+
+	switch (posixerrno) {
+	case ENOTDIR:
+	case ELOOP:
+	case EINVAL:		/* XXX sometimes this is not for files */
+	case ENAMETOOLONG:
+	case EBADF:
+		return (ISC_R_INVALIDFILE);
+	case ENOENT:
+		return (ISC_R_FILENOTFOUND);
+	case EACCES:
+	case EPERM:
+		return (ISC_R_NOPERM);
+	case EEXIST:
+		return (ISC_R_FILEEXISTS);
+	case EIO:
+		return (ISC_R_IOERROR);
+	case ENOMEM:
+		return (ISC_R_NOMEMORY);
+	case ENFILE:	
+	case EMFILE:
+		return (ISC_R_TOOMANYOPENFILES);
+	case EPIPE:
+#ifdef ECONNRESET
+	case ECONNRESET:
+#endif
+#ifdef ECONNABORTED
+	case ECONNABORTED:
+#endif
+		return (ISC_R_CONNECTIONRESET);
+#ifdef ENOTCONN
+	case ENOTCONN:
+		return (ISC_R_NOTCONNECTED);
+#endif
+#ifdef ETIMEDOUT
+	case ETIMEDOUT:
+		return (ISC_R_TIMEDOUT);
+#endif
+#ifdef ENOBUFS
+	case ENOBUFS:
+		return (ISC_R_NORESOURCES);
+#endif
+#ifdef EAFNOSUPPORT
+	case EAFNOSUPPORT:
+		return (ISC_R_FAMILYNOSUPPORT);
+#endif
+#ifdef ENETDOWN
+	case ENETDOWN:
+		return (ISC_R_NETDOWN);
+#endif
+#ifdef EHOSTDOWN
+	case EHOSTDOWN:
+		return (ISC_R_HOSTDOWN);
+#endif
+#ifdef ENETUNREACH
+	case ENETUNREACH:
+		return (ISC_R_NETUNREACH);
+#endif
+#ifdef EHOSTUNREACH
+	case EHOSTUNREACH:
+		return (ISC_R_HOSTUNREACH);
+#endif
+#ifdef EADDRINUSE
+	case EADDRINUSE:
+		return (ISC_R_ADDRINUSE);
+#endif
+	case EADDRNOTAVAIL:
+		return (ISC_R_ADDRNOTAVAIL);
+	case ECONNREFUSED:
+		return (ISC_R_CONNREFUSED);
+	default:
+		isc__strerror(posixerrno, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "unable to convert errno "
+				 "to isc_result: %d: %s",
+				 posixerrno, strbuf);
+		/*
+		 * XXXDCL would be nice if perhaps this function could
+		 * return the system's error string, so the caller
+		 * might have something more descriptive than "unexpected
+		 * error" to log with.
+		 */
+		return (ISC_R_UNEXPECTED);
+	}
+}
diff --git a/src/lib/bind9/unix/errno2result.h b/src/lib/bind9/unix/errno2result.h
new file mode 100644
index 0000000..8770a05
--- /dev/null
+++ b/src/lib/bind9/unix/errno2result.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: errno2result.h,v 1.12 2007-06-19 23:47:18 tbox Exp $ */
+
+#ifndef UNIX_ERRNO2RESULT_H
+#define UNIX_ERRNO2RESULT_H 1
+
+/*! \file */
+
+/* XXXDCL this should be moved to lib/isc/include/isc/errno2result.h. */
+
+#include <errno.h>		/* Provides errno. */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc__errno2result(int posixerrno);
+
+ISC_LANG_ENDDECLS
+
+#endif /* UNIX_ERRNO2RESULT_H */
diff --git a/src/lib/bind9/unix/file.c b/src/lib/bind9/unix/file.c
new file mode 100644
index 0000000..3e4d3e0
--- /dev/null
+++ b/src/lib/bind9/unix/file.c
@@ -0,0 +1,541 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2009, 2011  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2002  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Portions Copyright (c) 1987, 1993
+ *      The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by the University of
+ *      California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $Id: file.c,v 1.57.10.1 2011-03-04 14:10:13 smann Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <time.h>		/* Required for utimes on some platforms. */
+#include <unistd.h>		/* Required for mkstemp on NetBSD. */
+
+
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include <isc/dir.h>
+#include <isc/file.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/random.h>
+#include <isc/string.h>
+#include <isc/time.h>
+#include <isc/util.h>
+
+#include "errno2result.h"
+
+/*
+ * XXXDCL As the API for accessing file statistics undoubtedly gets expanded,
+ * it might be good to provide a mechanism that allows for the results
+ * of a previous stat() to be used again without having to do another stat,
+ * such as perl's mechanism of using "_" in place of a file name to indicate
+ * that the results of the last stat should be used.  But then you get into
+ * annoying MP issues.   BTW, Win32 has stat().
+ */
+static isc_result_t
+file_stats(const char *file, struct stat *stats) {
+	isc_result_t result = ISC_R_SUCCESS;
+
+	REQUIRE(file != NULL);
+	REQUIRE(stats != NULL);
+
+	if (stat(file, stats) != 0)
+		result = isc__errno2result(errno);
+
+	return (result);
+}
+
+isc_result_t
+isc_file_getmodtime(const char *file, isc_time_t *time) {
+	isc_result_t result;
+	struct stat stats;
+
+	REQUIRE(file != NULL);
+	REQUIRE(time != NULL);
+
+	result = file_stats(file, &stats);
+
+	if (result == ISC_R_SUCCESS)
+		/*
+		 * XXXDCL some operating systems provide nanoseconds, too,
+		 * such as BSD/OS via st_mtimespec.
+		 */
+		isc_time_set(time, stats.st_mtime, 0);
+
+	return (result);
+}
+
+isc_result_t
+isc_file_settime(const char *file, isc_time_t *time) {
+	struct timeval times[2];
+
+	REQUIRE(file != NULL && time != NULL);
+
+	/*
+	 * tv_sec is at least a 32 bit quantity on all platforms we're
+	 * dealing with, but it is signed on most (all?) of them,
+	 * so we need to make sure the high bit isn't set.  This unfortunately
+	 * loses when either:
+	 *   * tv_sec becomes a signed 64 bit integer but long is 32 bits
+	 *	and isc_time_seconds > LONG_MAX, or
+	 *   * isc_time_seconds is changed to be > 32 bits but long is 32 bits
+	 *      and isc_time_seconds has at least 33 significant bits.
+	 */
+	times[0].tv_sec = times[1].tv_sec = (long)isc_time_seconds(time);
+
+	/*
+	 * Here is the real check for the high bit being set.
+	 */
+	if ((times[0].tv_sec &
+	     (1ULL << (sizeof(times[0].tv_sec) * CHAR_BIT - 1))) != 0)
+		return (ISC_R_RANGE);
+
+	/*
+	 * isc_time_nanoseconds guarantees a value that divided by 1000 will
+	 * fit into the minimum possible size tv_usec field.  Unfortunately,
+	 * we don't know what that type is so can't cast directly ... but
+	 * we can at least cast to signed so the IRIX compiler shuts up.
+	 */
+	times[0].tv_usec = times[1].tv_usec =
+		(isc_int32_t)(isc_time_nanoseconds(time) / 1000);
+
+	if (utimes(file, times) < 0)
+		return (isc__errno2result(errno));
+
+	return (ISC_R_SUCCESS);
+}
+
+#undef TEMPLATE
+#define TEMPLATE "tmp-XXXXXXXXXX" /*%< 14 characters. */
+
+isc_result_t
+isc_file_mktemplate(const char *path, char *buf, size_t buflen) {
+	return (isc_file_template(path, TEMPLATE, buf, buflen));
+}
+
+isc_result_t
+isc_file_template(const char *path, const char *templet, char *buf,
+			size_t buflen) {
+	char *s;
+
+	REQUIRE(path != NULL);
+	REQUIRE(templet != NULL);
+	REQUIRE(buf != NULL);
+
+	s = strrchr(templet, '/');
+	if (s != NULL)
+		templet = s + 1;
+
+	s = strrchr(path, '/');
+
+	if (s != NULL) {
+		if ((s - path + 1 + strlen(templet) + 1) > buflen)
+			return (ISC_R_NOSPACE);
+
+		strncpy(buf, path, s - path + 1);
+		buf[s - path + 1] = '\0';
+		strcat(buf, templet);
+	} else {
+		if ((strlen(templet) + 1) > buflen)
+			return (ISC_R_NOSPACE);
+
+		strcpy(buf, templet);
+	}
+
+	return (ISC_R_SUCCESS);
+}
+
+static char alphnum[] =
+	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+
+isc_result_t
+isc_file_renameunique(const char *file, char *templet) {
+	char *x;
+	char *cp;
+	isc_uint32_t which;
+
+	REQUIRE(file != NULL);
+	REQUIRE(templet != NULL);
+
+	cp = templet;
+	while (*cp != '\0')
+		cp++;
+	if (cp == templet)
+		return (ISC_R_FAILURE);
+
+	x = cp--;
+	while (cp >= templet && *cp == 'X') {
+		isc_random_get(&which);
+		*cp = alphnum[which % (sizeof(alphnum) - 1)];
+		x = cp--;
+	}
+	while (link(file, templet) == -1) {
+		if (errno != EEXIST)
+			return (isc__errno2result(errno));
+		for (cp = x;;) {
+			char *t;
+			if (*cp == '\0')
+				return (ISC_R_FAILURE);
+			t = strchr(alphnum, *cp);
+			if (t == NULL || *++t == '\0')
+				*cp++ = alphnum[0];
+			else {
+				*cp = *t;
+				break;
+			}
+		}
+	}
+	if (unlink(file) < 0)
+		if (errno != ENOENT)
+			return (isc__errno2result(errno));
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_file_openunique(char *templet, FILE **fp) {
+	int mode = S_IWUSR|S_IRUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;
+	return (isc_file_openuniquemode(templet, mode, fp));
+}
+
+isc_result_t
+isc_file_openuniqueprivate(char *templet, FILE **fp) {
+	int mode = S_IWUSR|S_IRUSR;
+	return (isc_file_openuniquemode(templet, mode, fp));
+}
+
+isc_result_t
+isc_file_openuniquemode(char *templet, int mode, FILE **fp) {
+	int fd;
+	FILE *f;
+	isc_result_t result = ISC_R_SUCCESS;
+	char *x;
+	char *cp;
+	isc_uint32_t which;
+
+	REQUIRE(templet != NULL);
+	REQUIRE(fp != NULL && *fp == NULL);
+
+	cp = templet;
+	while (*cp != '\0')
+		cp++;
+	if (cp == templet)
+		return (ISC_R_FAILURE);
+
+	x = cp--;
+	while (cp >= templet && *cp == 'X') {
+		isc_random_get(&which);
+		*cp = alphnum[which % (sizeof(alphnum) - 1)];
+		x = cp--;
+	}
+
+
+	while ((fd = open(templet, O_RDWR|O_CREAT|O_EXCL, mode)) == -1) {
+		if (errno != EEXIST)
+			return (isc__errno2result(errno));
+		for (cp = x;;) {
+			char *t;
+			if (*cp == '\0')
+				return (ISC_R_FAILURE);
+			t = strchr(alphnum, *cp);
+			if (t == NULL || *++t == '\0')
+				*cp++ = alphnum[0];
+			else {
+				*cp = *t;
+				break;
+			}
+		}
+	}
+	f = fdopen(fd, "w+");
+	if (f == NULL) {
+		result = isc__errno2result(errno);
+		if (remove(templet) < 0) {
+			isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+				      ISC_LOGMODULE_FILE, ISC_LOG_ERROR,
+				      "remove '%s': failed", templet);
+		}
+		(void)close(fd);
+	} else
+		*fp = f;
+
+	return (result);
+}
+
+isc_result_t
+isc_file_remove(const char *filename) {
+	int r;
+
+	REQUIRE(filename != NULL);
+
+	r = unlink(filename);
+	if (r == 0)
+		return (ISC_R_SUCCESS);
+	else
+		return (isc__errno2result(errno));
+}
+
+isc_result_t
+isc_file_rename(const char *oldname, const char *newname) {
+	int r;
+
+	REQUIRE(oldname != NULL);
+	REQUIRE(newname != NULL);
+
+	r = rename(oldname, newname);
+	if (r == 0)
+		return (ISC_R_SUCCESS);
+	else
+		return (isc__errno2result(errno));
+}
+
+isc_boolean_t
+isc_file_exists(const char *pathname) {
+	struct stat stats;
+
+	REQUIRE(pathname != NULL);
+
+	return (ISC_TF(file_stats(pathname, &stats) == ISC_R_SUCCESS));
+}
+
+isc_result_t
+isc_file_isplainfile(const char *filename) {
+	/*
+	 * This function returns success if filename is a plain file.
+	 */
+	struct stat filestat;
+	memset(&filestat,0,sizeof(struct stat));
+
+	if ((stat(filename, &filestat)) == -1)
+		return(isc__errno2result(errno));
+
+	if(! S_ISREG(filestat.st_mode))
+		return(ISC_R_INVALIDFILE);
+
+	return(ISC_R_SUCCESS);
+}
+
+isc_boolean_t
+isc_file_isabsolute(const char *filename) {
+	REQUIRE(filename != NULL);
+	return (ISC_TF(filename[0] == '/'));
+}
+
+isc_boolean_t
+isc_file_iscurrentdir(const char *filename) {
+	REQUIRE(filename != NULL);
+	return (ISC_TF(filename[0] == '.' && filename[1] == '\0'));
+}
+
+isc_boolean_t
+isc_file_ischdiridempotent(const char *filename) {
+	REQUIRE(filename != NULL);
+	if (isc_file_isabsolute(filename))
+		return (ISC_TRUE);
+	if (isc_file_iscurrentdir(filename))
+		return (ISC_TRUE);
+	return (ISC_FALSE);
+}
+
+const char *
+isc_file_basename(const char *filename) {
+	char *s;
+
+	REQUIRE(filename != NULL);
+
+	s = strrchr(filename, '/');
+	if (s == NULL)
+		return (filename);
+
+	return (s + 1);
+}
+
+isc_result_t
+isc_file_progname(const char *filename, char *buf, size_t buflen) {
+	const char *base;
+	size_t len;
+
+	REQUIRE(filename != NULL);
+	REQUIRE(buf != NULL);
+
+	base = isc_file_basename(filename);
+	len = strlen(base) + 1;
+
+	if (len > buflen)
+		return (ISC_R_NOSPACE);
+	memcpy(buf, base, len);
+
+	return (ISC_R_SUCCESS);
+}
+
+/*
+ * Put the absolute name of the current directory into 'dirname', which is
+ * a buffer of at least 'length' characters.  End the string with the
+ * appropriate path separator, such that the final product could be
+ * concatenated with a relative pathname to make a valid pathname string.
+ */
+static isc_result_t
+dir_current(char *dirname, size_t length) {
+	char *cwd;
+	isc_result_t result = ISC_R_SUCCESS;
+
+	REQUIRE(dirname != NULL);
+	REQUIRE(length > 0U);
+
+	cwd = getcwd(dirname, length);
+
+	if (cwd == NULL) {
+		if (errno == ERANGE)
+			result = ISC_R_NOSPACE;
+		else
+			result = isc__errno2result(errno);
+	} else {
+		if (strlen(dirname) + 1 == length)
+			result = ISC_R_NOSPACE;
+		else if (dirname[1] != '\0')
+			strcat(dirname, "/");
+	}
+
+	return (result);
+}
+
+isc_result_t
+isc_file_absolutepath(const char *filename, char *path, size_t pathlen) {
+	isc_result_t result;
+	result = dir_current(path, pathlen);
+	if (result != ISC_R_SUCCESS)
+		return (result);
+	if (strlen(path) + strlen(filename) + 1 > pathlen)
+		return (ISC_R_NOSPACE);
+	strcat(path, filename);
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_file_truncate(const char *filename, isc_offset_t size) {
+	isc_result_t result = ISC_R_SUCCESS;
+
+	if (truncate(filename, size) < 0)
+		result = isc__errno2result(errno);
+	return (result);
+}
+
+isc_result_t
+isc_file_safecreate(const char *filename, FILE **fp) {
+	isc_result_t result;
+	int flags;
+	struct stat sb;
+	FILE *f;
+	int fd;
+
+	REQUIRE(filename != NULL);
+	REQUIRE(fp != NULL && *fp == NULL);
+
+	result = file_stats(filename, &sb);
+	if (result == ISC_R_SUCCESS) {
+		if ((sb.st_mode & S_IFREG) == 0)
+			return (ISC_R_INVALIDFILE);
+		flags = O_WRONLY | O_TRUNC;
+	} else if (result == ISC_R_FILENOTFOUND) {
+		flags = O_WRONLY | O_CREAT | O_EXCL;
+	} else
+		return (result);
+
+	fd = open(filename, flags, S_IRUSR | S_IWUSR);
+	if (fd == -1)
+		return (isc__errno2result(errno));
+
+	f = fdopen(fd, "w");
+	if (f == NULL) {
+		result = isc__errno2result(errno);
+		close(fd);
+		return (result);
+	}
+
+	*fp = f;
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_file_splitpath(isc_mem_t *mctx, char *path, char **dirname, char **basename)
+{
+	char *dir, *file, *slash;
+
+	slash = strrchr(path, '/');
+
+	if (slash == path) {
+		file = ++slash;
+		dir = isc_mem_strdup(mctx, "/");
+	} else if (slash != NULL) {
+		file = ++slash;
+		dir = isc_mem_allocate(mctx, slash - path);
+		if (dir != NULL)
+			strlcpy(dir, path, slash - path);
+	} else {
+		file = path;
+		dir = isc_mem_strdup(mctx, ".");
+	}
+
+	if (dir == NULL)
+		return (ISC_R_NOMEMORY);
+
+	if (*file == '\0') {
+		isc_mem_free(mctx, dir);
+		return (ISC_R_INVALIDFILE);
+	}
+
+	*dirname = dir;
+	*basename = file;
+
+	return (ISC_R_SUCCESS);
+}
diff --git a/src/lib/bind9/unix/fsaccess.c b/src/lib/bind9/unix/fsaccess.c
new file mode 100644
index 0000000..c974819
--- /dev/null
+++ b/src/lib/bind9/unix/fsaccess.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: fsaccess.c,v 1.13 2007-06-19 23:47:18 tbox Exp $ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+
+#include "errno2result.h"
+
+/*! \file
+ * \brief
+ * The OS-independent part of the API is in lib/isc.
+ */
+#include "../fsaccess.c"
+
+isc_result_t
+isc_fsaccess_set(const char *path, isc_fsaccess_t access) {
+	struct stat statb;
+	mode_t mode;
+	isc_boolean_t is_dir = ISC_FALSE;
+	isc_fsaccess_t bits;
+	isc_result_t result;
+
+	if (stat(path, &statb) != 0)
+		return (isc__errno2result(errno));
+
+	if ((statb.st_mode & S_IFDIR) != 0)
+		is_dir = ISC_TRUE;
+	else if ((statb.st_mode & S_IFREG) == 0)
+		return (ISC_R_INVALIDFILE);
+
+	result = check_bad_bits(access, is_dir);
+	if (result != ISC_R_SUCCESS)
+		return (result);
+
+	/*
+	 * Done with checking bad bits.  Set mode_t.
+	 */
+	mode = 0;
+
+#define SET_AND_CLEAR1(modebit) \
+	if ((access & bits) != 0) { \
+		mode |= modebit; \
+		access &= ~bits; \
+	}
+#define SET_AND_CLEAR(user, group, other) \
+	SET_AND_CLEAR1(user); \
+	bits <<= STEP; \
+	SET_AND_CLEAR1(group); \
+	bits <<= STEP; \
+	SET_AND_CLEAR1(other);
+
+	bits = ISC_FSACCESS_READ | ISC_FSACCESS_LISTDIRECTORY;
+
+	SET_AND_CLEAR(S_IRUSR, S_IRGRP, S_IROTH);
+
+	bits = ISC_FSACCESS_WRITE |
+	       ISC_FSACCESS_CREATECHILD |
+	       ISC_FSACCESS_DELETECHILD;
+
+	SET_AND_CLEAR(S_IWUSR, S_IWGRP, S_IWOTH);
+
+	bits = ISC_FSACCESS_EXECUTE |
+	       ISC_FSACCESS_ACCESSCHILD;
+
+	SET_AND_CLEAR(S_IXUSR, S_IXGRP, S_IXOTH);
+
+	INSIST(access == 0);
+
+	if (chmod(path, mode) < 0)
+		return (isc__errno2result(errno));
+
+	return (ISC_R_SUCCESS);
+}
diff --git a/src/lib/bind9/unix/ifiter_getifaddrs.c b/src/lib/bind9/unix/ifiter_getifaddrs.c
new file mode 100644
index 0000000..90a3faf
--- /dev/null
+++ b/src/lib/bind9/unix/ifiter_getifaddrs.c
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2004, 2005, 2007-2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: ifiter_getifaddrs.c,v 1.13 2009-09-24 23:48:13 tbox Exp $ */
+
+/*! \file
+ * \brief
+ * Obtain the list of network interfaces using the getifaddrs(3) library.
+ */
+
+#include <ifaddrs.h>
+
+/*% Iterator Magic */
+#define IFITER_MAGIC		ISC_MAGIC('I', 'F', 'I', 'G')
+/*% Valid Iterator */
+#define VALID_IFITER(t)		ISC_MAGIC_VALID(t, IFITER_MAGIC)
+
+#ifdef __linux
+static isc_boolean_t seenv6 = ISC_FALSE;
+#endif
+
+/*% Iterator structure */
+struct isc_interfaceiter {
+	unsigned int		magic;		/*%< Magic number. */
+	isc_mem_t		*mctx;
+	void			*buf;		/*%< (unused) */
+	unsigned int		bufsize;	/*%< (always 0) */
+	struct ifaddrs		*ifaddrs;	/*%< List of ifaddrs */
+	struct ifaddrs		*pos;		/*%< Ptr to current ifaddr */
+	isc_interface_t		current;	/*%< Current interface data. */
+	isc_result_t		result;		/*%< Last result code. */
+#ifdef  __linux
+	FILE *                  proc;
+	char                    entry[ISC_IF_INET6_SZ];
+	isc_result_t            valid;
+#endif
+};
+
+isc_result_t
+isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) {
+	isc_interfaceiter_t *iter;
+	isc_result_t result;
+	char strbuf[ISC_STRERRORSIZE];
+
+	REQUIRE(mctx != NULL);
+	REQUIRE(iterp != NULL);
+	REQUIRE(*iterp == NULL);
+
+	iter = isc_mem_get(mctx, sizeof(*iter));
+	if (iter == NULL)
+		return (ISC_R_NOMEMORY);
+
+	iter->mctx = mctx;
+	iter->buf = NULL;
+	iter->bufsize = 0;
+	iter->ifaddrs = NULL;
+#ifdef __linux
+	/*
+	 * Only open "/proc/net/if_inet6" if we have never seen a IPv6
+	 * address returned by getifaddrs().
+	 */
+	if (!seenv6)
+		iter->proc = fopen("/proc/net/if_inet6", "r");
+	else
+		iter->proc = NULL;
+	iter->valid = ISC_R_FAILURE;
+#endif
+
+	if (getifaddrs(&iter->ifaddrs) < 0) {
+		isc__strerror(errno, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 isc_msgcat_get(isc_msgcat,
+						ISC_MSGSET_IFITERGETIFADDRS,
+						ISC_MSG_GETIFADDRS,
+						"getting interface "
+						"addresses: getifaddrs: %s"),
+				 strbuf);
+		result = ISC_R_UNEXPECTED;
+		goto failure;
+	}
+
+	/*
+	 * A newly created iterator has an undefined position
+	 * until isc_interfaceiter_first() is called.
+	 */
+	iter->pos = NULL;
+	iter->result = ISC_R_FAILURE;
+
+	iter->magic = IFITER_MAGIC;
+	*iterp = iter;
+	return (ISC_R_SUCCESS);
+
+ failure:
+#ifdef __linux
+	if (iter->proc != NULL)
+		fclose(iter->proc);
+#endif
+	if (iter->ifaddrs != NULL) /* just in case */
+		freeifaddrs(iter->ifaddrs);
+	isc_mem_put(mctx, iter, sizeof(*iter));
+	return (result);
+}
+
+/*
+ * Get information about the current interface to iter->current.
+ * If successful, return ISC_R_SUCCESS.
+ * If the interface has an unsupported address family,
+ * return ISC_R_IGNORE.
+ */
+
+static isc_result_t
+internal_current(isc_interfaceiter_t *iter) {
+	struct ifaddrs *ifa;
+	int family;
+	unsigned int namelen;
+
+	REQUIRE(VALID_IFITER(iter));
+
+	ifa = iter->pos;
+
+#ifdef __linux
+	if (iter->pos == NULL)
+		return (linux_if_inet6_current(iter));
+#endif
+
+	INSIST(ifa != NULL);
+	INSIST(ifa->ifa_name != NULL);
+
+	if (ifa->ifa_addr == NULL)
+		return (ISC_R_IGNORE);
+
+	family = ifa->ifa_addr->sa_family;
+	if (family != AF_INET && family != AF_INET6)
+		return (ISC_R_IGNORE);
+
+#ifdef __linux
+	if (family == AF_INET6)
+		seenv6 = ISC_TRUE;
+#endif
+
+	memset(&iter->current, 0, sizeof(iter->current));
+
+	namelen = strlen(ifa->ifa_name);
+	if (namelen > sizeof(iter->current.name) - 1)
+		namelen = sizeof(iter->current.name) - 1;
+
+	memset(iter->current.name, 0, sizeof(iter->current.name));
+	memcpy(iter->current.name, ifa->ifa_name, namelen);
+
+	iter->current.flags = 0;
+
+	if ((ifa->ifa_flags & IFF_UP) != 0)
+		iter->current.flags |= INTERFACE_F_UP;
+
+	if ((ifa->ifa_flags & IFF_POINTOPOINT) != 0)
+		iter->current.flags |= INTERFACE_F_POINTTOPOINT;
+
+	if ((ifa->ifa_flags & IFF_LOOPBACK) != 0)
+		iter->current.flags |= INTERFACE_F_LOOPBACK;
+
+	iter->current.af = family;
+
+	get_addr(family, &iter->current.address, ifa->ifa_addr, ifa->ifa_name);
+
+	if (ifa->ifa_netmask != NULL)
+		get_addr(family, &iter->current.netmask, ifa->ifa_netmask,
+			 ifa->ifa_name);
+
+	if (ifa->ifa_dstaddr != NULL &&
+	    (iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0)
+		get_addr(family, &iter->current.dstaddress, ifa->ifa_dstaddr,
+			 ifa->ifa_name);
+
+	return (ISC_R_SUCCESS);
+}
+
+/*
+ * Step the iterator to the next interface.  Unlike
+ * isc_interfaceiter_next(), this may leave the iterator
+ * positioned on an interface that will ultimately
+ * be ignored.  Return ISC_R_NOMORE if there are no more
+ * interfaces, otherwise ISC_R_SUCCESS.
+ */
+static isc_result_t
+internal_next(isc_interfaceiter_t *iter) {
+
+	if (iter->pos != NULL)
+		iter->pos = iter->pos->ifa_next;
+	if (iter->pos == NULL) {
+#ifdef __linux
+		if (!seenv6)
+			return (linux_if_inet6_next(iter));
+#endif
+		return (ISC_R_NOMORE);
+	}
+
+	return (ISC_R_SUCCESS);
+}
+
+static void
+internal_destroy(isc_interfaceiter_t *iter) {
+
+#ifdef __linux
+	if (iter->proc != NULL)
+		fclose(iter->proc);
+	iter->proc = NULL;
+#endif
+	if (iter->ifaddrs)
+		freeifaddrs(iter->ifaddrs);
+	iter->ifaddrs = NULL;
+}
+
+static
+void internal_first(isc_interfaceiter_t *iter) {
+
+#ifdef __linux
+	linux_if_inet6_first(iter);
+#endif
+	iter->pos = iter->ifaddrs;
+}
diff --git a/src/lib/bind9/unix/ifiter_ioctl.c b/src/lib/bind9/unix/ifiter_ioctl.c
new file mode 100644
index 0000000..010b365
--- /dev/null
+++ b/src/lib/bind9/unix/ifiter_ioctl.c
@@ -0,0 +1,931 @@
+/*
+ * Copyright (C) 2004-2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: ifiter_ioctl.c,v 1.62 2009-01-18 23:48:14 tbox Exp $ */
+
+/*! \file
+ * \brief
+ * Obtain the list of network interfaces using the SIOCGLIFCONF ioctl.
+ * See netintro(4).
+ */
+
+#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
+#ifdef ISC_PLATFORM_HAVEIF_LADDRCONF
+#define lifc_len iflc_len
+#define lifc_buf iflc_buf
+#define lifc_req iflc_req
+#define LIFCONF if_laddrconf
+#else
+#define ISC_HAVE_LIFC_FAMILY 1
+#define ISC_HAVE_LIFC_FLAGS 1
+#define LIFCONF lifconf
+#endif
+
+#ifdef ISC_PLATFORM_HAVEIF_LADDRREQ
+#define lifr_addr iflr_addr
+#define lifr_name iflr_name
+#define lifr_dstaddr iflr_dstaddr
+#define lifr_flags iflr_flags
+#define ss_family sa_family
+#define LIFREQ if_laddrreq
+#else
+#define LIFREQ lifreq
+#endif
+#endif
+
+#define IFITER_MAGIC		ISC_MAGIC('I', 'F', 'I', 'T')
+#define VALID_IFITER(t)		ISC_MAGIC_VALID(t, IFITER_MAGIC)
+
+struct isc_interfaceiter {
+	unsigned int		magic;		/* Magic number. */
+	isc_mem_t		*mctx;
+	int			mode;
+	int			socket;
+	struct ifconf 		ifc;
+	void			*buf;		/* Buffer for sysctl data. */
+	unsigned int		bufsize;	/* Bytes allocated. */
+	unsigned int		pos;		/* Current offset in
+						   SIOCGIFCONF data */
+#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
+	int			socket6;
+	struct LIFCONF 		lifc;
+	void			*buf6;		/* Buffer for sysctl data. */
+	unsigned int		bufsize6;	/* Bytes allocated. */
+	unsigned int		pos6;		/* Current offset in
+						   SIOCGLIFCONF data */
+	isc_result_t		result6;	/* Last result code. */
+	isc_boolean_t		first6;
+#endif
+#ifdef HAVE_TRUCLUSTER
+	int			clua_context;	/* Cluster alias context */
+	isc_boolean_t		clua_done;
+	struct sockaddr		clua_sa;
+#endif
+#ifdef	__linux
+	FILE *			proc;
+	char			entry[ISC_IF_INET6_SZ];
+	isc_result_t		valid;
+#endif
+	isc_interface_t		current;	/* Current interface data. */
+	isc_result_t		result;		/* Last result code. */
+};
+
+#ifdef HAVE_TRUCLUSTER
+#include <clua/clua.h>
+#include <sys/socket.h>
+#endif
+
+
+/*%
+ * Size of buffer for SIOCGLIFCONF, in bytes.  We assume no sane system
+ * will have more than a megabyte of interface configuration data.
+ */
+#define IFCONF_BUFSIZE_INITIAL	4096
+#define IFCONF_BUFSIZE_MAX	1048576
+
+#ifdef __linux
+#ifndef IF_NAMESIZE
+# ifdef IFNAMSIZ
+#  define IF_NAMESIZE  IFNAMSIZ
+# else
+#  define IF_NAMESIZE 16
+# endif
+#endif
+#endif
+
+static isc_result_t
+getbuf4(isc_interfaceiter_t *iter) {
+	char strbuf[ISC_STRERRORSIZE];
+
+	iter->bufsize = IFCONF_BUFSIZE_INITIAL;
+
+	for (;;) {
+		iter->buf = isc_mem_get(iter->mctx, iter->bufsize);
+		if (iter->buf == NULL)
+			return (ISC_R_NOMEMORY);
+
+		memset(&iter->ifc.ifc_len, 0, sizeof(iter->ifc.ifc_len));
+		iter->ifc.ifc_len = iter->bufsize;
+		iter->ifc.ifc_buf = iter->buf;
+		/*
+		 * Ignore the HP/UX warning about "integer overflow during
+		 * conversion".  It comes from its own macro definition,
+		 * and is really hard to shut up.
+		 */
+		if (ioctl(iter->socket, SIOCGIFCONF, (char *)&iter->ifc)
+		    == -1) {
+			if (errno != EINVAL) {
+				isc__strerror(errno, strbuf, sizeof(strbuf));
+				UNEXPECTED_ERROR(__FILE__, __LINE__,
+						 isc_msgcat_get(isc_msgcat,
+							ISC_MSGSET_IFITERIOCTL,
+							ISC_MSG_GETIFCONFIG,
+							"get interface "
+							"configuration: %s"),
+						 strbuf);
+				goto unexpected;
+			}
+			/*
+			 * EINVAL.  Retry with a bigger buffer.
+			 */
+		} else {
+			/*
+			 * The ioctl succeeded.
+			 * Some OS's just return what will fit rather
+			 * than set EINVAL if the buffer is too small
+			 * to fit all the interfaces in.  If
+			 * ifc.lifc_len is too near to the end of the
+			 * buffer we will grow it just in case and
+			 * retry.
+			 */
+			if (iter->ifc.ifc_len + 2 * sizeof(struct ifreq)
+			    < iter->bufsize)
+				break;
+		}
+		if (iter->bufsize >= IFCONF_BUFSIZE_MAX) {
+			UNEXPECTED_ERROR(__FILE__, __LINE__,
+					 isc_msgcat_get(isc_msgcat,
+							ISC_MSGSET_IFITERIOCTL,
+							ISC_MSG_BUFFERMAX,
+							"get interface "
+							"configuration: "
+							"maximum buffer "
+							"size exceeded"));
+			goto unexpected;
+		}
+		isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
+
+		iter->bufsize *= 2;
+	}
+	return (ISC_R_SUCCESS);
+
+ unexpected:
+	isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
+	iter->buf = NULL;
+	return (ISC_R_UNEXPECTED);
+}
+
+#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
+static isc_result_t
+getbuf6(isc_interfaceiter_t *iter) {
+	char strbuf[ISC_STRERRORSIZE];
+	isc_result_t result;
+
+	iter->bufsize6 = IFCONF_BUFSIZE_INITIAL;
+
+	for (;;) {
+		iter->buf6 = isc_mem_get(iter->mctx, iter->bufsize6);
+		if (iter->buf6 == NULL)
+			return (ISC_R_NOMEMORY);
+
+		memset(&iter->lifc, 0, sizeof(iter->lifc));
+#ifdef ISC_HAVE_LIFC_FAMILY
+		iter->lifc.lifc_family = AF_INET6;
+#endif
+#ifdef ISC_HAVE_LIFC_FLAGS
+		iter->lifc.lifc_flags = 0;
+#endif
+		iter->lifc.lifc_len = iter->bufsize6;
+		iter->lifc.lifc_buf = iter->buf6;
+		/*
+		 * Ignore the HP/UX warning about "integer overflow during
+		 * conversion".  It comes from its own macro definition,
+		 * and is really hard to shut up.
+		 */
+		if (ioctl(iter->socket6, SIOCGLIFCONF, (char *)&iter->lifc)
+		    == -1) {
+#ifdef __hpux
+			/*
+			 * IPv6 interface scanning is not available on all
+			 * kernels w/ IPv6 sockets.
+			 */
+			if (errno == ENOENT) {
+				isc__strerror(errno, strbuf, sizeof(strbuf));
+				isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+					      ISC_LOGMODULE_INTERFACE,
+					      ISC_LOG_DEBUG(1),
+					      isc_msgcat_get(isc_msgcat,
+							ISC_MSGSET_IFITERIOCTL,
+							ISC_MSG_GETIFCONFIG,
+							"get interface "
+							"configuration: %s"),
+					       strbuf);
+				result = ISC_R_FAILURE;
+				goto cleanup;
+			}
+#endif
+			if (errno != EINVAL) {
+				isc__strerror(errno, strbuf, sizeof(strbuf));
+				UNEXPECTED_ERROR(__FILE__, __LINE__,
+						 isc_msgcat_get(isc_msgcat,
+							ISC_MSGSET_IFITERIOCTL,
+							ISC_MSG_GETIFCONFIG,
+							"get interface "
+							"configuration: %s"),
+						 strbuf);
+				result = ISC_R_UNEXPECTED;
+				goto cleanup;
+			}
+			/*
+			 * EINVAL.  Retry with a bigger buffer.
+			 */
+		} else {
+			/*
+			 * The ioctl succeeded.
+			 * Some OS's just return what will fit rather
+			 * than set EINVAL if the buffer is too small
+			 * to fit all the interfaces in.  If
+			 * ifc.ifc_len is too near to the end of the
+			 * buffer we will grow it just in case and
+			 * retry.
+			 */
+			if (iter->lifc.lifc_len + 2 * sizeof(struct LIFREQ)
+			    < iter->bufsize6)
+				break;
+		}
+		if (iter->bufsize6 >= IFCONF_BUFSIZE_MAX) {
+			UNEXPECTED_ERROR(__FILE__, __LINE__,
+					 isc_msgcat_get(isc_msgcat,
+							ISC_MSGSET_IFITERIOCTL,
+							ISC_MSG_BUFFERMAX,
+							"get interface "
+							"configuration: "
+							"maximum buffer "
+							"size exceeded"));
+			result = ISC_R_UNEXPECTED;
+			goto cleanup;
+		}
+		isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
+
+		iter->bufsize6 *= 2;
+	}
+
+	if (iter->lifc.lifc_len != 0)
+		iter->mode = 6;
+	return (ISC_R_SUCCESS);
+
+ cleanup:
+	isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
+	iter->buf6 = NULL;
+	return (result);
+}
+#endif
+
+isc_result_t
+isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) {
+	isc_interfaceiter_t *iter;
+	isc_result_t result;
+	char strbuf[ISC_STRERRORSIZE];
+
+	REQUIRE(mctx != NULL);
+	REQUIRE(iterp != NULL);
+	REQUIRE(*iterp == NULL);
+
+	iter = isc_mem_get(mctx, sizeof(*iter));
+	if (iter == NULL)
+		return (ISC_R_NOMEMORY);
+
+	iter->mctx = mctx;
+	iter->mode = 4;
+	iter->buf = NULL;
+	iter->pos = (unsigned int) -1;
+#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
+	iter->buf6 = NULL;
+	iter->pos6 = (unsigned int) -1;
+	iter->result6 = ISC_R_NOMORE;
+	iter->socket6 = -1;
+	iter->first6 = ISC_FALSE;
+#endif
+
+	/*
+	 * Get the interface configuration, allocating more memory if
+	 * necessary.
+	 */
+
+#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
+	result = isc_net_probeipv6();
+	if (result == ISC_R_SUCCESS) {
+		/*
+		 * Create an unbound datagram socket to do the SIOCGLIFCONF
+		 * ioctl on.  HP/UX requires an AF_INET6 socket for
+		 * SIOCGLIFCONF to get IPv6 addresses.
+		 */
+		if ((iter->socket6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+			isc__strerror(errno, strbuf, sizeof(strbuf));
+			UNEXPECTED_ERROR(__FILE__, __LINE__,
+					 isc_msgcat_get(isc_msgcat,
+							ISC_MSGSET_IFITERIOCTL,
+							ISC_MSG_MAKESCANSOCKET,
+							"making interface "
+							"scan socket: %s"),
+					 strbuf);
+			result = ISC_R_UNEXPECTED;
+			goto socket6_failure;
+		}
+		result = iter->result6 = getbuf6(iter);
+		if (result != ISC_R_NOTIMPLEMENTED && result != ISC_R_SUCCESS)
+			goto ioctl6_failure;
+	}
+#endif
+	if ((iter->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+		isc__strerror(errno, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 isc_msgcat_get(isc_msgcat,
+						ISC_MSGSET_IFITERIOCTL,
+						ISC_MSG_MAKESCANSOCKET,
+						"making interface "
+						"scan socket: %s"),
+				 strbuf);
+		result = ISC_R_UNEXPECTED;
+		goto socket_failure;
+	}
+	result = getbuf4(iter);
+	if (result != ISC_R_SUCCESS)
+		goto ioctl_failure;
+
+	/*
+	 * A newly created iterator has an undefined position
+	 * until isc_interfaceiter_first() is called.
+	 */
+#ifdef HAVE_TRUCLUSTER
+	iter->clua_context = -1;
+	iter->clua_done = ISC_TRUE;
+#endif
+#ifdef __linux
+	iter->proc = fopen("/proc/net/if_inet6", "r");
+	iter->valid = ISC_R_FAILURE;
+#endif
+	iter->result = ISC_R_FAILURE;
+
+	iter->magic = IFITER_MAGIC;
+	*iterp = iter;
+	return (ISC_R_SUCCESS);
+
+ ioctl_failure:
+	if (iter->buf != NULL)
+		isc_mem_put(mctx, iter->buf, iter->bufsize);
+	(void) close(iter->socket);
+
+ socket_failure:
+#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
+	if (iter->buf6 != NULL)
+		isc_mem_put(mctx, iter->buf6, iter->bufsize6);
+  ioctl6_failure:
+	if (iter->socket6 != -1)
+		(void) close(iter->socket6);
+  socket6_failure:
+#endif
+
+	isc_mem_put(mctx, iter, sizeof(*iter));
+	return (result);
+}
+
+#ifdef HAVE_TRUCLUSTER
+static void
+get_inaddr(isc_netaddr_t *dst, struct in_addr *src) {
+	dst->family = AF_INET;
+	memcpy(&dst->type.in, src, sizeof(struct in_addr));
+}
+
+static isc_result_t
+internal_current_clusteralias(isc_interfaceiter_t *iter) {
+	struct clua_info ci;
+	if (clua_getaliasinfo(&iter->clua_sa, &ci) != CLUA_SUCCESS)
+		return (ISC_R_IGNORE);
+	memset(&iter->current, 0, sizeof(iter->current));
+	iter->current.af = iter->clua_sa.sa_family;
+	memset(iter->current.name, 0, sizeof(iter->current.name));
+	sprintf(iter->current.name, "clua%d", ci.aliasid);
+	iter->current.flags = INTERFACE_F_UP;
+	get_inaddr(&iter->current.address, &ci.addr);
+	get_inaddr(&iter->current.netmask, &ci.netmask);
+	return (ISC_R_SUCCESS);
+}
+#endif
+
+/*
+ * Get information about the current interface to iter->current.
+ * If successful, return ISC_R_SUCCESS.
+ * If the interface has an unsupported address family, or if
+ * some operation on it fails, return ISC_R_IGNORE to make
+ * the higher-level iterator code ignore it.
+ */
+
+static isc_result_t
+internal_current4(isc_interfaceiter_t *iter) {
+	struct ifreq *ifrp;
+	struct ifreq ifreq;
+	int family;
+	char strbuf[ISC_STRERRORSIZE];
+#if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR)
+	struct lifreq lifreq;
+#else
+	char sabuf[256];
+#endif
+	int i, bits, prefixlen;
+
+	REQUIRE(VALID_IFITER(iter));
+
+	if (iter->ifc.ifc_len == 0 ||
+	    iter->pos == (unsigned int)iter->ifc.ifc_len) {
+#ifdef __linux
+		return (linux_if_inet6_current(iter));
+#else
+		return (ISC_R_NOMORE);
+#endif
+	}
+
+	INSIST( iter->pos < (unsigned int) iter->ifc.ifc_len);
+
+	ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos);
+
+	memset(&ifreq, 0, sizeof(ifreq));
+	memcpy(&ifreq, ifrp, sizeof(ifreq));
+
+	family = ifreq.ifr_addr.sa_family;
+#if defined(ISC_PLATFORM_HAVEIPV6)
+	if (family != AF_INET && family != AF_INET6)
+#else
+	if (family != AF_INET)
+#endif
+		return (ISC_R_IGNORE);
+
+	memset(&iter->current, 0, sizeof(iter->current));
+	iter->current.af = family;
+
+	INSIST(sizeof(ifreq.ifr_name) <= sizeof(iter->current.name));
+	memset(iter->current.name, 0, sizeof(iter->current.name));
+	memcpy(iter->current.name, ifreq.ifr_name, sizeof(ifreq.ifr_name));
+
+	get_addr(family, &iter->current.address,
+		 (struct sockaddr *)&ifrp->ifr_addr, ifreq.ifr_name);
+
+	/*
+	 * If the interface does not have a address ignore it.
+	 */
+	switch (family) {
+	case AF_INET:
+		if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY))
+			return (ISC_R_IGNORE);
+		break;
+	case AF_INET6:
+		if (memcmp(&iter->current.address.type.in6, &in6addr_any,
+			   sizeof(in6addr_any)) == 0)
+			return (ISC_R_IGNORE);
+		break;
+	}
+
+	/*
+	 * Get interface flags.
+	 */
+
+	iter->current.flags = 0;
+
+	/*
+	 * Ignore the HP/UX warning about "integer overflow during
+	 * conversion.  It comes from its own macro definition,
+	 * and is really hard to shut up.
+	 */
+	if (ioctl(iter->socket, SIOCGIFFLAGS, (char *) &ifreq) < 0) {
+		isc__strerror(errno, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "%s: getting interface flags: %s",
+				 ifreq.ifr_name, strbuf);
+		return (ISC_R_IGNORE);
+	}
+
+	if ((ifreq.ifr_flags & IFF_UP) != 0)
+		iter->current.flags |= INTERFACE_F_UP;
+
+#ifdef IFF_POINTOPOINT
+	if ((ifreq.ifr_flags & IFF_POINTOPOINT) != 0)
+		iter->current.flags |= INTERFACE_F_POINTTOPOINT;
+#endif
+
+	if ((ifreq.ifr_flags & IFF_LOOPBACK) != 0)
+		iter->current.flags |= INTERFACE_F_LOOPBACK;
+
+	if (family == AF_INET)
+		goto inet;
+
+#if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR)
+	memset(&lifreq, 0, sizeof(lifreq));
+	memcpy(lifreq.lifr_name, iter->current.name, sizeof(lifreq.lifr_name));
+	memcpy(&lifreq.lifr_addr, &iter->current.address.type.in6,
+	       sizeof(iter->current.address.type.in6));
+
+	if (ioctl(iter->socket, SIOCGLIFADDR, &lifreq) < 0) {
+		isc__strerror(errno, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "%s: getting interface address: %s",
+				 ifreq.ifr_name, strbuf);
+		return (ISC_R_IGNORE);
+	}
+	prefixlen = lifreq.lifr_addrlen;
+#else
+	isc_netaddr_format(&iter->current.address, sabuf, sizeof(sabuf));
+	isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+		      ISC_LOGMODULE_INTERFACE,
+		      ISC_LOG_INFO,
+		      isc_msgcat_get(isc_msgcat,
+				     ISC_MSGSET_IFITERIOCTL,
+				     ISC_MSG_GETIFCONFIG,
+				     "prefix length for %s is unknown "
+				     "(assume 128)"), sabuf);
+	prefixlen = 128;
+#endif
+
+	/*
+	 * Netmask already zeroed.
+	 */
+	iter->current.netmask.family = family;
+	for (i = 0; i < 16; i++) {
+		if (prefixlen > 8) {
+			bits = 0;
+			prefixlen -= 8;
+		} else {
+			bits = 8 - prefixlen;
+			prefixlen = 0;
+		}
+		iter->current.netmask.type.in6.s6_addr[i] = (~0 << bits) & 0xff;
+	}
+	return (ISC_R_SUCCESS);
+
+ inet:
+	if (family != AF_INET)
+		return (ISC_R_IGNORE);
+#ifdef IFF_POINTOPOINT
+	/*
+	 * If the interface is point-to-point, get the destination address.
+	 */
+	if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) {
+		/*
+		 * Ignore the HP/UX warning about "integer overflow during
+		 * conversion.  It comes from its own macro definition,
+		 * and is really hard to shut up.
+		 */
+		if (ioctl(iter->socket, SIOCGIFDSTADDR, (char *)&ifreq)
+		    < 0) {
+			isc__strerror(errno, strbuf, sizeof(strbuf));
+			UNEXPECTED_ERROR(__FILE__, __LINE__,
+				isc_msgcat_get(isc_msgcat,
+					       ISC_MSGSET_IFITERIOCTL,
+					       ISC_MSG_GETDESTADDR,
+					       "%s: getting "
+					       "destination address: %s"),
+					 ifreq.ifr_name, strbuf);
+			return (ISC_R_IGNORE);
+		}
+		get_addr(family, &iter->current.dstaddress,
+			 (struct sockaddr *)&ifreq.ifr_dstaddr, ifreq.ifr_name);
+	}
+#endif
+
+	/*
+	 * Get the network mask.
+	 */
+	memset(&ifreq, 0, sizeof(ifreq));
+	memcpy(&ifreq, ifrp, sizeof(ifreq));
+	/*
+	 * Ignore the HP/UX warning about "integer overflow during
+	 * conversion.  It comes from its own macro definition,
+	 * and is really hard to shut up.
+	 */
+	if (ioctl(iter->socket, SIOCGIFNETMASK, (char *)&ifreq) < 0) {
+		isc__strerror(errno, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+			isc_msgcat_get(isc_msgcat,
+				       ISC_MSGSET_IFITERIOCTL,
+				       ISC_MSG_GETNETMASK,
+				       "%s: getting netmask: %s"),
+				       ifreq.ifr_name, strbuf);
+		return (ISC_R_IGNORE);
+	}
+	get_addr(family, &iter->current.netmask,
+		 (struct sockaddr *)&ifreq.ifr_addr, ifreq.ifr_name);
+	return (ISC_R_SUCCESS);
+}
+
+#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
+static isc_result_t
+internal_current6(isc_interfaceiter_t *iter) {
+	struct LIFREQ *ifrp;
+	struct LIFREQ lifreq;
+	int family;
+	char strbuf[ISC_STRERRORSIZE];
+	int fd;
+
+	REQUIRE(VALID_IFITER(iter));
+	if (iter->result6 != ISC_R_SUCCESS)
+		return (iter->result6);
+	REQUIRE(iter->pos6 < (unsigned int) iter->lifc.lifc_len);
+
+	ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos6);
+
+	memset(&lifreq, 0, sizeof(lifreq));
+	memcpy(&lifreq, ifrp, sizeof(lifreq));
+
+	family = lifreq.lifr_addr.ss_family;
+#ifdef ISC_PLATFORM_HAVEIPV6
+	if (family != AF_INET && family != AF_INET6)
+#else
+	if (family != AF_INET)
+#endif
+		return (ISC_R_IGNORE);
+
+	memset(&iter->current, 0, sizeof(iter->current));
+	iter->current.af = family;
+
+	INSIST(sizeof(lifreq.lifr_name) <= sizeof(iter->current.name));
+	memset(iter->current.name, 0, sizeof(iter->current.name));
+	memcpy(iter->current.name, lifreq.lifr_name, sizeof(lifreq.lifr_name));
+
+	get_addr(family, &iter->current.address,
+		 (struct sockaddr *)&lifreq.lifr_addr, lifreq.lifr_name);
+
+	/*
+	 * If the interface does not have a address ignore it.
+	 */
+	switch (family) {
+	case AF_INET:
+		if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY))
+			return (ISC_R_IGNORE);
+		break;
+	case AF_INET6:
+		if (memcmp(&iter->current.address.type.in6, &in6addr_any,
+			   sizeof(in6addr_any)) == 0)
+			return (ISC_R_IGNORE);
+		break;
+	}
+
+	/*
+	 * Get interface flags.
+	 */
+
+	iter->current.flags = 0;
+
+	if (family == AF_INET6)
+		fd = iter->socket6;
+	else
+		fd = iter->socket;
+
+	/*
+	 * Ignore the HP/UX warning about "integer overflow during
+	 * conversion.  It comes from its own macro definition,
+	 * and is really hard to shut up.
+	 */
+	if (ioctl(fd, SIOCGLIFFLAGS, (char *) &lifreq) < 0) {
+		isc__strerror(errno, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "%s: getting interface flags: %s",
+				 lifreq.lifr_name, strbuf);
+		return (ISC_R_IGNORE);
+	}
+
+	if ((lifreq.lifr_flags & IFF_UP) != 0)
+		iter->current.flags |= INTERFACE_F_UP;
+
+#ifdef IFF_POINTOPOINT
+	if ((lifreq.lifr_flags & IFF_POINTOPOINT) != 0)
+		iter->current.flags |= INTERFACE_F_POINTTOPOINT;
+#endif
+
+	if ((lifreq.lifr_flags & IFF_LOOPBACK) != 0)
+		iter->current.flags |= INTERFACE_F_LOOPBACK;
+
+#ifdef IFF_POINTOPOINT
+	/*
+	 * If the interface is point-to-point, get the destination address.
+	 */
+	if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) {
+		/*
+		 * Ignore the HP/UX warning about "integer overflow during
+		 * conversion.  It comes from its own macro definition,
+		 * and is really hard to shut up.
+		 */
+		if (ioctl(fd, SIOCGLIFDSTADDR, (char *)&lifreq)
+		    < 0) {
+			isc__strerror(errno, strbuf, sizeof(strbuf));
+			UNEXPECTED_ERROR(__FILE__, __LINE__,
+				isc_msgcat_get(isc_msgcat,
+					       ISC_MSGSET_IFITERIOCTL,
+					       ISC_MSG_GETDESTADDR,
+					       "%s: getting "
+					       "destination address: %s"),
+					 lifreq.lifr_name, strbuf);
+			return (ISC_R_IGNORE);
+		}
+		get_addr(family, &iter->current.dstaddress,
+			 (struct sockaddr *)&lifreq.lifr_dstaddr,
+			 lifreq.lifr_name);
+	}
+#endif
+
+	/*
+	 * Get the network mask.  Netmask already zeroed.
+	 */
+	memset(&lifreq, 0, sizeof(lifreq));
+	memcpy(&lifreq, ifrp, sizeof(lifreq));
+
+#ifdef lifr_addrlen
+	/*
+	 * Special case: if the system provides lifr_addrlen member, the
+	 * netmask of an IPv6 address can be derived from the length, since
+	 * an IPv6 address always has a contiguous mask.
+	 */
+	if (family == AF_INET6) {
+		int i, bits;
+
+		iter->current.netmask.family = family;
+		for (i = 0; i < lifreq.lifr_addrlen; i += 8) {
+			bits = lifreq.lifr_addrlen - i;
+			bits = (bits < 8) ? (8 - bits) : 0;
+			iter->current.netmask.type.in6.s6_addr[i / 8] =
+				(~0 << bits) & 0xff;
+		}
+
+		return (ISC_R_SUCCESS);
+	}
+#endif
+
+	/*
+	 * Ignore the HP/UX warning about "integer overflow during
+	 * conversion.  It comes from its own macro definition,
+	 * and is really hard to shut up.
+	 */
+	if (ioctl(fd, SIOCGLIFNETMASK, (char *)&lifreq) < 0) {
+		isc__strerror(errno, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 isc_msgcat_get(isc_msgcat,
+						ISC_MSGSET_IFITERIOCTL,
+						ISC_MSG_GETNETMASK,
+						"%s: getting netmask: %s"),
+				 lifreq.lifr_name, strbuf);
+		return (ISC_R_IGNORE);
+	}
+	get_addr(family, &iter->current.netmask,
+		 (struct sockaddr *)&lifreq.lifr_addr, lifreq.lifr_name);
+
+	return (ISC_R_SUCCESS);
+}
+#endif
+
+static isc_result_t
+internal_current(isc_interfaceiter_t *iter) {
+#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
+	if (iter->mode == 6) {
+		iter->result6 = internal_current6(iter);
+		if (iter->result6 != ISC_R_NOMORE)
+			return (iter->result6);
+	}
+#endif
+#ifdef HAVE_TRUCLUSTER
+	if (!iter->clua_done)
+		return(internal_current_clusteralias(iter));
+#endif
+	return (internal_current4(iter));
+}
+
+/*
+ * Step the iterator to the next interface.  Unlike
+ * isc_interfaceiter_next(), this may leave the iterator
+ * positioned on an interface that will ultimately
+ * be ignored.  Return ISC_R_NOMORE if there are no more
+ * interfaces, otherwise ISC_R_SUCCESS.
+ */
+static isc_result_t
+internal_next4(isc_interfaceiter_t *iter) {
+#ifdef ISC_PLATFORM_HAVESALEN
+	struct ifreq *ifrp;
+#endif
+
+	if (iter->pos < (unsigned int) iter->ifc.ifc_len) {
+#ifdef ISC_PLATFORM_HAVESALEN
+		ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos);
+
+		if (ifrp->ifr_addr.sa_len > sizeof(struct sockaddr))
+			iter->pos += sizeof(ifrp->ifr_name) +
+				     ifrp->ifr_addr.sa_len;
+		else
+#endif
+			iter->pos += sizeof(struct ifreq);
+
+	} else {
+		INSIST(iter->pos == (unsigned int) iter->ifc.ifc_len);
+#ifdef __linux
+		return (linux_if_inet6_next(iter));
+#else
+		return (ISC_R_NOMORE);
+#endif
+	}
+	return (ISC_R_SUCCESS);
+}
+
+#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
+static isc_result_t
+internal_next6(isc_interfaceiter_t *iter) {
+#ifdef ISC_PLATFORM_HAVESALEN
+	struct LIFREQ *ifrp;
+#endif
+
+	if (iter->result6 != ISC_R_SUCCESS && iter->result6 != ISC_R_IGNORE)
+		return (iter->result6);
+
+	REQUIRE(iter->pos6 < (unsigned int) iter->lifc.lifc_len);
+
+#ifdef ISC_PLATFORM_HAVESALEN
+	ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos6);
+
+	if (ifrp->lifr_addr.sa_len > sizeof(struct sockaddr))
+		iter->pos6 += sizeof(ifrp->lifr_name) + ifrp->lifr_addr.sa_len;
+	else
+#endif
+		iter->pos6 += sizeof(struct LIFREQ);
+
+	if (iter->pos6 >= (unsigned int) iter->lifc.lifc_len)
+		return (ISC_R_NOMORE);
+
+	return (ISC_R_SUCCESS);
+}
+#endif
+
+static isc_result_t
+internal_next(isc_interfaceiter_t *iter) {
+#ifdef HAVE_TRUCLUSTER
+	int clua_result;
+#endif
+#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
+	if (iter->mode == 6) {
+		iter->result6 = internal_next6(iter);
+		if (iter->result6 != ISC_R_NOMORE)
+			return (iter->result6);
+		if (iter->first6) {
+			iter->first6 = ISC_FALSE;
+			return (ISC_R_SUCCESS);
+		}
+	}
+#endif
+#ifdef HAVE_TRUCLUSTER
+	if (!iter->clua_done) {
+		clua_result = clua_getaliasaddress(&iter->clua_sa,
+						   &iter->clua_context);
+		if (clua_result != CLUA_SUCCESS)
+			iter->clua_done = ISC_TRUE;
+		return (ISC_R_SUCCESS);
+	}
+#endif
+	return (internal_next4(iter));
+}
+
+static void
+internal_destroy(isc_interfaceiter_t *iter) {
+	(void) close(iter->socket);
+#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
+	if (iter->socket6 != -1)
+		(void) close(iter->socket6);
+	if (iter->buf6 != NULL) {
+		isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
+	}
+#endif
+#ifdef __linux
+	if (iter->proc != NULL)
+		fclose(iter->proc);
+#endif
+}
+
+static
+void internal_first(isc_interfaceiter_t *iter) {
+#ifdef HAVE_TRUCLUSTER
+	int clua_result;
+#endif
+	iter->pos = 0;
+#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
+	iter->pos6 = 0;
+	if (iter->result6 == ISC_R_NOMORE)
+		iter->result6 = ISC_R_SUCCESS;
+	iter->first6 = ISC_TRUE;
+#endif
+#ifdef HAVE_TRUCLUSTER
+	iter->clua_context = 0;
+	clua_result = clua_getaliasaddress(&iter->clua_sa,
+					   &iter->clua_context);
+	iter->clua_done = ISC_TF(clua_result != CLUA_SUCCESS);
+#endif
+#ifdef __linux
+	linux_if_inet6_first(iter);
+#endif
+}
diff --git a/src/lib/bind9/unix/ifiter_sysctl.c b/src/lib/bind9/unix/ifiter_sysctl.c
new file mode 100644
index 0000000..bb30b6a
--- /dev/null
+++ b/src/lib/bind9/unix/ifiter_sysctl.c
@@ -0,0 +1,302 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: ifiter_sysctl.c,v 1.25 2007-06-19 23:47:18 tbox Exp $ */
+
+/*! \file
+ * \brief
+ * Obtain the list of network interfaces using sysctl.
+ * See TCP/IP Illustrated Volume 2, sections 19.8, 19.14,
+ * and 19.16.
+ */
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+
+#include <net/route.h>
+#include <net/if_dl.h>
+
+/* XXX what about Alpha? */
+#ifdef sgi
+#define ROUNDUP(a) ((a) > 0 ? \
+		(1 + (((a) - 1) | (sizeof(__uint64_t) - 1))) : \
+		sizeof(__uint64_t))
+#else
+#define ROUNDUP(a) ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) \
+                    : sizeof(long))
+#endif
+
+#define IFITER_MAGIC		ISC_MAGIC('I', 'F', 'I', 'S')
+#define VALID_IFITER(t)		ISC_MAGIC_VALID(t, IFITER_MAGIC)
+
+struct isc_interfaceiter {
+	unsigned int		magic;		/* Magic number. */
+	isc_mem_t		*mctx;
+	void			*buf;		/* Buffer for sysctl data. */
+	unsigned int		bufsize;	/* Bytes allocated. */
+	unsigned int		bufused;	/* Bytes used. */
+	unsigned int		pos;		/* Current offset in
+						   sysctl data. */
+	isc_interface_t		current;	/* Current interface data. */
+	isc_result_t		result;		/* Last result code. */
+};
+
+static int mib[6] = {
+	CTL_NET,
+	PF_ROUTE,
+        0,
+	0, 			/* Any address family. */
+        NET_RT_IFLIST,
+	0 			/* Flags. */
+};
+
+isc_result_t
+isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) {
+	isc_interfaceiter_t *iter;
+	isc_result_t result;
+	size_t bufsize;
+	size_t bufused;
+	char strbuf[ISC_STRERRORSIZE];
+
+	REQUIRE(mctx != NULL);
+	REQUIRE(iterp != NULL);
+	REQUIRE(*iterp == NULL);
+
+	iter = isc_mem_get(mctx, sizeof(*iter));
+	if (iter == NULL)
+		return (ISC_R_NOMEMORY);
+
+	iter->mctx = mctx;
+	iter->buf = 0;
+
+	/*
+	 * Determine the amount of memory needed.
+	 */
+	bufsize = 0;
+	if (sysctl(mib, 6, NULL, &bufsize, NULL, (size_t) 0) < 0) {
+		isc__strerror(errno, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 isc_msgcat_get(isc_msgcat,
+						ISC_MSGSET_IFITERSYSCTL,
+						ISC_MSG_GETIFLISTSIZE,
+						"getting interface "
+						"list size: sysctl: %s"),
+				 strbuf);
+		result = ISC_R_UNEXPECTED;
+		goto failure;
+	}
+	iter->bufsize = bufsize;
+
+	iter->buf = isc_mem_get(iter->mctx, iter->bufsize);
+	if (iter->buf == NULL) {
+		result = ISC_R_NOMEMORY;
+		goto failure;
+	}
+
+	bufused = bufsize;
+	if (sysctl(mib, 6, iter->buf, &bufused, NULL, (size_t) 0) < 0) {
+		isc__strerror(errno, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 isc_msgcat_get(isc_msgcat,
+						ISC_MSGSET_IFITERSYSCTL,
+						ISC_MSG_GETIFLIST,
+						"getting interface list: "
+						"sysctl: %s"),
+				 strbuf);
+		result = ISC_R_UNEXPECTED;
+		goto failure;
+	}
+	iter->bufused = bufused;
+	INSIST(iter->bufused <= iter->bufsize);
+
+	/*
+	 * A newly created iterator has an undefined position
+	 * until isc_interfaceiter_first() is called.
+	 */
+	iter->pos = (unsigned int) -1;
+	iter->result = ISC_R_FAILURE;
+
+	iter->magic = IFITER_MAGIC;
+	*iterp = iter;
+	return (ISC_R_SUCCESS);
+
+ failure:
+	if (iter->buf != NULL)
+		isc_mem_put(mctx, iter->buf, iter->bufsize);
+	isc_mem_put(mctx, iter, sizeof(*iter));
+	return (result);
+}
+
+/*
+ * Get information about the current interface to iter->current.
+ * If successful, return ISC_R_SUCCESS.
+ * If the interface has an unsupported address family,
+ * return ISC_R_IGNORE.  In case of other failure,
+ * return ISC_R_UNEXPECTED.
+ */
+
+static isc_result_t
+internal_current(isc_interfaceiter_t *iter) {
+	struct ifa_msghdr *ifam, *ifam_end;
+
+	REQUIRE(VALID_IFITER(iter));
+	REQUIRE (iter->pos < (unsigned int) iter->bufused);
+
+	ifam = (struct ifa_msghdr *) ((char *) iter->buf + iter->pos);
+	ifam_end = (struct ifa_msghdr *) ((char *) iter->buf + iter->bufused);
+
+	if (ifam->ifam_type == RTM_IFINFO) {
+		struct if_msghdr *ifm = (struct if_msghdr *) ifam;
+		struct sockaddr_dl *sdl = (struct sockaddr_dl *) (ifm + 1);
+		unsigned int namelen;
+
+		memset(&iter->current, 0, sizeof(iter->current));
+
+		namelen = sdl->sdl_nlen;
+		if (namelen > sizeof(iter->current.name) - 1)
+			namelen = sizeof(iter->current.name) - 1;
+
+		memset(iter->current.name, 0, sizeof(iter->current.name));
+		memcpy(iter->current.name, sdl->sdl_data, namelen);
+
+		iter->current.flags = 0;
+
+		if ((ifam->ifam_flags & IFF_UP) != 0)
+			iter->current.flags |= INTERFACE_F_UP;
+
+		if ((ifam->ifam_flags & IFF_POINTOPOINT) != 0)
+			iter->current.flags |= INTERFACE_F_POINTTOPOINT;
+
+		if ((ifam->ifam_flags & IFF_LOOPBACK) != 0)
+			iter->current.flags |= INTERFACE_F_LOOPBACK;
+
+		/*
+		 * This is not an interface address.
+		 * Force another iteration.
+		 */
+		return (ISC_R_IGNORE);
+	} else if (ifam->ifam_type == RTM_NEWADDR) {
+		int i;
+		int family;
+		struct sockaddr *mask_sa = NULL;
+		struct sockaddr *addr_sa = NULL;
+		struct sockaddr *dst_sa = NULL;
+
+		struct sockaddr *sa = (struct sockaddr *)(ifam + 1);
+		family = sa->sa_family;
+
+		for (i = 0; i < RTAX_MAX; i++)
+		{
+			if ((ifam->ifam_addrs & (1 << i)) == 0)
+				continue;
+
+			INSIST(sa < (struct sockaddr *) ifam_end);
+
+			switch (i) {
+			case RTAX_NETMASK: /* Netmask */
+				mask_sa = sa;
+				break;
+			case RTAX_IFA: /* Interface address */
+				addr_sa = sa;
+				break;
+			case RTAX_BRD: /* Broadcast or destination address */
+				dst_sa = sa;
+				break;
+			}
+#ifdef ISC_PLATFORM_HAVESALEN
+			sa = (struct sockaddr *)((char*)(sa)
+					 + ROUNDUP(sa->sa_len));
+#else
+#ifdef sgi
+			/*
+			 * Do as the contributed SGI code does.
+			 */
+			sa = (struct sockaddr *)((char*)(sa)
+					 + ROUNDUP(_FAKE_SA_LEN_DST(sa)));
+#else
+			/* XXX untested. */
+			sa = (struct sockaddr *)((char*)(sa)
+					 + ROUNDUP(sizeof(struct sockaddr)));
+#endif
+#endif
+		}
+
+		if (addr_sa == NULL)
+			return (ISC_R_IGNORE);
+
+		family = addr_sa->sa_family;
+		if (family != AF_INET && family != AF_INET6)
+			return (ISC_R_IGNORE);
+
+		iter->current.af = family;
+
+		get_addr(family, &iter->current.address, addr_sa,
+			 iter->current.name);
+
+		if (mask_sa != NULL)
+			get_addr(family, &iter->current.netmask, mask_sa,
+				 iter->current.name);
+
+		if (dst_sa != NULL &&
+		    (iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0)
+			get_addr(family, &iter->current.dstaddress, dst_sa,
+				 iter->current.name);
+
+		return (ISC_R_SUCCESS);
+	} else {
+		printf(isc_msgcat_get(isc_msgcat, ISC_MSGSET_IFITERSYSCTL,
+				      ISC_MSG_UNEXPECTEDTYPE,
+				      "warning: unexpected interface list "
+				      "message type\n"));
+		return (ISC_R_IGNORE);
+	}
+}
+
+/*
+ * Step the iterator to the next interface.  Unlike
+ * isc_interfaceiter_next(), this may leave the iterator
+ * positioned on an interface that will ultimately
+ * be ignored.  Return ISC_R_NOMORE if there are no more
+ * interfaces, otherwise ISC_R_SUCCESS.
+ */
+static isc_result_t
+internal_next(isc_interfaceiter_t *iter) {
+	struct ifa_msghdr *ifam;
+	REQUIRE (iter->pos < (unsigned int) iter->bufused);
+
+	ifam = (struct ifa_msghdr *) ((char *) iter->buf + iter->pos);
+
+	iter->pos += ifam->ifam_msglen;
+
+	if (iter->pos >= iter->bufused)
+		return (ISC_R_NOMORE);
+
+	return (ISC_R_SUCCESS);
+}
+
+static void
+internal_destroy(isc_interfaceiter_t *iter) {
+	UNUSED(iter); /* Unused. */
+	/*
+	 * Do nothing.
+	 */
+}
+
+static
+void internal_first(isc_interfaceiter_t *iter) {
+	iter->pos = 0;
+}
diff --git a/src/lib/bind9/unix/include/isc/dir.h b/src/lib/bind9/unix/include/isc/dir.h
new file mode 100644
index 0000000..a6e4440
--- /dev/null
+++ b/src/lib/bind9/unix/include/isc/dir.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: dir.h,v 1.21 2007-06-19 23:47:19 tbox Exp $ */
+
+/* Principal Authors: DCL */
+
+#ifndef ISC_DIR_H
+#define ISC_DIR_H 1
+
+/*! \file */
+
+#include <sys/types.h>		/* Required on some systems. */
+#include <dirent.h>
+
+#include <isc/lang.h>
+#include <isc/result.h>
+
+#define ISC_DIR_NAMEMAX 256
+#define ISC_DIR_PATHMAX 1024
+
+/*% Directory Entry */
+typedef struct isc_direntry {
+	/*!
+	 * Ideally, this should be NAME_MAX, but AIX does not define it by
+	 * default and dynamically allocating the space based on pathconf()
+	 * complicates things undesirably, as does adding special conditionals
+	 * just for AIX.  So a comfortably sized buffer is chosen instead.
+	 */
+	char 		name[ISC_DIR_NAMEMAX];
+	unsigned int	length;
+} isc_direntry_t;
+
+/*% Directory */
+typedef struct isc_dir {
+	unsigned int	magic;
+	/*!
+	 * As with isc_direntry_t->name, making this "right" for all systems
+	 * is slightly problematic because AIX does not define PATH_MAX.
+	 */
+	char		dirname[ISC_DIR_PATHMAX];
+	isc_direntry_t	entry;
+	DIR *		handle;
+} isc_dir_t;
+
+ISC_LANG_BEGINDECLS
+
+void
+isc_dir_init(isc_dir_t *dir);
+
+isc_result_t
+isc_dir_open(isc_dir_t *dir, const char *dirname);
+
+isc_result_t
+isc_dir_read(isc_dir_t *dir);
+
+isc_result_t
+isc_dir_reset(isc_dir_t *dir);
+
+void
+isc_dir_close(isc_dir_t *dir);
+
+isc_result_t
+isc_dir_chdir(const char *dirname);
+
+isc_result_t
+isc_dir_chroot(const char *dirname);
+
+isc_result_t
+isc_dir_createunique(char *templet);
+/*!<
+ * Use a templet (such as from isc_file_mktemplate()) to create a uniquely
+ * named, empty directory.  The templet string is modified in place.
+ * If result == ISC_R_SUCCESS, it is the name of the directory that was
+ * created.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_DIR_H */
diff --git a/src/lib/bind9/unix/include/isc/int.h b/src/lib/bind9/unix/include/isc/int.h
new file mode 100644
index 0000000..177e68a
--- /dev/null
+++ b/src/lib/bind9/unix/include/isc/int.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: int.h,v 1.16 2007-06-19 23:47:19 tbox Exp $ */
+
+#ifndef ISC_INT_H
+#define ISC_INT_H 1
+
+/*! \file */
+
+typedef char				isc_int8_t;
+typedef unsigned char			isc_uint8_t;
+typedef short				isc_int16_t;
+typedef unsigned short			isc_uint16_t;
+typedef int				isc_int32_t;
+typedef unsigned int			isc_uint32_t;
+typedef long long			isc_int64_t;
+typedef unsigned long long		isc_uint64_t;
+
+#define ISC_INT8_MIN	-128
+#define ISC_INT8_MAX	127
+#define ISC_UINT8_MAX	255
+
+#define ISC_INT16_MIN	-32768
+#define ISC_INT16_MAX	32767
+#define ISC_UINT16_MAX	65535
+
+/*%
+ * Note that "int" is 32 bits on all currently supported Unix-like operating
+ * systems, but "long" can be either 32 bits or 64 bits, thus the 32 bit
+ * constants are not qualified with "L".
+ */
+#define ISC_INT32_MIN	-2147483648
+#define ISC_INT32_MAX	2147483647
+#define ISC_UINT32_MAX	4294967295U
+
+#define ISC_INT64_MIN	-9223372036854775808LL
+#define ISC_INT64_MAX	9223372036854775807LL
+#define ISC_UINT64_MAX	18446744073709551615ULL
+
+#endif /* ISC_INT_H */
diff --git a/src/lib/bind9/unix/include/isc/keyboard.h b/src/lib/bind9/unix/include/isc/keyboard.h
new file mode 100644
index 0000000..0f15b1a
--- /dev/null
+++ b/src/lib/bind9/unix/include/isc/keyboard.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: keyboard.h,v 1.11 2007-06-19 23:47:19 tbox Exp $ */
+
+#ifndef ISC_KEYBOARD_H
+#define ISC_KEYBOARD_H 1
+
+/*! \file */
+
+#include <termios.h>
+
+#include <isc/lang.h>
+#include <isc/result.h>
+
+ISC_LANG_BEGINDECLS
+
+typedef struct {
+	int fd;
+	struct termios saved_mode;
+	isc_result_t result;
+} isc_keyboard_t;
+
+isc_result_t
+isc_keyboard_open(isc_keyboard_t *keyboard);
+
+isc_result_t
+isc_keyboard_close(isc_keyboard_t *keyboard, unsigned int sleepseconds);
+
+isc_result_t
+isc_keyboard_getchar(isc_keyboard_t *keyboard, unsigned char *cp);
+
+isc_boolean_t
+isc_keyboard_canceled(isc_keyboard_t *keyboard);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_KEYBOARD_H */
diff --git a/src/lib/bind9/unix/include/isc/net.h b/src/lib/bind9/unix/include/isc/net.h
new file mode 100644
index 0000000..112f1d7
--- /dev/null
+++ b/src/lib/bind9/unix/include/isc/net.h
@@ -0,0 +1,364 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2008  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: net.h,v 1.50 2008-12-01 04:14:54 marka Exp $ */
+
+#ifndef ISC_NET_H
+#define ISC_NET_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file
+ * \brief
+ * Basic Networking Types
+ *
+ * This module is responsible for defining the following basic networking
+ * types:
+ *
+ *\li		struct in_addr
+ *\li		struct in6_addr
+ *\li		struct in6_pktinfo
+ *\li		struct sockaddr
+ *\li		struct sockaddr_in
+ *\li		struct sockaddr_in6
+ *\li		in_port_t
+ *
+ * It ensures that the AF_ and PF_ macros are defined.
+ *
+ * It declares ntoh[sl]() and hton[sl]().
+ *
+ * It declares inet_aton(), inet_ntop(), and inet_pton().
+ *
+ * It ensures that #INADDR_LOOPBACK, #INADDR_ANY, #IN6ADDR_ANY_INIT,
+ * in6addr_any, and in6addr_loopback are available.
+ *
+ * It ensures that IN_MULTICAST() is available to check for multicast
+ * addresses.
+ *
+ * MP:
+ *\li	No impact.
+ *
+ * Reliability:
+ *\li	No anticipated impact.
+ *
+ * Resources:
+ *\li	N/A.
+ *
+ * Security:
+ *\li	No anticipated impact.
+ *
+ * Standards:
+ *\li	BSD Socket API
+ *\li	RFC2553
+ */
+
+/***
+ *** Imports.
+ ***/
+#include <isc/platform.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>		/* Contractual promise. */
+
+#include <net/if.h>
+
+#include <netinet/in.h>		/* Contractual promise. */
+#include <arpa/inet.h>		/* Contractual promise. */
+#ifdef ISC_PLATFORM_NEEDNETINETIN6H
+#include <netinet/in6.h>	/* Required on UnixWare. */
+#endif
+#ifdef ISC_PLATFORM_NEEDNETINET6IN6H
+#include <netinet6/in6.h>	/* Required on BSD/OS for in6_pktinfo. */
+#endif
+
+#ifndef ISC_PLATFORM_HAVEIPV6
+#include <isc/ipv6.h>		/* Contractual promise. */
+#endif
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+#ifdef ISC_PLATFORM_HAVEINADDR6
+#define in6_addr in_addr6	/*%< Required for pre RFC2133 implementations. */
+#endif
+
+#ifdef ISC_PLATFORM_HAVEIPV6
+#ifndef IN6ADDR_ANY_INIT
+#ifdef s6_addr
+/*%
+ * Required for some pre RFC2133 implementations.
+ * IN6ADDR_ANY_INIT and IN6ADDR_LOOPBACK_INIT were added in
+ * draft-ietf-ipngwg-bsd-api-04.txt or draft-ietf-ipngwg-bsd-api-05.txt.
+ * If 's6_addr' is defined then assume that there is a union and three
+ * levels otherwise assume two levels required.
+ */
+#define IN6ADDR_ANY_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } }
+#else
+#define IN6ADDR_ANY_INIT { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } }
+#endif
+#endif
+
+#ifndef IN6ADDR_LOOPBACK_INIT
+#ifdef s6_addr
+/*% IPv6 address loopback init */
+#define IN6ADDR_LOOPBACK_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } } }
+#else
+#define IN6ADDR_LOOPBACK_INIT { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } }
+#endif
+#endif
+
+#ifndef IN6_IS_ADDR_V4MAPPED
+/*% Is IPv6 address V4 mapped? */
+#define IN6_IS_ADDR_V4MAPPED(x) \
+	 (memcmp((x)->s6_addr, in6addr_any.s6_addr, 10) == 0 && \
+	  (x)->s6_addr[10] == 0xff && (x)->s6_addr[11] == 0xff)
+#endif
+
+#ifndef IN6_IS_ADDR_V4COMPAT
+/*% Is IPv6 address V4 compatible? */
+#define IN6_IS_ADDR_V4COMPAT(x) \
+	 (memcmp((x)->s6_addr, in6addr_any.s6_addr, 12) == 0 && \
+	 ((x)->s6_addr[12] != 0 || (x)->s6_addr[13] != 0 || \
+	  (x)->s6_addr[14] != 0 || \
+	  ((x)->s6_addr[15] != 0 && (x)->s6_addr[15] != 1)))
+#endif
+
+#ifndef IN6_IS_ADDR_MULTICAST
+/*% Is IPv6 address multicast? */
+#define IN6_IS_ADDR_MULTICAST(a)        ((a)->s6_addr[0] == 0xff)
+#endif
+
+#ifndef IN6_IS_ADDR_LINKLOCAL
+/*% Is IPv6 address linklocal? */
+#define IN6_IS_ADDR_LINKLOCAL(a) \
+	(((a)->s6_addr[0] == 0xfe) && (((a)->s6_addr[1] & 0xc0) == 0x80))
+#endif
+
+#ifndef IN6_IS_ADDR_SITELOCAL
+/*% is IPv6 address sitelocal? */
+#define IN6_IS_ADDR_SITELOCAL(a) \
+	(((a)->s6_addr[0] == 0xfe) && (((a)->s6_addr[1] & 0xc0) == 0xc0))
+#endif
+
+
+#ifndef IN6_IS_ADDR_LOOPBACK
+/*% is IPv6 address loopback? */
+#define IN6_IS_ADDR_LOOPBACK(x) \
+	(memcmp((x)->s6_addr, in6addr_loopback.s6_addr, 16) == 0)
+#endif
+#endif
+
+#ifndef AF_INET6
+/*% IPv6 */
+#define AF_INET6 99
+#endif
+
+#ifndef PF_INET6
+/*% IPv6 */
+#define PF_INET6 AF_INET6
+#endif
+
+#ifndef INADDR_LOOPBACK
+/*% inaddr loopback */
+#define INADDR_LOOPBACK 0x7f000001UL
+#endif
+
+#ifndef ISC_PLATFORM_HAVEIN6PKTINFO
+/*% IPv6 packet info */
+struct in6_pktinfo {
+	struct in6_addr ipi6_addr;    /*%< src/dst IPv6 address */
+	unsigned int    ipi6_ifindex; /*%< send/recv interface index */
+};
+#endif
+
+#if defined(ISC_PLATFORM_HAVEIPV6) && defined(ISC_PLATFORM_NEEDIN6ADDRANY)
+extern const struct in6_addr isc_net_in6addrany;
+/*%
+ * Cope with a missing in6addr_any and in6addr_loopback.
+ */
+#define in6addr_any isc_net_in6addrany
+#endif
+
+#if defined(ISC_PLATFORM_HAVEIPV6) && defined(ISC_PLATFORM_NEEDIN6ADDRLOOPBACK)
+extern const struct in6_addr isc_net_in6addrloop;
+#define in6addr_loopback isc_net_in6addrloop
+#endif
+
+#ifdef ISC_PLATFORM_FIXIN6ISADDR
+#undef  IN6_IS_ADDR_GEOGRAPHIC
+/*!
+ * \brief
+ * Fix UnixWare 7.1.1's broken IN6_IS_ADDR_* definitions.
+ */
+#define IN6_IS_ADDR_GEOGRAPHIC(a) (((a)->S6_un.S6_l[0] & 0xE0) == 0x80)
+#undef  IN6_IS_ADDR_IPX
+#define IN6_IS_ADDR_IPX(a)        (((a)->S6_un.S6_l[0] & 0xFE) == 0x04)
+#undef  IN6_IS_ADDR_LINKLOCAL
+#define IN6_IS_ADDR_LINKLOCAL(a)  (((a)->S6_un.S6_l[0] & 0xC0FF) == 0x80FE)
+#undef  IN6_IS_ADDR_MULTICAST
+#define IN6_IS_ADDR_MULTICAST(a)  (((a)->S6_un.S6_l[0] & 0xFF) == 0xFF)
+#undef  IN6_IS_ADDR_NSAP
+#define IN6_IS_ADDR_NSAP(a)       (((a)->S6_un.S6_l[0] & 0xFE) == 0x02)
+#undef  IN6_IS_ADDR_PROVIDER
+#define IN6_IS_ADDR_PROVIDER(a)   (((a)->S6_un.S6_l[0] & 0xE0) == 0x40)
+#undef  IN6_IS_ADDR_SITELOCAL
+#define IN6_IS_ADDR_SITELOCAL(a)  (((a)->S6_un.S6_l[0] & 0xC0FF) == 0xC0FE)
+#endif /* ISC_PLATFORM_FIXIN6ISADDR */
+
+#ifdef ISC_PLATFORM_NEEDPORTT
+/*%
+ * Ensure type in_port_t is defined.
+ */
+typedef isc_uint16_t in_port_t;
+#endif
+
+#ifndef MSG_TRUNC
+/*%
+ * If this system does not have MSG_TRUNC (as returned from recvmsg())
+ * ISC_PLATFORM_RECVOVERFLOW will be defined.  This will enable the MSG_TRUNC
+ * faking code in socket.c.
+ */
+#define ISC_PLATFORM_RECVOVERFLOW
+#endif
+
+/*% IP address. */
+#define ISC__IPADDR(x)	((isc_uint32_t)htonl((isc_uint32_t)(x)))
+
+/*% Is IP address multicast? */
+#define ISC_IPADDR_ISMULTICAST(i) \
+		(((isc_uint32_t)(i) & ISC__IPADDR(0xf0000000)) \
+		 == ISC__IPADDR(0xe0000000))
+
+#define ISC_IPADDR_ISEXPERIMENTAL(i) \
+		(((isc_uint32_t)(i) & ISC__IPADDR(0xf0000000)) \
+		 == ISC__IPADDR(0xf0000000))
+
+/***
+ *** Functions.
+ ***/
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_net_probeipv4(void);
+/*%<
+ * Check if the system's kernel supports IPv4.
+ *
+ * Returns:
+ *
+ *\li	#ISC_R_SUCCESS		IPv4 is supported.
+ *\li	#ISC_R_NOTFOUND		IPv4 is not supported.
+ *\li	#ISC_R_DISABLED		IPv4 is disabled.
+ *\li	#ISC_R_UNEXPECTED
+ */
+
+isc_result_t
+isc_net_probeipv6(void);
+/*%<
+ * Check if the system's kernel supports IPv6.
+ *
+ * Returns:
+ *
+ *\li	#ISC_R_SUCCESS		IPv6 is supported.
+ *\li	#ISC_R_NOTFOUND		IPv6 is not supported.
+ *\li	#ISC_R_DISABLED		IPv6 is disabled.
+ *\li	#ISC_R_UNEXPECTED
+ */
+
+isc_result_t
+isc_net_probe_ipv6only(void);
+/*%<
+ * Check if the system's kernel supports the IPV6_V6ONLY socket option.
+ *
+ * Returns:
+ *
+ *\li	#ISC_R_SUCCESS		the option is supported for both TCP and UDP.
+ *\li	#ISC_R_NOTFOUND		IPv6 itself or the option is not supported.
+ *\li	#ISC_R_UNEXPECTED
+ */
+
+isc_result_t
+isc_net_probe_ipv6pktinfo(void);
+/*
+ * Check if the system's kernel supports the IPV6_(RECV)PKTINFO socket option
+ * for UDP sockets.
+ *
+ * Returns:
+ *
+ * \li	#ISC_R_SUCCESS		the option is supported.
+ * \li	#ISC_R_NOTFOUND		IPv6 itself or the option is not supported.
+ * \li	#ISC_R_UNEXPECTED
+ */
+
+void
+isc_net_disableipv4(void);
+
+void
+isc_net_disableipv6(void);
+
+void
+isc_net_enableipv4(void);
+
+void
+isc_net_enableipv6(void);
+
+isc_result_t
+isc_net_probeunix(void);
+/*
+ * Returns whether UNIX domain sockets are supported.
+ */
+
+isc_result_t
+isc_net_getudpportrange(int af, in_port_t *low, in_port_t *high);
+/*%<
+ * Returns system's default range of ephemeral UDP ports, if defined.
+ * If the range is not available or unknown, ISC_NET_PORTRANGELOW and
+ * ISC_NET_PORTRANGEHIGH will be returned.
+ *
+ * Requires:
+ *
+ *\li	'low' and 'high' must be non NULL.
+ *
+ * Returns:
+ *
+ *\li	*low and *high will be the ports specifying the low and high ends of
+ *	the range.
+ */
+
+#ifdef ISC_PLATFORM_NEEDNTOP
+const char *
+isc_net_ntop(int af, const void *src, char *dst, size_t size);
+#define inet_ntop isc_net_ntop
+#endif
+
+#ifdef ISC_PLATFORM_NEEDPTON
+int
+isc_net_pton(int af, const char *src, void *dst);
+#undef inet_pton
+#define inet_pton isc_net_pton
+#endif
+
+int
+isc_net_aton(const char *cp, struct in_addr *addr);
+#undef inet_aton
+#define inet_aton isc_net_aton
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_NET_H */
diff --git a/src/lib/bind9/unix/include/isc/netdb.h b/src/lib/bind9/unix/include/isc/netdb.h
new file mode 100644
index 0000000..d6703f1
--- /dev/null
+++ b/src/lib/bind9/unix/include/isc/netdb.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: netdb.h,v 1.11 2007-06-19 23:47:19 tbox Exp $ */
+
+#ifndef ISC_NETDB_H
+#define ISC_NETDB_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file
+ * \brief
+ * Portable netdb.h support.
+ *
+ * This module is responsible for defining the get<x>by<y> APIs.
+ *
+ * MP:
+ *\li	No impact.
+ *
+ * Reliability:
+ *\li	No anticipated impact.
+ *
+ * Resources:
+ *\li	N/A.
+ *
+ * Security:
+ *\li	No anticipated impact.
+ *
+ * Standards:
+ *\li	BSD API
+ */
+
+/***
+ *** Imports.
+ ***/
+
+#include <isc/net.h>
+
+#include <netdb.h>
+
+#endif /* ISC_NETDB_H */
diff --git a/src/lib/bind9/unix/include/isc/offset.h b/src/lib/bind9/unix/include/isc/offset.h
new file mode 100644
index 0000000..2920899
--- /dev/null
+++ b/src/lib/bind9/unix/include/isc/offset.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2008  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: offset.h,v 1.17 2008-12-01 23:47:45 tbox Exp $ */
+
+#ifndef ISC_OFFSET_H
+#define ISC_OFFSET_H 1
+
+/*! \file
+ * \brief
+ * File offsets are operating-system dependent.
+ */
+#include <limits.h>             /* Required for CHAR_BIT. */
+#include <sys/types.h>
+#include <stddef.h>		/* For Linux Standard Base. */
+
+typedef off_t isc_offset_t;
+
+/*%
+ * POSIX says "Additionally, blkcnt_t and off_t are extended signed integral
+ * types", so the maximum value is all 1s except for the high bit.
+ * This definition is more complex than it really needs to be because it was
+ * crafted to keep both the SunOS 5.6 and the HP/UX 11 compilers quiet about
+ * integer overflow.  For example, though this is equivalent to just left
+ * shifting 1 to the high bit and then inverting the bits, the SunOS compiler
+ * is unhappy about shifting a positive "1" to negative in a signed integer.
+ */
+#define ISC_OFFSET_MAXIMUM \
+	(~(((off_t)-1 >> (sizeof(off_t) * CHAR_BIT - 1)) \
+		      << (sizeof(off_t) * CHAR_BIT - 1)))
+
+#endif /* ISC_OFFSET_H */
diff --git a/src/lib/bind9/unix/include/isc/stat.h b/src/lib/bind9/unix/include/isc/stat.h
new file mode 100644
index 0000000..4489002
--- /dev/null
+++ b/src/lib/bind9/unix/include/isc/stat.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2004, 2007  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: stat.h,v 1.5 2007-06-19 23:47:19 tbox Exp $ */
+
+#ifndef ISC_STAT_H
+#define ISC_STAT_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*
+ * Portable netdb.h support.
+ *
+ * This module is responsible for defining S_IS??? macros.
+ *
+ * MP:
+ *	No impact.
+ *
+ * Reliability:
+ *	No anticipated impact.
+ *
+ * Resources:
+ *	N/A.
+ *
+ * Security:
+ *	No anticipated impact.
+ *
+ */
+
+/***
+ *** Imports.
+ ***/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#endif /* ISC_STAT_H */
diff --git a/src/lib/bind9/unix/include/isc/stdtime.h b/src/lib/bind9/unix/include/isc/stdtime.h
new file mode 100644
index 0000000..cadb382
--- /dev/null
+++ b/src/lib/bind9/unix/include/isc/stdtime.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2011  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: stdtime.h,v 1.14.814.2 2011-03-18 23:47:15 tbox Exp $ */
+
+#ifndef ISC_STDTIME_H
+#define ISC_STDTIME_H 1
+
+/*! \file */
+
+#include <isc/lang.h>
+#include <isc/int.h>
+
+/*%
+ * It's public information that 'isc_stdtime_t' is an unsigned integral type.
+ * Applications that want maximum portability should not assume anything
+ * about its size.
+ */
+typedef isc_uint32_t isc_stdtime_t;
+
+/* but this flag helps... */
+#define STDTIME_ON_32BITS	1
+
+/*
+ * isc_stdtime32_t is a 32-bit version of isc_stdtime_t.  A variable of this
+ * type should only be used as an opaque integer (e.g.,) to compare two
+ * time values.
+ */
+typedef isc_uint32_t isc_stdtime32_t;
+
+ISC_LANG_BEGINDECLS
+/* */
+void
+isc_stdtime_get(isc_stdtime_t *t);
+/*%<
+ * Set 't' to the number of seconds since 00:00:00 UTC, January 1, 1970.
+ *
+ * Requires:
+ *
+ *\li	't' is a valid pointer.
+ */
+
+#define isc_stdtime_convert32(t, t32p) (*(t32p) = t)
+/*
+ * Convert the standard time to its 32-bit version.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_STDTIME_H */
diff --git a/src/lib/bind9/unix/include/isc/strerror.h b/src/lib/bind9/unix/include/isc/strerror.h
new file mode 100644
index 0000000..ac8d496
--- /dev/null
+++ b/src/lib/bind9/unix/include/isc/strerror.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2008  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: strerror.h,v 1.10 2008-12-01 23:47:45 tbox Exp $ */
+
+#ifndef ISC_STRERROR_H
+#define ISC_STRERROR_H
+
+/*! \file */
+
+#include <sys/types.h>
+
+#include <isc/lang.h>
+
+ISC_LANG_BEGINDECLS
+
+/*% String Error Size */
+#define ISC_STRERRORSIZE 128
+
+/*%
+ * Provide a thread safe wrapper to strerror().
+ *
+ * Requires:
+ * 	'buf' to be non NULL.
+ */
+void
+isc__strerror(int num, char *buf, size_t bufsize);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_STRERROR_H */
diff --git a/src/lib/bind9/unix/include/isc/syslog.h b/src/lib/bind9/unix/include/isc/syslog.h
new file mode 100644
index 0000000..7ac714b
--- /dev/null
+++ b/src/lib/bind9/unix/include/isc/syslog.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: syslog.h,v 1.7 2007-06-19 23:47:19 tbox Exp $ */
+
+#ifndef ISC_SYSLOG_H
+#define ISC_SYSLOG_H 1
+
+/*! \file */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_syslog_facilityfromstring(const char *str, int *facilityp);
+/*%<
+ * Convert 'str' to the appropriate syslog facility constant.
+ *
+ * Requires:
+ *
+ *\li	'str' is not NULL
+ *\li	'facilityp' is not NULL
+ *
+ * Returns:
+ * \li	#ISC_R_SUCCESS
+ * \li	#ISC_R_NOTFOUND
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_SYSLOG_H */
diff --git a/src/lib/bind9/unix/include/isc/time.h b/src/lib/bind9/unix/include/isc/time.h
new file mode 100644
index 0000000..19f0810
--- /dev/null
+++ b/src/lib/bind9/unix/include/isc/time.h
@@ -0,0 +1,334 @@
+/*
+ * Copyright (C) 2004-2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: time.h,v 1.40 2009-01-05 23:47:54 tbox Exp $ */
+
+#ifndef ISC_TIME_H
+#define ISC_TIME_H 1
+
+/*! \file */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+/***
+ *** Intervals
+ ***/
+
+/*!
+ *  \brief
+ * The contents of this structure are private, and MUST NOT be accessed
+ * directly by callers.
+ *
+ * The contents are exposed only to allow callers to avoid dynamic allocation.
+ */
+struct isc_interval {
+	unsigned int seconds;
+	unsigned int nanoseconds;
+};
+
+extern isc_interval_t *isc_interval_zero;
+
+ISC_LANG_BEGINDECLS
+
+void
+isc_interval_set(isc_interval_t *i,
+		 unsigned int seconds, unsigned int nanoseconds);
+/*%<
+ * Set 'i' to a value representing an interval of 'seconds' seconds and
+ * 'nanoseconds' nanoseconds, suitable for use in isc_time_add() and
+ * isc_time_subtract().
+ *
+ * Requires:
+ *
+ *\li	't' is a valid pointer.
+ *\li	nanoseconds < 1000000000.
+ */
+
+isc_boolean_t
+isc_interval_iszero(const isc_interval_t *i);
+/*%<
+ * Returns ISC_TRUE iff. 'i' is the zero interval.
+ *
+ * Requires:
+ *
+ *\li	'i' is a valid pointer.
+ */
+
+/***
+ *** Absolute Times
+ ***/
+
+/*%
+ * The contents of this structure are private, and MUST NOT be accessed
+ * directly by callers.
+ *
+ * The contents are exposed only to allow callers to avoid dynamic allocation.
+ */
+
+struct isc_time {
+	unsigned int	seconds;
+	unsigned int	nanoseconds;
+};
+
+extern isc_time_t *isc_time_epoch;
+
+void
+isc_time_set(isc_time_t *t, unsigned int seconds, unsigned int nanoseconds);
+/*%<
+ * Set 't' to a value which represents the given number of seconds and
+ * nanoseconds since 00:00:00 January 1, 1970, UTC.
+ *
+ * Notes:
+ *\li	The Unix version of this call is equivalent to:
+ *\code
+ *	isc_time_settoepoch(t);
+ *	isc_interval_set(i, seconds, nanoseconds);
+ *	isc_time_add(t, i, t);
+ *\endcode
+ *
+ * Requires:
+ *\li	't' is a valid pointer.
+ *\li	nanoseconds < 1000000000.
+ */
+
+void
+isc_time_settoepoch(isc_time_t *t);
+/*%<
+ * Set 't' to the time of the epoch.
+ *
+ * Notes:
+ *\li	The date of the epoch is platform-dependent.
+ *
+ * Requires:
+ *
+ *\li	't' is a valid pointer.
+ */
+
+isc_boolean_t
+isc_time_isepoch(const isc_time_t *t);
+/*%<
+ * Returns ISC_TRUE iff. 't' is the epoch ("time zero").
+ *
+ * Requires:
+ *
+ *\li	't' is a valid pointer.
+ */
+
+isc_result_t
+isc_time_now(isc_time_t *t);
+/*%<
+ * Set 't' to the current absolute time.
+ *
+ * Requires:
+ *
+ *\li	't' is a valid pointer.
+ *
+ * Returns:
+ *
+ *\li	Success
+ *\li	Unexpected error
+ *		Getting the time from the system failed.
+ *\li	Out of range
+ *		The time from the system is too large to be represented
+ *		in the current definition of isc_time_t.
+ */
+
+isc_result_t
+isc_time_nowplusinterval(isc_time_t *t, const isc_interval_t *i);
+/*%<
+ * Set *t to the current absolute time + i.
+ *
+ * Note:
+ *\li	This call is equivalent to:
+ *
+ *\code
+ *		isc_time_now(t);
+ *		isc_time_add(t, i, t);
+ *\endcode
+ *
+ * Requires:
+ *
+ *\li	't' and 'i' are valid pointers.
+ *
+ * Returns:
+ *
+ *\li	Success
+ *\li	Unexpected error
+ *		Getting the time from the system failed.
+ *\li	Out of range
+ *		The interval added to the time from the system is too large to
+ *		be represented in the current definition of isc_time_t.
+ */
+
+int
+isc_time_compare(const isc_time_t *t1, const isc_time_t *t2);
+/*%<
+ * Compare the times referenced by 't1' and 't2'
+ *
+ * Requires:
+ *
+ *\li	't1' and 't2' are valid pointers.
+ *
+ * Returns:
+ *
+ *\li	-1		t1 < t2		(comparing times, not pointers)
+ *\li	0		t1 = t2
+ *\li	1		t1 > t2
+ */
+
+isc_result_t
+isc_time_add(const isc_time_t *t, const isc_interval_t *i, isc_time_t *result);
+/*%<
+ * Add 'i' to 't', storing the result in 'result'.
+ *
+ * Requires:
+ *
+ *\li	't', 'i', and 'result' are valid pointers.
+ *
+ * Returns:
+ *\li	Success
+ *\li	Out of range
+ * 		The interval added to the time is too large to
+ *		be represented in the current definition of isc_time_t.
+ */
+
+isc_result_t
+isc_time_subtract(const isc_time_t *t, const isc_interval_t *i,
+		  isc_time_t *result);
+/*%<
+ * Subtract 'i' from 't', storing the result in 'result'.
+ *
+ * Requires:
+ *
+ *\li	't', 'i', and 'result' are valid pointers.
+ *
+ * Returns:
+ *\li	Success
+ *\li	Out of range
+ *		The interval is larger than the time since the epoch.
+ */
+
+isc_uint64_t
+isc_time_microdiff(const isc_time_t *t1, const isc_time_t *t2);
+/*%<
+ * Find the difference in microseconds between time t1 and time t2.
+ * t2 is the subtrahend of t1; ie, difference = t1 - t2.
+ *
+ * Requires:
+ *
+ *\li	't1' and 't2' are valid pointers.
+ *
+ * Returns:
+ *\li	The difference of t1 - t2, or 0 if t1 <= t2.
+ */
+
+isc_uint32_t
+isc_time_seconds(const isc_time_t *t);
+/*%<
+ * Return the number of seconds since the epoch stored in a time structure.
+ *
+ * Requires:
+ *
+ *\li	't' is a valid pointer.
+ */
+
+isc_result_t
+isc_time_secondsastimet(const isc_time_t *t, time_t *secondsp);
+/*%<
+ * Ensure the number of seconds in an isc_time_t is representable by a time_t.
+ *
+ * Notes:
+ *\li	The number of seconds stored in an isc_time_t might be larger
+ *	than the number of seconds a time_t is able to handle.  Since
+ *	time_t is mostly opaque according to the ANSI/ISO standard
+ *	(essentially, all you can be sure of is that it is an arithmetic type,
+ *	not even necessarily integral), it can be tricky to ensure that
+ *	the isc_time_t is in the range a time_t can handle.  Use this
+ *	function in place of isc_time_seconds() any time you need to set a
+ *	time_t from an isc_time_t.
+ *
+ * Requires:
+ *\li	't' is a valid pointer.
+ *
+ * Returns:
+ *\li	Success
+ *\li	Out of range
+ */
+
+isc_uint32_t
+isc_time_nanoseconds(const isc_time_t *t);
+/*%<
+ * Return the number of nanoseconds stored in a time structure.
+ *
+ * Notes:
+ *\li	This is the number of nanoseconds in excess of the number
+ *	of seconds since the epoch; it will always be less than one
+ *	full second.
+ *
+ * Requires:
+ *\li	't' is a valid pointer.
+ *
+ * Ensures:
+ *\li	The returned value is less than 1*10^9.
+ */
+
+void
+isc_time_formattimestamp(const isc_time_t *t, char *buf, unsigned int len);
+/*%<
+ * Format the time 't' into the buffer 'buf' of length 'len',
+ * using a format like "30-Aug-2000 04:06:47.997" and the local time zone.
+ * If the text does not fit in the buffer, the result is indeterminate,
+ * but is always guaranteed to be null terminated.
+ *
+ *  Requires:
+ *\li      'len' > 0
+ *\li      'buf' points to an array of at least len chars
+ *
+ */
+
+void
+isc_time_formathttptimestamp(const isc_time_t *t, char *buf, unsigned int len);
+/*%<
+ * Format the time 't' into the buffer 'buf' of length 'len',
+ * using a format like "Mon, 30 Aug 2000 04:06:47 GMT"
+ * If the text does not fit in the buffer, the result is indeterminate,
+ * but is always guaranteed to be null terminated.
+ *
+ *  Requires:
+ *\li      'len' > 0
+ *\li      'buf' points to an array of at least len chars
+ *
+ */
+
+void
+isc_time_formatISO8601(const isc_time_t *t, char *buf, unsigned int len);
+/*%<
+ * Format the time 't' into the buffer 'buf' of length 'len',
+ * using the ISO8601 format: "yyyy-mm-ddThh:mm:ssZ"
+ * If the text does not fit in the buffer, the result is indeterminate,
+ * but is always guaranteed to be null terminated.
+ *
+ *  Requires:
+ *\li      'len' > 0
+ *\li      'buf' points to an array of at least len chars
+ *
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_TIME_H */
diff --git a/src/lib/bind9/unix/interfaceiter.c b/src/lib/bind9/unix/interfaceiter.c
new file mode 100644
index 0000000..37fc3b1
--- /dev/null
+++ b/src/lib/bind9/unix/interfaceiter.c
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2008  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: interfaceiter.c,v 1.45 2008-12-01 03:51:47 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#ifdef HAVE_SYS_SOCKIO_H
+#include <sys/sockio.h>		/* Required for ifiter_ioctl.c. */
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <isc/interfaceiter.h>
+#include <isc/log.h>
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/msgs.h>
+#include <isc/net.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/strerror.h>
+#include <isc/string.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+/* Must follow <isc/net.h>. */
+#ifdef HAVE_NET_IF6_H
+#include <net/if6.h>
+#endif
+#include <net/if.h>
+
+/* Common utility functions */
+
+/*%
+ * Extract the network address part from a "struct sockaddr".
+ * \brief
+ * The address family is given explicitly
+ * instead of using src->sa_family, because the latter does not work
+ * for copying a network mask obtained by SIOCGIFNETMASK (it does
+ * not have a valid address family).
+ */
+
+static void
+get_addr(unsigned int family, isc_netaddr_t *dst, struct sockaddr *src,
+	 char *ifname)
+{
+	struct sockaddr_in6 *sa6;
+
+#if !defined(ISC_PLATFORM_HAVEIFNAMETOINDEX) || \
+    !defined(ISC_PLATFORM_HAVESCOPEID)
+	UNUSED(ifname);
+#endif
+
+	/* clear any remaining value for safety */
+	memset(dst, 0, sizeof(*dst));
+
+	dst->family = family;
+	switch (family) {
+	case AF_INET:
+		memcpy(&dst->type.in,
+		       &((struct sockaddr_in *) src)->sin_addr,
+		       sizeof(struct in_addr));
+		break;
+	case AF_INET6:
+		sa6 = (struct sockaddr_in6 *)src;
+		memcpy(&dst->type.in6, &sa6->sin6_addr,
+		       sizeof(struct in6_addr));
+#ifdef ISC_PLATFORM_HAVESCOPEID
+		if (sa6->sin6_scope_id != 0)
+			isc_netaddr_setzone(dst, sa6->sin6_scope_id);
+		else {
+			/*
+			 * BSD variants embed scope zone IDs in the 128bit
+			 * address as a kernel internal form.  Unfortunately,
+			 * the embedded IDs are not hidden from applications
+			 * when getting access to them by sysctl or ioctl.
+			 * We convert the internal format to the pure address
+			 * part and the zone ID part.
+			 * Since multicast addresses should not appear here
+			 * and they cannot be distinguished from netmasks,
+			 * we only consider unicast link-local addresses.
+			 */
+			if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr)) {
+				isc_uint16_t zone16;
+
+				memcpy(&zone16, &sa6->sin6_addr.s6_addr[2],
+				       sizeof(zone16));
+				zone16 = ntohs(zone16);
+				if (zone16 != 0) {
+					/* the zone ID is embedded */
+					isc_netaddr_setzone(dst,
+							    (isc_uint32_t)zone16);
+					dst->type.in6.s6_addr[2] = 0;
+					dst->type.in6.s6_addr[3] = 0;
+#ifdef ISC_PLATFORM_HAVEIFNAMETOINDEX
+				} else if (ifname != NULL) {
+					unsigned int zone;
+
+					/*
+					 * sin6_scope_id is still not provided,
+					 * but the corresponding interface name
+					 * is know.  Use the interface ID as
+					 * the link ID.
+					 */
+					zone = if_nametoindex(ifname);
+					if (zone != 0) {
+						isc_netaddr_setzone(dst,
+								    (isc_uint32_t)zone);
+					}
+#endif
+				}
+			}
+		}
+#endif
+		break;
+	default:
+		INSIST(0);
+		break;
+	}
+}
+
+/*
+ * Include system-dependent code.
+ */
+
+#ifdef __linux
+#define ISC_IF_INET6_SZ \
+    sizeof("00000000000000000000000000000001 01 80 10 80 XXXXXXloXXXXXXXX\n")
+static isc_result_t linux_if_inet6_next(isc_interfaceiter_t *);
+static isc_result_t linux_if_inet6_current(isc_interfaceiter_t *);
+static void linux_if_inet6_first(isc_interfaceiter_t *iter);
+#endif
+
+#if HAVE_GETIFADDRS
+#include "ifiter_getifaddrs.c"
+#elif HAVE_IFLIST_SYSCTL
+#include "ifiter_sysctl.c"
+#else
+#include "ifiter_ioctl.c"
+#endif
+
+#ifdef __linux
+static void
+linux_if_inet6_first(isc_interfaceiter_t *iter) {
+	if (iter->proc != NULL) {
+		rewind(iter->proc);
+		(void)linux_if_inet6_next(iter);
+	} else
+		iter->valid = ISC_R_NOMORE;
+}
+
+static isc_result_t
+linux_if_inet6_next(isc_interfaceiter_t *iter) {
+	if (iter->proc != NULL &&
+	    fgets(iter->entry, sizeof(iter->entry), iter->proc) != NULL)
+		iter->valid = ISC_R_SUCCESS;
+	else
+		iter->valid = ISC_R_NOMORE;
+	return (iter->valid);
+}
+
+static isc_result_t
+linux_if_inet6_current(isc_interfaceiter_t *iter) {
+	char address[33];
+	char name[IF_NAMESIZE+1];
+	struct in6_addr addr6;
+	int ifindex, prefix, flag3, flag4;
+	int res;
+	unsigned int i;
+
+	if (iter->valid != ISC_R_SUCCESS)
+		return (iter->valid);
+	if (iter->proc == NULL) {
+		isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+			      ISC_LOGMODULE_INTERFACE, ISC_LOG_ERROR,
+			      "/proc/net/if_inet6:iter->proc == NULL");
+		return (ISC_R_FAILURE);
+	}
+
+	res = sscanf(iter->entry, "%32[a-f0-9] %x %x %x %x %16s\n",
+		     address, &ifindex, &prefix, &flag3, &flag4, name);
+	if (res != 6) {
+		isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+			      ISC_LOGMODULE_INTERFACE, ISC_LOG_ERROR,
+			      "/proc/net/if_inet6:sscanf() -> %d (expected 6)",
+			      res);
+		return (ISC_R_FAILURE);
+	}
+	if (strlen(address) != 32) {
+		isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+			      ISC_LOGMODULE_INTERFACE, ISC_LOG_ERROR,
+			      "/proc/net/if_inet6:strlen(%s) != 32", address);
+		return (ISC_R_FAILURE);
+	}
+	for (i = 0; i < 16; i++) {
+		unsigned char byte;
+		static const char hex[] = "0123456789abcdef";
+		byte = ((strchr(hex, address[i * 2]) - hex) << 4) |
+		       (strchr(hex, address[i * 2 + 1]) - hex);
+		addr6.s6_addr[i] = byte;
+	}
+	iter->current.af = AF_INET6;
+	iter->current.flags = INTERFACE_F_UP;
+	isc_netaddr_fromin6(&iter->current.address, &addr6);
+	if (isc_netaddr_islinklocal(&iter->current.address)) {
+		isc_netaddr_setzone(&iter->current.address,
+				    (isc_uint32_t)ifindex);
+	}
+	for (i = 0; i < 16; i++) {
+		if (prefix > 8) {
+			addr6.s6_addr[i] = 0xff;
+			prefix -= 8;
+		} else {
+			addr6.s6_addr[i] = (0xff << (8 - prefix)) & 0xff;
+			prefix = 0;
+		}
+	}
+	isc_netaddr_fromin6(&iter->current.netmask, &addr6);
+	strncpy(iter->current.name, name, sizeof(iter->current.name));
+	return (ISC_R_SUCCESS);
+}
+#endif
+
+/*
+ * The remaining code is common to the sysctl and ioctl case.
+ */
+
+isc_result_t
+isc_interfaceiter_current(isc_interfaceiter_t *iter,
+			  isc_interface_t *ifdata)
+{
+	REQUIRE(iter->result == ISC_R_SUCCESS);
+	memcpy(ifdata, &iter->current, sizeof(*ifdata));
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_interfaceiter_first(isc_interfaceiter_t *iter) {
+	isc_result_t result;
+
+	REQUIRE(VALID_IFITER(iter));
+
+	internal_first(iter);
+	for (;;) {
+		result = internal_current(iter);
+		if (result != ISC_R_IGNORE)
+			break;
+		result = internal_next(iter);
+		if (result != ISC_R_SUCCESS)
+			break;
+	}
+	iter->result = result;
+	return (result);
+}
+
+isc_result_t
+isc_interfaceiter_next(isc_interfaceiter_t *iter) {
+	isc_result_t result;
+
+	REQUIRE(VALID_IFITER(iter));
+	REQUIRE(iter->result == ISC_R_SUCCESS);
+
+	for (;;) {
+		result = internal_next(iter);
+		if (result != ISC_R_SUCCESS)
+			break;
+		result = internal_current(iter);
+		if (result != ISC_R_IGNORE)
+			break;
+	}
+	iter->result = result;
+	return (result);
+}
+
+void
+isc_interfaceiter_destroy(isc_interfaceiter_t **iterp)
+{
+	isc_interfaceiter_t *iter;
+	REQUIRE(iterp != NULL);
+	iter = *iterp;
+	REQUIRE(VALID_IFITER(iter));
+
+	internal_destroy(iter);
+	if (iter->buf != NULL)
+		isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
+
+	iter->magic = 0;
+	isc_mem_put(iter->mctx, iter, sizeof(*iter));
+	*iterp = NULL;
+}
diff --git a/src/lib/bind9/unix/ipv6.c b/src/lib/bind9/unix/ipv6.c
new file mode 100644
index 0000000..3fb1424
--- /dev/null
+++ b/src/lib/bind9/unix/ipv6.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: ipv6.c,v 1.14 2007-06-19 23:47:18 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/ipv6.h>
+
+const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
+const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
diff --git a/src/lib/bind9/unix/keyboard.c b/src/lib/bind9/unix/keyboard.c
new file mode 100644
index 0000000..d022c03
--- /dev/null
+++ b/src/lib/bind9/unix/keyboard.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2004, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: keyboard.c,v 1.13 2007-06-19 23:47:18 tbox Exp $ */
+
+#include <config.h>
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/uio.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <isc/keyboard.h>
+#include <isc/util.h>
+
+isc_result_t
+isc_keyboard_open(isc_keyboard_t *keyboard) {
+	int fd;
+	isc_result_t ret;
+	struct termios current_mode;
+
+	REQUIRE(keyboard != NULL);
+
+	fd = open("/dev/tty", O_RDONLY, 0);
+	if (fd < 0)
+		return (ISC_R_IOERROR);
+
+	keyboard->fd = fd;
+
+	if (tcgetattr(fd, &keyboard->saved_mode) < 0) {
+		ret = ISC_R_IOERROR;
+		goto errout;
+	}
+
+	current_mode = keyboard->saved_mode;
+
+	current_mode.c_iflag &=
+			~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
+	current_mode.c_oflag &= ~OPOST;
+	current_mode.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
+	current_mode.c_cflag &= ~(CSIZE|PARENB);
+	current_mode.c_cflag |= CS8;
+
+	current_mode.c_cc[VMIN] = 1;
+	current_mode.c_cc[VTIME] = 0;
+	if (tcsetattr(fd, TCSAFLUSH, &current_mode) < 0) {
+		ret = ISC_R_IOERROR;
+		goto errout;
+	}
+
+	keyboard->result = ISC_R_SUCCESS;
+
+	return (ISC_R_SUCCESS);
+
+ errout:
+	close (fd);
+
+	return (ret);
+}
+
+isc_result_t
+isc_keyboard_close(isc_keyboard_t *keyboard, unsigned int sleeptime) {
+	REQUIRE(keyboard != NULL);
+
+	if (sleeptime > 0 && keyboard->result != ISC_R_CANCELED)
+		(void)sleep(sleeptime);
+
+	(void)tcsetattr(keyboard->fd, TCSAFLUSH, &keyboard->saved_mode);
+	(void)close(keyboard->fd);
+
+	keyboard->fd = -1;
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_keyboard_getchar(isc_keyboard_t *keyboard, unsigned char *cp) {
+	ssize_t cc;
+	unsigned char c;
+	cc_t *controlchars;
+
+	REQUIRE(keyboard != NULL);
+	REQUIRE(cp != NULL);
+
+	cc = read(keyboard->fd, &c, 1);
+	if (cc < 0) {
+		keyboard->result = ISC_R_IOERROR;
+		return (keyboard->result);
+	}
+
+	controlchars = keyboard->saved_mode.c_cc;
+	if (c == controlchars[VINTR] || c == controlchars[VQUIT]) {
+		keyboard->result = ISC_R_CANCELED;
+		return (keyboard->result);
+	}
+
+	*cp = c;
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_boolean_t
+isc_keyboard_canceled(isc_keyboard_t *keyboard) {
+	return (ISC_TF(keyboard->result == ISC_R_CANCELED));
+}
diff --git a/src/lib/bind9/unix/net.c b/src/lib/bind9/unix/net.c
new file mode 100644
index 0000000..11a06ce
--- /dev/null
+++ b/src/lib/bind9/unix/net.c
@@ -0,0 +1,524 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2008  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: net.c,v 1.40 2008-07-04 05:52:31 each Exp $ */
+
+#include <config.h>
+
+#include <sys/types.h>
+
+#if defined(HAVE_SYS_SYSCTL_H)
+#if defined(HAVE_SYS_PARAM_H)
+#include <sys/param.h>
+#endif
+#include <sys/sysctl.h>
+#endif
+
+#include <errno.h>
+#include <unistd.h>
+
+#include <isc/log.h>
+#include <isc/msgs.h>
+#include <isc/net.h>
+#include <isc/once.h>
+#include <isc/strerror.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+/*%
+ * Definitions about UDP port range specification.  This is a total mess of
+ * portability variants: some use sysctl (but the sysctl names vary), some use
+ * system-specific interfaces, some have the same interface for IPv4 and IPv6,
+ * some separate them, etc...
+ */
+
+/*%
+ * The last resort defaults: use all non well known port space
+ */
+#ifndef ISC_NET_PORTRANGELOW
+#define ISC_NET_PORTRANGELOW 1024
+#endif	/* ISC_NET_PORTRANGELOW */
+#ifndef ISC_NET_PORTRANGEHIGH
+#define ISC_NET_PORTRANGEHIGH 65535
+#endif	/* ISC_NET_PORTRANGEHIGH */
+
+#ifdef HAVE_SYSCTLBYNAME
+
+/*%
+ * sysctl variants
+ */
+#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__DragonFly__)
+#define USE_SYSCTL_PORTRANGE
+#define SYSCTL_V4PORTRANGE_LOW	"net.inet.ip.portrange.hifirst"
+#define SYSCTL_V4PORTRANGE_HIGH	"net.inet.ip.portrange.hilast"
+#define SYSCTL_V6PORTRANGE_LOW	"net.inet.ip.portrange.hifirst"
+#define SYSCTL_V6PORTRANGE_HIGH	"net.inet.ip.portrange.hilast"
+#endif
+
+#ifdef __NetBSD__
+#define USE_SYSCTL_PORTRANGE
+#define SYSCTL_V4PORTRANGE_LOW	"net.inet.ip.anonportmin"
+#define SYSCTL_V4PORTRANGE_HIGH	"net.inet.ip.anonportmax"
+#define SYSCTL_V6PORTRANGE_LOW	"net.inet6.ip6.anonportmin"
+#define SYSCTL_V6PORTRANGE_HIGH	"net.inet6.ip6.anonportmax"
+#endif
+
+#else /* !HAVE_SYSCTLBYNAME */
+
+#ifdef __OpenBSD__
+#define USE_SYSCTL_PORTRANGE
+#define SYSCTL_V4PORTRANGE_LOW	{ CTL_NET, PF_INET, IPPROTO_IP, \
+				  IPCTL_IPPORT_HIFIRSTAUTO }
+#define SYSCTL_V4PORTRANGE_HIGH	{ CTL_NET, PF_INET, IPPROTO_IP, \
+				  IPCTL_IPPORT_HILASTAUTO }
+/* Same for IPv6 */
+#define SYSCTL_V6PORTRANGE_LOW	SYSCTL_V4PORTRANGE_LOW
+#define SYSCTL_V6PORTRANGE_HIGH	SYSCTL_V4PORTRANGE_HIGH
+#endif
+
+#endif /* HAVE_SYSCTLBYNAME */
+
+#if defined(ISC_PLATFORM_HAVEIPV6)
+# if defined(ISC_PLATFORM_NEEDIN6ADDRANY)
+const struct in6_addr isc_net_in6addrany = IN6ADDR_ANY_INIT;
+# endif
+
+# if defined(ISC_PLATFORM_NEEDIN6ADDRLOOPBACK)
+const struct in6_addr isc_net_in6addrloop = IN6ADDR_LOOPBACK_INIT;
+# endif
+
+# if defined(WANT_IPV6)
+static isc_once_t 	once_ipv6only = ISC_ONCE_INIT;
+# endif
+
+# if defined(ISC_PLATFORM_HAVEIN6PKTINFO)
+static isc_once_t 	once_ipv6pktinfo = ISC_ONCE_INIT;
+# endif
+#endif /* ISC_PLATFORM_HAVEIPV6 */
+
+static isc_once_t 	once = ISC_ONCE_INIT;
+
+static isc_result_t	ipv4_result = ISC_R_NOTFOUND;
+static isc_result_t	ipv6_result = ISC_R_NOTFOUND;
+static isc_result_t	unix_result = ISC_R_NOTFOUND;
+static isc_result_t	ipv6only_result = ISC_R_NOTFOUND;
+static isc_result_t	ipv6pktinfo_result = ISC_R_NOTFOUND;
+
+static isc_result_t
+try_proto(int domain) {
+	int s;
+	isc_result_t result = ISC_R_SUCCESS;
+	char strbuf[ISC_STRERRORSIZE];
+
+	s = socket(domain, SOCK_STREAM, 0);
+	if (s == -1) {
+		switch (errno) {
+#ifdef EAFNOSUPPORT
+		case EAFNOSUPPORT:
+#endif
+#ifdef EPROTONOSUPPORT
+		case EPROTONOSUPPORT:
+#endif
+#ifdef EINVAL
+		case EINVAL:
+#endif
+			return (ISC_R_NOTFOUND);
+		default:
+			isc__strerror(errno, strbuf, sizeof(strbuf));
+			UNEXPECTED_ERROR(__FILE__, __LINE__,
+					 "socket() %s: %s",
+					 isc_msgcat_get(isc_msgcat,
+							ISC_MSGSET_GENERAL,
+							ISC_MSG_FAILED,
+							"failed"),
+					 strbuf);
+			return (ISC_R_UNEXPECTED);
+		}
+	}
+
+#ifdef ISC_PLATFORM_HAVEIPV6
+#ifdef WANT_IPV6
+#ifdef ISC_PLATFORM_HAVEIN6PKTINFO
+	if (domain == PF_INET6) {
+		struct sockaddr_in6 sin6;
+		unsigned int len;
+
+		/*
+		 * Check to see if IPv6 is broken, as is common on Linux.
+		 */
+		len = sizeof(sin6);
+		if (getsockname(s, (struct sockaddr *)&sin6, (void *)&len) < 0)
+		{
+			isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+				      ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
+				      "retrieving the address of an IPv6 "
+				      "socket from the kernel failed.");
+			isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+				      ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
+				      "IPv6 is not supported.");
+			result = ISC_R_NOTFOUND;
+		} else {
+			if (len == sizeof(struct sockaddr_in6))
+				result = ISC_R_SUCCESS;
+			else {
+				isc_log_write(isc_lctx,
+					      ISC_LOGCATEGORY_GENERAL,
+					      ISC_LOGMODULE_SOCKET,
+					      ISC_LOG_ERROR,
+					      "IPv6 structures in kernel and "
+					      "user space do not match.");
+				isc_log_write(isc_lctx,
+					      ISC_LOGCATEGORY_GENERAL,
+					      ISC_LOGMODULE_SOCKET,
+					      ISC_LOG_ERROR,
+					      "IPv6 is not supported.");
+				result = ISC_R_NOTFOUND;
+			}
+		}
+	}
+#endif
+#endif
+#endif
+
+	(void)close(s);
+
+	return (result);
+}
+
+static void
+initialize_action(void) {
+	ipv4_result = try_proto(PF_INET);
+#ifdef ISC_PLATFORM_HAVEIPV6
+#ifdef WANT_IPV6
+#ifdef ISC_PLATFORM_HAVEIN6PKTINFO
+	ipv6_result = try_proto(PF_INET6);
+#endif
+#endif
+#endif
+#ifdef ISC_PLATFORM_HAVESYSUNH
+	unix_result = try_proto(PF_UNIX);
+#endif
+}
+
+static void
+initialize(void) {
+	RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_net_probeipv4(void) {
+	initialize();
+	return (ipv4_result);
+}
+
+isc_result_t
+isc_net_probeipv6(void) {
+	initialize();
+	return (ipv6_result);
+}
+
+isc_result_t
+isc_net_probeunix(void) {
+	initialize();
+	return (unix_result);
+}
+
+#ifdef ISC_PLATFORM_HAVEIPV6
+#ifdef WANT_IPV6
+static void
+try_ipv6only(void) {
+#ifdef IPV6_V6ONLY
+	int s, on;
+	char strbuf[ISC_STRERRORSIZE];
+#endif
+	isc_result_t result;
+
+	result = isc_net_probeipv6();
+	if (result != ISC_R_SUCCESS) {
+		ipv6only_result = result;
+		return;
+	}
+
+#ifndef IPV6_V6ONLY
+	ipv6only_result = ISC_R_NOTFOUND;
+	return;
+#else
+	/* check for TCP sockets */
+	s = socket(PF_INET6, SOCK_STREAM, 0);
+	if (s == -1) {
+		isc__strerror(errno, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "socket() %s: %s",
+				 isc_msgcat_get(isc_msgcat,
+						ISC_MSGSET_GENERAL,
+						ISC_MSG_FAILED,
+						"failed"),
+				 strbuf);
+		ipv6only_result = ISC_R_UNEXPECTED;
+		return;
+	}
+
+	on = 1;
+	if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) {
+		ipv6only_result = ISC_R_NOTFOUND;
+		goto close;
+	}
+
+	close(s);
+
+	/* check for UDP sockets */
+	s = socket(PF_INET6, SOCK_DGRAM, 0);
+	if (s == -1) {
+		isc__strerror(errno, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "socket() %s: %s",
+				 isc_msgcat_get(isc_msgcat,
+						ISC_MSGSET_GENERAL,
+						ISC_MSG_FAILED,
+						"failed"),
+				 strbuf);
+		ipv6only_result = ISC_R_UNEXPECTED;
+		return;
+	}
+
+	on = 1;
+	if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) {
+		ipv6only_result = ISC_R_NOTFOUND;
+		goto close;
+	}
+
+	close(s);
+
+	ipv6only_result = ISC_R_SUCCESS;
+
+close:
+	close(s);
+	return;
+#endif /* IPV6_V6ONLY */
+}
+
+static void
+initialize_ipv6only(void) {
+	RUNTIME_CHECK(isc_once_do(&once_ipv6only,
+				  try_ipv6only) == ISC_R_SUCCESS);
+}
+#endif /* WANT_IPV6 */
+
+#ifdef ISC_PLATFORM_HAVEIN6PKTINFO
+static void
+try_ipv6pktinfo(void) {
+	int s, on;
+	char strbuf[ISC_STRERRORSIZE];
+	isc_result_t result;
+	int optname;
+
+	result = isc_net_probeipv6();
+	if (result != ISC_R_SUCCESS) {
+		ipv6pktinfo_result = result;
+		return;
+	}
+
+	/* we only use this for UDP sockets */
+	s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+	if (s == -1) {
+		isc__strerror(errno, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "socket() %s: %s",
+				 isc_msgcat_get(isc_msgcat,
+						ISC_MSGSET_GENERAL,
+						ISC_MSG_FAILED,
+						"failed"),
+				 strbuf);
+		ipv6pktinfo_result = ISC_R_UNEXPECTED;
+		return;
+	}
+
+#ifdef IPV6_RECVPKTINFO
+	optname = IPV6_RECVPKTINFO;
+#else
+	optname = IPV6_PKTINFO;
+#endif
+	on = 1;
+	if (setsockopt(s, IPPROTO_IPV6, optname, &on, sizeof(on)) < 0) {
+		ipv6pktinfo_result = ISC_R_NOTFOUND;
+		goto close;
+	}
+
+	close(s);
+	ipv6pktinfo_result = ISC_R_SUCCESS;
+
+close:
+	close(s);
+	return;
+}
+
+static void
+initialize_ipv6pktinfo(void) {
+	RUNTIME_CHECK(isc_once_do(&once_ipv6pktinfo,
+				  try_ipv6pktinfo) == ISC_R_SUCCESS);
+}
+#endif /* ISC_PLATFORM_HAVEIN6PKTINFO */
+#endif /* ISC_PLATFORM_HAVEIPV6 */
+
+isc_result_t
+isc_net_probe_ipv6only(void) {
+#ifdef ISC_PLATFORM_HAVEIPV6
+#ifdef WANT_IPV6
+	initialize_ipv6only();
+#else
+	ipv6only_result = ISC_R_NOTFOUND;
+#endif
+#endif
+	return (ipv6only_result);
+}
+
+isc_result_t
+isc_net_probe_ipv6pktinfo(void) {
+#ifdef ISC_PLATFORM_HAVEIPV6
+#ifdef ISC_PLATFORM_HAVEIN6PKTINFO
+#ifdef WANT_IPV6
+	initialize_ipv6pktinfo();
+#else
+	ipv6pktinfo_result = ISC_R_NOTFOUND;
+#endif
+#endif
+#endif
+	return (ipv6pktinfo_result);
+}
+
+#if defined(USE_SYSCTL_PORTRANGE)
+#if defined(HAVE_SYSCTLBYNAME)
+static isc_result_t
+getudpportrange_sysctl(int af, in_port_t *low, in_port_t *high) {
+	int port_low, port_high;
+	size_t portlen;
+	const char *sysctlname_lowport, *sysctlname_hiport;
+
+	if (af == AF_INET) {
+		sysctlname_lowport = SYSCTL_V4PORTRANGE_LOW;
+		sysctlname_hiport = SYSCTL_V4PORTRANGE_HIGH;
+	} else {
+		sysctlname_lowport = SYSCTL_V6PORTRANGE_LOW;
+		sysctlname_hiport = SYSCTL_V6PORTRANGE_HIGH;
+	}
+	portlen = sizeof(portlen);
+	if (sysctlbyname(sysctlname_lowport, &port_low, &portlen,
+			 NULL, 0) < 0) {
+		return (ISC_R_FAILURE);
+	}
+	portlen = sizeof(portlen);
+	if (sysctlbyname(sysctlname_hiport, &port_high, &portlen,
+			 NULL, 0) < 0) {
+		return (ISC_R_FAILURE);
+	}
+	if ((port_low & ~0xffff) != 0 || (port_high & ~0xffff) != 0)
+		return (ISC_R_RANGE);
+
+	*low = (in_port_t)port_low;
+	*high = (in_port_t)port_high;
+
+	return (ISC_R_SUCCESS);
+}
+#else /* !HAVE_SYSCTLBYNAME */
+static isc_result_t
+getudpportrange_sysctl(int af, in_port_t *low, in_port_t *high) {
+	int mib_lo4[4] = SYSCTL_V4PORTRANGE_LOW;
+	int mib_hi4[4] = SYSCTL_V4PORTRANGE_HIGH;
+	int mib_lo6[4] = SYSCTL_V6PORTRANGE_LOW;
+	int mib_hi6[4] = SYSCTL_V6PORTRANGE_HIGH;
+	int *mib_lo, *mib_hi, miblen;
+	int port_low, port_high;
+	size_t portlen;
+
+	if (af == AF_INET) {
+		mib_lo = mib_lo4;
+		mib_hi = mib_hi4;
+		miblen = sizeof(mib_lo4) / sizeof(mib_lo4[0]);
+	} else {
+		mib_lo = mib_lo6;
+		mib_hi = mib_hi6;
+		miblen = sizeof(mib_lo6) / sizeof(mib_lo6[0]);
+	}
+
+	portlen = sizeof(portlen);
+	if (sysctl(mib_lo, miblen, &port_low, &portlen, NULL, 0) < 0) {
+		return (ISC_R_FAILURE);
+	}
+
+	portlen = sizeof(portlen);
+	if (sysctl(mib_hi, miblen, &port_high, &portlen, NULL, 0) < 0) {
+		return (ISC_R_FAILURE);
+	}
+
+	if ((port_low & ~0xffff) != 0 || (port_high & ~0xffff) != 0)
+		return (ISC_R_RANGE);
+
+	*low = (in_port_t) port_low;
+	*high = (in_port_t) port_high;
+
+	return (ISC_R_SUCCESS);
+}
+#endif /* HAVE_SYSCTLBYNAME */
+#endif /* USE_SYSCTL_PORTRANGE */
+
+isc_result_t
+isc_net_getudpportrange(int af, in_port_t *low, in_port_t *high) {
+	int result = ISC_R_FAILURE;
+
+	REQUIRE(low != NULL && high != NULL);
+
+#if defined(USE_SYSCTL_PORTRANGE)
+	result = getudpportrange_sysctl(af, low, high);
+#else
+	UNUSED(af);
+#endif
+
+	if (result != ISC_R_SUCCESS) {
+		*low = ISC_NET_PORTRANGELOW;
+		*high = ISC_NET_PORTRANGEHIGH;
+	}
+
+	return (ISC_R_SUCCESS);	/* we currently never fail in this function */
+}
+
+void
+isc_net_disableipv4(void) {
+	initialize();
+	if (ipv4_result == ISC_R_SUCCESS)
+		ipv4_result = ISC_R_DISABLED;
+}
+
+void
+isc_net_disableipv6(void) {
+	initialize();
+	if (ipv6_result == ISC_R_SUCCESS)
+		ipv6_result = ISC_R_DISABLED;
+}
+
+void
+isc_net_enableipv4(void) {
+	initialize();
+	if (ipv4_result == ISC_R_DISABLED)
+		ipv4_result = ISC_R_SUCCESS;
+}
+
+void
+isc_net_enableipv6(void) {
+	initialize();
+	if (ipv6_result == ISC_R_DISABLED)
+		ipv6_result = ISC_R_SUCCESS;
+}
diff --git a/src/lib/bind9/unix/os.c b/src/lib/bind9/unix/os.c
new file mode 100644
index 0000000..1a3faf2
--- /dev/null
+++ b/src/lib/bind9/unix/os.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: os.c,v 1.18 2007-06-19 23:47:18 tbox Exp $ */
+
+#include <config.h>
+
+#include <isc/os.h>
+
+
+#ifdef HAVE_SYSCONF
+
+#include <unistd.h>
+
+#ifndef __hpux
+static inline long
+sysconf_ncpus(void) {
+#if defined(_SC_NPROCESSORS_ONLN)
+	return sysconf((_SC_NPROCESSORS_ONLN));
+#elif defined(_SC_NPROC_ONLN)
+	return sysconf((_SC_NPROC_ONLN));
+#else
+	return (0);
+#endif
+}
+#endif
+#endif /* HAVE_SYSCONF */
+
+
+#ifdef __hpux
+
+#include <sys/pstat.h>
+
+static inline int
+hpux_ncpus(void) {
+	struct pst_dynamic psd;
+	if (pstat_getdynamic(&psd, sizeof(psd), 1, 0) != -1)
+		return (psd.psd_proc_cnt);
+	else
+		return (0);
+}
+
+#endif /* __hpux */
+
+#if defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_SYSCTLBYNAME)
+#include <sys/types.h>  /* for FreeBSD */
+#include <sys/param.h>  /* for NetBSD */
+#include <sys/sysctl.h>
+
+static int
+sysctl_ncpus(void) {
+	int ncpu, result;
+	size_t len;
+
+	len = sizeof(ncpu);
+	result = sysctlbyname("hw.ncpu", &ncpu, &len , 0, 0);
+	if (result != -1)
+		return (ncpu);
+	return (0);
+}
+#endif
+
+unsigned int
+isc_os_ncpus(void) {
+	long ncpus = 0;
+
+#ifdef __hpux
+	ncpus = hpux_ncpus();
+#elif defined(HAVE_SYSCONF)
+	ncpus = sysconf_ncpus();
+#endif
+#if defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_SYSCTLBYNAME)
+	if (ncpus <= 0)
+		ncpus = sysctl_ncpus();
+#endif
+	if (ncpus <= 0)
+		ncpus = 1;
+
+	return ((unsigned int)ncpus);
+}
diff --git a/src/lib/bind9/unix/resource.c b/src/lib/bind9/unix/resource.c
new file mode 100644
index 0000000..99a4b8c
--- /dev/null
+++ b/src/lib/bind9/unix/resource.c
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2004, 2007-2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: resource.c,v 1.23 2009-02-13 23:48:14 tbox Exp $ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/time.h>	/* Required on some systems for <sys/resource.h>. */
+#include <sys/resource.h>
+
+#include <isc/platform.h>
+#include <isc/resource.h>
+#include <isc/result.h>
+#include <isc/util.h>
+
+#ifdef __linux__
+#include <linux/fs.h>	/* To get the large NR_OPEN. */
+#endif
+
+#if defined(__hpux) && defined(HAVE_SYS_DYNTUNE_H)
+#include <sys/dyntune.h>
+#endif
+
+#include "errno2result.h"
+
+static isc_result_t
+resource2rlim(isc_resource_t resource, int *rlim_resource) {
+	isc_result_t result = ISC_R_SUCCESS;
+
+	switch (resource) {
+	case isc_resource_coresize:
+		*rlim_resource = RLIMIT_CORE;
+		break;
+	case isc_resource_cputime:
+		*rlim_resource = RLIMIT_CPU;
+		break;
+	case isc_resource_datasize:
+		*rlim_resource = RLIMIT_DATA;
+		break;
+	case isc_resource_filesize:
+		*rlim_resource = RLIMIT_FSIZE;
+		break;
+	case isc_resource_lockedmemory:
+#ifdef RLIMIT_MEMLOCK
+		*rlim_resource = RLIMIT_MEMLOCK;
+#else
+		result = ISC_R_NOTIMPLEMENTED;
+#endif
+		break;
+	case isc_resource_openfiles:
+#ifdef RLIMIT_NOFILE
+		*rlim_resource = RLIMIT_NOFILE;
+#else
+		result = ISC_R_NOTIMPLEMENTED;
+#endif
+		break;
+	case isc_resource_processes:
+#ifdef RLIMIT_NPROC
+		*rlim_resource = RLIMIT_NPROC;
+#else
+		result = ISC_R_NOTIMPLEMENTED;
+#endif
+		break;
+	case isc_resource_residentsize:
+#ifdef RLIMIT_RSS
+		*rlim_resource = RLIMIT_RSS;
+#else
+		result = ISC_R_NOTIMPLEMENTED;
+#endif
+		break;
+	case isc_resource_stacksize:
+		*rlim_resource = RLIMIT_STACK;
+		break;
+	default:
+		/*
+		 * This test is not very robust if isc_resource_t
+		 * changes, but generates a clear assertion message.
+		 */
+		REQUIRE(resource >= isc_resource_coresize &&
+			resource <= isc_resource_stacksize);
+
+		result = ISC_R_RANGE;
+		break;
+	}
+
+	return (result);
+}
+
+isc_result_t
+isc_resource_setlimit(isc_resource_t resource, isc_resourcevalue_t value) {
+	struct rlimit rl;
+	ISC_PLATFORM_RLIMITTYPE rlim_value;
+	int unixresult;
+	int unixresource;
+	isc_result_t result;
+
+	result = resource2rlim(resource, &unixresource);
+	if (result != ISC_R_SUCCESS)
+		return (result);
+
+	if (value == ISC_RESOURCE_UNLIMITED)
+		rlim_value = RLIM_INFINITY;
+
+	else {
+		/*
+		 * isc_resourcevalue_t was chosen as an unsigned 64 bit
+		 * integer so that it could contain the maximum range of
+		 * reasonable values.  Unfortunately, this exceeds the typical
+		 * range on Unix systems.  Ensure the range of
+		 * ISC_PLATFORM_RLIMITTYPE is not overflowed.
+		 */
+		isc_resourcevalue_t rlim_max;
+		isc_boolean_t rlim_t_is_signed =
+			ISC_TF(((double)(ISC_PLATFORM_RLIMITTYPE)-1) < 0);
+
+		if (rlim_t_is_signed)
+			rlim_max = ~((ISC_PLATFORM_RLIMITTYPE)1 <<
+				     (sizeof(ISC_PLATFORM_RLIMITTYPE) * 8 - 1));
+		else
+			rlim_max = (ISC_PLATFORM_RLIMITTYPE)-1;
+
+		if (value > rlim_max)
+			value = rlim_max;
+
+		rlim_value = value;
+	}
+
+	rl.rlim_cur = rl.rlim_max = rlim_value;
+	unixresult = setrlimit(unixresource, &rl);
+
+	if (unixresult == 0)
+		return (ISC_R_SUCCESS);
+
+#if defined(OPEN_MAX) && defined(__APPLE__)
+	/*
+	 * The Darwin kernel doesn't accept RLIM_INFINITY for rlim_cur; the
+	 * maximum possible value is OPEN_MAX.  BIND8 used to use
+	 * sysconf(_SC_OPEN_MAX) for such a case, but this value is much
+	 * smaller than OPEN_MAX and is not really effective.
+	 */
+	if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
+		rl.rlim_cur = OPEN_MAX;
+		unixresult = setrlimit(unixresource, &rl);
+		if (unixresult == 0)
+			return (ISC_R_SUCCESS);
+	}
+#elif defined(__linux__)
+#ifndef NR_OPEN
+#define NR_OPEN (1024*1024)
+#endif
+
+	/*
+	 * Some Linux kernels don't accept RLIM_INFINIT; the maximum
+	 * possible value is the NR_OPEN defined in linux/fs.h.
+	 */
+	if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
+		rl.rlim_cur = rl.rlim_max = NR_OPEN;
+		unixresult = setrlimit(unixresource, &rl);
+		if (unixresult == 0)
+			return (ISC_R_SUCCESS);
+	}
+#elif defined(__hpux) && defined(HAVE_SYS_DYNTUNE_H)
+	if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
+		uint64_t maxfiles;
+		if (gettune("maxfiles_lim", &maxfiles) == 0) {
+			rl.rlim_cur = rl.rlim_max = maxfiles;
+			unixresult = setrlimit(unixresource, &rl);
+			if (unixresult == 0)
+				return (ISC_R_SUCCESS);
+		}
+	}
+#endif
+	if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
+		if (getrlimit(unixresource, &rl) == 0) {
+			rl.rlim_cur = rl.rlim_max;
+			unixresult = setrlimit(unixresource, &rl);
+			if (unixresult == 0)
+				return (ISC_R_SUCCESS);
+		}
+	}
+	return (isc__errno2result(errno));
+}
+
+isc_result_t
+isc_resource_getlimit(isc_resource_t resource, isc_resourcevalue_t *value) {
+	int unixresult;
+	int unixresource;
+	struct rlimit rl;
+	isc_result_t result;
+
+	result = resource2rlim(resource, &unixresource);
+	if (result == ISC_R_SUCCESS) {
+		unixresult = getrlimit(unixresource, &rl);
+		INSIST(unixresult == 0);
+		*value = rl.rlim_max;
+	}
+
+	return (result);
+}
+
+isc_result_t
+isc_resource_getcurlimit(isc_resource_t resource, isc_resourcevalue_t *value) {
+	int unixresult;
+	int unixresource;
+	struct rlimit rl;
+	isc_result_t result;
+
+	result = resource2rlim(resource, &unixresource);
+	if (result == ISC_R_SUCCESS) {
+		unixresult = getrlimit(unixresource, &rl);
+		INSIST(unixresult == 0);
+		*value = rl.rlim_cur;
+	}
+
+	return (result);
+}
diff --git a/src/lib/bind9/unix/socket.c b/src/lib/bind9/unix/socket.c
new file mode 100644
index 0000000..aabe352
--- /dev/null
+++ b/src/lib/bind9/unix/socket.c
@@ -0,0 +1,5902 @@
+/*
+ * Copyright (C) 2004-2011  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: socket.c,v 1.333.14.5 2011-03-11 06:47:08 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/uio.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <isc/buffer.h>
+#include <isc/bufferlist.h>
+#include <isc/condition.h>
+#include <isc/formatcheck.h>
+#include <isc/list.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/msgs.h>
+#include <isc/mutex.h>
+#include <isc/net.h>
+#include <isc/once.h>
+#include <isc/platform.h>
+#include <isc/print.h>
+#include <isc/region.h>
+#include <isc/socket.h>
+#include <isc/stats.h>
+#include <isc/strerror.h>
+#include <isc/task.h>
+#include <isc/thread.h>
+#include <isc/util.h>
+#include <isc/xml.h>
+
+#ifdef ISC_PLATFORM_HAVESYSUNH
+#include <sys/un.h>
+#endif
+#ifdef ISC_PLATFORM_HAVEKQUEUE
+#include <sys/event.h>
+#endif
+#ifdef ISC_PLATFORM_HAVEEPOLL
+#include <sys/epoll.h>
+#endif
+#ifdef ISC_PLATFORM_HAVEDEVPOLL
+#if defined(HAVE_SYS_DEVPOLL_H)
+#include <sys/devpoll.h>
+#elif defined(HAVE_DEVPOLL_H)
+#include <devpoll.h>
+#endif
+#endif
+
+#include "errno2result.h"
+
+/* See task.c about the following definition: */
+#ifdef BIND9
+#ifdef ISC_PLATFORM_USETHREADS
+#define USE_WATCHER_THREAD
+#else
+#define USE_SHARED_MANAGER
+#endif	/* ISC_PLATFORM_USETHREADS */
+#endif	/* BIND9 */
+
+#ifndef USE_WATCHER_THREAD
+#include "socket_p.h"
+#include "../task_p.h"
+#endif /* USE_WATCHER_THREAD */
+
+#if defined(SO_BSDCOMPAT) && defined(__linux__)
+#include <sys/utsname.h>
+#endif
+
+/*%
+ * Choose the most preferable multiplex method.
+ */
+#ifdef ISC_PLATFORM_HAVEKQUEUE
+#define USE_KQUEUE
+#elif defined (ISC_PLATFORM_HAVEEPOLL)
+#define USE_EPOLL
+#elif defined (ISC_PLATFORM_HAVEDEVPOLL)
+#define USE_DEVPOLL
+typedef struct {
+	unsigned int want_read : 1,
+		want_write : 1;
+} pollinfo_t;
+#else
+#define USE_SELECT
+#endif	/* ISC_PLATFORM_HAVEKQUEUE */
+
+#ifndef USE_WATCHER_THREAD
+#if defined(USE_KQUEUE) || defined(USE_EPOLL) || defined(USE_DEVPOLL)
+struct isc_socketwait {
+	int nevents;
+};
+#elif defined (USE_SELECT)
+struct isc_socketwait {
+	fd_set *readset;
+	fd_set *writeset;
+	int nfds;
+	int maxfd;
+};
+#endif	/* USE_KQUEUE */
+#endif /* !USE_WATCHER_THREAD */
+
+/*%
+ * Maximum number of allowable open sockets.  This is also the maximum
+ * allowable socket file descriptor.
+ *
+ * Care should be taken before modifying this value for select():
+ * The API standard doesn't ensure select() accept more than (the system default
+ * of) FD_SETSIZE descriptors, and the default size should in fact be fine in
+ * the vast majority of cases.  This constant should therefore be increased only
+ * when absolutely necessary and possible, i.e., the server is exhausting all
+ * available file descriptors (up to FD_SETSIZE) and the select() function
+ * and FD_xxx macros support larger values than FD_SETSIZE (which may not
+ * always by true, but we keep using some of them to ensure as much
+ * portability as possible).  Note also that overall server performance
+ * may be rather worsened with a larger value of this constant due to
+ * inherent scalability problems of select().
+ *
+ * As a special note, this value shouldn't have to be touched if
+ * this is a build for an authoritative only DNS server.
+ */
+#ifndef ISC_SOCKET_MAXSOCKETS
+#if defined(USE_KQUEUE) || defined(USE_EPOLL) || defined(USE_DEVPOLL)
+#define ISC_SOCKET_MAXSOCKETS 4096
+#elif defined(USE_SELECT)
+#define ISC_SOCKET_MAXSOCKETS FD_SETSIZE
+#endif	/* USE_KQUEUE... */
+#endif	/* ISC_SOCKET_MAXSOCKETS */
+
+#ifdef USE_SELECT
+/*%
+ * Mac OS X needs a special definition to support larger values in select().
+ * We always define this because a larger value can be specified run-time.
+ */
+#ifdef __APPLE__
+#define _DARWIN_UNLIMITED_SELECT
+#endif	/* __APPLE__ */
+#endif	/* USE_SELECT */
+
+#ifdef ISC_SOCKET_USE_POLLWATCH
+/*%
+ * If this macro is defined, enable workaround for a Solaris /dev/poll kernel
+ * bug: DP_POLL ioctl could keep sleeping even if socket I/O is possible for
+ * some of the specified FD.  The idea is based on the observation that it's
+ * likely for a busy server to keep receiving packets.  It specifically works
+ * as follows: the socket watcher is first initialized with the state of
+ * "poll_idle".  While it's in the idle state it keeps sleeping until a socket
+ * event occurs.  When it wakes up for a socket I/O event, it moves to the
+ * poll_active state, and sets the poll timeout to a short period
+ * (ISC_SOCKET_POLLWATCH_TIMEOUT msec).  If timeout occurs in this state, the
+ * watcher goes to the poll_checking state with the same timeout period.
+ * In this state, the watcher tries to detect whether this is a break
+ * during intermittent events or the kernel bug is triggered.  If the next
+ * polling reports an event within the short period, the previous timeout is
+ * likely to be a kernel bug, and so the watcher goes back to the active state.
+ * Otherwise, it moves to the idle state again.
+ *
+ * It's not clear whether this is a thread-related bug, but since we've only
+ * seen this with threads, this workaround is used only when enabling threads.
+ */
+
+typedef enum { poll_idle, poll_active, poll_checking } pollstate_t;
+
+#ifndef ISC_SOCKET_POLLWATCH_TIMEOUT
+#define ISC_SOCKET_POLLWATCH_TIMEOUT 10
+#endif	/* ISC_SOCKET_POLLWATCH_TIMEOUT */
+#endif	/* ISC_SOCKET_USE_POLLWATCH */
+
+/*%
+ * Size of per-FD lock buckets.
+ */
+#ifdef ISC_PLATFORM_USETHREADS
+#define FDLOCK_COUNT		1024
+#define FDLOCK_ID(fd)		((fd) % FDLOCK_COUNT)
+#else
+#define FDLOCK_COUNT		1
+#define FDLOCK_ID(fd)		0
+#endif	/* ISC_PLATFORM_USETHREADS */
+
+/*%
+ * Maximum number of events communicated with the kernel.  There should normally
+ * be no need for having a large number.
+ */
+#if defined(USE_KQUEUE) || defined(USE_EPOLL) || defined(USE_DEVPOLL)
+#ifndef ISC_SOCKET_MAXEVENTS
+#define ISC_SOCKET_MAXEVENTS	64
+#endif
+#endif
+
+/*%
+ * Some systems define the socket length argument as an int, some as size_t,
+ * some as socklen_t.  This is here so it can be easily changed if needed.
+ */
+#ifndef ISC_SOCKADDR_LEN_T
+#define ISC_SOCKADDR_LEN_T unsigned int
+#endif
+
+/*%
+ * Define what the possible "soft" errors can be.  These are non-fatal returns
+ * of various network related functions, like recv() and so on.
+ *
+ * For some reason, BSDI (and perhaps others) will sometimes return <0
+ * from recv() but will have errno==0.  This is broken, but we have to
+ * work around it here.
+ */
+#define SOFT_ERROR(e)	((e) == EAGAIN || \
+			 (e) == EWOULDBLOCK || \
+			 (e) == EINTR || \
+			 (e) == 0)
+
+#define DLVL(x) ISC_LOGCATEGORY_GENERAL, ISC_LOGMODULE_SOCKET, ISC_LOG_DEBUG(x)
+
+/*!<
+ * DLVL(90)  --  Function entry/exit and other tracing.
+ * DLVL(70)  --  Socket "correctness" -- including returning of events, etc.
+ * DLVL(60)  --  Socket data send/receive
+ * DLVL(50)  --  Event tracing, including receiving/sending completion events.
+ * DLVL(20)  --  Socket creation/destruction.
+ */
+#define TRACE_LEVEL		90
+#define CORRECTNESS_LEVEL	70
+#define IOEVENT_LEVEL		60
+#define EVENT_LEVEL		50
+#define CREATION_LEVEL		20
+
+#define TRACE		DLVL(TRACE_LEVEL)
+#define CORRECTNESS	DLVL(CORRECTNESS_LEVEL)
+#define IOEVENT		DLVL(IOEVENT_LEVEL)
+#define EVENT		DLVL(EVENT_LEVEL)
+#define CREATION	DLVL(CREATION_LEVEL)
+
+typedef isc_event_t intev_t;
+
+#define SOCKET_MAGIC		ISC_MAGIC('I', 'O', 'i', 'o')
+#define VALID_SOCKET(s)		ISC_MAGIC_VALID(s, SOCKET_MAGIC)
+
+/*!
+ * IPv6 control information.  If the socket is an IPv6 socket we want
+ * to collect the destination address and interface so the client can
+ * set them on outgoing packets.
+ */
+#ifdef ISC_PLATFORM_HAVEIN6PKTINFO
+#ifndef USE_CMSG
+#define USE_CMSG	1
+#endif
+#endif
+
+/*%
+ * NetBSD and FreeBSD can timestamp packets.  XXXMLG Should we have
+ * a setsockopt() like interface to request timestamps, and if the OS
+ * doesn't do it for us, call gettimeofday() on every UDP receive?
+ */
+#ifdef SO_TIMESTAMP
+#ifndef USE_CMSG
+#define USE_CMSG	1
+#endif
+#endif
+
+/*%
+ * The size to raise the receive buffer to (from BIND 8).
+ */
+#define RCVBUFSIZE (32*1024)
+
+/*%
+ * The number of times a send operation is repeated if the result is EINTR.
+ */
+#define NRETRIES 10
+
+typedef struct isc__socket isc__socket_t;
+typedef struct isc__socketmgr isc__socketmgr_t;
+
+#define NEWCONNSOCK(ev) ((isc__socket_t *)(ev)->newsocket)
+
+struct isc__socket {
+	/* Not locked. */
+	isc_socket_t		common;
+	isc__socketmgr_t	*manager;
+	isc_mutex_t		lock;
+	isc_sockettype_t	type;
+	const isc_statscounter_t	*statsindex;
+
+	/* Locked by socket lock. */
+	ISC_LINK(isc__socket_t)	link;
+	unsigned int		references;
+	int			fd;
+	int			pf;
+	char				name[16];
+	void *				tag;
+
+	ISC_LIST(isc_socketevent_t)		send_list;
+	ISC_LIST(isc_socketevent_t)		recv_list;
+	ISC_LIST(isc_socket_newconnev_t)	accept_list;
+	isc_socket_connev_t		       *connect_ev;
+
+	/*
+	 * Internal events.  Posted when a descriptor is readable or
+	 * writable.  These are statically allocated and never freed.
+	 * They will be set to non-purgable before use.
+	 */
+	intev_t			readable_ev;
+	intev_t			writable_ev;
+
+	isc_sockaddr_t		peer_address;  /* remote address */
+
+	unsigned int		pending_recv : 1,
+				pending_send : 1,
+				pending_accept : 1,
+				listener : 1, /* listener socket */
+				connected : 1,
+				connecting : 1, /* connect pending */
+				bound : 1; /* bound to local addr */
+
+#ifdef ISC_NET_RECVOVERFLOW
+	unsigned char		overflow; /* used for MSG_TRUNC fake */
+#endif
+
+	char			*recvcmsgbuf;
+	ISC_SOCKADDR_LEN_T	recvcmsgbuflen;
+	char			*sendcmsgbuf;
+	ISC_SOCKADDR_LEN_T	sendcmsgbuflen;
+
+	void			*fdwatcharg;
+	isc_sockfdwatch_t	fdwatchcb;
+	int			fdwatchflags;
+	isc_task_t		*fdwatchtask;
+};
+
+#define SOCKET_MANAGER_MAGIC	ISC_MAGIC('I', 'O', 'm', 'g')
+#define VALID_MANAGER(m)	ISC_MAGIC_VALID(m, SOCKET_MANAGER_MAGIC)
+
+struct isc__socketmgr {
+	/* Not locked. */
+	isc_socketmgr_t		common;
+	isc_mem_t	       *mctx;
+	isc_mutex_t		lock;
+	isc_mutex_t		*fdlock;
+	isc_stats_t		*stats;
+#ifdef USE_KQUEUE
+	int			kqueue_fd;
+	int			nevents;
+	struct kevent		*events;
+#endif	/* USE_KQUEUE */
+#ifdef USE_EPOLL
+	int			epoll_fd;
+	int			nevents;
+	struct epoll_event	*events;
+#endif	/* USE_EPOLL */
+#ifdef USE_DEVPOLL
+	int			devpoll_fd;
+	int			nevents;
+	struct pollfd		*events;
+#endif	/* USE_DEVPOLL */
+#ifdef USE_SELECT
+	int			fd_bufsize;
+#endif	/* USE_SELECT */
+	unsigned int		maxsocks;
+#ifdef ISC_PLATFORM_USETHREADS
+	int			pipe_fds[2];
+#endif
+
+	/* Locked by fdlock. */
+	isc__socket_t	       **fds;
+	int			*fdstate;
+#ifdef USE_DEVPOLL
+	pollinfo_t		*fdpollinfo;
+#endif
+
+	/* Locked by manager lock. */
+	ISC_LIST(isc__socket_t)	socklist;
+#ifdef USE_SELECT
+	fd_set			*read_fds;
+	fd_set			*read_fds_copy;
+	fd_set			*write_fds;
+	fd_set			*write_fds_copy;
+	int			maxfd;
+#endif	/* USE_SELECT */
+	int			reserved;	/* unlocked */
+#ifdef USE_WATCHER_THREAD
+	isc_thread_t		watcher;
+	isc_condition_t		shutdown_ok;
+#else /* USE_WATCHER_THREAD */
+	unsigned int		refs;
+#endif /* USE_WATCHER_THREAD */
+	int			maxudp;
+};
+
+#ifdef USE_SHARED_MANAGER
+static isc__socketmgr_t *socketmgr = NULL;
+#endif /* USE_SHARED_MANAGER */
+
+#define CLOSED			0	/* this one must be zero */
+#define MANAGED			1
+#define CLOSE_PENDING		2
+
+/*
+ * send() and recv() iovec counts
+ */
+#define MAXSCATTERGATHER_SEND	(ISC_SOCKET_MAXSCATTERGATHER)
+#ifdef ISC_NET_RECVOVERFLOW
+# define MAXSCATTERGATHER_RECV	(ISC_SOCKET_MAXSCATTERGATHER + 1)
+#else
+# define MAXSCATTERGATHER_RECV	(ISC_SOCKET_MAXSCATTERGATHER)
+#endif
+
+static void send_recvdone_event(isc__socket_t *, isc_socketevent_t **);
+static void send_senddone_event(isc__socket_t *, isc_socketevent_t **);
+static void free_socket(isc__socket_t **);
+static isc_result_t allocate_socket(isc__socketmgr_t *, isc_sockettype_t,
+				    isc__socket_t **);
+static void destroy(isc__socket_t **);
+static void internal_accept(isc_task_t *, isc_event_t *);
+static void internal_connect(isc_task_t *, isc_event_t *);
+static void internal_recv(isc_task_t *, isc_event_t *);
+static void internal_send(isc_task_t *, isc_event_t *);
+static void internal_fdwatch_write(isc_task_t *, isc_event_t *);
+static void internal_fdwatch_read(isc_task_t *, isc_event_t *);
+static void process_cmsg(isc__socket_t *, struct msghdr *, isc_socketevent_t *);
+static void build_msghdr_send(isc__socket_t *, isc_socketevent_t *,
+			      struct msghdr *, struct iovec *, size_t *);
+static void build_msghdr_recv(isc__socket_t *, isc_socketevent_t *,
+			      struct msghdr *, struct iovec *, size_t *);
+#ifdef USE_WATCHER_THREAD
+static isc_boolean_t process_ctlfd(isc__socketmgr_t *manager);
+#endif
+
+/*%
+ * The following can be either static or public, depending on build environment.
+ */
+
+#ifdef BIND9
+#define ISC_SOCKETFUNC_SCOPE
+#else
+#define ISC_SOCKETFUNC_SCOPE static
+#endif
+
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
+		   isc_socket_t **socketp);
+ISC_SOCKETFUNC_SCOPE void
+isc__socket_attach(isc_socket_t *sock, isc_socket_t **socketp);
+ISC_SOCKETFUNC_SCOPE void
+isc__socket_detach(isc_socket_t **socketp);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
+		       unsigned int maxsocks);
+ISC_SOCKETFUNC_SCOPE void
+isc__socketmgr_destroy(isc_socketmgr_t **managerp);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_recvv(isc_socket_t *sock, isc_bufferlist_t *buflist,
+		 unsigned int minimum, isc_task_t *task,
+		  isc_taskaction_t action, const void *arg);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_recv(isc_socket_t *sock, isc_region_t *region,
+		 unsigned int minimum, isc_task_t *task,
+		 isc_taskaction_t action, const void *arg);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_recv2(isc_socket_t *sock, isc_region_t *region,
+		  unsigned int minimum, isc_task_t *task,
+		  isc_socketevent_t *event, unsigned int flags);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_send(isc_socket_t *sock, isc_region_t *region,
+		 isc_task_t *task, isc_taskaction_t action, const void *arg);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_sendto(isc_socket_t *sock, isc_region_t *region,
+		   isc_task_t *task, isc_taskaction_t action, const void *arg,
+		   isc_sockaddr_t *address, struct in6_pktinfo *pktinfo);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_sendv(isc_socket_t *sock, isc_bufferlist_t *buflist,
+		  isc_task_t *task, isc_taskaction_t action, const void *arg);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist,
+		    isc_task_t *task, isc_taskaction_t action, const void *arg,
+		    isc_sockaddr_t *address, struct in6_pktinfo *pktinfo);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_sendto2(isc_socket_t *sock, isc_region_t *region,
+		    isc_task_t *task,
+		    isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
+		    isc_socketevent_t *event, unsigned int flags);
+ISC_SOCKETFUNC_SCOPE void
+isc__socket_cleanunix(isc_sockaddr_t *sockaddr, isc_boolean_t active);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_permunix(isc_sockaddr_t *sockaddr, isc_uint32_t perm,
+		     isc_uint32_t owner, isc_uint32_t group);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr,
+		 unsigned int options);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_filter(isc_socket_t *sock, const char *filter);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_listen(isc_socket_t *sock, unsigned int backlog);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_accept(isc_socket_t *sock,
+		   isc_task_t *task, isc_taskaction_t action, const void *arg);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr,
+		    isc_task_t *task, isc_taskaction_t action,
+		    const void *arg);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_getpeername(isc_socket_t *sock, isc_sockaddr_t *addressp);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp);
+ISC_SOCKETFUNC_SCOPE void
+isc__socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how);
+ISC_SOCKETFUNC_SCOPE isc_sockettype_t
+isc__socket_gettype(isc_socket_t *sock);
+ISC_SOCKETFUNC_SCOPE isc_boolean_t
+isc__socket_isbound(isc_socket_t *sock);
+ISC_SOCKETFUNC_SCOPE void
+isc__socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes);
+#if defined(HAVE_LIBXML2) && defined(BIND9)
+ISC_SOCKETFUNC_SCOPE void
+isc__socketmgr_renderxml(isc_socketmgr_t *mgr0, xmlTextWriterPtr writer);
+#endif
+
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_fdwatchcreate(isc_socketmgr_t *manager, int fd, int flags,
+			  isc_sockfdwatch_t callback, void *cbarg,
+			  isc_task_t *task, isc_socket_t **socketp);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_fdwatchpoke(isc_socket_t *sock, int flags);
+
+static struct {
+	isc_socketmethods_t methods;
+
+	/*%
+	 * The following are defined just for avoiding unused static functions.
+	 */
+#ifndef BIND9
+	void *recvv, *send, *sendv, *sendto2, *cleanunix, *permunix, *filter,
+		*listen, *accept, *getpeername, *isbound;
+#endif
+} socketmethods = {
+	{
+		isc__socket_attach,
+		isc__socket_detach,
+		isc__socket_bind,
+		isc__socket_sendto,
+		isc__socket_connect,
+		isc__socket_recv,
+		isc__socket_cancel,
+		isc__socket_getsockname,
+		isc__socket_gettype,
+		isc__socket_ipv6only,
+		isc__socket_fdwatchpoke
+	}
+#ifndef BIND9
+	,
+	(void *)isc__socket_recvv, (void *)isc__socket_send,
+	(void *)isc__socket_sendv, (void *)isc__socket_sendto2,
+	(void *)isc__socket_cleanunix, (void *)isc__socket_permunix,
+	(void *)isc__socket_filter, (void *)isc__socket_listen,
+	(void *)isc__socket_accept, (void *)isc__socket_getpeername,
+	(void *)isc__socket_isbound
+#endif
+};
+
+static isc_socketmgrmethods_t socketmgrmethods = {
+	isc__socketmgr_destroy,
+	isc__socket_create,
+	isc__socket_fdwatchcreate
+};
+
+#define SELECT_POKE_SHUTDOWN		(-1)
+#define SELECT_POKE_NOTHING		(-2)
+#define SELECT_POKE_READ		(-3)
+#define SELECT_POKE_ACCEPT		(-3) /*%< Same as _READ */
+#define SELECT_POKE_WRITE		(-4)
+#define SELECT_POKE_CONNECT		(-4) /*%< Same as _WRITE */
+#define SELECT_POKE_CLOSE		(-5)
+
+#define SOCK_DEAD(s)			((s)->references == 0)
+
+/*%
+ * Shortcut index arrays to get access to statistics counters.
+ */
+enum {
+	STATID_OPEN = 0,
+	STATID_OPENFAIL = 1,
+	STATID_CLOSE = 2,
+	STATID_BINDFAIL = 3,
+	STATID_CONNECTFAIL = 4,
+	STATID_CONNECT = 5,
+	STATID_ACCEPTFAIL = 6,
+	STATID_ACCEPT = 7,
+	STATID_SENDFAIL = 8,
+	STATID_RECVFAIL = 9
+};
+static const isc_statscounter_t upd4statsindex[] = {
+	isc_sockstatscounter_udp4open,
+	isc_sockstatscounter_udp4openfail,
+	isc_sockstatscounter_udp4close,
+	isc_sockstatscounter_udp4bindfail,
+	isc_sockstatscounter_udp4connectfail,
+	isc_sockstatscounter_udp4connect,
+	-1,
+	-1,
+	isc_sockstatscounter_udp4sendfail,
+	isc_sockstatscounter_udp4recvfail
+};
+static const isc_statscounter_t upd6statsindex[] = {
+	isc_sockstatscounter_udp6open,
+	isc_sockstatscounter_udp6openfail,
+	isc_sockstatscounter_udp6close,
+	isc_sockstatscounter_udp6bindfail,
+	isc_sockstatscounter_udp6connectfail,
+	isc_sockstatscounter_udp6connect,
+	-1,
+	-1,
+	isc_sockstatscounter_udp6sendfail,
+	isc_sockstatscounter_udp6recvfail
+};
+static const isc_statscounter_t tcp4statsindex[] = {
+	isc_sockstatscounter_tcp4open,
+	isc_sockstatscounter_tcp4openfail,
+	isc_sockstatscounter_tcp4close,
+	isc_sockstatscounter_tcp4bindfail,
+	isc_sockstatscounter_tcp4connectfail,
+	isc_sockstatscounter_tcp4connect,
+	isc_sockstatscounter_tcp4acceptfail,
+	isc_sockstatscounter_tcp4accept,
+	isc_sockstatscounter_tcp4sendfail,
+	isc_sockstatscounter_tcp4recvfail
+};
+static const isc_statscounter_t tcp6statsindex[] = {
+	isc_sockstatscounter_tcp6open,
+	isc_sockstatscounter_tcp6openfail,
+	isc_sockstatscounter_tcp6close,
+	isc_sockstatscounter_tcp6bindfail,
+	isc_sockstatscounter_tcp6connectfail,
+	isc_sockstatscounter_tcp6connect,
+	isc_sockstatscounter_tcp6acceptfail,
+	isc_sockstatscounter_tcp6accept,
+	isc_sockstatscounter_tcp6sendfail,
+	isc_sockstatscounter_tcp6recvfail
+};
+static const isc_statscounter_t unixstatsindex[] = {
+	isc_sockstatscounter_unixopen,
+	isc_sockstatscounter_unixopenfail,
+	isc_sockstatscounter_unixclose,
+	isc_sockstatscounter_unixbindfail,
+	isc_sockstatscounter_unixconnectfail,
+	isc_sockstatscounter_unixconnect,
+	isc_sockstatscounter_unixacceptfail,
+	isc_sockstatscounter_unixaccept,
+	isc_sockstatscounter_unixsendfail,
+	isc_sockstatscounter_unixrecvfail
+};
+static const isc_statscounter_t fdwatchstatsindex[] = {
+	-1,
+	-1,
+	isc_sockstatscounter_fdwatchclose,
+	isc_sockstatscounter_fdwatchbindfail,
+	isc_sockstatscounter_fdwatchconnectfail,
+	isc_sockstatscounter_fdwatchconnect,
+	-1,
+	-1,
+	isc_sockstatscounter_fdwatchsendfail,
+	isc_sockstatscounter_fdwatchrecvfail
+};
+
+#if defined(USE_KQUEUE) || defined(USE_EPOLL) || defined(USE_DEVPOLL) || \
+    defined(USE_WATCHER_THREAD)
+static void
+manager_log(isc__socketmgr_t *sockmgr,
+	    isc_logcategory_t *category, isc_logmodule_t *module, int level,
+	    const char *fmt, ...) ISC_FORMAT_PRINTF(5, 6);
+static void
+manager_log(isc__socketmgr_t *sockmgr,
+	    isc_logcategory_t *category, isc_logmodule_t *module, int level,
+	    const char *fmt, ...)
+{
+	char msgbuf[2048];
+	va_list ap;
+
+	if (! isc_log_wouldlog(isc_lctx, level))
+		return;
+
+	va_start(ap, fmt);
+	vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
+	va_end(ap);
+
+	isc_log_write(isc_lctx, category, module, level,
+		      "sockmgr %p: %s", sockmgr, msgbuf);
+}
+#endif
+
+static void
+socket_log(isc__socket_t *sock, isc_sockaddr_t *address,
+	   isc_logcategory_t *category, isc_logmodule_t *module, int level,
+	   isc_msgcat_t *msgcat, int msgset, int message,
+	   const char *fmt, ...) ISC_FORMAT_PRINTF(9, 10);
+static void
+socket_log(isc__socket_t *sock, isc_sockaddr_t *address,
+	   isc_logcategory_t *category, isc_logmodule_t *module, int level,
+	   isc_msgcat_t *msgcat, int msgset, int message,
+	   const char *fmt, ...)
+{
+	char msgbuf[2048];
+	char peerbuf[ISC_SOCKADDR_FORMATSIZE];
+	va_list ap;
+
+	if (! isc_log_wouldlog(isc_lctx, level))
+		return;
+
+	va_start(ap, fmt);
+	vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
+	va_end(ap);
+
+	if (address == NULL) {
+		isc_log_iwrite(isc_lctx, category, module, level,
+			       msgcat, msgset, message,
+			       "socket %p: %s", sock, msgbuf);
+	} else {
+		isc_sockaddr_format(address, peerbuf, sizeof(peerbuf));
+		isc_log_iwrite(isc_lctx, category, module, level,
+			       msgcat, msgset, message,
+			       "socket %p %s: %s", sock, peerbuf, msgbuf);
+	}
+}
+
+#if defined(_AIX) && defined(ISC_NET_BSD44MSGHDR) && \
+    defined(USE_CMSG) && defined(IPV6_RECVPKTINFO)
+/*
+ * AIX has a kernel bug where IPV6_RECVPKTINFO gets cleared by
+ * setting IPV6_V6ONLY.
+ */
+static void
+FIX_IPV6_RECVPKTINFO(isc__socket_t *sock)
+{
+	char strbuf[ISC_STRERRORSIZE];
+	int on = 1;
+
+	if (sock->pf != AF_INET6 || sock->type != isc_sockettype_udp)
+		return;
+
+	if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_RECVPKTINFO,
+		       (void *)&on, sizeof(on)) < 0) {
+
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "setsockopt(%d, IPV6_RECVPKTINFO) "
+				 "%s: %s", sock->fd,
+				 isc_msgcat_get(isc_msgcat,
+						ISC_MSGSET_GENERAL,
+						ISC_MSG_FAILED,
+						"failed"),
+				 strbuf);
+	}
+}
+#else
+#define FIX_IPV6_RECVPKTINFO(sock) (void)0
+#endif
+
+/*%
+ * Increment socket-related statistics counters.
+ */
+static inline void
+inc_stats(isc_stats_t *stats, isc_statscounter_t counterid) {
+	REQUIRE(counterid != -1);
+
+	if (stats != NULL)
+		isc_stats_increment(stats, counterid);
+}
+
+static inline isc_result_t
+watch_fd(isc__socketmgr_t *manager, int fd, int msg) {
+	isc_result_t result = ISC_R_SUCCESS;
+
+#ifdef USE_KQUEUE
+	struct kevent evchange;
+
+	memset(&evchange, 0, sizeof(evchange));
+	if (msg == SELECT_POKE_READ)
+		evchange.filter = EVFILT_READ;
+	else
+		evchange.filter = EVFILT_WRITE;
+	evchange.flags = EV_ADD;
+	evchange.ident = fd;
+	if (kevent(manager->kqueue_fd, &evchange, 1, NULL, 0, NULL) != 0)
+		result = isc__errno2result(errno);
+
+	return (result);
+#elif defined(USE_EPOLL)
+	struct epoll_event event;
+
+	if (msg == SELECT_POKE_READ)
+		event.events = EPOLLIN;
+	else
+		event.events = EPOLLOUT;
+	memset(&event.data, 0, sizeof(event.data));
+	event.data.fd = fd;
+	if (epoll_ctl(manager->epoll_fd, EPOLL_CTL_ADD, fd, &event) == -1 &&
+	    errno != EEXIST) {
+		result = isc__errno2result(errno);
+	}
+
+	return (result);
+#elif defined(USE_DEVPOLL)
+	struct pollfd pfd;
+	int lockid = FDLOCK_ID(fd);
+
+	memset(&pfd, 0, sizeof(pfd));
+	if (msg == SELECT_POKE_READ)
+		pfd.events = POLLIN;
+	else
+		pfd.events = POLLOUT;
+	pfd.fd = fd;
+	pfd.revents = 0;
+	LOCK(&manager->fdlock[lockid]);
+	if (write(manager->devpoll_fd, &pfd, sizeof(pfd)) == -1)
+		result = isc__errno2result(errno);
+	else {
+		if (msg == SELECT_POKE_READ)
+			manager->fdpollinfo[fd].want_read = 1;
+		else
+			manager->fdpollinfo[fd].want_write = 1;
+	}
+	UNLOCK(&manager->fdlock[lockid]);
+
+	return (result);
+#elif defined(USE_SELECT)
+	LOCK(&manager->lock);
+	if (msg == SELECT_POKE_READ)
+		FD_SET(fd, manager->read_fds);
+	if (msg == SELECT_POKE_WRITE)
+		FD_SET(fd, manager->write_fds);
+	UNLOCK(&manager->lock);
+
+	return (result);
+#endif
+}
+
+static inline isc_result_t
+unwatch_fd(isc__socketmgr_t *manager, int fd, int msg) {
+	isc_result_t result = ISC_R_SUCCESS;
+
+#ifdef USE_KQUEUE
+	struct kevent evchange;
+
+	memset(&evchange, 0, sizeof(evchange));
+	if (msg == SELECT_POKE_READ)
+		evchange.filter = EVFILT_READ;
+	else
+		evchange.filter = EVFILT_WRITE;
+	evchange.flags = EV_DELETE;
+	evchange.ident = fd;
+	if (kevent(manager->kqueue_fd, &evchange, 1, NULL, 0, NULL) != 0)
+		result = isc__errno2result(errno);
+
+	return (result);
+#elif defined(USE_EPOLL)
+	struct epoll_event event;
+
+	if (msg == SELECT_POKE_READ)
+		event.events = EPOLLIN;
+	else
+		event.events = EPOLLOUT;
+	memset(&event.data, 0, sizeof(event.data));
+	event.data.fd = fd;
+	if (epoll_ctl(manager->epoll_fd, EPOLL_CTL_DEL, fd, &event) == -1 &&
+	    errno != ENOENT) {
+		char strbuf[ISC_STRERRORSIZE];
+		isc__strerror(errno, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "epoll_ctl(DEL), %d: %s", fd, strbuf);
+		result = ISC_R_UNEXPECTED;
+	}
+	return (result);
+#elif defined(USE_DEVPOLL)
+	struct pollfd pfds[2];
+	size_t writelen = sizeof(pfds[0]);
+	int lockid = FDLOCK_ID(fd);
+
+	memset(pfds, 0, sizeof(pfds));
+	pfds[0].events = POLLREMOVE;
+	pfds[0].fd = fd;
+
+	/*
+	 * Canceling read or write polling via /dev/poll is tricky.  Since it
+	 * only provides a way of canceling per FD, we may need to re-poll the
+	 * socket for the other operation.
+	 */
+	LOCK(&manager->fdlock[lockid]);
+	if (msg == SELECT_POKE_READ &&
+	    manager->fdpollinfo[fd].want_write == 1) {
+		pfds[1].events = POLLOUT;
+		pfds[1].fd = fd;
+		writelen += sizeof(pfds[1]);
+	}
+	if (msg == SELECT_POKE_WRITE &&
+	    manager->fdpollinfo[fd].want_read == 1) {
+		pfds[1].events = POLLIN;
+		pfds[1].fd = fd;
+		writelen += sizeof(pfds[1]);
+	}
+
+	if (write(manager->devpoll_fd, pfds, writelen) == -1)
+		result = isc__errno2result(errno);
+	else {
+		if (msg == SELECT_POKE_READ)
+			manager->fdpollinfo[fd].want_read = 0;
+		else
+			manager->fdpollinfo[fd].want_write = 0;
+	}
+	UNLOCK(&manager->fdlock[lockid]);
+
+	return (result);
+#elif defined(USE_SELECT)
+	LOCK(&manager->lock);
+	if (msg == SELECT_POKE_READ)
+		FD_CLR(fd, manager->read_fds);
+	else if (msg == SELECT_POKE_WRITE)
+		FD_CLR(fd, manager->write_fds);
+	UNLOCK(&manager->lock);
+
+	return (result);
+#endif
+}
+
+static void
+wakeup_socket(isc__socketmgr_t *manager, int fd, int msg) {
+	isc_result_t result;
+	int lockid = FDLOCK_ID(fd);
+
+	/*
+	 * This is a wakeup on a socket.  If the socket is not in the
+	 * process of being closed, start watching it for either reads
+	 * or writes.
+	 */
+
+	INSIST(fd >= 0 && fd < (int)manager->maxsocks);
+
+	if (msg == SELECT_POKE_CLOSE) {
+		/* No one should be updating fdstate, so no need to lock it */
+		INSIST(manager->fdstate[fd] == CLOSE_PENDING);
+		manager->fdstate[fd] = CLOSED;
+		(void)unwatch_fd(manager, fd, SELECT_POKE_READ);
+		(void)unwatch_fd(manager, fd, SELECT_POKE_WRITE);
+		(void)close(fd);
+		return;
+	}
+
+	LOCK(&manager->fdlock[lockid]);
+	if (manager->fdstate[fd] == CLOSE_PENDING) {
+		UNLOCK(&manager->fdlock[lockid]);
+
+		/*
+		 * We accept (and ignore) any error from unwatch_fd() as we are
+		 * closing the socket, hoping it doesn't leave dangling state in
+		 * the kernel.
+		 * Note that unwatch_fd() must be called after releasing the
+		 * fdlock; otherwise it could cause deadlock due to a lock order
+		 * reversal.
+		 */
+		(void)unwatch_fd(manager, fd, SELECT_POKE_READ);
+		(void)unwatch_fd(manager, fd, SELECT_POKE_WRITE);
+		return;
+	}
+	if (manager->fdstate[fd] != MANAGED) {
+		UNLOCK(&manager->fdlock[lockid]);
+		return;
+	}
+	UNLOCK(&manager->fdlock[lockid]);
+
+	/*
+	 * Set requested bit.
+	 */
+	result = watch_fd(manager, fd, msg);
+	if (result != ISC_R_SUCCESS) {
+		/*
+		 * XXXJT: what should we do?  Ignoring the failure of watching
+		 * a socket will make the application dysfunctional, but there
+		 * seems to be no reasonable recovery process.
+		 */
+		isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+			      ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
+			      "failed to start watching FD (%d): %s",
+			      fd, isc_result_totext(result));
+	}
+}
+
+#ifdef USE_WATCHER_THREAD
+/*
+ * Poke the select loop when there is something for us to do.
+ * The write is required (by POSIX) to complete.  That is, we
+ * will not get partial writes.
+ */
+static void
+select_poke(isc__socketmgr_t *mgr, int fd, int msg) {
+	int cc;
+	int buf[2];
+	char strbuf[ISC_STRERRORSIZE];
+
+	buf[0] = fd;
+	buf[1] = msg;
+
+	do {
+		cc = write(mgr->pipe_fds[1], buf, sizeof(buf));
+#ifdef ENOSR
+		/*
+		 * Treat ENOSR as EAGAIN but loop slowly as it is
+		 * unlikely to clear fast.
+		 */
+		if (cc < 0 && errno == ENOSR) {
+			sleep(1);
+			errno = EAGAIN;
+		}
+#endif
+	} while (cc < 0 && SOFT_ERROR(errno));
+
+	if (cc < 0) {
+		isc__strerror(errno, strbuf, sizeof(strbuf));
+		FATAL_ERROR(__FILE__, __LINE__,
+			    isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
+					   ISC_MSG_WRITEFAILED,
+					   "write() failed "
+					   "during watcher poke: %s"),
+			    strbuf);
+	}
+
+	INSIST(cc == sizeof(buf));
+}
+
+/*
+ * Read a message on the internal fd.
+ */
+static void
+select_readmsg(isc__socketmgr_t *mgr, int *fd, int *msg) {
+	int buf[2];
+	int cc;
+	char strbuf[ISC_STRERRORSIZE];
+
+	cc = read(mgr->pipe_fds[0], buf, sizeof(buf));
+	if (cc < 0) {
+		*msg = SELECT_POKE_NOTHING;
+		*fd = -1;	/* Silence compiler. */
+		if (SOFT_ERROR(errno))
+			return;
+
+		isc__strerror(errno, strbuf, sizeof(strbuf));
+		FATAL_ERROR(__FILE__, __LINE__,
+			    isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
+					   ISC_MSG_READFAILED,
+					   "read() failed "
+					   "during watcher poke: %s"),
+			    strbuf);
+
+		return;
+	}
+	INSIST(cc == sizeof(buf));
+
+	*fd = buf[0];
+	*msg = buf[1];
+}
+#else /* USE_WATCHER_THREAD */
+/*
+ * Update the state of the socketmgr when something changes.
+ */
+static void
+select_poke(isc__socketmgr_t *manager, int fd, int msg) {
+	if (msg == SELECT_POKE_SHUTDOWN)
+		return;
+	else if (fd >= 0)
+		wakeup_socket(manager, fd, msg);
+	return;
+}
+#endif /* USE_WATCHER_THREAD */
+
+/*
+ * Make a fd non-blocking.
+ */
+static isc_result_t
+make_nonblock(int fd) {
+	int ret;
+	int flags;
+	char strbuf[ISC_STRERRORSIZE];
+#ifdef USE_FIONBIO_IOCTL
+	int on = 1;
+
+	ret = ioctl(fd, FIONBIO, (char *)&on);
+#else
+	flags = fcntl(fd, F_GETFL, 0);
+	flags |= PORT_NONBLOCK;
+	ret = fcntl(fd, F_SETFL, flags);
+#endif
+
+	if (ret == -1) {
+		isc__strerror(errno, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+#ifdef USE_FIONBIO_IOCTL
+				 "ioctl(%d, FIONBIO, &on): %s", fd,
+#else
+				 "fcntl(%d, F_SETFL, %d): %s", fd, flags,
+#endif
+				 strbuf);
+
+		return (ISC_R_UNEXPECTED);
+	}
+
+	return (ISC_R_SUCCESS);
+}
+
+#ifdef USE_CMSG
+/*
+ * Not all OSes support advanced CMSG macros: CMSG_LEN and CMSG_SPACE.
+ * In order to ensure as much portability as possible, we provide wrapper
+ * functions of these macros.
+ * Note that cmsg_space() could run slow on OSes that do not have
+ * CMSG_SPACE.
+ */
+static inline ISC_SOCKADDR_LEN_T
+cmsg_len(ISC_SOCKADDR_LEN_T len) {
+#ifdef CMSG_LEN
+	return (CMSG_LEN(len));
+#else
+	ISC_SOCKADDR_LEN_T hdrlen;
+
+	/*
+	 * Cast NULL so that any pointer arithmetic performed by CMSG_DATA
+	 * is correct.
+	 */
+	hdrlen = (ISC_SOCKADDR_LEN_T)CMSG_DATA(((struct cmsghdr *)NULL));
+	return (hdrlen + len);
+#endif
+}
+
+static inline ISC_SOCKADDR_LEN_T
+cmsg_space(ISC_SOCKADDR_LEN_T len) {
+#ifdef CMSG_SPACE
+	return (CMSG_SPACE(len));
+#else
+	struct msghdr msg;
+	struct cmsghdr *cmsgp;
+	/*
+	 * XXX: The buffer length is an ad-hoc value, but should be enough
+	 * in a practical sense.
+	 */
+	char dummybuf[sizeof(struct cmsghdr) + 1024];
+
+	memset(&msg, 0, sizeof(msg));
+	msg.msg_control = dummybuf;
+	msg.msg_controllen = sizeof(dummybuf);
+
+	cmsgp = (struct cmsghdr *)dummybuf;
+	cmsgp->cmsg_len = cmsg_len(len);
+
+	cmsgp = CMSG_NXTHDR(&msg, cmsgp);
+	if (cmsgp != NULL)
+		return ((char *)cmsgp - (char *)msg.msg_control);
+	else
+		return (0);
+#endif
+}
+#endif /* USE_CMSG */
+
+/*
+ * Process control messages received on a socket.
+ */
+static void
+process_cmsg(isc__socket_t *sock, struct msghdr *msg, isc_socketevent_t *dev) {
+#ifdef USE_CMSG
+	struct cmsghdr *cmsgp;
+#ifdef ISC_PLATFORM_HAVEIN6PKTINFO
+	struct in6_pktinfo *pktinfop;
+#endif
+#ifdef SO_TIMESTAMP
+	struct timeval *timevalp;
+#endif
+#endif
+
+	/*
+	 * sock is used only when ISC_NET_BSD44MSGHDR and USE_CMSG are defined.
+	 * msg and dev are used only when ISC_NET_BSD44MSGHDR is defined.
+	 * They are all here, outside of the CPP tests, because it is
+	 * more consistent with the usual ISC coding style.
+	 */
+	UNUSED(sock);
+	UNUSED(msg);
+	UNUSED(dev);
+
+#ifdef ISC_NET_BSD44MSGHDR
+
+#ifdef MSG_TRUNC
+	if ((msg->msg_flags & MSG_TRUNC) == MSG_TRUNC)
+		dev->attributes |= ISC_SOCKEVENTATTR_TRUNC;
+#endif
+
+#ifdef MSG_CTRUNC
+	if ((msg->msg_flags & MSG_CTRUNC) == MSG_CTRUNC)
+		dev->attributes |= ISC_SOCKEVENTATTR_CTRUNC;
+#endif
+
+#ifndef USE_CMSG
+	return;
+#else
+	if (msg->msg_controllen == 0U || msg->msg_control == NULL)
+		return;
+
+#ifdef SO_TIMESTAMP
+	timevalp = NULL;
+#endif
+#ifdef ISC_PLATFORM_HAVEIN6PKTINFO
+	pktinfop = NULL;
+#endif
+
+	cmsgp = CMSG_FIRSTHDR(msg);
+	while (cmsgp != NULL) {
+		socket_log(sock, NULL, TRACE,
+			   isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_PROCESSCMSG,
+			   "processing cmsg %p", cmsgp);
+
+#ifdef ISC_PLATFORM_HAVEIN6PKTINFO
+		if (cmsgp->cmsg_level == IPPROTO_IPV6
+		    && cmsgp->cmsg_type == IPV6_PKTINFO) {
+
+			pktinfop = (struct in6_pktinfo *)CMSG_DATA(cmsgp);
+			memcpy(&dev->pktinfo, pktinfop,
+			       sizeof(struct in6_pktinfo));
+			dev->attributes |= ISC_SOCKEVENTATTR_PKTINFO;
+			socket_log(sock, NULL, TRACE,
+				   isc_msgcat, ISC_MSGSET_SOCKET,
+				   ISC_MSG_IFRECEIVED,
+				   "interface received on ifindex %u",
+				   dev->pktinfo.ipi6_ifindex);
+			if (IN6_IS_ADDR_MULTICAST(&pktinfop->ipi6_addr))
+				dev->attributes |= ISC_SOCKEVENTATTR_MULTICAST;
+			goto next;
+		}
+#endif
+
+#ifdef SO_TIMESTAMP
+		if (cmsgp->cmsg_level == SOL_SOCKET
+		    && cmsgp->cmsg_type == SCM_TIMESTAMP) {
+			timevalp = (struct timeval *)CMSG_DATA(cmsgp);
+			dev->timestamp.seconds = timevalp->tv_sec;
+			dev->timestamp.nanoseconds = timevalp->tv_usec * 1000;
+			dev->attributes |= ISC_SOCKEVENTATTR_TIMESTAMP;
+			goto next;
+		}
+#endif
+
+	next:
+		cmsgp = CMSG_NXTHDR(msg, cmsgp);
+	}
+#endif /* USE_CMSG */
+
+#endif /* ISC_NET_BSD44MSGHDR */
+}
+
+/*
+ * Construct an iov array and attach it to the msghdr passed in.  This is
+ * the SEND constructor, which will use the used region of the buffer
+ * (if using a buffer list) or will use the internal region (if a single
+ * buffer I/O is requested).
+ *
+ * Nothing can be NULL, and the done event must list at least one buffer
+ * on the buffer linked list for this function to be meaningful.
+ *
+ * If write_countp != NULL, *write_countp will hold the number of bytes
+ * this transaction can send.
+ */
+static void
+build_msghdr_send(isc__socket_t *sock, isc_socketevent_t *dev,
+		  struct msghdr *msg, struct iovec *iov, size_t *write_countp)
+{
+	unsigned int iovcount;
+	isc_buffer_t *buffer;
+	isc_region_t used;
+	size_t write_count;
+	size_t skip_count;
+
+	memset(msg, 0, sizeof(*msg));
+
+	if (!sock->connected) {
+		msg->msg_name = (void *)&dev->address.type.sa;
+		msg->msg_namelen = dev->address.length;
+	} else {
+		msg->msg_name = NULL;
+		msg->msg_namelen = 0;
+	}
+
+	buffer = ISC_LIST_HEAD(dev->bufferlist);
+	write_count = 0;
+	iovcount = 0;
+
+	/*
+	 * Single buffer I/O?  Skip what we've done so far in this region.
+	 */
+	if (buffer == NULL) {
+		write_count = dev->region.length - dev->n;
+		iov[0].iov_base = (void *)(dev->region.base + dev->n);
+		iov[0].iov_len = write_count;
+		iovcount = 1;
+
+		goto config;
+	}
+
+	/*
+	 * Multibuffer I/O.
+	 * Skip the data in the buffer list that we have already written.
+	 */
+	skip_count = dev->n;
+	while (buffer != NULL) {
+		REQUIRE(ISC_BUFFER_VALID(buffer));
+		if (skip_count < isc_buffer_usedlength(buffer))
+			break;
+		skip_count -= isc_buffer_usedlength(buffer);
+		buffer = ISC_LIST_NEXT(buffer, link);
+	}
+
+	while (buffer != NULL) {
+		INSIST(iovcount < MAXSCATTERGATHER_SEND);
+
+		isc_buffer_usedregion(buffer, &used);
+
+		if (used.length > 0) {
+			iov[iovcount].iov_base = (void *)(used.base
+							  + skip_count);
+			iov[iovcount].iov_len = used.length - skip_count;
+			write_count += (used.length - skip_count);
+			skip_count = 0;
+			iovcount++;
+		}
+		buffer = ISC_LIST_NEXT(buffer, link);
+	}
+
+	INSIST(skip_count == 0U);
+
+ config:
+	msg->msg_iov = iov;
+	msg->msg_iovlen = iovcount;
+
+#ifdef ISC_NET_BSD44MSGHDR
+	msg->msg_control = NULL;
+	msg->msg_controllen = 0;
+	msg->msg_flags = 0;
+#if defined(USE_CMSG) && defined(ISC_PLATFORM_HAVEIN6PKTINFO)
+	if ((sock->type == isc_sockettype_udp)
+	    && ((dev->attributes & ISC_SOCKEVENTATTR_PKTINFO) != 0)) {
+		struct cmsghdr *cmsgp;
+		struct in6_pktinfo *pktinfop;
+
+		socket_log(sock, NULL, TRACE,
+			   isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_SENDTODATA,
+			   "sendto pktinfo data, ifindex %u",
+			   dev->pktinfo.ipi6_ifindex);
+
+		msg->msg_controllen = cmsg_space(sizeof(struct in6_pktinfo));
+		INSIST(msg->msg_controllen <= sock->sendcmsgbuflen);
+		msg->msg_control = (void *)sock->sendcmsgbuf;
+
+		cmsgp = (struct cmsghdr *)sock->sendcmsgbuf;
+		cmsgp->cmsg_level = IPPROTO_IPV6;
+		cmsgp->cmsg_type = IPV6_PKTINFO;
+		cmsgp->cmsg_len = cmsg_len(sizeof(struct in6_pktinfo));
+		pktinfop = (struct in6_pktinfo *)CMSG_DATA(cmsgp);
+		memcpy(pktinfop, &dev->pktinfo, sizeof(struct in6_pktinfo));
+	}
+#endif /* USE_CMSG && ISC_PLATFORM_HAVEIPV6 */
+#else /* ISC_NET_BSD44MSGHDR */
+	msg->msg_accrights = NULL;
+	msg->msg_accrightslen = 0;
+#endif /* ISC_NET_BSD44MSGHDR */
+
+	if (write_countp != NULL)
+		*write_countp = write_count;
+}
+
+/*
+ * Construct an iov array and attach it to the msghdr passed in.  This is
+ * the RECV constructor, which will use the available region of the buffer
+ * (if using a buffer list) or will use the internal region (if a single
+ * buffer I/O is requested).
+ *
+ * Nothing can be NULL, and the done event must list at least one buffer
+ * on the buffer linked list for this function to be meaningful.
+ *
+ * If read_countp != NULL, *read_countp will hold the number of bytes
+ * this transaction can receive.
+ */
+static void
+build_msghdr_recv(isc__socket_t *sock, isc_socketevent_t *dev,
+		  struct msghdr *msg, struct iovec *iov, size_t *read_countp)
+{
+	unsigned int iovcount;
+	isc_buffer_t *buffer;
+	isc_region_t available;
+	size_t read_count;
+
+	memset(msg, 0, sizeof(struct msghdr));
+
+	if (sock->type == isc_sockettype_udp) {
+		memset(&dev->address, 0, sizeof(dev->address));
+#ifdef BROKEN_RECVMSG
+		if (sock->pf == AF_INET) {
+			msg->msg_name = (void *)&dev->address.type.sin;
+			msg->msg_namelen = sizeof(dev->address.type.sin6);
+		} else if (sock->pf == AF_INET6) {
+			msg->msg_name = (void *)&dev->address.type.sin6;
+			msg->msg_namelen = sizeof(dev->address.type.sin6);
+#ifdef ISC_PLATFORM_HAVESYSUNH
+		} else if (sock->pf == AF_UNIX) {
+			msg->msg_name = (void *)&dev->address.type.sunix;
+			msg->msg_namelen = sizeof(dev->address.type.sunix);
+#endif
+		} else {
+			msg->msg_name = (void *)&dev->address.type.sa;
+			msg->msg_namelen = sizeof(dev->address.type);
+		}
+#else
+		msg->msg_name = (void *)&dev->address.type.sa;
+		msg->msg_namelen = sizeof(dev->address.type);
+#endif
+#ifdef ISC_NET_RECVOVERFLOW
+		/* If needed, steal one iovec for overflow detection. */
+		maxiov--;
+#endif
+	} else { /* TCP */
+		msg->msg_name = NULL;
+		msg->msg_namelen = 0;
+		dev->address = sock->peer_address;
+	}
+
+	buffer = ISC_LIST_HEAD(dev->bufferlist);
+	read_count = 0;
+
+	/*
+	 * Single buffer I/O?  Skip what we've done so far in this region.
+	 */
+	if (buffer == NULL) {
+		read_count = dev->region.length - dev->n;
+		iov[0].iov_base = (void *)(dev->region.base + dev->n);
+		iov[0].iov_len = read_count;
+		iovcount = 1;
+
+		goto config;
+	}
+
+	/*
+	 * Multibuffer I/O.
+	 * Skip empty buffers.
+	 */
+	while (buffer != NULL) {
+		REQUIRE(ISC_BUFFER_VALID(buffer));
+		if (isc_buffer_availablelength(buffer) != 0)
+			break;
+		buffer = ISC_LIST_NEXT(buffer, link);
+	}
+
+	iovcount = 0;
+	while (buffer != NULL) {
+		INSIST(iovcount < MAXSCATTERGATHER_RECV);
+
+		isc_buffer_availableregion(buffer, &available);
+
+		if (available.length > 0) {
+			iov[iovcount].iov_base = (void *)(available.base);
+			iov[iovcount].iov_len = available.length;
+			read_count += available.length;
+			iovcount++;
+		}
+		buffer = ISC_LIST_NEXT(buffer, link);
+	}
+
+ config:
+
+	/*
+	 * If needed, set up to receive that one extra byte.  Note that
+	 * we know there is at least one iov left, since we stole it
+	 * at the top of this function.
+	 */
+#ifdef ISC_NET_RECVOVERFLOW
+	if (sock->type == isc_sockettype_udp) {
+		iov[iovcount].iov_base = (void *)(&sock->overflow);
+		iov[iovcount].iov_len = 1;
+		iovcount++;
+	}
+#endif
+
+	msg->msg_iov = iov;
+	msg->msg_iovlen = iovcount;
+
+#ifdef ISC_NET_BSD44MSGHDR
+	msg->msg_control = NULL;
+	msg->msg_controllen = 0;
+	msg->msg_flags = 0;
+#if defined(USE_CMSG)
+	if (sock->type == isc_sockettype_udp) {
+		msg->msg_control = sock->recvcmsgbuf;
+		msg->msg_controllen = sock->recvcmsgbuflen;
+	}
+#endif /* USE_CMSG */
+#else /* ISC_NET_BSD44MSGHDR */
+	msg->msg_accrights = NULL;
+	msg->msg_accrightslen = 0;
+#endif /* ISC_NET_BSD44MSGHDR */
+
+	if (read_countp != NULL)
+		*read_countp = read_count;
+}
+
+static void
+set_dev_address(isc_sockaddr_t *address, isc__socket_t *sock,
+		isc_socketevent_t *dev)
+{
+	if (sock->type == isc_sockettype_udp) {
+		if (address != NULL)
+			dev->address = *address;
+		else
+			dev->address = sock->peer_address;
+	} else if (sock->type == isc_sockettype_tcp) {
+		INSIST(address == NULL);
+		dev->address = sock->peer_address;
+	}
+}
+
+static void
+destroy_socketevent(isc_event_t *event) {
+	isc_socketevent_t *ev = (isc_socketevent_t *)event;
+
+	INSIST(ISC_LIST_EMPTY(ev->bufferlist));
+
+	(ev->destroy)(event);
+}
+
+static isc_socketevent_t *
+allocate_socketevent(isc__socket_t *sock, isc_eventtype_t eventtype,
+		     isc_taskaction_t action, const void *arg)
+{
+	isc_socketevent_t *ev;
+
+	ev = (isc_socketevent_t *)isc_event_allocate(sock->manager->mctx,
+						     sock, eventtype,
+						     action, arg,
+						     sizeof(*ev));
+
+	if (ev == NULL)
+		return (NULL);
+
+	ev->result = ISC_R_UNEXPECTED;
+	ISC_LINK_INIT(ev, ev_link);
+	ISC_LIST_INIT(ev->bufferlist);
+	ev->region.base = NULL;
+	ev->n = 0;
+	ev->offset = 0;
+	ev->attributes = 0;
+	ev->destroy = ev->ev_destroy;
+	ev->ev_destroy = destroy_socketevent;
+
+	return (ev);
+}
+
+#if defined(ISC_SOCKET_DEBUG)
+static void
+dump_msg(struct msghdr *msg) {
+	unsigned int i;
+
+	printf("MSGHDR %p\n", msg);
+	printf("\tname %p, namelen %ld\n", msg->msg_name,
+	       (long) msg->msg_namelen);
+	printf("\tiov %p, iovlen %ld\n", msg->msg_iov,
+	       (long) msg->msg_iovlen);
+	for (i = 0; i < (unsigned int)msg->msg_iovlen; i++)
+		printf("\t\t%d\tbase %p, len %ld\n", i,
+		       msg->msg_iov[i].iov_base,
+		       (long) msg->msg_iov[i].iov_len);
+#ifdef ISC_NET_BSD44MSGHDR
+	printf("\tcontrol %p, controllen %ld\n", msg->msg_control,
+	       (long) msg->msg_controllen);
+#endif
+}
+#endif
+
+#define DOIO_SUCCESS		0	/* i/o ok, event sent */
+#define DOIO_SOFT		1	/* i/o ok, soft error, no event sent */
+#define DOIO_HARD		2	/* i/o error, event sent */
+#define DOIO_EOF		3	/* EOF, no event sent */
+
+static int
+doio_recv(isc__socket_t *sock, isc_socketevent_t *dev) {
+	int cc;
+	struct iovec iov[MAXSCATTERGATHER_RECV];
+	size_t read_count;
+	size_t actual_count;
+	struct msghdr msghdr;
+	isc_buffer_t *buffer;
+	int recv_errno;
+	char strbuf[ISC_STRERRORSIZE];
+
+	build_msghdr_recv(sock, dev, &msghdr, iov, &read_count);
+
+#if defined(ISC_SOCKET_DEBUG)
+	dump_msg(&msghdr);
+#endif
+
+	cc = recvmsg(sock->fd, &msghdr, 0);
+	recv_errno = errno;
+
+#if defined(ISC_SOCKET_DEBUG)
+	dump_msg(&msghdr);
+#endif
+
+	if (cc < 0) {
+		if (SOFT_ERROR(recv_errno))
+			return (DOIO_SOFT);
+
+		if (isc_log_wouldlog(isc_lctx, IOEVENT_LEVEL)) {
+			isc__strerror(recv_errno, strbuf, sizeof(strbuf));
+			socket_log(sock, NULL, IOEVENT,
+				   isc_msgcat, ISC_MSGSET_SOCKET,
+				   ISC_MSG_DOIORECV,
+				  "doio_recv: recvmsg(%d) %d bytes, err %d/%s",
+				   sock->fd, cc, recv_errno, strbuf);
+		}
+
+#define SOFT_OR_HARD(_system, _isc) \
+	if (recv_errno == _system) { \
+		if (sock->connected) { \
+			dev->result = _isc; \
+			inc_stats(sock->manager->stats, \
+				  sock->statsindex[STATID_RECVFAIL]); \
+			return (DOIO_HARD); \
+		} \
+		return (DOIO_SOFT); \
+	}
+#define ALWAYS_HARD(_system, _isc) \
+	if (recv_errno == _system) { \
+		dev->result = _isc; \
+		inc_stats(sock->manager->stats, \
+			  sock->statsindex[STATID_RECVFAIL]); \
+		return (DOIO_HARD); \
+	}
+
+		SOFT_OR_HARD(ECONNREFUSED, ISC_R_CONNREFUSED);
+		SOFT_OR_HARD(ENETUNREACH, ISC_R_NETUNREACH);
+		SOFT_OR_HARD(EHOSTUNREACH, ISC_R_HOSTUNREACH);
+		SOFT_OR_HARD(EHOSTDOWN, ISC_R_HOSTDOWN);
+		/* HPUX 11.11 can return EADDRNOTAVAIL. */
+		SOFT_OR_HARD(EADDRNOTAVAIL, ISC_R_ADDRNOTAVAIL);
+		ALWAYS_HARD(ENOBUFS, ISC_R_NORESOURCES);
+		/*
+		 * HPUX returns EPROTO and EINVAL on receiving some ICMP/ICMPv6
+		 * errors.
+		 */
+#ifdef EPROTO
+		SOFT_OR_HARD(EPROTO, ISC_R_HOSTUNREACH);
+#endif
+		SOFT_OR_HARD(EINVAL, ISC_R_HOSTUNREACH);
+
+#undef SOFT_OR_HARD
+#undef ALWAYS_HARD
+
+		dev->result = isc__errno2result(recv_errno);
+		inc_stats(sock->manager->stats,
+			  sock->statsindex[STATID_RECVFAIL]);
+		return (DOIO_HARD);
+	}
+
+	/*
+	 * On TCP and UNIX sockets, zero length reads indicate EOF,
+	 * while on UDP sockets, zero length reads are perfectly valid,
+	 * although strange.
+	 */
+	switch (sock->type) {
+	case isc_sockettype_tcp:
+	case isc_sockettype_unix:
+		if (cc == 0)
+			return (DOIO_EOF);
+		break;
+	case isc_sockettype_udp:
+		break;
+	case isc_sockettype_fdwatch:
+	default:
+		INSIST(0);
+	}
+
+	if (sock->type == isc_sockettype_udp) {
+		dev->address.length = msghdr.msg_namelen;
+		if (isc_sockaddr_getport(&dev->address) == 0) {
+			if (isc_log_wouldlog(isc_lctx, IOEVENT_LEVEL)) {
+				socket_log(sock, &dev->address, IOEVENT,
+					   isc_msgcat, ISC_MSGSET_SOCKET,
+					   ISC_MSG_ZEROPORT,
+					   "dropping source port zero packet");
+			}
+			return (DOIO_SOFT);
+		}
+		/*
+		 * Simulate a firewall blocking UDP responses bigger than
+		 * 512 bytes.
+		 */
+		if (sock->manager->maxudp != 0 && cc > sock->manager->maxudp)
+			return (DOIO_SOFT);
+	}
+
+	socket_log(sock, &dev->address, IOEVENT,
+		   isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_PKTRECV,
+		   "packet received correctly");
+
+	/*
+	 * Overflow bit detection.  If we received MORE bytes than we should,
+	 * this indicates an overflow situation.  Set the flag in the
+	 * dev entry and adjust how much we read by one.
+	 */
+#ifdef ISC_NET_RECVOVERFLOW
+	if ((sock->type == isc_sockettype_udp) && ((size_t)cc > read_count)) {
+		dev->attributes |= ISC_SOCKEVENTATTR_TRUNC;
+		cc--;
+	}
+#endif
+
+	/*
+	 * If there are control messages attached, run through them and pull
+	 * out the interesting bits.
+	 */
+	if (sock->type == isc_sockettype_udp)
+		process_cmsg(sock, &msghdr, dev);
+
+	/*
+	 * update the buffers (if any) and the i/o count
+	 */
+	dev->n += cc;
+	actual_count = cc;
+	buffer = ISC_LIST_HEAD(dev->bufferlist);
+	while (buffer != NULL && actual_count > 0U) {
+		REQUIRE(ISC_BUFFER_VALID(buffer));
+		if (isc_buffer_availablelength(buffer) <= actual_count) {
+			actual_count -= isc_buffer_availablelength(buffer);
+			isc_buffer_add(buffer,
+				       isc_buffer_availablelength(buffer));
+		} else {
+			isc_buffer_add(buffer, actual_count);
+			actual_count = 0;
+			POST(actual_count);
+			break;
+		}
+		buffer = ISC_LIST_NEXT(buffer, link);
+		if (buffer == NULL) {
+			INSIST(actual_count == 0U);
+		}
+	}
+
+	/*
+	 * If we read less than we expected, update counters,
+	 * and let the upper layer poke the descriptor.
+	 */
+	if (((size_t)cc != read_count) && (dev->n < dev->minimum))
+		return (DOIO_SOFT);
+
+	/*
+	 * Full reads are posted, or partials if partials are ok.
+	 */
+	dev->result = ISC_R_SUCCESS;
+	return (DOIO_SUCCESS);
+}
+
+/*
+ * Returns:
+ *	DOIO_SUCCESS	The operation succeeded.  dev->result contains
+ *			ISC_R_SUCCESS.
+ *
+ *	DOIO_HARD	A hard or unexpected I/O error was encountered.
+ *			dev->result contains the appropriate error.
+ *
+ *	DOIO_SOFT	A soft I/O error was encountered.  No senddone
+ *			event was sent.  The operation should be retried.
+ *
+ *	No other return values are possible.
+ */
+static int
+doio_send(isc__socket_t *sock, isc_socketevent_t *dev) {
+	int cc;
+	struct iovec iov[MAXSCATTERGATHER_SEND];
+	size_t write_count;
+	struct msghdr msghdr;
+	char addrbuf[ISC_SOCKADDR_FORMATSIZE];
+	int attempts = 0;
+	int send_errno;
+	char strbuf[ISC_STRERRORSIZE];
+
+	build_msghdr_send(sock, dev, &msghdr, iov, &write_count);
+
+ resend:
+	cc = sendmsg(sock->fd, &msghdr, 0);
+	send_errno = errno;
+
+	/*
+	 * Check for error or block condition.
+	 */
+	if (cc < 0) {
+		if (send_errno == EINTR && ++attempts < NRETRIES)
+			goto resend;
+
+		if (SOFT_ERROR(send_errno))
+			return (DOIO_SOFT);
+
+#define SOFT_OR_HARD(_system, _isc) \
+	if (send_errno == _system) { \
+		if (sock->connected) { \
+			dev->result = _isc; \
+			inc_stats(sock->manager->stats, \
+				  sock->statsindex[STATID_SENDFAIL]); \
+			return (DOIO_HARD); \
+		} \
+		return (DOIO_SOFT); \
+	}
+#define ALWAYS_HARD(_system, _isc) \
+	if (send_errno == _system) { \
+		dev->result = _isc; \
+		inc_stats(sock->manager->stats, \
+			  sock->statsindex[STATID_SENDFAIL]); \
+		return (DOIO_HARD); \
+	}
+
+		SOFT_OR_HARD(ECONNREFUSED, ISC_R_CONNREFUSED);
+		ALWAYS_HARD(EACCES, ISC_R_NOPERM);
+		ALWAYS_HARD(EAFNOSUPPORT, ISC_R_ADDRNOTAVAIL);
+		ALWAYS_HARD(EADDRNOTAVAIL, ISC_R_ADDRNOTAVAIL);
+		ALWAYS_HARD(EHOSTUNREACH, ISC_R_HOSTUNREACH);
+#ifdef EHOSTDOWN
+		ALWAYS_HARD(EHOSTDOWN, ISC_R_HOSTUNREACH);
+#endif
+		ALWAYS_HARD(ENETUNREACH, ISC_R_NETUNREACH);
+		ALWAYS_HARD(ENOBUFS, ISC_R_NORESOURCES);
+		ALWAYS_HARD(EPERM, ISC_R_HOSTUNREACH);
+		ALWAYS_HARD(EPIPE, ISC_R_NOTCONNECTED);
+		ALWAYS_HARD(ECONNRESET, ISC_R_CONNECTIONRESET);
+
+#undef SOFT_OR_HARD
+#undef ALWAYS_HARD
+
+		/*
+		 * The other error types depend on whether or not the
+		 * socket is UDP or TCP.  If it is UDP, some errors
+		 * that we expect to be fatal under TCP are merely
+		 * annoying, and are really soft errors.
+		 *
+		 * However, these soft errors are still returned as
+		 * a status.
+		 */
+		isc_sockaddr_format(&dev->address, addrbuf, sizeof(addrbuf));
+		isc__strerror(send_errno, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__, "internal_send: %s: %s",
+				 addrbuf, strbuf);
+		dev->result = isc__errno2result(send_errno);
+		inc_stats(sock->manager->stats,
+			  sock->statsindex[STATID_SENDFAIL]);
+		return (DOIO_HARD);
+	}
+
+	if (cc == 0) {
+		inc_stats(sock->manager->stats,
+			  sock->statsindex[STATID_SENDFAIL]);
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "doio_send: send() %s 0",
+				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+						ISC_MSG_RETURNED, "returned"));
+	}
+
+	/*
+	 * If we write less than we expected, update counters, poke.
+	 */
+	dev->n += cc;
+	if ((size_t)cc != write_count)
+		return (DOIO_SOFT);
+
+	/*
+	 * Exactly what we wanted to write.  We're done with this
+	 * entry.  Post its completion event.
+	 */
+	dev->result = ISC_R_SUCCESS;
+	return (DOIO_SUCCESS);
+}
+
+/*
+ * Kill.
+ *
+ * Caller must ensure that the socket is not locked and no external
+ * references exist.
+ */
+static void
+closesocket(isc__socketmgr_t *manager, isc__socket_t *sock, int fd) {
+	isc_sockettype_t type = sock->type;
+	int lockid = FDLOCK_ID(fd);
+
+	/*
+	 * No one has this socket open, so the watcher doesn't have to be
+	 * poked, and the socket doesn't have to be locked.
+	 */
+	LOCK(&manager->fdlock[lockid]);
+	manager->fds[fd] = NULL;
+	if (type == isc_sockettype_fdwatch)
+		manager->fdstate[fd] = CLOSED;
+	else
+		manager->fdstate[fd] = CLOSE_PENDING;
+	UNLOCK(&manager->fdlock[lockid]);
+	if (type == isc_sockettype_fdwatch) {
+		/*
+		 * The caller may close the socket once this function returns,
+		 * and `fd' may be reassigned for a new socket.  So we do
+		 * unwatch_fd() here, rather than defer it via select_poke().
+		 * Note: this may complicate data protection among threads and
+		 * may reduce performance due to additional locks.  One way to
+		 * solve this would be to dup() the watched descriptor, but we
+		 * take a simpler approach at this moment.
+		 */
+		(void)unwatch_fd(manager, fd, SELECT_POKE_READ);
+		(void)unwatch_fd(manager, fd, SELECT_POKE_WRITE);
+	} else
+		select_poke(manager, fd, SELECT_POKE_CLOSE);
+
+	inc_stats(manager->stats, sock->statsindex[STATID_CLOSE]);
+
+	/*
+	 * update manager->maxfd here (XXX: this should be implemented more
+	 * efficiently)
+	 */
+#ifdef USE_SELECT
+	LOCK(&manager->lock);
+	if (manager->maxfd == fd) {
+		int i;
+
+		manager->maxfd = 0;
+		for (i = fd - 1; i >= 0; i--) {
+			lockid = FDLOCK_ID(i);
+
+			LOCK(&manager->fdlock[lockid]);
+			if (manager->fdstate[i] == MANAGED) {
+				manager->maxfd = i;
+				UNLOCK(&manager->fdlock[lockid]);
+				break;
+			}
+			UNLOCK(&manager->fdlock[lockid]);
+		}
+#ifdef ISC_PLATFORM_USETHREADS
+		if (manager->maxfd < manager->pipe_fds[0])
+			manager->maxfd = manager->pipe_fds[0];
+#endif
+	}
+	UNLOCK(&manager->lock);
+#endif	/* USE_SELECT */
+}
+
+static void
+destroy(isc__socket_t **sockp) {
+	int fd;
+	isc__socket_t *sock = *sockp;
+	isc__socketmgr_t *manager = sock->manager;
+
+	socket_log(sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET,
+		   ISC_MSG_DESTROYING, "destroying");
+
+	INSIST(ISC_LIST_EMPTY(sock->accept_list));
+	INSIST(ISC_LIST_EMPTY(sock->recv_list));
+	INSIST(ISC_LIST_EMPTY(sock->send_list));
+	INSIST(sock->connect_ev == NULL);
+	REQUIRE(sock->fd == -1 || sock->fd < (int)manager->maxsocks);
+
+	if (sock->fd >= 0) {
+		fd = sock->fd;
+		sock->fd = -1;
+		closesocket(manager, sock, fd);
+	}
+
+	LOCK(&manager->lock);
+
+	ISC_LIST_UNLINK(manager->socklist, sock, link);
+
+#ifdef USE_WATCHER_THREAD
+	if (ISC_LIST_EMPTY(manager->socklist))
+		SIGNAL(&manager->shutdown_ok);
+#endif /* USE_WATCHER_THREAD */
+
+	/* can't unlock manager as its memory context is still used */
+	free_socket(sockp);
+
+	UNLOCK(&manager->lock);
+}
+
+static isc_result_t
+allocate_socket(isc__socketmgr_t *manager, isc_sockettype_t type,
+		isc__socket_t **socketp)
+{
+	isc__socket_t *sock;
+	isc_result_t result;
+	ISC_SOCKADDR_LEN_T cmsgbuflen;
+
+	sock = isc_mem_get(manager->mctx, sizeof(*sock));
+
+	if (sock == NULL)
+		return (ISC_R_NOMEMORY);
+
+	result = ISC_R_UNEXPECTED;
+
+	sock->common.magic = 0;
+	sock->common.impmagic = 0;
+	sock->references = 0;
+
+	sock->manager = manager;
+	sock->type = type;
+	sock->fd = -1;
+	sock->statsindex = NULL;
+
+	ISC_LINK_INIT(sock, link);
+
+	sock->recvcmsgbuf = NULL;
+	sock->sendcmsgbuf = NULL;
+
+	/*
+	 * set up cmsg buffers
+	 */
+	cmsgbuflen = 0;
+#if defined(USE_CMSG) && defined(ISC_PLATFORM_HAVEIN6PKTINFO)
+	cmsgbuflen += cmsg_space(sizeof(struct in6_pktinfo));
+#endif
+#if defined(USE_CMSG) && defined(SO_TIMESTAMP)
+	cmsgbuflen += cmsg_space(sizeof(struct timeval));
+#endif
+	sock->recvcmsgbuflen = cmsgbuflen;
+	if (sock->recvcmsgbuflen != 0U) {
+		sock->recvcmsgbuf = isc_mem_get(manager->mctx, cmsgbuflen);
+		if (sock->recvcmsgbuf == NULL)
+			goto error;
+	}
+
+	cmsgbuflen = 0;
+#if defined(USE_CMSG) && defined(ISC_PLATFORM_HAVEIN6PKTINFO)
+	cmsgbuflen += cmsg_space(sizeof(struct in6_pktinfo));
+#endif
+	sock->sendcmsgbuflen = cmsgbuflen;
+	if (sock->sendcmsgbuflen != 0U) {
+		sock->sendcmsgbuf = isc_mem_get(manager->mctx, cmsgbuflen);
+		if (sock->sendcmsgbuf == NULL)
+			goto error;
+	}
+
+	memset(sock->name, 0, sizeof(sock->name));
+	sock->tag = NULL;
+
+	/*
+	 * set up list of readers and writers to be initially empty
+	 */
+	ISC_LIST_INIT(sock->recv_list);
+	ISC_LIST_INIT(sock->send_list);
+	ISC_LIST_INIT(sock->accept_list);
+	sock->connect_ev = NULL;
+	sock->pending_recv = 0;
+	sock->pending_send = 0;
+	sock->pending_accept = 0;
+	sock->listener = 0;
+	sock->connected = 0;
+	sock->connecting = 0;
+	sock->bound = 0;
+
+	/*
+	 * initialize the lock
+	 */
+	result = isc_mutex_init(&sock->lock);
+	if (result != ISC_R_SUCCESS) {
+		sock->common.magic = 0;
+		sock->common.impmagic = 0;
+		goto error;
+	}
+
+	/*
+	 * Initialize readable and writable events
+	 */
+	ISC_EVENT_INIT(&sock->readable_ev, sizeof(intev_t),
+		       ISC_EVENTATTR_NOPURGE, NULL, ISC_SOCKEVENT_INTR,
+		       NULL, sock, sock, NULL, NULL);
+	ISC_EVENT_INIT(&sock->writable_ev, sizeof(intev_t),
+		       ISC_EVENTATTR_NOPURGE, NULL, ISC_SOCKEVENT_INTW,
+		       NULL, sock, sock, NULL, NULL);
+
+	sock->common.magic = ISCAPI_SOCKET_MAGIC;
+	sock->common.impmagic = SOCKET_MAGIC;
+	*socketp = sock;
+
+	return (ISC_R_SUCCESS);
+
+ error:
+	if (sock->recvcmsgbuf != NULL)
+		isc_mem_put(manager->mctx, sock->recvcmsgbuf,
+			    sock->recvcmsgbuflen);
+	if (sock->sendcmsgbuf != NULL)
+		isc_mem_put(manager->mctx, sock->sendcmsgbuf,
+			    sock->sendcmsgbuflen);
+	isc_mem_put(manager->mctx, sock, sizeof(*sock));
+
+	return (result);
+}
+
+/*
+ * This event requires that the various lists be empty, that the reference
+ * count be 1, and that the magic number is valid.  The other socket bits,
+ * like the lock, must be initialized as well.  The fd associated must be
+ * marked as closed, by setting it to -1 on close, or this routine will
+ * also close the socket.
+ */
+static void
+free_socket(isc__socket_t **socketp) {
+	isc__socket_t *sock = *socketp;
+
+	INSIST(sock->references == 0);
+	INSIST(VALID_SOCKET(sock));
+	INSIST(!sock->connecting);
+	INSIST(!sock->pending_recv);
+	INSIST(!sock->pending_send);
+	INSIST(!sock->pending_accept);
+	INSIST(ISC_LIST_EMPTY(sock->recv_list));
+	INSIST(ISC_LIST_EMPTY(sock->send_list));
+	INSIST(ISC_LIST_EMPTY(sock->accept_list));
+	INSIST(!ISC_LINK_LINKED(sock, link));
+
+	if (sock->recvcmsgbuf != NULL)
+		isc_mem_put(sock->manager->mctx, sock->recvcmsgbuf,
+			    sock->recvcmsgbuflen);
+	if (sock->sendcmsgbuf != NULL)
+		isc_mem_put(sock->manager->mctx, sock->sendcmsgbuf,
+			    sock->sendcmsgbuflen);
+
+	sock->common.magic = 0;
+	sock->common.impmagic = 0;
+
+	DESTROYLOCK(&sock->lock);
+
+	isc_mem_put(sock->manager->mctx, sock, sizeof(*sock));
+
+	*socketp = NULL;
+}
+
+#ifdef SO_BSDCOMPAT
+/*
+ * This really should not be necessary to do.  Having to workout
+ * which kernel version we are on at run time so that we don't cause
+ * the kernel to issue a warning about us using a deprecated socket option.
+ * Such warnings should *never* be on by default in production kernels.
+ *
+ * We can't do this a build time because executables are moved between
+ * machines and hence kernels.
+ *
+ * We can't just not set SO_BSDCOMAT because some kernels require it.
+ */
+
+static isc_once_t         bsdcompat_once = ISC_ONCE_INIT;
+isc_boolean_t bsdcompat = ISC_TRUE;
+
+static void
+clear_bsdcompat(void) {
+#ifdef __linux__
+	 struct utsname buf;
+	 char *endp;
+	 long int major;
+	 long int minor;
+
+	 uname(&buf);    /* Can only fail if buf is bad in Linux. */
+
+	 /* Paranoia in parsing can be increased, but we trust uname(). */
+	 major = strtol(buf.release, &endp, 10);
+	 if (*endp == '.') {
+		minor = strtol(endp+1, &endp, 10);
+		if ((major > 2) || ((major == 2) && (minor >= 4))) {
+			bsdcompat = ISC_FALSE;
+		}
+	 }
+#endif /* __linux __ */
+}
+#endif
+
+static isc_result_t
+opensocket(isc__socketmgr_t *manager, isc__socket_t *sock) {
+	char strbuf[ISC_STRERRORSIZE];
+	const char *err = "socket";
+	int tries = 0;
+#if defined(USE_CMSG) || defined(SO_BSDCOMPAT)
+	int on = 1;
+#endif
+#if defined(SO_RCVBUF)
+	ISC_SOCKADDR_LEN_T optlen;
+	int size;
+#endif
+
+ again:
+	switch (sock->type) {
+	case isc_sockettype_udp:
+		sock->fd = socket(sock->pf, SOCK_DGRAM, IPPROTO_UDP);
+		break;
+	case isc_sockettype_tcp:
+		sock->fd = socket(sock->pf, SOCK_STREAM, IPPROTO_TCP);
+		break;
+	case isc_sockettype_unix:
+		sock->fd = socket(sock->pf, SOCK_STREAM, 0);
+		break;
+	case isc_sockettype_fdwatch:
+		/*
+		 * We should not be called for isc_sockettype_fdwatch sockets.
+		 */
+		INSIST(0);
+		break;
+	}
+	if (sock->fd == -1 && errno == EINTR && tries++ < 42)
+		goto again;
+
+#ifdef F_DUPFD
+	/*
+	 * Leave a space for stdio and TCP to work in.
+	 */
+	if (manager->reserved != 0 && sock->type == isc_sockettype_udp &&
+	    sock->fd >= 0 && sock->fd < manager->reserved) {
+		int new, tmp;
+		new = fcntl(sock->fd, F_DUPFD, manager->reserved);
+		tmp = errno;
+		(void)close(sock->fd);
+		errno = tmp;
+		sock->fd = new;
+		err = "isc_socket_create: fcntl/reserved";
+	} else if (sock->fd >= 0 && sock->fd < 20) {
+		int new, tmp;
+		new = fcntl(sock->fd, F_DUPFD, 20);
+		tmp = errno;
+		(void)close(sock->fd);
+		errno = tmp;
+		sock->fd = new;
+		err = "isc_socket_create: fcntl";
+	}
+#endif
+
+	if (sock->fd >= (int)manager->maxsocks) {
+		(void)close(sock->fd);
+		isc_log_iwrite(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+			       ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
+			       isc_msgcat, ISC_MSGSET_SOCKET,
+			       ISC_MSG_TOOMANYFDS,
+			       "socket: file descriptor exceeds limit (%d/%u)",
+			       sock->fd, manager->maxsocks);
+		return (ISC_R_NORESOURCES);
+	}
+
+	if (sock->fd < 0) {
+		switch (errno) {
+		case EMFILE:
+		case ENFILE:
+			isc__strerror(errno, strbuf, sizeof(strbuf));
+			isc_log_iwrite(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+				       ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
+				       isc_msgcat, ISC_MSGSET_SOCKET,
+				       ISC_MSG_TOOMANYFDS,
+				       "%s: %s", err, strbuf);
+			/* fallthrough */
+		case ENOBUFS:
+			return (ISC_R_NORESOURCES);
+
+		case EPROTONOSUPPORT:
+		case EPFNOSUPPORT:
+		case EAFNOSUPPORT:
+		/*
+		 * Linux 2.2 (and maybe others) return EINVAL instead of
+		 * EAFNOSUPPORT.
+		 */
+		case EINVAL:
+			return (ISC_R_FAMILYNOSUPPORT);
+
+		default:
+			isc__strerror(errno, strbuf, sizeof(strbuf));
+			UNEXPECTED_ERROR(__FILE__, __LINE__,
+					 "%s() %s: %s", err,
+					 isc_msgcat_get(isc_msgcat,
+							ISC_MSGSET_GENERAL,
+							ISC_MSG_FAILED,
+							"failed"),
+					 strbuf);
+			return (ISC_R_UNEXPECTED);
+		}
+	}
+
+	if (make_nonblock(sock->fd) != ISC_R_SUCCESS) {
+		(void)close(sock->fd);
+		return (ISC_R_UNEXPECTED);
+	}
+
+#ifdef SO_BSDCOMPAT
+	RUNTIME_CHECK(isc_once_do(&bsdcompat_once,
+				  clear_bsdcompat) == ISC_R_SUCCESS);
+	if (sock->type != isc_sockettype_unix && bsdcompat &&
+	    setsockopt(sock->fd, SOL_SOCKET, SO_BSDCOMPAT,
+		       (void *)&on, sizeof(on)) < 0) {
+		isc__strerror(errno, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "setsockopt(%d, SO_BSDCOMPAT) %s: %s",
+				 sock->fd,
+				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+						ISC_MSG_FAILED, "failed"),
+				 strbuf);
+		/* Press on... */
+	}
+#endif
+
+#ifdef SO_NOSIGPIPE
+	if (setsockopt(sock->fd, SOL_SOCKET, SO_NOSIGPIPE,
+		       (void *)&on, sizeof(on)) < 0) {
+		isc__strerror(errno, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "setsockopt(%d, SO_NOSIGPIPE) %s: %s",
+				 sock->fd,
+				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+						ISC_MSG_FAILED, "failed"),
+				 strbuf);
+		/* Press on... */
+	}
+#endif
+
+#if defined(USE_CMSG) || defined(SO_RCVBUF)
+	if (sock->type == isc_sockettype_udp) {
+
+#if defined(USE_CMSG)
+#if defined(SO_TIMESTAMP)
+		if (setsockopt(sock->fd, SOL_SOCKET, SO_TIMESTAMP,
+			       (void *)&on, sizeof(on)) < 0
+		    && errno != ENOPROTOOPT) {
+			isc__strerror(errno, strbuf, sizeof(strbuf));
+			UNEXPECTED_ERROR(__FILE__, __LINE__,
+					 "setsockopt(%d, SO_TIMESTAMP) %s: %s",
+					 sock->fd,
+					 isc_msgcat_get(isc_msgcat,
+							ISC_MSGSET_GENERAL,
+							ISC_MSG_FAILED,
+							"failed"),
+					 strbuf);
+			/* Press on... */
+		}
+#endif /* SO_TIMESTAMP */
+
+#if defined(ISC_PLATFORM_HAVEIPV6)
+		if (sock->pf == AF_INET6 && sock->recvcmsgbuflen == 0U) {
+			/*
+			 * Warn explicitly because this anomaly can be hidden
+			 * in usual operation (and unexpectedly appear later).
+			 */
+			UNEXPECTED_ERROR(__FILE__, __LINE__,
+					 "No buffer available to receive "
+					 "IPv6 destination");
+		}
+#ifdef ISC_PLATFORM_HAVEIN6PKTINFO
+#ifdef IPV6_RECVPKTINFO
+		/* RFC 3542 */
+		if ((sock->pf == AF_INET6)
+		    && (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_RECVPKTINFO,
+				   (void *)&on, sizeof(on)) < 0)) {
+			isc__strerror(errno, strbuf, sizeof(strbuf));
+			UNEXPECTED_ERROR(__FILE__, __LINE__,
+					 "setsockopt(%d, IPV6_RECVPKTINFO) "
+					 "%s: %s", sock->fd,
+					 isc_msgcat_get(isc_msgcat,
+							ISC_MSGSET_GENERAL,
+							ISC_MSG_FAILED,
+							"failed"),
+					 strbuf);
+		}
+#else
+		/* RFC 2292 */
+		if ((sock->pf == AF_INET6)
+		    && (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_PKTINFO,
+				   (void *)&on, sizeof(on)) < 0)) {
+			isc__strerror(errno, strbuf, sizeof(strbuf));
+			UNEXPECTED_ERROR(__FILE__, __LINE__,
+					 "setsockopt(%d, IPV6_PKTINFO) %s: %s",
+					 sock->fd,
+					 isc_msgcat_get(isc_msgcat,
+							ISC_MSGSET_GENERAL,
+							ISC_MSG_FAILED,
+							"failed"),
+					 strbuf);
+		}
+#endif /* IPV6_RECVPKTINFO */
+#endif /* ISC_PLATFORM_HAVEIN6PKTINFO */
+#ifdef IPV6_USE_MIN_MTU        /* RFC 3542, not too common yet*/
+		/* use minimum MTU */
+		if (sock->pf == AF_INET6) {
+			(void)setsockopt(sock->fd, IPPROTO_IPV6,
+					 IPV6_USE_MIN_MTU,
+					 (void *)&on, sizeof(on));
+		}
+#endif
+#if defined(IPV6_MTU)
+		/*
+		 * Use minimum MTU on IPv6 sockets.
+		 */
+		if (sock->pf == AF_INET6) {
+			int mtu = 1280;
+			(void)setsockopt(sock->fd, IPPROTO_IPV6, IPV6_MTU,
+					 &mtu, sizeof(mtu));
+		}
+#endif
+#if defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DONT)
+		/*
+		 * Turn off Path MTU discovery on IPv6/UDP sockets.
+		 */
+		if (sock->pf == AF_INET6) {
+			int action = IPV6_PMTUDISC_DONT;
+			(void)setsockopt(sock->fd, IPPROTO_IPV6, IPV6_MTU_DISCOVER,
+					 &action, sizeof(action));
+		}
+#endif
+#endif /* ISC_PLATFORM_HAVEIPV6 */
+#endif /* defined(USE_CMSG) */
+
+#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
+		/*
+		 * Turn off Path MTU discovery on IPv4/UDP sockets.
+		 */
+		if (sock->pf == AF_INET) {
+			int action = IP_PMTUDISC_DONT;
+			(void)setsockopt(sock->fd, IPPROTO_IP, IP_MTU_DISCOVER,
+					 &action, sizeof(action));
+		}
+#endif
+#if defined(IP_DONTFRAG)
+		/*
+		 * Turn off Path MTU discovery on IPv4/UDP sockets.
+		 */
+		if (sock->pf == AF_INET) {
+			int off = 0;
+			(void)setsockopt(sock->fd, IPPROTO_IP, IP_DONTFRAG,
+					 &off, sizeof(off));
+		}
+#endif
+
+#if defined(SO_RCVBUF)
+		optlen = sizeof(size);
+		if (getsockopt(sock->fd, SOL_SOCKET, SO_RCVBUF,
+			       (void *)&size, &optlen) >= 0 &&
+		     size < RCVBUFSIZE) {
+			size = RCVBUFSIZE;
+			if (setsockopt(sock->fd, SOL_SOCKET, SO_RCVBUF,
+				       (void *)&size, sizeof(size)) == -1) {
+				isc__strerror(errno, strbuf, sizeof(strbuf));
+				UNEXPECTED_ERROR(__FILE__, __LINE__,
+					"setsockopt(%d, SO_RCVBUF, %d) %s: %s",
+					sock->fd, size,
+					isc_msgcat_get(isc_msgcat,
+						       ISC_MSGSET_GENERAL,
+						       ISC_MSG_FAILED,
+						       "failed"),
+					strbuf);
+			}
+		}
+#endif
+	}
+#endif /* defined(USE_CMSG) || defined(SO_RCVBUF) */
+
+	inc_stats(manager->stats, sock->statsindex[STATID_OPEN]);
+
+	return (ISC_R_SUCCESS);
+}
+
+/*%
+ * Create a new 'type' socket managed by 'manager'.  Events
+ * will be posted to 'task' and when dispatched 'action' will be
+ * called with 'arg' as the arg value.  The new socket is returned
+ * in 'socketp'.
+ */
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_create(isc_socketmgr_t *manager0, int pf, isc_sockettype_t type,
+		   isc_socket_t **socketp)
+{
+	isc__socket_t *sock = NULL;
+	isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0;
+	isc_result_t result;
+	int lockid;
+
+	REQUIRE(VALID_MANAGER(manager));
+	REQUIRE(socketp != NULL && *socketp == NULL);
+	REQUIRE(type != isc_sockettype_fdwatch);
+
+	result = allocate_socket(manager, type, &sock);
+	if (result != ISC_R_SUCCESS)
+		return (result);
+
+	switch (sock->type) {
+	case isc_sockettype_udp:
+		sock->statsindex =
+			(pf == AF_INET) ? upd4statsindex : upd6statsindex;
+		break;
+	case isc_sockettype_tcp:
+		sock->statsindex =
+			(pf == AF_INET) ? tcp4statsindex : tcp6statsindex;
+		break;
+	case isc_sockettype_unix:
+		sock->statsindex = unixstatsindex;
+		break;
+	default:
+		INSIST(0);
+	}
+
+	sock->pf = pf;
+	result = opensocket(manager, sock);
+	if (result != ISC_R_SUCCESS) {
+		inc_stats(manager->stats, sock->statsindex[STATID_OPENFAIL]);
+		free_socket(&sock);
+		return (result);
+	}
+
+	sock->common.methods = (isc_socketmethods_t *)&socketmethods;
+	sock->references = 1;
+	*socketp = (isc_socket_t *)sock;
+
+	/*
+	 * Note we don't have to lock the socket like we normally would because
+	 * there are no external references to it yet.
+	 */
+
+	lockid = FDLOCK_ID(sock->fd);
+	LOCK(&manager->fdlock[lockid]);
+	manager->fds[sock->fd] = sock;
+	manager->fdstate[sock->fd] = MANAGED;
+#ifdef USE_DEVPOLL
+	INSIST(sock->manager->fdpollinfo[sock->fd].want_read == 0 &&
+	       sock->manager->fdpollinfo[sock->fd].want_write == 0);
+#endif
+	UNLOCK(&manager->fdlock[lockid]);
+
+	LOCK(&manager->lock);
+	ISC_LIST_APPEND(manager->socklist, sock, link);
+#ifdef USE_SELECT
+	if (manager->maxfd < sock->fd)
+		manager->maxfd = sock->fd;
+#endif
+	UNLOCK(&manager->lock);
+
+	socket_log(sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET,
+		   ISC_MSG_CREATED, "created");
+
+	return (ISC_R_SUCCESS);
+}
+
+#ifdef BIND9
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_open(isc_socket_t *sock0) {
+	isc_result_t result;
+	isc__socket_t *sock = (isc__socket_t *)sock0;
+
+	REQUIRE(VALID_SOCKET(sock));
+
+	LOCK(&sock->lock);
+	REQUIRE(sock->references == 1);
+	REQUIRE(sock->type != isc_sockettype_fdwatch);
+	UNLOCK(&sock->lock);
+	/*
+	 * We don't need to retain the lock hereafter, since no one else has
+	 * this socket.
+	 */
+	REQUIRE(sock->fd == -1);
+
+	result = opensocket(sock->manager, sock);
+	if (result != ISC_R_SUCCESS)
+		sock->fd = -1;
+
+	if (result == ISC_R_SUCCESS) {
+		int lockid = FDLOCK_ID(sock->fd);
+
+		LOCK(&sock->manager->fdlock[lockid]);
+		sock->manager->fds[sock->fd] = sock;
+		sock->manager->fdstate[sock->fd] = MANAGED;
+#ifdef USE_DEVPOLL
+		INSIST(sock->manager->fdpollinfo[sock->fd].want_read == 0 &&
+		       sock->manager->fdpollinfo[sock->fd].want_write == 0);
+#endif
+		UNLOCK(&sock->manager->fdlock[lockid]);
+
+#ifdef USE_SELECT
+		LOCK(&sock->manager->lock);
+		if (sock->manager->maxfd < sock->fd)
+			sock->manager->maxfd = sock->fd;
+		UNLOCK(&sock->manager->lock);
+#endif
+	}
+
+	return (result);
+}
+#endif	/* BIND9 */
+
+/*
+ * Create a new 'type' socket managed by 'manager'.  Events
+ * will be posted to 'task' and when dispatched 'action' will be
+ * called with 'arg' as the arg value.  The new socket is returned
+ * in 'socketp'.
+ */
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_fdwatchcreate(isc_socketmgr_t *manager0, int fd, int flags,
+			  isc_sockfdwatch_t callback, void *cbarg,
+			  isc_task_t *task, isc_socket_t **socketp)
+{
+	isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0;
+	isc__socket_t *sock = NULL;
+	isc_result_t result;
+	int lockid;
+
+	REQUIRE(VALID_MANAGER(manager));
+	REQUIRE(socketp != NULL && *socketp == NULL);
+
+	result = allocate_socket(manager, isc_sockettype_fdwatch, &sock);
+	if (result != ISC_R_SUCCESS)
+		return (result);
+
+	sock->fd = fd;
+	sock->fdwatcharg = cbarg;
+	sock->fdwatchcb = callback;
+	sock->fdwatchflags = flags;
+	sock->fdwatchtask = task;
+	sock->statsindex = fdwatchstatsindex;
+
+	sock->common.methods = (isc_socketmethods_t *)&socketmethods;
+	sock->references = 1;
+	*socketp = (isc_socket_t *)sock;
+
+	/*
+	 * Note we don't have to lock the socket like we normally would because
+	 * there are no external references to it yet.
+	 */
+
+	lockid = FDLOCK_ID(sock->fd);
+	LOCK(&manager->fdlock[lockid]);
+	manager->fds[sock->fd] = sock;
+	manager->fdstate[sock->fd] = MANAGED;
+	UNLOCK(&manager->fdlock[lockid]);
+
+	LOCK(&manager->lock);
+	ISC_LIST_APPEND(manager->socklist, sock, link);
+#ifdef USE_SELECT
+	if (manager->maxfd < sock->fd)
+		manager->maxfd = sock->fd;
+#endif
+	UNLOCK(&manager->lock);
+
+	if (flags & ISC_SOCKFDWATCH_READ)
+		select_poke(sock->manager, sock->fd, SELECT_POKE_READ);
+	if (flags & ISC_SOCKFDWATCH_WRITE)
+		select_poke(sock->manager, sock->fd, SELECT_POKE_WRITE);
+
+	socket_log(sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET,
+		   ISC_MSG_CREATED, "fdwatch-created");
+
+	return (ISC_R_SUCCESS);
+}
+
+/*
+ * Indicate to the manager that it should watch the socket again.
+ * This can be used to restart watching if the previous event handler
+ * didn't indicate there was more data to be processed.  Primarily
+ * it is for writing but could be used for reading if desired
+ */
+
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_fdwatchpoke(isc_socket_t *sock0, int flags)
+{
+	isc__socket_t *sock = (isc__socket_t *)sock0;
+
+	REQUIRE(VALID_SOCKET(sock));
+
+	/*
+	 * We check both flags first to allow us to get the lock
+	 * once but only if we need it.
+	 */
+
+	if ((flags & (ISC_SOCKFDWATCH_READ | ISC_SOCKFDWATCH_WRITE)) != 0) {
+		LOCK(&sock->lock);
+		if (((flags & ISC_SOCKFDWATCH_READ) != 0) &&
+		    !sock->pending_recv)
+			select_poke(sock->manager, sock->fd,
+				    SELECT_POKE_READ);
+		if (((flags & ISC_SOCKFDWATCH_WRITE) != 0) &&
+		    !sock->pending_send)
+			select_poke(sock->manager, sock->fd,
+				    SELECT_POKE_WRITE);
+		UNLOCK(&sock->lock);
+	}
+
+	socket_log(sock, NULL, TRACE, isc_msgcat, ISC_MSGSET_SOCKET,
+		   ISC_MSG_POKED, "fdwatch-poked flags: %d", flags);
+
+	return (ISC_R_SUCCESS);
+}
+
+/*
+ * Attach to a socket.  Caller must explicitly detach when it is done.
+ */
+ISC_SOCKETFUNC_SCOPE void
+isc__socket_attach(isc_socket_t *sock0, isc_socket_t **socketp) {
+	isc__socket_t *sock = (isc__socket_t *)sock0;
+
+	REQUIRE(VALID_SOCKET(sock));
+	REQUIRE(socketp != NULL && *socketp == NULL);
+
+	LOCK(&sock->lock);
+	sock->references++;
+	UNLOCK(&sock->lock);
+
+	*socketp = (isc_socket_t *)sock;
+}
+
+/*
+ * Dereference a socket.  If this is the last reference to it, clean things
+ * up by destroying the socket.
+ */
+ISC_SOCKETFUNC_SCOPE void
+isc__socket_detach(isc_socket_t **socketp) {
+	isc__socket_t *sock;
+	isc_boolean_t kill_socket = ISC_FALSE;
+
+	REQUIRE(socketp != NULL);
+	sock = (isc__socket_t *)*socketp;
+	REQUIRE(VALID_SOCKET(sock));
+
+	LOCK(&sock->lock);
+	REQUIRE(sock->references > 0);
+	sock->references--;
+	if (sock->references == 0)
+		kill_socket = ISC_TRUE;
+	UNLOCK(&sock->lock);
+
+	if (kill_socket)
+		destroy(&sock);
+
+	*socketp = NULL;
+}
+
+#ifdef BIND9
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_close(isc_socket_t *sock0) {
+	isc__socket_t *sock = (isc__socket_t *)sock0;
+	int fd;
+	isc__socketmgr_t *manager;
+
+	REQUIRE(VALID_SOCKET(sock));
+
+	LOCK(&sock->lock);
+
+	REQUIRE(sock->references == 1);
+	REQUIRE(sock->type != isc_sockettype_fdwatch);
+	REQUIRE(sock->fd >= 0 && sock->fd < (int)sock->manager->maxsocks);
+
+	INSIST(!sock->connecting);
+	INSIST(!sock->pending_recv);
+	INSIST(!sock->pending_send);
+	INSIST(!sock->pending_accept);
+	INSIST(ISC_LIST_EMPTY(sock->recv_list));
+	INSIST(ISC_LIST_EMPTY(sock->send_list));
+	INSIST(ISC_LIST_EMPTY(sock->accept_list));
+	INSIST(sock->connect_ev == NULL);
+
+	manager = sock->manager;
+	fd = sock->fd;
+	sock->fd = -1;
+	memset(sock->name, 0, sizeof(sock->name));
+	sock->tag = NULL;
+	sock->listener = 0;
+	sock->connected = 0;
+	sock->connecting = 0;
+	sock->bound = 0;
+	isc_sockaddr_any(&sock->peer_address);
+
+	UNLOCK(&sock->lock);
+
+	closesocket(manager, sock, fd);
+
+	return (ISC_R_SUCCESS);
+}
+#endif	/* BIND9 */
+
+/*
+ * I/O is possible on a given socket.  Schedule an event to this task that
+ * will call an internal function to do the I/O.  This will charge the
+ * task with the I/O operation and let our select loop handler get back
+ * to doing something real as fast as possible.
+ *
+ * The socket and manager must be locked before calling this function.
+ */
+static void
+dispatch_recv(isc__socket_t *sock) {
+	intev_t *iev;
+	isc_socketevent_t *ev;
+	isc_task_t *sender;
+
+	INSIST(!sock->pending_recv);
+
+	if (sock->type != isc_sockettype_fdwatch) {
+		ev = ISC_LIST_HEAD(sock->recv_list);
+		if (ev == NULL)
+			return;
+		socket_log(sock, NULL, EVENT, NULL, 0, 0,
+			   "dispatch_recv:  event %p -> task %p",
+			   ev, ev->ev_sender);
+		sender = ev->ev_sender;
+	} else {
+		sender = sock->fdwatchtask;
+	}
+
+	sock->pending_recv = 1;
+	iev = &sock->readable_ev;
+
+	sock->references++;
+	iev->ev_sender = sock;
+	if (sock->type == isc_sockettype_fdwatch)
+		iev->ev_action = internal_fdwatch_read;
+	else
+		iev->ev_action = internal_recv;
+	iev->ev_arg = sock;
+
+	isc_task_send(sender, (isc_event_t **)&iev);
+}
+
+static void
+dispatch_send(isc__socket_t *sock) {
+	intev_t *iev;
+	isc_socketevent_t *ev;
+	isc_task_t *sender;
+
+	INSIST(!sock->pending_send);
+
+	if (sock->type != isc_sockettype_fdwatch) {
+		ev = ISC_LIST_HEAD(sock->send_list);
+		if (ev == NULL)
+			return;
+		socket_log(sock, NULL, EVENT, NULL, 0, 0,
+			   "dispatch_send:  event %p -> task %p",
+			   ev, ev->ev_sender);
+		sender = ev->ev_sender;
+	} else {
+		sender = sock->fdwatchtask;
+	}
+
+	sock->pending_send = 1;
+	iev = &sock->writable_ev;
+
+	sock->references++;
+	iev->ev_sender = sock;
+	if (sock->type == isc_sockettype_fdwatch)
+		iev->ev_action = internal_fdwatch_write;
+	else
+		iev->ev_action = internal_send;
+	iev->ev_arg = sock;
+
+	isc_task_send(sender, (isc_event_t **)&iev);
+}
+
+/*
+ * Dispatch an internal accept event.
+ */
+static void
+dispatch_accept(isc__socket_t *sock) {
+	intev_t *iev;
+	isc_socket_newconnev_t *ev;
+
+	INSIST(!sock->pending_accept);
+
+	/*
+	 * Are there any done events left, or were they all canceled
+	 * before the manager got the socket lock?
+	 */
+	ev = ISC_LIST_HEAD(sock->accept_list);
+	if (ev == NULL)
+		return;
+
+	sock->pending_accept = 1;
+	iev = &sock->readable_ev;
+
+	sock->references++;  /* keep socket around for this internal event */
+	iev->ev_sender = sock;
+	iev->ev_action = internal_accept;
+	iev->ev_arg = sock;
+
+	isc_task_send(ev->ev_sender, (isc_event_t **)&iev);
+}
+
+static void
+dispatch_connect(isc__socket_t *sock) {
+	intev_t *iev;
+	isc_socket_connev_t *ev;
+
+	iev = &sock->writable_ev;
+
+	ev = sock->connect_ev;
+	INSIST(ev != NULL); /* XXX */
+
+	INSIST(sock->connecting);
+
+	sock->references++;  /* keep socket around for this internal event */
+	iev->ev_sender = sock;
+	iev->ev_action = internal_connect;
+	iev->ev_arg = sock;
+
+	isc_task_send(ev->ev_sender, (isc_event_t **)&iev);
+}
+
+/*
+ * Dequeue an item off the given socket's read queue, set the result code
+ * in the done event to the one provided, and send it to the task it was
+ * destined for.
+ *
+ * If the event to be sent is on a list, remove it before sending.  If
+ * asked to, send and detach from the socket as well.
+ *
+ * Caller must have the socket locked if the event is attached to the socket.
+ */
+static void
+send_recvdone_event(isc__socket_t *sock, isc_socketevent_t **dev) {
+	isc_task_t *task;
+
+	task = (*dev)->ev_sender;
+
+	(*dev)->ev_sender = sock;
+
+	if (ISC_LINK_LINKED(*dev, ev_link))
+		ISC_LIST_DEQUEUE(sock->recv_list, *dev, ev_link);
+
+	if (((*dev)->attributes & ISC_SOCKEVENTATTR_ATTACHED)
+	    == ISC_SOCKEVENTATTR_ATTACHED)
+		isc_task_sendanddetach(&task, (isc_event_t **)dev);
+	else
+		isc_task_send(task, (isc_event_t **)dev);
+}
+
+/*
+ * See comments for send_recvdone_event() above.
+ *
+ * Caller must have the socket locked if the event is attached to the socket.
+ */
+static void
+send_senddone_event(isc__socket_t *sock, isc_socketevent_t **dev) {
+	isc_task_t *task;
+
+	INSIST(dev != NULL && *dev != NULL);
+
+	task = (*dev)->ev_sender;
+	(*dev)->ev_sender = sock;
+
+	if (ISC_LINK_LINKED(*dev, ev_link))
+		ISC_LIST_DEQUEUE(sock->send_list, *dev, ev_link);
+
+	if (((*dev)->attributes & ISC_SOCKEVENTATTR_ATTACHED)
+	    == ISC_SOCKEVENTATTR_ATTACHED)
+		isc_task_sendanddetach(&task, (isc_event_t **)dev);
+	else
+		isc_task_send(task, (isc_event_t **)dev);
+}
+
+/*
+ * Call accept() on a socket, to get the new file descriptor.  The listen
+ * socket is used as a prototype to create a new isc_socket_t.  The new
+ * socket has one outstanding reference.  The task receiving the event
+ * will be detached from just after the event is delivered.
+ *
+ * On entry to this function, the event delivered is the internal
+ * readable event, and the first item on the accept_list should be
+ * the done event we want to send.  If the list is empty, this is a no-op,
+ * so just unlock and return.
+ */
+static void
+internal_accept(isc_task_t *me, isc_event_t *ev) {
+	isc__socket_t *sock;
+	isc__socketmgr_t *manager;
+	isc_socket_newconnev_t *dev;
+	isc_task_t *task;
+	ISC_SOCKADDR_LEN_T addrlen;
+	int fd;
+	isc_result_t result = ISC_R_SUCCESS;
+	char strbuf[ISC_STRERRORSIZE];
+	const char *err = "accept";
+
+	UNUSED(me);
+
+	sock = ev->ev_sender;
+	INSIST(VALID_SOCKET(sock));
+
+	LOCK(&sock->lock);
+	socket_log(sock, NULL, TRACE,
+		   isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTLOCK,
+		   "internal_accept called, locked socket");
+
+	manager = sock->manager;
+	INSIST(VALID_MANAGER(manager));
+
+	INSIST(sock->listener);
+	INSIST(sock->pending_accept == 1);
+	sock->pending_accept = 0;
+
+	INSIST(sock->references > 0);
+	sock->references--;  /* the internal event is done with this socket */
+	if (sock->references == 0) {
+		UNLOCK(&sock->lock);
+		destroy(&sock);
+		return;
+	}
+
+	/*
+	 * Get the first item off the accept list.
+	 * If it is empty, unlock the socket and return.
+	 */
+	dev = ISC_LIST_HEAD(sock->accept_list);
+	if (dev == NULL) {
+		UNLOCK(&sock->lock);
+		return;
+	}
+
+	/*
+	 * Try to accept the new connection.  If the accept fails with
+	 * EAGAIN or EINTR, simply poke the watcher to watch this socket
+	 * again.  Also ignore ECONNRESET, which has been reported to
+	 * be spuriously returned on Linux 2.2.19 although it is not
+	 * a documented error for accept().  ECONNABORTED has been
+	 * reported for Solaris 8.  The rest are thrown in not because
+	 * we have seen them but because they are ignored by other
+	 * daemons such as BIND 8 and Apache.
+	 */
+
+	addrlen = sizeof(NEWCONNSOCK(dev)->peer_address.type);
+	memset(&NEWCONNSOCK(dev)->peer_address.type, 0, addrlen);
+	fd = accept(sock->fd, &NEWCONNSOCK(dev)->peer_address.type.sa,
+		    (void *)&addrlen);
+
+#ifdef F_DUPFD
+	/*
+	 * Leave a space for stdio to work in.
+	 */
+	if (fd >= 0 && fd < 20) {
+		int new, tmp;
+		new = fcntl(fd, F_DUPFD, 20);
+		tmp = errno;
+		(void)close(fd);
+		errno = tmp;
+		fd = new;
+		err = "accept/fcntl";
+	}
+#endif
+
+	if (fd < 0) {
+		if (SOFT_ERROR(errno))
+			goto soft_error;
+		switch (errno) {
+		case ENFILE:
+		case EMFILE:
+			isc_log_iwrite(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+				       ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
+				       isc_msgcat, ISC_MSGSET_SOCKET,
+				       ISC_MSG_TOOMANYFDS,
+				       "%s: too many open file descriptors",
+				       err);
+			goto soft_error;
+
+		case ENOBUFS:
+		case ENOMEM:
+		case ECONNRESET:
+		case ECONNABORTED:
+		case EHOSTUNREACH:
+		case EHOSTDOWN:
+		case ENETUNREACH:
+		case ENETDOWN:
+		case ECONNREFUSED:
+#ifdef EPROTO
+		case EPROTO:
+#endif
+#ifdef ENONET
+		case ENONET:
+#endif
+			goto soft_error;
+		default:
+			break;
+		}
+		isc__strerror(errno, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "internal_accept: %s() %s: %s", err,
+				 isc_msgcat_get(isc_msgcat,
+						ISC_MSGSET_GENERAL,
+						ISC_MSG_FAILED,
+						"failed"),
+				 strbuf);
+		fd = -1;
+		result = ISC_R_UNEXPECTED;
+	} else {
+		if (addrlen == 0U) {
+			UNEXPECTED_ERROR(__FILE__, __LINE__,
+					 "internal_accept(): "
+					 "accept() failed to return "
+					 "remote address");
+
+			(void)close(fd);
+			goto soft_error;
+		} else if (NEWCONNSOCK(dev)->peer_address.type.sa.sa_family !=
+			   sock->pf)
+		{
+			UNEXPECTED_ERROR(__FILE__, __LINE__,
+					 "internal_accept(): "
+					 "accept() returned peer address "
+					 "family %u (expected %u)",
+					 NEWCONNSOCK(dev)->peer_address.
+					 type.sa.sa_family,
+					 sock->pf);
+			(void)close(fd);
+			goto soft_error;
+		} else if (fd >= (int)manager->maxsocks) {
+			isc_log_iwrite(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+				       ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
+				       isc_msgcat, ISC_MSGSET_SOCKET,
+				       ISC_MSG_TOOMANYFDS,
+				       "accept: "
+				       "file descriptor exceeds limit (%d/%u)",
+				       fd, manager->maxsocks);
+			(void)close(fd);
+			goto soft_error;
+		}
+	}
+
+	if (fd != -1) {
+		NEWCONNSOCK(dev)->peer_address.length = addrlen;
+		NEWCONNSOCK(dev)->pf = sock->pf;
+	}
+
+	/*
+	 * Pull off the done event.
+	 */
+	ISC_LIST_UNLINK(sock->accept_list, dev, ev_link);
+
+	/*
+	 * Poke watcher if there are more pending accepts.
+	 */
+	if (!ISC_LIST_EMPTY(sock->accept_list))
+		select_poke(sock->manager, sock->fd, SELECT_POKE_ACCEPT);
+
+	UNLOCK(&sock->lock);
+
+	if (fd != -1 && (make_nonblock(fd) != ISC_R_SUCCESS)) {
+		(void)close(fd);
+		fd = -1;
+		result = ISC_R_UNEXPECTED;
+	}
+
+	/*
+	 * -1 means the new socket didn't happen.
+	 */
+	if (fd != -1) {
+		int lockid = FDLOCK_ID(fd);
+
+		LOCK(&manager->fdlock[lockid]);
+		manager->fds[fd] = NEWCONNSOCK(dev);
+		manager->fdstate[fd] = MANAGED;
+		UNLOCK(&manager->fdlock[lockid]);
+
+		LOCK(&manager->lock);
+		ISC_LIST_APPEND(manager->socklist, NEWCONNSOCK(dev), link);
+
+		NEWCONNSOCK(dev)->fd = fd;
+		NEWCONNSOCK(dev)->bound = 1;
+		NEWCONNSOCK(dev)->connected = 1;
+
+		/*
+		 * Save away the remote address
+		 */
+		dev->address = NEWCONNSOCK(dev)->peer_address;
+
+#ifdef USE_SELECT
+		if (manager->maxfd < fd)
+			manager->maxfd = fd;
+#endif
+
+		socket_log(sock, &NEWCONNSOCK(dev)->peer_address, CREATION,
+			   isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTEDCXN,
+			   "accepted connection, new socket %p",
+			   dev->newsocket);
+
+		UNLOCK(&manager->lock);
+
+		inc_stats(manager->stats, sock->statsindex[STATID_ACCEPT]);
+	} else {
+		inc_stats(manager->stats, sock->statsindex[STATID_ACCEPTFAIL]);
+		NEWCONNSOCK(dev)->references--;
+		free_socket((isc__socket_t **)&dev->newsocket);
+	}
+
+	/*
+	 * Fill in the done event details and send it off.
+	 */
+	dev->result = result;
+	task = dev->ev_sender;
+	dev->ev_sender = sock;
+
+	isc_task_sendanddetach(&task, ISC_EVENT_PTR(&dev));
+	return;
+
+ soft_error:
+	select_poke(sock->manager, sock->fd, SELECT_POKE_ACCEPT);
+	UNLOCK(&sock->lock);
+
+	inc_stats(manager->stats, sock->statsindex[STATID_ACCEPTFAIL]);
+	return;
+}
+
+static void
+internal_recv(isc_task_t *me, isc_event_t *ev) {
+	isc_socketevent_t *dev;
+	isc__socket_t *sock;
+
+	INSIST(ev->ev_type == ISC_SOCKEVENT_INTR);
+
+	sock = ev->ev_sender;
+	INSIST(VALID_SOCKET(sock));
+
+	LOCK(&sock->lock);
+	socket_log(sock, NULL, IOEVENT,
+		   isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_INTERNALRECV,
+		   "internal_recv: task %p got event %p", me, ev);
+
+	INSIST(sock->pending_recv == 1);
+	sock->pending_recv = 0;
+
+	INSIST(sock->references > 0);
+	sock->references--;  /* the internal event is done with this socket */
+	if (sock->references == 0) {
+		UNLOCK(&sock->lock);
+		destroy(&sock);
+		return;
+	}
+
+	/*
+	 * Try to do as much I/O as possible on this socket.  There are no
+	 * limits here, currently.
+	 */
+	dev = ISC_LIST_HEAD(sock->recv_list);
+	while (dev != NULL) {
+		switch (doio_recv(sock, dev)) {
+		case DOIO_SOFT:
+			goto poke;
+
+		case DOIO_EOF:
+			/*
+			 * read of 0 means the remote end was closed.
+			 * Run through the event queue and dispatch all
+			 * the events with an EOF result code.
+			 */
+			do {
+				dev->result = ISC_R_EOF;
+				send_recvdone_event(sock, &dev);
+				dev = ISC_LIST_HEAD(sock->recv_list);
+			} while (dev != NULL);
+			goto poke;
+
+		case DOIO_SUCCESS:
+		case DOIO_HARD:
+			send_recvdone_event(sock, &dev);
+			break;
+		}
+
+		dev = ISC_LIST_HEAD(sock->recv_list);
+	}
+
+ poke:
+	if (!ISC_LIST_EMPTY(sock->recv_list))
+		select_poke(sock->manager, sock->fd, SELECT_POKE_READ);
+
+	UNLOCK(&sock->lock);
+}
+
+static void
+internal_send(isc_task_t *me, isc_event_t *ev) {
+	isc_socketevent_t *dev;
+	isc__socket_t *sock;
+
+	INSIST(ev->ev_type == ISC_SOCKEVENT_INTW);
+
+	/*
+	 * Find out what socket this is and lock it.
+	 */
+	sock = (isc__socket_t *)ev->ev_sender;
+	INSIST(VALID_SOCKET(sock));
+
+	LOCK(&sock->lock);
+	socket_log(sock, NULL, IOEVENT,
+		   isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_INTERNALSEND,
+		   "internal_send: task %p got event %p", me, ev);
+
+	INSIST(sock->pending_send == 1);
+	sock->pending_send = 0;
+
+	INSIST(sock->references > 0);
+	sock->references--;  /* the internal event is done with this socket */
+	if (sock->references == 0) {
+		UNLOCK(&sock->lock);
+		destroy(&sock);
+		return;
+	}
+
+	/*
+	 * Try to do as much I/O as possible on this socket.  There are no
+	 * limits here, currently.
+	 */
+	dev = ISC_LIST_HEAD(sock->send_list);
+	while (dev != NULL) {
+		switch (doio_send(sock, dev)) {
+		case DOIO_SOFT:
+			goto poke;
+
+		case DOIO_HARD:
+		case DOIO_SUCCESS:
+			send_senddone_event(sock, &dev);
+			break;
+		}
+
+		dev = ISC_LIST_HEAD(sock->send_list);
+	}
+
+ poke:
+	if (!ISC_LIST_EMPTY(sock->send_list))
+		select_poke(sock->manager, sock->fd, SELECT_POKE_WRITE);
+
+	UNLOCK(&sock->lock);
+}
+
+static void
+internal_fdwatch_write(isc_task_t *me, isc_event_t *ev) {
+	isc__socket_t *sock;
+	int more_data;
+
+	INSIST(ev->ev_type == ISC_SOCKEVENT_INTW);
+
+	/*
+	 * Find out what socket this is and lock it.
+	 */
+	sock = (isc__socket_t *)ev->ev_sender;
+	INSIST(VALID_SOCKET(sock));
+
+	LOCK(&sock->lock);
+	socket_log(sock, NULL, IOEVENT,
+		   isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_INTERNALSEND,
+		   "internal_fdwatch_write: task %p got event %p", me, ev);
+
+	INSIST(sock->pending_send == 1);
+
+	UNLOCK(&sock->lock);
+	more_data = (sock->fdwatchcb)(me, (isc_socket_t *)sock,
+				      sock->fdwatcharg, ISC_SOCKFDWATCH_WRITE);
+	LOCK(&sock->lock);
+
+	sock->pending_send = 0;
+
+	INSIST(sock->references > 0);
+	sock->references--;  /* the internal event is done with this socket */
+	if (sock->references == 0) {
+		UNLOCK(&sock->lock);
+		destroy(&sock);
+		return;
+	}
+
+	if (more_data)
+		select_poke(sock->manager, sock->fd, SELECT_POKE_WRITE);
+
+	UNLOCK(&sock->lock);
+}
+
+static void
+internal_fdwatch_read(isc_task_t *me, isc_event_t *ev) {
+	isc__socket_t *sock;
+	int more_data;
+
+	INSIST(ev->ev_type == ISC_SOCKEVENT_INTR);
+
+	/*
+	 * Find out what socket this is and lock it.
+	 */
+	sock = (isc__socket_t *)ev->ev_sender;
+	INSIST(VALID_SOCKET(sock));
+
+	LOCK(&sock->lock);
+	socket_log(sock, NULL, IOEVENT,
+		   isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_INTERNALRECV,
+		   "internal_fdwatch_read: task %p got event %p", me, ev);
+
+	INSIST(sock->pending_recv == 1);
+
+	UNLOCK(&sock->lock);
+	more_data = (sock->fdwatchcb)(me, (isc_socket_t *)sock,
+				      sock->fdwatcharg, ISC_SOCKFDWATCH_READ);
+	LOCK(&sock->lock);
+
+	sock->pending_recv = 0;
+
+	INSIST(sock->references > 0);
+	sock->references--;  /* the internal event is done with this socket */
+	if (sock->references == 0) {
+		UNLOCK(&sock->lock);
+		destroy(&sock);
+		return;
+	}
+
+	if (more_data)
+		select_poke(sock->manager, sock->fd, SELECT_POKE_READ);
+
+	UNLOCK(&sock->lock);
+}
+
+/*
+ * Process read/writes on each fd here.  Avoid locking
+ * and unlocking twice if both reads and writes are possible.
+ */
+static void
+process_fd(isc__socketmgr_t *manager, int fd, isc_boolean_t readable,
+	   isc_boolean_t writeable)
+{
+	isc__socket_t *sock;
+	isc_boolean_t unlock_sock;
+	isc_boolean_t unwatch_read = ISC_FALSE, unwatch_write = ISC_FALSE;
+	int lockid = FDLOCK_ID(fd);
+
+	/*
+	 * If the socket is going to be closed, don't do more I/O.
+	 */
+	LOCK(&manager->fdlock[lockid]);
+	if (manager->fdstate[fd] == CLOSE_PENDING) {
+		UNLOCK(&manager->fdlock[lockid]);
+
+		(void)unwatch_fd(manager, fd, SELECT_POKE_READ);
+		(void)unwatch_fd(manager, fd, SELECT_POKE_WRITE);
+		return;
+	}
+
+	sock = manager->fds[fd];
+	unlock_sock = ISC_FALSE;
+	if (readable) {
+		if (sock == NULL) {
+			unwatch_read = ISC_TRUE;
+			goto check_write;
+		}
+		unlock_sock = ISC_TRUE;
+		LOCK(&sock->lock);
+		if (!SOCK_DEAD(sock)) {
+			if (sock->listener)
+				dispatch_accept(sock);
+			else
+				dispatch_recv(sock);
+		}
+		unwatch_read = ISC_TRUE;
+	}
+check_write:
+	if (writeable) {
+		if (sock == NULL) {
+			unwatch_write = ISC_TRUE;
+			goto unlock_fd;
+		}
+		if (!unlock_sock) {
+			unlock_sock = ISC_TRUE;
+			LOCK(&sock->lock);
+		}
+		if (!SOCK_DEAD(sock)) {
+			if (sock->connecting)
+				dispatch_connect(sock);
+			else
+				dispatch_send(sock);
+		}
+		unwatch_write = ISC_TRUE;
+	}
+	if (unlock_sock)
+		UNLOCK(&sock->lock);
+
+ unlock_fd:
+	UNLOCK(&manager->fdlock[lockid]);
+	if (unwatch_read)
+		(void)unwatch_fd(manager, fd, SELECT_POKE_READ);
+	if (unwatch_write)
+		(void)unwatch_fd(manager, fd, SELECT_POKE_WRITE);
+
+}
+
+#ifdef USE_KQUEUE
+static isc_boolean_t
+process_fds(isc__socketmgr_t *manager, struct kevent *events, int nevents) {
+	int i;
+	isc_boolean_t readable, writable;
+	isc_boolean_t done = ISC_FALSE;
+#ifdef USE_WATCHER_THREAD
+	isc_boolean_t have_ctlevent = ISC_FALSE;
+#endif
+
+	if (nevents == manager->nevents) {
+		/*
+		 * This is not an error, but something unexpected.  If this
+		 * happens, it may indicate the need for increasing
+		 * ISC_SOCKET_MAXEVENTS.
+		 */
+		manager_log(manager, ISC_LOGCATEGORY_GENERAL,
+			    ISC_LOGMODULE_SOCKET, ISC_LOG_INFO,
+			    "maximum number of FD events (%d) received",
+			    nevents);
+	}
+
+	for (i = 0; i < nevents; i++) {
+		REQUIRE(events[i].ident < manager->maxsocks);
+#ifdef USE_WATCHER_THREAD
+		if (events[i].ident == (uintptr_t)manager->pipe_fds[0]) {
+			have_ctlevent = ISC_TRUE;
+			continue;
+		}
+#endif
+		readable = ISC_TF(events[i].filter == EVFILT_READ);
+		writable = ISC_TF(events[i].filter == EVFILT_WRITE);
+		process_fd(manager, events[i].ident, readable, writable);
+	}
+
+#ifdef USE_WATCHER_THREAD
+	if (have_ctlevent)
+		done = process_ctlfd(manager);
+#endif
+
+	return (done);
+}
+#elif defined(USE_EPOLL)
+static isc_boolean_t
+process_fds(isc__socketmgr_t *manager, struct epoll_event *events, int nevents)
+{
+	int i;
+	isc_boolean_t done = ISC_FALSE;
+#ifdef USE_WATCHER_THREAD
+	isc_boolean_t have_ctlevent = ISC_FALSE;
+#endif
+
+	if (nevents == manager->nevents) {
+		manager_log(manager, ISC_LOGCATEGORY_GENERAL,
+			    ISC_LOGMODULE_SOCKET, ISC_LOG_INFO,
+			    "maximum number of FD events (%d) received",
+			    nevents);
+	}
+
+	for (i = 0; i < nevents; i++) {
+		REQUIRE(events[i].data.fd < (int)manager->maxsocks);
+#ifdef USE_WATCHER_THREAD
+		if (events[i].data.fd == manager->pipe_fds[0]) {
+			have_ctlevent = ISC_TRUE;
+			continue;
+		}
+#endif
+		if ((events[i].events & EPOLLERR) != 0 ||
+		    (events[i].events & EPOLLHUP) != 0) {
+			/*
+			 * epoll does not set IN/OUT bits on an erroneous
+			 * condition, so we need to try both anyway.  This is a
+			 * bit inefficient, but should be okay for such rare
+			 * events.  Note also that the read or write attempt
+			 * won't block because we use non-blocking sockets.
+			 */
+			events[i].events |= (EPOLLIN | EPOLLOUT);
+		}
+		process_fd(manager, events[i].data.fd,
+			   (events[i].events & EPOLLIN) != 0,
+			   (events[i].events & EPOLLOUT) != 0);
+	}
+
+#ifdef USE_WATCHER_THREAD
+	if (have_ctlevent)
+		done = process_ctlfd(manager);
+#endif
+
+	return (done);
+}
+#elif defined(USE_DEVPOLL)
+static isc_boolean_t
+process_fds(isc__socketmgr_t *manager, struct pollfd *events, int nevents) {
+	int i;
+	isc_boolean_t done = ISC_FALSE;
+#ifdef USE_WATCHER_THREAD
+	isc_boolean_t have_ctlevent = ISC_FALSE;
+#endif
+
+	if (nevents == manager->nevents) {
+		manager_log(manager, ISC_LOGCATEGORY_GENERAL,
+			    ISC_LOGMODULE_SOCKET, ISC_LOG_INFO,
+			    "maximum number of FD events (%d) received",
+			    nevents);
+	}
+
+	for (i = 0; i < nevents; i++) {
+		REQUIRE(events[i].fd < (int)manager->maxsocks);
+#ifdef USE_WATCHER_THREAD
+		if (events[i].fd == manager->pipe_fds[0]) {
+			have_ctlevent = ISC_TRUE;
+			continue;
+		}
+#endif
+		process_fd(manager, events[i].fd,
+			   (events[i].events & POLLIN) != 0,
+			   (events[i].events & POLLOUT) != 0);
+	}
+
+#ifdef USE_WATCHER_THREAD
+	if (have_ctlevent)
+		done = process_ctlfd(manager);
+#endif
+
+	return (done);
+}
+#elif defined(USE_SELECT)
+static void
+process_fds(isc__socketmgr_t *manager, int maxfd, fd_set *readfds,
+	    fd_set *writefds)
+{
+	int i;
+
+	REQUIRE(maxfd <= (int)manager->maxsocks);
+
+	for (i = 0; i < maxfd; i++) {
+#ifdef USE_WATCHER_THREAD
+		if (i == manager->pipe_fds[0] || i == manager->pipe_fds[1])
+			continue;
+#endif /* USE_WATCHER_THREAD */
+		process_fd(manager, i, FD_ISSET(i, readfds),
+			   FD_ISSET(i, writefds));
+	}
+}
+#endif
+
+#ifdef USE_WATCHER_THREAD
+static isc_boolean_t
+process_ctlfd(isc__socketmgr_t *manager) {
+	int msg, fd;
+
+	for (;;) {
+		select_readmsg(manager, &fd, &msg);
+
+		manager_log(manager, IOEVENT,
+			    isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
+					   ISC_MSG_WATCHERMSG,
+					   "watcher got message %d "
+					   "for socket %d"), msg, fd);
+
+		/*
+		 * Nothing to read?
+		 */
+		if (msg == SELECT_POKE_NOTHING)
+			break;
+
+		/*
+		 * Handle shutdown message.  We really should
+		 * jump out of this loop right away, but
+		 * it doesn't matter if we have to do a little
+		 * more work first.
+		 */
+		if (msg == SELECT_POKE_SHUTDOWN)
+			return (ISC_TRUE);
+
+		/*
+		 * This is a wakeup on a socket.  Look
+		 * at the event queue for both read and write,
+		 * and decide if we need to watch on it now
+		 * or not.
+		 */
+		wakeup_socket(manager, fd, msg);
+	}
+
+	return (ISC_FALSE);
+}
+
+/*
+ * This is the thread that will loop forever, always in a select or poll
+ * call.
+ *
+ * When select returns something to do, track down what thread gets to do
+ * this I/O and post the event to it.
+ */
+static isc_threadresult_t
+watcher(void *uap) {
+	isc__socketmgr_t *manager = uap;
+	isc_boolean_t done;
+	int ctlfd;
+	int cc;
+#ifdef USE_KQUEUE
+	const char *fnname = "kevent()";
+#elif defined (USE_EPOLL)
+	const char *fnname = "epoll_wait()";
+#elif defined(USE_DEVPOLL)
+	const char *fnname = "ioctl(DP_POLL)";
+	struct dvpoll dvp;
+#elif defined (USE_SELECT)
+	const char *fnname = "select()";
+	int maxfd;
+#endif
+	char strbuf[ISC_STRERRORSIZE];
+#ifdef ISC_SOCKET_USE_POLLWATCH
+	pollstate_t pollstate = poll_idle;
+#endif
+
+	/*
+	 * Get the control fd here.  This will never change.
+	 */
+	ctlfd = manager->pipe_fds[0];
+	done = ISC_FALSE;
+	while (!done) {
+		do {
+#ifdef USE_KQUEUE
+			cc = kevent(manager->kqueue_fd, NULL, 0,
+				    manager->events, manager->nevents, NULL);
+#elif defined(USE_EPOLL)
+			cc = epoll_wait(manager->epoll_fd, manager->events,
+					manager->nevents, -1);
+#elif defined(USE_DEVPOLL)
+			dvp.dp_fds = manager->events;
+			dvp.dp_nfds = manager->nevents;
+#ifndef ISC_SOCKET_USE_POLLWATCH
+			dvp.dp_timeout = -1;
+#else
+			if (pollstate == poll_idle)
+				dvp.dp_timeout = -1;
+			else
+				dvp.dp_timeout = ISC_SOCKET_POLLWATCH_TIMEOUT;
+#endif	/* ISC_SOCKET_USE_POLLWATCH */
+			cc = ioctl(manager->devpoll_fd, DP_POLL, &dvp);
+#elif defined(USE_SELECT)
+			LOCK(&manager->lock);
+			memcpy(manager->read_fds_copy, manager->read_fds,
+			       manager->fd_bufsize);
+			memcpy(manager->write_fds_copy, manager->write_fds,
+			       manager->fd_bufsize);
+			maxfd = manager->maxfd + 1;
+			UNLOCK(&manager->lock);
+
+			cc = select(maxfd, manager->read_fds_copy,
+				    manager->write_fds_copy, NULL, NULL);
+#endif	/* USE_KQUEUE */
+
+			if (cc < 0 && !SOFT_ERROR(errno)) {
+				isc__strerror(errno, strbuf, sizeof(strbuf));
+				FATAL_ERROR(__FILE__, __LINE__,
+					    "%s %s: %s", fnname,
+					    isc_msgcat_get(isc_msgcat,
+							   ISC_MSGSET_GENERAL,
+							   ISC_MSG_FAILED,
+							   "failed"), strbuf);
+			}
+
+#if defined(USE_DEVPOLL) && defined(ISC_SOCKET_USE_POLLWATCH)
+			if (cc == 0) {
+				if (pollstate == poll_active)
+					pollstate = poll_checking;
+				else if (pollstate == poll_checking)
+					pollstate = poll_idle;
+			} else if (cc > 0) {
+				if (pollstate == poll_checking) {
+					/*
+					 * XXX: We'd like to use a more
+					 * verbose log level as it's actually an
+					 * unexpected event, but the kernel bug
+					 * reportedly happens pretty frequently
+					 * (and it can also be a false positive)
+					 * so it would be just too noisy.
+					 */
+					manager_log(manager,
+						    ISC_LOGCATEGORY_GENERAL,
+						    ISC_LOGMODULE_SOCKET,
+						    ISC_LOG_DEBUG(1),
+						    "unexpected POLL timeout");
+				}
+				pollstate = poll_active;
+			}
+#endif
+		} while (cc < 0);
+
+#if defined(USE_KQUEUE) || defined (USE_EPOLL) || defined (USE_DEVPOLL)
+		done = process_fds(manager, manager->events, cc);
+#elif defined(USE_SELECT)
+		process_fds(manager, maxfd, manager->read_fds_copy,
+			    manager->write_fds_copy);
+
+		/*
+		 * Process reads on internal, control fd.
+		 */
+		if (FD_ISSET(ctlfd, manager->read_fds_copy))
+			done = process_ctlfd(manager);
+#endif
+	}
+
+	manager_log(manager, TRACE, "%s",
+		    isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+				   ISC_MSG_EXITING, "watcher exiting"));
+
+	return ((isc_threadresult_t)0);
+}
+#endif /* USE_WATCHER_THREAD */
+
+#ifdef BIND9
+ISC_SOCKETFUNC_SCOPE void
+isc__socketmgr_setreserved(isc_socketmgr_t *manager0, isc_uint32_t reserved) {
+	isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0;
+
+	REQUIRE(VALID_MANAGER(manager));
+
+	manager->reserved = reserved;
+}
+
+ISC_SOCKETFUNC_SCOPE void
+isc___socketmgr_maxudp(isc_socketmgr_t *manager0, int maxudp) {
+	isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0;
+
+	REQUIRE(VALID_MANAGER(manager));
+
+	manager->maxudp = maxudp;
+}
+#endif	/* BIND9 */
+
+/*
+ * Create a new socket manager.
+ */
+
+static isc_result_t
+setup_watcher(isc_mem_t *mctx, isc__socketmgr_t *manager) {
+	isc_result_t result;
+#if defined(USE_KQUEUE) || defined(USE_EPOLL) || defined(USE_DEVPOLL)
+	char strbuf[ISC_STRERRORSIZE];
+#endif
+
+#ifdef USE_KQUEUE
+	manager->nevents = ISC_SOCKET_MAXEVENTS;
+	manager->events = isc_mem_get(mctx, sizeof(struct kevent) *
+				      manager->nevents);
+	if (manager->events == NULL)
+		return (ISC_R_NOMEMORY);
+	manager->kqueue_fd = kqueue();
+	if (manager->kqueue_fd == -1) {
+		result = isc__errno2result(errno);
+		isc__strerror(errno, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "kqueue %s: %s",
+				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+						ISC_MSG_FAILED, "failed"),
+				 strbuf);
+		isc_mem_put(mctx, manager->events,
+			    sizeof(struct kevent) * manager->nevents);
+		return (result);
+	}
+
+#ifdef USE_WATCHER_THREAD
+	result = watch_fd(manager, manager->pipe_fds[0], SELECT_POKE_READ);
+	if (result != ISC_R_SUCCESS) {
+		close(manager->kqueue_fd);
+		isc_mem_put(mctx, manager->events,
+			    sizeof(struct kevent) * manager->nevents);
+		return (result);
+	}
+#endif	/* USE_WATCHER_THREAD */
+#elif defined(USE_EPOLL)
+	manager->nevents = ISC_SOCKET_MAXEVENTS;
+	manager->events = isc_mem_get(mctx, sizeof(struct epoll_event) *
+				      manager->nevents);
+	if (manager->events == NULL)
+		return (ISC_R_NOMEMORY);
+	manager->epoll_fd = epoll_create(manager->nevents);
+	if (manager->epoll_fd == -1) {
+		result = isc__errno2result(errno);
+		isc__strerror(errno, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "epoll_create %s: %s",
+				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+						ISC_MSG_FAILED, "failed"),
+				 strbuf);
+		isc_mem_put(mctx, manager->events,
+			    sizeof(struct epoll_event) * manager->nevents);
+		return (result);
+	}
+#ifdef USE_WATCHER_THREAD
+	result = watch_fd(manager, manager->pipe_fds[0], SELECT_POKE_READ);
+	if (result != ISC_R_SUCCESS) {
+		close(manager->epoll_fd);
+		isc_mem_put(mctx, manager->events,
+			    sizeof(struct epoll_event) * manager->nevents);
+		return (result);
+	}
+#endif	/* USE_WATCHER_THREAD */
+#elif defined(USE_DEVPOLL)
+	/*
+	 * XXXJT: /dev/poll seems to reject large numbers of events,
+	 * so we should be careful about redefining ISC_SOCKET_MAXEVENTS.
+	 */
+	manager->nevents = ISC_SOCKET_MAXEVENTS;
+	manager->events = isc_mem_get(mctx, sizeof(struct pollfd) *
+				      manager->nevents);
+	if (manager->events == NULL)
+		return (ISC_R_NOMEMORY);
+	/*
+	 * Note: fdpollinfo should be able to support all possible FDs, so
+	 * it must have maxsocks entries (not nevents).
+	 */
+	manager->fdpollinfo = isc_mem_get(mctx, sizeof(pollinfo_t) *
+					  manager->maxsocks);
+	if (manager->fdpollinfo == NULL) {
+		isc_mem_put(mctx, manager->events,
+			    sizeof(struct pollfd) * manager->nevents);
+		return (ISC_R_NOMEMORY);
+	}
+	memset(manager->fdpollinfo, 0, sizeof(pollinfo_t) * manager->maxsocks);
+	manager->devpoll_fd = open("/dev/poll", O_RDWR);
+	if (manager->devpoll_fd == -1) {
+		result = isc__errno2result(errno);
+		isc__strerror(errno, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "open(/dev/poll) %s: %s",
+				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+						ISC_MSG_FAILED, "failed"),
+				 strbuf);
+		isc_mem_put(mctx, manager->events,
+			    sizeof(struct pollfd) * manager->nevents);
+		isc_mem_put(mctx, manager->fdpollinfo,
+			    sizeof(pollinfo_t) * manager->maxsocks);
+		return (result);
+	}
+#ifdef USE_WATCHER_THREAD
+	result = watch_fd(manager, manager->pipe_fds[0], SELECT_POKE_READ);
+	if (result != ISC_R_SUCCESS) {
+		close(manager->devpoll_fd);
+		isc_mem_put(mctx, manager->events,
+			    sizeof(struct pollfd) * manager->nevents);
+		isc_mem_put(mctx, manager->fdpollinfo,
+			    sizeof(pollinfo_t) * manager->maxsocks);
+		return (result);
+	}
+#endif	/* USE_WATCHER_THREAD */
+#elif defined(USE_SELECT)
+	UNUSED(result);
+
+#if ISC_SOCKET_MAXSOCKETS > FD_SETSIZE
+	/*
+	 * Note: this code should also cover the case of MAXSOCKETS <=
+	 * FD_SETSIZE, but we separate the cases to avoid possible portability
+	 * issues regarding howmany() and the actual representation of fd_set.
+	 */
+	manager->fd_bufsize = howmany(manager->maxsocks, NFDBITS) *
+		sizeof(fd_mask);
+#else
+	manager->fd_bufsize = sizeof(fd_set);
+#endif
+
+	manager->read_fds = NULL;
+	manager->read_fds_copy = NULL;
+	manager->write_fds = NULL;
+	manager->write_fds_copy = NULL;
+
+	manager->read_fds = isc_mem_get(mctx, manager->fd_bufsize);
+	if (manager->read_fds != NULL)
+		manager->read_fds_copy = isc_mem_get(mctx, manager->fd_bufsize);
+	if (manager->read_fds_copy != NULL)
+		manager->write_fds = isc_mem_get(mctx, manager->fd_bufsize);
+	if (manager->write_fds != NULL) {
+		manager->write_fds_copy = isc_mem_get(mctx,
+						      manager->fd_bufsize);
+	}
+	if (manager->write_fds_copy == NULL) {
+		if (manager->write_fds != NULL) {
+			isc_mem_put(mctx, manager->write_fds,
+				    manager->fd_bufsize);
+		}
+		if (manager->read_fds_copy != NULL) {
+			isc_mem_put(mctx, manager->read_fds_copy,
+				    manager->fd_bufsize);
+		}
+		if (manager->read_fds != NULL) {
+			isc_mem_put(mctx, manager->read_fds,
+				    manager->fd_bufsize);
+		}
+		return (ISC_R_NOMEMORY);
+	}
+	memset(manager->read_fds, 0, manager->fd_bufsize);
+	memset(manager->write_fds, 0, manager->fd_bufsize);
+
+#ifdef USE_WATCHER_THREAD
+	(void)watch_fd(manager, manager->pipe_fds[0], SELECT_POKE_READ);
+	manager->maxfd = manager->pipe_fds[0];
+#else /* USE_WATCHER_THREAD */
+	manager->maxfd = 0;
+#endif /* USE_WATCHER_THREAD */
+#endif	/* USE_KQUEUE */
+
+	return (ISC_R_SUCCESS);
+}
+
+static void
+cleanup_watcher(isc_mem_t *mctx, isc__socketmgr_t *manager) {
+#ifdef USE_WATCHER_THREAD
+	isc_result_t result;
+
+	result = unwatch_fd(manager, manager->pipe_fds[0], SELECT_POKE_READ);
+	if (result != ISC_R_SUCCESS) {
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "epoll_ctl(DEL) %s",
+				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+						ISC_MSG_FAILED, "failed"));
+	}
+#endif	/* USE_WATCHER_THREAD */
+
+#ifdef USE_KQUEUE
+	close(manager->kqueue_fd);
+	isc_mem_put(mctx, manager->events,
+		    sizeof(struct kevent) * manager->nevents);
+#elif defined(USE_EPOLL)
+	close(manager->epoll_fd);
+	isc_mem_put(mctx, manager->events,
+		    sizeof(struct epoll_event) * manager->nevents);
+#elif defined(USE_DEVPOLL)
+	close(manager->devpoll_fd);
+	isc_mem_put(mctx, manager->events,
+		    sizeof(struct pollfd) * manager->nevents);
+	isc_mem_put(mctx, manager->fdpollinfo,
+		    sizeof(pollinfo_t) * manager->maxsocks);
+#elif defined(USE_SELECT)
+	if (manager->read_fds != NULL)
+		isc_mem_put(mctx, manager->read_fds, manager->fd_bufsize);
+	if (manager->read_fds_copy != NULL)
+		isc_mem_put(mctx, manager->read_fds_copy, manager->fd_bufsize);
+	if (manager->write_fds != NULL)
+		isc_mem_put(mctx, manager->write_fds, manager->fd_bufsize);
+	if (manager->write_fds_copy != NULL)
+		isc_mem_put(mctx, manager->write_fds_copy, manager->fd_bufsize);
+#endif	/* USE_KQUEUE */
+}
+
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) {
+	return (isc__socketmgr_create2(mctx, managerp, 0));
+}
+
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
+		       unsigned int maxsocks)
+{
+	int i;
+	isc__socketmgr_t *manager;
+#ifdef USE_WATCHER_THREAD
+	char strbuf[ISC_STRERRORSIZE];
+#endif
+	isc_result_t result;
+
+	REQUIRE(managerp != NULL && *managerp == NULL);
+
+#ifdef USE_SHARED_MANAGER
+	if (socketmgr != NULL) {
+		/* Don't allow maxsocks to be updated */
+		if (maxsocks > 0 && socketmgr->maxsocks != maxsocks)
+			return (ISC_R_EXISTS);
+
+		socketmgr->refs++;
+		*managerp = (isc_socketmgr_t *)socketmgr;
+		return (ISC_R_SUCCESS);
+	}
+#endif /* USE_SHARED_MANAGER */
+
+	if (maxsocks == 0)
+		maxsocks = ISC_SOCKET_MAXSOCKETS;
+
+	manager = isc_mem_get(mctx, sizeof(*manager));
+	if (manager == NULL)
+		return (ISC_R_NOMEMORY);
+
+	/* zero-clear so that necessary cleanup on failure will be easy */
+	memset(manager, 0, sizeof(*manager));
+	manager->maxsocks = maxsocks;
+	manager->reserved = 0;
+	manager->maxudp = 0;
+	manager->fds = isc_mem_get(mctx,
+				   manager->maxsocks * sizeof(isc__socket_t *));
+	if (manager->fds == NULL) {
+		result = ISC_R_NOMEMORY;
+		goto free_manager;
+	}
+	manager->fdstate = isc_mem_get(mctx, manager->maxsocks * sizeof(int));
+	if (manager->fdstate == NULL) {
+		result = ISC_R_NOMEMORY;
+		goto free_manager;
+	}
+	manager->stats = NULL;
+
+	manager->common.methods = &socketmgrmethods;
+	manager->common.magic = ISCAPI_SOCKETMGR_MAGIC;
+	manager->common.impmagic = SOCKET_MANAGER_MAGIC;
+	manager->mctx = NULL;
+	memset(manager->fds, 0, manager->maxsocks * sizeof(isc_socket_t *));
+	ISC_LIST_INIT(manager->socklist);
+	result = isc_mutex_init(&manager->lock);
+	if (result != ISC_R_SUCCESS)
+		goto free_manager;
+	manager->fdlock = isc_mem_get(mctx, FDLOCK_COUNT * sizeof(isc_mutex_t));
+	if (manager->fdlock == NULL) {
+		result = ISC_R_NOMEMORY;
+		goto cleanup_lock;
+	}
+	for (i = 0; i < FDLOCK_COUNT; i++) {
+		result = isc_mutex_init(&manager->fdlock[i]);
+		if (result != ISC_R_SUCCESS) {
+			while (--i >= 0)
+				DESTROYLOCK(&manager->fdlock[i]);
+			isc_mem_put(mctx, manager->fdlock,
+				    FDLOCK_COUNT * sizeof(isc_mutex_t));
+			manager->fdlock = NULL;
+			goto cleanup_lock;
+		}
+	}
+
+#ifdef USE_WATCHER_THREAD
+	if (isc_condition_init(&manager->shutdown_ok) != ISC_R_SUCCESS) {
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "isc_condition_init() %s",
+				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+						ISC_MSG_FAILED, "failed"));
+		result = ISC_R_UNEXPECTED;
+		goto cleanup_lock;
+	}
+
+	/*
+	 * Create the special fds that will be used to wake up the
+	 * select/poll loop when something internal needs to be done.
+	 */
+	if (pipe(manager->pipe_fds) != 0) {
+		isc__strerror(errno, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "pipe() %s: %s",
+				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+						ISC_MSG_FAILED, "failed"),
+				 strbuf);
+		result = ISC_R_UNEXPECTED;
+		goto cleanup_condition;
+	}
+
+	RUNTIME_CHECK(make_nonblock(manager->pipe_fds[0]) == ISC_R_SUCCESS);
+#if 0
+	RUNTIME_CHECK(make_nonblock(manager->pipe_fds[1]) == ISC_R_SUCCESS);
+#endif
+#endif	/* USE_WATCHER_THREAD */
+
+#ifdef USE_SHARED_MANAGER
+	manager->refs = 1;
+#endif /* USE_SHARED_MANAGER */
+
+	/*
+	 * Set up initial state for the select loop
+	 */
+	result = setup_watcher(mctx, manager);
+	if (result != ISC_R_SUCCESS)
+		goto cleanup;
+	memset(manager->fdstate, 0, manager->maxsocks * sizeof(int));
+#ifdef USE_WATCHER_THREAD
+	/*
+	 * Start up the select/poll thread.
+	 */
+	if (isc_thread_create(watcher, manager, &manager->watcher) !=
+	    ISC_R_SUCCESS) {
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "isc_thread_create() %s",
+				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+						ISC_MSG_FAILED, "failed"));
+		cleanup_watcher(mctx, manager);
+		result = ISC_R_UNEXPECTED;
+		goto cleanup;
+	}
+#endif /* USE_WATCHER_THREAD */
+	isc_mem_attach(mctx, &manager->mctx);
+
+#ifdef USE_SHARED_MANAGER
+	socketmgr = manager;
+#endif /* USE_SHARED_MANAGER */
+	*managerp = (isc_socketmgr_t *)manager;
+
+	return (ISC_R_SUCCESS);
+
+cleanup:
+#ifdef USE_WATCHER_THREAD
+	(void)close(manager->pipe_fds[0]);
+	(void)close(manager->pipe_fds[1]);
+#endif	/* USE_WATCHER_THREAD */
+
+#ifdef USE_WATCHER_THREAD
+cleanup_condition:
+	(void)isc_condition_destroy(&manager->shutdown_ok);
+#endif	/* USE_WATCHER_THREAD */
+
+
+cleanup_lock:
+	if (manager->fdlock != NULL) {
+		for (i = 0; i < FDLOCK_COUNT; i++)
+			DESTROYLOCK(&manager->fdlock[i]);
+	}
+	DESTROYLOCK(&manager->lock);
+
+free_manager:
+	if (manager->fdlock != NULL) {
+		isc_mem_put(mctx, manager->fdlock,
+			    FDLOCK_COUNT * sizeof(isc_mutex_t));
+	}
+	if (manager->fdstate != NULL) {
+		isc_mem_put(mctx, manager->fdstate,
+			    manager->maxsocks * sizeof(int));
+	}
+	if (manager->fds != NULL) {
+		isc_mem_put(mctx, manager->fds,
+			    manager->maxsocks * sizeof(isc_socket_t *));
+	}
+	isc_mem_put(mctx, manager, sizeof(*manager));
+
+	return (result);
+}
+
+#ifdef BIND9
+isc_result_t
+isc__socketmgr_getmaxsockets(isc_socketmgr_t *manager0, unsigned int *nsockp) {
+	isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0;
+	REQUIRE(VALID_MANAGER(manager));
+	REQUIRE(nsockp != NULL);
+
+	*nsockp = manager->maxsocks;
+
+	return (ISC_R_SUCCESS);
+}
+
+void
+isc__socketmgr_setstats(isc_socketmgr_t *manager0, isc_stats_t *stats) {
+	isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0;
+
+	REQUIRE(VALID_MANAGER(manager));
+	REQUIRE(ISC_LIST_EMPTY(manager->socklist));
+	REQUIRE(manager->stats == NULL);
+	REQUIRE(isc_stats_ncounters(stats) == isc_sockstatscounter_max);
+
+	isc_stats_attach(stats, &manager->stats);
+}
+#endif
+
+ISC_SOCKETFUNC_SCOPE void
+isc__socketmgr_destroy(isc_socketmgr_t **managerp) {
+	isc__socketmgr_t *manager;
+	int i;
+	isc_mem_t *mctx;
+
+	/*
+	 * Destroy a socket manager.
+	 */
+
+	REQUIRE(managerp != NULL);
+	manager = (isc__socketmgr_t *)*managerp;
+	REQUIRE(VALID_MANAGER(manager));
+
+#ifdef USE_SHARED_MANAGER
+	manager->refs--;
+	if (manager->refs > 0) {
+		*managerp = NULL;
+		return;
+	}
+	socketmgr = NULL;
+#endif /* USE_SHARED_MANAGER */
+
+	LOCK(&manager->lock);
+
+	/*
+	 * Wait for all sockets to be destroyed.
+	 */
+	while (!ISC_LIST_EMPTY(manager->socklist)) {
+#ifdef USE_WATCHER_THREAD
+		manager_log(manager, CREATION, "%s",
+			    isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
+					   ISC_MSG_SOCKETSREMAIN,
+					   "sockets exist"));
+		WAIT(&manager->shutdown_ok, &manager->lock);
+#else /* USE_WATCHER_THREAD */
+		UNLOCK(&manager->lock);
+		isc__taskmgr_dispatch(NULL);
+		LOCK(&manager->lock);
+#endif /* USE_WATCHER_THREAD */
+	}
+
+	UNLOCK(&manager->lock);
+
+	/*
+	 * Here, poke our select/poll thread.  Do this by closing the write
+	 * half of the pipe, which will send EOF to the read half.
+	 * This is currently a no-op in the non-threaded case.
+	 */
+	select_poke(manager, 0, SELECT_POKE_SHUTDOWN);
+
+#ifdef USE_WATCHER_THREAD
+	/*
+	 * Wait for thread to exit.
+	 */
+	if (isc_thread_join(manager->watcher, NULL) != ISC_R_SUCCESS)
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "isc_thread_join() %s",
+				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+						ISC_MSG_FAILED, "failed"));
+#endif /* USE_WATCHER_THREAD */
+
+	/*
+	 * Clean up.
+	 */
+	cleanup_watcher(manager->mctx, manager);
+
+#ifdef USE_WATCHER_THREAD
+	(void)close(manager->pipe_fds[0]);
+	(void)close(manager->pipe_fds[1]);
+	(void)isc_condition_destroy(&manager->shutdown_ok);
+#endif /* USE_WATCHER_THREAD */
+
+	for (i = 0; i < (int)manager->maxsocks; i++)
+		if (manager->fdstate[i] == CLOSE_PENDING) /* no need to lock */
+			(void)close(i);
+
+	isc_mem_put(manager->mctx, manager->fds,
+		    manager->maxsocks * sizeof(isc__socket_t *));
+	isc_mem_put(manager->mctx, manager->fdstate,
+		    manager->maxsocks * sizeof(int));
+
+	if (manager->stats != NULL)
+		isc_stats_detach(&manager->stats);
+
+	if (manager->fdlock != NULL) {
+		for (i = 0; i < FDLOCK_COUNT; i++)
+			DESTROYLOCK(&manager->fdlock[i]);
+		isc_mem_put(manager->mctx, manager->fdlock,
+			    FDLOCK_COUNT * sizeof(isc_mutex_t));
+	}
+	DESTROYLOCK(&manager->lock);
+	manager->common.magic = 0;
+	manager->common.impmagic = 0;
+	mctx= manager->mctx;
+	isc_mem_put(mctx, manager, sizeof(*manager));
+
+	isc_mem_detach(&mctx);
+
+	*managerp = NULL;
+
+#ifdef USE_SHARED_MANAGER
+	socketmgr = NULL;
+#endif
+}
+
+static isc_result_t
+socket_recv(isc__socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
+	    unsigned int flags)
+{
+	int io_state;
+	isc_boolean_t have_lock = ISC_FALSE;
+	isc_task_t *ntask = NULL;
+	isc_result_t result = ISC_R_SUCCESS;
+
+	dev->ev_sender = task;
+
+	if (sock->type == isc_sockettype_udp) {
+		io_state = doio_recv(sock, dev);
+	} else {
+		LOCK(&sock->lock);
+		have_lock = ISC_TRUE;
+
+		if (ISC_LIST_EMPTY(sock->recv_list))
+			io_state = doio_recv(sock, dev);
+		else
+			io_state = DOIO_SOFT;
+	}
+
+	switch (io_state) {
+	case DOIO_SOFT:
+		/*
+		 * We couldn't read all or part of the request right now, so
+		 * queue it.
+		 *
+		 * Attach to socket and to task
+		 */
+		isc_task_attach(task, &ntask);
+		dev->attributes |= ISC_SOCKEVENTATTR_ATTACHED;
+
+		if (!have_lock) {
+			LOCK(&sock->lock);
+			have_lock = ISC_TRUE;
+		}
+
+		/*
+		 * Enqueue the request.  If the socket was previously not being
+		 * watched, poke the watcher to start paying attention to it.
+		 */
+		if (ISC_LIST_EMPTY(sock->recv_list) && !sock->pending_recv)
+			select_poke(sock->manager, sock->fd, SELECT_POKE_READ);
+		ISC_LIST_ENQUEUE(sock->recv_list, dev, ev_link);
+
+		socket_log(sock, NULL, EVENT, NULL, 0, 0,
+			   "socket_recv: event %p -> task %p",
+			   dev, ntask);
+
+		if ((flags & ISC_SOCKFLAG_IMMEDIATE) != 0)
+			result = ISC_R_INPROGRESS;
+		break;
+
+	case DOIO_EOF:
+		dev->result = ISC_R_EOF;
+		/* fallthrough */
+
+	case DOIO_HARD:
+	case DOIO_SUCCESS:
+		if ((flags & ISC_SOCKFLAG_IMMEDIATE) == 0)
+			send_recvdone_event(sock, &dev);
+		break;
+	}
+
+	if (have_lock)
+		UNLOCK(&sock->lock);
+
+	return (result);
+}
+
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_recvv(isc_socket_t *sock0, isc_bufferlist_t *buflist,
+		  unsigned int minimum, isc_task_t *task,
+		  isc_taskaction_t action, const void *arg)
+{
+	isc__socket_t *sock = (isc__socket_t *)sock0;
+	isc_socketevent_t *dev;
+	isc__socketmgr_t *manager;
+	unsigned int iocount;
+	isc_buffer_t *buffer;
+
+	REQUIRE(VALID_SOCKET(sock));
+	REQUIRE(buflist != NULL);
+	REQUIRE(!ISC_LIST_EMPTY(*buflist));
+	REQUIRE(task != NULL);
+	REQUIRE(action != NULL);
+
+	manager = sock->manager;
+	REQUIRE(VALID_MANAGER(manager));
+
+	iocount = isc_bufferlist_availablecount(buflist);
+	REQUIRE(iocount > 0);
+
+	INSIST(sock->bound);
+
+	dev = allocate_socketevent(sock, ISC_SOCKEVENT_RECVDONE, action, arg);
+	if (dev == NULL) {
+		return (ISC_R_NOMEMORY);
+	}
+
+	/*
+	 * UDP sockets are always partial read
+	 */
+	if (sock->type == isc_sockettype_udp)
+		dev->minimum = 1;
+	else {
+		if (minimum == 0)
+			dev->minimum = iocount;
+		else
+			dev->minimum = minimum;
+	}
+
+	/*
+	 * Move each buffer from the passed in list to our internal one.
+	 */
+	buffer = ISC_LIST_HEAD(*buflist);
+	while (buffer != NULL) {
+		ISC_LIST_DEQUEUE(*buflist, buffer, link);
+		ISC_LIST_ENQUEUE(dev->bufferlist, buffer, link);
+		buffer = ISC_LIST_HEAD(*buflist);
+	}
+
+	return (socket_recv(sock, dev, task, 0));
+}
+
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_recv(isc_socket_t *sock0, isc_region_t *region,
+		 unsigned int minimum, isc_task_t *task,
+		 isc_taskaction_t action, const void *arg)
+{
+	isc__socket_t *sock = (isc__socket_t *)sock0;
+	isc_socketevent_t *dev;
+	isc__socketmgr_t *manager;
+
+	REQUIRE(VALID_SOCKET(sock));
+	REQUIRE(action != NULL);
+
+	manager = sock->manager;
+	REQUIRE(VALID_MANAGER(manager));
+
+	INSIST(sock->bound);
+
+	dev = allocate_socketevent(sock, ISC_SOCKEVENT_RECVDONE, action, arg);
+	if (dev == NULL)
+		return (ISC_R_NOMEMORY);
+
+	return (isc__socket_recv2(sock0, region, minimum, task, dev, 0));
+}
+
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_recv2(isc_socket_t *sock0, isc_region_t *region,
+		  unsigned int minimum, isc_task_t *task,
+		  isc_socketevent_t *event, unsigned int flags)
+{
+	isc__socket_t *sock = (isc__socket_t *)sock0;
+
+	event->ev_sender = sock;
+	event->result = ISC_R_UNEXPECTED;
+	ISC_LIST_INIT(event->bufferlist);
+	event->region = *region;
+	event->n = 0;
+	event->offset = 0;
+	event->attributes = 0;
+
+	/*
+	 * UDP sockets are always partial read.
+	 */
+	if (sock->type == isc_sockettype_udp)
+		event->minimum = 1;
+	else {
+		if (minimum == 0)
+			event->minimum = region->length;
+		else
+			event->minimum = minimum;
+	}
+
+	return (socket_recv(sock, event, task, flags));
+}
+
+static isc_result_t
+socket_send(isc__socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
+	    isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
+	    unsigned int flags)
+{
+	int io_state;
+	isc_boolean_t have_lock = ISC_FALSE;
+	isc_task_t *ntask = NULL;
+	isc_result_t result = ISC_R_SUCCESS;
+
+	dev->ev_sender = task;
+
+	set_dev_address(address, sock, dev);
+	if (pktinfo != NULL) {
+		dev->attributes |= ISC_SOCKEVENTATTR_PKTINFO;
+		dev->pktinfo = *pktinfo;
+
+		if (!isc_sockaddr_issitelocal(&dev->address) &&
+		    !isc_sockaddr_islinklocal(&dev->address)) {
+			socket_log(sock, NULL, TRACE, isc_msgcat,
+				   ISC_MSGSET_SOCKET, ISC_MSG_PKTINFOPROVIDED,
+				   "pktinfo structure provided, ifindex %u "
+				   "(set to 0)", pktinfo->ipi6_ifindex);
+
+			/*
+			 * Set the pktinfo index to 0 here, to let the
+			 * kernel decide what interface it should send on.
+			 */
+			dev->pktinfo.ipi6_ifindex = 0;
+		}
+	}
+
+	if (sock->type == isc_sockettype_udp)
+		io_state = doio_send(sock, dev);
+	else {
+		LOCK(&sock->lock);
+		have_lock = ISC_TRUE;
+
+		if (ISC_LIST_EMPTY(sock->send_list))
+			io_state = doio_send(sock, dev);
+		else
+			io_state = DOIO_SOFT;
+	}
+
+	switch (io_state) {
+	case DOIO_SOFT:
+		/*
+		 * We couldn't send all or part of the request right now, so
+		 * queue it unless ISC_SOCKFLAG_NORETRY is set.
+		 */
+		if ((flags & ISC_SOCKFLAG_NORETRY) == 0) {
+			isc_task_attach(task, &ntask);
+			dev->attributes |= ISC_SOCKEVENTATTR_ATTACHED;
+
+			if (!have_lock) {
+				LOCK(&sock->lock);
+				have_lock = ISC_TRUE;
+			}
+
+			/*
+			 * Enqueue the request.  If the socket was previously
+			 * not being watched, poke the watcher to start
+			 * paying attention to it.
+			 */
+			if (ISC_LIST_EMPTY(sock->send_list) &&
+			    !sock->pending_send)
+				select_poke(sock->manager, sock->fd,
+					    SELECT_POKE_WRITE);
+			ISC_LIST_ENQUEUE(sock->send_list, dev, ev_link);
+
+			socket_log(sock, NULL, EVENT, NULL, 0, 0,
+				   "socket_send: event %p -> task %p",
+				   dev, ntask);
+
+			if ((flags & ISC_SOCKFLAG_IMMEDIATE) != 0)
+				result = ISC_R_INPROGRESS;
+			break;
+		}
+
+	case DOIO_HARD:
+	case DOIO_SUCCESS:
+		if ((flags & ISC_SOCKFLAG_IMMEDIATE) == 0)
+			send_senddone_event(sock, &dev);
+		break;
+	}
+
+	if (have_lock)
+		UNLOCK(&sock->lock);
+
+	return (result);
+}
+
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_send(isc_socket_t *sock, isc_region_t *region,
+		 isc_task_t *task, isc_taskaction_t action, const void *arg)
+{
+	/*
+	 * REQUIRE() checking is performed in isc_socket_sendto().
+	 */
+	return (isc__socket_sendto(sock, region, task, action, arg, NULL,
+				   NULL));
+}
+
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_sendto(isc_socket_t *sock0, isc_region_t *region,
+		   isc_task_t *task, isc_taskaction_t action, const void *arg,
+		   isc_sockaddr_t *address, struct in6_pktinfo *pktinfo)
+{
+	isc__socket_t *sock = (isc__socket_t *)sock0;
+	isc_socketevent_t *dev;
+	isc__socketmgr_t *manager;
+
+	REQUIRE(VALID_SOCKET(sock));
+	REQUIRE(region != NULL);
+	REQUIRE(task != NULL);
+	REQUIRE(action != NULL);
+
+	manager = sock->manager;
+	REQUIRE(VALID_MANAGER(manager));
+
+	INSIST(sock->bound);
+
+	dev = allocate_socketevent(sock, ISC_SOCKEVENT_SENDDONE, action, arg);
+	if (dev == NULL) {
+		return (ISC_R_NOMEMORY);
+	}
+
+	dev->region = *region;
+
+	return (socket_send(sock, dev, task, address, pktinfo, 0));
+}
+
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_sendv(isc_socket_t *sock, isc_bufferlist_t *buflist,
+		  isc_task_t *task, isc_taskaction_t action, const void *arg)
+{
+	return (isc__socket_sendtov(sock, buflist, task, action, arg, NULL,
+				    NULL));
+}
+
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_sendtov(isc_socket_t *sock0, isc_bufferlist_t *buflist,
+		    isc_task_t *task, isc_taskaction_t action, const void *arg,
+		    isc_sockaddr_t *address, struct in6_pktinfo *pktinfo)
+{
+	isc__socket_t *sock = (isc__socket_t *)sock0;
+	isc_socketevent_t *dev;
+	isc__socketmgr_t *manager;
+	unsigned int iocount;
+	isc_buffer_t *buffer;
+
+	REQUIRE(VALID_SOCKET(sock));
+	REQUIRE(buflist != NULL);
+	REQUIRE(!ISC_LIST_EMPTY(*buflist));
+	REQUIRE(task != NULL);
+	REQUIRE(action != NULL);
+
+	manager = sock->manager;
+	REQUIRE(VALID_MANAGER(manager));
+
+	iocount = isc_bufferlist_usedcount(buflist);
+	REQUIRE(iocount > 0);
+
+	dev = allocate_socketevent(sock, ISC_SOCKEVENT_SENDDONE, action, arg);
+	if (dev == NULL) {
+		return (ISC_R_NOMEMORY);
+	}
+
+	/*
+	 * Move each buffer from the passed in list to our internal one.
+	 */
+	buffer = ISC_LIST_HEAD(*buflist);
+	while (buffer != NULL) {
+		ISC_LIST_DEQUEUE(*buflist, buffer, link);
+		ISC_LIST_ENQUEUE(dev->bufferlist, buffer, link);
+		buffer = ISC_LIST_HEAD(*buflist);
+	}
+
+	return (socket_send(sock, dev, task, address, pktinfo, 0));
+}
+
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_sendto2(isc_socket_t *sock0, isc_region_t *region,
+		    isc_task_t *task,
+		    isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
+		    isc_socketevent_t *event, unsigned int flags)
+{
+	isc__socket_t *sock = (isc__socket_t *)sock0;
+
+	REQUIRE(VALID_SOCKET(sock));
+	REQUIRE((flags & ~(ISC_SOCKFLAG_IMMEDIATE|ISC_SOCKFLAG_NORETRY)) == 0);
+	if ((flags & ISC_SOCKFLAG_NORETRY) != 0)
+		REQUIRE(sock->type == isc_sockettype_udp);
+	event->ev_sender = sock;
+	event->result = ISC_R_UNEXPECTED;
+	ISC_LIST_INIT(event->bufferlist);
+	event->region = *region;
+	event->n = 0;
+	event->offset = 0;
+	event->attributes = 0;
+
+	return (socket_send(sock, event, task, address, pktinfo, flags));
+}
+
+ISC_SOCKETFUNC_SCOPE void
+isc__socket_cleanunix(isc_sockaddr_t *sockaddr, isc_boolean_t active) {
+#ifdef ISC_PLATFORM_HAVESYSUNH
+	int s;
+	struct stat sb;
+	char strbuf[ISC_STRERRORSIZE];
+
+	if (sockaddr->type.sa.sa_family != AF_UNIX)
+		return;
+
+#ifndef S_ISSOCK
+#if defined(S_IFMT) && defined(S_IFSOCK)
+#define S_ISSOCK(mode) ((mode & S_IFMT)==S_IFSOCK)
+#elif defined(_S_IFMT) && defined(S_IFSOCK)
+#define S_ISSOCK(mode) ((mode & _S_IFMT)==S_IFSOCK)
+#endif
+#endif
+
+#ifndef S_ISFIFO
+#if defined(S_IFMT) && defined(S_IFIFO)
+#define S_ISFIFO(mode) ((mode & S_IFMT)==S_IFIFO)
+#elif defined(_S_IFMT) && defined(S_IFIFO)
+#define S_ISFIFO(mode) ((mode & _S_IFMT)==S_IFIFO)
+#endif
+#endif
+
+#if !defined(S_ISFIFO) && !defined(S_ISSOCK)
+#error You need to define S_ISFIFO and S_ISSOCK as appropriate for your platform.  See <sys/stat.h>.
+#endif
+
+#ifndef S_ISFIFO
+#define S_ISFIFO(mode) 0
+#endif
+
+#ifndef S_ISSOCK
+#define S_ISSOCK(mode) 0
+#endif
+
+	if (active) {
+		if (stat(sockaddr->type.sunix.sun_path, &sb) < 0) {
+			isc__strerror(errno, strbuf, sizeof(strbuf));
+			isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+				      ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
+				      "isc_socket_cleanunix: stat(%s): %s",
+				      sockaddr->type.sunix.sun_path, strbuf);
+			return;
+		}
+		if (!(S_ISSOCK(sb.st_mode) || S_ISFIFO(sb.st_mode))) {
+			isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+				      ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
+				      "isc_socket_cleanunix: %s: not a socket",
+				      sockaddr->type.sunix.sun_path);
+			return;
+		}
+		if (unlink(sockaddr->type.sunix.sun_path) < 0) {
+			isc__strerror(errno, strbuf, sizeof(strbuf));
+			isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+				      ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
+				      "isc_socket_cleanunix: unlink(%s): %s",
+				      sockaddr->type.sunix.sun_path, strbuf);
+		}
+		return;
+	}
+
+	s = socket(AF_UNIX, SOCK_STREAM, 0);
+	if (s < 0) {
+		isc__strerror(errno, strbuf, sizeof(strbuf));
+		isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+			      ISC_LOGMODULE_SOCKET, ISC_LOG_WARNING,
+			      "isc_socket_cleanunix: socket(%s): %s",
+			      sockaddr->type.sunix.sun_path, strbuf);
+		return;
+	}
+
+	if (stat(sockaddr->type.sunix.sun_path, &sb) < 0) {
+		switch (errno) {
+		case ENOENT:    /* We exited cleanly last time */
+			break;
+		default:
+			isc__strerror(errno, strbuf, sizeof(strbuf));
+			isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+				      ISC_LOGMODULE_SOCKET, ISC_LOG_WARNING,
+				      "isc_socket_cleanunix: stat(%s): %s",
+				      sockaddr->type.sunix.sun_path, strbuf);
+			break;
+		}
+		goto cleanup;
+	}
+
+	if (!(S_ISSOCK(sb.st_mode) || S_ISFIFO(sb.st_mode))) {
+		isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+			      ISC_LOGMODULE_SOCKET, ISC_LOG_WARNING,
+			      "isc_socket_cleanunix: %s: not a socket",
+			      sockaddr->type.sunix.sun_path);
+		goto cleanup;
+	}
+
+	if (connect(s, (struct sockaddr *)&sockaddr->type.sunix,
+		    sizeof(sockaddr->type.sunix)) < 0) {
+		switch (errno) {
+		case ECONNREFUSED:
+		case ECONNRESET:
+			if (unlink(sockaddr->type.sunix.sun_path) < 0) {
+				isc__strerror(errno, strbuf, sizeof(strbuf));
+				isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+					      ISC_LOGMODULE_SOCKET,
+					      ISC_LOG_WARNING,
+					      "isc_socket_cleanunix: "
+					      "unlink(%s): %s",
+					      sockaddr->type.sunix.sun_path,
+					      strbuf);
+			}
+			break;
+		default:
+			isc__strerror(errno, strbuf, sizeof(strbuf));
+			isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+				      ISC_LOGMODULE_SOCKET, ISC_LOG_WARNING,
+				      "isc_socket_cleanunix: connect(%s): %s",
+				      sockaddr->type.sunix.sun_path, strbuf);
+			break;
+		}
+	}
+ cleanup:
+	close(s);
+#else
+	UNUSED(sockaddr);
+	UNUSED(active);
+#endif
+}
+
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_permunix(isc_sockaddr_t *sockaddr, isc_uint32_t perm,
+		    isc_uint32_t owner, isc_uint32_t group)
+{
+#ifdef ISC_PLATFORM_HAVESYSUNH
+	isc_result_t result = ISC_R_SUCCESS;
+	char strbuf[ISC_STRERRORSIZE];
+	char path[sizeof(sockaddr->type.sunix.sun_path)];
+#ifdef NEED_SECURE_DIRECTORY
+	char *slash;
+#endif
+
+	REQUIRE(sockaddr->type.sa.sa_family == AF_UNIX);
+	INSIST(strlen(sockaddr->type.sunix.sun_path) < sizeof(path));
+	strcpy(path, sockaddr->type.sunix.sun_path);
+
+#ifdef NEED_SECURE_DIRECTORY
+	slash = strrchr(path, '/');
+	if (slash != NULL) {
+		if (slash != path)
+			*slash = '\0';
+		else
+			strcpy(path, "/");
+	} else
+		strcpy(path, ".");
+#endif
+
+	if (chmod(path, perm) < 0) {
+		isc__strerror(errno, strbuf, sizeof(strbuf));
+		isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+			      ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
+			      "isc_socket_permunix: chmod(%s, %d): %s",
+			      path, perm, strbuf);
+		result = ISC_R_FAILURE;
+	}
+	if (chown(path, owner, group) < 0) {
+		isc__strerror(errno, strbuf, sizeof(strbuf));
+		isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+			      ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
+			      "isc_socket_permunix: chown(%s, %d, %d): %s",
+			      path, owner, group,
+			      strbuf);
+		result = ISC_R_FAILURE;
+	}
+	return (result);
+#else
+	UNUSED(sockaddr);
+	UNUSED(perm);
+	UNUSED(owner);
+	UNUSED(group);
+	return (ISC_R_NOTIMPLEMENTED);
+#endif
+}
+
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_bind(isc_socket_t *sock0, isc_sockaddr_t *sockaddr,
+		 unsigned int options) {
+	isc__socket_t *sock = (isc__socket_t *)sock0;
+	char strbuf[ISC_STRERRORSIZE];
+	int on = 1;
+
+	REQUIRE(VALID_SOCKET(sock));
+
+	LOCK(&sock->lock);
+
+	INSIST(!sock->bound);
+
+	if (sock->pf != sockaddr->type.sa.sa_family) {
+		UNLOCK(&sock->lock);
+		return (ISC_R_FAMILYMISMATCH);
+	}
+	/*
+	 * Only set SO_REUSEADDR when we want a specific port.
+	 */
+#ifdef AF_UNIX
+	if (sock->pf == AF_UNIX)
+		goto bind_socket;
+#endif
+	if ((options & ISC_SOCKET_REUSEADDRESS) != 0 &&
+	    isc_sockaddr_getport(sockaddr) != (in_port_t)0 &&
+	    setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on,
+		       sizeof(on)) < 0) {
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "setsockopt(%d) %s", sock->fd,
+				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+						ISC_MSG_FAILED, "failed"));
+		/* Press on... */
+	}
+#ifdef AF_UNIX
+ bind_socket:
+#endif
+	if (bind(sock->fd, &sockaddr->type.sa, sockaddr->length) < 0) {
+		inc_stats(sock->manager->stats,
+			  sock->statsindex[STATID_BINDFAIL]);
+
+		UNLOCK(&sock->lock);
+		switch (errno) {
+		case EACCES:
+			return (ISC_R_NOPERM);
+		case EADDRNOTAVAIL:
+			return (ISC_R_ADDRNOTAVAIL);
+		case EADDRINUSE:
+			return (ISC_R_ADDRINUSE);
+		case EINVAL:
+			return (ISC_R_BOUND);
+		default:
+			isc__strerror(errno, strbuf, sizeof(strbuf));
+			UNEXPECTED_ERROR(__FILE__, __LINE__, "bind: %s",
+					 strbuf);
+			return (ISC_R_UNEXPECTED);
+		}
+	}
+
+	socket_log(sock, sockaddr, TRACE,
+		   isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_BOUND, "bound");
+	sock->bound = 1;
+
+	UNLOCK(&sock->lock);
+	return (ISC_R_SUCCESS);
+}
+
+/*
+ * Enable this only for specific OS versions, and only when they have repaired
+ * their problems with it.  Until then, this is is broken and needs to be
+ * diabled by default.  See RT22589 for details.
+ */
+#undef ENABLE_ACCEPTFILTER
+
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_filter(isc_socket_t *sock0, const char *filter) {
+	isc__socket_t *sock = (isc__socket_t *)sock0;
+#if defined(SO_ACCEPTFILTER) && defined(ENABLE_ACCEPTFILTER)
+	char strbuf[ISC_STRERRORSIZE];
+	struct accept_filter_arg afa;
+#else
+	UNUSED(sock);
+	UNUSED(filter);
+#endif
+
+	REQUIRE(VALID_SOCKET(sock));
+
+#if defined(SO_ACCEPTFILTER) && defined(ENABLE_ACCEPTFILTER)
+	bzero(&afa, sizeof(afa));
+	strncpy(afa.af_name, filter, sizeof(afa.af_name));
+	if (setsockopt(sock->fd, SOL_SOCKET, SO_ACCEPTFILTER,
+			 &afa, sizeof(afa)) == -1) {
+		isc__strerror(errno, strbuf, sizeof(strbuf));
+		socket_log(sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET,
+			   ISC_MSG_FILTER, "setsockopt(SO_ACCEPTFILTER): %s",
+			   strbuf);
+		return (ISC_R_FAILURE);
+	}
+	return (ISC_R_SUCCESS);
+#else
+	return (ISC_R_NOTIMPLEMENTED);
+#endif
+}
+
+/*
+ * Set up to listen on a given socket.  We do this by creating an internal
+ * event that will be dispatched when the socket has read activity.  The
+ * watcher will send the internal event to the task when there is a new
+ * connection.
+ *
+ * Unlike in read, we don't preallocate a done event here.  Every time there
+ * is a new connection we'll have to allocate a new one anyway, so we might
+ * as well keep things simple rather than having to track them.
+ */
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_listen(isc_socket_t *sock0, unsigned int backlog) {
+	isc__socket_t *sock = (isc__socket_t *)sock0;
+	char strbuf[ISC_STRERRORSIZE];
+
+	REQUIRE(VALID_SOCKET(sock));
+
+	LOCK(&sock->lock);
+
+	REQUIRE(!sock->listener);
+	REQUIRE(sock->bound);
+	REQUIRE(sock->type == isc_sockettype_tcp ||
+		sock->type == isc_sockettype_unix);
+
+	if (backlog == 0)
+		backlog = SOMAXCONN;
+
+	if (listen(sock->fd, (int)backlog) < 0) {
+		UNLOCK(&sock->lock);
+		isc__strerror(errno, strbuf, sizeof(strbuf));
+
+		UNEXPECTED_ERROR(__FILE__, __LINE__, "listen: %s", strbuf);
+
+		return (ISC_R_UNEXPECTED);
+	}
+
+	sock->listener = 1;
+
+	UNLOCK(&sock->lock);
+	return (ISC_R_SUCCESS);
+}
+
+/*
+ * This should try to do aggressive accept() XXXMLG
+ */
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_accept(isc_socket_t *sock0,
+		  isc_task_t *task, isc_taskaction_t action, const void *arg)
+{
+	isc__socket_t *sock = (isc__socket_t *)sock0;
+	isc_socket_newconnev_t *dev;
+	isc__socketmgr_t *manager;
+	isc_task_t *ntask = NULL;
+	isc__socket_t *nsock;
+	isc_result_t result;
+	isc_boolean_t do_poke = ISC_FALSE;
+
+	REQUIRE(VALID_SOCKET(sock));
+	manager = sock->manager;
+	REQUIRE(VALID_MANAGER(manager));
+
+	LOCK(&sock->lock);
+
+	REQUIRE(sock->listener);
+
+	/*
+	 * Sender field is overloaded here with the task we will be sending
+	 * this event to.  Just before the actual event is delivered the
+	 * actual ev_sender will be touched up to be the socket.
+	 */
+	dev = (isc_socket_newconnev_t *)
+		isc_event_allocate(manager->mctx, task, ISC_SOCKEVENT_NEWCONN,
+				   action, arg, sizeof(*dev));
+	if (dev == NULL) {
+		UNLOCK(&sock->lock);
+		return (ISC_R_NOMEMORY);
+	}
+	ISC_LINK_INIT(dev, ev_link);
+
+	result = allocate_socket(manager, sock->type, &nsock);
+	if (result != ISC_R_SUCCESS) {
+		isc_event_free(ISC_EVENT_PTR(&dev));
+		UNLOCK(&sock->lock);
+		return (result);
+	}
+
+	/*
+	 * Attach to socket and to task.
+	 */
+	isc_task_attach(task, &ntask);
+	if (isc_task_exiting(ntask)) {
+		isc_task_detach(&ntask);
+		isc_event_free(ISC_EVENT_PTR(&dev));
+		UNLOCK(&sock->lock);
+		return (ISC_R_SHUTTINGDOWN);
+	}
+	nsock->references++;
+	nsock->statsindex = sock->statsindex;
+
+	dev->ev_sender = ntask;
+	dev->newsocket = (isc_socket_t *)nsock;
+
+	/*
+	 * Poke watcher here.  We still have the socket locked, so there
+	 * is no race condition.  We will keep the lock for such a short
+	 * bit of time waking it up now or later won't matter all that much.
+	 */
+	if (ISC_LIST_EMPTY(sock->accept_list))
+		do_poke = ISC_TRUE;
+
+	ISC_LIST_ENQUEUE(sock->accept_list, dev, ev_link);
+
+	if (do_poke)
+		select_poke(manager, sock->fd, SELECT_POKE_ACCEPT);
+
+	UNLOCK(&sock->lock);
+	return (ISC_R_SUCCESS);
+}
+
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_connect(isc_socket_t *sock0, isc_sockaddr_t *addr,
+		   isc_task_t *task, isc_taskaction_t action, const void *arg)
+{
+	isc__socket_t *sock = (isc__socket_t *)sock0;
+	isc_socket_connev_t *dev;
+	isc_task_t *ntask = NULL;
+	isc__socketmgr_t *manager;
+	int cc;
+	char strbuf[ISC_STRERRORSIZE];
+	char addrbuf[ISC_SOCKADDR_FORMATSIZE];
+
+	REQUIRE(VALID_SOCKET(sock));
+	REQUIRE(addr != NULL);
+	REQUIRE(task != NULL);
+	REQUIRE(action != NULL);
+
+	manager = sock->manager;
+	REQUIRE(VALID_MANAGER(manager));
+	REQUIRE(addr != NULL);
+
+	if (isc_sockaddr_ismulticast(addr))
+		return (ISC_R_MULTICAST);
+
+	LOCK(&sock->lock);
+
+	REQUIRE(!sock->connecting);
+
+	dev = (isc_socket_connev_t *)isc_event_allocate(manager->mctx, sock,
+							ISC_SOCKEVENT_CONNECT,
+							action,	arg,
+							sizeof(*dev));
+	if (dev == NULL) {
+		UNLOCK(&sock->lock);
+		return (ISC_R_NOMEMORY);
+	}
+	ISC_LINK_INIT(dev, ev_link);
+
+	/*
+	 * Try to do the connect right away, as there can be only one
+	 * outstanding, and it might happen to complete.
+	 */
+	sock->peer_address = *addr;
+	cc = connect(sock->fd, &addr->type.sa, addr->length);
+	if (cc < 0) {
+		/*
+		 * HP-UX "fails" to connect a UDP socket and sets errno to
+		 * EINPROGRESS if it's non-blocking.  We'd rather regard this as
+		 * a success and let the user detect it if it's really an error
+		 * at the time of sending a packet on the socket.
+		 */
+		if (sock->type == isc_sockettype_udp && errno == EINPROGRESS) {
+			cc = 0;
+			goto success;
+		}
+		if (SOFT_ERROR(errno) || errno == EINPROGRESS)
+			goto queue;
+
+		switch (errno) {
+#define ERROR_MATCH(a, b) case a: dev->result = b; goto err_exit;
+			ERROR_MATCH(EACCES, ISC_R_NOPERM);
+			ERROR_MATCH(EADDRNOTAVAIL, ISC_R_ADDRNOTAVAIL);
+			ERROR_MATCH(EAFNOSUPPORT, ISC_R_ADDRNOTAVAIL);
+			ERROR_MATCH(ECONNREFUSED, ISC_R_CONNREFUSED);
+			ERROR_MATCH(EHOSTUNREACH, ISC_R_HOSTUNREACH);
+#ifdef EHOSTDOWN
+			ERROR_MATCH(EHOSTDOWN, ISC_R_HOSTUNREACH);
+#endif
+			ERROR_MATCH(ENETUNREACH, ISC_R_NETUNREACH);
+			ERROR_MATCH(ENOBUFS, ISC_R_NORESOURCES);
+			ERROR_MATCH(EPERM, ISC_R_HOSTUNREACH);
+			ERROR_MATCH(EPIPE, ISC_R_NOTCONNECTED);
+			ERROR_MATCH(ECONNRESET, ISC_R_CONNECTIONRESET);
+#undef ERROR_MATCH
+		}
+
+		sock->connected = 0;
+
+		isc__strerror(errno, strbuf, sizeof(strbuf));
+		isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__, "connect(%s) %d/%s",
+				 addrbuf, errno, strbuf);
+
+		UNLOCK(&sock->lock);
+		inc_stats(sock->manager->stats,
+			  sock->statsindex[STATID_CONNECTFAIL]);
+		isc_event_free(ISC_EVENT_PTR(&dev));
+		return (ISC_R_UNEXPECTED);
+
+	err_exit:
+		sock->connected = 0;
+		isc_task_send(task, ISC_EVENT_PTR(&dev));
+
+		UNLOCK(&sock->lock);
+		inc_stats(sock->manager->stats,
+			  sock->statsindex[STATID_CONNECTFAIL]);
+		return (ISC_R_SUCCESS);
+	}
+
+	/*
+	 * If connect completed, fire off the done event.
+	 */
+ success:
+	if (cc == 0) {
+		sock->connected = 1;
+		sock->bound = 1;
+		dev->result = ISC_R_SUCCESS;
+		isc_task_send(task, ISC_EVENT_PTR(&dev));
+
+		UNLOCK(&sock->lock);
+
+		inc_stats(sock->manager->stats,
+			  sock->statsindex[STATID_CONNECT]);
+
+		return (ISC_R_SUCCESS);
+	}
+
+ queue:
+
+	/*
+	 * Attach to task.
+	 */
+	isc_task_attach(task, &ntask);
+
+	sock->connecting = 1;
+
+	dev->ev_sender = ntask;
+
+	/*
+	 * Poke watcher here.  We still have the socket locked, so there
+	 * is no race condition.  We will keep the lock for such a short
+	 * bit of time waking it up now or later won't matter all that much.
+	 */
+	if (sock->connect_ev == NULL)
+		select_poke(manager, sock->fd, SELECT_POKE_CONNECT);
+
+	sock->connect_ev = dev;
+
+	UNLOCK(&sock->lock);
+	return (ISC_R_SUCCESS);
+}
+
+/*
+ * Called when a socket with a pending connect() finishes.
+ */
+static void
+internal_connect(isc_task_t *me, isc_event_t *ev) {
+	isc__socket_t *sock;
+	isc_socket_connev_t *dev;
+	isc_task_t *task;
+	int cc;
+	ISC_SOCKADDR_LEN_T optlen;
+	char strbuf[ISC_STRERRORSIZE];
+	char peerbuf[ISC_SOCKADDR_FORMATSIZE];
+
+	UNUSED(me);
+	INSIST(ev->ev_type == ISC_SOCKEVENT_INTW);
+
+	sock = ev->ev_sender;
+	INSIST(VALID_SOCKET(sock));
+
+	LOCK(&sock->lock);
+
+	/*
+	 * When the internal event was sent the reference count was bumped
+	 * to keep the socket around for us.  Decrement the count here.
+	 */
+	INSIST(sock->references > 0);
+	sock->references--;
+	if (sock->references == 0) {
+		UNLOCK(&sock->lock);
+		destroy(&sock);
+		return;
+	}
+
+	/*
+	 * Has this event been canceled?
+	 */
+	dev = sock->connect_ev;
+	if (dev == NULL) {
+		INSIST(!sock->connecting);
+		UNLOCK(&sock->lock);
+		return;
+	}
+
+	INSIST(sock->connecting);
+	sock->connecting = 0;
+
+	/*
+	 * Get any possible error status here.
+	 */
+	optlen = sizeof(cc);
+	if (getsockopt(sock->fd, SOL_SOCKET, SO_ERROR,
+		       (void *)&cc, (void *)&optlen) < 0)
+		cc = errno;
+	else
+		errno = cc;
+
+	if (errno != 0) {
+		/*
+		 * If the error is EAGAIN, just re-select on this
+		 * fd and pretend nothing strange happened.
+		 */
+		if (SOFT_ERROR(errno) || errno == EINPROGRESS) {
+			sock->connecting = 1;
+			select_poke(sock->manager, sock->fd,
+				    SELECT_POKE_CONNECT);
+			UNLOCK(&sock->lock);
+
+			return;
+		}
+
+		inc_stats(sock->manager->stats,
+			  sock->statsindex[STATID_CONNECTFAIL]);
+
+		/*
+		 * Translate other errors into ISC_R_* flavors.
+		 */
+		switch (errno) {
+#define ERROR_MATCH(a, b) case a: dev->result = b; break;
+			ERROR_MATCH(EACCES, ISC_R_NOPERM);
+			ERROR_MATCH(EADDRNOTAVAIL, ISC_R_ADDRNOTAVAIL);
+			ERROR_MATCH(EAFNOSUPPORT, ISC_R_ADDRNOTAVAIL);
+			ERROR_MATCH(ECONNREFUSED, ISC_R_CONNREFUSED);
+			ERROR_MATCH(EHOSTUNREACH, ISC_R_HOSTUNREACH);
+#ifdef EHOSTDOWN
+			ERROR_MATCH(EHOSTDOWN, ISC_R_HOSTUNREACH);
+#endif
+			ERROR_MATCH(ENETUNREACH, ISC_R_NETUNREACH);
+			ERROR_MATCH(ENOBUFS, ISC_R_NORESOURCES);
+			ERROR_MATCH(EPERM, ISC_R_HOSTUNREACH);
+			ERROR_MATCH(EPIPE, ISC_R_NOTCONNECTED);
+			ERROR_MATCH(ETIMEDOUT, ISC_R_TIMEDOUT);
+			ERROR_MATCH(ECONNRESET, ISC_R_CONNECTIONRESET);
+#undef ERROR_MATCH
+		default:
+			dev->result = ISC_R_UNEXPECTED;
+			isc_sockaddr_format(&sock->peer_address, peerbuf,
+					    sizeof(peerbuf));
+			isc__strerror(errno, strbuf, sizeof(strbuf));
+			UNEXPECTED_ERROR(__FILE__, __LINE__,
+					 "internal_connect: connect(%s) %s",
+					 peerbuf, strbuf);
+		}
+	} else {
+		inc_stats(sock->manager->stats,
+			  sock->statsindex[STATID_CONNECT]);
+		dev->result = ISC_R_SUCCESS;
+		sock->connected = 1;
+		sock->bound = 1;
+	}
+
+	sock->connect_ev = NULL;
+
+	UNLOCK(&sock->lock);
+
+	task = dev->ev_sender;
+	dev->ev_sender = sock;
+	isc_task_sendanddetach(&task, ISC_EVENT_PTR(&dev));
+}
+
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_getpeername(isc_socket_t *sock0, isc_sockaddr_t *addressp) {
+	isc__socket_t *sock = (isc__socket_t *)sock0;
+	isc_result_t result;
+
+	REQUIRE(VALID_SOCKET(sock));
+	REQUIRE(addressp != NULL);
+
+	LOCK(&sock->lock);
+
+	if (sock->connected) {
+		*addressp = sock->peer_address;
+		result = ISC_R_SUCCESS;
+	} else {
+		result = ISC_R_NOTCONNECTED;
+	}
+
+	UNLOCK(&sock->lock);
+
+	return (result);
+}
+
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_getsockname(isc_socket_t *sock0, isc_sockaddr_t *addressp) {
+	isc__socket_t *sock = (isc__socket_t *)sock0;
+	ISC_SOCKADDR_LEN_T len;
+	isc_result_t result;
+	char strbuf[ISC_STRERRORSIZE];
+
+	REQUIRE(VALID_SOCKET(sock));
+	REQUIRE(addressp != NULL);
+
+	LOCK(&sock->lock);
+
+	if (!sock->bound) {
+		result = ISC_R_NOTBOUND;
+		goto out;
+	}
+
+	result = ISC_R_SUCCESS;
+
+	len = sizeof(addressp->type);
+	if (getsockname(sock->fd, &addressp->type.sa, (void *)&len) < 0) {
+		isc__strerror(errno, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__, "getsockname: %s",
+				 strbuf);
+		result = ISC_R_UNEXPECTED;
+		goto out;
+	}
+	addressp->length = (unsigned int)len;
+
+ out:
+	UNLOCK(&sock->lock);
+
+	return (result);
+}
+
+/*
+ * Run through the list of events on this socket, and cancel the ones
+ * queued for task "task" of type "how".  "how" is a bitmask.
+ */
+ISC_SOCKETFUNC_SCOPE void
+isc__socket_cancel(isc_socket_t *sock0, isc_task_t *task, unsigned int how) {
+	isc__socket_t *sock = (isc__socket_t *)sock0;
+
+	REQUIRE(VALID_SOCKET(sock));
+
+	/*
+	 * Quick exit if there is nothing to do.  Don't even bother locking
+	 * in this case.
+	 */
+	if (how == 0)
+		return;
+
+	LOCK(&sock->lock);
+
+	/*
+	 * All of these do the same thing, more or less.
+	 * Each will:
+	 *	o If the internal event is marked as "posted" try to
+	 *	  remove it from the task's queue.  If this fails, mark it
+	 *	  as canceled instead, and let the task clean it up later.
+	 *	o For each I/O request for that task of that type, post
+	 *	  its done event with status of "ISC_R_CANCELED".
+	 *	o Reset any state needed.
+	 */
+	if (((how & ISC_SOCKCANCEL_RECV) == ISC_SOCKCANCEL_RECV)
+	    && !ISC_LIST_EMPTY(sock->recv_list)) {
+		isc_socketevent_t      *dev;
+		isc_socketevent_t      *next;
+		isc_task_t	       *current_task;
+
+		dev = ISC_LIST_HEAD(sock->recv_list);
+
+		while (dev != NULL) {
+			current_task = dev->ev_sender;
+			next = ISC_LIST_NEXT(dev, ev_link);
+
+			if ((task == NULL) || (task == current_task)) {
+				dev->result = ISC_R_CANCELED;
+				send_recvdone_event(sock, &dev);
+			}
+			dev = next;
+		}
+	}
+
+	if (((how & ISC_SOCKCANCEL_SEND) == ISC_SOCKCANCEL_SEND)
+	    && !ISC_LIST_EMPTY(sock->send_list)) {
+		isc_socketevent_t      *dev;
+		isc_socketevent_t      *next;
+		isc_task_t	       *current_task;
+
+		dev = ISC_LIST_HEAD(sock->send_list);
+
+		while (dev != NULL) {
+			current_task = dev->ev_sender;
+			next = ISC_LIST_NEXT(dev, ev_link);
+
+			if ((task == NULL) || (task == current_task)) {
+				dev->result = ISC_R_CANCELED;
+				send_senddone_event(sock, &dev);
+			}
+			dev = next;
+		}
+	}
+
+	if (((how & ISC_SOCKCANCEL_ACCEPT) == ISC_SOCKCANCEL_ACCEPT)
+	    && !ISC_LIST_EMPTY(sock->accept_list)) {
+		isc_socket_newconnev_t *dev;
+		isc_socket_newconnev_t *next;
+		isc_task_t	       *current_task;
+
+		dev = ISC_LIST_HEAD(sock->accept_list);
+		while (dev != NULL) {
+			current_task = dev->ev_sender;
+			next = ISC_LIST_NEXT(dev, ev_link);
+
+			if ((task == NULL) || (task == current_task)) {
+
+				ISC_LIST_UNLINK(sock->accept_list, dev,
+						ev_link);
+
+				NEWCONNSOCK(dev)->references--;
+				free_socket((isc__socket_t **)&dev->newsocket);
+
+				dev->result = ISC_R_CANCELED;
+				dev->ev_sender = sock;
+				isc_task_sendanddetach(&current_task,
+						       ISC_EVENT_PTR(&dev));
+			}
+
+			dev = next;
+		}
+	}
+
+	/*
+	 * Connecting is not a list.
+	 */
+	if (((how & ISC_SOCKCANCEL_CONNECT) == ISC_SOCKCANCEL_CONNECT)
+	    && sock->connect_ev != NULL) {
+		isc_socket_connev_t    *dev;
+		isc_task_t	       *current_task;
+
+		INSIST(sock->connecting);
+		sock->connecting = 0;
+
+		dev = sock->connect_ev;
+		current_task = dev->ev_sender;
+
+		if ((task == NULL) || (task == current_task)) {
+			sock->connect_ev = NULL;
+
+			dev->result = ISC_R_CANCELED;
+			dev->ev_sender = sock;
+			isc_task_sendanddetach(&current_task,
+					       ISC_EVENT_PTR(&dev));
+		}
+	}
+
+	UNLOCK(&sock->lock);
+}
+
+ISC_SOCKETFUNC_SCOPE isc_sockettype_t
+isc__socket_gettype(isc_socket_t *sock0) {
+	isc__socket_t *sock = (isc__socket_t *)sock0;
+
+	REQUIRE(VALID_SOCKET(sock));
+
+	return (sock->type);
+}
+
+ISC_SOCKETFUNC_SCOPE isc_boolean_t
+isc__socket_isbound(isc_socket_t *sock0) {
+	isc__socket_t *sock = (isc__socket_t *)sock0;
+	isc_boolean_t val;
+
+	REQUIRE(VALID_SOCKET(sock));
+
+	LOCK(&sock->lock);
+	val = ((sock->bound) ? ISC_TRUE : ISC_FALSE);
+	UNLOCK(&sock->lock);
+
+	return (val);
+}
+
+ISC_SOCKETFUNC_SCOPE void
+isc__socket_ipv6only(isc_socket_t *sock0, isc_boolean_t yes) {
+	isc__socket_t *sock = (isc__socket_t *)sock0;
+#if defined(IPV6_V6ONLY)
+	int onoff = yes ? 1 : 0;
+#else
+	UNUSED(yes);
+	UNUSED(sock);
+#endif
+
+	REQUIRE(VALID_SOCKET(sock));
+
+#ifdef IPV6_V6ONLY
+	if (sock->pf == AF_INET6) {
+		if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY,
+			       (void *)&onoff, sizeof(int)) < 0) {
+			char strbuf[ISC_STRERRORSIZE];
+
+			UNEXPECTED_ERROR(__FILE__, __LINE__,
+					 "setsockopt(%d, IPV6_V6ONLY) "
+					 "%s: %s", sock->fd,
+					 isc_msgcat_get(isc_msgcat,
+							ISC_MSGSET_GENERAL,
+							ISC_MSG_FAILED,
+							"failed"),
+					 strbuf);
+		}
+	}
+	FIX_IPV6_RECVPKTINFO(sock);	/* AIX */
+#endif
+}
+
+#ifndef USE_WATCHER_THREAD
+/*
+ * In our assumed scenario, we can simply use a single static object.
+ * XXX: this is not true if the application uses multiple threads with
+ *      'multi-context' mode.  Fixing this is a future TODO item.
+ */
+static isc_socketwait_t swait_private;
+
+int
+isc__socketmgr_waitevents(isc_socketmgr_t *manager0, struct timeval *tvp,
+			  isc_socketwait_t **swaitp)
+{
+	isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0;
+
+
+	int n;
+#ifdef USE_KQUEUE
+	struct timespec ts, *tsp;
+#endif
+#ifdef USE_EPOLL
+	int timeout;
+#endif
+#ifdef USE_DEVPOLL
+	struct dvpoll dvp;
+#endif
+
+	REQUIRE(swaitp != NULL && *swaitp == NULL);
+
+#ifdef USE_SHARED_MANAGER
+	if (manager == NULL)
+		manager = socketmgr;
+#endif
+	if (manager == NULL)
+		return (0);
+
+#ifdef USE_KQUEUE
+	if (tvp != NULL) {
+		ts.tv_sec = tvp->tv_sec;
+		ts.tv_nsec = tvp->tv_usec * 1000;
+		tsp = &ts;
+	} else
+		tsp = NULL;
+	swait_private.nevents = kevent(manager->kqueue_fd, NULL, 0,
+				       manager->events, manager->nevents,
+				       tsp);
+	n = swait_private.nevents;
+#elif defined(USE_EPOLL)
+	if (tvp != NULL)
+		timeout = tvp->tv_sec * 1000 + (tvp->tv_usec + 999) / 1000;
+	else
+		timeout = -1;
+	swait_private.nevents = epoll_wait(manager->epoll_fd,
+					   manager->events,
+					   manager->nevents, timeout);
+	n = swait_private.nevents;
+#elif defined(USE_DEVPOLL)
+	dvp.dp_fds = manager->events;
+	dvp.dp_nfds = manager->nevents;
+	if (tvp != NULL) {
+		dvp.dp_timeout = tvp->tv_sec * 1000 +
+			(tvp->tv_usec + 999) / 1000;
+	} else
+		dvp.dp_timeout = -1;
+	swait_private.nevents = ioctl(manager->devpoll_fd, DP_POLL, &dvp);
+	n = swait_private.nevents;
+#elif defined(USE_SELECT)
+	memcpy(manager->read_fds_copy, manager->read_fds,  manager->fd_bufsize);
+	memcpy(manager->write_fds_copy, manager->write_fds,
+	       manager->fd_bufsize);
+
+	swait_private.readset = manager->read_fds_copy;
+	swait_private.writeset = manager->write_fds_copy;
+	swait_private.maxfd = manager->maxfd + 1;
+
+	n = select(swait_private.maxfd, swait_private.readset,
+		   swait_private.writeset, NULL, tvp);
+#endif
+
+	*swaitp = &swait_private;
+	return (n);
+}
+
+isc_result_t
+isc__socketmgr_dispatch(isc_socketmgr_t *manager0, isc_socketwait_t *swait) {
+	isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0;
+
+	REQUIRE(swait == &swait_private);
+
+#ifdef USE_SHARED_MANAGER
+	if (manager == NULL)
+		manager = socketmgr;
+#endif
+	if (manager == NULL)
+		return (ISC_R_NOTFOUND);
+
+#if defined(USE_KQUEUE) || defined(USE_EPOLL) || defined(USE_DEVPOLL)
+	(void)process_fds(manager, manager->events, swait->nevents);
+	return (ISC_R_SUCCESS);
+#elif defined(USE_SELECT)
+	process_fds(manager, swait->maxfd, swait->readset, swait->writeset);
+	return (ISC_R_SUCCESS);
+#endif
+}
+#endif /* USE_WATCHER_THREAD */
+
+#ifdef BIND9
+void
+isc__socket_setname(isc_socket_t *socket0, const char *name, void *tag) {
+	isc__socket_t *socket = (isc__socket_t *)socket0;
+
+	/*
+	 * Name 'socket'.
+	 */
+
+	REQUIRE(VALID_SOCKET(socket));
+
+	LOCK(&socket->lock);
+	memset(socket->name, 0, sizeof(socket->name));
+	strncpy(socket->name, name, sizeof(socket->name) - 1);
+	socket->tag = tag;
+	UNLOCK(&socket->lock);
+}
+
+ISC_SOCKETFUNC_SCOPE const char *
+isc__socket_getname(isc_socket_t *socket0) {
+	isc__socket_t *socket = (isc__socket_t *)socket0;
+
+	return (socket->name);
+}
+
+void *
+isc__socket_gettag(isc_socket_t *socket0) {
+	isc__socket_t *socket = (isc__socket_t *)socket0;
+
+	return (socket->tag);
+}
+#endif	/* BIND9 */
+
+#ifdef USE_SOCKETIMPREGISTER
+isc_result_t
+isc__socket_register() {
+	return (isc_socket_register(isc__socketmgr_create));
+}
+#endif
+
+#if defined(HAVE_LIBXML2) && defined(BIND9)
+
+static const char *
+_socktype(isc_sockettype_t type)
+{
+	if (type == isc_sockettype_udp)
+		return ("udp");
+	else if (type == isc_sockettype_tcp)
+		return ("tcp");
+	else if (type == isc_sockettype_unix)
+		return ("unix");
+	else if (type == isc_sockettype_fdwatch)
+		return ("fdwatch");
+	else
+		return ("not-initialized");
+}
+
+ISC_SOCKETFUNC_SCOPE void
+isc_socketmgr_renderxml(isc_socketmgr_t *mgr0, xmlTextWriterPtr writer) {
+	isc__socketmgr_t *mgr = (isc__socketmgr_t *)mgr0;
+	isc__socket_t *sock;
+	char peerbuf[ISC_SOCKADDR_FORMATSIZE];
+	isc_sockaddr_t addr;
+	ISC_SOCKADDR_LEN_T len;
+
+	LOCK(&mgr->lock);
+
+#ifdef USE_SHARED_MANAGER
+	xmlTextWriterStartElement(writer, ISC_XMLCHAR "references");
+	xmlTextWriterWriteFormatString(writer, "%d", mgr->refs);
+	xmlTextWriterEndElement(writer);
+#endif	/* USE_SHARED_MANAGER */
+
+	xmlTextWriterStartElement(writer, ISC_XMLCHAR "sockets");
+	sock = ISC_LIST_HEAD(mgr->socklist);
+	while (sock != NULL) {
+		LOCK(&sock->lock);
+		xmlTextWriterStartElement(writer, ISC_XMLCHAR "socket");
+
+		xmlTextWriterStartElement(writer, ISC_XMLCHAR "id");
+		xmlTextWriterWriteFormatString(writer, "%p", sock);
+		xmlTextWriterEndElement(writer);
+
+		if (sock->name[0] != 0) {
+			xmlTextWriterStartElement(writer, ISC_XMLCHAR "name");
+			xmlTextWriterWriteFormatString(writer, "%s",
+						       sock->name);
+			xmlTextWriterEndElement(writer); /* name */
+		}
+
+		xmlTextWriterStartElement(writer, ISC_XMLCHAR "references");
+		xmlTextWriterWriteFormatString(writer, "%d", sock->references);
+		xmlTextWriterEndElement(writer);
+
+		xmlTextWriterWriteElement(writer, ISC_XMLCHAR "type",
+					  ISC_XMLCHAR _socktype(sock->type));
+
+		if (sock->connected) {
+			isc_sockaddr_format(&sock->peer_address, peerbuf,
+					    sizeof(peerbuf));
+			xmlTextWriterWriteElement(writer,
+						  ISC_XMLCHAR "peer-address",
+						  ISC_XMLCHAR peerbuf);
+		}
+
+		len = sizeof(addr);
+		if (getsockname(sock->fd, &addr.type.sa, (void *)&len) == 0) {
+			isc_sockaddr_format(&addr, peerbuf, sizeof(peerbuf));
+			xmlTextWriterWriteElement(writer,
+						  ISC_XMLCHAR "local-address",
+						  ISC_XMLCHAR peerbuf);
+		}
+
+		xmlTextWriterStartElement(writer, ISC_XMLCHAR "states");
+		if (sock->pending_recv)
+			xmlTextWriterWriteElement(writer, ISC_XMLCHAR "state",
+						ISC_XMLCHAR "pending-receive");
+		if (sock->pending_send)
+			xmlTextWriterWriteElement(writer, ISC_XMLCHAR "state",
+						  ISC_XMLCHAR "pending-send");
+		if (sock->pending_accept)
+			xmlTextWriterWriteElement(writer, ISC_XMLCHAR "state",
+						 ISC_XMLCHAR "pending_accept");
+		if (sock->listener)
+			xmlTextWriterWriteElement(writer, ISC_XMLCHAR "state",
+						  ISC_XMLCHAR "listener");
+		if (sock->connected)
+			xmlTextWriterWriteElement(writer, ISC_XMLCHAR "state",
+						  ISC_XMLCHAR "connected");
+		if (sock->connecting)
+			xmlTextWriterWriteElement(writer, ISC_XMLCHAR "state",
+						  ISC_XMLCHAR "connecting");
+		if (sock->bound)
+			xmlTextWriterWriteElement(writer, ISC_XMLCHAR "state",
+						  ISC_XMLCHAR "bound");
+
+		xmlTextWriterEndElement(writer); /* states */
+
+		xmlTextWriterEndElement(writer); /* socket */
+
+		UNLOCK(&sock->lock);
+		sock = ISC_LIST_NEXT(sock, link);
+	}
+	xmlTextWriterEndElement(writer); /* sockets */
+
+	UNLOCK(&mgr->lock);
+}
+#endif /* HAVE_LIBXML2 */
diff --git a/src/lib/bind9/unix/socket_p.h b/src/lib/bind9/unix/socket_p.h
new file mode 100644
index 0000000..b6c4b6a
--- /dev/null
+++ b/src/lib/bind9/unix/socket_p.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2004, 2005, 2007-2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: socket_p.h,v 1.15 2009-09-02 23:48:03 tbox Exp $ */
+
+#ifndef ISC_SOCKET_P_H
+#define ISC_SOCKET_P_H
+
+/*! \file */
+
+#ifdef ISC_PLATFORM_NEEDSYSSELECTH
+#include <sys/select.h>
+#endif
+
+typedef struct isc_socketwait isc_socketwait_t;
+int isc__socketmgr_waitevents(isc_socketmgr_t *, struct timeval *,
+			      isc_socketwait_t **);
+isc_result_t isc__socketmgr_dispatch(isc_socketmgr_t *, isc_socketwait_t *);
+#endif /* ISC_SOCKET_P_H */
diff --git a/src/lib/bind9/unix/stdio.c b/src/lib/bind9/unix/stdio.c
new file mode 100644
index 0000000..9221d2a
--- /dev/null
+++ b/src/lib/bind9/unix/stdio.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2004, 2007, 2011  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: stdio.c,v 1.8.814.2 2011-03-05 23:52:09 tbox Exp $ */
+
+#include <config.h>
+
+#include <errno.h>
+#include <unistd.h>
+
+#include <isc/stdio.h>
+#include <isc/stat.h>
+
+#include "errno2result.h"
+
+isc_result_t
+isc_stdio_open(const char *filename, const char *mode, FILE **fp) {
+	FILE *f;
+
+	f = fopen(filename, mode);
+	if (f == NULL)
+		return (isc__errno2result(errno));
+	*fp = f;
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_stdio_close(FILE *f) {
+	int r;
+
+	r = fclose(f);
+	if (r == 0)
+		return (ISC_R_SUCCESS);
+	else
+		return (isc__errno2result(errno));
+}
+
+isc_result_t
+isc_stdio_seek(FILE *f, long offset, int whence) {
+	int r;
+
+	r = fseek(f, offset, whence);
+	if (r == 0)
+		return (ISC_R_SUCCESS);
+	else
+		return (isc__errno2result(errno));
+}
+
+isc_result_t
+isc_stdio_read(void *ptr, size_t size, size_t nmemb, FILE *f, size_t *nret) {
+	isc_result_t result = ISC_R_SUCCESS;
+	size_t r;
+
+	clearerr(f);
+	r = fread(ptr, size, nmemb, f);
+	if (r != nmemb) {
+		if (feof(f))
+			result = ISC_R_EOF;
+		else
+			result = isc__errno2result(errno);
+	}
+	if (nret != NULL)
+		*nret = r;
+	return (result);
+}
+
+isc_result_t
+isc_stdio_write(const void *ptr, size_t size, size_t nmemb, FILE *f,
+	       size_t *nret)
+{
+	isc_result_t result = ISC_R_SUCCESS;
+	size_t r;
+
+	clearerr(f);
+	r = fwrite(ptr, size, nmemb, f);
+	if (r != nmemb)
+		result = isc__errno2result(errno);
+	if (nret != NULL)
+		*nret = r;
+	return (result);
+}
+
+isc_result_t
+isc_stdio_flush(FILE *f) {
+	int r;
+
+	r = fflush(f);
+	if (r == 0)
+		return (ISC_R_SUCCESS);
+	else
+		return (isc__errno2result(errno));
+}
+
+isc_result_t
+isc_stdio_sync(FILE *f) {
+	int r;
+
+	r = fsync(fileno(f));
+	if (r == 0)
+		return (ISC_R_SUCCESS);
+	else
+		return (isc__errno2result(errno));
+}
+
diff --git a/src/lib/bind9/unix/stdtime.c b/src/lib/bind9/unix/stdtime.c
new file mode 100644
index 0000000..11b2533
--- /dev/null
+++ b/src/lib/bind9/unix/stdtime.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: stdtime.c,v 1.19 2007-06-19 23:47:18 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stddef.h>	/* NULL */
+#include <stdlib.h>	/* NULL */
+#include <syslog.h>
+
+#include <sys/time.h>
+
+#include <isc/stdtime.h>
+#include <isc/util.h>
+
+#ifndef ISC_FIX_TV_USEC
+#define ISC_FIX_TV_USEC 1
+#endif
+
+#define US_PER_S 1000000
+
+#if ISC_FIX_TV_USEC
+static inline void
+fix_tv_usec(struct timeval *tv) {
+	isc_boolean_t fixed = ISC_FALSE;
+
+	if (tv->tv_usec < 0) {
+		fixed = ISC_TRUE;
+		do {
+			tv->tv_sec -= 1;
+			tv->tv_usec += US_PER_S;
+		} while (tv->tv_usec < 0);
+	} else if (tv->tv_usec >= US_PER_S) {
+		fixed = ISC_TRUE;
+		do {
+			tv->tv_sec += 1;
+			tv->tv_usec -= US_PER_S;
+		} while (tv->tv_usec >=US_PER_S);
+	}
+	/*
+	 * Call syslog directly as we are called from the logging functions.
+	 */
+	if (fixed)
+		(void)syslog(LOG_ERR, "gettimeofday returned bad tv_usec: corrected");
+}
+#endif
+
+void
+isc_stdtime_get(isc_stdtime_t *t) {
+	struct timeval tv;
+
+	/*
+	 * Set 't' to the number of seconds since 00:00:00 UTC, January 1,
+	 * 1970.
+	 */
+
+	REQUIRE(t != NULL);
+
+	RUNTIME_CHECK(gettimeofday(&tv, NULL) != -1);
+
+#if ISC_FIX_TV_USEC
+	fix_tv_usec(&tv);
+	INSIST(tv.tv_usec >= 0);
+#else
+	INSIST(tv.tv_usec >= 0 && tv.tv_usec < US_PER_S);
+#endif
+
+	*t = (unsigned int)tv.tv_sec;
+}
diff --git a/src/lib/bind9/unix/strerror.c b/src/lib/bind9/unix/strerror.c
new file mode 100644
index 0000000..4a61a97
--- /dev/null
+++ b/src/lib/bind9/unix/strerror.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: strerror.c,v 1.10 2009-02-16 23:48:04 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include <isc/mutex.h>
+#include <isc/once.h>
+#include <isc/print.h>
+#include <isc/strerror.h>
+#include <isc/util.h>
+
+#ifdef HAVE_STRERROR
+/*%
+ * We need to do this this way for profiled locks.
+ */
+static isc_mutex_t isc_strerror_lock;
+static void init_lock(void) {
+	RUNTIME_CHECK(isc_mutex_init(&isc_strerror_lock) == ISC_R_SUCCESS);
+}
+#else
+extern const char * const sys_errlist[];
+extern const int sys_nerr;
+#endif
+
+void
+isc__strerror(int num, char *buf, size_t size) {
+#ifdef HAVE_STRERROR
+	char *msg;
+	unsigned int unum = (unsigned int)num;
+	static isc_once_t once = ISC_ONCE_INIT;
+
+	REQUIRE(buf != NULL);
+
+	RUNTIME_CHECK(isc_once_do(&once, init_lock) == ISC_R_SUCCESS);
+
+	LOCK(&isc_strerror_lock);
+	msg = strerror(num);
+	if (msg != NULL)
+		snprintf(buf, size, "%s", msg);
+	else
+		snprintf(buf, size, "Unknown error: %u", unum);
+	UNLOCK(&isc_strerror_lock);
+#else
+	unsigned int unum = (unsigned int)num;
+
+	REQUIRE(buf != NULL);
+
+	if (num >= 0 && num < sys_nerr)
+		snprintf(buf, size, "%s", sys_errlist[num]);
+	else
+		snprintf(buf, size, "Unknown error: %u", unum);
+#endif
+}
diff --git a/src/lib/bind9/unix/syslog.c b/src/lib/bind9/unix/syslog.c
new file mode 100644
index 0000000..a752abd
--- /dev/null
+++ b/src/lib/bind9/unix/syslog.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: syslog.c,v 1.8 2007-09-13 04:45:18 each Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <syslog.h>
+
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/syslog.h>
+#include <isc/util.h>
+
+static struct dsn_c_pvt_sfnt {
+	int val;
+	const char *strval;
+} facilities[] = {
+	{ LOG_KERN,			"kern" },
+	{ LOG_USER,			"user" },
+	{ LOG_MAIL,			"mail" },
+	{ LOG_DAEMON,			"daemon" },
+	{ LOG_AUTH,			"auth" },
+	{ LOG_SYSLOG,			"syslog" },
+	{ LOG_LPR,			"lpr" },
+#ifdef LOG_NEWS
+	{ LOG_NEWS,			"news" },
+#endif
+#ifdef LOG_UUCP
+	{ LOG_UUCP,			"uucp" },
+#endif
+#ifdef LOG_CRON
+	{ LOG_CRON,			"cron" },
+#endif
+#ifdef LOG_AUTHPRIV
+	{ LOG_AUTHPRIV,			"authpriv" },
+#endif
+#ifdef LOG_FTP
+	{ LOG_FTP,			"ftp" },
+#endif
+	{ LOG_LOCAL0,			"local0"},
+	{ LOG_LOCAL1,			"local1"},
+	{ LOG_LOCAL2,			"local2"},
+	{ LOG_LOCAL3,			"local3"},
+	{ LOG_LOCAL4,			"local4"},
+	{ LOG_LOCAL5,			"local5"},
+	{ LOG_LOCAL6,			"local6"},
+	{ LOG_LOCAL7,			"local7"},
+	{ 0,				NULL }
+};
+
+isc_result_t
+isc_syslog_facilityfromstring(const char *str, int *facilityp) {
+	int i;
+
+	REQUIRE(str != NULL);
+	REQUIRE(facilityp != NULL);
+
+	for (i = 0; facilities[i].strval != NULL; i++) {
+		if (strcasecmp(facilities[i].strval, str) == 0) {
+			*facilityp = facilities[i].val;
+			return (ISC_R_SUCCESS);
+		}
+	}
+	return (ISC_R_NOTFOUND);
+
+}
diff --git a/src/lib/bind9/unix/time.c b/src/lib/bind9/unix/time.c
new file mode 100644
index 0000000..8d1d9fa
--- /dev/null
+++ b/src/lib/bind9/unix/time.c
@@ -0,0 +1,438 @@
+/*
+ * Copyright (C) 2004-2008, 2011  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2001, 2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: time.c,v 1.56.608.2 2011-03-12 04:59:19 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <syslog.h>
+#include <time.h>
+
+#include <sys/time.h>	/* Required for struct timeval on some platforms. */
+
+#include <isc/log.h>
+#include <isc/print.h>
+#include <isc/strerror.h>
+#include <isc/string.h>
+#include <isc/time.h>
+#include <isc/util.h>
+
+#define NS_PER_S	1000000000	/*%< Nanoseconds per second. */
+#define NS_PER_US	1000		/*%< Nanoseconds per microsecond. */
+#define US_PER_S	1000000		/*%< Microseconds per second. */
+
+/*
+ * All of the INSIST()s checks of nanoseconds < NS_PER_S are for
+ * consistency checking of the type. In lieu of magic numbers, it
+ * is the best we've got.  The check is only performed on functions which
+ * need an initialized type.
+ */
+
+#ifndef ISC_FIX_TV_USEC
+#define ISC_FIX_TV_USEC 1
+#endif
+
+/*%
+ *** Intervals
+ ***/
+
+static isc_interval_t zero_interval = { 0, 0 };
+isc_interval_t *isc_interval_zero = &zero_interval;
+
+#if ISC_FIX_TV_USEC
+static inline void
+fix_tv_usec(struct timeval *tv) {
+	isc_boolean_t fixed = ISC_FALSE;
+
+	if (tv->tv_usec < 0) {
+		fixed = ISC_TRUE;
+		do {
+			tv->tv_sec -= 1;
+			tv->tv_usec += US_PER_S;
+		} while (tv->tv_usec < 0);
+	} else if (tv->tv_usec >= US_PER_S) {
+		fixed = ISC_TRUE;
+		do {
+			tv->tv_sec += 1;
+			tv->tv_usec -= US_PER_S;
+		} while (tv->tv_usec >=US_PER_S);
+	}
+	/*
+	 * Call syslog directly as was are called from the logging functions.
+	 */
+	if (fixed)
+		(void)syslog(LOG_ERR, "gettimeofday returned bad tv_usec: corrected");
+}
+#endif
+
+void
+isc_interval_set(isc_interval_t *i,
+		 unsigned int seconds, unsigned int nanoseconds)
+{
+	REQUIRE(i != NULL);
+	REQUIRE(nanoseconds < NS_PER_S);
+
+	i->seconds = seconds;
+	i->nanoseconds = nanoseconds;
+}
+
+isc_boolean_t
+isc_interval_iszero(const isc_interval_t *i) {
+	REQUIRE(i != NULL);
+	INSIST(i->nanoseconds < NS_PER_S);
+
+	if (i->seconds == 0 && i->nanoseconds == 0)
+		return (ISC_TRUE);
+
+	return (ISC_FALSE);
+}
+
+
+/***
+ *** Absolute Times
+ ***/
+
+static isc_time_t epoch = { 0, 0 };
+isc_time_t *isc_time_epoch = &epoch;
+
+void
+isc_time_set(isc_time_t *t, unsigned int seconds, unsigned int nanoseconds) {
+	REQUIRE(t != NULL);
+	REQUIRE(nanoseconds < NS_PER_S);
+
+	t->seconds = seconds;
+	t->nanoseconds = nanoseconds;
+}
+
+void
+isc_time_settoepoch(isc_time_t *t) {
+	REQUIRE(t != NULL);
+
+	t->seconds = 0;
+	t->nanoseconds = 0;
+}
+
+isc_boolean_t
+isc_time_isepoch(const isc_time_t *t) {
+	REQUIRE(t != NULL);
+	INSIST(t->nanoseconds < NS_PER_S);
+
+	if (t->seconds == 0 && t->nanoseconds == 0)
+		return (ISC_TRUE);
+
+	return (ISC_FALSE);
+}
+
+
+isc_result_t
+isc_time_now(isc_time_t *t) {
+	struct timeval tv;
+	char strbuf[ISC_STRERRORSIZE];
+
+	REQUIRE(t != NULL);
+
+	if (gettimeofday(&tv, NULL) == -1) {
+		isc__strerror(errno, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__, "%s", strbuf);
+		return (ISC_R_UNEXPECTED);
+	}
+
+	/*
+	 * Does POSIX guarantee the signedness of tv_sec and tv_usec?  If not,
+	 * then this test will generate warnings for platforms on which it is
+	 * unsigned.  In any event, the chances of any of these problems
+	 * happening are pretty much zero, but since the libisc library ensures
+	 * certain things to be true ...
+	 */
+#if ISC_FIX_TV_USEC
+	fix_tv_usec(&tv);
+	if (tv.tv_sec < 0)
+		return (ISC_R_UNEXPECTED);
+#else
+	if (tv.tv_sec < 0 || tv.tv_usec < 0 || tv.tv_usec >= US_PER_S)
+		return (ISC_R_UNEXPECTED);
+#endif
+
+	/*
+	 * Ensure the tv_sec value fits in t->seconds.
+	 */
+	if (sizeof(tv.tv_sec) > sizeof(t->seconds) &&
+	    ((tv.tv_sec | (unsigned int)-1) ^ (unsigned int)-1) != 0U)
+		return (ISC_R_RANGE);
+
+	t->seconds = tv.tv_sec;
+	t->nanoseconds = tv.tv_usec * NS_PER_US;
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_time_nowplusinterval(isc_time_t *t, const isc_interval_t *i) {
+	struct timeval tv;
+	char strbuf[ISC_STRERRORSIZE];
+
+	REQUIRE(t != NULL);
+	REQUIRE(i != NULL);
+	INSIST(i->nanoseconds < NS_PER_S);
+
+	if (gettimeofday(&tv, NULL) == -1) {
+		isc__strerror(errno, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__, "%s", strbuf);
+		return (ISC_R_UNEXPECTED);
+	}
+
+	/*
+	 * Does POSIX guarantee the signedness of tv_sec and tv_usec?  If not,
+	 * then this test will generate warnings for platforms on which it is
+	 * unsigned.  In any event, the chances of any of these problems
+	 * happening are pretty much zero, but since the libisc library ensures
+	 * certain things to be true ...
+	 */
+#if ISC_FIX_TV_USEC
+	fix_tv_usec(&tv);
+	if (tv.tv_sec < 0)
+		return (ISC_R_UNEXPECTED);
+#else
+	if (tv.tv_sec < 0 || tv.tv_usec < 0 || tv.tv_usec >= US_PER_S)
+		return (ISC_R_UNEXPECTED);
+#endif
+
+	/*
+	 * Ensure the resulting seconds value fits in the size of an
+	 * unsigned int.  (It is written this way as a slight optimization;
+	 * note that even if both values == INT_MAX, then when added
+	 * and getting another 1 added below the result is UINT_MAX.)
+	 */
+	if ((tv.tv_sec > INT_MAX || i->seconds > INT_MAX) &&
+	    ((long long)tv.tv_sec + i->seconds > UINT_MAX))
+		return (ISC_R_RANGE);
+
+	t->seconds = tv.tv_sec + i->seconds;
+	t->nanoseconds = tv.tv_usec * NS_PER_US + i->nanoseconds;
+	if (t->nanoseconds >= NS_PER_S) {
+		t->seconds++;
+		t->nanoseconds -= NS_PER_S;
+	}
+
+	return (ISC_R_SUCCESS);
+}
+
+int
+isc_time_compare(const isc_time_t *t1, const isc_time_t *t2) {
+	REQUIRE(t1 != NULL && t2 != NULL);
+	INSIST(t1->nanoseconds < NS_PER_S && t2->nanoseconds < NS_PER_S);
+
+	if (t1->seconds < t2->seconds)
+		return (-1);
+	if (t1->seconds > t2->seconds)
+		return (1);
+	if (t1->nanoseconds < t2->nanoseconds)
+		return (-1);
+	if (t1->nanoseconds > t2->nanoseconds)
+		return (1);
+	return (0);
+}
+
+isc_result_t
+isc_time_add(const isc_time_t *t, const isc_interval_t *i, isc_time_t *result)
+{
+	REQUIRE(t != NULL && i != NULL && result != NULL);
+	INSIST(t->nanoseconds < NS_PER_S && i->nanoseconds < NS_PER_S);
+
+	/*
+	 * Ensure the resulting seconds value fits in the size of an
+	 * unsigned int.  (It is written this way as a slight optimization;
+	 * note that even if both values == INT_MAX, then when added
+	 * and getting another 1 added below the result is UINT_MAX.)
+	 */
+	if ((t->seconds > INT_MAX || i->seconds > INT_MAX) &&
+	    ((long long)t->seconds + i->seconds > UINT_MAX))
+		return (ISC_R_RANGE);
+
+	result->seconds = t->seconds + i->seconds;
+	result->nanoseconds = t->nanoseconds + i->nanoseconds;
+	if (result->nanoseconds >= NS_PER_S) {
+		result->seconds++;
+		result->nanoseconds -= NS_PER_S;
+	}
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_time_subtract(const isc_time_t *t, const isc_interval_t *i,
+		  isc_time_t *result)
+{
+	REQUIRE(t != NULL && i != NULL && result != NULL);
+	INSIST(t->nanoseconds < NS_PER_S && i->nanoseconds < NS_PER_S);
+
+	if ((unsigned int)t->seconds < i->seconds ||
+	    ((unsigned int)t->seconds == i->seconds &&
+	     t->nanoseconds < i->nanoseconds))
+	    return (ISC_R_RANGE);
+
+	result->seconds = t->seconds - i->seconds;
+	if (t->nanoseconds >= i->nanoseconds)
+		result->nanoseconds = t->nanoseconds - i->nanoseconds;
+	else {
+		result->nanoseconds = NS_PER_S - i->nanoseconds +
+			t->nanoseconds;
+		result->seconds--;
+	}
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_uint64_t
+isc_time_microdiff(const isc_time_t *t1, const isc_time_t *t2) {
+	isc_uint64_t i1, i2, i3;
+
+	REQUIRE(t1 != NULL && t2 != NULL);
+	INSIST(t1->nanoseconds < NS_PER_S && t2->nanoseconds < NS_PER_S);
+
+	i1 = (isc_uint64_t)t1->seconds * NS_PER_S + t1->nanoseconds;
+	i2 = (isc_uint64_t)t2->seconds * NS_PER_S + t2->nanoseconds;
+
+	if (i1 <= i2)
+		return (0);
+
+	i3 = i1 - i2;
+
+	/*
+	 * Convert to microseconds.
+	 */
+	i3 /= NS_PER_US;
+
+	return (i3);
+}
+
+isc_uint32_t
+isc_time_seconds(const isc_time_t *t) {
+	REQUIRE(t != NULL);
+	INSIST(t->nanoseconds < NS_PER_S);
+
+	return ((isc_uint32_t)t->seconds);
+}
+
+isc_result_t
+isc_time_secondsastimet(const isc_time_t *t, time_t *secondsp) {
+	isc_uint64_t i;
+	time_t seconds;
+
+	REQUIRE(t != NULL);
+	INSIST(t->nanoseconds < NS_PER_S);
+
+	/*
+	 * Ensure that the number of seconds represented by t->seconds
+	 * can be represented by a time_t.  Since t->seconds is an unsigned
+	 * int and since time_t is mostly opaque, this is trickier than
+	 * it seems.  (This standardized opaqueness of time_t is *very*
+	 * frustrating; time_t is not even limited to being an integral
+	 * type.)
+	 *
+	 * The mission, then, is to avoid generating any kind of warning
+	 * about "signed versus unsigned" while trying to determine if the
+	 * the unsigned int t->seconds is out range for tv_sec, which is
+	 * pretty much only true if time_t is a signed integer of the same
+	 * size as the return value of isc_time_seconds.
+	 *
+	 * The use of the 64 bit integer ``i'' takes advantage of C's
+	 * conversion rules to either zero fill or sign extend the widened
+	 * type.
+	 *
+	 * Solaris 5.6 gives this warning about the left shift:
+	 *	warning: integer overflow detected: op "<<"
+	 * if the U(nsigned) qualifier is not on the 1.
+	 */
+	seconds = (time_t)t->seconds;
+
+	INSIST(sizeof(unsigned int) == sizeof(isc_uint32_t));
+	INSIST(sizeof(time_t) >= sizeof(isc_uint32_t));
+
+	if (sizeof(time_t) == sizeof(isc_uint32_t) &&	       /* Same size. */
+	    (time_t)0.5 != 0.5 &&	       /* Not a floating point type. */
+	    (i = (time_t)-1) != 4294967295u &&		       /* Is signed. */
+	    (seconds &
+	     (1U << (sizeof(time_t) * CHAR_BIT - 1))) != 0U) {   /* Negative. */
+		/*
+		 * This UNUSED() is here to shut up the IRIX compiler:
+		 *	variable "i" was set but never used
+		 * when the value of i *was* used in the third test.
+		 * (Let's hope the compiler got the actual test right.)
+		 */
+		UNUSED(i);
+		return (ISC_R_RANGE);
+	}
+
+	*secondsp = seconds;
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_uint32_t
+isc_time_nanoseconds(const isc_time_t *t) {
+	REQUIRE(t != NULL);
+
+	ENSURE(t->nanoseconds < NS_PER_S);
+
+	return ((isc_uint32_t)t->nanoseconds);
+}
+
+void
+isc_time_formattimestamp(const isc_time_t *t, char *buf, unsigned int len) {
+	time_t now;
+	unsigned int flen;
+
+	REQUIRE(len > 0);
+
+	now = (time_t) t->seconds;
+	flen = strftime(buf, len, "%d-%b-%Y %X", localtime(&now));
+	INSIST(flen < len);
+	if (flen != 0)
+		snprintf(buf + flen, len - flen,
+			 ".%03u", t->nanoseconds / 1000000);
+	else
+		snprintf(buf, len, "99-Bad-9999 99:99:99.999");
+}
+
+void
+isc_time_formathttptimestamp(const isc_time_t *t, char *buf, unsigned int len) {
+	time_t now;
+	unsigned int flen;
+
+	REQUIRE(len > 0);
+
+	now = (time_t)t->seconds;
+	flen = strftime(buf, len, "%a, %d %b %Y %H:%M:%S GMT", gmtime(&now));
+	INSIST(flen < len);
+}
+
+void
+isc_time_formatISO8601(const isc_time_t *t, char *buf, unsigned int len) {
+	time_t now;
+	unsigned int flen;
+
+	REQUIRE(len > 0);
+
+	now = (time_t)t->seconds;
+	flen = strftime(buf, len, "%Y-%m-%dT%H:%M:%SZ", gmtime(&now));
+	INSIST(flen < len);
+}
diff --git a/src/lib/bind9/version.c b/src/lib/bind9/version.c
new file mode 100644
index 0000000..a43baaa
--- /dev/null
+++ b/src/lib/bind9/version.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: version.c,v 1.15 2007-06-19 23:47:17 tbox Exp $ */
+
+/*! \file */
+
+#include <isc/version.h>
+
+const char isc_version[] = "B10-0"; // VERSION;
+
+const unsigned int isc_libinterface = "B10-0"; // LIBINTERFACE;
+const unsigned int isc_librevision = "B10-0"; // LIBREVISION;
+const unsigned int isc_libage = "B10-0"; // LIBAGE;
diff --git a/src/lib/bind9/win32/DLLMain.c b/src/lib/bind9/win32/DLLMain.c
new file mode 100644
index 0000000..1e8d63e
--- /dev/null
+++ b/src/lib/bind9/win32/DLLMain.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2004, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: DLLMain.c,v 1.7 2007-06-18 23:47:49 tbox Exp $ */
+
+#include <windows.h>
+#include <stdio.h>
+
+/*
+ * Called when we enter the DLL
+ */
+__declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE hinstDLL,
+					  DWORD fdwReason, LPVOID lpvReserved)
+{
+	switch (fdwReason) 
+	{ 
+	/*
+	 * The DLL is loading due to process 
+	 * initialization or a call to LoadLibrary. 
+	 */
+	case DLL_PROCESS_ATTACH: 
+		break; 
+ 
+	/* The attached process creates a new thread.  */
+	case DLL_THREAD_ATTACH: 
+		break; 
+ 
+	/* The thread of the attached process terminates. */
+	case DLL_THREAD_DETACH: 
+		break; 
+ 
+	/*
+	 * The DLL is unloading from a process due to 
+	 * process termination or a call to FreeLibrary. 
+	 */
+	case DLL_PROCESS_DETACH: 
+		break; 
+
+	default: 
+		break; 
+	} 
+	return (TRUE);
+}
+
diff --git a/src/lib/bind9/win32/app.c b/src/lib/bind9/win32/app.c
new file mode 100644
index 0000000..f04d3d7
--- /dev/null
+++ b/src/lib/bind9/win32/app.c
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2004, 2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: app.c,v 1.9 2009-09-02 23:48:03 tbox Exp $ */
+
+#include <config.h>
+
+#include <sys/types.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <process.h>
+
+#include <isc/app.h>
+#include <isc/boolean.h>
+#include <isc/condition.h>
+#include <isc/msgs.h>
+#include <isc/mutex.h>
+#include <isc/event.h>
+#include <isc/platform.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/time.h>
+#include <isc/util.h>
+#include <isc/thread.h>
+
+static isc_eventlist_t	on_run;
+static isc_mutex_t	lock;
+static isc_boolean_t	shutdown_requested = ISC_FALSE;
+static isc_boolean_t	running = ISC_FALSE;
+/*
+ * We assume that 'want_shutdown' can be read and written atomically.
+ */
+static isc_boolean_t	want_shutdown = ISC_FALSE;
+/*
+ * We assume that 'want_reload' can be read and written atomically.
+ */
+static isc_boolean_t	want_reload = ISC_FALSE;
+
+static isc_boolean_t	blocked  = ISC_FALSE;
+
+static isc_thread_t	blockedthread;
+
+/* Events to wait for */
+
+#define NUM_EVENTS 2
+
+enum {
+	RELOAD_EVENT,
+	SHUTDOWN_EVENT
+};
+
+static HANDLE hEvents[NUM_EVENTS];
+DWORD  dwWaitResult;
+
+/*
+ * We need to remember which thread is the main thread...
+ */
+static isc_thread_t	main_thread;
+
+isc_result_t
+isc__app_start(void) {
+	isc_result_t result;
+
+	/*
+	 * Start an ISC library application.
+	 */
+
+	main_thread = GetCurrentThread();
+
+	result = isc_mutex_init(&lock);
+	if (result != ISC_R_SUCCESS)
+		return (result);
+
+	/* Create the reload event in a non-signaled state */
+	hEvents[RELOAD_EVENT] = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+	/* Create the shutdown event in a non-signaled state */
+	hEvents[SHUTDOWN_EVENT] = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+	ISC_LIST_INIT(on_run);
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc__app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action,
+	      void *arg) {
+	isc_event_t *event;
+	isc_task_t *cloned_task = NULL;
+	isc_result_t result;
+
+
+	LOCK(&lock);
+	if (running) {
+		result = ISC_R_ALREADYRUNNING;
+		goto unlock;
+	}
+
+	/*
+	 * Note that we store the task to which we're going to send the event
+	 * in the event's "sender" field.
+	 */
+	isc_task_attach(task, &cloned_task);
+	event = isc_event_allocate(mctx, cloned_task, ISC_APPEVENT_SHUTDOWN,
+				   action, arg, sizeof(*event));
+	if (event == NULL) {
+		result = ISC_R_NOMEMORY;
+		goto unlock;
+	}
+
+	ISC_LIST_APPEND(on_run, event, ev_link);
+	result = ISC_R_SUCCESS;
+
+ unlock:
+	UNLOCK(&lock);
+	return (result);
+}
+
+isc_result_t
+isc__app_run(void) {
+	isc_event_t *event, *next_event;
+	isc_task_t *task;
+	HANDLE *pHandles = NULL;
+
+	REQUIRE(main_thread == GetCurrentThread());
+	LOCK(&lock);
+	if (!running) {
+		running = ISC_TRUE;
+
+		/*
+		 * Post any on-run events (in FIFO order).
+		 */
+		for (event = ISC_LIST_HEAD(on_run);
+		     event != NULL;
+		     event = next_event) {
+			next_event = ISC_LIST_NEXT(event, ev_link);
+			ISC_LIST_UNLINK(on_run, event, ev_link);
+			task = event->ev_sender;
+			event->ev_sender = NULL;
+			isc_task_sendanddetach(&task, &event);
+		}
+
+	}
+
+	UNLOCK(&lock);
+
+	/*
+	 * There is no danger if isc_app_shutdown() is called before we wait
+	 * for events.
+	 */
+
+	while (!want_shutdown) {
+		dwWaitResult = WaitForMultipleObjects(NUM_EVENTS, hEvents,
+						      FALSE, INFINITE);
+
+		/* See why we returned */
+
+		if (WaitSucceeded(dwWaitResult, NUM_EVENTS)) {
+			/*
+			 * The return was due to one of the events
+			 * being signaled
+			 */
+			switch (WaitSucceededIndex(dwWaitResult)) {
+			case RELOAD_EVENT:
+				want_reload = ISC_TRUE;
+				break;
+
+			case SHUTDOWN_EVENT:
+				want_shutdown = ISC_TRUE;
+				break;
+			}
+		}
+		if (want_reload) {
+			want_reload = ISC_FALSE;
+			return (ISC_R_RELOAD);
+		}
+
+		if (want_shutdown && blocked)
+			exit(-1);
+	}
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc__app_shutdown(void) {
+	isc_boolean_t want_kill = ISC_TRUE;
+
+	LOCK(&lock);
+	REQUIRE(running);
+
+	if (shutdown_requested)
+		want_kill = ISC_FALSE;		/* We're only signaling once */
+	else
+		shutdown_requested = ISC_TRUE;
+
+	UNLOCK(&lock);
+	if (want_kill)
+		SetEvent(hEvents[SHUTDOWN_EVENT]);
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc__app_reload(void) {
+	isc_boolean_t want_reload = ISC_TRUE;
+
+	LOCK(&lock);
+	REQUIRE(running);
+
+	/*
+	 * Don't send the reload signal if we're shutting down.
+	 */
+	if (shutdown_requested)
+		want_reload = ISC_FALSE;
+
+	UNLOCK(&lock);
+	if (want_reload)
+		SetEvent(hEvents[RELOAD_EVENT]);
+
+	return (ISC_R_SUCCESS);
+}
+
+void
+isc__app_finish(void) {
+	DESTROYLOCK(&lock);
+}
+
+void
+isc__app_block(void) {
+	REQUIRE(running);
+	REQUIRE(!blocked);
+
+	blocked = ISC_TRUE;
+	blockedthread = GetCurrentThread();
+}
+
+void
+isc__app_unblock(void) {
+	REQUIRE(running);
+	REQUIRE(blocked);
+	blocked = ISC_FALSE;
+	REQUIRE(blockedthread == GetCurrentThread());
+}
diff --git a/src/lib/bind9/win32/condition.c b/src/lib/bind9/win32/condition.c
new file mode 100644
index 0000000..d3c6fd8
--- /dev/null
+++ b/src/lib/bind9/win32/condition.c
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2004, 2006, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: condition.c,v 1.23 2007-06-18 23:47:49 tbox Exp $ */
+
+#include <config.h>
+
+#include <isc/condition.h>
+#include <isc/assertions.h>
+#include <isc/util.h>
+#include <isc/thread.h>
+#include <isc/time.h>
+
+#define LSIGNAL		0
+#define LBROADCAST	1
+
+isc_result_t
+isc_condition_init(isc_condition_t *cond) {
+	HANDLE h;
+
+	REQUIRE(cond != NULL);
+
+	cond->waiters = 0;
+	/*
+	 * This handle is shared across all threads
+	 */
+	h = CreateEvent(NULL, FALSE, FALSE, NULL);
+	if (h == NULL) {
+		/* XXX */
+		return (ISC_R_UNEXPECTED);
+	}
+	cond->events[LSIGNAL] = h;
+
+	/*
+	 * The threadlist will hold the actual events needed
+	 * for the wait condition
+	 */
+	ISC_LIST_INIT(cond->threadlist);
+
+	return (ISC_R_SUCCESS);
+}
+
+/*
+ * Add the thread to the threadlist along with the required events
+ */
+static isc_result_t
+register_thread(unsigned long thrd, isc_condition_t *gblcond,
+		isc_condition_thread_t **localcond)
+{
+	HANDLE hc;
+	isc_condition_thread_t *newthread;
+
+	REQUIRE(localcond != NULL && *localcond == NULL);
+
+	newthread = malloc(sizeof(isc_condition_thread_t));
+	if (newthread == NULL)
+		return (ISC_R_NOMEMORY);
+
+	/*
+	 * Create the thread-specific handle
+	 */
+	hc = CreateEvent(NULL, FALSE, FALSE, NULL);
+	if (hc == NULL) {
+		free(newthread);
+		return (ISC_R_UNEXPECTED);
+	}
+
+	/*
+	 * Add the thread ID and handles to list of threads for broadcast
+	 */
+	newthread->handle[LSIGNAL] = gblcond->events[LSIGNAL];
+	newthread->handle[LBROADCAST] = hc;
+	newthread->th = thrd;
+
+	/*
+	 * The thread is holding the manager lock so this is safe
+	 */
+	ISC_LIST_APPEND(gblcond->threadlist, newthread, link);
+	*localcond = newthread;
+	return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+find_thread_condition(unsigned long thrd, isc_condition_t *cond,
+		      isc_condition_thread_t **threadcondp)
+{
+	isc_condition_thread_t *threadcond;
+
+	REQUIRE(threadcondp != NULL && *threadcondp == NULL);
+
+	/*
+	 * Look for the thread ID.
+	 */
+	for (threadcond = ISC_LIST_HEAD(cond->threadlist);
+	     threadcond != NULL;
+	     threadcond = ISC_LIST_NEXT(threadcond, link)) {
+
+		if (threadcond->th == thrd) {
+			*threadcondp = threadcond;
+			return (ISC_R_SUCCESS);
+		}
+	}
+
+	/*
+	 * Not found, so add it.
+	 */
+	return (register_thread(thrd, cond, threadcondp));
+}
+
+isc_result_t
+isc_condition_signal(isc_condition_t *cond) {
+
+	/*
+	 * Unlike pthreads, the caller MUST hold the lock associated with
+	 * the condition variable when calling us.
+	 */
+	REQUIRE(cond != NULL);
+
+	if (!SetEvent(cond->events[LSIGNAL])) {
+		/* XXX */
+		return (ISC_R_UNEXPECTED);
+	}
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_condition_broadcast(isc_condition_t *cond) {
+
+	isc_condition_thread_t *threadcond;
+	isc_boolean_t failed = ISC_FALSE;
+
+	/*
+	 * Unlike pthreads, the caller MUST hold the lock associated with
+	 * the condition variable when calling us.
+	 */
+	REQUIRE(cond != NULL);
+
+	/*
+	 * Notify every thread registered for this
+	 */
+	for (threadcond = ISC_LIST_HEAD(cond->threadlist);
+	     threadcond != NULL;
+	     threadcond = ISC_LIST_NEXT(threadcond, link)) {
+
+		if (!SetEvent(threadcond->handle[LBROADCAST]))
+			failed = ISC_TRUE;
+	}
+
+	if (failed)
+		return (ISC_R_UNEXPECTED);
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_condition_destroy(isc_condition_t *cond) {
+
+	isc_condition_thread_t *next, *threadcond;
+
+	REQUIRE(cond != NULL);
+	REQUIRE(cond->waiters == 0);
+
+	(void)CloseHandle(cond->events[LSIGNAL]);
+
+	/*
+	 * Delete the threadlist
+	 */
+	threadcond = ISC_LIST_HEAD(cond->threadlist);
+
+	while (threadcond != NULL) {
+		next = ISC_LIST_NEXT(threadcond, link);
+		DEQUEUE(cond->threadlist, threadcond, link);
+		(void) CloseHandle(threadcond->handle[LBROADCAST]);
+		free(threadcond);
+		threadcond = next;
+	}
+
+	return (ISC_R_SUCCESS);
+}
+
+/*
+ * This is always called when the mutex (lock) is held, but because
+ * we are waiting we need to release it and reacquire it as soon as the wait
+ * is over. This allows other threads to make use of the object guarded
+ * by the mutex but it should never try to delete it as long as the
+ * number of waiters > 0. Always reacquire the mutex regardless of the
+ * result of the wait. Note that EnterCriticalSection will wait to acquire
+ * the mutex.
+ */
+static isc_result_t
+wait(isc_condition_t *cond, isc_mutex_t *mutex, DWORD milliseconds) {
+	DWORD result;
+	isc_result_t tresult;
+	isc_condition_thread_t *threadcond = NULL;
+
+	/*
+	 * Get the thread events needed for the wait
+	 */
+	tresult = find_thread_condition(isc_thread_self(), cond, &threadcond);
+	if (tresult !=  ISC_R_SUCCESS)
+		return (tresult);
+
+	cond->waiters++;
+	LeaveCriticalSection(mutex);
+	result = WaitForMultipleObjects(2, threadcond->handle, FALSE,
+					milliseconds);
+	EnterCriticalSection(mutex);
+	cond->waiters--;
+	if (result == WAIT_FAILED) {
+		/* XXX */
+		return (ISC_R_UNEXPECTED);
+	}
+	if (result == WAIT_TIMEOUT)
+		return (ISC_R_TIMEDOUT);
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_condition_wait(isc_condition_t *cond, isc_mutex_t *mutex) {
+	return (wait(cond, mutex, INFINITE));
+}
+
+isc_result_t
+isc_condition_waituntil(isc_condition_t *cond, isc_mutex_t *mutex,
+			isc_time_t *t) {
+	DWORD milliseconds;
+	isc_uint64_t microseconds;
+	isc_time_t now;
+
+	if (isc_time_now(&now) != ISC_R_SUCCESS) {
+		/* XXX */
+		return (ISC_R_UNEXPECTED);
+	}
+
+	microseconds = isc_time_microdiff(t, &now);
+	if (microseconds > 0xFFFFFFFFi64 * 1000)
+		milliseconds = 0xFFFFFFFF;
+	else
+		milliseconds = (DWORD)(microseconds / 1000);
+
+	return (wait(cond, mutex, milliseconds));
+}
diff --git a/src/lib/bind9/win32/dir.c b/src/lib/bind9/win32/dir.c
new file mode 100644
index 0000000..a9fb424
--- /dev/null
+++ b/src/lib/bind9/win32/dir.c
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2004, 2007-2009, 2011  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: dir.c,v 1.18.424.2 2011-03-12 04:59:19 tbox Exp $ */
+
+/* Principal Authors: DCL */
+
+#include <config.h>
+
+#include <string.h>
+#include <direct.h>
+#include <process.h>
+#include <io.h>
+
+#include <sys/stat.h>
+
+#include <isc/dir.h>
+#include <isc/magic.h>
+#include <isc/assertions.h>
+#include <isc/util.h>
+
+#include "errno2result.h"
+
+#define ISC_DIR_MAGIC		ISC_MAGIC('D', 'I', 'R', '*')
+#define VALID_DIR(dir)		ISC_MAGIC_VALID(dir, ISC_DIR_MAGIC)
+
+static isc_result_t
+start_directory(isc_dir_t *p);
+
+void
+isc_dir_init(isc_dir_t *dir) {
+	REQUIRE(dir != NULL);
+
+	dir->dirname[0] = '\0';
+
+	dir->entry.name[0] = '\0';
+	dir->entry.length = 0;
+	memset(&(dir->entry.find_data), 0, sizeof(dir->entry.find_data));
+
+	dir->entry_filled = ISC_FALSE;
+	dir->search_handle = INVALID_HANDLE_VALUE;
+
+	dir->magic = ISC_DIR_MAGIC;
+}
+
+/*
+ * Allocate workspace and open directory stream. If either one fails,
+ * NULL will be returned.
+ */
+isc_result_t
+isc_dir_open(isc_dir_t *dir, const char *dirname) {
+	char *p;
+	isc_result_t result;
+
+	REQUIRE(dirname != NULL);
+	REQUIRE(VALID_DIR(dir) && dir->search_handle == INVALID_HANDLE_VALUE);
+
+	/*
+	 * Copy directory name.  Need to have enough space for the name,
+	 * a possible path separator, the wildcard, and the final NUL.
+	 */
+	if (strlen(dirname) + 3 > sizeof(dir->dirname))
+		/* XXXDCL ? */
+		return (ISC_R_NOSPACE);
+	strcpy(dir->dirname, dirname);
+
+	/*
+	 * Append path separator, if needed, and "*".
+	 */
+	p = dir->dirname + strlen(dir->dirname);
+	if (dir->dirname < p && *(p - 1) != '\\' && *(p - 1) != ':')
+		*p++ = '\\';
+	*p++ = '*';
+	*p = '\0';
+
+	/*
+	 * Open stream.
+	 */
+	result = start_directory(dir);
+
+	return (result);
+}
+
+/*
+ * Return previously retrieved file or get next one.  Unix's dirent has
+ * separate open and read functions, but the Win32 and DOS interfaces open
+ * the dir stream and reads the first file in one operation.
+ */
+isc_result_t
+isc_dir_read(isc_dir_t *dir) {
+	REQUIRE(VALID_DIR(dir) && dir->search_handle != INVALID_HANDLE_VALUE);
+
+	if (dir->entry_filled)
+		/*
+		 * start_directory() already filled in the first entry.
+		 */
+		dir->entry_filled = ISC_FALSE;
+
+	else {
+		/*
+		 * Fetch next file in directory.
+		 */
+		if (FindNextFile(dir->search_handle,
+				 &dir->entry.find_data) == FALSE)
+			/*
+			 * Either the last file has been processed or
+			 * an error has occurred.  The former is not
+			 * really an error, but the latter is.
+			 */
+			if (GetLastError() == ERROR_NO_MORE_FILES)
+				return (ISC_R_NOMORE);
+			else
+				return (ISC_R_UNEXPECTED);
+	}
+
+	/*
+	 * Make sure that the space for the name is long enough.
+	 */
+	strcpy(dir->entry.name, dir->entry.find_data.cFileName);
+	dir->entry.length = strlen(dir->entry.name);
+
+	return (ISC_R_SUCCESS);
+}
+
+/*
+ * Close directory stream.
+ */
+void
+isc_dir_close(isc_dir_t *dir) {
+       REQUIRE(VALID_DIR(dir) && dir->search_handle != INVALID_HANDLE_VALUE);
+
+       FindClose(dir->search_handle);
+       dir->search_handle = INVALID_HANDLE_VALUE;
+}
+
+/*
+ * Reposition directory stream at start.
+ */
+isc_result_t
+isc_dir_reset(isc_dir_t *dir) {
+	isc_result_t result;
+
+	REQUIRE(VALID_DIR(dir) && dir->search_handle != INVALID_HANDLE_VALUE);
+	REQUIRE(dir->dirname != NULL);
+
+	/*
+	 * NT cannot reposition the seek pointer to the beginning of the
+	 * the directory stream, but rather the directory needs to be
+	 * closed and reopened.  The latter might fail.
+	 */
+
+	isc_dir_close(dir);
+
+	result = start_directory(dir);
+
+	return (result);
+}
+
+/*
+ * Initialize isc_dir_t structure with new directory. The function
+ * returns 0 on failure and nonzero on success.
+ *
+ * Note:
+ * - Be sure to close previous stream before opening new one
+ */
+static isc_result_t
+start_directory(isc_dir_t *dir)
+{
+	REQUIRE(VALID_DIR(dir));
+	REQUIRE(dir->search_handle == INVALID_HANDLE_VALUE);
+
+	dir->entry_filled = ISC_FALSE;
+
+	/*
+	 * Open stream and retrieve first file.
+	 */
+	dir->search_handle = FindFirstFile(dir->dirname,
+					    &dir->entry.find_data);
+
+	if (dir->search_handle == INVALID_HANDLE_VALUE) {
+		/*
+		 * Something went wrong but we don't know what. GetLastError()
+		 * could give us more information about the error, but the
+		 * MSDN documentation is frustratingly thin about what
+		 * possible errors could have resulted.  (Score one for
+		 * the Unix manual pages.)  So there is just this lame error
+		 * instead of being able to differentiate ISC_R_NOTFOUND
+		 * from ISC_R_UNEXPECTED.
+		 */
+		return (ISC_R_FAILURE);
+	}
+
+	/*
+	 * Make sure that the space for the name is long enough.
+	 */
+	INSIST(sizeof(dir->entry.name) >
+	       strlen(dir->entry.find_data.cFileName));
+
+	/*
+	 * Fill in the data for the first entry of the directory.
+	 */
+	strcpy(dir->entry.name, dir->entry.find_data.cFileName);
+	dir->entry.length = strlen(dir->entry.name);
+
+	dir->entry_filled = ISC_TRUE;
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_dir_chdir(const char *dirname) {
+	/*
+	 * Change the current directory to 'dirname'.
+	 */
+
+	REQUIRE(dirname != NULL);
+
+	if (chdir(dirname) < 0)
+		return (isc__errno2result(errno));
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_dir_chroot(const char *dirname) {
+	return (ISC_R_NOTIMPLEMENTED);
+}
+
+isc_result_t
+isc_dir_createunique(char *templet) {
+	isc_result_t result;
+	char *x;
+	char *p;
+	int i;
+	int pid;
+
+	REQUIRE(templet != NULL);
+
+	/*
+	 * mkdtemp is not portable, so this emulates it.
+	 */
+
+	pid = getpid();
+
+	/*
+	 * Replace trailing Xs with the process-id, zero-filled.
+	 */
+	for (x = templet + strlen(templet) - 1; *x == 'X' && x >= templet;
+	     x--, pid /= 10)
+		*x = pid % 10 + '0';
+
+	x++;			/* Set x to start of ex-Xs. */
+
+	do {
+		i = mkdir(templet);
+		i = chmod(templet, 0700);
+
+		if (i == 0 || errno != EEXIST)
+			break;
+
+		/*
+		 * The BSD algorithm.
+		 */
+		p = x;
+		while (*p != '\0') {
+			if (isdigit(*p & 0xff))
+				*p = 'a';
+			else if (*p != 'z')
+				++*p;
+			else {
+				/*
+				 * Reset character and move to next.
+				 */
+				*p++ = 'a';
+				continue;
+			}
+
+			break;
+		}
+
+		if (*p == '\0') {
+			/*
+			 * Tried all combinations.  errno should already
+			 * be EEXIST, but ensure it is anyway for
+			 * isc__errno2result().
+			 */
+			errno = EEXIST;
+			break;
+		}
+	} while (1);
+
+	if (i == -1)
+		result = isc__errno2result(errno);
+	else
+		result = ISC_R_SUCCESS;
+
+	return (result);
+}
diff --git a/src/lib/bind9/win32/entropy.c b/src/lib/bind9/win32/entropy.c
new file mode 100644
index 0000000..2228d65
--- /dev/null
+++ b/src/lib/bind9/win32/entropy.c
@@ -0,0 +1,307 @@
+/*
+ * Copyright (C) 2004, 2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2002  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: entropy.c,v 1.10 2009-01-18 23:48:14 tbox Exp $ */
+
+/*
+ * This is the system dependent part of the ISC entropy API.
+ */
+
+#include <config.h>
+
+#include <windows.h>
+#include <wincrypt.h>
+
+#include <process.h>
+#include <io.h>
+#include <share.h>
+
+/*
+ * There is only one variable in the entropy data structures that is not
+ * system independent, but pulling the structure that uses it into this file
+ * ultimately means pulling several other independent structures here also to
+ * resolve their interdependencies.  Thus only the problem variable's type
+ * is defined here.
+ */
+#define FILESOURCE_HANDLE_TYPE	HCRYPTPROV
+
+typedef struct {
+	int dummy;
+} isc_entropyusocketsource_t;
+
+#include "../entropy.c"
+
+static unsigned int
+get_from_filesource(isc_entropysource_t *source, isc_uint32_t desired) {
+	isc_entropy_t *ent = source->ent;
+	unsigned char buf[128];
+	HCRYPTPROV hcryptprov = source->sources.file.handle;
+	ssize_t ndesired;
+	unsigned int added;
+
+	if (source->bad)
+		return (0);
+
+	desired = desired / 8 + (((desired & 0x07) > 0) ? 1 : 0);
+
+	added = 0;
+	while (desired > 0) {
+		ndesired = ISC_MIN(desired, sizeof(buf));
+		if (!CryptGenRandom(hcryptprov, ndesired, buf)) {
+			CryptReleaseContext(hcryptprov, 0);
+			source->bad = ISC_TRUE;
+			goto out;
+		}
+
+		entropypool_adddata(ent, buf, ndesired, ndesired * 8);
+		added += ndesired * 8;
+		desired -= ndesired;
+	}
+
+ out:
+	return (added);
+}
+
+/*
+ * Poll each source, trying to get data from it to stuff into the entropy
+ * pool.
+ */
+static void
+fillpool(isc_entropy_t *ent, unsigned int desired, isc_boolean_t blocking) {
+	unsigned int added;
+	unsigned int remaining;
+	unsigned int needed;
+	unsigned int nsource;
+	isc_entropysource_t *source;
+	isc_entropysource_t *firstsource;
+
+	REQUIRE(VALID_ENTROPY(ent));
+
+	needed = desired;
+
+	/*
+	 * This logic is a little strange, so an explanation is in order.
+	 *
+	 * If needed is 0, it means we are being asked to "fill to whatever
+	 * we think is best."  This means that if we have at least a
+	 * partially full pool (say, > 1/4th of the pool) we probably don't
+	 * need to add anything.
+	 *
+	 * Also, we will check to see if the "pseudo" count is too high.
+	 * If it is, try to mix in better data.  Too high is currently
+	 * defined as 1/4th of the pool.
+	 *
+	 * Next, if we are asked to add a specific bit of entropy, make
+	 * certain that we will do so.  Clamp how much we try to add to
+	 * (DIGEST_SIZE * 8 < needed < POOLBITS - entropy).
+	 *
+	 * Note that if we are in a blocking mode, we will only try to
+	 * get as much data as we need, not as much as we might want
+	 * to build up.
+	 */
+	if (needed == 0) {
+		REQUIRE(!blocking);
+
+		if ((ent->pool.entropy >= RND_POOLBITS / 4)
+		    && (ent->pool.pseudo <= RND_POOLBITS / 4))
+			return;
+
+		needed = THRESHOLD_BITS * 4;
+	} else {
+		needed = ISC_MAX(needed, THRESHOLD_BITS);
+		needed = ISC_MIN(needed, RND_POOLBITS);
+	}
+
+	/*
+	 * In any case, clamp how much we need to how much we can add.
+	 */
+	needed = ISC_MIN(needed, RND_POOLBITS - ent->pool.entropy);
+
+	/*
+	 * But wait!  If we're not yet initialized, we need at least
+	 *	THRESHOLD_BITS
+	 * of randomness.
+	 */
+	if (ent->initialized < THRESHOLD_BITS)
+		needed = ISC_MAX(needed, THRESHOLD_BITS - ent->initialized);
+
+	/*
+	 * Poll each file source to see if we can read anything useful from
+	 * it.  XXXMLG When where are multiple sources, we should keep a
+	 * record of which one we last used so we can start from it (or the
+	 * next one) to avoid letting some sources build up entropy while
+	 * others are always drained.
+	 */
+
+	added = 0;
+	remaining = needed;
+	if (ent->nextsource == NULL) {
+		ent->nextsource = ISC_LIST_HEAD(ent->sources);
+		if (ent->nextsource == NULL)
+			return;
+	}
+	source = ent->nextsource;
+	/*
+	 * Remember the first source so we can break if we have looped back to
+	 * the beginning and still have nothing
+	 */
+	firstsource = source;
+ again_file:
+	for (nsource = 0; nsource < ent->nsources; nsource++) {
+		unsigned int got;
+
+		if (remaining == 0)
+			break;
+
+		got = 0;
+
+		if (source->type == ENTROPY_SOURCETYPE_FILE)
+			got = get_from_filesource(source, remaining);
+
+		added += got;
+
+		remaining -= ISC_MIN(remaining, got);
+
+		source = ISC_LIST_NEXT(source, link);
+		if (source == NULL)
+			source = ISC_LIST_HEAD(ent->sources);
+	}
+	ent->nextsource = source;
+
+	/*
+	 * Go again only if there's been progress and we've not
+	 * gone back to the beginning
+	 */
+	if (!(ent->nextsource == firstsource && added == 0)) {
+		if (blocking && remaining != 0) {
+				goto again_file;
+		}
+	}
+
+	/*
+	 * Here, if there are bits remaining to be had and we can block,
+	 * check to see if we have a callback source.  If so, call them.
+	 */
+	source = ISC_LIST_HEAD(ent->sources);
+	while ((remaining != 0) && (source != NULL)) {
+		unsigned int got;
+
+		got = 0;
+
+		if (source->type == ENTROPY_SOURCETYPE_CALLBACK)
+			got = get_from_callback(source, remaining, blocking);
+
+		added += got;
+		remaining -= ISC_MIN(remaining, got);
+
+		if (added >= needed)
+			break;
+
+		source = ISC_LIST_NEXT(source, link);
+	}
+
+	/*
+	 * Mark as initialized if we've added enough data.
+	 */
+	if (ent->initialized < THRESHOLD_BITS)
+		ent->initialized += added;
+}
+
+
+
+/*
+ * Requires "ent" be locked.
+ */
+static void
+destroyfilesource(isc_entropyfilesource_t *source) {
+	CryptReleaseContext(source->handle, 0);
+}
+
+static void
+destroyusocketsource(isc_entropyusocketsource_t *source) {
+	UNUSED(source);
+}
+
+
+isc_result_t
+isc_entropy_createfilesource(isc_entropy_t *ent, const char *fname) {
+	isc_result_t ret;
+	isc_entropysource_t *source;
+	HCRYPTPROV hcryptprov;
+	DWORD errval;
+	BOOL err;
+
+	REQUIRE(VALID_ENTROPY(ent));
+	REQUIRE(fname != NULL);
+
+	LOCK(&ent->lock);
+
+	source = NULL;
+
+	/*
+	 * The first time we just try to acquire the context
+	 */
+	err = CryptAcquireContext(&hcryptprov, NULL, NULL, PROV_RSA_FULL,
+				  CRYPT_VERIFYCONTEXT);
+	if (!err){
+		errval = GetLastError();
+		ret = ISC_R_IOERROR;
+		goto errout;
+	}
+
+	source = isc_mem_get(ent->mctx, sizeof(isc_entropysource_t));
+	if (source == NULL) {
+		ret = ISC_R_NOMEMORY;
+		goto closecontext;
+	}
+
+	/*
+	 * From here down, no failures can occur.
+	 */
+	source->magic = SOURCE_MAGIC;
+	source->type = ENTROPY_SOURCETYPE_FILE;
+	source->ent = ent;
+	source->total = 0;
+	source->bad = ISC_FALSE;
+	memset(source->name, 0, sizeof(source->name));
+	ISC_LINK_INIT(source, link);
+	source->sources.file.handle = hcryptprov;
+
+	/*
+	 * Hook it into the entropy system.
+	 */
+	ISC_LIST_APPEND(ent->sources, source, link);
+	ent->nsources++;
+
+	UNLOCK(&ent->lock);
+	return (ISC_R_SUCCESS);
+
+ closecontext:
+	CryptReleaseContext(hcryptprov, 0);
+
+ errout:
+	if (source != NULL)
+		isc_mem_put(ent->mctx, source, sizeof(isc_entropysource_t));
+
+	UNLOCK(&ent->lock);
+
+	return (ret);
+}
+
+
+
+
diff --git a/src/lib/bind9/win32/errno2result.c b/src/lib/bind9/win32/errno2result.c
new file mode 100644
index 0000000..afe338d
--- /dev/null
+++ b/src/lib/bind9/win32/errno2result.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2008  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2002  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: errno2result.c,v 1.17 2008-09-12 04:46:25 marka Exp $ */
+
+#include <config.h>
+
+#include <winsock2.h>
+#include "errno2result.h"
+#include <isc/result.h>
+#include <isc/strerror.h>
+#include <isc/util.h>
+
+/*
+ * Convert a POSIX errno value into an isc_result_t.  The
+ * list of supported errno values is not complete; new users
+ * of this function should add any expected errors that are
+ * not already there.
+ */
+isc_result_t
+isc__errno2resultx(int posixerrno, const char *file, int line) {
+	char strbuf[ISC_STRERRORSIZE];
+
+	switch (posixerrno) {
+	case ENOTDIR:
+	case WSAELOOP:
+	case WSAEINVAL:
+	case EINVAL:		/* XXX sometimes this is not for files */
+	case ENAMETOOLONG:
+	case WSAENAMETOOLONG:
+	case EBADF:
+	case WSAEBADF:
+		return (ISC_R_INVALIDFILE);
+	case ENOENT:
+		return (ISC_R_FILENOTFOUND);
+	case EACCES:
+	case WSAEACCES:
+	case EPERM:
+		return (ISC_R_NOPERM);
+	case EEXIST:
+		return (ISC_R_FILEEXISTS);
+	case EIO:
+		return (ISC_R_IOERROR);
+	case ENOMEM:
+		return (ISC_R_NOMEMORY);
+	case ENFILE:
+	case EMFILE:
+	case WSAEMFILE:
+		return (ISC_R_TOOMANYOPENFILES);
+	case ERROR_CANCELLED:
+		return (ISC_R_CANCELED);
+	case ERROR_CONNECTION_REFUSED:
+	case WSAECONNREFUSED:
+		return (ISC_R_CONNREFUSED);
+	case WSAENOTCONN:
+	case ERROR_CONNECTION_INVALID:
+		return (ISC_R_NOTCONNECTED);
+	case ERROR_HOST_UNREACHABLE:
+	case WSAEHOSTUNREACH:
+		return (ISC_R_HOSTUNREACH);
+	case ERROR_NETWORK_UNREACHABLE:
+	case WSAENETUNREACH:
+		return (ISC_R_NETUNREACH);
+	case ERROR_NO_NETWORK:
+		return (ISC_R_NETUNREACH);
+	case ERROR_PORT_UNREACHABLE:
+		return (ISC_R_HOSTUNREACH);
+	case ERROR_SEM_TIMEOUT:
+		return (ISC_R_TIMEDOUT);
+	case WSAECONNRESET:
+	case WSAENETRESET:
+	case WSAECONNABORTED:
+	case WSAEDISCON:
+	case ERROR_OPERATION_ABORTED:
+	case ERROR_CONNECTION_ABORTED:
+	case ERROR_REQUEST_ABORTED:
+		return (ISC_R_CONNECTIONRESET);
+	case WSAEADDRNOTAVAIL:
+		return (ISC_R_ADDRNOTAVAIL);
+	case ERROR_NETNAME_DELETED:
+	case WSAENETDOWN:
+		return (ISC_R_NETUNREACH);
+	case WSAEHOSTDOWN:
+		return (ISC_R_HOSTUNREACH);
+	case WSAENOBUFS:
+		return (ISC_R_NORESOURCES);
+	default:
+		isc__strerror(posixerrno, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(file, line, "unable to convert errno "
+				 "to isc_result: %d: %s", posixerrno, strbuf);
+		/*
+		 * XXXDCL would be nice if perhaps this function could
+		 * return the system's error string, so the caller
+		 * might have something more descriptive than "unexpected
+		 * error" to log with.
+		 */
+		return (ISC_R_UNEXPECTED);
+	}
+}
diff --git a/src/lib/bind9/win32/errno2result.h b/src/lib/bind9/win32/errno2result.h
new file mode 100644
index 0000000..edf59d9
--- /dev/null
+++ b/src/lib/bind9/win32/errno2result.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: errno2result.h,v 1.10 2007-06-19 23:47:19 tbox Exp $ */
+
+#ifndef UNIX_ERRNO2RESULT_H
+#define UNIX_ERRNO2RESULT_H 1
+
+/* XXXDCL this should be moved to lib/isc/include/isc/errno2result.h. */
+
+#include <errno.h>		/* Provides errno. */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+#define isc__errno2result(posixerrno) \
+	isc__errno2resultx(posixerrno, __FILE__, __LINE__)
+
+isc_result_t
+isc__errno2resultx(int posixerrno, const char *file, int line);
+
+ISC_LANG_ENDDECLS
+
+#endif /* UNIX_ERRNO2RESULT_H */
diff --git a/src/lib/bind9/win32/file.c b/src/lib/bind9/win32/file.c
new file mode 100644
index 0000000..344a34d
--- /dev/null
+++ b/src/lib/bind9/win32/file.c
@@ -0,0 +1,619 @@
+/*
+ * Copyright (C) 2004, 2007, 2009, 2011  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2002  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: file.c,v 1.39.8.1 2011-03-04 14:10:13 smann Exp $ */
+
+#include <config.h>
+
+#undef rename
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <io.h>
+#include <process.h>
+
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/utime.h>
+
+#include <isc/file.h>
+#include <isc/mem.h>
+#include <isc/result.h>
+#include <isc/time.h>
+#include <isc/util.h>
+#include <isc/stat.h>
+#include <isc/string.h>
+
+#include "errno2result.h"
+
+/*
+ * Emulate UNIX mkstemp, which returns an open FD to the new file
+ *
+ */
+static int
+gettemp(char *path, int *doopen) {
+	char *start, *trv;
+	struct stat sbuf;
+	int pid;
+
+	trv = strrchr(path, 'X');
+	trv++;
+	pid = getpid();
+	/* extra X's get set to 0's */
+	while (*--trv == 'X') {
+		*trv = (pid % 10) + '0';
+		pid /= 10;
+	}
+	/*
+	 * check the target directory; if you have six X's and it
+	 * doesn't exist this runs for a *very* long time.
+	 */
+	for (start = trv + 1;; --trv) {
+		if (trv <= path)
+			break;
+		if (*trv == '\\') {
+			*trv = '\0';
+			if (stat(path, &sbuf))
+				return (0);
+			if (!S_ISDIR(sbuf.st_mode)) {
+				errno = ENOTDIR;
+				return (0);
+			}
+			*trv = '\\';
+			break;
+		}
+	}
+
+	for (;;) {
+		if (doopen) {
+			if ((*doopen =
+			    open(path, O_CREAT|O_EXCL|O_RDWR,
+				 _S_IREAD | _S_IWRITE)) >= 0)
+				return (1);
+			if (errno != EEXIST)
+				return (0);
+		} else if (stat(path, &sbuf))
+			return (errno == ENOENT ? 1 : 0);
+
+		/* tricky little algorithm for backward compatibility */
+		for (trv = start;;) {
+			if (!*trv)
+				return (0);
+			if (*trv == 'z')
+				*trv++ = 'a';
+			else {
+				if (isdigit(*trv))
+					*trv = 'a';
+				else
+					++*trv;
+				break;
+			}
+		}
+	}
+	/*NOTREACHED*/
+}
+
+static int
+mkstemp(char *path) {
+	int fd;
+
+	return (gettemp(path, &fd) ? fd : -1);
+}
+
+/*
+ * XXXDCL As the API for accessing file statistics undoubtedly gets expanded,
+ * it might be good to provide a mechanism that allows for the results
+ * of a previous stat() to be used again without having to do another stat,
+ * such as perl's mechanism of using "_" in place of a file name to indicate
+ * that the results of the last stat should be used.  But then you get into
+ * annoying MP issues.   BTW, Win32 has stat().
+ */
+static isc_result_t
+file_stats(const char *file, struct stat *stats) {
+	isc_result_t result = ISC_R_SUCCESS;
+
+	REQUIRE(file != NULL);
+	REQUIRE(stats != NULL);
+
+	if (stat(file, stats) != 0)
+		result = isc__errno2result(errno);
+
+	return (result);
+}
+
+/*
+ * isc_file_safemovefile is needed to be defined here to ensure that
+ * any file with the new name is renamed to a backup name and then the
+ * rename is done. If all goes well then the backup can be deleted,
+ * otherwise it gets renamed back.
+ */
+
+int
+isc_file_safemovefile(const char *oldname, const char *newname) {
+	BOOL filestatus;
+	char buf[512];
+	struct stat sbuf;
+	BOOL exists = FALSE;
+	int tmpfd;
+
+	/*
+	 * Make sure we have something to do
+	 */
+	if (stat(oldname, &sbuf) != 0) {
+		errno = ENOENT;
+		return (-1);
+	}
+
+	/*
+	 * Rename to a backup the new file if it still exists
+	 */
+	if (stat(newname, &sbuf) == 0) {
+		exists = TRUE;
+		strcpy(buf, newname);
+		strcat(buf, ".XXXXX");
+		tmpfd = mkstemp(buf);
+		if (tmpfd > 0)
+			_close(tmpfd);
+		DeleteFile(buf);
+		_chmod(newname, _S_IREAD | _S_IWRITE);
+
+		filestatus = MoveFile(newname, buf);
+	}
+	/* Now rename the file to the new name
+	 */
+	_chmod(oldname, _S_IREAD | _S_IWRITE);
+
+	filestatus = MoveFile(oldname, newname);
+	if (filestatus == 0) {
+		/*
+		 * Try to rename the backup back to the original name
+		 * if the backup got created
+		 */
+		if (exists == TRUE) {
+			filestatus = MoveFile(buf, newname);
+			if (filestatus == 0)
+				errno = EACCES;
+		}
+		return (-1);
+	}
+
+	/*
+	 * Delete the backup file if it got created
+	 */
+	if (exists == TRUE)
+		filestatus = DeleteFile(buf);
+	return (0);
+}
+
+isc_result_t
+isc_file_getmodtime(const char *file, isc_time_t *time) {
+	int fh;
+
+	REQUIRE(file != NULL);
+	REQUIRE(time != NULL);
+
+	if ((fh = open(file, _O_RDONLY | _O_BINARY)) < 0)
+		return (isc__errno2result(errno));
+
+	if (!GetFileTime((HANDLE) _get_osfhandle(fh),
+			 NULL,
+			 NULL,
+			 &time->absolute))
+	{
+		close(fh);
+		errno = EINVAL;
+		return (isc__errno2result(errno));
+	}
+	close(fh);
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_file_settime(const char *file, isc_time_t *time) {
+	int fh;
+
+	REQUIRE(file != NULL && time != NULL);
+
+	if ((fh = open(file, _O_RDWR | _O_BINARY)) < 0)
+		return (isc__errno2result(errno));
+
+	/*
+	 * Set the date via the filedate system call and return.  Failing
+	 * this call implies the new file times are not supported by the
+	 * underlying file system.
+	 */
+	if (!SetFileTime((HANDLE) _get_osfhandle(fh),
+			 NULL,
+			 &time->absolute,
+			 &time->absolute))
+	{
+		close(fh);
+		errno = EINVAL;
+		return (isc__errno2result(errno));
+	}
+
+	close(fh);
+	return (ISC_R_SUCCESS);
+
+}
+
+#undef TEMPLATE
+#define TEMPLATE "XXXXXXXXXX.tmp" /* 14 characters. */
+
+isc_result_t
+isc_file_mktemplate(const char *path, char *buf, size_t buflen) {
+	return (isc_file_template(path, TEMPLATE, buf, buflen));
+}
+
+isc_result_t
+isc_file_template(const char *path, const char *templet, char *buf,
+			size_t buflen) {
+	char *s;
+
+	REQUIRE(path != NULL);
+	REQUIRE(templet != NULL);
+	REQUIRE(buf != NULL);
+
+	s = strrchr(templet, '\\');
+	if (s != NULL)
+		templet = s + 1;
+
+	s = strrchr(path, '\\');
+
+	if (s != NULL) {
+		if ((s - path + 1 + strlen(templet) + 1) > buflen)
+			return (ISC_R_NOSPACE);
+
+		strncpy(buf, path, s - path + 1);
+		buf[s - path + 1] = '\0';
+		strcat(buf, templet);
+	} else {
+		if ((strlen(templet) + 1) > buflen)
+			return (ISC_R_NOSPACE);
+
+		strcpy(buf, templet);
+	}
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_file_renameunique(const char *file, char *templet) {
+	int fd = -1;
+	int res = 0;
+	isc_result_t result = ISC_R_SUCCESS;
+
+	REQUIRE(file != NULL);
+	REQUIRE(templet != NULL);
+
+	fd = mkstemp(templet);
+	if (fd == -1)
+		result = isc__errno2result(errno);
+	else
+		close(fd);
+
+	if (result == ISC_R_SUCCESS) {
+		res = isc_file_safemovefile(file, templet);
+		if (res != 0) {
+			result = isc__errno2result(errno);
+			(void)unlink(templet);
+		}
+	}
+	return (result);
+}
+
+isc_result_t
+isc_file_openuniqueprivate(char *templet, FILE **fp) {
+	int mode = _S_IREAD | _S_IWRITE;
+	return (isc_file_openuniquemode(templet, mode, fp));
+}
+
+isc_result_t
+isc_file_openunique(char *templet, FILE **fp) {
+	int mode = _S_IREAD | _S_IWRITE;
+	return (isc_file_openuniquemode(templet, mode, fp));
+}
+
+isc_result_t
+isc_file_openuniquemode(char *templet, int mode, FILE **fp) {
+	int fd;
+	FILE *f;
+	isc_result_t result = ISC_R_SUCCESS;
+
+	REQUIRE(templet != NULL);
+	REQUIRE(fp != NULL && *fp == NULL);
+
+	/*
+	 * Win32 does not have mkstemp. Using emulation above.
+	 */
+	fd = mkstemp(templet);
+
+	if (fd == -1)
+		result = isc__errno2result(errno);
+	if (result == ISC_R_SUCCESS) {
+#if 1
+		UNUSED(mode);
+#else
+		(void)fchmod(fd, mode);
+#endif
+		f = fdopen(fd, "w+");
+		if (f == NULL) {
+			result = isc__errno2result(errno);
+			(void)remove(templet);
+			(void)close(fd);
+		} else
+			*fp = f;
+	}
+
+	return (result);
+}
+
+isc_result_t
+isc_file_remove(const char *filename) {
+	int r;
+
+	REQUIRE(filename != NULL);
+
+	r = unlink(filename);
+	if (r == 0)
+		return (ISC_R_SUCCESS);
+	else
+		return (isc__errno2result(errno));
+}
+
+isc_result_t
+isc_file_rename(const char *oldname, const char *newname) {
+	int r;
+
+	REQUIRE(oldname != NULL);
+	REQUIRE(newname != NULL);
+
+	r = isc_file_safemovefile(oldname, newname);
+	if (r == 0)
+		return (ISC_R_SUCCESS);
+	else
+		return (isc__errno2result(errno));
+}
+
+isc_boolean_t
+isc_file_exists(const char *pathname) {
+	struct stat stats;
+
+	REQUIRE(pathname != NULL);
+
+	return (ISC_TF(file_stats(pathname, &stats) == ISC_R_SUCCESS));
+}
+
+isc_result_t
+isc_file_isplainfile(const char *filename) {
+	/*
+	 * This function returns success if filename is a plain file.
+	 */
+	struct stat filestat;
+	memset(&filestat,0,sizeof(struct stat));
+
+	if ((stat(filename, &filestat)) == -1)
+		return(isc__errno2result(errno));
+
+	if(! S_ISREG(filestat.st_mode))
+		return(ISC_R_INVALIDFILE);
+
+	return(ISC_R_SUCCESS);
+}
+
+isc_boolean_t
+isc_file_isabsolute(const char *filename) {
+	REQUIRE(filename != NULL);
+	/*
+	 * Look for c:\path\... style, c:/path/... or \\computer\shar\path...
+	 * the UNC style file specs
+	 */
+	if ((filename[0] == '\\') && (filename[1] == '\\'))
+		return (ISC_TRUE);
+	if (isalpha(filename[0]) && filename[1] == ':' && filename[2] == '\\')
+		return (ISC_TRUE);
+	if (isalpha(filename[0]) && filename[1] == ':' && filename[2] == '/')
+		return (ISC_TRUE);
+	return (ISC_FALSE);
+}
+
+isc_boolean_t
+isc_file_iscurrentdir(const char *filename) {
+	REQUIRE(filename != NULL);
+	return (ISC_TF(filename[0] == '.' && filename[1] == '\0'));
+}
+
+isc_boolean_t
+isc_file_ischdiridempotent(const char *filename) {
+	REQUIRE(filename != NULL);
+
+	if (isc_file_isabsolute(filename))
+		return (ISC_TRUE);
+	if (filename[0] == '\\')
+		return (ISC_TRUE);
+	if (filename[0] == '/')
+		return (ISC_TRUE);
+	if (isc_file_iscurrentdir(filename))
+		return (ISC_TRUE);
+	return (ISC_FALSE);
+}
+
+const char *
+isc_file_basename(const char *filename) {
+	char *s;
+
+	REQUIRE(filename != NULL);
+
+	s = strrchr(filename, '\\');
+	if (s == NULL)
+		return (filename);
+	return (s + 1);
+}
+
+isc_result_t
+isc_file_progname(const char *filename, char *progname, size_t namelen) {
+	const char *s;
+	char *p;
+	size_t len;
+
+	REQUIRE(filename != NULL);
+	REQUIRE(progname != NULL);
+
+	/*
+	 * Strip the path from the name
+	 */
+	s = isc_file_basename(filename);
+	if (s == NULL) {
+		return (ISC_R_NOSPACE);
+	}
+
+	/*
+	 * Strip any and all suffixes
+	 */
+	p = strchr(s, '.');
+	if (p == NULL) {
+		if (namelen <= strlen(s))
+			return (ISC_R_NOSPACE);
+
+		strcpy(progname, s);
+		return (ISC_R_SUCCESS);
+	}
+
+	/*
+	 * Copy the result to the buffer
+	 */
+	len = p - s;
+	if (len >= namelen)
+		return (ISC_R_NOSPACE);
+
+	strncpy(progname, s, len);
+	progname[len] = '\0';
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_file_absolutepath(const char *filename, char *path, size_t pathlen) {
+	char *ptrname;
+	DWORD retval;
+
+	REQUIRE(filename != NULL);
+	REQUIRE(path != NULL);
+
+	retval = GetFullPathName(filename, pathlen, path, &ptrname);
+
+	/* Something went wrong in getting the path */
+	if (retval == 0)
+		return (ISC_R_NOTFOUND);
+	/* Caller needs to provide a larger buffer to contain the string */
+	if (retval >= pathlen)
+		return (ISC_R_NOSPACE);
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_file_truncate(const char *filename, isc_offset_t size) {
+	int fh;
+
+	REQUIRE(filename != NULL && size >= 0);
+
+	if ((fh = open(filename, _O_RDWR | _O_BINARY)) < 0)
+		return (isc__errno2result(errno));
+
+	if(_chsize(fh, size) != 0) {
+		close(fh);
+		return (isc__errno2result(errno));
+	}
+	close(fh);
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_file_safecreate(const char *filename, FILE **fp) {
+	isc_result_t result;
+	int flags;
+	struct stat sb;
+	FILE *f;
+	int fd;
+
+	REQUIRE(filename != NULL);
+	REQUIRE(fp != NULL && *fp == NULL);
+
+	result = file_stats(filename, &sb);
+	if (result == ISC_R_SUCCESS) {
+		if ((sb.st_mode & S_IFREG) == 0)
+			return (ISC_R_INVALIDFILE);
+		flags = O_WRONLY | O_TRUNC;
+	} else if (result == ISC_R_FILENOTFOUND) {
+		flags = O_WRONLY | O_CREAT | O_EXCL;
+	} else
+		return (result);
+
+	fd = open(filename, flags, S_IRUSR | S_IWUSR);
+	if (fd == -1)
+		return (isc__errno2result(errno));
+
+	f = fdopen(fd, "w");
+	if (f == NULL) {
+		result = isc__errno2result(errno);
+		close(fd);
+		return (result);
+	}
+
+	*fp = f;
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_file_splitpath(isc_mem_t *mctx, char *path, char **dirname, char **basename)
+{
+	char *dir, *file, *slash;
+	char *backslash;
+
+	slash = strrchr(path, '/');
+
+	backslash = strrchr(path, '\\');
+	if ((slash != NULL && backslash != NULL && backslash > slash) ||
+	    (slash == NULL && backslash != NULL))
+		slash = backslash;
+
+	if (slash == path) {
+		file = ++slash;
+		dir = isc_mem_strdup(mctx, "/");
+	} else if (slash != NULL) {
+		file = ++slash;
+		dir = isc_mem_allocate(mctx, slash - path);
+		if (dir != NULL)
+			strlcpy(dir, path, slash - path);
+	} else {
+		file = path;
+		dir = isc_mem_strdup(mctx, ".");
+	}
+
+	if (dir == NULL)
+		return (ISC_R_NOMEMORY);
+
+	if (*file == '\0') {
+		isc_mem_free(mctx, dir);
+		return (ISC_R_INVALIDFILE);
+	}
+
+	*dirname = dir;
+	*basename = file;
+
+	return (ISC_R_SUCCESS);
+}
diff --git a/src/lib/bind9/win32/fsaccess.c b/src/lib/bind9/win32/fsaccess.c
new file mode 100644
index 0000000..2f1f6c8
--- /dev/null
+++ b/src/lib/bind9/win32/fsaccess.c
@@ -0,0 +1,375 @@
+/*
+ * Copyright (C) 2004, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2002  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: fsaccess.c,v 1.15 2007-06-19 23:47:19 tbox Exp $ */
+
+/*
+ * Note that Win32 does not have the concept of files having access
+ * and ownership bits.  The FAT File system only has a readonly flag
+ * for everyone and that's all. NTFS uses ACL's which is a totally
+ * different concept of controlling access.
+ *
+ * This code needs to be revisited to set up proper access control for
+ * NTFS file systems.  Nothing can be done for FAT file systems.
+ */
+
+#include <config.h>
+
+#include <aclapi.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <io.h>
+#include <errno.h>
+
+#include <isc/file.h>
+#include <isc/stat.h>
+
+#include "errno2result.h"
+
+/*
+ * The OS-independent part of the API is in lib/isc.
+ */
+#include "../fsaccess.c"
+
+/* Store the user account name locally */
+static char username[255] = "\0";
+static DWORD namelen = 0;
+
+/*
+ * In order to set or retrieve access information, we need to obtain
+ * the File System type.  These could be UNC-type shares.
+ */
+
+BOOL
+is_ntfs(const char * file) {
+
+	char drive[255];
+	char FSType[20];
+	char tmpbuf[256];
+	char *machinename;
+	char *sharename;
+	char filename[1024];
+
+	REQUIRE(filename != NULL);
+
+	if (isc_file_absolutepath(file, filename,
+		sizeof(filename)) != ISC_R_SUCCESS) {
+		return (FALSE);
+	}
+
+	/*
+	 * Look for c:\path\... style, c:/path/... or \\computer\shar\path...
+	 * the UNC style file specs
+	 */
+	if (isalpha(filename[0]) && filename[1] == ':' && 
+		(filename[2] == '\\' || filename[2] == '/')) {
+		strncpy(drive, filename, 3);
+		drive[3] = '\0';
+	}
+
+	else if ((filename[0] == '\\') && (filename[1] == '\\')) {
+		/* Find the machine and share name and rebuild the UNC */
+		strcpy(tmpbuf, filename);
+		machinename = strtok(tmpbuf, "\\");
+		sharename = strtok(NULL, "\\");
+		strcpy(drive, "\\\\");
+		strcat(drive, machinename);
+		strcat(drive, "\\");
+		strcat(drive, sharename);
+		strcat(drive, "\\");
+
+	}
+	else /* Not determinable */
+		return (FALSE);
+		
+	GetVolumeInformation(drive, NULL, 0, NULL, 0, NULL, FSType,
+			     sizeof(FSType));
+	if(strcmp(FSType,"NTFS") == 0)
+		return (TRUE);
+	else
+		return (FALSE);
+}
+
+/*
+ * If it's not NTFS, we assume that it is FAT and proceed
+ * with almost nothing to do. Only the write flag can be set or
+ * cleared.
+ */
+isc_result_t
+FAT_fsaccess_set(const char *path, isc_fsaccess_t access) {
+	int mode;
+	isc_fsaccess_t bits;
+
+	/*
+	 * Done with checking bad bits.  Set mode_t.
+	 */
+	mode = 0;
+
+#define SET_AND_CLEAR1(modebit) \
+	if ((access & bits) != 0) { \
+		mode |= modebit; \
+		access &= ~bits; \
+	}
+#define SET_AND_CLEAR(user, group, other) \
+	SET_AND_CLEAR1(user); \
+	bits <<= STEP; \
+	SET_AND_CLEAR1(group); \
+	bits <<= STEP; \
+	SET_AND_CLEAR1(other);
+
+	bits = ISC_FSACCESS_READ | ISC_FSACCESS_LISTDIRECTORY;
+
+	SET_AND_CLEAR(S_IRUSR, S_IRGRP, S_IROTH);
+
+	bits = ISC_FSACCESS_WRITE |
+	       ISC_FSACCESS_CREATECHILD |
+	       ISC_FSACCESS_DELETECHILD;
+
+	SET_AND_CLEAR(S_IWUSR, S_IWGRP, S_IWOTH);
+
+	INSIST(access == 0);
+
+	if (_chmod(path, mode) < 0)
+		return (isc__errno2result(errno));
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+NTFS_Access_Control(const char *filename, const char *user, int access,
+		    isc_boolean_t isdir) {
+	SECURITY_DESCRIPTOR sd;
+	BYTE aclBuffer[1024];
+	PACL pacl=(PACL)&aclBuffer;
+	BYTE sidBuffer[100];
+	PSID psid=(PSID) &sidBuffer;
+	DWORD sidBufferSize = sizeof(sidBuffer);
+	BYTE adminSidBuffer[100];
+	PSID padminsid=(PSID) &adminSidBuffer;
+	DWORD adminSidBufferSize = sizeof(adminSidBuffer);
+	BYTE otherSidBuffer[100];
+	PSID pothersid=(PSID) &otherSidBuffer;
+	DWORD otherSidBufferSize = sizeof(otherSidBuffer);
+	char domainBuffer[100];
+	DWORD domainBufferSize = sizeof(domainBuffer);
+	SID_NAME_USE snu;
+	int errval;
+	DWORD NTFSbits;
+	int caccess;
+
+
+	/* Initialize an ACL */
+	if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
+		return (ISC_R_NOPERM);
+	if (!InitializeAcl(pacl, sizeof(aclBuffer), ACL_REVISION))
+		return (ISC_R_NOPERM);
+	if (!LookupAccountName(0, user, psid, &sidBufferSize, domainBuffer,
+			  &domainBufferSize, &snu))
+		return (ISC_R_NOPERM);
+	domainBufferSize = sizeof(domainBuffer);
+	if (!LookupAccountName(0, "Administrators", padminsid,
+		&adminSidBufferSize, domainBuffer, &domainBufferSize, &snu)) {
+		errval = GetLastError();
+		return (ISC_R_NOPERM);
+	}
+	domainBufferSize = sizeof(domainBuffer);
+	if (!LookupAccountName(0, "Everyone", pothersid,
+		&otherSidBufferSize, domainBuffer, &domainBufferSize, &snu)) {
+		errval = GetLastError();
+		return (ISC_R_NOPERM);
+	}
+
+	caccess = access;
+	/* Owner check */
+
+	NTFSbits = 0;
+	if (caccess & ISC_FSACCESS_READ)
+		NTFSbits |= FILE_GENERIC_READ;
+	if (caccess & ISC_FSACCESS_WRITE)
+		NTFSbits |= FILE_GENERIC_WRITE;
+	if (caccess & ISC_FSACCESS_EXECUTE)
+		NTFSbits |= FILE_GENERIC_EXECUTE;
+
+	/* For directories check the directory-specific bits */
+	if (isdir == ISC_TRUE) {
+		if (caccess & ISC_FSACCESS_CREATECHILD)
+			NTFSbits |= FILE_ADD_SUBDIRECTORY | FILE_ADD_FILE;
+		if (caccess & ISC_FSACCESS_DELETECHILD)
+			NTFSbits |= FILE_DELETE_CHILD;
+		if (caccess & ISC_FSACCESS_LISTDIRECTORY)
+			NTFSbits |= FILE_LIST_DIRECTORY;
+		if (caccess & ISC_FSACCESS_ACCESSCHILD)
+			NTFSbits |= FILE_TRAVERSE;
+	}
+
+	if (NTFSbits == (FILE_GENERIC_READ | FILE_GENERIC_WRITE
+		     | FILE_GENERIC_EXECUTE))
+		     NTFSbits |= FILE_ALL_ACCESS;
+	/*
+	 * Owner and Administrator also get STANDARD_RIGHTS_ALL
+	 * to ensure that they have full control
+	 */
+
+	NTFSbits |= STANDARD_RIGHTS_ALL;
+
+	/* Add the ACE to the ACL */
+	if (!AddAccessAllowedAce(pacl, ACL_REVISION, NTFSbits, psid))
+		return (ISC_R_NOPERM);
+	if (!AddAccessAllowedAce(pacl, ACL_REVISION, NTFSbits, padminsid))
+		return (ISC_R_NOPERM);
+
+	/*
+	 * Group is ignored since we can be in multiple groups or no group
+	 * and its meaning is not clear on Win32
+	 */
+
+	caccess = caccess >> STEP;
+
+	/*
+	 * Other check.  We translate this to be the same as Everyone
+	 */
+
+	caccess = caccess >> STEP;
+
+	NTFSbits = 0;
+	if (caccess & ISC_FSACCESS_READ)
+		NTFSbits |= FILE_GENERIC_READ;
+	if (caccess & ISC_FSACCESS_WRITE)
+		NTFSbits |= FILE_GENERIC_WRITE;
+	if (caccess & ISC_FSACCESS_EXECUTE)
+		NTFSbits |= FILE_GENERIC_EXECUTE;
+
+	/* For directories check the directory-specific bits */
+	if (isdir == TRUE) {
+		if (caccess & ISC_FSACCESS_CREATECHILD)
+			NTFSbits |= FILE_ADD_SUBDIRECTORY | FILE_ADD_FILE;
+		if (caccess & ISC_FSACCESS_DELETECHILD)
+			NTFSbits |= FILE_DELETE_CHILD;
+		if (caccess & ISC_FSACCESS_LISTDIRECTORY)
+			NTFSbits |= FILE_LIST_DIRECTORY;
+		if (caccess & ISC_FSACCESS_ACCESSCHILD)
+			NTFSbits |= FILE_TRAVERSE;
+	}
+	/* Add the ACE to the ACL */
+	if (!AddAccessAllowedAce(pacl, ACL_REVISION, NTFSbits,
+				 pothersid))
+		return (ISC_R_NOPERM);
+
+	if (!SetSecurityDescriptorDacl(&sd, TRUE, pacl, FALSE))
+		return (ISC_R_NOPERM);
+	if (!SetFileSecurity(filename, DACL_SECURITY_INFORMATION, &sd)) {
+		return (ISC_R_NOPERM);
+	}
+
+	return(ISC_R_SUCCESS);
+}
+
+isc_result_t
+NTFS_fsaccess_set(const char *path, isc_fsaccess_t access,
+		  isc_boolean_t isdir){
+
+	/*
+	 * For NTFS we first need to get the name of the account under
+	 * which BIND is running
+	 */
+	if (namelen <= 0) {
+		namelen = sizeof(username);
+		if (GetUserName(username, &namelen) == 0)
+			return (ISC_R_FAILURE);
+	}
+	return (NTFS_Access_Control(path, username, access, isdir));
+}
+
+isc_result_t
+isc_fsaccess_set(const char *path, isc_fsaccess_t access) {
+	struct stat statb;
+	isc_boolean_t is_dir = ISC_FALSE;
+	isc_result_t result;
+
+	if (stat(path, &statb) != 0)
+		return (isc__errno2result(errno));
+
+	if ((statb.st_mode & S_IFDIR) != 0)
+		is_dir = ISC_TRUE;
+	else if ((statb.st_mode & S_IFREG) == 0)
+		return (ISC_R_INVALIDFILE);
+
+	result = check_bad_bits(access, is_dir);
+	if (result != ISC_R_SUCCESS)
+		return (result);
+
+	/*
+	 * Determine if this is a FAT or NTFS disk and
+	 * call the appropriate function to set the permissions
+	 */
+	if (is_ntfs(path))
+		return (NTFS_fsaccess_set(path, access, is_dir));
+	else
+		return (FAT_fsaccess_set(path, access));
+}
+
+isc_result_t
+isc_fsaccess_changeowner(const char *filename, const char *user) {
+	SECURITY_DESCRIPTOR psd;
+	BYTE sidBuffer[500];
+	BYTE groupBuffer[500];
+	PSID psid=(PSID) &sidBuffer;
+	DWORD sidBufferSize = sizeof(sidBuffer);
+	char domainBuffer[100];
+	DWORD domainBufferSize = sizeof(domainBuffer);
+	SID_NAME_USE snu;
+	PSID pSidGroup = (PSID) &groupBuffer;
+	DWORD groupBufferSize = sizeof(groupBuffer);
+
+
+	/*
+	 * Determine if this is a FAT or NTFS disk and
+	 * call the appropriate function to set the ownership
+	 * FAT disks do not have ownership attributes so it's
+	 * a noop.
+	 */
+	if (is_ntfs(filename) == FALSE)
+		return (ISC_R_SUCCESS);
+
+	if (!InitializeSecurityDescriptor(&psd, SECURITY_DESCRIPTOR_REVISION))
+		return (ISC_R_NOPERM);
+
+	if (!LookupAccountName(0, user, psid, &sidBufferSize, domainBuffer,
+		&domainBufferSize, &snu))
+		return (ISC_R_NOPERM);
+
+	/* Make sure administrators can get to it */
+	domainBufferSize = sizeof(domainBuffer);
+	if (!LookupAccountName(0, "Administrators", pSidGroup,
+		&groupBufferSize, domainBuffer, &domainBufferSize, &snu))
+		return (ISC_R_NOPERM);
+
+	if (!SetSecurityDescriptorOwner(&psd, psid, FALSE))
+		return (ISC_R_NOPERM);
+
+	if (!SetSecurityDescriptorGroup(&psd, pSidGroup, FALSE))
+		return (ISC_R_NOPERM);
+
+	if (!SetFileSecurity(filename,
+		OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION,
+		&psd))
+		return (ISC_R_NOPERM);
+
+	return (ISC_R_SUCCESS);
+}
+
diff --git a/src/lib/bind9/win32/include/isc/bind_registry.h b/src/lib/bind9/win32/include/isc/bind_registry.h
new file mode 100644
index 0000000..7cc2870
--- /dev/null
+++ b/src/lib/bind9/win32/include/isc/bind_registry.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2004, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: bind_registry.h,v 1.8 2007-06-19 23:47:20 tbox Exp $ */
+
+#ifndef ISC_BINDREGISTRY_H
+#define ISC_BINDREGISTRY_H
+
+/*
+ * BIND makes use of the following Registry keys in various places, especially
+ * during startup and installation
+ */
+
+#define BIND_SUBKEY		"Software\\ISC\\BIND"
+#define BIND_SESSION		"CurrentSession"
+#define BIND_SESSION_SUBKEY	"Software\\ISC\\BIND\\CurrentSession"
+#define BIND_UNINSTALL_SUBKEY	\
+	"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ISC BIND"
+
+#define EVENTLOG_APP_SUBKEY	\
+	"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application"
+#define BIND_MESSAGE_SUBKEY	\
+	"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\named"
+#define BIND_MESSAGE_NAME	"named"
+
+#define BIND_SERVICE_SUBKEY	\
+	"SYSTEM\\CurrentControlSet\\Services\\named"
+
+
+#define BIND_CONFIGFILE		0
+#define BIND_DEBUGLEVEL		1
+#define BIND_QUERYLOG		2
+#define BIND_FOREGROUND		3
+#define BIND_PORT		4
+
+#endif /* ISC_BINDREGISTRY_H */
diff --git a/src/lib/bind9/win32/include/isc/bindevt.h b/src/lib/bind9/win32/include/isc/bindevt.h
new file mode 100644
index 0000000..5ed5516
--- /dev/null
+++ b/src/lib/bind9/win32/include/isc/bindevt.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2004, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: bindevt.h,v 1.6 2007-06-19 23:47:20 tbox Exp $ */
+
+#ifndef ISC_BINDEVT_H
+#define ISC_BINDEVT_H 1
+
+/*
+ * This is used for the event log for both logging the messages and
+ * later on by the event viewer when looking at the events
+ */
+
+/*
+ * Values are 32 bit values layed out as follows:
+ *
+ *   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
+ *   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ *  +---+-+-+-----------------------+-------------------------------+
+ *  |Sev|C|R|     Facility          |               Code            |
+ *  +---+-+-+-----------------------+-------------------------------+
+ *
+ *  where
+ *
+ *      Sev - is the severity code
+ *
+ *          00 - Success
+ *          01 - Informational
+ *          10 - Warning
+ *          11 - Error
+ *
+ *      C - is the Customer code flag
+ *
+ *      R - is a reserved bit
+ *
+ *      Facility - is the facility code
+ *
+ *      Code - is the facility's status code
+ *
+ *
+ * Define the facility codes
+ */
+ 
+
+/*
+ * Define the severity codes
+ */
+
+
+/*
+ * MessageId: BIND_ERR_MSG
+ *
+ * MessageText:
+ *
+ *  %1
+ */
+#define BIND_ERR_MSG		((DWORD)0xC0000001L)
+
+/*
+ * MessageId: BIND_WARN_MSG
+ *
+ * MessageText:
+ *
+ *  %1
+ */
+#define BIND_WARN_MSG		((DWORD)0x80000002L)
+
+/*
+ * MessageId: BIND_INFO_MSG
+ *
+ * MessageText:
+ *
+ *  %1
+ */
+#define BIND_INFO_MSG		((DWORD)0x40000003L)
+
+#endif /* ISC_BINDEVT_H */
diff --git a/src/lib/bind9/win32/include/isc/condition.h b/src/lib/bind9/win32/include/isc/condition.h
new file mode 100644
index 0000000..c19d8b9
--- /dev/null
+++ b/src/lib/bind9/win32/include/isc/condition.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2004, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: condition.h,v 1.17 2007-06-18 23:47:49 tbox Exp $ */
+
+#ifndef ISC_CONDITION_H
+#define ISC_CONDITION_H 1
+
+#include <windows.h>
+
+#include <isc/lang.h>
+#include <isc/mutex.h>
+#include <isc/thread.h>
+#include <isc/types.h>
+
+typedef struct isc_condition_thread isc_condition_thread_t;
+
+struct isc_condition_thread {
+	unsigned long				th;
+	HANDLE					handle[2];
+	ISC_LINK(isc_condition_thread_t)	link;
+
+};
+
+typedef struct isc_condition {
+	HANDLE 		events[2];
+	unsigned int	waiters;
+	ISC_LIST(isc_condition_thread_t) threadlist;
+} isc_condition_t;
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_condition_init(isc_condition_t *);
+
+isc_result_t
+isc_condition_wait(isc_condition_t *, isc_mutex_t *);
+
+isc_result_t
+isc_condition_signal(isc_condition_t *);
+
+isc_result_t
+isc_condition_broadcast(isc_condition_t *);
+
+isc_result_t
+isc_condition_destroy(isc_condition_t *);
+
+isc_result_t
+isc_condition_waituntil(isc_condition_t *, isc_mutex_t *, isc_time_t *);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_CONDITION_H */
diff --git a/src/lib/bind9/win32/include/isc/dir.h b/src/lib/bind9/win32/include/isc/dir.h
new file mode 100644
index 0000000..a82fc61
--- /dev/null
+++ b/src/lib/bind9/win32/include/isc/dir.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2004, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: dir.h,v 1.15 2007-06-19 23:47:20 tbox Exp $ */
+
+/* Principal Authors: DCL */
+
+#ifndef ISC_DIR_H
+#define ISC_DIR_H 1
+
+#include <windows.h>
+#include <stdlib.h>
+
+#include <isc/lang.h>
+#include <isc/boolean.h>
+#include <isc/result.h>
+
+#define ISC_DIR_NAMEMAX _MAX_FNAME
+#define ISC_DIR_PATHMAX _MAX_PATH
+
+typedef struct {
+	char 		name[ISC_DIR_NAMEMAX];
+	unsigned int	length;
+	WIN32_FIND_DATA	find_data;
+} isc_direntry_t;
+
+typedef struct {
+	unsigned int	magic;
+	char		dirname[ISC_DIR_PATHMAX];
+	isc_direntry_t	entry;
+	isc_boolean_t	entry_filled;
+	HANDLE        	search_handle;
+} isc_dir_t;
+
+ISC_LANG_BEGINDECLS
+
+void
+isc_dir_init(isc_dir_t *dir);
+
+isc_result_t
+isc_dir_open(isc_dir_t *dir, const char *dirname);
+
+isc_result_t
+isc_dir_read(isc_dir_t *dir);
+
+isc_result_t
+isc_dir_reset(isc_dir_t *dir);
+
+void
+isc_dir_close(isc_dir_t *dir);
+
+isc_result_t
+isc_dir_chdir(const char *dirname);
+
+isc_result_t
+isc_dir_chroot(const char *dirname);
+
+isc_result_t
+isc_dir_createunique(char *templet);
+/*
+ * Use a templet (such as from isc_file_mktemplate()) to create a uniquely
+ * named, empty directory.  The templet string is modified in place.
+ * If result == ISC_R_SUCCESS, it is the name of the directory that was
+ * created.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_DIR_H */
diff --git a/src/lib/bind9/win32/include/isc/int.h b/src/lib/bind9/win32/include/isc/int.h
new file mode 100644
index 0000000..b74ac0c
--- /dev/null
+++ b/src/lib/bind9/win32/include/isc/int.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2004, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: int.h,v 1.13 2007-06-19 23:47:20 tbox Exp $ */
+
+#ifndef ISC_INT_H
+#define ISC_INT_H 1
+
+#define _INTEGRAL_MAX_BITS 64
+#include <limits.h>
+
+typedef __int8				isc_int8_t;
+typedef unsigned __int8			isc_uint8_t;
+typedef __int16				isc_int16_t;
+typedef unsigned __int16		isc_uint16_t;
+typedef __int32				isc_int32_t;
+typedef unsigned __int32		isc_uint32_t;
+typedef __int64				isc_int64_t;
+typedef unsigned __int64		isc_uint64_t;
+
+#define ISC_INT8_MIN	-128
+#define ISC_INT8_MAX	127
+#define ISC_UINT8_MAX	255
+
+#define ISC_INT16_MIN	-32768
+#define ISC_INT16_MAX	32767
+#define ISC_UINT16_MAX	65535
+
+/*
+ * Note that "int" is 32 bits on all currently supported Unix-like operating
+ * systems, but "long" can be either 32 bits or 64 bits, thus the 32 bit
+ * constants are not qualified with "L".
+ */
+#define ISC_INT32_MIN	_I32_MIN
+#define ISC_INT32_MAX	_I32_MAX
+#define ISC_UINT32_MAX	_UI32_MAX
+
+#define ISC_INT64_MIN	_I64_MIN
+#define ISC_INT64_MAX	_I64_MAX
+#define ISC_UINT64_MAX	_UI64_MAX
+
+#endif /* ISC_INT_H */
diff --git a/src/lib/bind9/win32/include/isc/ipv6.h b/src/lib/bind9/win32/include/isc/ipv6.h
new file mode 100644
index 0000000..5172020
--- /dev/null
+++ b/src/lib/bind9/win32/include/isc/ipv6.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2011  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: ipv6.h,v 1.19.814.2 2011-02-28 01:20:04 tbox Exp $ */
+
+#ifndef ISC_IPV6_H
+#define ISC_IPV6_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*
+ * IPv6 definitions for systems which do not support IPv6.
+ *
+ * MP:
+ *	No impact.
+ *
+ * Reliability:
+ *	No anticipated impact.
+ *
+ * Resources:
+ *	N/A.
+ *
+ * Security:
+ *	No anticipated impact.
+ *
+ * Standards:
+ *	RFC2553.
+ */
+
+#if _MSC_VER < 1300
+#define in6_addr in_addr6
+#endif
+
+#ifndef IN6ADDR_ANY_INIT
+#define IN6ADDR_ANY_INIT 	{{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }}
+#endif
+#ifndef IN6ADDR_LOOPBACK_INIT
+#define IN6ADDR_LOOPBACK_INIT 	{{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 }}
+#endif
+
+LIBISC_EXTERNAL_DATA extern const struct in6_addr isc_in6addr_any;
+LIBISC_EXTERNAL_DATA extern const struct in6_addr isc_in6addr_loopback;
+
+/*
+ * Unspecified
+ */
+#ifndef IN6_IS_ADDR_UNSPECIFIED
+#define IN6_IS_ADDR_UNSPECIFIED(a) (\
+*((u_long *)((a)->s6_addr)    ) == 0 && \
+*((u_long *)((a)->s6_addr) + 1) == 0 && \
+*((u_long *)((a)->s6_addr) + 2) == 0 && \
+*((u_long *)((a)->s6_addr) + 3) == 0 \
+)
+#endif
+
+/*
+ * Loopback
+ */
+#ifndef IN6_IS_ADDR_LOOPBACK
+#define IN6_IS_ADDR_LOOPBACK(a) (\
+*((u_long *)((a)->s6_addr)    ) == 0 && \
+*((u_long *)((a)->s6_addr) + 1) == 0 && \
+*((u_long *)((a)->s6_addr) + 2) == 0 && \
+*((u_long *)((a)->s6_addr) + 3) == htonl(1) \
+)
+#endif
+
+/*
+ * IPv4 compatible
+ */
+#define IN6_IS_ADDR_V4COMPAT(a)  (\
+*((u_long *)((a)->s6_addr)    ) == 0 && \
+*((u_long *)((a)->s6_addr) + 1) == 0 && \
+*((u_long *)((a)->s6_addr) + 2) == 0 && \
+*((u_long *)((a)->s6_addr) + 3) != 0 && \
+*((u_long *)((a)->s6_addr) + 3) != htonl(1) \
+)
+
+/*
+ * Mapped
+ */
+#define IN6_IS_ADDR_V4MAPPED(a) (\
+*((u_long *)((a)->s6_addr)    ) == 0 && \
+*((u_long *)((a)->s6_addr) + 1) == 0 && \
+*((u_long *)((a)->s6_addr) + 2) == htonl(0x0000ffff))
+
+/*
+ * Multicast
+ */
+#define IN6_IS_ADDR_MULTICAST(a)	\
+	((a)->s6_addr[0] == 0xffU)
+
+/*
+ * Unicast link / site local.
+ */
+#ifndef IN6_IS_ADDR_LINKLOCAL
+#define IN6_IS_ADDR_LINKLOCAL(a)	(\
+       ((a)->s6_addr[0] == 0xfe) && \
+       (((a)->s6_addr[1] & 0xc0) == 0x80))
+#endif
+
+#ifndef IN6_IS_ADDR_SITELOCAL
+#define IN6_IS_ADDR_SITELOCAL(a)	(\
+       ((a)->s6_addr[0] == 0xfe) && \
+       (((a)->s6_addr[1] & 0xc0) == 0xc0))
+#endif
+
+#endif /* ISC_IPV6_H */
diff --git a/src/lib/bind9/win32/include/isc/keyboard.h b/src/lib/bind9/win32/include/isc/keyboard.h
new file mode 100644
index 0000000..6b568ed
--- /dev/null
+++ b/src/lib/bind9/win32/include/isc/keyboard.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2004, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: keyboard.h,v 1.6 2007-06-19 23:47:20 tbox Exp $ */
+
+#ifndef ISC_KEYBOARD_H
+#define ISC_KEYBOARD_H 1
+
+#include <isc/lang.h>
+#include <isc/result.h>
+
+ISC_LANG_BEGINDECLS
+
+typedef struct {
+	int fd;
+	isc_result_t result;
+} isc_keyboard_t;
+
+isc_result_t
+isc_keyboard_open(isc_keyboard_t *keyboard);
+
+isc_result_t
+isc_keyboard_close(isc_keyboard_t *keyboard, unsigned int sleepseconds);
+
+isc_result_t
+isc_keyboard_getchar(isc_keyboard_t *keyboard, unsigned char *cp);
+
+isc_boolean_t
+isc_keyboard_canceled(isc_keyboard_t *keyboard);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_KEYBOARD_H */
diff --git a/src/lib/bind9/win32/include/isc/mutex.h b/src/lib/bind9/win32/include/isc/mutex.h
new file mode 100644
index 0000000..52c1a63
--- /dev/null
+++ b/src/lib/bind9/win32/include/isc/mutex.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2004, 2007-2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: mutex.h,v 1.22 2009-01-18 23:48:14 tbox Exp $ */
+
+#ifndef ISC_MUTEX_H
+#define ISC_MUTEX_H 1
+
+#include <isc/net.h>
+#include <windows.h>
+
+#include <isc/result.h>
+
+typedef CRITICAL_SECTION isc_mutex_t;
+
+/*
+ * This definition is here since some versions of WINBASE.H
+ * omits it for some reason.
+ */
+#if (_WIN32_WINNT < 0x0400)
+WINBASEAPI BOOL WINAPI
+TryEnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
+#endif /* _WIN32_WINNT < 0x0400 */
+
+#define isc_mutex_init(mp) \
+	(InitializeCriticalSection((mp)), ISC_R_SUCCESS)
+#define isc_mutex_lock(mp) \
+	(EnterCriticalSection((mp)), ISC_R_SUCCESS)
+#define isc_mutex_unlock(mp) \
+	(LeaveCriticalSection((mp)), ISC_R_SUCCESS)
+#define isc_mutex_trylock(mp) \
+	(TryEnterCriticalSection((mp)) ? ISC_R_SUCCESS : ISC_R_LOCKBUSY)
+#define isc_mutex_destroy(mp) \
+	(DeleteCriticalSection((mp)), ISC_R_SUCCESS)
+
+/*
+ * This is a placeholder for now since we are not keeping any mutex stats
+ */
+#define isc_mutex_stats(fp) do {} while (0)
+
+#endif /* ISC_MUTEX_H */
diff --git a/src/lib/bind9/win32/include/isc/net.h b/src/lib/bind9/win32/include/isc/net.h
new file mode 100644
index 0000000..53f24b1
--- /dev/null
+++ b/src/lib/bind9/win32/include/isc/net.h
@@ -0,0 +1,344 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2008  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: net.h,v 1.31 2008-12-01 03:51:47 marka Exp $ */
+
+#ifndef ISC_NET_H
+#define ISC_NET_H 1
+
+/*
+ * Also define LWRES_IPV6_H to keep it from being included if liblwres is
+ * being used, or redefinition errors will occur.
+ */
+#define LWRES_IPV6_H 1
+
+
+
+/*****
+ ***** Module Info
+ *****/
+
+/*
+ * Basic Networking Types
+ *
+ * This module is responsible for defining the following basic networking
+ * types:
+ *
+ *		struct in_addr
+ *		struct in6_addr
+ *		struct in6_pktinfo
+ *		struct sockaddr
+ *		struct sockaddr_in
+ *		struct sockaddr_in6
+ *		in_port_t
+ *
+ * It ensures that the AF_ and PF_ macros are defined.
+ *
+ * It declares ntoh[sl]() and hton[sl]().
+ *
+ * It declares inet_aton(), inet_ntop(), and inet_pton().
+ *
+ * It ensures that INADDR_ANY, IN6ADDR_ANY_INIT, in6addr_any, and
+ * in6addr_loopback are available.
+ *
+ * It ensures that IN_MULTICAST() is available to check for multicast
+ * addresses.
+ *
+ * MP:
+ *	No impact.
+ *
+ * Reliability:
+ *	No anticipated impact.
+ *
+ * Resources:
+ *	N/A.
+ *
+ * Security:
+ *	No anticipated impact.
+ *
+ * Standards:
+ *	BSD Socket API
+ *	RFC2553
+ */
+
+/***
+ *** Imports.
+ ***/
+#include <isc/platform.h>
+
+/*
+ * Because of some sort of problem in the MS header files, this cannot
+ * be simple "#include <winsock2.h>", because winsock2.h tries to include
+ * windows.h, which then generates an error out of mswsock.h.  _You_
+ * figure it out.
+ */
+#ifndef _WINSOCKAPI_
+#define _WINSOCKAPI_   /* Prevent inclusion of winsock.h in windows.h */
+#endif
+
+#include <winsock2.h>
+
+#include <sys/types.h>
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+#include <ws2tcpip.h>
+#include <isc/ipv6.h>
+
+/*
+ * This is here because named client, interfacemgr.c, etc. use the name as
+ * a variable
+ */
+#undef interface
+
+#ifndef INADDR_LOOPBACK
+#define INADDR_LOOPBACK 0x7f000001UL
+#endif
+
+#ifndef ISC_PLATFORM_HAVEIN6PKTINFO
+struct in6_pktinfo {
+	struct in6_addr ipi6_addr;    /* src/dst IPv6 address */
+	unsigned int    ipi6_ifindex; /* send/recv interface index */
+};
+#endif
+
+#if _MSC_VER < 1300
+#define in6addr_any isc_in6addr_any
+#define in6addr_loopback isc_in6addr_loopback
+#endif
+
+/*
+ * Ensure type in_port_t is defined.
+ */
+#ifdef ISC_PLATFORM_NEEDPORTT
+typedef isc_uint16_t in_port_t;
+#endif
+
+/*
+ * If this system does not have MSG_TRUNC (as returned from recvmsg())
+ * ISC_PLATFORM_RECVOVERFLOW will be defined.  This will enable the MSG_TRUNC
+ * faking code in socket.c.
+ */
+#ifndef MSG_TRUNC
+#define ISC_PLATFORM_RECVOVERFLOW
+#endif
+
+#define ISC__IPADDR(x)	((isc_uint32_t)htonl((isc_uint32_t)(x)))
+
+#define ISC_IPADDR_ISMULTICAST(i) \
+		(((isc_uint32_t)(i) & ISC__IPADDR(0xf0000000)) \
+		 == ISC__IPADDR(0xe0000000))
+
+#define ISC_IPADDR_ISEXPERIMENTAL(i) \
+		(((isc_uint32_t)(i) & ISC__IPADDR(0xf0000000)) \
+		 == ISC__IPADDR(0xf0000000))
+
+/*
+ * Fix the FD_SET and FD_CLR Macros to properly cast
+ */
+#undef FD_CLR
+#define FD_CLR(fd, set) do { \
+    u_int __i; \
+    for (__i = 0; __i < ((fd_set FAR *)(set))->fd_count; __i++) { \
+	if (((fd_set FAR *)(set))->fd_array[__i] == (SOCKET) fd) { \
+	    while (__i < ((fd_set FAR *)(set))->fd_count-1) { \
+		((fd_set FAR *)(set))->fd_array[__i] = \
+		    ((fd_set FAR *)(set))->fd_array[__i+1]; \
+		__i++; \
+	    } \
+	    ((fd_set FAR *)(set))->fd_count--; \
+	    break; \
+	} \
+    } \
+} while (0)
+
+#undef FD_SET
+#define FD_SET(fd, set) do { \
+    u_int __i; \
+    for (__i = 0; __i < ((fd_set FAR *)(set))->fd_count; __i++) { \
+	if (((fd_set FAR *)(set))->fd_array[__i] == (SOCKET)(fd)) { \
+	    break; \
+	} \
+    } \
+    if (__i == ((fd_set FAR *)(set))->fd_count) { \
+	if (((fd_set FAR *)(set))->fd_count < FD_SETSIZE) { \
+	    ((fd_set FAR *)(set))->fd_array[__i] = (SOCKET)(fd); \
+	    ((fd_set FAR *)(set))->fd_count++; \
+	} \
+    } \
+} while (0)
+
+/*
+ * Windows Sockets errors redefined as regular Berkeley error constants.
+ * These are usually commented out in Windows NT to avoid conflicts with errno.h.
+ * Use the WSA constants instead.
+ */
+
+#define EWOULDBLOCK             WSAEWOULDBLOCK
+#define EINPROGRESS             WSAEINPROGRESS
+#define EALREADY                WSAEALREADY
+#define ENOTSOCK                WSAENOTSOCK
+#define EDESTADDRREQ            WSAEDESTADDRREQ
+#define EMSGSIZE                WSAEMSGSIZE
+#define EPROTOTYPE              WSAEPROTOTYPE
+#define ENOPROTOOPT             WSAENOPROTOOPT
+#define EPROTONOSUPPORT         WSAEPROTONOSUPPORT
+#define ESOCKTNOSUPPORT         WSAESOCKTNOSUPPORT
+#define EOPNOTSUPP              WSAEOPNOTSUPP
+#define EPFNOSUPPORT            WSAEPFNOSUPPORT
+#define EAFNOSUPPORT            WSAEAFNOSUPPORT
+#define EADDRINUSE              WSAEADDRINUSE
+#define EADDRNOTAVAIL           WSAEADDRNOTAVAIL
+#define ENETDOWN                WSAENETDOWN
+#define ENETUNREACH             WSAENETUNREACH
+#define ENETRESET               WSAENETRESET
+#define ECONNABORTED            WSAECONNABORTED
+#define ECONNRESET              WSAECONNRESET
+#define ENOBUFS                 WSAENOBUFS
+#define EISCONN                 WSAEISCONN
+#define ENOTCONN                WSAENOTCONN
+#define ESHUTDOWN               WSAESHUTDOWN
+#define ETOOMANYREFS            WSAETOOMANYREFS
+#define ETIMEDOUT               WSAETIMEDOUT
+#define ECONNREFUSED            WSAECONNREFUSED
+#define ELOOP                   WSAELOOP
+#define EHOSTDOWN               WSAEHOSTDOWN
+#define EHOSTUNREACH            WSAEHOSTUNREACH
+#define EPROCLIM                WSAEPROCLIM
+#define EUSERS                  WSAEUSERS
+#define EDQUOT                  WSAEDQUOT
+#define ESTALE                  WSAESTALE
+#define EREMOTE                 WSAEREMOTE
+
+
+/***
+ *** Functions.
+ ***/
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_net_probeipv4(void);
+/*
+ * Check if the system's kernel supports IPv4.
+ *
+ * Returns:
+ *
+ *	ISC_R_SUCCESS		IPv4 is supported.
+ *	ISC_R_NOTFOUND		IPv4 is not supported.
+ *	ISC_R_DISABLED		IPv4 is disabled.
+ *	ISC_R_UNEXPECTED
+ */
+
+isc_result_t
+isc_net_probeipv6(void);
+/*
+ * Check if the system's kernel supports IPv6.
+ *
+ * Returns:
+ *
+ *	ISC_R_SUCCESS		IPv6 is supported.
+ *	ISC_R_NOTFOUND		IPv6 is not supported.
+ *	ISC_R_DISABLED		IPv6 is disabled.
+ *	ISC_R_UNEXPECTED
+ */
+
+isc_result_t
+isc_net_probeunix(void);
+/*
+ * Check if UNIX domain sockets are supported.
+ *
+ * Returns:
+ *
+ *	ISC_R_SUCCESS
+ *	ISC_R_NOTFOUND
+ */
+
+isc_result_t
+isc_net_probe_ipv6only(void);
+/*
+ * Check if the system's kernel supports the IPV6_V6ONLY socket option.
+ *
+ * Returns:
+ *
+ *	ISC_R_SUCCESS		the option is supported for both TCP and UDP.
+ *	ISC_R_NOTFOUND		IPv6 itself or the option is not supported.
+ *	ISC_R_UNEXPECTED
+ */
+
+isc_result_t
+isc_net_probe_ipv6pktinfo(void);
+/*
+ * Check if the system's kernel supports the IPV6_(RECV)PKTINFO socket option
+ * for UDP sockets.
+ *
+ * Returns:
+ *
+ *	ISC_R_SUCCESS		the option is supported.
+ *	ISC_R_NOTFOUND		IPv6 itself or the option is not supported.
+ *	ISC_R_UNEXPECTED
+ */
+
+void
+isc_net_disableipv4(void);
+
+void
+isc_net_disableipv6(void);
+
+void
+isc_net_enableipv4(void);
+
+void
+isc_net_enableipv6(void);
+
+isc_result_t
+isc_net_getudpportrange(int af, in_port_t *low, in_port_t *high);
+/*%<
+ * Returns system's default range of ephemeral UDP ports, if defined.
+ * If the range is not available or unknown, ISC_NET_PORTRANGELOW and
+ * ISC_NET_PORTRANGEHIGH will be returned.
+ *
+ * Requires:
+ *
+ *\li	'low' and 'high' must be non NULL.
+ *
+ * Returns:
+ *
+ *\li	*low and *high will be the ports specifying the low and high ends of
+ *	the range.
+ */
+
+#ifdef ISC_PLATFORM_NEEDNTOP
+const char *
+isc_net_ntop(int af, const void *src, char *dst, size_t size);
+#define inet_ntop isc_net_ntop
+#endif
+
+#ifdef ISC_PLATFORM_NEEDPTON
+int
+isc_net_pton(int af, const char *src, void *dst);
+#define inet_pton isc_net_pton
+#endif
+
+int
+isc_net_aton(const char *cp, struct in_addr *addr);
+#define inet_aton isc_net_aton
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_NET_H */
diff --git a/src/lib/bind9/win32/include/isc/netdb.h b/src/lib/bind9/win32/include/isc/netdb.h
new file mode 100644
index 0000000..2ac4e53
--- /dev/null
+++ b/src/lib/bind9/win32/include/isc/netdb.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2004, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: netdb.h,v 1.9 2007-06-19 23:47:20 tbox Exp $ */
+
+#ifndef ISC_NETDB_H
+#define ISC_NETDB_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*
+ * Portable netdb.h support.
+ *
+ * This module is responsible for defining the get<x>by<y> APIs.
+ *
+ * MP:
+ *	No impact.
+ *
+ * Reliability:
+ *	No anticipated impact.
+ *
+ * Resources:
+ *	N/A.
+ *
+ * Security:
+ *	No anticipated impact.
+ *
+ * Standards:
+ *	BSD API
+ */
+
+/***
+ *** Imports.
+ ***/
+
+#include <isc/net.h>
+
+#endif /* ISC_NETDB_H */
diff --git a/src/lib/bind9/win32/include/isc/ntgroups.h b/src/lib/bind9/win32/include/isc/ntgroups.h
new file mode 100644
index 0000000..c6fdcc6
--- /dev/null
+++ b/src/lib/bind9/win32/include/isc/ntgroups.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2004, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: ntgroups.h,v 1.5 2007-06-19 23:47:20 tbox Exp $ */
+
+#ifndef ISC_NTGROUPS_H
+#define ISC_NTGROUPS_H 1
+
+#include <isc/lang.h>
+#include <isc/result.h>
+
+ISC_LANG_BEGINDECLS
+
+
+isc_result_t
+isc_ntsecurity_getaccountgroups(char *name, char **Groups, unsigned int maxgroups,
+	     unsigned int *total);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_NTGROUPS_H */
diff --git a/src/lib/bind9/win32/include/isc/ntpaths.h b/src/lib/bind9/win32/include/isc/ntpaths.h
new file mode 100644
index 0000000..f0af53e
--- /dev/null
+++ b/src/lib/bind9/win32/include/isc/ntpaths.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2004, 2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: ntpaths.h,v 1.20 2009-07-14 22:54:57 each Exp $ */
+
+/*
+ * Windows-specific path definitions
+ * These routines are used to set up and return system-specific path
+ * information about the files enumerated in NtPaths
+ */
+
+#ifndef ISC_NTPATHS_H
+#define ISC_NTPATHS_H
+
+#include <isc/lang.h>
+
+/*
+ * Index of paths needed
+ */
+enum NtPaths {
+	NAMED_CONF_PATH,
+	LWRES_CONF_PATH,
+	RESOLV_CONF_PATH,
+	RNDC_CONF_PATH,
+	NAMED_PID_PATH,
+	LWRESD_PID_PATH,
+	LOCAL_STATE_DIR,
+	SYS_CONF_DIR,
+	RNDC_KEY_PATH,
+	SESSION_KEY_PATH
+};
+
+/*
+ * Define macros to get the path of the config files
+ */
+#define NAMED_CONFFILE isc_ntpaths_get(NAMED_CONF_PATH)
+#define RNDC_CONFFILE isc_ntpaths_get(RNDC_CONF_PATH)
+#define RNDC_KEYFILE isc_ntpaths_get(RNDC_KEY_PATH)
+#define SESSION_KEYFILE isc_ntpaths_get(SESSION_KEY_PATH)
+#define RESOLV_CONF isc_ntpaths_get(RESOLV_CONF_PATH)
+
+/*
+ * Information about where the files are on disk
+ */
+#define NS_LOCALSTATEDIR	"/dns/bin"
+#define NS_SYSCONFDIR		"/dns/etc"
+
+ISC_LANG_BEGINDECLS
+
+void
+isc_ntpaths_init(void);
+
+char *
+isc_ntpaths_get(int);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_NTPATHS_H */
diff --git a/src/lib/bind9/win32/include/isc/offset.h b/src/lib/bind9/win32/include/isc/offset.h
new file mode 100644
index 0000000..42b8d95
--- /dev/null
+++ b/src/lib/bind9/win32/include/isc/offset.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2004, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: offset.h,v 1.6 2007-06-19 23:47:20 tbox Exp $ */
+
+#ifndef ISC_OFFSET_H
+#define ISC_OFFSET_H 1
+
+/*
+ * File offsets are operating-system dependent.
+ */
+#include <limits.h>             /* Required for CHAR_BIT. */
+#include <sys/types.h>
+
+typedef _off_t isc_offset_t;
+
+/*
+ * POSIX says "Additionally, blkcnt_t and off_t are extended signed integral
+ * types", so the maximum value is all 1s except for the high bit.
+ * This definition is more complex than it really needs to be because it was
+ * crafted to keep both the SunOS 5.6 and the HP/UX 11 compilers quiet about
+ * integer overflow.  For example, though this is equivalent to just left
+ * shifting 1 to the high bit and then inverting the bits, the SunOS compiler
+ * is unhappy about shifting a positive "1" to negative in a signed integer.
+ */
+#define ISC_OFFSET_MAXIMUM \
+	(~(((off_t)-1 >> (sizeof(off_t) * CHAR_BIT - 1)) \
+		      << (sizeof(off_t) * CHAR_BIT - 1)))
+
+#endif /* ISC_OFFSET_H */
diff --git a/src/lib/bind9/win32/include/isc/once.h b/src/lib/bind9/win32/include/isc/once.h
new file mode 100644
index 0000000..d123dac
--- /dev/null
+++ b/src/lib/bind9/win32/include/isc/once.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2004, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: once.h,v 1.9 2007-06-19 23:47:20 tbox Exp $ */
+
+#ifndef ISC_ONCE_H
+#define ISC_ONCE_H 1
+
+#include <isc/lang.h>
+#include <isc/result.h>
+
+ISC_LANG_BEGINDECLS
+
+typedef struct {
+	int status;
+	int counter;
+} isc_once_t;
+
+#define ISC_ONCE_INIT_NEEDED 0
+#define ISC_ONCE_INIT_DONE 1
+
+#define ISC_ONCE_INIT { ISC_ONCE_INIT_NEEDED, 1 }
+
+isc_result_t
+isc_once_do(isc_once_t *controller, void(*function)(void));
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_ONCE_H */
diff --git a/src/lib/bind9/win32/include/isc/platform.h b/src/lib/bind9/win32/include/isc/platform.h
new file mode 100644
index 0000000..2f9cfed
--- /dev/null
+++ b/src/lib/bind9/win32/include/isc/platform.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2004, 2005, 2007-2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: platform.h,v 1.19 2009-09-29 23:48:04 tbox Exp $ */
+
+#ifndef ISC_PLATFORM_H
+#define ISC_PLATFORM_H 1
+
+/*****
+ ***** Platform-dependent defines.
+ *****/
+
+#define ISC_PLATFORM_USETHREADS
+
+/***
+ *** Network.
+ ***/
+
+#define ISC_PLATFORM_HAVEIPV6
+#if _MSC_VER > 1200
+#define ISC_PLATFORM_HAVEIN6PKTINFO
+#endif
+#define ISC_PLATFORM_HAVESCOPEID
+#define ISC_PLATFORM_NEEDPORTT
+#undef MSG_TRUNC
+#define ISC_PLATFORM_NEEDNTOP
+#define ISC_PLATFORM_NEEDPTON
+
+#define ISC_PLATFORM_QUADFORMAT "I64"
+
+#define ISC_PLATFORM_NEEDSTRSEP
+#define ISC_PLATFORM_NEEDSTRLCPY
+#define ISC_PLATFORM_NEEDSTRLCAT
+#define ISC_PLATFORM_NEEDSTRLCPY
+
+/*
+ * Used to control how extern data is linked; needed for Win32 platforms.
+ */
+#define ISC_PLATFORM_USEDECLSPEC 1
+
+/*
+ * Define this here for now as winsock2.h defines h_errno
+ * and we don't want to redeclare it.
+ */
+#define ISC_PLATFORM_NONSTDHERRNO
+
+/*
+ * Define if the platform has <sys/un.h>.
+ */
+#undef ISC_PLATFORM_HAVESYSUNH
+
+/*
+ * Defines for the noreturn attribute.
+ */
+#define ISC_PLATFORM_NORETURN_PRE __declspec(noreturn)
+#define ISC_PLATFORM_NORETURN_POST
+
+ /*
+ * Set up a macro for importing and exporting from the DLL
+ */
+
+#ifdef LIBISC_EXPORTS
+#define LIBISC_EXTERNAL_DATA __declspec(dllexport)
+#else
+#define LIBISC_EXTERNAL_DATA __declspec(dllimport)
+#endif
+
+#ifdef LIBISCCFG_EXPORTS
+#define LIBISCCFG_EXTERNAL_DATA __declspec(dllexport)
+#else
+#define LIBISCCFG_EXTERNAL_DATA __declspec(dllimport)
+#endif
+
+#ifdef LIBISCCC_EXPORTS
+#define LIBISCCC_EXTERNAL_DATA __declspec(dllexport)
+#else
+#define LIBISCCC_EXTERNAL_DATA __declspec(dllimport)
+#endif
+
+#ifdef LIBDNS_EXPORTS
+#define LIBDNS_EXTERNAL_DATA __declspec(dllexport)
+#else
+#define LIBDNS_EXTERNAL_DATA __declspec(dllimport)
+#endif
+
+#ifdef LIBBIND9_EXPORTS
+#define LIBBIND9_EXTERNAL_DATA __declspec(dllexport)
+#else
+#define LIBBIND9_EXTERNAL_DATA __declspec(dllimport)
+#endif
+
+#endif /* ISC_PLATFORM_H */
diff --git a/src/lib/bind9/win32/include/isc/stat.h b/src/lib/bind9/win32/include/isc/stat.h
new file mode 100644
index 0000000..a2b2e59
--- /dev/null
+++ b/src/lib/bind9/win32/include/isc/stat.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2004, 2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001, 2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: stat.h,v 1.9 2009-10-01 23:48:08 tbox Exp $ */
+
+#ifndef ISC_STAT_H
+#define ISC_STAT_H 1
+
+#include <sys/stat.h>
+
+/* open() under unix allows setting of read/write permissions
+ * at the owner, group and other levels.  These don't exist in NT
+ * We'll just map them all to the NT equivalent
+ */
+
+#define S_IREAD	_S_IREAD	/* read permission, owner */
+#define S_IWRITE _S_IWRITE	/* write permission, owner */
+#define S_IRUSR _S_IREAD	/* Owner read permission */
+#define S_IWUSR _S_IWRITE	/* Owner write permission */
+#define S_IRGRP _S_IREAD	/* Group read permission */
+#define S_IWGRP _S_IWRITE	/* Group write permission */
+#define S_IROTH _S_IREAD	/* Other read permission */
+#define S_IWOTH _S_IWRITE	/* Other write permission */
+
+#ifndef S_IFMT
+# define S_IFMT   _S_IFMT
+#endif
+#ifndef S_IFDIR
+# define S_IFDIR  _S_IFDIR
+#endif
+#ifndef S_IFCHR
+# define S_IFCHR  _S_IFCHR
+#endif
+#ifndef S_IFREG
+# define S_IFREG  _S_IFREG
+#endif
+
+#ifndef S_ISDIR
+# define S_ISDIR(m)	(((m) & S_IFMT) == S_IFDIR)
+#endif
+#ifndef S_ISREG
+# define S_ISREG(m)	(((m) & S_IFMT) == S_IFREG)
+#endif
+
+#endif /* ISC_STAT_H */
diff --git a/src/lib/bind9/win32/include/isc/stdtime.h b/src/lib/bind9/win32/include/isc/stdtime.h
new file mode 100644
index 0000000..0d7482c
--- /dev/null
+++ b/src/lib/bind9/win32/include/isc/stdtime.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2011  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: stdtime.h,v 1.12.814.2 2011-03-18 23:47:15 tbox Exp $ */
+
+#ifndef ISC_STDTIME_H
+#define ISC_STDTIME_H 1
+
+#include <isc/lang.h>
+#include <isc/int.h>
+
+/*
+ * It's public information that 'isc_stdtime_t' is an unsigned integral type.
+ * Applications that want maximum portability should not assume anything
+ * about its size.
+ */
+typedef isc_uint32_t isc_stdtime_t;
+
+/* but this flag helps... */
+#define STDTIME_ON_32BITS	1
+
+/*
+ * isc_stdtime32_t is a 32-bit version of isc_stdtime_t.  A variable of this
+ * type should only be used as an opaque integer (e.g.,) to compare two
+ * time values.
+ */
+typedef isc_uint32_t isc_stdtime32_t;
+
+ISC_LANG_BEGINDECLS
+
+void
+isc_stdtime_get(isc_stdtime_t *t);
+/*
+ * Set 't' to the number of seconds since 00:00:00 UTC, January 1, 1970.
+ *
+ * Requires:
+ *
+ *	't' is a valid pointer.
+ */
+
+#define isc_stdtime_convert32(t, t32p) (*(t32p) = t)
+/*
+ * Convert the standard time to its 32-bit version.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_STDTIME_H */
diff --git a/src/lib/bind9/win32/include/isc/strerror.h b/src/lib/bind9/win32/include/isc/strerror.h
new file mode 100644
index 0000000..25041be
--- /dev/null
+++ b/src/lib/bind9/win32/include/isc/strerror.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2004, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: strerror.h,v 1.5 2007-06-19 23:47:20 tbox Exp $ */
+
+#ifndef ISC_STRERROR_H
+#define ISC_STRERROR_H
+
+#include <sys/types.h>
+
+#include <isc/lang.h>
+
+ISC_LANG_BEGINDECLS
+
+#define ISC_STRERRORSIZE 128
+
+/*
+ * Provide a thread safe wrapper to strerrror().
+ *
+ * Requires:
+ * 	'buf' to be non NULL.
+ */
+void
+isc__strerror(int num, char *buf, size_t bufsize);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_STRERROR_H */
diff --git a/src/lib/bind9/win32/include/isc/syslog.h b/src/lib/bind9/win32/include/isc/syslog.h
new file mode 100644
index 0000000..8f2ed81
--- /dev/null
+++ b/src/lib/bind9/win32/include/isc/syslog.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2004, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: syslog.h,v 1.5 2007-06-19 23:47:20 tbox Exp $ */
+
+#ifndef ISC_SYSLOG_H
+#define ISC_SYSLOG_H 1
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_syslog_facilityfromstring(const char *str, int *facilityp);
+/*
+ * Convert 'str' to the appropriate syslog facility constant.
+ *
+ * Requires:
+ *
+ *	'str' is not NULL
+ *	'facilityp' is not NULL
+ *
+ * Returns:
+ * 	ISC_R_SUCCESS
+ * 	ISC_R_NOTFOUND
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_SYSLOG_H */
diff --git a/src/lib/bind9/win32/include/isc/thread.h b/src/lib/bind9/win32/include/isc/thread.h
new file mode 100644
index 0000000..0926b60
--- /dev/null
+++ b/src/lib/bind9/win32/include/isc/thread.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: thread.h,v 1.25 2009-09-29 04:37:08 marka Exp $ */
+
+#ifndef ISC_THREAD_H
+#define ISC_THREAD_H 1
+
+#include <windows.h>
+
+#include <isc/lang.h>
+#include <isc/result.h>
+
+/*
+ * Inlines to help with wait retrun checking
+ */
+
+/* check handle for NULL and INVALID_HANDLE */
+inline BOOL IsValidHandle( HANDLE hHandle) {
+    return ((hHandle != NULL) && (hHandle != INVALID_HANDLE_VALUE));
+}
+
+/* validate wait return codes... */
+inline BOOL WaitSucceeded( DWORD dwWaitResult, DWORD dwHandleCount) {
+    return ((dwWaitResult >= WAIT_OBJECT_0) &&
+	    (dwWaitResult < WAIT_OBJECT_0 + dwHandleCount));
+}
+
+inline BOOL WaitAbandoned( DWORD dwWaitResult, DWORD dwHandleCount) {
+    return ((dwWaitResult >= WAIT_ABANDONED_0) &&
+	    (dwWaitResult < WAIT_ABANDONED_0 + dwHandleCount));
+}
+
+inline BOOL WaitTimeout( DWORD dwWaitResult) {
+    return (dwWaitResult == WAIT_TIMEOUT);
+}
+
+inline BOOL WaitFailed( DWORD dwWaitResult) {
+    return (dwWaitResult == WAIT_FAILED);
+}
+
+/* compute object indices for waits... */
+inline DWORD WaitSucceededIndex( DWORD dwWaitResult) {
+    return (dwWaitResult - WAIT_OBJECT_0);
+}
+
+inline DWORD WaitAbandonedIndex( DWORD dwWaitResult) {
+    return (dwWaitResult - WAIT_ABANDONED_0);
+}
+
+
+
+typedef HANDLE isc_thread_t;
+typedef DWORD isc_threadresult_t;
+typedef void * isc_threadarg_t;
+typedef isc_threadresult_t (WINAPI *isc_threadfunc_t)(isc_threadarg_t);
+typedef DWORD isc_thread_key_t;
+
+#define isc_thread_self (unsigned long)GetCurrentThreadId
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_thread_create(isc_threadfunc_t, isc_threadarg_t, isc_thread_t *);
+
+isc_result_t
+isc_thread_join(isc_thread_t, isc_threadresult_t *);
+
+void
+isc_thread_setconcurrency(unsigned int level);
+
+int
+isc_thread_key_create(isc_thread_key_t *key, void (*func)(void *));
+
+int
+isc_thread_key_delete(isc_thread_key_t key);
+
+void *
+isc_thread_key_getspecific(isc_thread_key_t);
+
+int
+isc_thread_key_setspecific(isc_thread_key_t key, void *value);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_THREAD_H */
diff --git a/src/lib/bind9/win32/include/isc/time.h b/src/lib/bind9/win32/include/isc/time.h
new file mode 100644
index 0000000..5ba038c
--- /dev/null
+++ b/src/lib/bind9/win32/include/isc/time.h
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2004, 2006-2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: time.h,v 1.35 2009-01-05 23:47:54 tbox Exp $ */
+
+#ifndef ISC_TIME_H
+#define ISC_TIME_H 1
+
+#include <windows.h>
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+/***
+ *** Intervals
+ ***/
+
+/*
+ * The contents of this structure are private, and MUST NOT be accessed
+ * directly by callers.
+ *
+ * The contents are exposed only to allow callers to avoid dynamic allocation.
+ */
+struct isc_interval {
+	isc_int64_t interval;
+};
+
+LIBISC_EXTERNAL_DATA extern isc_interval_t *isc_interval_zero;
+
+ISC_LANG_BEGINDECLS
+
+void
+isc_interval_set(isc_interval_t *i,
+		 unsigned int seconds, unsigned int nanoseconds);
+/*
+ * Set 'i' to a value representing an interval of 'seconds' seconds and
+ * 'nanoseconds' nanoseconds, suitable for use in isc_time_add() and
+ * isc_time_subtract().
+ *
+ * Requires:
+ *
+ *	't' is a valid pointer.
+ *	nanoseconds < 1000000000.
+ */
+
+isc_boolean_t
+isc_interval_iszero(const isc_interval_t *i);
+/*
+ * Returns ISC_TRUE iff. 'i' is the zero interval.
+ *
+ * Requires:
+ *
+ *	'i' is a valid pointer.
+ */
+
+/***
+ *** Absolute Times
+ ***/
+
+/*
+ * The contents of this structure are private, and MUST NOT be accessed
+ * directly by callers.
+ *
+ * The contents are exposed only to allow callers to avoid dynamic allocation.
+ */
+
+struct isc_time {
+	FILETIME absolute;
+};
+
+LIBISC_EXTERNAL_DATA extern isc_time_t *isc_time_epoch;
+
+void
+isc_time_set(isc_time_t *t, unsigned int seconds, unsigned int nanoseconds);
+/*%<
+ * Set 't' to a value which represents the given number of seconds and
+ * nanoseconds since 00:00:00 January 1, 1970, UTC.
+ *
+ * Requires:
+ *\li   't' is a valid pointer.
+ *\li   nanoseconds < 1000000000.
+ */
+
+void
+isc_time_settoepoch(isc_time_t *t);
+/*
+ * Set 't' to the time of the epoch.
+ *
+ * Notes:
+ * 	The date of the epoch is platform-dependent.
+ *
+ * Requires:
+ *
+ *	't' is a valid pointer.
+ */
+
+isc_boolean_t
+isc_time_isepoch(const isc_time_t *t);
+/*
+ * Returns ISC_TRUE iff. 't' is the epoch ("time zero").
+ *
+ * Requires:
+ *
+ *	't' is a valid pointer.
+ */
+
+isc_result_t
+isc_time_now(isc_time_t *t);
+/*
+ * Set 't' to the current absolute time.
+ *
+ * Requires:
+ *
+ *	't' is a valid pointer.
+ *
+ * Returns:
+ *
+ *	Success
+ *	Unexpected error
+ *		Getting the time from the system failed.
+ *	Out of range
+ *		The time from the system is too large to be represented
+ *		in the current definition of isc_time_t.
+ */
+
+isc_result_t
+isc_time_nowplusinterval(isc_time_t *t, const isc_interval_t *i);
+/*
+ * Set *t to the current absolute time + i.
+ *
+ * Note:
+ *	This call is equivalent to:
+ *
+ *		isc_time_now(t);
+ *		isc_time_add(t, i, t);
+ *
+ * Requires:
+ *
+ *	't' and 'i' are valid pointers.
+ *
+ * Returns:
+ *
+ *	Success
+ *	Unexpected error
+ *		Getting the time from the system failed.
+ *	Out of range
+ *		The interval added to the time from the system is too large to
+ *		be represented in the current definition of isc_time_t.
+ */
+
+int
+isc_time_compare(const isc_time_t *t1, const isc_time_t *t2);
+/*
+ * Compare the times referenced by 't1' and 't2'
+ *
+ * Requires:
+ *
+ *	't1' and 't2' are valid pointers.
+ *
+ * Returns:
+ *
+ *	-1		t1 < t2		(comparing times, not pointers)
+ *	0		t1 = t2
+ *	1		t1 > t2
+ */
+
+isc_result_t
+isc_time_add(const isc_time_t *t, const isc_interval_t *i, isc_time_t *result);
+/*
+ * Add 'i' to 't', storing the result in 'result'.
+ *
+ * Requires:
+ *
+ *	't', 'i', and 'result' are valid pointers.
+ *
+ * Returns:
+ * 	Success
+ *	Out of range
+ * 		The interval added to the time is too large to
+ *		be represented in the current definition of isc_time_t.
+ */
+
+isc_result_t
+isc_time_subtract(const isc_time_t *t, const isc_interval_t *i,
+		  isc_time_t *result);
+/*
+ * Subtract 'i' from 't', storing the result in 'result'.
+ *
+ * Requires:
+ *
+ *	't', 'i', and 'result' are valid pointers.
+ *
+ * Returns:
+ *	Success
+ *	Out of range
+ *		The interval is larger than the time since the epoch.
+ */
+
+isc_uint64_t
+isc_time_microdiff(const isc_time_t *t1, const isc_time_t *t2);
+/*
+ * Find the difference in milliseconds between time t1 and time t2.
+ * t2 is the subtrahend of t1; ie, difference = t1 - t2.
+ *
+ * Requires:
+ *
+ *	't1' and 't2' are valid pointers.
+ *
+ * Returns:
+ *	The difference of t1 - t2, or 0 if t1 <= t2.
+ */
+
+isc_uint32_t
+isc_time_nanoseconds(const isc_time_t *t);
+/*
+ * Return the number of nanoseconds stored in a time structure.
+ *
+ * Notes:
+ *	This is the number of nanoseconds in excess of the number
+ *	of seconds since the epoch; it will always be less than one
+ *	full second.
+ *
+ * Requires:
+ *	't' is a valid pointer.
+ *
+ * Ensures:
+ *	The returned value is less than 1*10^9.
+ */
+
+void
+isc_time_formattimestamp(const isc_time_t *t, char *buf, unsigned int len);
+/*
+ * Format the time 't' into the buffer 'buf' of length 'len',
+ * using a format like "30-Aug-2000 04:06:47.997" and the local time zone.
+ * If the text does not fit in the buffer, the result is indeterminate,
+ * but is always guaranteed to be null terminated.
+ *
+ *  Requires:
+ *      'len' > 0
+ *      'buf' points to an array of at least len chars
+ *
+ */
+
+void
+isc_time_formathttptimestamp(const isc_time_t *t, char *buf, unsigned int len);
+/*
+ * Format the time 't' into the buffer 'buf' of length 'len',
+ * using a format like "Mon, 30 Aug 2000 04:06:47 GMT"
+ * If the text does not fit in the buffer, the result is indeterminate,
+ * but is always guaranteed to be null terminated.
+ *
+ *  Requires:
+ *      'len' > 0
+ *      'buf' points to an array of at least len chars
+ *
+ */
+
+void
+isc_time_formatISO8601(const isc_time_t *t, char *buf, unsigned int len);
+/*%<
+ * Format the time 't' into the buffer 'buf' of length 'len',
+ * using the ISO8601 format: "yyyy-mm-ddThh:mm:ssZ"
+ * If the text does not fit in the buffer, the result is indeterminate,
+ * but is always guaranteed to be null terminated.
+ *
+ *  Requires:
+ *\li      'len' > 0
+ *\li      'buf' points to an array of at least len chars
+ *
+ */
+
+isc_uint32_t
+isc_time_seconds(const isc_time_t *t);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_TIME_H */
diff --git a/src/lib/bind9/win32/include/isc/win32os.h b/src/lib/bind9/win32/include/isc/win32os.h
new file mode 100644
index 0000000..0879ddb
--- /dev/null
+++ b/src/lib/bind9/win32/include/isc/win32os.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2004, 2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2002  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: win32os.h,v 1.7 2009-06-25 23:48:02 tbox Exp $ */
+
+#ifndef ISC_WIN32OS_H
+#define ISC_WIN32OS_H 1
+
+#include <isc/lang.h>
+
+ISC_LANG_BEGINDECLS
+
+/*
+ * Return the number of CPUs available on the system, or 1 if this cannot
+ * be determined.
+ */
+
+unsigned int
+isc_win32os_majorversion(void);
+/*
+ * Major Version of the O/S.
+ */
+
+unsigned int
+isc_win32os_minorversion(void);
+/*
+ * Minor Version of the O/S.
+ */
+
+unsigned int
+isc_win32os_servicepackmajor(void);
+/*
+ * Major Version of the Service Pack for O/S.
+ */
+
+unsigned int
+isc_win32os_servicepackminor(void);
+/*
+ * Minor Version of the Service Pack for O/S.
+ */
+
+int
+isc_win32os_versioncheck(unsigned int major, unsigned int minor,
+		     unsigned int updatemajor, unsigned int updateminor);
+
+/*
+ * Checks the current version of the operating system with the
+ * supplied version information.
+ * Returns:
+ * -1	if less than the version information supplied
+ *  0   if equal to all of the version information supplied
+ * +1   if greater than the version information supplied
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_WIN32OS_H */
diff --git a/src/lib/bind9/win32/interfaceiter.c b/src/lib/bind9/win32/interfaceiter.c
new file mode 100644
index 0000000..aba0771
--- /dev/null
+++ b/src/lib/bind9/win32/interfaceiter.c
@@ -0,0 +1,500 @@
+/*
+ * Copyright (C) 2004, 2007-2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: interfaceiter.c,v 1.15 2009-01-18 23:48:14 tbox Exp $ */
+
+/*
+ * Note that this code will need to be revisited to support IPv6 Interfaces.
+ * For now we just iterate through IPv4 interfaces.
+ */
+
+#include <config.h>
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <isc/interfaceiter.h>
+#include <isc/mem.h>
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/strerror.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+void InitSockets(void);
+
+/* Common utility functions */
+
+/*
+ * Extract the network address part from a "struct sockaddr".
+ *
+ * The address family is given explicitly
+ * instead of using src->sa_family, because the latter does not work
+ * for copying a network mask obtained by SIOCGIFNETMASK (it does
+ * not have a valid address family).
+ */
+
+
+#define IFITER_MAGIC		0x49464954U	/* IFIT. */
+#define VALID_IFITER(t)		((t) != NULL && (t)->magic == IFITER_MAGIC)
+
+struct isc_interfaceiter {
+	unsigned int		magic;		/* Magic number. */
+	isc_mem_t		*mctx;
+	int			socket;
+	INTERFACE_INFO		IFData;		/* Current Interface Info */
+	int			numIF;		/* Current Interface count */
+	int			v4IF;		/* Number of IPv4 Interfaces */
+	INTERFACE_INFO		*buf4;		/* Buffer for WSAIoctl data. */
+	unsigned int		buf4size;	/* Bytes allocated. */
+	INTERFACE_INFO		*pos4;		/* Current offset in IF List */
+	SOCKET_ADDRESS_LIST	*buf6;
+	unsigned int		buf6size;	/* Bytes allocated. */
+	unsigned int		pos6;
+	isc_interface_t		current;	/* Current interface data. */
+	isc_result_t		result;		/* Last result code. */
+};
+
+
+/*
+ * Size of buffer for SIO_GET_INTERFACE_LIST, in number of interfaces.
+ * We assume no sane system will have more than than 1K of IP addresses on
+ * all of its adapters.
+ */
+#define IFCONF_SIZE_INITIAL	  16
+#define IFCONF_SIZE_INCREMENT	  64
+#define IFCONF_SIZE_MAX		1040
+
+static void
+get_addr(unsigned int family, isc_netaddr_t *dst, struct sockaddr *src) {
+	dst->family = family;
+	switch (family) {
+	case AF_INET:
+		memcpy(&dst->type.in,
+		       &((struct sockaddr_in *) src)->sin_addr,
+		       sizeof(struct in_addr));
+		break;
+	case	AF_INET6:
+		memcpy(&dst->type.in6,
+		       &((struct sockaddr_in6 *) src)->sin6_addr,
+		       sizeof(struct in6_addr));
+		dst->zone = ((struct sockaddr_in6 *) src)->sin6_scope_id;
+		break;
+	default:
+		INSIST(0);
+		break;
+	}
+}
+
+isc_result_t
+isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) {
+	char strbuf[ISC_STRERRORSIZE];
+	isc_interfaceiter_t *iter;
+	isc_result_t result;
+	int error;
+	unsigned long bytesReturned = 0;
+
+	REQUIRE(mctx != NULL);
+	REQUIRE(iterp != NULL);
+	REQUIRE(*iterp == NULL);
+
+	iter = isc_mem_get(mctx, sizeof(*iter));
+	if (iter == NULL)
+		return (ISC_R_NOMEMORY);
+
+	InitSockets();
+
+	iter->mctx = mctx;
+	iter->buf4 = NULL;
+	iter->buf6 = NULL;
+	iter->pos4 = NULL;
+	iter->pos6 = 0;
+	iter->buf6size = 0;
+	iter->buf4size = 0;
+	iter->result = ISC_R_FAILURE;
+	iter->numIF = 0;
+	iter->v4IF = 0;
+
+	/*
+	 * Create an unbound datagram socket to do the
+	 * SIO_GET_INTERFACE_LIST WSAIoctl on.
+	 */
+	if ((iter->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+		error = WSAGetLastError();
+		if (error == WSAEAFNOSUPPORT)
+			goto inet6_only;
+		isc__strerror(error, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				"making interface scan socket: %s",
+				strbuf);
+		result = ISC_R_UNEXPECTED;
+		goto socket_failure;
+	}
+
+	/*
+	 * Get the interface configuration, allocating more memory if
+	 * necessary.
+	 */
+	iter->buf4size = IFCONF_SIZE_INITIAL*sizeof(INTERFACE_INFO);
+
+	for (;;) {
+		iter->buf4 = isc_mem_get(mctx, iter->buf4size);
+		if (iter->buf4 == NULL) {
+			result = ISC_R_NOMEMORY;
+			goto alloc_failure;
+		}
+
+		if (WSAIoctl(iter->socket, SIO_GET_INTERFACE_LIST,
+			     0, 0, iter->buf4, iter->buf4size,
+			     &bytesReturned, 0, 0) == SOCKET_ERROR)
+		{
+			error = WSAGetLastError();
+			if (error != WSAEFAULT && error != WSAENOBUFS) {
+				errno = error;
+				isc__strerror(error, strbuf, sizeof(strbuf));
+				UNEXPECTED_ERROR(__FILE__, __LINE__,
+						"get interface configuration: %s",
+						strbuf);
+				result = ISC_R_UNEXPECTED;
+				goto ioctl_failure;
+			}
+			/*
+			 * EINVAL.  Retry with a bigger buffer.
+			 */
+		} else {
+			/*
+			 * The WSAIoctl succeeded.
+			 * If the number of the returned bytes is the same
+			 * as the buffer size, we will grow it just in
+			 * case and retry.
+			 */
+			if (bytesReturned > 0 &&
+			    (bytesReturned < iter->buf4size))
+				break;
+		}
+		if (iter->buf4size >= IFCONF_SIZE_MAX*sizeof(INTERFACE_INFO)) {
+			UNEXPECTED_ERROR(__FILE__, __LINE__,
+					 "get interface configuration: "
+					 "maximum buffer size exceeded");
+			result = ISC_R_UNEXPECTED;
+			goto ioctl_failure;
+		}
+		isc_mem_put(mctx, iter->buf4, iter->buf4size);
+
+		iter->buf4size += IFCONF_SIZE_INCREMENT *
+			sizeof(INTERFACE_INFO);
+	}
+
+	/*
+	 * A newly created iterator has an undefined position
+	 * until isc_interfaceiter_first() is called.
+	 */
+	iter->v4IF = bytesReturned/sizeof(INTERFACE_INFO);
+
+	/* We don't need the socket any more, so close it */
+	closesocket(iter->socket);
+
+ inet6_only:
+	/*
+	 * Create an unbound datagram socket to do the
+	 * SIO_ADDRESS_LIST_QUERY WSAIoctl on.
+	 */
+	if ((iter->socket = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+		error = WSAGetLastError();
+		if (error == WSAEAFNOSUPPORT)
+			goto inet_only;
+		isc__strerror(error, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				"making interface scan socket: %s",
+				strbuf);
+		result = ISC_R_UNEXPECTED;
+		goto ioctl_failure;
+	}
+
+	/*
+	 * Get the interface configuration, allocating more memory if
+	 * necessary.
+	 */
+	iter->buf6size = sizeof(SOCKET_ADDRESS_LIST) +
+			 IFCONF_SIZE_INITIAL*sizeof(SOCKET_ADDRESS);
+
+	for (;;) {
+		iter->buf6 = isc_mem_get(mctx, iter->buf6size);
+		if (iter->buf6 == NULL) {
+			result = ISC_R_NOMEMORY;
+			goto ioctl_failure;
+		}
+
+		if (WSAIoctl(iter->socket, SIO_ADDRESS_LIST_QUERY,
+			     0, 0, iter->buf6, iter->buf6size,
+			     &bytesReturned, 0, 0) == SOCKET_ERROR)
+		{
+			error = WSAGetLastError();
+			if (error != WSAEFAULT && error != WSAENOBUFS) {
+				errno = error;
+				isc__strerror(error, strbuf, sizeof(strbuf));
+				UNEXPECTED_ERROR(__FILE__, __LINE__,
+						 "sio address list query: %s",
+						 strbuf);
+				result = ISC_R_UNEXPECTED;
+				goto ioctl6_failure;
+			}
+			/*
+			 * EINVAL.  Retry with a bigger buffer.
+			 */
+		} else
+			break;
+
+		if (iter->buf6size >= IFCONF_SIZE_MAX*sizeof(SOCKET_ADDRESS)) {
+			UNEXPECTED_ERROR(__FILE__, __LINE__,
+					 "get interface configuration: "
+					 "maximum buffer size exceeded");
+			result = ISC_R_UNEXPECTED;
+			goto ioctl6_failure;
+		}
+		isc_mem_put(mctx, iter->buf6, iter->buf6size);
+
+		iter->buf6size += IFCONF_SIZE_INCREMENT *
+			sizeof(SOCKET_ADDRESS);
+	}
+
+	closesocket(iter->socket);
+
+ inet_only:
+	iter->magic = IFITER_MAGIC;
+	*iterp = iter;
+	return (ISC_R_SUCCESS);
+
+ ioctl6_failure:
+	isc_mem_put(mctx, iter->buf6, iter->buf6size);
+
+ ioctl_failure:
+	if (iter->buf4 != NULL)
+		isc_mem_put(mctx, iter->buf4, iter->buf4size);
+
+ alloc_failure:
+	if (iter->socket >= 0)
+		(void) closesocket(iter->socket);
+
+ socket_failure:
+	isc_mem_put(mctx, iter, sizeof(*iter));
+	return (result);
+}
+
+/*
+ * Get information about the current interface to iter->current.
+ * If successful, return ISC_R_SUCCESS.
+ * If the interface has an unsupported address family, or if
+ * some operation on it fails, return ISC_R_IGNORE to make
+ * the higher-level iterator code ignore it.
+ */
+
+static isc_result_t
+internal_current(isc_interfaceiter_t *iter) {
+	BOOL ifNamed = FALSE;
+	unsigned long flags;
+
+	REQUIRE(VALID_IFITER(iter));
+	REQUIRE(iter->numIF >= 0);
+
+	memset(&iter->current, 0, sizeof(iter->current));
+	iter->current.af = AF_INET;
+
+	get_addr(AF_INET, &iter->current.address,
+		 (struct sockaddr *)&(iter->IFData.iiAddress));
+
+	/*
+	 * Get interface flags.
+	 */
+
+	iter->current.flags = 0;
+	flags = iter->IFData.iiFlags;
+
+	if ((flags & IFF_UP) != 0)
+		iter->current.flags |= INTERFACE_F_UP;
+
+	if ((flags & IFF_POINTTOPOINT) != 0) {
+		iter->current.flags |= INTERFACE_F_POINTTOPOINT;
+		sprintf(iter->current.name, "PPP Interface %d", iter->numIF);
+		ifNamed = TRUE;
+	}
+
+	if ((flags & IFF_LOOPBACK) != 0) {
+		iter->current.flags |= INTERFACE_F_LOOPBACK;
+		sprintf(iter->current.name, "Loopback Interface %d",
+			iter->numIF);
+		ifNamed = TRUE;
+	}
+
+	/*
+	 * If the interface is point-to-point, get the destination address.
+	 */
+	if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) {
+		get_addr(AF_INET, &iter->current.dstaddress,
+		(struct sockaddr *)&(iter->IFData.iiBroadcastAddress));
+	}
+
+	if (ifNamed == FALSE)
+		sprintf(iter->current.name,
+			"TCP/IP Interface %d", iter->numIF);
+
+	/*
+	 * Get the network mask.
+	 */
+	get_addr(AF_INET, &iter->current.netmask,
+		 (struct sockaddr *)&(iter->IFData.iiNetmask));
+
+	return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+internal_current6(isc_interfaceiter_t *iter) {
+	BOOL ifNamed = FALSE;
+	int i;
+
+	REQUIRE(VALID_IFITER(iter));
+	REQUIRE(iter->pos6 >= 0);
+	REQUIRE(iter->buf6 != 0);
+
+	memset(&iter->current, 0, sizeof(iter->current));
+	iter->current.af = AF_INET6;
+
+	get_addr(AF_INET6, &iter->current.address,
+		 iter->buf6->Address[iter->pos6].lpSockaddr);
+
+	/*
+	 * Get interface flags.
+	 */
+
+	iter->current.flags = INTERFACE_F_UP;
+
+	if (ifNamed == FALSE)
+		sprintf(iter->current.name,
+			"TCP/IPv6 Interface %d", iter->pos6 + 1);
+
+	for (i = 0; i< 16; i++)
+		iter->current.netmask.type.in6.s6_addr[i] = 0xff;
+	iter->current.netmask.family = AF_INET6;
+	return (ISC_R_SUCCESS);
+}
+
+/*
+ * Step the iterator to the next interface.  Unlike
+ * isc_interfaceiter_next(), this may leave the iterator
+ * positioned on an interface that will ultimately
+ * be ignored.  Return ISC_R_NOMORE if there are no more
+ * interfaces, otherwise ISC_R_SUCCESS.
+ */
+static isc_result_t
+internal_next(isc_interfaceiter_t *iter) {
+	if (iter->numIF >= iter->v4IF)
+		return (ISC_R_NOMORE);
+
+	/*
+	 * The first one needs to be set up to point to the last
+	 * Element of the array.  Go to the end and back up
+	 * Microsoft's implementation is peculiar for returning
+	 * the list in reverse order
+	 */
+
+	if (iter->numIF == 0)
+		iter->pos4 = (INTERFACE_INFO *)(iter->buf4 + (iter->v4IF));
+
+	iter->pos4--;
+	if (&(iter->pos4) < &(iter->buf4))
+		return (ISC_R_NOMORE);
+
+	memset(&(iter->IFData), 0, sizeof(INTERFACE_INFO));
+	memcpy(&(iter->IFData), iter->pos4, sizeof(INTERFACE_INFO));
+	iter->numIF++;
+
+	return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+internal_next6(isc_interfaceiter_t *iter) {
+	if (iter->pos6 == 0)
+		return (ISC_R_NOMORE);
+	iter->pos6--;
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_interfaceiter_current(isc_interfaceiter_t *iter,
+			  isc_interface_t *ifdata) {
+	REQUIRE(iter->result == ISC_R_SUCCESS);
+	memcpy(ifdata, &iter->current, sizeof(*ifdata));
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_interfaceiter_first(isc_interfaceiter_t *iter) {
+
+	REQUIRE(VALID_IFITER(iter));
+
+	if (iter->buf6 != NULL)
+		iter->pos6 = iter->buf6->iAddressCount;
+	iter->result = ISC_R_SUCCESS;
+	return (isc_interfaceiter_next(iter));
+}
+
+isc_result_t
+isc_interfaceiter_next(isc_interfaceiter_t *iter) {
+	isc_result_t result;
+
+	REQUIRE(VALID_IFITER(iter));
+	REQUIRE(iter->result == ISC_R_SUCCESS);
+
+	for (;;) {
+		result = internal_next(iter);
+		if (result == ISC_R_NOMORE) {
+			result = internal_next6(iter);
+			if (result != ISC_R_SUCCESS)
+				break;
+			result = internal_current6(iter);
+			if (result != ISC_R_IGNORE)
+				break;
+		} else if (result != ISC_R_SUCCESS)
+			break;
+		result = internal_current(iter);
+		if (result != ISC_R_IGNORE)
+			break;
+	}
+	iter->result = result;
+	return (result);
+}
+
+void
+isc_interfaceiter_destroy(isc_interfaceiter_t **iterp) {
+	isc_interfaceiter_t *iter;
+	REQUIRE(iterp != NULL);
+	iter = *iterp;
+	REQUIRE(VALID_IFITER(iter));
+
+	if (iter->buf4 != NULL)
+		isc_mem_put(iter->mctx, iter->buf4, iter->buf4size);
+	if (iter->buf6 != NULL)
+		isc_mem_put(iter->mctx, iter->buf6, iter->buf6size);
+
+	iter->magic = 0;
+	isc_mem_put(iter->mctx, iter, sizeof(*iter));
+	*iterp = NULL;
+}
diff --git a/src/lib/bind9/win32/ipv6.c b/src/lib/bind9/win32/ipv6.c
new file mode 100644
index 0000000..b461544
--- /dev/null
+++ b/src/lib/bind9/win32/ipv6.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2004, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: ipv6.c,v 1.8 2007-06-19 23:47:19 tbox Exp $ */
+
+#include <isc/net.h>
+#include <isc/platform.h>
+
+LIBISC_EXTERNAL_DATA const struct in6_addr isc_in6addr_any =
+	IN6ADDR_ANY_INIT;
+
+LIBISC_EXTERNAL_DATA const struct in6_addr isc_in6addr_loopback =
+	IN6ADDR_LOOPBACK_INIT;
diff --git a/src/lib/bind9/win32/keyboard.c b/src/lib/bind9/win32/keyboard.c
new file mode 100644
index 0000000..61a9bf8
--- /dev/null
+++ b/src/lib/bind9/win32/keyboard.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2004, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: keyboard.c,v 1.7 2007-06-19 23:47:19 tbox Exp $ */
+
+#include <config.h>
+
+#include <sys/types.h>
+
+#include <windows.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <io.h>
+
+#include <isc/keyboard.h>
+#include <isc/util.h>
+
+isc_result_t
+isc_keyboard_open(isc_keyboard_t *keyboard) {
+	int fd;
+
+	REQUIRE(keyboard != NULL);
+
+	fd = _fileno(stdin);
+	if (fd < 0)
+		return (ISC_R_IOERROR);
+
+	keyboard->fd = fd;
+
+	keyboard->result = ISC_R_SUCCESS;
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_keyboard_close(isc_keyboard_t *keyboard, unsigned int sleeptime) {
+	REQUIRE(keyboard != NULL);
+
+	if (sleeptime > 0 && keyboard->result != ISC_R_CANCELED)
+		(void)Sleep(sleeptime*1000);
+
+	keyboard->fd = -1;
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_keyboard_getchar(isc_keyboard_t *keyboard, unsigned char *cp) {
+	ssize_t cc;
+	unsigned char c;
+
+	REQUIRE(keyboard != NULL);
+	REQUIRE(cp != NULL);
+
+	cc = read(keyboard->fd, &c, 1);
+	if (cc < 0) {
+		keyboard->result = ISC_R_IOERROR;
+		return (keyboard->result);
+	}
+
+	*cp = c;
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_boolean_t
+isc_keyboard_canceled(isc_keyboard_t *keyboard) {
+	return (ISC_TF(keyboard->result == ISC_R_CANCELED));
+}
+
diff --git a/src/lib/bind9/win32/libgen.h b/src/lib/bind9/win32/libgen.h
new file mode 100644
index 0000000..af1ac55
--- /dev/null
+++ b/src/lib/bind9/win32/libgen.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2009  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: libgen.h,v 1.3 2009-07-17 23:47:41 tbox Exp $ */
+
+#ifndef LIBGEN_H
+#define LIBGEN_H 1
+
+char *basename(const char *);
+char *dirname(const char *);
+
+#endif
diff --git a/src/lib/bind9/win32/net.c b/src/lib/bind9/win32/net.c
new file mode 100644
index 0000000..5dda77f
--- /dev/null
+++ b/src/lib/bind9/win32/net.c
@@ -0,0 +1,332 @@
+/*
+ * Copyright (C) 2004, 2005, 2007-2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: net.c,v 1.20 2009-09-08 23:41:50 tbox Exp $ */
+
+#include <config.h>
+
+#include <errno.h>
+#include <unistd.h>
+
+#include <isc/log.h>
+#include <isc/msgs.h>
+#include <isc/net.h>
+#include <isc/once.h>
+#include <isc/strerror.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+/*%
+ * Definitions about UDP port range specification.  This is a total mess of
+ * portability variants: some use sysctl (but the sysctl names vary), some use
+ * system-specific interfaces, some have the same interface for IPv4 and IPv6,
+ * some separate them, etc...
+ */
+
+/*%
+ * The last resort defaults: use all non well known port space
+ */
+#ifndef ISC_NET_PORTRANGELOW
+#define ISC_NET_PORTRANGELOW 1024
+#endif	/* ISC_NET_PORTRANGELOW */
+#ifndef ISC_NET_PORTRANGEHIGH
+#define ISC_NET_PORTRANGEHIGH 65535
+#endif	/* ISC_NET_PORTRANGEHIGH */
+
+#if defined(ISC_PLATFORM_HAVEIPV6) && defined(ISC_PLATFORM_NEEDIN6ADDRANY)
+const struct in6_addr isc_net_in6addrany = IN6ADDR_ANY_INIT;
+#endif
+
+static isc_once_t 	once = ISC_ONCE_INIT;
+static isc_once_t 	once_ipv6only = ISC_ONCE_INIT;
+static isc_once_t 	once_ipv6pktinfo = ISC_ONCE_INIT;
+static isc_result_t	ipv4_result = ISC_R_NOTFOUND;
+static isc_result_t	ipv6_result = ISC_R_NOTFOUND;
+static isc_result_t	ipv6only_result = ISC_R_NOTFOUND;
+static isc_result_t	ipv6pktinfo_result = ISC_R_NOTFOUND;
+
+void InitSockets(void);
+
+static isc_result_t
+try_proto(int domain) {
+	SOCKET s;
+	isc_result_t result = ISC_R_SUCCESS;
+	char strbuf[ISC_STRERRORSIZE];
+	int errval;
+
+	s = socket(domain, SOCK_STREAM, IPPROTO_TCP);
+	if (s == INVALID_SOCKET) {
+		errval = WSAGetLastError();
+		switch (errval) {
+		case WSAEAFNOSUPPORT:
+		case WSAEPROTONOSUPPORT:
+		case WSAEINVAL:
+			return (ISC_R_NOTFOUND);
+		default:
+			isc__strerror(errval, strbuf, sizeof(strbuf));
+			UNEXPECTED_ERROR(__FILE__, __LINE__,
+					 "socket() %s: %s",
+					 isc_msgcat_get(isc_msgcat,
+							ISC_MSGSET_GENERAL,
+							ISC_MSG_FAILED,
+							"failed"),
+					 strbuf);
+			return (ISC_R_UNEXPECTED);
+		}
+	}
+
+	closesocket(s);
+
+	return (ISC_R_SUCCESS);
+}
+
+static void
+initialize_action(void) {
+	InitSockets();
+	ipv4_result = try_proto(PF_INET);
+#ifdef ISC_PLATFORM_HAVEIPV6
+#ifdef WANT_IPV6
+#ifdef ISC_PLATFORM_HAVEIN6PKTINFO
+	ipv6_result = try_proto(PF_INET6);
+#endif
+#endif
+#endif
+}
+
+static void
+initialize(void) {
+	RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_net_probeipv4(void) {
+	initialize();
+	return (ipv4_result);
+}
+
+isc_result_t
+isc_net_probeipv6(void) {
+	initialize();
+	return (ipv6_result);
+}
+
+isc_result_t
+isc_net_probeunix(void) {
+	return (ISC_R_NOTFOUND);
+}
+
+#ifdef ISC_PLATFORM_HAVEIPV6
+#ifdef WANT_IPV6
+static void
+try_ipv6only(void) {
+#ifdef IPV6_V6ONLY
+	SOCKET s;
+	int on;
+	char strbuf[ISC_STRERRORSIZE];
+#endif
+	isc_result_t result;
+
+	result = isc_net_probeipv6();
+	if (result != ISC_R_SUCCESS) {
+		ipv6only_result = result;
+		return;
+	}
+
+#ifndef IPV6_V6ONLY
+	ipv6only_result = ISC_R_NOTFOUND;
+	return;
+#else
+	/* check for TCP sockets */
+	s = socket(PF_INET6, SOCK_STREAM, 0);
+	if (s == INVALID_SOCKET) {
+		isc__strerror(errno, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "socket() %s: %s",
+				 isc_msgcat_get(isc_msgcat,
+						ISC_MSGSET_GENERAL,
+						ISC_MSG_FAILED,
+						"failed"),
+				 strbuf);
+		ipv6only_result = ISC_R_UNEXPECTED;
+		return;
+	}
+
+	on = 1;
+	if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) {
+		ipv6only_result = ISC_R_NOTFOUND;
+		goto close;
+	}
+
+	closesocket(s);
+
+	/* check for UDP sockets */
+	s = socket(PF_INET6, SOCK_DGRAM, 0);
+	if (s == INVALID_SOCKET) {
+		isc__strerror(errno, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "socket() %s: %s",
+				 isc_msgcat_get(isc_msgcat,
+						ISC_MSGSET_GENERAL,
+						ISC_MSG_FAILED,
+						"failed"),
+				 strbuf);
+		ipv6only_result = ISC_R_UNEXPECTED;
+		return;
+	}
+
+	on = 1;
+	if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) {
+		ipv6only_result = ISC_R_NOTFOUND;
+		goto close;
+	}
+
+	ipv6only_result = ISC_R_SUCCESS;
+
+close:
+	closesocket(s);
+	return;
+#endif /* IPV6_V6ONLY */
+}
+
+static void
+initialize_ipv6only(void) {
+	RUNTIME_CHECK(isc_once_do(&once_ipv6only,
+				  try_ipv6only) == ISC_R_SUCCESS);
+}
+
+static void
+try_ipv6pktinfo(void) {
+	int s, on;
+	char strbuf[ISC_STRERRORSIZE];
+	isc_result_t result;
+	int optname;
+
+	result = isc_net_probeipv6();
+	if (result != ISC_R_SUCCESS) {
+		ipv6pktinfo_result = result;
+		return;
+	}
+
+	/* we only use this for UDP sockets */
+	s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+	if (s == INVALID_SOCKET) {
+		isc__strerror(errno, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "socket() %s: %s",
+				 isc_msgcat_get(isc_msgcat,
+						ISC_MSGSET_GENERAL,
+						ISC_MSG_FAILED,
+						"failed"),
+				 strbuf);
+		ipv6pktinfo_result = ISC_R_UNEXPECTED;
+		return;
+	}
+
+#ifdef IPV6_RECVPKTINFO
+	optname = IPV6_RECVPKTINFO;
+#else
+	optname = IPV6_PKTINFO;
+#endif
+	on = 1;
+	if (setsockopt(s, IPPROTO_IPV6, optname, (const char *) &on,
+		       sizeof(on)) < 0) {
+		ipv6pktinfo_result = ISC_R_NOTFOUND;
+		goto close;
+	}
+
+	ipv6pktinfo_result = ISC_R_SUCCESS;
+
+close:
+	closesocket(s);
+	return;
+}
+
+static void
+initialize_ipv6pktinfo(void) {
+	RUNTIME_CHECK(isc_once_do(&once_ipv6pktinfo,
+				  try_ipv6pktinfo) == ISC_R_SUCCESS);
+}
+#endif /* WANT_IPV6 */
+#endif /* ISC_PLATFORM_HAVEIPV6 */
+
+isc_result_t
+isc_net_probe_ipv6only(void) {
+#ifdef ISC_PLATFORM_HAVEIPV6
+#ifdef WANT_IPV6
+	initialize_ipv6only();
+#else
+	ipv6only_result = ISC_R_NOTFOUND;
+#endif
+#endif
+	return (ipv6only_result);
+}
+
+isc_result_t
+isc_net_probe_ipv6pktinfo(void) {
+#ifdef ISC_PLATFORM_HAVEIPV6
+#ifdef WANT_IPV6
+	initialize_ipv6pktinfo();
+#else
+	ipv6pktinfo_result = ISC_R_NOTFOUND;
+#endif
+#endif
+	return (ipv6pktinfo_result);
+}
+
+isc_result_t
+isc_net_getudpportrange(int af, in_port_t *low, in_port_t *high) {
+	int result = ISC_R_FAILURE;
+
+	REQUIRE(low != NULL && high != NULL);
+
+	UNUSED(af);
+
+	if (result != ISC_R_SUCCESS) {
+		*low = ISC_NET_PORTRANGELOW;
+		*high = ISC_NET_PORTRANGEHIGH;
+	}
+
+	return (ISC_R_SUCCESS);	/* we currently never fail in this function */
+}
+
+void
+isc_net_disableipv4(void) {
+	initialize();
+	if (ipv4_result == ISC_R_SUCCESS)
+		ipv4_result = ISC_R_DISABLED;
+}
+
+void
+isc_net_disableipv6(void) {
+	initialize();
+	if (ipv6_result == ISC_R_SUCCESS)
+		ipv6_result = ISC_R_DISABLED;
+}
+
+void
+isc_net_enableipv4(void) {
+	initialize();
+	if (ipv4_result == ISC_R_DISABLED)
+		ipv4_result = ISC_R_SUCCESS;
+}
+
+void
+isc_net_enableipv6(void) {
+	initialize();
+	if (ipv6_result == ISC_R_DISABLED)
+		ipv6_result = ISC_R_SUCCESS;
+}
diff --git a/src/lib/bind9/win32/netdb.h b/src/lib/bind9/win32/netdb.h
new file mode 100644
index 0000000..a5ae29c
--- /dev/null
+++ b/src/lib/bind9/win32/netdb.h
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2004, 2006, 2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: netdb.h,v 1.9 2009-01-18 23:48:14 tbox Exp $ */
+
+#ifndef NETDB_H
+#define NETDB_H 1
+
+#include <stddef.h>
+#include <winsock2.h>
+
+/*
+ * Define if <netdb.h> does not declare struct addrinfo.
+ */
+
+struct addrinfo {
+	int		ai_flags;      /* AI_PASSIVE, AI_CANONNAME */
+	int		ai_family;     /* PF_xxx */
+	int		ai_socktype;   /* SOCK_xxx */
+	int		ai_protocol;   /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
+	size_t		ai_addrlen;    /* Length of ai_addr */
+	char		*ai_canonname; /* Canonical name for hostname */
+	struct sockaddr	*ai_addr;      /* Binary address */
+	struct addrinfo	*ai_next;      /* Next structure in linked list */
+};
+
+
+/*
+ * Undefine all \#defines we are interested in as <netdb.h> may or may not have
+ * defined them.
+ */
+
+/*
+ * Error return codes from gethostbyname() and gethostbyaddr()
+ * (left in extern int h_errno).
+ */
+
+#undef	NETDB_INTERNAL
+#undef	NETDB_SUCCESS
+#undef	HOST_NOT_FOUND
+#undef	TRY_AGAIN
+#undef	NO_RECOVERY
+#undef	NO_DATA
+#undef	NO_ADDRESS
+
+#define	NETDB_INTERNAL	-1	/* see errno */
+#define	NETDB_SUCCESS	0	/* no problem */
+#define	HOST_NOT_FOUND	1 /* Authoritative Answer Host not found */
+#define	TRY_AGAIN	2 /* Non-Authoritative Host not found, or SERVERFAIL */
+#define	NO_RECOVERY	3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */
+#define	NO_DATA		4 /* Valid name, no data record of requested type */
+#define	NO_ADDRESS	NO_DATA		/* no address, look for MX record */
+
+/*
+ * Error return codes from getaddrinfo()
+ */
+
+#undef	EAI_ADDRFAMILY
+#undef	EAI_AGAIN
+#undef	EAI_BADFLAGS
+#undef	EAI_FAIL
+#undef	EAI_FAMILY
+#undef	EAI_MEMORY
+#undef	EAI_NODATA
+#undef	EAI_NONAME
+#undef	EAI_SERVICE
+#undef	EAI_SOCKTYPE
+#undef	EAI_SYSTEM
+#undef	EAI_BADHINTS
+#undef	EAI_PROTOCOL
+#undef	EAI_MAX
+
+#define	EAI_ADDRFAMILY	 1	/* address family for hostname not supported */
+#define	EAI_AGAIN	 2	/* temporary failure in name resolution */
+#define	EAI_BADFLAGS	 3	/* invalid value for ai_flags */
+#define	EAI_FAIL	 4	/* non-recoverable failure in name resolution */
+#define	EAI_FAMILY	 5	/* ai_family not supported */
+#define	EAI_MEMORY	 6	/* memory allocation failure */
+#define	EAI_NODATA	 7	/* no address associated with hostname */
+#define	EAI_NONAME	 8	/* hostname nor servname provided, or not known */
+#define	EAI_SERVICE	 9	/* servname not supported for ai_socktype */
+#define	EAI_SOCKTYPE	10	/* ai_socktype not supported */
+#define	EAI_SYSTEM	11	/* system error returned in errno */
+#define EAI_BADHINTS	12
+#define EAI_PROTOCOL	13
+#define EAI_MAX		14
+
+/*
+ * Flag values for getaddrinfo()
+ */
+#undef	AI_PASSIVE
+#undef	AI_CANONNAME
+#undef	AI_NUMERICHOST
+
+#define	AI_PASSIVE	0x00000001
+#define	AI_CANONNAME	0x00000002
+#define AI_NUMERICHOST	0x00000004
+
+/*
+ * Flag values for getipnodebyname()
+ */
+#undef AI_V4MAPPED
+#undef AI_ALL
+#undef AI_ADDRCONFIG
+#undef AI_DEFAULT
+
+#define AI_V4MAPPED	0x00000008
+#define AI_ALL		0x00000010
+#define AI_ADDRCONFIG	0x00000020
+#define AI_DEFAULT	(AI_V4MAPPED|AI_ADDRCONFIG)
+
+/*
+ * Constants for getnameinfo()
+ */
+#undef	NI_MAXHOST
+#undef	NI_MAXSERV
+
+#define	NI_MAXHOST	1025
+#define	NI_MAXSERV	32
+
+/*
+ * Flag values for getnameinfo()
+ */
+#undef	NI_NOFQDN
+#undef	NI_NUMERICHOST
+#undef	NI_NAMEREQD
+#undef	NI_NUMERICSERV
+#undef	NI_DGRAM
+#undef	NI_NUMERICSCOPE
+
+#define	NI_NOFQDN	0x00000001
+#define	NI_NUMERICHOST	0x00000002
+#define	NI_NAMEREQD	0x00000004
+#define	NI_NUMERICSERV	0x00000008
+#define	NI_DGRAM	0x00000010
+#define	NI_NUMERICSCOPE	0x00000020	/*2553bis-00*/
+
+/*
+ * Structures for getrrsetbyname()
+ */
+struct rdatainfo {
+	unsigned int		rdi_length;
+	unsigned char		*rdi_data;
+};
+
+struct rrsetinfo {
+	unsigned int		rri_flags;
+	int			rri_rdclass;
+	int			rri_rdtype;
+	unsigned int		rri_ttl;
+	unsigned int		rri_nrdatas;
+	unsigned int		rri_nsigs;
+	char			*rri_name;
+	struct rdatainfo	*rri_rdatas;
+	struct rdatainfo	*rri_sigs;
+};
+
+/*
+ * Flags for getrrsetbyname()
+ */
+#define RRSET_VALIDATED		0x00000001
+	/* Set was dnssec validated */
+
+/*
+ * Return codes for getrrsetbyname()
+ */
+#define ERRSET_SUCCESS		0
+#define ERRSET_NOMEMORY		1
+#define ERRSET_FAIL		2
+#define ERRSET_INVAL		3
+
+
+#endif /* NETDB_H */
diff --git a/src/lib/bind9/win32/ntgroups.c b/src/lib/bind9/win32/ntgroups.c
new file mode 100644
index 0000000..b618f9e
--- /dev/null
+++ b/src/lib/bind9/win32/ntgroups.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2004, 2006, 2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: ntgroups.c,v 1.12 2009-09-29 23:48:04 tbox Exp $ */
+
+/*
+ * The NT Groups have two groups that are not well documented and are
+ * not normally seen: None and Everyone.  A user account belongs to
+ * any number of groups, but if it is not a member of any group then
+ * it is a member of the None Group. The None group is not listed
+ * anywhere. You cannot remove an account from the none group except
+ * by making it a member of some other group, The second group is the
+ * Everyone group.  All accounts, no matter how many groups that they
+ * belong to, also belong to the Everyone group. You cannot remove an
+ * account from the Everyone group.
+ */
+
+#ifndef UNICODE
+#define UNICODE
+#endif /* UNICODE */
+
+/*
+ * Silence warnings.
+ */
+#define _CRT_SECURE_NO_DEPRECATE 1
+
+#include <windows.h>
+#include <assert.h>
+#include <lm.h>
+
+#include <isc/ntgroups.h>
+#include <isc/result.h>
+
+#define MAX_NAME_LENGTH 256
+
+isc_result_t
+isc_ntsecurity_getaccountgroups(char *username, char **GroupList,
+				unsigned int maxgroups,
+				unsigned int *totalGroups) {
+	LPGROUP_USERS_INFO_0 pTmpBuf;
+	LPLOCALGROUP_USERS_INFO_0 pTmpLBuf;
+	DWORD i;
+	LPLOCALGROUP_USERS_INFO_0 pBuf = NULL;
+	LPGROUP_USERS_INFO_0 pgrpBuf = NULL;
+	DWORD dwLevel = 0;
+	DWORD dwFlags = LG_INCLUDE_INDIRECT;
+	DWORD dwPrefMaxLen = MAX_PREFERRED_LENGTH;
+	DWORD dwEntriesRead = 0;
+	DWORD dwTotalEntries = 0;
+	NET_API_STATUS nStatus;
+	DWORD dwTotalCount = 0;
+	size_t retlen;
+	wchar_t user[MAX_NAME_LENGTH];
+
+	retlen = mbstowcs(user, username, MAX_NAME_LENGTH);
+
+	*totalGroups = 0;
+	/*
+	 * Call the NetUserGetLocalGroups function
+	 * specifying information level 0.
+	 *
+	 * The LG_INCLUDE_INDIRECT flag specifies that the
+	 * function should also return the names of the local
+	 * groups in which the user is indirectly a member.
+	 */
+	nStatus = NetUserGetLocalGroups(NULL,
+				   user,
+				   dwLevel,
+				   dwFlags,
+				   (LPBYTE *) &pBuf,
+				   dwPrefMaxLen,
+				   &dwEntriesRead,
+				   &dwTotalEntries);
+	/*
+	 * See if the call succeeds,
+	 */
+	if (nStatus != NERR_Success) {
+		if (nStatus == ERROR_ACCESS_DENIED)
+			return (ISC_R_NOPERM);
+		if (nStatus == ERROR_MORE_DATA)
+			return (ISC_R_NOSPACE);
+		if (nStatus == NERR_UserNotFound)
+			dwEntriesRead = 0;
+	}
+
+	dwTotalCount = 0;
+	if (pBuf != NULL) {
+		pTmpLBuf = pBuf;
+		/*
+		 * Loop through the entries
+		 */
+		 for (i = 0;
+		     (i < dwEntriesRead && *totalGroups < maxgroups); i++) {
+			assert(pTmpLBuf != NULL);
+			if (pTmpLBuf == NULL)
+				break;
+			retlen = wcslen(pTmpLBuf->lgrui0_name);
+			GroupList[*totalGroups] = (char *) malloc(retlen +1);
+			if (GroupList[*totalGroups] == NULL)
+				return (ISC_R_NOMEMORY);
+
+			retlen = wcstombs(GroupList[*totalGroups],
+				 pTmpLBuf->lgrui0_name, retlen);
+			GroupList[*totalGroups][retlen] = '\0';
+			if (strcmp(GroupList[*totalGroups], "None") == 0)
+				free(GroupList[*totalGroups]);
+			else
+				(*totalGroups)++;
+			pTmpLBuf++;
+		}
+	}
+	/* Free the allocated memory. */
+	if (pBuf != NULL)
+		NetApiBufferFree(pBuf);
+
+
+	/*
+	 * Call the NetUserGetGroups function, specifying level 0.
+	 */
+	nStatus = NetUserGetGroups(NULL,
+			      user,
+			      dwLevel,
+			      (LPBYTE*)&pgrpBuf,
+			      dwPrefMaxLen,
+			      &dwEntriesRead,
+			      &dwTotalEntries);
+	/*
+	 * See if the call succeeds,
+	 */
+	if (nStatus != NERR_Success) {
+		if (nStatus == ERROR_ACCESS_DENIED)
+			return (ISC_R_NOPERM);
+		if (nStatus == ERROR_MORE_DATA)
+			return (ISC_R_NOSPACE);
+		if (nStatus == NERR_UserNotFound)
+			dwEntriesRead = 0;
+	}
+
+	if (pgrpBuf != NULL) {
+		pTmpBuf = pgrpBuf;
+		/*
+		 * Loop through the entries
+		 */
+		 for (i = 0;
+		     (i < dwEntriesRead && *totalGroups < maxgroups); i++) {
+			assert(pTmpBuf != NULL);
+
+			if (pTmpBuf == NULL)
+				break;
+			retlen = wcslen(pTmpBuf->grui0_name);
+			GroupList[*totalGroups] = (char *) malloc(retlen +1);
+			if (GroupList[*totalGroups] == NULL)
+				return (ISC_R_NOMEMORY);
+
+			retlen = wcstombs(GroupList[*totalGroups],
+				 pTmpBuf->grui0_name, retlen);
+			GroupList[*totalGroups][retlen] = '\0';
+			if (strcmp(GroupList[*totalGroups], "None") == 0)
+				free(GroupList[*totalGroups]);
+			else
+				(*totalGroups)++;
+			pTmpBuf++;
+		}
+	}
+	/*
+	 * Free the allocated memory.
+	 */
+	if (pgrpBuf != NULL)
+		NetApiBufferFree(pgrpBuf);
+
+	return (ISC_R_SUCCESS);
+}
diff --git a/src/lib/bind9/win32/ntpaths.c b/src/lib/bind9/win32/ntpaths.c
new file mode 100644
index 0000000..88e77f4
--- /dev/null
+++ b/src/lib/bind9/win32/ntpaths.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2004, 2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: ntpaths.c,v 1.15 2009-07-14 22:54:57 each Exp $ */
+
+/*
+ * This module fetches the required path information that is specific
+ * to NT systems which can have its configuration and system files
+ * almost anywhere. It can be used to override whatever the application
+ * had previously assigned to the pointer. Basic information about the
+ * file locations are stored in the registry.
+ */
+
+#include <config.h>
+#include <isc/bind_registry.h>
+#include <isc/ntpaths.h>
+
+/*
+ * Module Variables
+ */
+
+static char systemDir[MAX_PATH];
+static char namedBase[MAX_PATH];
+static char ns_confFile[MAX_PATH];
+static char lwresd_confFile[MAX_PATH];
+static char lwresd_resolvconfFile[MAX_PATH];
+static char rndc_confFile[MAX_PATH];
+static char ns_defaultpidfile[MAX_PATH];
+static char lwresd_defaultpidfile[MAX_PATH];
+static char local_state_dir[MAX_PATH];
+static char sys_conf_dir[MAX_PATH];
+static char rndc_keyFile[MAX_PATH];
+static char session_keyFile[MAX_PATH];
+
+static DWORD baseLen = MAX_PATH;
+static BOOL Initialized = FALSE;
+
+void
+isc_ntpaths_init() {
+	HKEY hKey;
+	BOOL keyFound = TRUE;
+
+	memset(namedBase, 0, MAX_PATH);
+	if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, BIND_SUBKEY, 0, KEY_READ, &hKey)
+		!= ERROR_SUCCESS)
+		keyFound = FALSE;
+
+	if (keyFound == TRUE) {
+		/* Get the named directory */
+		if (RegQueryValueEx(hKey, "InstallDir", NULL, NULL,
+			(LPBYTE)namedBase, &baseLen) != ERROR_SUCCESS)
+			keyFound = FALSE;
+		RegCloseKey(hKey);
+	}
+
+	GetSystemDirectory(systemDir, MAX_PATH);
+
+	if (keyFound == FALSE)
+		/* Use the System Directory as a default */
+		strcpy(namedBase, systemDir);
+
+	strcpy(ns_confFile, namedBase);
+	strcat(ns_confFile, "\\etc\\named.conf");
+
+	strcpy(lwresd_confFile, namedBase);
+	strcat(lwresd_confFile, "\\etc\\lwresd.conf");
+
+	strcpy(lwresd_resolvconfFile, systemDir);
+	strcat(lwresd_resolvconfFile, "\\Drivers\\etc\\resolv.conf");
+
+	strcpy(rndc_keyFile, namedBase);
+	strcat(rndc_keyFile, "\\etc\\rndc.key");
+
+	strcpy(session_keyFile, namedBase);
+	strcat(session_keyFile, "\\etc\\session.key");
+
+	strcpy(rndc_confFile, namedBase);
+	strcat(rndc_confFile, "\\etc\\rndc.conf");
+	strcpy(ns_defaultpidfile, namedBase);
+	strcat(ns_defaultpidfile, "\\etc\\named.pid");
+
+	strcpy(lwresd_defaultpidfile, namedBase);
+	strcat(lwresd_defaultpidfile, "\\etc\\lwresd.pid");
+
+	strcpy(local_state_dir, namedBase);
+	strcat(local_state_dir, "\\bin");
+
+	strcpy(sys_conf_dir, namedBase);
+	strcat(sys_conf_dir, "\\etc");
+
+	Initialized = TRUE;
+}
+
+char *
+isc_ntpaths_get(int ind) {
+	if (!Initialized)
+		isc_ntpaths_init();
+
+	switch (ind) {
+	case NAMED_CONF_PATH:
+		return (ns_confFile);
+		break;
+	case LWRES_CONF_PATH:
+		return (lwresd_confFile);
+		break;
+	case RESOLV_CONF_PATH:
+		return (lwresd_resolvconfFile);
+		break;
+	case RNDC_CONF_PATH:
+		return (rndc_confFile);
+		break;
+	case NAMED_PID_PATH:
+		return (ns_defaultpidfile);
+		break;
+	case LWRESD_PID_PATH:
+		return (lwresd_defaultpidfile);
+		break;
+	case LOCAL_STATE_DIR:
+		return (local_state_dir);
+		break;
+	case SYS_CONF_DIR:
+		return (sys_conf_dir);
+		break;
+	case RNDC_KEY_PATH:
+		return (rndc_keyFile);
+		break;
+	case SESSION_KEY_PATH:
+		return (session_keyFile);
+		break;
+	default:
+		return (NULL);
+	}
+}
diff --git a/src/lib/bind9/win32/once.c b/src/lib/bind9/win32/once.c
new file mode 100644
index 0000000..db431fb
--- /dev/null
+++ b/src/lib/bind9/win32/once.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2004, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: once.c,v 1.12 2007-06-18 23:47:49 tbox Exp $ */
+
+/* Principal Authors: DCL */
+
+#include <config.h>
+
+#include <windows.h>
+
+#include <isc/once.h>
+#include <isc/assertions.h>
+#include <isc/util.h>
+
+isc_result_t
+isc_once_do(isc_once_t *controller, void(*function)(void)) {
+	REQUIRE(controller != NULL && function != NULL);
+
+	if (controller->status == ISC_ONCE_INIT_NEEDED) {
+
+		if (InterlockedDecrement(&controller->counter) == 0) {
+			if (controller->status == ISC_ONCE_INIT_NEEDED) {
+				function();
+				controller->status = ISC_ONCE_INIT_DONE;
+			}
+		} else {
+			while (controller->status == ISC_ONCE_INIT_NEEDED) {
+				/*
+				 * Sleep(0) indicates that this thread 
+				 * should be suspended to allow other 
+				 * waiting threads to execute.
+				 */
+				Sleep(0);
+			}
+		}
+	}
+
+	return (ISC_R_SUCCESS);
+}
diff --git a/src/lib/bind9/win32/os.c b/src/lib/bind9/win32/os.c
new file mode 100644
index 0000000..725d383
--- /dev/null
+++ b/src/lib/bind9/win32/os.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2004, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2002  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: os.c,v 1.8 2007-06-19 23:47:19 tbox Exp $ */
+
+#include <windows.h>
+
+#include <isc/os.h>
+
+static BOOL bInit = FALSE;
+static SYSTEM_INFO SystemInfo;
+
+static void
+initialize_action(void) {
+	if (bInit)
+		return;
+	
+	GetSystemInfo(&SystemInfo);
+	bInit = TRUE;
+}
+
+unsigned int
+isc_os_ncpus(void) {
+	long ncpus = 1;
+	initialize_action();
+	ncpus = SystemInfo.dwNumberOfProcessors;
+	if (ncpus <= 0)
+		ncpus = 1;
+
+	return ((unsigned int)ncpus);
+}
diff --git a/src/lib/bind9/win32/resource.c b/src/lib/bind9/win32/resource.c
new file mode 100644
index 0000000..be58e9e
--- /dev/null
+++ b/src/lib/bind9/win32/resource.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2004, 2007, 2008  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: resource.c,v 1.10 2008-07-11 23:47:09 tbox Exp $ */
+
+#include <config.h>
+
+#include <stdio.h>
+
+#include <isc/platform.h>
+#include <isc/resource.h>
+#include <isc/result.h>
+#include <isc/util.h>
+
+#include "errno2result.h"
+
+/*
+ * Windows limits the maximum number of open files to 2048
+ */
+
+#define WIN32_MAX_OPEN_FILES	2048
+
+isc_result_t
+isc_resource_setlimit(isc_resource_t resource, isc_resourcevalue_t value) {
+	isc_resourcevalue_t rlim_value;
+	int wresult;
+
+	if (resource != isc_resource_openfiles)
+		return (ISC_R_NOTIMPLEMENTED);
+
+
+	if (value == ISC_RESOURCE_UNLIMITED)
+		rlim_value = WIN32_MAX_OPEN_FILES;
+	else
+		rlim_value = min(value, WIN32_MAX_OPEN_FILES);
+
+	wresult = _setmaxstdio((int) rlim_value);
+
+	if (wresult > 0)
+		return (ISC_R_SUCCESS);
+	else
+		return (isc__errno2result(errno));
+}
+
+isc_result_t
+isc_resource_getlimit(isc_resource_t resource, isc_resourcevalue_t *value) {
+
+	if (resource != isc_resource_openfiles)
+		return (ISC_R_NOTIMPLEMENTED);
+
+	*value = WIN32_MAX_OPEN_FILES;
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_resource_getcurlimit(isc_resource_t resource, isc_resourcevalue_t *value) {
+	return (isc_resource_getlimit(resource, value));
+}
diff --git a/src/lib/bind9/win32/socket.c b/src/lib/bind9/win32/socket.c
new file mode 100644
index 0000000..65985a8
--- /dev/null
+++ b/src/lib/bind9/win32/socket.c
@@ -0,0 +1,3911 @@
+/*
+ * Copyright (C) 2004-2010  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: socket.c,v 1.87 2010-12-09 06:08:05 marka Exp $ */
+
+/* This code uses functions which are only available on Server 2003 and
+ * higher, and Windows XP and higher.
+ *
+ * This code is by nature multithreaded and takes advantage of various
+ * features to pass on information through the completion port for
+ * when I/O is completed.  All sends, receives, accepts, and connects are
+ * completed through the completion port.
+ *
+ * The number of Completion Port Worker threads used is the total number
+ * of CPU's + 1. This increases the likelihood that a Worker Thread is
+ * available for processing a completed request.
+ *
+ * XXXPDM 5 August, 2002
+ */
+
+#define MAKE_EXTERNAL 1
+#include <config.h>
+
+#include <sys/types.h>
+
+#ifndef _WINSOCKAPI_
+#define _WINSOCKAPI_   /* Prevent inclusion of winsock.h in windows.h */
+#endif
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <io.h>
+#include <fcntl.h>
+#include <process.h>
+
+#include <isc/buffer.h>
+#include <isc/bufferlist.h>
+#include <isc/condition.h>
+#include <isc/list.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/msgs.h>
+#include <isc/mutex.h>
+#include <isc/net.h>
+#include <isc/once.h>
+#include <isc/os.h>
+#include <isc/platform.h>
+#include <isc/print.h>
+#include <isc/region.h>
+#include <isc/socket.h>
+#include <isc/stats.h>
+#include <isc/strerror.h>
+#include <isc/syslog.h>
+#include <isc/task.h>
+#include <isc/thread.h>
+#include <isc/util.h>
+#include <isc/win32os.h>
+
+#include <mswsock.h>
+
+#include "errno2result.h"
+
+/*
+ * How in the world can Microsoft exist with APIs like this?
+ * We can't actually call this directly, because it turns out
+ * no library exports this function.  Instead, we need to
+ * issue a runtime call to get the address.
+ */
+LPFN_CONNECTEX ISCConnectEx;
+LPFN_ACCEPTEX ISCAcceptEx;
+LPFN_GETACCEPTEXSOCKADDRS ISCGetAcceptExSockaddrs;
+
+/*
+ * Run expensive internal consistency checks.
+ */
+#ifdef ISC_SOCKET_CONSISTENCY_CHECKS
+#define CONSISTENT(sock) consistent(sock)
+#else
+#define CONSISTENT(sock) do {} while (0)
+#endif
+static void consistent(isc_socket_t *sock);
+
+/*
+ * Define this macro to control the behavior of connection
+ * resets on UDP sockets.  See Microsoft KnowledgeBase Article Q263823
+ * for details.
+ * NOTE: This requires that Windows 2000 systems install Service Pack 2
+ * or later.
+ */
+#ifndef SIO_UDP_CONNRESET
+#define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
+#endif
+
+/*
+ * Some systems define the socket length argument as an int, some as size_t,
+ * some as socklen_t.  This is here so it can be easily changed if needed.
+ */
+#ifndef ISC_SOCKADDR_LEN_T
+#define ISC_SOCKADDR_LEN_T unsigned int
+#endif
+
+/*
+ * Define what the possible "soft" errors can be.  These are non-fatal returns
+ * of various network related functions, like recv() and so on.
+ */
+#define SOFT_ERROR(e)	((e) == WSAEINTR || \
+			 (e) == WSAEWOULDBLOCK || \
+			 (e) == EWOULDBLOCK || \
+			 (e) == EINTR || \
+			 (e) == EAGAIN || \
+			 (e) == 0)
+
+/*
+ * Pending errors are not really errors and should be
+ * kept separate
+ */
+#define PENDING_ERROR(e) ((e) == WSA_IO_PENDING || (e) == 0)
+
+#define DOIO_SUCCESS	  0       /* i/o ok, event sent */
+#define DOIO_SOFT	  1       /* i/o ok, soft error, no event sent */
+#define DOIO_HARD	  2       /* i/o error, event sent */
+#define DOIO_EOF	  3       /* EOF, no event sent */
+#define DOIO_PENDING	  4       /* status when i/o is in process */
+#define DOIO_NEEDMORE	  5       /* IO was processed, but we need more due to minimum */
+
+#define DLVL(x) ISC_LOGCATEGORY_GENERAL, ISC_LOGMODULE_SOCKET, ISC_LOG_DEBUG(x)
+
+/*
+ * DLVL(90)  --  Function entry/exit and other tracing.
+ * DLVL(70)  --  Socket "correctness" -- including returning of events, etc.
+ * DLVL(60)  --  Socket data send/receive
+ * DLVL(50)  --  Event tracing, including receiving/sending completion events.
+ * DLVL(20)  --  Socket creation/destruction.
+ */
+#define TRACE_LEVEL		90
+#define CORRECTNESS_LEVEL	70
+#define IOEVENT_LEVEL		60
+#define EVENT_LEVEL		50
+#define CREATION_LEVEL		20
+
+#define TRACE		DLVL(TRACE_LEVEL)
+#define CORRECTNESS	DLVL(CORRECTNESS_LEVEL)
+#define IOEVENT		DLVL(IOEVENT_LEVEL)
+#define EVENT		DLVL(EVENT_LEVEL)
+#define CREATION	DLVL(CREATION_LEVEL)
+
+typedef isc_event_t intev_t;
+
+/*
+ * Socket State
+ */
+enum {
+  SOCK_INITIALIZED,	/* Socket Initialized */
+  SOCK_OPEN,		/* Socket opened but nothing yet to do */
+  SOCK_DATA,		/* Socket sending or receiving data */
+  SOCK_LISTEN,		/* TCP Socket listening for connects */
+  SOCK_ACCEPT,		/* TCP socket is waiting to accept */
+  SOCK_CONNECT,		/* TCP Socket connecting */
+  SOCK_CLOSED,		/* Socket has been closed */
+};
+
+#define SOCKET_MAGIC		ISC_MAGIC('I', 'O', 'i', 'o')
+#define VALID_SOCKET(t)		ISC_MAGIC_VALID(t, SOCKET_MAGIC)
+
+/*
+ * IPv6 control information.  If the socket is an IPv6 socket we want
+ * to collect the destination address and interface so the client can
+ * set them on outgoing packets.
+ */
+#ifdef ISC_PLATFORM_HAVEIPV6
+#ifndef USE_CMSG
+#define USE_CMSG	1
+#endif
+#endif
+
+/*
+ * We really  don't want to try and use these control messages. Win32
+ * doesn't have this mechanism before XP.
+ */
+#undef USE_CMSG
+
+/*
+ * Message header for recvmsg and sendmsg calls.
+ * Used value-result for recvmsg, value only for sendmsg.
+ */
+struct msghdr {
+	SOCKADDR_STORAGE to_addr;	/* UDP send/recv address */
+	int      to_addr_len;		/* length of the address */
+	WSABUF  *msg_iov;		/* scatter/gather array */
+	u_int   msg_iovlen;             /* # elements in msg_iov */
+	void	*msg_control;           /* ancillary data, see below */
+	u_int   msg_controllen;         /* ancillary data buffer len */
+	int	msg_totallen;		/* total length of this message */
+} msghdr;
+
+/*
+ * The size to raise the receive buffer to.
+ */
+#define RCVBUFSIZE (32*1024)
+
+/*
+ * The number of times a send operation is repeated if the result
+ * is WSAEINTR.
+ */
+#define NRETRIES 10
+
+struct isc_socket {
+	/* Not locked. */
+	unsigned int		magic;
+	isc_socketmgr_t	       *manager;
+	isc_mutex_t		lock;
+	isc_sockettype_t	type;
+
+	/* Pointers to scatter/gather buffers */
+	WSABUF			iov[ISC_SOCKET_MAXSCATTERGATHER];
+
+	/* Locked by socket lock. */
+	ISC_LINK(isc_socket_t)	link;
+	unsigned int		references; /* EXTERNAL references */
+	SOCKET			fd;	/* file handle */
+	int			pf;	/* protocol family */
+	char			name[16];
+	void *			tag;
+
+	/*
+	 * Each recv() call uses this buffer.  It is a per-socket receive
+	 * buffer that allows us to decouple the system recv() from the
+	 * recv_list done events.  This means the items on the recv_list
+	 * can be removed without having to cancel pending system recv()
+	 * calls.  It also allows us to read-ahead in some cases.
+	 */
+	struct {
+		SOCKADDR_STORAGE	from_addr;	   // UDP send/recv address
+		int		from_addr_len;	   // length of the address
+		char		*base;		   // the base of the buffer
+		char		*consume_position; // where to start copying data from next
+		unsigned int	len;		   // the actual size of this buffer
+		unsigned int	remaining;	   // the number of bytes remaining
+	} recvbuf;
+
+	ISC_LIST(isc_socketevent_t)		send_list;
+	ISC_LIST(isc_socketevent_t)		recv_list;
+	ISC_LIST(isc_socket_newconnev_t)	accept_list;
+	isc_socket_connev_t		       *connect_ev;
+
+	isc_sockaddr_t		address;  /* remote address */
+
+	unsigned int		listener : 1,	/* listener socket */
+				connected : 1,
+				pending_connect : 1, /* connect pending */
+				bound : 1;	/* bound to local addr */
+	unsigned int		pending_iocp;	/* Should equal the counters below. Debug. */
+	unsigned int		pending_recv;  /* Number of outstanding recv() calls. */
+	unsigned int		pending_send;  /* Number of outstanding send() calls. */
+	unsigned int		pending_accept; /* Number of outstanding accept() calls. */
+	unsigned int		state; /* Socket state. Debugging and consistency checking. */
+	int			state_lineno;  /* line which last touched state */
+};
+
+#define _set_state(sock, _state) do { (sock)->state = (_state); (sock)->state_lineno = __LINE__; } while (0)
+
+/*
+ * Buffer structure
+ */
+typedef struct buflist buflist_t;
+
+struct buflist {
+	void			*buf;
+	unsigned int		buflen;
+	ISC_LINK(buflist_t)	link;
+};
+
+/*
+ * I/O Completion ports Info structures
+ */
+
+static HANDLE hHeapHandle = NULL;
+typedef struct IoCompletionInfo {
+	OVERLAPPED		overlapped;
+	isc_socketevent_t	*dev;  /* send()/recv() done event */
+	isc_socket_connev_t	*cdev; /* connect() done event */
+	isc_socket_newconnev_t	*adev; /* accept() done event */
+	void			*acceptbuffer;
+	DWORD			received_bytes;
+	int			request_type;
+	struct msghdr		messagehdr;
+	ISC_LIST(buflist_t)	bufferlist;	/*%< list of buffers */
+} IoCompletionInfo;
+
+/*
+ * Define a maximum number of I/O Completion Port worker threads
+ * to handle the load on the Completion Port. The actual number
+ * used is the number of CPU's + 1.
+ */
+#define MAX_IOCPTHREADS 20
+
+#define SOCKET_MANAGER_MAGIC	ISC_MAGIC('I', 'O', 'm', 'g')
+#define VALID_MANAGER(m)	ISC_MAGIC_VALID(m, SOCKET_MANAGER_MAGIC)
+
+struct isc_socketmgr {
+	/* Not locked. */
+	unsigned int			magic;
+	isc_mem_t		       *mctx;
+	isc_mutex_t			lock;
+	isc_stats_t		       *stats;
+
+	/* Locked by manager lock. */
+	ISC_LIST(isc_socket_t)		socklist;
+	isc_boolean_t			bShutdown;
+	isc_condition_t			shutdown_ok;
+	HANDLE				hIoCompletionPort;
+	int				maxIOCPThreads;
+	HANDLE				hIOCPThreads[MAX_IOCPTHREADS];
+	DWORD				dwIOCPThreadIds[MAX_IOCPTHREADS];
+
+	/*
+	 * Debugging.
+	 * Modified by InterlockedIncrement() and InterlockedDecrement()
+	 */
+	LONG				totalSockets;
+	LONG				iocp_total;
+};
+
+enum {
+	SOCKET_RECV,
+	SOCKET_SEND,
+	SOCKET_ACCEPT,
+	SOCKET_CONNECT
+};
+
+/*
+ * send() and recv() iovec counts
+ */
+#define MAXSCATTERGATHER_SEND	(ISC_SOCKET_MAXSCATTERGATHER)
+#define MAXSCATTERGATHER_RECV	(ISC_SOCKET_MAXSCATTERGATHER)
+
+static isc_threadresult_t WINAPI SocketIoThread(LPVOID ThreadContext);
+static void maybe_free_socket(isc_socket_t **, int);
+static void free_socket(isc_socket_t **, int);
+static isc_boolean_t senddone_is_active(isc_socket_t *sock, isc_socketevent_t *dev);
+static isc_boolean_t acceptdone_is_active(isc_socket_t *sock, isc_socket_newconnev_t *dev);
+static isc_boolean_t connectdone_is_active(isc_socket_t *sock, isc_socket_connev_t *dev);
+static void send_recvdone_event(isc_socket_t *sock, isc_socketevent_t **dev);
+static void send_senddone_event(isc_socket_t *sock, isc_socketevent_t **dev);
+static void send_acceptdone_event(isc_socket_t *sock, isc_socket_newconnev_t **adev);
+static void send_connectdone_event(isc_socket_t *sock, isc_socket_connev_t **cdev);
+static void send_recvdone_abort(isc_socket_t *sock, isc_result_t result);
+static void queue_receive_event(isc_socket_t *sock, isc_task_t *task, isc_socketevent_t *dev);
+static void queue_receive_request(isc_socket_t *sock);
+
+/*
+ * This is used to dump the contents of the sock structure
+ * You should make sure that the sock is locked before
+ * dumping it. Since the code uses simple printf() statements
+ * it should only be used interactively.
+ */
+void
+sock_dump(isc_socket_t *sock) {
+	isc_socketevent_t *ldev;
+	isc_socket_newconnev_t *ndev;
+
+#if 0
+	isc_sockaddr_t addr;
+	char socktext[256];
+
+	isc_socket_getpeername(sock, &addr);
+	isc_sockaddr_format(&addr, socktext, sizeof(socktext));
+	printf("Remote Socket: %s\n", socktext);
+	isc_socket_getsockname(sock, &addr);
+	isc_sockaddr_format(&addr, socktext, sizeof(socktext));
+	printf("This Socket: %s\n", socktext);
+#endif
+
+	printf("\n\t\tSock Dump\n");
+	printf("\t\tfd: %u\n", sock->fd);
+	printf("\t\treferences: %d\n", sock->references);
+	printf("\t\tpending_accept: %d\n", sock->pending_accept);
+	printf("\t\tconnecting: %d\n", sock->pending_connect);
+	printf("\t\tconnected: %d\n", sock->connected);
+	printf("\t\tbound: %d\n", sock->bound);
+	printf("\t\tpending_iocp: %d\n", sock->pending_iocp);
+	printf("\t\tsocket type: %d\n", sock->type);
+
+	printf("\n\t\tSock Recv List\n");
+	ldev = ISC_LIST_HEAD(sock->recv_list);
+	while (ldev != NULL) {
+		printf("\t\tdev: %p\n", ldev);
+		ldev = ISC_LIST_NEXT(ldev, ev_link);
+	}
+
+	printf("\n\t\tSock Send List\n");
+	ldev = ISC_LIST_HEAD(sock->send_list);
+	while (ldev != NULL) {
+		printf("\t\tdev: %p\n", ldev);
+		ldev = ISC_LIST_NEXT(ldev, ev_link);
+	}
+
+	printf("\n\t\tSock Accept List\n");
+	ndev = ISC_LIST_HEAD(sock->accept_list);
+	while (ndev != NULL) {
+		printf("\t\tdev: %p\n", ldev);
+		ndev = ISC_LIST_NEXT(ndev, ev_link);
+	}
+}
+
+static void
+socket_log(int lineno, isc_socket_t *sock, isc_sockaddr_t *address,
+	   isc_logcategory_t *category, isc_logmodule_t *module, int level,
+	   isc_msgcat_t *msgcat, int msgset, int message,
+	   const char *fmt, ...) ISC_FORMAT_PRINTF(9, 10);
+
+/*  This function will add an entry to the I/O completion port
+ *  that will signal the I/O thread to exit (gracefully)
+ */
+static void
+signal_iocompletionport_exit(isc_socketmgr_t *manager) {
+	int i;
+	int errval;
+	char strbuf[ISC_STRERRORSIZE];
+
+	REQUIRE(VALID_MANAGER(manager));
+	for (i = 0; i < manager->maxIOCPThreads; i++) {
+		if (!PostQueuedCompletionStatus(manager->hIoCompletionPort,
+						0, 0, 0)) {
+			errval = GetLastError();
+			isc__strerror(errval, strbuf, sizeof(strbuf));
+			FATAL_ERROR(__FILE__, __LINE__,
+				isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
+				ISC_MSG_FAILED,
+				"Can't request service thread to exit: %s"),
+				strbuf);
+		}
+	}
+}
+
+/*
+ * Create the worker threads for the I/O Completion Port
+ */
+void
+iocompletionport_createthreads(int total_threads, isc_socketmgr_t *manager) {
+	int errval;
+	char strbuf[ISC_STRERRORSIZE];
+	int i;
+
+	INSIST(total_threads > 0);
+	REQUIRE(VALID_MANAGER(manager));
+	/*
+	 * We need at least one
+	 */
+	for (i = 0; i < total_threads; i++) {
+		manager->hIOCPThreads[i] = CreateThread(NULL, 0, SocketIoThread,
+						manager, 0,
+						&manager->dwIOCPThreadIds[i]);
+		if (manager->hIOCPThreads[i] == NULL) {
+			errval = GetLastError();
+			isc__strerror(errval, strbuf, sizeof(strbuf));
+			FATAL_ERROR(__FILE__, __LINE__,
+				isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
+				ISC_MSG_FAILED,
+				"Can't create IOCP thread: %s"),
+				strbuf);
+			exit(1);
+		}
+	}
+}
+
+/*
+ *  Create/initialise the I/O completion port
+ */
+void
+iocompletionport_init(isc_socketmgr_t *manager) {
+	int errval;
+	char strbuf[ISC_STRERRORSIZE];
+
+	REQUIRE(VALID_MANAGER(manager));
+	/*
+	 * Create a private heap to handle the socket overlapped structure
+	 * The minimum number of structures is 10, there is no maximum
+	 */
+	hHeapHandle = HeapCreate(0, 10 * sizeof(IoCompletionInfo), 0);
+	if (hHeapHandle == NULL) {
+		errval = GetLastError();
+		isc__strerror(errval, strbuf, sizeof(strbuf));
+		FATAL_ERROR(__FILE__, __LINE__,
+			    isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
+					   ISC_MSG_FAILED,
+					   "HeapCreate() failed during "
+					   "initialization: %s"),
+			    strbuf);
+		exit(1);
+	}
+
+	manager->maxIOCPThreads = min(isc_os_ncpus() + 1, MAX_IOCPTHREADS);
+
+	/* Now Create the Completion Port */
+	manager->hIoCompletionPort = CreateIoCompletionPort(
+			INVALID_HANDLE_VALUE, NULL,
+			0, manager->maxIOCPThreads);
+	if (manager->hIoCompletionPort == NULL) {
+		errval = GetLastError();
+		isc__strerror(errval, strbuf, sizeof(strbuf));
+		FATAL_ERROR(__FILE__, __LINE__,
+				isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
+				ISC_MSG_FAILED,
+				"CreateIoCompletionPort() failed "
+				"during initialization: %s"),
+				strbuf);
+		exit(1);
+	}
+
+	/*
+	 * Worker threads for servicing the I/O
+	 */
+	iocompletionport_createthreads(manager->maxIOCPThreads, manager);
+}
+
+/*
+ * Associate a socket with an IO Completion Port.  This allows us to queue events for it
+ * and have our worker pool of threads process them.
+ */
+void
+iocompletionport_update(isc_socket_t *sock) {
+	HANDLE hiocp;
+	char strbuf[ISC_STRERRORSIZE];
+
+	REQUIRE(VALID_SOCKET(sock));
+
+	hiocp = CreateIoCompletionPort((HANDLE)sock->fd,
+		sock->manager->hIoCompletionPort, (ULONG_PTR)sock, 0);
+
+	if (hiocp == NULL) {
+		DWORD errval = GetLastError();
+		isc__strerror(errval, strbuf, sizeof(strbuf));
+		isc_log_iwrite(isc_lctx,
+				ISC_LOGCATEGORY_GENERAL,
+				ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
+				isc_msgcat, ISC_MSGSET_SOCKET,
+				ISC_MSG_TOOMANYHANDLES,
+				"iocompletionport_update: failed to open"
+				" io completion port: %s",
+				strbuf);
+
+		/* XXXMLG temporary hack to make failures detected.
+		 * This function should return errors to the caller, not
+		 * exit here.
+		 */
+		FATAL_ERROR(__FILE__, __LINE__,
+				isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
+				ISC_MSG_FAILED,
+				"CreateIoCompletionPort() failed "
+				"during initialization: %s"),
+				strbuf);
+		exit(1);
+	}
+
+	InterlockedIncrement(&sock->manager->iocp_total);
+}
+
+/*
+ * Routine to cleanup and then close the socket.
+ * Only close the socket here if it is NOT associated
+ * with an event, otherwise the WSAWaitForMultipleEvents
+ * may fail due to the fact that the Wait should not
+ * be running while closing an event or a socket.
+ * The socket is locked before calling this function
+ */
+void
+socket_close(isc_socket_t *sock) {
+
+	REQUIRE(sock != NULL);
+
+	if (sock->fd != INVALID_SOCKET) {
+		closesocket(sock->fd);
+		sock->fd = INVALID_SOCKET;
+		_set_state(sock, SOCK_CLOSED);
+		InterlockedDecrement(&sock->manager->totalSockets);
+	}
+}
+
+static isc_once_t initialise_once = ISC_ONCE_INIT;
+static isc_boolean_t initialised = ISC_FALSE;
+
+static void
+initialise(void) {
+	WORD wVersionRequested;
+	WSADATA wsaData;
+	int err;
+	SOCKET sock;
+	GUID GUIDConnectEx = WSAID_CONNECTEX;
+	GUID GUIDAcceptEx = WSAID_ACCEPTEX;
+	GUID GUIDGetAcceptExSockaddrs = WSAID_GETACCEPTEXSOCKADDRS;
+	DWORD dwBytes;
+
+	/* Need Winsock 2.2 or better */
+	wVersionRequested = MAKEWORD(2, 2);
+
+	err = WSAStartup(wVersionRequested, &wsaData);
+	if (err != 0) {
+		char strbuf[ISC_STRERRORSIZE];
+		isc__strerror(err, strbuf, sizeof(strbuf));
+		FATAL_ERROR(__FILE__, __LINE__, "WSAStartup() %s: %s",
+			    isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+					   ISC_MSG_FAILED, "failed"),
+			    strbuf);
+		exit(1);
+	}
+	/*
+	 * The following APIs do not exist as functions in a library, but we must
+	 * ask winsock for them.  They are "extensions" -- but why they cannot be
+	 * actual functions is beyond me.  So, ask winsock for the pointers to the
+	 * functions we need.
+	 */
+	sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+	INSIST(sock != INVALID_SOCKET);
+	err = WSAIoctl(sock,  SIO_GET_EXTENSION_FUNCTION_POINTER,
+		 &GUIDConnectEx, sizeof(GUIDConnectEx),
+		 &ISCConnectEx, sizeof(ISCConnectEx),
+		 &dwBytes, NULL, NULL);
+	INSIST(err == 0);
+
+	err = WSAIoctl(sock,  SIO_GET_EXTENSION_FUNCTION_POINTER,
+		 &GUIDAcceptEx, sizeof(GUIDAcceptEx),
+		 &ISCAcceptEx, sizeof(ISCAcceptEx),
+		 &dwBytes, NULL, NULL);
+	INSIST(err == 0);
+
+	err = WSAIoctl(sock,  SIO_GET_EXTENSION_FUNCTION_POINTER,
+		 &GUIDGetAcceptExSockaddrs, sizeof(GUIDGetAcceptExSockaddrs),
+		 &ISCGetAcceptExSockaddrs, sizeof(ISCGetAcceptExSockaddrs),
+		 &dwBytes, NULL, NULL);
+	INSIST(err == 0);
+
+	closesocket(sock);
+
+	initialised = ISC_TRUE;
+}
+
+/*
+ * Initialize socket services
+ */
+void
+InitSockets(void) {
+	RUNTIME_CHECK(isc_once_do(&initialise_once,
+				  initialise) == ISC_R_SUCCESS);
+	if (!initialised)
+		exit(1);
+}
+
+int
+internal_sendmsg(isc_socket_t *sock, IoCompletionInfo *lpo,
+		 struct msghdr *messagehdr, int flags, int *Error)
+{
+	int Result;
+	DWORD BytesSent;
+	DWORD Flags = flags;
+	int total_sent;
+
+	*Error = 0;
+	Result = WSASendTo(sock->fd, messagehdr->msg_iov,
+			   messagehdr->msg_iovlen, &BytesSent,
+			   Flags, (SOCKADDR *)&messagehdr->to_addr,
+			   messagehdr->to_addr_len, (LPWSAOVERLAPPED)lpo,
+			   NULL);
+
+	total_sent = (int)BytesSent;
+
+	/* Check for errors.*/
+	if (Result == SOCKET_ERROR) {
+		*Error = WSAGetLastError();
+
+		switch (*Error) {
+		case WSA_IO_INCOMPLETE:
+		case WSA_WAIT_IO_COMPLETION:
+		case WSA_IO_PENDING:
+		case NO_ERROR:		/* Strange, but okay */
+			sock->pending_iocp++;
+			sock->pending_send++;
+			break;
+
+		default:
+			return (-1);
+			break;
+		}
+	} else {
+		sock->pending_iocp++;
+		sock->pending_send++;
+	}
+
+	if (lpo != NULL)
+		return (0);
+	else
+		return (total_sent);
+}
+
+static void
+queue_receive_request(isc_socket_t *sock) {
+	DWORD Flags = 0;
+	DWORD NumBytes = 0;
+	int total_bytes = 0;
+	int Result;
+	int Error;
+	int need_retry;
+	WSABUF iov[1];
+	IoCompletionInfo *lpo = NULL;
+	isc_result_t isc_result;
+
+ retry:
+	need_retry = ISC_FALSE;
+
+	/*
+	 * If we already have a receive pending, do nothing.
+	 */
+	if (sock->pending_recv > 0) {
+		if (lpo != NULL)
+			HeapFree(hHeapHandle, 0, lpo);
+		return;
+	}
+
+	/*
+	 * If no one is waiting, do nothing.
+	 */
+	if (ISC_LIST_EMPTY(sock->recv_list)) {
+		if (lpo != NULL)
+			HeapFree(hHeapHandle, 0, lpo);
+		return;
+	}
+
+	INSIST(sock->recvbuf.remaining == 0);
+	INSIST(sock->fd != INVALID_SOCKET);
+
+	iov[0].len = sock->recvbuf.len;
+	iov[0].buf = sock->recvbuf.base;
+
+	if (lpo == NULL) {
+		lpo = (IoCompletionInfo *)HeapAlloc(hHeapHandle,
+						    HEAP_ZERO_MEMORY,
+						    sizeof(IoCompletionInfo));
+		RUNTIME_CHECK(lpo != NULL);
+	} else
+		ZeroMemory(lpo, sizeof(IoCompletionInfo));
+	lpo->request_type = SOCKET_RECV;
+
+	sock->recvbuf.from_addr_len = sizeof(sock->recvbuf.from_addr);
+
+	Error = 0;
+	Result = WSARecvFrom((SOCKET)sock->fd, iov, 1,
+			     &NumBytes, &Flags,
+			     (SOCKADDR *)&sock->recvbuf.from_addr,
+			     &sock->recvbuf.from_addr_len,
+			     (LPWSAOVERLAPPED)lpo, NULL);
+
+	/* Check for errors. */
+	if (Result == SOCKET_ERROR) {
+		Error = WSAGetLastError();
+
+		switch (Error) {
+		case WSA_IO_PENDING:
+			sock->pending_iocp++;
+			sock->pending_recv++;
+			break;
+
+		/* direct error: no completion event */
+		case ERROR_HOST_UNREACHABLE:
+		case WSAENETRESET:
+		case WSAECONNRESET:
+			if (!sock->connected) {
+				/* soft error */
+				need_retry = ISC_TRUE;
+				break;
+			}
+			/* FALLTHROUGH */
+
+		default:
+			isc_result = isc__errno2result(Error);
+			if (isc_result == ISC_R_UNEXPECTED)
+				UNEXPECTED_ERROR(__FILE__, __LINE__,
+					"WSARecvFrom: Windows error code: %d, isc result %d",
+					Error, isc_result);
+			send_recvdone_abort(sock, isc_result);
+			HeapFree(hHeapHandle, 0, lpo);
+			lpo = NULL;
+			break;
+		}
+	} else {
+		/*
+		 * The recv() finished immediately, but we will still get
+		 * a completion event.  Rather than duplicate code, let
+		 * that thread handle sending the data along its way.
+		 */
+		sock->pending_iocp++;
+		sock->pending_recv++;
+	}
+
+	socket_log(__LINE__, sock, NULL, IOEVENT,
+		   isc_msgcat, ISC_MSGSET_SOCKET,
+		   ISC_MSG_DOIORECV,
+		   "queue_io_request: fd %d result %d error %d",
+		   sock->fd, Result, Error);
+
+	CONSISTENT(sock);
+
+	if (need_retry)
+		goto retry;
+}
+
+static void
+manager_log(isc_socketmgr_t *sockmgr, isc_logcategory_t *category,
+	    isc_logmodule_t *module, int level, const char *fmt, ...)
+{
+	char msgbuf[2048];
+	va_list ap;
+
+	if (!isc_log_wouldlog(isc_lctx, level))
+		return;
+
+	va_start(ap, fmt);
+	vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
+	va_end(ap);
+
+	isc_log_write(isc_lctx, category, module, level,
+		      "sockmgr %p: %s", sockmgr, msgbuf);
+}
+
+static void
+socket_log(int lineno, isc_socket_t *sock, isc_sockaddr_t *address,
+	   isc_logcategory_t *category, isc_logmodule_t *module, int level,
+	   isc_msgcat_t *msgcat, int msgset, int message,
+	   const char *fmt, ...)
+{
+	char msgbuf[2048];
+	char peerbuf[256];
+	va_list ap;
+
+
+	if (!isc_log_wouldlog(isc_lctx, level))
+		return;
+
+	va_start(ap, fmt);
+	vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
+	va_end(ap);
+
+	if (address == NULL) {
+		isc_log_iwrite(isc_lctx, category, module, level,
+			       msgcat, msgset, message,
+			       "socket %p line %d: %s", sock, lineno, msgbuf);
+	} else {
+		isc_sockaddr_format(address, peerbuf, sizeof(peerbuf));
+		isc_log_iwrite(isc_lctx, category, module, level,
+			       msgcat, msgset, message,
+				   "socket %p line %d peer %s: %s", sock, lineno,
+				   peerbuf, msgbuf);
+	}
+
+}
+
+/*
+ * Make an fd SOCKET non-blocking.
+ */
+static isc_result_t
+make_nonblock(SOCKET fd) {
+	int ret;
+	unsigned long flags = 1;
+	char strbuf[ISC_STRERRORSIZE];
+
+	/* Set the socket to non-blocking */
+	ret = ioctlsocket(fd, FIONBIO, &flags);
+
+	if (ret == -1) {
+		isc__strerror(errno, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "ioctlsocket(%d, FIOBIO, %d): %s",
+				 fd, flags, strbuf);
+
+		return (ISC_R_UNEXPECTED);
+	}
+
+	return (ISC_R_SUCCESS);
+}
+
+/*
+ * Windows 2000 systems incorrectly cause UDP sockets using WSARecvFrom
+ * to not work correctly, returning a WSACONNRESET error when a WSASendTo
+ * fails with an "ICMP port unreachable" response and preventing the
+ * socket from using the WSARecvFrom in subsequent operations.
+ * The function below fixes this, but requires that Windows 2000
+ * Service Pack 2 or later be installed on the system.  NT 4.0
+ * systems are not affected by this and work correctly.
+ * See Microsoft Knowledge Base Article Q263823 for details of this.
+ */
+isc_result_t
+connection_reset_fix(SOCKET fd) {
+	DWORD dwBytesReturned = 0;
+	BOOL  bNewBehavior = FALSE;
+	DWORD status;
+
+	if (isc_win32os_majorversion() < 5)
+		return (ISC_R_SUCCESS); /*  NT 4.0 has no problem */
+
+	/* disable bad behavior using IOCTL: SIO_UDP_CONNRESET */
+	status = WSAIoctl(fd, SIO_UDP_CONNRESET, &bNewBehavior,
+			  sizeof(bNewBehavior), NULL, 0,
+			  &dwBytesReturned, NULL, NULL);
+	if (status != SOCKET_ERROR)
+		return (ISC_R_SUCCESS);
+	else {
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "WSAIoctl(SIO_UDP_CONNRESET, oldBehaviour) %s",
+				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+						ISC_MSG_FAILED, "failed"));
+		return (ISC_R_UNEXPECTED);
+	}
+}
+
+/*
+ * Construct an iov array and attach it to the msghdr passed in.  This is
+ * the SEND constructor, which will use the used region of the buffer
+ * (if using a buffer list) or will use the internal region (if a single
+ * buffer I/O is requested).
+ *
+ * Nothing can be NULL, and the done event must list at least one buffer
+ * on the buffer linked list for this function to be meaningful.
+ */
+static void
+build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev,
+		  struct msghdr *msg, char *cmsg, WSABUF *iov,
+		  IoCompletionInfo  *lpo)
+{
+	unsigned int iovcount;
+	isc_buffer_t *buffer;
+	buflist_t  *cpbuffer;
+	isc_region_t used;
+	size_t write_count;
+	size_t skip_count;
+
+	memset(msg, 0, sizeof(*msg));
+
+	memcpy(&msg->to_addr, &dev->address.type, dev->address.length);
+	msg->to_addr_len = dev->address.length;
+
+	buffer = ISC_LIST_HEAD(dev->bufferlist);
+	write_count = 0;
+	iovcount = 0;
+
+	/*
+	 * Single buffer I/O?  Skip what we've done so far in this region.
+	 */
+	if (buffer == NULL) {
+		write_count = dev->region.length - dev->n;
+		cpbuffer = HeapAlloc(hHeapHandle, HEAP_ZERO_MEMORY, sizeof(buflist_t));
+		RUNTIME_CHECK(cpbuffer != NULL);
+		cpbuffer->buf = HeapAlloc(hHeapHandle, HEAP_ZERO_MEMORY, write_count);
+		RUNTIME_CHECK(cpbuffer->buf != NULL);
+
+		socket_log(__LINE__, sock, NULL, TRACE,
+		   isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTLOCK,
+		   "alloc_buffer %p %d %p %d", cpbuffer, sizeof(buflist_t),
+		   cpbuffer->buf, write_count);
+
+		memcpy(cpbuffer->buf,(dev->region.base + dev->n), write_count);
+		cpbuffer->buflen = write_count;
+		ISC_LIST_ENQUEUE(lpo->bufferlist, cpbuffer, link);
+		iov[0].buf = cpbuffer->buf;
+		iov[0].len = write_count;
+		iovcount = 1;
+
+		goto config;
+	}
+
+	/*
+	 * Multibuffer I/O.
+	 * Skip the data in the buffer list that we have already written.
+	 */
+	skip_count = dev->n;
+	while (buffer != NULL) {
+		REQUIRE(ISC_BUFFER_VALID(buffer));
+		if (skip_count < isc_buffer_usedlength(buffer))
+			break;
+		skip_count -= isc_buffer_usedlength(buffer);
+		buffer = ISC_LIST_NEXT(buffer, link);
+	}
+
+	while (buffer != NULL) {
+		INSIST(iovcount < MAXSCATTERGATHER_SEND);
+
+		isc_buffer_usedregion(buffer, &used);
+
+		if (used.length > 0) {
+			int uselen = used.length - skip_count;
+			cpbuffer = HeapAlloc(hHeapHandle, HEAP_ZERO_MEMORY, sizeof(buflist_t));
+			RUNTIME_CHECK(cpbuffer != NULL);
+			cpbuffer->buf = HeapAlloc(hHeapHandle, HEAP_ZERO_MEMORY, uselen);
+			RUNTIME_CHECK(cpbuffer->buf != NULL);
+
+			socket_log(__LINE__, sock, NULL, TRACE,
+			   isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTLOCK,
+			   "alloc_buffer %p %d %p %d", cpbuffer, sizeof(buflist_t),
+			   cpbuffer->buf, write_count);
+
+			memcpy(cpbuffer->buf,(used.base + skip_count), uselen);
+			cpbuffer->buflen = uselen;
+			iov[iovcount].buf = cpbuffer->buf;
+			iov[iovcount].len = used.length - skip_count;
+			write_count += uselen;
+			skip_count = 0;
+			iovcount++;
+		}
+		buffer = ISC_LIST_NEXT(buffer, link);
+	}
+
+	INSIST(skip_count == 0);
+
+ config:
+	msg->msg_iov = iov;
+	msg->msg_iovlen = iovcount;
+	msg->msg_totallen = write_count;
+}
+
+static void
+set_dev_address(isc_sockaddr_t *address, isc_socket_t *sock,
+		isc_socketevent_t *dev)
+{
+	if (sock->type == isc_sockettype_udp) {
+		if (address != NULL)
+			dev->address = *address;
+		else
+			dev->address = sock->address;
+	} else if (sock->type == isc_sockettype_tcp) {
+		INSIST(address == NULL);
+		dev->address = sock->address;
+	}
+}
+
+static void
+destroy_socketevent(isc_event_t *event) {
+	isc_socketevent_t *ev = (isc_socketevent_t *)event;
+
+	INSIST(ISC_LIST_EMPTY(ev->bufferlist));
+
+	(ev->destroy)(event);
+}
+
+static isc_socketevent_t *
+allocate_socketevent(isc_socket_t *sock, isc_eventtype_t eventtype,
+		     isc_taskaction_t action, const void *arg)
+{
+	isc_socketevent_t *ev;
+
+	ev = (isc_socketevent_t *)isc_event_allocate(sock->manager->mctx,
+						     sock, eventtype,
+						     action, arg,
+						     sizeof(*ev));
+	if (ev == NULL)
+		return (NULL);
+
+	ev->result = ISC_R_IOERROR; // XXXMLG temporary change to detect failure to set
+	ISC_LINK_INIT(ev, ev_link);
+	ISC_LIST_INIT(ev->bufferlist);
+	ev->region.base = NULL;
+	ev->n = 0;
+	ev->offset = 0;
+	ev->attributes = 0;
+	ev->destroy = ev->ev_destroy;
+	ev->ev_destroy = destroy_socketevent;
+
+	return (ev);
+}
+
+#if defined(ISC_SOCKET_DEBUG)
+static void
+dump_msg(struct msghdr *msg, isc_socket_t *sock) {
+	unsigned int i;
+
+	printf("MSGHDR %p, Socket #: %u\n", msg, sock->fd);
+	printf("\tname %p, namelen %d\n", msg->msg_name, msg->msg_namelen);
+	printf("\tiov %p, iovlen %d\n", msg->msg_iov, msg->msg_iovlen);
+	for (i = 0; i < (unsigned int)msg->msg_iovlen; i++)
+		printf("\t\t%d\tbase %p, len %d\n", i,
+		       msg->msg_iov[i].buf,
+		       msg->msg_iov[i].len);
+}
+#endif
+
+/*
+ * map the error code
+ */
+int
+map_socket_error(isc_socket_t *sock, int windows_errno, int *isc_errno,
+		 char *errorstring, size_t bufsize) {
+
+	int doreturn;
+	switch (windows_errno) {
+	case WSAECONNREFUSED:
+		*isc_errno = ISC_R_CONNREFUSED;
+		if (sock->connected)
+			doreturn = DOIO_HARD;
+		else
+			doreturn = DOIO_SOFT;
+		break;
+	case WSAENETUNREACH:
+	case ERROR_NETWORK_UNREACHABLE:
+		*isc_errno = ISC_R_NETUNREACH;
+		if (sock->connected)
+			doreturn = DOIO_HARD;
+		else
+			doreturn = DOIO_SOFT;
+		break;
+	case ERROR_PORT_UNREACHABLE:
+	case ERROR_HOST_UNREACHABLE:
+	case WSAEHOSTUNREACH:
+		*isc_errno = ISC_R_HOSTUNREACH;
+		if (sock->connected)
+			doreturn = DOIO_HARD;
+		else
+			doreturn = DOIO_SOFT;
+		break;
+	case WSAENETDOWN:
+		*isc_errno = ISC_R_NETDOWN;
+		if (sock->connected)
+			doreturn = DOIO_HARD;
+		else
+			doreturn = DOIO_SOFT;
+		break;
+	case WSAEHOSTDOWN:
+		*isc_errno = ISC_R_HOSTDOWN;
+		if (sock->connected)
+			doreturn = DOIO_HARD;
+		else
+			doreturn = DOIO_SOFT;
+		break;
+	case WSAEACCES:
+		*isc_errno = ISC_R_NOPERM;
+		if (sock->connected)
+			doreturn = DOIO_HARD;
+		else
+			doreturn = DOIO_SOFT;
+		break;
+	case WSAECONNRESET:
+	case WSAENETRESET:
+	case WSAECONNABORTED:
+	case WSAEDISCON:
+		*isc_errno = ISC_R_CONNECTIONRESET;
+		if (sock->connected)
+			doreturn = DOIO_HARD;
+		else
+			doreturn = DOIO_SOFT;
+		break;
+	case WSAENOTCONN:
+		*isc_errno = ISC_R_NOTCONNECTED;
+		if (sock->connected)
+			doreturn = DOIO_HARD;
+		else
+			doreturn = DOIO_SOFT;
+		break;
+	case ERROR_OPERATION_ABORTED:
+	case ERROR_CONNECTION_ABORTED:
+	case ERROR_REQUEST_ABORTED:
+		*isc_errno = ISC_R_CONNECTIONRESET;
+		doreturn = DOIO_HARD;
+		break;
+	case WSAENOBUFS:
+		*isc_errno = ISC_R_NORESOURCES;
+		doreturn = DOIO_HARD;
+		break;
+	case WSAEAFNOSUPPORT:
+		*isc_errno = ISC_R_FAMILYNOSUPPORT;
+		doreturn = DOIO_HARD;
+		break;
+	case WSAEADDRNOTAVAIL:
+		*isc_errno = ISC_R_ADDRNOTAVAIL;
+		doreturn = DOIO_HARD;
+		break;
+	case WSAEDESTADDRREQ:
+		*isc_errno = ISC_R_BADADDRESSFORM;
+		doreturn = DOIO_HARD;
+		break;
+	case ERROR_NETNAME_DELETED:
+		*isc_errno = ISC_R_NETDOWN;
+		doreturn = DOIO_HARD;
+		break;
+	default:
+		*isc_errno = ISC_R_IOERROR;
+		doreturn = DOIO_HARD;
+		break;
+	}
+	if (doreturn == DOIO_HARD) {
+		isc__strerror(windows_errno, errorstring, bufsize);
+	}
+	return (doreturn);
+}
+
+static void
+fill_recv(isc_socket_t *sock, isc_socketevent_t *dev) {
+	isc_region_t r;
+	int copylen;
+	isc_buffer_t *buffer;
+
+	INSIST(dev->n < dev->minimum);
+	INSIST(sock->recvbuf.remaining > 0);
+	INSIST(sock->pending_recv == 0);
+
+	if (sock->type == isc_sockettype_udp) {
+		dev->address.length = sock->recvbuf.from_addr_len;
+		memcpy(&dev->address.type, &sock->recvbuf.from_addr,
+		    sock->recvbuf.from_addr_len);
+		if (isc_sockaddr_getport(&dev->address) == 0) {
+			if (isc_log_wouldlog(isc_lctx, IOEVENT_LEVEL)) {
+				socket_log(__LINE__, sock, &dev->address, IOEVENT,
+					   isc_msgcat, ISC_MSGSET_SOCKET,
+					   ISC_MSG_ZEROPORT,
+					   "dropping source port zero packet");
+			}
+			sock->recvbuf.remaining = 0;
+			return;
+		}
+	} else if (sock->type == isc_sockettype_tcp) {
+		dev->address = sock->address;
+	}
+
+	/*
+	 * Run through the list of buffers we were given, and find the
+	 * first one with space.  Once it is found, loop through, filling
+	 * the buffers as much as possible.
+	 */
+	buffer = ISC_LIST_HEAD(dev->bufferlist);
+	if (buffer != NULL) { // Multi-buffer receive
+		while (buffer != NULL && sock->recvbuf.remaining > 0) {
+			REQUIRE(ISC_BUFFER_VALID(buffer));
+			if (isc_buffer_availablelength(buffer) > 0) {
+				isc_buffer_availableregion(buffer, &r);
+				copylen = min(r.length, sock->recvbuf.remaining);
+				memcpy(r.base, sock->recvbuf.consume_position, copylen);
+				sock->recvbuf.consume_position += copylen;
+				sock->recvbuf.remaining -= copylen;
+				isc_buffer_add(buffer, copylen);
+				dev->n += copylen;
+			}
+			buffer = ISC_LIST_NEXT(buffer, link);
+		}
+	} else { // Single-buffer receive
+		copylen = min(dev->region.length - dev->n, sock->recvbuf.remaining);
+		memcpy(dev->region.base + dev->n, sock->recvbuf.consume_position, copylen);
+		sock->recvbuf.consume_position += copylen;
+		sock->recvbuf.remaining -= copylen;
+		dev->n += copylen;
+	}
+
+	/*
+	 * UDP receives are all-consuming.  That is, if we have 4k worth of
+	 * data in our receive buffer, and the caller only gave us
+	 * 1k of space, we will toss the remaining 3k of data.  TCP
+	 * will keep the extra data around and use it for later requests.
+	 */
+	if (sock->type == isc_sockettype_udp)
+		sock->recvbuf.remaining = 0;
+}
+
+/*
+ * Copy out as much data from the internal buffer to done events.
+ * As each done event is filled, send it along its way.
+ */
+static void
+completeio_recv(isc_socket_t *sock)
+{
+	isc_socketevent_t *dev;
+
+	/*
+	 * If we are in the process of filling our buffer, we cannot
+	 * touch it yet, so don't.
+	 */
+	if (sock->pending_recv > 0)
+		return;
+
+	while (sock->recvbuf.remaining > 0 && !ISC_LIST_EMPTY(sock->recv_list)) {
+		dev = ISC_LIST_HEAD(sock->recv_list);
+
+		/*
+		 * See if we have sufficient data in our receive buffer
+		 * to handle this.  If we do, copy out the data.
+		 */
+		fill_recv(sock, dev);
+
+		/*
+		 * Did we satisfy it?
+		 */
+		if (dev->n >= dev->minimum) {
+			dev->result = ISC_R_SUCCESS;
+			send_recvdone_event(sock, &dev);
+		}
+	}
+}
+
+/*
+ * Returns:
+ *	DOIO_SUCCESS	The operation succeeded.  dev->result contains
+ *			ISC_R_SUCCESS.
+ *
+ *	DOIO_HARD	A hard or unexpected I/O error was encountered.
+ *			dev->result contains the appropriate error.
+ *
+ *	DOIO_SOFT	A soft I/O error was encountered.  No senddone
+ *			event was sent.  The operation should be retried.
+ *
+ *	No other return values are possible.
+ */
+static int
+completeio_send(isc_socket_t *sock, isc_socketevent_t *dev,
+		struct msghdr *messagehdr, int cc, int send_errno)
+{
+	char addrbuf[ISC_SOCKADDR_FORMATSIZE];
+	char strbuf[ISC_STRERRORSIZE];
+
+	if (send_errno != 0) {
+		if (SOFT_ERROR(send_errno))
+			return (DOIO_SOFT);
+
+		return (map_socket_error(sock, send_errno, &dev->result,
+			strbuf, sizeof(strbuf)));
+
+		/*
+		 * The other error types depend on whether or not the
+		 * socket is UDP or TCP.  If it is UDP, some errors
+		 * that we expect to be fatal under TCP are merely
+		 * annoying, and are really soft errors.
+		 *
+		 * However, these soft errors are still returned as
+		 * a status.
+		 */
+		isc_sockaddr_format(&dev->address, addrbuf, sizeof(addrbuf));
+		isc__strerror(send_errno, strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__, "completeio_send: %s: %s",
+				 addrbuf, strbuf);
+		dev->result = isc__errno2result(send_errno);
+		return (DOIO_HARD);
+	}
+
+	/*
+	 * If we write less than we expected, update counters, poke.
+	 */
+	dev->n += cc;
+	if (cc != messagehdr->msg_totallen)
+		return (DOIO_SOFT);
+
+	/*
+	 * Exactly what we wanted to write.  We're done with this
+	 * entry.  Post its completion event.
+	 */
+	dev->result = ISC_R_SUCCESS;
+	return (DOIO_SUCCESS);
+}
+
+static int
+startio_send(isc_socket_t *sock, isc_socketevent_t *dev, int *nbytes,
+	     int *send_errno)
+{
+	char *cmsg = NULL;
+	char strbuf[ISC_STRERRORSIZE];
+	IoCompletionInfo *lpo;
+	int status;
+	struct msghdr *msghdr;
+
+	lpo = (IoCompletionInfo *)HeapAlloc(hHeapHandle,
+					    HEAP_ZERO_MEMORY,
+					    sizeof(IoCompletionInfo));
+	RUNTIME_CHECK(lpo != NULL);
+	lpo->request_type = SOCKET_SEND;
+	lpo->dev = dev;
+	msghdr = &lpo->messagehdr;
+	memset(msghdr, 0, sizeof(struct msghdr));
+	ISC_LIST_INIT(lpo->bufferlist);
+
+	build_msghdr_send(sock, dev, msghdr, cmsg, sock->iov, lpo);
+
+	*nbytes = internal_sendmsg(sock, lpo, msghdr, 0, send_errno);
+
+	if (*nbytes < 0) {
+		/*
+		 * I/O has been initiated
+		 * completion will be through the completion port
+		 */
+		if (PENDING_ERROR(*send_errno)) {
+			status = DOIO_PENDING;
+			goto done;
+		}
+
+		if (SOFT_ERROR(*send_errno)) {
+			status = DOIO_SOFT;
+			goto done;
+		}
+
+		/*
+		 * If we got this far then something is wrong
+		 */
+		if (isc_log_wouldlog(isc_lctx, IOEVENT_LEVEL)) {
+			isc__strerror(*send_errno, strbuf, sizeof(strbuf));
+			socket_log(__LINE__, sock, NULL, IOEVENT,
+				   isc_msgcat, ISC_MSGSET_SOCKET,
+				   ISC_MSG_INTERNALSEND,
+				   "startio_send: internal_sendmsg(%d) %d "
+				   "bytes, err %d/%s",
+				   sock->fd, *nbytes, *send_errno, strbuf);
+		}
+		status = DOIO_HARD;
+		goto done;
+	}
+	dev->result = ISC_R_SUCCESS;
+	status = DOIO_SOFT;
+ done:
+	_set_state(sock, SOCK_DATA);
+	return (status);
+}
+
+static isc_result_t
+allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type,
+		isc_socket_t **socketp) {
+	isc_socket_t *sock;
+	isc_result_t result;
+
+	sock = isc_mem_get(manager->mctx, sizeof(*sock));
+
+	if (sock == NULL)
+		return (ISC_R_NOMEMORY);
+
+	sock->magic = 0;
+	sock->references = 0;
+
+	sock->manager = manager;
+	sock->type = type;
+	sock->fd = INVALID_SOCKET;
+
+	ISC_LINK_INIT(sock, link);
+
+	/*
+	 * set up list of readers and writers to be initially empty
+	 */
+	ISC_LIST_INIT(sock->recv_list);
+	ISC_LIST_INIT(sock->send_list);
+	ISC_LIST_INIT(sock->accept_list);
+	sock->connect_ev = NULL;
+	sock->pending_accept = 0;
+	sock->pending_recv = 0;
+	sock->pending_send = 0;
+	sock->pending_iocp = 0;
+	sock->listener = 0;
+	sock->connected = 0;
+	sock->pending_connect = 0;
+	sock->bound = 0;
+	memset(sock->name, 0, sizeof(sock->name));	// zero the name field
+	_set_state(sock, SOCK_INITIALIZED);
+
+	sock->recvbuf.len = 65536;
+	sock->recvbuf.consume_position = sock->recvbuf.base;
+	sock->recvbuf.remaining = 0;
+	sock->recvbuf.base = isc_mem_get(manager->mctx, sock->recvbuf.len); // max buffer size
+	if (sock->recvbuf.base == NULL) {
+		sock->magic = 0;
+		goto error;
+	}
+
+	/*
+	 * initialize the lock
+	 */
+	result = isc_mutex_init(&sock->lock);
+	if (result != ISC_R_SUCCESS) {
+		sock->magic = 0;
+		isc_mem_put(manager->mctx, sock->recvbuf.base, sock->recvbuf.len);
+		sock->recvbuf.base = NULL;
+		goto error;
+	}
+
+	socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
+		   "allocated");
+
+	sock->magic = SOCKET_MAGIC;
+	*socketp = sock;
+
+	return (ISC_R_SUCCESS);
+
+ error:
+	isc_mem_put(manager->mctx, sock, sizeof(*sock));
+
+	return (result);
+}
+
+/*
+ * Verify that the socket state is consistent.
+ */
+static void
+consistent(isc_socket_t *sock) {
+
+	isc_socketevent_t *dev;
+	isc_socket_newconnev_t *nev;
+	unsigned int count;
+	char *crash_reason;
+	isc_boolean_t crash = ISC_FALSE;
+
+	REQUIRE(sock->pending_iocp == sock->pending_recv + sock->pending_send
+		+ sock->pending_accept + sock->pending_connect);
+
+	dev = ISC_LIST_HEAD(sock->send_list);
+	count = 0;
+	while (dev != NULL) {
+		count++;
+		dev = ISC_LIST_NEXT(dev, ev_link);
+	}
+	if (count > sock->pending_send) {
+		crash = ISC_TRUE;
+		crash_reason = "send_list > sock->pending_send";
+	}
+
+	nev = ISC_LIST_HEAD(sock->accept_list);
+	count = 0;
+	while (nev != NULL) {
+		count++;
+		nev = ISC_LIST_NEXT(nev, ev_link);
+	}
+	if (count > sock->pending_accept) {
+		crash = ISC_TRUE;
+		crash_reason = "send_list > sock->pending_send";
+	}
+
+	if (crash) {
+		socket_log(__LINE__, sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET,
+			   ISC_MSG_DESTROYING, "SOCKET INCONSISTENT: %s",
+			   crash_reason);
+		sock_dump(sock);
+		INSIST(crash == ISC_FALSE);
+	}
+}
+
+/*
+ * Maybe free the socket.
+ *
+ * This function will verify tht the socket is no longer in use in any way,
+ * either internally or externally.  This is the only place where this
+ * check is to be made; if some bit of code believes that IT is done with
+ * the socket (e.g., some reference counter reaches zero), it should call
+ * this function.
+ *
+ * When calling this function, the socket must be locked, and the manager
+ * must be unlocked.
+ *
+ * When this function returns, *socketp will be NULL.  No tricks to try
+ * to hold on to this pointer are allowed.
+ */
+static void
+maybe_free_socket(isc_socket_t **socketp, int lineno) {
+	isc_socket_t *sock = *socketp;
+	*socketp = NULL;
+
+	INSIST(VALID_SOCKET(sock));
+	CONSISTENT(sock);
+
+	if (sock->pending_iocp > 0
+	    || sock->pending_recv > 0
+	    || sock->pending_send > 0
+	    || sock->pending_accept > 0
+	    || sock->references > 0
+	    || sock->pending_connect == 1
+	    || !ISC_LIST_EMPTY(sock->recv_list)
+	    || !ISC_LIST_EMPTY(sock->send_list)
+	    || !ISC_LIST_EMPTY(sock->accept_list)
+	    || sock->fd != INVALID_SOCKET) {
+		UNLOCK(&sock->lock);
+		return;
+	}
+	UNLOCK(&sock->lock);
+
+	free_socket(&sock, lineno);
+}
+
+void
+free_socket(isc_socket_t **sockp, int lineno) {
+	isc_socketmgr_t *manager;
+	isc_socket_t *sock = *sockp;
+	*sockp = NULL;
+
+	manager = sock->manager;
+
+	/*
+	 * Seems we can free the socket after all.
+	 */
+	manager = sock->manager;
+	socket_log(__LINE__, sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET,
+		   ISC_MSG_DESTROYING, "freeing socket line %d fd %d lock %p semaphore %p",
+		   lineno, sock->fd, &sock->lock, sock->lock.LockSemaphore);
+
+	sock->magic = 0;
+	DESTROYLOCK(&sock->lock);
+
+	if (sock->recvbuf.base != NULL)
+		isc_mem_put(manager->mctx, sock->recvbuf.base, sock->recvbuf.len);
+
+	LOCK(&manager->lock);
+	if (ISC_LINK_LINKED(sock, link))
+		ISC_LIST_UNLINK(manager->socklist, sock, link);
+	isc_mem_put(manager->mctx, sock, sizeof(*sock));
+
+	if (ISC_LIST_EMPTY(manager->socklist))
+		SIGNAL(&manager->shutdown_ok);
+	UNLOCK(&manager->lock);
+}
+
+/*
+ * Create a new 'type' socket managed by 'manager'.  Events
+ * will be posted to 'task' and when dispatched 'action' will be
+ * called with 'arg' as the arg value.  The new socket is returned
+ * in 'socketp'.
+ */
+isc_result_t
+isc__socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
+		  isc_socket_t **socketp) {
+	isc_socket_t *sock = NULL;
+	isc_result_t result;
+#if defined(USE_CMSG)
+	int on = 1;
+#endif
+#if defined(SO_RCVBUF)
+	ISC_SOCKADDR_LEN_T optlen;
+	int size;
+#endif
+	int socket_errno;
+	char strbuf[ISC_STRERRORSIZE];
+
+	REQUIRE(VALID_MANAGER(manager));
+	REQUIRE(socketp != NULL && *socketp == NULL);
+	REQUIRE(type != isc_sockettype_fdwatch);
+
+	result = allocate_socket(manager, type, &sock);
+	if (result != ISC_R_SUCCESS)
+		return (result);
+
+	sock->pf = pf;
+	switch (type) {
+	case isc_sockettype_udp:
+		sock->fd = socket(pf, SOCK_DGRAM, IPPROTO_UDP);
+		if (sock->fd != INVALID_SOCKET) {
+			result = connection_reset_fix(sock->fd);
+			if (result != ISC_R_SUCCESS) {
+				socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
+					"closed %d %d %d con_reset_fix_failed",
+					sock->pending_recv, sock->pending_send,
+					sock->references);
+				closesocket(sock->fd);
+				_set_state(sock, SOCK_CLOSED);
+				sock->fd = INVALID_SOCKET;
+				free_socket(&sock, __LINE__);
+				return (result);
+			}
+		}
+		break;
+	case isc_sockettype_tcp:
+		sock->fd = socket(pf, SOCK_STREAM, IPPROTO_TCP);
+		break;
+	}
+
+	if (sock->fd == INVALID_SOCKET) {
+		socket_errno = WSAGetLastError();
+		free_socket(&sock, __LINE__);
+
+		switch (socket_errno) {
+		case WSAEMFILE:
+		case WSAENOBUFS:
+			return (ISC_R_NORESOURCES);
+
+		case WSAEPROTONOSUPPORT:
+		case WSAEPFNOSUPPORT:
+		case WSAEAFNOSUPPORT:
+			return (ISC_R_FAMILYNOSUPPORT);
+
+		default:
+			isc__strerror(socket_errno, strbuf, sizeof(strbuf));
+			UNEXPECTED_ERROR(__FILE__, __LINE__,
+					 "socket() %s: %s",
+					 isc_msgcat_get(isc_msgcat,
+							ISC_MSGSET_GENERAL,
+							ISC_MSG_FAILED,
+							"failed"),
+					 strbuf);
+			return (ISC_R_UNEXPECTED);
+		}
+	}
+
+	result = make_nonblock(sock->fd);
+	if (result != ISC_R_SUCCESS) {
+		socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
+			"closed %d %d %d make_nonblock_failed",
+			sock->pending_recv, sock->pending_send,
+			sock->references);
+		closesocket(sock->fd);
+		sock->fd = INVALID_SOCKET;
+		free_socket(&sock, __LINE__);
+		return (result);
+	}
+
+
+#if defined(USE_CMSG) || defined(SO_RCVBUF)
+	if (type == isc_sockettype_udp) {
+
+#if defined(USE_CMSG)
+#if defined(ISC_PLATFORM_HAVEIPV6)
+#ifdef IPV6_RECVPKTINFO
+		/* 2292bis */
+		if ((pf == AF_INET6)
+		    && (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_RECVPKTINFO,
+				   (char *)&on, sizeof(on)) < 0)) {
+			isc__strerror(WSAGetLastError(), strbuf, sizeof(strbuf));
+			UNEXPECTED_ERROR(__FILE__, __LINE__,
+					 "setsockopt(%d, IPV6_RECVPKTINFO) "
+					 "%s: %s", sock->fd,
+					 isc_msgcat_get(isc_msgcat,
+							ISC_MSGSET_GENERAL,
+							ISC_MSG_FAILED,
+							"failed"),
+					 strbuf);
+		}
+#else
+		/* 2292 */
+		if ((pf == AF_INET6)
+		    && (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_PKTINFO,
+				   (char *)&on, sizeof(on)) < 0)) {
+			isc__strerror(WSAGetLastError(), strbuf, sizeof(strbuf));
+			UNEXPECTED_ERROR(__FILE__, __LINE__,
+					 "setsockopt(%d, IPV6_PKTINFO) %s: %s",
+					 sock->fd,
+					 isc_msgcat_get(isc_msgcat,
+							ISC_MSGSET_GENERAL,
+							ISC_MSG_FAILED,
+							"failed"),
+					 strbuf);
+		}
+#endif /* IPV6_RECVPKTINFO */
+#ifdef IPV6_USE_MIN_MTU	/*2292bis, not too common yet*/
+		/* use minimum MTU */
+		if (pf == AF_INET6) {
+			(void)setsockopt(sock->fd, IPPROTO_IPV6,
+					 IPV6_USE_MIN_MTU,
+					 (char *)&on, sizeof(on));
+		}
+#endif
+#endif /* ISC_PLATFORM_HAVEIPV6 */
+#endif /* defined(USE_CMSG) */
+
+#if defined(SO_RCVBUF)
+	       optlen = sizeof(size);
+	       if (getsockopt(sock->fd, SOL_SOCKET, SO_RCVBUF,
+			      (char *)&size, &optlen) >= 0 &&
+		    size < RCVBUFSIZE) {
+		       size = RCVBUFSIZE;
+		       (void)setsockopt(sock->fd, SOL_SOCKET, SO_RCVBUF,
+					(char *)&size, sizeof(size));
+	       }
+#endif
+
+	}
+#endif /* defined(USE_CMSG) || defined(SO_RCVBUF) */
+
+	_set_state(sock, SOCK_OPEN);
+	sock->references = 1;
+	*socketp = sock;
+
+	iocompletionport_update(sock);
+
+	/*
+	 * Note we don't have to lock the socket like we normally would because
+	 * there are no external references to it yet.
+	 */
+	LOCK(&manager->lock);
+	ISC_LIST_APPEND(manager->socklist, sock, link);
+	InterlockedIncrement(&manager->totalSockets);
+	UNLOCK(&manager->lock);
+
+	socket_log(__LINE__, sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET,
+		   ISC_MSG_CREATED, "created %u type %u", sock->fd, type);
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_socket_open(isc_socket_t *sock) {
+	REQUIRE(VALID_SOCKET(sock));
+	REQUIRE(sock->type != isc_sockettype_fdwatch);
+
+	return (ISC_R_NOTIMPLEMENTED);
+}
+
+/*
+ * Attach to a socket.  Caller must explicitly detach when it is done.
+ */
+void
+isc__socket_attach(isc_socket_t *sock, isc_socket_t **socketp) {
+	REQUIRE(VALID_SOCKET(sock));
+	REQUIRE(socketp != NULL && *socketp == NULL);
+
+	LOCK(&sock->lock);
+	CONSISTENT(sock);
+	sock->references++;
+	UNLOCK(&sock->lock);
+
+	*socketp = sock;
+}
+
+/*
+ * Dereference a socket.  If this is the last reference to it, clean things
+ * up by destroying the socket.
+ */
+void
+isc__socket_detach(isc_socket_t **socketp) {
+	isc_socket_t *sock;
+	isc_boolean_t kill_socket = ISC_FALSE;
+
+	REQUIRE(socketp != NULL);
+	sock = *socketp;
+	REQUIRE(VALID_SOCKET(sock));
+	REQUIRE(sock->type != isc_sockettype_fdwatch);
+
+	LOCK(&sock->lock);
+	CONSISTENT(sock);
+	REQUIRE(sock->references > 0);
+	sock->references--;
+
+	socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
+		"detach_socket %d %d %d",
+		sock->pending_recv, sock->pending_send,
+		sock->references);
+
+	if (sock->references == 0 && sock->fd != INVALID_SOCKET) {
+		closesocket(sock->fd);
+		sock->fd = INVALID_SOCKET;
+		_set_state(sock, SOCK_CLOSED);
+	}
+
+	maybe_free_socket(&sock, __LINE__);
+
+	*socketp = NULL;
+}
+
+isc_result_t
+isc_socket_close(isc_socket_t *sock) {
+	REQUIRE(VALID_SOCKET(sock));
+	REQUIRE(sock->type != isc_sockettype_fdwatch);
+
+	return (ISC_R_NOTIMPLEMENTED);
+}
+
+/*
+ * Dequeue an item off the given socket's read queue, set the result code
+ * in the done event to the one provided, and send it to the task it was
+ * destined for.
+ *
+ * If the event to be sent is on a list, remove it before sending.  If
+ * asked to, send and detach from the task as well.
+ *
+ * Caller must have the socket locked if the event is attached to the socket.
+ */
+static void
+send_recvdone_event(isc_socket_t *sock, isc_socketevent_t **dev) {
+	isc_task_t *task;
+
+	task = (*dev)->ev_sender;
+	(*dev)->ev_sender = sock;
+
+	if (ISC_LINK_LINKED(*dev, ev_link))
+		ISC_LIST_DEQUEUE(sock->recv_list, *dev, ev_link);
+
+	if (((*dev)->attributes & ISC_SOCKEVENTATTR_ATTACHED)
+	    == ISC_SOCKEVENTATTR_ATTACHED)
+		isc_task_sendanddetach(&task, (isc_event_t **)dev);
+	else
+		isc_task_send(task, (isc_event_t **)dev);
+
+	CONSISTENT(sock);
+}
+
+/*
+ * See comments for send_recvdone_event() above.
+ */
+static void
+send_senddone_event(isc_socket_t *sock, isc_socketevent_t **dev) {
+	isc_task_t *task;
+
+	INSIST(dev != NULL && *dev != NULL);
+
+	task = (*dev)->ev_sender;
+	(*dev)->ev_sender = sock;
+
+	if (ISC_LINK_LINKED(*dev, ev_link))
+		ISC_LIST_DEQUEUE(sock->send_list, *dev, ev_link);
+
+	if (((*dev)->attributes & ISC_SOCKEVENTATTR_ATTACHED)
+	    == ISC_SOCKEVENTATTR_ATTACHED)
+		isc_task_sendanddetach(&task, (isc_event_t **)dev);
+	else
+		isc_task_send(task, (isc_event_t **)dev);
+
+	CONSISTENT(sock);
+}
+
+/*
+ * See comments for send_recvdone_event() above.
+ */
+static void
+send_acceptdone_event(isc_socket_t *sock, isc_socket_newconnev_t **adev) {
+	isc_task_t *task;
+
+	INSIST(adev != NULL && *adev != NULL);
+
+	task = (*adev)->ev_sender;
+	(*adev)->ev_sender = sock;
+
+	if (ISC_LINK_LINKED(*adev, ev_link))
+		ISC_LIST_DEQUEUE(sock->accept_list, *adev, ev_link);
+
+	isc_task_sendanddetach(&task, (isc_event_t **)adev);
+
+	CONSISTENT(sock);
+}
+
+/*
+ * See comments for send_recvdone_event() above.
+ */
+static void
+send_connectdone_event(isc_socket_t *sock, isc_socket_connev_t **cdev) {
+	isc_task_t *task;
+
+	INSIST(cdev != NULL && *cdev != NULL);
+
+	task = (*cdev)->ev_sender;
+	(*cdev)->ev_sender = sock;
+
+	sock->connect_ev = NULL;
+
+	isc_task_sendanddetach(&task, (isc_event_t **)cdev);
+
+	CONSISTENT(sock);
+}
+
+/*
+ * On entry to this function, the event delivered is the internal
+ * readable event, and the first item on the accept_list should be
+ * the done event we want to send.  If the list is empty, this is a no-op,
+ * so just close the new connection, unlock, and return.
+ *
+ * Note the socket is locked before entering here
+ */
+static void
+internal_accept(isc_socket_t *sock, IoCompletionInfo *lpo, int accept_errno) {
+	isc_socket_newconnev_t *adev;
+	isc_result_t result = ISC_R_SUCCESS;
+	isc_socket_t *nsock;
+	struct sockaddr *localaddr;
+	int localaddr_len = sizeof(*localaddr);
+	struct sockaddr *remoteaddr;
+	int remoteaddr_len = sizeof(*remoteaddr);
+
+	INSIST(VALID_SOCKET(sock));
+	LOCK(&sock->lock);
+	CONSISTENT(sock);
+
+	socket_log(__LINE__, sock, NULL, TRACE,
+		   isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTLOCK,
+		   "internal_accept called");
+
+	INSIST(sock->listener);
+
+	INSIST(sock->pending_iocp > 0);
+	sock->pending_iocp--;
+	INSIST(sock->pending_accept > 0);
+	sock->pending_accept--;
+
+	adev = lpo->adev;
+
+	/*
+	 * If the event is no longer in the list we can just return.
+	 */
+	if (!acceptdone_is_active(sock, adev))
+		goto done;
+
+	nsock = adev->newsocket;
+
+	/*
+	 * Pull off the done event.
+	 */
+	ISC_LIST_UNLINK(sock->accept_list, adev, ev_link);
+
+	/*
+	 * Extract the addresses from the socket, copy them into the structure,
+	 * and return the new socket.
+	 */
+	ISCGetAcceptExSockaddrs(lpo->acceptbuffer, 0,
+		sizeof(SOCKADDR_STORAGE) + 16, sizeof(SOCKADDR_STORAGE) + 16,
+		(LPSOCKADDR *)&localaddr, &localaddr_len,
+		(LPSOCKADDR *)&remoteaddr, &remoteaddr_len);
+	memcpy(&adev->address.type, remoteaddr, remoteaddr_len);
+	adev->address.length = remoteaddr_len;
+	nsock->address = adev->address;
+	nsock->pf = adev->address.type.sa.sa_family;
+
+	socket_log(__LINE__, nsock, &nsock->address, TRACE,
+		   isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTLOCK,
+		   "internal_accept parent %p", sock);
+
+	result = make_nonblock(adev->newsocket->fd);
+	INSIST(result == ISC_R_SUCCESS);
+
+	INSIST(setsockopt(nsock->fd, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
+			  (char *)&sock->fd, sizeof(sock->fd)) == 0);
+
+	/*
+	 * Hook it up into the manager.
+	 */
+	nsock->bound = 1;
+	nsock->connected = 1;
+	_set_state(nsock, SOCK_OPEN);
+
+	LOCK(&nsock->manager->lock);
+	ISC_LIST_APPEND(nsock->manager->socklist, nsock, link);
+	InterlockedIncrement(&nsock->manager->totalSockets);
+	UNLOCK(&nsock->manager->lock);
+
+	socket_log(__LINE__, sock, &nsock->address, CREATION,
+		   isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTEDCXN,
+		   "accepted_connection new_socket %p fd %d",
+		   nsock, nsock->fd);
+
+	adev->result = result;
+	send_acceptdone_event(sock, &adev);
+
+done:
+	CONSISTENT(sock);
+	UNLOCK(&sock->lock);
+
+	HeapFree(hHeapHandle, 0, lpo->acceptbuffer);
+	lpo->acceptbuffer = NULL;
+}
+
+/*
+ * Called when a socket with a pending connect() finishes.
+ * Note that the socket is locked before entering.
+ */
+static void
+internal_connect(isc_socket_t *sock, IoCompletionInfo *lpo, int connect_errno) {
+	isc_socket_connev_t *cdev;
+	char strbuf[ISC_STRERRORSIZE];
+
+	INSIST(VALID_SOCKET(sock));
+
+	LOCK(&sock->lock);
+
+	INSIST(sock->pending_iocp > 0);
+	sock->pending_iocp--;
+	INSIST(sock->pending_connect == 1);
+	sock->pending_connect = 0;
+
+	/*
+	 * Has this event been canceled?
+	 */
+	cdev = lpo->cdev;
+	if (!connectdone_is_active(sock, cdev)) {
+		sock->pending_connect = 0;
+		if (sock->fd != INVALID_SOCKET) {
+			closesocket(sock->fd);
+			sock->fd = INVALID_SOCKET;
+			_set_state(sock, SOCK_CLOSED);
+		}
+		CONSISTENT(sock);
+		UNLOCK(&sock->lock);
+		return;
+	}
+
+	/*
+	 * Check possible Windows network event error status here.
+	 */
+	if (connect_errno != 0) {
+		/*
+		 * If the error is SOFT, just try again on this
+		 * fd and pretend nothing strange happened.
+		 */
+		if (SOFT_ERROR(connect_errno) ||
+		    connect_errno == WSAEINPROGRESS) {
+			sock->pending_connect = 1;
+			CONSISTENT(sock);
+			UNLOCK(&sock->lock);
+			return;
+		}
+
+		/*
+		 * Translate other errors into ISC_R_* flavors.
+		 */
+		switch (connect_errno) {
+#define ERROR_MATCH(a, b) case a: cdev->result = b; break;
+			ERROR_MATCH(WSAEACCES, ISC_R_NOPERM);
+			ERROR_MATCH(WSAEADDRNOTAVAIL, ISC_R_ADDRNOTAVAIL);
+			ERROR_MATCH(WSAEAFNOSUPPORT, ISC_R_ADDRNOTAVAIL);
+			ERROR_MATCH(WSAECONNREFUSED, ISC_R_CONNREFUSED);
+			ERROR_MATCH(WSAEHOSTUNREACH, ISC_R_HOSTUNREACH);
+			ERROR_MATCH(WSAEHOSTDOWN, ISC_R_HOSTDOWN);
+			ERROR_MATCH(WSAENETUNREACH, ISC_R_NETUNREACH);
+			ERROR_MATCH(WSAENETDOWN, ISC_R_NETDOWN);
+			ERROR_MATCH(WSAENOBUFS, ISC_R_NORESOURCES);
+			ERROR_MATCH(WSAECONNRESET, ISC_R_CONNECTIONRESET);
+			ERROR_MATCH(WSAECONNABORTED, ISC_R_CONNECTIONRESET);
+			ERROR_MATCH(WSAETIMEDOUT, ISC_R_TIMEDOUT);
+#undef ERROR_MATCH
+		default:
+			cdev->result = ISC_R_UNEXPECTED;
+			isc__strerror(connect_errno, strbuf, sizeof(strbuf));
+			UNEXPECTED_ERROR(__FILE__, __LINE__,
+					 "internal_connect: connect() %s",
+					 strbuf);
+		}
+	} else {
+		INSIST(setsockopt(sock->fd, SOL_SOCKET,
+				  SO_UPDATE_CONNECT_CONTEXT, NULL, 0) == 0);
+		cdev->result = ISC_R_SUCCESS;
+		sock->connected = 1;
+		socket_log(__LINE__, sock, &sock->address, IOEVENT,
+			   isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTEDCXN,
+			   "internal_connect: success");
+	}
+
+	send_connectdone_event(sock, &cdev);
+
+	UNLOCK(&sock->lock);
+}
+
+/*
+ * Loop through the socket, returning ISC_R_EOF for each done event pending.
+ */
+static void
+send_recvdone_abort(isc_socket_t *sock, isc_result_t result) {
+	isc_socketevent_t *dev;
+
+	while (!ISC_LIST_EMPTY(sock->recv_list)) {
+		dev = ISC_LIST_HEAD(sock->recv_list);
+		dev->result = result;
+		send_recvdone_event(sock, &dev);
+	}
+}
+
+/*
+ * Take the data we received in our private buffer, and if any recv() calls on
+ * our list are satisfied, send the corresponding done event.
+ *
+ * If we need more data (there are still items on the recv_list after we consume all
+ * our data) then arrange for another system recv() call to fill our buffers.
+ */
+static void
+internal_recv(isc_socket_t *sock, int nbytes)
+{
+	INSIST(VALID_SOCKET(sock));
+
+	LOCK(&sock->lock);
+	CONSISTENT(sock);
+
+	socket_log(__LINE__, sock, NULL, IOEVENT,
+		   isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_INTERNALRECV,
+		   "internal_recv: %d bytes received", nbytes);
+
+	/*
+	 * If we got here, the I/O operation succeeded.  However, we might still have removed this
+	 * event from our notification list (or never placed it on it due to immediate completion.)
+	 * Handle the reference counting here, and handle the cancellation event just after.
+	 */
+	INSIST(sock->pending_iocp > 0);
+	sock->pending_iocp--;
+	INSIST(sock->pending_recv > 0);
+	sock->pending_recv--;
+
+	/*
+	 * The only way we could have gotten here is that our I/O has successfully completed.
+	 * Update our pointers, and move on.  The only odd case here is that we might not
+	 * have received enough data on a TCP stream to satisfy the minimum requirements.  If
+	 * this is the case, we will re-issue the recv() call for what we need.
+	 *
+	 * We do check for a recv() of 0 bytes on a TCP stream.  This means the remote end
+	 * has closed.
+	 */
+	if (nbytes == 0 && sock->type == isc_sockettype_tcp) {
+		send_recvdone_abort(sock, ISC_R_EOF);
+		maybe_free_socket(&sock, __LINE__);
+		return;
+	}
+	sock->recvbuf.remaining = nbytes;
+	sock->recvbuf.consume_position = sock->recvbuf.base;
+	completeio_recv(sock);
+
+	/*
+	 * If there are more receivers waiting for data, queue another receive
+	 * here.
+	 */
+	queue_receive_request(sock);
+
+	/*
+	 * Unlock and/or destroy if we are the last thing this socket has left to do.
+	 */
+	maybe_free_socket(&sock, __LINE__);
+}
+
+static void
+internal_send(isc_socket_t *sock, isc_socketevent_t *dev,
+	      struct msghdr *messagehdr, int nbytes, int send_errno, IoCompletionInfo *lpo)
+{
+	buflist_t *buffer;
+
+	/*
+	 * Find out what socket this is and lock it.
+	 */
+	INSIST(VALID_SOCKET(sock));
+
+	LOCK(&sock->lock);
+	CONSISTENT(sock);
+
+	socket_log(__LINE__, sock, NULL, IOEVENT,
+		   isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_INTERNALSEND,
+		   "internal_send: task got socket event %p", dev);
+
+	buffer = ISC_LIST_HEAD(lpo->bufferlist);
+	while (buffer != NULL) {
+		ISC_LIST_DEQUEUE(lpo->bufferlist, buffer, link);
+
+		socket_log(__LINE__, sock, NULL, TRACE,
+		   isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTLOCK,
+		   "free_buffer %p %p", buffer, buffer->buf);
+
+		HeapFree(hHeapHandle, 0, buffer->buf);
+		HeapFree(hHeapHandle, 0, buffer);
+		buffer = ISC_LIST_HEAD(lpo->bufferlist);
+	}
+
+	INSIST(sock->pending_iocp > 0);
+	sock->pending_iocp--;
+	INSIST(sock->pending_send > 0);
+	sock->pending_send--;
+
+	/* If the event is no longer in the list we can just return */
+	if (!senddone_is_active(sock, dev))
+		goto done;
+
+	/*
+	 * Set the error code and send things on its way.
+	 */
+	switch (completeio_send(sock, dev, messagehdr, nbytes, send_errno)) {
+	case DOIO_SOFT:
+		break;
+	case DOIO_HARD:
+	case DOIO_SUCCESS:
+		send_senddone_event(sock, &dev);
+		break;
+	}
+
+ done:
+	maybe_free_socket(&sock, __LINE__);
+}
+
+/*
+ * These return if the done event passed in is on the list (or for connect, is
+ * the one we're waiting for.  Using these ensures we will not double-send an
+ * event.
+ */
+static isc_boolean_t
+senddone_is_active(isc_socket_t *sock, isc_socketevent_t *dev)
+{
+	isc_socketevent_t *ldev;
+
+	ldev = ISC_LIST_HEAD(sock->send_list);
+	while (ldev != NULL && ldev != dev)
+		ldev = ISC_LIST_NEXT(ldev, ev_link);
+
+	return (ldev == NULL ? ISC_FALSE : ISC_TRUE);
+}
+
+static isc_boolean_t
+acceptdone_is_active(isc_socket_t *sock, isc_socket_newconnev_t *dev)
+{
+	isc_socket_newconnev_t *ldev;
+
+	ldev = ISC_LIST_HEAD(sock->accept_list);
+	while (ldev != NULL && ldev != dev)
+		ldev = ISC_LIST_NEXT(ldev, ev_link);
+
+	return (ldev == NULL ? ISC_FALSE : ISC_TRUE);
+}
+
+static isc_boolean_t
+connectdone_is_active(isc_socket_t *sock, isc_socket_connev_t *dev)
+{
+	return (sock->connect_ev == dev ? ISC_TRUE : ISC_FALSE);
+}
+
+//
+// The Windows network stack seems to have two very distinct paths depending
+// on what is installed.  Specifically, if something is looking at network
+// connections (like an anti-virus or anti-malware application, such as
+// McAfee products) Windows may return additional error conditions which
+// were not previously returned.
+//
+// One specific one is when a TCP SYN scan is used.  In this situation,
+// Windows responds with the SYN-ACK, but the scanner never responds with
+// the 3rd packet, the ACK.  Windows consiers this a partially open connection.
+// Most Unix networking stacks, and Windows without McAfee installed, will
+// not return this to the caller.  However, with this product installed,
+// Windows returns this as a failed status on the Accept() call.  Here, we
+// will just re-issue the ISCAcceptEx() call as if nothing had happened.
+//
+// This code should only be called when the listening socket has received
+// such an error.  Additionally, the "parent" socket must be locked.
+// Additionally, the lpo argument is re-used here, and must not be freed
+// by the caller.
+//
+static isc_result_t
+restart_accept(isc_socket_t *parent, IoCompletionInfo *lpo)
+{
+	isc_socket_t *nsock = lpo->adev->newsocket;
+	SOCKET new_fd;
+
+	/*
+	 * AcceptEx() requires we pass in a socket.  Note that we carefully
+	 * do not close the previous socket in case of an error message returned by
+	 * our new socket() call.  If we return an error here, our caller will
+	 * clean up.
+	 */
+	new_fd = socket(parent->pf, SOCK_STREAM, IPPROTO_TCP);
+	if (nsock->fd == INVALID_SOCKET) {
+		return (ISC_R_FAILURE); // parent will ask windows for error message
+	}
+	closesocket(nsock->fd);
+	nsock->fd = new_fd;
+
+	memset(&lpo->overlapped, 0, sizeof(lpo->overlapped));
+
+	ISCAcceptEx(parent->fd,
+		    nsock->fd,				/* Accepted Socket */
+		    lpo->acceptbuffer,			/* Buffer for initial Recv */
+		    0,					/* Length of Buffer */
+		    sizeof(SOCKADDR_STORAGE) + 16,	/* Local address length + 16 */
+		    sizeof(SOCKADDR_STORAGE) + 16,	/* Remote address lengh + 16 */
+		    (LPDWORD)&lpo->received_bytes,	/* Bytes Recved */
+		    (LPOVERLAPPED)lpo			/* Overlapped structure */
+		    );
+
+	InterlockedDecrement(&nsock->manager->iocp_total);
+	iocompletionport_update(nsock);
+
+	return (ISC_R_SUCCESS);
+}
+
+/*
+ * This is the I/O Completion Port Worker Function. It loops forever
+ * waiting for I/O to complete and then forwards them for further
+ * processing. There are a number of these in separate threads.
+ */
+static isc_threadresult_t WINAPI
+SocketIoThread(LPVOID ThreadContext) {
+	isc_socketmgr_t *manager = ThreadContext;
+	BOOL bSuccess = FALSE;
+	DWORD nbytes;
+	IoCompletionInfo *lpo = NULL;
+	isc_socket_t *sock = NULL;
+	int request;
+	struct msghdr *messagehdr = NULL;
+	int errval;
+	char strbuf[ISC_STRERRORSIZE];
+	int errstatus;
+
+	REQUIRE(VALID_MANAGER(manager));
+
+	/*
+	 * Set the thread priority high enough so I/O will
+	 * preempt normal recv packet processing, but not
+	 * higher than the timer sync thread.
+	 */
+	if (!SetThreadPriority(GetCurrentThread(),
+			       THREAD_PRIORITY_ABOVE_NORMAL)) {
+		errval = GetLastError();
+		isc__strerror(errval, strbuf, sizeof(strbuf));
+		FATAL_ERROR(__FILE__, __LINE__,
+				isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
+				ISC_MSG_FAILED,
+				"Can't set thread priority: %s"),
+				strbuf);
+	}
+
+	/*
+	 * Loop forever waiting on I/O Completions and then processing them
+	 */
+	while (TRUE) {
+		wait_again:
+		bSuccess = GetQueuedCompletionStatus(manager->hIoCompletionPort,
+						     &nbytes, (LPDWORD)&sock,
+						     (LPWSAOVERLAPPED *)&lpo,
+						     INFINITE);
+		if (lpo == NULL) /* Received request to exit */
+			break;
+
+		REQUIRE(VALID_SOCKET(sock));
+
+		request = lpo->request_type;
+
+		errstatus = 0;
+		if (!bSuccess) {
+			isc_result_t isc_result;
+
+			/*
+			 * Did the I/O operation complete?
+			 */
+			errstatus = GetLastError();
+			isc_result = isc__errno2resultx(errstatus, __FILE__, __LINE__);
+
+			LOCK(&sock->lock);
+			CONSISTENT(sock);
+			switch (request) {
+			case SOCKET_RECV:
+				INSIST(sock->pending_iocp > 0);
+				sock->pending_iocp--;
+				INSIST(sock->pending_recv > 0);
+				sock->pending_recv--;
+				if (!sock->connected &&
+				    ((errstatus == ERROR_HOST_UNREACHABLE) ||
+				     (errstatus == WSAENETRESET) ||
+				     (errstatus == WSAECONNRESET))) {
+					/* ignore soft errors */
+					queue_receive_request(sock);
+					break;
+				}
+				send_recvdone_abort(sock, isc_result);
+				if (isc_result == ISC_R_UNEXPECTED) {
+					UNEXPECTED_ERROR(__FILE__, __LINE__,
+						"SOCKET_RECV: Windows error code: %d, returning ISC error %d",
+						errstatus, isc_result);
+				}
+				break;
+
+			case SOCKET_SEND:
+				INSIST(sock->pending_iocp > 0);
+				sock->pending_iocp--;
+				INSIST(sock->pending_send > 0);
+				sock->pending_send--;
+				if (senddone_is_active(sock, lpo->dev)) {
+					lpo->dev->result = isc_result;
+					socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
+						"canceled_send");
+					send_senddone_event(sock, &lpo->dev);
+				}
+				break;
+
+			case SOCKET_ACCEPT:
+				INSIST(sock->pending_iocp > 0);
+				INSIST(sock->pending_accept > 0);
+
+				socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
+					"Accept: errstatus=%d isc_result=%d", errstatus, isc_result);
+
+				if (acceptdone_is_active(sock, lpo->adev)) {
+					if (restart_accept(sock, lpo) == ISC_R_SUCCESS) {
+						UNLOCK(&sock->lock);
+						goto wait_again;
+					} else {
+						errstatus = GetLastError();
+						isc_result = isc__errno2resultx(errstatus, __FILE__, __LINE__);
+						socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
+							"restart_accept() failed: errstatus=%d isc_result=%d",
+							errstatus, isc_result);
+					}
+				}
+
+				sock->pending_iocp--;
+				sock->pending_accept--;
+				if (acceptdone_is_active(sock, lpo->adev)) {
+					closesocket(lpo->adev->newsocket->fd);
+					lpo->adev->newsocket->fd = INVALID_SOCKET;
+					lpo->adev->newsocket->references--;
+					free_socket(&lpo->adev->newsocket, __LINE__);
+					lpo->adev->result = isc_result;
+					socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
+						"canceled_accept");
+					send_acceptdone_event(sock, &lpo->adev);
+				}
+				break;
+
+			case SOCKET_CONNECT:
+				INSIST(sock->pending_iocp > 0);
+				sock->pending_iocp--;
+				INSIST(sock->pending_connect == 1);
+				sock->pending_connect = 0;
+				if (connectdone_is_active(sock, lpo->cdev)) {
+					lpo->cdev->result = isc_result;
+					socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
+						"canceled_connect");
+					send_connectdone_event(sock, &lpo->cdev);
+				}
+				break;
+			}
+			maybe_free_socket(&sock, __LINE__);
+
+			if (lpo != NULL)
+				HeapFree(hHeapHandle, 0, lpo);
+			continue;
+		}
+
+		messagehdr = &lpo->messagehdr;
+
+		switch (request) {
+		case SOCKET_RECV:
+			internal_recv(sock, nbytes);
+			break;
+		case SOCKET_SEND:
+			internal_send(sock, lpo->dev, messagehdr, nbytes, errstatus, lpo);
+			break;
+		case SOCKET_ACCEPT:
+			internal_accept(sock, lpo, errstatus);
+			break;
+		case SOCKET_CONNECT:
+			internal_connect(sock, lpo, errstatus);
+			break;
+		}
+
+		if (lpo != NULL)
+			HeapFree(hHeapHandle, 0, lpo);
+	}
+
+	/*
+	 * Exit Completion Port Thread
+	 */
+	manager_log(manager, TRACE,
+		    isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+				   ISC_MSG_EXITING, "SocketIoThread exiting"));
+	return ((isc_threadresult_t)0);
+}
+
+/*
+ * Create a new socket manager.
+ */
+isc_result_t
+isc__socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) {
+	return (isc_socketmgr_create2(mctx, managerp, 0));
+}
+
+isc_result_t
+isc__socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
+		       unsigned int maxsocks)
+{
+	isc_socketmgr_t *manager;
+	isc_result_t result;
+
+	REQUIRE(managerp != NULL && *managerp == NULL);
+
+	if (maxsocks != 0)
+		return (ISC_R_NOTIMPLEMENTED);
+
+	manager = isc_mem_get(mctx, sizeof(*manager));
+	if (manager == NULL)
+		return (ISC_R_NOMEMORY);
+
+	InitSockets();
+
+	manager->magic = SOCKET_MANAGER_MAGIC;
+	manager->mctx = NULL;
+	manager->stats = NULL;
+	ISC_LIST_INIT(manager->socklist);
+	result = isc_mutex_init(&manager->lock);
+	if (result != ISC_R_SUCCESS) {
+		isc_mem_put(mctx, manager, sizeof(*manager));
+		return (result);
+	}
+	if (isc_condition_init(&manager->shutdown_ok) != ISC_R_SUCCESS) {
+		DESTROYLOCK(&manager->lock);
+		isc_mem_put(mctx, manager, sizeof(*manager));
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "isc_condition_init() %s",
+				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+						ISC_MSG_FAILED, "failed"));
+		return (ISC_R_UNEXPECTED);
+	}
+
+	isc_mem_attach(mctx, &manager->mctx);
+
+	iocompletionport_init(manager);	/* Create the Completion Ports */
+
+	manager->bShutdown = ISC_FALSE;
+	manager->totalSockets = 0;
+	manager->iocp_total = 0;
+
+	*managerp = manager;
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc__socketmgr_getmaxsockets(isc_socketmgr_t *manager, unsigned int *nsockp) {
+	REQUIRE(VALID_MANAGER(manager));
+	REQUIRE(nsockp != NULL);
+
+	return (ISC_R_NOTIMPLEMENTED);
+}
+
+void
+isc__socketmgr_setstats(isc_socketmgr_t *manager, isc_stats_t *stats) {
+	REQUIRE(VALID_MANAGER(manager));
+	REQUIRE(ISC_LIST_EMPTY(manager->socklist));
+	REQUIRE(manager->stats == NULL);
+	REQUIRE(isc_stats_ncounters(stats) == isc_sockstatscounter_max);
+
+	isc_stats_attach(stats, &manager->stats);
+}
+
+void
+isc__socketmgr_destroy(isc_socketmgr_t **managerp) {
+	isc_socketmgr_t *manager;
+	int i;
+	isc_mem_t *mctx;
+
+	/*
+	 * Destroy a socket manager.
+	 */
+
+	REQUIRE(managerp != NULL);
+	manager = *managerp;
+	REQUIRE(VALID_MANAGER(manager));
+
+	LOCK(&manager->lock);
+
+	/*
+	 * Wait for all sockets to be destroyed.
+	 */
+	while (!ISC_LIST_EMPTY(manager->socklist)) {
+		manager_log(manager, CREATION,
+			    isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
+					   ISC_MSG_SOCKETSREMAIN,
+					   "sockets exist"));
+		WAIT(&manager->shutdown_ok, &manager->lock);
+	}
+
+	UNLOCK(&manager->lock);
+
+	/*
+	 * Here, we need to had some wait code for the completion port
+	 * thread.
+	 */
+	signal_iocompletionport_exit(manager);
+	manager->bShutdown = ISC_TRUE;
+
+	/*
+	 * Wait for threads to exit.
+	 */
+	for (i = 0; i < manager->maxIOCPThreads; i++) {
+		if (isc_thread_join((isc_thread_t) manager->hIOCPThreads[i],
+			NULL) != ISC_R_SUCCESS)
+			UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "isc_thread_join() for Completion Port %s",
+				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+						ISC_MSG_FAILED, "failed"));
+	}
+	/*
+	 * Clean up.
+	 */
+
+	CloseHandle(manager->hIoCompletionPort);
+
+	(void)isc_condition_destroy(&manager->shutdown_ok);
+
+	DESTROYLOCK(&manager->lock);
+	if (manager->stats != NULL)
+		isc_stats_detach(&manager->stats);
+	manager->magic = 0;
+	mctx= manager->mctx;
+	isc_mem_put(mctx, manager, sizeof(*manager));
+
+	isc_mem_detach(&mctx);
+
+	*managerp = NULL;
+}
+
+static void
+queue_receive_event(isc_socket_t *sock, isc_task_t *task, isc_socketevent_t *dev)
+{
+	isc_task_t *ntask = NULL;
+
+	isc_task_attach(task, &ntask);
+	dev->attributes |= ISC_SOCKEVENTATTR_ATTACHED;
+
+	/*
+	 * Enqueue the request.
+	 */
+	INSIST(!ISC_LINK_LINKED(dev, ev_link));
+	ISC_LIST_ENQUEUE(sock->recv_list, dev, ev_link);
+
+	socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
+		   "queue_receive_event: event %p -> task %p",
+		   dev, ntask);
+}
+
+/*
+ * Check the pending receive queue, and if we have data pending, give it to this
+ * caller.  If we have none, queue an I/O request.  If this caller is not the first
+ * on the list, then we will just queue this event and return.
+ *
+ * Caller must have the socket locked.
+ */
+static isc_result_t
+socket_recv(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
+	    unsigned int flags)
+{
+	int cc = 0;
+	isc_task_t *ntask = NULL;
+	isc_result_t result = ISC_R_SUCCESS;
+	int recv_errno = 0;
+
+	dev->ev_sender = task;
+
+	if (sock->fd == INVALID_SOCKET)
+		return (ISC_R_EOF);
+
+	/*
+	 * Queue our event on the list of things to do.  Call our function to
+	 * attempt to fill buffers as much as possible, and return done events.
+	 * We are going to lie about our handling of the ISC_SOCKFLAG_IMMEDIATE
+	 * here and tell our caller that we could not satisfy it immediately.
+	 */
+	queue_receive_event(sock, task, dev);
+	if ((flags & ISC_SOCKFLAG_IMMEDIATE) != 0)
+		result = ISC_R_INPROGRESS;
+
+	completeio_recv(sock);
+
+	/*
+	 * If there are more receivers waiting for data, queue another receive
+	 * here.  If the
+	 */
+	queue_receive_request(sock);
+
+	return (result);
+}
+
+isc_result_t
+isc__socket_recvv(isc_socket_t *sock, isc_bufferlist_t *buflist,
+		 unsigned int minimum, isc_task_t *task,
+		 isc_taskaction_t action, const void *arg)
+{
+	isc_socketevent_t *dev;
+	isc_socketmgr_t *manager;
+	unsigned int iocount;
+	isc_buffer_t *buffer;
+	isc_result_t ret;
+
+	REQUIRE(VALID_SOCKET(sock));
+	LOCK(&sock->lock);
+	CONSISTENT(sock);
+
+	/*
+	 * Make sure that the socket is not closed.  XXXMLG change error here?
+	 */
+	if (sock->fd == INVALID_SOCKET) {
+		UNLOCK(&sock->lock);
+		return (ISC_R_CONNREFUSED);
+	}
+
+	REQUIRE(buflist != NULL);
+	REQUIRE(!ISC_LIST_EMPTY(*buflist));
+	REQUIRE(task != NULL);
+	REQUIRE(action != NULL);
+
+	manager = sock->manager;
+	REQUIRE(VALID_MANAGER(manager));
+
+	iocount = isc_bufferlist_availablecount(buflist);
+	REQUIRE(iocount > 0);
+
+	INSIST(sock->bound);
+
+	dev = allocate_socketevent(sock, ISC_SOCKEVENT_RECVDONE, action, arg);
+	if (dev == NULL) {
+		UNLOCK(&sock->lock);
+		return (ISC_R_NOMEMORY);
+	}
+
+	/*
+	 * UDP sockets are always partial read
+	 */
+	if (sock->type == isc_sockettype_udp)
+		dev->minimum = 1;
+	else {
+		if (minimum == 0)
+			dev->minimum = iocount;
+		else
+			dev->minimum = minimum;
+	}
+
+	/*
+	 * Move each buffer from the passed in list to our internal one.
+	 */
+	buffer = ISC_LIST_HEAD(*buflist);
+	while (buffer != NULL) {
+		ISC_LIST_DEQUEUE(*buflist, buffer, link);
+		ISC_LIST_ENQUEUE(dev->bufferlist, buffer, link);
+		buffer = ISC_LIST_HEAD(*buflist);
+	}
+
+	ret = socket_recv(sock, dev, task, 0);
+
+	UNLOCK(&sock->lock);
+	return (ret);
+}
+
+isc_result_t
+isc__socket_recv(isc_socket_t *sock, isc_region_t *region,
+		 unsigned int minimum, isc_task_t *task,
+		 isc_taskaction_t action, const void *arg)
+{
+	isc_socketevent_t *dev;
+	isc_socketmgr_t *manager;
+	isc_result_t ret;
+
+	REQUIRE(VALID_SOCKET(sock));
+	LOCK(&sock->lock);
+	CONSISTENT(sock);
+
+	/*
+	 * make sure that the socket's not closed
+	 */
+	if (sock->fd == INVALID_SOCKET) {
+		UNLOCK(&sock->lock);
+		return (ISC_R_CONNREFUSED);
+	}
+	REQUIRE(action != NULL);
+
+	manager = sock->manager;
+	REQUIRE(VALID_MANAGER(manager));
+
+	INSIST(sock->bound);
+
+	dev = allocate_socketevent(sock, ISC_SOCKEVENT_RECVDONE, action, arg);
+	if (dev == NULL) {
+		UNLOCK(&sock->lock);
+		return (ISC_R_NOMEMORY);
+	}
+
+	ret = isc_socket_recv2(sock, region, minimum, task, dev, 0);
+	UNLOCK(&sock->lock);
+	return (ret);
+}
+
+isc_result_t
+isc__socket_recv2(isc_socket_t *sock, isc_region_t *region,
+		  unsigned int minimum, isc_task_t *task,
+		  isc_socketevent_t *event, unsigned int flags)
+{
+	isc_result_t ret;
+
+	REQUIRE(VALID_SOCKET(sock));
+	LOCK(&sock->lock);
+	CONSISTENT(sock);
+
+	event->result = ISC_R_UNEXPECTED;
+	event->ev_sender = sock;
+	/*
+	 * make sure that the socket's not closed
+	 */
+	if (sock->fd == INVALID_SOCKET) {
+		UNLOCK(&sock->lock);
+		return (ISC_R_CONNREFUSED);
+	}
+
+	ISC_LIST_INIT(event->bufferlist);
+	event->region = *region;
+	event->n = 0;
+	event->offset = 0;
+	event->attributes = 0;
+
+	/*
+	 * UDP sockets are always partial read.
+	 */
+	if (sock->type == isc_sockettype_udp)
+		event->minimum = 1;
+	else {
+		if (minimum == 0)
+			event->minimum = region->length;
+		else
+			event->minimum = minimum;
+	}
+
+	ret = socket_recv(sock, event, task, flags);
+	UNLOCK(&sock->lock);
+	return (ret);
+}
+
+/*
+ * Caller must have the socket locked.
+ */
+static isc_result_t
+socket_send(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
+	    isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
+	    unsigned int flags)
+{
+	int io_state;
+	int send_errno = 0;
+	int cc = 0;
+	isc_task_t *ntask = NULL;
+	isc_result_t result = ISC_R_SUCCESS;
+
+	dev->ev_sender = task;
+
+	set_dev_address(address, sock, dev);
+	if (pktinfo != NULL) {
+		socket_log(__LINE__, sock, NULL, TRACE, isc_msgcat, ISC_MSGSET_SOCKET,
+			   ISC_MSG_PKTINFOPROVIDED,
+			   "pktinfo structure provided, ifindex %u (set to 0)",
+			   pktinfo->ipi6_ifindex);
+
+		dev->attributes |= ISC_SOCKEVENTATTR_PKTINFO;
+		dev->pktinfo = *pktinfo;
+		/*
+		 * Set the pktinfo index to 0 here, to let the kernel decide
+		 * what interface it should send on.
+		 */
+		dev->pktinfo.ipi6_ifindex = 0;
+	}
+
+	io_state = startio_send(sock, dev, &cc, &send_errno);
+	switch (io_state) {
+	case DOIO_PENDING:	/* I/O started. Nothing more to do */
+	case DOIO_SOFT:
+		/*
+		 * We couldn't send all or part of the request right now, so
+		 * queue it unless ISC_SOCKFLAG_NORETRY is set.
+		 */
+		if ((flags & ISC_SOCKFLAG_NORETRY) == 0) {
+			isc_task_attach(task, &ntask);
+			dev->attributes |= ISC_SOCKEVENTATTR_ATTACHED;
+
+			/*
+			 * Enqueue the request.
+			 */
+			INSIST(!ISC_LINK_LINKED(dev, ev_link));
+			ISC_LIST_ENQUEUE(sock->send_list, dev, ev_link);
+
+			socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
+				   "socket_send: event %p -> task %p",
+				   dev, ntask);
+
+			if ((flags & ISC_SOCKFLAG_IMMEDIATE) != 0)
+				result = ISC_R_INPROGRESS;
+			break;
+		}
+
+	case DOIO_SUCCESS:
+		break;
+	}
+
+	return (result);
+}
+
+isc_result_t
+isc__socket_send(isc_socket_t *sock, isc_region_t *region,
+		 isc_task_t *task, isc_taskaction_t action, const void *arg)
+{
+	/*
+	 * REQUIRE() checking is performed in isc_socket_sendto().
+	 */
+	return (isc_socket_sendto(sock, region, task, action, arg, NULL,
+				  NULL));
+}
+
+isc_result_t
+isc__socket_sendto(isc_socket_t *sock, isc_region_t *region,
+		   isc_task_t *task, isc_taskaction_t action, const void *arg,
+		   isc_sockaddr_t *address, struct in6_pktinfo *pktinfo)
+{
+	isc_socketevent_t *dev;
+	isc_socketmgr_t *manager;
+	isc_result_t ret;
+
+	REQUIRE(VALID_SOCKET(sock));
+	REQUIRE(sock->type != isc_sockettype_fdwatch);
+
+	LOCK(&sock->lock);
+	CONSISTENT(sock);
+
+	/*
+	 * make sure that the socket's not closed
+	 */
+	if (sock->fd == INVALID_SOCKET) {
+		UNLOCK(&sock->lock);
+		return (ISC_R_CONNREFUSED);
+	}
+	REQUIRE(region != NULL);
+	REQUIRE(task != NULL);
+	REQUIRE(action != NULL);
+
+	manager = sock->manager;
+	REQUIRE(VALID_MANAGER(manager));
+
+	INSIST(sock->bound);
+
+	dev = allocate_socketevent(sock, ISC_SOCKEVENT_SENDDONE, action, arg);
+	if (dev == NULL) {
+		UNLOCK(&sock->lock);
+		return (ISC_R_NOMEMORY);
+	}
+	dev->region = *region;
+
+	ret = socket_send(sock, dev, task, address, pktinfo, 0);
+	UNLOCK(&sock->lock);
+	return (ret);
+}
+
+isc_result_t
+isc__socket_sendv(isc_socket_t *sock, isc_bufferlist_t *buflist,
+		  isc_task_t *task, isc_taskaction_t action, const void *arg)
+{
+	return (isc_socket_sendtov(sock, buflist, task, action, arg, NULL,
+				   NULL));
+}
+
+isc_result_t
+isc__socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist,
+		    isc_task_t *task, isc_taskaction_t action, const void *arg,
+		    isc_sockaddr_t *address, struct in6_pktinfo *pktinfo)
+{
+	isc_socketevent_t *dev;
+	isc_socketmgr_t *manager;
+	unsigned int iocount;
+	isc_buffer_t *buffer;
+	isc_result_t ret;
+
+	REQUIRE(VALID_SOCKET(sock));
+
+	LOCK(&sock->lock);
+	CONSISTENT(sock);
+
+	/*
+	 * make sure that the socket's not closed
+	 */
+	if (sock->fd == INVALID_SOCKET) {
+		UNLOCK(&sock->lock);
+		return (ISC_R_CONNREFUSED);
+	}
+	REQUIRE(buflist != NULL);
+	REQUIRE(!ISC_LIST_EMPTY(*buflist));
+	REQUIRE(task != NULL);
+	REQUIRE(action != NULL);
+
+	manager = sock->manager;
+	REQUIRE(VALID_MANAGER(manager));
+
+	iocount = isc_bufferlist_usedcount(buflist);
+	REQUIRE(iocount > 0);
+
+	dev = allocate_socketevent(sock, ISC_SOCKEVENT_SENDDONE, action, arg);
+	if (dev == NULL) {
+		UNLOCK(&sock->lock);
+		return (ISC_R_NOMEMORY);
+	}
+
+	/*
+	 * Move each buffer from the passed in list to our internal one.
+	 */
+	buffer = ISC_LIST_HEAD(*buflist);
+	while (buffer != NULL) {
+		ISC_LIST_DEQUEUE(*buflist, buffer, link);
+		ISC_LIST_ENQUEUE(dev->bufferlist, buffer, link);
+		buffer = ISC_LIST_HEAD(*buflist);
+	}
+
+	ret = socket_send(sock, dev, task, address, pktinfo, 0);
+	UNLOCK(&sock->lock);
+	return (ret);
+}
+
+isc_result_t
+isc__socket_sendto2(isc_socket_t *sock, isc_region_t *region,
+		    isc_task_t *task,
+		    isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
+		    isc_socketevent_t *event, unsigned int flags)
+{
+	isc_result_t ret;
+
+	REQUIRE(VALID_SOCKET(sock));
+	LOCK(&sock->lock);
+	CONSISTENT(sock);
+
+	REQUIRE((flags & ~(ISC_SOCKFLAG_IMMEDIATE|ISC_SOCKFLAG_NORETRY)) == 0);
+	if ((flags & ISC_SOCKFLAG_NORETRY) != 0)
+		REQUIRE(sock->type == isc_sockettype_udp);
+	event->ev_sender = sock;
+	event->result = ISC_R_UNEXPECTED;
+	/*
+	 * make sure that the socket's not closed
+	 */
+	if (sock->fd == INVALID_SOCKET) {
+		UNLOCK(&sock->lock);
+		return (ISC_R_CONNREFUSED);
+	}
+	ISC_LIST_INIT(event->bufferlist);
+	event->region = *region;
+	event->n = 0;
+	event->offset = 0;
+	event->attributes = 0;
+
+	ret = socket_send(sock, event, task, address, pktinfo, flags);
+	UNLOCK(&sock->lock);
+	return (ret);
+}
+
+isc_result_t
+isc__socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr,
+		 unsigned int options) {
+	int bind_errno;
+	char strbuf[ISC_STRERRORSIZE];
+	int on = 1;
+
+	REQUIRE(VALID_SOCKET(sock));
+	LOCK(&sock->lock);
+	CONSISTENT(sock);
+
+	/*
+	 * make sure that the socket's not closed
+	 */
+	if (sock->fd == INVALID_SOCKET) {
+		UNLOCK(&sock->lock);
+		return (ISC_R_CONNREFUSED);
+	}
+
+	INSIST(!sock->bound);
+
+	if (sock->pf != sockaddr->type.sa.sa_family) {
+		UNLOCK(&sock->lock);
+		return (ISC_R_FAMILYMISMATCH);
+	}
+	/*
+	 * Only set SO_REUSEADDR when we want a specific port.
+	 */
+	if ((options & ISC_SOCKET_REUSEADDRESS) != 0 &&
+	    isc_sockaddr_getport(sockaddr) != (in_port_t)0 &&
+	    setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, (char *)&on,
+		       sizeof(on)) < 0) {
+		UNEXPECTED_ERROR(__FILE__, __LINE__,
+				 "setsockopt(%d) %s", sock->fd,
+				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+						ISC_MSG_FAILED, "failed"));
+		/* Press on... */
+	}
+	if (bind(sock->fd, &sockaddr->type.sa, sockaddr->length) < 0) {
+		bind_errno = WSAGetLastError();
+		UNLOCK(&sock->lock);
+		switch (bind_errno) {
+		case WSAEACCES:
+			return (ISC_R_NOPERM);
+		case WSAEADDRNOTAVAIL:
+			return (ISC_R_ADDRNOTAVAIL);
+		case WSAEADDRINUSE:
+			return (ISC_R_ADDRINUSE);
+		case WSAEINVAL:
+			return (ISC_R_BOUND);
+		default:
+			isc__strerror(bind_errno, strbuf, sizeof(strbuf));
+			UNEXPECTED_ERROR(__FILE__, __LINE__, "bind: %s",
+					 strbuf);
+			return (ISC_R_UNEXPECTED);
+		}
+	}
+
+	socket_log(__LINE__, sock, sockaddr, TRACE,
+		   isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_BOUND, "bound");
+	sock->bound = 1;
+
+	UNLOCK(&sock->lock);
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc__socket_filter(isc_socket_t *sock, const char *filter) {
+	UNUSED(sock);
+	UNUSED(filter);
+
+	REQUIRE(VALID_SOCKET(sock));
+	return (ISC_R_NOTIMPLEMENTED);
+}
+
+/*
+ * Set up to listen on a given socket.  We do this by creating an internal
+ * event that will be dispatched when the socket has read activity.  The
+ * watcher will send the internal event to the task when there is a new
+ * connection.
+ *
+ * Unlike in read, we don't preallocate a done event here.  Every time there
+ * is a new connection we'll have to allocate a new one anyway, so we might
+ * as well keep things simple rather than having to track them.
+ */
+isc_result_t
+isc__socket_listen(isc_socket_t *sock, unsigned int backlog) {
+	char strbuf[ISC_STRERRORSIZE];
+
+	REQUIRE(VALID_SOCKET(sock));
+
+	LOCK(&sock->lock);
+	CONSISTENT(sock);
+
+	/*
+	 * make sure that the socket's not closed
+	 */
+	if (sock->fd == INVALID_SOCKET) {
+		UNLOCK(&sock->lock);
+		return (ISC_R_CONNREFUSED);
+	}
+
+	REQUIRE(!sock->listener);
+	REQUIRE(sock->bound);
+	REQUIRE(sock->type == isc_sockettype_tcp);
+
+	if (backlog == 0)
+		backlog = SOMAXCONN;
+
+	if (listen(sock->fd, (int)backlog) < 0) {
+		UNLOCK(&sock->lock);
+		isc__strerror(WSAGetLastError(), strbuf, sizeof(strbuf));
+
+		UNEXPECTED_ERROR(__FILE__, __LINE__, "listen: %s", strbuf);
+
+		return (ISC_R_UNEXPECTED);
+	}
+
+	socket_log(__LINE__, sock, NULL, TRACE,
+		   isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_BOUND, "listening");
+	sock->listener = 1;
+	_set_state(sock, SOCK_LISTEN);
+
+	UNLOCK(&sock->lock);
+	return (ISC_R_SUCCESS);
+}
+
+/*
+ * This should try to do aggressive accept() XXXMLG
+ */
+isc_result_t
+isc__socket_accept(isc_socket_t *sock,
+		   isc_task_t *task, isc_taskaction_t action, const void *arg)
+{
+	isc_socket_newconnev_t *adev;
+	isc_socketmgr_t *manager;
+	isc_task_t *ntask = NULL;
+	isc_socket_t *nsock;
+	isc_result_t result;
+	IoCompletionInfo *lpo;
+
+	REQUIRE(VALID_SOCKET(sock));
+
+	manager = sock->manager;
+	REQUIRE(VALID_MANAGER(manager));
+
+	LOCK(&sock->lock);
+	CONSISTENT(sock);
+
+	/*
+	 * make sure that the socket's not closed
+	 */
+	if (sock->fd == INVALID_SOCKET) {
+		UNLOCK(&sock->lock);
+		return (ISC_R_CONNREFUSED);
+	}
+
+	REQUIRE(sock->listener);
+
+	/*
+	 * Sender field is overloaded here with the task we will be sending
+	 * this event to.  Just before the actual event is delivered the
+	 * actual ev_sender will be touched up to be the socket.
+	 */
+	adev = (isc_socket_newconnev_t *)
+		isc_event_allocate(manager->mctx, task, ISC_SOCKEVENT_NEWCONN,
+				   action, arg, sizeof(*adev));
+	if (adev == NULL) {
+		UNLOCK(&sock->lock);
+		return (ISC_R_NOMEMORY);
+	}
+	ISC_LINK_INIT(adev, ev_link);
+
+	result = allocate_socket(manager, sock->type, &nsock);
+	if (result != ISC_R_SUCCESS) {
+		isc_event_free((isc_event_t **)&adev);
+		UNLOCK(&sock->lock);
+		return (result);
+	}
+
+	/*
+	 * AcceptEx() requires we pass in a socket.
+	 */
+	nsock->fd = socket(sock->pf, SOCK_STREAM, IPPROTO_TCP);
+	if (nsock->fd == INVALID_SOCKET) {
+		free_socket(&nsock, __LINE__);
+		isc_event_free((isc_event_t **)&adev);
+		UNLOCK(&sock->lock);
+		return (ISC_R_FAILURE); // XXXMLG need real error message
+	}
+
+	/*
+	 * Attach to socket and to task.
+	 */
+	isc_task_attach(task, &ntask);
+	if (isc_task_exiting(ntask)) {
+		isc_task_detach(&ntask);
+		isc_event_free(ISC_EVENT_PTR(&adev));
+		UNLOCK(&sock->lock);
+		return (ISC_R_SHUTTINGDOWN);
+	}
+	nsock->references++;
+
+	adev->ev_sender = ntask;
+	adev->newsocket = nsock;
+	_set_state(nsock, SOCK_ACCEPT);
+
+	/*
+	 * Queue io completion for an accept().
+	 */
+	lpo = (IoCompletionInfo *)HeapAlloc(hHeapHandle,
+					    HEAP_ZERO_MEMORY,
+					    sizeof(IoCompletionInfo));
+	RUNTIME_CHECK(lpo != NULL);
+	lpo->acceptbuffer = (void *)HeapAlloc(hHeapHandle, HEAP_ZERO_MEMORY,
+		(sizeof(SOCKADDR_STORAGE) + 16) * 2);
+	RUNTIME_CHECK(lpo->acceptbuffer != NULL);
+
+	lpo->adev = adev;
+	lpo->request_type = SOCKET_ACCEPT;
+
+	ISCAcceptEx(sock->fd,
+		    nsock->fd,				/* Accepted Socket */
+		    lpo->acceptbuffer,			/* Buffer for initial Recv */
+		    0,					/* Length of Buffer */
+		    sizeof(SOCKADDR_STORAGE) + 16,		/* Local address length + 16 */
+		    sizeof(SOCKADDR_STORAGE) + 16,		/* Remote address lengh + 16 */
+		    (LPDWORD)&lpo->received_bytes,	/* Bytes Recved */
+		    (LPOVERLAPPED)lpo			/* Overlapped structure */
+		    );
+	iocompletionport_update(nsock);
+
+	socket_log(__LINE__, sock, NULL, TRACE,
+		   isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_BOUND,
+		   "accepting for nsock %p fd %d", nsock, nsock->fd);
+
+	/*
+	 * Enqueue the event
+	 */
+	ISC_LIST_ENQUEUE(sock->accept_list, adev, ev_link);
+	sock->pending_accept++;
+	sock->pending_iocp++;
+
+	UNLOCK(&sock->lock);
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc__socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr,
+		    isc_task_t *task, isc_taskaction_t action, const void *arg)
+{
+	char strbuf[ISC_STRERRORSIZE];
+	isc_socket_connev_t *cdev;
+	isc_task_t *ntask = NULL;
+	isc_socketmgr_t *manager;
+	IoCompletionInfo *lpo;
+	int bind_errno;
+
+	REQUIRE(VALID_SOCKET(sock));
+	REQUIRE(addr != NULL);
+	REQUIRE(task != NULL);
+	REQUIRE(action != NULL);
+
+	manager = sock->manager;
+	REQUIRE(VALID_MANAGER(manager));
+	REQUIRE(addr != NULL);
+
+	if (isc_sockaddr_ismulticast(addr))
+		return (ISC_R_MULTICAST);
+
+	LOCK(&sock->lock);
+	CONSISTENT(sock);
+
+	/*
+	 * make sure that the socket's not closed
+	 */
+	if (sock->fd == INVALID_SOCKET) {
+		UNLOCK(&sock->lock);
+		return (ISC_R_CONNREFUSED);
+	}
+
+	/*
+	 * Windows sockets won't connect unless the socket is bound.
+	 */
+	if (!sock->bound) {
+		isc_sockaddr_t any;
+
+		isc_sockaddr_anyofpf(&any, isc_sockaddr_pf(addr));
+		if (bind(sock->fd, &any.type.sa, any.length) < 0) {
+			bind_errno = WSAGetLastError();
+			UNLOCK(&sock->lock);
+			switch (bind_errno) {
+			case WSAEACCES:
+				return (ISC_R_NOPERM);
+			case WSAEADDRNOTAVAIL:
+				return (ISC_R_ADDRNOTAVAIL);
+			case WSAEADDRINUSE:
+				return (ISC_R_ADDRINUSE);
+			case WSAEINVAL:
+				return (ISC_R_BOUND);
+			default:
+				isc__strerror(bind_errno, strbuf,
+					      sizeof(strbuf));
+				UNEXPECTED_ERROR(__FILE__, __LINE__,
+						 "bind: %s", strbuf);
+				return (ISC_R_UNEXPECTED);
+			}
+		}
+		sock->bound = 1;
+	}
+
+	REQUIRE(!sock->pending_connect);
+
+	cdev = (isc_socket_connev_t *)isc_event_allocate(manager->mctx, sock,
+							ISC_SOCKEVENT_CONNECT,
+							action,	arg,
+							sizeof(*cdev));
+	if (cdev == NULL) {
+		UNLOCK(&sock->lock);
+		return (ISC_R_NOMEMORY);
+	}
+	ISC_LINK_INIT(cdev, ev_link);
+
+	if (sock->type == isc_sockettype_tcp) {
+		/*
+		 * Queue io completion for an accept().
+		 */
+		lpo = (IoCompletionInfo *)HeapAlloc(hHeapHandle,
+						    HEAP_ZERO_MEMORY,
+						    sizeof(IoCompletionInfo));
+		lpo->cdev = cdev;
+		lpo->request_type = SOCKET_CONNECT;
+
+		sock->address = *addr;
+		ISCConnectEx(sock->fd, &addr->type.sa, addr->length,
+			NULL, 0, NULL, (LPOVERLAPPED)lpo);
+
+		/*
+		 * Attach to task.
+		 */
+		isc_task_attach(task, &ntask);
+		cdev->ev_sender = ntask;
+
+		sock->pending_connect = 1;
+		_set_state(sock, SOCK_CONNECT);
+
+		/*
+		 * Enqueue the request.
+		 */
+		sock->connect_ev = cdev;
+		sock->pending_iocp++;
+	} else {
+		WSAConnect(sock->fd, &addr->type.sa, addr->length, NULL, NULL, NULL, NULL);
+		cdev->result = ISC_R_SUCCESS;
+		isc_task_send(task, (isc_event_t **)&cdev);
+	}
+	CONSISTENT(sock);
+	UNLOCK(&sock->lock);
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc__socket_getpeername(isc_socket_t *sock, isc_sockaddr_t *addressp) {
+	isc_result_t result;
+
+	REQUIRE(VALID_SOCKET(sock));
+	REQUIRE(addressp != NULL);
+
+	LOCK(&sock->lock);
+	CONSISTENT(sock);
+
+	/*
+	 * make sure that the socket's not closed
+	 */
+	if (sock->fd == INVALID_SOCKET) {
+		UNLOCK(&sock->lock);
+		return (ISC_R_CONNREFUSED);
+	}
+
+	if (sock->connected) {
+		*addressp = sock->address;
+		result = ISC_R_SUCCESS;
+	} else {
+		result = ISC_R_NOTCONNECTED;
+	}
+
+	UNLOCK(&sock->lock);
+
+	return (result);
+}
+
+isc_result_t
+isc__socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp) {
+	ISC_SOCKADDR_LEN_T len;
+	isc_result_t result;
+	char strbuf[ISC_STRERRORSIZE];
+
+	REQUIRE(VALID_SOCKET(sock));
+	REQUIRE(addressp != NULL);
+
+	LOCK(&sock->lock);
+	CONSISTENT(sock);
+
+	/*
+	 * make sure that the socket's not closed
+	 */
+	if (sock->fd == INVALID_SOCKET) {
+		UNLOCK(&sock->lock);
+		return (ISC_R_CONNREFUSED);
+	}
+
+	if (!sock->bound) {
+		result = ISC_R_NOTBOUND;
+		goto out;
+	}
+
+	result = ISC_R_SUCCESS;
+
+	len = sizeof(addressp->type);
+	if (getsockname(sock->fd, &addressp->type.sa, (void *)&len) < 0) {
+		isc__strerror(WSAGetLastError(), strbuf, sizeof(strbuf));
+		UNEXPECTED_ERROR(__FILE__, __LINE__, "getsockname: %s",
+				 strbuf);
+		result = ISC_R_UNEXPECTED;
+		goto out;
+	}
+	addressp->length = (unsigned int)len;
+
+ out:
+	UNLOCK(&sock->lock);
+
+	return (result);
+}
+
+/*
+ * Run through the list of events on this socket, and cancel the ones
+ * queued for task "task" of type "how".  "how" is a bitmask.
+ */
+void
+isc__socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) {
+
+	REQUIRE(VALID_SOCKET(sock));
+
+	/*
+	 * Quick exit if there is nothing to do.  Don't even bother locking
+	 * in this case.
+	 */
+	if (how == 0)
+		return;
+
+	LOCK(&sock->lock);
+	CONSISTENT(sock);
+
+	/*
+	 * make sure that the socket's not closed
+	 */
+	if (sock->fd == INVALID_SOCKET) {
+		UNLOCK(&sock->lock);
+		return;
+	}
+
+	/*
+	 * All of these do the same thing, more or less.
+	 * Each will:
+	 *	o If the internal event is marked as "posted" try to
+	 *	  remove it from the task's queue.  If this fails, mark it
+	 *	  as canceled instead, and let the task clean it up later.
+	 *	o For each I/O request for that task of that type, post
+	 *	  its done event with status of "ISC_R_CANCELED".
+	 *	o Reset any state needed.
+	 */
+
+	if ((how & ISC_SOCKCANCEL_RECV) == ISC_SOCKCANCEL_RECV) {
+		isc_socketevent_t      *dev;
+		isc_socketevent_t      *next;
+		isc_task_t	       *current_task;
+
+		dev = ISC_LIST_HEAD(sock->recv_list);
+		while (dev != NULL) {
+			current_task = dev->ev_sender;
+			next = ISC_LIST_NEXT(dev, ev_link);
+			if ((task == NULL) || (task == current_task)) {
+				dev->result = ISC_R_CANCELED;
+				send_recvdone_event(sock, &dev);
+			}
+			dev = next;
+		}
+	}
+	how &= ~ISC_SOCKCANCEL_RECV;
+
+	if ((how & ISC_SOCKCANCEL_SEND) == ISC_SOCKCANCEL_SEND) {
+		isc_socketevent_t      *dev;
+		isc_socketevent_t      *next;
+		isc_task_t	       *current_task;
+
+		dev = ISC_LIST_HEAD(sock->send_list);
+
+		while (dev != NULL) {
+			current_task = dev->ev_sender;
+			next = ISC_LIST_NEXT(dev, ev_link);
+			if ((task == NULL) || (task == current_task)) {
+				dev->result = ISC_R_CANCELED;
+				send_senddone_event(sock, &dev);
+			}
+			dev = next;
+		}
+	}
+	how &= ~ISC_SOCKCANCEL_SEND;
+
+	if (((how & ISC_SOCKCANCEL_ACCEPT) == ISC_SOCKCANCEL_ACCEPT)
+	    && !ISC_LIST_EMPTY(sock->accept_list)) {
+		isc_socket_newconnev_t *dev;
+		isc_socket_newconnev_t *next;
+		isc_task_t	       *current_task;
+
+		dev = ISC_LIST_HEAD(sock->accept_list);
+		while (dev != NULL) {
+			current_task = dev->ev_sender;
+			next = ISC_LIST_NEXT(dev, ev_link);
+
+			if ((task == NULL) || (task == current_task)) {
+
+				dev->newsocket->references--;
+				closesocket(dev->newsocket->fd);
+				dev->newsocket->fd = INVALID_SOCKET;
+				free_socket(&dev->newsocket, __LINE__);
+
+				dev->result = ISC_R_CANCELED;
+				send_acceptdone_event(sock, &dev);
+			}
+
+			dev = next;
+		}
+	}
+	how &= ~ISC_SOCKCANCEL_ACCEPT;
+
+	/*
+	 * Connecting is not a list.
+	 */
+	if (((how & ISC_SOCKCANCEL_CONNECT) == ISC_SOCKCANCEL_CONNECT)
+	    && sock->connect_ev != NULL) {
+		isc_socket_connev_t    *dev;
+		isc_task_t	       *current_task;
+
+		INSIST(sock->pending_connect);
+
+		dev = sock->connect_ev;
+		current_task = dev->ev_sender;
+
+		if ((task == NULL) || (task == current_task)) {
+			closesocket(sock->fd);
+			sock->fd = INVALID_SOCKET;
+			_set_state(sock, SOCK_CLOSED);
+
+			sock->connect_ev = NULL;
+			dev->result = ISC_R_CANCELED;
+			send_connectdone_event(sock, &dev);
+		}
+	}
+	how &= ~ISC_SOCKCANCEL_CONNECT;
+
+	maybe_free_socket(&sock, __LINE__);
+}
+
+isc_sockettype_t
+isc__socket_gettype(isc_socket_t *sock) {
+	isc_sockettype_t type;
+
+	REQUIRE(VALID_SOCKET(sock));
+
+	LOCK(&sock->lock);
+
+	/*
+	 * make sure that the socket's not closed
+	 */
+	if (sock->fd == INVALID_SOCKET) {
+		UNLOCK(&sock->lock);
+		return (ISC_R_CONNREFUSED);
+	}
+
+	type = sock->type;
+	UNLOCK(&sock->lock);
+	return (type);
+}
+
+isc_boolean_t
+isc__socket_isbound(isc_socket_t *sock) {
+	isc_boolean_t val;
+
+	REQUIRE(VALID_SOCKET(sock));
+
+	LOCK(&sock->lock);
+	CONSISTENT(sock);
+
+	/*
+	 * make sure that the socket's not closed
+	 */
+	if (sock->fd == INVALID_SOCKET) {
+		UNLOCK(&sock->lock);
+		return (ISC_FALSE);
+	}
+
+	val = ((sock->bound) ? ISC_TRUE : ISC_FALSE);
+	UNLOCK(&sock->lock);
+
+	return (val);
+}
+
+void
+isc__socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes) {
+#if defined(IPV6_V6ONLY)
+	int onoff = yes ? 1 : 0;
+#else
+	UNUSED(yes);
+#endif
+
+	REQUIRE(VALID_SOCKET(sock));
+
+#ifdef IPV6_V6ONLY
+	if (sock->pf == AF_INET6) {
+		(void)setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY,
+				 (char *)&onoff, sizeof(onoff));
+	}
+#endif
+}
+
+void
+isc__socket_cleanunix(isc_sockaddr_t *addr, isc_boolean_t active) {
+	UNUSED(addr);
+	UNUSED(active);
+}
+
+isc_result_t
+isc__socket_permunix(isc_sockaddr_t *addr, isc_uint32_t perm,
+		     isc_uint32_t owner,	isc_uint32_t group)
+{
+	UNUSED(addr);
+	UNUSED(perm);
+	UNUSED(owner);
+	UNUSED(group);
+	return (ISC_R_NOTIMPLEMENTED);
+}
+
+void
+isc__socket_setname(isc_socket_t *socket, const char *name, void *tag) {
+
+	/*
+	 * Name 'socket'.
+	 */
+
+	REQUIRE(VALID_SOCKET(socket));
+
+	LOCK(&socket->lock);
+	memset(socket->name, 0, sizeof(socket->name));
+	strncpy(socket->name, name, sizeof(socket->name) - 1);
+	socket->tag = tag;
+	UNLOCK(&socket->lock);
+}
+
+const char *
+isc__socket_getname(isc_socket_t *socket) {
+	return (socket->name);
+}
+
+void *
+isc__socket_gettag(isc_socket_t *socket) {
+	return (socket->tag);
+}
+
+void
+isc__socketmgr_setreserved(isc_socketmgr_t *manager, isc_uint32_t reserved) {
+	UNUSED(manager);
+	UNUSED(reserved);
+}
+
+void
+isc___socketmgr_maxudp(isc_socketmgr_t *manager, int maxudp) {
+
+	UNUSED(manager);
+	UNUSED(maxudp);
+}
+
+#ifdef HAVE_LIBXML2
+
+static const char *
+_socktype(isc_sockettype_t type)
+{
+	if (type == isc_sockettype_udp)
+		return ("udp");
+	else if (type == isc_sockettype_tcp)
+		return ("tcp");
+	else if (type == isc_sockettype_unix)
+		return ("unix");
+	else if (type == isc_sockettype_fdwatch)
+		return ("fdwatch");
+	else
+		return ("not-initialized");
+}
+
+void
+isc_socketmgr_renderxml(isc_socketmgr_t *mgr, xmlTextWriterPtr writer)
+{
+	isc_socket_t *sock;
+	char peerbuf[ISC_SOCKADDR_FORMATSIZE];
+	isc_sockaddr_t addr;
+	ISC_SOCKADDR_LEN_T len;
+
+	LOCK(&mgr->lock);
+
+#ifndef ISC_PLATFORM_USETHREADS
+	xmlTextWriterStartElement(writer, ISC_XMLCHAR "references");
+	xmlTextWriterWriteFormatString(writer, "%d", mgr->refs);
+	xmlTextWriterEndElement(writer);
+#endif
+
+	xmlTextWriterStartElement(writer, ISC_XMLCHAR "sockets");
+	sock = ISC_LIST_HEAD(mgr->socklist);
+	while (sock != NULL) {
+		LOCK(&sock->lock);
+		xmlTextWriterStartElement(writer, ISC_XMLCHAR "socket");
+
+		xmlTextWriterStartElement(writer, ISC_XMLCHAR "id");
+		xmlTextWriterWriteFormatString(writer, "%p", sock);
+		xmlTextWriterEndElement(writer);
+
+		if (sock->name[0] != 0) {
+			xmlTextWriterStartElement(writer, ISC_XMLCHAR "name");
+			xmlTextWriterWriteFormatString(writer, "%s",
+						       sock->name);
+			xmlTextWriterEndElement(writer); /* name */
+		}
+
+		xmlTextWriterStartElement(writer, ISC_XMLCHAR "references");
+		xmlTextWriterWriteFormatString(writer, "%d", sock->references);
+		xmlTextWriterEndElement(writer);
+
+		xmlTextWriterWriteElement(writer, ISC_XMLCHAR "type",
+					  ISC_XMLCHAR _socktype(sock->type));
+
+		if (sock->connected) {
+			isc_sockaddr_format(&sock->address, peerbuf,
+					    sizeof(peerbuf));
+			xmlTextWriterWriteElement(writer,
+						  ISC_XMLCHAR "peer-address",
+						  ISC_XMLCHAR peerbuf);
+		}
+
+		len = sizeof(addr);
+		if (getsockname(sock->fd, &addr.type.sa, (void *)&len) == 0) {
+			isc_sockaddr_format(&addr, peerbuf, sizeof(peerbuf));
+			xmlTextWriterWriteElement(writer,
+						  ISC_XMLCHAR "local-address",
+						  ISC_XMLCHAR peerbuf);
+		}
+
+		xmlTextWriterStartElement(writer, ISC_XMLCHAR "states");
+		if (sock->pending_recv)
+			xmlTextWriterWriteElement(writer, ISC_XMLCHAR "state",
+						ISC_XMLCHAR "pending-receive");
+		if (sock->pending_send)
+			xmlTextWriterWriteElement(writer, ISC_XMLCHAR "state",
+						  ISC_XMLCHAR "pending-send");
+		if (sock->pending_accept)
+			xmlTextWriterWriteElement(writer, ISC_XMLCHAR "state",
+						 ISC_XMLCHAR "pending_accept");
+		if (sock->listener)
+			xmlTextWriterWriteElement(writer, ISC_XMLCHAR "state",
+						  ISC_XMLCHAR "listener");
+		if (sock->connected)
+			xmlTextWriterWriteElement(writer, ISC_XMLCHAR "state",
+						  ISC_XMLCHAR "connected");
+		if (sock->pending_connect)
+			xmlTextWriterWriteElement(writer, ISC_XMLCHAR "state",
+						  ISC_XMLCHAR "connecting");
+		if (sock->bound)
+			xmlTextWriterWriteElement(writer, ISC_XMLCHAR "state",
+						  ISC_XMLCHAR "bound");
+
+		xmlTextWriterEndElement(writer); /* states */
+
+		xmlTextWriterEndElement(writer); /* socket */
+
+		UNLOCK(&sock->lock);
+		sock = ISC_LIST_NEXT(sock, link);
+	}
+	xmlTextWriterEndElement(writer); /* sockets */
+
+	UNLOCK(&mgr->lock);
+}
+#endif /* HAVE_LIBXML2 */
diff --git a/src/lib/bind9/win32/stdio.c b/src/lib/bind9/win32/stdio.c
new file mode 100644
index 0000000..c04d580
--- /dev/null
+++ b/src/lib/bind9/win32/stdio.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2004, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: stdio.c,v 1.6 2007-06-19 23:47:19 tbox Exp $ */
+
+#include <config.h>
+
+#include <io.h>
+#include <errno.h>
+
+#include <isc/stdio.h>
+
+#include "errno2result.h"
+
+isc_result_t
+isc_stdio_open(const char *filename, const char *mode, FILE **fp) {
+	FILE *f;
+
+	f = fopen(filename, mode);
+	if (f == NULL)
+		return (isc__errno2result(errno));
+	*fp = f;
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_stdio_close(FILE *f) {
+	int r;
+
+	r = fclose(f);
+	if (r == 0)
+		return (ISC_R_SUCCESS);
+	else
+		return (isc__errno2result(errno));
+}
+
+isc_result_t
+isc_stdio_seek(FILE *f, long offset, int whence) {
+	int r;
+
+	r = fseek(f, offset, whence);
+	if (r == 0)
+		return (ISC_R_SUCCESS);
+	else
+		return (isc__errno2result(errno));
+}
+
+isc_result_t
+isc_stdio_read(void *ptr, size_t size, size_t nmemb, FILE *f, size_t *nret) {
+	isc_result_t result = ISC_R_SUCCESS;
+	size_t r;
+
+	clearerr(f);
+	r = fread(ptr, size, nmemb, f);
+	if (r != nmemb) {
+		if (feof(f))
+			result = ISC_R_EOF;
+		else
+			result = isc__errno2result(errno);
+	}
+	if (nret != NULL)
+		*nret = r;
+	return (result);
+}
+
+isc_result_t
+isc_stdio_write(const void *ptr, size_t size, size_t nmemb, FILE *f,
+	       size_t *nret)
+{
+	isc_result_t result = ISC_R_SUCCESS;
+	size_t r;
+
+	clearerr(f);
+	r = fwrite(ptr, size, nmemb, f);
+	if (r != nmemb)
+		result = isc__errno2result(errno);
+	if (nret != NULL)
+		*nret = r;
+	return (result);
+}
+
+isc_result_t
+isc_stdio_flush(FILE *f) {
+	int r;
+
+	r = fflush(f);
+	if (r == 0)
+		return (ISC_R_SUCCESS);
+	else
+		return (isc__errno2result(errno));
+}
+
+isc_result_t
+isc_stdio_sync(FILE *f) {
+	int r;
+
+	r = _commit(_fileno(f));
+	if (r == 0)
+		return (ISC_R_SUCCESS);
+	else
+		return (isc__errno2result(errno));
+}
+
diff --git a/src/lib/bind9/win32/stdtime.c b/src/lib/bind9/win32/stdtime.c
new file mode 100644
index 0000000..f01e68c
--- /dev/null
+++ b/src/lib/bind9/win32/stdtime.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2004, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: stdtime.c,v 1.12 2007-06-19 23:47:19 tbox Exp $ */
+
+#include <config.h>
+
+#include <time.h>
+
+#include <isc/assertions.h>
+#include <isc/stdtime.h>
+#include <isc/util.h>
+
+void
+isc_stdtime_get(isc_stdtime_t *t) {
+	/*
+	 * Set 't' to the number of seconds past 00:00:00 UTC, January 1, 1970.
+	 */
+
+	REQUIRE(t != NULL);
+
+	(void)time(t);
+}
diff --git a/src/lib/bind9/win32/strerror.c b/src/lib/bind9/win32/strerror.c
new file mode 100644
index 0000000..7bfbbaa
--- /dev/null
+++ b/src/lib/bind9/win32/strerror.c
@@ -0,0 +1,459 @@
+/*
+ * Copyright (C) 2004, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2001, 2002  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: strerror.c,v 1.8 2007-06-19 23:47:19 tbox Exp $ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <winsock2.h>
+
+#include <isc/mutex.h>
+#include <isc/once.h>
+#include <isc/print.h>
+#include <isc/strerror.h>
+#include <isc/util.h>
+
+/*
+ * Forward declarations
+ */
+
+char *
+FormatError(int error);
+
+char *
+GetWSAErrorMessage(int errval);
+
+char *
+NTstrerror(int err, BOOL *bfreebuf);
+
+/*
+ * We need to do this this way for profiled locks.
+ */
+
+static isc_mutex_t isc_strerror_lock;
+static void init_lock(void) {
+	RUNTIME_CHECK(isc_mutex_init(&isc_strerror_lock) == ISC_R_SUCCESS);
+}
+
+/*
+ * This routine needs to free up any buffer allocated by FormatMessage
+ * if that routine gets used.
+ */
+
+void
+isc__strerror(int num, char *buf, size_t size) {
+	char *msg;
+	BOOL freebuf;
+	unsigned int unum = num;
+	static isc_once_t once = ISC_ONCE_INIT;
+
+	REQUIRE(buf != NULL);
+
+	RUNTIME_CHECK(isc_once_do(&once, init_lock) == ISC_R_SUCCESS);
+
+	LOCK(&isc_strerror_lock);
+	freebuf = FALSE;
+	msg = NTstrerror(num, &freebuf);
+	if (msg != NULL)
+		snprintf(buf, size, "%s", msg);
+	else
+		snprintf(buf, size, "Unknown error: %u", unum);
+	if(freebuf && msg != NULL) {
+		LocalFree(msg);
+	}
+	UNLOCK(&isc_strerror_lock);
+}
+
+/*
+ * Note this will cause a memory leak unless the memory allocated here
+ * is freed by calling LocalFree.  isc__strerror does this before unlocking.
+ * This only gets called if there is a system type of error and will likely
+ * be an unusual event.
+ */
+char *
+FormatError(int error) {
+	LPVOID lpMsgBuf = NULL;
+	FormatMessage( 
+		FORMAT_MESSAGE_ALLOCATE_BUFFER | 
+		FORMAT_MESSAGE_FROM_SYSTEM | 
+		FORMAT_MESSAGE_IGNORE_INSERTS,
+		NULL,
+		error,
+		/* Default language */
+		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+		(LPTSTR) &lpMsgBuf,
+		0,
+		NULL); 
+
+	return (lpMsgBuf);
+}
+
+/*
+ * This routine checks the error value and calls the WSA Windows Sockets
+ * Error message function GetWSAErrorMessage below if it's within that range
+ * since those messages are not available in the system error messages.
+ */
+char *
+NTstrerror(int err, BOOL *bfreebuf) {
+	char *retmsg = NULL;
+
+	/* Copy the error value first in case of other errors */	
+	DWORD errval = err; 
+
+	*bfreebuf = FALSE;
+
+	/* Get the Winsock2 error messages */
+	if (errval >= WSABASEERR && errval <= (WSABASEERR + 1015)) {
+		retmsg = GetWSAErrorMessage(errval);
+		if (retmsg != NULL)
+			return (retmsg);
+	}
+	/*
+	 * If it's not one of the standard Unix error codes,
+	 * try a system error message
+	 */
+	if (errval > (DWORD) _sys_nerr) {
+		*bfreebuf = TRUE;
+		return (FormatError(errval));
+	} else {
+		return (strerror(errval));
+	}
+}
+
+/*
+ * This is a replacement for perror
+ */
+void __cdecl
+NTperror(char *errmsg) {
+	/* Copy the error value first in case of other errors */
+	int errval = errno; 
+	BOOL bfreebuf = FALSE;
+	char *msg;
+
+	msg = NTstrerror(errval, &bfreebuf);
+	fprintf(stderr, "%s: %s\n", errmsg, msg);
+	if(bfreebuf == TRUE) {
+		LocalFree(msg);
+	}
+
+}
+
+/*
+ * Return the error string related to Winsock2 errors.
+ * This function is necessary since FormatMessage knows nothing about them
+ * and there is no function to get them.
+ */
+char *
+GetWSAErrorMessage(int errval) {
+	char *msg;
+
+	switch (errval) {
+
+	case WSAEINTR:
+		msg = "Interrupted system call";
+		break;
+
+	case WSAEBADF:
+		msg = "Bad file number";
+		break;
+
+	case WSAEACCES:
+		msg = "Permission denied";
+		break;
+
+	case WSAEFAULT:
+		msg = "Bad address";
+		break;
+
+	case WSAEINVAL:
+		msg = "Invalid argument";
+		break;
+
+	case WSAEMFILE:
+		msg = "Too many open sockets";
+		break;
+
+	case WSAEWOULDBLOCK:
+		msg = "Operation would block";
+		break;
+
+	case WSAEINPROGRESS:
+		msg = "Operation now in progress";
+		break;
+
+	case WSAEALREADY:
+		msg = "Operation already in progress";
+		break;
+
+	case WSAENOTSOCK:
+		msg = "Socket operation on non-socket";
+		break;
+
+	case WSAEDESTADDRREQ:
+		msg = "Destination address required";
+		break;
+
+	case WSAEMSGSIZE:
+		msg = "Message too long";
+		break;
+
+	case WSAEPROTOTYPE:
+		msg = "Protocol wrong type for socket";
+		break;
+
+	case WSAENOPROTOOPT:
+		msg = "Bad protocol option";
+		break;
+
+	case WSAEPROTONOSUPPORT:
+		msg = "Protocol not supported";
+		break;
+
+	case WSAESOCKTNOSUPPORT:
+		msg = "Socket type not supported";
+		break;
+
+	case WSAEOPNOTSUPP:
+		msg = "Operation not supported on socket";
+		break;
+
+	case WSAEPFNOSUPPORT:
+		msg = "Protocol family not supported";
+		break;
+
+	case WSAEAFNOSUPPORT:
+		msg = "Address family not supported";
+		break;
+
+	case WSAEADDRINUSE:
+		msg = "Address already in use";
+		break;
+
+	case WSAEADDRNOTAVAIL:
+		msg = "Can't assign requested address";
+		break;
+
+	case WSAENETDOWN:
+		msg = "Network is down";
+		break;
+
+	case WSAENETUNREACH:
+		msg = "Network is unreachable";
+		break;
+
+	case WSAENETRESET:
+		msg = "Net connection reset";
+		break;
+
+	case WSAECONNABORTED:
+		msg = "Software caused connection abort";
+		break;
+
+	case WSAECONNRESET:
+		msg = "Connection reset by peer";
+		break;
+
+	case WSAENOBUFS:
+		msg = "No buffer space available";
+		break;
+
+	case WSAEISCONN:
+		msg = "Socket is already connected";
+		break;
+
+	case WSAENOTCONN:
+		msg = "Socket is not connected";
+		break;
+
+	case WSAESHUTDOWN:
+		msg = "Can't send after socket shutdown";
+		break;
+
+	case WSAETOOMANYREFS:
+		msg = "Too many references: can't splice";
+		break;
+
+	case WSAETIMEDOUT:
+		msg = "Connection timed out";
+		break;
+
+	case WSAECONNREFUSED:
+		msg = "Connection refused";
+		break;
+
+	case WSAELOOP:
+		msg = "Too many levels of symbolic links";
+		break;
+
+	case WSAENAMETOOLONG:
+		msg = "File name too long";
+		break;
+
+	case WSAEHOSTDOWN:
+		msg = "Host is down";
+		break;
+
+	case WSAEHOSTUNREACH:
+		msg = "No route to host";
+		break;
+
+	case WSAENOTEMPTY:
+		msg = "Directory not empty";
+		break;
+
+	case WSAEPROCLIM:
+		msg = "Too many processes";
+		break;
+
+	case WSAEUSERS:
+		msg = "Too many users";
+		break;
+
+	case WSAEDQUOT:
+		msg = "Disc quota exceeded";
+		break;
+
+	case WSAESTALE:
+		msg = "Stale NFS file handle";
+		break;
+
+	case WSAEREMOTE:
+		msg = "Too many levels of remote in path";
+		break;
+
+	case WSASYSNOTREADY:
+		msg = "Network system is unavailable";
+		break;
+
+	case WSAVERNOTSUPPORTED:
+		msg = "Winsock version out of range";
+		break;
+
+	case WSANOTINITIALISED:
+		msg = "WSAStartup not yet called";
+		break;
+
+	case WSAEDISCON:
+		msg = "Graceful shutdown in progress";
+		break;
+/*
+	case WSAHOST_NOT_FOUND:
+		msg = "Host not found";
+		break;
+
+	case WSANO_DATA:
+		msg = "No host data of that type was found";
+		break;
+*/
+	default:
+		msg = NULL;
+		break;
+	}
+	return (msg);
+}
+
+/*
+ * These error messages are more informative about CryptAPI Errors than the
+ * standard error messages
+ */
+
+char *
+GetCryptErrorMessage(int errval) {
+	char *msg;
+
+	switch (errval) {
+
+	case NTE_BAD_FLAGS:
+		msg = "The dwFlags parameter has an illegal value.";
+		break;
+	case NTE_BAD_KEYSET:
+		msg = "The Registry entry for the key container "
+			"could not be opened and may not exist.";
+		break;
+	case NTE_BAD_KEYSET_PARAM:
+		msg = "The pszContainer or pszProvider parameter "
+			"is set to an illegal value.";
+		break;
+	case NTE_BAD_PROV_TYPE:
+		msg = "The value of the dwProvType parameter is out "
+			"of range. All provider types must be from "
+			"1 to 999, inclusive.";
+		break;
+	case NTE_BAD_SIGNATURE:
+		msg = "The provider DLL signature did not verify "
+			"correctly. Either the DLL or the digital "
+			"signature has been tampered with.";
+		break;
+	case NTE_EXISTS:
+		msg = "The dwFlags parameter is CRYPT_NEWKEYSET, but the key"
+		      " container already exists.";
+		break;
+	case NTE_KEYSET_ENTRY_BAD:
+		msg = "The Registry entry for the pszContainer key container "
+		      "was found (in the HKEY_CURRENT_USER window), but is "
+		      "corrupt. See the section System Administration for "
+		      " etails about CryptoAPI's Registry usage.";
+		break;
+	case NTE_KEYSET_NOT_DEF:
+		msg = "No Registry entry exists in the HKEY_CURRENT_USER "
+			"window for the key container specified by "
+			"pszContainer.";
+		break;
+	case NTE_NO_MEMORY:
+		msg = "The CSP ran out of memory during the operation.";
+		break;
+	case NTE_PROV_DLL_NOT_FOUND:
+		msg = "The provider DLL file does not exist or is not on the "
+		      "current path.";
+		break;
+	case NTE_PROV_TYPE_ENTRY_BAD:
+		msg = "The Registry entry for the provider type specified by "
+		      "dwProvType is corrupt. This error may relate to "
+		      "either the user default CSP list or the machine "
+		      "default CSP list. See the section System "
+		      "Administration for details about CryptoAPI's "
+		      "Registry usage.";
+		break;
+	case NTE_PROV_TYPE_NO_MATCH:
+		msg = "The provider type specified by dwProvType does not "
+		      "match the provider type found in the Registry. Note "
+		      "that this error can only occur when pszProvider "
+		      "specifies an actual CSP name.";
+		break;
+	case NTE_PROV_TYPE_NOT_DEF:
+		msg = "No Registry entry exists for the provider type "
+		      "specified by dwProvType.";
+		break;
+	case NTE_PROVIDER_DLL_FAIL:
+		msg = "The provider DLL file could not be loaded, and "
+		      "may not exist. If it exists, then the file is "
+		      "not a valid DLL.";
+		break;
+	case NTE_SIGNATURE_FILE_BAD:
+		msg = "An error occurred while loading the DLL file image, "
+		      "prior to verifying its signature.";
+		break;
+
+	default:
+		msg = NULL;
+		break;
+	}
+	return msg;
+}
+
diff --git a/src/lib/bind9/win32/syslog.c b/src/lib/bind9/win32/syslog.c
new file mode 100644
index 0000000..588028d
--- /dev/null
+++ b/src/lib/bind9/win32/syslog.c
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2004, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2001-2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: syslog.c,v 1.10 2007-06-19 23:47:19 tbox Exp $ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <windows.h>
+#include <string.h>
+#include <stdlib.h>
+#include <syslog.h>
+
+#include <isc/bindevt.h>
+#include <isc/result.h>
+#include <isc/syslog.h>
+#include <isc/util.h>
+
+static HANDLE hAppLog = NULL;
+static FILE *log_stream;
+static int debug_level = 0;
+
+static struct dsn_c_pvt_sfnt {
+	int val;
+	const char *strval;
+} facilities[] = {
+	{ LOG_KERN,		"kern" },
+	{ LOG_USER,		"user" },
+	{ LOG_MAIL,		"mail" },
+	{ LOG_DAEMON,		"daemon" },
+	{ LOG_AUTH,		"auth" },
+	{ LOG_SYSLOG,		"syslog" },
+	{ LOG_LPR,		"lpr" },
+#ifdef LOG_NEWS
+	{ LOG_NEWS,		"news" },
+#endif
+#ifdef LOG_UUCP
+	{ LOG_UUCP,		"uucp" },
+#endif
+#ifdef LOG_CRON
+	{ LOG_CRON,		"cron" },
+#endif
+#ifdef LOG_AUTHPRIV
+	{ LOG_AUTHPRIV,		"authpriv" },
+#endif
+#ifdef LOG_FTP
+	{ LOG_FTP,		"ftp" },
+#endif
+	{ LOG_LOCAL0,		"local0"},
+	{ LOG_LOCAL1,		"local1"},
+	{ LOG_LOCAL2,		"local2"},
+	{ LOG_LOCAL3,		"local3"},
+	{ LOG_LOCAL4,		"local4"},
+	{ LOG_LOCAL5,		"local5"},
+	{ LOG_LOCAL6,		"local6"},
+	{ LOG_LOCAL7,		"local7"},
+	{ 0,			NULL }
+};
+
+isc_result_t
+isc_syslog_facilityfromstring(const char *str, int *facilityp) {
+	int i;
+
+	REQUIRE(str != NULL);
+	REQUIRE(facilityp != NULL);
+
+	for (i = 0; facilities[i].strval != NULL; i++) {
+		if (strcasecmp(facilities[i].strval, str) == 0) {
+			*facilityp = facilities[i].val;
+			return (ISC_R_SUCCESS);
+		}
+	}
+	return (ISC_R_NOTFOUND);
+}
+
+/*
+ * Log to the NT Event Log
+ */
+void
+syslog(int level, const char *fmt, ...) {
+	va_list ap;
+	char buf[1024];
+	char *str[1];
+
+	str[0] = buf;
+
+	va_start(ap, fmt);
+	vsprintf(buf, fmt, ap);
+	va_end(ap);
+
+	/* Make sure that the channel is open to write the event */
+	if (hAppLog != NULL) {
+		switch (level) {
+		case LOG_INFO:
+		case LOG_NOTICE:
+		case LOG_DEBUG:
+			ReportEvent(hAppLog, EVENTLOG_INFORMATION_TYPE, 0,
+				    BIND_INFO_MSG, NULL, 1, 0, str, NULL);
+			break;
+		case LOG_WARNING:
+			ReportEvent(hAppLog, EVENTLOG_WARNING_TYPE, 0,
+				    BIND_WARN_MSG, NULL, 1, 0, str, NULL);
+			break;
+		default:
+			ReportEvent(hAppLog, EVENTLOG_ERROR_TYPE, 0,
+				    BIND_ERR_MSG, NULL, 1, 0, str, NULL);
+			break;
+		}
+	}
+}
+
+/*
+ * Initialize event logging
+ */
+void
+openlog(const char *name, int flags, ...) {
+	/* Get a handle to the Application event log */
+	hAppLog = RegisterEventSource(NULL, name);
+}
+
+/*
+ * Close the Handle to the application Event Log
+ * We don't care whether or not we succeeded so ignore return values
+ * In fact if we failed then we would have nowhere to put the message
+ */
+void
+closelog() {
+	DeregisterEventSource(hAppLog);
+}
+
+/*
+ * Keep event logging synced with the current debug level
+ */
+void
+ModifyLogLevel(int level) {
+	debug_level = level;	
+}
+
+/*
+ * Initialize logging for the port section of libbind.
+ * Piggyback onto stream given.
+ */
+void
+InitNTLogging(FILE *stream, int debug) {
+	log_stream = stream;
+	ModifyLogLevel(debug);
+}
+/*
+ * This function is for reporting errors to the application
+ * event log in case the regular syslog is not available
+ * mainly during startup. It should not be used under normal
+ * circumstances.
+ */
+void
+NTReportError(const char *name, const char *str) {
+	HANDLE hNTAppLog = NULL;
+	const char *buf[1];
+
+	buf[0] = str;
+
+	hNTAppLog = RegisterEventSource(NULL, name);
+
+	ReportEvent(hNTAppLog, EVENTLOG_ERROR_TYPE, 0,
+		    BIND_ERR_MSG, NULL, 1, 0, buf, NULL);
+
+	DeregisterEventSource(hNTAppLog);
+}
diff --git a/src/lib/bind9/win32/syslog.h b/src/lib/bind9/win32/syslog.h
new file mode 100644
index 0000000..132be86
--- /dev/null
+++ b/src/lib/bind9/win32/syslog.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2004, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2001, 2002  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: syslog.h,v 1.7 2007-06-19 23:47:19 tbox Exp $ */
+
+#ifndef _SYSLOG_H
+#define _SYSLOG_H
+
+#include <stdio.h>
+
+/* Constant definitions for openlog() */
+#define LOG_PID		1
+#define LOG_CONS	2
+/* NT event log does not support facility level */
+#define LOG_KERN	0
+#define LOG_USER	0
+#define LOG_MAIL	0
+#define LOG_DAEMON	0
+#define LOG_AUTH	0
+#define LOG_SYSLOG	0
+#define LOG_LPR		0
+#define LOG_LOCAL0	0
+#define LOG_LOCAL1	0
+#define LOG_LOCAL2	0
+#define LOG_LOCAL3	0
+#define LOG_LOCAL4	0
+#define LOG_LOCAL5	0
+#define LOG_LOCAL6	0
+#define LOG_LOCAL7	0
+
+#define LOG_EMERG       0       /* system is unusable */
+#define LOG_ALERT       1       /* action must be taken immediately */
+#define LOG_CRIT        2       /* critical conditions */
+#define LOG_ERR         3       /* error conditions */
+#define LOG_WARNING     4       /* warning conditions */
+#define LOG_NOTICE      5       /* normal but signification condition */
+#define LOG_INFO        6       /* informational */
+#define LOG_DEBUG       7       /* debug-level messages */
+
+void
+syslog(int level, const char *fmt, ...);
+
+void
+openlog(const char *, int, ...);
+
+void
+closelog(void);
+
+void
+ModifyLogLevel(int level);
+
+void
+InitNTLogging(FILE *, int);
+
+void
+NTReportError(const char *, const char *);
+/*
+ * Include the event codes required for logging.
+ */
+#include <isc/bindevt.h>
+
+#endif
diff --git a/src/lib/bind9/win32/thread.c b/src/lib/bind9/win32/thread.c
new file mode 100644
index 0000000..63e909b
--- /dev/null
+++ b/src/lib/bind9/win32/thread.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: thread.c,v 1.24 2007-06-19 23:47:19 tbox Exp $ */
+
+#include <config.h>
+
+#include <process.h>
+
+#include <isc/thread.h>
+
+isc_result_t
+isc_thread_create(isc_threadfunc_t start, isc_threadarg_t arg,
+		  isc_thread_t *threadp)
+{
+	isc_thread_t thread;
+	unsigned int id;
+
+	thread = (isc_thread_t)_beginthreadex(NULL, 0, start, arg, 0, &id);
+	if (thread == NULL) {
+		/* XXX */
+		return (ISC_R_UNEXPECTED);
+	}
+
+	*threadp = thread;
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_thread_join(isc_thread_t thread, isc_threadresult_t *rp) {
+	DWORD result;
+
+	result = WaitForSingleObject(thread, INFINITE);
+	if (result != WAIT_OBJECT_0) {
+		/* XXX */
+		return (ISC_R_UNEXPECTED);
+	}
+	if (rp != NULL && !GetExitCodeThread(thread, rp)) {
+		/* XXX */
+		return (ISC_R_UNEXPECTED);
+	}
+	(void)CloseHandle(thread);
+
+	return (ISC_R_SUCCESS);
+}
+
+void
+isc_thread_setconcurrency(unsigned int level) {
+	/*
+	 * This is unnecessary on Win32 systems, but is here so that the
+	 * call exists
+	 */
+}
+
+void *
+isc_thread_key_getspecific(isc_thread_key_t key) {
+	return(TlsGetValue(key));
+}
+
+int
+isc_thread_key_setspecific(isc_thread_key_t key, void *value) {
+	return (TlsSetValue(key, value) ? 0 : GetLastError());
+}
+
+int
+isc_thread_key_create(isc_thread_key_t *key, void (*func)(void *)) {
+	*key = TlsAlloc();
+
+	return ((*key != -1) ? 0 : GetLastError());
+}
+
+int
+isc_thread_key_delete(isc_thread_key_t key) {
+	return (TlsFree(key) ? 0 : GetLastError());
+}
diff --git a/src/lib/bind9/win32/time.c b/src/lib/bind9/win32/time.c
new file mode 100644
index 0000000..42492f9
--- /dev/null
+++ b/src/lib/bind9/win32/time.c
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2004, 2006-2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2001, 2003  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: time.c,v 1.52 2009-08-14 07:51:08 marka Exp $ */
+
+#include <config.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <windows.h>
+
+#include <isc/assertions.h>
+#include <isc/time.h>
+#include <isc/util.h>
+
+/*
+ * struct FILETIME uses "100-nanoseconds intervals".
+ * NS / S = 1000000000 (10^9).
+ * While it is reasonably obvious that this makes the needed
+ * conversion factor 10^7, it is coded this way for additional clarity.
+ */
+#define NS_PER_S 	1000000000
+#define NS_INTERVAL	100
+#define INTERVALS_PER_S (NS_PER_S / NS_INTERVAL)
+#define UINT64_MAX	_UI64_MAX
+
+/***
+ *** Absolute Times
+ ***/
+
+static isc_time_t epoch = { { 0, 0 } };
+LIBISC_EXTERNAL_DATA isc_time_t *isc_time_epoch = &epoch;
+
+/***
+ *** Intervals
+ ***/
+
+static isc_interval_t zero_interval = { 0 };
+LIBISC_EXTERNAL_DATA isc_interval_t *isc_interval_zero = &zero_interval;
+
+void
+isc_interval_set(isc_interval_t *i, unsigned int seconds,
+		 unsigned int nanoseconds)
+{
+	REQUIRE(i != NULL);
+	REQUIRE(nanoseconds < NS_PER_S);
+
+	/*
+	 * This rounds nanoseconds up not down.
+	 */
+	i->interval = (LONGLONG)seconds * INTERVALS_PER_S
+		+ (nanoseconds + NS_INTERVAL - 1) / NS_INTERVAL;
+}
+
+isc_boolean_t
+isc_interval_iszero(const isc_interval_t *i) {
+	REQUIRE(i != NULL);
+	if (i->interval == 0)
+		return (ISC_TRUE);
+
+	return (ISC_FALSE);
+}
+
+void
+isc_time_set(isc_time_t *t, unsigned int seconds, unsigned int nanoseconds) {
+	SYSTEMTIME epoch = { 1970, 1, 4, 1, 0, 0, 0, 0 };
+	FILETIME temp;
+	ULARGE_INTEGER i1;
+
+	REQUIRE(t != NULL);
+	REQUIRE(nanoseconds < NS_PER_S);
+
+	SystemTimeToFileTime(&epoch, &temp);
+
+	i1.LowPart = t->absolute.dwLowDateTime;
+	i1.HighPart = t->absolute.dwHighDateTime;
+
+	i1.QuadPart += (unsigned __int64)nanoseconds/100;
+	i1.QuadPart += (unsigned __int64)seconds*10000000;
+
+	t->absolute.dwLowDateTime = i1.LowPart;
+	t->absolute.dwHighDateTime = i1.HighPart;
+}
+
+void
+isc_time_settoepoch(isc_time_t *t) {
+	REQUIRE(t != NULL);
+
+	t->absolute.dwLowDateTime = 0;
+	t->absolute.dwHighDateTime = 0;
+}
+
+isc_boolean_t
+isc_time_isepoch(const isc_time_t *t) {
+	REQUIRE(t != NULL);
+
+	if (t->absolute.dwLowDateTime == 0 &&
+	    t->absolute.dwHighDateTime == 0)
+		return (ISC_TRUE);
+
+	return (ISC_FALSE);
+}
+
+isc_result_t
+isc_time_now(isc_time_t *t) {
+	REQUIRE(t != NULL);
+
+	GetSystemTimeAsFileTime(&t->absolute);
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_time_nowplusinterval(isc_time_t *t, const isc_interval_t *i) {
+	ULARGE_INTEGER i1;
+
+	REQUIRE(t != NULL);
+	REQUIRE(i != NULL);
+
+	GetSystemTimeAsFileTime(&t->absolute);
+
+	i1.LowPart = t->absolute.dwLowDateTime;
+	i1.HighPart = t->absolute.dwHighDateTime;
+
+	if (UINT64_MAX - i1.QuadPart < (unsigned __int64)i->interval)
+		return (ISC_R_RANGE);
+
+	i1.QuadPart += i->interval;
+
+	t->absolute.dwLowDateTime  = i1.LowPart;
+	t->absolute.dwHighDateTime = i1.HighPart;
+
+	return (ISC_R_SUCCESS);
+}
+
+int
+isc_time_compare(const isc_time_t *t1, const isc_time_t *t2) {
+	REQUIRE(t1 != NULL && t2 != NULL);
+
+	return ((int)CompareFileTime(&t1->absolute, &t2->absolute));
+}
+
+isc_result_t
+isc_time_add(const isc_time_t *t, const isc_interval_t *i, isc_time_t *result)
+{
+	ULARGE_INTEGER i1;
+
+	REQUIRE(t != NULL && i != NULL && result != NULL);
+
+	i1.LowPart = t->absolute.dwLowDateTime;
+	i1.HighPart = t->absolute.dwHighDateTime;
+
+	if (UINT64_MAX - i1.QuadPart < (unsigned __int64)i->interval)
+		return (ISC_R_RANGE);
+
+	i1.QuadPart += i->interval;
+
+	result->absolute.dwLowDateTime = i1.LowPart;
+	result->absolute.dwHighDateTime = i1.HighPart;
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_time_subtract(const isc_time_t *t, const isc_interval_t *i,
+		  isc_time_t *result) {
+	ULARGE_INTEGER i1;
+
+	REQUIRE(t != NULL && i != NULL && result != NULL);
+
+	i1.LowPart = t->absolute.dwLowDateTime;
+	i1.HighPart = t->absolute.dwHighDateTime;
+
+	if (i1.QuadPart < (unsigned __int64) i->interval)
+		return (ISC_R_RANGE);
+
+	i1.QuadPart -= i->interval;
+
+	result->absolute.dwLowDateTime = i1.LowPart;
+	result->absolute.dwHighDateTime = i1.HighPart;
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_uint64_t
+isc_time_microdiff(const isc_time_t *t1, const isc_time_t *t2) {
+	ULARGE_INTEGER i1, i2;
+	LONGLONG i3;
+
+	REQUIRE(t1 != NULL && t2 != NULL);
+
+	i1.LowPart  = t1->absolute.dwLowDateTime;
+	i1.HighPart = t1->absolute.dwHighDateTime;
+	i2.LowPart  = t2->absolute.dwLowDateTime;
+	i2.HighPart = t2->absolute.dwHighDateTime;
+
+	if (i1.QuadPart <= i2.QuadPart)
+		return (0);
+
+	/*
+	 * Convert to microseconds.
+	 */
+	i3 = (i1.QuadPart - i2.QuadPart) / 10;
+
+	return (i3);
+}
+
+isc_uint32_t
+isc_time_seconds(const isc_time_t *t) {
+	SYSTEMTIME epoch = { 1970, 1, 4, 1, 0, 0, 0, 0 };
+	FILETIME temp;
+	ULARGE_INTEGER i1, i2;
+	LONGLONG i3;
+
+	SystemTimeToFileTime(&epoch, &temp);
+
+	i1.LowPart  = t->absolute.dwLowDateTime;
+	i1.HighPart = t->absolute.dwHighDateTime;
+	i2.LowPart  = temp.dwLowDateTime;
+	i2.HighPart = temp.dwHighDateTime;
+
+	i3 = (i1.QuadPart - i2.QuadPart) / 10000000;
+
+	return ((isc_uint32_t)i3);
+}
+
+isc_uint32_t
+isc_time_nanoseconds(const isc_time_t *t) {
+	ULARGE_INTEGER i;
+
+	i.LowPart  = t->absolute.dwLowDateTime;
+	i.HighPart = t->absolute.dwHighDateTime;
+	return ((isc_uint32_t)(i.QuadPart % 10000000) * 100);
+}
+
+void
+isc_time_formattimestamp(const isc_time_t *t, char *buf, unsigned int len) {
+	FILETIME localft;
+	SYSTEMTIME st;
+	char DateBuf[50];
+	char TimeBuf[50];
+
+	static const char badtime[] = "99-Bad-9999 99:99:99.999";
+
+	REQUIRE(len > 0);
+	if (FileTimeToLocalFileTime(&t->absolute, &localft) &&
+	    FileTimeToSystemTime(&localft, &st)) {
+		GetDateFormat(LOCALE_USER_DEFAULT, 0, &st, "dd-MMM-yyyy",
+			      DateBuf, 50);
+		GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOTIMEMARKER|
+			      TIME_FORCE24HOURFORMAT, &st, NULL, TimeBuf, 50);
+
+		snprintf(buf, len, "%s %s.%03u", DateBuf, TimeBuf,
+			 st.wMilliseconds);
+
+	} else
+		snprintf(buf, len, badtime);
+}
+
+void
+isc_time_formathttptimestamp(const isc_time_t *t, char *buf, unsigned int len) {
+	SYSTEMTIME st;
+	char DateBuf[50];
+	char TimeBuf[50];
+
+/* strftime() format: "%a, %d %b %Y %H:%M:%S GMT" */
+
+	REQUIRE(len > 0);
+	if (FileTimeToSystemTime(&t->absolute, &st)) {
+		GetDateFormat(LOCALE_USER_DEFAULT, 0, &st,
+			      "ddd',', dd-MMM-yyyy", DateBuf, 50);
+		GetTimeFormat(LOCALE_USER_DEFAULT,
+			      TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT,
+			      &st, "hh':'mm':'ss", TimeBuf, 50);
+
+		snprintf(buf, len, "%s %s GMT", DateBuf, TimeBuf);
+	} else {
+		buf[0] = 0;
+	}
+}
+
+void
+isc_time_formatISO8601(const isc_time_t *t, char *buf, unsigned int len) {
+	SYSTEMTIME st;
+	char DateBuf[50];
+	char TimeBuf[50];
+
+/* strtime() format: "%Y-%m-%dT%H:%M:%SZ" */
+
+	REQUIRE(len > 0);
+	if (FileTimeToSystemTime(&t->absolute, &st)) {
+		GetDateFormat(LOCALE_NEUTRAL, 0, &st, "yyyy-MM-dd",
+			      DateBuf, 50);
+		GetTimeFormat(LOCALE_NEUTRAL,
+			      TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT,
+			      &st, "hh':'mm':'ss", TimeBuf, 50);
+		snprintf(buf, len, "%s%sZ", DateBuf, TimeBuf);
+	} else {
+		buf[0] = 0;
+	}
+}
diff --git a/src/lib/bind9/win32/unistd.h b/src/lib/bind9/win32/unistd.h
new file mode 100644
index 0000000..9de0bde
--- /dev/null
+++ b/src/lib/bind9/win32/unistd.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2004, 2007-2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: unistd.h,v 1.10 2009-07-17 23:47:41 tbox Exp $ */
+
+/* None of these are defined in NT, so define them for our use */
+#define O_NONBLOCK 1
+#define PORT_NONBLOCK O_NONBLOCK
+
+/*
+ * fcntl() commands
+ */
+#define F_SETFL 0
+#define F_GETFL 1
+#define F_SETFD 2
+#define F_GETFD 3
+/*
+ * Enough problems not having full fcntl() without worrying about this!
+ */
+#undef F_DUPFD
+
+int fcntl(int, int, ...);
+
+/*
+ * access() related definitions for winXP
+ */
+#include <io.h>
+#ifndef F_OK
+#define	F_OK	0
+#endif
+
+#ifndef X_OK
+#define	X_OK	1
+#endif
+
+#ifndef W_OK
+#define W_OK 2
+#endif
+
+#ifndef R_OK
+#define R_OK 4
+#endif
+
+#define access _access
+
+#include <process.h>
diff --git a/src/lib/bind9/win32/version.c b/src/lib/bind9/win32/version.c
new file mode 100644
index 0000000..0dc0007
--- /dev/null
+++ b/src/lib/bind9/win32/version.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2004, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2001  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: version.c,v 1.7 2007-06-19 23:47:19 tbox Exp $ */
+
+#include <versions.h>
+
+#include <isc/version.h>
+
+LIBISC_EXTERNAL_DATA const char isc_version[] = VERSION;
+
+LIBISC_EXTERNAL_DATA const unsigned int isc_libinterface = LIBINTERFACE;
+LIBISC_EXTERNAL_DATA const unsigned int isc_librevision = LIBREVISION;
+LIBISC_EXTERNAL_DATA const unsigned int isc_libage = LIBAGE;
diff --git a/src/lib/bind9/win32/win32os.c b/src/lib/bind9/win32/win32os.c
new file mode 100644
index 0000000..ce71fe6
--- /dev/null
+++ b/src/lib/bind9/win32/win32os.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2004, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2002  Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: win32os.c,v 1.5 2007-06-19 23:47:19 tbox Exp $ */
+
+#include <windows.h>
+
+#include <isc/win32os.h>
+
+static BOOL bInit = FALSE;
+static OSVERSIONINFOEX osVer;
+
+static void
+initialize_action(void) {
+	BOOL bSuccess;
+
+	if (bInit)
+		return;	
+	/*
+	 * NOTE: VC++ 6.0 gets this function declaration wrong
+	 * so we compensate by casting the argument
+	 */
+	osVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+	bSuccess = GetVersionEx((OSVERSIONINFO *) &osVer);
+
+	/*
+	 * Versions of NT before NT4.0 SP6 did not return the
+	 * extra info that the EX structure provides and returns
+	 * a failure so we need to retry with the old structure.
+	 */
+	if(!bSuccess) {
+		osVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+		bSuccess = GetVersionEx((OSVERSIONINFO *) &osVer);
+	}
+	bInit = TRUE;
+}
+
+unsigned int
+isc_win32os_majorversion(void) {
+	initialize_action();
+	return ((unsigned int)osVer.dwMajorVersion);
+}
+
+unsigned int
+isc_win32os_minorversion(void) {
+	initialize_action();
+	return ((unsigned int)osVer.dwMinorVersion);
+}
+
+unsigned int
+isc_win32os_servicepackmajor(void) {
+	initialize_action();
+	return ((unsigned int)osVer.wServicePackMajor);
+}
+
+unsigned int
+isc_win32os_servicepackminor(void) {
+	initialize_action();
+	return ((unsigned int)osVer.wServicePackMinor);
+}
+
+int
+isc_win32os_versioncheck(unsigned int major, unsigned int minor,
+		     unsigned int spmajor, unsigned int spminor) {
+
+	initialize_action();
+
+	if (major < isc_win32os_majorversion())
+		return (1);
+	if (major > isc_win32os_majorversion())
+		return (-1);
+	if (minor < isc_win32os_minorversion())
+		return (1);
+	if (minor > isc_win32os_minorversion())
+		return (-1);
+	if (spmajor < isc_win32os_servicepackmajor())
+		return (1);
+	if (spmajor > isc_win32os_servicepackmajor())
+		return (-1);
+	if (spminor < isc_win32os_servicepackminor())
+		return (1);
+	if (spminor > isc_win32os_servicepackminor())
+		return (-1);
+
+	/* Exact */
+	return (0);
+}
\ No newline at end of file
diff --git a/src/lib/bind9/x86_32/include/isc/atomic.h b/src/lib/bind9/x86_32/include/isc/atomic.h
new file mode 100644
index 0000000..0e6a07e
--- /dev/null
+++ b/src/lib/bind9/x86_32/include/isc/atomic.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2005, 2007, 2008  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: atomic.h,v 1.10 2008-01-24 23:47:00 tbox Exp $ */
+
+#ifndef ISC_ATOMIC_H
+#define ISC_ATOMIC_H 1
+
+#include <isc/platform.h>
+#include <isc/types.h>
+
+#ifdef ISC_PLATFORM_USEGCCASM
+/*
+ * This routine atomically increments the value stored in 'p' by 'val', and
+ * returns the previous value.
+ */
+static __inline__ isc_int32_t
+isc_atomic_xadd(isc_int32_t *p, isc_int32_t val) {
+	isc_int32_t prev = val;
+
+	__asm__ volatile(
+#ifdef ISC_PLATFORM_USETHREADS
+		"lock;"
+#endif
+		"xadd %0, %1"
+		:"=q"(prev)
+		:"m"(*p), "0"(prev)
+		:"memory", "cc");
+
+	return (prev);
+}
+
+#ifdef ISC_PLATFORM_HAVEXADDQ
+static __inline__ isc_int64_t
+isc_atomic_xaddq(isc_int64_t *p, isc_int64_t val) {
+	isc_int64_t prev = val;
+
+	__asm__ volatile(
+#ifdef ISC_PLATFORM_USETHREADS
+	    "lock;"
+#endif
+	    "xaddq %0, %1"
+	    :"=q"(prev)
+	    :"m"(*p), "0"(prev)
+	    :"memory", "cc");
+
+	return (prev);
+}
+#endif /* ISC_PLATFORM_HAVEXADDQ */
+
+/*
+ * This routine atomically stores the value 'val' in 'p'.
+ */
+static __inline__ void
+isc_atomic_store(isc_int32_t *p, isc_int32_t val) {
+	__asm__ volatile(
+#ifdef ISC_PLATFORM_USETHREADS
+		/*
+		 * xchg should automatically lock memory, but we add it
+		 * explicitly just in case (it at least doesn't harm)
+		 */
+		"lock;"
+#endif
+
+		"xchgl %1, %0"
+		:
+		: "r"(val), "m"(*p)
+		: "memory");
+}
+
+/*
+ * This routine atomically replaces the value in 'p' with 'val', if the
+ * original value is equal to 'cmpval'.  The original value is returned in any
+ * case.
+ */
+static __inline__ isc_int32_t
+isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) {
+	__asm__ volatile(
+#ifdef ISC_PLATFORM_USETHREADS
+		"lock;"
+#endif
+		"cmpxchgl %1, %2"
+		: "=a"(cmpval)
+		: "r"(val), "m"(*p), "a"(cmpval)
+		: "memory");
+
+	return (cmpval);
+}
+
+#elif defined(ISC_PLATFORM_USESTDASM)
+/*
+ * The followings are "generic" assembly code which implements the same
+ * functionality in case the gcc extension cannot be used.  It should be
+ * better to avoid inlining below, since we directly refer to specific
+ * positions of the stack frame, which would not actually point to the
+ * intended address in the embedded mnemonic.
+ */
+#include <isc/util.h>		/* for 'UNUSED' macro */
+
+static isc_int32_t
+isc_atomic_xadd(isc_int32_t *p, isc_int32_t val) {
+	UNUSED(p);
+	UNUSED(val);
+
+	__asm (
+		"movl 8(%ebp), %ecx\n"
+		"movl 12(%ebp), %edx\n"
+#ifdef ISC_PLATFORM_USETHREADS
+		"lock;"
+#endif
+		"xadd %edx, (%ecx)\n"
+
+		/*
+		 * set the return value directly in the register so that we
+		 * can avoid guessing the correct position in the stack for a
+		 * local variable.
+		 */
+		"movl %edx, %eax"
+		);
+}
+
+static void
+isc_atomic_store(isc_int32_t *p, isc_int32_t val) {
+	UNUSED(p);
+	UNUSED(val);
+
+	__asm (
+		"movl 8(%ebp), %ecx\n"
+		"movl 12(%ebp), %edx\n"
+#ifdef ISC_PLATFORM_USETHREADS
+		"lock;"
+#endif
+		"xchgl (%ecx), %edx\n"
+		);
+}
+
+static isc_int32_t
+isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) {
+	UNUSED(p);
+	UNUSED(cmpval);
+	UNUSED(val);
+
+	__asm (
+		"movl 8(%ebp), %ecx\n"
+		"movl 12(%ebp), %eax\n"	/* must be %eax for cmpxchgl */
+		"movl 16(%ebp), %edx\n"
+#ifdef ISC_PLATFORM_USETHREADS
+		"lock;"
+#endif
+
+		/*
+		 * If (%ecx) == %eax then (%ecx) := %edx.
+		 % %eax is set to old (%ecx), which will be the return value.
+		 */
+		"cmpxchgl %edx, (%ecx)"
+		);
+}
+#else /* !ISC_PLATFORM_USEGCCASM && !ISC_PLATFORM_USESTDASM */
+
+#error "unsupported compiler.  disable atomic ops by --disable-atomic"
+
+#endif
+#endif /* ISC_ATOMIC_H */
diff --git a/src/lib/bind9/x86_64/include/isc/atomic.h b/src/lib/bind9/x86_64/include/isc/atomic.h
new file mode 100644
index 0000000..a9d3e61
--- /dev/null
+++ b/src/lib/bind9/x86_64/include/isc/atomic.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2005, 2007, 2008  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: atomic.h,v 1.6 2008-01-24 23:47:00 tbox Exp $ */
+
+#ifndef ISC_ATOMIC_H
+#define ISC_ATOMIC_H 1
+
+#include <isc/platform.h>
+#include <isc/types.h>
+
+#ifdef ISC_PLATFORM_USEGCCASM
+
+/* We share the gcc-version with x86_32 */
+#error "impossible case.  check build configuration"
+
+#elif defined(ISC_PLATFORM_USESTDASM)
+/*
+ * The followings are "generic" assembly code which implements the same
+ * functionality in case the gcc extension cannot be used.  It should be
+ * better to avoid inlining below, since we directly refer to specific
+ * registers for arguments, which would not actually correspond to the
+ * intended address or value in the embedded mnemonic.
+ */
+#include <isc/util.h>		/* for 'UNUSED' macro */
+
+static isc_int32_t
+isc_atomic_xadd(isc_int32_t *p, isc_int32_t val) {
+	UNUSED(p);
+	UNUSED(val);
+
+	__asm (
+		"movq %rdi, %rdx\n"
+		"movl %esi, %eax\n"
+#ifdef ISC_PLATFORM_USETHREADS
+		"lock;"
+#endif
+		"xadd %eax, (%rdx)\n"
+		/*
+		 * XXX: assume %eax will be used as the return value.
+		 */
+		);
+}
+
+#ifdef ISC_PLATFORM_HAVEXADDQ
+static isc_int64_t
+isc_atomic_xaddq(isc_int64_t *p, isc_int64_t val) {
+	UNUSED(p);
+	UNUSED(val);
+
+	__asm (
+		"movq %rdi, %rdx\n"
+		"movq %rsi, %rax\n"
+#ifdef ISC_PLATFORM_USETHREADS
+		"lock;"
+#endif
+		"xaddq %rax, (%rdx)\n"
+		/*
+		 * XXX: assume %rax will be used as the return value.
+		 */
+		);
+}
+#endif
+
+static void
+isc_atomic_store(isc_int32_t *p, isc_int32_t val) {
+	UNUSED(p);
+	UNUSED(val);
+
+	__asm (
+		"movq %rdi, %rax\n"
+		"movl %esi, %edx\n"
+#ifdef ISC_PLATFORM_USETHREADS
+		"lock;"
+#endif
+		"xchgl (%rax), %edx\n"
+		/*
+		 * XXX: assume %rax will be used as the return value.
+		 */
+		);
+}
+
+static isc_int32_t
+isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) {
+	UNUSED(p);
+	UNUSED(cmpval);
+	UNUSED(val);
+
+	__asm (
+		"movl %edx, %ecx\n"
+		"movl %esi, %eax\n"
+		"movq %rdi, %rdx\n"
+
+#ifdef ISC_PLATFORM_USETHREADS
+		"lock;"
+#endif
+		/*
+		 * If (%rdi) == %eax then (%rdi) := %edx.
+		 * %eax is set to old (%ecx), which will be the return value.
+		 */
+		"cmpxchgl %ecx, (%rdx)"
+		);
+}
+
+#else /* !ISC_PLATFORM_USEGCCASM && !ISC_PLATFORM_USESTDASM */
+
+#error "unsupported compiler.  disable atomic ops by --disable-atomic"
+
+#endif
+#endif /* ISC_ATOMIC_H */
diff --git a/src/lib/log/Makefile.am b/src/lib/log/Makefile.am
index 5770564..26ca996 100644
--- a/src/lib/log/Makefile.am
+++ b/src/lib/log/Makefile.am
@@ -5,6 +5,13 @@ AM_CPPFLAGS += $(BOOST_INCLUDES)
 AM_CPPFLAGS += -I$(top_srcdir)/src/lib/log -I$(top_builddir)/src/lib/log
 AM_CPPFLAGS += -I$(top_srcdir)/src/lib/util -I$(top_builddir)/src/lib/util
 
+AM_CPPFLAGS  += -I$(top_srcdir)/src/lib/bind9
+AM_CPPFLAGS  += -I$(top_srcdir)/src/lib/bind9/include
+AM_CPPFLAGS  += -I$(top_srcdir)/src/lib/bind9/unix/include
+AM_CPPFLAGS  += -I$(top_srcdir)/src/lib/bind9/nothreads/include
+AM_CPPFLAGS  += -I$(top_srcdir)/src/lib/bind9/x86_32/include
+AM_CPPFLAGS  += -Wformat -Wpointer-arith -Wmissing-prototypes
+
 CLEANFILES = *.gcno *.gcda
 
 lib_LTLIBRARIES = liblog.la
@@ -38,4 +45,6 @@ if USE_CLANGPP
 liblog_la_CXXFLAGS += -Wno-error
 endif
 liblog_la_CPPFLAGS = $(AM_CPPFLAGS)
-liblog_la_LIBADD = $(top_builddir)/src/lib/util/libutil.la
+liblog_la_LIBADD  = $(top_builddir)/src/lib/util/libutil.la
+liblog_la_LIBADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
+liblog_la_LIBADD += $(top_builddir)/src/lib/bind9/libbind9.la
diff --git a/src/lib/log/logger_impl.cc b/src/lib/log/logger_impl.cc
index 41153e9..de909be 100644
--- a/src/lib/log/logger_impl.cc
+++ b/src/lib/log/logger_impl.cc
@@ -14,6 +14,7 @@
 
 #include <iostream>
 #include <algorithm>
+#include <cassert>
 
 #include <stdarg.h>
 #include <stdio.h>
@@ -37,24 +38,88 @@ namespace log {
 // Static initializations
 
 LoggerImpl::LoggerInfoMap LoggerImpl::logger_info_;
+LoggerImpl::LoggerInfoMap LoggerImpl::bind9_info_;
 LoggerImpl::LoggerInfo LoggerImpl::root_logger_info_(isc::log::INFO, 0);
 
 // Constructor
-LoggerImpl::LoggerImpl(const std::string& name, bool)
+LoggerImpl::LoggerImpl(const std::string& name, bool) : mctx_(0), lctx_(0), lcfg_(0)
 {
-    // Are we the root logger?
+    // Regardless of anything else, category is the unadorned name of
+    // the logger.
+    category_ = name;
+
+    // Set up the module and category.
+    categories_[0].name = strdup(category_.c_str());
+    categories_[0].id = 0;
+    categories_[1].name = NULL;
+    categories_[1].id = 0;
+
+    modules_[0].name = strdup(getRootLoggerName().c_str());
+    modules_[0].id = 0;
+    modules_[1].name = NULL;
+
+    // The next set of code is concerned with static initialization.  This
+    // logger is instantiated with a given name.  If no other logger with this
+    // name has been created, we initialize the BIND 9 logging for that name.
+    // Otherwise we can omit the step.
+
+    bool initialized = false;
+
     if (name == getRootLoggerName()) {
+        // We are the root logger.
         is_root_ = true;
         name_ = name;
+
+        // See if it has already been initialized.
+        initialized = root_logger_info_.init;
+        root_logger_info_.init = true;
+
     } else {
+
+        // Not the root logger.  Create full name for this logger.
         is_root_ = false;
         name_ = getRootLoggerName() + "." + name;
+
+        // Has a copy of this module already been initialized?
+        LoggerInfoMap::iterator i = bind9_info_.find(name_);
+        if (i != bind9_info_.end()) {
+            // Yes!
+            initialized = true;
+        } else {
+
+            // No - add information to the map.
+            initialized = false;
+            bind9_info_[name_] =
+                LoggerInfo(isc::log::INFO, MIN_DEBUG_LEVEL, true);
+        }
     }
+
+    if (! initialized) {
+        bind9LogInit();
+    }
+}
+
+// Do BIND 9 Logging initialization
+
+void
+LoggerImpl::bind9LogInit() {
+
+    if ((isc_mem_create(0, 0, &mctx_) != ISC_R_SUCCESS) ||
+        (isc_log_create(mctx_, &lctx_, &lcfg_) != ISC_R_SUCCESS)) {
+        std::cout << "Unable to create BIND 9 context\n";
+    }
+
+    isc_log_registercategories(lctx_, categories_);
+    isc_log_registermodules(lctx_, modules_);
 }
 
+
 // Destructor. (Here because of virtual declaration.)
 
 LoggerImpl::~LoggerImpl() {
+    // Free up space for BIND 9 strings
+    free(const_cast<void*>(static_cast<const void*>(modules_[0].name))); modules_[0].name = NULL;
+    free(const_cast<void*>(static_cast<const void*>(categories_[0].name))); categories_[0].name = NULL;
 }
 
 // Set the severity for logging.
diff --git a/src/lib/log/logger_impl.h b/src/lib/log/logger_impl.h
index 9fc9cf9..6aaab31 100644
--- a/src/lib/log/logger_impl.h
+++ b/src/lib/log/logger_impl.h
@@ -28,6 +28,12 @@
 #include <log/message_types.h>
 #include <log/root_logger_name.h>
 
+extern "C" {
+#include <isc/result.h>
+#include <isc/mem.h>
+#include <isc/log.h>
+}
+
 namespace isc {
 namespace log {
 
@@ -50,9 +56,11 @@ public:
     struct LoggerInfo {
         isc::log::Severity  severity;
         int                 dbglevel;
+        bool                init;       ///< Initialized?
 
         LoggerInfo(isc::log::Severity sev = isc::log::INFO,
-            int dbg = MIN_DEBUG_LEVEL) : severity(sev), dbglevel(dbg)
+            int dbg = MIN_DEBUG_LEVEL, bool initialized = false) :
+            severity(sev), dbglevel(dbg), init(initialized)
         {}
     };
 
@@ -246,10 +254,13 @@ public:
         logger_info_.clear();
     }
 
+    // Initialize BIND 9 logging
+    void bind9LogInit();
 
 private:
     bool                is_root_;           ///< true if a root logger
     std::string         name_;              ///< Name of this logger
+    std::string         category_;          ///< Category of logger
 
     // Split the status of the root logger from this logger.  If - is will
     // probably be the usual case - no per-logger setting is enabled, a
@@ -258,6 +269,15 @@ private:
 
     static LoggerInfo       root_logger_info_;  ///< Status of root logger
     static LoggerInfoMap    logger_info_;       ///< Store of debug levels etc.
+    static LoggerInfoMap    bind9_info_;        ///< Parallel store for bind 9 stuff
+
+    // Categories and modules.  Each logger only has one category (the
+    // the logger name) and one module (the name of the root logger).
+    isc_logcategory_t       categories_[2];     ///< Category and NULL
+    isc_logmodule_t         modules_[2];        ///< Module and NULL
+    isc_mem_t*              mctx_;              ///< Memory context
+    isc_log_t*              lctx_;              ///< Logging context
+    isc_logconfig_t*        lcfg_;              ///< Logging configuration
 };
 
 } // namespace log




More information about the bind10-changes mailing list