]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
python contribution from Zdenek Vasicek and Marek Vavrusa (BSD licensed).
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Wed, 25 Mar 2009 14:47:47 +0000 (14:47 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Wed, 25 Mar 2009 14:47:47 +0000 (14:47 +0000)
git-svn-id: file:///svn/unbound/trunk@1556 be551aaa-1e26-0410-a405-d3ace91eadb9

99 files changed:
Makefile.in
ac_pkg_swig.m4 [new file with mode: 0644]
acx_python.m4 [new file with mode: 0644]
config.h.in
configure
configure.ac
contrib/README
contrib/python/LICENSE [new file with mode: 0644]
contrib/python/Makefile [new file with mode: 0644]
contrib/python/docs/Makefile [new file with mode: 0644]
contrib/python/docs/source/conf.py [new file with mode: 0644]
contrib/python/docs/source/examples/example1a.rst [new file with mode: 0644]
contrib/python/docs/source/examples/example1b.rst [new file with mode: 0644]
contrib/python/docs/source/examples/example2.rst [new file with mode: 0644]
contrib/python/docs/source/examples/example3.rst [new file with mode: 0644]
contrib/python/docs/source/examples/example4.rst [new file with mode: 0644]
contrib/python/docs/source/examples/example5.rst [new file with mode: 0644]
contrib/python/docs/source/examples/example6-1.py [new file with mode: 0644]
contrib/python/docs/source/examples/example6.rst [new file with mode: 0644]
contrib/python/docs/source/examples/example7-1.py [new file with mode: 0644]
contrib/python/docs/source/examples/example7-2.py [new file with mode: 0644]
contrib/python/docs/source/examples/example7.rst [new file with mode: 0644]
contrib/python/docs/source/examples/example8-1.py [new file with mode: 0644]
contrib/python/docs/source/examples/example8.rst [new file with mode: 0644]
contrib/python/docs/source/examples/index.rst [new file with mode: 0644]
contrib/python/docs/source/index.rst [new file with mode: 0644]
contrib/python/docs/source/install.rst [new file with mode: 0644]
contrib/python/docs/source/intro.rst [new file with mode: 0644]
contrib/python/docs/source/modules/unbound.rst [new file with mode: 0644]
contrib/python/examples/async-lookup.py [new file with mode: 0644]
contrib/python/examples/dns-lookup.py [new file with mode: 0644]
contrib/python/examples/dnssec-valid.py [new file with mode: 0644]
contrib/python/examples/example8-1.py [new file with mode: 0644]
contrib/python/examples/idn-lookup.py [new file with mode: 0644]
contrib/python/examples/mx-lookup.py [new file with mode: 0644]
contrib/python/examples/ns-lookup.py [new file with mode: 0644]
contrib/python/examples/reverse-lookup.py [new file with mode: 0644]
contrib/python/libunbound.i [new file with mode: 0644]
contrib/python/libunbound_wrap.c [new file with mode: 0644]
doc/CREDITS
doc/Changelog
doc/example.conf.in
doc/unbound.doxygen
libunbound/libunbound.c
libunbound/ubsyms.def
libunbound/unbound.h
pythonmod/LICENSE [new file with mode: 0644]
pythonmod/Makefile [new file with mode: 0644]
pythonmod/doc/Makefile [new file with mode: 0644]
pythonmod/doc/source/conf.py [new file with mode: 0644]
pythonmod/doc/source/examples/example0-1.py [new file with mode: 0644]
pythonmod/doc/source/examples/example0.rst [new file with mode: 0644]
pythonmod/doc/source/examples/example1.rst [new file with mode: 0644]
pythonmod/doc/source/examples/example2.rst [new file with mode: 0644]
pythonmod/doc/source/examples/example3.rst [new file with mode: 0644]
pythonmod/doc/source/examples/example4.rst [new file with mode: 0644]
pythonmod/doc/source/examples/index.rst [new file with mode: 0644]
pythonmod/doc/source/index.rst [new file with mode: 0644]
pythonmod/doc/source/install.rst [new file with mode: 0644]
pythonmod/doc/source/modules/config.rst [new file with mode: 0644]
pythonmod/doc/source/modules/env.rst [new file with mode: 0644]
pythonmod/doc/source/modules/functions.rst [new file with mode: 0644]
pythonmod/doc/source/modules/index.rst [new file with mode: 0644]
pythonmod/doc/source/modules/struct.rst [new file with mode: 0644]
pythonmod/doc/source/usecase.rst [new file with mode: 0644]
pythonmod/examples/calc.py [new file with mode: 0644]
pythonmod/examples/dict.py [new file with mode: 0644]
pythonmod/examples/dict_data.txt [new file with mode: 0644]
pythonmod/examples/log.py [new file with mode: 0644]
pythonmod/examples/resgen.py [new file with mode: 0644]
pythonmod/examples/resmod.py [new file with mode: 0644]
pythonmod/interface.i [new file with mode: 0644]
pythonmod/pythonmod.c [new file with mode: 0644]
pythonmod/pythonmod.h [new file with mode: 0644]
pythonmod/pythonmod_utils.c [new file with mode: 0644]
pythonmod/pythonmod_utils.h [new file with mode: 0644]
pythonmod/test-calc.conf [new file with mode: 0644]
pythonmod/test-dict.conf [new file with mode: 0644]
pythonmod/test-log.conf [new file with mode: 0644]
pythonmod/test-resgen.conf [new file with mode: 0644]
pythonmod/test-resmod.conf [new file with mode: 0644]
pythonmod/ubmodule-msg.py [new file with mode: 0644]
pythonmod/ubmodule-tst.py [new file with mode: 0644]
services/cache/dns.c
services/localzone.c
services/localzone.h
services/modstack.c
smallapp/unbound-checkconf.c
util/config_file.c
util/config_file.h
util/configlexer.c
util/configlexer.lex
util/configparser.c
util/configparser.h
util/configparser.y
util/data/msgencode.c
util/data/msgreply.c
util/data/msgreply.h
util/fptr_wlist.c

index 96a55cbaa68a01caa463af1b29212cfdfe322632..daac35d5f12449c77f3c8b34ba5531c448f3865a 100644 (file)
@@ -292,7 +292,7 @@ util/configparser.c util/configparser.h:  $(srcdir)/util/configparser.y
 clean:
        rm -f *.o *.d *.lo *~ tags
        rm -f unbound unbound-checkconf unbound-host unbound-control unbound-control-setup libunbound.la
-       rm -rf autom4te.cache .libs build doc/html
+       rm -rf autom4te.cache .libs build doc/html doc/xml
 
 realclean: clean
        rm -f config.status config.log config.h.in config.h
diff --git a/ac_pkg_swig.m4 b/ac_pkg_swig.m4
new file mode 100644 (file)
index 0000000..738f69d
--- /dev/null
@@ -0,0 +1,122 @@
+# ===========================================================================
+#              http://autoconf-archive.cryp.to/ac_pkg_swig.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AC_PROG_SWIG([major.minor.micro])
+#
+# DESCRIPTION
+#
+#   This macro searches for a SWIG installation on your system. If found you
+#   should call SWIG via $(SWIG). You can use the optional first argument to
+#   check if the version of the available SWIG is greater than or equal to
+#   the value of the argument. It should have the format: N[.N[.N]] (N is a
+#   number between 0 and 999. Only the first N is mandatory.)
+#
+#   If the version argument is given (e.g. 1.3.17), AC_PROG_SWIG checks that
+#   the swig package is this version number or higher.
+#
+#   In configure.in, use as:
+#
+#     AC_PROG_SWIG(1.3.17)
+#     SWIG_ENABLE_CXX
+#     SWIG_MULTI_MODULE_SUPPORT
+#     SWIG_PYTHON
+#
+# LAST MODIFICATION
+#
+#   2008-04-12
+#
+# COPYLEFT
+#
+#   Copyright (c) 2008 Sebastian Huber <sebastian-huber@web.de>
+#   Copyright (c) 2008 Alan W. Irwin <irwin@beluga.phys.uvic.ca>
+#   Copyright (c) 2008 Rafael Laboissiere <rafael@laboissiere.net>
+#   Copyright (c) 2008 Andrew Collier <colliera@ukzn.ac.za>
+#
+#   This program is free software; you can redistribute it and/or modify it
+#   under the terms of the GNU General Public License as published by the
+#   Free Software Foundation; either version 2 of the License, or (at your
+#   option) any later version.
+#
+#   This program is distributed in the hope that it will be useful, but
+#   WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+#   Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License along
+#   with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+#   As a special exception, the respective Autoconf Macro's copyright owner
+#   gives unlimited permission to copy, distribute and modify the configure
+#   scripts that are the output of Autoconf when processing the Macro. You
+#   need not follow the terms of the GNU General Public License when using
+#   or distributing such scripts, even though portions of the text of the
+#   Macro appear in them. The GNU General Public License (GPL) does govern
+#   all other use of the material that constitutes the Autoconf Macro.
+#
+#   This special exception to the GPL applies to versions of the Autoconf
+#   Macro released by the Autoconf Macro Archive. When you make and
+#   distribute a modified version of the Autoconf Macro, you may extend this
+#   special exception to the GPL to apply to your modified version as well.
+
+AC_DEFUN([AC_PROG_SWIG],[
+        AC_PATH_PROG([SWIG],[swig])
+        if test -z "$SWIG" ; then
+                AC_MSG_WARN([cannot find 'swig' program. You should look at http://www.swig.org])
+                SWIG='echo "Error: SWIG is not installed. You should look at http://www.swig.org" ; false'
+        elif test -n "$1" ; then
+                AC_MSG_CHECKING([for SWIG version])
+                [swig_version=`$SWIG -version 2>&1 | grep 'SWIG Version' | sed 's/.*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/g'`]
+                AC_MSG_RESULT([$swig_version])
+                if test -n "$swig_version" ; then
+                        # Calculate the required version number components
+                        [required=$1]
+                        [required_major=`echo $required | sed 's/[^0-9].*//'`]
+                        if test -z "$required_major" ; then
+                                [required_major=0]
+                        fi
+                        [required=`echo $required | sed 's/[0-9]*[^0-9]//'`]
+                        [required_minor=`echo $required | sed 's/[^0-9].*//'`]
+                        if test -z "$required_minor" ; then
+                                [required_minor=0]
+                        fi
+                        [required=`echo $required | sed 's/[0-9]*[^0-9]//'`]
+                        [required_patch=`echo $required | sed 's/[^0-9].*//'`]
+                        if test -z "$required_patch" ; then
+                                [required_patch=0]
+                        fi
+                        # Calculate the available version number components
+                        [available=$swig_version]
+                        [available_major=`echo $available | sed 's/[^0-9].*//'`]
+                        if test -z "$available_major" ; then
+                                [available_major=0]
+                        fi
+                        [available=`echo $available | sed 's/[0-9]*[^0-9]//'`]
+                        [available_minor=`echo $available | sed 's/[^0-9].*//'`]
+                        if test -z "$available_minor" ; then
+                                [available_minor=0]
+                        fi
+                        [available=`echo $available | sed 's/[0-9]*[^0-9]//'`]
+                        [available_patch=`echo $available | sed 's/[^0-9].*//'`]
+                        if test -z "$available_patch" ; then
+                                [available_patch=0]
+                        fi
+                        if test $available_major -ne $required_major \
+                                -o $available_minor -ne $required_minor \
+                                -o $available_patch -lt $required_patch ; then
+                                AC_MSG_WARN([SWIG version >= $1 is required.  You have $swig_version.  You should look at http://www.swig.org])
+                                SWIG='echo "Error: SWIG version >= $1 is required.  You have '"$swig_version"'.  You should look at http://www.swig.org" ; false'
+                        else
+                                AC_MSG_NOTICE([SWIG executable is '$SWIG'])
+                                SWIG_LIB=`$SWIG -swiglib`
+                                AC_MSG_NOTICE([SWIG library directory is '$SWIG_LIB'])
+                        fi
+                else
+                        AC_MSG_WARN([cannot determine SWIG version])
+                        SWIG='echo "Error: Cannot determine SWIG version.  You should look at http://www.swig.org" ; false'
+                fi
+        fi
+        AC_SUBST([SWIG_LIB])
+])
diff --git a/acx_python.m4 b/acx_python.m4
new file mode 100644 (file)
index 0000000..abf2328
--- /dev/null
@@ -0,0 +1,194 @@
+AC_DEFUN([AC_PYTHON_DEVEL],[
+        #
+        # Allow the use of a (user set) custom python version
+        #
+        AC_ARG_VAR([PYTHON_VERSION],[The installed Python
+                version to use, for example '2.3'. This string
+                will be appended to the Python interpreter
+                canonical name.])
+
+        AC_PATH_PROG([PYTHON],[python[$PYTHON_VERSION]])
+        if test -z "$PYTHON"; then
+           AC_MSG_ERROR([Cannot find python$PYTHON_VERSION in your system path])
+           PYTHON_VERSION=""
+        fi
+
+        #
+        # Check for a version of Python >= 2.1.0
+        #
+        AC_MSG_CHECKING([for a version of Python >= '2.1.0'])
+        ac_supports_python_ver=`$PYTHON -c "import sys, string; \
+                ver = string.split(sys.version)[[0]]; \
+                print ver >= '2.1.0'"`
+        if test "$ac_supports_python_ver" != "True"; then
+                if test -z "$PYTHON_NOVERSIONCHECK"; then
+                        AC_MSG_RESULT([no])
+                        AC_MSG_FAILURE([
+This version of the AC@&t@_PYTHON_DEVEL macro
+doesn't work properly with versions of Python before
+2.1.0. You may need to re-run configure, setting the
+variables PYTHON_CPPFLAGS, PYTHON_LDFLAGS, PYTHON_SITE_PKG,
+PYTHON_EXTRA_LIBS and PYTHON_EXTRA_LDFLAGS by hand.
+Moreover, to disable this check, set PYTHON_NOVERSIONCHECK
+to something else than an empty string.
+])
+                else
+                        AC_MSG_RESULT([skip at user request])
+                fi
+        else
+                AC_MSG_RESULT([yes])
+        fi
+
+        #
+        # if the macro parameter ``version'' is set, honour it
+        #
+        if test -n "$1"; then
+                AC_MSG_CHECKING([for a version of Python $1])
+                ac_supports_python_ver=`$PYTHON -c "import sys, string; \
+                        ver = string.split(sys.version)[[0]]; \
+                        print ver $1"`
+                if test "$ac_supports_python_ver" = "True"; then
+                   AC_MSG_RESULT([yes])
+                else
+                        AC_MSG_RESULT([no])
+                        AC_MSG_ERROR([this package requires Python $1.
+If you have it installed, but it isn't the default Python
+interpreter in your system path, please pass the PYTHON_VERSION
+variable to configure. See ``configure --help'' for reference.
+])
+                        PYTHON_VERSION=""
+                fi
+        fi
+
+        #
+        # Check if you have distutils, else fail
+        #
+        AC_MSG_CHECKING([for the distutils Python package])
+        ac_distutils_result=`$PYTHON -c "import distutils" 2>&1`
+        if test -z "$ac_distutils_result"; then
+                AC_MSG_RESULT([yes])
+        else
+                AC_MSG_RESULT([no])
+                AC_MSG_ERROR([cannot import Python module "distutils".
+Please check your Python installation. The error was:
+$ac_distutils_result])
+                PYTHON_VERSION=""
+        fi
+
+        #
+        # Check for Python include path
+        #
+        AC_MSG_CHECKING([for Python include path])
+        if test -z "$PYTHON_CPPFLAGS"; then
+                python_path=`$PYTHON -c "import distutils.sysconfig; \
+                        print distutils.sysconfig.get_python_inc();"`
+                if test -n "${python_path}"; then
+                        python_path="-I$python_path"
+                fi
+                PYTHON_CPPFLAGS=$python_path
+        fi
+        AC_MSG_RESULT([$PYTHON_CPPFLAGS])
+        AC_SUBST([PYTHON_CPPFLAGS])
+
+        #
+        # Check for Python library path
+        #
+        AC_MSG_CHECKING([for Python library path])
+        if test -z "$PYTHON_LDFLAGS"; then
+                # (makes two attempts to ensure we've got a version number
+                # from the interpreter)
+                py_version=`$PYTHON -c "from distutils.sysconfig import *; \
+                        from string import join; \
+                        print join(get_config_vars('VERSION'))"`
+                if test "$py_version" == "[None]"; then
+                        if test -n "$PYTHON_VERSION"; then
+                                py_version=$PYTHON_VERSION
+                        else
+                                py_version=`$PYTHON -c "import sys; \
+                                        print sys.version[[:3]]"`
+                        fi
+                fi
+
+                PYTHON_LDFLAGS=`$PYTHON -c "from distutils.sysconfig import *; \
+                        from string import join; \
+                        print '-L' + get_python_lib(0,1), \
+                        '-lpython';"`$py_version
+        fi
+        AC_MSG_RESULT([$PYTHON_LDFLAGS])
+        AC_SUBST([PYTHON_LDFLAGS])
+
+        #
+        # Check for site packages
+        #
+        AC_MSG_CHECKING([for Python site-packages path])
+        if test -z "$PYTHON_SITE_PKG"; then
+                PYTHON_SITE_PKG=`$PYTHON -c "import distutils.sysconfig; \
+                        print distutils.sysconfig.get_python_lib(0,0);"`
+        fi
+        AC_MSG_RESULT([$PYTHON_SITE_PKG])
+        AC_SUBST([PYTHON_SITE_PKG])
+
+        #
+        # libraries which must be linked in when embedding
+        #
+        AC_MSG_CHECKING(python extra libraries)
+        if test -z "$PYTHON_EXTRA_LIBS"; then
+           PYTHON_EXTRA_LIBS=`$PYTHON -c "import distutils.sysconfig; \
+                conf = distutils.sysconfig.get_config_var; \
+                print conf('LOCALMODLIBS'), conf('LIBS')"`
+        fi
+        AC_MSG_RESULT([$PYTHON_EXTRA_LIBS])
+        AC_SUBST(PYTHON_EXTRA_LIBS)
+
+        #
+        # linking flags needed when embedding
+        #
+        AC_MSG_CHECKING(python extra linking flags)
+        if test -z "$PYTHON_EXTRA_LDFLAGS"; then
+                PYTHON_EXTRA_LDFLAGS=`$PYTHON -c "import distutils.sysconfig; \
+                        conf = distutils.sysconfig.get_config_var; \
+                        print conf('LINKFORSHARED')"`
+        fi
+        AC_MSG_RESULT([$PYTHON_EXTRA_LDFLAGS])
+        AC_SUBST(PYTHON_EXTRA_LDFLAGS)
+
+        #
+        # final check to see if everything compiles alright
+        #
+        AC_MSG_CHECKING([consistency of all components of python development environment])
+        AC_LANG_PUSH([C])
+        # save current global flags
+        LIBS="$ac_save_LIBS $PYTHON_LDFLAGS"
+        CPPFLAGS="$ac_save_CPPFLAGS $PYTHON_CPPFLAGS"
+        AC_TRY_LINK([
+                #include <Python.h>
+        ],[
+                Py_Initialize();
+        ],[pythonexists=yes],[pythonexists=no])
+
+        AC_MSG_RESULT([$pythonexists])
+
+        if test ! "$pythonexists" = "yes"; then
+           AC_MSG_ERROR([
+  Could not link test program to Python. Maybe the main Python library has been
+  installed in some non-standard library path. If so, pass it to configure,
+  via the LDFLAGS environment variable.
+  Example: ./configure LDFLAGS="-L/usr/non-standard-path/python/lib"
+  ============================================================================
+   ERROR!
+   You probably have to install the development version of the Python package
+   for your distribution.  The exact name of this package varies among them.
+  ============================================================================
+           ])
+          PYTHON_VERSION=""
+        fi
+        AC_LANG_POP
+        # turn back to default flags
+        CPPFLAGS="$ac_save_CPPFLAGS"
+        LIBS="$ac_save_LIBS"
+
+        #
+        # all done!
+        #
+])
+
index 068e409abc8d4b64399af4fcf08c7f610752a3c3..3714ea93bbf5eea4912b1fea21e0329a9abeb092 100644 (file)
 /* Define to 1 if you have the <pwd.h> header file. */
 #undef HAVE_PWD_H
 
+/* Define if you have Python libraries and header files. */
+#undef HAVE_PYTHON
+
 /* Define to 1 if you have the `random' function. */
 #undef HAVE_RANDOM
 
 /* Define to 1 if you have the `strlcpy' function. */
 #undef HAVE_STRLCPY
 
+/* Define if you have Swig libraries and header files. */
+#undef HAVE_SWIG
+
 /* Define to 1 if you have the <syslog.h> header file. */
 #undef HAVE_SYSLOG_H
 
 /* Directory to chdir to */
 #undef RUN_DIR
 
+/* Shared data */
+#undef SHARE_DIR
+
 /* Define to 1 if you have the ANSI C header files. */
 #undef STDC_HEADERS
 
 /* the version of the windows API enabled */
 #undef WINVER
 
+/* Define if you want Python module. */
+#undef WITH_PYTHONMODULE
+
+/* Define if you want PyUnbound. */
+#undef WITH_PYUNBOUND
+
 /* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
    `char[]'. */
 #undef YYTEXT_POINTER
index ae7cc2922fcbbfd5400e033be745d366c42ff97f..bdb0d5304167fc4006bb475e38a84c07443f43be 100755 (executable)
--- a/configure
+++ b/configure
@@ -817,6 +817,7 @@ EGREP
 ub_conf_file
 UNBOUND_RUN_DIR
 UNBOUND_CHROOT_DIR
+UNBOUND_SHARE_DIR
 UNBOUND_PIDFILE
 UNBOUND_USERNAME
 DEPFLAG
@@ -843,6 +844,18 @@ ECHO
 RANLIB
 STRIP
 LIBTOOL
+PYTHON_VERSION
+PYTHON
+PYTHON_CPPFLAGS
+PYTHON_LDFLAGS
+PYTHON_SITE_PKG
+PYTHON_EXTRA_LIBS
+PYTHON_EXTRA_LDFLAGS
+SWIG
+SWIG_LIB
+swig
+WITH_PYTHONMODULE
+WITH_PYUNBOUND
 HAVE_SSL
 RUNTIME_PATH
 acx_pthread_config
@@ -867,7 +880,8 @@ LIBS
 CPPFLAGS
 CPP
 YACC
-YFLAGS'
+YFLAGS
+PYTHON_VERSION'
 ac_subdirs_all='ldns-src'
 
 # Initialize some variables set by options.
@@ -1466,6 +1480,8 @@ Optional Packages:
                           part of cfg file)
   --with-chroot-dir=path  set default directory to chroot to (by default same
                           as run-dir)
+  --with-share-dir=path   set default directory with shared data (by default
+                          same as share/unbound)
   --with-pidfile=filename set default pathname to unbound pidfile (default
                           run-dir/unbound.pid)
   --with-username=user    set default user that unbound changes to (default
@@ -1474,6 +1490,10 @@ Optional Packages:
   --with-pic              try to use only PIC/non-PIC objects [default=use
                           both]
   --with-tags[=TAGS]      include additional configurations [automatic]
+  --with-pyunbound        build PyUnbound, or --without-pyunbound to skip it.
+                          (default=no)
+  --with-pythonmodule     build Python module, or --without-pythonmodule to
+                          disable script engine. (default=no)
   --with-ssl=pathname     enable SSL (will check /usr/local/ssl /usr/lib/ssl
                           /usr/ssl /usr/pkg /usr/local /opt/local /usr/sfw
                           /usr)
@@ -1502,6 +1522,10 @@ Some influential environment variables:
   YFLAGS      The list of arguments that will be passed by default to $YACC.
               This script will default YFLAGS to the empty string to avoid a
               default value of `-d' given by some make applications.
+  PYTHON_VERSION
+              The installed Python version to use, for example '2.3'. This
+              string will be appended to the Python interpreter canonical
+              name.
 
 Use these variables to override the choices made by `configure' or to help
 it to find libraries and programs with nonstandard names/locations.
@@ -3392,6 +3416,21 @@ _ACEOF
 
 
 
+# Check whether --with-share-dir was given.
+if test "${with_share_dir+set}" = set; then
+  withval=$with_share_dir; UNBOUND_SHARE_DIR="$withval"
+else
+  UNBOUND_SHARE_DIR="$UNBOUND_RUN_DIR"
+fi
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SHARE_DIR "$UNBOUND_SHARE_DIR"
+_ACEOF
+
+
+
 # Check whether --with-pidfile was given.
 if test "${with_pidfile+set}" = set; then
   withval=$with_pidfile; UNBOUND_PIDFILE="$withval"
@@ -6842,7 +6881,7 @@ ia64-*-hpux*)
   ;;
 *-*-irix6*)
   # Find out which ABI we are using.
-  echo '#line 6845 "configure"' > conftest.$ac_ext
+  echo '#line 6884 "configure"' > conftest.$ac_ext
   if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
@@ -8156,11 +8195,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:8159: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:8198: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:8163: \$? = $ac_status" >&5
+   echo "$as_me:8202: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -8446,11 +8485,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:8449: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:8488: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:8453: \$? = $ac_status" >&5
+   echo "$as_me:8492: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -8550,11 +8589,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:8553: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:8592: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:8557: \$? = $ac_status" >&5
+   echo "$as_me:8596: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -10901,7 +10940,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 10904 "configure"
+#line 10943 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11001,7 +11040,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 11004 "configure"
+#line 11043 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -13421,11 +13460,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:13424: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:13463: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:13428: \$? = $ac_status" >&5
+   echo "$as_me:13467: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -13525,11 +13564,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:13528: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:13567: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:13532: \$? = $ac_status" >&5
+   echo "$as_me:13571: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -15089,11 +15128,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:15092: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:15131: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:15096: \$? = $ac_status" >&5
+   echo "$as_me:15135: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -15193,11 +15232,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:15196: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:15235: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:15200: \$? = $ac_status" >&5
+   echo "$as_me:15239: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -17382,11 +17421,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:17385: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:17424: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:17389: \$? = $ac_status" >&5
+   echo "$as_me:17428: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -17672,11 +17711,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:17675: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:17714: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:17679: \$? = $ac_status" >&5
+   echo "$as_me:17718: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -17776,11 +17815,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:17779: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:17818: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:17783: \$? = $ac_status" >&5
+   echo "$as_me:17822: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -21662,6 +21701,563 @@ echo "${ECHO_T}Fixing libtool for -rpath problems." >&6; }
 fi
 
 
+# Check for PyUnbound
+
+# Check whether --with-pyunbound was given.
+if test "${with_pyunbound+set}" = set; then
+  withval=$with_pyunbound;
+else
+   withval="no"
+fi
+
+
+ub_test_python=no
+ub_with_pyunbound=no
+if test x_$withval != x_no; then
+   ub_with_pyunbound=yes
+   ub_test_python=yes
+fi
+
+# Check for Python module
+
+# Check whether --with-pythonmodule was given.
+if test "${with_pythonmodule+set}" = set; then
+  withval=$with_pythonmodule;
+else
+   withval="no"
+fi
+
+
+ub_with_pythonmod=no
+if test x_$withval != x_no; then
+   ub_with_pythonmod=yes
+   ub_test_python=yes
+fi
+
+# Check for Python & SWIG only on PyUnbound or PyModule
+if test x_$ub_test_python != x_no; then
+
+   # Check for Python
+   ub_have_python=no
+
+        #
+        # Allow the use of a (user set) custom python version
+        #
+
+
+        # Extract the first word of "python[$PYTHON_VERSION]", so it can be a program name with args.
+set dummy python$PYTHON_VERSION; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_path_PYTHON+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $PYTHON in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_PYTHON="$PYTHON" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_PYTHON="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+PYTHON=$ac_cv_path_PYTHON
+if test -n "$PYTHON"; then
+  { echo "$as_me:$LINENO: result: $PYTHON" >&5
+echo "${ECHO_T}$PYTHON" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+        if test -z "$PYTHON"; then
+           { { echo "$as_me:$LINENO: error: Cannot find python$PYTHON_VERSION in your system path" >&5
+echo "$as_me: error: Cannot find python$PYTHON_VERSION in your system path" >&2;}
+   { (exit 1); exit 1; }; }
+           PYTHON_VERSION=""
+        fi
+
+        #
+        # Check for a version of Python >= 2.1.0
+        #
+        { echo "$as_me:$LINENO: checking for a version of Python >= '2.1.0'" >&5
+echo $ECHO_N "checking for a version of Python >= '2.1.0'... $ECHO_C" >&6; }
+        ac_supports_python_ver=`$PYTHON -c "import sys, string; \
+                ver = string.split(sys.version)[0]; \
+                print ver >= '2.1.0'"`
+        if test "$ac_supports_python_ver" != "True"; then
+                if test -z "$PYTHON_NOVERSIONCHECK"; then
+                        { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+                        { { echo "$as_me:$LINENO: error:
+This version of the AC_PYTHON_DEVEL macro
+doesn't work properly with versions of Python before
+2.1.0. You may need to re-run configure, setting the
+variables PYTHON_CPPFLAGS, PYTHON_LDFLAGS, PYTHON_SITE_PKG,
+PYTHON_EXTRA_LIBS and PYTHON_EXTRA_LDFLAGS by hand.
+Moreover, to disable this check, set PYTHON_NOVERSIONCHECK
+to something else than an empty string.
+
+See \`config.log' for more details." >&5
+echo "$as_me: error:
+This version of the AC_PYTHON_DEVEL macro
+doesn't work properly with versions of Python before
+2.1.0. You may need to re-run configure, setting the
+variables PYTHON_CPPFLAGS, PYTHON_LDFLAGS, PYTHON_SITE_PKG,
+PYTHON_EXTRA_LIBS and PYTHON_EXTRA_LDFLAGS by hand.
+Moreover, to disable this check, set PYTHON_NOVERSIONCHECK
+to something else than an empty string.
+
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+                else
+                        { echo "$as_me:$LINENO: result: skip at user request" >&5
+echo "${ECHO_T}skip at user request" >&6; }
+                fi
+        else
+                { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+        fi
+
+        #
+        # if the macro parameter ``version'' is set, honour it
+        #
+        if test -n ""; then
+                { echo "$as_me:$LINENO: checking for a version of Python " >&5
+echo $ECHO_N "checking for a version of Python ... $ECHO_C" >&6; }
+                ac_supports_python_ver=`$PYTHON -c "import sys, string; \
+                        ver = string.split(sys.version)[0]; \
+                        print ver "`
+                if test "$ac_supports_python_ver" = "True"; then
+                   { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+                else
+                        { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+                        { { echo "$as_me:$LINENO: error: this package requires Python .
+If you have it installed, but it isn't the default Python
+interpreter in your system path, please pass the PYTHON_VERSION
+variable to configure. See \`\`configure --help'' for reference.
+" >&5
+echo "$as_me: error: this package requires Python .
+If you have it installed, but it isn't the default Python
+interpreter in your system path, please pass the PYTHON_VERSION
+variable to configure. See \`\`configure --help'' for reference.
+" >&2;}
+   { (exit 1); exit 1; }; }
+                        PYTHON_VERSION=""
+                fi
+        fi
+
+        #
+        # Check if you have distutils, else fail
+        #
+        { echo "$as_me:$LINENO: checking for the distutils Python package" >&5
+echo $ECHO_N "checking for the distutils Python package... $ECHO_C" >&6; }
+        ac_distutils_result=`$PYTHON -c "import distutils" 2>&1`
+        if test -z "$ac_distutils_result"; then
+                { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+        else
+                { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+                { { echo "$as_me:$LINENO: error: cannot import Python module \"distutils\".
+Please check your Python installation. The error was:
+$ac_distutils_result" >&5
+echo "$as_me: error: cannot import Python module \"distutils\".
+Please check your Python installation. The error was:
+$ac_distutils_result" >&2;}
+   { (exit 1); exit 1; }; }
+                PYTHON_VERSION=""
+        fi
+
+        #
+        # Check for Python include path
+        #
+        { echo "$as_me:$LINENO: checking for Python include path" >&5
+echo $ECHO_N "checking for Python include path... $ECHO_C" >&6; }
+        if test -z "$PYTHON_CPPFLAGS"; then
+                python_path=`$PYTHON -c "import distutils.sysconfig; \
+                        print distutils.sysconfig.get_python_inc();"`
+                if test -n "${python_path}"; then
+                        python_path="-I$python_path"
+                fi
+                PYTHON_CPPFLAGS=$python_path
+        fi
+        { echo "$as_me:$LINENO: result: $PYTHON_CPPFLAGS" >&5
+echo "${ECHO_T}$PYTHON_CPPFLAGS" >&6; }
+
+
+        #
+        # Check for Python library path
+        #
+        { echo "$as_me:$LINENO: checking for Python library path" >&5
+echo $ECHO_N "checking for Python library path... $ECHO_C" >&6; }
+        if test -z "$PYTHON_LDFLAGS"; then
+                # (makes two attempts to ensure we've got a version number
+                # from the interpreter)
+                py_version=`$PYTHON -c "from distutils.sysconfig import *; \
+                        from string import join; \
+                        print join(get_config_vars('VERSION'))"`
+                if test "$py_version" == "None"; then
+                        if test -n "$PYTHON_VERSION"; then
+                                py_version=$PYTHON_VERSION
+                        else
+                                py_version=`$PYTHON -c "import sys; \
+                                        print sys.version[:3]"`
+                        fi
+                fi
+
+                PYTHON_LDFLAGS=`$PYTHON -c "from distutils.sysconfig import *; \
+                        from string import join; \
+                        print '-L' + get_python_lib(0,1), \
+                        '-lpython';"`$py_version
+        fi
+        { echo "$as_me:$LINENO: result: $PYTHON_LDFLAGS" >&5
+echo "${ECHO_T}$PYTHON_LDFLAGS" >&6; }
+
+
+        #
+        # Check for site packages
+        #
+        { echo "$as_me:$LINENO: checking for Python site-packages path" >&5
+echo $ECHO_N "checking for Python site-packages path... $ECHO_C" >&6; }
+        if test -z "$PYTHON_SITE_PKG"; then
+                PYTHON_SITE_PKG=`$PYTHON -c "import distutils.sysconfig; \
+                        print distutils.sysconfig.get_python_lib(0,0);"`
+        fi
+        { echo "$as_me:$LINENO: result: $PYTHON_SITE_PKG" >&5
+echo "${ECHO_T}$PYTHON_SITE_PKG" >&6; }
+
+
+        #
+        # libraries which must be linked in when embedding
+        #
+        { echo "$as_me:$LINENO: checking python extra libraries" >&5
+echo $ECHO_N "checking python extra libraries... $ECHO_C" >&6; }
+        if test -z "$PYTHON_EXTRA_LIBS"; then
+           PYTHON_EXTRA_LIBS=`$PYTHON -c "import distutils.sysconfig; \
+                conf = distutils.sysconfig.get_config_var; \
+                print conf('LOCALMODLIBS'), conf('LIBS')"`
+        fi
+        { echo "$as_me:$LINENO: result: $PYTHON_EXTRA_LIBS" >&5
+echo "${ECHO_T}$PYTHON_EXTRA_LIBS" >&6; }
+
+
+        #
+        # linking flags needed when embedding
+        #
+        { echo "$as_me:$LINENO: checking python extra linking flags" >&5
+echo $ECHO_N "checking python extra linking flags... $ECHO_C" >&6; }
+        if test -z "$PYTHON_EXTRA_LDFLAGS"; then
+                PYTHON_EXTRA_LDFLAGS=`$PYTHON -c "import distutils.sysconfig; \
+                        conf = distutils.sysconfig.get_config_var; \
+                        print conf('LINKFORSHARED')"`
+        fi
+        { echo "$as_me:$LINENO: result: $PYTHON_EXTRA_LDFLAGS" >&5
+echo "${ECHO_T}$PYTHON_EXTRA_LDFLAGS" >&6; }
+
+
+        #
+        # final check to see if everything compiles alright
+        #
+        { echo "$as_me:$LINENO: checking consistency of all components of python development environment" >&5
+echo $ECHO_N "checking consistency of all components of python development environment... $ECHO_C" >&6; }
+        ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+        # save current global flags
+        LIBS="$ac_save_LIBS $PYTHON_LDFLAGS"
+        CPPFLAGS="$ac_save_CPPFLAGS $PYTHON_CPPFLAGS"
+        cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+                #include <Python.h>
+
+int
+main ()
+{
+
+                Py_Initialize();
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  pythonexists=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       pythonexists=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+
+        { echo "$as_me:$LINENO: result: $pythonexists" >&5
+echo "${ECHO_T}$pythonexists" >&6; }
+
+        if test ! "$pythonexists" = "yes"; then
+           { { echo "$as_me:$LINENO: error:
+  Could not link test program to Python. Maybe the main Python library has been
+  installed in some non-standard library path. If so, pass it to configure,
+  via the LDFLAGS environment variable.
+  Example: ./configure LDFLAGS=\"-L/usr/non-standard-path/python/lib\"
+  ============================================================================
+   ERROR!
+   You probably have to install the development version of the Python package
+   for your distribution.  The exact name of this package varies among them.
+  ============================================================================
+           " >&5
+echo "$as_me: error:
+  Could not link test program to Python. Maybe the main Python library has been
+  installed in some non-standard library path. If so, pass it to configure,
+  via the LDFLAGS environment variable.
+  Example: ./configure LDFLAGS=\"-L/usr/non-standard-path/python/lib\"
+  ============================================================================
+   ERROR!
+   You probably have to install the development version of the Python package
+   for your distribution.  The exact name of this package varies among them.
+  ============================================================================
+           " >&2;}
+   { (exit 1); exit 1; }; }
+          PYTHON_VERSION=""
+        fi
+        ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+        # turn back to default flags
+        CPPFLAGS="$ac_save_CPPFLAGS"
+        LIBS="$ac_save_LIBS"
+
+        #
+        # all done!
+        #
+
+   if test ! -z "PYTHON_VERSION"; then
+
+      # Have Python
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_PYTHON 1
+_ACEOF
+
+      LIBS="$PYTHON_LDFLAGS $LIBS"
+      CFLAGS="$CFLAGS $PYTHON_CPPFLAGS"
+      ub_have_python=yes
+
+      # Check for SWIG
+      ub_have_swig=no
+
+        # Extract the first word of "swig", so it can be a program name with args.
+set dummy swig; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_path_SWIG+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $SWIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_SWIG="$SWIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_SWIG="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+SWIG=$ac_cv_path_SWIG
+if test -n "$SWIG"; then
+  { echo "$as_me:$LINENO: result: $SWIG" >&5
+echo "${ECHO_T}$SWIG" >&6; }
+else
+  { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+        if test -z "$SWIG" ; then
+                { echo "$as_me:$LINENO: WARNING: cannot find 'swig' program. You should look at http://www.swig.org" >&5
+echo "$as_me: WARNING: cannot find 'swig' program. You should look at http://www.swig.org" >&2;}
+                SWIG='echo "Error: SWIG is not installed. You should look at http://www.swig.org" ; false'
+        elif test -n "" ; then
+                { echo "$as_me:$LINENO: checking for SWIG version" >&5
+echo $ECHO_N "checking for SWIG version... $ECHO_C" >&6; }
+                swig_version=`$SWIG -version 2>&1 | grep 'SWIG Version' | sed 's/.*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/g'`
+                { echo "$as_me:$LINENO: result: $swig_version" >&5
+echo "${ECHO_T}$swig_version" >&6; }
+                if test -n "$swig_version" ; then
+                        # Calculate the required version number components
+                        required=
+                        required_major=`echo $required | sed 's/[^0-9].*//'`
+                        if test -z "$required_major" ; then
+                                required_major=0
+                        fi
+                        required=`echo $required | sed 's/[0-9]*[^0-9]//'`
+                        required_minor=`echo $required | sed 's/[^0-9].*//'`
+                        if test -z "$required_minor" ; then
+                                required_minor=0
+                        fi
+                        required=`echo $required | sed 's/[0-9]*[^0-9]//'`
+                        required_patch=`echo $required | sed 's/[^0-9].*//'`
+                        if test -z "$required_patch" ; then
+                                required_patch=0
+                        fi
+                        # Calculate the available version number components
+                        available=$swig_version
+                        available_major=`echo $available | sed 's/[^0-9].*//'`
+                        if test -z "$available_major" ; then
+                                available_major=0
+                        fi
+                        available=`echo $available | sed 's/[0-9]*[^0-9]//'`
+                        available_minor=`echo $available | sed 's/[^0-9].*//'`
+                        if test -z "$available_minor" ; then
+                                available_minor=0
+                        fi
+                        available=`echo $available | sed 's/[0-9]*[^0-9]//'`
+                        available_patch=`echo $available | sed 's/[^0-9].*//'`
+                        if test -z "$available_patch" ; then
+                                available_patch=0
+                        fi
+                        if test $available_major -ne $required_major \
+                                -o $available_minor -ne $required_minor \
+                                -o $available_patch -lt $required_patch ; then
+                                { echo "$as_me:$LINENO: WARNING: SWIG version >=  is required.  You have $swig_version.  You should look at http://www.swig.org" >&5
+echo "$as_me: WARNING: SWIG version >=  is required.  You have $swig_version.  You should look at http://www.swig.org" >&2;}
+                                SWIG='echo "Error: SWIG version >=  is required.  You have '"$swig_version"'.  You should look at http://www.swig.org" ; false'
+                        else
+                                { echo "$as_me:$LINENO: SWIG executable is '$SWIG'" >&5
+echo "$as_me: SWIG executable is '$SWIG'" >&6;}
+                                SWIG_LIB=`$SWIG -swiglib`
+                                { echo "$as_me:$LINENO: SWIG library directory is '$SWIG_LIB'" >&5
+echo "$as_me: SWIG library directory is '$SWIG_LIB'" >&6;}
+                        fi
+                else
+                        { echo "$as_me:$LINENO: WARNING: cannot determine SWIG version" >&5
+echo "$as_me: WARNING: cannot determine SWIG version" >&2;}
+                        SWIG='echo "Error: Cannot determine SWIG version.  You should look at http://www.swig.org" ; false'
+                fi
+        fi
+
+
+      { echo "$as_me:$LINENO: checking SWIG" >&5
+echo $ECHO_N "checking SWIG... $ECHO_C" >&6; }
+      if test -z SWIG; then
+         { echo "$as_me:$LINENO: result: failed" >&5
+echo "${ECHO_T}failed" >&6; }
+         swig=""
+
+      else
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_SWIG 1
+_ACEOF
+
+         swig="$SWIG"
+
+         { echo "$as_me:$LINENO: result: done" >&5
+echo "${ECHO_T}done" >&6; }
+      fi
+
+      # If have Python & SWIG
+      if test ! -z "SWIG"; then
+
+         # Declare PythonMod
+         if test x_$ub_with_pythonmod != x_no; then
+            { echo "$as_me:$LINENO: result: Will build Python module." >&5
+echo "${ECHO_T}Will build Python module." >&6; }
+
+cat >>confdefs.h <<\_ACEOF
+#define WITH_PYTHONMODULE 1
+_ACEOF
+
+            WITH_PYTHONMODULE=yes
+
+         fi
+
+         # Declare PyUnbound
+         if test x_$ub_with_pyunbound != x_no; then
+            { echo "$as_me:$LINENO: result: Will build PyUnbound." >&5
+echo "${ECHO_T}Will build PyUnbound." >&6; }
+
+cat >>confdefs.h <<\_ACEOF
+#define WITH_PYUNBOUND 1
+_ACEOF
+
+            WITH_PYUNBOUND=yes
+
+         fi
+      else
+         { echo "$as_me:$LINENO: result: SWIG libraries not found" >&5
+echo "${ECHO_T}SWIG libraries not found" >&6; }
+         ub_with_pyunbound=no
+         ub_with_pythonmod=no
+      fi
+   else
+      { echo "$as_me:$LINENO: result: Python libraries not found" >&5
+echo "${ECHO_T}Python libraries not found" >&6; }
+      ub_with_pyunbound=no
+      ub_with_pythonmod=no
+   fi
+fi
+
 # Checks for libraries.
 
 
@@ -28141,6 +28737,7 @@ EGREP!$EGREP$ac_delim
 ub_conf_file!$ub_conf_file$ac_delim
 UNBOUND_RUN_DIR!$UNBOUND_RUN_DIR$ac_delim
 UNBOUND_CHROOT_DIR!$UNBOUND_CHROOT_DIR$ac_delim
+UNBOUND_SHARE_DIR!$UNBOUND_SHARE_DIR$ac_delim
 UNBOUND_PIDFILE!$UNBOUND_PIDFILE$ac_delim
 UNBOUND_USERNAME!$UNBOUND_USERNAME$ac_delim
 DEPFLAG!$DEPFLAG$ac_delim
@@ -28167,11 +28764,64 @@ ECHO!$ECHO$ac_delim
 RANLIB!$RANLIB$ac_delim
 STRIP!$STRIP$ac_delim
 LIBTOOL!$LIBTOOL$ac_delim
+PYTHON_VERSION!$PYTHON_VERSION$ac_delim
+PYTHON!$PYTHON$ac_delim
+PYTHON_CPPFLAGS!$PYTHON_CPPFLAGS$ac_delim
+PYTHON_LDFLAGS!$PYTHON_LDFLAGS$ac_delim
+PYTHON_SITE_PKG!$PYTHON_SITE_PKG$ac_delim
+PYTHON_EXTRA_LIBS!$PYTHON_EXTRA_LIBS$ac_delim
+PYTHON_EXTRA_LDFLAGS!$PYTHON_EXTRA_LDFLAGS$ac_delim
+SWIG!$SWIG$ac_delim
+SWIG_LIB!$SWIG_LIB$ac_delim
+swig!$swig$ac_delim
+WITH_PYTHONMODULE!$WITH_PYTHONMODULE$ac_delim
+WITH_PYUNBOUND!$WITH_PYUNBOUND$ac_delim
 HAVE_SSL!$HAVE_SSL$ac_delim
 RUNTIME_PATH!$RUNTIME_PATH$ac_delim
 acx_pthread_config!$acx_pthread_config$ac_delim
 PTHREAD_CC!$PTHREAD_CC$ac_delim
 PTHREAD_LIBS!$PTHREAD_LIBS$ac_delim
+_ACEOF
+
+  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then
+    break
+  elif $ac_last_try; then
+    { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+   { (exit 1); exit 1; }; }
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+
+ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed`
+if test -n "$ac_eof"; then
+  ac_eof=`echo "$ac_eof" | sort -nru | sed 1q`
+  ac_eof=`expr $ac_eof + 1`
+fi
+
+cat >>$CONFIG_STATUS <<_ACEOF
+cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+_ACEOF
+sed '
+s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g
+s/^/s,@/; s/!/@,|#_!!_#|/
+:n
+t n
+s/'"$ac_delim"'$/,g/; t
+s/$/\\/; p
+N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n
+' >>$CONFIG_STATUS <conf$$subs.sed
+rm -f conf$$subs.sed
+cat >>$CONFIG_STATUS <<_ACEOF
+CEOF$ac_eof
+_ACEOF
+
+
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  cat >conf$$subs.sed <<_ACEOF
 PTHREAD_CFLAGS!$PTHREAD_CFLAGS$ac_delim
 staticexe!$staticexe$ac_delim
 CHECKLOCK_SRC!$CHECKLOCK_SRC$ac_delim
@@ -28182,7 +28832,7 @@ subdirs!$subdirs$ac_delim
 LTLIBOBJS!$LTLIBOBJS$ac_delim
 _ACEOF
 
-  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 92; then
+  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 8; then
     break
   elif $ac_last_try; then
     { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
@@ -28200,7 +28850,7 @@ if test -n "$ac_eof"; then
 fi
 
 cat >>$CONFIG_STATUS <<_ACEOF
-cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof
+cat >"\$tmp/subs-2.sed" <<\CEOF$ac_eof
 /@[a-zA-Z_][a-zA-Z_0-9]*@/!b end
 _ACEOF
 sed '
@@ -28458,7 +29108,7 @@ s&@builddir@&$ac_builddir&;t t
 s&@abs_builddir@&$ac_abs_builddir&;t t
 s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
 $ac_datarootdir_hack
-" $ac_file_inputs | sed -f "$tmp/subs-1.sed" >$tmp/out
+" $ac_file_inputs | sed -f "$tmp/subs-1.sed" | sed -f "$tmp/subs-2.sed" >$tmp/out
 
 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
   { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
index 49a39cdcbd786c5c312e24a29dfc97745278befc..f5f7d13711d26e6efd9f959d3aaafcce3c52f281 100644 (file)
@@ -3,6 +3,8 @@
 AC_PREREQ(2.56)
 sinclude(acx_nlnetlabs.m4)
 sinclude(acx_pthread.m4)
+sinclude(acx_python.m4)
+sinclude(ac_pkg_swig.m4)
 
 AC_INIT(unbound, 1.3.0, unbound-bugs@nlnetlabs.nl, unbound)
 
@@ -101,6 +103,14 @@ AC_SUBST(UNBOUND_CHROOT_DIR)
 ACX_ESCAPE_BACKSLASH($UNBOUND_CHOOT_DIR, hdr_chroot)
 AC_DEFINE_UNQUOTED(CHROOT_DIR, ["$hdr_chroot"], [Directory to chroot to])
 
+AC_ARG_WITH(share-dir,
+    AC_HELP_STRING([--with-share-dir=path],
+    [set default directory with shared data (by default same as share/unbound)]),
+    UNBOUND_SHARE_DIR="$withval",
+    UNBOUND_SHARE_DIR="$UNBOUND_RUN_DIR")
+AC_SUBST(UNBOUND_SHARE_DIR)
+AC_DEFINE_UNQUOTED(SHARE_DIR, ["$UNBOUND_SHARE_DIR"], [Shared data])
+
 AC_ARG_WITH(pidfile, 
     AC_HELP_STRING([--with-pidfile=filename], 
     [set default pathname to unbound pidfile (default run-dir/unbound.pid)]), 
@@ -197,6 +207,88 @@ ACX_TYPE_IN_PORT_T
 # add option to disable the evil rpath
 ACX_ARG_RPATH
 
+# Check for PyUnbound
+AC_ARG_WITH(pyunbound,
+   AC_HELP_STRING([--with-pyunbound],
+   [build PyUnbound, or --without-pyunbound to skip it. (default=no)]),
+   [], [ withval="no" ])
+
+ub_test_python=no
+ub_with_pyunbound=no
+if test x_$withval != x_no; then
+   ub_with_pyunbound=yes
+   ub_test_python=yes
+fi
+
+# Check for Python module
+AC_ARG_WITH(pythonmodule,
+   AC_HELP_STRING([--with-pythonmodule],
+   [build Python module, or --without-pythonmodule to disable script engine. (default=no)]),
+   [], [ withval="no" ])
+
+ub_with_pythonmod=no
+if test x_$withval != x_no; then
+   ub_with_pythonmod=yes
+   ub_test_python=yes
+fi
+
+# Check for Python & SWIG only on PyUnbound or PyModule
+if test x_$ub_test_python != x_no; then
+
+   # Check for Python
+   ub_have_python=no
+   AC_PYTHON_DEVEL
+   if test ! -z "PYTHON_VERSION"; then
+
+      # Have Python
+      AC_DEFINE(HAVE_PYTHON,1,[Define if you have Python libraries and header files.])
+      LIBS="$PYTHON_LDFLAGS $LIBS"
+      CFLAGS="$CFLAGS $PYTHON_CPPFLAGS"
+      ub_have_python=yes
+
+      # Check for SWIG
+      ub_have_swig=no
+      AC_PROG_SWIG
+      AC_MSG_CHECKING(SWIG)
+      if test -z SWIG; then
+         AC_MSG_RESULT(failed, won't build Python module and PyUnbound)
+         AC_SUBST(swig, "")
+      else
+         AC_DEFINE(HAVE_SWIG, 1, [Define if you have Swig libraries and header files.])
+         AC_SUBST(swig, "$SWIG")
+         AC_MSG_RESULT(done)
+      fi
+
+      # If have Python & SWIG
+      if test ! -z "SWIG"; then
+
+         # Declare PythonMod
+         if test x_$ub_with_pythonmod != x_no; then
+            AC_MSG_RESULT(Will build Python module.)
+            AC_DEFINE(WITH_PYTHONMODULE, 1, [Define if you want Python module.])
+            WITH_PYTHONMODULE=yes
+            AC_SUBST(WITH_PYTHONMODULE)
+         fi
+
+         # Declare PyUnbound
+         if test x_$ub_with_pyunbound != x_no; then
+            AC_MSG_RESULT(Will build PyUnbound.)
+            AC_DEFINE(WITH_PYUNBOUND, 1, [Define if you want PyUnbound.])
+            WITH_PYUNBOUND=yes
+            AC_SUBST(WITH_PYUNBOUND)
+         fi
+      else
+         AC_MSG_RESULT(SWIG libraries not found, won't build PythonMod or PyUnbound)
+         ub_with_pyunbound=no
+         ub_with_pythonmod=no
+      fi
+   else
+      AC_MSG_RESULT(Python libraries not found, won't build PythonMod or PyUnbound)
+      ub_with_pyunbound=no
+      ub_with_pythonmod=no
+   fi
+fi
+
 # Checks for libraries.
 ACX_WITH_SSL
 ACX_LIB_SSL
index f8ff7d9b162751b711c86e51c3d1e578218f71be..f35bca7abe08f3b37305f4669246a5efae72b3f2 100644 (file)
@@ -12,3 +12,4 @@ distribution but may be helpful.
 * unbound_cacti.tar.gz : setup files for cacti statistics report
 * selinux: the .fc and .te files for SElinux protection of the unbound daemon
 * unbound.plist: launchd configuration file for MacOSX.
+* python: use libunbound from python.
diff --git a/contrib/python/LICENSE b/contrib/python/LICENSE
new file mode 100644 (file)
index 0000000..7b769d0
--- /dev/null
@@ -0,0 +1,28 @@
+Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+                    Marek Vavrusa  (xvavru00 AT stud.fit.vutbr.cz)
+
+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 the organization 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
diff --git a/contrib/python/Makefile b/contrib/python/Makefile
new file mode 100644 (file)
index 0000000..1c8a500
--- /dev/null
@@ -0,0 +1,74 @@
+#
+# Makefile: compilation of pyUnbound and documentation, testing
+#
+# Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+#                     Marek Vavrusa  (xvavru00 AT stud.fit.vutbr.cz)
+#
+# This software is open source.
+# 
+# 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 the organization 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 COPYRIGHT HOLDERS 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.
+
+help:
+       @echo "Please use \`make <target>' where <target> is one of"
+       @echo "  testenv   to make test environment and run bash "
+       @echo "            usefull in case you don't want to install unbound but want to test examples"
+       @echo "  doc       to make documentation"
+       @echo "  clean     clean all"
+
+.PHONY: testenv clean doc swig
+
+_unbound.so:   ../../Makefile
+       $(MAKE) -C ../..
+
+../../.libs/libunbound.so.0:   ../../Makefile
+       $(MAKE) -C ../..
+
+../../ldns-src/lib/libldns.so: ../../ldns-src/Makefile
+       $(MAKE) -C ../../ldns-src
+
+clean:
+       rm -rdf examples/unbound
+       rm -f _unbound.so libunbound_wrap.o
+       $(MAKE) -C ../.. clean
+
+testenv: ../../.libs/libunbound.so.0 ../../ldns-src/lib/libldns.so _unbound.so
+       rm -rdf examples/unbound
+       cd examples && mkdir unbound && ln -s ../../unbound.py unbound/__init__.py && ln -s ../../_unbound.so unbound/_unbound.so && ln -s ../../../../.libs/libunbound.so.0 unbound/libunbound.so.0 && ln -s ../../../../ldns-src/lib/libldns.so.1 unbound/libldns.so.1 && ls -la
+       @echo "Run a script by typing ./script_name.py"
+       cd examples && LD_LIBRARY_PATH=unbound bash
+       rm -rdf examples/unbound
+
+doc: ../../.libs/libunbound.so.0 _unbound.so
+       $(MAKE) -C docs html
+
+#for development only
+swig: libunbound.i 
+       swig -python -o libunbound_wrap.c -I../.. libunbound.i
+       gcc -c libunbound_wrap.c -O9 -fPIC -I../.. -I/usr/include/python2.5 -I. -o libunbound_wrap.o
+       ld -shared libunbound_wrap.o -L../../.libs -lunbound -o _unbound.so 
+
diff --git a/contrib/python/docs/Makefile b/contrib/python/docs/Makefile
new file mode 100644 (file)
index 0000000..d54ecb9
--- /dev/null
@@ -0,0 +1,70 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS    =
+SPHINXBUILD   = sphinx-build
+PAPER         =
+
+# Internal variables.
+PAPEROPT_a4     = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS   = -d build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
+
+.PHONY: help clean html web pickle htmlhelp latex changes linkcheck
+
+help:
+       @echo "Please use \`make <target>' where <target> is one of"
+       @echo "  html      to make standalone HTML files"
+       @echo "  pickle    to make pickle files (usable by e.g. sphinx-web)"
+       @echo "  htmlhelp  to make HTML files and a HTML help project"
+       @echo "  latex     to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+       @echo "  changes   to make an overview over all changed/added/deprecated items"
+       @echo "  linkcheck to check all external links for integrity"
+
+clean:
+       -rm -rf build/*
+
+html:
+       mkdir -p build/html build/doctrees
+       LD_LIBRARY_PATH=../../../.libs:../../../ldns-src/lib $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) build/html
+       @echo
+       @echo "Build finished. The HTML pages are in build/html."
+
+pickle:
+       mkdir -p build/pickle build/doctrees
+       LD_LIBRARY_PATH=../../../.libs:../../../ldns-src/lib $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) build/pickle
+       @echo
+       @echo "Build finished; now you can process the pickle files or run"
+       @echo "  sphinx-web build/pickle"
+       @echo "to start the sphinx-web server."
+
+web: pickle
+
+htmlhelp:
+       mkdir -p build/htmlhelp build/doctrees
+       LD_LIBRARY_PATH=../../../.libs:../../../ldns-src/lib $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) build/htmlhelp
+       @echo
+       @echo "Build finished; now you can run HTML Help Workshop with the" \
+             ".hhp project file in build/htmlhelp."
+
+latex:
+       mkdir -p build/latex build/doctrees
+       LD_LIBRARY_PATH=../../../.libs:../../../ldns-src/lib $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) build/latex
+       @echo
+       @echo "Build finished; the LaTeX files are in build/latex."
+       @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
+             "run these through (pdf)latex."
+
+changes:
+       mkdir -p build/changes build/doctrees
+       LD_LIBRARY_PATH=../../../.libs:../../../ldns-src/lib $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) build/changes
+       @echo
+       @echo "The overview file is in build/changes."
+
+linkcheck:
+       mkdir -p build/linkcheck build/doctrees
+       LD_LIBRARY_PATH=../../../.libs:../../../ldns-src/lib $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) build/linkcheck
+       @echo
+       @echo "Link check complete; look for any errors in the above output " \
+             "or in build/linkcheck/output.txt."
diff --git a/contrib/python/docs/source/conf.py b/contrib/python/docs/source/conf.py
new file mode 100644 (file)
index 0000000..6309d50
--- /dev/null
@@ -0,0 +1,179 @@
+# -*- coding: utf-8 -*-
+#
+# Unbound documentation build configuration file
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# The contents of this file are pickled, so don't put values in the namespace
+# that aren't pickleable (module imports are okay, they're removed automatically).
+#
+# All configuration values have a default value; values that are commented out
+# serve to show the default value.
+
+import sys, os
+
+# If your extensions are in another directory, add it here. If the directory
+# is relative to the documentation root, use os.path.abspath to make it
+# absolute, like shown here.
+sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__),'../../')))
+#print sys.path
+
+# General configuration
+# ---------------------
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General substitutions.
+project = 'pyUnbound'
+copyright = '2009, Zdenek Vasicek, Marek Vavrusa'
+
+# The default replacements for |version| and |release|, also used in various
+# other places throughout the built documents.
+#
+# The short X.Y version.
+version = '1.0'
+# The full version, including alpha/beta/rc tags.
+release = '1.0.0'
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+today_fmt = '%B %d, %Y'
+
+# List of documents that shouldn't be included in the build.
+#unused_docs = []
+
+# List of directories, relative to source directories, that shouldn't be searched
+# for source files.
+#exclude_dirs = []
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+
+# Options for HTML output
+# -----------------------
+
+# The style sheet to use for HTML and HTML Help pages. A file of that name
+# must exist either in Sphinx' static/ path, or in one of the custom paths
+# given in html_static_path.
+html_style = 'default.css'
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar.  Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (within the static path) to place at the top of
+# the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+html_use_modindex = False
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, the reST sources are included in the HTML build as _sources/<name>.
+html_copy_source = False
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.  The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = ''
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'Unbounddoc'
+
+
+# Options for LaTeX output
+# ------------------------
+
+# The paper size ('letter' or 'a4').
+#latex_paper_size = 'letter'
+
+# The font size ('10pt', '11pt' or '12pt').
+#latex_font_size = '10pt'
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, document class [howto/manual]).
+latex_documents = [
+  ('index', 'Unbound.tex', 'Unbound Documentation',
+   'Zdenek Vasicek, Marek Vavrusa', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# Additional stuff for the LaTeX preamble.
+#latex_preamble = ''
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_use_modindex = True
diff --git a/contrib/python/docs/source/examples/example1a.rst b/contrib/python/docs/source/examples/example1a.rst
new file mode 100644 (file)
index 0000000..3c81547
--- /dev/null
@@ -0,0 +1,26 @@
+.. _example_resolve_name:
+
+==============================
+Resolve a name
+==============================
+
+This basic example shows how to create a context and resolve a host address (DNS record of A type).
+
+::
+
+       #!/usr/bin/python
+       import unbound
+       
+       ctx = unbound.ub_ctx()
+       ctx.resolvconf("/etc/resolv.conf")
+       
+       status, result = ctx.resolve("www.google.com")
+       if status == 0 and result.havedata:
+               print "Result.data:", result.data.address_list
+       elif status != 0:
+               print "Resolve error:", unbound.ub_strerror(status)
+
+In contrast with C API, the source code is more compact while the performance of C implementation is preserved. 
+The main advantage is that you need not take care about the deallocation and allocation of context and result structures; pyUnbound module do it automatically for you. 
+
+If only domain name is given, the :meth:`unbound.ub_ctx.resolve` looks for A records in IN class.
diff --git a/contrib/python/docs/source/examples/example1b.rst b/contrib/python/docs/source/examples/example1b.rst
new file mode 100644 (file)
index 0000000..ea1e6f5
--- /dev/null
@@ -0,0 +1,33 @@
+.. _example_reverse_lookup:
+
+==============================
+Reverse DNS lookup
+==============================
+
+Reverse DNS lookup involves determining the hostname associated with a given IP address.
+This example shows how reverse lookup can be done using unbound module.
+
+For the reverse DNS records, the special domain in-addr.arpa is reserved. 
+For example, a host name for the IP address 74.125.43.147 can be obtained by issuing a DNS query for the PTR record for address 147.43.125.74.in-addr.arpa.
+
+::
+
+       #!/usr/bin/python
+       import unbound
+       
+       ctx = unbound.ub_ctx()
+       ctx.resolvconf("/etc/resolv.conf")
+       
+       status, result = ctx.resolve(unbound.reverse("74.125.43.147") + ".in-addr.arpa.", unbound.RR_TYPE_PTR, unbound.RR_CLASS_IN)
+       if status == 0 and result.havedata:
+               print "Result.data:", result.data.domain_list
+       elif status != 0:
+               print "Resolve error:", unbound.ub_strerror(status)
+
+In order to simplify the python code, unbound module contains function which reverses the hostname components. 
+This function is defined as follows::
+
+       def reverse(domain):
+               return '.'.join([a for a in domain.split(".")][::-1])
+
+
diff --git a/contrib/python/docs/source/examples/example2.rst b/contrib/python/docs/source/examples/example2.rst
new file mode 100644 (file)
index 0000000..c009ec1
--- /dev/null
@@ -0,0 +1,41 @@
+.. _example_setup_ctx:
+
+==============================
+Lookup from threads
+==============================
+
+This example shows how to use unbound module from a threaded program. 
+In this example, three lookup threads are created which work in background. 
+Each thread resolves different DNS record. 
+
+::
+
+       #!/usr/bin/python
+       from unbound import ub_ctx, RR_TYPE_A, RR_CLASS_IN
+       from threading import Thread
+       
+       ctx = ub_ctx()
+       ctx.resolvconf("/etc/resolv.conf")
+       
+       class LookupThread(Thread):
+               def __init__(self,ctx, name):
+                       Thread.__init__(self)
+                       self.ctx = ctx
+                       self.name = name
+
+               def run(self):
+                       print "Thread lookup started:",self.name
+                       status, result = self.ctx.resolve(self.name, RR_TYPE_A, RR_CLASS_IN)
+                       if status == 0 and result.havedata:
+                               print "  Result:",self.name,":", result.data.address_list
+       
+       threads = []
+       for name in ["www.fit.vutbr.cz","www.vutbr.cz","www.google.com"]:
+               thread = LookupThread(ctx, name)
+               thread.start()
+               threads.append(thread)
+           
+       for thread in threads:
+               thread.join()
+
+
diff --git a/contrib/python/docs/source/examples/example3.rst b/contrib/python/docs/source/examples/example3.rst
new file mode 100644 (file)
index 0000000..9136033
--- /dev/null
@@ -0,0 +1,36 @@
+.. _example_asynch:
+
+==============================
+Asynchronous lookup
+==============================
+
+This example performs the name lookup in the background. 
+The main program keeps running while the name is resolved. 
+
+::
+
+       #!/usr/bin/python
+       import time
+       import unbound
+       
+       ctx = unbound.ub_ctx()
+       ctx.resolvconf("/etc/resolv.conf")
+       
+       def call_back(my_data,status,result):
+               print "Call_back:", my_data
+               if status == 0 and result.havedata:
+                       print "Result:", result.data.address_list
+                       my_data['done_flag'] = True
+       
+       
+       my_data = {'done_flag':False,'arbitrary':"object"}
+       status, async_id = ctx.resolve_async("www.seznam.cz", my_data, call_back, unbound.RR_TYPE_A, unbound.RR_CLASS_IN)
+               
+       while (status == 0) and (not my_data['done_flag']):
+               status = ctx.process()
+               time.sleep(0.1)
+       
+       if (status != 0):
+               print "Resolve error:", unbound.ub_strerror(status)
+
+The :meth:`unbound.ub_ctx.resolve_async` method is able to pass on any Python object. In this example, we used a dictionary object `my_data`.
diff --git a/contrib/python/docs/source/examples/example4.rst b/contrib/python/docs/source/examples/example4.rst
new file mode 100644 (file)
index 0000000..996ef4e
--- /dev/null
@@ -0,0 +1,34 @@
+.. _example_examine:
+
+==============================
+DNSSEC validator
+==============================
+
+This example program performs DNSSEC validation of a DNS lookup.
+
+::
+
+       #!/usr/bin/python
+       import os
+       from unbound import ub_ctx,RR_TYPE_A,RR_CLASS_IN
+       
+       ctx = ub_ctx()
+       ctx.resolvconf("/etc/resolv.conf")
+       if (os.path.isfile("keys")):
+               ctx.add_ta_file("keys") #read public keys for DNSSEC verification
+       
+       status, result = ctx.resolve("www.nic.cz", RR_TYPE_A, RR_CLASS_IN)
+       if status == 0 and result.havedata:
+       
+           print "Result:", result.data.address_list
+       
+           if result.secure:
+               print "Result is secure"
+           elif result.bogus:
+               print "Result is bogus"
+           else:
+               print "Result is insecure"
+
+More detailed informations can be seen in libUnbound DNSSEC tutorial `here`_.
+
+.. _here: http://www.unbound.net/documentation/libunbound-tutorial-6.html
diff --git a/contrib/python/docs/source/examples/example5.rst b/contrib/python/docs/source/examples/example5.rst
new file mode 100644 (file)
index 0000000..0a31d9a
--- /dev/null
@@ -0,0 +1,29 @@
+.. _example_resolver_only:
+
+==============================
+Resolver only
+==============================
+
+This example program shows how to perform DNS resolution only.
+Unbound contains two basic modules: resolver and validator.
+In case, the validator is not necessary, the validator module can be turned off using "module-config" option.
+This option contains a list of module names separated by the space char. This list determined which modules should be employed and in what order.
+
+::
+
+       #!/usr/bin/python
+       import os
+       from unbound import ub_ctx,RR_TYPE_A,RR_CLASS_IN
+       
+       ctx = ub_ctx()
+       ctx.set_option("module-config:","iterator")
+       ctx.resolvconf("/etc/resolv.conf")
+       
+       status, result = ctx.resolve("www.google.com", RR_TYPE_A, RR_CLASS_IN)
+       if status == 0 and result.havedata:
+       
+           print "Result:", result.data.address_list
+
+.. note::
+   The :meth:`unbound.ub_ctx.set_option` method must be used before the first resolution (i.e. before :meth:`unbound.ub_ctx.resolve` or :meth:`unbound.ub_ctx.resolve_async` call). 
+
diff --git a/contrib/python/docs/source/examples/example6-1.py b/contrib/python/docs/source/examples/example6-1.py
new file mode 100644 (file)
index 0000000..0f40544
--- /dev/null
@@ -0,0 +1,27 @@
+#!/usr/bin/python
+from unbound import ub_ctx,ub_strerror,RR_TYPE_A,RR_CLASS_IN
+
+ctx = ub_ctx()
+ctx.resolvconf("/etc/resolv.conf")
+       
+status, result = ctx.resolve("test.record.xxx", RR_TYPE_A, RR_CLASS_IN)
+if status == 0 and result.havedata:
+    print "Result:", result.data.address_list
+else:
+    print "No record found"
+
+#define new local zone
+status = ctx.zone_add("xxx.","static")
+if (status != 0): print "Error zone_add:",status, ub_strerror(status)
+
+#add RR to the zone
+status = ctx.data_add("test.record.xxx. IN A 1.2.3.4")
+if (status != 0): print "Error data_add:",status, ub_strerror(status)
+
+#lookup for an A record
+status, result = ctx.resolve("test.record.xxx", RR_TYPE_A, RR_CLASS_IN)
+if status == 0 and result.havedata:
+    print "Result:", result.data.as_address_list()
+else:
+    print "No record found"
+
diff --git a/contrib/python/docs/source/examples/example6.rst b/contrib/python/docs/source/examples/example6.rst
new file mode 100644 (file)
index 0000000..478e139
--- /dev/null
@@ -0,0 +1,11 @@
+.. _example_localzone:
+
+==============================
+Local zone manipulation
+==============================
+
+This example program shows how to define local zone containing custom DNS records.
+
+..     literalinclude:: example6-1.py
+       :language: python
+
diff --git a/contrib/python/docs/source/examples/example7-1.py b/contrib/python/docs/source/examples/example7-1.py
new file mode 100644 (file)
index 0000000..802bd1c
--- /dev/null
@@ -0,0 +1,17 @@
+#!/usr/bin/python
+# vim:fileencoding=utf-8
+#
+# IDN (Internationalized Domain Name) lookup support
+#
+import unbound
+
+ctx = unbound.ub_ctx()
+ctx.resolvconf("/etc/resolv.conf")
+
+status, result = ctx.resolve(u"www.háčkyčárky.cz", unbound.RR_TYPE_A, unbound.RR_CLASS_IN)
+if status == 0 and result.havedata:
+    print "Result:"
+    print "      raw data:", result.data
+    for k in result.data.address_list:
+        print "      address:%s" % k
+
diff --git a/contrib/python/docs/source/examples/example7-2.py b/contrib/python/docs/source/examples/example7-2.py
new file mode 100644 (file)
index 0000000..5a41f8d
--- /dev/null
@@ -0,0 +1,16 @@
+#!/usr/bin/python
+# vim:fileencoding=utf-8
+#
+# IDN (Internationalized Domain Name) lookup support (lookup for MX)
+#
+import unbound
+
+ctx = unbound.ub_ctx()
+ctx.resolvconf("/etc/resolv.conf")
+
+status, result = ctx.resolve(u"háčkyčárky.cz", unbound.RR_TYPE_MX, unbound.RR_CLASS_IN)
+if status == 0 and result.havedata:
+    print "Result:"
+    print "      raw data:", result.data
+    for k in result.data.mx_list_idn:
+        print "      priority:%d address:%s" % k
diff --git a/contrib/python/docs/source/examples/example7.rst b/contrib/python/docs/source/examples/example7.rst
new file mode 100644 (file)
index 0000000..d405021
--- /dev/null
@@ -0,0 +1,18 @@
+.. _example_idna:
+
+=================================================
+Internationalized domain name support
+=================================================
+
+Unlike the libUnbound, pyUnbound is able to handle IDN queries.
+
+..     literalinclude:: example7-1.py
+       :language: python
+
+If we use unicode string in :meth:`unbound.ub_ctx.resolve` method, the IDN DNAME conversion (if it is necessary) is performed on background.
+
+..     literalinclude:: example7-2.py
+       :language: python
+
+The :class:`unbound.ub_data` class contains attributes suffix which converts the dname to UTF string. These attributes have the '_idn' suffix.
+Apart from this aproach, two conversion functions exist (:func:`unbound.idn2dname` and :func:`unbound.dname2idn`).
diff --git a/contrib/python/docs/source/examples/example8-1.py b/contrib/python/docs/source/examples/example8-1.py
new file mode 100644 (file)
index 0000000..7906016
--- /dev/null
@@ -0,0 +1,31 @@
+#!/usr/bin/python
+# vim:fileencoding=utf-8
+#
+# Lookup for MX and NS records
+#
+import unbound
+
+ctx = unbound.ub_ctx()
+ctx.resolvconf("/etc/resolv.conf")
+
+status, result = ctx.resolve("nic.cz", unbound.RR_TYPE_MX, unbound.RR_CLASS_IN)
+if status == 0 and result.havedata:
+    print "Result:"
+    print "      raw data:", result.data
+    for k in result.data.mx_list:
+        print "      priority:%d address:%s" % k
+
+status, result = ctx.resolve("nic.cz", unbound.RR_TYPE_A, unbound.RR_CLASS_IN)
+if status == 0 and result.havedata:
+    print "Result:"
+    print "      raw data:", result.data
+    for k in result.data.address_list:
+        print "      address:%s" % k
+
+status, result = ctx.resolve("nic.cz", unbound.RR_TYPE_NS, unbound.RR_CLASS_IN)
+if status == 0 and result.havedata:
+    print "Result:"
+    print "      raw data:", result.data
+    for k in result.data.domain_list:
+        print "      host: %s" % k
+
diff --git a/contrib/python/docs/source/examples/example8.rst b/contrib/python/docs/source/examples/example8.rst
new file mode 100644 (file)
index 0000000..8cdfcdc
--- /dev/null
@@ -0,0 +1,28 @@
+.. _example_mxlookup:
+
+=================================================
+Lookup for MX and NS records
+=================================================
+
+The pyUnbound extension provides functions which are able to encode RAW RDATA produces by unbound resolver (see :class:`unbound.ub_data`).
+
+..     literalinclude:: example8-1.py
+       :language: python
+
+Previous example produces following output::
+
+       Result:
+               raw data: 00 0F 05 6D 61 69 6C 34 03 6E 69 63 02 63 7A 00;00 14 02 6D 78 05 63 7A 6E 69 63 03 6F 72 67 00;00 0A 04 6D 61 69 6C 03 6E 69 63 02 63 7A 00
+               priority:15 address: mail4.nic.cz.
+               priority:20 address: mx.cznic.org.
+               priority:10 address: mail.nic.cz.
+
+       Result:
+               raw data: D9 1F CD 32
+               address: 217.31.205.50
+
+       Result:
+               raw data: 01 61 02 6E 73 03 6E 69 63 02 63 7A 00;01 65 02 6E 73 03 6E 69 63 02 63 7A 00;01 63 02 6E 73 03 6E 69 63 02 63 7A 00
+               host: a.ns.nic.cz.
+               host: e.ns.nic.cz.
+               host: c.ns.nic.cz.
diff --git a/contrib/python/docs/source/examples/index.rst b/contrib/python/docs/source/examples/index.rst
new file mode 100644 (file)
index 0000000..c2c9cf4
--- /dev/null
@@ -0,0 +1,14 @@
+Examples
+==============================
+
+Here you can find several examples which utilizes the unbound library in Python environment. 
+Unbound is a caching validator and resolver and can be linked into an application, as a library where can answer DNS queries for the application. 
+This set of examples shows how to use the functions from Python environment.
+
+`Tutorials`
+
+.. toctree::
+       :maxdepth: 1
+       :glob:
+
+       example*
diff --git a/contrib/python/docs/source/index.rst b/contrib/python/docs/source/index.rst
new file mode 100644 (file)
index 0000000..b42e052
--- /dev/null
@@ -0,0 +1,27 @@
+PyUnbound documentation
+=======================================
+
+This project contains an Unbound wrapper providing the thinnest layer over the library possible. 
+Everything you can do from the libUnbound C API, you can do from Python, even more. 
+
+Contents
+----------
+.. toctree::
+       :maxdepth: 2
+
+       intro.rst
+       install.rst
+       examples/index.rst
+       modules/unbound
+
+Module Documentation
+-----------------------
+
+* Module :mod:`unbound`
+
+Indices and tables
+-------------------
+
+* :ref:`genindex`
+* :ref:`search`
+
diff --git a/contrib/python/docs/source/install.rst b/contrib/python/docs/source/install.rst
new file mode 100644 (file)
index 0000000..34108e0
--- /dev/null
@@ -0,0 +1,35 @@
+Installation
+===================================
+
+**Prerequisites**
+
+Python 2.4 or higher, SWIG 1.3 or higher, GNU make
+
+**Download**
+
+You can download the source codes `here`_.
+The latest release is 1.1.1, Jan 15, 2009.
+
+.. _here: unbound-1.1.1-py.tar.gz
+
+**Compiling**
+
+After downloading, you can compile the pyUnbound library by doing::
+
+       > tar -xzf unbound-1.1.1-py.tar.gz
+       > cd unbound-1.1.1
+       > ./configure --with-pyunbound
+       > make
+
+You need GNU make to compile sources; SWIG and Python devel libraries to compile extension module. 
+
+
+**Testing**
+
+If the compilation is successfull, you can test the python LDNS extension module by::
+
+       > cd contrib/python
+       > make testenv
+       > ./dns-lookup.py
+
+In contrib/examples you can find simple applications written in Python using the Unbound extension.
diff --git a/contrib/python/docs/source/intro.rst b/contrib/python/docs/source/intro.rst
new file mode 100644 (file)
index 0000000..f751f54
--- /dev/null
@@ -0,0 +1,39 @@
+Introduction
+===================================
+
+**Unbound**
+
+       `Unbound`_  is  an implementation of a DNS resolver, that performs caching and DNSSEC validation.
+       Together with unbound, the libunbound library is provided.
+       This library can be used to convert hostnames to ip addresses, and back, as well as obtain other information. 
+       Since the resolver allows to specify the class and type of a query (A record, NS, MX, ...), this library offers powerful resolving tool. 
+       The library also performs public-key validation of results with DNSSEC.
+       
+       .. _Unbound: http://www.unbound.net/documentation
+
+**pyUnbound**
+
+       The pyUnbound is an extension module for Python which provides an object-oriented interface to libunbound. 
+       It is the first Python module which offers thread-safe caching resolver.
+       
+       The interface was designed with the emphasis on the simplicity of use.
+       There are two main classes :class:`unbound.ub_ctx` (a validation and resolution context) and :class:`unbound.ub_result` which contains the validation and resolution results.
+       The objects are thread-safe, and a context can be used in non-threaded as well as threaded environment. 
+       Resolution can be performed blocking and non-blocking (i.e. asynchronous).  
+       The asynchronous method returns from the call immediately, so that processing can go on, while the results become available later.
+
+**Features**
+       * customizable caching validation resolver for synchronous and asynchronous lookups
+       * easy to use object interface
+       * easy to integrate extension module
+       * designed for thread environment (i.e. thread-safe)
+       * allows define and customize of local zone and its RR's during the operation (i.e. without restart)
+       * includes encoding functions to simplify the results retrieval
+       * Internationalized domain name (`IDN`_) support
+
+       .. _IDN: http://en.wikipedia.org/wiki/Internationalized_domain_name
+
+**Application area**
+       * DNS-based applications performing DNS lookups; the caching resolver can reduce overhead
+       * Applications where the validation of DNS records is required
+       * Great solution for customizable and dynamic DNS-based white/blacklists (spam rejection, connection rejection, ...) using the dynamic local zone manipulation
diff --git a/contrib/python/docs/source/modules/unbound.rst b/contrib/python/docs/source/modules/unbound.rst
new file mode 100644 (file)
index 0000000..21f4a12
--- /dev/null
@@ -0,0 +1,167 @@
+Unbound module documentation
+================================
+
+.. automodule:: unbound
+
+Class ub_ctx
+--------------
+.. autoclass:: ub_ctx
+       :members:
+       :undoc-members:
+       
+       .. automethod:: __init__ 
+
+Class ub_result
+----------------------
+.. autoclass:: ub_result
+       :members:
+
+       .. attribute:: qname
+
+               The original question, name text string.
+
+       .. attribute:: qtype
+
+               The class asked for.
+
+       .. attribute:: canonname
+
+               Canonical name for the result (the final cname). May be empty if no canonical name exists.
+
+       .. attribute:: answer_packet
+               
+               The DNS answer packet. Network formatted. Can contain DNSSEC types.
+
+       .. attribute:: havedata
+               
+               If there is any data, this property is true. If false, there was no data (nxdomain may be true, rcode can be set).
+
+       .. attribute:: secure
+               
+               True, if the result is validated securely.
+               False, if validation failed or domain queried has no security info.
+        
+               It is possible to get a result with no data (havedata is false),
+               and secure is true. This means that the non-existance of the data
+               was cryptographically proven (with signatures).
+
+       .. attribute:: bogus
+               
+               If the result was not secure (secure==0), and this result is due  to a security failure, bogus is true.
+               This means the data has been actively tampered with, signatures
+               failed, expected signatures were not present, timestamps on 
+               signatures were out of date and so on.
+        
+               If secure==0 and bogus==0, this can happen if the data is not secure 
+               because security is disabled for that domain name. 
+               This means the data is from a domain where data is not signed.
+
+       .. attribute:: nxdomain
+
+               If there was no data, and the domain did not exist, this is true. 
+               If it is false, and there was no data, then the domain name is purported to exist, but the requested data type is not available.
+
+       .. attribute:: rcode
+               
+               DNS RCODE for the result. May contain additional error code if there was no data due to an error. 
+               0 (RCODE_NOERROR) if okay. See predefined `RCODE_` constants.
+       
+               RCODE can be represented in display representation form (string) using :attr:`rcode_str` attribute.
+
+Class ub_data
+----------------------
+.. autoclass:: ub_data
+       :members:
+
+Functions
+----------------------
+.. autofunction:: reverse
+.. autofunction:: idn2dname
+.. autofunction:: dname2idn
+
+Predefined constants
+-----------------------
+
+**RCODE**
+       * RCODE_FORMERR = 1
+       * RCODE_NOERROR = 0
+       * RCODE_NOTAUTH = 9
+       * RCODE_NOTIMPL = 4
+       * RCODE_NOTZONE = 10
+       * RCODE_NXDOMAIN = 3
+       * RCODE_NXRRSET = 8
+       * RCODE_REFUSED = 5
+       * RCODE_SERVFAIL = 2
+       * RCODE_YXDOMAIN = 6
+       * RCODE_YXRRSET = 7
+
+**RR_CLASS**
+       * RR_CLASS_ANY = 255
+       * RR_CLASS_CH = 3
+       * RR_CLASS_HS = 4
+       * RR_CLASS_IN = 1
+       * RR_CLASS_NONE = 254
+
+**RR_TYPE**
+       * RR_TYPE_A = 1
+       * RR_TYPE_A6 = 38
+       * RR_TYPE_AAAA = 28
+       * RR_TYPE_AFSDB = 18
+       * RR_TYPE_ANY = 255
+       * RR_TYPE_APL = 42
+       * RR_TYPE_ATMA = 34
+       * RR_TYPE_AXFR = 252
+       * RR_TYPE_CERT = 37
+       * RR_TYPE_CNAME = 5
+       * RR_TYPE_DHCID = 49
+       * RR_TYPE_DLV = 32769
+       * RR_TYPE_DNAME = 39
+       * RR_TYPE_DNSKEY = 48
+       * RR_TYPE_DS = 43
+       * RR_TYPE_EID = 31
+       * RR_TYPE_GID = 102
+       * RR_TYPE_GPOS = 27
+       * RR_TYPE_HINFO = 13
+       * RR_TYPE_IPSECKEY = 45
+       * RR_TYPE_ISDN = 20
+       * RR_TYPE_IXFR = 251
+       * RR_TYPE_KEY = 25
+       * RR_TYPE_KX = 36
+       * RR_TYPE_LOC = 29
+       * RR_TYPE_MAILA = 254
+       * RR_TYPE_MAILB = 253
+       * RR_TYPE_MB = 7
+       * RR_TYPE_MD = 3
+       * RR_TYPE_MF = 4
+       * RR_TYPE_MG = 8
+       * RR_TYPE_MINFO = 14
+       * RR_TYPE_MR = 9
+       * RR_TYPE_MX = 15
+       * RR_TYPE_NAPTR = 35
+       * RR_TYPE_NIMLOC = 32
+       * RR_TYPE_NS = 2
+       * RR_TYPE_NSAP = 22
+       * RR_TYPE_NSAP_PTR = 23
+       * RR_TYPE_NSEC = 47
+       * RR_TYPE_NSEC3 = 50
+       * RR_TYPE_NSEC3PARAMS = 51
+       * RR_TYPE_NULL = 10
+       * RR_TYPE_NXT = 30
+       * RR_TYPE_OPT = 41
+       * RR_TYPE_PTR = 12
+       * RR_TYPE_PX = 26
+       * RR_TYPE_RP = 17
+       * RR_TYPE_RRSIG = 46
+       * RR_TYPE_RT = 21
+       * RR_TYPE_SIG = 24
+       * RR_TYPE_SINK = 40
+       * RR_TYPE_SOA = 6
+       * RR_TYPE_SRV = 33
+       * RR_TYPE_SSHFP = 44
+       * RR_TYPE_TSIG = 250
+       * RR_TYPE_TXT = 16
+       * RR_TYPE_UID = 101
+       * RR_TYPE_UINFO = 100
+       * RR_TYPE_UNSPEC = 103
+       * RR_TYPE_WKS = 11
+       * RR_TYPE_X25 = 19
diff --git a/contrib/python/examples/async-lookup.py b/contrib/python/examples/async-lookup.py
new file mode 100644 (file)
index 0000000..52a2d3c
--- /dev/null
@@ -0,0 +1,56 @@
+#!/usr/bin/python
+'''
+ async-lookup.py : This example shows how to use asynchronous lookups
+
+ Authors: Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+          Marek Vavrusa  (xvavru00 AT stud.fit.vutbr.cz)
+
+ Copyright (c) 2008. All rights reserved.
+
+ This software is open source.
+ 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.
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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.
+'''
+import unbound
+import time
+
+ctx = unbound.ub_ctx()
+ctx.resolvconf("/etc/resolv.conf")
+
+def call_back(my_data,status,result):
+    print "Call_back:", my_data
+    if status == 0 and result.havedata:
+        print "Result:", result.data.address_list
+        my_data['done_flag'] = True
+
+
+my_data = {'done_flag':False,'arbitrary':"object"}
+status, async_id = ctx.resolve_async("www.nic.cz", my_data, call_back, unbound.RR_TYPE_A, unbound.RR_CLASS_IN)
+        
+while (status == 0) and (not my_data['done_flag']):
+    status = ctx.process()
+    time.sleep(0.1)
+
+if (status != 0):
+    print "Resolve error:", unbound.ub_strerror(status)
diff --git a/contrib/python/examples/dns-lookup.py b/contrib/python/examples/dns-lookup.py
new file mode 100644 (file)
index 0000000..2821ed3
--- /dev/null
@@ -0,0 +1,44 @@
+#!/usr/bin/python
+'''
+ dns-lookup.py : This example shows how to resolve IP address
+
+ Authors: Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+          Marek Vavrusa  (xvavru00 AT stud.fit.vutbr.cz)
+
+ Copyright (c) 2008. All rights reserved.
+
+ This software is open source.
+ 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.
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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.
+'''
+import unbound
+
+ctx = unbound.ub_ctx()
+ctx.resolvconf("/etc/resolv.conf")
+
+status, result = ctx.resolve("www.nic.cz", unbound.RR_TYPE_A, unbound.RR_CLASS_IN)
+if status == 0 and result.havedata:
+    print "Result:", result.data.address_list
+elif status != 0:
+    print "Error:", unbound.ub_strerror(status)
diff --git a/contrib/python/examples/dnssec-valid.py b/contrib/python/examples/dnssec-valid.py
new file mode 100644 (file)
index 0000000..3e05ddd
--- /dev/null
@@ -0,0 +1,59 @@
+#!/usr/bin/python
+'''
+ dnssec-valid.py:  DNSSEC validation
+
+ Authors: Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+          Marek Vavrusa  (xvavru00 AT stud.fit.vutbr.cz)
+
+ Copyright (c) 2008. All rights reserved.
+
+ This software is open source.
+ 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.
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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.
+'''
+import os
+from unbound import ub_ctx,RR_TYPE_A,RR_CLASS_IN
+
+ctx = ub_ctx()
+ctx.resolvconf("/etc/resolv.conf")
+
+fw = open("dnssec-valid.txt","wb")
+ctx.debugout(fw)
+ctx.debuglevel(2)
+
+if os.path.isfile("keys"):
+    ctx.add_ta_file("keys") #read public keys for DNSSEC verificatio
+
+status, result = ctx.resolve("www.nic.cz", RR_TYPE_A, RR_CLASS_IN)
+if status == 0 and result.havedata:
+
+    print "Result:", result.data.address_list
+
+    if result.secure:
+        print "Result is secure"
+    elif result.bogus:
+        print "Result is bogus"
+    else:
+        print "Result is insecure"
+
diff --git a/contrib/python/examples/example8-1.py b/contrib/python/examples/example8-1.py
new file mode 100644 (file)
index 0000000..6816da0
--- /dev/null
@@ -0,0 +1,61 @@
+#!/usr/bin/python
+# vim:fileencoding=utf-8
+'''
+ example8-1.py: Example shows how to lookup for MX and NS records
+
+ Authors: Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+          Marek Vavrusa  (xvavru00 AT stud.fit.vutbr.cz)
+
+ Copyright (c) 2008. All rights reserved.
+
+ This software is open source.
+ 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.
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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.
+'''
+import unbound
+
+ctx = unbound.ub_ctx()
+ctx.resolvconf("/etc/resolv.conf")
+
+status, result = ctx.resolve("nic.cz", unbound.RR_TYPE_MX, unbound.RR_CLASS_IN)
+if status == 0 and result.havedata:
+    print "Result:"
+    print "      raw data:", result.data
+    for k in result.data.mx_list:
+        print "      priority:%d address:%s" % k
+
+status, result = ctx.resolve("nic.cz", unbound.RR_TYPE_A, unbound.RR_CLASS_IN)
+if status == 0 and result.havedata:
+    print "Result:"
+    print "      raw data:", result.data
+    for k in result.data.address_list:
+        print "      address:%s" % k
+
+status, result = ctx.resolve("nic.cz", unbound.RR_TYPE_NS, unbound.RR_CLASS_IN)
+if status == 0 and result.havedata:
+    print "Result:"
+    print "      raw data:", result.data
+    for k in result.data.domain_list:
+        print "      host: %s" % k
+
diff --git a/contrib/python/examples/idn-lookup.py b/contrib/python/examples/idn-lookup.py
new file mode 100644 (file)
index 0000000..7cfdc9e
--- /dev/null
@@ -0,0 +1,62 @@
+#!/usr/bin/python
+# vim:fileencoding=utf-8
+'''
+ idn-lookup.py: IDN (Internationalized Domain Name) lookup support 
+
+ Authors: Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+          Marek Vavrusa  (xvavru00 AT stud.fit.vutbr.cz)
+
+ Copyright (c) 2008. All rights reserved.
+
+ This software is open source.
+ 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.
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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.
+'''
+import unbound
+import locale
+
+ctx = unbound.ub_ctx()
+ctx.set_option("module-config:","iterator") #We don't need validation
+ctx.resolvconf("/etc/resolv.conf")
+
+#The unicode IDN string is automatically converted (if necessary)
+status, result = ctx.resolve(u"www.háčkyčárky.cz", unbound.RR_TYPE_A, unbound.RR_CLASS_IN)
+if status == 0 and result.havedata:
+    print "Result:"
+    print "      raw data:", result.data
+    for k in result.data.address_list:
+        print "      address:%s" % k
+
+status, result = ctx.resolve(u"háčkyčárky.cz", unbound.RR_TYPE_MX, unbound.RR_CLASS_IN)
+if status == 0 and result.havedata:
+    print "Result:"
+    print "      raw data:", result.data
+    for k in result.data.mx_list_idn:
+        print "      priority:%d address:%s" % k
+
+status, result = ctx.resolve(unbound.reverse('217.31.204.66')+'.in-addr.arpa', unbound.RR_TYPE_PTR, unbound.RR_CLASS_IN)
+if status == 0 and result.havedata:
+    print "Result.data:", result.data
+    for k in result.data.domain_list_idn:
+        print "      dname:%s" % k
diff --git a/contrib/python/examples/mx-lookup.py b/contrib/python/examples/mx-lookup.py
new file mode 100644 (file)
index 0000000..cdcd1b1
--- /dev/null
@@ -0,0 +1,53 @@
+#!/usr/bin/python
+# vim:fileencoding=utf-8
+'''
+ mx-lookup.py: Lookup for MX records
+
+ Authors: Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+          Marek Vavrusa  (xvavru00 AT stud.fit.vutbr.cz)
+
+ Copyright (c) 2008. All rights reserved.
+
+ This software is open source.
+ 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.
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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.
+'''
+import unbound
+
+ctx = unbound.ub_ctx()
+ctx.resolvconf("/etc/resolv.conf")
+
+status, result = ctx.resolve("nic.cz", unbound.RR_TYPE_MX, unbound.RR_CLASS_IN)
+if status == 0 and result.havedata:
+    print "Result:"
+    print "      raw data:", result.data
+    for k in result.data.mx_list:
+        print "      priority:%d address:%s" % k
+
+status, result = ctx.resolve("nic.cz", unbound.RR_TYPE_A, unbound.RR_CLASS_IN)
+if status == 0 and result.havedata:
+    print "Result:"
+    print "      raw data:", result.data
+    for k in result.data.address_list:
+        print "      address:%s" % k
diff --git a/contrib/python/examples/ns-lookup.py b/contrib/python/examples/ns-lookup.py
new file mode 100644 (file)
index 0000000..f9eafb2
--- /dev/null
@@ -0,0 +1,47 @@
+#!/usr/bin/python
+# vim:fileencoding=utf-8
+'''
+ ns-lookup.py: Example shows how to lookup for NS records 
+
+ Authors: Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+          Marek Vavrusa  (xvavru00 AT stud.fit.vutbr.cz)
+
+ Copyright (c) 2008. All rights reserved.
+
+ This software is open source.
+ 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.
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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.
+'''
+import unbound
+
+ctx = unbound.ub_ctx()
+ctx.resolvconf("/etc/resolv.conf")
+
+status, result = ctx.resolve("vutbr.cz", unbound.RR_TYPE_NS, unbound.RR_CLASS_IN)
+if status == 0 and result.havedata:
+    print "Result:"
+    print "      raw data:", result.data
+    for k in result.data.domain_list:
+        print "      host: %s" % k
+
diff --git a/contrib/python/examples/reverse-lookup.py b/contrib/python/examples/reverse-lookup.py
new file mode 100644 (file)
index 0000000..4d3e0bb
--- /dev/null
@@ -0,0 +1,43 @@
+#!/usr/bin/python
+'''
+ reverse-lookup.py: Example shows how to resolve reverse record 
+
+ Authors: Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+          Marek Vavrusa  (xvavru00 AT stud.fit.vutbr.cz)
+
+ Copyright (c) 2008. All rights reserved.
+
+ This software is open source.
+ 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.
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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.
+'''
+import unbound
+
+ctx = unbound.ub_ctx()
+ctx.resolvconf("/etc/resolv.conf")
+
+status, result = ctx.resolve(unbound.reverse("74.125.43.147") + ".in-addr.arpa.", unbound.RR_TYPE_PTR, unbound.RR_CLASS_IN)
+if status == 0 and result.havedata:
+    print "Result.data:", result.data, result.data.domain_list
+
diff --git a/contrib/python/libunbound.i b/contrib/python/libunbound.i
new file mode 100644 (file)
index 0000000..a9a71ac
--- /dev/null
@@ -0,0 +1,930 @@
+/*
+ * libounbound.i: pyUnbound module (libunbound wrapper for Python)
+ * 
+ * Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+ *                     Marek Vavrusa  (xvavru00 AT stud.fit.vutbr.cz)
+ *
+ * This software is open source.
+ * 
+ * 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 the organization 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 COPYRIGHT HOLDERS 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.
+ */
+%module unbound
+%{
+   #include <sys/types.h>
+   #include <sys/socket.h>
+   #include <netinet/in.h>
+   #include <arpa/inet.h>
+   #include "libunbound/unbound.h"
+%}
+
+%pythoncode %{
+   import encodings.idna
+%}
+
+//%include "doc.i"
+%include "file.i"
+
+%feature("docstring") strerror "Convert error value to a human readable string."
+
+// ================================================================================
+// ub_resolve - perform resolution and validation
+// ================================================================================
+%typemap(in,numinputs=0,noblock=1) (struct ub_result** result)  
+{ 
+   struct ub_result* newubr;
+   $1 = &newubr;
+} 
+  
+/* result generation */
+%typemap(argout,noblock=1) (struct ub_result** result)
+{
+  PyObject* tuple;
+  tuple = PyTuple_New(2);
+  PyTuple_SetItem(tuple, 0, $result);
+  if (result == 0) {
+     PyTuple_SetItem(tuple, 1, SWIG_NewPointerObj(SWIG_as_voidptr(newubr), SWIGTYPE_p_ub_result, SWIG_POINTER_OWN |  0 ));
+  } else {
+     PyTuple_SetItem(tuple, 1, Py_None);
+  }
+  $result = tuple;
+}
+
+                       
+// ================================================================================
+// ub_ctx - validation context
+// ================================================================================
+%nodefaultctor ub_ctx; //no default constructor & destructor
+%nodefaultdtor ub_ctx;
+
+%newobject ub_ctx_create;
+%delobject ub_ctx_delete;
+%rename(_ub_ctx_delete) ub_ctx_delete;
+
+%newobject ub_resolve;
+
+%inline %{
+  void ub_ctx_free_dbg (struct ub_ctx* c) {
+    printf("******** UB_CTX free 0x%lX ************\n", (long unsigned int)c);
+    ub_ctx_delete(c);
+  }
+
+  //RR types
+  enum enum_rr_type
+  {
+    /**  a host address */
+    RR_TYPE_A = 1, 
+    /**  an authoritative name server */
+    RR_TYPE_NS = 2, 
+    /**  a mail destination (Obsolete - use MX) */
+    RR_TYPE_MD = 3, 
+    /**  a mail forwarder (Obsolete - use MX) */
+    RR_TYPE_MF = 4, 
+    /**  the canonical name for an alias */
+    RR_TYPE_CNAME = 5, 
+    /**  marks the start of a zone of authority */
+    RR_TYPE_SOA = 6, 
+    /**  a mailbox domain name (EXPERIMENTAL) */
+    RR_TYPE_MB = 7, 
+    /**  a mail group member (EXPERIMENTAL) */
+    RR_TYPE_MG = 8, 
+    /**  a mail rename domain name (EXPERIMENTAL) */
+    RR_TYPE_MR = 9, 
+    /**  a null RR (EXPERIMENTAL) */
+    RR_TYPE_NULL = 10,
+    /**  a well known service description */
+    RR_TYPE_WKS = 11,
+    /**  a domain name pointer */
+    RR_TYPE_PTR = 12,
+    /**  host information */
+    RR_TYPE_HINFO = 13,
+    /**  mailbox or mail list information */
+    RR_TYPE_MINFO = 14,
+    /**  mail exchange */
+    RR_TYPE_MX = 15,
+    /**  text strings */
+    RR_TYPE_TXT = 16,
+    /**  RFC1183 */
+    RR_TYPE_RP = 17,
+    /**  RFC1183 */
+    RR_TYPE_AFSDB = 18,
+    /**  RFC1183 */
+    RR_TYPE_X25 = 19,
+    /**  RFC1183 */
+    RR_TYPE_ISDN = 20,
+    /**  RFC1183 */
+    RR_TYPE_RT = 21,
+    /**  RFC1706 */
+    RR_TYPE_NSAP = 22,
+    /**  RFC1348 */
+    RR_TYPE_NSAP_PTR = 23,
+    /**  2535typecode */
+    RR_TYPE_SIG = 24,
+    /**  2535typecode */
+    RR_TYPE_KEY = 25,
+    /**  RFC2163 */
+    RR_TYPE_PX = 26,
+    /**  RFC1712 */
+    RR_TYPE_GPOS = 27,
+    /**  ipv6 address */
+    RR_TYPE_AAAA = 28,
+    /**  LOC record  RFC1876 */
+    RR_TYPE_LOC = 29,
+    /**  2535typecode */
+    RR_TYPE_NXT = 30,
+    /**  draft-ietf-nimrod-dns-01.txt */
+    RR_TYPE_EID = 31,
+    /**  draft-ietf-nimrod-dns-01.txt */
+    RR_TYPE_NIMLOC = 32,
+    /**  SRV record RFC2782 */
+    RR_TYPE_SRV = 33,
+    /**  http://www.jhsoft.com/rfc/af-saa-0069.000.rtf */
+    RR_TYPE_ATMA = 34,
+    /**  RFC2915 */
+    RR_TYPE_NAPTR = 35,
+    /**  RFC2230 */
+    RR_TYPE_KX = 36,
+    /**  RFC2538 */
+    RR_TYPE_CERT = 37,
+    /**  RFC2874 */
+    RR_TYPE_A6 = 38,
+    /**  RFC2672 */
+    RR_TYPE_DNAME = 39,
+    /**  dnsind-kitchen-sink-02.txt */
+    RR_TYPE_SINK = 40,
+    /**  Pseudo OPT record... */
+    RR_TYPE_OPT = 41,
+    /**  RFC3123 */
+    RR_TYPE_APL = 42,
+    /**  draft-ietf-dnsext-delegation */
+    RR_TYPE_DS = 43,
+    /**  SSH Key Fingerprint */
+    RR_TYPE_SSHFP = 44,
+    /**  draft-richardson-ipseckey-rr-11.txt */
+    RR_TYPE_IPSECKEY = 45,
+    /**  draft-ietf-dnsext-dnssec-25 */
+    RR_TYPE_RRSIG = 46,
+    RR_TYPE_NSEC = 47,      
+    RR_TYPE_DNSKEY = 48,
+    RR_TYPE_DHCID = 49,
+
+    RR_TYPE_NSEC3 = 50,
+    RR_TYPE_NSEC3PARAMS = 51,
+
+    RR_TYPE_UINFO = 100,
+    RR_TYPE_UID = 101,
+    RR_TYPE_GID = 102,
+    RR_TYPE_UNSPEC = 103,
+
+    RR_TYPE_TSIG = 250,
+    RR_TYPE_IXFR = 251,
+    RR_TYPE_AXFR = 252,
+    /**  A request for mailbox-related records (MB, MG or MR) */
+    RR_TYPE_MAILB = 253,
+    /**  A request for mail agent RRs (Obsolete - see MX) */
+    RR_TYPE_MAILA = 254,
+    /**  any type (wildcard) */
+    RR_TYPE_ANY = 255,
+
+    /* RFC 4431, 5074, DNSSEC Lookaside Validation */
+    RR_TYPE_DLV = 32769,
+  };
+
+  // RR classes
+  enum enum_rr_class
+  { 
+    /** the Internet */
+    RR_CLASS_IN = 1,
+    /** Chaos class */
+    RR_CLASS_CH = 3,
+    /** Hesiod (Dyer 87) */
+    RR_CLASS_HS = 4,
+    /** None class, dynamic update */
+    RR_CLASS_NONE = 254,
+    /** Any class */
+    RR_CLASS_ANY = 255,
+  };
+%} 
+
+%feature("docstring") ub_ctx "Unbound resolving and validation context. 
+
+The validation context is created to hold the resolver status, validation keys and a small cache (containing messages, rrsets, roundtrip times, trusted keys, lameness information).
+
+**Usage**
+
+>>> import unbound
+>>> ctx = unbound.ub_ctx()
+>>> ctx.resolvconf(\"/etc/resolv.conf\")
+>>> status, result = ctx.resolve(\"www.google.com\", unbound.RR_TYPE_A, unbound.RR_CLASS_IN)
+>>> if status==0 and result.havedata:
+>>>    print \"Result:\",result.data.address_list
+Result: ['74.125.43.147', '74.125.43.99', '74.125.43.103', '74.125.43.104']
+"
+
+%extend ub_ctx
+{
+ %pythoncode %{
+        def __init__(self):
+            """Creates a resolving and validation context.
+               
+               An exception is invoked if the process of creation an ub_ctx instance fails.
+            """
+            self.this = _unbound.ub_ctx_create()
+            if not self.this:
+                raise Exception("Fatal error: unbound context initialization failed")
+
+        #__swig_destroy__ = _unbound.ub_ctx_free_dbg
+        __swig_destroy__ = _unbound._ub_ctx_delete
+
+        #UB_CTX_METHODS_#   
+        def add_ta(self,ta):
+            """Add a trust anchor to the given context.
+               
+               The trust anchor is a string, on one line, that holds a valid DNSKEY or DS RR.
+               
+               :param ta:
+                   string, with zone-format RR on one line. [domainname] [TTL optional] [type] [class optional] [rdata contents]
+               :returns: (int) 0 if OK, else error.
+            """
+            return _unbound.ub_ctx_add_ta(self,ta)
+            #parameters: struct ub_ctx *,char *,
+            #retvals: int
+
+        def add_ta_file(self,fname):
+            """Add trust anchors to the given context.
+               
+               Pass name of a file with DS and DNSKEY records (like from dig or drill).
+               
+               :param fname:
+                   filename of file with keyfile with trust anchors.
+               :returns: (int) 0 if OK, else error.
+            """
+            return _unbound.ub_ctx_add_ta_file(self,fname)
+            #parameters: struct ub_ctx *,char *,
+            #retvals: int
+
+        def config(self,fname):
+            """setup configuration for the given context.
+               
+               :param fname:
+                   unbound config file (not all settings applicable). This is a power-users interface that lets you specify all sorts of options. For some specific options, such as adding trust anchors, special routines exist.
+               :returns: (int) 0 if OK, else error.
+            """
+            return _unbound.ub_ctx_config(self,fname)
+            #parameters: struct ub_ctx *,char *,
+            #retvals: int
+
+        def debuglevel(self,d):
+            """Set debug verbosity for the context Output is directed to stderr.
+               
+               :param d:
+                   debug level, 0 is off, 1 is very minimal, 2 is detailed, and 3 is lots.
+               :returns: (int) 0 if OK, else error.
+            """
+            return _unbound.ub_ctx_debuglevel(self,d)
+            #parameters: struct ub_ctx *,int,
+            #retvals: int
+
+        def debugout(self,out):
+            """Set debug output (and error output) to the specified stream.
+               
+               Pass None to disable. Default is stderr.
+               
+               :param out:
+                   File stream to log to.
+               :returns: (int) 0 if OK, else error.
+
+               **Usage:**
+
+                  In order to log into file, use
+
+                  ::
+
+                    ctx = unbound.ub_ctx()
+                    fw = fopen("debug.log")
+                    ctx.debuglevel(3)
+                    ctx.debugout(fw)
+
+                  Another option is to print the debug informations to stderr output
+
+                  ::
+
+                    ctx = unbound.ub_ctx()
+                    ctx.debuglevel(10)
+                    ctx.debugout(sys.stderr) 
+            """
+            return _unbound.ub_ctx_debugout(self,out)
+            #parameters: struct ub_ctx *,void *,
+            #retvals: int
+
+        def hosts(self,fname="/etc/hosts"):
+            """Read list of hosts from the filename given.
+               
+               Usually "/etc/hosts". These addresses are not flagged as DNSSEC secure when queried for.
+               
+               :param fname:
+                   file name string. If None "/etc/hosts" is used.
+               :returns: (int) 0 if OK, else error.
+            """
+            return _unbound.ub_ctx_hosts(self,fname)
+            #parameters: struct ub_ctx *,char *,
+            #retvals: int
+
+        def print_local_zones(self):
+            """Print the local zones and their content (RR data) to the debug output.
+               
+               :returns: (int) 0 if OK, else error.
+            """
+            return _unbound.ub_ctx_print_local_zones(self)
+            #parameters: struct ub_ctx *,
+            #retvals: int
+
+        def resolvconf(self,fname="/etc/resolv.conf"):
+            """Read list of nameservers to use from the filename given.
+               
+               Usually "/etc/resolv.conf". Uses those nameservers as caching proxies. If they do not support DNSSEC, validation may fail.
+               
+               Only nameservers are picked up, the searchdomain, ndots and other settings from resolv.conf(5) are ignored.
+               
+               :param fname:
+                   file name string. If None "/etc/resolv.conf" is used.
+               :returns: (int) 0 if OK, else error.
+            """
+            return _unbound.ub_ctx_resolvconf(self,fname)
+            #parameters: struct ub_ctx *,char *,
+            #retvals: int
+
+        def set_async(self,dothread):
+            """Set a context behaviour for asynchronous action.
+               
+               :param dothread:
+                   if True, enables threading and a call to :meth:`resolve_async` creates a thread to handle work in the background. 
+                   If False, a process is forked to handle work in the background. 
+                   Changes to this setting after :meth:`async` calls have been made have no effect (delete and re-create the context to change).
+               :returns: (int) 0 if OK, else error.
+            """
+            return _unbound.ub_ctx_async(self,dothread)
+            #parameters: struct ub_ctx *,int,
+            #retvals: int
+
+        def set_fwd(self,addr):
+            """Set machine to forward DNS queries to, the caching resolver to use.
+               
+               IP4 or IP6 address. Forwards all DNS requests to that machine, which is expected to run a recursive resolver. If the  is not DNSSEC-capable, validation may fail. Can be called several times, in that case the addresses are used as backup servers.
+               
+               To read the list of nameservers from /etc/resolv.conf (from DHCP or so), use the call :meth:`resolvconf`.
+               
+               :param addr:
+                   address, IP4 or IP6 in string format. If the addr is None, forwarding is disabled.
+               :returns: (int) 0 if OK, else error.
+            """
+            return _unbound.ub_ctx_set_fwd(self,addr)
+            #parameters: struct ub_ctx *,char *,
+            #retvals: int
+
+        def set_option(self,opt,val):
+            """Set an option for the context.
+
+               Changes to the options after :meth:`resolve`, :meth:`resolve_async`, :meth:`zone_add`, :meth:`zone_remove`, :meth:`data_add` or :meth:`data_remove` have no effect (you have to delete and re-create the context).
+               
+               :param opt:
+                   option name from the unbound.conf config file format. (not all settings applicable). The name includes the trailing ':' for example set_option("logfile:", "mylog.txt"); This is a power-users interface that lets you specify all sorts of options. For some specific options, such as adding trust anchors, special routines exist.
+               :param val:
+                   value of the option.
+               :returns: (int) 0 if OK, else error.
+            """
+            return _unbound.ub_ctx_set_option(self,opt,val)
+            #parameters: struct ub_ctx *,char *,char *,
+            #retvals: int
+
+        def trustedkeys(self,fname):
+            """Add trust anchors to the given context.
+               
+               Pass the name of a bind-style config file with trusted-keys{}.
+               
+               :param fname:
+                   filename of file with bind-style config entries with trust anchors.
+               :returns: (int) 0 if OK, else error.
+            """
+            return _unbound.ub_ctx_trustedkeys(self,fname)
+            #parameters: struct ub_ctx *,char *,
+            #retvals: int
+        #_UB_CTX_METHODS#   
+        
+        def zone_print(self):
+            """Print local zones using debougout"""            
+            _unbound.ub_ctx_print_local_zones(self)
+
+        def zone_add(self,zonename,zonetype):
+            """Add new local zone
+
+               :param zonename: zone domain name (e.g. myzone.)
+               :param zonetype: type of the zone ("static",...) 
+               :returns: (int) 0 if OK, else error. 
+            """ 
+            return _unbound.ub_ctx_zone_add(self,zonename, zonetype)
+            #parameters: struct ub_ctx *,char*, char*
+            #retvals: int
+
+        def zone_remove(self,zonename):
+            """Remove local zone
+            
+               If exists, removes local zone with all the RRs.
+
+               :param zonename: zone domain name
+               :returns: (int) 0 if OK, else error. 
+            """ 
+            return _unbound.ub_ctx_zone_remove(self,zonename)
+            #parameters: struct ub_ctx *,char*
+            #retvals: int
+
+        def data_add(self,rrdata):
+            """Add new local RR data
+
+               :param rrdata: string, in zone-format on one line. [domainname] [TTL optional] [type] [class optional] [rdata contents]
+               :returns: (int) 0 if OK, else error. 
+
+               **Usage**
+                  The local data ...
+
+                  ::
+
+                    >>> ctx = unbound.ub_ctx()
+                    >>> ctx.zone_add("mydomain.net.","static")
+                    0
+                    >>> status = ctx.data_add("test.mydomain.net. IN A 192.168.1.1")
+                    0
+                    >>> status, result = ctx.resolve("test.mydomain.net")
+                    >>> if status==0 and result.havedata:
+                    >>>    print \"Result:\",result.data.address_list
+                    Result: ['192.168.1.1']
+
+            """ 
+            return _unbound.ub_ctx_data_add(self,rrdata)
+            #parameters: struct ub_ctx *,char*
+            #retvals: int
+
+        def data_remove(self,rrdata):
+            """Remove local RR data
+
+               If exists, remove resource record from local zone
+
+               :param rrdata: string, in zone-format on one line. [domainname] [TTL optional] [type] [class optional] [rdata contents]
+               :returns: (int) 0 if OK, else error. 
+            """ 
+            return _unbound.ub_ctx_data_remove(self,rrdata)
+            #parameters: struct ub_ctx *,char*
+            #retvals: int
+
+        #UB_METHODS_#
+        def cancel(self,async_id):
+            """Cancel an async query in progress.
+               
+               Its callback will not be called.
+               
+               :param async_id:
+                   which query to cancel.
+               :returns: (int) 0 if OK, else error.
+            """
+            return _unbound.ub_cancel(self,async_id)
+            #parameters: struct ub_ctx *,int,
+            #retvals: int
+
+        def get_fd(self):
+            """Get file descriptor.
+               
+               Wait for it to become readable, at this point answers are returned from the asynchronous validating resolver. Then call the ub_process to continue processing. This routine works immediately after context creation, the fd does not change.
+               
+               :returns: (int) -1 on error, or file descriptor to use select(2) with.
+            """
+            return _unbound.ub_fd(self)
+            #parameters: struct ub_ctx *,
+            #retvals: int
+
+        def poll(self):
+            """Poll a context to see if it has any new results Do not poll in a loop, instead extract the fd below to poll for readiness, and then check, or wait using the wait routine.
+               
+               :returns: (int) 0 if nothing to read, or nonzero if a result is available. If nonzero, call ctx_process() to do callbacks.
+            """
+            return _unbound.ub_poll(self)
+            #parameters: struct ub_ctx *,
+            #retvals: int
+
+        def process(self):
+            """Call this routine to continue processing results from the validating resolver (when the fd becomes readable).
+               
+               Will perform necessary callbacks.
+               
+               :returns: (int) 0 if OK, else error.
+            """
+            return _unbound.ub_process(self)
+            #parameters: struct ub_ctx *,
+            #retvals: int
+
+        def resolve(self,name,rrtype=RR_TYPE_A,rrclass=RR_CLASS_IN):
+            """Perform resolution and validation of the target name. 
+               
+               :param name:
+                   domain name in text format (a string or unicode string). IDN domain name have to be passed as a unicode string.
+               :param rrtype:
+                   type of RR in host order (optional argument). Default value is RR_TYPE_A (A class).
+               :param rrclass:
+                   class of RR in host order (optional argument). Default value is RR_CLASS_IN (for internet).
+               :returns: * (int) 0 if OK, else error.
+                         * (:class:`ub_result`) the result data is returned in a newly allocated result structure. May be None on return, return value is set to an error in that case (out of memory).
+            """
+            if isinstance(name, unicode): #probably IDN
+                return _unbound.ub_resolve(self,idn2dname(name),rrtype,rrclass)
+            else:
+                return _unbound.ub_resolve(self,name,rrtype,rrclass)
+            #parameters: struct ub_ctx *,char *,int,int,
+            #retvals: int,struct ub_result **
+
+        def resolve_async(self,name,mydata,callback,rrtype=RR_TYPE_A,rrclass=RR_CLASS_IN):
+            """Perform resolution and validation of the target name.
+               
+               Asynchronous, after a while, the callback will be called with your data and the result. 
+               If an error happens during processing, your callback will be called with error set to a nonzero value (and result==None).
+               
+               :param name:
+                   domain name in text format (a string or unicode string). IDN domain name have to be passed as a unicode string.
+               :param mydata:
+                   this data is your own data (you can pass arbitrary python object or None) which are passed on to the callback function.
+               :param callback:
+                   call-back function which is called on completion of the resolution. 
+               :param rrtype:
+                   type of RR in host order (optional argument). Default value is RR_TYPE_A (A class).
+               :param rrclass:
+                   class of RR in host order (optional argument). Default value is RR_CLASS_IN (for internet).
+               :returns: * (int) 0 if OK, else error.
+                         * (int) async_id, an identifier number is returned for the query as it is in progress. It can be used to cancel the query.
+
+               **Call-back function:**
+                    The call-back function looks as the follows::
+                    
+                        def call_back(mydata, status, result):
+                            pass
+
+                    **Parameters:** 
+                        * `mydata` - mydata object
+                        * `status` - 0 when a result has been found
+                        * `result` - the result structure. The result may be None, in that case err is set.
+
+            """
+            if isinstance(name, unicode): #probably IDN
+                return _unbound._ub_resolve_async(self,idn2dname(name),rrtype,rrclass,mydata,callback)
+            else:
+                return _unbound._ub_resolve_async(self,name,rrtype,rrclass,mydata,callback)
+            #parameters: struct ub_ctx *,char *,int,int,void *,ub_callback_t,
+            #retvals: int, int
+
+        def wait(self):
+            """Wait for a context to finish with results.
+               
+               Calls  after the wait for you. After the wait, there are no more outstanding asynchronous queries.
+               
+               :returns: (int) 0 if OK, else error.
+            """
+            return _unbound.ub_wait(self)
+            #parameters: struct ub_ctx *,
+            #retvals: int
+
+        #_UB_METHODS#
+ %}
+}
+
+
+// ================================================================================
+// ub_result - validation and resolution results
+// ================================================================================
+%nodefaultctor ub_result; //no default constructor & destructor
+%nodefaultdtor ub_result;
+
+%delobject ub_resolve_free;
+%rename(_ub_resolve_free) ub_resolve_free;
+%inline %{
+  void ub_resolve_free_dbg (struct ub_result* r) {
+    printf("******** UB_RESOLVE free 0x%lX ************\n", (long unsigned int)r);
+    ub_resolve_free(r);
+  }
+%} 
+
+%feature("docstring") ub_result "The validation and resolution results."
+
+//ub_result.rcode
+%inline %{
+  enum result_enum_rcode {
+    RCODE_NOERROR = 0,
+    RCODE_FORMERR = 1,
+    RCODE_SERVFAIL = 2,
+    RCODE_NXDOMAIN = 3,
+    RCODE_NOTIMPL = 4,
+    RCODE_REFUSED = 5,
+    RCODE_YXDOMAIN = 6,
+    RCODE_YXRRSET = 7,
+    RCODE_NXRRSET = 8,
+    RCODE_NOTAUTH = 9,
+    RCODE_NOTZONE = 10
+  };
+%}
+
+%pythoncode %{
+   class ub_data:
+      """Class which makes the resolution results accessible"""
+      def __init__(self, data):
+         """Creates ub_data class
+            :param data: a list of the result data in RAW format
+         """
+         if data == None:
+            raise Exception("ub_data init: No data")
+         self.data = data
+
+      def __str__(self):
+         """Represents data as string"""
+         return ';'.join([' '.join(map(lambda x:"%02X" % ord(x),a)) for a in self.data])
+
+      @staticmethod
+      def dname2str(s, ofs=0, maxlen=0):
+         """Parses DNAME and produces a list of labels
+        
+            :param ofs: where the conversion should start to parse data
+            :param maxlen: maximum length (0 means parse to the end)
+            :returns: list of labels (string)
+         """
+         if not s:
+            return []
+
+         res = []
+         slen = len(s)
+         if maxlen > 0:
+            slen = min(slen, maxlen)
+
+         idx = ofs
+         while (idx < slen):
+            complen = ord(s[idx])
+            res.append(s[idx+1:idx+1+complen])
+            idx += complen + 1
+
+         return res
+
+      def as_raw_data(self):
+         """Returns a list of RAW strings"""
+         return self.data
+
+      raw = property(as_raw_data, doc="Returns RAW data (a list of binary encoded strings). See :meth:`as_raw_data`")
+
+      def as_mx_list(self):
+         """Represents data as a list of MX records (query for RR_TYPE_MX)
+        
+            :returns: list of tuples (priority, dname)
+         """
+         return [(256*ord(rdf[0])+ord(rdf[1]),'.'.join([a for a in self.dname2str(rdf,2)])) for rdf in self.data]
+      
+      mx_list = property(as_mx_list, doc="Returns a list of tuples containing priority and domain names. See :meth:`as_mx_list`")
+
+      def as_idn_mx_list(self):
+         """Represents data as a list of MX records (query for RR_TYPE_MX)
+        
+            :returns: list of tuples (priority, unicode dname)
+         """
+         return [(256*ord(rdf[0])+ord(rdf[1]),'.'.join([encodings.idna.ToUnicode(a) for a in self.dname2str(rdf,2)])) for rdf in self.data]
+
+      mx_list_idn = property(as_idn_mx_list, doc="Returns a list of tuples containing priority and IDN domain names. See :meth:`as_idn_mx_list`")
+
+      def as_address_list(self):
+         """Represents data as a list of IP addresses (query for RR_TYPE_PTR)
+        
+            :returns: list of strings
+         """
+         return ['.'.join(map(lambda x:str(ord(x)),a)) for a in self.data]
+
+      address_list = property(as_address_list, doc="Returns a list of IP addresses. See :meth:`as_address_list`")
+
+      def as_domain_list(self):
+         """Represents data as a list of domain names (query for RR_TYPE_A)
+
+            :returns: list of strings
+         """
+         return map(lambda x:'.'.join(self.dname2str(x)), self.data)
+
+      domain_list = property(as_domain_list, doc="Returns a list of domain names. See :meth:`as_domain_list`")
+
+      def as_idn_domain_list(self):
+         """Represents data as a list of unicode domain names (query for RR_TYPE_A)
+
+            :returns: list of strings
+         """
+         return map(lambda x: '.'.join([encodings.idna.ToUnicode(a) for a in self.dname2str(x)]), self.data)
+
+      domain_list_idn = property(as_idn_domain_list, doc="Returns a list of IDN domain names. See :meth:`as_idn_domain_list`")
+%}
+        
+%extend ub_result
+{
+
+  %rename(_data) data;
+  
+  PyObject* _ub_result_data(struct ub_result* result) {
+    PyObject  *list;
+     int i,j,cnt;
+     if ((result == 0) || (!result->havedata) || (result->data == 0))
+        return Py_None;
+
+     for (cnt=0,i=0;;i++,cnt++) 
+         if (result->data[i] == 0)
+            break;
+     
+     list = PyList_New(cnt);
+     for (i=0;i<cnt;i++) 
+         PyList_SetItem(list, i, PyString_FromStringAndSize(result->data[i],result->len[i]));
+     
+     return list;
+  }
+  
+ %pythoncode %{
+   def __init__(self):
+       raise Exception("This class can't be created directly.")
+
+   #__swig_destroy__ = _unbound.ub_resolve_free_dbg
+   __swig_destroy__ = _unbound._ub_resolve_free
+
+   #havedata = property(_unbound.ub_result_havedata_get, _unbound.ub_result_havedata_set, "Havedata property")
+
+   rcode2str = {RCODE_NOERROR:'no error', RCODE_FORMERR:'form error', RCODE_SERVFAIL:'serv fail', RCODE_NXDOMAIN:'nx domain', RCODE_NOTIMPL:'not implemented', RCODE_REFUSED:'refused', RCODE_YXDOMAIN:'yxdomain', RCODE_YXRRSET:'yxrrset', RCODE_NXRRSET:'nxrrset', RCODE_NOTAUTH:'not auth', RCODE_NOTZONE:'not zone'}
+
+   def _get_rcode_str(self):
+       """Returns rcode in display representation form
+
+          :returns: string
+       """
+       return self.rcode2str[self.rcode]
+
+   __swig_getmethods__["rcode_str"] = _get_rcode_str
+   if _newclass:rcode_str = _swig_property(_get_rcode_str)
+
+   def _get_raw_data(self):
+       """Result data, a list of network order DNS rdata items. 
+
+          Data are represented as a list of strings. To decode RAW data to the list of IP addresses use :attr:`data` attribute which returns an :class:`ub_data` instance containing conversion function.
+       """
+       return self._ub_result_data(self)
+
+   __swig_getmethods__["rawdata"] = _get_raw_data
+   rawdata = property(_get_raw_data, doc="Returns raw data, a list of rdata items. To decode RAW data use the :attr:`data` attribute which returns an instance of :class:`ub_data` containing the conversion functions.")
+
+   def _get_data(self):
+       if not self.havedata: return None
+       return ub_data(self._ub_result_data(self))
+  
+   __swig_getmethods__["data"] = _get_data
+   data = property(_get_data, doc="Returns :class:`ub_data` instance containing various decoding functions or None")
+
+%}
+             
+}
+
+%exception ub_resolve
+%{ 
+  //printf("resolve_start(%lX)\n",(long unsigned int)arg1);
+  Py_BEGIN_ALLOW_THREADS 
+  $function 
+  Py_END_ALLOW_THREADS 
+  //printf("resolve_stop()\n");
+%} 
+
+%include "libunbound/unbound.h"
+
+%inline %{
+  //SWIG will see the ub_ctx as a class
+  struct ub_ctx {
+  };
+%}
+
+//ub_ctx_debugout void* parameter correction
+int ub_ctx_debugout(struct ub_ctx* ctx, FILE* out);
+
+// ================================================================================
+// ub_resolve_async - perform asynchronous resolution and validation
+// ================================================================================
+
+%typemap(in,numinputs=0,noblock=1) (int* async_id)  
+{ 
+   int asyncid = -1;
+   $1 = &asyncid;
+} 
+
+%apply PyObject* {void* mydata}
+       
+/* result generation */
+%typemap(argout,noblock=1) (int* async_id)
+{
+  PyObject* tuple;
+  tuple = PyTuple_New(2);
+  PyTuple_SetItem(tuple, 0, $result);
+  PyTuple_SetItem(tuple, 1, SWIG_From_int(asyncid));
+  $result = tuple;
+}
+
+// Grab a Python function object as a Python object.
+%typemap(in) (PyObject *pyfunc) {
+  if (!PyCallable_Check($input)) 
+  {
+     PyErr_SetString(PyExc_TypeError, "Need a callable object!");
+     return NULL;
+  }
+  $1 = $input;
+}
+   
+// Python callback workaround
+int _ub_resolve_async(struct ub_ctx* ctx, char* name, int rrtype, int rrclass, void* mydata, PyObject *pyfunc, int* async_id);
+
+%{
+   struct cb_data {
+      PyObject* data;
+      PyObject* func;
+   };
+
+   static void PythonCallBack(void* iddata, int status, struct ub_result* result)
+   {
+      PyObject *func, *arglist;
+      PyObject *fresult;
+      struct cb_data* id;
+      id = (struct cb_data*) iddata;
+      arglist = Py_BuildValue("(OiO)",id->data,status, SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_ub_result, 0 |  0 ));   // Build argument list
+      fresult = PyEval_CallObject(id->func,arglist);     // Call Python
+      Py_DECREF(id->func);
+      Py_DECREF(id->data);
+      free(id);
+      ub_resolve_free(result);                  //free ub_result
+      //ub_resolve_free_dbg(result);                  //free ub_result
+      Py_DECREF(arglist);                           // Trash arglist
+      Py_XDECREF(fresult);
+   }
+
+   int _ub_resolve_async(struct ub_ctx* ctx, char* name, int rrtype, int rrclass, PyObject* mydata, PyObject *pyfunc, int* async_id) {
+      struct cb_data* id;
+      id = (struct cb_data*) malloc(sizeof(struct cb_data));
+      id->data = mydata;
+      id->func = pyfunc;
+   
+      int i = ub_resolve_async(ctx,name,rrtype,rrclass, (void *) id, PythonCallBack, async_id);
+      Py_INCREF(mydata);
+      Py_INCREF(pyfunc);
+      return i;
+   }
+
+%}
+
+%pythoncode %{
+    ub_resolve_async = _unbound._ub_resolve_async
+
+    def reverse(domain):
+        """Reverse domain name
+        
+           Usable for reverse lookups when the IP address should be reversed
+        """
+        return '.'.join([a for a in domain.split(".")][::-1])
+
+    def idn2dname(idnname):
+        """Converts domain name in IDN format to canonic domain name
+
+           :param idnname: (unicode string) IDN name
+           :returns: (string) domain name
+        """
+        return '.'.join([encodings.idna.ToASCII(a) for a in idnname.split('.')])
+
+    def dname2idn(name):
+        """Converts canonic domain name in IDN format to unicode string
+
+            :param name: (string) domain name
+            :returns: (unicode string) domain name
+        """
+        return '.'.join([encodings.idna.ToUnicode(a) for a in name.split('.')])
+
+%}
+
diff --git a/contrib/python/libunbound_wrap.c b/contrib/python/libunbound_wrap.c
new file mode 100644 (file)
index 0000000..507349b
--- /dev/null
@@ -0,0 +1,5776 @@
+/* ----------------------------------------------------------------------------
+ * This file was automatically generated by SWIG (http://www.swig.org).
+ * Version 1.3.38
+ * 
+ * This file is not intended to be easily readable and contains a number of 
+ * coding conventions designed to improve portability and efficiency. Do not make
+ * changes to this file unless you know what you are doing--modify the SWIG 
+ * interface file instead. 
+ * ----------------------------------------------------------------------------- */
+
+#define SWIGPYTHON
+#define SWIG_PYTHON_DIRECTOR_NO_VTABLE
+
+/* -----------------------------------------------------------------------------
+ *  This section contains generic SWIG labels for method/variable
+ *  declarations/attributes, and other compiler dependent labels.
+ * ----------------------------------------------------------------------------- */
+
+/* template workaround for compilers that cannot correctly implement the C++ standard */
+#ifndef SWIGTEMPLATEDISAMBIGUATOR
+# if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x560)
+#  define SWIGTEMPLATEDISAMBIGUATOR template
+# elif defined(__HP_aCC)
+/* Needed even with `aCC -AA' when `aCC -V' reports HP ANSI C++ B3910B A.03.55 */
+/* If we find a maximum version that requires this, the test would be __HP_aCC <= 35500 for A.03.55 */
+#  define SWIGTEMPLATEDISAMBIGUATOR template
+# else
+#  define SWIGTEMPLATEDISAMBIGUATOR
+# endif
+#endif
+
+/* inline attribute */
+#ifndef SWIGINLINE
+# if defined(__cplusplus) || (defined(__GNUC__) && !defined(__STRICT_ANSI__))
+#   define SWIGINLINE inline
+# else
+#   define SWIGINLINE
+# endif
+#endif
+
+/* attribute recognised by some compilers to avoid 'unused' warnings */
+#ifndef SWIGUNUSED
+# if defined(__GNUC__)
+#   if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
+#     define SWIGUNUSED __attribute__ ((__unused__)) 
+#   else
+#     define SWIGUNUSED
+#   endif
+# elif defined(__ICC)
+#   define SWIGUNUSED __attribute__ ((__unused__)) 
+# else
+#   define SWIGUNUSED 
+# endif
+#endif
+
+#ifndef SWIG_MSC_UNSUPPRESS_4505
+# if defined(_MSC_VER)
+#   pragma warning(disable : 4505) /* unreferenced local function has been removed */
+# endif 
+#endif
+
+#ifndef SWIGUNUSEDPARM
+# ifdef __cplusplus
+#   define SWIGUNUSEDPARM(p)
+# else
+#   define SWIGUNUSEDPARM(p) p SWIGUNUSED 
+# endif
+#endif
+
+/* internal SWIG method */
+#ifndef SWIGINTERN
+# define SWIGINTERN static SWIGUNUSED
+#endif
+
+/* internal inline SWIG method */
+#ifndef SWIGINTERNINLINE
+# define SWIGINTERNINLINE SWIGINTERN SWIGINLINE
+#endif
+
+/* exporting methods */
+#if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+#  ifndef GCC_HASCLASSVISIBILITY
+#    define GCC_HASCLASSVISIBILITY
+#  endif
+#endif
+
+#ifndef SWIGEXPORT
+# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
+#   if defined(STATIC_LINKED)
+#     define SWIGEXPORT
+#   else
+#     define SWIGEXPORT __declspec(dllexport)
+#   endif
+# else
+#   if defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY)
+#     define SWIGEXPORT __attribute__ ((visibility("default")))
+#   else
+#     define SWIGEXPORT
+#   endif
+# endif
+#endif
+
+/* calling conventions for Windows */
+#ifndef SWIGSTDCALL
+# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
+#   define SWIGSTDCALL __stdcall
+# else
+#   define SWIGSTDCALL
+# endif 
+#endif
+
+/* Deal with Microsoft's attempt at deprecating C standard runtime functions */
+#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
+# define _CRT_SECURE_NO_DEPRECATE
+#endif
+
+/* Deal with Microsoft's attempt at deprecating methods in the standard C++ library */
+#if !defined(SWIG_NO_SCL_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_SCL_SECURE_NO_DEPRECATE)
+# define _SCL_SECURE_NO_DEPRECATE
+#endif
+
+
+
+/* Python.h has to appear first */
+#include <Python.h>
+
+/* -----------------------------------------------------------------------------
+ * swigrun.swg
+ *
+ * This file contains generic C API SWIG runtime support for pointer
+ * type checking.
+ * ----------------------------------------------------------------------------- */
+
+/* This should only be incremented when either the layout of swig_type_info changes,
+   or for whatever reason, the runtime changes incompatibly */
+#define SWIG_RUNTIME_VERSION "4"
+
+/* define SWIG_TYPE_TABLE_NAME as "SWIG_TYPE_TABLE" */
+#ifdef SWIG_TYPE_TABLE
+# define SWIG_QUOTE_STRING(x) #x
+# define SWIG_EXPAND_AND_QUOTE_STRING(x) SWIG_QUOTE_STRING(x)
+# define SWIG_TYPE_TABLE_NAME SWIG_EXPAND_AND_QUOTE_STRING(SWIG_TYPE_TABLE)
+#else
+# define SWIG_TYPE_TABLE_NAME
+#endif
+
+/*
+  You can use the SWIGRUNTIME and SWIGRUNTIMEINLINE macros for
+  creating a static or dynamic library from the SWIG runtime code.
+  In 99.9% of the cases, SWIG just needs to declare them as 'static'.
+  
+  But only do this if strictly necessary, ie, if you have problems
+  with your compiler or suchlike.
+*/
+
+#ifndef SWIGRUNTIME
+# define SWIGRUNTIME SWIGINTERN
+#endif
+
+#ifndef SWIGRUNTIMEINLINE
+# define SWIGRUNTIMEINLINE SWIGRUNTIME SWIGINLINE
+#endif
+
+/*  Generic buffer size */
+#ifndef SWIG_BUFFER_SIZE
+# define SWIG_BUFFER_SIZE 1024
+#endif
+
+/* Flags for pointer conversions */
+#define SWIG_POINTER_DISOWN        0x1
+#define SWIG_CAST_NEW_MEMORY       0x2
+
+/* Flags for new pointer objects */
+#define SWIG_POINTER_OWN           0x1
+
+
+/* 
+   Flags/methods for returning states.
+   
+   The SWIG conversion methods, as ConvertPtr, return and integer 
+   that tells if the conversion was successful or not. And if not,
+   an error code can be returned (see swigerrors.swg for the codes).
+   
+   Use the following macros/flags to set or process the returning
+   states.
+   
+   In old versions of SWIG, code such as the following was usually written:
+
+     if (SWIG_ConvertPtr(obj,vptr,ty.flags) != -1) {
+       // success code
+     } else {
+       //fail code
+     }
+
+   Now you can be more explicit:
+
+    int res = SWIG_ConvertPtr(obj,vptr,ty.flags);
+    if (SWIG_IsOK(res)) {
+      // success code
+    } else {
+      // fail code
+    }
+
+   which is the same really, but now you can also do
+
+    Type *ptr;
+    int res = SWIG_ConvertPtr(obj,(void **)(&ptr),ty.flags);
+    if (SWIG_IsOK(res)) {
+      // success code
+      if (SWIG_IsNewObj(res) {
+        ...
+       delete *ptr;
+      } else {
+        ...
+      }
+    } else {
+      // fail code
+    }
+    
+   I.e., now SWIG_ConvertPtr can return new objects and you can
+   identify the case and take care of the deallocation. Of course that
+   also requires SWIG_ConvertPtr to return new result values, such as
+
+      int SWIG_ConvertPtr(obj, ptr,...) {         
+        if (<obj is ok>) {                            
+          if (<need new object>) {                    
+            *ptr = <ptr to new allocated object>; 
+            return SWIG_NEWOBJ;                       
+          } else {                                    
+            *ptr = <ptr to old object>;               
+            return SWIG_OLDOBJ;                       
+          }                                   
+        } else {                                      
+          return SWIG_BADOBJ;                 
+        }                                             
+      }
+
+   Of course, returning the plain '0(success)/-1(fail)' still works, but you can be
+   more explicit by returning SWIG_BADOBJ, SWIG_ERROR or any of the
+   SWIG errors code.
+
+   Finally, if the SWIG_CASTRANK_MODE is enabled, the result code
+   allows to return the 'cast rank', for example, if you have this
+
+       int food(double)
+       int fooi(int);
+
+   and you call
+      food(1)   // cast rank '1'  (1 -> 1.0)
+      fooi(1)   // cast rank '0'
+
+   just use the SWIG_AddCast()/SWIG_CheckState()
+*/
+
+#define SWIG_OK                    (0) 
+#define SWIG_ERROR                 (-1)
+#define SWIG_IsOK(r)               (r >= 0)
+#define SWIG_ArgError(r)           ((r != SWIG_ERROR) ? r : SWIG_TypeError)  
+
+/* The CastRankLimit says how many bits are used for the cast rank */
+#define SWIG_CASTRANKLIMIT         (1 << 8)
+/* The NewMask denotes the object was created (using new/malloc) */
+#define SWIG_NEWOBJMASK            (SWIG_CASTRANKLIMIT  << 1)
+/* The TmpMask is for in/out typemaps that use temporal objects */
+#define SWIG_TMPOBJMASK            (SWIG_NEWOBJMASK << 1)
+/* Simple returning values */
+#define SWIG_BADOBJ                (SWIG_ERROR)
+#define SWIG_OLDOBJ                (SWIG_OK)
+#define SWIG_NEWOBJ                (SWIG_OK | SWIG_NEWOBJMASK)
+#define SWIG_TMPOBJ                (SWIG_OK | SWIG_TMPOBJMASK)
+/* Check, add and del mask methods */
+#define SWIG_AddNewMask(r)         (SWIG_IsOK(r) ? (r | SWIG_NEWOBJMASK) : r)
+#define SWIG_DelNewMask(r)         (SWIG_IsOK(r) ? (r & ~SWIG_NEWOBJMASK) : r)
+#define SWIG_IsNewObj(r)           (SWIG_IsOK(r) && (r & SWIG_NEWOBJMASK))
+#define SWIG_AddTmpMask(r)         (SWIG_IsOK(r) ? (r | SWIG_TMPOBJMASK) : r)
+#define SWIG_DelTmpMask(r)         (SWIG_IsOK(r) ? (r & ~SWIG_TMPOBJMASK) : r)
+#define SWIG_IsTmpObj(r)           (SWIG_IsOK(r) && (r & SWIG_TMPOBJMASK))
+
+/* Cast-Rank Mode */
+#if defined(SWIG_CASTRANK_MODE)
+#  ifndef SWIG_TypeRank
+#    define SWIG_TypeRank             unsigned long
+#  endif
+#  ifndef SWIG_MAXCASTRANK            /* Default cast allowed */
+#    define SWIG_MAXCASTRANK          (2)
+#  endif
+#  define SWIG_CASTRANKMASK          ((SWIG_CASTRANKLIMIT) -1)
+#  define SWIG_CastRank(r)           (r & SWIG_CASTRANKMASK)
+SWIGINTERNINLINE int SWIG_AddCast(int r) { 
+  return SWIG_IsOK(r) ? ((SWIG_CastRank(r) < SWIG_MAXCASTRANK) ? (r + 1) : SWIG_ERROR) : r;
+}
+SWIGINTERNINLINE int SWIG_CheckState(int r) { 
+  return SWIG_IsOK(r) ? SWIG_CastRank(r) + 1 : 0; 
+}
+#else /* no cast-rank mode */
+#  define SWIG_AddCast
+#  define SWIG_CheckState(r) (SWIG_IsOK(r) ? 1 : 0)
+#endif
+
+
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void *(*swig_converter_func)(void *, int *);
+typedef struct swig_type_info *(*swig_dycast_func)(void **);
+
+/* Structure to store information on one type */
+typedef struct swig_type_info {
+  const char             *name;                        /* mangled name of this type */
+  const char             *str;                 /* human readable name of this type */
+  swig_dycast_func        dcast;               /* dynamic cast function down a hierarchy */
+  struct swig_cast_info  *cast;                        /* linked list of types that can cast into this type */
+  void                   *clientdata;          /* language specific type data */
+  int                    owndata;              /* flag if the structure owns the clientdata */
+} swig_type_info;
+
+/* Structure to store a type and conversion function used for casting */
+typedef struct swig_cast_info {
+  swig_type_info         *type;                        /* pointer to type that is equivalent to this type */
+  swig_converter_func     converter;           /* function to cast the void pointers */
+  struct swig_cast_info  *next;                        /* pointer to next cast in linked list */
+  struct swig_cast_info  *prev;                        /* pointer to the previous cast */
+} swig_cast_info;
+
+/* Structure used to store module information
+ * Each module generates one structure like this, and the runtime collects
+ * all of these structures and stores them in a circularly linked list.*/
+typedef struct swig_module_info {
+  swig_type_info         **types;              /* Array of pointers to swig_type_info structures that are in this module */
+  size_t                 size;                 /* Number of types in this module */
+  struct swig_module_info *next;               /* Pointer to next element in circularly linked list */
+  swig_type_info         **type_initial;       /* Array of initially generated type structures */
+  swig_cast_info         **cast_initial;       /* Array of initially generated casting structures */
+  void                    *clientdata;         /* Language specific module data */
+} swig_module_info;
+
+/* 
+  Compare two type names skipping the space characters, therefore
+  "char*" == "char *" and "Class<int>" == "Class<int >", etc.
+
+  Return 0 when the two name types are equivalent, as in
+  strncmp, but skipping ' '.
+*/
+SWIGRUNTIME int
+SWIG_TypeNameComp(const char *f1, const char *l1,
+                 const char *f2, const char *l2) {
+  for (;(f1 != l1) && (f2 != l2); ++f1, ++f2) {
+    while ((*f1 == ' ') && (f1 != l1)) ++f1;
+    while ((*f2 == ' ') && (f2 != l2)) ++f2;
+    if (*f1 != *f2) return (*f1 > *f2) ? 1 : -1;
+  }
+  return (int)((l1 - f1) - (l2 - f2));
+}
+
+/*
+  Check type equivalence in a name list like <name1>|<name2>|...
+  Return 0 if not equal, 1 if equal
+*/
+SWIGRUNTIME int
+SWIG_TypeEquiv(const char *nb, const char *tb) {
+  int equiv = 0;
+  const char* te = tb + strlen(tb);
+  const char* ne = nb;
+  while (!equiv && *ne) {
+    for (nb = ne; *ne; ++ne) {
+      if (*ne == '|') break;
+    }
+    equiv = (SWIG_TypeNameComp(nb, ne, tb, te) == 0) ? 1 : 0;
+    if (*ne) ++ne;
+  }
+  return equiv;
+}
+
+/*
+  Check type equivalence in a name list like <name1>|<name2>|...
+  Return 0 if equal, -1 if nb < tb, 1 if nb > tb
+*/
+SWIGRUNTIME int
+SWIG_TypeCompare(const char *nb, const char *tb) {
+  int equiv = 0;
+  const char* te = tb + strlen(tb);
+  const char* ne = nb;
+  while (!equiv && *ne) {
+    for (nb = ne; *ne; ++ne) {
+      if (*ne == '|') break;
+    }
+    equiv = (SWIG_TypeNameComp(nb, ne, tb, te) == 0) ? 1 : 0;
+    if (*ne) ++ne;
+  }
+  return equiv;
+}
+
+
+/*
+  Check the typename
+*/
+SWIGRUNTIME swig_cast_info *
+SWIG_TypeCheck(const char *c, swig_type_info *ty) {
+  if (ty) {
+    swig_cast_info *iter = ty->cast;
+    while (iter) {
+      if (strcmp(iter->type->name, c) == 0) {
+        if (iter == ty->cast)
+          return iter;
+        /* Move iter to the top of the linked list */
+        iter->prev->next = iter->next;
+        if (iter->next)
+          iter->next->prev = iter->prev;
+        iter->next = ty->cast;
+        iter->prev = 0;
+        if (ty->cast) ty->cast->prev = iter;
+        ty->cast = iter;
+        return iter;
+      }
+      iter = iter->next;
+    }
+  }
+  return 0;
+}
+
+/* 
+  Identical to SWIG_TypeCheck, except strcmp is replaced with a pointer comparison
+*/
+SWIGRUNTIME swig_cast_info *
+SWIG_TypeCheckStruct(swig_type_info *from, swig_type_info *ty) {
+  if (ty) {
+    swig_cast_info *iter = ty->cast;
+    while (iter) {
+      if (iter->type == from) {
+        if (iter == ty->cast)
+          return iter;
+        /* Move iter to the top of the linked list */
+        iter->prev->next = iter->next;
+        if (iter->next)
+          iter->next->prev = iter->prev;
+        iter->next = ty->cast;
+        iter->prev = 0;
+        if (ty->cast) ty->cast->prev = iter;
+        ty->cast = iter;
+        return iter;
+      }
+      iter = iter->next;
+    }
+  }
+  return 0;
+}
+
+/*
+  Cast a pointer up an inheritance hierarchy
+*/
+SWIGRUNTIMEINLINE void *
+SWIG_TypeCast(swig_cast_info *ty, void *ptr, int *newmemory) {
+  return ((!ty) || (!ty->converter)) ? ptr : (*ty->converter)(ptr, newmemory);
+}
+
+/* 
+   Dynamic pointer casting. Down an inheritance hierarchy
+*/
+SWIGRUNTIME swig_type_info *
+SWIG_TypeDynamicCast(swig_type_info *ty, void **ptr) {
+  swig_type_info *lastty = ty;
+  if (!ty || !ty->dcast) return ty;
+  while (ty && (ty->dcast)) {
+    ty = (*ty->dcast)(ptr);
+    if (ty) lastty = ty;
+  }
+  return lastty;
+}
+
+/*
+  Return the name associated with this type
+*/
+SWIGRUNTIMEINLINE const char *
+SWIG_TypeName(const swig_type_info *ty) {
+  return ty->name;
+}
+
+/*
+  Return the pretty name associated with this type,
+  that is an unmangled type name in a form presentable to the user.
+*/
+SWIGRUNTIME const char *
+SWIG_TypePrettyName(const swig_type_info *type) {
+  /* The "str" field contains the equivalent pretty names of the
+     type, separated by vertical-bar characters.  We choose
+     to print the last name, as it is often (?) the most
+     specific. */
+  if (!type) return NULL;
+  if (type->str != NULL) {
+    const char *last_name = type->str;
+    const char *s;
+    for (s = type->str; *s; s++)
+      if (*s == '|') last_name = s+1;
+    return last_name;
+  }
+  else
+    return type->name;
+}
+
+/* 
+   Set the clientdata field for a type
+*/
+SWIGRUNTIME void
+SWIG_TypeClientData(swig_type_info *ti, void *clientdata) {
+  swig_cast_info *cast = ti->cast;
+  /* if (ti->clientdata == clientdata) return; */
+  ti->clientdata = clientdata;
+  
+  while (cast) {
+    if (!cast->converter) {
+      swig_type_info *tc = cast->type;
+      if (!tc->clientdata) {
+       SWIG_TypeClientData(tc, clientdata);
+      }
+    }    
+    cast = cast->next;
+  }
+}
+SWIGRUNTIME void
+SWIG_TypeNewClientData(swig_type_info *ti, void *clientdata) {
+  SWIG_TypeClientData(ti, clientdata);
+  ti->owndata = 1;
+}
+  
+/*
+  Search for a swig_type_info structure only by mangled name
+  Search is a O(log #types)
+  
+  We start searching at module start, and finish searching when start == end.  
+  Note: if start == end at the beginning of the function, we go all the way around
+  the circular list.
+*/
+SWIGRUNTIME swig_type_info *
+SWIG_MangledTypeQueryModule(swig_module_info *start, 
+                            swig_module_info *end, 
+                           const char *name) {
+  swig_module_info *iter = start;
+  do {
+    if (iter->size) {
+      register size_t l = 0;
+      register size_t r = iter->size - 1;
+      do {
+       /* since l+r >= 0, we can (>> 1) instead (/ 2) */
+       register size_t i = (l + r) >> 1; 
+       const char *iname = iter->types[i]->name;
+       if (iname) {
+         register int compare = strcmp(name, iname);
+         if (compare == 0) {       
+           return iter->types[i];
+         } else if (compare < 0) {
+           if (i) {
+             r = i - 1;
+           } else {
+             break;
+           }
+         } else if (compare > 0) {
+           l = i + 1;
+         }
+       } else {
+         break; /* should never happen */
+       }
+      } while (l <= r);
+    }
+    iter = iter->next;
+  } while (iter != end);
+  return 0;
+}
+
+/*
+  Search for a swig_type_info structure for either a mangled name or a human readable name.
+  It first searches the mangled names of the types, which is a O(log #types)
+  If a type is not found it then searches the human readable names, which is O(#types).
+  
+  We start searching at module start, and finish searching when start == end.  
+  Note: if start == end at the beginning of the function, we go all the way around
+  the circular list.
+*/
+SWIGRUNTIME swig_type_info *
+SWIG_TypeQueryModule(swig_module_info *start, 
+                     swig_module_info *end, 
+                    const char *name) {
+  /* STEP 1: Search the name field using binary search */
+  swig_type_info *ret = SWIG_MangledTypeQueryModule(start, end, name);
+  if (ret) {
+    return ret;
+  } else {
+    /* STEP 2: If the type hasn't been found, do a complete search
+       of the str field (the human readable name) */
+    swig_module_info *iter = start;
+    do {
+      register size_t i = 0;
+      for (; i < iter->size; ++i) {
+       if (iter->types[i]->str && (SWIG_TypeEquiv(iter->types[i]->str, name)))
+         return iter->types[i];
+      }
+      iter = iter->next;
+    } while (iter != end);
+  }
+  
+  /* neither found a match */
+  return 0;
+}
+
+/* 
+   Pack binary data into a string
+*/
+SWIGRUNTIME char *
+SWIG_PackData(char *c, void *ptr, size_t sz) {
+  static const char hex[17] = "0123456789abcdef";
+  register const unsigned char *u = (unsigned char *) ptr;
+  register const unsigned char *eu =  u + sz;
+  for (; u != eu; ++u) {
+    register unsigned char uu = *u;
+    *(c++) = hex[(uu & 0xf0) >> 4];
+    *(c++) = hex[uu & 0xf];
+  }
+  return c;
+}
+
+/* 
+   Unpack binary data from a string
+*/
+SWIGRUNTIME const char *
+SWIG_UnpackData(const char *c, void *ptr, size_t sz) {
+  register unsigned char *u = (unsigned char *) ptr;
+  register const unsigned char *eu = u + sz;
+  for (; u != eu; ++u) {
+    register char d = *(c++);
+    register unsigned char uu;
+    if ((d >= '0') && (d <= '9'))
+      uu = ((d - '0') << 4);
+    else if ((d >= 'a') && (d <= 'f'))
+      uu = ((d - ('a'-10)) << 4);
+    else 
+      return (char *) 0;
+    d = *(c++);
+    if ((d >= '0') && (d <= '9'))
+      uu |= (d - '0');
+    else if ((d >= 'a') && (d <= 'f'))
+      uu |= (d - ('a'-10));
+    else 
+      return (char *) 0;
+    *u = uu;
+  }
+  return c;
+}
+
+/* 
+   Pack 'void *' into a string buffer.
+*/
+SWIGRUNTIME char *
+SWIG_PackVoidPtr(char *buff, void *ptr, const char *name, size_t bsz) {
+  char *r = buff;
+  if ((2*sizeof(void *) + 2) > bsz) return 0;
+  *(r++) = '_';
+  r = SWIG_PackData(r,&ptr,sizeof(void *));
+  if (strlen(name) + 1 > (bsz - (r - buff))) return 0;
+  strcpy(r,name);
+  return buff;
+}
+
+SWIGRUNTIME const char *
+SWIG_UnpackVoidPtr(const char *c, void **ptr, const char *name) {
+  if (*c != '_') {
+    if (strcmp(c,"NULL") == 0) {
+      *ptr = (void *) 0;
+      return name;
+    } else {
+      return 0;
+    }
+  }
+  return SWIG_UnpackData(++c,ptr,sizeof(void *));
+}
+
+SWIGRUNTIME char *
+SWIG_PackDataName(char *buff, void *ptr, size_t sz, const char *name, size_t bsz) {
+  char *r = buff;
+  size_t lname = (name ? strlen(name) : 0);
+  if ((2*sz + 2 + lname) > bsz) return 0;
+  *(r++) = '_';
+  r = SWIG_PackData(r,ptr,sz);
+  if (lname) {
+    strncpy(r,name,lname+1);
+  } else {
+    *r = 0;
+  }
+  return buff;
+}
+
+SWIGRUNTIME const char *
+SWIG_UnpackDataName(const char *c, void *ptr, size_t sz, const char *name) {
+  if (*c != '_') {
+    if (strcmp(c,"NULL") == 0) {
+      memset(ptr,0,sz);
+      return name;
+    } else {
+      return 0;
+    }
+  }
+  return SWIG_UnpackData(++c,ptr,sz);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+/*  Errors in SWIG */
+#define  SWIG_UnknownError        -1 
+#define  SWIG_IOError             -2 
+#define  SWIG_RuntimeError        -3 
+#define  SWIG_IndexError          -4 
+#define  SWIG_TypeError           -5 
+#define  SWIG_DivisionByZero      -6 
+#define  SWIG_OverflowError       -7 
+#define  SWIG_SyntaxError         -8 
+#define  SWIG_ValueError          -9 
+#define  SWIG_SystemError         -10
+#define  SWIG_AttributeError      -11
+#define  SWIG_MemoryError         -12 
+#define  SWIG_NullReferenceError   -13
+
+
+
+/* Compatibility marcos for Python 3 */
+#if PY_VERSION_HEX >= 0x03000000
+
+#define PyClass_Check(obj) PyObject_IsInstance(obj, (PyObject *)&PyType_Type)
+#define PyInt_Check(x) PyLong_Check(x)
+#define PyInt_AsLong(x) PyLong_AsLong(x)
+#define PyInt_FromLong(x) PyLong_FromLong(x)
+#define PyString_Format(fmt, args)  PyUnicode_Format(fmt, args)
+
+#endif
+
+#ifndef Py_TYPE
+#  define Py_TYPE(op) ((op)->ob_type)
+#endif
+
+/* SWIG APIs for compatibility of both Python 2 & 3 */
+
+#if PY_VERSION_HEX >= 0x03000000
+#  define SWIG_Python_str_FromFormat PyUnicode_FromFormat
+#else
+#  define SWIG_Python_str_FromFormat PyString_FromFormat
+#endif
+
+SWIGINTERN char*
+SWIG_Python_str_AsChar(PyObject *str)
+{
+#if PY_VERSION_HEX >= 0x03000000
+  str = PyUnicode_AsUTF8String(str);
+  return PyBytes_AsString(str);
+#else
+  return PyString_AsString(str);
+#endif
+}
+
+SWIGINTERN PyObject*
+SWIG_Python_str_FromChar(const char *c)
+{
+#if PY_VERSION_HEX >= 0x03000000
+  return PyUnicode_FromString(c); 
+#else
+  return PyString_FromString(c);
+#endif
+}
+
+/* Add PyOS_snprintf for old Pythons */
+#if PY_VERSION_HEX < 0x02020000
+# if defined(_MSC_VER) || defined(__BORLANDC__) || defined(_WATCOM)
+#  define PyOS_snprintf _snprintf
+# else
+#  define PyOS_snprintf snprintf
+# endif
+#endif
+
+/* A crude PyString_FromFormat implementation for old Pythons */
+#if PY_VERSION_HEX < 0x02020000
+
+#ifndef SWIG_PYBUFFER_SIZE
+# define SWIG_PYBUFFER_SIZE 1024
+#endif
+
+static PyObject *
+PyString_FromFormat(const char *fmt, ...) {
+  va_list ap;
+  char buf[SWIG_PYBUFFER_SIZE * 2];
+  int res;
+  va_start(ap, fmt);
+  res = vsnprintf(buf, sizeof(buf), fmt, ap);
+  va_end(ap);
+  return (res < 0 || res >= (int)sizeof(buf)) ? 0 : PyString_FromString(buf);
+}
+#endif
+
+/* Add PyObject_Del for old Pythons */
+#if PY_VERSION_HEX < 0x01060000
+# define PyObject_Del(op) PyMem_DEL((op))
+#endif
+#ifndef PyObject_DEL
+# define PyObject_DEL PyObject_Del
+#endif
+
+/* A crude PyExc_StopIteration exception for old Pythons */
+#if PY_VERSION_HEX < 0x02020000
+# ifndef PyExc_StopIteration
+#  define PyExc_StopIteration PyExc_RuntimeError
+# endif
+# ifndef PyObject_GenericGetAttr
+#  define PyObject_GenericGetAttr 0
+# endif
+#endif
+
+/* Py_NotImplemented is defined in 2.1 and up. */
+#if PY_VERSION_HEX < 0x02010000
+# ifndef Py_NotImplemented
+#  define Py_NotImplemented PyExc_RuntimeError
+# endif
+#endif
+
+/* A crude PyString_AsStringAndSize implementation for old Pythons */
+#if PY_VERSION_HEX < 0x02010000
+# ifndef PyString_AsStringAndSize
+#  define PyString_AsStringAndSize(obj, s, len) {*s = PyString_AsString(obj); *len = *s ? strlen(*s) : 0;}
+# endif
+#endif
+
+/* PySequence_Size for old Pythons */
+#if PY_VERSION_HEX < 0x02000000
+# ifndef PySequence_Size
+#  define PySequence_Size PySequence_Length
+# endif
+#endif
+
+/* PyBool_FromLong for old Pythons */
+#if PY_VERSION_HEX < 0x02030000
+static
+PyObject *PyBool_FromLong(long ok)
+{
+  PyObject *result = ok ? Py_True : Py_False;
+  Py_INCREF(result);
+  return result;
+}
+#endif
+
+/* Py_ssize_t for old Pythons */
+/* This code is as recommended by: */
+/* http://www.python.org/dev/peps/pep-0353/#conversion-guidelines */
+#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN)
+typedef int Py_ssize_t;
+# define PY_SSIZE_T_MAX INT_MAX
+# define PY_SSIZE_T_MIN INT_MIN
+#endif
+
+/* -----------------------------------------------------------------------------
+ * error manipulation
+ * ----------------------------------------------------------------------------- */
+
+SWIGRUNTIME PyObject*
+SWIG_Python_ErrorType(int code) {
+  PyObject* type = 0;
+  switch(code) {
+  case SWIG_MemoryError:
+    type = PyExc_MemoryError;
+    break;
+  case SWIG_IOError:
+    type = PyExc_IOError;
+    break;
+  case SWIG_RuntimeError:
+    type = PyExc_RuntimeError;
+    break;
+  case SWIG_IndexError:
+    type = PyExc_IndexError;
+    break;
+  case SWIG_TypeError:
+    type = PyExc_TypeError;
+    break;
+  case SWIG_DivisionByZero:
+    type = PyExc_ZeroDivisionError;
+    break;
+  case SWIG_OverflowError:
+    type = PyExc_OverflowError;
+    break;
+  case SWIG_SyntaxError:
+    type = PyExc_SyntaxError;
+    break;
+  case SWIG_ValueError:
+    type = PyExc_ValueError;
+    break;
+  case SWIG_SystemError:
+    type = PyExc_SystemError;
+    break;
+  case SWIG_AttributeError:
+    type = PyExc_AttributeError;
+    break;
+  default:
+    type = PyExc_RuntimeError;
+  }
+  return type;
+}
+
+
+SWIGRUNTIME void
+SWIG_Python_AddErrorMsg(const char* mesg)
+{
+  PyObject *type = 0;
+  PyObject *value = 0;
+  PyObject *traceback = 0;
+
+  if (PyErr_Occurred()) PyErr_Fetch(&type, &value, &traceback);
+  if (value) {
+    PyObject *old_str = PyObject_Str(value);
+    PyErr_Clear();
+    Py_XINCREF(type);
+
+    PyErr_Format(type, "%s %s", SWIG_Python_str_AsChar(old_str), mesg);
+    Py_DECREF(old_str);
+    Py_DECREF(value);
+  } else {
+    PyErr_SetString(PyExc_RuntimeError, mesg);
+  }
+}
+
+#if defined(SWIG_PYTHON_NO_THREADS)
+#  if defined(SWIG_PYTHON_THREADS)
+#    undef SWIG_PYTHON_THREADS
+#  endif
+#endif
+#if defined(SWIG_PYTHON_THREADS) /* Threading support is enabled */
+#  if !defined(SWIG_PYTHON_USE_GIL) && !defined(SWIG_PYTHON_NO_USE_GIL)
+#    if (PY_VERSION_HEX >= 0x02030000) /* For 2.3 or later, use the PyGILState calls */
+#      define SWIG_PYTHON_USE_GIL
+#    endif
+#  endif
+#  if defined(SWIG_PYTHON_USE_GIL) /* Use PyGILState threads calls */
+#    ifndef SWIG_PYTHON_INITIALIZE_THREADS
+#     define SWIG_PYTHON_INITIALIZE_THREADS  PyEval_InitThreads() 
+#    endif
+#    ifdef __cplusplus /* C++ code */
+       class SWIG_Python_Thread_Block {
+         bool status;
+         PyGILState_STATE state;
+       public:
+         void end() { if (status) { PyGILState_Release(state); status = false;} }
+         SWIG_Python_Thread_Block() : status(true), state(PyGILState_Ensure()) {}
+         ~SWIG_Python_Thread_Block() { end(); }
+       };
+       class SWIG_Python_Thread_Allow {
+         bool status;
+         PyThreadState *save;
+       public:
+         void end() { if (status) { PyEval_RestoreThread(save); status = false; }}
+         SWIG_Python_Thread_Allow() : status(true), save(PyEval_SaveThread()) {}
+         ~SWIG_Python_Thread_Allow() { end(); }
+       };
+#      define SWIG_PYTHON_THREAD_BEGIN_BLOCK   SWIG_Python_Thread_Block _swig_thread_block
+#      define SWIG_PYTHON_THREAD_END_BLOCK     _swig_thread_block.end()
+#      define SWIG_PYTHON_THREAD_BEGIN_ALLOW   SWIG_Python_Thread_Allow _swig_thread_allow
+#      define SWIG_PYTHON_THREAD_END_ALLOW     _swig_thread_allow.end()
+#    else /* C code */
+#      define SWIG_PYTHON_THREAD_BEGIN_BLOCK   PyGILState_STATE _swig_thread_block = PyGILState_Ensure()
+#      define SWIG_PYTHON_THREAD_END_BLOCK     PyGILState_Release(_swig_thread_block)
+#      define SWIG_PYTHON_THREAD_BEGIN_ALLOW   PyThreadState *_swig_thread_allow = PyEval_SaveThread()
+#      define SWIG_PYTHON_THREAD_END_ALLOW     PyEval_RestoreThread(_swig_thread_allow)
+#    endif
+#  else /* Old thread way, not implemented, user must provide it */
+#    if !defined(SWIG_PYTHON_INITIALIZE_THREADS)
+#      define SWIG_PYTHON_INITIALIZE_THREADS
+#    endif
+#    if !defined(SWIG_PYTHON_THREAD_BEGIN_BLOCK)
+#      define SWIG_PYTHON_THREAD_BEGIN_BLOCK
+#    endif
+#    if !defined(SWIG_PYTHON_THREAD_END_BLOCK)
+#      define SWIG_PYTHON_THREAD_END_BLOCK
+#    endif
+#    if !defined(SWIG_PYTHON_THREAD_BEGIN_ALLOW)
+#      define SWIG_PYTHON_THREAD_BEGIN_ALLOW
+#    endif
+#    if !defined(SWIG_PYTHON_THREAD_END_ALLOW)
+#      define SWIG_PYTHON_THREAD_END_ALLOW
+#    endif
+#  endif
+#else /* No thread support */
+#  define SWIG_PYTHON_INITIALIZE_THREADS
+#  define SWIG_PYTHON_THREAD_BEGIN_BLOCK
+#  define SWIG_PYTHON_THREAD_END_BLOCK
+#  define SWIG_PYTHON_THREAD_BEGIN_ALLOW
+#  define SWIG_PYTHON_THREAD_END_ALLOW
+#endif
+
+/* -----------------------------------------------------------------------------
+ * Python API portion that goes into the runtime
+ * ----------------------------------------------------------------------------- */
+
+#ifdef __cplusplus
+extern "C" {
+#if 0
+} /* cc-mode */
+#endif
+#endif
+
+/* -----------------------------------------------------------------------------
+ * Constant declarations
+ * ----------------------------------------------------------------------------- */
+
+/* Constant Types */
+#define SWIG_PY_POINTER 4
+#define SWIG_PY_BINARY  5
+
+/* Constant information structure */
+typedef struct swig_const_info {
+  int type;
+  char *name;
+  long lvalue;
+  double dvalue;
+  void   *pvalue;
+  swig_type_info **ptype;
+} swig_const_info;
+
+
+/* -----------------------------------------------------------------------------
+ * Wrapper of PyInstanceMethod_New() used in Python 3
+ * It is exported to the generated module, used for -fastproxy
+ * ----------------------------------------------------------------------------- */
+SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *self, PyObject *func)
+{
+#if PY_VERSION_HEX >= 0x03000000
+  return PyInstanceMethod_New(func);
+#else
+  return NULL;
+#endif
+}
+
+#ifdef __cplusplus
+#if 0
+{ /* cc-mode */
+#endif
+}
+#endif
+
+
+/* -----------------------------------------------------------------------------
+ * See the LICENSE file for information on copyright, usage and redistribution
+ * of SWIG, and the README file for authors - http://www.swig.org/release.html.
+ *
+ * pyrun.swg
+ *
+ * This file contains the runtime support for Python modules
+ * and includes code for managing global variables and pointer
+ * type checking.
+ *
+ * ----------------------------------------------------------------------------- */
+
+/* Common SWIG API */
+
+/* for raw pointers */
+#define SWIG_Python_ConvertPtr(obj, pptr, type, flags)  SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, 0)
+#define SWIG_ConvertPtr(obj, pptr, type, flags)         SWIG_Python_ConvertPtr(obj, pptr, type, flags)
+#define SWIG_ConvertPtrAndOwn(obj,pptr,type,flags,own)  SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, own)
+#define SWIG_NewPointerObj(ptr, type, flags)            SWIG_Python_NewPointerObj(ptr, type, flags)
+#define SWIG_CheckImplicit(ty)                          SWIG_Python_CheckImplicit(ty) 
+#define SWIG_AcquirePtr(ptr, src)                       SWIG_Python_AcquirePtr(ptr, src)
+#define swig_owntype                                    int
+
+/* for raw packed data */
+#define SWIG_ConvertPacked(obj, ptr, sz, ty)            SWIG_Python_ConvertPacked(obj, ptr, sz, ty)
+#define SWIG_NewPackedObj(ptr, sz, type)                SWIG_Python_NewPackedObj(ptr, sz, type)
+
+/* for class or struct pointers */
+#define SWIG_ConvertInstance(obj, pptr, type, flags)    SWIG_ConvertPtr(obj, pptr, type, flags)
+#define SWIG_NewInstanceObj(ptr, type, flags)           SWIG_NewPointerObj(ptr, type, flags)
+
+/* for C or C++ function pointers */
+#define SWIG_ConvertFunctionPtr(obj, pptr, type)        SWIG_Python_ConvertFunctionPtr(obj, pptr, type)
+#define SWIG_NewFunctionPtrObj(ptr, type)               SWIG_Python_NewPointerObj(ptr, type, 0)
+
+/* for C++ member pointers, ie, member methods */
+#define SWIG_ConvertMember(obj, ptr, sz, ty)            SWIG_Python_ConvertPacked(obj, ptr, sz, ty)
+#define SWIG_NewMemberObj(ptr, sz, type)                SWIG_Python_NewPackedObj(ptr, sz, type)
+
+
+/* Runtime API */
+
+#define SWIG_GetModule(clientdata)                      SWIG_Python_GetModule()
+#define SWIG_SetModule(clientdata, pointer)             SWIG_Python_SetModule(pointer)
+#define SWIG_NewClientData(obj)                         SwigPyClientData_New(obj)
+
+#define SWIG_SetErrorObj                                SWIG_Python_SetErrorObj                            
+#define SWIG_SetErrorMsg                               SWIG_Python_SetErrorMsg                            
+#define SWIG_ErrorType(code)                           SWIG_Python_ErrorType(code)                        
+#define SWIG_Error(code, msg)                          SWIG_Python_SetErrorMsg(SWIG_ErrorType(code), msg) 
+#define SWIG_fail                                      goto fail                                          
+
+
+/* Runtime API implementation */
+
+/* Error manipulation */
+
+SWIGINTERN void 
+SWIG_Python_SetErrorObj(PyObject *errtype, PyObject *obj) {
+  SWIG_PYTHON_THREAD_BEGIN_BLOCK; 
+  PyErr_SetObject(errtype, obj);
+  Py_DECREF(obj);
+  SWIG_PYTHON_THREAD_END_BLOCK;
+}
+
+SWIGINTERN void 
+SWIG_Python_SetErrorMsg(PyObject *errtype, const char *msg) {
+  SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+  PyErr_SetString(errtype, (char *) msg);
+  SWIG_PYTHON_THREAD_END_BLOCK;
+}
+
+#define SWIG_Python_Raise(obj, type, desc)  SWIG_Python_SetErrorObj(SWIG_Python_ExceptionType(desc), obj)
+
+/* Set a constant value */
+
+SWIGINTERN void
+SWIG_Python_SetConstant(PyObject *d, const char *name, PyObject *obj) {   
+  PyDict_SetItemString(d, (char*) name, obj);
+  Py_DECREF(obj);                            
+}
+
+/* Append a value to the result obj */
+
+SWIGINTERN PyObject*
+SWIG_Python_AppendOutput(PyObject* result, PyObject* obj) {
+#if !defined(SWIG_PYTHON_OUTPUT_TUPLE)
+  if (!result) {
+    result = obj;
+  } else if (result == Py_None) {
+    Py_DECREF(result);
+    result = obj;
+  } else {
+    if (!PyList_Check(result)) {
+      PyObject *o2 = result;
+      result = PyList_New(1);
+      PyList_SetItem(result, 0, o2);
+    }
+    PyList_Append(result,obj);
+    Py_DECREF(obj);
+  }
+  return result;
+#else
+  PyObject*   o2;
+  PyObject*   o3;
+  if (!result) {
+    result = obj;
+  } else if (result == Py_None) {
+    Py_DECREF(result);
+    result = obj;
+  } else {
+    if (!PyTuple_Check(result)) {
+      o2 = result;
+      result = PyTuple_New(1);
+      PyTuple_SET_ITEM(result, 0, o2);
+    }
+    o3 = PyTuple_New(1);
+    PyTuple_SET_ITEM(o3, 0, obj);
+    o2 = result;
+    result = PySequence_Concat(o2, o3);
+    Py_DECREF(o2);
+    Py_DECREF(o3);
+  }
+  return result;
+#endif
+}
+
+/* Unpack the argument tuple */
+
+SWIGINTERN int
+SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, PyObject **objs)
+{
+  if (!args) {
+    if (!min && !max) {
+      return 1;
+    } else {
+      PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got none", 
+                  name, (min == max ? "" : "at least "), (int)min);
+      return 0;
+    }
+  }  
+  if (!PyTuple_Check(args)) {
+    PyErr_SetString(PyExc_SystemError, "UnpackTuple() argument list is not a tuple");
+    return 0;
+  } else {
+    register Py_ssize_t l = PyTuple_GET_SIZE(args);
+    if (l < min) {
+      PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got %d", 
+                  name, (min == max ? "" : "at least "), (int)min, (int)l);
+      return 0;
+    } else if (l > max) {
+      PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got %d", 
+                  name, (min == max ? "" : "at most "), (int)max, (int)l);
+      return 0;
+    } else {
+      register int i;
+      for (i = 0; i < l; ++i) {
+       objs[i] = PyTuple_GET_ITEM(args, i);
+      }
+      for (; l < max; ++l) {
+       objs[l] = 0;
+      }
+      return i + 1;
+    }    
+  }
+}
+
+/* A functor is a function object with one single object argument */
+#if PY_VERSION_HEX >= 0x02020000
+#define SWIG_Python_CallFunctor(functor, obj)          PyObject_CallFunctionObjArgs(functor, obj, NULL);
+#else
+#define SWIG_Python_CallFunctor(functor, obj)          PyObject_CallFunction(functor, "O", obj);
+#endif
+
+/*
+  Helper for static pointer initialization for both C and C++ code, for example
+  static PyObject *SWIG_STATIC_POINTER(MyVar) = NewSomething(...);
+*/
+#ifdef __cplusplus
+#define SWIG_STATIC_POINTER(var)  var
+#else
+#define SWIG_STATIC_POINTER(var)  var = 0; if (!var) var
+#endif
+
+/* -----------------------------------------------------------------------------
+ * Pointer declarations
+ * ----------------------------------------------------------------------------- */
+
+/* Flags for new pointer objects */
+#define SWIG_POINTER_NOSHADOW       (SWIG_POINTER_OWN      << 1)
+#define SWIG_POINTER_NEW            (SWIG_POINTER_NOSHADOW | SWIG_POINTER_OWN)
+
+#define SWIG_POINTER_IMPLICIT_CONV  (SWIG_POINTER_DISOWN   << 1)
+
+#ifdef __cplusplus
+extern "C" {
+#if 0
+} /* cc-mode */
+#endif
+#endif
+
+/*  How to access Py_None */
+#if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
+#  ifndef SWIG_PYTHON_NO_BUILD_NONE
+#    ifndef SWIG_PYTHON_BUILD_NONE
+#      define SWIG_PYTHON_BUILD_NONE
+#    endif
+#  endif
+#endif
+
+#ifdef SWIG_PYTHON_BUILD_NONE
+#  ifdef Py_None
+#   undef Py_None
+#   define Py_None SWIG_Py_None()
+#  endif
+SWIGRUNTIMEINLINE PyObject * 
+_SWIG_Py_None(void)
+{
+  PyObject *none = Py_BuildValue((char*)"");
+  Py_DECREF(none);
+  return none;
+}
+SWIGRUNTIME PyObject * 
+SWIG_Py_None(void)
+{
+  static PyObject *SWIG_STATIC_POINTER(none) = _SWIG_Py_None();
+  return none;
+}
+#endif
+
+/* The python void return value */
+
+SWIGRUNTIMEINLINE PyObject * 
+SWIG_Py_Void(void)
+{
+  PyObject *none = Py_None;
+  Py_INCREF(none);
+  return none;
+}
+
+/* SwigPyClientData */
+
+typedef struct {
+  PyObject *klass;
+  PyObject *newraw;
+  PyObject *newargs;
+  PyObject *destroy;
+  int delargs;
+  int implicitconv;
+} SwigPyClientData;
+
+SWIGRUNTIMEINLINE int 
+SWIG_Python_CheckImplicit(swig_type_info *ty)
+{
+  SwigPyClientData *data = (SwigPyClientData *)ty->clientdata;
+  return data ? data->implicitconv : 0;
+}
+
+SWIGRUNTIMEINLINE PyObject *
+SWIG_Python_ExceptionType(swig_type_info *desc) {
+  SwigPyClientData *data = desc ? (SwigPyClientData *) desc->clientdata : 0;
+  PyObject *klass = data ? data->klass : 0;
+  return (klass ? klass : PyExc_RuntimeError);
+}
+
+
+SWIGRUNTIME SwigPyClientData * 
+SwigPyClientData_New(PyObject* obj)
+{
+  if (!obj) {
+    return 0;
+  } else {
+    SwigPyClientData *data = (SwigPyClientData *)malloc(sizeof(SwigPyClientData));
+    /* the klass element */
+    data->klass = obj;
+    Py_INCREF(data->klass);
+    /* the newraw method and newargs arguments used to create a new raw instance */
+    if (PyClass_Check(obj)) {
+      data->newraw = 0;
+      data->newargs = obj;
+      Py_INCREF(obj);
+    } else {
+#if (PY_VERSION_HEX < 0x02020000)
+      data->newraw = 0;
+#else
+      data->newraw = PyObject_GetAttrString(data->klass, (char *)"__new__");
+#endif
+      if (data->newraw) {
+       Py_INCREF(data->newraw);
+       data->newargs = PyTuple_New(1);
+       PyTuple_SetItem(data->newargs, 0, obj);
+      } else {
+       data->newargs = obj;
+      }
+      Py_INCREF(data->newargs);
+    }
+    /* the destroy method, aka as the C++ delete method */
+    data->destroy = PyObject_GetAttrString(data->klass, (char *)"__swig_destroy__");
+    if (PyErr_Occurred()) {
+      PyErr_Clear();
+      data->destroy = 0;
+    }
+    if (data->destroy) {
+      int flags;
+      Py_INCREF(data->destroy);
+      flags = PyCFunction_GET_FLAGS(data->destroy);
+#ifdef METH_O
+      data->delargs = !(flags & (METH_O));
+#else
+      data->delargs = 0;
+#endif
+    } else {
+      data->delargs = 0;
+    }
+    data->implicitconv = 0;
+    return data;
+  }
+}
+
+SWIGRUNTIME void 
+SwigPyClientData_Del(SwigPyClientData* data)
+{
+  Py_XDECREF(data->newraw);
+  Py_XDECREF(data->newargs);
+  Py_XDECREF(data->destroy);
+}
+
+/* =============== SwigPyObject =====================*/
+
+typedef struct {
+  PyObject_HEAD
+  void *ptr;
+  swig_type_info *ty;
+  int own;
+  PyObject *next;
+} SwigPyObject;
+
+SWIGRUNTIME PyObject *
+SwigPyObject_long(SwigPyObject *v)
+{
+  return PyLong_FromVoidPtr(v->ptr);
+}
+
+SWIGRUNTIME PyObject *
+SwigPyObject_format(const char* fmt, SwigPyObject *v)
+{
+  PyObject *res = NULL;
+  PyObject *args = PyTuple_New(1);
+  if (args) {
+    if (PyTuple_SetItem(args, 0, SwigPyObject_long(v)) == 0) {
+      PyObject *ofmt = SWIG_Python_str_FromChar(fmt);
+      if (ofmt) {
+#if PY_VERSION_HEX >= 0x03000000
+       res = PyUnicode_Format(ofmt,args);
+#else
+       res = PyString_Format(ofmt,args);
+#endif
+       Py_DECREF(ofmt);
+      }
+      Py_DECREF(args);
+    }
+  }
+  return res;
+}
+
+SWIGRUNTIME PyObject *
+SwigPyObject_oct(SwigPyObject *v)
+{
+  return SwigPyObject_format("%o",v);
+}
+
+SWIGRUNTIME PyObject *
+SwigPyObject_hex(SwigPyObject *v)
+{
+  return SwigPyObject_format("%x",v);
+}
+
+SWIGRUNTIME PyObject *
+#ifdef METH_NOARGS
+SwigPyObject_repr(SwigPyObject *v)
+#else
+SwigPyObject_repr(SwigPyObject *v, PyObject *args)
+#endif
+{
+  const char *name = SWIG_TypePrettyName(v->ty);
+  PyObject *hex = SwigPyObject_hex(v);    
+  PyObject *repr = SWIG_Python_str_FromFormat("<Swig Object of type '%s' at %p>", name, hex);
+  Py_DECREF(hex);
+  if (v->next) {
+#ifdef METH_NOARGS
+    PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next);
+#else
+    PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next, args);
+#endif
+#if PY_VERSION_HEX >= 0x03000000
+    PyObject *joined = PyUnicode_Concat(repr, nrep);
+    Py_DecRef(repr);
+    Py_DecRef(nrep);
+    repr = joined;
+#else
+    PyString_ConcatAndDel(&repr,nrep);
+#endif
+  }
+  return repr;  
+}
+
+SWIGRUNTIME int
+SwigPyObject_print(SwigPyObject *v, FILE *fp, int SWIGUNUSEDPARM(flags))
+{
+#ifdef METH_NOARGS
+  PyObject *repr = SwigPyObject_repr(v);
+#else
+  PyObject *repr = SwigPyObject_repr(v, NULL);
+#endif
+  if (repr) {
+    fputs(SWIG_Python_str_AsChar(repr), fp);
+    Py_DECREF(repr);
+    return 0; 
+  } else {
+    return 1; 
+  }
+}
+
+SWIGRUNTIME PyObject *
+SwigPyObject_str(SwigPyObject *v)
+{
+  char result[SWIG_BUFFER_SIZE];
+  return SWIG_PackVoidPtr(result, v->ptr, v->ty->name, sizeof(result)) ?
+    SWIG_Python_str_FromChar(result) : 0;
+}
+
+SWIGRUNTIME int
+SwigPyObject_compare(SwigPyObject *v, SwigPyObject *w)
+{
+  void *i = v->ptr;
+  void *j = w->ptr;
+  return (i < j) ? -1 : ((i > j) ? 1 : 0);
+}
+
+/* Added for Python 3.x, whould it also useful for Python 2.x? */
+SWIGRUNTIME PyObject*
+SwigPyObject_richcompare(SwigPyObject *v, SwigPyObject *w, int op)
+{
+  PyObject* res;
+  if( op != Py_EQ && op != Py_NE ) {
+    Py_INCREF(Py_NotImplemented);
+    return Py_NotImplemented;
+  }
+  if( (SwigPyObject_compare(v, w)==0) == (op == Py_EQ) )
+    res = Py_True;
+  else
+    res = Py_False;
+  Py_INCREF(res);
+  return res;  
+}
+
+
+SWIGRUNTIME PyTypeObject* _PySwigObject_type(void);
+
+SWIGRUNTIME PyTypeObject*
+SwigPyObject_type(void) {
+  static PyTypeObject *SWIG_STATIC_POINTER(type) = _PySwigObject_type();
+  return type;
+}
+
+SWIGRUNTIMEINLINE int
+SwigPyObject_Check(PyObject *op) {
+  return (Py_TYPE(op) == SwigPyObject_type())
+    || (strcmp(Py_TYPE(op)->tp_name,"SwigPyObject") == 0);
+}
+
+SWIGRUNTIME PyObject *
+SwigPyObject_New(void *ptr, swig_type_info *ty, int own);
+
+SWIGRUNTIME void
+SwigPyObject_dealloc(PyObject *v)
+{
+  SwigPyObject *sobj = (SwigPyObject *) v;
+  PyObject *next = sobj->next;
+  if (sobj->own == SWIG_POINTER_OWN) {
+    swig_type_info *ty = sobj->ty;
+    SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0;
+    PyObject *destroy = data ? data->destroy : 0;
+    if (destroy) {
+      /* destroy is always a VARARGS method */
+      PyObject *res;
+      if (data->delargs) {
+       /* we need to create a temporal object to carry the destroy operation */
+       PyObject *tmp = SwigPyObject_New(sobj->ptr, ty, 0);
+       res = SWIG_Python_CallFunctor(destroy, tmp);
+       Py_DECREF(tmp);
+      } else {
+       PyCFunction meth = PyCFunction_GET_FUNCTION(destroy);
+       PyObject *mself = PyCFunction_GET_SELF(destroy);
+       res = ((*meth)(mself, v));
+      }
+      Py_XDECREF(res);
+    } 
+#if !defined(SWIG_PYTHON_SILENT_MEMLEAK)
+    else {
+      const char *name = SWIG_TypePrettyName(ty);
+      printf("swig/python detected a memory leak of type '%s', no destructor found.\n", (name ? name : "unknown"));
+    }
+#endif
+  } 
+  Py_XDECREF(next);
+  PyObject_DEL(v);
+}
+
+SWIGRUNTIME PyObject* 
+SwigPyObject_append(PyObject* v, PyObject* next)
+{
+  SwigPyObject *sobj = (SwigPyObject *) v;
+#ifndef METH_O
+  PyObject *tmp = 0;
+  if (!PyArg_ParseTuple(next,(char *)"O:append", &tmp)) return NULL;
+  next = tmp;
+#endif
+  if (!SwigPyObject_Check(next)) {
+    return NULL;
+  }
+  sobj->next = next;
+  Py_INCREF(next);
+  return SWIG_Py_Void();
+}
+
+SWIGRUNTIME PyObject* 
+#ifdef METH_NOARGS
+SwigPyObject_next(PyObject* v)
+#else
+SwigPyObject_next(PyObject* v, PyObject *SWIGUNUSEDPARM(args))
+#endif
+{
+  SwigPyObject *sobj = (SwigPyObject *) v;
+  if (sobj->next) {    
+    Py_INCREF(sobj->next);
+    return sobj->next;
+  } else {
+    return SWIG_Py_Void();
+  }
+}
+
+SWIGINTERN PyObject*
+#ifdef METH_NOARGS
+SwigPyObject_disown(PyObject *v)
+#else
+SwigPyObject_disown(PyObject* v, PyObject *SWIGUNUSEDPARM(args))
+#endif
+{
+  SwigPyObject *sobj = (SwigPyObject *)v;
+  sobj->own = 0;
+  return SWIG_Py_Void();
+}
+
+SWIGINTERN PyObject*
+#ifdef METH_NOARGS
+SwigPyObject_acquire(PyObject *v)
+#else
+SwigPyObject_acquire(PyObject* v, PyObject *SWIGUNUSEDPARM(args))
+#endif
+{
+  SwigPyObject *sobj = (SwigPyObject *)v;
+  sobj->own = SWIG_POINTER_OWN;
+  return SWIG_Py_Void();
+}
+
+SWIGINTERN PyObject*
+SwigPyObject_own(PyObject *v, PyObject *args)
+{
+  PyObject *val = 0;
+#if (PY_VERSION_HEX < 0x02020000)
+  if (!PyArg_ParseTuple(args,(char *)"|O:own",&val))
+#else
+  if (!PyArg_UnpackTuple(args, (char *)"own", 0, 1, &val)) 
+#endif
+    {
+      return NULL;
+    } 
+  else
+    {
+      SwigPyObject *sobj = (SwigPyObject *)v;
+      PyObject *obj = PyBool_FromLong(sobj->own);
+      if (val) {
+#ifdef METH_NOARGS
+       if (PyObject_IsTrue(val)) {
+         SwigPyObject_acquire(v);
+       } else {
+         SwigPyObject_disown(v);
+       }
+#else
+       if (PyObject_IsTrue(val)) {
+         SwigPyObject_acquire(v,args);
+       } else {
+         SwigPyObject_disown(v,args);
+       }
+#endif
+      } 
+      return obj;
+    }
+}
+
+#ifdef METH_O
+static PyMethodDef
+swigobject_methods[] = {
+  {(char *)"disown",  (PyCFunction)SwigPyObject_disown,  METH_NOARGS,  (char *)"releases ownership of the pointer"},
+  {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_NOARGS,  (char *)"aquires ownership of the pointer"},
+  {(char *)"own",     (PyCFunction)SwigPyObject_own,     METH_VARARGS, (char *)"returns/sets ownership of the pointer"},
+  {(char *)"append",  (PyCFunction)SwigPyObject_append,  METH_O,       (char *)"appends another 'this' object"},
+  {(char *)"next",    (PyCFunction)SwigPyObject_next,    METH_NOARGS,  (char *)"returns the next 'this' object"},
+  {(char *)"__repr__",(PyCFunction)SwigPyObject_repr,    METH_NOARGS,  (char *)"returns object representation"},
+  {0, 0, 0, 0}  
+};
+#else
+static PyMethodDef
+swigobject_methods[] = {
+  {(char *)"disown",  (PyCFunction)SwigPyObject_disown,  METH_VARARGS,  (char *)"releases ownership of the pointer"},
+  {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_VARARGS,  (char *)"aquires ownership of the pointer"},
+  {(char *)"own",     (PyCFunction)SwigPyObject_own,     METH_VARARGS,  (char *)"returns/sets ownership of the pointer"},
+  {(char *)"append",  (PyCFunction)SwigPyObject_append,  METH_VARARGS,  (char *)"appends another 'this' object"},
+  {(char *)"next",    (PyCFunction)SwigPyObject_next,    METH_VARARGS,  (char *)"returns the next 'this' object"},
+  {(char *)"__repr__",(PyCFunction)SwigPyObject_repr,   METH_VARARGS,  (char *)"returns object representation"},
+  {0, 0, 0, 0}  
+};
+#endif
+
+#if PY_VERSION_HEX < 0x02020000
+SWIGINTERN PyObject *
+SwigPyObject_getattr(SwigPyObject *sobj,char *name)
+{
+  return Py_FindMethod(swigobject_methods, (PyObject *)sobj, name);
+}
+#endif
+
+SWIGRUNTIME PyTypeObject*
+_PySwigObject_type(void) {
+  static char swigobject_doc[] = "Swig object carries a C/C++ instance pointer";
+  
+  static PyNumberMethods SwigPyObject_as_number = {
+    (binaryfunc)0, /*nb_add*/
+    (binaryfunc)0, /*nb_subtract*/
+    (binaryfunc)0, /*nb_multiply*/
+    /* nb_divide removed in Python 3 */
+#if PY_VERSION_HEX < 0x03000000
+    (binaryfunc)0, /*nb_divide*/
+#endif
+    (binaryfunc)0, /*nb_remainder*/
+    (binaryfunc)0, /*nb_divmod*/
+    (ternaryfunc)0,/*nb_power*/
+    (unaryfunc)0,  /*nb_negative*/
+    (unaryfunc)0,  /*nb_positive*/
+    (unaryfunc)0,  /*nb_absolute*/
+    (inquiry)0,    /*nb_nonzero*/
+    0,            /*nb_invert*/
+    0,            /*nb_lshift*/
+    0,            /*nb_rshift*/
+    0,            /*nb_and*/
+    0,            /*nb_xor*/
+    0,            /*nb_or*/
+#if PY_VERSION_HEX < 0x03000000
+    0,   /*nb_coerce*/
+#endif
+    (unaryfunc)SwigPyObject_long, /*nb_int*/
+    (unaryfunc)SwigPyObject_long, /*nb_long*/
+    (unaryfunc)0,                 /*nb_float*/
+#if PY_VERSION_HEX < 0x03000000
+    (unaryfunc)SwigPyObject_oct,  /*nb_oct*/
+    (unaryfunc)SwigPyObject_hex,  /*nb_hex*/
+#endif
+#if PY_VERSION_HEX >= 0x03000000 /* 3.0 */
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index, nb_inplace_divide removed */
+#elif PY_VERSION_HEX >= 0x02050000 /* 2.5.0 */
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index */
+#elif PY_VERSION_HEX >= 0x02020000 /* 2.2.0 */
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_true_divide */
+#elif PY_VERSION_HEX >= 0x02000000 /* 2.0.0 */
+    0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_or */
+#endif
+  };
+
+  static PyTypeObject swigpyobject_type;  
+  static int type_init = 0;
+  if (!type_init) {
+    const PyTypeObject tmp
+      = {
+       /* PyOjbect header changed in Python 3 */
+#if PY_VERSION_HEX >= 0x03000000
+       PyVarObject_HEAD_INIT(&PyType_Type, 0)
+#else    
+       PyObject_HEAD_INIT(NULL)
+       0,                                  /* ob_size */
+#endif
+       (char *)"SwigPyObject",             /* tp_name */
+       sizeof(SwigPyObject),               /* tp_basicsize */
+       0,                                  /* tp_itemsize */
+       (destructor)SwigPyObject_dealloc,   /* tp_dealloc */
+       (printfunc)SwigPyObject_print,      /* tp_print */
+#if PY_VERSION_HEX < 0x02020000
+       (getattrfunc)SwigPyObject_getattr,  /* tp_getattr */ 
+#else
+       (getattrfunc)0,                     /* tp_getattr */ 
+#endif
+       (setattrfunc)0,                     /* tp_setattr */ 
+       (cmpfunc)SwigPyObject_compare,      /* tp_compare */ 
+       (reprfunc)SwigPyObject_repr,        /* tp_repr */    
+       &SwigPyObject_as_number,            /* tp_as_number */
+       0,                                  /* tp_as_sequence */
+       0,                                  /* tp_as_mapping */
+       (hashfunc)0,                        /* tp_hash */
+       (ternaryfunc)0,                     /* tp_call */
+       (reprfunc)SwigPyObject_str,         /* tp_str */
+       PyObject_GenericGetAttr,            /* tp_getattro */
+       0,                                  /* tp_setattro */
+       0,                                  /* tp_as_buffer */
+       Py_TPFLAGS_DEFAULT,                 /* tp_flags */
+       swigobject_doc,                     /* tp_doc */        
+       0,                                  /* tp_traverse */
+       0,                                  /* tp_clear */
+       (richcmpfunc)SwigPyObject_richcompare,           /* tp_richcompare */
+       0,                                  /* tp_weaklistoffset */
+#if PY_VERSION_HEX >= 0x02020000
+       0,                                  /* tp_iter */
+       0,                                  /* tp_iternext */
+       swigobject_methods,                 /* tp_methods */ 
+       0,                                  /* tp_members */
+       0,                                  /* tp_getset */             
+       0,                                  /* tp_base */               
+       0,                                  /* tp_dict */               
+       0,                                  /* tp_descr_get */          
+       0,                                  /* tp_descr_set */          
+       0,                                  /* tp_dictoffset */         
+       0,                                  /* tp_init */               
+       0,                                  /* tp_alloc */              
+       0,                                  /* tp_new */                
+       0,                                  /* tp_free */          
+       0,                                  /* tp_is_gc */  
+       0,                                  /* tp_bases */   
+       0,                                  /* tp_mro */
+       0,                                  /* tp_cache */   
+       0,                                  /* tp_subclasses */
+       0,                                  /* tp_weaklist */
+#endif
+#if PY_VERSION_HEX >= 0x02030000
+       0,                                  /* tp_del */
+#endif
+#ifdef COUNT_ALLOCS
+       0,0,0,0                             /* tp_alloc -> tp_next */
+#endif
+      };
+    swigpyobject_type = tmp;
+    /* for Python 3 we already assigned the ob_type in PyVarObject_HEAD_INIT() */
+#if PY_VERSION_HEX < 0x03000000
+    swigpyobject_type.ob_type = &PyType_Type;
+#endif
+    type_init = 1;
+  }
+  return &swigpyobject_type;
+}
+
+SWIGRUNTIME PyObject *
+SwigPyObject_New(void *ptr, swig_type_info *ty, int own)
+{
+  SwigPyObject *sobj = PyObject_NEW(SwigPyObject, SwigPyObject_type());
+  if (sobj) {
+    sobj->ptr  = ptr;
+    sobj->ty   = ty;
+    sobj->own  = own;
+    sobj->next = 0;
+  }
+  return (PyObject *)sobj;
+}
+
+/* -----------------------------------------------------------------------------
+ * Implements a simple Swig Packed type, and use it instead of string
+ * ----------------------------------------------------------------------------- */
+
+typedef struct {
+  PyObject_HEAD
+  void *pack;
+  swig_type_info *ty;
+  size_t size;
+} SwigPyPacked;
+
+SWIGRUNTIME int
+SwigPyPacked_print(SwigPyPacked *v, FILE *fp, int SWIGUNUSEDPARM(flags))
+{
+  char result[SWIG_BUFFER_SIZE];
+  fputs("<Swig Packed ", fp); 
+  if (SWIG_PackDataName(result, v->pack, v->size, 0, sizeof(result))) {
+    fputs("at ", fp); 
+    fputs(result, fp); 
+  }
+  fputs(v->ty->name,fp); 
+  fputs(">", fp);
+  return 0; 
+}
+  
+SWIGRUNTIME PyObject *
+SwigPyPacked_repr(SwigPyPacked *v)
+{
+  char result[SWIG_BUFFER_SIZE];
+  if (SWIG_PackDataName(result, v->pack, v->size, 0, sizeof(result))) {
+    return SWIG_Python_str_FromFormat("<Swig Packed at %s%s>", result, v->ty->name);
+  } else {
+    return SWIG_Python_str_FromFormat("<Swig Packed %s>", v->ty->name);
+  }  
+}
+
+SWIGRUNTIME PyObject *
+SwigPyPacked_str(SwigPyPacked *v)
+{
+  char result[SWIG_BUFFER_SIZE];
+  if (SWIG_PackDataName(result, v->pack, v->size, 0, sizeof(result))){
+    return SWIG_Python_str_FromFormat("%s%s", result, v->ty->name);
+  } else {
+    return SWIG_Python_str_FromChar(v->ty->name);
+  }  
+}
+
+SWIGRUNTIME int
+SwigPyPacked_compare(SwigPyPacked *v, SwigPyPacked *w)
+{
+  size_t i = v->size;
+  size_t j = w->size;
+  int s = (i < j) ? -1 : ((i > j) ? 1 : 0);
+  return s ? s : strncmp((char *)v->pack, (char *)w->pack, 2*v->size);
+}
+
+SWIGRUNTIME PyTypeObject* _PySwigPacked_type(void);
+
+SWIGRUNTIME PyTypeObject*
+SwigPyPacked_type(void) {
+  static PyTypeObject *SWIG_STATIC_POINTER(type) = _PySwigPacked_type();
+  return type;
+}
+
+SWIGRUNTIMEINLINE int
+SwigPyPacked_Check(PyObject *op) {
+  return ((op)->ob_type == _PySwigPacked_type()) 
+    || (strcmp((op)->ob_type->tp_name,"SwigPyPacked") == 0);
+}
+
+SWIGRUNTIME void
+SwigPyPacked_dealloc(PyObject *v)
+{
+  if (SwigPyPacked_Check(v)) {
+    SwigPyPacked *sobj = (SwigPyPacked *) v;
+    free(sobj->pack);
+  }
+  PyObject_DEL(v);
+}
+
+SWIGRUNTIME PyTypeObject*
+_PySwigPacked_type(void) {
+  static char swigpacked_doc[] = "Swig object carries a C/C++ instance pointer";
+  static PyTypeObject swigpypacked_type;
+  static int type_init = 0;  
+  if (!type_init) {
+    const PyTypeObject tmp
+      = {
+    /* PyObject header changed in Python 3 */
+#if PY_VERSION_HEX>=0x03000000
+    PyVarObject_HEAD_INIT(&PyType_Type, 0)
+#else
+       PyObject_HEAD_INIT(NULL)
+    0,                             /* ob_size */       
+#endif
+       (char *)"SwigPyPacked",             /* tp_name */       
+       sizeof(SwigPyPacked),               /* tp_basicsize */  
+       0,                                  /* tp_itemsize */   
+       (destructor)SwigPyPacked_dealloc,   /* tp_dealloc */    
+       (printfunc)SwigPyPacked_print,      /* tp_print */      
+       (getattrfunc)0,                     /* tp_getattr */    
+       (setattrfunc)0,                     /* tp_setattr */    
+       (cmpfunc)SwigPyPacked_compare,      /* tp_compare */    
+       (reprfunc)SwigPyPacked_repr,        /* tp_repr */       
+       0,                                  /* tp_as_number */  
+       0,                                  /* tp_as_sequence */
+       0,                                  /* tp_as_mapping */ 
+       (hashfunc)0,                        /* tp_hash */       
+       (ternaryfunc)0,                     /* tp_call */       
+       (reprfunc)SwigPyPacked_str,         /* tp_str */        
+       PyObject_GenericGetAttr,            /* tp_getattro */
+       0,                                  /* tp_setattro */
+       0,                                  /* tp_as_buffer */
+       Py_TPFLAGS_DEFAULT,                 /* tp_flags */
+       swigpacked_doc,                     /* tp_doc */
+       0,                                  /* tp_traverse */
+       0,                                  /* tp_clear */
+       0,                                  /* tp_richcompare */
+       0,                                  /* tp_weaklistoffset */
+#if PY_VERSION_HEX >= 0x02020000
+       0,                                  /* tp_iter */
+       0,                                  /* tp_iternext */
+       0,                                  /* tp_methods */ 
+       0,                                  /* tp_members */
+       0,                                  /* tp_getset */             
+       0,                                  /* tp_base */               
+       0,                                  /* tp_dict */               
+       0,                                  /* tp_descr_get */          
+       0,                                  /* tp_descr_set */          
+       0,                                  /* tp_dictoffset */         
+       0,                                  /* tp_init */               
+       0,                                  /* tp_alloc */              
+       0,                                  /* tp_new */                
+       0,                                  /* tp_free */          
+        0,                                  /* tp_is_gc */  
+       0,                                  /* tp_bases */   
+       0,                                  /* tp_mro */
+       0,                                  /* tp_cache */   
+       0,                                  /* tp_subclasses */
+       0,                                  /* tp_weaklist */
+#endif
+#if PY_VERSION_HEX >= 0x02030000
+       0,                                  /* tp_del */
+#endif
+#ifdef COUNT_ALLOCS
+       0,0,0,0                             /* tp_alloc -> tp_next */
+#endif
+      };
+    swigpypacked_type = tmp;
+    /* for Python 3 the ob_type already assigned in PyVarObject_HEAD_INIT() */
+#if PY_VERSION_HEX < 0x03000000
+    swigpypacked_type.ob_type = &PyType_Type;
+#endif
+    type_init = 1;
+  }
+  return &swigpypacked_type;
+}
+
+SWIGRUNTIME PyObject *
+SwigPyPacked_New(void *ptr, size_t size, swig_type_info *ty)
+{
+  SwigPyPacked *sobj = PyObject_NEW(SwigPyPacked, SwigPyPacked_type());
+  if (sobj) {
+    void *pack = malloc(size);
+    if (pack) {
+      memcpy(pack, ptr, size);
+      sobj->pack = pack;
+      sobj->ty   = ty;
+      sobj->size = size;
+    } else {
+      PyObject_DEL((PyObject *) sobj);
+      sobj = 0;
+    }
+  }
+  return (PyObject *) sobj;
+}
+
+SWIGRUNTIME swig_type_info *
+SwigPyPacked_UnpackData(PyObject *obj, void *ptr, size_t size)
+{
+  if (SwigPyPacked_Check(obj)) {
+    SwigPyPacked *sobj = (SwigPyPacked *)obj;
+    if (sobj->size != size) return 0;
+    memcpy(ptr, sobj->pack, size);
+    return sobj->ty;
+  } else {
+    return 0;
+  }
+}
+
+/* -----------------------------------------------------------------------------
+ * pointers/data manipulation
+ * ----------------------------------------------------------------------------- */
+
+SWIGRUNTIMEINLINE PyObject *
+_SWIG_This(void)
+{
+    return SWIG_Python_str_FromChar("this");
+}
+
+SWIGRUNTIME PyObject *
+SWIG_This(void)
+{
+  static PyObject *SWIG_STATIC_POINTER(swig_this) = _SWIG_This();
+  return swig_this;
+}
+
+/* #define SWIG_PYTHON_SLOW_GETSET_THIS */
+
+/* TODO: I don't know how to implement the fast getset in Python 3 right now */
+#if PY_VERSION_HEX>=0x03000000
+#define SWIG_PYTHON_SLOW_GETSET_THIS 
+#endif
+
+SWIGRUNTIME SwigPyObject *
+SWIG_Python_GetSwigThis(PyObject *pyobj) 
+{
+  if (SwigPyObject_Check(pyobj)) {
+    return (SwigPyObject *) pyobj;
+  } else {
+    PyObject *obj = 0;
+#if (!defined(SWIG_PYTHON_SLOW_GETSET_THIS) && (PY_VERSION_HEX >= 0x02030000))
+    if (PyInstance_Check(pyobj)) {
+      obj = _PyInstance_Lookup(pyobj, SWIG_This());      
+    } else {
+      PyObject **dictptr = _PyObject_GetDictPtr(pyobj);
+      if (dictptr != NULL) {
+       PyObject *dict = *dictptr;
+       obj = dict ? PyDict_GetItem(dict, SWIG_This()) : 0;
+      } else {
+#ifdef PyWeakref_CheckProxy
+       if (PyWeakref_CheckProxy(pyobj)) {
+         PyObject *wobj = PyWeakref_GET_OBJECT(pyobj);
+         return wobj ? SWIG_Python_GetSwigThis(wobj) : 0;
+       }
+#endif
+       obj = PyObject_GetAttr(pyobj,SWIG_This());
+       if (obj) {
+         Py_DECREF(obj);
+       } else {
+         if (PyErr_Occurred()) PyErr_Clear();
+         return 0;
+       }
+      }
+    }
+#else
+    obj = PyObject_GetAttr(pyobj,SWIG_This());
+    if (obj) {
+      Py_DECREF(obj);
+    } else {
+      if (PyErr_Occurred()) PyErr_Clear();
+      return 0;
+    }
+#endif
+    if (obj && !SwigPyObject_Check(obj)) {
+      /* a PyObject is called 'this', try to get the 'real this'
+        SwigPyObject from it */ 
+      return SWIG_Python_GetSwigThis(obj);
+    }
+    return (SwigPyObject *)obj;
+  }
+}
+
+/* Acquire a pointer value */
+
+SWIGRUNTIME int
+SWIG_Python_AcquirePtr(PyObject *obj, int own) {
+  if (own == SWIG_POINTER_OWN) {
+    SwigPyObject *sobj = SWIG_Python_GetSwigThis(obj);
+    if (sobj) {
+      int oldown = sobj->own;
+      sobj->own = own;
+      return oldown;
+    }
+  }
+  return 0;
+}
+
+/* Convert a pointer value */
+
+SWIGRUNTIME int
+SWIG_Python_ConvertPtrAndOwn(PyObject *obj, void **ptr, swig_type_info *ty, int flags, int *own) {
+  if (!obj) return SWIG_ERROR;
+  if (obj == Py_None) {
+    if (ptr) *ptr = 0;
+    return SWIG_OK;
+  } else {
+    SwigPyObject *sobj = SWIG_Python_GetSwigThis(obj);
+    if (own)
+      *own = 0;
+    while (sobj) {
+      void *vptr = sobj->ptr;
+      if (ty) {
+       swig_type_info *to = sobj->ty;
+       if (to == ty) {
+         /* no type cast needed */
+         if (ptr) *ptr = vptr;
+         break;
+       } else {
+         swig_cast_info *tc = SWIG_TypeCheck(to->name,ty);
+         if (!tc) {
+           sobj = (SwigPyObject *)sobj->next;
+         } else {
+           if (ptr) {
+              int newmemory = 0;
+              *ptr = SWIG_TypeCast(tc,vptr,&newmemory);
+              if (newmemory == SWIG_CAST_NEW_MEMORY) {
+                assert(own);
+                if (own)
+                  *own = *own | SWIG_CAST_NEW_MEMORY;
+              }
+            }
+           break;
+         }
+       }
+      } else {
+       if (ptr) *ptr = vptr;
+       break;
+      }
+    }
+    if (sobj) {
+      if (own)
+        *own = *own | sobj->own;
+      if (flags & SWIG_POINTER_DISOWN) {
+       sobj->own = 0;
+      }
+      return SWIG_OK;
+    } else {
+      int res = SWIG_ERROR;
+      if (flags & SWIG_POINTER_IMPLICIT_CONV) {
+       SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0;
+       if (data && !data->implicitconv) {
+         PyObject *klass = data->klass;
+         if (klass) {
+           PyObject *impconv;
+           data->implicitconv = 1; /* avoid recursion and call 'explicit' constructors*/
+           impconv = SWIG_Python_CallFunctor(klass, obj);
+           data->implicitconv = 0;
+           if (PyErr_Occurred()) {
+             PyErr_Clear();
+             impconv = 0;
+           }
+           if (impconv) {
+             SwigPyObject *iobj = SWIG_Python_GetSwigThis(impconv);
+             if (iobj) {
+               void *vptr;
+               res = SWIG_Python_ConvertPtrAndOwn((PyObject*)iobj, &vptr, ty, 0, 0);
+               if (SWIG_IsOK(res)) {
+                 if (ptr) {
+                   *ptr = vptr;
+                   /* transfer the ownership to 'ptr' */
+                   iobj->own = 0;
+                   res = SWIG_AddCast(res);
+                   res = SWIG_AddNewMask(res);
+                 } else {
+                   res = SWIG_AddCast(res);                
+                 }
+               }
+             }
+             Py_DECREF(impconv);
+           }
+         }
+       }
+      }
+      return res;
+    }
+  }
+}
+
+/* Convert a function ptr value */
+
+SWIGRUNTIME int
+SWIG_Python_ConvertFunctionPtr(PyObject *obj, void **ptr, swig_type_info *ty) {
+  if (!PyCFunction_Check(obj)) {
+    return SWIG_ConvertPtr(obj, ptr, ty, 0);
+  } else {
+    void *vptr = 0;
+    
+    /* here we get the method pointer for callbacks */
+    const char *doc = (((PyCFunctionObject *)obj) -> m_ml -> ml_doc);
+    const char *desc = doc ? strstr(doc, "swig_ptr: ") : 0;
+    if (desc) {
+      desc = ty ? SWIG_UnpackVoidPtr(desc + 10, &vptr, ty->name) : 0;
+      if (!desc) return SWIG_ERROR;
+    }
+    if (ty) {
+      swig_cast_info *tc = SWIG_TypeCheck(desc,ty);
+      if (tc) {
+        int newmemory = 0;
+        *ptr = SWIG_TypeCast(tc,vptr,&newmemory);
+        assert(!newmemory); /* newmemory handling not yet implemented */
+      } else {
+        return SWIG_ERROR;
+      }
+    } else {
+      *ptr = vptr;
+    }
+    return SWIG_OK;
+  }
+}
+
+/* Convert a packed value value */
+
+SWIGRUNTIME int
+SWIG_Python_ConvertPacked(PyObject *obj, void *ptr, size_t sz, swig_type_info *ty) {
+  swig_type_info *to = SwigPyPacked_UnpackData(obj, ptr, sz);
+  if (!to) return SWIG_ERROR;
+  if (ty) {
+    if (to != ty) {
+      /* check type cast? */
+      swig_cast_info *tc = SWIG_TypeCheck(to->name,ty);
+      if (!tc) return SWIG_ERROR;
+    }
+  }
+  return SWIG_OK;
+}  
+
+/* -----------------------------------------------------------------------------
+ * Create a new pointer object
+ * ----------------------------------------------------------------------------- */
+
+/*
+  Create a new instance object, whitout calling __init__, and set the
+  'this' attribute.
+*/
+
+SWIGRUNTIME PyObject* 
+SWIG_Python_NewShadowInstance(SwigPyClientData *data, PyObject *swig_this)
+{
+#if (PY_VERSION_HEX >= 0x02020000)
+  PyObject *inst = 0;
+  PyObject *newraw = data->newraw;
+  if (newraw) {
+    inst = PyObject_Call(newraw, data->newargs, NULL);
+    if (inst) {
+#if !defined(SWIG_PYTHON_SLOW_GETSET_THIS)
+      PyObject **dictptr = _PyObject_GetDictPtr(inst);
+      if (dictptr != NULL) {
+       PyObject *dict = *dictptr;
+       if (dict == NULL) {
+         dict = PyDict_New();
+         *dictptr = dict;
+         PyDict_SetItem(dict, SWIG_This(), swig_this);
+       }
+      }
+#else
+      PyObject *key = SWIG_This();
+      PyObject_SetAttr(inst, key, swig_this);
+#endif
+    }
+  } else {
+#if PY_VERSION_HEX >= 0x03000000
+    inst = PyBaseObject_Type.tp_new((PyTypeObject*) data->newargs, Py_None, Py_None);
+    Py_INCREF(data->newargs);
+    PyObject_SetAttr(inst, SWIG_This(), swig_this);
+    Py_TYPE(inst)->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;
+#else
+    PyObject *dict = PyDict_New();
+    PyDict_SetItem(dict, SWIG_This(), swig_this);
+    inst = PyInstance_NewRaw(data->newargs, dict);
+    Py_DECREF(dict);
+#endif
+  }
+  return inst;
+#else
+#if (PY_VERSION_HEX >= 0x02010000)
+  PyObject *inst;
+  PyObject *dict = PyDict_New();
+  PyDict_SetItem(dict, SWIG_This(), swig_this);
+  inst = PyInstance_NewRaw(data->newargs, dict);
+  Py_DECREF(dict);
+  return (PyObject *) inst;
+#else
+  PyInstanceObject *inst = PyObject_NEW(PyInstanceObject, &PyInstance_Type);
+  if (inst == NULL) {
+    return NULL;
+  }
+  inst->in_class = (PyClassObject *)data->newargs;
+  Py_INCREF(inst->in_class);
+  inst->in_dict = PyDict_New();
+  if (inst->in_dict == NULL) {
+    Py_DECREF(inst);
+    return NULL;
+  }
+#ifdef Py_TPFLAGS_HAVE_WEAKREFS
+  inst->in_weakreflist = NULL;
+#endif
+#ifdef Py_TPFLAGS_GC
+  PyObject_GC_Init(inst);
+#endif
+  PyDict_SetItem(inst->in_dict, SWIG_This(), swig_this);
+  return (PyObject *) inst;
+#endif
+#endif
+}
+
+SWIGRUNTIME void
+SWIG_Python_SetSwigThis(PyObject *inst, PyObject *swig_this)
+{
+ PyObject *dict;
+#if (PY_VERSION_HEX >= 0x02020000) && !defined(SWIG_PYTHON_SLOW_GETSET_THIS)
+ PyObject **dictptr = _PyObject_GetDictPtr(inst);
+ if (dictptr != NULL) {
+   dict = *dictptr;
+   if (dict == NULL) {
+     dict = PyDict_New();
+     *dictptr = dict;
+   }
+   PyDict_SetItem(dict, SWIG_This(), swig_this);
+   return;
+ }
+#endif
+ dict = PyObject_GetAttrString(inst, (char*)"__dict__");
+ PyDict_SetItem(dict, SWIG_This(), swig_this);
+ Py_DECREF(dict);
+} 
+
+
+SWIGINTERN PyObject *
+SWIG_Python_InitShadowInstance(PyObject *args) {
+  PyObject *obj[2];
+  if (!SWIG_Python_UnpackTuple(args,(char*)"swiginit", 2, 2, obj)) {
+    return NULL;
+  } else {
+    SwigPyObject *sthis = SWIG_Python_GetSwigThis(obj[0]);
+    if (sthis) {
+      SwigPyObject_append((PyObject*) sthis, obj[1]);
+    } else {
+      SWIG_Python_SetSwigThis(obj[0], obj[1]);
+    }
+    return SWIG_Py_Void();
+  }
+}
+
+/* Create a new pointer object */
+
+SWIGRUNTIME PyObject *
+SWIG_Python_NewPointerObj(void *ptr, swig_type_info *type, int flags) {
+  if (!ptr) {
+    return SWIG_Py_Void();
+  } else {
+    int own = (flags & SWIG_POINTER_OWN) ? SWIG_POINTER_OWN : 0;
+    PyObject *robj = SwigPyObject_New(ptr, type, own);
+    SwigPyClientData *clientdata = type ? (SwigPyClientData *)(type->clientdata) : 0;
+    if (clientdata && !(flags & SWIG_POINTER_NOSHADOW)) {
+      PyObject *inst = SWIG_Python_NewShadowInstance(clientdata, robj);
+      if (inst) {
+       Py_DECREF(robj);
+       robj = inst;
+      }
+    }
+    return robj;
+  }
+}
+
+/* Create a new packed object */
+
+SWIGRUNTIMEINLINE PyObject *
+SWIG_Python_NewPackedObj(void *ptr, size_t sz, swig_type_info *type) {
+  return ptr ? SwigPyPacked_New((void *) ptr, sz, type) : SWIG_Py_Void();
+}
+
+/* -----------------------------------------------------------------------------*
+ *  Get type list 
+ * -----------------------------------------------------------------------------*/
+
+#ifdef SWIG_LINK_RUNTIME
+void *SWIG_ReturnGlobalTypeList(void *);
+#endif
+
+SWIGRUNTIME swig_module_info *
+SWIG_Python_GetModule(void) {
+  static void *type_pointer = (void *)0;
+  /* first check if module already created */
+  if (!type_pointer) {
+#ifdef SWIG_LINK_RUNTIME
+    type_pointer = SWIG_ReturnGlobalTypeList((void *)0);
+#else
+    type_pointer = PyCObject_Import((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION,
+                                   (char*)"type_pointer" SWIG_TYPE_TABLE_NAME);
+    if (PyErr_Occurred()) {
+      PyErr_Clear();
+      type_pointer = (void *)0;
+    }
+#endif
+  }
+  return (swig_module_info *) type_pointer;
+}
+
+#if PY_MAJOR_VERSION < 2
+/* PyModule_AddObject function was introduced in Python 2.0.  The following function
+   is copied out of Python/modsupport.c in python version 2.3.4 */
+SWIGINTERN int
+PyModule_AddObject(PyObject *m, char *name, PyObject *o)
+{
+  PyObject *dict;
+  if (!PyModule_Check(m)) {
+    PyErr_SetString(PyExc_TypeError,
+                   "PyModule_AddObject() needs module as first arg");
+    return SWIG_ERROR;
+  }
+  if (!o) {
+    PyErr_SetString(PyExc_TypeError,
+                   "PyModule_AddObject() needs non-NULL value");
+    return SWIG_ERROR;
+  }
+  
+  dict = PyModule_GetDict(m);
+  if (dict == NULL) {
+    /* Internal error -- modules must have a dict! */
+    PyErr_Format(PyExc_SystemError, "module '%s' has no __dict__",
+                PyModule_GetName(m));
+    return SWIG_ERROR;
+  }
+  if (PyDict_SetItemString(dict, name, o))
+    return SWIG_ERROR;
+  Py_DECREF(o);
+  return SWIG_OK;
+}
+#endif
+
+SWIGRUNTIME void
+SWIG_Python_DestroyModule(void *vptr)
+{
+  swig_module_info *swig_module = (swig_module_info *) vptr;
+  swig_type_info **types = swig_module->types;
+  size_t i;
+  for (i =0; i < swig_module->size; ++i) {
+    swig_type_info *ty = types[i];
+    if (ty->owndata) {
+      SwigPyClientData *data = (SwigPyClientData *) ty->clientdata;
+      if (data) SwigPyClientData_Del(data);
+    }
+  }
+  Py_DECREF(SWIG_This());
+}
+
+SWIGRUNTIME void
+SWIG_Python_SetModule(swig_module_info *swig_module) {
+  static PyMethodDef swig_empty_runtime_method_table[] = { {NULL, NULL, 0, NULL} };/* Sentinel */
+
+#if PY_VERSION_HEX >= 0x03000000
+ /* Add a dummy module object into sys.modules */
+  PyObject *module = PyImport_AddModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION);
+#else
+  PyObject *module = Py_InitModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION,
+                                  swig_empty_runtime_method_table);
+#endif
+  PyObject *pointer = PyCObject_FromVoidPtr((void *) swig_module, SWIG_Python_DestroyModule);
+  if (pointer && module) {
+    PyModule_AddObject(module, (char*)"type_pointer" SWIG_TYPE_TABLE_NAME, pointer);
+  } else {
+    Py_XDECREF(pointer);
+  }
+}
+
+/* The python cached type query */
+SWIGRUNTIME PyObject *
+SWIG_Python_TypeCache(void) {
+  static PyObject *SWIG_STATIC_POINTER(cache) = PyDict_New();
+  return cache;
+}
+
+SWIGRUNTIME swig_type_info *
+SWIG_Python_TypeQuery(const char *type)
+{
+  PyObject *cache = SWIG_Python_TypeCache();
+  PyObject *key = SWIG_Python_str_FromChar(type); 
+  PyObject *obj = PyDict_GetItem(cache, key);
+  swig_type_info *descriptor;
+  if (obj) {
+    descriptor = (swig_type_info *) PyCObject_AsVoidPtr(obj);
+  } else {
+    swig_module_info *swig_module = SWIG_Python_GetModule();
+    descriptor = SWIG_TypeQueryModule(swig_module, swig_module, type);
+    if (descriptor) {
+      obj = PyCObject_FromVoidPtr(descriptor, NULL);
+      PyDict_SetItem(cache, key, obj);
+      Py_DECREF(obj);
+    }
+  }
+  Py_DECREF(key);
+  return descriptor;
+}
+
+/* 
+   For backward compatibility only
+*/
+#define SWIG_POINTER_EXCEPTION  0
+#define SWIG_arg_fail(arg)      SWIG_Python_ArgFail(arg)
+#define SWIG_MustGetPtr(p, type, argnum, flags)  SWIG_Python_MustGetPtr(p, type, argnum, flags)
+
+SWIGRUNTIME int
+SWIG_Python_AddErrMesg(const char* mesg, int infront)
+{
+  if (PyErr_Occurred()) {
+    PyObject *type = 0;
+    PyObject *value = 0;
+    PyObject *traceback = 0;
+    PyErr_Fetch(&type, &value, &traceback);
+    if (value) {
+      PyObject *old_str = PyObject_Str(value);
+      Py_XINCREF(type);
+      PyErr_Clear();
+      if (infront) {
+       PyErr_Format(type, "%s %s", mesg, SWIG_Python_str_AsChar(old_str));
+      } else {
+       PyErr_Format(type, "%s %s", SWIG_Python_str_AsChar(old_str), mesg);
+      }
+      Py_DECREF(old_str);
+    }
+    return 1;
+  } else {
+    return 0;
+  }
+}
+  
+SWIGRUNTIME int
+SWIG_Python_ArgFail(int argnum)
+{
+  if (PyErr_Occurred()) {
+    /* add information about failing argument */
+    char mesg[256];
+    PyOS_snprintf(mesg, sizeof(mesg), "argument number %d:", argnum);
+    return SWIG_Python_AddErrMesg(mesg, 1);
+  } else {
+    return 0;
+  }
+}
+
+SWIGRUNTIMEINLINE const char *
+SwigPyObject_GetDesc(PyObject *self)
+{
+  SwigPyObject *v = (SwigPyObject *)self;
+  swig_type_info *ty = v ? v->ty : 0;
+  return ty ? ty->str : (char*)"";
+}
+
+SWIGRUNTIME void
+SWIG_Python_TypeError(const char *type, PyObject *obj)
+{
+  if (type) {
+#if defined(SWIG_COBJECT_TYPES)
+    if (obj && SwigPyObject_Check(obj)) {
+      const char *otype = (const char *) SwigPyObject_GetDesc(obj);
+      if (otype) {
+       PyErr_Format(PyExc_TypeError, "a '%s' is expected, 'SwigPyObject(%s)' is received",
+                    type, otype);
+       return;
+      }
+    } else 
+#endif      
+    {
+      const char *otype = (obj ? obj->ob_type->tp_name : 0); 
+      if (otype) {
+       PyObject *str = PyObject_Str(obj);
+       const char *cstr = str ? SWIG_Python_str_AsChar(str) : 0;
+       if (cstr) {
+         PyErr_Format(PyExc_TypeError, "a '%s' is expected, '%s(%s)' is received",
+                      type, otype, cstr);
+       } else {
+         PyErr_Format(PyExc_TypeError, "a '%s' is expected, '%s' is received",
+                      type, otype);
+       }
+       Py_XDECREF(str);
+       return;
+      }
+    }   
+    PyErr_Format(PyExc_TypeError, "a '%s' is expected", type);
+  } else {
+    PyErr_Format(PyExc_TypeError, "unexpected type is received");
+  }
+}
+
+
+/* Convert a pointer value, signal an exception on a type mismatch */
+SWIGRUNTIME void *
+SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int argnum, int flags) {
+  void *result;
+  if (SWIG_Python_ConvertPtr(obj, &result, ty, flags) == -1) {
+    PyErr_Clear();
+    if (flags & SWIG_POINTER_EXCEPTION) {
+      SWIG_Python_TypeError(SWIG_TypePrettyName(ty), obj);
+      SWIG_Python_ArgFail(argnum);
+    }
+  }
+  return result;
+}
+
+
+#ifdef __cplusplus
+#if 0
+{ /* cc-mode */
+#endif
+}
+#endif
+
+
+
+#define SWIG_exception_fail(code, msg) do { SWIG_Error(code, msg); SWIG_fail; } while(0) 
+
+#define SWIG_contract_assert(expr, msg) if (!(expr)) { SWIG_Error(SWIG_RuntimeError, msg); SWIG_fail; } else 
+
+
+
+/* -------- TYPES TABLE (BEGIN) -------- */
+
+#define SWIGTYPE_p_FILE swig_types[0]
+#define SWIGTYPE_p_char swig_types[1]
+#define SWIGTYPE_p_f_p_void_int_p_struct_ub_result__void swig_types[2]
+#define SWIGTYPE_p_int swig_types[3]
+#define SWIGTYPE_p_p_char swig_types[4]
+#define SWIGTYPE_p_p_ub_result swig_types[5]
+#define SWIGTYPE_p_ub_ctx swig_types[6]
+#define SWIGTYPE_p_ub_result swig_types[7]
+#define SWIGTYPE_p_void swig_types[8]
+static swig_type_info *swig_types[10];
+static swig_module_info swig_module = {swig_types, 9, 0, 0, 0, 0};
+#define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name)
+#define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name)
+
+/* -------- TYPES TABLE (END) -------- */
+
+#if (PY_VERSION_HEX <= 0x02000000)
+# if !defined(SWIG_PYTHON_CLASSIC)
+#  error "This python version requires swig to be run with the '-classic' option"
+# endif
+#endif
+
+/*-----------------------------------------------
+              @(target):= _unbound.so
+  ------------------------------------------------*/
+#if PY_VERSION_HEX >= 0x03000000
+#  define SWIG_init    PyInit__unbound
+
+#else
+#  define SWIG_init    init_unbound
+
+#endif
+#define SWIG_name    "_unbound"
+
+#define SWIGVERSION 0x010338 
+#define SWIG_VERSION SWIGVERSION
+
+
+#define SWIG_as_voidptr(a) (void *)((const void *)(a)) 
+#define SWIG_as_voidptrptr(a) ((void)SWIG_as_voidptr(*a),(void**)(a)) 
+
+
+   #include <sys/types.h>
+   #include <sys/socket.h>
+   #include <netinet/in.h>
+   #include <arpa/inet.h>
+   #include "libunbound/unbound.h"
+
+
+  void ub_ctx_free_dbg (struct ub_ctx* c) {
+    printf("******** UB_CTX free 0x%lX ************\n", (long unsigned int)c);
+    ub_ctx_delete(c);
+  }
+
+  //RR types
+  enum enum_rr_type
+  {
+    /**  a host address */
+    RR_TYPE_A = 1, 
+    /**  an authoritative name server */
+    RR_TYPE_NS = 2, 
+    /**  a mail destination (Obsolete - use MX) */
+    RR_TYPE_MD = 3, 
+    /**  a mail forwarder (Obsolete - use MX) */
+    RR_TYPE_MF = 4, 
+    /**  the canonical name for an alias */
+    RR_TYPE_CNAME = 5, 
+    /**  marks the start of a zone of authority */
+    RR_TYPE_SOA = 6, 
+    /**  a mailbox domain name (EXPERIMENTAL) */
+    RR_TYPE_MB = 7, 
+    /**  a mail group member (EXPERIMENTAL) */
+    RR_TYPE_MG = 8, 
+    /**  a mail rename domain name (EXPERIMENTAL) */
+    RR_TYPE_MR = 9, 
+    /**  a null RR (EXPERIMENTAL) */
+    RR_TYPE_NULL = 10,
+    /**  a well known service description */
+    RR_TYPE_WKS = 11,
+    /**  a domain name pointer */
+    RR_TYPE_PTR = 12,
+    /**  host information */
+    RR_TYPE_HINFO = 13,
+    /**  mailbox or mail list information */
+    RR_TYPE_MINFO = 14,
+    /**  mail exchange */
+    RR_TYPE_MX = 15,
+    /**  text strings */
+    RR_TYPE_TXT = 16,
+    /**  RFC1183 */
+    RR_TYPE_RP = 17,
+    /**  RFC1183 */
+    RR_TYPE_AFSDB = 18,
+    /**  RFC1183 */
+    RR_TYPE_X25 = 19,
+    /**  RFC1183 */
+    RR_TYPE_ISDN = 20,
+    /**  RFC1183 */
+    RR_TYPE_RT = 21,
+    /**  RFC1706 */
+    RR_TYPE_NSAP = 22,
+    /**  RFC1348 */
+    RR_TYPE_NSAP_PTR = 23,
+    /**  2535typecode */
+    RR_TYPE_SIG = 24,
+    /**  2535typecode */
+    RR_TYPE_KEY = 25,
+    /**  RFC2163 */
+    RR_TYPE_PX = 26,
+    /**  RFC1712 */
+    RR_TYPE_GPOS = 27,
+    /**  ipv6 address */
+    RR_TYPE_AAAA = 28,
+    /**  LOC record  RFC1876 */
+    RR_TYPE_LOC = 29,
+    /**  2535typecode */
+    RR_TYPE_NXT = 30,
+    /**  draft-ietf-nimrod-dns-01.txt */
+    RR_TYPE_EID = 31,
+    /**  draft-ietf-nimrod-dns-01.txt */
+    RR_TYPE_NIMLOC = 32,
+    /**  SRV record RFC2782 */
+    RR_TYPE_SRV = 33,
+    /**  http://www.jhsoft.com/rfc/af-saa-0069.000.rtf */
+    RR_TYPE_ATMA = 34,
+    /**  RFC2915 */
+    RR_TYPE_NAPTR = 35,
+    /**  RFC2230 */
+    RR_TYPE_KX = 36,
+    /**  RFC2538 */
+    RR_TYPE_CERT = 37,
+    /**  RFC2874 */
+    RR_TYPE_A6 = 38,
+    /**  RFC2672 */
+    RR_TYPE_DNAME = 39,
+    /**  dnsind-kitchen-sink-02.txt */
+    RR_TYPE_SINK = 40,
+    /**  Pseudo OPT record... */
+    RR_TYPE_OPT = 41,
+    /**  RFC3123 */
+    RR_TYPE_APL = 42,
+    /**  draft-ietf-dnsext-delegation */
+    RR_TYPE_DS = 43,
+    /**  SSH Key Fingerprint */
+    RR_TYPE_SSHFP = 44,
+    /**  draft-richardson-ipseckey-rr-11.txt */
+    RR_TYPE_IPSECKEY = 45,
+    /**  draft-ietf-dnsext-dnssec-25 */
+    RR_TYPE_RRSIG = 46,
+    RR_TYPE_NSEC = 47,      
+    RR_TYPE_DNSKEY = 48,
+    RR_TYPE_DHCID = 49,
+
+    RR_TYPE_NSEC3 = 50,
+    RR_TYPE_NSEC3PARAMS = 51,
+
+    RR_TYPE_UINFO = 100,
+    RR_TYPE_UID = 101,
+    RR_TYPE_GID = 102,
+    RR_TYPE_UNSPEC = 103,
+
+    RR_TYPE_TSIG = 250,
+    RR_TYPE_IXFR = 251,
+    RR_TYPE_AXFR = 252,
+    /**  A request for mailbox-related records (MB, MG or MR) */
+    RR_TYPE_MAILB = 253,
+    /**  A request for mail agent RRs (Obsolete - see MX) */
+    RR_TYPE_MAILA = 254,
+    /**  any type (wildcard) */
+    RR_TYPE_ANY = 255,
+
+    /* RFC 4431, 5074, DNSSEC Lookaside Validation */
+    RR_TYPE_DLV = 32769,
+  };
+
+  // RR classes
+  enum enum_rr_class
+  { 
+    /** the Internet */
+    RR_CLASS_IN = 1,
+    /** Chaos class */
+    RR_CLASS_CH = 3,
+    /** Hesiod (Dyer 87) */
+    RR_CLASS_HS = 4,
+    /** None class, dynamic update */
+    RR_CLASS_NONE = 254,
+    /** Any class */
+    RR_CLASS_ANY = 255,
+  };
+
+
+  #define SWIG_From_long   PyInt_FromLong 
+
+
+SWIGINTERNINLINE PyObject *
+SWIG_From_int  (int value)
+{    
+  return SWIG_From_long  (value);
+}
+
+
+  void ub_resolve_free_dbg (struct ub_result* r) {
+    printf("******** UB_RESOLVE free 0x%lX ************\n", (long unsigned int)r);
+    ub_resolve_free(r);
+  }
+
+
+  enum result_enum_rcode {
+    RCODE_NOERROR = 0,
+    RCODE_FORMERR = 1,
+    RCODE_SERVFAIL = 2,
+    RCODE_NXDOMAIN = 3,
+    RCODE_NOTIMPL = 4,
+    RCODE_REFUSED = 5,
+    RCODE_YXDOMAIN = 6,
+    RCODE_YXRRSET = 7,
+    RCODE_NXRRSET = 8,
+    RCODE_NOTAUTH = 9,
+    RCODE_NOTZONE = 10
+  };
+
+
+SWIGINTERN swig_type_info*
+SWIG_pchar_descriptor(void)
+{
+  static int init = 0;
+  static swig_type_info* info = 0;
+  if (!init) {
+    info = SWIG_TypeQuery("_p_char");
+    init = 1;
+  }
+  return info;
+}
+
+
+SWIGINTERN int
+SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc)
+{
+#if PY_VERSION_HEX>=0x03000000
+  if (PyUnicode_Check(obj)) 
+#else  
+  if (PyString_Check(obj)) 
+#endif
+  {
+    char *cstr; Py_ssize_t len;
+#if PY_VERSION_HEX>=0x03000000
+    obj = PyUnicode_AsUTF8String(obj);
+    PyBytes_AsStringAndSize(obj, &cstr, &len);
+#else
+    PyString_AsStringAndSize(obj, &cstr, &len);
+#endif
+    if (cptr) { 
+      if (alloc) {
+       /* 
+          In python the user should not be able to modify the inner
+          string representation. To warranty that, if you define
+          SWIG_PYTHON_SAFE_CSTRINGS, a new/copy of the python string
+          buffer is always returned.
+
+          The default behavior is just to return the pointer value,
+          so, be careful.
+       */ 
+#if defined(SWIG_PYTHON_SAFE_CSTRINGS)
+       if (*alloc != SWIG_OLDOBJ) 
+#else
+       if (*alloc == SWIG_NEWOBJ) 
+#endif
+         {
+           *cptr = (char *)memcpy((char *)malloc((len + 1)*sizeof(char)), cstr, sizeof(char)*(len + 1));
+           *alloc = SWIG_NEWOBJ;
+         }
+       else {
+         *cptr = cstr;
+         *alloc = SWIG_OLDOBJ;
+       }
+      } else {
+       *cptr = SWIG_Python_str_AsChar(obj);
+      }
+    }
+    if (psize) *psize = len + 1;
+    return SWIG_OK;
+  } else {
+    swig_type_info* pchar_descriptor = SWIG_pchar_descriptor();
+    if (pchar_descriptor) {
+      void* vptr = 0;
+      if (SWIG_ConvertPtr(obj, &vptr, pchar_descriptor, 0) == SWIG_OK) {
+       if (cptr) *cptr = (char *) vptr;
+       if (psize) *psize = vptr ? (strlen((char *)vptr) + 1) : 0;
+       if (alloc) *alloc = SWIG_OLDOBJ;
+       return SWIG_OK;
+      }
+    }
+  }
+  return SWIG_TypeError;
+}
+
+
+
+
+
+SWIGINTERNINLINE PyObject *
+SWIG_FromCharPtrAndSize(const char* carray, size_t size)
+{
+  if (carray) {
+    if (size > INT_MAX) {
+      swig_type_info* pchar_descriptor = SWIG_pchar_descriptor();
+      return pchar_descriptor ? 
+       SWIG_NewPointerObj((char *)(carray), pchar_descriptor, 0) : SWIG_Py_Void();
+    } else {
+#if PY_VERSION_HEX >= 0x03000000
+      return PyUnicode_FromStringAndSize(carray, (int)(size));
+#else
+      return PyString_FromStringAndSize(carray, (int)(size));
+#endif
+    }
+  } else {
+    return SWIG_Py_Void();
+  }
+}
+
+
+SWIGINTERNINLINE PyObject * 
+SWIG_FromCharPtr(const char *cptr)
+{ 
+  return SWIG_FromCharPtrAndSize(cptr, (cptr ? strlen(cptr) : 0));
+}
+
+
+#include <limits.h>
+#if !defined(SWIG_NO_LLONG_MAX)
+# if !defined(LLONG_MAX) && defined(__GNUC__) && defined (__LONG_LONG_MAX__)
+#   define LLONG_MAX __LONG_LONG_MAX__
+#   define LLONG_MIN (-LLONG_MAX - 1LL)
+#   define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL)
+# endif
+#endif
+
+
+SWIGINTERN int
+SWIG_AsVal_double (PyObject *obj, double *val)
+{
+  int res = SWIG_TypeError;
+  if (PyFloat_Check(obj)) {
+    if (val) *val = PyFloat_AsDouble(obj);
+    return SWIG_OK;
+  } else if (PyInt_Check(obj)) {
+    if (val) *val = PyInt_AsLong(obj);
+    return SWIG_OK;
+  } else if (PyLong_Check(obj)) {
+    double v = PyLong_AsDouble(obj);
+    if (!PyErr_Occurred()) {
+      if (val) *val = v;
+      return SWIG_OK;
+    } else {
+      PyErr_Clear();
+    }
+  }
+#ifdef SWIG_PYTHON_CAST_MODE
+  {
+    int dispatch = 0;
+    double d = PyFloat_AsDouble(obj);
+    if (!PyErr_Occurred()) {
+      if (val) *val = d;
+      return SWIG_AddCast(SWIG_OK);
+    } else {
+      PyErr_Clear();
+    }
+    if (!dispatch) {
+      long v = PyLong_AsLong(obj);
+      if (!PyErr_Occurred()) {
+       if (val) *val = v;
+       return SWIG_AddCast(SWIG_AddCast(SWIG_OK));
+      } else {
+       PyErr_Clear();
+      }
+    }
+  }
+#endif
+  return res;
+}
+
+
+#include <float.h>
+
+
+#include <math.h>
+
+
+SWIGINTERNINLINE int
+SWIG_CanCastAsInteger(double *d, double min, double max) {
+  double x = *d;
+  if ((min <= x && x <= max)) {
+   double fx = floor(x);
+   double cx = ceil(x);
+   double rd =  ((x - fx) < 0.5) ? fx : cx; /* simple rint */
+   if ((errno == EDOM) || (errno == ERANGE)) {
+     errno = 0;
+   } else {
+     double summ, reps, diff;
+     if (rd < x) {
+       diff = x - rd;
+     } else if (rd > x) {
+       diff = rd - x;
+     } else {
+       return 1;
+     }
+     summ = rd + x;
+     reps = diff/summ;
+     if (reps < 8*DBL_EPSILON) {
+       *d = rd;
+       return 1;
+     }
+   }
+  }
+  return 0;
+}
+
+
+SWIGINTERN int
+SWIG_AsVal_long (PyObject *obj, long* val)
+{
+  if (PyInt_Check(obj)) {
+    if (val) *val = PyInt_AsLong(obj);
+    return SWIG_OK;
+  } else if (PyLong_Check(obj)) {
+    long v = PyLong_AsLong(obj);
+    if (!PyErr_Occurred()) {
+      if (val) *val = v;
+      return SWIG_OK;
+    } else {
+      PyErr_Clear();
+    }
+  }
+#ifdef SWIG_PYTHON_CAST_MODE
+  {
+    int dispatch = 0;
+    long v = PyInt_AsLong(obj);
+    if (!PyErr_Occurred()) {
+      if (val) *val = v;
+      return SWIG_AddCast(SWIG_OK);
+    } else {
+      PyErr_Clear();
+    }
+    if (!dispatch) {
+      double d;
+      int res = SWIG_AddCast(SWIG_AsVal_double (obj,&d));
+      if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, LONG_MIN, LONG_MAX)) {
+       if (val) *val = (long)(d);
+       return res;
+      }
+    }
+  }
+#endif
+  return SWIG_TypeError;
+}
+
+
+SWIGINTERN int
+SWIG_AsVal_int (PyObject * obj, int *val)
+{
+  long v;
+  int res = SWIG_AsVal_long (obj, &v);
+  if (SWIG_IsOK(res)) {
+    if ((v < INT_MIN || v > INT_MAX)) {
+      return SWIG_OverflowError;
+    } else {
+      if (val) *val = (int)(v);
+    }
+  }  
+  return res;
+}
+
+SWIGINTERN PyObject *ub_result__ub_result_data(struct ub_result *self,struct ub_result *result){
+    PyObject  *list;
+     int i,j,cnt;
+     if ((result == 0) || (!result->havedata) || (result->data == 0))
+        return Py_None;
+
+     for (cnt=0,i=0;;i++,cnt++) 
+         if (result->data[i] == 0)
+            break;
+     
+     list = PyList_New(cnt);
+     for (i=0;i<cnt;i++) 
+         PyList_SetItem(list, i, PyString_FromStringAndSize(result->data[i],result->len[i]));
+     
+     return list;
+  }
+
+  //SWIG will see the ub_ctx as a class
+  struct ub_ctx {
+  };
+
+
+SWIGINTERN int
+SWIG_AsValFilePtr(PyObject *obj, FILE **val) {
+  static swig_type_info* desc = 0;
+  void *vptr = 0;
+  if (!desc) desc = SWIG_TypeQuery("FILE *");
+  if ((SWIG_ConvertPtr(obj, &vptr, desc, 0)) == SWIG_OK) {
+    if (val) *val = (FILE *)vptr;
+    return SWIG_OK;
+  }
+#if PY_VERSION_HEX < 0x03000000
+  if (PyFile_Check(obj)) {
+    if (val) *val =  PyFile_AsFile(obj);
+    return SWIG_OK;
+  }
+#endif
+  return SWIG_TypeError;
+}
+
+
+   struct cb_data {
+      PyObject* data;
+      PyObject* func;
+   };
+
+   static void PythonCallBack(void* iddata, int status, struct ub_result* result)
+   {
+      PyObject *func, *arglist;
+      PyObject *fresult;
+      struct cb_data* id;
+      id = (struct cb_data*) iddata;
+      arglist = Py_BuildValue("(OiO)",id->data,status, SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_ub_result, 0 |  0 ));   // Build argument list
+      fresult = PyEval_CallObject(id->func,arglist);     // Call Python
+      Py_DECREF(id->func);
+      Py_DECREF(id->data);
+      free(id);
+      ub_resolve_free(result);                  //free ub_result
+      //ub_resolve_free_dbg(result);                  //free ub_result
+      Py_DECREF(arglist);                           // Trash arglist
+      Py_XDECREF(fresult);
+   }
+
+   int _ub_resolve_async(struct ub_ctx* ctx, char* name, int rrtype, int rrclass, PyObject* mydata, PyObject *pyfunc, int* async_id) {
+      struct cb_data* id;
+      id = (struct cb_data*) malloc(sizeof(struct cb_data));
+      id->data = mydata;
+      id->func = pyfunc;
+   
+      int i = ub_resolve_async(ctx,name,rrtype,rrclass, (void *) id, PythonCallBack, async_id);
+      Py_INCREF(mydata);
+      Py_INCREF(pyfunc);
+      return i;
+   }
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+SWIGINTERN PyObject *_wrap_ub_ctx_free_dbg(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_ctx *arg1 = (struct ub_ctx *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:ub_ctx_free_dbg",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_ctx, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_ctx_free_dbg" "', argument " "1"" of type '" "struct ub_ctx *""'"); 
+  }
+  arg1 = (struct ub_ctx *)(argp1);
+  ub_ctx_free_dbg(arg1);
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_resolve_free_dbg(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_result *arg1 = (struct ub_result *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:ub_resolve_free_dbg",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_result, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_resolve_free_dbg" "', argument " "1"" of type '" "struct ub_result *""'"); 
+  }
+  arg1 = (struct ub_result *)(argp1);
+  ub_resolve_free_dbg(arg1);
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_result_qname_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_result *arg1 = (struct ub_result *) 0 ;
+  char *arg2 = (char *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:ub_result_qname_set",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_result, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_result_qname_set" "', argument " "1"" of type '" "struct ub_result *""'"); 
+  }
+  arg1 = (struct ub_result *)(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ub_result_qname_set" "', argument " "2"" of type '" "char *""'");
+  }
+  arg2 = (char *)(buf2);
+  if (arg1->qname) free((char*)arg1->qname);
+  if (arg2) {
+    size_t size = strlen((const char *)(arg2)) + 1;
+    arg1->qname = (char *)(char *)memcpy((char *)malloc((size)*sizeof(char)), (const char *)(arg2), sizeof(char)*(size));
+  } else {
+    arg1->qname = 0;
+  }
+  resultobj = SWIG_Py_Void();
+  if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_result_qname_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_result *arg1 = (struct ub_result *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  char *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:ub_result_qname_get",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_result, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_result_qname_get" "', argument " "1"" of type '" "struct ub_result *""'"); 
+  }
+  arg1 = (struct ub_result *)(argp1);
+  result = (char *) ((arg1)->qname);
+  resultobj = SWIG_FromCharPtr((const char *)result);
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_result_qtype_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_result *arg1 = (struct ub_result *) 0 ;
+  int arg2 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:ub_result_qtype_set",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_result, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_result_qtype_set" "', argument " "1"" of type '" "struct ub_result *""'"); 
+  }
+  arg1 = (struct ub_result *)(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "ub_result_qtype_set" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = (int)(val2);
+  if (arg1) (arg1)->qtype = arg2;
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_result_qtype_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_result *arg1 = (struct ub_result *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:ub_result_qtype_get",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_result, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_result_qtype_get" "', argument " "1"" of type '" "struct ub_result *""'"); 
+  }
+  arg1 = (struct ub_result *)(argp1);
+  result = (int) ((arg1)->qtype);
+  resultobj = SWIG_From_int((int)(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_result_qclass_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_result *arg1 = (struct ub_result *) 0 ;
+  int arg2 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:ub_result_qclass_set",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_result, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_result_qclass_set" "', argument " "1"" of type '" "struct ub_result *""'"); 
+  }
+  arg1 = (struct ub_result *)(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "ub_result_qclass_set" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = (int)(val2);
+  if (arg1) (arg1)->qclass = arg2;
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_result_qclass_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_result *arg1 = (struct ub_result *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:ub_result_qclass_get",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_result, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_result_qclass_get" "', argument " "1"" of type '" "struct ub_result *""'"); 
+  }
+  arg1 = (struct ub_result *)(argp1);
+  result = (int) ((arg1)->qclass);
+  resultobj = SWIG_From_int((int)(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_result__data_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_result *arg1 = (struct ub_result *) 0 ;
+  char **arg2 = (char **) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:ub_result__data_set",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_result, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_result__data_set" "', argument " "1"" of type '" "struct ub_result *""'"); 
+  }
+  arg1 = (struct ub_result *)(argp1);
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_p_char, 0 |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ub_result__data_set" "', argument " "2"" of type '" "char **""'"); 
+  }
+  arg2 = (char **)(argp2);
+  if (arg1) (arg1)->data = arg2;
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_result__data_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_result *arg1 = (struct ub_result *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  char **result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:ub_result__data_get",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_result, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_result__data_get" "', argument " "1"" of type '" "struct ub_result *""'"); 
+  }
+  arg1 = (struct ub_result *)(argp1);
+  result = (char **) ((arg1)->data);
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_p_char, 0 |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_result_len_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_result *arg1 = (struct ub_result *) 0 ;
+  int *arg2 = (int *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:ub_result_len_set",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_result, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_result_len_set" "', argument " "1"" of type '" "struct ub_result *""'"); 
+  }
+  arg1 = (struct ub_result *)(argp1);
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_int, SWIG_POINTER_DISOWN |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ub_result_len_set" "', argument " "2"" of type '" "int *""'"); 
+  }
+  arg2 = (int *)(argp2);
+  if (arg1) (arg1)->len = arg2;
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_result_len_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_result *arg1 = (struct ub_result *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  int *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:ub_result_len_get",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_result, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_result_len_get" "', argument " "1"" of type '" "struct ub_result *""'"); 
+  }
+  arg1 = (struct ub_result *)(argp1);
+  result = (int *) ((arg1)->len);
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_int, 0 |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_result_canonname_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_result *arg1 = (struct ub_result *) 0 ;
+  char *arg2 = (char *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:ub_result_canonname_set",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_result, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_result_canonname_set" "', argument " "1"" of type '" "struct ub_result *""'"); 
+  }
+  arg1 = (struct ub_result *)(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ub_result_canonname_set" "', argument " "2"" of type '" "char *""'");
+  }
+  arg2 = (char *)(buf2);
+  if (arg1->canonname) free((char*)arg1->canonname);
+  if (arg2) {
+    size_t size = strlen((const char *)(arg2)) + 1;
+    arg1->canonname = (char *)(char *)memcpy((char *)malloc((size)*sizeof(char)), (const char *)(arg2), sizeof(char)*(size));
+  } else {
+    arg1->canonname = 0;
+  }
+  resultobj = SWIG_Py_Void();
+  if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_result_canonname_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_result *arg1 = (struct ub_result *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  char *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:ub_result_canonname_get",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_result, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_result_canonname_get" "', argument " "1"" of type '" "struct ub_result *""'"); 
+  }
+  arg1 = (struct ub_result *)(argp1);
+  result = (char *) ((arg1)->canonname);
+  resultobj = SWIG_FromCharPtr((const char *)result);
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_result_rcode_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_result *arg1 = (struct ub_result *) 0 ;
+  int arg2 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:ub_result_rcode_set",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_result, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_result_rcode_set" "', argument " "1"" of type '" "struct ub_result *""'"); 
+  }
+  arg1 = (struct ub_result *)(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "ub_result_rcode_set" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = (int)(val2);
+  if (arg1) (arg1)->rcode = arg2;
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_result_rcode_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_result *arg1 = (struct ub_result *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:ub_result_rcode_get",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_result, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_result_rcode_get" "', argument " "1"" of type '" "struct ub_result *""'"); 
+  }
+  arg1 = (struct ub_result *)(argp1);
+  result = (int) ((arg1)->rcode);
+  resultobj = SWIG_From_int((int)(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_result_answer_packet_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_result *arg1 = (struct ub_result *) 0 ;
+  void *arg2 = (void *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:ub_result_answer_packet_set",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_result, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_result_answer_packet_set" "', argument " "1"" of type '" "struct ub_result *""'"); 
+  }
+  arg1 = (struct ub_result *)(argp1);
+  res2 = SWIG_ConvertPtr(obj1,SWIG_as_voidptrptr(&arg2), 0, SWIG_POINTER_DISOWN);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ub_result_answer_packet_set" "', argument " "2"" of type '" "void *""'"); 
+  }
+  if (arg1) (arg1)->answer_packet = arg2;
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_result_answer_packet_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_result *arg1 = (struct ub_result *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  void *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:ub_result_answer_packet_get",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_result, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_result_answer_packet_get" "', argument " "1"" of type '" "struct ub_result *""'"); 
+  }
+  arg1 = (struct ub_result *)(argp1);
+  result = (void *) ((arg1)->answer_packet);
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_void, 0 |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_result_answer_len_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_result *arg1 = (struct ub_result *) 0 ;
+  int arg2 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:ub_result_answer_len_set",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_result, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_result_answer_len_set" "', argument " "1"" of type '" "struct ub_result *""'"); 
+  }
+  arg1 = (struct ub_result *)(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "ub_result_answer_len_set" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = (int)(val2);
+  if (arg1) (arg1)->answer_len = arg2;
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_result_answer_len_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_result *arg1 = (struct ub_result *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:ub_result_answer_len_get",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_result, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_result_answer_len_get" "', argument " "1"" of type '" "struct ub_result *""'"); 
+  }
+  arg1 = (struct ub_result *)(argp1);
+  result = (int) ((arg1)->answer_len);
+  resultobj = SWIG_From_int((int)(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_result_havedata_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_result *arg1 = (struct ub_result *) 0 ;
+  int arg2 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:ub_result_havedata_set",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_result, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_result_havedata_set" "', argument " "1"" of type '" "struct ub_result *""'"); 
+  }
+  arg1 = (struct ub_result *)(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "ub_result_havedata_set" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = (int)(val2);
+  if (arg1) (arg1)->havedata = arg2;
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_result_havedata_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_result *arg1 = (struct ub_result *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:ub_result_havedata_get",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_result, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_result_havedata_get" "', argument " "1"" of type '" "struct ub_result *""'"); 
+  }
+  arg1 = (struct ub_result *)(argp1);
+  result = (int) ((arg1)->havedata);
+  resultobj = SWIG_From_int((int)(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_result_nxdomain_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_result *arg1 = (struct ub_result *) 0 ;
+  int arg2 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:ub_result_nxdomain_set",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_result, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_result_nxdomain_set" "', argument " "1"" of type '" "struct ub_result *""'"); 
+  }
+  arg1 = (struct ub_result *)(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "ub_result_nxdomain_set" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = (int)(val2);
+  if (arg1) (arg1)->nxdomain = arg2;
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_result_nxdomain_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_result *arg1 = (struct ub_result *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:ub_result_nxdomain_get",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_result, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_result_nxdomain_get" "', argument " "1"" of type '" "struct ub_result *""'"); 
+  }
+  arg1 = (struct ub_result *)(argp1);
+  result = (int) ((arg1)->nxdomain);
+  resultobj = SWIG_From_int((int)(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_result_secure_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_result *arg1 = (struct ub_result *) 0 ;
+  int arg2 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:ub_result_secure_set",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_result, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_result_secure_set" "', argument " "1"" of type '" "struct ub_result *""'"); 
+  }
+  arg1 = (struct ub_result *)(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "ub_result_secure_set" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = (int)(val2);
+  if (arg1) (arg1)->secure = arg2;
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_result_secure_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_result *arg1 = (struct ub_result *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:ub_result_secure_get",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_result, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_result_secure_get" "', argument " "1"" of type '" "struct ub_result *""'"); 
+  }
+  arg1 = (struct ub_result *)(argp1);
+  result = (int) ((arg1)->secure);
+  resultobj = SWIG_From_int((int)(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_result_bogus_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_result *arg1 = (struct ub_result *) 0 ;
+  int arg2 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:ub_result_bogus_set",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_result, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_result_bogus_set" "', argument " "1"" of type '" "struct ub_result *""'"); 
+  }
+  arg1 = (struct ub_result *)(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "ub_result_bogus_set" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = (int)(val2);
+  if (arg1) (arg1)->bogus = arg2;
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_result_bogus_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_result *arg1 = (struct ub_result *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:ub_result_bogus_get",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_result, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_result_bogus_get" "', argument " "1"" of type '" "struct ub_result *""'"); 
+  }
+  arg1 = (struct ub_result *)(argp1);
+  result = (int) ((arg1)->bogus);
+  resultobj = SWIG_From_int((int)(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_result__ub_result_data(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_result *arg1 = (struct ub_result *) 0 ;
+  struct ub_result *arg2 = (struct ub_result *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:ub_result__ub_result_data",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_result, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_result__ub_result_data" "', argument " "1"" of type '" "struct ub_result *""'"); 
+  }
+  arg1 = (struct ub_result *)(argp1);
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_ub_result, 0 |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ub_result__ub_result_data" "', argument " "2"" of type '" "struct ub_result *""'"); 
+  }
+  arg2 = (struct ub_result *)(argp2);
+  result = (PyObject *)ub_result__ub_result_data(arg1,arg2);
+  resultobj = result;
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *ub_result_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *obj;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigregister", &obj)) return NULL;
+  SWIG_TypeNewClientData(SWIGTYPE_p_ub_result, SWIG_NewClientData(obj));
+  return SWIG_Py_Void();
+}
+
+SWIGINTERN PyObject *_wrap_ub_ctx_create(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_ctx *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)":ub_ctx_create")) SWIG_fail;
+  result = (struct ub_ctx *)ub_ctx_create();
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_ub_ctx, SWIG_POINTER_OWN |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap__ub_ctx_delete(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_ctx *arg1 = (struct ub_ctx *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:_ub_ctx_delete",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_ctx, SWIG_POINTER_DISOWN |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "_ub_ctx_delete" "', argument " "1"" of type '" "struct ub_ctx *""'"); 
+  }
+  arg1 = (struct ub_ctx *)(argp1);
+  ub_ctx_delete(arg1);
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_ctx_set_option(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_ctx *arg1 = (struct ub_ctx *) 0 ;
+  char *arg2 = (char *) 0 ;
+  char *arg3 = (char *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  int res3 ;
+  char *buf3 = 0 ;
+  int alloc3 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOO:ub_ctx_set_option",&obj0,&obj1,&obj2)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_ctx, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_ctx_set_option" "', argument " "1"" of type '" "struct ub_ctx *""'"); 
+  }
+  arg1 = (struct ub_ctx *)(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ub_ctx_set_option" "', argument " "2"" of type '" "char *""'");
+  }
+  arg2 = (char *)(buf2);
+  res3 = SWIG_AsCharPtrAndSize(obj2, &buf3, NULL, &alloc3);
+  if (!SWIG_IsOK(res3)) {
+    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "ub_ctx_set_option" "', argument " "3"" of type '" "char *""'");
+  }
+  arg3 = (char *)(buf3);
+  result = (int)ub_ctx_set_option(arg1,arg2,arg3);
+  resultobj = SWIG_From_int((int)(result));
+  if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
+  if (alloc3 == SWIG_NEWOBJ) free((char*)buf3);
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
+  if (alloc3 == SWIG_NEWOBJ) free((char*)buf3);
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_ctx_config(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_ctx *arg1 = (struct ub_ctx *) 0 ;
+  char *arg2 = (char *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:ub_ctx_config",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_ctx, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_ctx_config" "', argument " "1"" of type '" "struct ub_ctx *""'"); 
+  }
+  arg1 = (struct ub_ctx *)(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ub_ctx_config" "', argument " "2"" of type '" "char *""'");
+  }
+  arg2 = (char *)(buf2);
+  result = (int)ub_ctx_config(arg1,arg2);
+  resultobj = SWIG_From_int((int)(result));
+  if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_ctx_set_fwd(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_ctx *arg1 = (struct ub_ctx *) 0 ;
+  char *arg2 = (char *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:ub_ctx_set_fwd",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_ctx, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_ctx_set_fwd" "', argument " "1"" of type '" "struct ub_ctx *""'"); 
+  }
+  arg1 = (struct ub_ctx *)(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ub_ctx_set_fwd" "', argument " "2"" of type '" "char *""'");
+  }
+  arg2 = (char *)(buf2);
+  result = (int)ub_ctx_set_fwd(arg1,arg2);
+  resultobj = SWIG_From_int((int)(result));
+  if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_ctx_resolvconf(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_ctx *arg1 = (struct ub_ctx *) 0 ;
+  char *arg2 = (char *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:ub_ctx_resolvconf",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_ctx, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_ctx_resolvconf" "', argument " "1"" of type '" "struct ub_ctx *""'"); 
+  }
+  arg1 = (struct ub_ctx *)(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ub_ctx_resolvconf" "', argument " "2"" of type '" "char *""'");
+  }
+  arg2 = (char *)(buf2);
+  result = (int)ub_ctx_resolvconf(arg1,arg2);
+  resultobj = SWIG_From_int((int)(result));
+  if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_ctx_hosts(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_ctx *arg1 = (struct ub_ctx *) 0 ;
+  char *arg2 = (char *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:ub_ctx_hosts",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_ctx, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_ctx_hosts" "', argument " "1"" of type '" "struct ub_ctx *""'"); 
+  }
+  arg1 = (struct ub_ctx *)(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ub_ctx_hosts" "', argument " "2"" of type '" "char *""'");
+  }
+  arg2 = (char *)(buf2);
+  result = (int)ub_ctx_hosts(arg1,arg2);
+  resultobj = SWIG_From_int((int)(result));
+  if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_ctx_add_ta(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_ctx *arg1 = (struct ub_ctx *) 0 ;
+  char *arg2 = (char *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:ub_ctx_add_ta",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_ctx, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_ctx_add_ta" "', argument " "1"" of type '" "struct ub_ctx *""'"); 
+  }
+  arg1 = (struct ub_ctx *)(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ub_ctx_add_ta" "', argument " "2"" of type '" "char *""'");
+  }
+  arg2 = (char *)(buf2);
+  result = (int)ub_ctx_add_ta(arg1,arg2);
+  resultobj = SWIG_From_int((int)(result));
+  if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_ctx_add_ta_file(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_ctx *arg1 = (struct ub_ctx *) 0 ;
+  char *arg2 = (char *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:ub_ctx_add_ta_file",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_ctx, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_ctx_add_ta_file" "', argument " "1"" of type '" "struct ub_ctx *""'"); 
+  }
+  arg1 = (struct ub_ctx *)(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ub_ctx_add_ta_file" "', argument " "2"" of type '" "char *""'");
+  }
+  arg2 = (char *)(buf2);
+  result = (int)ub_ctx_add_ta_file(arg1,arg2);
+  resultobj = SWIG_From_int((int)(result));
+  if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_ctx_trustedkeys(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_ctx *arg1 = (struct ub_ctx *) 0 ;
+  char *arg2 = (char *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:ub_ctx_trustedkeys",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_ctx, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_ctx_trustedkeys" "', argument " "1"" of type '" "struct ub_ctx *""'"); 
+  }
+  arg1 = (struct ub_ctx *)(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ub_ctx_trustedkeys" "', argument " "2"" of type '" "char *""'");
+  }
+  arg2 = (char *)(buf2);
+  result = (int)ub_ctx_trustedkeys(arg1,arg2);
+  resultobj = SWIG_From_int((int)(result));
+  if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_ctx_debugout__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_ctx *arg1 = (struct ub_ctx *) 0 ;
+  void *arg2 = (void *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:ub_ctx_debugout",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_ctx, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_ctx_debugout" "', argument " "1"" of type '" "struct ub_ctx *""'"); 
+  }
+  arg1 = (struct ub_ctx *)(argp1);
+  res2 = SWIG_ConvertPtr(obj1,SWIG_as_voidptrptr(&arg2), 0, 0);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ub_ctx_debugout" "', argument " "2"" of type '" "void *""'"); 
+  }
+  result = (int)ub_ctx_debugout(arg1,arg2);
+  resultobj = SWIG_From_int((int)(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_ctx_debuglevel(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_ctx *arg1 = (struct ub_ctx *) 0 ;
+  int arg2 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:ub_ctx_debuglevel",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_ctx, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_ctx_debuglevel" "', argument " "1"" of type '" "struct ub_ctx *""'"); 
+  }
+  arg1 = (struct ub_ctx *)(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "ub_ctx_debuglevel" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = (int)(val2);
+  result = (int)ub_ctx_debuglevel(arg1,arg2);
+  resultobj = SWIG_From_int((int)(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_ctx_async(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_ctx *arg1 = (struct ub_ctx *) 0 ;
+  int arg2 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:ub_ctx_async",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_ctx, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_ctx_async" "', argument " "1"" of type '" "struct ub_ctx *""'"); 
+  }
+  arg1 = (struct ub_ctx *)(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "ub_ctx_async" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = (int)(val2);
+  result = (int)ub_ctx_async(arg1,arg2);
+  resultobj = SWIG_From_int((int)(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_poll(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_ctx *arg1 = (struct ub_ctx *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:ub_poll",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_ctx, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_poll" "', argument " "1"" of type '" "struct ub_ctx *""'"); 
+  }
+  arg1 = (struct ub_ctx *)(argp1);
+  result = (int)ub_poll(arg1);
+  resultobj = SWIG_From_int((int)(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_wait(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_ctx *arg1 = (struct ub_ctx *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:ub_wait",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_ctx, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_wait" "', argument " "1"" of type '" "struct ub_ctx *""'"); 
+  }
+  arg1 = (struct ub_ctx *)(argp1);
+  result = (int)ub_wait(arg1);
+  resultobj = SWIG_From_int((int)(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_fd(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_ctx *arg1 = (struct ub_ctx *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:ub_fd",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_ctx, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_fd" "', argument " "1"" of type '" "struct ub_ctx *""'"); 
+  }
+  arg1 = (struct ub_ctx *)(argp1);
+  result = (int)ub_fd(arg1);
+  resultobj = SWIG_From_int((int)(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_process(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_ctx *arg1 = (struct ub_ctx *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:ub_process",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_ctx, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_process" "', argument " "1"" of type '" "struct ub_ctx *""'"); 
+  }
+  arg1 = (struct ub_ctx *)(argp1);
+  result = (int)ub_process(arg1);
+  resultobj = SWIG_From_int((int)(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_resolve(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_ctx *arg1 = (struct ub_ctx *) 0 ;
+  char *arg2 = (char *) 0 ;
+  int arg3 ;
+  int arg4 ;
+  struct ub_result **arg5 = (struct ub_result **) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  int val3 ;
+  int ecode3 = 0 ;
+  int val4 ;
+  int ecode4 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  int result;
+  
+  struct ub_result* newubr;
+  arg5 = &newubr;
+  if (!PyArg_ParseTuple(args,(char *)"OOOO:ub_resolve",&obj0,&obj1,&obj2,&obj3)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_ctx, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_resolve" "', argument " "1"" of type '" "struct ub_ctx *""'"); 
+  }
+  arg1 = (struct ub_ctx *)(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ub_resolve" "', argument " "2"" of type '" "char *""'");
+  }
+  arg2 = (char *)(buf2);
+  ecode3 = SWIG_AsVal_int(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "ub_resolve" "', argument " "3"" of type '" "int""'");
+  } 
+  arg3 = (int)(val3);
+  ecode4 = SWIG_AsVal_int(obj3, &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "ub_resolve" "', argument " "4"" of type '" "int""'");
+  } 
+  arg4 = (int)(val4);
+  
+  //printf("resolve_start(%lX)\n",(long unsigned int)arg1);
+  Py_BEGIN_ALLOW_THREADS 
+  result = (int)ub_resolve(arg1,arg2,arg3,arg4,arg5); 
+  Py_END_ALLOW_THREADS 
+  //printf("resolve_stop()\n");
+  
+  resultobj = SWIG_From_int((int)(result));
+  PyObject* tuple;
+  tuple = PyTuple_New(2);
+  PyTuple_SetItem(tuple, 0, resultobj);
+  if (result == 0) {
+    PyTuple_SetItem(tuple, 1, SWIG_NewPointerObj(SWIG_as_voidptr(newubr), SWIGTYPE_p_ub_result, SWIG_POINTER_OWN |  0 ));
+  } else {
+    PyTuple_SetItem(tuple, 1, Py_None);
+  }
+  resultobj = tuple;
+  if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_resolve_async(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_ctx *arg1 = (struct ub_ctx *) 0 ;
+  char *arg2 = (char *) 0 ;
+  int arg3 ;
+  int arg4 ;
+  void *arg5 = (void *) 0 ;
+  ub_callback_t arg6 = (ub_callback_t) 0 ;
+  int *arg7 = (int *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  int val3 ;
+  int ecode3 = 0 ;
+  int val4 ;
+  int ecode4 = 0 ;
+  int res5 ;
+  void *argp7 = 0 ;
+  int res7 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  PyObject * obj5 = 0 ;
+  PyObject * obj6 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOOOOOO:ub_resolve_async",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_ctx, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_resolve_async" "', argument " "1"" of type '" "struct ub_ctx *""'"); 
+  }
+  arg1 = (struct ub_ctx *)(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ub_resolve_async" "', argument " "2"" of type '" "char *""'");
+  }
+  arg2 = (char *)(buf2);
+  ecode3 = SWIG_AsVal_int(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "ub_resolve_async" "', argument " "3"" of type '" "int""'");
+  } 
+  arg3 = (int)(val3);
+  ecode4 = SWIG_AsVal_int(obj3, &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "ub_resolve_async" "', argument " "4"" of type '" "int""'");
+  } 
+  arg4 = (int)(val4);
+  res5 = SWIG_ConvertPtr(obj4,SWIG_as_voidptrptr(&arg5), 0, 0);
+  if (!SWIG_IsOK(res5)) {
+    SWIG_exception_fail(SWIG_ArgError(res5), "in method '" "ub_resolve_async" "', argument " "5"" of type '" "void *""'"); 
+  }
+  {
+    int res = SWIG_ConvertFunctionPtr(obj5, (void**)(&arg6), SWIGTYPE_p_f_p_void_int_p_struct_ub_result__void);
+    if (!SWIG_IsOK(res)) {
+      SWIG_exception_fail(SWIG_ArgError(res), "in method '" "ub_resolve_async" "', argument " "6"" of type '" "ub_callback_t""'"); 
+    }
+  }
+  res7 = SWIG_ConvertPtr(obj6, &argp7,SWIGTYPE_p_int, 0 |  0 );
+  if (!SWIG_IsOK(res7)) {
+    SWIG_exception_fail(SWIG_ArgError(res7), "in method '" "ub_resolve_async" "', argument " "7"" of type '" "int *""'"); 
+  }
+  arg7 = (int *)(argp7);
+  result = (int)ub_resolve_async(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+  resultobj = SWIG_From_int((int)(result));
+  if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_cancel(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_ctx *arg1 = (struct ub_ctx *) 0 ;
+  int arg2 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:ub_cancel",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_ctx, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_cancel" "', argument " "1"" of type '" "struct ub_ctx *""'"); 
+  }
+  arg1 = (struct ub_ctx *)(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "ub_cancel" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = (int)(val2);
+  result = (int)ub_cancel(arg1,arg2);
+  resultobj = SWIG_From_int((int)(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap__ub_resolve_free(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_result *arg1 = (struct ub_result *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:_ub_resolve_free",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_result, SWIG_POINTER_DISOWN |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "_ub_resolve_free" "', argument " "1"" of type '" "struct ub_result *""'"); 
+  }
+  arg1 = (struct ub_result *)(argp1);
+  ub_resolve_free(arg1);
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_strerror(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  int arg1 ;
+  int val1 ;
+  int ecode1 = 0 ;
+  PyObject * obj0 = 0 ;
+  char *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:ub_strerror",&obj0)) SWIG_fail;
+  ecode1 = SWIG_AsVal_int(obj0, &val1);
+  if (!SWIG_IsOK(ecode1)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "ub_strerror" "', argument " "1"" of type '" "int""'");
+  } 
+  arg1 = (int)(val1);
+  result = (char *)ub_strerror(arg1);
+  resultobj = SWIG_FromCharPtr((const char *)result);
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_ctx_print_local_zones(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_ctx *arg1 = (struct ub_ctx *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:ub_ctx_print_local_zones",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_ctx, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_ctx_print_local_zones" "', argument " "1"" of type '" "struct ub_ctx *""'"); 
+  }
+  arg1 = (struct ub_ctx *)(argp1);
+  result = (int)ub_ctx_print_local_zones(arg1);
+  resultobj = SWIG_From_int((int)(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_ctx_zone_add(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_ctx *arg1 = (struct ub_ctx *) 0 ;
+  char *arg2 = (char *) 0 ;
+  char *arg3 = (char *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  int res3 ;
+  char *buf3 = 0 ;
+  int alloc3 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOO:ub_ctx_zone_add",&obj0,&obj1,&obj2)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_ctx, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_ctx_zone_add" "', argument " "1"" of type '" "struct ub_ctx *""'"); 
+  }
+  arg1 = (struct ub_ctx *)(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ub_ctx_zone_add" "', argument " "2"" of type '" "char *""'");
+  }
+  arg2 = (char *)(buf2);
+  res3 = SWIG_AsCharPtrAndSize(obj2, &buf3, NULL, &alloc3);
+  if (!SWIG_IsOK(res3)) {
+    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "ub_ctx_zone_add" "', argument " "3"" of type '" "char *""'");
+  }
+  arg3 = (char *)(buf3);
+  result = (int)ub_ctx_zone_add(arg1,arg2,arg3);
+  resultobj = SWIG_From_int((int)(result));
+  if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
+  if (alloc3 == SWIG_NEWOBJ) free((char*)buf3);
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
+  if (alloc3 == SWIG_NEWOBJ) free((char*)buf3);
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_ctx_zone_remove(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_ctx *arg1 = (struct ub_ctx *) 0 ;
+  char *arg2 = (char *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:ub_ctx_zone_remove",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_ctx, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_ctx_zone_remove" "', argument " "1"" of type '" "struct ub_ctx *""'"); 
+  }
+  arg1 = (struct ub_ctx *)(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ub_ctx_zone_remove" "', argument " "2"" of type '" "char *""'");
+  }
+  arg2 = (char *)(buf2);
+  result = (int)ub_ctx_zone_remove(arg1,arg2);
+  resultobj = SWIG_From_int((int)(result));
+  if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_ctx_data_add(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_ctx *arg1 = (struct ub_ctx *) 0 ;
+  char *arg2 = (char *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:ub_ctx_data_add",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_ctx, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_ctx_data_add" "', argument " "1"" of type '" "struct ub_ctx *""'"); 
+  }
+  arg1 = (struct ub_ctx *)(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ub_ctx_data_add" "', argument " "2"" of type '" "char *""'");
+  }
+  arg2 = (char *)(buf2);
+  result = (int)ub_ctx_data_add(arg1,arg2);
+  resultobj = SWIG_From_int((int)(result));
+  if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_ctx_data_remove(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_ctx *arg1 = (struct ub_ctx *) 0 ;
+  char *arg2 = (char *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:ub_ctx_data_remove",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_ctx, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_ctx_data_remove" "', argument " "1"" of type '" "struct ub_ctx *""'"); 
+  }
+  arg1 = (struct ub_ctx *)(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ub_ctx_data_remove" "', argument " "2"" of type '" "char *""'");
+  }
+  arg2 = (char *)(buf2);
+  result = (int)ub_ctx_data_remove(arg1,arg2);
+  resultobj = SWIG_From_int((int)(result));
+  if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *ub_ctx_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *obj;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigregister", &obj)) return NULL;
+  SWIG_TypeNewClientData(SWIGTYPE_p_ub_ctx, SWIG_NewClientData(obj));
+  return SWIG_Py_Void();
+}
+
+SWIGINTERN PyObject *_wrap_ub_ctx_debugout__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_ctx *arg1 = (struct ub_ctx *) 0 ;
+  FILE *arg2 = (FILE *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  FILE *val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:ub_ctx_debugout",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_ctx, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ub_ctx_debugout" "', argument " "1"" of type '" "struct ub_ctx *""'"); 
+  }
+  arg1 = (struct ub_ctx *)(argp1);
+  ecode2 = SWIG_AsValFilePtr(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "ub_ctx_debugout" "', argument " "2"" of type '" "FILE *""'");
+  } 
+  arg2 = (FILE *)(val2);
+  result = (int)ub_ctx_debugout(arg1,arg2);
+  resultobj = SWIG_From_int((int)(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ub_ctx_debugout(PyObject *self, PyObject *args) {
+  int argc;
+  PyObject *argv[3];
+  int ii;
+  
+  if (!PyTuple_Check(args)) SWIG_fail;
+  argc = (int)PyObject_Length(args);
+  for (ii = 0; (ii < argc) && (ii < 2); ii++) {
+    argv[ii] = PyTuple_GET_ITEM(args,ii);
+  }
+  if (argc == 2) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_ub_ctx, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      {
+        int res = SWIG_AsValFilePtr(argv[1], NULL);
+        _v = SWIG_CheckState(res);
+      }
+      if (_v) {
+        return _wrap_ub_ctx_debugout__SWIG_1(self, args);
+      }
+    }
+  }
+  if (argc == 2) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_ub_ctx, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      void *ptr = 0;
+      int res = SWIG_ConvertPtr(argv[1], &ptr, 0, 0);
+      _v = SWIG_CheckState(res);
+      if (_v) {
+        return _wrap_ub_ctx_debugout__SWIG_0(self, args);
+      }
+    }
+  }
+  
+fail:
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number of arguments for overloaded function 'ub_ctx_debugout'.\n"
+    "  Possible C/C++ prototypes are:\n"
+    "    ub_ctx_debugout(struct ub_ctx *,void *)\n"
+    "    ub_ctx_debugout(struct ub_ctx *,FILE *)\n");
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap__ub_resolve_async(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  struct ub_ctx *arg1 = (struct ub_ctx *) 0 ;
+  char *arg2 = (char *) 0 ;
+  int arg3 ;
+  int arg4 ;
+  void *arg5 = (void *) 0 ;
+  PyObject *arg6 = (PyObject *) 0 ;
+  int *arg7 = (int *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  int val3 ;
+  int ecode3 = 0 ;
+  int val4 ;
+  int ecode4 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  PyObject * obj5 = 0 ;
+  int result;
+  
+  int asyncid = -1;
+  arg7 = &asyncid;
+  if (!PyArg_ParseTuple(args,(char *)"OOOOOO:_ub_resolve_async",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ub_ctx, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "_ub_resolve_async" "', argument " "1"" of type '" "struct ub_ctx *""'"); 
+  }
+  arg1 = (struct ub_ctx *)(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "_ub_resolve_async" "', argument " "2"" of type '" "char *""'");
+  }
+  arg2 = (char *)(buf2);
+  ecode3 = SWIG_AsVal_int(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "_ub_resolve_async" "', argument " "3"" of type '" "int""'");
+  } 
+  arg3 = (int)(val3);
+  ecode4 = SWIG_AsVal_int(obj3, &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "_ub_resolve_async" "', argument " "4"" of type '" "int""'");
+  } 
+  arg4 = (int)(val4);
+  arg5 = obj4;
+  {
+    if (!PyCallable_Check(obj5)) 
+    {
+      PyErr_SetString(PyExc_TypeError, "Need a callable object!");
+      return NULL;
+    }
+    arg6 = obj5;
+  }
+  result = (int)_ub_resolve_async(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+  resultobj = SWIG_From_int((int)(result));
+  PyObject* tuple;
+  tuple = PyTuple_New(2);
+  PyTuple_SetItem(tuple, 0, resultobj);
+  PyTuple_SetItem(tuple, 1, SWIG_From_int(asyncid));
+  resultobj = tuple;
+  if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
+  return NULL;
+}
+
+
+static PyMethodDef SwigMethods[] = {
+        { (char *)"SWIG_PyInstanceMethod_New", (PyCFunction)SWIG_PyInstanceMethod_New, METH_O, NULL},
+        { (char *)"ub_ctx_free_dbg", _wrap_ub_ctx_free_dbg, METH_VARARGS, NULL},
+        { (char *)"ub_resolve_free_dbg", _wrap_ub_resolve_free_dbg, METH_VARARGS, NULL},
+        { (char *)"ub_result_qname_set", _wrap_ub_result_qname_set, METH_VARARGS, NULL},
+        { (char *)"ub_result_qname_get", _wrap_ub_result_qname_get, METH_VARARGS, NULL},
+        { (char *)"ub_result_qtype_set", _wrap_ub_result_qtype_set, METH_VARARGS, NULL},
+        { (char *)"ub_result_qtype_get", _wrap_ub_result_qtype_get, METH_VARARGS, NULL},
+        { (char *)"ub_result_qclass_set", _wrap_ub_result_qclass_set, METH_VARARGS, NULL},
+        { (char *)"ub_result_qclass_get", _wrap_ub_result_qclass_get, METH_VARARGS, NULL},
+        { (char *)"ub_result__data_set", _wrap_ub_result__data_set, METH_VARARGS, NULL},
+        { (char *)"ub_result__data_get", _wrap_ub_result__data_get, METH_VARARGS, NULL},
+        { (char *)"ub_result_len_set", _wrap_ub_result_len_set, METH_VARARGS, NULL},
+        { (char *)"ub_result_len_get", _wrap_ub_result_len_get, METH_VARARGS, NULL},
+        { (char *)"ub_result_canonname_set", _wrap_ub_result_canonname_set, METH_VARARGS, NULL},
+        { (char *)"ub_result_canonname_get", _wrap_ub_result_canonname_get, METH_VARARGS, NULL},
+        { (char *)"ub_result_rcode_set", _wrap_ub_result_rcode_set, METH_VARARGS, NULL},
+        { (char *)"ub_result_rcode_get", _wrap_ub_result_rcode_get, METH_VARARGS, NULL},
+        { (char *)"ub_result_answer_packet_set", _wrap_ub_result_answer_packet_set, METH_VARARGS, NULL},
+        { (char *)"ub_result_answer_packet_get", _wrap_ub_result_answer_packet_get, METH_VARARGS, NULL},
+        { (char *)"ub_result_answer_len_set", _wrap_ub_result_answer_len_set, METH_VARARGS, NULL},
+        { (char *)"ub_result_answer_len_get", _wrap_ub_result_answer_len_get, METH_VARARGS, NULL},
+        { (char *)"ub_result_havedata_set", _wrap_ub_result_havedata_set, METH_VARARGS, NULL},
+        { (char *)"ub_result_havedata_get", _wrap_ub_result_havedata_get, METH_VARARGS, NULL},
+        { (char *)"ub_result_nxdomain_set", _wrap_ub_result_nxdomain_set, METH_VARARGS, NULL},
+        { (char *)"ub_result_nxdomain_get", _wrap_ub_result_nxdomain_get, METH_VARARGS, NULL},
+        { (char *)"ub_result_secure_set", _wrap_ub_result_secure_set, METH_VARARGS, NULL},
+        { (char *)"ub_result_secure_get", _wrap_ub_result_secure_get, METH_VARARGS, NULL},
+        { (char *)"ub_result_bogus_set", _wrap_ub_result_bogus_set, METH_VARARGS, NULL},
+        { (char *)"ub_result_bogus_get", _wrap_ub_result_bogus_get, METH_VARARGS, NULL},
+        { (char *)"ub_result__ub_result_data", _wrap_ub_result__ub_result_data, METH_VARARGS, NULL},
+        { (char *)"ub_result_swigregister", ub_result_swigregister, METH_VARARGS, NULL},
+        { (char *)"ub_ctx_create", _wrap_ub_ctx_create, METH_VARARGS, NULL},
+        { (char *)"_ub_ctx_delete", _wrap__ub_ctx_delete, METH_VARARGS, NULL},
+        { (char *)"ub_ctx_set_option", _wrap_ub_ctx_set_option, METH_VARARGS, NULL},
+        { (char *)"ub_ctx_config", _wrap_ub_ctx_config, METH_VARARGS, NULL},
+        { (char *)"ub_ctx_set_fwd", _wrap_ub_ctx_set_fwd, METH_VARARGS, NULL},
+        { (char *)"ub_ctx_resolvconf", _wrap_ub_ctx_resolvconf, METH_VARARGS, NULL},
+        { (char *)"ub_ctx_hosts", _wrap_ub_ctx_hosts, METH_VARARGS, NULL},
+        { (char *)"ub_ctx_add_ta", _wrap_ub_ctx_add_ta, METH_VARARGS, NULL},
+        { (char *)"ub_ctx_add_ta_file", _wrap_ub_ctx_add_ta_file, METH_VARARGS, NULL},
+        { (char *)"ub_ctx_trustedkeys", _wrap_ub_ctx_trustedkeys, METH_VARARGS, NULL},
+        { (char *)"ub_ctx_debuglevel", _wrap_ub_ctx_debuglevel, METH_VARARGS, NULL},
+        { (char *)"ub_ctx_async", _wrap_ub_ctx_async, METH_VARARGS, NULL},
+        { (char *)"ub_poll", _wrap_ub_poll, METH_VARARGS, NULL},
+        { (char *)"ub_wait", _wrap_ub_wait, METH_VARARGS, NULL},
+        { (char *)"ub_fd", _wrap_ub_fd, METH_VARARGS, NULL},
+        { (char *)"ub_process", _wrap_ub_process, METH_VARARGS, NULL},
+        { (char *)"ub_resolve", _wrap_ub_resolve, METH_VARARGS, NULL},
+        { (char *)"ub_resolve_async", _wrap_ub_resolve_async, METH_VARARGS, NULL},
+        { (char *)"ub_cancel", _wrap_ub_cancel, METH_VARARGS, NULL},
+        { (char *)"_ub_resolve_free", _wrap__ub_resolve_free, METH_VARARGS, NULL},
+        { (char *)"ub_strerror", _wrap_ub_strerror, METH_VARARGS, NULL},
+        { (char *)"ub_ctx_print_local_zones", _wrap_ub_ctx_print_local_zones, METH_VARARGS, NULL},
+        { (char *)"ub_ctx_zone_add", _wrap_ub_ctx_zone_add, METH_VARARGS, NULL},
+        { (char *)"ub_ctx_zone_remove", _wrap_ub_ctx_zone_remove, METH_VARARGS, NULL},
+        { (char *)"ub_ctx_data_add", _wrap_ub_ctx_data_add, METH_VARARGS, NULL},
+        { (char *)"ub_ctx_data_remove", _wrap_ub_ctx_data_remove, METH_VARARGS, NULL},
+        { (char *)"ub_ctx_swigregister", ub_ctx_swigregister, METH_VARARGS, NULL},
+        { (char *)"ub_ctx_debugout", _wrap_ub_ctx_debugout, METH_VARARGS, NULL},
+        { (char *)"_ub_resolve_async", _wrap__ub_resolve_async, METH_VARARGS, NULL},
+        { NULL, NULL, 0, NULL }
+};
+
+
+/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */
+
+static swig_type_info _swigt__p_FILE = {"_p_FILE", "FILE *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_char = {"_p_char", "char *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_f_p_void_int_p_struct_ub_result__void = {"_p_f_p_void_int_p_struct_ub_result__void", "void (*)(void *,int,struct ub_result *)|ub_callback_t", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_int = {"_p_int", "int *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_p_char = {"_p_p_char", "char **", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_p_ub_result = {"_p_p_ub_result", "struct ub_result **", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_ub_ctx = {"_p_ub_ctx", "struct ub_ctx *|ub_ctx *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_ub_result = {"_p_ub_result", "struct ub_result *|ub_result *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_void = {"_p_void", "void *", 0, 0, (void*)0, 0};
+
+static swig_type_info *swig_type_initial[] = {
+  &_swigt__p_FILE,
+  &_swigt__p_char,
+  &_swigt__p_f_p_void_int_p_struct_ub_result__void,
+  &_swigt__p_int,
+  &_swigt__p_p_char,
+  &_swigt__p_p_ub_result,
+  &_swigt__p_ub_ctx,
+  &_swigt__p_ub_result,
+  &_swigt__p_void,
+};
+
+static swig_cast_info _swigc__p_FILE[] = {  {&_swigt__p_FILE, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_char[] = {  {&_swigt__p_char, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_f_p_void_int_p_struct_ub_result__void[] = {  {&_swigt__p_f_p_void_int_p_struct_ub_result__void, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_int[] = {  {&_swigt__p_int, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_p_char[] = {  {&_swigt__p_p_char, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_p_ub_result[] = {  {&_swigt__p_p_ub_result, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_ub_ctx[] = {  {&_swigt__p_ub_ctx, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_ub_result[] = {  {&_swigt__p_ub_result, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_void[] = {  {&_swigt__p_void, 0, 0, 0},{0, 0, 0, 0}};
+
+static swig_cast_info *swig_cast_initial[] = {
+  _swigc__p_FILE,
+  _swigc__p_char,
+  _swigc__p_f_p_void_int_p_struct_ub_result__void,
+  _swigc__p_int,
+  _swigc__p_p_char,
+  _swigc__p_p_ub_result,
+  _swigc__p_ub_ctx,
+  _swigc__p_ub_result,
+  _swigc__p_void,
+};
+
+
+/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (END) -------- */
+
+static swig_const_info swig_const_table[] = {
+{0, 0, 0, 0.0, 0, 0}};
+
+#ifdef __cplusplus
+}
+#endif
+/* -----------------------------------------------------------------------------
+ * Type initialization:
+ * This problem is tough by the requirement that no dynamic 
+ * memory is used. Also, since swig_type_info structures store pointers to 
+ * swig_cast_info structures and swig_cast_info structures store pointers back
+ * to swig_type_info structures, we need some lookup code at initialization. 
+ * The idea is that swig generates all the structures that are needed. 
+ * The runtime then collects these partially filled structures. 
+ * The SWIG_InitializeModule function takes these initial arrays out of 
+ * swig_module, and does all the lookup, filling in the swig_module.types
+ * array with the correct data and linking the correct swig_cast_info
+ * structures together.
+ *
+ * The generated swig_type_info structures are assigned staticly to an initial 
+ * array. We just loop through that array, and handle each type individually.
+ * First we lookup if this type has been already loaded, and if so, use the
+ * loaded structure instead of the generated one. Then we have to fill in the
+ * cast linked list. The cast data is initially stored in something like a
+ * two-dimensional array. Each row corresponds to a type (there are the same
+ * number of rows as there are in the swig_type_initial array). Each entry in
+ * a column is one of the swig_cast_info structures for that type.
+ * The cast_initial array is actually an array of arrays, because each row has
+ * a variable number of columns. So to actually build the cast linked list,
+ * we find the array of casts associated with the type, and loop through it 
+ * adding the casts to the list. The one last trick we need to do is making
+ * sure the type pointer in the swig_cast_info struct is correct.
+ *
+ * First off, we lookup the cast->type name to see if it is already loaded. 
+ * There are three cases to handle:
+ *  1) If the cast->type has already been loaded AND the type we are adding
+ *     casting info to has not been loaded (it is in this module), THEN we
+ *     replace the cast->type pointer with the type pointer that has already
+ *     been loaded.
+ *  2) If BOTH types (the one we are adding casting info to, and the 
+ *     cast->type) are loaded, THEN the cast info has already been loaded by
+ *     the previous module so we just ignore it.
+ *  3) Finally, if cast->type has not already been loaded, then we add that
+ *     swig_cast_info to the linked list (because the cast->type) pointer will
+ *     be correct.
+ * ----------------------------------------------------------------------------- */
+
+#ifdef __cplusplus
+extern "C" {
+#if 0
+} /* c-mode */
+#endif
+#endif
+
+#if 0
+#define SWIGRUNTIME_DEBUG
+#endif
+
+
+SWIGRUNTIME void
+SWIG_InitializeModule(void *clientdata) {
+  size_t i;
+  swig_module_info *module_head, *iter;
+  int found, init;
+  
+  clientdata = clientdata;
+  
+  /* check to see if the circular list has been setup, if not, set it up */
+  if (swig_module.next==0) {
+    /* Initialize the swig_module */
+    swig_module.type_initial = swig_type_initial;
+    swig_module.cast_initial = swig_cast_initial;
+    swig_module.next = &swig_module;
+    init = 1;
+  } else {
+    init = 0;
+  }
+  
+  /* Try and load any already created modules */
+  module_head = SWIG_GetModule(clientdata);
+  if (!module_head) {
+    /* This is the first module loaded for this interpreter */
+    /* so set the swig module into the interpreter */
+    SWIG_SetModule(clientdata, &swig_module);
+    module_head = &swig_module;
+  } else {
+    /* the interpreter has loaded a SWIG module, but has it loaded this one? */
+    found=0;
+    iter=module_head;
+    do {
+      if (iter==&swig_module) {
+        found=1;
+        break;
+      }
+      iter=iter->next;
+    } while (iter!= module_head);
+    
+    /* if the is found in the list, then all is done and we may leave */
+    if (found) return;
+    /* otherwise we must add out module into the list */
+    swig_module.next = module_head->next;
+    module_head->next = &swig_module;
+  }
+  
+  /* When multiple interpeters are used, a module could have already been initialized in
+       a different interpreter, but not yet have a pointer in this interpreter.
+       In this case, we do not want to continue adding types... everything should be
+       set up already */
+  if (init == 0) return;
+  
+  /* Now work on filling in swig_module.types */
+#ifdef SWIGRUNTIME_DEBUG
+  printf("SWIG_InitializeModule: size %d\n", swig_module.size);
+#endif
+  for (i = 0; i < swig_module.size; ++i) {
+    swig_type_info *type = 0;
+    swig_type_info *ret;
+    swig_cast_info *cast;
+    
+#ifdef SWIGRUNTIME_DEBUG
+    printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name);
+#endif
+    
+    /* if there is another module already loaded */
+    if (swig_module.next != &swig_module) {
+      type = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, swig_module.type_initial[i]->name);
+    }
+    if (type) {
+      /* Overwrite clientdata field */
+#ifdef SWIGRUNTIME_DEBUG
+      printf("SWIG_InitializeModule: found type %s\n", type->name);
+#endif
+      if (swig_module.type_initial[i]->clientdata) {
+        type->clientdata = swig_module.type_initial[i]->clientdata;
+#ifdef SWIGRUNTIME_DEBUG
+        printf("SWIG_InitializeModule: found and overwrite type %s \n", type->name);
+#endif
+      }
+    } else {
+      type = swig_module.type_initial[i];
+    }
+    
+    /* Insert casting types */
+    cast = swig_module.cast_initial[i];
+    while (cast->type) {
+      /* Don't need to add information already in the list */
+      ret = 0;
+#ifdef SWIGRUNTIME_DEBUG
+      printf("SWIG_InitializeModule: look cast %s\n", cast->type->name);
+#endif
+      if (swig_module.next != &swig_module) {
+        ret = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, cast->type->name);
+#ifdef SWIGRUNTIME_DEBUG
+        if (ret) printf("SWIG_InitializeModule: found cast %s\n", ret->name);
+#endif
+      }
+      if (ret) {
+        if (type == swig_module.type_initial[i]) {
+#ifdef SWIGRUNTIME_DEBUG
+          printf("SWIG_InitializeModule: skip old type %s\n", ret->name);
+#endif
+          cast->type = ret;
+          ret = 0;
+        } else {
+          /* Check for casting already in the list */
+          swig_cast_info *ocast = SWIG_TypeCheck(ret->name, type);
+#ifdef SWIGRUNTIME_DEBUG
+          if (ocast) printf("SWIG_InitializeModule: skip old cast %s\n", ret->name);
+#endif
+          if (!ocast) ret = 0;
+        }
+      }
+      
+      if (!ret) {
+#ifdef SWIGRUNTIME_DEBUG
+        printf("SWIG_InitializeModule: adding cast %s\n", cast->type->name);
+#endif
+        if (type->cast) {
+          type->cast->prev = cast;
+          cast->next = type->cast;
+        }
+        type->cast = cast;
+      }
+      cast++;
+    }
+    /* Set entry in modules->types array equal to the type */
+    swig_module.types[i] = type;
+  }
+  swig_module.types[i] = 0;
+  
+#ifdef SWIGRUNTIME_DEBUG
+  printf("**** SWIG_InitializeModule: Cast List ******\n");
+  for (i = 0; i < swig_module.size; ++i) {
+    int j = 0;
+    swig_cast_info *cast = swig_module.cast_initial[i];
+    printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name);
+    while (cast->type) {
+      printf("SWIG_InitializeModule: cast type %s\n", cast->type->name);
+      cast++;
+      ++j;
+    }
+    printf("---- Total casts: %d\n",j);
+  }
+  printf("**** SWIG_InitializeModule: Cast List ******\n");
+#endif
+}
+
+/* This function will propagate the clientdata field of type to
+* any new swig_type_info structures that have been added into the list
+* of equivalent types.  It is like calling
+* SWIG_TypeClientData(type, clientdata) a second time.
+*/
+SWIGRUNTIME void
+SWIG_PropagateClientData(void) {
+  size_t i;
+  swig_cast_info *equiv;
+  static int init_run = 0;
+  
+  if (init_run) return;
+  init_run = 1;
+  
+  for (i = 0; i < swig_module.size; i++) {
+    if (swig_module.types[i]->clientdata) {
+      equiv = swig_module.types[i]->cast;
+      while (equiv) {
+        if (!equiv->converter) {
+          if (equiv->type && !equiv->type->clientdata)
+          SWIG_TypeClientData(equiv->type, swig_module.types[i]->clientdata);
+        }
+        equiv = equiv->next;
+      }
+    }
+  }
+}
+
+#ifdef __cplusplus
+#if 0
+{
+  /* c-mode */
+#endif
+}
+#endif
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+  
+  /* Python-specific SWIG API */
+#define SWIG_newvarlink()                             SWIG_Python_newvarlink()
+#define SWIG_addvarlink(p, name, get_attr, set_attr)  SWIG_Python_addvarlink(p, name, get_attr, set_attr)
+#define SWIG_InstallConstants(d, constants)           SWIG_Python_InstallConstants(d, constants)
+  
+  /* -----------------------------------------------------------------------------
+   * global variable support code.
+   * ----------------------------------------------------------------------------- */
+  
+  typedef struct swig_globalvar {
+    char       *name;                  /* Name of global variable */
+    PyObject *(*get_attr)(void);       /* Return the current value */
+    int       (*set_attr)(PyObject *); /* Set the value */
+    struct swig_globalvar *next;
+  } swig_globalvar;
+  
+  typedef struct swig_varlinkobject {
+    PyObject_HEAD
+    swig_globalvar *vars;
+  } swig_varlinkobject;
+  
+  SWIGINTERN PyObject *
+  swig_varlink_repr(swig_varlinkobject *SWIGUNUSEDPARM(v)) {
+#if PY_VERSION_HEX >= 0x03000000
+    return PyUnicode_InternFromString("<Swig global variables>");
+#else
+    return PyString_FromString("<Swig global variables>");
+#endif
+  }
+  
+  SWIGINTERN PyObject *
+  swig_varlink_str(swig_varlinkobject *v) {
+#if PY_VERSION_HEX >= 0x03000000
+    PyObject *str = PyUnicode_InternFromString("(");
+    PyObject *tail;
+    PyObject *joined;
+    swig_globalvar *var;
+    for (var = v->vars; var; var=var->next) {
+      tail = PyUnicode_FromString(var->name);
+      joined = PyUnicode_Concat(str, tail);
+      Py_DecRef(str);
+      Py_DecRef(tail);
+      str = joined;
+      if (var->next) {
+        tail = PyUnicode_InternFromString(", ");
+        joined = PyUnicode_Concat(str, tail);
+        Py_DecRef(str);
+        Py_DecRef(tail);
+        str = joined;
+      }
+    }
+    tail = PyUnicode_InternFromString(")");
+    joined = PyUnicode_Concat(str, tail);
+    Py_DecRef(str);
+    Py_DecRef(tail);
+    str = joined;
+#else
+    PyObject *str = PyString_FromString("(");
+    swig_globalvar *var;
+    for (var = v->vars; var; var=var->next) {
+      PyString_ConcatAndDel(&str,PyString_FromString(var->name));
+      if (var->next) PyString_ConcatAndDel(&str,PyString_FromString(", "));
+    }
+    PyString_ConcatAndDel(&str,PyString_FromString(")"));
+#endif
+    return str;
+  }
+  
+  SWIGINTERN int
+  swig_varlink_print(swig_varlinkobject *v, FILE *fp, int SWIGUNUSEDPARM(flags)) {
+    PyObject *str = swig_varlink_str(v);
+    fprintf(fp,"Swig global variables ");
+    fprintf(fp,"%s\n", SWIG_Python_str_AsChar(str));
+    Py_DECREF(str);
+    return 0;
+  }
+  
+  SWIGINTERN void
+  swig_varlink_dealloc(swig_varlinkobject *v) {
+    swig_globalvar *var = v->vars;
+    while (var) {
+      swig_globalvar *n = var->next;
+      free(var->name);
+      free(var);
+      var = n;
+    }
+  }
+  
+  SWIGINTERN PyObject *
+  swig_varlink_getattr(swig_varlinkobject *v, char *n) {
+    PyObject *res = NULL;
+    swig_globalvar *var = v->vars;
+    while (var) {
+      if (strcmp(var->name,n) == 0) {
+        res = (*var->get_attr)();
+        break;
+      }
+      var = var->next;
+    }
+    if (res == NULL && !PyErr_Occurred()) {
+      PyErr_SetString(PyExc_NameError,"Unknown C global variable");
+    }
+    return res;
+  }
+  
+  SWIGINTERN int
+  swig_varlink_setattr(swig_varlinkobject *v, char *n, PyObject *p) {
+    int res = 1;
+    swig_globalvar *var = v->vars;
+    while (var) {
+      if (strcmp(var->name,n) == 0) {
+        res = (*var->set_attr)(p);
+        break;
+      }
+      var = var->next;
+    }
+    if (res == 1 && !PyErr_Occurred()) {
+      PyErr_SetString(PyExc_NameError,"Unknown C global variable");
+    }
+    return res;
+  }
+  
+  SWIGINTERN PyTypeObject*
+  swig_varlink_type(void) {
+    static char varlink__doc__[] = "Swig var link object";
+    static PyTypeObject varlink_type;
+    static int type_init = 0;  
+    if (!type_init) {
+      const PyTypeObject tmp
+      = {
+        /* PyObject header changed in Python 3 */
+#if PY_VERSION_HEX >= 0x03000000
+        PyVarObject_HEAD_INIT(&PyType_Type, 0)
+#else
+        PyObject_HEAD_INIT(NULL)
+        0,                                  /* Number of items in variable part (ob_size) */
+#endif
+        (char *)"swigvarlink",              /* Type name (tp_name) */
+        sizeof(swig_varlinkobject),         /* Basic size (tp_basicsize) */
+        0,                                  /* Itemsize (tp_itemsize) */
+        (destructor) swig_varlink_dealloc,   /* Deallocator (tp_dealloc) */ 
+        (printfunc) swig_varlink_print,     /* Print (tp_print) */
+        (getattrfunc) swig_varlink_getattr, /* get attr (tp_getattr) */
+        (setattrfunc) swig_varlink_setattr, /* Set attr (tp_setattr) */
+        0,                                  /* tp_compare */
+        (reprfunc) swig_varlink_repr,       /* tp_repr */
+        0,                                  /* tp_as_number */
+        0,                                  /* tp_as_sequence */
+        0,                                  /* tp_as_mapping */
+        0,                                  /* tp_hash */
+        0,                                  /* tp_call */
+        (reprfunc)swig_varlink_str,        /* tp_str */
+        0,                                  /* tp_getattro */
+        0,                                  /* tp_setattro */
+        0,                                  /* tp_as_buffer */
+        0,                                  /* tp_flags */
+        varlink__doc__,                     /* tp_doc */
+        0,                                  /* tp_traverse */
+        0,                                  /* tp_clear */
+        0,                                  /* tp_richcompare */
+        0,                                  /* tp_weaklistoffset */
+#if PY_VERSION_HEX >= 0x02020000
+        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* tp_iter -> tp_weaklist */
+#endif
+#if PY_VERSION_HEX >= 0x02030000
+        0,                                  /* tp_del */
+#endif
+#ifdef COUNT_ALLOCS
+        0,0,0,0                             /* tp_alloc -> tp_next */
+#endif
+      };
+      varlink_type = tmp;
+      /* for Python 3 we already assigned the ob_type in PyVarObject_HEAD_INIT() */
+#if PY_VERSION_HEX < 0x03000000
+      varlink_type.ob_type = &PyType_Type;
+#endif
+      type_init = 1;
+    }
+    return &varlink_type;
+  }
+  
+  /* Create a variable linking object for use later */
+  SWIGINTERN PyObject *
+  SWIG_Python_newvarlink(void) {
+    swig_varlinkobject *result = PyObject_NEW(swig_varlinkobject, swig_varlink_type());
+    if (result) {
+      result->vars = 0;
+    }
+    return ((PyObject*) result);
+  }
+  
+  SWIGINTERN void 
+  SWIG_Python_addvarlink(PyObject *p, char *name, PyObject *(*get_attr)(void), int (*set_attr)(PyObject *p)) {
+    swig_varlinkobject *v = (swig_varlinkobject *) p;
+    swig_globalvar *gv = (swig_globalvar *) malloc(sizeof(swig_globalvar));
+    if (gv) {
+      size_t size = strlen(name)+1;
+      gv->name = (char *)malloc(size);
+      if (gv->name) {
+        strncpy(gv->name,name,size);
+        gv->get_attr = get_attr;
+        gv->set_attr = set_attr;
+        gv->next = v->vars;
+      }
+    }
+    v->vars = gv;
+  }
+  
+  SWIGINTERN PyObject *
+  SWIG_globals(void) {
+    static PyObject *_SWIG_globals = 0; 
+    if (!_SWIG_globals) _SWIG_globals = SWIG_newvarlink();  
+    return _SWIG_globals;
+  }
+  
+  /* -----------------------------------------------------------------------------
+   * constants/methods manipulation
+   * ----------------------------------------------------------------------------- */
+  
+  /* Install Constants */
+  SWIGINTERN void
+  SWIG_Python_InstallConstants(PyObject *d, swig_const_info constants[]) {
+    PyObject *obj = 0;
+    size_t i;
+    for (i = 0; constants[i].type; ++i) {
+      switch(constants[i].type) {
+      case SWIG_PY_POINTER:
+        obj = SWIG_NewPointerObj(constants[i].pvalue, *(constants[i]).ptype,0);
+        break;
+      case SWIG_PY_BINARY:
+        obj = SWIG_NewPackedObj(constants[i].pvalue, constants[i].lvalue, *(constants[i].ptype));
+        break;
+      default:
+        obj = 0;
+        break;
+      }
+      if (obj) {
+        PyDict_SetItemString(d, constants[i].name, obj);
+        Py_DECREF(obj);
+      }
+    }
+  }
+  
+  /* -----------------------------------------------------------------------------*/
+  /* Fix SwigMethods to carry the callback ptrs when needed */
+  /* -----------------------------------------------------------------------------*/
+  
+  SWIGINTERN void
+  SWIG_Python_FixMethods(PyMethodDef *methods,
+    swig_const_info *const_table,
+    swig_type_info **types,
+    swig_type_info **types_initial) {
+    size_t i;
+    for (i = 0; methods[i].ml_name; ++i) {
+      const char *c = methods[i].ml_doc;
+      if (c && (c = strstr(c, "swig_ptr: "))) {
+        int j;
+        swig_const_info *ci = 0;
+        const char *name = c + 10;
+        for (j = 0; const_table[j].type; ++j) {
+          if (strncmp(const_table[j].name, name, 
+              strlen(const_table[j].name)) == 0) {
+            ci = &(const_table[j]);
+            break;
+          }
+        }
+        if (ci) {
+          size_t shift = (ci->ptype) - types;
+          swig_type_info *ty = types_initial[shift];
+          size_t ldoc = (c - methods[i].ml_doc);
+          size_t lptr = strlen(ty->name)+2*sizeof(void*)+2;
+          char *ndoc = (char*)malloc(ldoc + lptr + 10);
+          if (ndoc) {
+            char *buff = ndoc;
+            void *ptr = (ci->type == SWIG_PY_POINTER) ? ci->pvalue : 0;
+            if (ptr) {
+              strncpy(buff, methods[i].ml_doc, ldoc);
+              buff += ldoc;
+              strncpy(buff, "swig_ptr: ", 10);
+              buff += 10;
+              SWIG_PackVoidPtr(buff, ptr, ty->name, lptr);
+              methods[i].ml_doc = ndoc;
+            }
+          }
+        }
+      }
+    }
+  } 
+  
+#ifdef __cplusplus
+}
+#endif
+
+/* -----------------------------------------------------------------------------*
+ *  Partial Init method
+ * -----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+#endif
+
+SWIGEXPORT 
+#if PY_VERSION_HEX >= 0x03000000
+PyObject*
+#else
+void
+#endif
+SWIG_init(void) {
+  PyObject *m, *d;
+  
+  /* Fix SwigMethods to carry the callback ptrs when needed */
+  SWIG_Python_FixMethods(SwigMethods, swig_const_table, swig_types, swig_type_initial);
+#if PY_VERSION_HEX >= 0x03000000
+  static struct PyModuleDef SWIG_module = {
+    PyModuleDef_HEAD_INIT,
+    (char *) SWIG_name,
+    NULL,
+    -1,
+    SwigMethods,
+    NULL,
+    NULL,
+    NULL,
+    NULL
+  };
+  
+  m = PyModule_Create(&SWIG_module);
+#else
+  m = Py_InitModule((char *) SWIG_name, SwigMethods);
+#endif
+  d = PyModule_GetDict(m);
+  
+  SWIG_InitializeModule(0);
+  SWIG_InstallConstants(d,swig_const_table);
+  
+  
+  SWIG_Python_SetConstant(d, "RR_TYPE_A",SWIG_From_int((int)(RR_TYPE_A)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_NS",SWIG_From_int((int)(RR_TYPE_NS)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_MD",SWIG_From_int((int)(RR_TYPE_MD)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_MF",SWIG_From_int((int)(RR_TYPE_MF)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_CNAME",SWIG_From_int((int)(RR_TYPE_CNAME)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_SOA",SWIG_From_int((int)(RR_TYPE_SOA)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_MB",SWIG_From_int((int)(RR_TYPE_MB)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_MG",SWIG_From_int((int)(RR_TYPE_MG)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_MR",SWIG_From_int((int)(RR_TYPE_MR)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_NULL",SWIG_From_int((int)(RR_TYPE_NULL)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_WKS",SWIG_From_int((int)(RR_TYPE_WKS)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_PTR",SWIG_From_int((int)(RR_TYPE_PTR)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_HINFO",SWIG_From_int((int)(RR_TYPE_HINFO)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_MINFO",SWIG_From_int((int)(RR_TYPE_MINFO)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_MX",SWIG_From_int((int)(RR_TYPE_MX)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_TXT",SWIG_From_int((int)(RR_TYPE_TXT)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_RP",SWIG_From_int((int)(RR_TYPE_RP)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_AFSDB",SWIG_From_int((int)(RR_TYPE_AFSDB)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_X25",SWIG_From_int((int)(RR_TYPE_X25)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_ISDN",SWIG_From_int((int)(RR_TYPE_ISDN)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_RT",SWIG_From_int((int)(RR_TYPE_RT)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_NSAP",SWIG_From_int((int)(RR_TYPE_NSAP)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_NSAP_PTR",SWIG_From_int((int)(RR_TYPE_NSAP_PTR)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_SIG",SWIG_From_int((int)(RR_TYPE_SIG)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_KEY",SWIG_From_int((int)(RR_TYPE_KEY)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_PX",SWIG_From_int((int)(RR_TYPE_PX)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_GPOS",SWIG_From_int((int)(RR_TYPE_GPOS)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_AAAA",SWIG_From_int((int)(RR_TYPE_AAAA)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_LOC",SWIG_From_int((int)(RR_TYPE_LOC)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_NXT",SWIG_From_int((int)(RR_TYPE_NXT)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_EID",SWIG_From_int((int)(RR_TYPE_EID)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_NIMLOC",SWIG_From_int((int)(RR_TYPE_NIMLOC)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_SRV",SWIG_From_int((int)(RR_TYPE_SRV)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_ATMA",SWIG_From_int((int)(RR_TYPE_ATMA)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_NAPTR",SWIG_From_int((int)(RR_TYPE_NAPTR)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_KX",SWIG_From_int((int)(RR_TYPE_KX)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_CERT",SWIG_From_int((int)(RR_TYPE_CERT)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_A6",SWIG_From_int((int)(RR_TYPE_A6)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_DNAME",SWIG_From_int((int)(RR_TYPE_DNAME)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_SINK",SWIG_From_int((int)(RR_TYPE_SINK)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_OPT",SWIG_From_int((int)(RR_TYPE_OPT)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_APL",SWIG_From_int((int)(RR_TYPE_APL)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_DS",SWIG_From_int((int)(RR_TYPE_DS)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_SSHFP",SWIG_From_int((int)(RR_TYPE_SSHFP)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_IPSECKEY",SWIG_From_int((int)(RR_TYPE_IPSECKEY)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_RRSIG",SWIG_From_int((int)(RR_TYPE_RRSIG)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_NSEC",SWIG_From_int((int)(RR_TYPE_NSEC)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_DNSKEY",SWIG_From_int((int)(RR_TYPE_DNSKEY)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_DHCID",SWIG_From_int((int)(RR_TYPE_DHCID)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_NSEC3",SWIG_From_int((int)(RR_TYPE_NSEC3)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_NSEC3PARAMS",SWIG_From_int((int)(RR_TYPE_NSEC3PARAMS)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_UINFO",SWIG_From_int((int)(RR_TYPE_UINFO)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_UID",SWIG_From_int((int)(RR_TYPE_UID)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_GID",SWIG_From_int((int)(RR_TYPE_GID)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_UNSPEC",SWIG_From_int((int)(RR_TYPE_UNSPEC)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_TSIG",SWIG_From_int((int)(RR_TYPE_TSIG)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_IXFR",SWIG_From_int((int)(RR_TYPE_IXFR)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_AXFR",SWIG_From_int((int)(RR_TYPE_AXFR)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_MAILB",SWIG_From_int((int)(RR_TYPE_MAILB)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_MAILA",SWIG_From_int((int)(RR_TYPE_MAILA)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_ANY",SWIG_From_int((int)(RR_TYPE_ANY)));
+  SWIG_Python_SetConstant(d, "RR_TYPE_DLV",SWIG_From_int((int)(RR_TYPE_DLV)));
+  SWIG_Python_SetConstant(d, "RR_CLASS_IN",SWIG_From_int((int)(RR_CLASS_IN)));
+  SWIG_Python_SetConstant(d, "RR_CLASS_CH",SWIG_From_int((int)(RR_CLASS_CH)));
+  SWIG_Python_SetConstant(d, "RR_CLASS_HS",SWIG_From_int((int)(RR_CLASS_HS)));
+  SWIG_Python_SetConstant(d, "RR_CLASS_NONE",SWIG_From_int((int)(RR_CLASS_NONE)));
+  SWIG_Python_SetConstant(d, "RR_CLASS_ANY",SWIG_From_int((int)(RR_CLASS_ANY)));
+  SWIG_Python_SetConstant(d, "RCODE_NOERROR",SWIG_From_int((int)(RCODE_NOERROR)));
+  SWIG_Python_SetConstant(d, "RCODE_FORMERR",SWIG_From_int((int)(RCODE_FORMERR)));
+  SWIG_Python_SetConstant(d, "RCODE_SERVFAIL",SWIG_From_int((int)(RCODE_SERVFAIL)));
+  SWIG_Python_SetConstant(d, "RCODE_NXDOMAIN",SWIG_From_int((int)(RCODE_NXDOMAIN)));
+  SWIG_Python_SetConstant(d, "RCODE_NOTIMPL",SWIG_From_int((int)(RCODE_NOTIMPL)));
+  SWIG_Python_SetConstant(d, "RCODE_REFUSED",SWIG_From_int((int)(RCODE_REFUSED)));
+  SWIG_Python_SetConstant(d, "RCODE_YXDOMAIN",SWIG_From_int((int)(RCODE_YXDOMAIN)));
+  SWIG_Python_SetConstant(d, "RCODE_YXRRSET",SWIG_From_int((int)(RCODE_YXRRSET)));
+  SWIG_Python_SetConstant(d, "RCODE_NXRRSET",SWIG_From_int((int)(RCODE_NXRRSET)));
+  SWIG_Python_SetConstant(d, "RCODE_NOTAUTH",SWIG_From_int((int)(RCODE_NOTAUTH)));
+  SWIG_Python_SetConstant(d, "RCODE_NOTZONE",SWIG_From_int((int)(RCODE_NOTZONE)));
+#if PY_VERSION_HEX >= 0x03000000
+  return m;
+#else
+  return;
+#endif
+}
+
index c512a8a1ae1e7b973c2d84cc7f3d1371916cab80..83b250de5e1050029c9f847cb2e010572ffd60b2 100644 (file)
@@ -11,6 +11,6 @@ At NLnet Labs, Jelte Jansen, Mark Santcroos and Matthijs Mekking
 reviewed the unbound C sources.
 
 Jakob Schlyter - for advice on secure settings, random numbers and blacklists.
-
 Ondřej Surý - running coverity analysis tool on 0.9 dev version.
 Alexander Gall - multihomed, anycast testing of unbound resolver server.
+Zdenek Vasicek and Marek Vavrusa - python module.
index 0a93ac4cb4c4ce28bf9b4eb0307f6f97f39d167c..ac8e92cfa7ba33cd845bdbab7a560ffec8e61282 100644 (file)
@@ -1,3 +1,7 @@
+25 March 2009: Wouter
+       - initial import of the python contribution from Zdenek Vasicek and
+         Marek Vavrusa.
+
 24 March 2009: Wouter
        - more neat configure.ac. Removed duplicate config.h includes.
        - neater config.h.in.
index 119aecd384459e0c899cbffff87a544040dfaf8d..52386ddd1a670d146b1d38d355e161740fb8a6eb 100644 (file)
@@ -386,6 +386,11 @@ server:
        # you need to do the reverse notation yourself.
        # local-data-ptr: "192.0.2.3 www.example.com"
 
+# Python config section, list python in the module-config string to enable.
+python:
+       # Script file to load
+       python-script: "@UNBOUND_SHARE_DIR@/ubmodule-tst.py"
+
 # Remote control config section. 
 remote-control:
        # Enable remote control with unbound-control(8) here.
index 066fe50516b086f3b4d5378c7d9a1dbdedbdae69..2baaeb3a2225d4eef6cab7078e00b2ea431c3895 100644 (file)
@@ -913,7 +913,7 @@ MAN_LINKS              = NO
 # generate an XML file that captures the structure of 
 # the code including all documentation.
 
-GENERATE_XML           = NO
+GENERATE_XML           = YES
 
 # The XML_OUTPUT tag is used to specify where the XML pages will be put. 
 # If a relative path is entered the value of OUTPUT_DIRECTORY will be 
index 9c5c79fcf71a569ae82ffd159d76a9a67194a2dd..4daa313015416a88ed0a10b48e892985a2d98a75 100644 (file)
@@ -906,3 +906,123 @@ ub_ctx_hosts(struct ub_ctx* ctx, char* fname)
        fclose(in);
        return UB_NOERROR;
 }
+
+static int ub_ctx_check_finalize(struct ub_ctx* ctx)
+{
+    int res = 0;
+    lock_basic_lock(&ctx->cfglock);
+    if (!ctx->finalized) {
+       res = context_finalize(ctx);
+    }
+    lock_basic_unlock(&ctx->cfglock);
+    return res;
+}
+
+/** Print local zones and RR data */
+int ub_ctx_print_local_zones(struct ub_ctx* ctx)
+{   
+    int res = ub_ctx_check_finalize(ctx);
+    if (res) return res;
+
+    local_zones_print(ctx->local_zones);
+
+    return UB_NOERROR;
+}
+
+/** Add a new zone */
+int ub_ctx_zone_add(struct ub_ctx* ctx, char *zone_name, char *zone_type)
+{
+       enum localzone_type t;
+       struct local_zone* z;
+       uint8_t* nm;
+       int nmlabs;
+       size_t nmlen;
+
+    int res = ub_ctx_check_finalize(ctx);
+    if (res) return res;
+
+       if(!local_zone_str2type(zone_type, &t)) {
+        return UB_SYNTAX;
+    }
+
+       if(!parse_dname(zone_name, &nm, &nmlen, &nmlabs)) {
+               return UB_SYNTAX;
+    }
+
+       lock_quick_lock(&ctx->local_zones->lock);
+       if((z=local_zones_find(ctx->local_zones, nm, nmlen, nmlabs, LDNS_RR_CLASS_IN))) {
+               /* already present in tree */
+               lock_rw_wrlock(&z->lock);
+               z->type = t; /* update type anyway */
+               lock_rw_unlock(&z->lock);
+               free(nm);
+               lock_quick_unlock(&ctx->local_zones->lock);
+               return UB_NOERROR;
+       }
+       if(!local_zones_add_zone(ctx->local_zones, nm, nmlen, nmlabs, LDNS_RR_CLASS_IN, t)) {
+               lock_quick_unlock(&ctx->local_zones->lock);
+               return UB_NOMEM;
+       }
+       lock_quick_unlock(&ctx->local_zones->lock);
+    return UB_NOERROR;
+}
+
+/** Remove zone */
+int ub_ctx_zone_remove(struct ub_ctx* ctx, char *zone_name)
+{   
+       struct local_zone* z;
+    uint8_t* nm;
+       int nmlabs;
+       size_t nmlen;
+
+    int res = ub_ctx_check_finalize(ctx);
+    if (res) return res;
+
+       if(!parse_dname(zone_name, &nm, &nmlen, &nmlabs)) {
+               return UB_SYNTAX;
+    }
+
+       lock_quick_lock(&ctx->local_zones->lock);
+       if((z=local_zones_find(ctx->local_zones, nm, nmlen, nmlabs, LDNS_RR_CLASS_IN))) {
+               /* present in tree */
+               local_zones_del_zone(ctx->local_zones, z);
+       }
+       free(nm);
+       lock_quick_unlock(&ctx->local_zones->lock);
+    return UB_NOERROR;
+}
+
+/** Add new RR data */
+int ub_ctx_data_add(struct ub_ctx* ctx, char *data)
+{
+    ldns_buffer* buf;
+    int res = ub_ctx_check_finalize(ctx);
+    if (res) return res;
+
+       lock_basic_lock(&ctx->cfglock);
+    buf = ldns_buffer_new(ctx->env->cfg->msg_buffer_size);
+       lock_basic_unlock(&ctx->cfglock);
+
+    res = local_zones_add_RR(ctx->local_zones, data, buf);
+
+    ldns_buffer_free(buf);
+    return (!res) ? UB_NOMEM : UB_NOERROR;
+}
+
+/* Remove RR data */
+int ub_ctx_data_remove(struct ub_ctx* ctx, char *data)
+{
+    uint8_t* nm;
+       int nmlabs;
+       size_t nmlen;
+    int res = ub_ctx_check_finalize(ctx);
+    if (res) return res;
+
+       if(!parse_dname(data, &nm, &nmlen, &nmlabs)) 
+               return UB_SYNTAX;
+
+       local_zones_del_data(ctx->local_zones, nm, nmlen, nmlabs, LDNS_RR_CLASS_IN);
+
+    free(nm);
+    return UB_NOERROR;
+}
index 7a8c5852fd6c84d58a2da617146e57e2a6749841..0d50a2b9e3620160edee5b2088decfcb3900e96c 100644 (file)
@@ -20,3 +20,8 @@ ub_resolve_async
 ub_cancel
 ub_resolve_free
 ub_strerror
+ub_ctx_print_local_zones
+ub_ctx_zone_add
+ub_ctx_zone_remove
+ub_ctx_data_add
+ub_ctx_data_remove
index e9e5f6ebcf80f567dbe6bfe57b10aa2ff5ba488c..7a7a31fa93171d67939e57d871c577cc1bf83526 100644 (file)
@@ -470,4 +470,10 @@ void ub_resolve_free(struct ub_result* result);
  */
 const char* ub_strerror(int err);
 
+int ub_ctx_print_local_zones(struct ub_ctx* ctx);
+int ub_ctx_zone_add(struct ub_ctx* ctx, char *zone_name, char *zone_type);
+int ub_ctx_zone_remove(struct ub_ctx* ctx, char *zone_name);
+int ub_ctx_data_add(struct ub_ctx* ctx, char *data);
+int ub_ctx_data_remove(struct ub_ctx* ctx, char *data);
+
 #endif /* _UB_UNBOUND_H */
diff --git a/pythonmod/LICENSE b/pythonmod/LICENSE
new file mode 100644 (file)
index 0000000..7b769d0
--- /dev/null
@@ -0,0 +1,28 @@
+Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+                    Marek Vavrusa  (xvavru00 AT stud.fit.vutbr.cz)
+
+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 the organization 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
diff --git a/pythonmod/Makefile b/pythonmod/Makefile
new file mode 100644 (file)
index 0000000..bf35bec
--- /dev/null
@@ -0,0 +1,58 @@
+# Makefile: tests unbound python module (please edit SCRIPT variable)
+#
+# Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+#                     Marek Vavrusa  (xvavru00 AT stud.fit.vutbr.cz)
+#
+# This software is open source.
+# 
+# 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 the organization 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 COPYRIGHT HOLDERS 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.
+
+SUEXEC  = sudo
+UNBOUND = ../unbound
+SCRIPT  = ./test-dict.conf
+
+UNBOUND_OPTS = -dv -c $(SCRIPT)
+
+.PHONY: test sudo suexec doc
+
+all: test
+
+$(UNBOUND):
+       make -C ..
+
+test: $(UNBOUND)
+       $(UNBOUND) $(UNBOUND_OPTS)
+
+sudo: $(UNBOUND)
+       sudo $(UNBOUND) $(UNBOUND_OPTS)
+
+suexec: $(UNBOUND)
+       su -c "$(UNBOUND) $(UNBOUND_OPTS)"
+
+doc:
+       $(MAKE) -C doc html
diff --git a/pythonmod/doc/Makefile b/pythonmod/doc/Makefile
new file mode 100644 (file)
index 0000000..b029353
--- /dev/null
@@ -0,0 +1,73 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS    =
+SPHINXBUILD   = sphinx-build
+PAPER         =
+
+# Internal variables.
+PAPEROPT_a4     = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS   = -d build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
+
+.PHONY: env help clean html web pickle htmlhelp latex changes linkcheck
+
+help:
+       @echo "Please use \`make <target>' where <target> is one of"
+       @echo "  html      to make standalone HTML files"
+       @echo "  pickle    to make pickle files (usable by e.g. sphinx-web)"
+       @echo "  htmlhelp  to make HTML files and a HTML help project"
+       @echo "  latex     to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+       @echo "  changes   to make an overview over all changed/added/deprecated items"
+       @echo "  linkcheck to check all external links for integrity"
+
+clean:
+       -rm -rf build/*
+   
+env:
+
+html: env
+       mkdir -p build/html build/doctrees
+       LD_LIBRARY_PATH=../../.libs:../../ldns-src/lib $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) build/html
+       @echo
+       @echo "Build finished. The HTML pages are in build/html."
+
+pickle: env
+       mkdir -p build/pickle build/doctrees
+       LD_LIBRARY_PATH=../../.libs:../../ldns-src/lib $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) build/pickle
+       @echo
+       @echo "Build finished; now you can process the pickle files or run"
+       @echo "  sphinx-web build/pickle"
+       @echo "to start the sphinx-web server."
+
+web: pickle
+
+htmlhelp: env
+       mkdir -p build/htmlhelp build/doctrees
+       LD_LIBRARY_PATH=../../.libs:../../ldns-src/lib $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) build/htmlhelp
+       @echo
+       @echo "Build finished; now you can run HTML Help Workshop with the" \
+             ".hhp project file in build/htmlhelp."
+
+latex: env
+       mkdir -p build/latex build/doctrees
+       LD_LIBRARY_PATH=../../.libs:../../ldns-src/lib $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) build/latex
+       @echo
+       @echo "Build finished; the LaTeX files are in build/latex."
+       @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
+             "run these through (pdf)latex."
+
+changes: env
+       mkdir -p build/changes build/doctrees
+       LD_LIBRARY_PATH=../../.libs:../../ldns-src/lib $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) build/changes
+       @echo
+       @echo "The overview file is in build/changes."
+
+linkcheck: env
+       mkdir -p build/linkcheck build/doctrees
+       LD_LIBRARY_PATH=../../.libs:../../ldns-src/lib $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) build/linkcheck
+       @echo
+       @echo "Link check complete; look for any errors in the above output " \
+             "or in build/linkcheck/output.txt."
+
diff --git a/pythonmod/doc/source/conf.py b/pythonmod/doc/source/conf.py
new file mode 100644 (file)
index 0000000..bc7a5ab
--- /dev/null
@@ -0,0 +1,179 @@
+# -*- coding: utf-8 -*-
+#
+# Unbound scripting interface documentation build configuration file
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# The contents of this file are pickled, so don't put values in the namespace
+# that aren't pickleable (module imports are okay, they're removed automatically).
+#
+# All configuration values have a default value; values that are commented out
+# serve to show the default value.
+
+import sys, os
+
+# If your extensions are in another directory, add it here. If the directory
+# is relative to the documentation root, use os.path.abspath to make it
+# absolute, like shown here.
+sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__),'../..')))
+#print sys.path
+
+# General configuration
+# ---------------------
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General substitutions.
+project = 'Unbound scriptable interface'
+copyright = '2009, Zdenek Vasicek, Marek Vavrusa'
+
+# The default replacements for |version| and |release|, also used in various
+# other places throughout the built documents.
+#
+# The short X.Y version.
+version = '1.0'
+# The full version, including alpha/beta/rc tags.
+release = '1.0.0'
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+today_fmt = '%B %d, %Y'
+
+# List of documents that shouldn't be included in the build.
+#unused_docs = []
+
+# List of directories, relative to source directories, that shouldn't be searched
+# for source files.
+#exclude_dirs = []
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+
+# Options for HTML output
+# -----------------------
+
+# The style sheet to use for HTML and HTML Help pages. A file of that name
+# must exist either in Sphinx' static/ path, or in one of the custom paths
+# given in html_static_path.
+html_style = 'default.css'
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar.  Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (within the static path) to place at the top of
+# the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+html_use_modindex = False
+
+# If false, no index is generated.
+html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, the reST sources are included in the HTML build as _sources/<name>.
+html_copy_source = False
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.  The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = ''
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'unbound_interface'
+
+
+# Options for LaTeX output
+# ------------------------
+
+# The paper size ('letter' or 'a4').
+#latex_paper_size = 'letter'
+
+# The font size ('10pt', '11pt' or '12pt').
+#latex_font_size = '10pt'
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, document class [howto/manual]).
+latex_documents = [
+  ('index', 'Unbound_interface.tex', 'Unbound scriptable interface',
+   'Zdenek Vasicek, Marek Vavrusa', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# Additional stuff for the LaTeX preamble.
+#latex_preamble = ''
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_use_modindex = True
diff --git a/pythonmod/doc/source/examples/example0-1.py b/pythonmod/doc/source/examples/example0-1.py
new file mode 100644 (file)
index 0000000..98a9acc
--- /dev/null
@@ -0,0 +1,37 @@
+
+print mod_env.fname   # Print module script name
+mod_env.data = "test" # Store global module data
+
+def init(id, cfg):
+   log_info("pythonmod: init called, module id is %d port: %d script: %s" % (id, cfg.port, cfg.python_script))
+   return True
+
+def deinit(id):
+   log_info("pythonmod: deinit called, module id is %d" % id)
+   return True
+
+def inform_super(id, qstate, superqstate, qdata):
+   return True
+
+def operate(id, event, qstate, qdata):
+   log_info("pythonmod: operate called, id: %d, event:%s" % (id, strmodulevent(event)))
+
+   if event == MODULE_EVENT_NEW:
+      qstate.ext_state[id] = MODULE_WAIT_MODULE 
+      return True
+
+   if event == MODULE_EVENT_MODDONE:
+      log_info("pythonmod: module we are waiting for is done")
+      qstate.ext_state[id] = MODULE_FINISHED 
+      return True
+
+   if event == MODULE_EVENT_PASS:
+      log_info("pythonmod: event_pass")
+      qstate.ext_state[id] = MODULE_ERROR 
+      return True
+
+   log_err("pythonmod: BAD event")
+   qstate.ext_state[id] = MODULE_ERROR
+   return True
+
+log_info("pythonmod: script loaded.")
diff --git a/pythonmod/doc/source/examples/example0.rst b/pythonmod/doc/source/examples/example0.rst
new file mode 100644 (file)
index 0000000..80eca5e
--- /dev/null
@@ -0,0 +1,129 @@
+.. _example_handler:
+
+Fundamentals
+================
+
+This basic example shows how to create simple python module which will pass on the requests to the iterator.
+
+How to enable python module
+----------------------------
+If you look into unbound configuration file, you can find the option `module-config` which specifies the names and the order of modules to be used.
+Example configuration::
+
+       module-config: "validator python iterator"
+
+As soon as the DNS query arrives, Unbound calls modules starting from leftmost - the validator *(it is the first module on the list)*.
+The validator does not know the answer *(it can only validate)*, thus it will pass on the event to the next module.
+Next module is python which can
+
+       a) generate answer *(response)*
+               When python module generates the response unbound calls validator. Validator grabs the answer and determines the security flag.
+
+       b) pass on the event to the iterator.
+               When iterator resolves the query, Unbound informs python module (event :data:`module_event_moddone`). In the end, when the python module is done, validator is called.
+
+Note that the python module is called with :data:`module_event_pass` event, because new DNS event was already handled by validator.
+
+Another situation occurs when we use the following configuration::
+
+       module-config: "python validator iterator"
+
+Python module is the first module here, so it's invoked with :data:`module_event_new` event *(new query)*.
+
+On Python module initialization, module loads script from `python-script` option::
+
+       python-script: "/unbound/test/ubmodule.py"
+
+Simple python module step by step
+---------------------------------
+
+Script file must contain four compulsory functions:
+
+.. function:: init(id, cfg)
+
+   Initialize module internals, like database etc.
+   Called just once on module load.
+
+   :param id: module identifier (integer)
+   :param cfg: :class:`config_file` configuration structure
+
+::
+
+   def init(id, cfg):
+      log_info("pythonmod: init called, module id is %d port: %d script: %s" % (id, cfg.port, cfg.python_script))
+      return True
+
+
+.. function:: deinit(id)
+
+   Deinitialize module internals.
+   Called just once on module unload.
+
+   :param id: module identifier (integer)
+
+::
+
+   def deinit(id):
+      log_info("pythonmod: deinit called, module id is %d" % id)
+      return True
+
+
+.. function:: inform_super(id, qstate, superqstate, qdata)
+
+   Inform super querystate about the results from this subquerystate.
+   Is called when the querystate is finished.
+
+   :param id: module identifier (integer)
+   :param qstate: :class:`module_qstate` Query state
+   :param superqstate: :class:`pythonmod_qstate` Mesh state
+   :param qdata: :class:`query_info` Query data
+
+::
+
+   def inform_super(id, qstate, superqstate, qdata):
+      return True
+
+
+
+.. function:: operate(id, event, qstate, qdata)
+
+   Perform action on pending query. Accepts a new query, or work on pending query.
+
+   You have to set qstate.ext_state on exit.
+   The state informs unbound about result and controls the following states.
+
+   :param id: module identifier (integer)
+   :param qstate: :class:`module_qstate` query state structure
+   :param qdata: :class:`query_info` per query data, here you can store your own data
+
+::
+
+   def operate(id, event, qstate, qdata):
+      log_info("pythonmod: operate called, id: %d, event:%s" % (id, strmodulevent(event)))
+      if event == MODULE_EVENT_NEW:
+         qstate.ext_state[id] = MODULE_WAIT_MODULE 
+         return True
+
+      if event == MODULE_EVENT_MODDONE:
+         qstate.ext_state[id] = MODULE_FINISHED 
+         return True
+
+      if event == MODULE_EVENT_PASS:
+         qstate.ext_state[id] = MODULE_ERROR 
+         return True
+
+      log_err("pythonmod: BAD event")
+      qstate.ext_state[id] = MODULE_ERROR
+      return True
+
+
+Complete source code
+--------------------
+
+..     literalinclude:: example0-1.py
+       :language: python
+
+As you can see, the source code is much more flexible in contrast to C modules. 
+Moreover, compulsory functions called on appropriate module events allows to handle almost
+anything from web control to query analysis.
+
diff --git a/pythonmod/doc/source/examples/example1.rst b/pythonmod/doc/source/examples/example1.rst
new file mode 100644 (file)
index 0000000..09d7803
--- /dev/null
@@ -0,0 +1,42 @@
+.. _log_handler:
+
+Packet logger
+=========================
+
+This example shows how to log and print details about query and response.
+As soon as the ``iterator`` has finished (event is :data:`module_event_moddone`), ``qstate.return_msg`` contains response packet or ``None``.
+This packet will be send to a client that asked for it.
+
+Complete source code
+--------------------
+
+.. literalinclude:: ../../../examples/log.py
+   :language: python
+
+Testing
+------------------
+Run the unbound server:
+
+``root@localhost>unbound -dv -c ./test-log.conf``
+
+In case you use own configuration file, don't forget to enable python module: ``module-config: "validator python iterator"`` and use valid script path: ``python-script: "./examples/log.py"``.
+
+Example of output::    
+
+   [1231790168] unbound[7941:0] info: response for <f.gtld-servers.NET. AAAA IN>
+   [1231790168] unbound[7941:0] info: reply from <gtld-servers.NET.> 192.5.6.31#53
+   [1231790168] unbound[7941:0] info: query response was ANSWER
+   [1231790168] unbound[7941:0] info: pythonmod: operate called, id: 1, event:module_event_moddone
+   ----------------------------------------------------------------------------------------------------
+   Query: f.gtld-servers.NET., type: AAAA (28), class: IN (1) 
+   ----------------------------------------------------------------------------------------------------
+   Return    reply :: flags: 8080, QDcount: 1, Security:0, TTL=86400
+             qinfo :: qname: ['f', 'gtld-servers', 'NET', ''] f.gtld-servers.NET., qtype: AAAA, qclass: IN
+   Reply:
+   0 : ['gtld-servers', 'NET', ''] gtld-servers.NET. flags: 0000 type: SOA (6) class: IN (1)
+      0 : TTL= 86400
+          0x00 | 00 3A 02 41 32 05 4E 53 54 4C 44 03 43 4F 4D 00 05 | . : . A 2 . N S T L D . C O M . . 
+          0x10 | 05 6E 73 74 6C 64 0C 76 65 72 69 73 69 67 6E 2D 67 | . n s t l d . v e r i s i g n - g 
+          0x20 | 67 72 73 03 43 4F 4D 00 77 74 2D 64 00 00 0E 10 00 | g r s . C O M . w t - d . . . . . 
+          0x30 | 00 00 03 84 00 12 75 00 00 01 51 80                | . . . . . . u . . . Q . 
+
diff --git a/pythonmod/doc/source/examples/example2.rst b/pythonmod/doc/source/examples/example2.rst
new file mode 100644 (file)
index 0000000..a0bfee4
--- /dev/null
@@ -0,0 +1,46 @@
+Response generation
+=====================
+
+This example shows how to handle queries and generate response packet.
+
+.. note::
+   If the python module is the first module and validator module is enabled (``module-config: "python validator iterator"``),
+   a return_msg security flag has to be set at least to 2. Leaving security flag untouched causes that the
+   response will be refused by unbound worker as unbound will consider it as non-valid response.
+
+Complete source code
+--------------------
+
+.. literalinclude:: ../../../examples/resgen.py
+   :language: python
+
+Testing
+-------
+
+Run the unbound server:
+
+``root@localhost>unbound -dv -c ./test-resgen.conf``
+
+Query for a A record ending with .localdomain
+
+``dig A test.xxx.localdomain @127.0.0.1``
+
+Dig produces the following output::
+
+       ;; global options:  printcmd
+       ;; Got answer:
+       ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48426
+       ;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
+       
+       ;; QUESTION SECTION:
+       ;test.xxx.localdomain.          IN      A
+       
+       ;; ANSWER SECTION:
+       test.xxx.localdomain.   10      IN      A       127.0.0.1
+       
+       ;; Query time: 2 msec
+       ;; SERVER: 127.0.0.1#53(127.0.0.1)
+       ;; WHEN: Mon Jan 01 12:46:02 2009
+       ;; MSG SIZE  rcvd: 54
+
+As we handle (override) in python module only queries ending with "localdomain.", the unboud can still resolve host names.
diff --git a/pythonmod/doc/source/examples/example3.rst b/pythonmod/doc/source/examples/example3.rst
new file mode 100644 (file)
index 0000000..8ba43a8
--- /dev/null
@@ -0,0 +1,63 @@
+Response modification
+=====================
+
+This example shows how to modify the response produced by the ``iterator`` module.
+
+As soon as the iterator module returns the response, we :
+
+1. invalidate the data in cache
+2. modify the response *TTL*
+3. rewrite the data in cache
+4. return modified packet
+
+Note that the steps 1 and 3 are neccessary only in case, the python module is the first module in the processing chain.
+In other cases, the validator module guarantees updating data which are produced by iterator module.
+
+Complete source code
+--------------------
+
+.. literalinclude:: ../../../examples/resmod.py
+   :language: python
+
+Testing
+-------
+
+Run Unbound server:
+
+``root@localhost>unbound -dv -c ./test-resmod.conf``
+
+Issue a query for name ending with "nic.cz."
+
+``>>>dig A @127.0.0.1 www.nic.cz``
+
+::
+
+       ;; global options:  printcmd
+       ;; Got answer:
+       ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48831
+       ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 3, ADDITIONAL: 5
+       
+       ;; QUESTION SECTION:
+       ;www.nic.cz.                    IN      A
+       
+       ;; ANSWER SECTION:
+       www.nic.cz.             10      IN      A       217.31.205.50
+       
+       ;; AUTHORITY SECTION:
+       nic.cz.                 10      IN      NS      e.ns.nic.cz.
+       nic.cz.                 10      IN      NS      a.ns.nic.cz.
+       nic.cz.                 10      IN      NS      c.ns.nic.cz.
+       
+       ;; ADDITIONAL SECTION:
+       a.ns.nic.cz.            10      IN      A       217.31.205.180
+       a.ns.nic.cz.            10      IN      AAAA    2001:1488:dada:176::180
+       c.ns.nic.cz.            10      IN      A       195.66.241.202
+       c.ns.nic.cz.            10      IN      AAAA    2a01:40:1000::2
+       e.ns.nic.cz.            10      IN      A       194.146.105.38
+       
+       ;; Query time: 166 msec
+       ;; SERVER: 127.0.0.1#53(127.0.0.1)
+       ;; WHEN: Mon Jan 02 13:39:43 2009
+       ;; MSG SIZE  rcvd: 199
+
+As you can see, TTL of all the records is set to 10.
diff --git a/pythonmod/doc/source/examples/example4.rst b/pythonmod/doc/source/examples/example4.rst
new file mode 100644 (file)
index 0000000..0f8353d
--- /dev/null
@@ -0,0 +1,164 @@
+DNS-based language dictionary
+===============================
+
+This example shows how to create a simple language dictionary based on **DNS**
+service within 15 minutes. The translation will be performed using TXT resource records.
+
+Key parts
+-----------
+
+Initialization
+~~~~~~~~~~~~~~~~~~~~~~~
+On **init()** module loads dictionary from a text file containing records in ``word [tab] translation`` format.
+::
+
+   def init(id, cfg):
+      log_info("pythonmod: dict init")
+      f = open("examples/dict_data.txt", "r")
+      ...
+
+The suitable file can be found at http://slovnik.zcu.cz
+
+DNS query and word lookup
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Let's define the following format od DNS queries: ``word1[.]word2[.] ... wordN[.]{en,cs}[._dict_.cz.]``.
+Word lookup is done by simple ``dict`` lookup from broken DNS request.
+Query name is divided into a list of labels. This list is accesible as qname_list attribute.
+::
+
+   aword = ' '.join(qstate.qinfo.qname_list[0:-4]) #skip last four labels
+   adict = qstate.qinfo.qname_list[-4] #get 4th label from the end
+
+   words = [] #list of words
+   if (adict == "en") and (aword in en_dict):
+      words = en_dict[aword] 
+
+   if (adict == "cs") and (aword in cz_dict):
+      words = cz_dict[aword] # CS -> EN
+
+In the first step, we get a string in the form: ``word1[space]word2[space]...word[space]``.
+In the second assignment, fourth label from the end is obtained. This label should contains *"cs"* or *"en"*.
+This label determines the direction of translation.
+
+
+Forming of a DNS reply
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+DNS reply is formed only on valid match and added as TXT answer.
+::
+
+       msg = DNSMessage(qstate.qinfo.qname_str, RR_TYPE_TXT, RR_CLASS_IN, PKT_AA)
+
+       for w in words:
+               msg.answer.append("%s 300 IN TXT \"%s\"" % (qstate.qinfo.qname_str, w.replace("\"", "\\\"")))
+
+       if not msg.set_return_msg(qstate):
+               qstate.ext_state[id] = MODULE_ERROR 
+               return True
+
+       qstate.return_rcode = RCODE_NOERROR
+       qstate.ext_state[id] = MODULE_FINISHED 
+       return True
+
+In the first step, a :class:`DNSMessage` instance is created for a given query *(type TXT)*.
+The fourth argument specifies the flags *(authoritative answer)*.
+In the second step, we append TXT records containing the translation *(on the right side of RR)*.
+Then, the response is finished and ``qstate.return_msg`` contains new response.
+If no error, the module sets :attr:`module_qstate.return_rcode` and :attr:`module_qstate.ext_state`.
+
+**Steps:**
+
+1. create :class:`DNSMessage` instance
+2. append TXT records containing the translation
+3. set response to ``qstate.return_msg``
+
+Testing
+-------
+
+Run the Unbound server:
+
+``root@localhost>unbound -dv -c ./test-dict.conf``
+
+In case you use own configuration file, don't forget to enable Python module::
+
+       module-config: "validator python iterator"
+
+and use valid script path::
+
+       python-script: "./examples/dict.py"
+
+The translation from english word *"a bar fly"* to Czech can be done by doing:
+
+``>>>dig TXT @127.0.0.1 a.bar.fly.en._dict_.cz``
+
+::     
+
+       ; (1 server found)
+       ;; global options:  printcmd
+       ;; Got answer:
+       ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48691
+       ;; flags: aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
+       
+       ;; QUESTION SECTION:
+       ;a.bar.fly.en._dict_.cz.                IN      TXT
+       
+       ;; ANSWER SECTION:
+       a.bar.fly.en._dict_.cz. 300     IN      TXT     "barov\253 povale\232"
+       
+       ;; Query time: 5 msec
+       ;; SERVER: 127.0.0.1#53(127.0.0.1)
+       ;; WHEN: Mon Jan 01 17:44:18 2009
+       ;; MSG SIZE  rcvd: 67
+       
+``>>>dig TXT @127.0.0.1 nic.cs._dict_.cz``
+::
+       
+       ; <<>> DiG 9.5.0-P2 <<>> TXT @127.0.0.1 nic.cs._dict_.cz
+       ; (1 server found)
+       ;; global options:  printcmd
+       ;; Got answer:
+       ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 58710
+       ;; flags: aa rd ra; QUERY: 1, ANSWER: 6, AUTHORITY: 0, ADDITIONAL: 0
+       
+       ;; QUESTION SECTION:
+       ;nic.cs._dict_.cz.              IN      TXT
+       
+       ;; ANSWER SECTION:
+       nic.cs._dict_.cz.       300     IN      TXT     "aught"
+       nic.cs._dict_.cz.       300     IN      TXT     "naught"
+       nic.cs._dict_.cz.       300     IN      TXT     "nihil"
+       nic.cs._dict_.cz.       300     IN      TXT     "nix"
+       nic.cs._dict_.cz.       300     IN      TXT     "nothing"
+       nic.cs._dict_.cz.       300     IN      TXT     "zilch"
+       
+       ;; Query time: 0 msec
+       ;; SERVER: 127.0.0.1#53(127.0.0.1)
+       ;; WHEN: Mon Jan 01 17:45:39 2009
+       ;; MSG SIZE  rcvd: 143
+
+Proof that the unbound still works as resolver.
+
+``>>>dig A @127.0.0.1 www.nic.cz``
+::
+
+       ; (1 server found)
+       ;; global options:  printcmd
+       ;; Got answer:
+       ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 19996
+       ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 3, ADDITIONAL: 5
+       
+       ;; QUESTION SECTION:
+       ;www.nic.cz.                    IN      A
+       
+       ;; ANSWER SECTION:
+       www.nic.cz.             1662    IN      A       217.31.205.50
+       
+       ;; AUTHORITY SECTION:
+       ...
+
+Complete source code
+--------------------
+
+.. literalinclude:: ../../../examples/dict.py
+   :language: python
diff --git a/pythonmod/doc/source/examples/index.rst b/pythonmod/doc/source/examples/index.rst
new file mode 100644 (file)
index 0000000..6c50225
--- /dev/null
@@ -0,0 +1,15 @@
+.. _Tutorials:
+
+==============================
+Tutorials
+==============================
+
+Here you can find several tutorials which clarify the usage and capabilities of Unbound scriptable interface. 
+
+`Tutorials`
+
+.. toctree::
+       :maxdepth: 2
+       :glob:
+
+       example*
diff --git a/pythonmod/doc/source/index.rst b/pythonmod/doc/source/index.rst
new file mode 100644 (file)
index 0000000..fe9bcf4
--- /dev/null
@@ -0,0 +1,34 @@
+Unbound scriptable interface
+=======================================
+
+Python module for **Unbound** provides easy-to-use flexible solution,
+for scripting query events and much more!
+
+Along with extensible **SWIG** interface, it turns **Unbound** into dynamic *DNS* service
+designed for rapid development of *DNS* based applications, like detailed *(per query/domain)* statistics,
+monitoring with anything Python can offer *(database backend, http server)*.
+
+**Key features**
+   * Rapid dynamic DNS-based application development in **Python**
+   * Extensible interface with **SWIG**
+   * Easy to use debugging and analysis tool
+   * Capable to produce authoritative answers
+   * Support for logging or doing detailed statistics
+   * Allows to manipulate with content of cache memory
+
+Contents
+--------
+.. toctree::
+   :maxdepth: 2
+
+   install
+   examples/index
+   usecase
+   modules/index
+
+Indices and tables
+-------------------
+
+* :ref:`genindex`
+* :ref:`search`
+
diff --git a/pythonmod/doc/source/install.rst b/pythonmod/doc/source/install.rst
new file mode 100644 (file)
index 0000000..991e2b4
--- /dev/null
@@ -0,0 +1,59 @@
+Installation
+===================================
+
+**Prerequisites**
+
+Python 2.4 or higher, SWIG 1.3 or higher, GNU make
+
+**Download**
+
+You can download the source codes `here`_.
+The latest release is 1.1.1, Jan 15, 2009.
+
+.. _here: unbound-1.1.1-py.tar.gz
+
+**Compiling**
+
+After downloading, you can compile the Unbound library by doing::
+
+       > tar -xzf unbound-1.1.1-py.tar.gz
+       > cd unbound-1.1.1
+       > ./configure --with-pythonmodule
+       > make
+
+You need GNU make to compile sources.
+SWIG and Python devel libraries to compile extension module. 
+
+**Testing**
+
+If the compilation is successful, you can test the extension module by::
+
+       > cd pythonmod
+       > make sudo # or "make test" or "make suexec"
+
+This will start unbound server with language dictionary service (see :ref:`Tutorials`).
+In order to test this service, type::
+  
+   > dig TXT @127.0.0.1 aught.en._dict_.cz
+
+Dig should print this message (czech equivalent of aught)::
+
+   ; <<>> DiG 9.5.0-P2 <<>> TXT @127.0.0.1 aught.en._dict_.cz
+   ; (1 server found)
+   ;; global options:  printcmd
+   ;; Got answer:
+   ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 30085
+   ;; flags: aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
+   
+   ;; QUESTION SECTION:
+   ;aught.en._dict_.cz.                IN      TXT
+   
+   ;; ANSWER SECTION:
+   aught.en._dict_.cz. 300     IN      TXT     "nic"
+   
+   ;; Query time: 11 msec
+   ;; SERVER: 127.0.0.1#53(127.0.0.1)
+   ;; WHEN: Thu Jan 10 16:45:58 2009
+   ;; MSG SIZE  rcvd: 52
+
+The ``pythonmod/examples`` directory contains simple applications written in Python.
diff --git a/pythonmod/doc/source/modules/config.rst b/pythonmod/doc/source/modules/config.rst
new file mode 100644 (file)
index 0000000..1277bce
--- /dev/null
@@ -0,0 +1,350 @@
+Configuration interface
+=======================
+
+Currently passed to Python module in init(module_id, cfg).
+
+config_file
+--------------------
+
+.. class:: config_file
+
+   This class provides these data attributes:
+
+   .. attribute:: verbosity
+   
+      Verbosity level as specified in the config file.
+
+   .. attribute:: stat_interval
+   
+      Statistics interval (in seconds).
+   
+   .. attribute:: stat_cumulative
+   
+      If false, statistics values are reset after printing them.
+   
+   .. attribute:: stat_extended
+   
+      If true, the statistics are kept in greater detail.
+
+   .. attribute:: num_threads
+   
+      Number of threads to create.
+
+   .. attribute:: port
+   
+      Port on which queries are answered.
+
+   .. attribute:: do_ip4
+   
+      Do ip4 query support.
+
+   .. attribute:: do_ip6
+   
+      Do ip6 query support.
+
+   .. attribute:: do_udp
+   
+      Do udp query support.
+   
+   .. attribute:: do_tcp
+   
+      Do tcp query support.
+
+   .. attribute:: outgoing_num_ports
+   
+      Outgoing port range number of ports (per thread).
+
+   .. attribute:: outgoing_num_tcp
+   
+      Number of outgoing tcp buffers per (per thread).
+
+   .. attribute:: incoming_num_tcp
+   
+      Number of incoming tcp buffers per (per thread).
+
+   .. attribute:: outgoing_avail_ports
+   
+      Allowed udp port numbers, array with 0 if not allowed.
+
+   .. attribute:: msg_buffer_size
+   
+      Number of bytes buffer size for DNS messages.
+
+   .. attribute:: msg_cache_size
+   
+      Size of the message cache.
+   
+   .. attribute:: msg_cache_slabs
+   
+      Slabs in the message cache.
+   
+   .. attribute:: num_queries_per_thread
+   
+      Number of queries every thread can service.
+   
+   .. attribute:: jostle_time
+   
+      Number of msec to wait before items can be jostled out.
+   
+   .. attribute:: rrset_cache_size
+   
+      Size of the rrset cache.
+   
+   .. attribute:: rrset_cache_slabs
+   
+      Slabs in the rrset cache.
+   
+   .. attribute:: host_ttl
+   
+      Host cache ttl in seconds.
+
+   .. attribute:: lame_ttl
+   
+      Host is lame for a zone ttl, in seconds.
+
+   .. attribute:: infra_cache_slabs
+   
+      Number of slabs in the infra host cache.
+   
+   .. attribute:: infra_cache_numhosts
+   
+      Max number of hosts in the infra cache.
+   
+   .. attribute:: infra_cache_lame_size
+   
+      Max size of lame zones per host in the infra cache.
+
+   .. attribute:: target_fetch_policy
+   
+      The target fetch policy for the iterator.
+
+   .. attribute:: if_automatic
+   
+      Automatic interface for incoming messages. Uses ipv6 remapping,
+      and recvmsg/sendmsg ancillary data to detect interfaces, boolean.
+   
+   .. attribute:: num_ifs
+   
+      Number of interfaces to open. If 0 default all interfaces.
+   
+   .. attribute:: ifs
+   
+      Interface description strings (IP addresses).
+
+   .. attribute:: num_out_ifs
+   
+      Number of outgoing interfaces to open. 
+      If 0 default all interfaces.
+
+   .. attribute:: out_ifs
+   
+      Outgoing interface description strings (IP addresses).
+      
+   .. attribute:: root_hints
+   
+      The root hints.
+   
+   .. attribute:: stubs
+   
+      The stub definitions, linked list.
+   
+   .. attribute:: forwards
+   
+      The forward zone definitions, linked list.
+   
+   .. attribute:: donotqueryaddrs
+   
+      List of donotquery addresses, linked list.
+   
+   .. attribute:: acls
+   
+      List of access control entries, linked list.
+   
+   .. attribute:: donotquery_localhost
+   
+      Use default localhost donotqueryaddr entries.
+
+   .. attribute:: harden_short_bufsize
+   
+      Harden against very small edns buffer sizes.
+   
+   .. attribute:: harden_large_queries
+   
+      Harden against very large query sizes.
+   
+   .. attribute:: harden_glue
+   
+      Harden against spoofed glue (out of zone data).
+   
+   .. attribute:: harden_dnssec_stripped
+   
+      Harden against receiving no DNSSEC data for trust anchor.
+   
+   .. attribute:: harden_referral_path
+   
+      Harden the referral path, query for NS,A,AAAA and validate.
+   
+   .. attribute:: use_caps_bits_for_id
+   
+      Use 0x20 bits in query as random ID bits.
+   
+   .. attribute:: private_address
+   
+      Strip away these private addrs from answers, no DNS Rebinding.
+   
+   .. attribute:: private_domain
+   
+      Allow domain (and subdomains) to use private address space.
+   
+   .. attribute:: unwanted_threshold
+   
+      What threshold for unwanted action.
+
+   .. attribute:: chrootdir
+   
+      Chrootdir, if not "" or chroot will be done.
+   
+   .. attribute:: username
+   
+      Username to change to, if not "".
+   
+   .. attribute:: directory
+   
+      Working directory.
+   
+   .. attribute:: logfile
+   
+      Filename to log to.
+   
+   .. attribute:: pidfile
+   
+      Pidfile to write pid to.
+
+   .. attribute:: use_syslog
+   
+      Should log messages be sent to syslogd.
+
+   .. attribute:: hide_identity
+   
+      Do not report identity (id.server, hostname.bind).
+   
+   .. attribute:: hide_version
+   
+      Do not report version (version.server, version.bind).
+   
+   .. attribute:: identity
+   
+      Identity, hostname is returned if "".
+   
+   .. attribute:: version
+   
+      Version, package version returned if "".
+
+   .. attribute:: module_conf
+   
+      The module configuration string.
+   
+   .. attribute:: trust_anchor_file_list
+   
+      Files with trusted DS and DNSKEYs in zonefile format, list.
+   
+   .. attribute:: trust_anchor_list
+   
+      List of trustanchor keys, linked list.
+   
+   .. attribute:: trusted_keys_file_list
+   
+      Files with trusted DNSKEYs in named.conf format, list.
+   
+   .. attribute:: dlv_anchor_file
+   
+      DLV anchor file.
+   
+   .. attribute:: dlv_anchor_list
+   
+      DLV anchor inline.
+
+   .. attribute:: max_ttl
+   
+      The number of seconds maximal TTL used for RRsets and messages.
+   
+   .. attribute:: val_date_override
+   
+      If not 0, this value is the validation date for RRSIGs.
+   
+   .. attribute:: bogus_ttl 
+   
+      This value sets the number of seconds before revalidating bogus.
+   
+   .. attribute:: val_clean_additional
+   
+      Should validator clean additional section for secure msgs.
+   
+   .. attribute:: val_permissive_mode
+   
+      Should validator allow bogus messages to go through.
+   
+   .. attribute:: val_nsec3_key_iterations
+   
+      Nsec3 maximum iterations per key size, string.
+   
+   .. attribute:: key_cache_size
+   
+      Size of the key cache.
+   
+   .. attribute:: key_cache_slabs
+   
+      Slabs in the key cache.
+   
+   .. attribute:: neg_cache_size
+   
+      Size of the neg cache.
+
+   
+   .. attribute:: local_zones
+   
+      Local zones config.
+   
+   .. attribute:: local_zones_nodefault
+   
+      Local zones nodefault list.
+   
+   .. attribute:: local_data
+   
+      Local data RRs configged.
+
+   .. attribute:: remote_control_enable
+   
+      Remote control section. enable toggle.
+   
+   .. attribute:: control_ifs
+   
+      The interfaces the remote control should listen on.
+   
+   .. attribute:: control_port
+   
+      Port number for the control port.
+   
+   .. attribute:: server_key_file
+   
+      Private key file for server.
+   
+   .. attribute:: server_cert_file
+   
+      Certificate file for server.
+   
+   .. attribute:: control_key_file
+   
+      Private key file for unbound-control.
+   
+   .. attribute:: control_cert_file
+   
+      Certificate file for unbound-control.
+
+   .. attribute:: do_daemonize
+   
+      Daemonize, i.e. fork into the background.
+
+   .. attribute:: python_script
+   
+      Python script file.
diff --git a/pythonmod/doc/source/modules/env.rst b/pythonmod/doc/source/modules/env.rst
new file mode 100644 (file)
index 0000000..42dbbd1
--- /dev/null
@@ -0,0 +1,412 @@
+Global environment
+==================
+
+Global variables
+----------------
+
+.. envvar:: mod_env
+
+   Module environment, contains data pointer for module-specific data.
+   See :class:`pythonmod_env`.
+
+
+Predefined constants
+-----------------------
+
+Module extended state
+~~~~~~~~~~~~~~~~~~~~~~~
+
+.. data:: module_state_initial
+
+   Initial state - new DNS query.
+
+.. data:: module_wait_reply
+
+   Waiting for reply to outgoing network query.
+
+.. data:: module_wait_module
+
+   Module is waiting for another module.
+   
+.. data:: module_wait_subquery
+
+   Module is waiting for sub-query.
+   
+.. data:: module_error
+
+   Module could not finish the query.
+   
+.. data:: module_finished
+
+   Module is finished with query.
+
+Module event
+~~~~~~~~~~~~~
+.. data:: module_event_new
+
+   New DNS query.
+   
+.. data:: module_event_pass
+
+   Query passed by other module.
+   
+.. data:: module_event_reply
+
+   Reply inbound from server.
+   
+.. data:: module_event_noreply
+
+   No reply, timeout or other error.
+   
+.. data:: module_event_capsfail
+
+   Reply is there, but capitalisation check failed.
+   
+.. data:: module_event_moddone
+
+   Next module is done, and its reply is awaiting you.
+   
+.. data:: module_event_error
+
+   Error occured.
+
+Security status
+~~~~~~~~~~~~~~~~
+
+.. data:: sec_status_unchecked
+
+   Means that object has yet to be validated.
+
+.. data:: sec_status_bogus
+
+   Means that the object *(RRset or message)* failed to validate
+   *(according to local policy)*, but should have validated.
+   
+.. data:: sec_status_indeterminate
+
+   Means that the object is insecure, but not 
+   authoritatively so. Generally this means that the RRset is not 
+   below a configured trust anchor.
+   
+.. data:: sec_status_insecure
+
+   Means that the object is authoritatively known to be 
+   insecure. Generally this means that this RRset is below a trust 
+   anchor, but also below a verified, insecure delegation.
+
+.. data:: sec_status_secure
+
+   Means that the object (RRset or message) validated according to local policy.
+
+Resource records (RR sets)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The different RR classes.
+
+   .. data:: RR_CLASS_IN
+   
+      Internet.
+      
+   .. data:: RR_CLASS_CH
+   
+      Chaos.
+      
+   .. data:: RR_CLASS_HS
+   
+      Hesiod (Dyer 87)
+      
+   .. data:: RR_CLASS_NONE
+   
+      None class, dynamic update.
+      
+   .. data:: RR_CLASS_ANY
+      
+      Any class.
+   
+
+The different RR types.
+
+
+   .. data:: RR_TYPE_A 
+   
+      A host address.
+      
+   .. data:: RR_TYPE_NS
+   
+      An authoritative name server.
+      
+   .. data:: RR_TYPE_MD 
+      
+      A mail destination (Obsolete - use MX).
+      
+   .. data:: RR_TYPE_MF 
+   
+      A mail forwarder (Obsolete - use MX).
+      
+   .. data:: RR_TYPE_CNAME 
+      
+      The canonical name for an alias.
+      
+   .. data:: RR_TYPE_SOA 
+      
+      Marks the start of a zone of authority.
+      
+   .. data:: RR_TYPE_MB 
+      
+      A mailbox domain name (EXPERIMENTAL).
+      
+   .. data:: RR_TYPE_MG 
+      
+      A mail group member (EXPERIMENTAL).
+      
+   .. data:: RR_TYPE_MR 
+      
+      A mail rename domain name (EXPERIMENTAL).
+      
+   .. data:: RR_TYPE_NULL
+      
+      A null RR (EXPERIMENTAL).
+      
+   .. data:: RR_TYPE_WKS
+      
+      A well known service description.
+      
+   .. data:: RR_TYPE_PTR
+   
+      A domain name pointer.
+      
+   .. data:: RR_TYPE_HINFO
+   
+      Host information.
+      
+   .. data:: RR_TYPE_MINFO
+   
+      Mailbox or mail list information.
+      
+   .. data:: RR_TYPE_MX
+   
+      Mail exchange.
+      
+   .. data:: RR_TYPE_TXT
+   
+      Text strings.
+   
+   .. data:: RR_TYPE_RP
+   
+      RFC1183.
+      
+   .. data:: RR_TYPE_AFSDB
+      
+      RFC1183.
+      
+   .. data:: RR_TYPE_X25
+      
+      RFC1183.
+      
+   .. data:: RR_TYPE_ISDN
+   
+      RFC1183.
+      
+   .. data:: RR_TYPE_RT
+      
+      RFC1183.
+      
+   .. data:: RR_TYPE_NSAP
+      
+      RFC1706.
+      
+   .. data:: RR_TYPE_NSAP_PTR
+      
+      RFC1348.
+      
+   .. data:: RR_TYPE_SIG
+      
+      2535typecode.
+      
+   .. data:: RR_TYPE_KEY
+      
+      2535typecode.
+      
+   .. data:: RR_TYPE_PX
+      
+      RFC2163.
+      
+   .. data:: RR_TYPE_GPOS
+      
+      RFC1712.
+      
+   .. data:: RR_TYPE_AAAA
+      
+      IPv6 address.
+      
+   .. data:: RR_TYPE_LOC
+      
+      LOC record  RFC1876.
+      
+   .. data:: RR_TYPE_NXT
+      
+      2535typecode.
+      
+   .. data:: RR_TYPE_EID
+      
+      draft-ietf-nimrod-dns-01.txt.
+      
+   .. data:: RR_TYPE_NIMLOC
+      
+      draft-ietf-nimrod-dns-01.txt.
+      
+   .. data:: RR_TYPE_SRV
+      
+      SRV record RFC2782.
+      
+   .. data:: RR_TYPE_ATMA
+   
+      http://www.jhsoft.com/rfc/af-saa-0069.000.rtf.
+      
+   .. data:: RR_TYPE_NAPTR
+      
+      RFC2915.
+      
+   .. data:: RR_TYPE_KX
+      
+      RFC2230.
+      
+   .. data:: RR_TYPE_CERT
+      
+      RFC2538.
+      
+   .. data:: RR_TYPE_A6
+      
+      RFC2874.
+      
+   .. data:: RR_TYPE_DNAME
+      
+      RFC2672.
+      
+   .. data:: RR_TYPE_SINK
+      
+      dnsind-kitchen-sink-02.txt.
+      
+   .. data:: RR_TYPE_OPT
+      
+      Pseudo OPT record.
+      
+   .. data:: RR_TYPE_APL
+      
+      RFC3123.
+      
+   .. data:: RR_TYPE_DS
+      
+      draft-ietf-dnsext-delegation.
+      
+   .. data:: RR_TYPE_SSHFP
+      
+      SSH Key Fingerprint.
+   
+   .. data:: RR_TYPE_IPSECKEY
+      
+      draft-richardson-ipseckey-rr-11.txt.
+      
+   .. data:: RR_TYPE_RRSIG
+      
+      draft-ietf-dnsext-dnssec-25.
+      
+   .. data:: RR_TYPE_NSEC      
+   .. data:: RR_TYPE_DNSKEY
+   .. data:: RR_TYPE_DHCID
+   .. data:: RR_TYPE_NSEC3
+   .. data:: RR_TYPE_NSEC3PARAMS
+   .. data:: RR_TYPE_UINFO
+   .. data:: RR_TYPE_UID
+   .. data:: RR_TYPE_GID
+   .. data:: RR_TYPE_UNSPEC
+   .. data:: RR_TYPE_TSIG
+   .. data:: RR_TYPE_IXFR
+   .. data:: RR_TYPE_AXFR
+   .. data:: RR_TYPE_MAILB
+      
+      A request for mailbox-related records (MB, MG or MR).
+      
+   .. data:: RR_TYPE_MAILA
+      
+      A request for mail agent RRs (Obsolete - see MX).
+      
+   .. data:: RR_TYPE_ANY
+      
+      Any type *(wildcard)*.
+   
+   .. data:: RR_TYPE_DLV
+      
+      RFC 4431, 5074, DNSSEC Lookaside Validation.
+   
+Return codes
+~~~~~~~~~~~~
+
+Return codes for packets.
+
+.. data:: RCODE_NOERROR
+.. data:: RCODE_FORMERR
+.. data:: RCODE_SERVFAIL
+.. data:: RCODE_NXDOMAIN
+.. data:: RCODE_NOTIMPL
+.. data:: RCODE_REFUSED
+.. data:: RCODE_YXDOMAIN
+.. data:: RCODE_YXRRSET
+.. data:: RCODE_NXRRSET
+.. data:: RCODE_NOTAUTH
+.. data:: RCODE_NOTZONE
+   
+Packet data
+~~~~~~~~~~~~
+
+.. data:: PKT_QR
+
+   Query - query flag.
+   
+.. data:: PKT_AA
+
+   Authoritative Answer - server flag.
+   
+.. data:: PKT_TC
+   
+   Truncated - server flag.
+   
+.. data:: PKT_RD
+   
+   Recursion desired - query flag.
+   
+.. data:: PKT_CD
+
+   Checking disabled - query flag.
+   
+.. data:: PKT_RA
+   
+   Recursion available - server flag.
+   
+.. data:: PKT_AD
+   
+   Authenticated data - server flag.
+
+
+Verbosity value
+~~~~~~~~~~~~~~~~
+
+.. data:: NO_VERBOSE
+
+   No verbose messages.
+   
+.. data:: VERB_OPS
+
+   Operational information.
+   
+.. data:: VERB_DETAIL
+
+   Detailed information.
+   
+.. data:: VERB_QUERY
+
+   Query level information.
+   
+.. data:: VERB_ALGO
+
+   Algorithm level information.
diff --git a/pythonmod/doc/source/modules/functions.rst b/pythonmod/doc/source/modules/functions.rst
new file mode 100644 (file)
index 0000000..45a469f
--- /dev/null
@@ -0,0 +1,120 @@
+Scriptable functions
+====================
+
+Network
+-------
+
+.. function:: ntohs(netshort)
+
+   This subroutine converts values between the host and network byte order. 
+   Specifically, **ntohs()** converts 16-bit quantities from network byte order to host byte order.
+   
+   :param netshort: 16-bit short addr
+   :rtype: converted addr
+   
+   
+Cache
+-----
+
+.. function:: storeQueryInCache(qstate, qinfo, msgrep, is_referral)
+
+   Store pending query in local cache.
+   
+   :param qstate: :class:`module_qstate`
+   :param qinfo: :class:`query_info`
+   :param msgrep: :class:`reply_info`
+   :param is_referal: integer
+   :rtype: boolean
+   
+.. function:: invalidateQueryInCache(qstate, qinfo)
+
+   Invalidate record in local cache.
+
+   :param qstate: :class:`module_qstate`
+   :param qinfo: :class:`query_info`
+
+
+Logging
+-------
+
+.. function:: verbose(level, msg)
+
+   Log a verbose message, pass the level for this message.
+   No trailing newline is needed.
+
+   :param level: verbosity level for this message, compared to global verbosity setting.
+   :param msg: string message
+
+.. function:: log_info(msg)
+
+   Log informational message. No trailing newline is needed.
+
+   :param msg: string message
+
+.. function:: log_err(msg)
+
+   Log error message. No trailing newline is needed.
+
+   :param msg: string message
+
+.. function:: log_warn(msg)
+
+   Log warning message. No trailing newline is needed.
+
+   :param msg: string message
+
+.. function:: log_hex(msg, data, length)
+
+   Log a hex-string to the log. Can be any length.
+   performs mallocs to do so, slow. But debug useful.
+
+   :param msg: string desc to accompany the hexdump.
+   :param data: data to dump in hex format.
+   :param length: length of data.
+   
+.. function:: log_dns_msg(str, qinfo, reply)
+
+   Log DNS message.
+   
+   :param str: string message
+   :param qinfo: :class:`query_info`
+   :param reply: :class:`reply_info`
+   
+.. function:: log_query_info(verbosity_value, str, qinf)
+
+   Log query information.
+   
+   :param verbosity_value: see constants
+   :param str: string message
+   :param qinf: :class:`query_info`
+   
+.. function:: regional_log_stats(r)
+
+   Log regional statistics.
+   
+   :param r: :class:`regional`
+
+Debugging
+---------
+
+.. function:: strextstate(module_ext_state)
+
+   Debug utility, module external qstate to string.
+   
+   :param module_ext_state: the state value.
+   :rtype: descriptive string.
+
+.. function:: strmodulevent(module_event)
+
+   Debug utility, module event to string.
+   
+   :param module_event: the module event value.
+   :rtype: descriptive string.
+   
+.. function:: ldns_rr_type2str(atype)
+
+   Convert RR type to string.
+   
+.. function:: ldns_rr_class2str(aclass)
+
+   Convert RR class to string.
diff --git a/pythonmod/doc/source/modules/index.rst b/pythonmod/doc/source/modules/index.rst
new file mode 100644 (file)
index 0000000..ff0b956
--- /dev/null
@@ -0,0 +1,11 @@
+Unbound module documentation
+=======================================
+
+.. toctree::
+   :maxdepth: 2
+
+   env
+   struct
+   functions
+   config
+
diff --git a/pythonmod/doc/source/modules/struct.rst b/pythonmod/doc/source/modules/struct.rst
new file mode 100644 (file)
index 0000000..c41e10b
--- /dev/null
@@ -0,0 +1,427 @@
+Scriptable structures
+=====================
+
+module_qstate
+-----------------------
+
+.. class:: module_qstate
+
+   Module state, per query.
+   
+   This class provides these data attributes:
+   
+   .. attribute:: qinfo
+   
+      (:class:`query_info`) Informations about query being answered. Name, RR type, RR class.
+   
+   .. attribute:: query_flags
+   
+      (uint16) Flags for query. See QF_BIT\_ predefined constants.
+      
+   .. attribute:: is_priming
+   
+      If this is a (stub or root) priming query (with hints).
+   
+   .. attribute:: reply
+   
+      comm_reply contains server replies.
+      
+   .. attribute:: return_msg
+   
+      (:class:`dns_msg`) The reply message, with message for client and calling module (read-only attribute).
+               Note that if you want to create of modify return_msg you should use :class:`DNSMessage`.
+      
+   .. attribute:: return_rcode
+   
+      The rcode, in case of error, instead of a reply message. Determines whether the return_msg contains reply.
+   
+   .. attribute:: region
+   
+      Region for this query. Cleared when query process finishes.
+   
+   .. attribute:: curmod
+   
+      Which module is executing.
+      
+   .. attribute:: ext_state[]
+   
+      Module states.
+      
+   .. attribute:: env
+   
+      Environment for this query.
+      
+   .. attribute:: mesh_info
+   
+      Mesh related information for this query.
+
+
+query_info
+----------------
+
+.. class:: query_info
+
+   This class provides these data attributes:
+
+   .. attribute:: qname
+   
+      The original question in the wireformat format (e.g. \\x03www\\x03nic\\x02cz\\x00 for www.nic.cz)
+   
+   .. attribute:: qname_len
+   
+      Lenght of question name (number of bytes).
+       
+   .. attribute:: qname_list[]
+   
+      The question ``qname`` converted into list of labels (e.g. ['www','nic','cz',''] for www.nic.cz)
+   
+   .. attribute:: qname_str
+   
+      The question ``qname`` converted into string (e.g. www.nic.cz. for www.nic.cz)
+
+   .. attribute:: qtype
+   
+      The class type asked for. See RR_TYPE\_ predefined constants.
+   
+   .. attribute:: qtype_str
+   
+      The ``qtype`` in display presentation format (string) (e.g 'A' for RR_TYPE_A)
+
+   .. attribute:: qclass
+   
+      The question class. See RR_CLASS\_ predefined constants.
+   
+   .. attribute:: qclass_str
+   
+      The ``qclass`` in display presentation format (string).
+   
+reply_info
+--------------------
+
+.. class:: reply_info
+
+   This class provides these data attributes:
+
+   .. attribute:: flags
+   
+      The flags for the answer, host byte order.
+   
+   .. attribute:: qdcount
+   
+      Number of RRs in the query section.
+      If qdcount is not 0, then it is 1, and the data that appears
+      in the reply is the same as the query_info.
+      Host byte order.
+   
+   .. attribute:: ttl
+   
+      TTL of the entire reply (for negative caching).
+      only for use when there are 0 RRsets in this message.
+      if there are RRsets, check those instead.
+   
+   .. attribute:: security
+   
+      The security status from DNSSEC validation of this message. See sec_status\_ predefined constants.
+   
+   .. attribute:: an_numrrsets
+   
+      Number of RRsets in each section.
+      The answer section. Add up the RRs in every RRset to calculate
+      the number of RRs, and the count for the dns packet. 
+      The number of RRs in RRsets can change due to RRset updates.
+   
+   .. attribute:: ns_numrrsets
+   
+      Count of authority section RRsets
+   
+   .. attribute:: ar_numrrsets
+   
+      Count of additional section RRsets 
+   
+   .. attribute:: rrset_count
+   
+      Number of RRsets: an_numrrsets + ns_numrrsets + ar_numrrsets 
+   
+   .. attribute:: rrsets[]
+   
+         (:class:`ub_packed_rrset_key`) List of RR sets in the order in which they appear in the reply message.  
+         Number of elements is ancount + nscount + arcount RRsets.
+   
+   .. attribute:: ref[]
+   
+         (:class:`rrset_ref`) Packed array of ids (see counts) and pointers to packed_rrset_key.
+         The number equals ancount + nscount + arcount RRsets. 
+         These are sorted in ascending pointer, the locking order. So
+         this list can be locked (and id, ttl checked), to see if 
+         all the data is available and recent enough.
+   
+
+dns_msg
+--------------
+
+.. class:: dns_msg
+
+   Region allocated message reply
+
+   This class provides these data attributes:
+
+   .. attribute:: qinfo
+   
+      (:class:`query_info`) Informations about query.
+   
+   .. attribute:: rep
+   
+      (:class:`reply_info`) This attribute points to the packed reply structure.
+
+
+packed_rrset_key
+----------------------
+   
+.. class:: packed_rrset_key
+
+   The identifying information for an RRset.
+
+   This class provides these data attributes:
+
+   .. attribute:: dname
+   
+      The domain name. If not empty (for ``id = None``) it is allocated, and
+      contains the wireformat domain name. This dname is not canonicalized.
+      E.g., the dname contains \\x03www\\x03nic\\x02cz\\x00 for www.nic.cz.
+   
+   .. attribute:: dname_len
+   
+      Length of the domain name, including last 0 root octet. 
+      
+   .. attribute:: dname_list[]
+   
+      The domain name ``dname`` converted into list of labels (see :attr:`query_info.qname_list`).
+   
+   .. attribute:: dname_str
+   
+      The domain name ``dname`` converted into string (see :attr:`query_info.qname_str`).
+
+   .. attribute:: flags
+   
+      Flags.
+      
+   .. attribute:: type
+   
+      The rrset type in network format.
+
+   .. attribute:: type_str
+   
+      The rrset type in display presentation format.
+      
+   .. attribute:: rrset_class
+   
+      The rrset class in network format.
+
+   .. attribute:: rrset_class_str
+   
+      The rrset class in display presentation format.
+
+ub_packed_rrset_key
+-------------------------
+
+.. class:: ub_packed_rrset_key
+
+   This structure contains an RRset. A set of resource records that
+   share the same domain name, type and class.
+   Due to memory management and threading, the key structure cannot be
+   deleted, although the data can be. The id can be set to 0 to store and the
+   structure can be recycled with a new id.
+   
+   The :class:`ub_packed_rrset_key` provides these data attributes:
+   
+   .. attribute:: entry
+      
+      (:class:`lruhash_entry`) Entry into hashtable. Note the lock is never destroyed,
+      even when this key is retired to the cache. 
+      the data pointer (if not None) points to a :class:`packed_rrset`.
+    
+   .. attribute:: id
+      
+      The ID of this rrset. unique, based on threadid + sequenceno. 
+      ids are not reused, except after flushing the cache.
+      zero is an unused entry, and never a valid id.
+      Check this value after getting entry.lock.
+      The other values in this struct may only be altered after changing
+      the id (which needs a writelock on entry.lock).
+      
+   .. attribute:: rk
+   
+      (:class:`packed_rrset_key`) RR set data.
+
+
+lruhash_entry
+-------------------------
+
+.. class:: lruhash_entry
+
+   The :class:`ub_packed_rrset_key` provides these data attributes:
+
+   .. attribute:: lock
+
+      rwlock for access to the contents of the entry. Note that you cannot change hash and key, if so, you have to delete it to change hash or key.
+
+   .. attribute:: data
+
+      (:class:`packed_rrset_data`) entry data stored in wireformat (RRs and RRsigs).
+
+packed_rrset_data
+-----------------------
+   
+.. class:: packed_rrset_data
+
+   Rdata is stored in wireformat. The dname is stored in wireformat.
+   
+   TTLs are stored as absolute values (and could be expired).
+   
+   RRSIGs are stored in the arrays after the regular rrs.
+   
+   You need the packed_rrset_key to know dname, type, class of the
+   resource records in this RRset. (if signed the rrsig gives the type too).
+
+   The :class:`packed_rrset_data` provides these data attributes:
+
+   .. attribute:: ttl
+   
+      TTL (in seconds like time()) of the RRset.
+      Same for all RRs see rfc2181(5.2).
+   
+   .. attribute:: count
+      
+      Number of RRs.
+   
+   .. attribute:: rrsig_count
+      
+      Number of rrsigs, if 0 no rrsigs.
+      
+   .. attribute:: trust
+   
+      The trustworthiness of the RRset data.
+      
+   .. attribute:: security
+   
+      Security status of the RRset data. See sec_status\_ predefined constants.
+      
+   .. attribute:: rr_len[]
+   
+      Length of every RR's rdata, rr_len[i] is size of rr_data[i].
+      
+   .. attribute:: rr_ttl[]
+   
+      TTL of every rr. rr_ttl[i] ttl of rr i.
+      
+   .. attribute:: rr_data[]
+   
+      Array of RR's rdata (list of strings). The rdata is stored in uncompressed wireformat. 
+      The first 16B of rr_data[i] is rdlength in network format.
+   
+
+DNSMessage
+----------------
+   
+.. class:: DNSMessage
+
+   Abstract representation of DNS message.
+   
+   **Usage**
+
+      This example shows how to create an authoritative answer response
+               
+      ::
+
+         msg = DNSMessage(qstate.qinfo.qname_str, RR_TYPE_A, RR_CLASS_IN, PKT_AA)
+
+         #append RR
+         if (qstate.qinfo.qtype == RR_TYPE_A) or (qstate.qinfo.qtype == RR_TYPE_ANY):
+             msg.answer.append("%s 10 IN A 127.0.0.1" % qstate.qinfo.qname_str)
+         
+         #set qstate.return_msg 
+         if not msg.set_return_msg(qstate):
+             raise Exception("Can't create response")
+
+   The :class:`DNSMessage` provides these methods and data attributes:
+   
+   .. method:: __init__(self, rr_name, rr_type, rr_class = RR_CLASS_IN, query_flags = 0, default_ttl = 0)
+   
+      Prepares an answer (DNS packet) from qiven information. Query flags are combination of PKT_xx contants.
+      
+   .. method:: set_return_msg(self, qstate)
+   
+      This method fills qstate return message according to the given informations. 
+               It takes lists of RRs in each section of answer, created necessray RRsets in wire format and store the result in :attr:`qstate.return_msg`.
+               Returns 1 if OK.
+   
+   .. attribute:: rr_name
+   
+      RR name of question.
+      
+   .. attribute:: rr_type
+   
+      RR type of question.
+      
+   .. attribute:: rr_class
+   
+      RR class of question.
+      
+   .. attribute:: default_ttl
+   
+      Default time-to-live.
+      
+   .. attribute:: query_flags
+   
+      Query flags. See PKT\_ predefined constants.
+      
+   .. attribute:: question[]
+   
+      List of resource records that should appear (in the same order) in question section of answer.
+      
+   .. attribute:: answer[]
+   
+      List of resource records that should appear (in the same order) in answer section of answer.
+     
+   .. attribute:: authority[]
+   
+      List of resource records that should appear (in the same order) in authority section of answer.
+      
+   .. attribute:: additional[]
+   
+      List of resource records that should appear (in the same order) in additional section of answer.
+
+pythonmod_env
+-----------------------
+
+.. class:: pythonmod_env
+
+   Global state for the module. 
+
+   This class provides these data attributes:
+
+   .. attribute:: data
+   
+      Here you can keep your own data shared across each thread.
+
+   .. attribute:: fname
+   
+       Python script filename.
+   
+   .. attribute:: qstate
+   
+      Module query state.
+
+pythonmod_qstate
+-----------------------
+
+.. class:: pythonmod_qstate
+
+   Per query state for the iterator module.
+       
+   This class provides these data attributes:
+       
+   .. attribute:: data
+       
+          Here you can keep your own private data (each thread has own data object).
+
diff --git a/pythonmod/doc/source/usecase.rst b/pythonmod/doc/source/usecase.rst
new file mode 100644 (file)
index 0000000..7a77349
--- /dev/null
@@ -0,0 +1,38 @@
+Use cases (examples)
+====================
+
+Dynamic DNS Service discovery (DNS-SD_)
+-------------------------------------------
+Synchronized with database engine, for example *MySQL*. 
+
+.. _DNS-SD: http://www.dns-sd.org/
+
+Firewall control
+----------------
+Control firewall (e.g. enable incomming SSH connection) with DNS query signed with private key. 
+So firewall can blocks every service during normal operation.
+
+Scriptable DNS-based blacklist (DNS-BL_)
+-------------------------------------------
+Scripted in Python with already provided features, takes advantage of DNS reply, because
+almost every mail server supports DNS based blacklisting.
+
+.. _DNS-BL: http://www.dnsbl.org
+
+DNS based Wake-On-Lan
+---------------------
+Controled by secured queries secured with private key.
+
+Dynamic translation service
+---------------------------
+DNS request can be translated to virtualy any answer, that's easy to implement in client side
+because of many DNS libraries available.
+
+Examples :
+ * **Dictionary** - using *IDN* for non-ascii strings transfer, ``dig TXT slovo.en._dict_.nic.cz`` returns translation of "slovo" to EN.
+ * **Translation** - Extends *DNS-SD*, for example DNS to Jabber to find out people logged in.
+ * **Exchange rate calculator** - ``dig TXT 1000.99.czk.eur._rates_.nic.cz`` returns the given sum (1000.99 CZK) in EURs.
+
+Dynamic ENUM service 
+--------------------
+Support for redirection, synchronization, etc.
diff --git a/pythonmod/examples/calc.py b/pythonmod/examples/calc.py
new file mode 100644 (file)
index 0000000..3230e37
--- /dev/null
@@ -0,0 +1,77 @@
+# -*- coding: utf-8 -*-
+'''
+ calc.py: DNS-based calculator 
+
+ Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+                     Marek Vavrusa  (xvavru00 AT stud.fit.vutbr.cz)
+
+ This software is open source.
+ 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 the organization 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 COPYRIGHT HOLDERS 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.
+'''
+
+#Try: dig @localhost 1*25._calc_.cz.
+
+def init(id, cfg): return True
+def deinit(id): return True
+def inform_super(id, qstate, superqstate, qdata): return True
+
+def operate(id, event, qstate, qdata):
+
+    if (event == MODULE_EVENT_NEW) or (event == MODULE_EVENT_PASS):
+
+        if qstate.qinfo.qname_str.endswith("._calc_.cz."):
+            try:
+                res = eval(''.join(qstate.qinfo.qname_list[0:-3]))
+            except:
+                res = "exception"
+
+            msg = DNSMessage(qstate.qinfo.qname_str, RR_TYPE_TXT, RR_CLASS_IN, PKT_QR | PKT_RA | PKT_AA) #, 300)
+            msg.answer.append("%s 300 IN TXT \"%s\"" % (qstate.qinfo.qname_str,res))
+            if not msg.set_return_msg(qstate):
+               qstate.ext_state[id] = MODULE_ERROR 
+               return True
+
+            qstate.return_rcode = RCODE_NOERROR
+            qstate.ext_state[id] = MODULE_FINISHED 
+            return True
+
+        else: 
+            #Pass on the unknown query to the iterator
+            qstate.ext_state[id] = MODULE_WAIT_MODULE 
+            return True
+
+    elif event == MODULE_EVENT_MODDONE: 
+        #the iterator has finished
+        qstate.ext_state[id] = MODULE_FINISHED
+        return True
+
+    log_err("pythonmod: Unknown event")
+    qstate.ext_state[id] = MODULE_ERROR
+    return True
+
diff --git a/pythonmod/examples/dict.py b/pythonmod/examples/dict.py
new file mode 100644 (file)
index 0000000..c8088a8
--- /dev/null
@@ -0,0 +1,121 @@
+# -*- coding: utf-8 -*-
+'''
+ calc.py: DNS-based czech-english dictionary
+
+ Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+                     Marek Vavrusa  (xvavru00 AT stud.fit.vutbr.cz)
+
+ This software is open source.
+ 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 the organization 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 COPYRIGHT HOLDERS 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.
+'''
+import os
+cz_dict = {}
+en_dict = {}
+
+def init(id, cfg):
+   log_info("pythonmod: dict init")
+   f = open("examples/dict_data.txt", "r")
+   try:
+      for line in f:
+         if line.startswith('#'):
+            continue
+         itm = line.split("\t", 3)
+         if len(itm) < 2: 
+            continue
+         en,cs = itm[0:2]
+
+         if not (cs in cz_dict):
+            cz_dict[cs] = [en]     # [cs] = en
+         else:
+            cz_dict[cs].append(en) # [cs] = en
+
+         if not (en in en_dict):
+            en_dict[en] = [cs]     # [en] = cs
+         else:
+            en_dict[en].append(cs) # [en] = cs
+
+   finally:
+      f.close()
+   return True
+
+def deinit(id):
+   log_info("pythonmod: dict deinit")
+   return True
+
+def operate(id, event, qstate, qdata):
+    if (event == MODULE_EVENT_NEW) or (event == MODULE_EVENT_PASS):
+
+       if qstate.qinfo.qname_str.endswith("._dict_.cz."):
+        
+         aword = ' '.join(qstate.qinfo.qname_list[0:-4])
+         adict = qstate.qinfo.qname_list[-4]
+
+         log_info("pythonmod: dictionary look up; word:%s dict:%s" % (aword,adict))
+
+         words = []
+         if (adict == "en") and (aword in en_dict):
+            words = en_dict[aword] # EN -> CS
+         if (adict == "cs") and (aword in cz_dict):
+            words = cz_dict[aword] # CS -> EN
+
+         if len(words) and ((qstate.qinfo.qtype == RR_TYPE_TXT) or (qstate.qinfo.qtype == RR_TYPE_ANY)):
+
+            msg = DNSMessage(qstate.qinfo.qname_str, RR_TYPE_TXT, RR_CLASS_IN, PKT_RD | PKT_RA | PKT_AA)
+            for w in words:
+                msg.answer.append("%s 300 IN TXT \"%s\"" % (qstate.qinfo.qname_str,w.replace("\"","\\\"")))
+
+            if not msg.set_return_msg(qstate):
+               qstate.ext_state[id] = MODULE_ERROR 
+               return True
+
+            qstate.return_rcode = RCODE_NOERROR
+            qstate.ext_state[id] = MODULE_FINISHED 
+            return True
+
+         else:
+            qstate.return_rcode = RCODE_SERVFAIL
+            qstate.ext_state[id] = MODULE_FINISHED 
+            return True
+
+       else: #Pass on the unknown query to the iterator
+         qstate.ext_state[id] = MODULE_WAIT_MODULE 
+         return True
+
+    elif event == MODULE_EVENT_MODDONE: #the iterator has finished
+         #we don't need modify result
+         qstate.ext_state[id] = MODULE_FINISHED
+         return True
+
+    log_err("pythonmod: Unknown event")
+    qstate.ext_state[id] = MODULE_ERROR
+    return True
+
+def inform_super(id, qstate, superqstate, qdata):
+   return True
+
diff --git a/pythonmod/examples/dict_data.txt b/pythonmod/examples/dict_data.txt
new file mode 100644 (file)
index 0000000..04cd3ba
--- /dev/null
@@ -0,0 +1,6 @@
+*      *                       web
+computer       poèítaèový      adj:            Zdenìk Bro¾
+computer       poèítaè n:              
+domain doména  n:              Zdenìk Bro¾
+query  otazník n:              Zdenìk Bro¾
+network        sí»     n: [it.]        poèítaèová      
diff --git a/pythonmod/examples/log.py b/pythonmod/examples/log.py
new file mode 100644 (file)
index 0000000..c17106b
--- /dev/null
@@ -0,0 +1,119 @@
+import os
+'''
+ calc.py: Response packet logger
+
+ Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+                     Marek Vavrusa  (xvavru00 AT stud.fit.vutbr.cz)
+
+ This software is open source.
+ 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 the organization 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 COPYRIGHT HOLDERS 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.
+'''
+
+def dataHex(data, prefix=""):
+    """Converts binary string data to display representation form"""
+    res = ""
+    for i in range(0, (len(data)+15)/16):
+        res += "%s0x%02X | " % (prefix, i*16)
+        d = map(lambda x:ord(x), data[i*16:i*16+17])
+        for ch in d:
+            res += "%02X " % ch
+        for i in range(0,17-len(d)):
+            res += "   "
+        res += "| "
+        for ch in d:
+            if (ch < 32) or (ch > 127):
+                res += ". "
+            else:
+                res += "%c " % ch
+        res += "\n"
+    return res
+
+def logDnsMsg(qstate):
+    """Logs response"""
+
+    r  = qstate.return_msg.rep
+    q  = qstate.return_msg.qinfo
+
+    print "-"*100
+    print("Query: %s, type: %s (%d), class: %s (%d) " % (
+            qstate.qinfo.qname_str, qstate.qinfo.qtype_str, qstate.qinfo.qtype,
+            qstate.qinfo.qclass_str, qstate.qinfo.qclass))
+    print "-"*100
+    print "Return    reply :: flags: %04X, QDcount: %d, Security:%d, TTL=%d" % (r.flags, r.qdcount, r.security, r.ttl)
+    print "          qinfo :: qname: %s %s, qtype: %s, qclass: %s" % (str(q.qname_list), q.qname_str, q.qtype_str, q.qclass_str)
+
+    if (r):
+        print "Reply:"
+        for i in range(0, r.rrset_count):
+            rr = r.rrsets[i]
+
+            rk = rr.rk
+            print i,":",rk.dname_list, rk.dname_str, "flags: %04X" % rk.flags,
+            print "type:",rk.type_str,"(%d)" % ntohs(rk.type), "class:",rk.rrset_class_str,"(%d)" % ntohs(rk.rrset_class)
+
+            d = rr.entry.data
+            for j in range(0,d.count+d.rrsig_count):
+                print "  ",j,":","TTL=",d.rr_ttl[j],
+                if (j >= d.count): print "rrsig",
+                print 
+                print dataHex(d.rr_data[j],"       ")
+
+    print "-"*100
+
+def init(id, cfg):
+   log_info("pythonmod: init called, module id is %d port: %d script: %s" % (id, cfg.port, cfg.python_script))
+   return True
+
+def deinit(id):
+   log_info("pythonmod: deinit called, module id is %d" % id)
+   return True
+
+def inform_super(id, qstate, superqstate, qdata):
+   return True
+
+def operate(id, event, qstate, qdata):
+   log_info("pythonmod: operate called, id: %d, event:%s" % (id, strmodulevent(event)))
+  
+   if (event == MODULE_EVENT_NEW) or (event == MODULE_EVENT_PASS):
+      #Pass on the new event to the iterator
+      qstate.ext_state[id] = MODULE_WAIT_MODULE 
+      return True
+
+   if event == MODULE_EVENT_MODDONE:
+      #Iterator finished, show response (if any)
+
+      if (qstate.return_msg):
+          logDnsMsg(qstate)
+
+      qstate.ext_state[id] = MODULE_FINISHED 
+      return True
+
+   qstate.ext_state[id] = MODULE_ERROR
+   return True
+
diff --git a/pythonmod/examples/resgen.py b/pythonmod/examples/resgen.py
new file mode 100644 (file)
index 0000000..804c0bd
--- /dev/null
@@ -0,0 +1,73 @@
+'''
+ resgen.py: This example shows how to generate authoritative response
+
+ Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+                     Marek Vavrusa  (xvavru00 AT stud.fit.vutbr.cz)
+
+ This software is open source.
+ 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 the organization 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 COPYRIGHT HOLDERS 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.
+'''
+def init(id, cfg): return True
+
+def deinit(id): return True
+
+def inform_super(id, qstate, superqstate, qdata): return True
+
+def operate(id, event, qstate, qdata):
+    if (event == MODULE_EVENT_NEW) or (event == MODULE_EVENT_PASS):
+        if (qstate.qinfo.qname_str.endswith(".localdomain.")): #query name ends with localdomain
+            #create instance of DNS message (packet) with given parameters
+            msg = DNSMessage(qstate.qinfo.qname_str, RR_TYPE_A, RR_CLASS_IN, PKT_QR | PKT_RA | PKT_AA)
+            #append RR
+            if (qstate.qinfo.qtype == RR_TYPE_A) or (qstate.qinfo.qtype == RR_TYPE_ANY):
+                msg.answer.append("%s 10 IN A 127.0.0.1" % qstate.qinfo.qname_str)
+            #set qstate.return_msg 
+            if not msg.set_return_msg(qstate):
+                qstate.ext_state[id] = MODULE_ERROR 
+                return True
+
+            #we don't need validation, result is valid
+            qstate.return_msg.rep.security = 2
+
+            qstate.return_rcode = RCODE_NOERROR
+            qstate.ext_state[id] = MODULE_FINISHED 
+            return True
+        else:
+            #pass the query to validator
+            qstate.ext_state[id] = MODULE_WAIT_MODULE 
+            return True
+
+    if event == MODULE_EVENT_MODDONE:
+        log_info("pythonmod: iterator module done")
+        qstate.ext_state[id] = MODULE_FINISHED 
+        return True
+      
+    log_err("pythonmod: bad event")
+    qstate.ext_state[id] = MODULE_ERROR
+    return True
diff --git a/pythonmod/examples/resmod.py b/pythonmod/examples/resmod.py
new file mode 100644 (file)
index 0000000..cf392e4
--- /dev/null
@@ -0,0 +1,88 @@
+'''
+ resmod.py: This example shows how to modify the response from iterator 
+
+ Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+                     Marek Vavrusa  (xvavru00 AT stud.fit.vutbr.cz)
+
+ This software is open source.
+ 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 the organization 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 COPYRIGHT HOLDERS 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.
+'''
+
+def init(id, cfg): return True
+
+def deinit(id): return True
+
+def inform_super(id, qstate, superqstate, qdata): return True
+
+def setTTL(qstate, ttl):
+    """Updates return_msg TTL and the TTL of all the RRs"""
+    if qstate.return_msg:
+        qstate.return_msg.rep.ttl = ttl
+        if (qstate.return_msg.rep):
+            for i in range(0,qstate.return_msg.rep.rrset_count):
+                d = qstate.return_msg.rep.rrsets[i].entry.data
+                for j in range(0,d.count+d.rrsig_count):
+                    d.rr_ttl[j] = ttl
+
+def operate(id, event, qstate, qdata):
+    if (event == MODULE_EVENT_NEW) or (event == MODULE_EVENT_PASS):
+        #pass the query to validator
+        qstate.ext_state[id] = MODULE_WAIT_MODULE 
+        return True
+
+    if event == MODULE_EVENT_MODDONE:
+        log_info("pythonmod: iterator module done")
+
+        if not qstate.return_msg:
+            qstate.ext_state[id] = MODULE_FINISHED 
+            return True
+
+        #modify the response
+
+        qdn = qstate.qinfo.qname_str
+        if qdn.endswith(".nic.cz."):
+            #invalidate response in cache added by iterator
+            #invalidateQueryInCache(qstate, qstate.return_msg.qinfo)
+
+            #modify TTL to 10 secs and store response in cache
+            #setTTL(qstate, 5)
+            #if not storeQueryInCache(qstate, qstate.return_msg.qinfo, qstate.return_msg.rep, 0):
+            #    qstate.ext_state[id] = MODULE_ERROR
+            #    return False
+
+            #modify TTL of response, which will be send to a) validator and then b) client
+            setTTL(qstate, 10)
+            qstate.return_rcode = RCODE_NOERROR
+
+        qstate.ext_state[id] = MODULE_FINISHED 
+        return True
+      
+    log_err("pythonmod: bad event")
+    qstate.ext_state[id] = MODULE_ERROR
+    return True
diff --git a/pythonmod/interface.i b/pythonmod/interface.i
new file mode 100644 (file)
index 0000000..399cbd5
--- /dev/null
@@ -0,0 +1,803 @@
+/*
+ * interface.i: unbound python module
+ */
+
+%module Unbound
+%{
+   #include <sys/types.h>
+   #include <sys/socket.h>
+   #include <netinet/in.h>
+   #include <arpa/inet.h>
+   #include <stdarg.h>
+   #include "config.h"
+   #include "util/log.h"
+   #include "util/module.h"
+   #include "util/regional.h"
+   #include "util/config_file.h"
+   #include "util/data/msgreply.h"
+   #include "util/data/packed_rrset.h"
+   #include "util/storage/lruhash.h"
+   #include "services/cache/dns.h"
+%}
+
+%include "stdint.i" // uint_16_t can be known type now
+
+%inline %{
+   //converts [len][data][len][data][0] string to a List of labels (PyStrings)
+   PyObject* GetNameAsLabelList(const char* name, int len) {
+     PyObject* list;
+     int cnt=0, i;
+
+     i = 0;
+     while (i < len) {
+        i += name[i] + 1;
+        cnt++;
+     }
+
+     list = PyList_New(cnt);
+     i = 0; cnt = 0;
+     while (i < len) {
+        PyList_SetItem(list, cnt, PyString_FromStringAndSize(name + i + 1, name[i]));
+        i += name[i] + 1;
+        cnt++;
+     }
+     return list;
+   }
+%}
+
+/* ************************************************************************************ * 
+   Structure query_info
+ * ************************************************************************************ */
+/* Query info */
+%ignore query_info::qname;
+%ignore query_info::qname_len;
+
+
+struct query_info {
+   %immutable;
+   char* qname;
+   size_t qname_len;
+   uint16_t qtype;
+   uint16_t qclass;
+   %mutable;
+};
+
+%inline %{
+   enum enum_rr_class  { 
+      RR_CLASS_IN = 1,
+      RR_CLASS_CH      = 3,
+      RR_CLASS_HS      = 4,
+      RR_CLASS_NONE = 254,
+      RR_CLASS_ANY = 255,
+   };
+   
+   enum enum_rr_type {
+      RR_TYPE_A = 1, 
+      RR_TYPE_NS = 2, 
+      RR_TYPE_MD = 3, 
+      RR_TYPE_MF = 4, 
+      RR_TYPE_CNAME = 5, 
+      RR_TYPE_SOA = 6, 
+      RR_TYPE_MB = 7, 
+      RR_TYPE_MG = 8, 
+      RR_TYPE_MR = 9, 
+      RR_TYPE_NULL = 10,
+      RR_TYPE_WKS = 11,
+      RR_TYPE_PTR = 12,
+      RR_TYPE_HINFO = 13,
+      RR_TYPE_MINFO = 14,
+      RR_TYPE_MX = 15,
+      RR_TYPE_TXT = 16,
+      RR_TYPE_RP = 17,
+      RR_TYPE_AFSDB = 18,
+      RR_TYPE_X25 = 19,
+      RR_TYPE_ISDN = 20,
+      RR_TYPE_RT = 21,
+      RR_TYPE_NSAP = 22,
+      RR_TYPE_NSAP_PTR = 23,
+      RR_TYPE_SIG = 24,
+      RR_TYPE_KEY = 25,
+      RR_TYPE_PX = 26,
+      RR_TYPE_GPOS = 27,
+      RR_TYPE_AAAA = 28,
+      RR_TYPE_LOC = 29,
+      RR_TYPE_NXT = 30,
+      RR_TYPE_EID = 31,
+      RR_TYPE_NIMLOC = 32,
+      RR_TYPE_SRV = 33,
+      RR_TYPE_ATMA = 34,
+      RR_TYPE_NAPTR = 35,
+      RR_TYPE_KX = 36,
+      RR_TYPE_CERT = 37,
+      RR_TYPE_A6 = 38,
+      RR_TYPE_DNAME = 39,
+      RR_TYPE_SINK = 40,
+      RR_TYPE_OPT = 41,
+      RR_TYPE_APL = 42,
+      RR_TYPE_DS = 43,
+      RR_TYPE_SSHFP = 44,
+      RR_TYPE_IPSECKEY = 45,
+      RR_TYPE_RRSIG = 46,
+      RR_TYPE_NSEC = 47,      
+      RR_TYPE_DNSKEY = 48,
+      RR_TYPE_DHCID = 49,
+      RR_TYPE_NSEC3 = 50,
+      RR_TYPE_NSEC3PARAMS = 51,
+      RR_TYPE_UINFO = 100,
+      RR_TYPE_UID = 101,
+      RR_TYPE_GID = 102,
+      RR_TYPE_UNSPEC = 103,
+      RR_TYPE_TSIG = 250,
+      RR_TYPE_IXFR = 251,
+      RR_TYPE_AXFR = 252,
+      RR_TYPE_MAILB = 253,
+      RR_TYPE_MAILA = 254,
+      RR_TYPE_ANY = 255,
+      RR_TYPE_DLV = 32769,
+   };
+
+   PyObject* _get_qname(struct query_info* q) {
+      return PyString_FromStringAndSize(q->qname, q->qname_len);
+   } 
+
+   PyObject* _get_qname_components(struct query_info* q) {
+      return GetNameAsLabelList(q->qname, q->qname_len);
+   }
+%}
+
+%inline %{
+   PyObject* dnameAsStr(const char* dname) {
+       char buf[LDNS_MAX_DOMAINLEN+1];
+       buf[0] = '\0';
+       dname_str(dname, buf);
+       return PyString_FromString(buf);
+   }
+%}
+
+%extend query_info {
+   %pythoncode %{
+        def _get_qtype_str(self): return ldns_rr_type2str(self.qtype)
+        __swig_getmethods__["qtype_str"] = _get_qtype_str
+        if _newclass:qtype_str = _swig_property(_get_qtype_str)
+
+        def _get_qclass_str(self): return ldns_rr_class2str(self.qclass)
+        __swig_getmethods__["qclass_str"] = _get_qclass_str
+        if _newclass:qclass_str = _swig_property(_get_qclass_str)
+
+        __swig_getmethods__["qname"] = _Unbound._get_qname
+        if _newclass:qname = _swig_property(_Unbound._get_qname)
+        
+        __swig_getmethods__["qname_list"] = _Unbound._get_qname_components
+        if _newclass:qname_list = _swig_property(_Unbound._get_qname_components)
+
+        def _get_qname_str(self): return dnameAsStr(self.qname)
+        __swig_getmethods__["qname_str"] = _get_qname_str
+        if _newclass:qname_str = _swig_property(_get_qname_str)
+   %}
+}
+
+/* ************************************************************************************ * 
+   Structure packed_rrset_key
+ * ************************************************************************************ */
+%ignore packed_rrset_key::dname;
+%ignore packed_rrset_key::dname_len;
+
+/* RRsets */
+struct packed_rrset_key {
+   %immutable;
+   char*    dname;
+   size_t   dname_len;
+   uint32_t flags; 
+   uint16_t type;  //rrset type in network format
+   uint16_t rrset_class; //rrset class in network format
+   %mutable;
+};
+
+//This subroutine converts values between the host and network byte order. 
+//Specifically, ntohs() converts 16-bit quantities from network byte order to host byte order.
+uint16_t ntohs(uint16_t netshort);
+
+%inline %{
+   PyObject* _get_dname(struct packed_rrset_key* k) {
+      return PyString_FromStringAndSize(k->dname, k->dname_len);
+   } 
+   PyObject* _get_dname_components(struct packed_rrset_key* k) {
+      return GetNameAsLabelList(k->dname, k->dname_len);
+   }
+%}
+
+%extend packed_rrset_key {
+   %pythoncode %{
+        def _get_type_str(self): return ldns_rr_type2str(_Unbound.ntohs(self.type))
+        __swig_getmethods__["type_str"] = _get_type_str
+        if _newclass:type_str = _swig_property(_get_type_str)
+
+        def _get_class_str(self): return ldns_rr_class2str(_Unbound.ntohs(self.rrset_class))
+        __swig_getmethods__["rrset_class_str"] = _get_class_str
+        if _newclass:rrset_class_str = _swig_property(_get_class_str)
+
+        __swig_getmethods__["dname"] = _Unbound._get_dname
+        if _newclass:dname = _swig_property(_Unbound._get_dname)
+
+        __swig_getmethods__["dname_list"] = _Unbound._get_dname_components
+        if _newclass:dname_list = _swig_property(_Unbound._get_dname_components)
+
+        def _get_dname_str(self): return dnameAsStr(self.dname)
+        __swig_getmethods__["dname_str"] = _get_dname_str
+        if _newclass:dname_str = _swig_property(_get_dname_str)
+   %}
+}
+
+#if defined(SWIGWORDSIZE64) 
+typedef long int                rrset_id_t;
+#else 
+typedef long long int           rrset_id_t;
+#endif 
+
+struct ub_packed_rrset_key {
+   struct lruhash_entry entry;
+   rrset_id_t id;
+   struct packed_rrset_key rk;
+};
+
+struct lruhash_entry {
+       lock_rw_t lock;
+       struct lruhash_entry* overflow_next;
+       struct lruhash_entry* lru_next;
+       struct lruhash_entry* lru_prev;
+       hashvalue_t hash;
+       void* key;
+       struct packed_rrset_data* data;
+};
+
+%ignore packed_rrset_data::rr_len;
+%ignore packed_rrset_data::rr_ttl;
+%ignore packed_rrset_data::rr_data;
+
+struct packed_rrset_data {
+       uint32_t ttl; //TTL (in seconds like time())
+
+       size_t count; //number of rrs
+       size_t rrsig_count; //number of rrsigs
+
+       enum rrset_trust trust; 
+       enum sec_status security;
+
+       size_t* rr_len;   //length of every rr's rdata
+       uint32_t *rr_ttl; //ttl of every rr
+       uint8_t** rr_data; //array of pointers to every rr's rdata; The rr_data[i] rdata is stored in uncompressed wireformat. 
+};
+
+%pythoncode %{
+    class RRSetData_RRLen:
+        def __init__(self, obj): self.obj = obj
+        def __getitem__(self, index): return _Unbound._get_data_rr_len(self.obj, index)
+        def __len__(self): return obj.count + obj.rrsig_count
+    class RRSetData_RRTTL:
+        def __init__(self, obj): self.obj = obj
+        def __getitem__(self, index): return _Unbound._get_data_rr_ttl(self.obj, index)
+        def __setitem__(self, index, value): _Unbound._set_data_rr_ttl(self.obj, index, value)
+        def __len__(self): return obj.count + obj.rrsig_count
+    class RRSetData_RRData:
+        def __init__(self, obj): self.obj = obj
+        def __getitem__(self, index): return _Unbound._get_data_rr_data(self.obj, index)
+        def __len__(self): return obj.count + obj.rrsig_count
+%}
+
+%inline %{
+   PyObject* _get_data_rr_len(struct packed_rrset_data* d, int idx) {
+     if ((d != NULL) && (idx >= 0) && (idx < (d->count+d->rrsig_count))) 
+        return PyInt_FromLong(d->rr_len[idx]);
+     return Py_None;
+   }
+   void _set_data_rr_ttl(struct packed_rrset_data* d, int idx, uint32_t ttl)
+   {
+     if ((d != NULL) && (idx >= 0) && (idx < (d->count+d->rrsig_count))) 
+        d->rr_ttl[idx] = ttl;
+   }
+   PyObject* _get_data_rr_ttl(struct packed_rrset_data* d, int idx) {
+     if ((d != NULL) && (idx >= 0) && (idx < (d->count+d->rrsig_count))) 
+        return PyInt_FromLong(d->rr_ttl[idx]);
+     return Py_None;
+   }
+   PyObject* _get_data_rr_data(struct packed_rrset_data* d, int idx) {
+     if ((d != NULL) && (idx >= 0) && (idx < (d->count+d->rrsig_count))) 
+        return PyString_FromStringAndSize(d->rr_data[idx],d->rr_len[idx]);
+     return Py_None;
+   }
+%}
+
+%extend packed_rrset_data {
+   %pythoncode %{
+        def _get_data_rr_len(self): return RRSetData_RRLen(self)
+        __swig_getmethods__["rr_len"] = _get_data_rr_len
+        if _newclass:rr_len = _swig_property(_get_data_rr_len)
+        def _get_data_rr_ttl(self): return RRSetData_RRTTL(self)
+        __swig_getmethods__["rr_ttl"] =_get_data_rr_ttl
+        if _newclass:rr_len = _swig_property(_get_data_rr_ttl)
+        def _get_data_rr_data(self): return RRSetData_RRData(self)
+        __swig_getmethods__["rr_data"] = _get_data_rr_data
+        if _newclass:rr_len = _swig_property(_get_data_rr_data)
+   %}
+}
+
+/* ************************************************************************************ * 
+   Structure reply_info
+ * ************************************************************************************ */
+/* Messages */
+%ignore reply_info::rrsets;
+%ignore reply_info::ref;
+
+struct reply_info {
+   uint16_t flags;
+   uint16_t qdcount;
+   uint32_t ttl;
+
+   uint16_t authoritative;
+   enum sec_status security;
+
+   size_t an_numrrsets;
+   size_t ns_numrrsets;
+   size_t ar_numrrsets;
+   size_t rrset_count; // an_numrrsets + ns_numrrsets + ar_numrrsets
+
+   struct ub_packed_rrset_key** rrsets;
+   struct rrset_ref ref[1]; //?
+};
+
+struct rrset_ref {
+       struct ub_packed_rrset_key* key;
+       rrset_id_t id;
+};
+
+struct dns_msg {
+   struct query_info qinfo;
+   struct reply_info *rep;
+};
+
+%pythoncode %{
+    class ReplyInfo_RRSet:
+        def __init__(self, obj): self.obj = obj
+        def __getitem__(self, index): return _Unbound._rrset_rrsets_get(self.obj, index)
+        def __len__(self): return obj.rrset_count
+
+    class ReplyInfo_Ref:
+        def __init__(self, obj): self.obj = obj
+        def __getitem__(self, index): return _Unbound._rrset_ref_get(self.obj, index)
+        def __len__(self): return obj.rrset_count
+%}
+
+%inline %{
+   struct ub_packed_rrset_key* _rrset_rrsets_get(struct reply_info* r, int idx) {
+     if ((r != NULL) && (idx >= 0) && (idx < r->rrset_count))
+        return r->rrsets[idx];
+     return NULL;
+   }
+
+   struct rrset_ref* _rrset_ref_get(struct reply_info* r, int idx) {
+     if ((r != NULL) && (idx >= 0) && (idx < r->rrset_count)) {
+//printf("_rrset_ref_get: %lX key:%lX\n", r->ref + idx, r->ref[idx].key);
+             return &(r->ref[idx]);
+//        return &(r->ref[idx]);
+     }
+//printf("_rrset_ref_get: NULL\n");
+     return NULL;
+   }
+%}
+
+%extend reply_info {
+   %pythoncode %{
+        def _rrset_ref_get(self): return ReplyInfo_Ref(self)
+        __swig_getmethods__["ref"] = _rrset_ref_get
+        if _newclass:ref = _swig_property(_rrset_ref_get)
+
+        def _rrset_rrsets_get(self): return ReplyInfo_RRSet(self)
+        __swig_getmethods__["rrsets"] = _rrset_rrsets_get
+        if _newclass:rrsets = _swig_property(_rrset_rrsets_get)
+   %}
+}
+
+/* ************************************************************************************ * 
+   Structure module_qstate
+ * ************************************************************************************ */
+%ignore module_qstate::ext_state;
+%ignore module_qstate::minfo;
+
+/* Query state */
+struct module_qstate {
+   struct query_info qinfo;
+   uint16_t query_flags; //See QF_BIT_xx constants
+   int      is_priming;
+
+   struct comm_reply* reply;
+   struct dns_msg* return_msg;
+   int    return_rcode;
+   struct regional* region; /* unwrapped */
+
+   int    curmod;
+
+   enum   module_ext_state ext_state[MAX_MODULE];
+   void*  minfo[MAX_MODULE];
+
+   struct module_env* env;         /* unwrapped */
+   struct mesh_state* mesh_info;
+};
+
+%constant int MODULE_COUNT = MAX_MODULE;
+
+%constant int QF_BIT_CD = 0x0010;
+%constant int QF_BIT_AD = 0x0020;
+%constant int QF_BIT_Z  = 0x0040;
+%constant int QF_BIT_RA = 0x0080;
+%constant int QF_BIT_RD = 0x0100;
+%constant int QF_BIT_TC = 0x0200;
+%constant int QF_BIT_AA = 0x0400;
+%constant int QF_BIT_QR = 0x8000;
+
+%inline %{
+ enum enum_return_rcode {
+       RCODE_NOERROR = 0,
+       RCODE_FORMERR = 1,
+       RCODE_SERVFAIL = 2,
+       RCODE_NXDOMAIN = 3,
+       RCODE_NOTIMPL = 4,
+       RCODE_REFUSED = 5,
+       RCODE_YXDOMAIN = 6,
+       RCODE_YXRRSET = 7,
+       RCODE_NXRRSET = 8,
+       RCODE_NOTAUTH = 9,
+       RCODE_NOTZONE = 10
+ };
+%}
+
+%pythoncode %{
+    class ExtState:
+        def __init__(self, obj): self.obj = obj
+        def __str__(self):
+            return ", ".join([_Unbound.strextstate(_Unbound._ext_state_get(self.obj,a)) for a in range(0, _Unbound.MODULE_COUNT)])
+        def __getitem__(self, index): return _Unbound._ext_state_get(self.obj, index)
+        def __setitem__(self, index, value): _Unbound._ext_state_set(self.obj, index, value)
+        def __len__(self): return _Unbound.MODULE_COUNT
+%}
+
+%inline %{
+   enum module_ext_state _ext_state_get(struct module_qstate* q, int idx) {
+     if ((q != NULL) && (idx >= 0) && (idx < MAX_MODULE)) {
+        return q->ext_state[idx];
+     } 
+     return 0;
+   }
+  
+   void _ext_state_set(struct module_qstate* q, int idx, enum module_ext_state state) {
+     if ((q != NULL) && (idx >= 0) && (idx < MAX_MODULE)) {
+        q->ext_state[idx] = state;
+     } 
+   }
+%}
+
+%extend module_qstate {
+   %pythoncode %{
+        def set_ext_state(self, id, state):
+            """Sets the ext state"""
+            _Unbound._ext_state_set(self, id, state)
+
+        def __ext_state_get(self): return ExtState(self)
+        __swig_getmethods__["ext_state"] = __ext_state_get
+        if _newclass:ext_state = _swig_property(__ext_state_get)#, __ext_state_set)
+   %}
+}
+
+/* ************************************************************************************ * 
+   Structure config_strlist
+ * ************************************************************************************ */
+struct config_strlist {
+   struct config_strlist* next;
+   char* str;
+};
+
+/* ************************************************************************************ * 
+   Structure config_str2list
+ * ************************************************************************************ */
+struct config_str2list {
+   struct config_str2list* next;
+   char* str;
+   char* str2;
+};
+
+/* ************************************************************************************ * 
+   Structure config_file
+ * ************************************************************************************ */
+struct config_file {
+   int verbosity;
+   int stat_interval;
+   int stat_cumulative;
+   int stat_extended;
+   int num_threads;
+   int port;
+   int do_ip4;
+   int do_ip6;
+   int do_udp;
+   int do_tcp;
+   int outgoing_num_ports;
+   size_t outgoing_num_tcp;
+   size_t incoming_num_tcp;
+   int* outgoing_avail_ports;
+   size_t msg_buffer_size;
+   size_t msg_cache_size;
+   size_t msg_cache_slabs;
+   size_t num_queries_per_thread;
+   size_t jostle_time;
+   size_t rrset_cache_size;
+   size_t rrset_cache_slabs;
+   int host_ttl;
+   int lame_ttl;
+   size_t infra_cache_slabs;
+   size_t infra_cache_numhosts;
+   size_t infra_cache_lame_size;
+   char* target_fetch_policy;
+   int if_automatic;
+   int num_ifs;
+   char **ifs;
+   int num_out_ifs;
+   char **out_ifs;
+   struct config_strlist* root_hints;
+   struct config_stub* stubs;
+   struct config_stub* forwards;
+   struct config_strlist* donotqueryaddrs;
+   struct config_str2list* acls;
+   int donotquery_localhost;
+   int harden_short_bufsize;
+   int harden_large_queries;
+   int harden_glue;
+   int harden_dnssec_stripped;
+   int harden_referral_path;
+   int use_caps_bits_for_id;
+   struct config_strlist* private_address;
+   struct config_strlist* private_domain;
+   size_t unwanted_threshold;
+   char* chrootdir;
+   char* username;
+   char* directory;
+   char* logfile;
+   char* pidfile;
+   int use_syslog;
+   int hide_identity;
+   int hide_version;
+   char* identity;
+   char* version;
+   char* module_conf;
+   struct config_strlist* trust_anchor_file_list;
+   struct config_strlist* trust_anchor_list;
+   struct config_strlist* trusted_keys_file_list;
+   char* dlv_anchor_file;
+   struct config_strlist* dlv_anchor_list;
+   int max_ttl;
+   int32_t val_date_override;
+   int bogus_ttl; 
+   int val_clean_additional;
+   int val_permissive_mode;
+   char* val_nsec3_key_iterations;
+   size_t key_cache_size;
+   size_t key_cache_slabs;
+   size_t neg_cache_size;
+   struct config_str2list* local_zones;
+   struct config_strlist* local_zones_nodefault;
+   struct config_strlist* local_data;
+   int remote_control_enable;
+   struct config_strlist* control_ifs;
+   int control_port;
+   char* server_key_file;
+   char* server_cert_file;
+   char* control_key_file;
+   char* control_cert_file;
+   int do_daemonize;
+   char* python_script;
+};
+
+/* ************************************************************************************ * 
+   Enums
+ * ************************************************************************************ */
+%rename ("MODULE_STATE_INITIAL") "module_state_initial";
+%rename ("MODULE_WAIT_REPLY") "module_wait_reply";
+%rename ("MODULE_WAIT_MODULE") "module_wait_module";
+%rename ("MODULE_WAIT_SUBQUERY") "module_wait_subquery";
+%rename ("MODULE_ERROR") "module_error";
+%rename ("MODULE_FINISHED") "module_finished";
+
+enum module_ext_state {
+   module_state_initial = 0,
+   module_wait_reply,
+   module_wait_module,
+   module_wait_subquery,
+   module_error,
+   module_finished
+};
+
+%rename ("MODULE_EVENT_NEW") "module_event_new";
+%rename ("MODULE_EVENT_PASS") "module_event_pass";
+%rename ("MODULE_EVENT_REPLY") "module_event_reply";
+%rename ("MODULE_EVENT_NOREPLY") "module_event_noreply";
+%rename ("MODULE_EVENT_CAPSFAIL") "module_event_capsfail";
+%rename ("MODULE_EVENT_MODDONE") "module_event_moddone";
+%rename ("MODULE_EVENT_ERROR") "module_event_error";
+
+enum module_ev {
+   module_event_new = 0,
+   module_event_pass,
+   module_event_reply,
+   module_event_noreply,
+   module_event_capsfail,
+   module_event_moddone,
+   module_event_error
+};
+
+enum sec_status {
+   sec_status_unchecked = 0,
+   sec_status_bogus,
+   sec_status_indeterminate,
+   sec_status_insecure,
+   sec_status_secure
+};
+
+enum verbosity_value {
+   NO_VERBOSE = 0,
+   VERB_OPS,
+   VERB_DETAIL,
+   VERB_QUERY,
+   VERB_ALGO
+};
+
+%{
+int checkList(PyObject *l) 
+{
+    PyObject* item;
+    int i;
+
+    if (l == Py_None) 
+       return 1;
+
+    if (PyList_Check(l)) 
+    {
+       for (i=0; i < PyList_Size(l); i++) 
+       {
+           item = PyList_GetItem(l, i);
+           if (!PyString_Check(item))
+              return 0;
+       }
+       return 1;
+    }
+
+    return 0;
+}
+
+ldns_rr_list* createRRList(PyObject *l, uint32_t default_ttl) 
+{
+    PyObject* item;
+    ldns_status status;
+    ldns_rr_list* rr_list;
+    ldns_rr* rr;
+    int i;
+
+    if (PyList_Size(l) == 0)
+       return NULL;
+
+    rr_list = ldns_rr_list_new();
+
+    for (i=0; i < PyList_Size(l); i++) 
+    {
+        item = PyList_GetItem(l, i);
+
+        status = ldns_rr_new_frm_str(&rr, PyString_AsString(item), default_ttl, 0, 0);
+        if (status != LDNS_STATUS_OK) 
+            continue;
+
+        if (!ldns_rr_list_push_rr(rr_list, rr)) 
+            continue;
+
+    }
+    return rr_list;
+}
+
+int set_return_msg(struct module_qstate* qstate, 
+                   const char* rr_name, ldns_rr_type rr_type, ldns_rr_class rr_class , uint16_t flags, uint32_t default_ttl,
+                   PyObject* question, PyObject* answer, PyObject* authority, PyObject* additional) 
+{
+     ldns_pkt* pkt = 0;
+     ldns_status status;
+     ldns_rr_list* rr_list1 = 0,*rr_list2 = 0,*rr_list3 = 0,*rr_list4 = 0;
+        ldns_buffer *qb = 0;
+     struct dns_msg* m = 0;
+        struct msg_parse* p = 0;
+     int res = 1;
+     
+     if ((!checkList(question)) || (!checkList(answer)) || (!checkList(authority)) || (!checkList(additional)))
+        return 0;
+
+     status = ldns_pkt_query_new_frm_str(&pkt, rr_name, rr_type, rr_class, flags);
+     if ((status != LDNS_STATUS_OK) || (pkt == 0))
+        return 0;
+
+     rr_list1 = createRRList(question, default_ttl);
+     if ((rr_list1) && (res)) res = ldns_pkt_push_rr_list(pkt, LDNS_SECTION_QUESTION, rr_list1);
+     rr_list2 = createRRList(answer, default_ttl);
+     if ((rr_list2) && (res)) res = ldns_pkt_push_rr_list(pkt, LDNS_SECTION_ANSWER, rr_list2);
+     rr_list3 = createRRList(authority, default_ttl);
+     if ((rr_list3) && (res)) res = ldns_pkt_push_rr_list(pkt, LDNS_SECTION_AUTHORITY, rr_list3);
+     rr_list4 = createRRList(additional, default_ttl);
+     if ((rr_list4) && (res)) res = ldns_pkt_push_rr_list(pkt, LDNS_SECTION_ADDITIONAL, rr_list4);
+
+     if ((res) && ((qb = ldns_buffer_new(LDNS_MIN_BUFLEN)) == 0)) res = 0;
+     if ((res) && (ldns_pkt2buffer_wire(qb, pkt) != LDNS_STATUS_OK)) res = 0;
+
+     if (res) res = createResponse(qstate, qb);
+
+     if (qb) ldns_buffer_free(qb);
+
+     ldns_pkt_free(pkt); //this function dealocates pkt as well as rr_lists
+     return res;
+}
+%}
+
+%constant uint16_t PKT_QR = 1;      /* QueRy - query flag */
+%constant uint16_t PKT_AA = 2;      /* Authoritative Answer - server flag */
+%constant uint16_t PKT_TC = 4;      /* TrunCated - server flag */
+%constant uint16_t PKT_RD = 8;      /* Recursion Desired - query flag */
+%constant uint16_t PKT_CD = 16;     /* Checking Disabled - query flag */
+%constant uint16_t PKT_RA = 32;     /* Recursion Available - server flag */
+%constant uint16_t PKT_AD = 64;     /* Authenticated Data - server flag */
+
+int set_return_msg(struct module_qstate* qstate, 
+                   const char* rr_name, int rr_type, int rr_class , uint16_t flags, uint32_t default_ttl,
+                   PyObject* question, PyObject* answer, PyObject* authority, PyObject* additional);
+
+%pythoncode %{
+    class DNSMessage:
+        def __init__(self, rr_name, rr_type, rr_class = RR_CLASS_IN, query_flags = 0, default_ttl = 0):
+            """Query flags is a combination of PKT_xx contants"""
+            self.rr_name = rr_name
+            self.rr_type = rr_type
+            self.rr_class = rr_class
+            self.default_ttl = default_ttl
+            self.query_flags = query_flags
+            self.question = []
+            self.answer = []
+            self.authority = []
+            self.additional = []
+
+        def set_return_msg(self, qstate):
+            """Returns 1 if OK"""
+            status = _Unbound.set_return_msg(qstate, self.rr_name, self.rr_type, self.rr_class, 
+                                           self.query_flags, self.default_ttl,
+                                           self.question, self.answer, self.authority, self.additional)
+
+            if (status) and (PKT_AA & self.query_flags):
+                qstate.return_msg.rep.authoritative = 1
+
+            return status 
+
+%}
+/* ************************************************************************************ * 
+   Functions
+ * ************************************************************************************ */
+
+// Various debuging functions
+void verbose(enum verbosity_value level, const char* format, ...);
+void log_info(const char* format, ...);
+void log_err(const char* format, ...);
+void log_warn(const char* format, ...);
+void log_hex(const char* msg, void* data, size_t length);
+void log_dns_msg(const char* str, struct query_info* qinfo, struct reply_info* rep);
+void log_query_info(enum verbosity_value v, const char* str, struct query_info* qinf);
+void regional_log_stats(struct regional *r);
+
+// LDNS functions
+char *ldns_rr_type2str(const uint16_t atype);
+char *ldns_rr_class2str(const uint16_t aclass);
+
+// Functions from pythonmod_utils
+int storeQueryInCache(struct module_qstate* qstate, struct query_info* qinfo, struct reply_info* msgrep, int is_referral);
+void invalidateQueryInCache(struct module_qstate* qstate, struct query_info* qinfo);
+
+// Module conversion functions
+const char* strextstate(enum module_ext_state s);
+const char* strmodulevent(enum module_ev e);
diff --git a/pythonmod/pythonmod.c b/pythonmod/pythonmod.c
new file mode 100644 (file)
index 0000000..10068ae
--- /dev/null
@@ -0,0 +1,292 @@
+/*
+ * pythonmod.c: unbound module C wrapper
+ * 
+ * Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+ *                     Marek Vavrusa  (xvavru00 AT stud.fit.vutbr.cz)
+ *
+ * This software is open source.
+ * 
+ * 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 the organization 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 COPYRIGHT HOLDERS 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.
+ */
+#include "config.h"
+#include "pythonmod/pythonmod.h"
+#include "util/module.h"
+#include "util/config_file.h"
+#include "pythonmod_utils.h"
+#include <Python.h>
+
+// Generated
+#include "pythonmod/interface.h"
+
+int pythonmod_init(struct module_env* env, int id)
+{
+   // Initialize module
+   struct pythonmod_env* pe = (struct pythonmod_env*)calloc(1, sizeof(struct pythonmod_env));
+   if (!pe) 
+   {
+      log_err("pythonmod: malloc failure");
+      return 0;
+   }
+
+   env->modinfo[id] = (void*) pe;
+   pe->fname = NULL;
+   pe->module = NULL;
+   pe->dict = NULL;
+   pe->data = NULL;
+   pe->qstate = NULL;
+
+   // Initialize module
+   if ((pe->fname = env->cfg->python_script) == NULL) 
+   {
+      log_err("pythonmod: no script given.");
+      return 0;
+   }
+
+   // Initialize Python libraries
+   if (!Py_IsInitialized()) 
+   {
+      Py_SetProgramName("unbound");
+      Py_NoSiteFlag = 1;
+      Py_Initialize();
+      PyEval_InitThreads();
+      PyEval_ReleaseLock();
+      SWIG_init();
+   }
+
+   // Initialize Python
+   PyRun_SimpleString("import sys \n");
+   PyRun_SimpleString("sys.path.append('.') \n");
+   PyRun_SimpleString("sys.path.append('"RUN_DIR"') \n");
+   if (PyRun_SimpleString("from Unbound import *\n") < 0)
+   {
+      log_err("pythonmod: cannot initialize core module: Unbound.py"); 
+      return 0;
+   }
+
+   // Check Python file load
+   FILE* script_py = NULL;
+   if ((script_py = fopen(pe->fname, "r")) == NULL) 
+   {
+      log_err("pythonmod: can't open file %s for reading", pe->fname);
+      return 0;
+   }
+
+   // Load file
+   pe->module = PyImport_AddModule("__main__");
+   pe->dict = PyModule_GetDict(pe->module);
+   pe->data = Py_None;
+   Py_INCREF(pe->data);
+   PyModule_AddObject(pe->module, "mod_env", pe->data);
+
+   //TODO: deallocation of pe->... if an error occurs
+  
+   if (PyRun_SimpleFile(script_py, pe->fname) < 0) 
+   {
+      log_err("pythonmod: can't parse Python script %s", pe->fname);
+      return 0;
+   }
+
+   fclose(script_py);
+
+   if ((pe->func_init = PyDict_GetItemString(pe->dict, "init")) == NULL) 
+   {
+      log_err("pythonmod: function init is missing in %s", pe->fname);
+      return 0;
+   }
+   if ((pe->func_deinit = PyDict_GetItemString(pe->dict, "deinit")) == NULL) 
+   {
+      log_err("pythonmod: function deinit is missing in %s", pe->fname);
+      return 0;
+   }
+   if ((pe->func_operate = PyDict_GetItemString(pe->dict, "operate")) == NULL) 
+   {
+      log_err("pythonmod: function operate is missing in %s", pe->fname);
+      return 0;
+   }
+   if ((pe->func_inform = PyDict_GetItemString(pe->dict, "inform_super")) == NULL) 
+   {
+      log_err("pythonmod: function inform_super is missing in %s", pe->fname);
+      return 0;
+   }
+
+   PyEval_AcquireLock();
+   PyObject* py_cfg = SWIG_NewPointerObj((void*) env->cfg, SWIGTYPE_p_config_file, 0);
+   PyObject* res = PyObject_CallFunction(pe->func_init, "iO", id, py_cfg);
+   if (PyErr_Occurred()) 
+   {
+      log_err("pythonmod: Exception occurred in function init");
+      PyErr_Print();
+   }
+
+   Py_XDECREF(res);
+   Py_XDECREF(py_cfg);
+   PyEval_ReleaseLock();
+
+   return 1;
+}
+
+void pythonmod_deinit(struct module_env* env, int id)
+{
+   struct pythonmod_env* pe = env->modinfo[id];
+   if(pe == NULL)
+      return;
+
+   // Free Python resources
+   if(pe->module != NULL)
+   {
+      // Deinit module
+      PyEval_AcquireLock();
+      PyObject* res = PyObject_CallFunction(pe->func_deinit, "i", id);
+      if (PyErr_Occurred()) {
+         log_err("pythonmod: Exception occurred in function deinit");
+         PyErr_Print();
+      }
+      // Free result if any
+      Py_XDECREF(res);
+      // Free shared data if any
+      Py_XDECREF(pe->data);
+
+      Py_Finalize();
+   }
+
+   // Module is deallocated in Python
+   env->modinfo[id] = NULL;
+}
+
+void pythonmod_inform_super(struct module_qstate* qstate, int id, struct module_qstate* super)
+{
+   struct pythonmod_env* pe = (struct pythonmod_env*)qstate->env->modinfo[id];
+   struct pythonmod_qstate* pq = (struct pythonmod_qstate*)qstate->minfo[id];
+
+   log_query_info(VERB_ALGO, "pythonmod: inform_super, sub is", &qstate->qinfo);
+   log_query_info(VERB_ALGO, "super is", &super->qinfo);
+
+   PyObject* py_qstate = SWIG_NewPointerObj((void*) qstate, SWIGTYPE_p_module_qstate, 0);
+   PyObject* py_sqstate = SWIG_NewPointerObj((void*) super, SWIGTYPE_p_module_qstate, 0);
+
+   PyEval_AcquireLock();
+   PyObject* res = PyObject_CallFunction(pe->func_inform, "iOOO", id, py_qstate, py_sqstate, pq->data);
+
+   if (PyErr_Occurred()) 
+   {
+      log_err("pythonmod: Exception occurred in function inform_super");
+      PyErr_Print();
+      qstate->ext_state[id] = module_error;
+   } 
+   else if ((res == NULL)  || (!PyObject_IsTrue(res))) 
+   {
+      log_err("pythonmod: python returned bad code in inform_super");
+      qstate->ext_state[id] = module_error;
+   } 
+
+   Py_XDECREF(res);
+   Py_XDECREF(py_sqstate);
+   Py_XDECREF(py_qstate);
+
+   PyEval_ReleaseLock();
+}
+
+void pythonmod_operate(struct module_qstate* qstate, enum module_ev event, int id, struct outbound_entry* outbound)
+{
+   struct pythonmod_env* pe = (struct pythonmod_env*)qstate->env->modinfo[id];
+   struct pythonmod_qstate* pq = (struct pythonmod_qstate*)qstate->minfo[id];
+
+   if ( pq == NULL)
+   { 
+      // create qstate
+      pq = qstate->minfo[id] = malloc(sizeof(struct pythonmod_qstate));
+      
+      //Initialize per query data
+      pq->data = Py_None;
+      Py_INCREF(pq->data);
+   }
+
+   // Lock Python
+   PyEval_AcquireLock();
+
+   // Call operate
+   PyObject* py_qstate = SWIG_NewPointerObj((void*) qstate, SWIGTYPE_p_module_qstate, 0);
+   PyObject* res = PyObject_CallFunction(pe->func_operate, "iiOO", id, (int) event, py_qstate, pq->data);
+   if (PyErr_Occurred()) 
+   {
+      log_err("pythonmod: Exception occurred in function operate, event: %s", strmodulevent(event));
+      PyErr_Print();
+      qstate->ext_state[id] = module_error;
+   } 
+   else if ((res == NULL)  || (!PyObject_IsTrue(res))) 
+   {
+      log_err("pythonmod: python returned bad code, event: %s", strmodulevent(event));
+      qstate->ext_state[id] = module_error;
+   } 
+   Py_XDECREF(res);
+   Py_XDECREF(py_qstate);
+
+   // Unlock Python
+   PyEval_ReleaseLock();
+
+}
+
+void pythonmod_clear(struct module_qstate* qstate, int id)
+{
+   if (qstate == NULL)
+      return;
+
+   struct pythonmod_qstate* pq = qstate->minfo[id];
+   log_info("pythonmod: clear, id: %d, pq:%lX", id, (unsigned long int)pq);
+   if(pq != NULL)
+   {
+      Py_DECREF(pq->data);
+      // Free qstate
+      free(pq);
+   }
+
+   qstate->minfo[id] = NULL;
+}
+
+size_t pythonmod_get_mem(struct module_env* env, int id)
+{
+   struct pythonmod_env* pe = (struct pythonmod_env*)env->modinfo[id];
+   log_info("pythonmod: get_mem, id: %d, pe:%lX", id, (unsigned long int)pe);
+   if(!pe)
+      return 0;
+   return sizeof(*pe);
+}
+
+/**
+* The module function block 
+*/
+static struct module_func_block pythonmod_block = {
+   "python",
+   &pythonmod_init, &pythonmod_deinit, &pythonmod_operate, &pythonmod_inform_super, 
+   &pythonmod_clear, &pythonmod_get_mem
+};
+
+struct module_func_block* pythonmod_get_funcblock()
+{
+   return &pythonmod_block;
+}
diff --git a/pythonmod/pythonmod.h b/pythonmod/pythonmod.h
new file mode 100644 (file)
index 0000000..a394e59
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * pythonmod.h: module header file
+ * 
+ * Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+ *                     Marek Vavrusa  (xvavru00 AT stud.fit.vutbr.cz)
+ *
+ * This software is open source.
+ * 
+ * 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 the organization 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 COPYRIGHT HOLDERS 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.
+ */
+#ifndef PYTHONMOD_H
+#define PYTHONMOD_H
+#include "util/module.h"
+#include "services/outbound_list.h"
+#include <Python.h>
+
+struct PyObject;
+
+/**
+ * Global state for the module. 
+ */
+struct pythonmod_env {
+
+   /** Python script filename. */
+   const char* fname;
+
+   /** Python module. */
+   PyObject* module;
+
+   /** Module functions */
+   PyObject* func_init;
+   PyObject* func_deinit;
+   PyObject* func_operate;
+   PyObject* func_inform;
+
+   /** Python dictionary. */
+   PyObject* dict;
+
+   /** Module data. */
+   PyObject* data;
+
+   /** Module qstate. */
+   struct module_qstate* qstate;
+};
+
+/**
+ * Per query state for the iterator module.
+ */
+struct pythonmod_qstate {
+
+   /** Module per query data. */
+   PyObject* data;
+};
+
+/**
+ * Get the module function block.
+ * @return: function block with function pointers to module methods.
+ */
+struct module_func_block* pythonmod_get_funcblock();
+
+/** python module init */
+int pythonmod_init(struct module_env* env, int id);
+
+/** python module deinit */
+void pythonmod_deinit(struct module_env* env, int id);
+
+/** python module operate on a query */
+void pythonmod_operate(struct module_qstate* qstate, enum module_ev event, int id, struct outbound_entry* outbound);
+
+/** python module  */
+void pythonmod_inform_super(struct module_qstate* qstate, int id, struct module_qstate* super);
+
+/** python module cleanup query state */
+void pythonmod_clear(struct module_qstate* qstate, int id);
+
+/** python module alloc size routine */
+size_t pythonmod_get_mem(struct module_env* env, int id);
+#endif /* PYTHONMOD_H */
diff --git a/pythonmod/pythonmod_utils.c b/pythonmod/pythonmod_utils.c
new file mode 100644 (file)
index 0000000..6ad6fde
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * pythonmod_utils.c: utilities used by wrapper
+ *
+ * Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+ *                     Marek Vavrusa  (xvavru00 AT stud.fit.vutbr.cz)
+ *
+ * This software is open source.
+ * 
+ * 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 the organization 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 COPYRIGHT HOLDERS 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.
+ */
+#include "util/module.h"
+#include "util/net_help.h"
+#include "services/cache/dns.h"
+#include "util/data/msgparse.h"
+#include "util/data/msgreply.h"
+#include <Python.h>
+
+/** Store the reply_info and query_info pair in message cache (qstate->msg_cache) */
+int storeQueryInCache(struct module_qstate* qstate, struct query_info* qinfo, struct reply_info* msgrep, int is_referral)
+{
+    if (!msgrep) 
+       return 0;
+
+    if (msgrep->authoritative)  //authoritative answer can't be stored in cache
+    {
+       PyErr_SetString(PyExc_ValueError, "Authoritative answer can't be stored");
+       return 0;
+    }
+
+    return dns_cache_store(qstate->env, qinfo, msgrep, is_referral);
+}
+
+/**  Invalidate the message associated with query_info stored in message cache */
+void invalidateQueryInCache(struct module_qstate* qstate, struct query_info* qinfo)
+{ 
+    hashvalue_t h;
+    struct lruhash_entry* e;
+    struct reply_info *r;
+    size_t i, j;
+
+    h = query_info_hash(qinfo);
+    if ((e=slabhash_lookup(qstate->env->msg_cache, h, qinfo, 0))) 
+    {
+        r = (struct reply_info*)(e->data);
+        if (r) 
+        {
+           r->ttl = 0;
+           for(i=0; i< r->rrset_count; i++) 
+           {
+               struct packed_rrset_data* data = (struct packed_rrset_data*) r->ref[i].key->entry.data;
+               if(i>0 && r->ref[i].key == r->ref[i-1].key)
+                   continue;
+      
+               data->ttl = r->ttl;
+               for(j=0; j<data->count + data->rrsig_count; j++)
+                   data->rr_ttl[j] = r->ttl;
+           }
+        }
+        lock_rw_unlock(&e->lock);
+    } else {
+        log_info("invalidateQueryInCache: qinfo is not in cache");
+    }
+}
+
+/** Create response according to the ldns packet content */
+int createResponse(struct module_qstate* qstate, ldns_buffer* pkt)
+{
+    struct msg_parse* prs;
+    struct edns_data edns;
+    
+    /* parse message */
+    prs = (struct msg_parse*) regional_alloc(qstate->env->scratch, sizeof(struct msg_parse));
+    if (!prs) {
+        log_err("storeResponse: out of memory on incoming message");
+        return 0;
+    }
+
+    memset(prs, 0, sizeof(*prs));
+    memset(&edns, 0, sizeof(edns));
+
+    ldns_buffer_set_position(pkt, 0);
+    if (parse_packet(pkt, prs, qstate->env->scratch) != LDNS_RCODE_NOERROR) {
+        verbose(VERB_ALGO, "storeResponse: parse error on reply packet");
+        return 0;
+    }
+    /* edns is not examined, but removed from message to help cache */
+    if(parse_extract_edns(prs, &edns) != LDNS_RCODE_NOERROR)
+        return 0;
+
+    /* remove CD-bit, we asked for in case we handle validation ourself */
+    prs->flags &= ~BIT_CD;
+
+    /* allocate response dns_msg in region */
+    qstate->return_msg = (struct dns_msg*)regional_alloc(qstate->region, sizeof(struct dns_msg));
+    if (!qstate->return_msg)
+       return 0;
+
+    memset(qstate->return_msg, 0, sizeof(*qstate->return_msg));
+    if(!parse_create_msg(pkt, prs, NULL, &(qstate->return_msg)->qinfo, &(qstate->return_msg)->rep, qstate->region)) {
+        log_err("storeResponse: malloc failure: allocating incoming dns_msg");
+        return 0;
+    }
+    
+    /* Make sure that the RA flag is set (since the presence of 
+     * this module means that recursion is available) */
+    //qstate->return_msg->rep->flags |= BIT_RA;
+
+    /* Clear the AA flag */
+    /* FIXME: does this action go here or in some other module? */
+    //qstate->return_msg->rep->flags &= ~BIT_AA;
+
+    /* make sure QR flag is on */
+    //qstate->return_msg->rep->flags |= BIT_QR;
+
+    if(verbosity >= VERB_ALGO)
+        log_dns_msg("storeResponse: packet:", &qstate->return_msg->qinfo, qstate->return_msg->rep);
+
+    return 1;
+}
diff --git a/pythonmod/pythonmod_utils.h b/pythonmod/pythonmod_utils.h
new file mode 100644 (file)
index 0000000..b2042ab
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * pythonmod_utils.h: utils header file
+ * 
+ * Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+ *                     Marek Vavrusa  (xvavru00 AT stud.fit.vutbr.cz)
+ *
+ * This software is open source.
+ * 
+ * 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 the organization 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 COPYRIGHT HOLDERS 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.
+ */
+#ifndef PYTHONMOD_UTILS_H
+#define PYTHONMOD_UTILS_H
+
+#include "util/module.h"
+
+/**
+ *  Store the reply_info and query_info pair in message cache (qstate->msg_cache)
+ *
+ * @param qstate: module environment
+ * @param qinfo: query info, the query for which answer is stored.
+ * @param msgrep: reply in dns_msg
+ * @param is_referral: If true, then the given message to be stored is a
+ *      referral. The cache implementation may use this as a hint.
+ *      It will store only the RRsets, not the message.
+ * @return 0 on alloc error (out of memory).
+ */
+int storeQueryInCache(struct module_qstate* qstate, struct query_info* qinfo, struct reply_info* msgrep, int is_referral);
+
+
+/**
+ *  Invalidate the message associated with query_info stored in message cache.
+ *
+ *  This function invalidates the record in message cache associated with the given query only if such a record exists.
+ *
+ * @param qstate: module environment
+ * @param qinfo: query info, the query for which answer is stored.
+ */
+void invalidateQueryInCache(struct module_qstate* qstate, struct query_info* qinfo);
+
+/**
+ *  Create response according to the ldns packet content
+ *
+ *  This function fills qstate.return_msg up with data of a given packet
+ * 
+ * @param qstate: module environment
+ * @param pkt: a ldns_buffer which contains ldns_packet data
+ */
+int createResponse(struct module_qstate* qstate, ldns_buffer* pkt);
+
+#endif /* PYTHONMOD_UTILS_H */
diff --git a/pythonmod/test-calc.conf b/pythonmod/test-calc.conf
new file mode 100644 (file)
index 0000000..47a9d2c
--- /dev/null
@@ -0,0 +1,438 @@
+#
+# Example configuration file.
+#
+# See unbound.conf(5) man page.
+#
+# this is a comment.
+
+#Use this to include other text into the file.
+#include: "otherfile.conf"
+
+# The server clause sets the main parameters. 
+server:
+       # whitespace is not necessary, but looks cleaner.
+
+       # verbosity number, 0 is least verbose. 1 is default.
+       verbosity: 1
+
+       # print statistics to the log (for every thread) every N seconds.
+       # Set to "" or 0 to disable. Default is disabled.
+       # statistics-interval: 0
+       
+       # enable cumulative statistics, without clearing them after printing.
+       # statistics-cumulative: no
+
+       # enable extended statistics (query types, answer codes, status)
+       # printed from unbound-control. default off, because of speed.
+       # extended-statistics: no
+
+       # number of threads to create. 1 disables threading.
+       # num-threads: 1
+
+       # specify the interfaces to answer queries from by ip-address.
+       # The default is to listen to localhost (127.0.0.1 and ::1).
+       # specify 0.0.0.0 and ::0 to bind to all available interfaces.
+       # specify every interface on a new 'interface:' labelled line.
+       # The listen interfaces are not changed on reload, only on restart.
+       interface: 0.0.0.0
+       # interface: 192.0.2.154
+       # interface: 2001:DB8::5
+       
+       # enable this feature to copy the source address of queries to reply.
+       # Socket options are not supported on all platforms. experimental. 
+       # interface-automatic: no
+
+       # port to answer queries from
+       # port: 53
+
+       # specify the interfaces to send outgoing queries to authoritative
+       # server from by ip-address. If none, the default (all) interface
+       # is used. Specify every interface on a 'outgoing-interface:' line.
+       # outgoing-interface: 192.0.2.153
+       # outgoing-interface: 2001:DB8::5
+       # outgoing-interface: 2001:DB8::6
+
+       # number of ports to allocate per thread, determines the size of the
+       # port range that can be open simultaneously. 
+       # outgoing-range: 256
+       
+       # permit unbound to use this port number or port range for
+       # making outgoing queries, using an outgoing interface.
+       # outgoing-port-permit: 32768
+
+       # deny unbound the use this of port number or port range for
+       # making outgoing queries, using an outgoing interface.
+       # Use this to make sure unbound does not grab a UDP port that some
+       # other server on this computer needs. The default is to avoid
+       # IANA-assigned port numbers.
+       # outgoing-port-avoid: "3200-3208"
+
+       # number of outgoing simultaneous tcp buffers to hold per thread.
+       # outgoing-num-tcp: 10
+
+       # number of incoming simultaneous tcp buffers to hold per thread.
+       # incoming-num-tcp: 10
+       
+       # buffer size for handling DNS data. No messages larger than this
+       # size can be sent or received, by UDP or TCP. In bytes.
+       # msg-buffer-size: 65552
+
+       # the amount of memory to use for the message cache.
+       # plain value in bytes or you can append k, m or G. default is "4Mb". 
+       # msg-cache-size: 4m
+
+       # the number of slabs to use for the message cache.
+       # the number of slabs must be a power of 2.
+       # more slabs reduce lock contention, but fragment memory usage.
+       # msg-cache-slabs: 4
+
+       # the number of queries that a thread gets to service.
+       # num-queries-per-thread: 1024
+
+       # if very busy, 50% queries run to completion, 50% get timeout in msec
+       # jostle-timeout: 200
+
+       # the amount of memory to use for the RRset cache.
+       # plain value in bytes or you can append k, m or G. default is "4Mb". 
+       # rrset-cache-size: 4m
+
+       # the number of slabs to use for the RRset cache.
+       # the number of slabs must be a power of 2.
+       # more slabs reduce lock contention, but fragment memory usage.
+       # rrset-cache-slabs: 4
+       
+       # the time to live (TTL) value cap for RRsets and messages in the
+       # cache. Items are not cached for longer. In seconds.
+       # cache-max-ttl: 86400
+
+       # the time to live (TTL) value for cached roundtrip times and
+       # EDNS version information for hosts. In seconds.
+       # infra-host-ttl: 900
+
+       # the time to live (TTL) value for cached lame delegations. In sec.
+       # infra-lame-ttl: 900
+
+       # the number of slabs to use for the Infrastructure cache.
+       # the number of slabs must be a power of 2.
+       # more slabs reduce lock contention, but fragment memory usage.
+       # infra-cache-slabs: 4
+
+       # the maximum number of hosts that are cached (roundtrip times, EDNS).
+       # infra-cache-numhosts: 10000
+
+       # the maximum size of the lame zones cached per host. in bytes.
+       # infra-cache-lame-size: 10k
+
+       # Enable IPv4, "yes" or "no".
+       # do-ip4: yes
+
+       # Enable IPv6, "yes" or "no".
+       # do-ip6: yes
+
+       # Enable UDP, "yes" or "no".
+       # do-udp: yes
+
+       # Enable TCP, "yes" or "no".
+       # do-tcp: yes
+
+       # Detach from the terminal, run in background, "yes" or "no".
+       do-daemonize: no
+
+       # control which clients are allowed to make (recursive) queries
+       # to this server. Specify classless netblocks with /size and action.
+       # By default everything is refused, except for localhost.
+       # Choose deny (drop message), refuse (polite error reply),
+       # allow (recursive ok), allow_snoop (recursive and nonrecursive ok)
+       access-control: 0.0.0.0/0 allow
+       # access-control: 127.0.0.0/8 allow
+       # access-control: ::0/0 refuse
+       # access-control: ::1 allow
+       # access-control: ::ffff:127.0.0.1 allow
+
+       # if given, a chroot(2) is done to the given directory.
+       # i.e. you can chroot to the working directory, for example,
+       # for extra security, but make sure all files are in that directory.
+       #
+       # If chroot is enabled, you should pass the configfile (from the
+       # commandline) as a full path from the original root. After the
+       # chroot has been performed the now defunct portion of the config 
+       # file path is removed to be able to reread the config after a reload. 
+       #
+       # All other file paths (working dir, logfile, roothints, and
+       # key files) can be specified in several ways:
+       #       o as an absolute path relative to the new root.
+       #       o as a relative path to the working directory.
+       #       o as an absolute path relative to the original root.
+       # In the last case the path is adjusted to remove the unused portion.
+       #
+       # The pid file can be absolute and outside of the chroot, it is 
+       # written just prior to performing the chroot and dropping permissions.
+       #
+       # Additionally, unbound may need to access /dev/random (for entropy).
+       # How to do this is specific to your OS.
+       #
+       # If you give "" no chroot is performed. The path must not end in a /.
+   chroot: ""
+
+       # if given, user privileges are dropped (after binding port),
+       # and the given username is assumed. Default is user "unbound".
+       # If you give "" no privileges are dropped.
+       username: ""
+
+       # the working directory. The relative files in this config are 
+       # relative to this directory. If you give "" the working directory
+       # is not changed.
+       directory: ""
+
+       # the log file, "" means log to stderr. 
+       # Use of this option sets use-syslog to "no".
+       logfile: ""
+       
+       # Log to syslog(3) if yes. The log facility LOG_DAEMON is used to 
+       # log to, with identity "unbound". If yes, it overrides the logfile.
+       # use-syslog: yes 
+
+       # the pid file. Can be an absolute path outside of chroot/work dir.
+       pidfile: "unbound.pid"
+       
+       # file to read root hints from.
+       # get one from ftp://FTP.INTERNIC.NET/domain/named.cache
+       # root-hints: ""
+       
+       # enable to not answer id.server and hostname.bind queries.
+       # hide-identity: no
+       
+       # enable to not answer version.server and version.bind queries.
+       # hide-version: no
+       
+       # the identity to report. Leave "" or default to return hostname.
+       # identity: ""
+       
+       # the version to report. Leave "" or default to return package version.
+       # version: ""
+       
+       # the target fetch policy.
+       # series of integers describing the policy per dependency depth. 
+       # The number of values in the list determines the maximum dependency 
+       # depth the recursor will pursue before giving up. Each integer means:
+       #       -1 : fetch all targets opportunistically,
+       #       0: fetch on demand,
+       #       positive value: fetch that many targets opportunistically.
+       # Enclose the list of numbers between quotes ("").
+       # target-fetch-policy: "3 2 1 0 0"
+       
+       # Harden against very small EDNS buffer sizes. 
+       # harden-short-bufsize: no
+       
+       # Harden against unseemly large queries.
+       # harden-large-queries: no
+       
+       # Harden against out of zone rrsets, to avoid spoofing attempts. 
+       # harden-glue: yes
+       
+       # Harden against receiving dnssec-stripped data. If you turn it
+       # off, failing to validate dnskey data for a trustanchor will 
+       # trigger insecure mode for that zone (like without a trustanchor).
+       # Default on, which insists on dnssec data for trust-anchored zones.
+       # harden-dnssec-stripped: yes
+
+   # Harden the referral path by performing additional queries for
+       # infrastructure data.  Validates the replies (if possible).
+       # Default off, because the lookups burden the server.  Experimental 
+       # implementation of draft-wijngaards-dnsext-resolver-side-mitigation.
+       # harden-referral-path: no
+
+       # Use 0x20-encoded random bits in the query to foil spoof attempts.
+       # This feature is an experimental implementation of draft dns-0x20.
+       # use-caps-for-id: no
+       
+       # Enforce privacy of these addresses. Strips them away from answers. 
+       # It may cause DNSSEC validation to additionally mark it as bogus. 
+       # Protects against 'DNS Rebinding' (uses browser as network proxy). 
+       # Only 'private-domain' and 'local-data' names are allowed to have 
+       # these private addresses. No default.
+       # private-address: 10.0.0.0/8
+       # private-address: 172.16.0.0/12
+       # private-address: 192.168.0.0/16
+       # private-address: 192.254.0.0/16
+       # private-address: fd00::/8
+       # private-address: fe80::/10
+
+       # Allow the domain (and its subdomains) to contain private addresses.
+       # local-data statements are allowed to contain private addresses too.
+       # private-domain: "example.com"
+       
+       # If nonzero, unwanted replies are not only reported in statistics,
+       # but also a running total is kept per thread. If it reaches the
+       # threshold, a warning is printed and a defensive action is taken,
+       # the cache is cleared to flush potential poison out of it.
+       # A suggested value is 10000000, the default is 0 (turned off).
+       # unwanted-reply-threshold: 0
+
+       # Do not query the following addresses. No DNS queries are sent there.
+       # List one address per entry. List classless netblocks with /size,
+       # do-not-query-address: 127.0.0.1/8
+       # do-not-query-address: ::1
+       
+       # if yes, the above default do-not-query-address entries are present.
+       # if no, localhost can be queried (for testing and debugging).
+       # do-not-query-localhost: yes
+       
+       # module configuration of the server. A string with identifiers
+       # separated by spaces. "iterator" or "validator iterator"
+   module-config: "validator python iterator"
+       
+       # File with DLV trusted keys. Same format as trust-anchor-file.
+       # There can be only one DLV configured, it is trusted from root down.
+       # Download https://secure.isc.org/ops/dlv/dlv.isc.org.key
+       # dlv-anchor-file: "dlv.isc.org.key"
+
+       # File with trusted keys for validation. Specify more than one file
+       # with several entries, one file per entry.
+       # Zone file format, with DS and DNSKEY entries.
+       # trust-anchor-file: ""
+       
+       # Trusted key for validation. DS or DNSKEY. specify the RR on a
+       # single line, surrounded by "". TTL is ignored. class is IN default.
+       # (These examples are from August 2007 and may not be valid anymore).
+       # trust-anchor: "nlnetlabs.nl. DNSKEY 257 3 5 AQPzzTWMz8qSWIQlfRnPckx2BiVmkVN6LPupO3mbz7FhLSnm26n6iG9N Lby97Ji453aWZY3M5/xJBSOS2vWtco2t8C0+xeO1bc/d6ZTy32DHchpW 6rDH1vp86Ll+ha0tmwyy9QP7y2bVw5zSbFCrefk8qCUBgfHm9bHzMG1U BYtEIQ=="
+       # trust-anchor: "jelte.nlnetlabs.nl. DS 42860 5 1 14D739EB566D2B1A5E216A0BA4D17FA9B038BE4A"
+
+       # File with trusted keys for validation. Specify more than one file
+       # with several entries, one file per entry. Like trust-anchor-file
+       # but has a different file format. Format is BIND-9 style format, 
+       # the trusted-keys { name flag proto algo "key"; }; clauses are read.
+       # trusted-keys-file: ""
+       
+       # Override the date for validation with a specific fixed date.
+       # Do not set this unless you are debugging signature inception
+       # and expiration. "" or "0" turns the feature off. 
+       # val-override-date: ""
+       
+       # The time to live for bogus data, rrsets and messages. This avoids
+       # some of the revalidation, until the time interval expires. in secs.
+       # val-bogus-ttl: 60
+       
+       # Should additional section of secure message also be kept clean of
+       # unsecure data. Useful to shield the users of this validator from
+       # potential bogus data in the additional section. All unsigned data 
+       # in the additional section is removed from secure messages.
+       # val-clean-additional: yes
+       
+       # Turn permissive mode on to permit bogus messages. Thus, messages
+       # for which security checks failed will be returned to clients,
+       # instead of SERVFAIL. It still performs the security checks, which
+       # result in interesting log files and possibly the AD bit in
+       # replies if the message is found secure. The default is off.
+       # val-permissive-mode: no
+       
+       # It is possible to configure NSEC3 maximum iteration counts per
+       # keysize. Keep this table very short, as linear search is done.
+       # A message with an NSEC3 with larger count is marked insecure.
+       # List in ascending order the keysize and count values.
+       # val-nsec3-keysize-iterations: "1024 150 2048 500 4096 2500"
+
+       # the amount of memory to use for the key cache.
+       # plain value in bytes or you can append k, m or G. default is "4Mb". 
+       # key-cache-size: 4m
+
+       # the number of slabs to use for the key cache.
+       # the number of slabs must be a power of 2.
+       # more slabs reduce lock contention, but fragment memory usage.
+       # key-cache-slabs: 4
+       
+       # the amount of memory to use for the negative cache (used for DLV).
+       # plain value in bytes or you can append k, m or G. default is "1Mb". 
+       # neg-cache-size: 1m
+
+       # a number of locally served zones can be configured.
+       #       local-zone: <zone> <type>
+       #       local-data: "<resource record string>"
+       # o deny serves local data (if any), else, drops queries. 
+       # o refuse serves local data (if any), else, replies with error.
+       # o static serves local data, else, nxdomain or nodata answer.
+       # o transparent serves local data, else, resolves normally .
+       # o redirect serves the zone data for any subdomain in the zone.
+       # o nodefault can be used to normally resolve AS112 zones.
+       #
+       # defaults are localhost address, reverse for 127.0.0.1 and ::1
+       # and nxdomain for AS112 zones. If you configure one of these zones
+       # the default content is omitted, or you can omit it with 'nodefault'.
+       # 
+       # If you configure local-data without specifying local-zone, by
+       # default a transparent local-zone is created for the data.
+       #
+       # You can add locally served data with
+       # local-zone: "local." static
+       # local-data: "mycomputer.local. IN A 192.0.2.51"
+       # local-data: 'mytext.local TXT "content of text record"'
+       #
+       # You can override certain queries with
+       # local-data: "adserver.example.com A 127.0.0.1"
+       #
+       # You can redirect a domain to a fixed address with
+       # (this makes example.com, www.example.com, etc, all go to 192.0.2.3)
+       # local-zone: "example.com" redirect
+       # local-data: "example.com A 192.0.2.3"
+       #
+       # Shorthand to make PTR records, "IPv4 name" or "IPv6 name".
+       # You can also add PTR records using local-data directly, but then
+       # you need to do the reverse notation yourself.
+       # local-data-ptr: "192.0.2.3 www.example.com"
+
+# Python config section
+python:
+   # Script file to load
+   python-script: "./examples/calc.py"
+
+# Remote control config section. 
+remote-control:
+       # Enable remote control with unbound-control(8) here.
+       # set up the keys and certificates with unbound-control-setup.
+       # control-enable: no
+
+       # what interfaces are listened to for remote control.
+       # give 0.0.0.0 and ::0 to listen to all interfaces.
+       # control-interface: 127.0.0.1
+       # control-interface: ::1
+
+       # port number for remote control operations.
+       # control-port: 953
+
+       # unbound server key file.
+       # server-key-file: "/usr/local/etc/unbound/unbound_server.key"
+
+       # unbound server certificate file.
+       # server-cert-file: "/usr/local/etc/unbound/unbound_server.pem"
+
+       # unbound-control key file.
+       # control-key-file: "/usr/local/etc/unbound/unbound_control.key"
+
+       # unbound-control certificate file.
+       # control-cert-file: "/usr/local/etc/unbound/unbound_control.pem"
+
+# Stub zones.
+# Create entries like below, to make all queries for 'example.com' and 
+# 'example.org' go to the given list of nameservers. list zero or more 
+# nameservers by hostname or by ipaddress. If you set stub-prime to yes, 
+# the list is treated as priming hints (default is no).
+# stub-zone:
+#      name: "example.com"
+#      stub-addr: 192.0.2.68
+#      stub-prime: "no"
+# stub-zone:
+#      name: "example.org"
+#      stub-host: ns.example.com.
+
+# Forward zones
+# Create entries like below, to make all queries for 'example.com' and
+# 'example.org' go to the given list of servers. These servers have to handle
+# recursion to other nameservers. List zero or more nameservers by hostname
+# or by ipaddress. Use an entry with name "." to forward all queries.
+# forward-zone:
+#      name: "example.com"
+#      forward-addr: 192.0.2.68
+#      forward-addr: 192.0.2.73@5355  # forward to port 5355.
+# forward-zone:
+#      name: "example.org"
+#      forward-host: fwd.example.com
diff --git a/pythonmod/test-dict.conf b/pythonmod/test-dict.conf
new file mode 100644 (file)
index 0000000..8f03283
--- /dev/null
@@ -0,0 +1,438 @@
+#
+# Example configuration file.
+#
+# See unbound.conf(5) man page.
+#
+# this is a comment.
+
+#Use this to include other text into the file.
+#include: "otherfile.conf"
+
+# The server clause sets the main parameters. 
+server:
+       # whitespace is not necessary, but looks cleaner.
+
+       # verbosity number, 0 is least verbose. 1 is default.
+       verbosity: 1
+
+       # print statistics to the log (for every thread) every N seconds.
+       # Set to "" or 0 to disable. Default is disabled.
+       # statistics-interval: 0
+       
+       # enable cumulative statistics, without clearing them after printing.
+       # statistics-cumulative: no
+
+       # enable extended statistics (query types, answer codes, status)
+       # printed from unbound-control. default off, because of speed.
+       # extended-statistics: no
+
+       # number of threads to create. 1 disables threading.
+       # num-threads: 1
+
+       # specify the interfaces to answer queries from by ip-address.
+       # The default is to listen to localhost (127.0.0.1 and ::1).
+       # specify 0.0.0.0 and ::0 to bind to all available interfaces.
+       # specify every interface on a new 'interface:' labelled line.
+       # The listen interfaces are not changed on reload, only on restart.
+       interface: 0.0.0.0
+       # interface: 192.0.2.154
+       # interface: 2001:DB8::5
+       
+       # enable this feature to copy the source address of queries to reply.
+       # Socket options are not supported on all platforms. experimental. 
+       # interface-automatic: no
+
+       # port to answer queries from
+       # port: 53
+
+       # specify the interfaces to send outgoing queries to authoritative
+       # server from by ip-address. If none, the default (all) interface
+       # is used. Specify every interface on a 'outgoing-interface:' line.
+       # outgoing-interface: 192.0.2.153
+       # outgoing-interface: 2001:DB8::5
+       # outgoing-interface: 2001:DB8::6
+
+       # number of ports to allocate per thread, determines the size of the
+       # port range that can be open simultaneously. 
+       # outgoing-range: 256
+       
+       # permit unbound to use this port number or port range for
+       # making outgoing queries, using an outgoing interface.
+       # outgoing-port-permit: 32768
+
+       # deny unbound the use this of port number or port range for
+       # making outgoing queries, using an outgoing interface.
+       # Use this to make sure unbound does not grab a UDP port that some
+       # other server on this computer needs. The default is to avoid
+       # IANA-assigned port numbers.
+       # outgoing-port-avoid: "3200-3208"
+
+       # number of outgoing simultaneous tcp buffers to hold per thread.
+       # outgoing-num-tcp: 10
+
+       # number of incoming simultaneous tcp buffers to hold per thread.
+       # incoming-num-tcp: 10
+       
+       # buffer size for handling DNS data. No messages larger than this
+       # size can be sent or received, by UDP or TCP. In bytes.
+       # msg-buffer-size: 65552
+
+       # the amount of memory to use for the message cache.
+       # plain value in bytes or you can append k, m or G. default is "4Mb". 
+       # msg-cache-size: 4m
+
+       # the number of slabs to use for the message cache.
+       # the number of slabs must be a power of 2.
+       # more slabs reduce lock contention, but fragment memory usage.
+       # msg-cache-slabs: 4
+
+       # the number of queries that a thread gets to service.
+       # num-queries-per-thread: 1024
+
+       # if very busy, 50% queries run to completion, 50% get timeout in msec
+       # jostle-timeout: 200
+
+       # the amount of memory to use for the RRset cache.
+       # plain value in bytes or you can append k, m or G. default is "4Mb". 
+       # rrset-cache-size: 4m
+
+       # the number of slabs to use for the RRset cache.
+       # the number of slabs must be a power of 2.
+       # more slabs reduce lock contention, but fragment memory usage.
+       # rrset-cache-slabs: 4
+       
+       # the time to live (TTL) value cap for RRsets and messages in the
+       # cache. Items are not cached for longer. In seconds.
+       # cache-max-ttl: 86400
+
+       # the time to live (TTL) value for cached roundtrip times and
+       # EDNS version information for hosts. In seconds.
+       # infra-host-ttl: 900
+
+       # the time to live (TTL) value for cached lame delegations. In sec.
+       # infra-lame-ttl: 900
+
+       # the number of slabs to use for the Infrastructure cache.
+       # the number of slabs must be a power of 2.
+       # more slabs reduce lock contention, but fragment memory usage.
+       # infra-cache-slabs: 4
+
+       # the maximum number of hosts that are cached (roundtrip times, EDNS).
+       # infra-cache-numhosts: 10000
+
+       # the maximum size of the lame zones cached per host. in bytes.
+       # infra-cache-lame-size: 10k
+
+       # Enable IPv4, "yes" or "no".
+       # do-ip4: yes
+
+       # Enable IPv6, "yes" or "no".
+       # do-ip6: yes
+
+       # Enable UDP, "yes" or "no".
+       # do-udp: yes
+
+       # Enable TCP, "yes" or "no".
+       # do-tcp: yes
+
+       # Detach from the terminal, run in background, "yes" or "no".
+       do-daemonize: no
+
+       # control which clients are allowed to make (recursive) queries
+       # to this server. Specify classless netblocks with /size and action.
+       # By default everything is refused, except for localhost.
+       # Choose deny (drop message), refuse (polite error reply),
+       # allow (recursive ok), allow_snoop (recursive and nonrecursive ok)
+       access-control: 0.0.0.0/0 allow
+       # access-control: 127.0.0.0/8 allow
+       # access-control: ::0/0 refuse
+       # access-control: ::1 allow
+       # access-control: ::ffff:127.0.0.1 allow
+
+       # if given, a chroot(2) is done to the given directory.
+       # i.e. you can chroot to the working directory, for example,
+       # for extra security, but make sure all files are in that directory.
+       #
+       # If chroot is enabled, you should pass the configfile (from the
+       # commandline) as a full path from the original root. After the
+       # chroot has been performed the now defunct portion of the config 
+       # file path is removed to be able to reread the config after a reload. 
+       #
+       # All other file paths (working dir, logfile, roothints, and
+       # key files) can be specified in several ways:
+       #       o as an absolute path relative to the new root.
+       #       o as a relative path to the working directory.
+       #       o as an absolute path relative to the original root.
+       # In the last case the path is adjusted to remove the unused portion.
+       #
+       # The pid file can be absolute and outside of the chroot, it is 
+       # written just prior to performing the chroot and dropping permissions.
+       #
+       # Additionally, unbound may need to access /dev/random (for entropy).
+       # How to do this is specific to your OS.
+       #
+       # If you give "" no chroot is performed. The path must not end in a /.
+   chroot: ""
+
+       # if given, user privileges are dropped (after binding port),
+       # and the given username is assumed. Default is user "unbound".
+       # If you give "" no privileges are dropped.
+       username: ""
+
+       # the working directory. The relative files in this config are 
+       # relative to this directory. If you give "" the working directory
+       # is not changed.
+       directory: ""
+
+       # the log file, "" means log to stderr. 
+       # Use of this option sets use-syslog to "no".
+       logfile: ""
+       
+       # Log to syslog(3) if yes. The log facility LOG_DAEMON is used to 
+       # log to, with identity "unbound". If yes, it overrides the logfile.
+       # use-syslog: yes 
+
+       # the pid file. Can be an absolute path outside of chroot/work dir.
+       pidfile: "unbound.pid"
+       
+       # file to read root hints from.
+       # get one from ftp://FTP.INTERNIC.NET/domain/named.cache
+       # root-hints: ""
+       
+       # enable to not answer id.server and hostname.bind queries.
+       # hide-identity: no
+       
+       # enable to not answer version.server and version.bind queries.
+       # hide-version: no
+       
+       # the identity to report. Leave "" or default to return hostname.
+       # identity: ""
+       
+       # the version to report. Leave "" or default to return package version.
+       # version: ""
+       
+       # the target fetch policy.
+       # series of integers describing the policy per dependency depth. 
+       # The number of values in the list determines the maximum dependency 
+       # depth the recursor will pursue before giving up. Each integer means:
+       #       -1 : fetch all targets opportunistically,
+       #       0: fetch on demand,
+       #       positive value: fetch that many targets opportunistically.
+       # Enclose the list of numbers between quotes ("").
+       # target-fetch-policy: "3 2 1 0 0"
+       
+       # Harden against very small EDNS buffer sizes. 
+       # harden-short-bufsize: no
+       
+       # Harden against unseemly large queries.
+       # harden-large-queries: no
+       
+       # Harden against out of zone rrsets, to avoid spoofing attempts. 
+       # harden-glue: yes
+       
+       # Harden against receiving dnssec-stripped data. If you turn it
+       # off, failing to validate dnskey data for a trustanchor will 
+       # trigger insecure mode for that zone (like without a trustanchor).
+       # Default on, which insists on dnssec data for trust-anchored zones.
+       # harden-dnssec-stripped: yes
+
+   # Harden the referral path by performing additional queries for
+       # infrastructure data.  Validates the replies (if possible).
+       # Default off, because the lookups burden the server.  Experimental 
+       # implementation of draft-wijngaards-dnsext-resolver-side-mitigation.
+       # harden-referral-path: no
+
+       # Use 0x20-encoded random bits in the query to foil spoof attempts.
+       # This feature is an experimental implementation of draft dns-0x20.
+       # use-caps-for-id: no
+       
+       # Enforce privacy of these addresses. Strips them away from answers. 
+       # It may cause DNSSEC validation to additionally mark it as bogus. 
+       # Protects against 'DNS Rebinding' (uses browser as network proxy). 
+       # Only 'private-domain' and 'local-data' names are allowed to have 
+       # these private addresses. No default.
+       # private-address: 10.0.0.0/8
+       # private-address: 172.16.0.0/12
+       # private-address: 192.168.0.0/16
+       # private-address: 192.254.0.0/16
+       # private-address: fd00::/8
+       # private-address: fe80::/10
+
+       # Allow the domain (and its subdomains) to contain private addresses.
+       # local-data statements are allowed to contain private addresses too.
+       # private-domain: "example.com"
+       
+       # If nonzero, unwanted replies are not only reported in statistics,
+       # but also a running total is kept per thread. If it reaches the
+       # threshold, a warning is printed and a defensive action is taken,
+       # the cache is cleared to flush potential poison out of it.
+       # A suggested value is 10000000, the default is 0 (turned off).
+       # unwanted-reply-threshold: 0
+
+       # Do not query the following addresses. No DNS queries are sent there.
+       # List one address per entry. List classless netblocks with /size,
+       # do-not-query-address: 127.0.0.1/8
+       # do-not-query-address: ::1
+       
+       # if yes, the above default do-not-query-address entries are present.
+       # if no, localhost can be queried (for testing and debugging).
+       # do-not-query-localhost: yes
+       
+       # module configuration of the server. A string with identifiers
+       # separated by spaces. "iterator" or "validator iterator"
+   module-config: "validator python iterator"
+       
+       # File with DLV trusted keys. Same format as trust-anchor-file.
+       # There can be only one DLV configured, it is trusted from root down.
+       # Download https://secure.isc.org/ops/dlv/dlv.isc.org.key
+       # dlv-anchor-file: "dlv.isc.org.key"
+
+       # File with trusted keys for validation. Specify more than one file
+       # with several entries, one file per entry.
+       # Zone file format, with DS and DNSKEY entries.
+       # trust-anchor-file: ""
+       
+       # Trusted key for validation. DS or DNSKEY. specify the RR on a
+       # single line, surrounded by "". TTL is ignored. class is IN default.
+       # (These examples are from August 2007 and may not be valid anymore).
+       # trust-anchor: "nlnetlabs.nl. DNSKEY 257 3 5 AQPzzTWMz8qSWIQlfRnPckx2BiVmkVN6LPupO3mbz7FhLSnm26n6iG9N Lby97Ji453aWZY3M5/xJBSOS2vWtco2t8C0+xeO1bc/d6ZTy32DHchpW 6rDH1vp86Ll+ha0tmwyy9QP7y2bVw5zSbFCrefk8qCUBgfHm9bHzMG1U BYtEIQ=="
+       # trust-anchor: "jelte.nlnetlabs.nl. DS 42860 5 1 14D739EB566D2B1A5E216A0BA4D17FA9B038BE4A"
+
+       # File with trusted keys for validation. Specify more than one file
+       # with several entries, one file per entry. Like trust-anchor-file
+       # but has a different file format. Format is BIND-9 style format, 
+       # the trusted-keys { name flag proto algo "key"; }; clauses are read.
+       # trusted-keys-file: ""
+       
+       # Override the date for validation with a specific fixed date.
+       # Do not set this unless you are debugging signature inception
+       # and expiration. "" or "0" turns the feature off. 
+       # val-override-date: ""
+       
+       # The time to live for bogus data, rrsets and messages. This avoids
+       # some of the revalidation, until the time interval expires. in secs.
+       # val-bogus-ttl: 60
+       
+       # Should additional section of secure message also be kept clean of
+       # unsecure data. Useful to shield the users of this validator from
+       # potential bogus data in the additional section. All unsigned data 
+       # in the additional section is removed from secure messages.
+       # val-clean-additional: yes
+       
+       # Turn permissive mode on to permit bogus messages. Thus, messages
+       # for which security checks failed will be returned to clients,
+       # instead of SERVFAIL. It still performs the security checks, which
+       # result in interesting log files and possibly the AD bit in
+       # replies if the message is found secure. The default is off.
+       # val-permissive-mode: no
+       
+       # It is possible to configure NSEC3 maximum iteration counts per
+       # keysize. Keep this table very short, as linear search is done.
+       # A message with an NSEC3 with larger count is marked insecure.
+       # List in ascending order the keysize and count values.
+       # val-nsec3-keysize-iterations: "1024 150 2048 500 4096 2500"
+
+       # the amount of memory to use for the key cache.
+       # plain value in bytes or you can append k, m or G. default is "4Mb". 
+       # key-cache-size: 4m
+
+       # the number of slabs to use for the key cache.
+       # the number of slabs must be a power of 2.
+       # more slabs reduce lock contention, but fragment memory usage.
+       # key-cache-slabs: 4
+       
+       # the amount of memory to use for the negative cache (used for DLV).
+       # plain value in bytes or you can append k, m or G. default is "1Mb". 
+       # neg-cache-size: 1m
+
+       # a number of locally served zones can be configured.
+       #       local-zone: <zone> <type>
+       #       local-data: "<resource record string>"
+       # o deny serves local data (if any), else, drops queries. 
+       # o refuse serves local data (if any), else, replies with error.
+       # o static serves local data, else, nxdomain or nodata answer.
+       # o transparent serves local data, else, resolves normally .
+       # o redirect serves the zone data for any subdomain in the zone.
+       # o nodefault can be used to normally resolve AS112 zones.
+       #
+       # defaults are localhost address, reverse for 127.0.0.1 and ::1
+       # and nxdomain for AS112 zones. If you configure one of these zones
+       # the default content is omitted, or you can omit it with 'nodefault'.
+       # 
+       # If you configure local-data without specifying local-zone, by
+       # default a transparent local-zone is created for the data.
+       #
+       # You can add locally served data with
+       # local-zone: "local." static
+       # local-data: "mycomputer.local. IN A 192.0.2.51"
+       # local-data: 'mytext.local TXT "content of text record"'
+       #
+       # You can override certain queries with
+       # local-data: "adserver.example.com A 127.0.0.1"
+       #
+       # You can redirect a domain to a fixed address with
+       # (this makes example.com, www.example.com, etc, all go to 192.0.2.3)
+       # local-zone: "example.com" redirect
+       # local-data: "example.com A 192.0.2.3"
+       #
+       # Shorthand to make PTR records, "IPv4 name" or "IPv6 name".
+       # You can also add PTR records using local-data directly, but then
+       # you need to do the reverse notation yourself.
+       # local-data-ptr: "192.0.2.3 www.example.com"
+
+# Python config section
+python:
+   # Script file to load
+   python-script: "./examples/dict.py"
+
+# Remote control config section. 
+remote-control:
+       # Enable remote control with unbound-control(8) here.
+       # set up the keys and certificates with unbound-control-setup.
+       # control-enable: no
+
+       # what interfaces are listened to for remote control.
+       # give 0.0.0.0 and ::0 to listen to all interfaces.
+       # control-interface: 127.0.0.1
+       # control-interface: ::1
+
+       # port number for remote control operations.
+       # control-port: 953
+
+       # unbound server key file.
+       # server-key-file: "/usr/local/etc/unbound/unbound_server.key"
+
+       # unbound server certificate file.
+       # server-cert-file: "/usr/local/etc/unbound/unbound_server.pem"
+
+       # unbound-control key file.
+       # control-key-file: "/usr/local/etc/unbound/unbound_control.key"
+
+       # unbound-control certificate file.
+       # control-cert-file: "/usr/local/etc/unbound/unbound_control.pem"
+
+# Stub zones.
+# Create entries like below, to make all queries for 'example.com' and 
+# 'example.org' go to the given list of nameservers. list zero or more 
+# nameservers by hostname or by ipaddress. If you set stub-prime to yes, 
+# the list is treated as priming hints (default is no).
+# stub-zone:
+#      name: "example.com"
+#      stub-addr: 192.0.2.68
+#      stub-prime: "no"
+# stub-zone:
+#      name: "example.org"
+#      stub-host: ns.example.com.
+
+# Forward zones
+# Create entries like below, to make all queries for 'example.com' and
+# 'example.org' go to the given list of servers. These servers have to handle
+# recursion to other nameservers. List zero or more nameservers by hostname
+# or by ipaddress. Use an entry with name "." to forward all queries.
+# forward-zone:
+#      name: "example.com"
+#      forward-addr: 192.0.2.68
+#      forward-addr: 192.0.2.73@5355  # forward to port 5355.
+# forward-zone:
+#      name: "example.org"
+#      forward-host: fwd.example.com
diff --git a/pythonmod/test-log.conf b/pythonmod/test-log.conf
new file mode 100644 (file)
index 0000000..8237e6a
--- /dev/null
@@ -0,0 +1,438 @@
+#
+# Example configuration file.
+#
+# See unbound.conf(5) man page.
+#
+# this is a comment.
+
+#Use this to include other text into the file.
+#include: "otherfile.conf"
+
+# The server clause sets the main parameters. 
+server:
+       # whitespace is not necessary, but looks cleaner.
+
+       # verbosity number, 0 is least verbose. 1 is default.
+       verbosity: 1
+
+       # print statistics to the log (for every thread) every N seconds.
+       # Set to "" or 0 to disable. Default is disabled.
+       # statistics-interval: 0
+       
+       # enable cumulative statistics, without clearing them after printing.
+       # statistics-cumulative: no
+
+       # enable extended statistics (query types, answer codes, status)
+       # printed from unbound-control. default off, because of speed.
+       # extended-statistics: no
+
+       # number of threads to create. 1 disables threading.
+       # num-threads: 1
+
+       # specify the interfaces to answer queries from by ip-address.
+       # The default is to listen to localhost (127.0.0.1 and ::1).
+       # specify 0.0.0.0 and ::0 to bind to all available interfaces.
+       # specify every interface on a new 'interface:' labelled line.
+       # The listen interfaces are not changed on reload, only on restart.
+       interface: 0.0.0.0
+       # interface: 192.0.2.154
+       # interface: 2001:DB8::5
+       
+       # enable this feature to copy the source address of queries to reply.
+       # Socket options are not supported on all platforms. experimental. 
+       # interface-automatic: no
+
+       # port to answer queries from
+       # port: 53
+
+       # specify the interfaces to send outgoing queries to authoritative
+       # server from by ip-address. If none, the default (all) interface
+       # is used. Specify every interface on a 'outgoing-interface:' line.
+       # outgoing-interface: 192.0.2.153
+       # outgoing-interface: 2001:DB8::5
+       # outgoing-interface: 2001:DB8::6
+
+       # number of ports to allocate per thread, determines the size of the
+       # port range that can be open simultaneously. 
+       # outgoing-range: 256
+       
+       # permit unbound to use this port number or port range for
+       # making outgoing queries, using an outgoing interface.
+       # outgoing-port-permit: 32768
+
+       # deny unbound the use this of port number or port range for
+       # making outgoing queries, using an outgoing interface.
+       # Use this to make sure unbound does not grab a UDP port that some
+       # other server on this computer needs. The default is to avoid
+       # IANA-assigned port numbers.
+       # outgoing-port-avoid: "3200-3208"
+
+       # number of outgoing simultaneous tcp buffers to hold per thread.
+       # outgoing-num-tcp: 10
+
+       # number of incoming simultaneous tcp buffers to hold per thread.
+       # incoming-num-tcp: 10
+       
+       # buffer size for handling DNS data. No messages larger than this
+       # size can be sent or received, by UDP or TCP. In bytes.
+       # msg-buffer-size: 65552
+
+       # the amount of memory to use for the message cache.
+       # plain value in bytes or you can append k, m or G. default is "4Mb". 
+       # msg-cache-size: 4m
+
+       # the number of slabs to use for the message cache.
+       # the number of slabs must be a power of 2.
+       # more slabs reduce lock contention, but fragment memory usage.
+       # msg-cache-slabs: 4
+
+       # the number of queries that a thread gets to service.
+       # num-queries-per-thread: 1024
+
+       # if very busy, 50% queries run to completion, 50% get timeout in msec
+       # jostle-timeout: 200
+
+       # the amount of memory to use for the RRset cache.
+       # plain value in bytes or you can append k, m or G. default is "4Mb". 
+       # rrset-cache-size: 4m
+
+       # the number of slabs to use for the RRset cache.
+       # the number of slabs must be a power of 2.
+       # more slabs reduce lock contention, but fragment memory usage.
+       # rrset-cache-slabs: 4
+       
+       # the time to live (TTL) value cap for RRsets and messages in the
+       # cache. Items are not cached for longer. In seconds.
+       # cache-max-ttl: 86400
+
+       # the time to live (TTL) value for cached roundtrip times and
+       # EDNS version information for hosts. In seconds.
+       # infra-host-ttl: 900
+
+       # the time to live (TTL) value for cached lame delegations. In sec.
+       # infra-lame-ttl: 900
+
+       # the number of slabs to use for the Infrastructure cache.
+       # the number of slabs must be a power of 2.
+       # more slabs reduce lock contention, but fragment memory usage.
+       # infra-cache-slabs: 4
+
+       # the maximum number of hosts that are cached (roundtrip times, EDNS).
+       # infra-cache-numhosts: 10000
+
+       # the maximum size of the lame zones cached per host. in bytes.
+       # infra-cache-lame-size: 10k
+
+       # Enable IPv4, "yes" or "no".
+       # do-ip4: yes
+
+       # Enable IPv6, "yes" or "no".
+       # do-ip6: yes
+
+       # Enable UDP, "yes" or "no".
+       # do-udp: yes
+
+       # Enable TCP, "yes" or "no".
+       # do-tcp: yes
+
+       # Detach from the terminal, run in background, "yes" or "no".
+       do-daemonize: no
+
+       # control which clients are allowed to make (recursive) queries
+       # to this server. Specify classless netblocks with /size and action.
+       # By default everything is refused, except for localhost.
+       # Choose deny (drop message), refuse (polite error reply),
+       # allow (recursive ok), allow_snoop (recursive and nonrecursive ok)
+       access-control: 0.0.0.0/0 allow
+       # access-control: 127.0.0.0/8 allow
+       # access-control: ::0/0 refuse
+       # access-control: ::1 allow
+       # access-control: ::ffff:127.0.0.1 allow
+
+       # if given, a chroot(2) is done to the given directory.
+       # i.e. you can chroot to the working directory, for example,
+       # for extra security, but make sure all files are in that directory.
+       #
+       # If chroot is enabled, you should pass the configfile (from the
+       # commandline) as a full path from the original root. After the
+       # chroot has been performed the now defunct portion of the config 
+       # file path is removed to be able to reread the config after a reload. 
+       #
+       # All other file paths (working dir, logfile, roothints, and
+       # key files) can be specified in several ways:
+       #       o as an absolute path relative to the new root.
+       #       o as a relative path to the working directory.
+       #       o as an absolute path relative to the original root.
+       # In the last case the path is adjusted to remove the unused portion.
+       #
+       # The pid file can be absolute and outside of the chroot, it is 
+       # written just prior to performing the chroot and dropping permissions.
+       #
+       # Additionally, unbound may need to access /dev/random (for entropy).
+       # How to do this is specific to your OS.
+       #
+       # If you give "" no chroot is performed. The path must not end in a /.
+   chroot: ""
+
+       # if given, user privileges are dropped (after binding port),
+       # and the given username is assumed. Default is user "unbound".
+       # If you give "" no privileges are dropped.
+       username: ""
+
+       # the working directory. The relative files in this config are 
+       # relative to this directory. If you give "" the working directory
+       # is not changed.
+       directory: ""
+
+       # the log file, "" means log to stderr. 
+       # Use of this option sets use-syslog to "no".
+       logfile: ""
+       
+       # Log to syslog(3) if yes. The log facility LOG_DAEMON is used to 
+       # log to, with identity "unbound". If yes, it overrides the logfile.
+       # use-syslog: yes 
+
+       # the pid file. Can be an absolute path outside of chroot/work dir.
+       pidfile: "unbound.pid"
+       
+       # file to read root hints from.
+       # get one from ftp://FTP.INTERNIC.NET/domain/named.cache
+       # root-hints: ""
+       
+       # enable to not answer id.server and hostname.bind queries.
+       # hide-identity: no
+       
+       # enable to not answer version.server and version.bind queries.
+       # hide-version: no
+       
+       # the identity to report. Leave "" or default to return hostname.
+       # identity: ""
+       
+       # the version to report. Leave "" or default to return package version.
+       # version: ""
+       
+       # the target fetch policy.
+       # series of integers describing the policy per dependency depth. 
+       # The number of values in the list determines the maximum dependency 
+       # depth the recursor will pursue before giving up. Each integer means:
+       #       -1 : fetch all targets opportunistically,
+       #       0: fetch on demand,
+       #       positive value: fetch that many targets opportunistically.
+       # Enclose the list of numbers between quotes ("").
+       # target-fetch-policy: "3 2 1 0 0"
+       
+       # Harden against very small EDNS buffer sizes. 
+       # harden-short-bufsize: no
+       
+       # Harden against unseemly large queries.
+       # harden-large-queries: no
+       
+       # Harden against out of zone rrsets, to avoid spoofing attempts. 
+       # harden-glue: yes
+       
+       # Harden against receiving dnssec-stripped data. If you turn it
+       # off, failing to validate dnskey data for a trustanchor will 
+       # trigger insecure mode for that zone (like without a trustanchor).
+       # Default on, which insists on dnssec data for trust-anchored zones.
+       # harden-dnssec-stripped: yes
+
+   # Harden the referral path by performing additional queries for
+       # infrastructure data.  Validates the replies (if possible).
+       # Default off, because the lookups burden the server.  Experimental 
+       # implementation of draft-wijngaards-dnsext-resolver-side-mitigation.
+       # harden-referral-path: no
+
+       # Use 0x20-encoded random bits in the query to foil spoof attempts.
+       # This feature is an experimental implementation of draft dns-0x20.
+       # use-caps-for-id: no
+       
+       # Enforce privacy of these addresses. Strips them away from answers. 
+       # It may cause DNSSEC validation to additionally mark it as bogus. 
+       # Protects against 'DNS Rebinding' (uses browser as network proxy). 
+       # Only 'private-domain' and 'local-data' names are allowed to have 
+       # these private addresses. No default.
+       # private-address: 10.0.0.0/8
+       # private-address: 172.16.0.0/12
+       # private-address: 192.168.0.0/16
+       # private-address: 192.254.0.0/16
+       # private-address: fd00::/8
+       # private-address: fe80::/10
+
+       # Allow the domain (and its subdomains) to contain private addresses.
+       # local-data statements are allowed to contain private addresses too.
+       # private-domain: "example.com"
+       
+       # If nonzero, unwanted replies are not only reported in statistics,
+       # but also a running total is kept per thread. If it reaches the
+       # threshold, a warning is printed and a defensive action is taken,
+       # the cache is cleared to flush potential poison out of it.
+       # A suggested value is 10000000, the default is 0 (turned off).
+       # unwanted-reply-threshold: 0
+
+       # Do not query the following addresses. No DNS queries are sent there.
+       # List one address per entry. List classless netblocks with /size,
+       # do-not-query-address: 127.0.0.1/8
+       # do-not-query-address: ::1
+       
+       # if yes, the above default do-not-query-address entries are present.
+       # if no, localhost can be queried (for testing and debugging).
+       # do-not-query-localhost: yes
+       
+       # module configuration of the server. A string with identifiers
+       # separated by spaces. "iterator" or "validator iterator"
+   module-config: "validator python iterator"
+       
+       # File with DLV trusted keys. Same format as trust-anchor-file.
+       # There can be only one DLV configured, it is trusted from root down.
+       # Download https://secure.isc.org/ops/dlv/dlv.isc.org.key
+       # dlv-anchor-file: "dlv.isc.org.key"
+
+       # File with trusted keys for validation. Specify more than one file
+       # with several entries, one file per entry.
+       # Zone file format, with DS and DNSKEY entries.
+       # trust-anchor-file: ""
+       
+       # Trusted key for validation. DS or DNSKEY. specify the RR on a
+       # single line, surrounded by "". TTL is ignored. class is IN default.
+       # (These examples are from August 2007 and may not be valid anymore).
+       # trust-anchor: "nlnetlabs.nl. DNSKEY 257 3 5 AQPzzTWMz8qSWIQlfRnPckx2BiVmkVN6LPupO3mbz7FhLSnm26n6iG9N Lby97Ji453aWZY3M5/xJBSOS2vWtco2t8C0+xeO1bc/d6ZTy32DHchpW 6rDH1vp86Ll+ha0tmwyy9QP7y2bVw5zSbFCrefk8qCUBgfHm9bHzMG1U BYtEIQ=="
+       # trust-anchor: "jelte.nlnetlabs.nl. DS 42860 5 1 14D739EB566D2B1A5E216A0BA4D17FA9B038BE4A"
+
+       # File with trusted keys for validation. Specify more than one file
+       # with several entries, one file per entry. Like trust-anchor-file
+       # but has a different file format. Format is BIND-9 style format, 
+       # the trusted-keys { name flag proto algo "key"; }; clauses are read.
+       # trusted-keys-file: ""
+       
+       # Override the date for validation with a specific fixed date.
+       # Do not set this unless you are debugging signature inception
+       # and expiration. "" or "0" turns the feature off. 
+       # val-override-date: ""
+       
+       # The time to live for bogus data, rrsets and messages. This avoids
+       # some of the revalidation, until the time interval expires. in secs.
+       # val-bogus-ttl: 60
+       
+       # Should additional section of secure message also be kept clean of
+       # unsecure data. Useful to shield the users of this validator from
+       # potential bogus data in the additional section. All unsigned data 
+       # in the additional section is removed from secure messages.
+       # val-clean-additional: yes
+       
+       # Turn permissive mode on to permit bogus messages. Thus, messages
+       # for which security checks failed will be returned to clients,
+       # instead of SERVFAIL. It still performs the security checks, which
+       # result in interesting log files and possibly the AD bit in
+       # replies if the message is found secure. The default is off.
+       # val-permissive-mode: no
+       
+       # It is possible to configure NSEC3 maximum iteration counts per
+       # keysize. Keep this table very short, as linear search is done.
+       # A message with an NSEC3 with larger count is marked insecure.
+       # List in ascending order the keysize and count values.
+       # val-nsec3-keysize-iterations: "1024 150 2048 500 4096 2500"
+
+       # the amount of memory to use for the key cache.
+       # plain value in bytes or you can append k, m or G. default is "4Mb". 
+       # key-cache-size: 4m
+
+       # the number of slabs to use for the key cache.
+       # the number of slabs must be a power of 2.
+       # more slabs reduce lock contention, but fragment memory usage.
+       # key-cache-slabs: 4
+       
+       # the amount of memory to use for the negative cache (used for DLV).
+       # plain value in bytes or you can append k, m or G. default is "1Mb". 
+       # neg-cache-size: 1m
+
+       # a number of locally served zones can be configured.
+       #       local-zone: <zone> <type>
+       #       local-data: "<resource record string>"
+       # o deny serves local data (if any), else, drops queries. 
+       # o refuse serves local data (if any), else, replies with error.
+       # o static serves local data, else, nxdomain or nodata answer.
+       # o transparent serves local data, else, resolves normally .
+       # o redirect serves the zone data for any subdomain in the zone.
+       # o nodefault can be used to normally resolve AS112 zones.
+       #
+       # defaults are localhost address, reverse for 127.0.0.1 and ::1
+       # and nxdomain for AS112 zones. If you configure one of these zones
+       # the default content is omitted, or you can omit it with 'nodefault'.
+       # 
+       # If you configure local-data without specifying local-zone, by
+       # default a transparent local-zone is created for the data.
+       #
+       # You can add locally served data with
+       # local-zone: "local." static
+       # local-data: "mycomputer.local. IN A 192.0.2.51"
+       # local-data: 'mytext.local TXT "content of text record"'
+       #
+       # You can override certain queries with
+       # local-data: "adserver.example.com A 127.0.0.1"
+       #
+       # You can redirect a domain to a fixed address with
+       # (this makes example.com, www.example.com, etc, all go to 192.0.2.3)
+       # local-zone: "example.com" redirect
+       # local-data: "example.com A 192.0.2.3"
+       #
+       # Shorthand to make PTR records, "IPv4 name" or "IPv6 name".
+       # You can also add PTR records using local-data directly, but then
+       # you need to do the reverse notation yourself.
+       # local-data-ptr: "192.0.2.3 www.example.com"
+
+# Python config section
+python:
+   # Script file to load
+   python-script: "./examples/log.py"
+
+# Remote control config section. 
+remote-control:
+       # Enable remote control with unbound-control(8) here.
+       # set up the keys and certificates with unbound-control-setup.
+       # control-enable: no
+
+       # what interfaces are listened to for remote control.
+       # give 0.0.0.0 and ::0 to listen to all interfaces.
+       # control-interface: 127.0.0.1
+       # control-interface: ::1
+
+       # port number for remote control operations.
+       # control-port: 953
+
+       # unbound server key file.
+       # server-key-file: "/usr/local/etc/unbound/unbound_server.key"
+
+       # unbound server certificate file.
+       # server-cert-file: "/usr/local/etc/unbound/unbound_server.pem"
+
+       # unbound-control key file.
+       # control-key-file: "/usr/local/etc/unbound/unbound_control.key"
+
+       # unbound-control certificate file.
+       # control-cert-file: "/usr/local/etc/unbound/unbound_control.pem"
+
+# Stub zones.
+# Create entries like below, to make all queries for 'example.com' and 
+# 'example.org' go to the given list of nameservers. list zero or more 
+# nameservers by hostname or by ipaddress. If you set stub-prime to yes, 
+# the list is treated as priming hints (default is no).
+# stub-zone:
+#      name: "example.com"
+#      stub-addr: 192.0.2.68
+#      stub-prime: "no"
+# stub-zone:
+#      name: "example.org"
+#      stub-host: ns.example.com.
+
+# Forward zones
+# Create entries like below, to make all queries for 'example.com' and
+# 'example.org' go to the given list of servers. These servers have to handle
+# recursion to other nameservers. List zero or more nameservers by hostname
+# or by ipaddress. Use an entry with name "." to forward all queries.
+# forward-zone:
+#      name: "example.com"
+#      forward-addr: 192.0.2.68
+#      forward-addr: 192.0.2.73@5355  # forward to port 5355.
+# forward-zone:
+#      name: "example.org"
+#      forward-host: fwd.example.com
diff --git a/pythonmod/test-resgen.conf b/pythonmod/test-resgen.conf
new file mode 100644 (file)
index 0000000..352ade1
--- /dev/null
@@ -0,0 +1,438 @@
+#
+# Example configuration file.
+#
+# See unbound.conf(5) man page.
+#
+# this is a comment.
+
+#Use this to include other text into the file.
+#include: "otherfile.conf"
+
+# The server clause sets the main parameters. 
+server:
+       # whitespace is not necessary, but looks cleaner.
+
+       # verbosity number, 0 is least verbose. 1 is default.
+       verbosity: 1
+
+       # print statistics to the log (for every thread) every N seconds.
+       # Set to "" or 0 to disable. Default is disabled.
+       # statistics-interval: 0
+       
+       # enable cumulative statistics, without clearing them after printing.
+       # statistics-cumulative: no
+
+       # enable extended statistics (query types, answer codes, status)
+       # printed from unbound-control. default off, because of speed.
+       # extended-statistics: no
+
+       # number of threads to create. 1 disables threading.
+       # num-threads: 1
+
+       # specify the interfaces to answer queries from by ip-address.
+       # The default is to listen to localhost (127.0.0.1 and ::1).
+       # specify 0.0.0.0 and ::0 to bind to all available interfaces.
+       # specify every interface on a new 'interface:' labelled line.
+       # The listen interfaces are not changed on reload, only on restart.
+       interface: 0.0.0.0
+       # interface: 192.0.2.154
+       # interface: 2001:DB8::5
+       
+       # enable this feature to copy the source address of queries to reply.
+       # Socket options are not supported on all platforms. experimental. 
+       # interface-automatic: no
+
+       # port to answer queries from
+       # port: 53
+
+       # specify the interfaces to send outgoing queries to authoritative
+       # server from by ip-address. If none, the default (all) interface
+       # is used. Specify every interface on a 'outgoing-interface:' line.
+       # outgoing-interface: 192.0.2.153
+       # outgoing-interface: 2001:DB8::5
+       # outgoing-interface: 2001:DB8::6
+
+       # number of ports to allocate per thread, determines the size of the
+       # port range that can be open simultaneously. 
+       # outgoing-range: 256
+       
+       # permit unbound to use this port number or port range for
+       # making outgoing queries, using an outgoing interface.
+       # outgoing-port-permit: 32768
+
+       # deny unbound the use this of port number or port range for
+       # making outgoing queries, using an outgoing interface.
+       # Use this to make sure unbound does not grab a UDP port that some
+       # other server on this computer needs. The default is to avoid
+       # IANA-assigned port numbers.
+       # outgoing-port-avoid: "3200-3208"
+
+       # number of outgoing simultaneous tcp buffers to hold per thread.
+       # outgoing-num-tcp: 10
+
+       # number of incoming simultaneous tcp buffers to hold per thread.
+       # incoming-num-tcp: 10
+       
+       # buffer size for handling DNS data. No messages larger than this
+       # size can be sent or received, by UDP or TCP. In bytes.
+       # msg-buffer-size: 65552
+
+       # the amount of memory to use for the message cache.
+       # plain value in bytes or you can append k, m or G. default is "4Mb". 
+       # msg-cache-size: 4m
+
+       # the number of slabs to use for the message cache.
+       # the number of slabs must be a power of 2.
+       # more slabs reduce lock contention, but fragment memory usage.
+       # msg-cache-slabs: 4
+
+       # the number of queries that a thread gets to service.
+       # num-queries-per-thread: 1024
+
+       # if very busy, 50% queries run to completion, 50% get timeout in msec
+       # jostle-timeout: 200
+
+       # the amount of memory to use for the RRset cache.
+       # plain value in bytes or you can append k, m or G. default is "4Mb". 
+       # rrset-cache-size: 4m
+
+       # the number of slabs to use for the RRset cache.
+       # the number of slabs must be a power of 2.
+       # more slabs reduce lock contention, but fragment memory usage.
+       # rrset-cache-slabs: 4
+       
+       # the time to live (TTL) value cap for RRsets and messages in the
+       # cache. Items are not cached for longer. In seconds.
+       # cache-max-ttl: 86400
+
+       # the time to live (TTL) value for cached roundtrip times and
+       # EDNS version information for hosts. In seconds.
+       # infra-host-ttl: 900
+
+       # the time to live (TTL) value for cached lame delegations. In sec.
+       # infra-lame-ttl: 900
+
+       # the number of slabs to use for the Infrastructure cache.
+       # the number of slabs must be a power of 2.
+       # more slabs reduce lock contention, but fragment memory usage.
+       # infra-cache-slabs: 4
+
+       # the maximum number of hosts that are cached (roundtrip times, EDNS).
+       # infra-cache-numhosts: 10000
+
+       # the maximum size of the lame zones cached per host. in bytes.
+       # infra-cache-lame-size: 10k
+
+       # Enable IPv4, "yes" or "no".
+       # do-ip4: yes
+
+       # Enable IPv6, "yes" or "no".
+       # do-ip6: yes
+
+       # Enable UDP, "yes" or "no".
+       # do-udp: yes
+
+       # Enable TCP, "yes" or "no".
+       # do-tcp: yes
+
+       # Detach from the terminal, run in background, "yes" or "no".
+       do-daemonize: no
+
+       # control which clients are allowed to make (recursive) queries
+       # to this server. Specify classless netblocks with /size and action.
+       # By default everything is refused, except for localhost.
+       # Choose deny (drop message), refuse (polite error reply),
+       # allow (recursive ok), allow_snoop (recursive and nonrecursive ok)
+       access-control: 0.0.0.0/0 allow
+       # access-control: 127.0.0.0/8 allow
+       # access-control: ::0/0 refuse
+       # access-control: ::1 allow
+       # access-control: ::ffff:127.0.0.1 allow
+
+       # if given, a chroot(2) is done to the given directory.
+       # i.e. you can chroot to the working directory, for example,
+       # for extra security, but make sure all files are in that directory.
+       #
+       # If chroot is enabled, you should pass the configfile (from the
+       # commandline) as a full path from the original root. After the
+       # chroot has been performed the now defunct portion of the config 
+       # file path is removed to be able to reread the config after a reload. 
+       #
+       # All other file paths (working dir, logfile, roothints, and
+       # key files) can be specified in several ways:
+       #       o as an absolute path relative to the new root.
+       #       o as a relative path to the working directory.
+       #       o as an absolute path relative to the original root.
+       # In the last case the path is adjusted to remove the unused portion.
+       #
+       # The pid file can be absolute and outside of the chroot, it is 
+       # written just prior to performing the chroot and dropping permissions.
+       #
+       # Additionally, unbound may need to access /dev/random (for entropy).
+       # How to do this is specific to your OS.
+       #
+       # If you give "" no chroot is performed. The path must not end in a /.
+   chroot: ""
+
+       # if given, user privileges are dropped (after binding port),
+       # and the given username is assumed. Default is user "unbound".
+       # If you give "" no privileges are dropped.
+       username: ""
+
+       # the working directory. The relative files in this config are 
+       # relative to this directory. If you give "" the working directory
+       # is not changed.
+       directory: ""
+
+       # the log file, "" means log to stderr. 
+       # Use of this option sets use-syslog to "no".
+       logfile: ""
+       
+       # Log to syslog(3) if yes. The log facility LOG_DAEMON is used to 
+       # log to, with identity "unbound". If yes, it overrides the logfile.
+       # use-syslog: yes 
+
+       # the pid file. Can be an absolute path outside of chroot/work dir.
+       pidfile: "unbound.pid"
+       
+       # file to read root hints from.
+       # get one from ftp://FTP.INTERNIC.NET/domain/named.cache
+       # root-hints: ""
+       
+       # enable to not answer id.server and hostname.bind queries.
+       # hide-identity: no
+       
+       # enable to not answer version.server and version.bind queries.
+       # hide-version: no
+       
+       # the identity to report. Leave "" or default to return hostname.
+       # identity: ""
+       
+       # the version to report. Leave "" or default to return package version.
+       # version: ""
+       
+       # the target fetch policy.
+       # series of integers describing the policy per dependency depth. 
+       # The number of values in the list determines the maximum dependency 
+       # depth the recursor will pursue before giving up. Each integer means:
+       #       -1 : fetch all targets opportunistically,
+       #       0: fetch on demand,
+       #       positive value: fetch that many targets opportunistically.
+       # Enclose the list of numbers between quotes ("").
+       # target-fetch-policy: "3 2 1 0 0"
+       
+       # Harden against very small EDNS buffer sizes. 
+       # harden-short-bufsize: no
+       
+       # Harden against unseemly large queries.
+       # harden-large-queries: no
+       
+       # Harden against out of zone rrsets, to avoid spoofing attempts. 
+       # harden-glue: yes
+       
+       # Harden against receiving dnssec-stripped data. If you turn it
+       # off, failing to validate dnskey data for a trustanchor will 
+       # trigger insecure mode for that zone (like without a trustanchor).
+       # Default on, which insists on dnssec data for trust-anchored zones.
+       # harden-dnssec-stripped: yes
+
+   # Harden the referral path by performing additional queries for
+       # infrastructure data.  Validates the replies (if possible).
+       # Default off, because the lookups burden the server.  Experimental 
+       # implementation of draft-wijngaards-dnsext-resolver-side-mitigation.
+       # harden-referral-path: no
+
+       # Use 0x20-encoded random bits in the query to foil spoof attempts.
+       # This feature is an experimental implementation of draft dns-0x20.
+       # use-caps-for-id: no
+       
+       # Enforce privacy of these addresses. Strips them away from answers. 
+       # It may cause DNSSEC validation to additionally mark it as bogus. 
+       # Protects against 'DNS Rebinding' (uses browser as network proxy). 
+       # Only 'private-domain' and 'local-data' names are allowed to have 
+       # these private addresses. No default.
+       # private-address: 10.0.0.0/8
+       # private-address: 172.16.0.0/12
+       # private-address: 192.168.0.0/16
+       # private-address: 192.254.0.0/16
+       # private-address: fd00::/8
+       # private-address: fe80::/10
+
+       # Allow the domain (and its subdomains) to contain private addresses.
+       # local-data statements are allowed to contain private addresses too.
+       # private-domain: "example.com"
+       
+       # If nonzero, unwanted replies are not only reported in statistics,
+       # but also a running total is kept per thread. If it reaches the
+       # threshold, a warning is printed and a defensive action is taken,
+       # the cache is cleared to flush potential poison out of it.
+       # A suggested value is 10000000, the default is 0 (turned off).
+       # unwanted-reply-threshold: 0
+
+       # Do not query the following addresses. No DNS queries are sent there.
+       # List one address per entry. List classless netblocks with /size,
+       # do-not-query-address: 127.0.0.1/8
+       # do-not-query-address: ::1
+       
+       # if yes, the above default do-not-query-address entries are present.
+       # if no, localhost can be queried (for testing and debugging).
+       # do-not-query-localhost: yes
+       
+       # module configuration of the server. A string with identifiers
+       # separated by spaces. "iterator" or "validator iterator"
+   module-config: "validator python iterator"
+       
+       # File with DLV trusted keys. Same format as trust-anchor-file.
+       # There can be only one DLV configured, it is trusted from root down.
+       # Download https://secure.isc.org/ops/dlv/dlv.isc.org.key
+       # dlv-anchor-file: "dlv.isc.org.key"
+
+       # File with trusted keys for validation. Specify more than one file
+       # with several entries, one file per entry.
+       # Zone file format, with DS and DNSKEY entries.
+       # trust-anchor-file: ""
+       
+       # Trusted key for validation. DS or DNSKEY. specify the RR on a
+       # single line, surrounded by "". TTL is ignored. class is IN default.
+       # (These examples are from August 2007 and may not be valid anymore).
+       # trust-anchor: "nlnetlabs.nl. DNSKEY 257 3 5 AQPzzTWMz8qSWIQlfRnPckx2BiVmkVN6LPupO3mbz7FhLSnm26n6iG9N Lby97Ji453aWZY3M5/xJBSOS2vWtco2t8C0+xeO1bc/d6ZTy32DHchpW 6rDH1vp86Ll+ha0tmwyy9QP7y2bVw5zSbFCrefk8qCUBgfHm9bHzMG1U BYtEIQ=="
+       # trust-anchor: "jelte.nlnetlabs.nl. DS 42860 5 1 14D739EB566D2B1A5E216A0BA4D17FA9B038BE4A"
+
+       # File with trusted keys for validation. Specify more than one file
+       # with several entries, one file per entry. Like trust-anchor-file
+       # but has a different file format. Format is BIND-9 style format, 
+       # the trusted-keys { name flag proto algo "key"; }; clauses are read.
+       # trusted-keys-file: ""
+       
+       # Override the date for validation with a specific fixed date.
+       # Do not set this unless you are debugging signature inception
+       # and expiration. "" or "0" turns the feature off. 
+       # val-override-date: ""
+       
+       # The time to live for bogus data, rrsets and messages. This avoids
+       # some of the revalidation, until the time interval expires. in secs.
+       # val-bogus-ttl: 60
+       
+       # Should additional section of secure message also be kept clean of
+       # unsecure data. Useful to shield the users of this validator from
+       # potential bogus data in the additional section. All unsigned data 
+       # in the additional section is removed from secure messages.
+       # val-clean-additional: yes
+       
+       # Turn permissive mode on to permit bogus messages. Thus, messages
+       # for which security checks failed will be returned to clients,
+       # instead of SERVFAIL. It still performs the security checks, which
+       # result in interesting log files and possibly the AD bit in
+       # replies if the message is found secure. The default is off.
+       # val-permissive-mode: no
+       
+       # It is possible to configure NSEC3 maximum iteration counts per
+       # keysize. Keep this table very short, as linear search is done.
+       # A message with an NSEC3 with larger count is marked insecure.
+       # List in ascending order the keysize and count values.
+       # val-nsec3-keysize-iterations: "1024 150 2048 500 4096 2500"
+
+       # the amount of memory to use for the key cache.
+       # plain value in bytes or you can append k, m or G. default is "4Mb". 
+       # key-cache-size: 4m
+
+       # the number of slabs to use for the key cache.
+       # the number of slabs must be a power of 2.
+       # more slabs reduce lock contention, but fragment memory usage.
+       # key-cache-slabs: 4
+       
+       # the amount of memory to use for the negative cache (used for DLV).
+       # plain value in bytes or you can append k, m or G. default is "1Mb". 
+       # neg-cache-size: 1m
+
+       # a number of locally served zones can be configured.
+       #       local-zone: <zone> <type>
+       #       local-data: "<resource record string>"
+       # o deny serves local data (if any), else, drops queries. 
+       # o refuse serves local data (if any), else, replies with error.
+       # o static serves local data, else, nxdomain or nodata answer.
+       # o transparent serves local data, else, resolves normally .
+       # o redirect serves the zone data for any subdomain in the zone.
+       # o nodefault can be used to normally resolve AS112 zones.
+       #
+       # defaults are localhost address, reverse for 127.0.0.1 and ::1
+       # and nxdomain for AS112 zones. If you configure one of these zones
+       # the default content is omitted, or you can omit it with 'nodefault'.
+       # 
+       # If you configure local-data without specifying local-zone, by
+       # default a transparent local-zone is created for the data.
+       #
+       # You can add locally served data with
+       # local-zone: "local." static
+       # local-data: "mycomputer.local. IN A 192.0.2.51"
+       # local-data: 'mytext.local TXT "content of text record"'
+       #
+       # You can override certain queries with
+       # local-data: "adserver.example.com A 127.0.0.1"
+       #
+       # You can redirect a domain to a fixed address with
+       # (this makes example.com, www.example.com, etc, all go to 192.0.2.3)
+       # local-zone: "example.com" redirect
+       # local-data: "example.com A 192.0.2.3"
+       #
+       # Shorthand to make PTR records, "IPv4 name" or "IPv6 name".
+       # You can also add PTR records using local-data directly, but then
+       # you need to do the reverse notation yourself.
+       # local-data-ptr: "192.0.2.3 www.example.com"
+
+# Python config section
+python:
+   # Script file to load
+   python-script: "./examples/resgen.py"
+
+# Remote control config section. 
+remote-control:
+       # Enable remote control with unbound-control(8) here.
+       # set up the keys and certificates with unbound-control-setup.
+       # control-enable: no
+
+       # what interfaces are listened to for remote control.
+       # give 0.0.0.0 and ::0 to listen to all interfaces.
+       # control-interface: 127.0.0.1
+       # control-interface: ::1
+
+       # port number for remote control operations.
+       # control-port: 953
+
+       # unbound server key file.
+       # server-key-file: "/usr/local/etc/unbound/unbound_server.key"
+
+       # unbound server certificate file.
+       # server-cert-file: "/usr/local/etc/unbound/unbound_server.pem"
+
+       # unbound-control key file.
+       # control-key-file: "/usr/local/etc/unbound/unbound_control.key"
+
+       # unbound-control certificate file.
+       # control-cert-file: "/usr/local/etc/unbound/unbound_control.pem"
+
+# Stub zones.
+# Create entries like below, to make all queries for 'example.com' and 
+# 'example.org' go to the given list of nameservers. list zero or more 
+# nameservers by hostname or by ipaddress. If you set stub-prime to yes, 
+# the list is treated as priming hints (default is no).
+# stub-zone:
+#      name: "example.com"
+#      stub-addr: 192.0.2.68
+#      stub-prime: "no"
+# stub-zone:
+#      name: "example.org"
+#      stub-host: ns.example.com.
+
+# Forward zones
+# Create entries like below, to make all queries for 'example.com' and
+# 'example.org' go to the given list of servers. These servers have to handle
+# recursion to other nameservers. List zero or more nameservers by hostname
+# or by ipaddress. Use an entry with name "." to forward all queries.
+# forward-zone:
+#      name: "example.com"
+#      forward-addr: 192.0.2.68
+#      forward-addr: 192.0.2.73@5355  # forward to port 5355.
+# forward-zone:
+#      name: "example.org"
+#      forward-host: fwd.example.com
diff --git a/pythonmod/test-resmod.conf b/pythonmod/test-resmod.conf
new file mode 100644 (file)
index 0000000..e716478
--- /dev/null
@@ -0,0 +1,439 @@
+#
+# Example configuration file.
+#
+# See unbound.conf(5) man page.
+#
+# this is a comment.
+
+#Use this to include other text into the file.
+#include: "otherfile.conf"
+
+# The server clause sets the main parameters. 
+server:
+       # whitespace is not necessary, but looks cleaner.
+
+       # verbosity number, 0 is least verbose. 1 is default.
+       verbosity: 1
+
+       # print statistics to the log (for every thread) every N seconds.
+       # Set to "" or 0 to disable. Default is disabled.
+       # statistics-interval: 0
+       
+       # enable cumulative statistics, without clearing them after printing.
+       # statistics-cumulative: no
+
+       # enable extended statistics (query types, answer codes, status)
+       # printed from unbound-control. default off, because of speed.
+       # extended-statistics: no
+
+       # number of threads to create. 1 disables threading.
+       # num-threads: 1
+
+       # specify the interfaces to answer queries from by ip-address.
+       # The default is to listen to localhost (127.0.0.1 and ::1).
+       # specify 0.0.0.0 and ::0 to bind to all available interfaces.
+       # specify every interface on a new 'interface:' labelled line.
+       # The listen interfaces are not changed on reload, only on restart.
+       interface: 0.0.0.0
+       # interface: 192.0.2.154
+       # interface: 2001:DB8::5
+       
+       # enable this feature to copy the source address of queries to reply.
+       # Socket options are not supported on all platforms. experimental. 
+       # interface-automatic: no
+
+       # port to answer queries from
+       # port: 53
+
+       # specify the interfaces to send outgoing queries to authoritative
+       # server from by ip-address. If none, the default (all) interface
+       # is used. Specify every interface on a 'outgoing-interface:' line.
+       # outgoing-interface: 192.0.2.153
+       # outgoing-interface: 2001:DB8::5
+       # outgoing-interface: 2001:DB8::6
+
+       # number of ports to allocate per thread, determines the size of the
+       # port range that can be open simultaneously. 
+       # outgoing-range: 256
+       
+       # permit unbound to use this port number or port range for
+       # making outgoing queries, using an outgoing interface.
+       # outgoing-port-permit: 32768
+
+       # deny unbound the use this of port number or port range for
+       # making outgoing queries, using an outgoing interface.
+       # Use this to make sure unbound does not grab a UDP port that some
+       # other server on this computer needs. The default is to avoid
+       # IANA-assigned port numbers.
+       # outgoing-port-avoid: "3200-3208"
+
+       # number of outgoing simultaneous tcp buffers to hold per thread.
+       # outgoing-num-tcp: 10
+
+       # number of incoming simultaneous tcp buffers to hold per thread.
+       # incoming-num-tcp: 10
+       
+       # buffer size for handling DNS data. No messages larger than this
+       # size can be sent or received, by UDP or TCP. In bytes.
+       # msg-buffer-size: 65552
+
+       # the amount of memory to use for the message cache.
+       # plain value in bytes or you can append k, m or G. default is "4Mb". 
+       # msg-cache-size: 4m
+
+       # the number of slabs to use for the message cache.
+       # the number of slabs must be a power of 2.
+       # more slabs reduce lock contention, but fragment memory usage.
+       # msg-cache-slabs: 4
+
+       # the number of queries that a thread gets to service.
+       # num-queries-per-thread: 1024
+
+       # if very busy, 50% queries run to completion, 50% get timeout in msec
+       # jostle-timeout: 200
+
+       # the amount of memory to use for the RRset cache.
+       # plain value in bytes or you can append k, m or G. default is "4Mb". 
+       # rrset-cache-size: 4m
+
+       # the number of slabs to use for the RRset cache.
+       # the number of slabs must be a power of 2.
+       # more slabs reduce lock contention, but fragment memory usage.
+       # rrset-cache-slabs: 4
+       
+       # the time to live (TTL) value cap for RRsets and messages in the
+       # cache. Items are not cached for longer. In seconds.
+       # cache-max-ttl: 86400
+
+       # the time to live (TTL) value for cached roundtrip times and
+       # EDNS version information for hosts. In seconds.
+       # infra-host-ttl: 900
+
+       # the time to live (TTL) value for cached lame delegations. In sec.
+       # infra-lame-ttl: 900
+
+       # the number of slabs to use for the Infrastructure cache.
+       # the number of slabs must be a power of 2.
+       # more slabs reduce lock contention, but fragment memory usage.
+       # infra-cache-slabs: 4
+
+       # the maximum number of hosts that are cached (roundtrip times, EDNS).
+       # infra-cache-numhosts: 10000
+
+       # the maximum size of the lame zones cached per host. in bytes.
+       # infra-cache-lame-size: 10k
+
+       # Enable IPv4, "yes" or "no".
+       # do-ip4: yes
+
+       # Enable IPv6, "yes" or "no".
+       # do-ip6: yes
+
+       # Enable UDP, "yes" or "no".
+       # do-udp: yes
+
+       # Enable TCP, "yes" or "no".
+       # do-tcp: yes
+
+       # Detach from the terminal, run in background, "yes" or "no".
+       do-daemonize: no
+
+       # control which clients are allowed to make (recursive) queries
+       # to this server. Specify classless netblocks with /size and action.
+       # By default everything is refused, except for localhost.
+       # Choose deny (drop message), refuse (polite error reply),
+       # allow (recursive ok), allow_snoop (recursive and nonrecursive ok)
+       access-control: 0.0.0.0/0 allow
+       # access-control: 127.0.0.0/8 allow
+       # access-control: ::0/0 refuse
+       # access-control: ::1 allow
+       # access-control: ::ffff:127.0.0.1 allow
+
+       # if given, a chroot(2) is done to the given directory.
+       # i.e. you can chroot to the working directory, for example,
+       # for extra security, but make sure all files are in that directory.
+       #
+       # If chroot is enabled, you should pass the configfile (from the
+       # commandline) as a full path from the original root. After the
+       # chroot has been performed the now defunct portion of the config 
+       # file path is removed to be able to reread the config after a reload. 
+       #
+       # All other file paths (working dir, logfile, roothints, and
+       # key files) can be specified in several ways:
+       #       o as an absolute path relative to the new root.
+       #       o as a relative path to the working directory.
+       #       o as an absolute path relative to the original root.
+       # In the last case the path is adjusted to remove the unused portion.
+       #
+       # The pid file can be absolute and outside of the chroot, it is 
+       # written just prior to performing the chroot and dropping permissions.
+       #
+       # Additionally, unbound may need to access /dev/random (for entropy).
+       # How to do this is specific to your OS.
+       #
+       # If you give "" no chroot is performed. The path must not end in a /.
+   chroot: ""
+
+       # if given, user privileges are dropped (after binding port),
+       # and the given username is assumed. Default is user "unbound".
+       # If you give "" no privileges are dropped.
+       username: ""
+
+       # the working directory. The relative files in this config are 
+       # relative to this directory. If you give "" the working directory
+       # is not changed.
+       directory: ""
+
+       # the log file, "" means log to stderr. 
+       # Use of this option sets use-syslog to "no".
+       logfile: ""
+       
+       # Log to syslog(3) if yes. The log facility LOG_DAEMON is used to 
+       # log to, with identity "unbound". If yes, it overrides the logfile.
+       # use-syslog: yes 
+
+       # the pid file. Can be an absolute path outside of chroot/work dir.
+       pidfile: "unbound.pid"
+       
+       # file to read root hints from.
+       # get one from ftp://FTP.INTERNIC.NET/domain/named.cache
+       # root-hints: ""
+       
+       # enable to not answer id.server and hostname.bind queries.
+       # hide-identity: no
+       
+       # enable to not answer version.server and version.bind queries.
+       # hide-version: no
+       
+       # the identity to report. Leave "" or default to return hostname.
+       # identity: ""
+       
+       # the version to report. Leave "" or default to return package version.
+       # version: ""
+       
+       # the target fetch policy.
+       # series of integers describing the policy per dependency depth. 
+       # The number of values in the list determines the maximum dependency 
+       # depth the recursor will pursue before giving up. Each integer means:
+       #       -1 : fetch all targets opportunistically,
+       #       0: fetch on demand,
+       #       positive value: fetch that many targets opportunistically.
+       # Enclose the list of numbers between quotes ("").
+       # target-fetch-policy: "3 2 1 0 0"
+       
+       # Harden against very small EDNS buffer sizes. 
+       # harden-short-bufsize: no
+       
+       # Harden against unseemly large queries.
+       # harden-large-queries: no
+       
+       # Harden against out of zone rrsets, to avoid spoofing attempts. 
+       # harden-glue: yes
+       
+       # Harden against receiving dnssec-stripped data. If you turn it
+       # off, failing to validate dnskey data for a trustanchor will 
+       # trigger insecure mode for that zone (like without a trustanchor).
+       # Default on, which insists on dnssec data for trust-anchored zones.
+       # harden-dnssec-stripped: yes
+
+   # Harden the referral path by performing additional queries for
+       # infrastructure data.  Validates the replies (if possible).
+       # Default off, because the lookups burden the server.  Experimental 
+       # implementation of draft-wijngaards-dnsext-resolver-side-mitigation.
+       # harden-referral-path: no
+
+       # Use 0x20-encoded random bits in the query to foil spoof attempts.
+       # This feature is an experimental implementation of draft dns-0x20.
+       # use-caps-for-id: no
+       
+       # Enforce privacy of these addresses. Strips them away from answers. 
+       # It may cause DNSSEC validation to additionally mark it as bogus. 
+       # Protects against 'DNS Rebinding' (uses browser as network proxy). 
+       # Only 'private-domain' and 'local-data' names are allowed to have 
+       # these private addresses. No default.
+       # private-address: 10.0.0.0/8
+       # private-address: 172.16.0.0/12
+       # private-address: 192.168.0.0/16
+       # private-address: 192.254.0.0/16
+       # private-address: fd00::/8
+       # private-address: fe80::/10
+
+       # Allow the domain (and its subdomains) to contain private addresses.
+       # local-data statements are allowed to contain private addresses too.
+       # private-domain: "example.com"
+       
+       # If nonzero, unwanted replies are not only reported in statistics,
+       # but also a running total is kept per thread. If it reaches the
+       # threshold, a warning is printed and a defensive action is taken,
+       # the cache is cleared to flush potential poison out of it.
+       # A suggested value is 10000000, the default is 0 (turned off).
+       # unwanted-reply-threshold: 0
+
+       # Do not query the following addresses. No DNS queries are sent there.
+       # List one address per entry. List classless netblocks with /size,
+       # do-not-query-address: 127.0.0.1/8
+       # do-not-query-address: ::1
+       
+       # if yes, the above default do-not-query-address entries are present.
+       # if no, localhost can be queried (for testing and debugging).
+       # do-not-query-localhost: yes
+       
+       # module configuration of the server. A string with identifiers
+       # separated by spaces. "iterator" or "validator iterator"
+    #module-config: "python iterator"
+    module-config: "validator python iterator"
+       
+       # File with DLV trusted keys. Same format as trust-anchor-file.
+       # There can be only one DLV configured, it is trusted from root down.
+       # Download https://secure.isc.org/ops/dlv/dlv.isc.org.key
+       # dlv-anchor-file: "dlv.isc.org.key"
+
+       # File with trusted keys for validation. Specify more than one file
+       # with several entries, one file per entry.
+       # Zone file format, with DS and DNSKEY entries.
+       # trust-anchor-file: ""
+       
+       # Trusted key for validation. DS or DNSKEY. specify the RR on a
+       # single line, surrounded by "". TTL is ignored. class is IN default.
+       # (These examples are from August 2007 and may not be valid anymore).
+       # trust-anchor: "nlnetlabs.nl. DNSKEY 257 3 5 AQPzzTWMz8qSWIQlfRnPckx2BiVmkVN6LPupO3mbz7FhLSnm26n6iG9N Lby97Ji453aWZY3M5/xJBSOS2vWtco2t8C0+xeO1bc/d6ZTy32DHchpW 6rDH1vp86Ll+ha0tmwyy9QP7y2bVw5zSbFCrefk8qCUBgfHm9bHzMG1U BYtEIQ=="
+       # trust-anchor: "jelte.nlnetlabs.nl. DS 42860 5 1 14D739EB566D2B1A5E216A0BA4D17FA9B038BE4A"
+
+       # File with trusted keys for validation. Specify more than one file
+       # with several entries, one file per entry. Like trust-anchor-file
+       # but has a different file format. Format is BIND-9 style format, 
+       # the trusted-keys { name flag proto algo "key"; }; clauses are read.
+       # trusted-keys-file: ""
+       
+       # Override the date for validation with a specific fixed date.
+       # Do not set this unless you are debugging signature inception
+       # and expiration. "" or "0" turns the feature off. 
+       # val-override-date: ""
+       
+       # The time to live for bogus data, rrsets and messages. This avoids
+       # some of the revalidation, until the time interval expires. in secs.
+       # val-bogus-ttl: 60
+       
+       # Should additional section of secure message also be kept clean of
+       # unsecure data. Useful to shield the users of this validator from
+       # potential bogus data in the additional section. All unsigned data 
+       # in the additional section is removed from secure messages.
+       # val-clean-additional: yes
+       
+       # Turn permissive mode on to permit bogus messages. Thus, messages
+       # for which security checks failed will be returned to clients,
+       # instead of SERVFAIL. It still performs the security checks, which
+       # result in interesting log files and possibly the AD bit in
+       # replies if the message is found secure. The default is off.
+       # val-permissive-mode: no
+       
+       # It is possible to configure NSEC3 maximum iteration counts per
+       # keysize. Keep this table very short, as linear search is done.
+       # A message with an NSEC3 with larger count is marked insecure.
+       # List in ascending order the keysize and count values.
+       # val-nsec3-keysize-iterations: "1024 150 2048 500 4096 2500"
+
+       # the amount of memory to use for the key cache.
+       # plain value in bytes or you can append k, m or G. default is "4Mb". 
+       # key-cache-size: 4m
+
+       # the number of slabs to use for the key cache.
+       # the number of slabs must be a power of 2.
+       # more slabs reduce lock contention, but fragment memory usage.
+       # key-cache-slabs: 4
+       
+       # the amount of memory to use for the negative cache (used for DLV).
+       # plain value in bytes or you can append k, m or G. default is "1Mb". 
+       # neg-cache-size: 1m
+
+       # a number of locally served zones can be configured.
+       #       local-zone: <zone> <type>
+       #       local-data: "<resource record string>"
+       # o deny serves local data (if any), else, drops queries. 
+       # o refuse serves local data (if any), else, replies with error.
+       # o static serves local data, else, nxdomain or nodata answer.
+       # o transparent serves local data, else, resolves normally .
+       # o redirect serves the zone data for any subdomain in the zone.
+       # o nodefault can be used to normally resolve AS112 zones.
+       #
+       # defaults are localhost address, reverse for 127.0.0.1 and ::1
+       # and nxdomain for AS112 zones. If you configure one of these zones
+       # the default content is omitted, or you can omit it with 'nodefault'.
+       # 
+       # If you configure local-data without specifying local-zone, by
+       # default a transparent local-zone is created for the data.
+       #
+       # You can add locally served data with
+       # local-zone: "local." static
+       # local-data: "mycomputer.local. IN A 192.0.2.51"
+       # local-data: 'mytext.local TXT "content of text record"'
+       #
+       # You can override certain queries with
+       # local-data: "adserver.example.com A 127.0.0.1"
+       #
+       # You can redirect a domain to a fixed address with
+       # (this makes example.com, www.example.com, etc, all go to 192.0.2.3)
+       # local-zone: "example.com" redirect
+       # local-data: "example.com A 192.0.2.3"
+       #
+       # Shorthand to make PTR records, "IPv4 name" or "IPv6 name".
+       # You can also add PTR records using local-data directly, but then
+       # you need to do the reverse notation yourself.
+       # local-data-ptr: "192.0.2.3 www.example.com"
+
+# Python config section
+python:
+   # Script file to load
+   python-script: "./examples/resmod.py"
+
+# Remote control config section. 
+remote-control:
+       # Enable remote control with unbound-control(8) here.
+       # set up the keys and certificates with unbound-control-setup.
+       # control-enable: no
+
+       # what interfaces are listened to for remote control.
+       # give 0.0.0.0 and ::0 to listen to all interfaces.
+       # control-interface: 127.0.0.1
+       # control-interface: ::1
+
+       # port number for remote control operations.
+       # control-port: 953
+
+       # unbound server key file.
+       # server-key-file: "/usr/local/etc/unbound/unbound_server.key"
+
+       # unbound server certificate file.
+       # server-cert-file: "/usr/local/etc/unbound/unbound_server.pem"
+
+       # unbound-control key file.
+       # control-key-file: "/usr/local/etc/unbound/unbound_control.key"
+
+       # unbound-control certificate file.
+       # control-cert-file: "/usr/local/etc/unbound/unbound_control.pem"
+
+# Stub zones.
+# Create entries like below, to make all queries for 'example.com' and 
+# 'example.org' go to the given list of nameservers. list zero or more 
+# nameservers by hostname or by ipaddress. If you set stub-prime to yes, 
+# the list is treated as priming hints (default is no).
+# stub-zone:
+#      name: "example.com"
+#      stub-addr: 192.0.2.68
+#      stub-prime: "no"
+# stub-zone:
+#      name: "example.org"
+#      stub-host: ns.example.com.
+
+# Forward zones
+# Create entries like below, to make all queries for 'example.com' and
+# 'example.org' go to the given list of servers. These servers have to handle
+# recursion to other nameservers. List zero or more nameservers by hostname
+# or by ipaddress. Use an entry with name "." to forward all queries.
+# forward-zone:
+#      name: "example.com"
+#      forward-addr: 192.0.2.68
+#      forward-addr: 192.0.2.73@5355  # forward to port 5355.
+# forward-zone:
+#      name: "example.org"
+#      forward-host: fwd.example.com
diff --git a/pythonmod/ubmodule-msg.py b/pythonmod/ubmodule-msg.py
new file mode 100644 (file)
index 0000000..d234d60
--- /dev/null
@@ -0,0 +1,156 @@
+# -*- coding: utf-8 -*-
+'''
+ ubmodule-msg.py: simple response packet logger
+
+ Authors: Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+          Marek Vavrusa  (xvavru00 AT stud.fit.vutbr.cz)
+
+ Copyright (c) 2008. All rights reserved.
+
+ This software is open source.
+ 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.
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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.
+'''
+import os
+
+def init(id, cfg):
+    log_info("pythonmod: init called, module id is %d port: %d script: %s" % (id, cfg.port, cfg.python_script))
+    return True
+
+def deinit(id):
+    log_info("pythonmod: deinit called, module id is %d" % id)
+    return True
+
+def inform_super(id, qstate, superqstate, qdata):
+    return True
+
+def setTTL(qstate, ttl):
+    """Sets return_msg TTL and all the RRs TTL"""
+    if qstate.return_msg:
+        qstate.return_msg.rep.ttl = ttl
+        if (qstate.return_msg.rep):
+            for i in range(0,qstate.return_msg.rep.rrset_count):
+                d = qstate.return_msg.rep.rrsets[i].entry.data
+                for j in range(0,d.count+d.rrsig_count):
+                    d.rr_ttl[j] = ttl
+
+def dataHex(data, prefix=""):
+    res = ""
+    for i in range(0, (len(data)+15)/16):
+        res += "%s0x%02X | " % (prefix, i*16)
+        d = map(lambda x:ord(x), data[i*16:i*16+17])
+        for ch in d:
+            res += "%02X " % ch
+        for i in range(0,17-len(d)):
+            res += "   "
+        res += "| "
+        for ch in d:
+            if (ch < 32) or (ch > 127):
+                res += ". "
+            else:
+                res += "%c " % ch
+        res += "\n"
+    return res
+
+def printReturnMsg(qstate):
+    print "Return MSG rep   :: flags: %04X, QDcount: %d, Security:%d, TTL=%d" % (qstate.return_msg.rep.flags, qstate.return_msg.rep.qdcount,qstate.return_msg.rep.security, qstate.return_msg.rep.ttl)
+    print "           qinfo :: qname:",qstate.return_msg.qinfo.qname_list, qstate.return_msg.qinfo.qname_str, "type:",qstate.return_msg.qinfo.qtype_str, "class:",qstate.return_msg.qinfo.qclass_str
+    if (qstate.return_msg.rep):
+        print "RRSets:",qstate.return_msg.rep.rrset_count
+        prevkey = None
+        for i in range(0,qstate.return_msg.rep.rrset_count):
+            r = qstate.return_msg.rep.rrsets[i]
+            rk = r.rk
+            print i,":",rk.dname_list, rk.dname_str, "flags: %04X" % rk.flags,
+            print "type:",rk.type_str,"(%d)" % ntohs(rk.type), "class:",rk.rrset_class_str,"(%d)" % ntohs(rk.rrset_class)
+
+            d = r.entry.data
+            print "    RRDatas:",d.count+d.rrsig_count
+            for j in range(0,d.count+d.rrsig_count):
+                print "    ",j,":","TTL=",d.rr_ttl[j],"RR data:"
+                print dataHex(d.rr_data[j],"         ")
+
+
+def operate(id, event, qstate, qdata):
+    log_info("pythonmod: operate called, id: %d, event:%s" % (id, strmodulevent(event)))
+    #print "pythonmod: per query data", qdata
+
+    print "Query:", ''.join(map(lambda x:chr(max(32,ord(x))),qstate.qinfo.qname)), qstate.qinfo.qname_list, qstate.qinfo.qname_str,
+    print "Type:",qstate.qinfo.qtype_str,"(%d)" % qstate.qinfo.qtype,
+    print "Class:",qstate.qinfo.qclass_str,"(%d)" % qstate.qinfo.qclass
+    print
+
+    #if event == MODULE_EVENT_PASS: #pokud mame "validator python iterator"
+    if (event == MODULE_EVENT_NEW) and (qstate.qinfo.qname_str.endswith(".seznam.cz.")): #pokud mame "python validator iterator"
+        print qstate.qinfo.qname_str
+
+        qstate.ext_state[id] = MODULE_FINISHED 
+
+        msg = DNSMessage(qstate.qinfo.qname_str, RR_TYPE_A, RR_CLASS_IN, PKT_QR | PKT_RA | PKT_AA) #, 300)
+        #msg.authority.append("xxx.seznam.cz. 10 IN A 192.168.1.1")
+        #msg.additional.append("yyy.seznam.cz. 10 IN A 1.1.1.2.")
+
+        if qstate.qinfo.qtype == RR_TYPE_A:
+            msg.answer.append("%s 10 IN A 192.168.1.1" % qstate.qinfo.qname_str)
+        if (qstate.qinfo.qtype == RR_TYPE_SRV) or (qstate.qinfo.qtype == RR_TYPE_ANY):
+            msg.answer.append("%s 10 IN SRV 0 0 80 neinfo.example.com." % qstate.qinfo.qname_str)
+        if (qstate.qinfo.qtype == RR_TYPE_TXT) or (qstate.qinfo.qtype == RR_TYPE_ANY):
+            msg.answer.append("%s 10 IN TXT path=/" % qstate.qinfo.qname_str)
+
+        if not msg.set_return_msg(qstate):
+            qstate.ext_state[id] = MODULE_ERROR 
+            return True
+
+        #qstate.return_msg.rep.security = 2 #pokud nebude nasledovat validator, je zapotrebi nastavit security, aby nebyl paket zahozen v mesh_send_reply
+        printReturnMsg(qstate)
+
+        #Authoritative result can't be stored in cache
+        #if (not storeQueryInCache(qstate, qstate.return_msg.qinfo, qstate.return_msg.rep, 0)):
+        #    print "Can't store in cache"
+        #    qstate.ext_state[id] = MODULE_ERROR
+        #    return False
+        #print "Store OK"
+
+        qstate.return_rcode = RCODE_NOERROR
+        return True
+
+    if event == MODULE_EVENT_NEW:
+        qstate.ext_state[id] = MODULE_WAIT_MODULE 
+        return True
+
+    if event == MODULE_EVENT_MODDONE:
+        log_info("pythonmod: previous module done")
+        qstate.ext_state[id] = MODULE_FINISHED 
+        return True
+      
+    if event == MODULE_EVENT_PASS:
+        log_info("pythonmod: event_pass")
+        qstate.ext_state[id] = MODULE_ERROR 
+        return True
+
+    log_err("pythonmod: BAD event")
+    qstate.ext_state[id] = MODULE_ERROR
+    return True
+
+log_info("pythonmod: script loaded.")
diff --git a/pythonmod/ubmodule-tst.py b/pythonmod/ubmodule-tst.py
new file mode 100644 (file)
index 0000000..d0d4cd4
--- /dev/null
@@ -0,0 +1,149 @@
+# -*- coding: utf-8 -*-
+'''
+ ubmodule-tst.py:  
+
+ Authors: Zdenek Vasicek (vasicek AT fit.vutbr.cz)
+          Marek Vavrusa  (xvavru00 AT stud.fit.vutbr.cz)
+
+ Copyright (c) 2008. All rights reserved.
+
+ This software is open source.
+ 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.
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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.
+'''
+def init(id, cfg):
+    log_info("pythonmod: init called, module id is %d port: %d script: %s" % (id, cfg.port, cfg.python_script))
+    return True
+
+def deinit(id):
+    log_info("pythonmod: deinit called, module id is %d" % id)
+    return True
+
+def inform_super(id, qstate, superqstate, qdata):
+    return True
+
+def setTTL(qstate, ttl):
+    """Sets return_msg TTL and all the RRs TTL"""
+    if qstate.return_msg:
+        qstate.return_msg.rep.ttl = ttl
+        if (qstate.return_msg.rep):
+            for i in range(0,qstate.return_msg.rep.rrset_count):
+                d = qstate.return_msg.rep.rrsets[i].entry.data
+                for j in range(0,d.count+d.rrsig_count):
+                    d.rr_ttl[j] = ttl
+
+def dataHex(data, prefix=""):
+    res = ""
+    for i in range(0, (len(data)+15)/16):
+        res += "%s0x%02X | " % (prefix, i*16)
+        d = map(lambda x:ord(x), data[i*16:i*16+17])
+        for ch in d:
+            res += "%02X " % ch
+        for i in range(0,17-len(d)):
+            res += "   "
+        res += "| "
+        for ch in d:
+            if (ch < 32) or (ch > 127):
+                res += ". "
+            else:
+                res += "%c " % ch
+        res += "\n"
+    return res
+
+def printReturnMsg(qstate):
+    print "Return MSG rep   :: flags: %04X, QDcount: %d, Security:%d, TTL=%d" % (qstate.return_msg.rep.flags, qstate.return_msg.rep.qdcount,qstate.return_msg.rep.security, qstate.return_msg.rep.ttl)
+    print "           qinfo :: qname:",qstate.return_msg.qinfo.qname_list, qstate.return_msg.qinfo.qname_str, "type:",qstate.return_msg.qinfo.qtype_str, "class:",qstate.return_msg.qinfo.qclass_str
+    if (qstate.return_msg.rep):
+        print "RRSets:",qstate.return_msg.rep.rrset_count
+        prevkey = None
+        for i in range(0,qstate.return_msg.rep.rrset_count):
+            r = qstate.return_msg.rep.rrsets[i]
+            rk = r.rk
+            print i,":",rk.dname_list, rk.dname_str, "flags: %04X" % rk.flags,
+            print "type:",rk.type_str,"(%d)" % ntohs(rk.type), "class:",rk.rrset_class_str,"(%d)" % ntohs(rk.rrset_class)
+
+            d = r.entry.data
+            print "    RRDatas:",d.count+d.rrsig_count
+            for j in range(0,d.count+d.rrsig_count):
+                print "    ",j,":","TTL=",d.rr_ttl[j],"RR data:"
+                print dataHex(d.rr_data[j],"         ")
+
+def operate(id, event, qstate, qdata):
+    log_info("pythonmod: operate called, id: %d, event:%s" % (id, strmodulevent(event)))
+    #print "pythonmod: per query data", qdata
+
+    print "Query:", ''.join(map(lambda x:chr(max(32,ord(x))),qstate.qinfo.qname)), qstate.qinfo.qname_list, 
+    print "Type:",qstate.qinfo.qtype_str,"(%d)" % qstate.qinfo.qtype,
+    print "Class:",qstate.qinfo.qclass_str,"(%d)" % qstate.qinfo.qclass
+    print
+
+    # TEST:
+    #   > dig @127.0.0.1 www.seznam.cz A
+    #   > dig @127.0.0.1 3.76.75.77.in-addr.arpa. PTR
+    #   prvni dva dotazy vrati TTL 100
+    #   > dig @127.0.0.1 www.seznam.cz A
+    #   > dig @127.0.0.1 3.76.75.77.in-addr.arpa. PTR
+    #   dalsi dva dotazy vrati TTL 10, ktere se bude s dalsimi dotazy snizovat, nez vyprsi a znovu se zaktivuje mesh
+    if qstate.return_msg:
+        printReturnMsg(qstate)
+
+        #qdn = '.'.join(qstate.qinfo.qname_list)
+        qdn = qstate.qinfo.qname_str
+
+        #Pokud dotaz konci na nasledujici, pozmenime TTL zpravy, ktera se posle klientovi (return_msg) i zpravy v CACHE 
+        if qdn.endswith(".seznam.cz.") or qdn.endswith('.in-addr.arpa.'):
+            #pokud je v cache odpoved z iteratoru, pak ji zneplatnime, jinak se moduly nazavolaji do te doby, nez vyprsi TTL
+            invalidateQueryInCache(qstate, qstate.return_msg.qinfo)
+
+            if (qstate.return_msg.rep.authoritative):
+                print "X"*300
+
+            setTTL(qstate, 10) #do cache nastavime TTL na 10
+            if not storeQueryInCache(qstate, qstate.return_msg.qinfo, qstate.return_msg.rep, 0):
+                qstate.ext_state[id] = MODULE_ERROR
+                return False
+
+            setTTL(qstate, 100) #odpoved klientovi prijde s TTL 100
+            qstate.return_rcode = RCODE_NOERROR
+
+    if event == MODULE_EVENT_NEW:
+        qstate.ext_state[id] = MODULE_WAIT_MODULE 
+        return True
+
+    if event == MODULE_EVENT_MODDONE:
+        log_info("pythonmod: previous module done")
+        qstate.ext_state[id] = MODULE_FINISHED 
+        return True
+      
+    if event == MODULE_EVENT_PASS:
+        log_info("pythonmod: event_pass")
+        qstate.ext_state[id] = MODULE_ERROR 
+        return True
+
+    log_err("pythonmod: BAD event")
+    qstate.ext_state[id] = MODULE_ERROR
+    return True
+
+log_info("pythonmod: script loaded.")
index 2164dd3b0937557fe70f6cd0a58659a0d6473bf9..2e7ba642ebab7bbe29c0bf0724ed67ebdfc89cfe 100644 (file)
@@ -432,6 +432,7 @@ tomsg(struct module_env* env, struct msgreply_entry* e, struct reply_info* r,
        msg->rep->ns_numrrsets = r->ns_numrrsets;
        msg->rep->ar_numrrsets = r->ar_numrrsets;
        msg->rep->rrset_count = r->rrset_count;
+        msg->rep->authoritative = r->authoritative;
        if(!rrset_array_lock(r->ref, r->rrset_count, now))
                return NULL;
        for(i=0; i<msg->rep->rrset_count; i++) {
@@ -461,6 +462,7 @@ rrset_msg(struct ub_packed_rrset_key* rrset, struct regional* region,
        if(!msg)
                return NULL;
        msg->rep->flags = BIT_QR; /* reply, no AA, no error */
+        msg->rep->authoritative = 0; /* reply stored in cache can't be authoritative */
        msg->rep->qdcount = 1;
        msg->rep->ttl = d->ttl - now;
        msg->rep->security = sec_status_unchecked;
@@ -495,6 +497,7 @@ synth_dname_msg(struct ub_packed_rrset_key* rrset, struct regional* region,
        if(!msg)
                return NULL;
        msg->rep->flags = BIT_QR; /* reply, no AA, no error */
+        msg->rep->authoritative = 0; /* reply stored in cache can't be authoritative */
        msg->rep->qdcount = 1;
        msg->rep->ttl = d->ttl - now;
        msg->rep->security = sec_status_unchecked;
index 3934ec626bab3583563d041735e17434b6ffc369..1be05d1538207282ff86f7af48618d48aa9ff740 100644 (file)
@@ -120,7 +120,7 @@ local_data_cmp(const void* d1, const void* d2)
 }
 
 /** form wireformat from text format domain name */
-static int
+int
 parse_dname(const char* str, uint8_t** res, size_t* len, int* labs)
 {
        ldns_rdf* rdf;
index 1652a95af2d92709801fc96de319db6d7f35f4ce..687b89546cfdb0afab5aa1a6f7569e850d17c200 100644 (file)
@@ -294,4 +294,10 @@ int local_zones_add_RR(struct local_zones* zones, const char* rr,
 void local_zones_del_data(struct local_zones* zones, 
        uint8_t* name, size_t len, int labs, uint16_t dclass);
 
+
+/** 
+ * Form wireformat from text format domain name. 
+ */
+int parse_dname(const char* str, uint8_t** res, size_t* len, int* labs);
+
 #endif /* SERVICES_LOCALZONE_H */
index fe352ff49377847ba35e5866161be102e3d9b442..b9252ce7ef3abdd9774096d84aa73d23ce5df2b8 100644 (file)
 #include "iterator/iterator.h"
 #include "validator/validator.h"
 
+#ifdef WITH_PYTHONMODULE
+#include "pythonmod/pythonmod.h"
+#endif
+
 /** count number of modules (words) in the string */
 static int
 count_modules(const char* s)
@@ -109,21 +113,29 @@ struct
 module_func_block* module_factory(const char** str)
 {
         /* these are the modules available */
-        int num = 2;
-        const char* names[] = {"iterator", "validator", NULL};
+        const char* names[] = {"iterator", "validator", 
+#ifdef WITH_PYTHONMODULE
+               "python", 
+#endif
+               NULL};
         struct module_func_block* (*fb[])(void) = 
-                {&iter_get_funcblock, &val_get_funcblock, NULL};
+                {&iter_get_funcblock, &val_get_funcblock, 
+#ifdef WITH_PYTHONMODULE
+               &pythonmod_get_funcblock, 
+#endif
+               NULL};
 
-        int i;
+        int i = 0;
         const char* s = *str;
         while(*s && isspace((int)*s))
                 s++;
-        for(i=0; i<num; i++) {
+       while(names[i]) {
                 if(strncmp(names[i], s, strlen(names[i])) == 0) {
                         s += strlen(names[i]);
                         *str = s;
                         return (*fb[i])();
                 }
+               i++;
         }
         return NULL;
 }
index 7e416ec53a31a9e5d5ec17d9250f206ecbe5ab16..99949396e1f238516d1141a53a28516609b3fcb5 100644 (file)
@@ -61,6 +61,9 @@
 #ifdef HAVE_GLOB_H
 #include <glob.h>
 #endif
+#ifdef WITH_PYTHONMODULE
+#include "pythonmod/pythonmod.h"
+#endif
 
 /** Give checkconf usage, and exit (1). */
 static void
@@ -547,6 +550,9 @@ checkconf(const char* cfgfile, const char* opt)
        morechecks(cfg, cfgfile);
        check_mod(cfg, iter_get_funcblock());
        check_mod(cfg, val_get_funcblock());
+#ifdef WITH_PYTHONMODULE
+       check_mod(cfg, pythonmod_get_funcblock());
+#endif
        check_fwd(cfg);
        if(opt) print_option(cfg, opt);
        else    printf("unbound-checkconf: no errors in %s\n", cfgfile);
index 75851802212c1230c44a1871319fb2612c649126..59f54b0fc77ff0b09ff1bd90eac0821dbc9d79ef 100644 (file)
@@ -157,6 +157,8 @@ config_create()
        cfg->local_zones_nodefault = NULL;
        cfg->local_data = NULL;
 
+       if(!(cfg->python_script = strdup(SHARE_DIR"/ubmodule.py")))
+               goto error_exit;
        cfg->remote_control_enable = 0;
        cfg->control_ifs = NULL;
        cfg->control_port = 953;
@@ -384,6 +386,8 @@ int config_set_option(struct config_file* cfg, const char* opt,
                return cfg_parse_memsize(val, &cfg->neg_cache_size);
        } else if(strcmp(opt, "local-data:") == 0) {
                return cfg_strlist_insert(&cfg->local_data, strdup(val));
+       } else if(strcmp(opt, "local-zone:") == 0) {
+               return cfg_parse_local_zone(cfg, val);
        } else if(strcmp(opt, "control-enable:") == 0) {
                IS_YES_OR_NO;
                cfg->remote_control_enable = (strcmp(val, "yes") == 0);
@@ -407,6 +411,9 @@ int config_set_option(struct config_file* cfg, const char* opt,
        } else if(strcmp(opt, "module-config:") == 0) {
                free(cfg->module_conf);
                return (cfg->module_conf = strdup(val)) != NULL;
+       } else if(strcmp(opt, "python-script:") == 0) {
+               free(cfg->python_script);
+               return (cfg->python_script = strdup(val)) != NULL;
        } else {
                /* unknown or unsupported (from the library interface) */
                return 0;
@@ -917,7 +924,7 @@ fname_after_chroot(const char* fname, struct config_file* cfg, int use_chdir)
 }
 
 /** return next space character in string */
-static char* next_space_pos(char* str)
+static char* next_space_pos(const char* str)
 {
        char* sp = strchr(str, ' ');
        char* tab = strchr(str, '\t');
@@ -929,7 +936,7 @@ static char* next_space_pos(char* str)
 }
 
 /** return last space character in string */
-static char* last_space_pos(char* str)
+static char* last_space_pos(const char* str)
 {
        char* sp = strrchr(str, ' ');
        char* tab = strrchr(str, '\t');
@@ -940,6 +947,49 @@ static char* last_space_pos(char* str)
        return (sp>tab)?sp:tab;
 }
 
+int 
+cfg_parse_local_zone(struct config_file* cfg, const char* val)
+{
+       const char *type, *name_end, *name;
+       char buf[256];
+
+       /* parse it as: [zone_name] [between stuff] [zone_type] */
+       name = val;
+       while(*name && isspace(*name))
+               name++;
+       if(!*name) {
+               log_err("syntax error: too short: %s", val);
+               return 0;
+       }
+       name_end = next_space_pos(name);
+       if(!name_end || !*name_end) {
+               log_err("syntax error: expected zone type: %s", val);
+               return 0;
+       }
+       if (name_end - name > 255) {
+               log_err("syntax error: bad zone name: %s", val);
+               return 0;
+       }
+       strncpy(buf, name, (size_t)(name_end-name));
+       buf[name_end-name] = '\0';
+
+       type = last_space_pos(name_end);
+       while(type && *type && isspace(*type))
+               type++;
+       if(!type || !*type) {
+               log_err("syntax error: expected zone type: %s", val);
+               return 0;
+       }
+
+       if(strcmp(type, "nodefault")==0) {
+               return cfg_strlist_insert(&cfg->local_zones_nodefault, 
+                       strdup(name));
+       } else {
+               return cfg_str2list_insert(&cfg->local_zones, strdup(buf),
+                       strdup(type));
+       }
+}
+
 char* cfg_ptr_reverse(char* str)
 {
        char* ip, *ip_end;
index f50f863a7db69f05bcd1ef143a8adac41676c8b9..b5f88239b1c913de13501a0a6bbe47b78c172fb6 100644 (file)
@@ -241,6 +241,9 @@ struct config_file {
        /** certificate file for unbound-control */
        char* control_cert_file;
 
+       /** Python script file */
+       char* python_script;
+
        /** daemonize, i.e. fork into the background. */
        int do_daemonize;
 };
@@ -394,6 +397,14 @@ int cfg_count_numbers(const char* str);
  */
 int cfg_parse_memsize(const char* str, size_t* res);
 
+/**
+ * Parse local-zone directive into two strings and register it in the config.
+ * @param cfg: to put it in.
+ * @param val: argument strings to local-zone, "example.com nodefault".
+ * @return: false on failure
+ */
+int cfg_parse_local_zone(struct config_file* cfg, const char* val);
+
 /**
  * Mark "number" or "low-high" as available or not in ports array.
  * @param str: string in input
index d178422bfb557061d391e7ad812ad12ba5c5aeb3..d7dbde8ffbbc28b0f28c57a3132088eaa0e8d134 100644 (file)
@@ -362,8 +362,8 @@ static void yy_fatal_error (yyconst char msg[]  );
        *yy_cp = '\0'; \
        (yy_c_buf_p) = yy_cp;
 
-#define YY_NUM_RULES 115
-#define YY_END_OF_BUFFER 116
+#define YY_NUM_RULES 117
+#define YY_END_OF_BUFFER 118
 /* This struct is not used in this scanner,
    but its presence is necessary. */
 struct yy_trans_info
@@ -371,126 +371,127 @@ struct yy_trans_info
        flex_int32_t yy_verify;
        flex_int32_t yy_nxt;
        };
-static yyconst flex_int16_t yy_accept[1074] =
+static yyconst flex_int16_t yy_accept[1088] =
     {   0,
-        1,    1,   97,   97,  101,  101,  105,  105,  109,  109,
-        1,    1,  116,  113,    1,   95,   95,  114,  113,  114,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,   97,
-       98,   98,   99,  114,  101,  102,  102,  103,  114,  108,
-      105,  106,  106,  107,  114,  109,  110,  110,  111,  114,
-      112,   96,  112,  100,  114,  112,  113,    0,    1,    0,
-      113,    0,    2,    0,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-       97,    0,  101,    0,  108,    0,  105,  109,    0,  112,
-        0,  112,    0,  112,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  112,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  112,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,   50,  113,  113,  113,  113,
-      113,    6,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  112,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  112,  113,  113,   20,  113,  113,  113,
-      113,   12,   13,  113,   15,   14,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,    3,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  112,  113,
-
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  104,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,   23,  113,
-      113,  113,  113,  113,  113,  113,   24,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,   63,  104,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,   62,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,   21,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,   22,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,   17,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,   51,   52,  113,   49,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,    5,  113,  113,  113,
-
-      113,  113,  113,  113,  113,   65,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,   81,   80,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,   25,  113,  113,  113,  113,   53,
-      113,  113,  113,  113,  113,   78,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,   42,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,    4,
-
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,   89,  113,
-       16,  113,  113,  113,   55,   56,   54,  113,  113,  113,
-      113,  113,   61,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,   69,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,   31,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,   60,
-
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,   64,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,   71,  113,  113,  113,
-      113,   59,  113,   87,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,   32,
-       33,  113,   38,   74,  113,   82,   79,  113,   27,  113,
-       76,  113,  113,  113,  113,  113,    7,  113,   48,   86,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,   66,  113,
-
-      113,   94,  113,  113,  113,  113,  113,  113,  113,  113,
-      113,  113,   75,   26,   28,  113,  113,  113,  113,  113,
-       47,  113,  113,  113,   90,  113,  113,  113,  113,  113,
-      113,   45,  113,  113,  113,  113,  113,  113,   92,  113,
-      113,  113,  113,  113,  113,  113,   11,  113,  113,  113,
-      113,  113,  113,   10,  113,  113,   29,  113,   91,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,   93,
-       88,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-       34,  113,  113,  113,  113,  113,   30,  113,  113,  113,
-       67,   68,  113,  113,  113,   70,  113,  113,  113,  113,
-
-      113,  113,  113,  113,  113,  113,  113,  113,   18,  113,
-      113,  113,  113,  113,  113,  113,  113,  113,  113,  113,
-       85,  113,  113,  113,  113,  113,  113,   19,  113,    9,
-      113,  113,   83,   39,  113,  113,  113,   73,   57,  113,
-      113,   41,   44,   40,  113,   35,  113,    8,  113,  113,
-       72,  113,  113,  113,   36,  113,   84,  113,  113,   58,
-       43,   37,  113,  113,  113,  113,   46,  113,  113,  113,
-      113,   77,    0
+        1,    1,   99,   99,  103,  103,  107,  107,  111,  111,
+        1,    1,  118,  115,    1,   97,   97,  116,  115,  116,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,   99,
+      100,  100,  101,  116,  103,  104,  104,  105,  116,  110,
+      107,  108,  108,  109,  116,  111,  112,  112,  113,  116,
+      114,   98,  114,  102,  116,  114,  115,    0,    1,    0,
+      115,    0,    2,    0,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,   99,    0,  103,    0,  110,    0,  107,  111,    0,
+      114,    0,  114,    0,  114,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  114,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  114,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,   50,  115,
+      115,  115,  115,  115,    6,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  114,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  114,  115,
+      115,   20,  115,  115,  115,  115,   12,   13,  115,   15,
+       14,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+       95,  115,  115,  115,  115,    3,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+
+      115,  115,  115,  115,  115,  114,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  106,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,   23,  115,  115,  115,  115,
+      115,  115,  115,   24,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,   63,
+      106,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,   62,  115,  115,  115,  115,  115,
+
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,   21,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,   22,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,   17,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,   51,   52,  115,   49,  115,  115,  115,  115,  115,
+
+      115,  115,  115,  115,  115,  115,    5,  115,  115,  115,
+      115,  115,  115,  115,  115,   65,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,   81,   80,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,   25,  115,  115,  115,  115,
+       53,  115,  115,  115,  115,  115,   78,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,   42,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+        4,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+       89,  115,   16,  115,  115,  115,   55,   56,   54,  115,
+      115,  115,  115,  115,   61,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,   69,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,   31,  115,
+
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,   60,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,   64,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,   94,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+       71,  115,  115,  115,  115,   59,  115,   87,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,   32,   33,  115,   38,   74,  115,   82,
+       79,  115,   27,  115,   76,  115,  115,  115,  115,  115,
+        7,  115,   48,   86,  115,  115,  115,  115,  115,  115,
+
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,   66,  115,  115,   96,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,   75,   26,   28,  115,
+      115,  115,  115,  115,   47,  115,  115,  115,   90,  115,
+      115,  115,  115,  115,  115,   45,  115,  115,  115,  115,
+      115,  115,   92,  115,  115,  115,  115,  115,  115,  115,
+       11,  115,  115,  115,  115,  115,  115,   10,  115,  115,
+       29,  115,   91,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,   93,   88,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,   34,  115,  115,  115,  115,  115,
+
+       30,  115,  115,  115,   67,   68,  115,  115,  115,   70,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,   18,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,   85,  115,  115,  115,  115,  115,
+      115,   19,  115,    9,  115,  115,   83,   39,  115,  115,
+      115,   73,   57,  115,  115,   41,   44,   40,  115,   35,
+      115,    8,  115,  115,   72,  115,  115,  115,   36,  115,
+       84,  115,  115,   58,   43,   37,  115,  115,  115,  115,
+       46,  115,  115,  115,  115,   77,    0
     } ;
 
 static yyconst flex_int32_t yy_ec[256] =
@@ -533,253 +534,259 @@ static yyconst flex_int32_t yy_meta[40] =
         1,    1,    1,    1,    1,    1,    1,    1,    1
     } ;
 
-static yyconst flex_int16_t yy_base[1088] =
+static yyconst flex_int16_t yy_base[1102] =
     {   0,
         0,    0,   37,   40,   44,   51,   63,   75,   56,   68,
-       87,  108, 2075, 2061,   50, 2157, 2157, 2157,  129,   94,
+       87,  108, 2101, 2087,   50, 2184, 2184, 2184,  129,   94,
        33,  124,   94,   49,   74,   61,   91,   92,  110,  111,
-      112,  133,   50,  135,  137,  136,  145,  143,  159, 2060,
-     2157, 2157, 2157,  122, 2058, 2157, 2157, 2157,  157, 2057,
-     2067, 2157, 2157, 2157,  176, 2055, 2157, 2157, 2157,  180,
-     2054, 2157,  184, 2157,  188,   90, 2052,  194,  198, 2061,
-      205, 2060, 2157, 2059,  158,  166,  122,  116,  189,  181,
-      206,  190,  198,  200,  208,  209,  217,  192,  202,  221,
-      222,  225,  229,  231,  230,  213,  235,  234,  236,  240,
-
-      241,  244,  246,  247,  249,  250,  251,  254,   72,  255,
-     1981,  266, 1615,  271, 1560,  286,  875,  651,  269,  384,
-      290,  296,  280,  266,  289,  283,  292,  293,  295,  302,
-      314,  298,  301,  303,  272,  304,  305,  310,  311,  312,
-      316,  320,  330,  332,  321,  344,  340,  346,  348,  347,
-      349,  333,  337,  350,  351,  352,  356,  360,  147,  361,
-      358,  362,  369,  372,  373,  370,  366,  374,  376,  381,
-      383,  388,  393,  308,  390,  395,  396,  397,  401,  402,
-      404,  412,  408,  410,  411,  413,  416,  417,  418,  420,
-      419,  426,  425,  438,  423,  427,  433,  436,  443,  445,
-
-      446,  442,  454,  448,  455,  456,  463,  459,  457,  461,
-      466,  467,  486,  472,  470,  471,  474,  478,  476,  480,
-      483,  484,  494,  507,  490,  497,  506,  509,  508,  511,
-      514,  515,  482,  516,  517,  530,  521,  531,  518,  538,
-      532,  534,  535,  539,  542, 2157,  544,  547,  548,  549,
-      550, 2157,  551,  552,  553,  559,  555,  563,  564,  566,
-      574,  567,  575,  570,  577,  581,  585,  583,  584,  588,
-      589,  592,  594,  604,  600,  610,  591,  601,  611,  605,
-      620,  622,  617,  624,  626,  632,  628,  630,  636,  635,
-      637,  629,  638,  640,  644,  645,  653,  655,  657,  650,
-
-      659,  665,  662,  666,  667,  671,  672,  673,  674,  675,
-      682,  684,  678,  696,  685,  688,  686,  689,  694,  702,
-      698,  700,  703,  706,  710,  711,  712,  713,  715,  716,
-      714,  717,  723,  725,  728,  733, 2157,  740,  727,  736,
-      738, 2157, 2157,  739, 2157, 2157,  741,  742,  748,  757,
-      747,  749,  754,  759,  755,  765,  763,  770,  774,  760,
-      773,  782,  772,  784,  786,  788,  790,  792,  793,  794,
-      797,  798,  804,  811,  807,  795,  813,  815, 2157,  799,
-      816,  817,  819,  821,  823,  824,  827,  830,  825,  831,
-      832,  833,  839,  842,  841,  847,  846,  849,  851,  852,
-
-      853,  878,  855,  856,  858,  861,  862,  868,  884,  865,
-      857,  873,  870,  888,  886,  890,  898, 2157,  904,  902,
-      893,  895,  901,  907,  913,  891,  903,  919, 2157,  915,
-      920,  921,  922,  923,  928,  936, 2157,  933,  924,  935,
-      938,  940,  942,  943,  944,  948,  950,  949,  951,  957,
-      953,  966,  970,  952,  959,  969,  971,  976,  973,  974,
-      975, 2157,  215,  978,  982,  979,  980,  981,  993,  986,
-      990,  987,  997,  999,  996, 1002, 1003, 1008, 1009, 1010,
-     1011, 1012, 1013, 1016, 1014, 1017, 2157, 1022, 1020, 1018,
-     1035, 1042, 1033, 1044, 1047, 1045, 1051, 1043, 1049, 1058,
-
-     1059, 1055, 1061, 1062, 1064, 1066, 1056, 1063, 1069, 1072,
-     1073, 1074, 1084, 1086, 1087, 1089, 1075, 1091, 1096, 1079,
-     1094, 1102, 2157, 1108, 1110, 1111, 1104, 1107, 1115, 1112,
-     1116, 1117, 1118, 1120, 1121, 1123, 2157, 1129,  615, 1125,
-     1122, 1130, 1133, 1134, 1131, 1138, 1139, 1142, 1147, 1148,
-     1151, 1154, 1155, 1156, 1163, 1164, 1167, 2157, 1165, 1162,
-     1178, 1172, 1174, 1179, 1180, 1182, 1183, 1184, 1186, 1190,
-     1187, 1191, 1188, 1192, 1194, 1195, 1198, 1209, 1199, 1216,
-     1217, 2157, 2157, 1221, 2157, 1210, 1218, 1200, 1222, 1223,
-     1229, 1224, 1230, 1226, 1232, 1234, 2157, 1239, 1235, 1240,
-
-     1025, 1241, 1247, 1243, 1245, 2157, 1249, 1248, 1256, 1261,
-     1250, 1252, 1264, 1265, 1267, 1271, 1274, 1258, 1275, 1277,
-     1280, 1284, 1281, 1282, 1283, 1285, 1287, 1289, 2157, 2157,
-     1294, 1298, 1290, 1303, 1308, 1311, 1314, 1310, 1316, 1318,
-     1319, 1320, 1321, 1323, 2157, 1331, 1332, 1328, 1337, 2157,
-     1335, 1324, 1325, 1339, 1345, 2157, 1347, 1348, 1349, 1351,
-     1350, 1353, 1357, 1365, 1358, 1361, 1366, 1374, 1362, 1376,
-     1382, 1364, 1378, 1381, 1384, 1387, 1388, 2157, 1394, 1390,
-     1397, 1393, 1396, 1404, 1400, 1401, 1402, 1403, 1405, 1406,
-     1409, 1407, 1411, 1417, 1416, 1413, 1428, 1415, 1430, 2157,
-
-     1431, 1438, 1434, 1435, 1440, 1443, 1444, 1437, 1447, 1448,
-     1449, 1450, 1460, 1463, 1466, 1465, 1472, 1468, 1469, 1451,
-     1479, 1471, 1475, 1482, 1478, 1483, 1485, 1486, 2157, 1489,
-     2157, 1496, 1492, 1490, 2157, 2157, 2157, 1503,  751, 1504,
-     1286, 1507, 2157, 1494, 1511, 1500, 1513, 1515, 1516, 1502,
-     1509, 1518, 1520, 1519, 1524, 1531, 1526, 1534, 1536, 1535,
-     1541, 1532, 1542, 1548, 1544, 1545, 1547, 1551, 1556, 1557,
-     1555, 1558, 1553, 1554, 1569, 2157, 1572, 1559, 1574, 1577,
-     1579, 1580, 1581, 1582, 1590, 2157, 1586, 1592, 1593, 1596,
-     1597, 1600, 1598, 1601, 1603, 1605, 1607, 1609, 1610, 2157,
-
-     1611, 1612, 1616, 1617, 1620, 1627, 1623, 1633, 1635, 1630,
-     1638, 1640, 2157, 1641, 1643, 1644, 1648, 1650, 1645, 1652,
-     1653, 1657, 1658, 1660, 1662, 1664, 1665, 1667, 1670, 1671,
-     1673, 1672, 1674, 1676, 1686, 1680, 2157, 1682, 1688, 1693,
-     1696, 2157, 1689, 2157, 1695, 1699, 1706, 1703, 1708, 1710,
-     1700, 1712, 1713, 1719, 1715, 1717, 1722, 1716, 1723, 2157,
-     2157, 1728, 2157, 2157, 1731, 2157, 2157, 1735, 2157, 1737,
-     2157, 1743, 1739, 1726, 1741, 1744, 2157, 1746, 2157, 2157,
-     1747, 1748, 1751, 1754, 1755, 1757, 1758, 1759, 1760, 1761,
-     1765, 1768, 1762, 1766, 1769, 1773, 1774, 1784, 2157, 1776,
-
-     1789, 2157, 1787, 1780, 1785, 1791, 1792, 1800, 1802, 1793,
-     1795, 1801, 2157, 2157, 2157, 1804, 1806, 1813, 1805, 1810,
-     2157, 1816, 1817, 1819, 2157, 1822, 1825, 1826, 1827, 1829,
-     1830, 2157, 1831, 1837, 1839, 1833, 1841, 1850, 2157, 1851,
-     1843, 1854, 1852, 1853, 1858, 1860, 2157, 1845, 1863, 1866,
-     1867, 1870, 1868, 2157, 1871, 1872, 2157, 1875, 2157, 1877,
-     1883, 1886, 1888, 1891, 1881, 1879, 1900, 1902, 1892, 2157,
-     2157, 1894, 1898, 1903, 1904, 1905, 1907, 1908, 1909, 1911,
-     2157, 1912, 1914, 1917, 1919, 1921, 2157, 1924, 1925, 1926,
-     2157, 2157, 1935, 1928, 1936, 2157, 1938, 1939, 1941, 1947,
-
-     1944, 1942, 1949, 1948, 1950, 1952, 1955, 1959, 2157, 1963,
-     1965, 1966, 1968, 1970, 1972, 1974, 1973, 1978, 1980, 1975,
-     2157, 1982, 1984, 1990, 1996, 1992, 1999, 2157, 2000, 2157,
-     2003, 2004, 2157, 2157, 2005, 2007, 2010, 2157, 2157, 2008,
-     2012, 2157, 2157, 2157, 2018, 2157, 2019, 2157, 2021, 2011,
-     2157, 2014, 2025, 2030, 2157, 2034, 2157, 2027, 2035, 2157,
-     2157, 2157, 2037, 2022, 2044, 2031, 2157, 2038, 2045, 2046,
-     2048, 2157, 2157, 2078, 2084, 2090, 2096, 2102,   94, 2108,
-     2114, 2120, 2126, 2132, 2138, 2144, 2150
+      112,  133,   50,  135,  137,  136,  145,  143,  164, 2086,
+     2184, 2184, 2184,  122, 2084, 2184, 2184, 2184,  157, 2081,
+     2091, 2184, 2184, 2184,  179, 2079, 2184, 2184, 2184,  167,
+     2078, 2184,  185, 2184,  189,   90, 2077,  195,  199, 2086,
+      206, 1658, 2184, 1620,  190,  199,  122,  116,  149,  182,
+      208,  191,  201,  207,  209,  161,  212,  210,  147,  217,
+      222,  216,  214,  228,  230,  231,  233,  234,  236,  238,
+
+      240,  239,  241,  244,  246,  248,  242,  249,  250,   72,
+      256, 1547,  273,  880,  277,  812,  284,  736,  600,  278,
+      526,  288,  294,  502,  287,  291,  281,  292,  293,  295,
+      302,  314,  298,  301,  303,  257,  304,  305,  310,  311,
+      312,  316,  320,  330,  332,  321,  344,  340,  346,  348,
+      347,  349,  333,  337,  350,  351,  352,  356,  357,  360,
+      362,  363,  365,  367,  374,  376,  375,  373,  378,  381,
+      383,  382,  387,  388,  395,  308,  391,  399,  401,  403,
+      393,  408,  410,  416,  404,  413,  414,  417,  419,  420,
+      422,  421,  423,  426,  428,  436,  430,  441,  431,  442,
+
+      445,  447,  449,  452,  453,  460,  456,  458,  459,  466,
+      464,  462,  465,  471,  470,  491,  472,  477,  475,  478,
+      485,  481,  483,  488,  489,  495,  512,  499,  502,  504,
+      511,  513,  514,  515,  521,  522,  523,  524,  539,  535,
+      537,  544,  551,  538,  516,  548,  536,  549, 2184,  554,
+      540,  552,  556,  558, 2184,  559,  562,  563,  564,  571,
+      567,  569,  573,  575,  582,  578,  583,  580,  590,  586,
+      592,  593,  594,  597,  596,  603,  606,  613,  607,  622,
+      611,  609,  614,  619,  626,  628,  634,  631,  636,  638,
+      637,  639,  645,  644,  641,  647,  649,  650,  653,  651,
+
+      660,  659,  666,  658,  663,  674,  672,  673,  677,  679,
+      657,  681,  682,  683,  690,  691,  693,  694,  701,  698,
+      699,  704,  705,  706,  712,  708,  710,  711,  713,  715,
+      717,  720,  726,  728,  732,  722,  735,  724,  736,  739,
+      745, 2184,  748,  747,  749,  751, 2184, 2184,  750, 2184,
+     2184,  752,  754,  760,  768,  759,  753,  756,  763,  769,
+      773,  770,  777,  779,  783,  784,  788,  790,  791,  794,
+      795,  800,  799,  801,  797,  808,  804,  817,  819,  802,
+     2184,  820,  810,  825,  827, 2184,  822,  828,  818,  833,
+      829,  834,  835,  841,  844,  839,  845,  846,  847,  852,
+
+      856,  854,  850,  855,  861,  865,  862,  866,  891,  867,
+      869,  871,  874,  873,  881,  878,  883,  870,  888,  893,
+      901,  899,  903,  906, 2184,  915,  908,  912,  914,  916,
+      917,  918,  919,  920,  929, 2184,  925,  928,  930,  932,
+      936,  941,  943, 2184,  946,  948,  944,  949,  952,  953,
+      956,  954,  960,  962,  963,  965,  966,  964,  968,  977,
+      980,  973,  984,  974,  981,  989,  986,  987,  990, 2184,
+      259,  991,  997,  994,  998, 1000, 1001, 1002, 1008, 1003,
+     1009, 1011, 1010, 1013, 1019, 1020, 1022, 1024, 1025, 1026,
+     1027, 1030, 1028, 1031, 2184, 1036, 1034, 1038, 1047, 1054,
+
+     1051, 1060, 1056, 1061, 1062, 1059, 1065, 1072, 1074, 1070,
+     1076, 1068, 1081, 1078, 1071, 1087, 1079, 1088, 1090, 1091,
+     1092, 1095, 1100, 1097, 1104, 1105, 1106, 1107, 1109, 1113,
+     1110, 2184, 1120, 1123, 1126, 1122, 1124, 1129, 1130, 1132,
+     1133, 1134, 1136, 1137, 1139, 2184, 1145, 1138, 1141, 1142,
+     1146, 1149, 1148, 1154, 1155, 1158, 1165, 1170, 1160, 1171,
+     1161, 1169, 1177, 1184, 1186, 1187, 2184, 1189, 1173, 1196,
+     1198, 1183, 1193, 1205, 1185, 1201, 1203, 1206, 1207, 1208,
+     1209, 1210, 1212, 1213, 1214, 1215, 1218, 1227, 1219, 1233,
+     1236, 2184, 2184, 1238, 2184, 1240, 1230, 1234, 1241, 1242,
+
+     1248, 1244, 1249, 1251, 1252, 1253, 2184, 1255, 1254, 1258,
+     1039, 1260, 1266, 1263, 1269, 2184, 1271, 1267, 1277, 1281,
+     1268, 1270, 1279, 1288, 1295, 1291, 1285, 1287, 1289, 1297,
+     1299, 1305, 1298, 1301, 1302, 1304, 1308, 1306, 2184, 2184,
+     1310, 1315, 1314, 1316, 1326, 1332, 1330, 1331, 1334, 1336,
+     1338, 1337, 1339, 1341, 1342, 2184, 1348, 1349, 1350, 1358,
+     2184, 1345, 1346, 1359, 1363, 1362, 2184, 1365, 1366, 1368,
+     1369, 1372, 1371, 1375, 1382, 1376, 1383, 1384, 1392, 1389,
+     1394, 1400, 1396, 1399, 1403, 1405, 1407, 1408, 2184, 1414,
+     1397, 1418, 1410, 1421, 1427, 1412, 1416, 1423, 1425, 1428,
+
+     1429, 1432, 1430, 1437, 1434, 1438, 1439, 1451, 1440, 1442,
+     2184, 1448, 1459, 1444, 1456, 1457, 1460, 1461, 1467, 1468,
+     1470, 1471, 1472, 1474, 1478, 1484, 1490, 1477, 1491, 1492,
+     1494, 1475, 1501, 1495, 1497, 1503, 1499, 1506, 1507, 1510,
+     2184, 1508, 2184, 1514, 1512, 1516, 2184, 2184, 2184, 1523,
+     1521, 1527, 1522, 1532, 2184, 1529, 1533, 1535, 1536, 1539,
+     1540, 1542, 1541, 1545, 1544, 1537, 1553, 1559, 1543, 1560,
+     1564, 1563, 1567, 1570, 1554, 1576, 1573, 1575, 1577, 1580,
+     1581, 1583, 1587, 1585, 1586, 1582, 1584, 1598, 2184, 1601,
+     1589, 1603, 1606, 1608, 1590, 1611, 1613, 1620, 2184, 1616,
+
+     1622, 1623, 1626, 1627, 1629, 1628, 1630, 1631, 1634, 1636,
+     1637, 1639, 2184, 1641, 1642, 1645, 1646, 1652, 1662, 1654,
+     1664, 1666, 1640, 1669, 1671, 2184, 1672, 1674, 1656, 1679,
+     1676, 1680, 1681, 1682, 1688, 1685, 1690, 2184, 1692, 1693,
+     1695, 1697, 1700, 1699, 1701, 1702, 1703, 1707, 1713, 1710,
+     2184, 1711, 1715, 1721, 1723, 2184, 1725, 2184, 1726, 1727,
+     1734, 1735, 1738, 1743, 1728, 1730, 1740, 1749, 1746, 1747,
+     1751, 1753, 1755, 2184, 2184, 1758, 2184, 2184, 1765, 2184,
+     2184, 1767, 2184, 1769, 2184, 1775, 1771, 1760, 1762, 1773,
+     2184, 1780, 2184, 2184, 1777, 1781, 1785, 1787, 1788, 1736,
+
+     1789, 1791, 1792, 1774, 1796, 1793, 1797, 1798, 1799, 1805,
+     1806, 1808, 2184, 1809, 1813, 2184, 1815, 1816, 1817, 1820,
+     1819, 1822, 1830, 1826, 1828, 1829, 2184, 2184, 2184, 1831,
+     1837, 1833, 1839, 1842, 2184, 1844, 1845, 1853, 2184, 1855,
+     1846, 1848, 1858, 1861, 1859, 2184, 1850, 1869, 1870, 1862,
+     1872, 1879, 2184, 1876, 1873, 1880, 1882, 1884, 1886, 1888,
+     2184, 1889, 1890, 1895, 1892, 1896, 1898, 2184, 1902, 1899,
+     2184, 1906, 2184, 1900, 1913, 1907, 1916, 1918, 1919, 1921,
+     1927, 1924, 1925, 2184, 2184, 1926, 1928, 1930, 1931, 1933,
+     1932, 1934, 1939, 1941, 2184, 1940, 1944, 1951, 1942, 1954,
+
+     2184, 1955, 1953, 1956, 2184, 2184, 1966, 1957, 1959, 2184,
+     1967, 1969, 1970, 1974, 1975, 1976, 1978, 1977, 1979, 1980,
+     1984, 1987, 2184, 1990, 1993, 1994, 1997, 2001, 1998, 2002,
+     2003, 2007, 2009, 2010, 2184, 2015, 2012, 2019, 2022, 2025,
+     2027, 2184, 2031, 2184, 2034, 2035, 2184, 2184, 2028, 2038,
+     2039, 2184, 2184, 2004, 2041, 2184, 2184, 2184, 2043, 2184,
+     2046, 2184, 2048, 2049, 2184, 2051, 2053, 2055, 2184, 2057,
+     2184, 2058, 2059, 2184, 2184, 2184, 2061, 2062, 2067, 2063,
+     2184, 2068, 2071, 2073, 2075, 2184, 2184, 2105, 2111, 2117,
+     2123, 2129,   94, 2135, 2141, 2147, 2153, 2159, 2165, 2171,
+
+     2177
     } ;
 
-static yyconst flex_int16_t yy_def[1088] =
+static yyconst flex_int16_t yy_def[1102] =
     {   0,
-     1073,    1, 1074, 1074, 1075, 1075, 1076, 1076, 1077, 1077,
-     1078, 1078, 1073, 1079, 1073, 1073, 1073, 1073, 1080, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1081,
-     1073, 1073, 1073, 1081, 1082, 1073, 1073, 1073, 1082, 1083,
-     1073, 1073, 1073, 1073, 1083, 1084, 1073, 1073, 1073, 1084,
-     1085, 1073, 1086, 1073, 1085, 1085, 1079, 1079, 1073, 1087,
-     1080, 1087, 1073, 1080, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1081, 1081, 1082, 1082, 1083, 1083, 1073, 1084, 1084, 1085,
-     1085, 1086, 1086, 1085, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1085, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1085, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1073, 1079, 1079, 1079, 1079,
-     1079, 1073, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1085, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1085, 1079, 1079, 1073, 1079, 1079, 1079,
-     1079, 1073, 1073, 1079, 1073, 1073, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1073, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1085, 1079,
-
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1073, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1073, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1073, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1073, 1085, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1073, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1073, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1073, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1073, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1073, 1073, 1079, 1073, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1073, 1079, 1079, 1079,
-
-     1079, 1079, 1079, 1079, 1079, 1073, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1073, 1073,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1073, 1079, 1079, 1079, 1079, 1073,
-     1079, 1079, 1079, 1079, 1079, 1073, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1073, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1073,
-
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1073, 1079,
-     1073, 1079, 1079, 1079, 1073, 1073, 1073, 1079, 1079, 1079,
-     1079, 1079, 1073, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1073, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1073, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1073,
-
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1073, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1073, 1079, 1079, 1079,
-     1079, 1073, 1079, 1073, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1073,
-     1073, 1079, 1073, 1073, 1079, 1073, 1073, 1079, 1073, 1079,
-     1073, 1079, 1079, 1079, 1079, 1079, 1073, 1079, 1073, 1073,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1073, 1079,
-
-     1079, 1073, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1079, 1079, 1073, 1073, 1073, 1079, 1079, 1079, 1079, 1079,
-     1073, 1079, 1079, 1079, 1073, 1079, 1079, 1079, 1079, 1079,
-     1079, 1073, 1079, 1079, 1079, 1079, 1079, 1079, 1073, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1073, 1079, 1079, 1079,
-     1079, 1079, 1079, 1073, 1079, 1079, 1073, 1079, 1073, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1073,
-     1073, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1073, 1079, 1079, 1079, 1079, 1079, 1073, 1079, 1079, 1079,
-     1073, 1073, 1079, 1079, 1079, 1073, 1079, 1079, 1079, 1079,
-
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1073, 1079,
-     1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079, 1079,
-     1073, 1079, 1079, 1079, 1079, 1079, 1079, 1073, 1079, 1073,
-     1079, 1079, 1073, 1073, 1079, 1079, 1079, 1073, 1073, 1079,
-     1079, 1073, 1073, 1073, 1079, 1073, 1079, 1073, 1079, 1079,
-     1073, 1079, 1079, 1079, 1073, 1079, 1073, 1079, 1079, 1073,
-     1073, 1073, 1079, 1079, 1079, 1079, 1073, 1079, 1079, 1079,
-     1079, 1073,    0, 1073, 1073, 1073, 1073, 1073, 1073, 1073,
-     1073, 1073, 1073, 1073, 1073, 1073, 1073
+     1087,    1, 1088, 1088, 1089, 1089, 1090, 1090, 1091, 1091,
+     1092, 1092, 1087, 1093, 1087, 1087, 1087, 1087, 1094, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1095,
+     1087, 1087, 1087, 1095, 1096, 1087, 1087, 1087, 1096, 1097,
+     1087, 1087, 1087, 1087, 1097, 1098, 1087, 1087, 1087, 1098,
+     1099, 1087, 1100, 1087, 1099, 1099, 1093, 1093, 1087, 1101,
+     1094, 1101, 1087, 1094, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1095, 1095, 1096, 1096, 1097, 1097, 1087, 1098, 1098,
+     1099, 1099, 1100, 1100, 1099, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1099, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1099, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1087, 1093,
+     1093, 1093, 1093, 1093, 1087, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1099, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1099, 1093,
+     1093, 1087, 1093, 1093, 1093, 1093, 1087, 1087, 1093, 1087,
+     1087, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1087, 1093, 1093, 1093, 1093, 1087, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+
+     1093, 1093, 1093, 1093, 1093, 1099, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1087, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1087, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1087, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1087,
+     1099, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1087, 1093, 1093, 1093, 1093, 1093,
+
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1087, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1087, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1087, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1087, 1087, 1093, 1087, 1093, 1093, 1093, 1093, 1093,
+
+     1093, 1093, 1093, 1093, 1093, 1093, 1087, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1087, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1087, 1087,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1087, 1093, 1093, 1093, 1093,
+     1087, 1093, 1093, 1093, 1093, 1093, 1087, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1087, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1087, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1087, 1093, 1087, 1093, 1093, 1093, 1087, 1087, 1087, 1093,
+     1093, 1093, 1093, 1093, 1087, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1087, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1087, 1093,
+
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1087, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1087, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1087, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1087, 1093, 1093, 1093, 1093, 1087, 1093, 1087, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1087, 1087, 1093, 1087, 1087, 1093, 1087,
+     1087, 1093, 1087, 1093, 1087, 1093, 1093, 1093, 1093, 1093,
+     1087, 1093, 1087, 1087, 1093, 1093, 1093, 1093, 1093, 1093,
+
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1087, 1093, 1093, 1087, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1087, 1087, 1087, 1093,
+     1093, 1093, 1093, 1093, 1087, 1093, 1093, 1093, 1087, 1093,
+     1093, 1093, 1093, 1093, 1093, 1087, 1093, 1093, 1093, 1093,
+     1093, 1093, 1087, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1087, 1093, 1093, 1093, 1093, 1093, 1093, 1087, 1093, 1093,
+     1087, 1093, 1087, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1087, 1087, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1087, 1093, 1093, 1093, 1093, 1093,
+
+     1087, 1093, 1093, 1093, 1087, 1087, 1093, 1093, 1093, 1087,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1087, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+     1093, 1093, 1093, 1093, 1087, 1093, 1093, 1093, 1093, 1093,
+     1093, 1087, 1093, 1087, 1093, 1093, 1087, 1087, 1093, 1093,
+     1093, 1087, 1087, 1093, 1093, 1087, 1087, 1087, 1093, 1087,
+     1093, 1087, 1093, 1093, 1087, 1093, 1093, 1093, 1087, 1093,
+     1087, 1093, 1093, 1087, 1087, 1087, 1093, 1093, 1093, 1093,
+     1087, 1093, 1093, 1093, 1093, 1087,    0, 1087, 1087, 1087,
+     1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087,
+
+     1087
     } ;
 
-static yyconst flex_int16_t yy_nxt[2197] =
+static yyconst flex_int16_t yy_nxt[2224] =
     {   0,
        14,   15,   16,   17,   18,   19,   18,   14,   14,   14,
        14,   18,   20,   21,   14,   22,   23,   24,   25,   14,
@@ -790,242 +797,245 @@ static yyconst flex_int16_t yy_nxt[2197] =
        59,   68,   68,   49,   51,   52,   53,   54,   60,   18,
        57,   58,   59,   68,   84,   55,   51,   52,   53,   54,
        60,   18,   85,   96,   68,   82,   68,   55,   15,   16,
-       17,   62,   63,   64,   67,   67,  164,   67,   67,   65,
+       17,   62,   63,   64,   67,   67,  166,   67,   67,   65,
 
-       67,   83,  121,   68,   68,   67,   68,   86,   66,   15,
-       16,   17,   62,   63,   64,   79,  124,   87,   80,   88,
-       65,   81,   68,   68,   68,  111,  111,   89,   68,   66,
+       67,   83,  122,   68,   68,   67,   68,   86,   66,   15,
+       16,   17,   62,   63,   64,   79,  125,   87,   80,   88,
+       65,   81,   68,   68,   68,  112,  112,   89,   68,   66,
        72,   73,   72,   72,   68,   72,   68,   76,   90,   91,
-       72,   74,  128,   92,   77,   68,   93,   68,   68,   68,
-       94,   78,  127,  103,  100,   68,   97,   68,  105,   68,
-      113,  207,   98,  113,  101,   99,   95,  102,  104,  107,
-       68,   68,  109,  125,  108,  106,  110,  115,   68,  115,
-      115,  126,  115,  118,  118,   72,   73,   72,   72,  120,
-       72,  120,  120,   68,  120,   67,  123,   67,   67,   69,
-
-       67,   68,   68,   70,   68,   67,   72,   73,   72,   72,
-       68,   72,   68,  131,   68,  130,   72,   74,   68,  129,
-       68,   68,  133,  141,  136,   68,  137,  121,  134,   68,
-      135,  132,  138,   68,   68,  139,  143,   68,  145,  142,
-      144,   68,   68,   68,  146,  150,   68,   68,   68,  140,
-      148,  151,   68,   68,  147,  149,   68,  153,   68,   68,
-      158,   68,   68,   68,  152,  154,   68,   68,  155,  111,
-      111,  163,  118,  118,  113,  156,  157,  113,  121,  160,
-      159,  166,   73,  161,   68,  165,  162,  115,  181,  115,
-      115,  120,  115,  120,  120,   68,  120,   72,   73,   72,
-
-       72,   68,   72,  168,   68,   68,  167,   68,  123,  172,
-       68,  178,  171,   68,   68,   68,   68,   68,  179,  169,
-       68,  182,   68,   68,   68,  170,   68,  189,   68,  187,
-      173,  183,   68,   68,  184,  174,  224,  185,  180,  191,
-      175,  186,   68,  190,   68,   68,  176,  177,  188,   68,
-      192,  194,   68,  196,  193,  197,   68,  195,   68,   68,
-       68,   68,   68,   68,   68,  200,  198,  199,   68,  204,
-       68,  201,   68,   68,   68,  210,  211,  202,   68,  213,
-      208,   68,  121,  203,   68,   68,   68,  214,   68,  209,
-      205,  218,  206,   68,  216,   68,  121,  217,  221,  212,
-
-       68,  222,   68,  219,  215,   68,  223,   68,   68,   68,
-      226,  220,  227,   68,   68,  230,   68,  225,  228,  232,
-       68,  231,   68,   68,   68,   68,  236,  229,   68,   68,
-       68,   68,   68,  239,  246,   68,  235,   68,   68,   68,
-      233,  238,  247,  234,  240,   68,  237,  242,   68,  243,
-       68,  241,  244,  245,   68,   68,  252,   68,   68,  253,
-       68,  255,  248,  250,  251,  249,   68,   68,   68,   68,
-      259,   68,  257,   68,  254,   68,  260,  258,   68,   68,
-      256,  263,   68,  121,   68,  275,   68,  262,   68,  261,
-       68,  272,   68,  265,   68,   68,   68,  264,   68,  271,
-
-      266,  267,   68,  292,  273,  274,   68,  277,  276,   68,
-      279,  280,  268,  269,  270,  278,  281,  282,   68,   68,
-       68,   68,  283,   68,  287,  284,   68,   68,   68,   68,
-       68,  298,  293,   68,  285,  286,  290,  295,  294,  296,
-      289,  288,   68,   68,   68,  299,   68,   68,  297,  291,
-       68,   68,  302,  300,   68,  304,   68,  305,  301,   68,
-       68,   68,   68,   68,   68,   68,  313,   68,  307,  311,
-      308,   68,  303,  312,  309,   68,   68,  316,   68,   68,
-      306,  321,   68,  310,  317,  314,   68,   68,  324,   68,
-      326,  322,  318,   68,  315,   68,   68,   68,  320,  323,
-
-       68,   68,  319,   68,   68,  331,  121,  325,  327,  328,
-      334,  335,   68,   68,  329,  338,   68,   68,  330,  333,
-      332,  337,   68,   68,  344,  336,  340,   68,  339,   68,
-      341,  342,   68,  343,   68,  345,   68,  346,   68,  347,
-       68,   68,   68,  350,   68,  348,  349,   68,   68,   68,
-       68,  351,   68,  607,  352,  354,   68,   68,  359,  356,
-      360,  353,   68,  119,  357,   68,  355,   68,  358,   68,
-      361,   68,  366,  362,   68,  364,  365,   68,   68,   68,
-      367,  368,  369,   68,   68,   68,   68,   68,  370,  375,
-       68,  373,  374,  377,   68,  363,   68,   68,   68,  372,
-
-       68,   68,  371,  378,  381,  376,   68,  379,   68,  385,
-       68,  386,   68,  382,   68,   68,  387,  380,   68,  383,
-      388,  384,   68,   68,   68,   68,   68,   68,   68,   68,
-      393,  392,  394,  395,  389,   68,  391,  121,  397,   68,
-       68,  390,  399,  400,  396,   68,  401,  402,   68,  398,
-       68,   68,   68,   68,   68,  409,  404,  403,  408,   68,
-       68,   68,  407,   68,  415,  405,   68,   68,  406,   68,
-      418,   68,   68,  410,  419,   68,  411,   68,  420,  416,
-      797,  412,   68,  422,   68,   68,   68,  413,  414,  423,
-      421,  417,  424,  425,   68,  426,   68,  429,   68,  427,
-
-       68,  428,   68,  430,   68,   68,   68,   68,  431,   68,
-       68,   68,  432,  433,  435,  437,   68,  436,  438,   68,
-      444,  440,  439,   68,  434,   68,  441,   68,   68,   68,
-      442,   68,  445,   68,  451,   68,   68,   68,  443,   68,
-      447,  449,   68,   68,   68,   68,  452,  448,  446,  455,
-      450,   68,  457,   68,   68,  454,  453,  458,   68,   68,
-      462,   68,  463,  121,   68,   68,  456,   68,   68,   68,
-       68,  459,  460,   68,   68,  476,  117,   68,  461,  464,
-       68,  481,   68,  472,  473,   68,  482,  483,  475,  465,
-       68,  480,  471,  466,  474,  467,   68,  477,   68,  468,
-
-       68,  469,   68,   68,  478,   68,  470,   68,  484,  487,
-       68,  488,  485,   68,   68,   68,   68,  489,  492,   68,
-      491,  486,  479,  495,  490,   68,  497,   68,  493,  496,
-      494,   68,   68,   68,   68,   68,   68,  499,  500,  501,
-       68,  503,  498,  504,  502,   68,  505,   68,   68,  506,
-       68,  507,   68,  509,   68,   68,   68,  510,  512,  511,
-       68,   68,   68,   68,   68,   68,  516,  508,  517,   68,
-      523,   68,  518,  520,  513,  515,  519,  521,   68,  522,
-      514,   68,   68,   68,  526,   68,   68,   68,   68,  531,
-       68,   68,   68,   68,   68,  528,  532,  525,   68,   68,
-
-      524,  537,   68,  527,  530,   68,  533,  534,   68,   68,
-      535,   68,  529,  536,   68,   68,  540,  538,  539,  543,
-       68,   68,   68,   68,   68,   68,   68,  541,   68,   68,
-       68,  549,   68,  542,   68,  544,  545,   68,  552,  665,
-      554,  546,  548,  550,  547,   68,  551,   68,  553,  557,
-      555,  560,  556,  558,   68,   68,   68,   68,  559,   68,
-      561,   68,  562,   68,  563,  566,  567,   68,   68,  564,
-       68,   68,  568,   68,   68,   68,   68,  569,   68,  565,
-      574,   68,  576,  570,   68,   68,   68,   68,  571,  578,
-      572,   68,  573,  575,  577,  582,   68,  583,   68,   68,
-
-      585,   68,  579,   68,  584,  581,   68,  586,   68,  589,
-      580,  587,  590,  588,   68,  592,   68,  593,  594,   68,
-       68,  591,   68,   68,   68,  595,  597,   68,   68,   68,
-       68,  601,   68,   68,   68,   68,  605,   68,  596,  609,
-      606,   68,   68,   68,  598,   68,   68,  600,  599,  611,
-       68,   68,  602,  604,   68,  608,  615,  613,  603,   68,
-       68,  616,  610,   68,  617,  612,   68,   68,   68,  614,
-      623,  624,  619,  622,   68,   68,   68,   68,  618,   68,
-      625,  620,  626,  630,   68,  628,   68,  633,  621,  629,
-       68,   68,   68,  627,   68,   68,   68,  632,   68,   68,
-
-       68,  641,   68,   68,   68,  631,   68,   68,  642,  645,
-       68,   68,   68,  634,  635,  636,  638,  637,  640,  643,
-      639,   68,   68,  648,  649,  651,  646,  644,   68,   68,
-       68,  647,  650,   68,   68,   68,   68,  653,   68,  654,
-      656,   68,   68,  658,   68,  652,   68,   68,  660,  659,
-      655,   68,   68,   68,  667,   68,  657,   68,  666,   68,
-       68,   68,   68,  669,   68,  661,  670,  663,   68,  662,
-       68,  672,  664,   68,  673,  668,   68,   68,  678,   68,
-      674,  676,  677,   68,  675,  671,   68,   68,  679,   68,
-      681,  685,   68,   68,   68,   68,   68,   68,   68,   68,
-
-      799,   68,   68,  683,  680,  684,   68,  682,  690,  693,
-       68,  691,  689,  686,  687,   68,  688,  692,  699,  694,
-       68,  695,   68,   68,  696,  700,   68,  697,   68,  698,
-       68,   68,   68,   68,  706,   68,   68,   68,  708,  709,
-       68,  702,  701,   68,   68,  704,  710,   68,  703,   68,
-      705,   68,  711,  707,  714,  713,  715,   68,  712,   68,
-       68,   68,   68,   68,  719,   68,  720,  716,  721,   68,
-       68,  722,  725,   68,   68,  717,   68,   68,   68,  718,
-      723,  724,  726,  730,  728,  729,   68,  731,   68,  732,
-       68,  727,  735,   68,   68,  736,   68,  733,  737,   68,
-
-       68,  739,   68,  738,  741,   68,   68,  743,   68,   68,
-      734,  744,   68,   68,   68,   68,   68,   68,   68,   68,
-      740,   68,  753,   68,  745,   68,  746,   68,   68,   68,
-      742,  747,  755,  748,  749,  750,  756,  757,  751,  754,
-       68,  759,   68,   68,  752,  763,   68,   68,  762,   68,
-       68,  758,   68,  760,  765,   68,   68,  766,  761,   68,
-       68,   68,   68,   68,  767,  770,  764,  774,  769,  771,
-      775,  768,   68,  777,  776,   68,  773,   68,   68,  779,
-       68,   68,  772,   68,   68,  781,  783,   68,  782,  778,
-       68,   68,  780,  786,   68,   68,  787,   68,   68,  785,
-
-      788,   68,   68,  789,   68,  784,   68,  790,   68,  792,
-      796,  795,   68,  791,   68,   68,   68,  798,  800,   68,
-      793,   68,  794,   68,  802,   68,  801,   68,   68,  807,
-       68,   68,   68,  803,  810,  809,   68,  804,   68,  805,
-      806,  808,  813,   68,   68,  812,   68,   68,   68,  811,
-      816,  815,  817,   68,   68,  821,   68,   68,  818,   68,
-       68,  822,  819,   68,  814,   68,   68,   68,   68,   68,
-       68,   68,  116,  824,  820,  825,  823,  826,  828,  829,
-      827,   68,  832,  830,   68,  831,   68,  833,  837,   68,
-      834,   68,   68,   68,   68,  836,  835,  840,   68,  841,
-
-      838,  842,   68,  844,   68,   68,  845,  843,   68,   68,
-       68,  839,   68,   68,  847,   68,  848,   68,  850,   68,
-      846,   68,   68,   68,   68,  849,  856,  114,   68,   68,
-      859,  860,   68,  854,  851,   68,  852,  857,  861,   68,
-      853,  858,   68,  855,  863,   68,  864,   68,  862,  866,
-       68,  867,   68,   68,  869,   68,   68,   68,  868,  871,
-       68,  865,   68,  873,   68,   68,  875,  874,  877,   68,
-       68,  879,   68,  880,   68,  870,   68,   68,  882,   68,
-      872,  876,   68,   68,   68,   68,   68,  884,   68,  878,
-      886,  883,   68,  890,   68,  888,  891,  889,   68,  887,
-
-       68,   68,  881,  895,  885,   68,  894,   68,   68,  893,
-      897,   68,   68,  896,  892,   68,  898,  899,   68,  900,
-       68,  902,   68,  901,   68,   68,  906,   68,   68,   68,
-      905,   68,  903,  907,   68,   68,  910,  911,   68,  909,
-       68,  912,  913,   68,  904,  908,  914,   68,  915,   68,
-      916,   68,  917,   68,  918,   68,   68,  921,   68,   68,
-       68,  920,  923,   68,  922,  925,   68,   68,  924,   68,
-       68,   68,   68,   68,   68,  919,  932,   68,   68,  926,
-       68,   68,  928,  929,  930,   68,   68,  927,   68,  933,
-      937,  938,   68,  931,  936,  939,   68,   68,  935,   68,
-
-      934,   68,  941,   68,   68,   68,  940,   68,  942,  948,
-      943,  947,   68,   68,   68,  944,   68,   68,   68,  945,
-      949,  953,   68,  946,  954,   68,  950,  957,   68,   68,
-      959,   68,  955,  951,   68,  960,  952,   68,   68,   68,
-      956,   68,   68,   68,  963,   68,  964,  962,  958,   68,
-      965,   68,  970,   68,  967,   68,  968,   68,  966,  961,
-      969,  971,   68,   68,   68,   68,   68,  973,  972,  974,
-       68,  977,   68,  975,  976,   68,  979,  981,   68,   68,
-       68,  978,   68,   68,   68,  984,  987,   68,  982,   68,
-      983,   68,  985,   68,  980,   68,  989,  986,   68,  991,
-
-       68,  990,  992,   68,   68,  994,   68,  995,  997,  988,
-       68,  993,   68,  996,   68,   68,   68,   68,  999,   68,
-       68,   68, 1002,   68,   68,  998,   68, 1007, 1009,   68,
-     1005,   68, 1001,   68, 1000, 1010,   68,   68,   68, 1003,
-       68, 1016, 1011, 1006, 1008, 1012, 1004,   68,   68, 1013,
-       68,   68, 1015,   68,   68, 1018,   68, 1017, 1021,   68,
-       68,   68,   68, 1014,   68, 1025, 1028,   68, 1020, 1024,
-     1019,   68, 1022, 1023, 1030,   68, 1029,   68,   68, 1033,
-       68, 1034,   68, 1027,   68,   68,   68,   68, 1026, 1038,
-       68, 1039,   68,  112,   68, 1042,   68, 1031, 1036, 1041,
-
-     1032, 1043,   68, 1035,   68, 1037, 1040, 1044,   68, 1045,
-     1046,   68,   68, 1047, 1048,   68,   68,   68, 1051,   68,
-       68, 1049,   68,   68,   68, 1050,   68, 1052, 1054, 1055,
-       68,   68, 1057,   68,   68, 1056, 1060,   68, 1058,   68,
-     1053, 1061,   68,   68, 1059, 1062,   68,   68, 1064,   68,
-       68, 1063, 1068, 1065, 1066, 1067,   68,   68,   68, 1072,
-       68,   73,   73,   73,   68, 1069,  121,  119,  117,  116,
-      114, 1070,  112,   68, 1073, 1073, 1073, 1071,   40,   40,
-       40,   40,   40,   40,   45,   45,   45,   45,   45,   45,
-       50,   50,   50,   50,   50,   50,   56,   56,   56,   56,
-
-       56,   56,   61,   61,   61,   61,   61,   61,   71,   71,
-       71,   71,   71,   71,  111,  111, 1073, 1073,  111,  111,
-      113,  113, 1073,  113, 1073,  113,  115, 1073, 1073, 1073,
-     1073,  115,  118,  118, 1073, 1073,  118,  118,  120, 1073,
-     1073, 1073, 1073,  120,  122,  122,  122,  122,  122,  122,
-       72,   72,   72,   72,   72,   72,   13, 1073, 1073, 1073,
-     1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073,
-     1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073,
-     1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073,
-     1073, 1073, 1073, 1073, 1073, 1073
-
+       72,   74,  129,   92,   77,   68,   93,   68,   68,   68,
+       94,   78,  128,  104,  101,   68,   97,   68,  106,   68,
+      114,   68,   98,  114,  102,   99,   95,  103,  105,  108,
+      119,  119,  100,   68,  109,  107,   68,  110,  138,  130,
+      116,  111,  116,  116,  143,  116,   72,   73,   72,   72,
+      121,   72,  121,  121,   68,  121,   67,  124,   67,   67,
+
+       69,   67,   68,   68,   70,  126,   67,   72,   73,   72,
+       72,   68,   72,   68,  127,  132,  131,   72,   74,   68,
+       68,   68,   68,  134,   68,  137,   68,  139,   68,   68,
+      140,  135,  144,  133,   68,  147,  145,  136,  146,  148,
+       68,  142,   68,   68,  141,   68,   68,  149,   68,  152,
+       68,   68,   68,   68,   68,  150,   68,  154,   68,  160,
+       68,   68,   68,  151,  153,  156,  157,  165,   68,   68,
+      155,  122,  158,  183,  159,  163,  112,  112,  162,  161,
+      114,  119,  119,  114,  164,  116,  167,  116,  116,  121,
+      116,  121,  121,   68,  121,   72,   73,   72,   72,  122,
+
+       72,  170,  168,   68,   68,   68,  124,   68,  169,  174,
+       68,  180,  173,   68,   68,   68,   68,   68,  181,  171,
+       68,  184,   68,   68,   68,  172,   68,  191,   68,  189,
+      175,  185,   68,   68,  186,  176,  227,  187,  182,  193,
+      177,  188,   68,  192,   68,   68,  178,  179,  190,   68,
+      194,  196,   68,  198,  195,  199,   68,  197,   68,   68,
+       68,   68,   68,   68,   68,  202,  200,  201,   68,   68,
+      204,  203,   68,  207,   68,   68,  210,   68,  205,   68,
+      213,  214,  211,  216,  206,  122,   68,   68,   68,  217,
+       68,  208,  209,   68,   68,   68,  212,  219,  221,   68,
+
+       68,  225,  224,   68,  215,   68,  218,   68,  226,  220,
+      222,   68,  223,   68,  229,   68,   68,  230,  228,  232,
+       68,  233,   68,  235,  231,   68,   68,  234,   68,   68,
+      239,   68,   68,   68,   68,   68,  236,  242,   68,  238,
+       68,  249,   68,   68,  241,  243,  237,  245,   68,  240,
+      247,  248,  246,   68,   68,  244,  250,   68,  255,   68,
+      251,   68,  256,  252,   68,   68,  254,  259,   68,  253,
+       68,   68,   68,  263,   68,  261,   68,   68,   68,  257,
+      262,  264,   68,   68,   68,  258,  267,  122,  260,   68,
+       68,  266,  279,   68,  265,   68,  269,   68,  276,  275,
+
+       68,   68,  268,   68,   73,  270,  271,   68,  277,  278,
+      281,   68,  284,  280,   68,  283,   68,  272,  273,  274,
+      282,  285,  286,   68,   68,   68,   68,   68,   68,  291,
+      288,  287,  289,   68,   68,   68,   68,  290,  122,  297,
+      305,  293,  294,  296,  292,  298,  299,   68,   68,   68,
+       68,   68,   68,  300,  301,  295,   68,  302,  303,  304,
+       68,   68,  308,   68,   68,  306,   68,  309,   68,  307,
+       68,   68,  311,  310,   68,   68,   68,  312,  318,   68,
+      316,   68,  313,   68,  317,   68,  321,   68,  315,  326,
+       68,  314,   68,  322,   68,   68,  329,  319,   68,  327,
+
+      320,  323,   68,  331,   68,   68,   68,  325,   68,   68,
+      328,  324,  120,  332,  336,   68,  333,  330,  122,   68,
+      340,   68,  339,   68,  334,   68,   68,  337,  335,  345,
+      338,   68,  341,  342,   68,  343,  344,  347,   68,  348,
+       68,  349,  350,   68,  346,  352,   68,  351,   68,   68,
+       68,   68,  355,   68,  353,  354,   68,   68,  357,   68,
+      356,   68,   68,   68,  364,   68,  359,  365,  361,   68,
+       68,   68,   68,  362,  366,   68,  360,  363,   68,  358,
+      370,  371,  367,  369,   68,   68,   68,  376,  373,   68,
+      372,   68,  374,   68,   68,   68,  375,  380,  382,  378,
+
+      379,  381,   68,   68,  368,   68,   68,  377,  385,  384,
+       68,   68,  386,   68,  383,  388,   68,   68,   68,  392,
+       68,  393,   68,   68,   68,   68,  394,   68,  395,   68,
+      387,  389,   68,  391,   68,  390,   68,  118,   68,  399,
+       68,  396,  398,  400,   68,  401,  397,   68,  122,  402,
+      405,   68,  403,  406,  407,  409,  404,   68,  408,   68,
+       68,   68,   68,   68,   68,   68,   68,  416,   68,  411,
+      415,   68,   68,  414,  425,   68,  422,  410,  412,  413,
+       68,   68,   68,  423,  417,   68,  427,  418,  426,   68,
+      429,   68,  419,  424,  430,   68,   68,  428,  420,  421,
+
+       68,  433,   68,   68,  432,  436,   68,   68,  435,   68,
+      437,   68,   68,   68,   68,  431,   68,  434,  438,  439,
+       68,  440,   68,  443,  117,  442,  445,  441,  444,   68,
+       68,   68,   68,  446,   68,  447,  448,   68,  449,   68,
+       68,   68,  450,  452,  453,   68,   68,   68,  459,  454,
+      451,   68,  457,   68,  455,  456,   68,   68,   68,   68,
+      460,  458,   68,  463,   68,  465,   68,   68,   68,  462,
+      461,  466,  470,   68,   68,  468,  471,  122,   68,   68,
+      464,   68,   68,   68,  467,   68,   68,  469,  484,  472,
+       68,  485,  115,   68,  489,   68,  480,  481,  486,  483,
+
+       68,  490,  473,   68,  479,   68,  474,  482,  475,  488,
+      491,   68,  476,   68,  477,   68,  487,  495,   68,  478,
+       68,  492,  496,  497,   68,  493,   68,   68,   68,   68,
+       68,   68,   68,  500,  494,  502,  505,   68,  501,  499,
+       68,   68,   68,  498,   68,  507,  504,  508,   68,  509,
+      512,  503,  506,   68,  511,   68,   68,  510,   68,  513,
+       68,   68,  514,  515,   68,   68,   68,  518,   68,  521,
+      519,  516,   68,  520,   68,   68,   68,   68,   68,  527,
+       68,  517,  525,  526,  529,   68,   68,  530,  524,   68,
+      522,  528,   68,   68,  523,  532,   68,  535,   68,   68,
+
+      531,   68,   68,   68,  540,  533,   68,  534,  537,   68,
+       68,  541,   68,   68,   68,   68,  536,  539,  544,  546,
+       68,   68,   68,   68,  542,   68,  543,  538,  549,  545,
+      548,   68,   68,  547,   68,  552,   68,   68,   68,   68,
+       68,  550,   68,   68,  551,  558,   68,  553,   68,  554,
+       68,   68,  561,  676,  563,  555,  557,  559,  556,   68,
+      560,  566,  562,   68,  565,  567,   68,  569,   68,  570,
+      564,   68,   68,   68,   68,  572,  568,   68,  571,  575,
+       68,  576,   68,   68,   68,  573,   68,  577,   68,  579,
+       68,   68,  578,   68,  580,  574,  581,  583,  582,   68,
+
+       68,  585,   68,   68,   68,  584,  592,   68,  588,   68,
+      587,  593,   68,  586,  594,  595,   68,   68,   68,   68,
+      589,   68,   68,  591,  598,   68,  597,  602,  590,  601,
+      603,  600,   68,  604,   68,   68,   68,  596,   68,  599,
+      607,   68,   68,  605,   68,   68,   68,  611,   68,   68,
+       68,   68,  615,   68,   68,  606,  616,   68,   68,  619,
+       68,   68,  608,  610,  609,  621,   68,   68,  612,  614,
+       68,  618,   68,   68,  613,  625,  617,   68,  620,  622,
+      623,   68,   68,   68,  626,   68,  624,  627,  630,   68,
+      628,  633,  629,  634,  632,   68,   68,   68,   68,   68,
+
+      635,   68,  631,  638,  637,   68,  636,  639,   68,  640,
+       68,  642,  643,   68,  641,   68,  644,   68,   68,   68,
+       68,   68,   68,  651,   68,   68,   68,   68,  652,  656,
+       68,   68,  645,  648,  646,  654,  650,  647,  653,   68,
+      659,  649,   68,  660,  657,   68,   68,  655,   68,  661,
+       68,  658,   68,   68,   68,  662,   68,  663,  665,  667,
+       68,   68,  669,   68,   68,   68,   68,   68,  671,  666,
+       68,  664,   68,  678,  670,   68,  668,  677,   68,   68,
+       68,   68,   68,   68,  672,  673,  674,  680,  681,   68,
+      675,   68,  683,   68,  684,  679,  687,   68,  685,   68,
+
+       68,   68,  686,   68,  682,  688,  689,   68,  690,   68,
+       68,   68,  696,   68,   68,  691,   68,   68,   68,  692,
+       68,  693,   68,  694,  695,  704,   68,   68,   68,  701,
+      697,  700,  702,  698,  703,  699,  705,  707,   68,  710,
+      708,  711,   68,   68,   68,  706,   68,  709,   68,   68,
+       68,   68,  717,   68,   68,  720,  721,   68,   68,  713,
+       68,   68,   68,  712,  715,  725,  714,  716,  722,  718,
+       68,   68,  719,  723,   68,   68,  726,   68,   68,  724,
+       68,   68,  731,   68,   68,  732,  733,   68,   68,  737,
+      727,  728,  729,  734,   68,   68,   68,  730,  735,  736,
+
+      738,   68,  740,  741,   68,  743,   68,  744,   68,   68,
+      742,   68,   68,  739,  747,   68,  748,   68,  749,   68,
+       68,  751,   68,  750,   68,  753,   68,  752,   68,  745,
+       68,  746,  755,   68,  756,   68,  757,   68,  758,   68,
+       68,   68,   68,  759,   68,  765,   68,  754,  760,   68,
+       68,   68,   68,  768,   68,  761,   68,  762,  767,  769,
+       68,  763,  766,   68,  771,  774,  775,  764,   68,   68,
+      773,   68,   68,   68,  778,  777,  776,  770,  772,   68,
+       68,  779,   68,   68,   68,  787,   68,   68,  783,   68,
+       68,  788,  784,  780,  781,  789,   68,  790,  792,  782,
+
+      786,  791,   68,   68,   68,  785,   68,   68,  796,   68,
+      794,   68,  795,   68,  799,   68,  793,  800,   68,   68,
+       68,  798,   68,  801,   68,  802,   68,  805,   68,  797,
+      809,  803,  804,   68,   68,   68,  812,  808,  806,   68,
+      811,   68,  807,  813,   68,   68,  815,   68,   68,   68,
+      810,   68,   68,   68,   68,   68,   68,   68,  823,  113,
+      817,  814,  822,  818,  819,   68,   68,  824,  816,  820,
+      826,   68,   68,  821,  825,   68,   68,  828,  829,   68,
+      830,  827,   68,  834,  831,   68,  833,   68,   68,   68,
+      835,  838,   68,   68,   68,   68,   68,   68,   68,   68,
+
+      832,   68,   68,  837,  840,  839,  836,  841,  842,  843,
+       68,  844,  846,   68,  845,   68,  847,  851,   68,  848,
+       68,  853,   73,   68,  850,   68,  849,  854,   68,  852,
+      855,  856,   68,  858,   68,   68,  859,  857,   68,   68,
+       68,   68,   68,   68,  861,  862,   68,  864,   68,   68,
+      860,   68,   68,   68,   68,  863,  870,   68,   68,  873,
+       73,  868,  865,  874,   68,  866,   68,  871,   68,  867,
+      872,  879,  869,  875,   68,  877,   68,  878,   68,  876,
+      880,   68,  881,   68,   68,  883,   68,  884,   68,  882,
+      885,   68,   68,   68,   68,  889,  888,   68,  887,  891,
+
+       68,  893,   68,  894,   68,   68,  886,   68,  896,   68,
+      890,   68,   68,   68,   68,   68,  892,  898,  900,   68,
+      904,  897,   68,   68,  902,   68,  905,   68,  903,  901,
+      909,  895,  899,   68,  908,   68,  907,   68,   68,   68,
+       68,  911,   68,  906,  912,  913,   68,   68,   68,  910,
+       68,  914,   68,  915,  916,   68,  920,  919,   68,   68,
+      917,   68,  918,   68,  921,   68,  941,   68,  923,  925,
+       68,  926,   68,  924,   68,  922,  927,   68,  928,   68,
+      929,   68,  930,   68,  931,   68,   68,   68,  932,   68,
+      934,  935,   68,   68,  936,  937,  933,   68,  939,   68,
+
+       68,   68,  938,   68,   68,   68,  945,  946,   68,   68,
+       68,   68,  940,  942,  947,  943,  944,   68,   68,  953,
+       68,   68,  951,  952,  950,   68,  955,   68,   68,   68,
+      949,   68,   68,  961,   68,  948,  956,  962,   68,  954,
+       68,   68,   68,   68,  968,   68,  957,  958,  959,   68,
+      960,   68,  967,  963,   68,  971,   68,   68,   68,  964,
+       68,  965,   68,  966,  973,   68,  969,   68,  974,  976,
+       68,   68,  970,   68,   68,  977,  972,  980,  978,  979,
+      975,   68,   68,  984,   68,   68,  981,  982,   68,  983,
+      985,   68,   68,  986,   68,  988,   68,  987,   68,  991,
+
+       68,   68,   68,  989,   68,  990,  995,   68,   68,  992,
+       68,   68,   68,  996,   68,  998,  997, 1001,   68,   68,
+      993,  994, 1004,  999, 1000,   68, 1003, 1005,   68, 1006,
+       68,   68, 1002,   68, 1009, 1010,   68,   68,   68,   68,
+       68, 1011,   68,   68,   68,   68,   68, 1008, 1013, 1007,
+     1016,   68,   68,   68,   68, 1021,   68, 1012, 1024, 1015,
+     1019, 1014, 1023,   68, 1017,   68,   68,   68,   68,   68,
+     1030,   68, 1018, 1020, 1022, 1025, 1026, 1027,   68,   68,
+     1031,   68,   68, 1029, 1032, 1035,   68,   68,   68,   68,
+       68,   68,   68, 1028, 1039, 1042,   68, 1034, 1038,   68,
+
+     1033, 1044,   68, 1036, 1043,   68,   68, 1037, 1047,   68,
+       68, 1041, 1048,   68,   68,   68,   68, 1040, 1052,   68,
+     1053,   68,   68, 1056,   68, 1045, 1050,   68, 1046, 1049,
+     1057,   68, 1055, 1058,   68, 1051, 1067,   68, 1060,   68,
+       68, 1054, 1059,   68, 1061, 1062,   68,   68, 1064, 1065,
+       68,   68, 1063,   68, 1069,   68, 1066, 1068,   68, 1071,
+       68,   68, 1070,   68, 1074,   68, 1075,   68, 1076,   68,
+       68,   68, 1078,   68,   68,   68, 1072, 1079, 1081,   68,
+       68, 1073, 1077,   68, 1082,   68, 1086,   68,   73,   68,
+      122,  120,  118,  117, 1080, 1083,  115, 1084,  113,   68,
+
+     1087, 1087, 1087, 1087, 1085,   40,   40,   40,   40,   40,
+       40,   45,   45,   45,   45,   45,   45,   50,   50,   50,
+       50,   50,   50,   56,   56,   56,   56,   56,   56,   61,
+       61,   61,   61,   61,   61,   71,   71,   71,   71,   71,
+       71,  112,  112, 1087, 1087,  112,  112,  114,  114, 1087,
+      114, 1087,  114,  116, 1087, 1087, 1087, 1087,  116,  119,
+      119, 1087, 1087,  119,  119,  121, 1087, 1087, 1087, 1087,
+      121,  123,  123,  123,  123,  123,  123,   72,   72,   72,
+       72,   72,   72,   13, 1087, 1087, 1087, 1087, 1087, 1087,
+     1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087,
+
+     1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087,
+     1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087,
+     1087, 1087, 1087
     } ;
 
-static yyconst flex_int16_t yy_chk[2197] =
+static yyconst flex_int16_t yy_chk[2224] =
     {   0,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
@@ -1035,240 +1045,243 @@ static yyconst flex_int16_t yy_chk[2197] =
         5,   15,    4,    6,    6,   15,    5,    6,    9,    9,
         9,   24,   33,    6,    7,    7,    7,    7,    9,    7,
        10,   10,   10,   26,   26,    7,    8,    8,    8,    8,
-       10,    8,   26,   33,  109,   24,   25,    8,   11,   11,
-       11,   11,   11,   11, 1079,   20,  109,   20,   20,   11,
+       10,    8,   26,   33,  110,   24,   25,    8,   11,   11,
+       11,   11,   11,   11, 1093,   20,  110,   20,   20,   11,
 
        20,   25,   66,   27,   28,   20,   23,   27,   11,   12,
        12,   12,   12,   12,   12,   23,   66,   27,   23,   28,
        12,   23,   29,   30,   31,   44,   44,   29,   78,   12,
        19,   19,   19,   19,   77,   19,   22,   22,   30,   31,
        19,   19,   78,   31,   22,   32,   32,   34,   36,   35,
-       32,   22,   77,   36,   35,   38,   34,   37,   37,  159,
-       49,  159,   34,   49,   35,   34,   32,   35,   36,   38,
-       75,   39,   39,   75,   38,   37,   39,   55,   76,   55,
-       55,   76,   55,   60,   60,   63,   63,   63,   63,   65,
-       63,   65,   65,   80,   65,   68,   63,   68,   68,   69,
-
-       68,   79,   82,   69,   88,   68,   71,   71,   71,   71,
-       83,   71,   84,   81,   89,   80,   71,   71,   81,   79,
-       85,   86,   82,   88,   85,   96,   86,  463,   83,   87,
-       84,   81,   87,   90,   91,   87,   90,   92,   91,   89,
-       90,   93,   95,   94,   92,   96,   98,   97,   99,   87,
-       94,   97,  100,  101,   93,   95,  102,   99,  103,  104,
-      104,  105,  106,  107,   98,  100,  108,  110,  101,  112,
-      112,  108,  119,  119,  114,  102,  103,  114,  124,  105,
-      104,  124,  123,  106,  135,  110,  107,  116,  135,  116,
-      116,  121,  116,  121,  121,  126,  121,  122,  122,  122,
-
-      122,  125,  122,  126,  127,  128,  125,  129,  122,  130,
-      132,  132,  129,  133,  130,  134,  136,  137,  133,  127,
-      174,  136,  138,  139,  140,  128,  131,  142,  141,  140,
-      131,  137,  142,  145,  138,  131,  174,  138,  134,  144,
-      131,  139,  143,  143,  144,  152,  131,  131,  141,  153,
-      144,  146,  147,  148,  145,  149,  146,  147,  148,  150,
-      149,  151,  154,  155,  156,  152,  150,  151,  157,  156,
-      161,  153,  158,  160,  162,  162,  163,  154,  167,  164,
-      160,  163,  166,  155,  164,  165,  168,  165,  169,  161,
-      157,  168,  158,  170,  166,  171,  120,  167,  171,  163,
-
-      172,  172,  175,  169,  165,  173,  173,  176,  177,  178,
-      176,  170,  177,  179,  180,  180,  181,  175,  178,  182,
-      183,  181,  184,  185,  182,  186,  186,  179,  187,  188,
-      189,  191,  190,  189,  195,  195,  185,  193,  192,  196,
-      183,  188,  196,  184,  190,  197,  187,  192,  198,  193,
-      194,  191,  194,  194,  202,  199,  200,  200,  201,  201,
-      204,  203,  197,  198,  199,  197,  203,  205,  206,  209,
-      207,  208,  205,  210,  202,  207,  208,  206,  211,  212,
-      204,  211,  215,  216,  214,  218,  217,  210,  219,  209,
-      218,  215,  220,  212,  233,  221,  222,  211,  213,  214,
-
-      213,  213,  225,  233,  216,  217,  223,  220,  219,  226,
-      222,  223,  213,  213,  213,  221,  224,  224,  227,  224,
-      229,  228,  225,  230,  229,  226,  231,  232,  234,  235,
-      239,  239,  234,  237,  227,  228,  232,  236,  235,  237,
-      231,  230,  236,  238,  241,  240,  242,  243,  238,  232,
-      240,  244,  243,  241,  245,  245,  247,  247,  242,  248,
-      249,  250,  251,  253,  254,  255,  256,  257,  249,  254,
-      250,  256,  244,  255,  251,  258,  259,  259,  260,  262,
-      248,  261,  264,  253,  259,  257,  261,  263,  263,  265,
-      265,  261,  259,  266,  258,  268,  269,  267,  260,  262,
-
-      270,  271,  259,  277,  272,  270,  273,  264,  266,  267,
-      273,  274,  275,  278,  268,  277,  274,  280,  269,  272,
-      271,  276,  276,  279,  283,  275,  279,  539,  278,  283,
-      280,  281,  281,  282,  282,  284,  284,  285,  285,  286,
-      287,  292,  288,  289,  286,  287,  288,  290,  289,  291,
-      293,  290,  294,  539,  291,  293,  295,  296,  296,  295,
-      297,  292,  300,  118,  295,  297,  294,  298,  295,  299,
-      298,  301,  302,  299,  303,  300,  301,  302,  304,  305,
-      303,  304,  305,  306,  307,  308,  309,  310,  306,  311,
-      313,  309,  310,  313,  311,  299,  312,  315,  317,  308,
-
-      316,  318,  307,  314,  316,  312,  319,  314,  314,  320,
-      321,  321,  322,  317,  320,  323,  322,  315,  324,  318,
-      323,  319,  325,  326,  327,  328,  331,  329,  330,  332,
-      328,  327,  329,  330,  324,  333,  326,  334,  332,  339,
-      335,  325,  334,  335,  331,  336,  336,  338,  340,  333,
-      341,  344,  338,  347,  348,  349,  340,  339,  348,  351,
-      349,  352,  347,  739,  351,  341,  353,  355,  344,  350,
-      354,  354,  360,  350,  355,  357,  350,  356,  356,  352,
-      739,  350,  358,  358,  363,  361,  359,  350,  350,  359,
-      357,  353,  360,  361,  362,  362,  364,  365,  365,  363,
-
-      366,  364,  367,  366,  368,  369,  370,  376,  367,  371,
-      372,  380,  368,  369,  371,  373,  373,  372,  374,  375,
-      380,  376,  375,  374,  370,  377,  377,  378,  381,  382,
-      378,  383,  381,  384,  387,  385,  386,  389,  378,  387,
-      383,  385,  388,  390,  391,  392,  388,  384,  382,  391,
-      386,  393,  393,  395,  394,  390,  389,  394,  397,  396,
-      398,  398,  399,  399,  400,  401,  392,  403,  404,  411,
-      405,  395,  396,  406,  407,  408,  117,  410,  397,  400,
-      408,  411,  413,  404,  405,  412,  412,  413,  407,  401,
-      402,  410,  403,  402,  406,  402,  409,  409,  415,  402,
-
-      414,  402,  416,  426,  409,  421,  402,  422,  414,  417,
-      417,  419,  415,  423,  420,  427,  419,  420,  423,  424,
-      422,  416,  409,  426,  421,  425,  428,  430,  424,  427,
-      425,  428,  431,  432,  433,  434,  439,  431,  432,  433,
-      435,  435,  430,  436,  434,  438,  438,  440,  436,  438,
-      441,  439,  442,  441,  443,  444,  445,  442,  444,  443,
-      446,  448,  447,  449,  454,  451,  448,  440,  449,  450,
-      455,  455,  450,  452,  445,  447,  451,  453,  452,  454,
-      446,  456,  453,  457,  458,  459,  460,  461,  458,  465,
-      464,  466,  467,  468,  465,  460,  466,  457,  470,  472,
-
-      456,  471,  471,  459,  464,  469,  467,  468,  475,  473,
-      469,  474,  461,  470,  476,  477,  474,  472,  473,  477,
-      478,  479,  480,  481,  482,  483,  485,  475,  484,  486,
-      490,  483,  489,  476,  488,  478,  479,  601,  486,  601,
-      489,  480,  482,  484,  481,  493,  485,  491,  488,  492,
-      490,  494,  491,  492,  492,  498,  494,  496,  493,  495,
-      495,  499,  496,  497,  497,  500,  501,  502,  507,  498,
-      500,  501,  502,  503,  504,  508,  505,  503,  506,  499,
-      505,  509,  507,  504,  510,  511,  512,  517,  504,  509,
-      504,  520,  504,  506,  508,  513,  513,  514,  514,  515,
-
-      516,  516,  510,  518,  515,  512,  521,  517,  519,  520,
-      511,  518,  521,  519,  522,  524,  527,  525,  526,  528,
-      524,  522,  525,  526,  530,  527,  529,  529,  531,  532,
-      533,  533,  534,  535,  541,  536,  538,  540,  528,  541,
-      538,  538,  542,  545,  530,  543,  544,  532,  531,  543,
-      546,  547,  534,  536,  548,  540,  547,  545,  535,  549,
-      550,  548,  542,  551,  549,  544,  552,  553,  554,  546,
-      555,  556,  551,  554,  560,  555,  556,  559,  550,  557,
-      557,  552,  559,  562,  562,  561,  563,  565,  553,  561,
-      561,  564,  565,  560,  566,  567,  568,  564,  569,  571,
-
-      573,  573,  570,  572,  574,  563,  575,  576,  574,  577,
-      577,  579,  588,  566,  567,  568,  570,  569,  572,  575,
-      571,  578,  586,  580,  581,  586,  578,  576,  580,  581,
-      587,  579,  584,  584,  589,  590,  592,  588,  594,  589,
-      591,  591,  593,  593,  595,  587,  596,  599,  595,  594,
-      590,  598,  600,  602,  603,  604,  592,  605,  602,  603,
-      608,  607,  611,  605,  612,  596,  607,  599,  609,  598,
-      618,  609,  600,  610,  610,  604,  613,  614,  615,  615,
-      611,  613,  614,  616,  612,  608,  617,  619,  616,  620,
-      618,  622,  621,  623,  624,  625,  622,  626,  741,  627,
-
-      741,  628,  633,  620,  617,  621,  631,  619,  627,  631,
-      632,  627,  626,  623,  624,  634,  625,  628,  636,  632,
-      635,  633,  638,  636,  634,  637,  637,  634,  639,  635,
-      640,  641,  642,  643,  643,  644,  652,  653,  646,  647,
-      648,  639,  638,  646,  647,  641,  648,  651,  640,  649,
-      642,  654,  649,  644,  652,  651,  653,  655,  649,  657,
-      658,  659,  661,  660,  658,  662,  659,  654,  660,  663,
-      665,  661,  664,  666,  669,  655,  672,  664,  667,  657,
-      662,  663,  665,  669,  667,  668,  668,  670,  670,  671,
-      673,  666,  674,  674,  671,  675,  675,  672,  676,  676,
-
-      677,  679,  680,  677,  681,  682,  679,  683,  683,  681,
-      673,  684,  685,  686,  687,  688,  684,  689,  690,  692,
-      680,  691,  691,  693,  685,  696,  685,  698,  695,  694,
-      682,  685,  693,  686,  687,  688,  694,  695,  689,  692,
-      697,  697,  699,  701,  690,  702,  703,  704,  701,  708,
-      702,  696,  705,  698,  704,  706,  707,  705,  699,  709,
-      710,  711,  712,  720,  706,  709,  703,  713,  708,  710,
-      714,  707,  713,  715,  714,  714,  712,  716,  715,  717,
-      718,  719,  711,  722,  717,  719,  721,  723,  720,  716,
-      725,  721,  718,  724,  724,  726,  725,  727,  728,  723,
-
-      726,  730,  734,  727,  733,  722,  744,  728,  732,  732,
-      738,  734,  746,  730,  750,  738,  740,  740,  742,  742,
-      732,  751,  733,  745,  745,  747,  744,  748,  749,  750,
-      752,  754,  753,  746,  753,  752,  755,  747,  757,  748,
-      749,  751,  756,  756,  762,  755,  758,  760,  759,  754,
-      759,  758,  760,  761,  763,  764,  765,  766,  761,  767,
-      764,  765,  762,  768,  757,  773,  774,  771,  769,  770,
-      772,  778,  115,  767,  763,  768,  766,  769,  770,  771,
-      769,  775,  774,  772,  777,  773,  779,  775,  780,  780,
-      777,  781,  782,  783,  784,  779,  778,  783,  787,  784,
-
-      781,  785,  785,  788,  788,  789,  789,  787,  790,  791,
-      793,  782,  792,  794,  791,  795,  792,  796,  794,  797,
-      790,  798,  799,  801,  802,  793,  801,  113,  803,  804,
-      804,  805,  805,  798,  795,  807,  796,  802,  806,  806,
-      797,  803,  810,  799,  808,  808,  809,  809,  807,  811,
-      811,  812,  812,  814,  815,  815,  816,  819,  814,  817,
-      817,  810,  818,  819,  820,  821,  821,  820,  822,  822,
-      823,  824,  824,  825,  825,  816,  826,  827,  827,  828,
-      818,  821,  829,  830,  832,  831,  833,  829,  834,  823,
-      831,  828,  836,  835,  838,  833,  836,  834,  835,  832,
-
-      839,  843,  826,  841,  830,  840,  840,  845,  841,  839,
-      845,  846,  851,  843,  838,  848,  846,  847,  847,  848,
-      849,  850,  850,  849,  852,  853,  854,  855,  858,  856,
-      853,  854,  851,  855,  857,  859,  858,  859,  874,  857,
-      862,  862,  865,  865,  852,  856,  868,  868,  870,  870,
-      872,  873,  873,  875,  874,  872,  876,  878,  878,  881,
-      882,  876,  882,  883,  881,  884,  884,  885,  883,  886,
-      887,  888,  889,  890,  893,  875,  891,  891,  894,  885,
-      892,  895,  887,  888,  889,  896,  897,  886,  900,  892,
-      896,  897,  904,  890,  895,  898,  898,  905,  894,  903,
-
-      893,  901,  901,  906,  907,  910,  900,  911,  903,  909,
-      904,  908,  908,  912,  909,  905,  916,  919,  917,  906,
-      910,  917,  920,  907,  918,  918,  911,  922,  922,  923,
-      924,  924,  919,  912,  926,  926,  916,  927,  928,  929,
-      920,  930,  931,  933,  929,  936,  930,  928,  923,  934,
-      931,  935,  937,  937,  934,  941,  935,  948,  933,  927,
-      936,  938,  938,  940,  943,  944,  942,  941,  940,  942,
-      945,  945,  946,  943,  944,  949,  948,  950,  950,  951,
-      953,  946,  952,  955,  956,  953,  958,  958,  951,  960,
-      952,  966,  955,  965,  949,  961,  961,  956,  962,  963,
-
-      963,  962,  964,  964,  969,  966,  972,  967,  969,  960,
-      973,  965,  967,  968,  968,  974,  975,  976,  973,  977,
-      978,  979,  976,  980,  982,  972,  983,  982,  984,  984,
-      979,  985,  975,  986,  974,  985,  988,  989,  990,  977,
-      994,  994,  986,  980,  983,  988,  978,  993,  995,  989,
-      997,  998,  993,  999, 1002,  997, 1001,  995, 1000, 1000,
-     1004, 1003, 1005,  990, 1006, 1004, 1007, 1007,  999, 1003,
-      998, 1008, 1001, 1002, 1010, 1010, 1008, 1011, 1012, 1013,
-     1013, 1014, 1014, 1006, 1015, 1017, 1016, 1020, 1005, 1018,
-     1018, 1019, 1019,  111, 1022, 1023, 1023, 1011, 1016, 1022,
-
-     1012, 1024, 1024, 1015, 1026, 1017, 1020, 1025, 1025, 1026,
-     1027, 1027, 1029, 1029, 1031, 1031, 1032, 1035, 1036, 1036,
-     1040, 1032, 1037, 1050, 1041, 1035, 1052, 1037, 1041, 1045,
-     1045, 1047, 1049, 1049, 1064, 1047, 1053, 1053, 1050, 1058,
-     1040, 1054, 1054, 1066, 1052, 1056, 1056, 1059, 1059, 1063,
-     1068, 1058, 1066, 1063, 1064, 1065, 1065, 1069, 1070, 1071,
-     1071,   74,   72,   70,   67, 1068,   61,   56,   51,   50,
-       45, 1069,   40,   14,   13,    0,    0, 1070, 1074, 1074,
-     1074, 1074, 1074, 1074, 1075, 1075, 1075, 1075, 1075, 1075,
-     1076, 1076, 1076, 1076, 1076, 1076, 1077, 1077, 1077, 1077,
-
-     1077, 1077, 1078, 1078, 1078, 1078, 1078, 1078, 1080, 1080,
-     1080, 1080, 1080, 1080, 1081, 1081,    0,    0, 1081, 1081,
-     1082, 1082,    0, 1082,    0, 1082, 1083,    0,    0,    0,
-        0, 1083, 1084, 1084,    0,    0, 1084, 1084, 1085,    0,
-        0,    0,    0, 1085, 1086, 1086, 1086, 1086, 1086, 1086,
-     1087, 1087, 1087, 1087, 1087, 1087, 1073, 1073, 1073, 1073,
-     1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073,
-     1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073,
-     1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073,
-     1073, 1073, 1073, 1073, 1073, 1073
-
+       32,   22,   77,   36,   35,   38,   34,   37,   37,   89,
+       49,   79,   34,   49,   35,   34,   32,   35,   36,   38,
+       60,   60,   34,   86,   38,   37,   39,   39,   86,   79,
+       55,   39,   55,   55,   89,   55,   63,   63,   63,   63,
+       65,   63,   65,   65,   80,   65,   68,   63,   68,   68,
+
+       69,   68,   75,   82,   69,   75,   68,   71,   71,   71,
+       71,   76,   71,   83,   76,   81,   80,   71,   71,   84,
+       81,   85,   88,   82,   87,   85,   93,   87,   92,   90,
+       87,   83,   90,   81,   91,   92,   90,   84,   91,   93,
+       94,   88,   95,   96,   87,   97,   98,   94,   99,   97,
+      100,  102,  101,  103,  107,   95,  104,   99,  105,  105,
+      106,  108,  109,   96,   98,  101,  102,  109,  111,  136,
+      100,  471,  103,  136,  104,  107,  113,  113,  106,  105,
+      115,  120,  120,  115,  108,  117,  111,  117,  117,  122,
+      117,  122,  122,  127,  122,  123,  123,  123,  123,  125,
+
+      123,  127,  125,  126,  128,  129,  123,  130,  126,  131,
+      133,  133,  130,  134,  131,  135,  137,  138,  134,  128,
+      176,  137,  139,  140,  141,  129,  132,  143,  142,  141,
+      132,  138,  143,  146,  139,  132,  176,  139,  135,  145,
+      132,  140,  144,  144,  145,  153,  132,  132,  142,  154,
+      145,  147,  148,  149,  146,  150,  147,  148,  149,  151,
+      150,  152,  155,  156,  157,  153,  151,  152,  158,  159,
+      155,  154,  160,  158,  161,  162,  161,  163,  156,  164,
+      164,  165,  162,  166,  157,  168,  165,  167,  166,  167,
+      169,  159,  160,  170,  172,  171,  163,  168,  170,  173,
+
+      174,  174,  173,  177,  165,  181,  167,  175,  175,  169,
+      171,  178,  172,  179,  178,  180,  185,  179,  177,  181,
+      182,  182,  183,  184,  180,  186,  187,  183,  184,  188,
+      188,  189,  190,  192,  191,  193,  185,  191,  194,  187,
+      195,  197,  197,  199,  190,  192,  186,  194,  196,  189,
+      196,  196,  195,  198,  200,  193,  198,  201,  202,  202,
+      199,  203,  203,  199,  204,  205,  201,  206,  207,  200,
+      208,  209,  206,  210,  212,  208,  211,  213,  210,  204,
+      209,  211,  215,  214,  217,  205,  214,  219,  207,  218,
+      220,  213,  221,  222,  212,  223,  215,  221,  218,  217,
+
+      224,  225,  214,  216,  124,  216,  216,  226,  219,  220,
+      223,  228,  226,  222,  229,  225,  230,  216,  216,  216,
+      224,  227,  227,  231,  227,  232,  233,  234,  245,  232,
+      229,  228,  230,  235,  236,  237,  238,  231,  121,  237,
+      245,  234,  235,  236,  233,  238,  239,  240,  247,  241,
+      244,  239,  251,  240,  241,  235,  242,  242,  243,  244,
+      246,  248,  248,  243,  252,  246,  250,  250,  253,  247,
+      254,  256,  252,  251,  257,  258,  259,  253,  260,  261,
+      258,  262,  254,  260,  259,  263,  263,  264,  257,  265,
+      266,  256,  268,  263,  265,  267,  267,  261,  270,  265,
+
+      262,  263,  269,  269,  271,  272,  273,  264,  275,  274,
+      266,  263,  119,  270,  274,  276,  271,  268,  277,  279,
+      278,  282,  277,  281,  272,  278,  283,  275,  273,  283,
+      276,  284,  279,  280,  280,  281,  282,  285,  285,  286,
+      286,  287,  288,  288,  284,  290,  287,  289,  289,  291,
+      290,  292,  293,  295,  291,  292,  294,  293,  295,  296,
+      294,  297,  298,  300,  300,  299,  297,  301,  299,  311,
+      304,  302,  301,  299,  302,  305,  298,  299,  303,  296,
+      305,  306,  303,  304,  307,  308,  306,  311,  308,  309,
+      307,  310,  309,  312,  313,  314,  310,  315,  316,  313,
+
+      314,  315,  315,  316,  303,  317,  318,  312,  319,  318,
+      320,  321,  319,  319,  317,  321,  322,  323,  324,  325,
+      326,  326,  327,  328,  325,  329,  327,  330,  328,  331,
+      320,  322,  332,  324,  336,  323,  338,  118,  333,  332,
+      334,  329,  331,  333,  335,  334,  330,  337,  339,  335,
+      338,  340,  336,  339,  340,  343,  337,  341,  341,  344,
+      343,  345,  349,  346,  352,  357,  353,  354,  358,  345,
+      353,  356,  354,  352,  359,  359,  356,  344,  346,  349,
+      355,  360,  362,  357,  355,  361,  361,  355,  360,  363,
+      363,  364,  355,  358,  364,  365,  366,  362,  355,  355,
+
+      367,  367,  368,  369,  366,  370,  370,  371,  369,  375,
+      371,  373,  372,  374,  380,  365,  377,  368,  372,  373,
+      376,  374,  383,  377,  116,  376,  379,  375,  378,  378,
+      389,  379,  382,  380,  387,  382,  383,  384,  384,  385,
+      388,  391,  385,  387,  388,  390,  392,  393,  394,  389,
+      385,  396,  392,  394,  390,  391,  395,  397,  398,  399,
+      395,  393,  403,  398,  400,  400,  402,  404,  401,  397,
+      396,  401,  405,  405,  407,  403,  406,  406,  408,  410,
+      399,  411,  418,  412,  402,  414,  413,  404,  415,  407,
+      416,  416,  114,  415,  418,  417,  411,  412,  416,  414,
+
+      419,  419,  408,  409,  410,  420,  409,  413,  409,  417,
+      420,  422,  409,  421,  409,  423,  416,  424,  424,  409,
+      427,  421,  426,  427,  428,  422,  429,  426,  430,  431,
+      432,  433,  434,  430,  423,  432,  435,  437,  431,  429,
+      438,  435,  439,  428,  440,  438,  434,  439,  441,  440,
+      443,  433,  437,  442,  442,  443,  447,  441,  445,  445,
+      446,  448,  445,  446,  449,  450,  452,  449,  451,  452,
+      450,  447,  453,  451,  454,  455,  458,  456,  457,  458,
+      459,  448,  456,  457,  460,  462,  464,  461,  455,  460,
+      453,  459,  461,  465,  454,  463,  463,  466,  467,  468,
+
+      462,  466,  469,  472,  473,  464,  474,  465,  468,  473,
+      475,  474,  476,  477,  478,  480,  467,  472,  477,  479,
+      479,  481,  483,  482,  475,  484,  476,  469,  482,  478,
+      481,  485,  486,  480,  487,  485,  488,  489,  490,  491,
+      493,  483,  492,  494,  484,  491,  497,  486,  496,  487,
+      498,  611,  494,  611,  497,  488,  490,  492,  489,  499,
+      493,  500,  496,  501,  499,  500,  500,  502,  503,  503,
+      498,  506,  502,  504,  505,  505,  501,  507,  504,  508,
+      512,  509,  510,  515,  508,  506,  509,  510,  511,  512,
+      514,  517,  511,  513,  512,  507,  512,  513,  512,  516,
+
+      518,  515,  519,  520,  521,  514,  522,  522,  518,  524,
+      517,  523,  523,  516,  524,  525,  525,  526,  527,  528,
+      519,  529,  531,  521,  528,  530,  527,  533,  520,  531,
+      534,  530,  533,  535,  536,  534,  537,  526,  535,  529,
+      538,  538,  539,  536,  540,  541,  542,  542,  543,  544,
+      548,  545,  547,  549,  550,  537,  547,  547,  551,  550,
+      553,  552,  539,  541,  540,  552,  554,  555,  543,  545,
+      556,  549,  559,  561,  544,  556,  548,  557,  551,  553,
+      554,  562,  558,  560,  557,  569,  555,  558,  561,  563,
+      559,  564,  560,  565,  563,  572,  564,  575,  565,  566,
+
+      566,  568,  562,  570,  569,  573,  568,  570,  570,  571,
+      571,  573,  574,  576,  572,  577,  575,  574,  578,  579,
+      580,  581,  582,  582,  583,  584,  585,  586,  583,  587,
+      587,  589,  576,  579,  577,  585,  581,  578,  584,  588,
+      590,  580,  597,  591,  588,  590,  598,  586,  591,  594,
+      594,  589,  596,  599,  600,  596,  602,  597,  599,  601,
+      601,  603,  603,  604,  605,  606,  609,  608,  605,  600,
+      610,  598,  612,  613,  604,  614,  602,  612,  613,  618,
+      621,  615,  622,  617,  606,  608,  609,  615,  617,  619,
+      610,  623,  619,  620,  620,  614,  623,  627,  621,  628,
+
+      624,  629,  622,  626,  618,  624,  625,  625,  626,  630,
+      633,  631,  632,  634,  635,  627,  636,  632,  638,  628,
+      637,  629,  641,  630,  631,  641,  643,  642,  644,  637,
+      633,  636,  637,  634,  638,  635,  642,  644,  645,  646,
+      644,  647,  647,  648,  646,  643,  649,  645,  650,  652,
+      651,  653,  653,  654,  655,  657,  658,  662,  663,  649,
+      657,  658,  659,  648,  651,  662,  650,  652,  659,  654,
+      660,  664,  655,  660,  666,  665,  663,  668,  669,  660,
+      670,  671,  669,  673,  672,  670,  671,  674,  676,  675,
+      664,  665,  666,  672,  675,  677,  678,  668,  673,  674,
+
+      676,  680,  678,  679,  679,  681,  681,  682,  683,  691,
+      680,  684,  682,  677,  685,  685,  686,  686,  687,  687,
+      688,  690,  693,  688,  696,  692,  690,  691,  697,  683,
+      692,  684,  694,  694,  695,  698,  696,  699,  696,  695,
+      700,  701,  703,  696,  702,  702,  705,  693,  697,  704,
+      706,  707,  709,  705,  710,  698,  714,  699,  704,  706,
+      712,  700,  703,  708,  708,  712,  713,  701,  715,  716,
+      710,  713,  717,  718,  716,  715,  714,  707,  709,  719,
+      720,  717,  721,  722,  723,  725,  724,  732,  721,  728,
+      725,  726,  722,  718,  719,  726,  726,  727,  729,  720,
+
+      724,  728,  727,  729,  730,  723,  731,  734,  733,  735,
+      731,  737,  732,  733,  736,  736,  730,  737,  738,  739,
+      742,  735,  740,  738,  745,  739,  744,  744,  746,  734,
+      750,  740,  742,  751,  753,  750,  753,  746,  744,  752,
+      752,  756,  745,  754,  754,  757,  757,  758,  759,  766,
+      751,  760,  761,  763,  762,  769,  765,  764,  765,  112,
+      759,  756,  764,  760,  761,  767,  775,  766,  758,  762,
+      768,  768,  770,  763,  767,  772,  771,  770,  771,  773,
+      772,  769,  774,  776,  773,  777,  775,  778,  776,  779,
+      777,  780,  780,  781,  786,  782,  787,  784,  785,  783,
+
+      774,  791,  795,  779,  782,  781,  778,  782,  783,  784,
+      788,  785,  787,  790,  786,  792,  788,  793,  793,  790,
+      794,  795,   74,  796,  792,  797,  791,  796,  800,  794,
+      797,  798,  798,  801,  801,  802,  802,  800,  803,  804,
+      806,  805,  807,  808,  804,  805,  809,  807,  810,  811,
+      803,  812,  823,  814,  815,  806,  814,  816,  817,  817,
+       72,  811,  808,  818,  818,  809,  820,  815,  829,  810,
+      816,  823,  812,  819,  819,  821,  821,  822,  822,  820,
+      824,  824,  825,  825,  827,  828,  828,  829,  831,  827,
+      830,  830,  832,  833,  834,  834,  833,  836,  832,  835,
+
+      835,  837,  837,  839,  839,  840,  831,  841,  841,  842,
+      834,  844,  843,  845,  846,  847,  836,  843,  845,  848,
+      849,  842,  850,  852,  847,  849,  850,  853,  848,  846,
+      855,  840,  844,  854,  854,  855,  853,  857,  859,  860,
+      865,  859,  866,  852,  860,  861,  861,  862,  900,  857,
+      863,  862,  867,  863,  864,  864,  868,  867,  869,  870,
+      865,  868,  866,  871,  869,  872,  900,  873,  871,  873,
+      876,  876,  888,  872,  889,  870,  879,  879,  882,  882,
+      884,  884,  886,  887,  887,  890,  904,  886,  888,  895,
+      890,  892,  892,  896,  895,  896,  889,  897,  898,  898,
+
+      899,  901,  897,  902,  903,  906,  904,  905,  905,  907,
+      908,  909,  899,  901,  906,  902,  903,  910,  911,  912,
+      912,  914,  910,  911,  909,  915,  915,  917,  918,  919,
+      908,  921,  920,  922,  922,  907,  917,  923,  924,  914,
+      925,  926,  923,  930,  932,  932,  918,  919,  920,  931,
+      921,  933,  931,  924,  934,  936,  936,  937,  941,  925,
+      942,  926,  947,  930,  938,  938,  933,  940,  940,  942,
+      943,  945,  934,  944,  950,  943,  937,  947,  944,  945,
+      941,  948,  949,  951,  951,  955,  948,  949,  954,  950,
+      952,  952,  956,  954,  957,  956,  958,  955,  959,  959,
+
+      960,  962,  963,  957,  965,  958,  964,  964,  966,  960,
+      967,  970,  974,  965,  969,  967,  966,  972,  972,  976,
+      962,  963,  976,  969,  970,  975,  975,  977,  977,  978,
+      978,  979,  974,  980,  981,  982,  982,  983,  986,  981,
+      987,  983,  988,  989,  991,  990,  992,  980,  987,  979,
+      990,  993,  996,  994,  999,  996,  997,  986,  999,  989,
+      993,  988,  998,  998,  991, 1003, 1000, 1002, 1004, 1008,
+     1008, 1009,  992,  994,  997, 1000, 1002, 1003, 1007, 1011,
+     1009, 1012, 1013, 1007, 1011, 1014, 1014, 1015, 1016, 1018,
+     1017, 1019, 1020, 1004, 1018, 1021, 1021, 1013, 1017, 1022,
+
+     1012, 1024, 1024, 1015, 1022, 1025, 1026, 1016, 1027, 1027,
+     1029, 1020, 1028, 1028, 1030, 1031, 1054, 1019, 1032, 1032,
+     1033, 1033, 1034, 1037, 1037, 1025, 1030, 1036, 1026, 1029,
+     1038, 1038, 1036, 1039, 1039, 1031, 1054, 1040, 1041, 1041,
+     1049, 1034, 1040, 1043, 1043, 1045, 1045, 1046, 1049, 1050,
+     1050, 1051, 1046, 1055, 1059, 1059, 1051, 1055, 1061, 1063,
+     1063, 1064, 1061, 1066, 1067, 1067, 1068, 1068, 1070, 1070,
+     1072, 1073, 1073, 1077, 1078, 1080, 1064, 1077, 1079, 1079,
+     1082, 1066, 1072, 1083, 1080, 1084, 1085, 1085,   70,   67,
+       61,   56,   51,   50, 1078, 1082,   45, 1083,   40,   14,
+
+       13,    0,    0,    0, 1084, 1088, 1088, 1088, 1088, 1088,
+     1088, 1089, 1089, 1089, 1089, 1089, 1089, 1090, 1090, 1090,
+     1090, 1090, 1090, 1091, 1091, 1091, 1091, 1091, 1091, 1092,
+     1092, 1092, 1092, 1092, 1092, 1094, 1094, 1094, 1094, 1094,
+     1094, 1095, 1095,    0,    0, 1095, 1095, 1096, 1096,    0,
+     1096,    0, 1096, 1097,    0,    0,    0,    0, 1097, 1098,
+     1098,    0,    0, 1098, 1098, 1099,    0,    0,    0,    0,
+     1099, 1100, 1100, 1100, 1100, 1100, 1100, 1101, 1101, 1101,
+     1101, 1101, 1101, 1087, 1087, 1087, 1087, 1087, 1087, 1087,
+     1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087,
+
+     1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087,
+     1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087,
+     1087, 1087, 1087
     } ;
 
 static yy_state_type yy_last_accepting_state;
@@ -1392,7 +1405,7 @@ static void config_end_include(void)
 #define YY_NO_INPUT 1
 #endif
 
-#line 1394 "<stdout>"
+#line 1407 "<stdout>"
 
 #define INITIAL 0
 #define quotedstring 1
@@ -1579,7 +1592,7 @@ YY_DECL
     
 #line 120 "util/configlexer.lex"
 
-#line 1581 "<stdout>"
+#line 1594 "<stdout>"
 
        if ( !(yy_init) )
                {
@@ -1638,13 +1651,13 @@ yy_match:
                        while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
                                {
                                yy_current_state = (int) yy_def[yy_current_state];
-                               if ( yy_current_state >= 1074 )
+                               if ( yy_current_state >= 1088 )
                                        yy_c = yy_meta[(unsigned int) yy_c];
                                }
                        yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
                        ++yy_cp;
                        }
-               while ( yy_base[yy_current_state] != 2157 );
+               while ( yy_base[yy_current_state] != 2184 );
 
 yy_find_action:
                yy_act = yy_accept[yy_current_state];
@@ -2142,43 +2155,53 @@ YY_RULE_SETUP
 case 94:
 YY_RULE_SETUP
 #line 217 "util/configlexer.lex"
-{ YDVAR(1, VAR_DOMAIN_INSECURE) }
+{ YDVAR(1, VAR_PYTHON_SCRIPT) }
        YY_BREAK
 case 95:
-/* rule 95 can match eol */
 YY_RULE_SETUP
 #line 218 "util/configlexer.lex"
+{ YDVAR(0, VAR_PYTHON) }
+       YY_BREAK
+case 96:
+YY_RULE_SETUP
+#line 219 "util/configlexer.lex"
+{ YDVAR(1, VAR_DOMAIN_INSECURE) }
+       YY_BREAK
+case 97:
+/* rule 97 can match eol */
+YY_RULE_SETUP
+#line 220 "util/configlexer.lex"
 { LEXOUT(("NL\n")); cfg_parser->line++; }
        YY_BREAK
 /* Quoted strings. Strip leading and ending quotes */
-case 96:
+case 98:
 YY_RULE_SETUP
-#line 221 "util/configlexer.lex"
+#line 223 "util/configlexer.lex"
 { BEGIN(quotedstring); LEXOUT(("QS ")); }
        YY_BREAK
 case YY_STATE_EOF(quotedstring):
-#line 222 "util/configlexer.lex"
+#line 224 "util/configlexer.lex"
 {
         yyerror("EOF inside quoted string");
        if(--num_args == 0) { BEGIN(INITIAL); }
        else                { BEGIN(val); }
 }
        YY_BREAK
-case 97:
+case 99:
 YY_RULE_SETUP
-#line 227 "util/configlexer.lex"
+#line 229 "util/configlexer.lex"
 { LEXOUT(("STR(%s) ", yytext)); yymore(); }
        YY_BREAK
-case 98:
-/* rule 98 can match eol */
+case 100:
+/* rule 100 can match eol */
 YY_RULE_SETUP
-#line 228 "util/configlexer.lex"
+#line 230 "util/configlexer.lex"
 { yyerror("newline inside quoted string, no end \""); 
                          cfg_parser->line++; BEGIN(INITIAL); }
        YY_BREAK
-case 99:
+case 101:
 YY_RULE_SETUP
-#line 230 "util/configlexer.lex"
+#line 232 "util/configlexer.lex"
 {
         LEXOUT(("QE "));
        if(--num_args == 0) { BEGIN(INITIAL); }
@@ -2191,34 +2214,34 @@ YY_RULE_SETUP
 }
        YY_BREAK
 /* Single Quoted strings. Strip leading and ending quotes */
-case 100:
+case 102:
 YY_RULE_SETUP
-#line 242 "util/configlexer.lex"
+#line 244 "util/configlexer.lex"
 { BEGIN(singlequotedstr); LEXOUT(("SQS ")); }
        YY_BREAK
 case YY_STATE_EOF(singlequotedstr):
-#line 243 "util/configlexer.lex"
+#line 245 "util/configlexer.lex"
 {
         yyerror("EOF inside quoted string");
        if(--num_args == 0) { BEGIN(INITIAL); }
        else                { BEGIN(val); }
 }
        YY_BREAK
-case 101:
+case 103:
 YY_RULE_SETUP
-#line 248 "util/configlexer.lex"
+#line 250 "util/configlexer.lex"
 { LEXOUT(("STR(%s) ", yytext)); yymore(); }
        YY_BREAK
-case 102:
-/* rule 102 can match eol */
+case 104:
+/* rule 104 can match eol */
 YY_RULE_SETUP
-#line 249 "util/configlexer.lex"
+#line 251 "util/configlexer.lex"
 { yyerror("newline inside quoted string, no end '"); 
                             cfg_parser->line++; BEGIN(INITIAL); }
        YY_BREAK
-case 103:
+case 105:
 YY_RULE_SETUP
-#line 251 "util/configlexer.lex"
+#line 253 "util/configlexer.lex"
 {
         LEXOUT(("SQE "));
        if(--num_args == 0) { BEGIN(INITIAL); }
@@ -2231,38 +2254,38 @@ YY_RULE_SETUP
 }
        YY_BREAK
 /* include: directive */
-case 104:
+case 106:
 YY_RULE_SETUP
-#line 263 "util/configlexer.lex"
+#line 265 "util/configlexer.lex"
 { 
        LEXOUT(("v(%s) ", yytext)); inc_prev = YYSTATE; BEGIN(include); }
        YY_BREAK
 case YY_STATE_EOF(include):
-#line 265 "util/configlexer.lex"
+#line 267 "util/configlexer.lex"
 {
         yyerror("EOF inside include directive");
         BEGIN(inc_prev);
 }
        YY_BREAK
-case 105:
+case 107:
 YY_RULE_SETUP
-#line 269 "util/configlexer.lex"
+#line 271 "util/configlexer.lex"
 { LEXOUT(("ISP ")); /* ignore */ }
        YY_BREAK
-case 106:
-/* rule 106 can match eol */
+case 108:
+/* rule 108 can match eol */
 YY_RULE_SETUP
-#line 270 "util/configlexer.lex"
+#line 272 "util/configlexer.lex"
 { LEXOUT(("NL\n")); cfg_parser->line++;}
        YY_BREAK
-case 107:
+case 109:
 YY_RULE_SETUP
-#line 271 "util/configlexer.lex"
+#line 273 "util/configlexer.lex"
 { LEXOUT(("IQS ")); BEGIN(include_quoted); }
        YY_BREAK
-case 108:
+case 110:
 YY_RULE_SETUP
-#line 272 "util/configlexer.lex"
+#line 274 "util/configlexer.lex"
 {
        LEXOUT(("Iunquotedstr(%s) ", yytext));
        config_start_include(yytext);
@@ -2270,27 +2293,27 @@ YY_RULE_SETUP
 }
        YY_BREAK
 case YY_STATE_EOF(include_quoted):
-#line 277 "util/configlexer.lex"
+#line 279 "util/configlexer.lex"
 {
         yyerror("EOF inside quoted string");
         BEGIN(inc_prev);
 }
        YY_BREAK
-case 109:
+case 111:
 YY_RULE_SETUP
-#line 281 "util/configlexer.lex"
+#line 283 "util/configlexer.lex"
 { LEXOUT(("ISTR(%s) ", yytext)); yymore(); }
        YY_BREAK
-case 110:
-/* rule 110 can match eol */
+case 112:
+/* rule 112 can match eol */
 YY_RULE_SETUP
-#line 282 "util/configlexer.lex"
+#line 284 "util/configlexer.lex"
 { yyerror("newline before \" in include name"); 
                                  cfg_parser->line++; BEGIN(inc_prev); }
        YY_BREAK
-case 111:
+case 113:
 YY_RULE_SETUP
-#line 284 "util/configlexer.lex"
+#line 286 "util/configlexer.lex"
 {
        LEXOUT(("IQE "));
        yytext[yyleng - 1] = '\0';
@@ -2300,7 +2323,7 @@ YY_RULE_SETUP
        YY_BREAK
 case YY_STATE_EOF(INITIAL):
 case YY_STATE_EOF(val):
-#line 290 "util/configlexer.lex"
+#line 292 "util/configlexer.lex"
 {
        yy_set_bol(1); /* Set beginning of line, so "^" rules match.  */
        if (config_include_stack_ptr == 0) {
@@ -2311,33 +2334,33 @@ case YY_STATE_EOF(val):
        }
 }
        YY_BREAK
-case 112:
+case 114:
 YY_RULE_SETUP
-#line 300 "util/configlexer.lex"
+#line 302 "util/configlexer.lex"
 { LEXOUT(("unquotedstr(%s) ", yytext)); 
                        if(--num_args == 0) { BEGIN(INITIAL); }
                        yylval.str = strdup(yytext); return STRING; }
        YY_BREAK
-case 113:
+case 115:
 YY_RULE_SETUP
-#line 304 "util/configlexer.lex"
+#line 306 "util/configlexer.lex"
 {
        ub_c_error_msg("unknown keyword '%s'", yytext);
        }
        YY_BREAK
-case 114:
+case 116:
 YY_RULE_SETUP
-#line 308 "util/configlexer.lex"
+#line 310 "util/configlexer.lex"
 {
        ub_c_error_msg("stray '%s'", yytext);
        }
        YY_BREAK
-case 115:
+case 117:
 YY_RULE_SETUP
-#line 312 "util/configlexer.lex"
+#line 314 "util/configlexer.lex"
 ECHO;
        YY_BREAK
-#line 2339 "<stdout>"
+#line 2362 "<stdout>"
 
        case YY_END_OF_BUFFER:
                {
@@ -2627,7 +2650,7 @@ static int yy_get_next_buffer (void)
                while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
                        {
                        yy_current_state = (int) yy_def[yy_current_state];
-                       if ( yy_current_state >= 1074 )
+                       if ( yy_current_state >= 1088 )
                                yy_c = yy_meta[(unsigned int) yy_c];
                        }
                yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
@@ -2655,11 +2678,11 @@ static int yy_get_next_buffer (void)
        while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
                {
                yy_current_state = (int) yy_def[yy_current_state];
-               if ( yy_current_state >= 1074 )
+               if ( yy_current_state >= 1088 )
                        yy_c = yy_meta[(unsigned int) yy_c];
                }
        yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-       yy_is_jam = (yy_current_state == 1073);
+       yy_is_jam = (yy_current_state == 1087);
 
        return yy_is_jam ? 0 : yy_current_state;
 }
@@ -3296,7 +3319,7 @@ void yyfree (void * ptr )
 
 #define YYTABLES_NAME "yytables"
 
-#line 312 "util/configlexer.lex"
+#line 314 "util/configlexer.lex"
 
 
 
index bed3b3a47d00146080dce1237baebfcf7a58562d..1d47b77e32b2553c1a3423fc7354c721aec24d02 100644 (file)
@@ -214,6 +214,8 @@ server-key-file{COLON}              { YDVAR(1, VAR_SERVER_KEY_FILE) }
 server-cert-file{COLON}                { YDVAR(1, VAR_SERVER_CERT_FILE) }
 control-key-file{COLON}                { YDVAR(1, VAR_CONTROL_KEY_FILE) }
 control-cert-file{COLON}       { YDVAR(1, VAR_CONTROL_CERT_FILE) }
+python-script{COLON}           { YDVAR(1, VAR_PYTHON_SCRIPT) }
+python{COLON}                  { YDVAR(0, VAR_PYTHON) }
 domain-insecure{COLON}         { YDVAR(1, VAR_DOMAIN_INSECURE) }
 <INITIAL,val>{NEWLINE}         { LEXOUT(("NL\n")); cfg_parser->line++; }
 
index 6b1fc6eeabe5d92517daf6101a1ac958f061dd36..b63ece88360b0f22054ce2a00d200cf3d002416b 100644 (file)
      VAR_STUB_PRIME = 354,
      VAR_UNWANTED_REPLY_THRESHOLD = 355,
      VAR_LOG_TIME_ASCII = 356,
-     VAR_DOMAIN_INSECURE = 357
+     VAR_DOMAIN_INSECURE = 357,
+     VAR_PYTHON = 358,
+     VAR_PYTHON_SCRIPT = 359
    };
 #endif
 /* Tokens.  */
 #define VAR_UNWANTED_REPLY_THRESHOLD 355
 #define VAR_LOG_TIME_ASCII 356
 #define VAR_DOMAIN_INSECURE 357
+#define VAR_PYTHON 358
+#define VAR_PYTHON_SCRIPT 359
 
 
 
@@ -327,7 +331,7 @@ typedef union YYSTYPE
        char*   str;
 }
 /* Line 187 of yacc.c.  */
-#line 331 "util/configparser.c"
+#line 335 "util/configparser.c"
        YYSTYPE;
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
@@ -340,7 +344,7 @@ typedef union YYSTYPE
 
 
 /* Line 216 of yacc.c.  */
-#line 344 "util/configparser.c"
+#line 348 "util/configparser.c"
 
 #ifdef short
 # undef short
@@ -555,20 +559,20 @@ union yyalloc
 /* YYFINAL -- State number of the termination state.  */
 #define YYFINAL  2
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   184
+#define YYLAST   194
 
 /* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  103
+#define YYNTOKENS  105
 /* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  104
+#define YYNNTS  108
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  197
+#define YYNRULES  203
 /* YYNRULES -- Number of states.  */
-#define YYNSTATES  289
+#define YYNSTATES  296
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
-#define YYMAXUTOK   357
+#define YYMAXUTOK   359
 
 #define YYTRANSLATE(YYX)                                               \
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -611,7 +615,7 @@ static const yytype_uint8 yytranslate[] =
       65,    66,    67,    68,    69,    70,    71,    72,    73,    74,
       75,    76,    77,    78,    79,    80,    81,    82,    83,    84,
       85,    86,    87,    88,    89,    90,    91,    92,    93,    94,
-      95,    96,    97,    98,    99,   100,   101,   102
+      95,    96,    97,    98,    99,   100,   101,   102,   103,   104
 };
 
 #if YYDEBUG
@@ -619,105 +623,109 @@ static const yytype_uint8 yytranslate[] =
    YYRHS.  */
 static const yytype_uint16 yyprhs[] =
 {
-       0,     0,     3,     4,     7,    10,    13,    16,    19,    21,
-      24,    25,    27,    29,    31,    33,    35,    37,    39,    41,
-      43,    45,    47,    49,    51,    53,    55,    57,    59,    61,
-      63,    65,    67,    69,    71,    73,    75,    77,    79,    81,
-      83,    85,    87,    89,    91,    93,    95,    97,    99,   101,
-     103,   105,   107,   109,   111,   113,   115,   117,   119,   121,
-     123,   125,   127,   129,   131,   133,   135,   137,   139,   141,
-     143,   145,   147,   149,   151,   153,   155,   157,   159,   161,
-     163,   165,   167,   169,   171,   173,   175,   177,   180,   181,
-     183,   185,   187,   189,   191,   194,   195,   197,   199,   201,
+       0,     0,     3,     4,     7,    10,    13,    16,    19,    22,
+      24,    27,    28,    30,    32,    34,    36,    38,    40,    42,
+      44,    46,    48,    50,    52,    54,    56,    58,    60,    62,
+      64,    66,    68,    70,    72,    74,    76,    78,    80,    82,
+      84,    86,    88,    90,    92,    94,    96,    98,   100,   102,
+     104,   106,   108,   110,   112,   114,   116,   118,   120,   122,
+     124,   126,   128,   130,   132,   134,   136,   138,   140,   142,
+     144,   146,   148,   150,   152,   154,   156,   158,   160,   162,
+     164,   166,   168,   170,   172,   174,   176,   178,   180,   183,
+     184,   186,   188,   190,   192,   194,   197,   198,   200,   202,
      204,   207,   210,   213,   216,   219,   222,   225,   228,   231,
      234,   237,   240,   243,   246,   249,   252,   255,   258,   261,
      264,   267,   270,   273,   276,   279,   282,   285,   288,   291,
      294,   297,   300,   303,   306,   309,   312,   315,   318,   321,
      324,   327,   330,   333,   336,   339,   342,   345,   348,   351,
      354,   357,   360,   363,   366,   369,   372,   375,   378,   381,
-     384,   388,   391,   394,   397,   400,   403,   406,   409,   412,
-     415,   418,   422,   425,   428,   431,   434,   437,   440,   443,
-     446,   449,   451,   454,   455,   457,   459,   461,   463,   465,
-     467,   469,   472,   475,   478,   481,   484,   487
+     384,   387,   391,   394,   397,   400,   403,   406,   409,   412,
+     415,   418,   421,   425,   428,   431,   434,   437,   440,   443,
+     446,   449,   452,   454,   457,   458,   460,   462,   464,   466,
+     468,   470,   472,   475,   478,   481,   484,   487,   490,   493,
+     495,   498,   499,   501
 };
 
 /* YYRHS -- A `-1'-separated list of the rules' RHS.  */
 static const yytype_int16 yyrhs[] =
 {
-     104,     0,    -1,    -1,   104,   105,    -1,   106,   107,    -1,
-     109,   110,    -1,   112,   113,    -1,   197,   198,    -1,    11,
-      -1,   107,   108,    -1,    -1,   115,    -1,   116,    -1,   120,
-      -1,   123,    -1,   129,    -1,   130,    -1,   131,    -1,   132,
-      -1,   121,    -1,   136,    -1,   137,    -1,   138,    -1,   139,
-      -1,   140,    -1,   153,    -1,   154,    -1,   155,    -1,   157,
-      -1,   158,    -1,   126,    -1,   159,    -1,   160,    -1,   163,
-      -1,   161,    -1,   162,    -1,   164,    -1,   165,    -1,   166,
-      -1,   174,    -1,   148,    -1,   149,    -1,   150,    -1,   151,
-      -1,   167,    -1,   177,    -1,   144,    -1,   146,    -1,   178,
-      -1,   180,    -1,   181,    -1,   182,    -1,   127,    -1,   152,
-      -1,   184,    -1,   185,    -1,   145,    -1,   183,    -1,   134,
-      -1,   122,    -1,   141,    -1,   175,    -1,   179,    -1,   168,
-      -1,   176,    -1,   187,    -1,   188,    -1,   128,    -1,   117,
-      -1,   133,    -1,   170,    -1,   118,    -1,   124,    -1,   125,
-      -1,   142,    -1,   143,    -1,   186,    -1,   169,    -1,   171,
-      -1,   172,    -1,   119,    -1,   189,    -1,   156,    -1,   173,
-      -1,   135,    -1,   147,    -1,    38,    -1,   110,   111,    -1,
-      -1,   190,    -1,   191,    -1,   192,    -1,   193,    -1,    44,
-      -1,   113,   114,    -1,    -1,   194,    -1,   195,    -1,   196,
-      -1,    13,    10,    -1,    12,    10,    -1,    76,    10,    -1,
-      79,    10,    -1,    96,    10,    -1,    14,    10,    -1,    16,
-      10,    -1,    67,    10,    -1,    15,    10,    -1,    80,    10,
-      -1,    81,    10,    -1,    31,    10,    -1,    60,    10,    -1,
-      75,    10,    -1,    17,    10,    -1,    18,    10,    -1,    19,
-      10,    -1,    20,    10,    -1,    77,    10,    -1,    66,    10,
-      -1,   101,    10,    -1,    21,    10,    -1,    22,    10,    -1,
-      23,    10,    -1,    24,    10,    -1,    25,    10,    -1,    68,
-      10,    -1,    82,    10,    -1,    83,    10,    -1,    54,    10,
-      -1,    64,    10,    -1,    55,    10,    -1,   102,    10,    -1,
-      48,    10,    -1,    49,    10,    -1,    50,    10,    -1,    51,
-      10,    -1,    61,    10,    -1,    26,    10,    -1,    27,    10,
-      -1,    28,    10,    -1,    98,    10,    -1,    29,    10,    -1,
-      30,    10,    -1,    32,    10,    -1,    33,    10,    -1,    35,
-      10,    -1,    36,    10,    -1,    34,    10,    -1,    41,    10,
-      -1,    42,    10,    -1,    43,    10,    -1,    52,    10,    -1,
-      71,    10,    -1,    85,    10,    -1,    78,    10,    -1,    86,
-      10,    -1,    87,    10,    -1,   100,    10,    -1,    47,    10,
-      -1,    69,    10,    -1,    72,    10,    10,    -1,    53,    10,
-      -1,    56,    10,    -1,    70,    10,    -1,    57,    10,    -1,
-      58,    10,    -1,    59,    10,    -1,    65,    10,    -1,    62,
-      10,    -1,    63,    10,    -1,    84,    10,    -1,    73,    10,
-      10,    -1,    74,    10,    -1,    97,    10,    -1,    37,    10,
-      -1,    39,    10,    -1,    40,    10,    -1,    99,    10,    -1,
-      37,    10,    -1,    45,    10,    -1,    46,    10,    -1,    88,
-      -1,   198,   199,    -1,    -1,   200,    -1,   202,    -1,   201,
-      -1,   203,    -1,   204,    -1,   205,    -1,   206,    -1,    89,
-      10,    -1,    91,    10,    -1,    90,    10,    -1,    92,    10,
-      -1,    93,    10,    -1,    94,    10,    -1,    95,    10,    -1
+     106,     0,    -1,    -1,   106,   107,    -1,   108,   109,    -1,
+     111,   112,    -1,   114,   115,    -1,   209,   210,    -1,   199,
+     200,    -1,    11,    -1,   109,   110,    -1,    -1,   117,    -1,
+     118,    -1,   122,    -1,   125,    -1,   131,    -1,   132,    -1,
+     133,    -1,   134,    -1,   123,    -1,   138,    -1,   139,    -1,
+     140,    -1,   141,    -1,   142,    -1,   155,    -1,   156,    -1,
+     157,    -1,   159,    -1,   160,    -1,   128,    -1,   161,    -1,
+     162,    -1,   165,    -1,   163,    -1,   164,    -1,   166,    -1,
+     167,    -1,   168,    -1,   176,    -1,   150,    -1,   151,    -1,
+     152,    -1,   153,    -1,   169,    -1,   179,    -1,   146,    -1,
+     148,    -1,   180,    -1,   182,    -1,   183,    -1,   184,    -1,
+     129,    -1,   154,    -1,   186,    -1,   187,    -1,   147,    -1,
+     185,    -1,   136,    -1,   124,    -1,   143,    -1,   177,    -1,
+     181,    -1,   170,    -1,   178,    -1,   189,    -1,   190,    -1,
+     130,    -1,   119,    -1,   135,    -1,   172,    -1,   120,    -1,
+     126,    -1,   127,    -1,   144,    -1,   145,    -1,   188,    -1,
+     171,    -1,   173,    -1,   174,    -1,   121,    -1,   191,    -1,
+     158,    -1,   175,    -1,   137,    -1,   149,    -1,    38,    -1,
+     112,   113,    -1,    -1,   192,    -1,   193,    -1,   194,    -1,
+     195,    -1,    44,    -1,   115,   116,    -1,    -1,   196,    -1,
+     197,    -1,   198,    -1,    13,    10,    -1,    12,    10,    -1,
+      76,    10,    -1,    79,    10,    -1,    96,    10,    -1,    14,
+      10,    -1,    16,    10,    -1,    67,    10,    -1,    15,    10,
+      -1,    80,    10,    -1,    81,    10,    -1,    31,    10,    -1,
+      60,    10,    -1,    75,    10,    -1,    17,    10,    -1,    18,
+      10,    -1,    19,    10,    -1,    20,    10,    -1,    77,    10,
+      -1,    66,    10,    -1,   101,    10,    -1,    21,    10,    -1,
+      22,    10,    -1,    23,    10,    -1,    24,    10,    -1,    25,
+      10,    -1,    68,    10,    -1,    82,    10,    -1,    83,    10,
+      -1,    54,    10,    -1,    64,    10,    -1,    55,    10,    -1,
+     102,    10,    -1,    48,    10,    -1,    49,    10,    -1,    50,
+      10,    -1,    51,    10,    -1,    61,    10,    -1,    26,    10,
+      -1,    27,    10,    -1,    28,    10,    -1,    98,    10,    -1,
+      29,    10,    -1,    30,    10,    -1,    32,    10,    -1,    33,
+      10,    -1,    35,    10,    -1,    36,    10,    -1,    34,    10,
+      -1,    41,    10,    -1,    42,    10,    -1,    43,    10,    -1,
+      52,    10,    -1,    71,    10,    -1,    85,    10,    -1,    78,
+      10,    -1,    86,    10,    -1,    87,    10,    -1,   100,    10,
+      -1,    47,    10,    -1,    69,    10,    -1,    72,    10,    10,
+      -1,    53,    10,    -1,    56,    10,    -1,    70,    10,    -1,
+      57,    10,    -1,    58,    10,    -1,    59,    10,    -1,    65,
+      10,    -1,    62,    10,    -1,    63,    10,    -1,    84,    10,
+      -1,    73,    10,    10,    -1,    74,    10,    -1,    97,    10,
+      -1,    37,    10,    -1,    39,    10,    -1,    40,    10,    -1,
+      99,    10,    -1,    37,    10,    -1,    45,    10,    -1,    46,
+      10,    -1,    88,    -1,   200,   201,    -1,    -1,   202,    -1,
+     204,    -1,   203,    -1,   205,    -1,   206,    -1,   207,    -1,
+     208,    -1,    89,    10,    -1,    91,    10,    -1,    90,    10,
+      -1,    92,    10,    -1,    93,    10,    -1,    94,    10,    -1,
+      95,    10,    -1,   103,    -1,   210,   211,    -1,    -1,   212,
+      -1,   104,    10,    -1
 };
 
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,   103,   103,   103,   104,   104,   105,   105,   109,   114,
-     115,   116,   116,   116,   117,   117,   118,   118,   118,   119,
-     119,   119,   120,   120,   120,   121,   121,   122,   122,   123,
-     123,   124,   124,   125,   125,   126,   126,   127,   127,   128,
-     128,   129,   129,   129,   130,   130,   130,   131,   131,   131,
-     132,   132,   133,   133,   134,   134,   135,   135,   136,   136,
-     136,   137,   137,   138,   138,   139,   139,   139,   140,   140,
-     141,   141,   142,   142,   143,   143,   143,   144,   144,   145,
-     145,   146,   146,   147,   147,   148,   150,   162,   163,   164,
-     164,   164,   164,   166,   178,   179,   180,   180,   180,   182,
-     191,   200,   211,   220,   229,   238,   251,   266,   275,   284,
-     293,   302,   311,   320,   329,   338,   347,   356,   365,   379,
-     388,   395,   402,   409,   417,   424,   431,   438,   445,   453,
-     461,   468,   475,   484,   493,   500,   507,   518,   526,   539,
-     548,   557,   565,   578,   587,   596,   605,   614,   627,   634,
-     644,   654,   664,   674,   684,   694,   701,   708,   717,   724,
-     734,   748,   755,   773,   782,   791,   801,   811,   818,   826,
-     839,   847,   867,   874,   889,   896,   903,   910,   920,   927,
-     934,   941,   946,   947,   948,   948,   948,   949,   949,   949,
-     950,   952,   962,   971,   978,   985,   992,   999
+       0,   103,   103,   103,   104,   104,   105,   105,   106,   110,
+     115,   116,   117,   117,   117,   118,   118,   119,   119,   119,
+     120,   120,   120,   121,   121,   121,   122,   122,   123,   123,
+     124,   124,   125,   125,   126,   126,   127,   127,   128,   128,
+     129,   129,   130,   130,   130,   131,   131,   131,   132,   132,
+     132,   133,   133,   134,   134,   135,   135,   136,   136,   137,
+     137,   137,   138,   138,   139,   139,   140,   140,   140,   141,
+     141,   142,   142,   143,   143,   144,   144,   144,   145,   145,
+     146,   146,   147,   147,   148,   148,   149,   151,   163,   164,
+     165,   165,   165,   165,   167,   179,   180,   181,   181,   181,
+     183,   192,   201,   212,   221,   230,   239,   252,   267,   276,
+     285,   294,   303,   312,   321,   330,   339,   348,   357,   366,
+     380,   389,   396,   403,   410,   418,   425,   432,   439,   446,
+     454,   462,   469,   476,   485,   494,   501,   508,   519,   527,
+     540,   549,   558,   566,   579,   588,   597,   606,   615,   628,
+     635,   645,   655,   665,   675,   685,   695,   702,   709,   718,
+     725,   735,   749,   756,   774,   783,   792,   802,   812,   819,
+     827,   840,   848,   868,   875,   890,   897,   904,   911,   921,
+     928,   935,   942,   947,   948,   949,   949,   949,   950,   950,
+     950,   951,   953,   963,   972,   979,   986,   993,  1000,  1007,
+    1012,  1013,  1014,  1016
 };
 #endif
 
@@ -758,17 +766,17 @@ static const char *const yytname[] =
   "VAR_SERVER_CERT_FILE", "VAR_CONTROL_KEY_FILE", "VAR_CONTROL_CERT_FILE",
   "VAR_EXTENDED_STATISTICS", "VAR_LOCAL_DATA_PTR", "VAR_JOSTLE_TIMEOUT",
   "VAR_STUB_PRIME", "VAR_UNWANTED_REPLY_THRESHOLD", "VAR_LOG_TIME_ASCII",
-  "VAR_DOMAIN_INSECURE", "$accept", "toplevelvars", "toplevelvar",
-  "serverstart", "contents_server", "content_server", "stubstart",
-  "contents_stub", "content_stub", "forwardstart", "contents_forward",
-  "content_forward", "server_num_threads", "server_verbosity",
-  "server_statistics_interval", "server_statistics_cumulative",
-  "server_extended_statistics", "server_port", "server_interface",
-  "server_outgoing_interface", "server_outgoing_range",
-  "server_outgoing_port_permit", "server_outgoing_port_avoid",
-  "server_outgoing_num_tcp", "server_incoming_num_tcp",
-  "server_interface_automatic", "server_do_ip4", "server_do_ip6",
-  "server_do_udp", "server_do_tcp", "server_do_daemonize",
+  "VAR_DOMAIN_INSECURE", "VAR_PYTHON", "VAR_PYTHON_SCRIPT", "$accept",
+  "toplevelvars", "toplevelvar", "serverstart", "contents_server",
+  "content_server", "stubstart", "contents_stub", "content_stub",
+  "forwardstart", "contents_forward", "content_forward",
+  "server_num_threads", "server_verbosity", "server_statistics_interval",
+  "server_statistics_cumulative", "server_extended_statistics",
+  "server_port", "server_interface", "server_outgoing_interface",
+  "server_outgoing_range", "server_outgoing_port_permit",
+  "server_outgoing_port_avoid", "server_outgoing_num_tcp",
+  "server_incoming_num_tcp", "server_interface_automatic", "server_do_ip4",
+  "server_do_ip6", "server_do_udp", "server_do_tcp", "server_do_daemonize",
   "server_use_syslog", "server_log_time_ascii", "server_chroot",
   "server_username", "server_directory", "server_logfile",
   "server_pidfile", "server_root_hints", "server_dlv_anchor_file",
@@ -797,7 +805,8 @@ static const char *const yytname[] =
   "stub_prime", "forward_name", "forward_host", "forward_addr", "rcstart",
   "contents_rc", "content_rc", "rc_control_enable", "rc_control_port",
   "rc_control_interface", "rc_server_key_file", "rc_server_cert_file",
-  "rc_control_key_file", "rc_control_cert_file", 0
+  "rc_control_key_file", "rc_control_cert_file", "pythonstart",
+  "contents_py", "content_py", "py_script", 0
 };
 #endif
 
@@ -816,58 +825,60 @@ static const yytype_uint16 yytoknum[] =
      325,   326,   327,   328,   329,   330,   331,   332,   333,   334,
      335,   336,   337,   338,   339,   340,   341,   342,   343,   344,
      345,   346,   347,   348,   349,   350,   351,   352,   353,   354,
-     355,   356,   357
+     355,   356,   357,   358,   359
 };
 # endif
 
 /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 static const yytype_uint8 yyr1[] =
 {
-       0,   103,   104,   104,   105,   105,   105,   105,   106,   107,
-     107,   108,   108,   108,   108,   108,   108,   108,   108,   108,
-     108,   108,   108,   108,   108,   108,   108,   108,   108,   108,
-     108,   108,   108,   108,   108,   108,   108,   108,   108,   108,
-     108,   108,   108,   108,   108,   108,   108,   108,   108,   108,
-     108,   108,   108,   108,   108,   108,   108,   108,   108,   108,
-     108,   108,   108,   108,   108,   108,   108,   108,   108,   108,
-     108,   108,   108,   108,   108,   108,   108,   108,   108,   108,
-     108,   108,   108,   108,   108,   108,   109,   110,   110,   111,
-     111,   111,   111,   112,   113,   113,   114,   114,   114,   115,
-     116,   117,   118,   119,   120,   121,   122,   123,   124,   125,
-     126,   127,   128,   129,   130,   131,   132,   133,   134,   135,
-     136,   137,   138,   139,   140,   141,   142,   143,   144,   145,
-     146,   147,   148,   149,   150,   151,   152,   153,   154,   155,
-     156,   157,   158,   159,   160,   161,   162,   163,   164,   165,
-     166,   167,   168,   169,   170,   171,   172,   173,   174,   175,
-     176,   177,   178,   179,   180,   181,   182,   183,   184,   185,
-     186,   187,   188,   189,   190,   191,   192,   193,   194,   195,
-     196,   197,   198,   198,   199,   199,   199,   199,   199,   199,
-     199,   200,   201,   202,   203,   204,   205,   206
+       0,   105,   106,   106,   107,   107,   107,   107,   107,   108,
+     109,   109,   110,   110,   110,   110,   110,   110,   110,   110,
+     110,   110,   110,   110,   110,   110,   110,   110,   110,   110,
+     110,   110,   110,   110,   110,   110,   110,   110,   110,   110,
+     110,   110,   110,   110,   110,   110,   110,   110,   110,   110,
+     110,   110,   110,   110,   110,   110,   110,   110,   110,   110,
+     110,   110,   110,   110,   110,   110,   110,   110,   110,   110,
+     110,   110,   110,   110,   110,   110,   110,   110,   110,   110,
+     110,   110,   110,   110,   110,   110,   110,   111,   112,   112,
+     113,   113,   113,   113,   114,   115,   115,   116,   116,   116,
+     117,   118,   119,   120,   121,   122,   123,   124,   125,   126,
+     127,   128,   129,   130,   131,   132,   133,   134,   135,   136,
+     137,   138,   139,   140,   141,   142,   143,   144,   145,   146,
+     147,   148,   149,   150,   151,   152,   153,   154,   155,   156,
+     157,   158,   159,   160,   161,   162,   163,   164,   165,   166,
+     167,   168,   169,   170,   171,   172,   173,   174,   175,   176,
+     177,   178,   179,   180,   181,   182,   183,   184,   185,   186,
+     187,   188,   189,   190,   191,   192,   193,   194,   195,   196,
+     197,   198,   199,   200,   200,   201,   201,   201,   201,   201,
+     201,   201,   202,   203,   204,   205,   206,   207,   208,   209,
+     210,   210,   211,   212
 };
 
 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
 static const yytype_uint8 yyr2[] =
 {
-       0,     2,     0,     2,     2,     2,     2,     2,     1,     2,
-       0,     1,     1,     1,     1,     1,     1,     1,     1,     1,
+       0,     2,     0,     2,     2,     2,     2,     2,     2,     1,
+       2,     0,     1,     1,     1,     1,     1,     1,     1,     1,
        1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
        1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
        1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
        1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
        1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
        1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
-       1,     1,     1,     1,     1,     1,     1,     2,     0,     1,
-       1,     1,     1,     1,     2,     0,     1,     1,     1,     2,
+       1,     1,     1,     1,     1,     1,     1,     1,     2,     0,
+       1,     1,     1,     1,     1,     2,     0,     1,     1,     1,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       3,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     3,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     1,     2,     0,     1,     1,     1,     1,     1,     1,
-       1,     2,     2,     2,     2,     2,     2,     2
+       2,     2,     3,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     1,     2,     0,     1,     1,     1,     1,     1,
+       1,     1,     2,     2,     2,     2,     2,     2,     2,     1,
+       2,     0,     1,     2
 };
 
 /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
@@ -875,8 +886,8 @@ static const yytype_uint8 yyr2[] =
    means the default is an error.  */
 static const yytype_uint8 yydefact[] =
 {
-       2,     0,     1,     8,    86,    93,   181,     3,    10,    88,
-      95,   183,     4,     5,     6,     7,     0,     0,     0,     0,
+       2,     0,     1,     9,    87,    94,   182,   199,     3,    11,
+      89,    96,   184,   201,     4,     5,     6,     8,     7,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
@@ -884,94 +895,96 @@ static const yytype_uint8 yydefact[] =
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     9,    11,    12,    68,    71,    80,    13,    19,    59,
-      14,    72,    73,    30,    52,    67,    15,    16,    17,    18,
-      69,    58,    84,    20,    21,    22,    23,    24,    60,    74,
-      75,    46,    56,    47,    85,    40,    41,    42,    43,    53,
-      25,    26,    27,    82,    28,    29,    31,    32,    34,    35,
-      33,    36,    37,    38,    44,    63,    77,    70,    78,    79,
-      83,    39,    61,    64,    45,    48,    62,    49,    50,    51,
-      57,    54,    55,    76,    65,    66,    81,     0,     0,     0,
-       0,    87,    89,    90,    91,    92,     0,     0,     0,    94,
-      96,    97,    98,     0,     0,     0,     0,     0,     0,     0,
-     182,   184,   186,   185,   187,   188,   189,   190,   100,    99,
-     104,   107,   105,   113,   114,   115,   116,   120,   121,   122,
-     123,   124,   137,   138,   139,   141,   142,   110,   143,   144,
-     147,   145,   146,   148,   149,   150,   158,   132,   133,   134,
-     135,   151,   161,   128,   130,   162,   164,   165,   166,   111,
-     136,   168,   169,   129,   167,   118,   106,   125,   159,   163,
-     152,     0,     0,   172,   112,   101,   117,   154,   102,   108,
-     109,   126,   127,   170,   153,   155,   156,   103,   173,   140,
-     157,   119,   131,   174,   175,   176,   177,   178,   179,   180,
-     191,   193,   192,   194,   195,   196,   197,   160,   171
+       0,     0,     0,     0,    10,    12,    13,    69,    72,    81,
+      14,    20,    60,    15,    73,    74,    31,    53,    68,    16,
+      17,    18,    19,    70,    59,    85,    21,    22,    23,    24,
+      25,    61,    75,    76,    47,    57,    48,    86,    41,    42,
+      43,    44,    54,    26,    27,    28,    83,    29,    30,    32,
+      33,    35,    36,    34,    37,    38,    39,    45,    64,    78,
+      71,    79,    80,    84,    40,    62,    65,    46,    49,    63,
+      50,    51,    52,    58,    55,    56,    77,    66,    67,    82,
+       0,     0,     0,     0,    88,    90,    91,    92,    93,     0,
+       0,     0,    95,    97,    98,    99,     0,     0,     0,     0,
+       0,     0,     0,   183,   185,   187,   186,   188,   189,   190,
+     191,     0,   200,   202,   101,   100,   105,   108,   106,   114,
+     115,   116,   117,   121,   122,   123,   124,   125,   138,   139,
+     140,   142,   143,   111,   144,   145,   148,   146,   147,   149,
+     150,   151,   159,   133,   134,   135,   136,   152,   162,   129,
+     131,   163,   165,   166,   167,   112,   137,   169,   170,   130,
+     168,   119,   107,   126,   160,   164,   153,     0,     0,   173,
+     113,   102,   118,   155,   103,   109,   110,   127,   128,   171,
+     154,   156,   157,   104,   174,   141,   158,   120,   132,   175,
+     176,   177,   178,   179,   180,   181,   192,   194,   193,   195,
+     196,   197,   198,   203,   161,   172
 };
 
 /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int16 yydefgoto[] =
 {
-      -1,     1,     7,     8,    12,    91,     9,    13,   171,    10,
-      14,   179,    92,    93,    94,    95,    96,    97,    98,    99,
-     100,   101,   102,   103,   104,   105,   106,   107,   108,   109,
-     110,   111,   112,   113,   114,   115,   116,   117,   118,   119,
-     120,   121,   122,   123,   124,   125,   126,   127,   128,   129,
-     130,   131,   132,   133,   134,   135,   136,   137,   138,   139,
-     140,   141,   142,   143,   144,   145,   146,   147,   148,   149,
-     150,   151,   152,   153,   154,   155,   156,   157,   158,   159,
-     160,   161,   162,   163,   164,   165,   166,   172,   173,   174,
-     175,   180,   181,   182,    11,    15,   190,   191,   192,   193,
-     194,   195,   196,   197
+      -1,     1,     8,     9,    14,    94,    10,    15,   174,    11,
+      16,   182,    95,    96,    97,    98,    99,   100,   101,   102,
+     103,   104,   105,   106,   107,   108,   109,   110,   111,   112,
+     113,   114,   115,   116,   117,   118,   119,   120,   121,   122,
+     123,   124,   125,   126,   127,   128,   129,   130,   131,   132,
+     133,   134,   135,   136,   137,   138,   139,   140,   141,   142,
+     143,   144,   145,   146,   147,   148,   149,   150,   151,   152,
+     153,   154,   155,   156,   157,   158,   159,   160,   161,   162,
+     163,   164,   165,   166,   167,   168,   169,   175,   176,   177,
+     178,   183,   184,   185,    12,    17,   193,   194,   195,   196,
+     197,   198,   199,   200,    13,    18,   202,   203
 };
 
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
    STATE-NUM.  */
-#define YYPACT_NINF -13
+#define YYPACT_NINF -103
 static const yytype_int16 yypact[] =
 {
-     -13,    76,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,
-     -13,   -13,   -12,    40,    46,     4,    15,    16,    17,    18,
-      22,    23,    24,    68,    71,    72,    90,    91,    92,    93,
-      94,    95,    96,    97,    98,    99,   100,   101,   102,   103,
-     105,   106,   107,   108,   109,   111,   112,   113,   114,   115,
-     116,   117,   118,   119,   120,   121,   122,   123,   124,   125,
-     126,   127,   128,   130,   131,   132,   133,   134,   135,   136,
-     137,   138,   139,   140,   141,   142,   143,   144,   145,   146,
-     147,   148,   149,   150,   151,   152,   153,   155,   156,   157,
-     158,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,
-     -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,
-     -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,
-     -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,
-     -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,
-     -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,
-     -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,
-     -13,   -13,   -13,   -13,   -13,   -13,   -13,   159,   160,   161,
-     162,   -13,   -13,   -13,   -13,   -13,   163,   164,   165,   -13,
-     -13,   -13,   -13,   166,   167,   168,   169,   170,   171,   172,
-     -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,
-     -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,
-     -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,
-     -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,
-     -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,
-     -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,
-     -13,   173,   174,   -13,   -13,   -13,   -13,   -13,   -13,   -13,
-     -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,
-     -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,
-     -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13
+    -103,     0,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,
+    -103,  -103,  -103,  -103,    92,   -36,   -32,   -74,  -102,    -4,
+      -3,    -2,    -1,     2,    12,    13,    14,    15,    16,    17,
+      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
+      29,    30,    31,    32,    33,    35,    36,    37,    38,    39,
+      40,    41,    42,    43,    44,    45,    46,    47,    48,    49,
+      50,    51,    52,    54,    55,    56,    57,    58,    59,    60,
+      61,    62,    63,    64,    65,    66,    67,    68,    69,    70,
+      71,    72,    73,    74,    75,    76,    77,    79,    80,    81,
+      82,    83,    84,    85,  -103,  -103,  -103,  -103,  -103,  -103,
+    -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,
+    -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,
+    -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,
+    -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,
+    -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,
+    -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,
+    -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,
+      86,    87,    88,    89,  -103,  -103,  -103,  -103,  -103,    90,
+      91,   119,  -103,  -103,  -103,  -103,   120,   121,   122,   126,
+     127,   128,   170,  -103,  -103,  -103,  -103,  -103,  -103,  -103,
+    -103,   171,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,
+    -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,
+    -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,
+    -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,
+    -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,
+    -103,  -103,  -103,  -103,  -103,  -103,  -103,   172,   173,  -103,
+    -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,
+    -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,
+    -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,
+    -103,  -103,  -103,  -103,  -103,  -103
 };
 
 /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int8 yypgoto[] =
 {
-     -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,
-     -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,
-     -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,
-     -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,
-     -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,
-     -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,
-     -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,
-     -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,
-     -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,
-     -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,
-     -13,   -13,   -13,   -13
+    -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,
+    -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,
+    -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,
+    -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,
+    -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,
+    -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,
+    -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,
+    -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,
+    -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,
+    -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103,
+    -103,  -103,  -103,  -103,  -103,  -103,  -103,  -103
 };
 
 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
@@ -981,74 +994,77 @@ static const yytype_int8 yypgoto[] =
 #define YYTABLE_NINF -1
 static const yytype_uint16 yytable[] =
 {
-      16,    17,    18,    19,    20,    21,    22,    23,    24,    25,
-      26,    27,    28,    29,    30,    31,    32,    33,    34,    35,
-      36,    37,    38,    39,    40,   198,   199,   200,   201,    41,
-      42,    43,   202,   203,   204,    44,    45,    46,    47,    48,
-      49,    50,    51,    52,    53,    54,    55,    56,    57,    58,
-      59,    60,    61,    62,    63,    64,    65,    66,    67,    68,
-      69,    70,    71,    72,    73,    74,    75,    76,    77,    78,
-      79,    80,    81,    82,    83,    84,     2,   167,   205,   168,
-     169,   206,   207,   176,    85,    86,    87,     3,    88,    89,
-      90,   177,   178,   183,   184,   185,   186,   187,   188,   189,
-     208,   209,   210,   211,   212,   213,   214,   215,   216,   217,
-     218,   219,   220,   221,     4,   222,   223,   224,   225,   226,
-       5,   227,   228,   229,   230,   231,   232,   233,   234,   235,
-     236,   237,   238,   239,   240,   241,   242,   243,   244,   170,
-     245,   246,   247,   248,   249,   250,   251,   252,   253,   254,
-     255,   256,   257,   258,   259,   260,   261,   262,   263,   264,
-     265,   266,   267,   268,     6,   269,   270,   271,   272,   273,
-     274,   275,   276,   277,   278,   279,   280,   281,   282,   283,
-     284,   285,   286,   287,   288
+       2,   170,   201,   171,   172,   179,   204,   205,   206,   207,
+       0,     3,   208,   180,   181,   186,   187,   188,   189,   190,
+     191,   192,   209,   210,   211,   212,   213,   214,   215,   216,
+     217,   218,   219,   220,   221,   222,   223,   224,     4,   225,
+     226,   227,   228,   229,     5,   230,   231,   232,   233,   234,
+     235,   236,   237,   238,   239,   240,   241,   242,   243,   244,
+     245,   246,   247,   173,   248,   249,   250,   251,   252,   253,
+     254,   255,   256,   257,   258,   259,   260,   261,   262,   263,
+     264,   265,   266,   267,   268,   269,   270,   271,     6,   272,
+     273,   274,   275,   276,   277,   278,   279,   280,   281,   282,
+     283,   284,     0,     7,    19,    20,    21,    22,    23,    24,
+      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
+      35,    36,    37,    38,    39,    40,    41,    42,    43,   285,
+     286,   287,   288,    44,    45,    46,   289,   290,   291,    47,
+      48,    49,    50,    51,    52,    53,    54,    55,    56,    57,
+      58,    59,    60,    61,    62,    63,    64,    65,    66,    67,
+      68,    69,    70,    71,    72,    73,    74,    75,    76,    77,
+      78,    79,    80,    81,    82,    83,    84,    85,    86,    87,
+     292,   293,   294,   295,     0,     0,     0,     0,    88,    89,
+      90,     0,    91,    92,    93
 };
 
-static const yytype_uint8 yycheck[] =
+static const yytype_int8 yycheck[] =
 {
-      12,    13,    14,    15,    16,    17,    18,    19,    20,    21,
-      22,    23,    24,    25,    26,    27,    28,    29,    30,    31,
-      32,    33,    34,    35,    36,    10,    10,    10,    10,    41,
-      42,    43,    10,    10,    10,    47,    48,    49,    50,    51,
-      52,    53,    54,    55,    56,    57,    58,    59,    60,    61,
-      62,    63,    64,    65,    66,    67,    68,    69,    70,    71,
-      72,    73,    74,    75,    76,    77,    78,    79,    80,    81,
-      82,    83,    84,    85,    86,    87,     0,    37,    10,    39,
-      40,    10,    10,    37,    96,    97,    98,    11,   100,   101,
-     102,    45,    46,    89,    90,    91,    92,    93,    94,    95,
+       0,    37,   104,    39,    40,    37,    10,    10,    10,    10,
+      -1,    11,    10,    45,    46,    89,    90,    91,    92,    93,
+      94,    95,    10,    10,    10,    10,    10,    10,    10,    10,
+      10,    10,    10,    10,    10,    10,    10,    10,    38,    10,
+      10,    10,    10,    10,    44,    10,    10,    10,    10,    10,
       10,    10,    10,    10,    10,    10,    10,    10,    10,    10,
-      10,    10,    10,    10,    38,    10,    10,    10,    10,    10,
-      44,    10,    10,    10,    10,    10,    10,    10,    10,    10,
-      10,    10,    10,    10,    10,    10,    10,    10,    10,    99,
+      10,    10,    10,    99,    10,    10,    10,    10,    10,    10,
       10,    10,    10,    10,    10,    10,    10,    10,    10,    10,
+      10,    10,    10,    10,    10,    10,    10,    10,    88,    10,
       10,    10,    10,    10,    10,    10,    10,    10,    10,    10,
-      10,    10,    10,    10,    88,    10,    10,    10,    10,    10,
-      10,    10,    10,    10,    10,    10,    10,    10,    10,    10,
-      10,    10,    10,    10,    10
+      10,    10,    -1,   103,    12,    13,    14,    15,    16,    17,
+      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
+      28,    29,    30,    31,    32,    33,    34,    35,    36,    10,
+      10,    10,    10,    41,    42,    43,    10,    10,    10,    47,
+      48,    49,    50,    51,    52,    53,    54,    55,    56,    57,
+      58,    59,    60,    61,    62,    63,    64,    65,    66,    67,
+      68,    69,    70,    71,    72,    73,    74,    75,    76,    77,
+      78,    79,    80,    81,    82,    83,    84,    85,    86,    87,
+      10,    10,    10,    10,    -1,    -1,    -1,    -1,    96,    97,
+      98,    -1,   100,   101,   102
 };
 
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
    symbol of state STATE-NUM.  */
 static const yytype_uint8 yystos[] =
 {
-       0,   104,     0,    11,    38,    44,    88,   105,   106,   109,
-     112,   197,   107,   110,   113,   198,    12,    13,    14,    15,
-      16,    17,    18,    19,    20,    21,    22,    23,    24,    25,
-      26,    27,    28,    29,    30,    31,    32,    33,    34,    35,
-      36,    41,    42,    43,    47,    48,    49,    50,    51,    52,
-      53,    54,    55,    56,    57,    58,    59,    60,    61,    62,
-      63,    64,    65,    66,    67,    68,    69,    70,    71,    72,
-      73,    74,    75,    76,    77,    78,    79,    80,    81,    82,
-      83,    84,    85,    86,    87,    96,    97,    98,   100,   101,
-     102,   108,   115,   116,   117,   118,   119,   120,   121,   122,
-     123,   124,   125,   126,   127,   128,   129,   130,   131,   132,
-     133,   134,   135,   136,   137,   138,   139,   140,   141,   142,
-     143,   144,   145,   146,   147,   148,   149,   150,   151,   152,
-     153,   154,   155,   156,   157,   158,   159,   160,   161,   162,
-     163,   164,   165,   166,   167,   168,   169,   170,   171,   172,
-     173,   174,   175,   176,   177,   178,   179,   180,   181,   182,
-     183,   184,   185,   186,   187,   188,   189,    37,    39,    40,
-      99,   111,   190,   191,   192,   193,    37,    45,    46,   114,
-     194,   195,   196,    89,    90,    91,    92,    93,    94,    95,
-     199,   200,   201,   202,   203,   204,   205,   206,    10,    10,
+       0,   106,     0,    11,    38,    44,    88,   103,   107,   108,
+     111,   114,   199,   209,   109,   112,   115,   200,   210,    12,
+      13,    14,    15,    16,    17,    18,    19,    20,    21,    22,
+      23,    24,    25,    26,    27,    28,    29,    30,    31,    32,
+      33,    34,    35,    36,    41,    42,    43,    47,    48,    49,
+      50,    51,    52,    53,    54,    55,    56,    57,    58,    59,
+      60,    61,    62,    63,    64,    65,    66,    67,    68,    69,
+      70,    71,    72,    73,    74,    75,    76,    77,    78,    79,
+      80,    81,    82,    83,    84,    85,    86,    87,    96,    97,
+      98,   100,   101,   102,   110,   117,   118,   119,   120,   121,
+     122,   123,   124,   125,   126,   127,   128,   129,   130,   131,
+     132,   133,   134,   135,   136,   137,   138,   139,   140,   141,
+     142,   143,   144,   145,   146,   147,   148,   149,   150,   151,
+     152,   153,   154,   155,   156,   157,   158,   159,   160,   161,
+     162,   163,   164,   165,   166,   167,   168,   169,   170,   171,
+     172,   173,   174,   175,   176,   177,   178,   179,   180,   181,
+     182,   183,   184,   185,   186,   187,   188,   189,   190,   191,
+      37,    39,    40,    99,   113,   192,   193,   194,   195,    37,
+      45,    46,   116,   196,   197,   198,    89,    90,    91,    92,
+      93,    94,    95,   201,   202,   203,   204,   205,   206,   207,
+     208,   104,   211,   212,    10,    10,    10,    10,    10,    10,
       10,    10,    10,    10,    10,    10,    10,    10,    10,    10,
       10,    10,    10,    10,    10,    10,    10,    10,    10,    10,
       10,    10,    10,    10,    10,    10,    10,    10,    10,    10,
@@ -1057,7 +1073,7 @@ static const yytype_uint8 yystos[] =
       10,    10,    10,    10,    10,    10,    10,    10,    10,    10,
       10,    10,    10,    10,    10,    10,    10,    10,    10,    10,
       10,    10,    10,    10,    10,    10,    10,    10,    10,    10,
-      10,    10,    10,    10,    10,    10,    10,    10,    10
+      10,    10,    10,    10,    10,    10
 };
 
 #define yyerrok                (yyerrstatus = 0)
@@ -1871,15 +1887,15 @@ yyreduce:
   YY_REDUCE_PRINT (yyn);
   switch (yyn)
     {
-        case 8:
-#line 110 "util/configparser.y"
+        case 9:
+#line 111 "util/configparser.y"
     { 
                OUTYY(("\nP(server:)\n")); 
        }
     break;
 
-  case 86:
-#line 151 "util/configparser.y"
+  case 87:
+#line 152 "util/configparser.y"
     {
                struct config_stub* s;
                OUTYY(("\nP(stub_zone:)\n")); 
@@ -1892,8 +1908,8 @@ yyreduce:
        }
     break;
 
-  case 93:
-#line 167 "util/configparser.y"
+  case 94:
+#line 168 "util/configparser.y"
     {
                struct config_stub* s;
                OUTYY(("\nP(forward_zone:)\n")); 
@@ -1906,8 +1922,8 @@ yyreduce:
        }
     break;
 
-  case 99:
-#line 183 "util/configparser.y"
+  case 100:
+#line 184 "util/configparser.y"
     { 
                OUTYY(("P(server_num_threads:%s)\n", (yyvsp[(2) - (2)].str))); 
                if(atoi((yyvsp[(2) - (2)].str)) == 0 && strcmp((yyvsp[(2) - (2)].str), "0") != 0)
@@ -1917,8 +1933,8 @@ yyreduce:
        }
     break;
 
-  case 100:
-#line 192 "util/configparser.y"
+  case 101:
+#line 193 "util/configparser.y"
     { 
                OUTYY(("P(server_verbosity:%s)\n", (yyvsp[(2) - (2)].str))); 
                if(atoi((yyvsp[(2) - (2)].str)) == 0 && strcmp((yyvsp[(2) - (2)].str), "0") != 0)
@@ -1928,8 +1944,8 @@ yyreduce:
        }
     break;
 
-  case 101:
-#line 201 "util/configparser.y"
+  case 102:
+#line 202 "util/configparser.y"
     { 
                OUTYY(("P(server_statistics_interval:%s)\n", (yyvsp[(2) - (2)].str))); 
                if(strcmp((yyvsp[(2) - (2)].str), "") == 0 || strcmp((yyvsp[(2) - (2)].str), "0") == 0)
@@ -1941,8 +1957,8 @@ yyreduce:
        }
     break;
 
-  case 102:
-#line 212 "util/configparser.y"
+  case 103:
+#line 213 "util/configparser.y"
     {
                OUTYY(("P(server_statistics_cumulative:%s)\n", (yyvsp[(2) - (2)].str)));
                if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0)
@@ -1952,8 +1968,8 @@ yyreduce:
        }
     break;
 
-  case 103:
-#line 221 "util/configparser.y"
+  case 104:
+#line 222 "util/configparser.y"
     {
                OUTYY(("P(server_extended_statistics:%s)\n", (yyvsp[(2) - (2)].str)));
                if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0)
@@ -1963,8 +1979,8 @@ yyreduce:
        }
     break;
 
-  case 104:
-#line 230 "util/configparser.y"
+  case 105:
+#line 231 "util/configparser.y"
     {
                OUTYY(("P(server_port:%s)\n", (yyvsp[(2) - (2)].str)));
                if(atoi((yyvsp[(2) - (2)].str)) == 0)
@@ -1974,8 +1990,8 @@ yyreduce:
        }
     break;
 
-  case 105:
-#line 239 "util/configparser.y"
+  case 106:
+#line 240 "util/configparser.y"
     {
                OUTYY(("P(server_interface:%s)\n", (yyvsp[(2) - (2)].str)));
                if(cfg_parser->cfg->num_ifs == 0)
@@ -1989,8 +2005,8 @@ yyreduce:
        }
     break;
 
-  case 106:
-#line 252 "util/configparser.y"
+  case 107:
+#line 253 "util/configparser.y"
     {
                OUTYY(("P(server_outgoing_interface:%s)\n", (yyvsp[(2) - (2)].str)));
                if(cfg_parser->cfg->num_out_ifs == 0)
@@ -2006,8 +2022,8 @@ yyreduce:
        }
     break;
 
-  case 107:
-#line 267 "util/configparser.y"
+  case 108:
+#line 268 "util/configparser.y"
     {
                OUTYY(("P(server_outgoing_range:%s)\n", (yyvsp[(2) - (2)].str)));
                if(atoi((yyvsp[(2) - (2)].str)) == 0)
@@ -2017,8 +2033,8 @@ yyreduce:
        }
     break;
 
-  case 108:
-#line 276 "util/configparser.y"
+  case 109:
+#line 277 "util/configparser.y"
     {
                OUTYY(("P(server_outgoing_port_permit:%s)\n", (yyvsp[(2) - (2)].str)));
                if(!cfg_mark_ports((yyvsp[(2) - (2)].str), 1, 
@@ -2028,8 +2044,8 @@ yyreduce:
        }
     break;
 
-  case 109:
-#line 285 "util/configparser.y"
+  case 110:
+#line 286 "util/configparser.y"
     {
                OUTYY(("P(server_outgoing_port_avoid:%s)\n", (yyvsp[(2) - (2)].str)));
                if(!cfg_mark_ports((yyvsp[(2) - (2)].str), 0, 
@@ -2039,8 +2055,8 @@ yyreduce:
        }
     break;
 
-  case 110:
-#line 294 "util/configparser.y"
+  case 111:
+#line 295 "util/configparser.y"
     {
                OUTYY(("P(server_outgoing_num_tcp:%s)\n", (yyvsp[(2) - (2)].str)));
                if(atoi((yyvsp[(2) - (2)].str)) == 0 && strcmp((yyvsp[(2) - (2)].str), "0") != 0)
@@ -2050,8 +2066,8 @@ yyreduce:
        }
     break;
 
-  case 111:
-#line 303 "util/configparser.y"
+  case 112:
+#line 304 "util/configparser.y"
     {
                OUTYY(("P(server_incoming_num_tcp:%s)\n", (yyvsp[(2) - (2)].str)));
                if(atoi((yyvsp[(2) - (2)].str)) == 0 && strcmp((yyvsp[(2) - (2)].str), "0") != 0)
@@ -2061,8 +2077,8 @@ yyreduce:
        }
     break;
 
-  case 112:
-#line 312 "util/configparser.y"
+  case 113:
+#line 313 "util/configparser.y"
     {
                OUTYY(("P(server_interface_automatic:%s)\n", (yyvsp[(2) - (2)].str)));
                if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0)
@@ -2072,8 +2088,8 @@ yyreduce:
        }
     break;
 
-  case 113:
-#line 321 "util/configparser.y"
+  case 114:
+#line 322 "util/configparser.y"
     {
                OUTYY(("P(server_do_ip4:%s)\n", (yyvsp[(2) - (2)].str)));
                if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0)
@@ -2083,8 +2099,8 @@ yyreduce:
        }
     break;
 
-  case 114:
-#line 330 "util/configparser.y"
+  case 115:
+#line 331 "util/configparser.y"
     {
                OUTYY(("P(server_do_ip6:%s)\n", (yyvsp[(2) - (2)].str)));
                if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0)
@@ -2094,8 +2110,8 @@ yyreduce:
        }
     break;
 
-  case 115:
-#line 339 "util/configparser.y"
+  case 116:
+#line 340 "util/configparser.y"
     {
                OUTYY(("P(server_do_udp:%s)\n", (yyvsp[(2) - (2)].str)));
                if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0)
@@ -2105,8 +2121,8 @@ yyreduce:
        }
     break;
 
-  case 116:
-#line 348 "util/configparser.y"
+  case 117:
+#line 349 "util/configparser.y"
     {
                OUTYY(("P(server_do_tcp:%s)\n", (yyvsp[(2) - (2)].str)));
                if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0)
@@ -2116,8 +2132,8 @@ yyreduce:
        }
     break;
 
-  case 117:
-#line 357 "util/configparser.y"
+  case 118:
+#line 358 "util/configparser.y"
     {
                OUTYY(("P(server_do_daemonize:%s)\n", (yyvsp[(2) - (2)].str)));
                if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0)
@@ -2127,8 +2143,8 @@ yyreduce:
        }
     break;
 
-  case 118:
-#line 366 "util/configparser.y"
+  case 119:
+#line 367 "util/configparser.y"
     {
                OUTYY(("P(server_use_syslog:%s)\n", (yyvsp[(2) - (2)].str)));
                if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0)
@@ -2143,8 +2159,8 @@ yyreduce:
        }
     break;
 
-  case 119:
-#line 380 "util/configparser.y"
+  case 120:
+#line 381 "util/configparser.y"
     {
                OUTYY(("P(server_log_time_ascii:%s)\n", (yyvsp[(2) - (2)].str)));
                if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0)
@@ -2154,8 +2170,8 @@ yyreduce:
        }
     break;
 
-  case 120:
-#line 389 "util/configparser.y"
+  case 121:
+#line 390 "util/configparser.y"
     {
                OUTYY(("P(server_chroot:%s)\n", (yyvsp[(2) - (2)].str)));
                free(cfg_parser->cfg->chrootdir);
@@ -2163,8 +2179,8 @@ yyreduce:
        }
     break;
 
-  case 121:
-#line 396 "util/configparser.y"
+  case 122:
+#line 397 "util/configparser.y"
     {
                OUTYY(("P(server_username:%s)\n", (yyvsp[(2) - (2)].str)));
                free(cfg_parser->cfg->username);
@@ -2172,8 +2188,8 @@ yyreduce:
        }
     break;
 
-  case 122:
-#line 403 "util/configparser.y"
+  case 123:
+#line 404 "util/configparser.y"
     {
                OUTYY(("P(server_directory:%s)\n", (yyvsp[(2) - (2)].str)));
                free(cfg_parser->cfg->directory);
@@ -2181,8 +2197,8 @@ yyreduce:
        }
     break;
 
-  case 123:
-#line 410 "util/configparser.y"
+  case 124:
+#line 411 "util/configparser.y"
     {
                OUTYY(("P(server_logfile:%s)\n", (yyvsp[(2) - (2)].str)));
                free(cfg_parser->cfg->logfile);
@@ -2191,8 +2207,8 @@ yyreduce:
        }
     break;
 
-  case 124:
-#line 418 "util/configparser.y"
+  case 125:
+#line 419 "util/configparser.y"
     {
                OUTYY(("P(server_pidfile:%s)\n", (yyvsp[(2) - (2)].str)));
                free(cfg_parser->cfg->pidfile);
@@ -2200,8 +2216,8 @@ yyreduce:
        }
     break;
 
-  case 125:
-#line 425 "util/configparser.y"
+  case 126:
+#line 426 "util/configparser.y"
     {
                OUTYY(("P(server_root_hints:%s)\n", (yyvsp[(2) - (2)].str)));
                if(!cfg_strlist_insert(&cfg_parser->cfg->root_hints, (yyvsp[(2) - (2)].str)))
@@ -2209,8 +2225,8 @@ yyreduce:
        }
     break;
 
-  case 126:
-#line 432 "util/configparser.y"
+  case 127:
+#line 433 "util/configparser.y"
     {
                OUTYY(("P(server_dlv_anchor_file:%s)\n", (yyvsp[(2) - (2)].str)));
                free(cfg_parser->cfg->dlv_anchor_file);
@@ -2218,8 +2234,8 @@ yyreduce:
        }
     break;
 
-  case 127:
-#line 439 "util/configparser.y"
+  case 128:
+#line 440 "util/configparser.y"
     {
                OUTYY(("P(server_dlv_anchor:%s)\n", (yyvsp[(2) - (2)].str)));
                if(!cfg_strlist_insert(&cfg_parser->cfg->dlv_anchor_list, (yyvsp[(2) - (2)].str)))
@@ -2227,8 +2243,8 @@ yyreduce:
        }
     break;
 
-  case 128:
-#line 446 "util/configparser.y"
+  case 129:
+#line 447 "util/configparser.y"
     {
                OUTYY(("P(server_trust_anchor_file:%s)\n", (yyvsp[(2) - (2)].str)));
                if(!cfg_strlist_insert(&cfg_parser->cfg->
@@ -2237,8 +2253,8 @@ yyreduce:
        }
     break;
 
-  case 129:
-#line 454 "util/configparser.y"
+  case 130:
+#line 455 "util/configparser.y"
     {
                OUTYY(("P(server_trusted_keys_file:%s)\n", (yyvsp[(2) - (2)].str)));
                if(!cfg_strlist_insert(&cfg_parser->cfg->
@@ -2247,8 +2263,8 @@ yyreduce:
        }
     break;
 
-  case 130:
-#line 462 "util/configparser.y"
+  case 131:
+#line 463 "util/configparser.y"
     {
                OUTYY(("P(server_trust_anchor:%s)\n", (yyvsp[(2) - (2)].str)));
                if(!cfg_strlist_insert(&cfg_parser->cfg->trust_anchor_list, (yyvsp[(2) - (2)].str)))
@@ -2256,8 +2272,8 @@ yyreduce:
        }
     break;
 
-  case 131:
-#line 469 "util/configparser.y"
+  case 132:
+#line 470 "util/configparser.y"
     {
                OUTYY(("P(server_domain_insecure:%s)\n", (yyvsp[(2) - (2)].str)));
                if(!cfg_strlist_insert(&cfg_parser->cfg->domain_insecure, (yyvsp[(2) - (2)].str)))
@@ -2265,8 +2281,8 @@ yyreduce:
        }
     break;
 
-  case 132:
-#line 476 "util/configparser.y"
+  case 133:
+#line 477 "util/configparser.y"
     {
                OUTYY(("P(server_hide_identity:%s)\n", (yyvsp[(2) - (2)].str)));
                if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0)
@@ -2276,8 +2292,8 @@ yyreduce:
        }
     break;
 
-  case 133:
-#line 485 "util/configparser.y"
+  case 134:
+#line 486 "util/configparser.y"
     {
                OUTYY(("P(server_hide_version:%s)\n", (yyvsp[(2) - (2)].str)));
                if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0)
@@ -2287,8 +2303,8 @@ yyreduce:
        }
     break;
 
-  case 134:
-#line 494 "util/configparser.y"
+  case 135:
+#line 495 "util/configparser.y"
     {
                OUTYY(("P(server_identity:%s)\n", (yyvsp[(2) - (2)].str)));
                free(cfg_parser->cfg->identity);
@@ -2296,8 +2312,8 @@ yyreduce:
        }
     break;
 
-  case 135:
-#line 501 "util/configparser.y"
+  case 136:
+#line 502 "util/configparser.y"
     {
                OUTYY(("P(server_version:%s)\n", (yyvsp[(2) - (2)].str)));
                free(cfg_parser->cfg->version);
@@ -2305,8 +2321,8 @@ yyreduce:
        }
     break;
 
-  case 136:
-#line 508 "util/configparser.y"
+  case 137:
+#line 509 "util/configparser.y"
     {
                OUTYY(("P(server_msg_buffer_size:%s)\n", (yyvsp[(2) - (2)].str)));
                if(atoi((yyvsp[(2) - (2)].str)) == 0)
@@ -2318,8 +2334,8 @@ yyreduce:
        }
     break;
 
-  case 137:
-#line 519 "util/configparser.y"
+  case 138:
+#line 520 "util/configparser.y"
     {
                OUTYY(("P(server_msg_cache_size:%s)\n", (yyvsp[(2) - (2)].str)));
                if(!cfg_parse_memsize((yyvsp[(2) - (2)].str), &cfg_parser->cfg->msg_cache_size))
@@ -2328,8 +2344,8 @@ yyreduce:
        }
     break;
 
-  case 138:
-#line 527 "util/configparser.y"
+  case 139:
+#line 528 "util/configparser.y"
     {
                OUTYY(("P(server_msg_cache_slabs:%s)\n", (yyvsp[(2) - (2)].str)));
                if(atoi((yyvsp[(2) - (2)].str)) == 0)
@@ -2343,8 +2359,8 @@ yyreduce:
        }
     break;
 
-  case 139:
-#line 540 "util/configparser.y"
+  case 140:
+#line 541 "util/configparser.y"
     {
                OUTYY(("P(server_num_queries_per_thread:%s)\n", (yyvsp[(2) - (2)].str)));
                if(atoi((yyvsp[(2) - (2)].str)) == 0)
@@ -2354,8 +2370,8 @@ yyreduce:
        }
     break;
 
-  case 140:
-#line 549 "util/configparser.y"
+  case 141:
+#line 550 "util/configparser.y"
     {
                OUTYY(("P(server_jostle_timeout:%s)\n", (yyvsp[(2) - (2)].str)));
                if(atoi((yyvsp[(2) - (2)].str)) == 0 && strcmp((yyvsp[(2) - (2)].str), "0") != 0)
@@ -2365,8 +2381,8 @@ yyreduce:
        }
     break;
 
-  case 141:
-#line 558 "util/configparser.y"
+  case 142:
+#line 559 "util/configparser.y"
     {
                OUTYY(("P(server_rrset_cache_size:%s)\n", (yyvsp[(2) - (2)].str)));
                if(!cfg_parse_memsize((yyvsp[(2) - (2)].str), &cfg_parser->cfg->rrset_cache_size))
@@ -2375,8 +2391,8 @@ yyreduce:
        }
     break;
 
-  case 142:
-#line 566 "util/configparser.y"
+  case 143:
+#line 567 "util/configparser.y"
     {
                OUTYY(("P(server_rrset_cache_slabs:%s)\n", (yyvsp[(2) - (2)].str)));
                if(atoi((yyvsp[(2) - (2)].str)) == 0)
@@ -2390,8 +2406,8 @@ yyreduce:
        }
     break;
 
-  case 143:
-#line 579 "util/configparser.y"
+  case 144:
+#line 580 "util/configparser.y"
     {
                OUTYY(("P(server_infra_host_ttl:%s)\n", (yyvsp[(2) - (2)].str)));
                if(atoi((yyvsp[(2) - (2)].str)) == 0 && strcmp((yyvsp[(2) - (2)].str), "0") != 0)
@@ -2401,8 +2417,8 @@ yyreduce:
        }
     break;
 
-  case 144:
-#line 588 "util/configparser.y"
+  case 145:
+#line 589 "util/configparser.y"
     {
                OUTYY(("P(server_infra_lame_ttl:%s)\n", (yyvsp[(2) - (2)].str)));
                if(atoi((yyvsp[(2) - (2)].str)) == 0 && strcmp((yyvsp[(2) - (2)].str), "0") != 0)
@@ -2412,8 +2428,8 @@ yyreduce:
        }
     break;
 
-  case 145:
-#line 597 "util/configparser.y"
+  case 146:
+#line 598 "util/configparser.y"
     {
                OUTYY(("P(server_infra_cache_numhosts:%s)\n", (yyvsp[(2) - (2)].str)));
                if(atoi((yyvsp[(2) - (2)].str)) == 0)
@@ -2423,8 +2439,8 @@ yyreduce:
        }
     break;
 
-  case 146:
-#line 606 "util/configparser.y"
+  case 147:
+#line 607 "util/configparser.y"
     {
                OUTYY(("P(server_infra_cache_lame_size:%s)\n", (yyvsp[(2) - (2)].str)));
                if(!cfg_parse_memsize((yyvsp[(2) - (2)].str), &cfg_parser->cfg->
@@ -2434,8 +2450,8 @@ yyreduce:
        }
     break;
 
-  case 147:
-#line 615 "util/configparser.y"
+  case 148:
+#line 616 "util/configparser.y"
     {
                OUTYY(("P(server_infra_cache_slabs:%s)\n", (yyvsp[(2) - (2)].str)));
                if(atoi((yyvsp[(2) - (2)].str)) == 0)
@@ -2449,8 +2465,8 @@ yyreduce:
        }
     break;
 
-  case 148:
-#line 628 "util/configparser.y"
+  case 149:
+#line 629 "util/configparser.y"
     {
                OUTYY(("P(server_target_fetch_policy:%s)\n", (yyvsp[(2) - (2)].str)));
                free(cfg_parser->cfg->target_fetch_policy);
@@ -2458,8 +2474,8 @@ yyreduce:
        }
     break;
 
-  case 149:
-#line 635 "util/configparser.y"
+  case 150:
+#line 636 "util/configparser.y"
     {
                OUTYY(("P(server_harden_short_bufsize:%s)\n", (yyvsp[(2) - (2)].str)));
                if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0)
@@ -2470,8 +2486,8 @@ yyreduce:
        }
     break;
 
-  case 150:
-#line 645 "util/configparser.y"
+  case 151:
+#line 646 "util/configparser.y"
     {
                OUTYY(("P(server_harden_large_queries:%s)\n", (yyvsp[(2) - (2)].str)));
                if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0)
@@ -2482,8 +2498,8 @@ yyreduce:
        }
     break;
 
-  case 151:
-#line 655 "util/configparser.y"
+  case 152:
+#line 656 "util/configparser.y"
     {
                OUTYY(("P(server_harden_glue:%s)\n", (yyvsp[(2) - (2)].str)));
                if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0)
@@ -2494,8 +2510,8 @@ yyreduce:
        }
     break;
 
-  case 152:
-#line 665 "util/configparser.y"
+  case 153:
+#line 666 "util/configparser.y"
     {
                OUTYY(("P(server_harden_dnssec_stripped:%s)\n", (yyvsp[(2) - (2)].str)));
                if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0)
@@ -2506,8 +2522,8 @@ yyreduce:
        }
     break;
 
-  case 153:
-#line 675 "util/configparser.y"
+  case 154:
+#line 676 "util/configparser.y"
     {
                OUTYY(("P(server_harden_referral_path:%s)\n", (yyvsp[(2) - (2)].str)));
                if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0)
@@ -2518,8 +2534,8 @@ yyreduce:
        }
     break;
 
-  case 154:
-#line 685 "util/configparser.y"
+  case 155:
+#line 686 "util/configparser.y"
     {
                OUTYY(("P(server_use_caps_for_id:%s)\n", (yyvsp[(2) - (2)].str)));
                if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0)
@@ -2530,8 +2546,8 @@ yyreduce:
        }
     break;
 
-  case 155:
-#line 695 "util/configparser.y"
+  case 156:
+#line 696 "util/configparser.y"
     {
                OUTYY(("P(server_private_address:%s)\n", (yyvsp[(2) - (2)].str)));
                if(!cfg_strlist_insert(&cfg_parser->cfg->private_address, (yyvsp[(2) - (2)].str)))
@@ -2539,8 +2555,8 @@ yyreduce:
        }
     break;
 
-  case 156:
-#line 702 "util/configparser.y"
+  case 157:
+#line 703 "util/configparser.y"
     {
                OUTYY(("P(server_private_domain:%s)\n", (yyvsp[(2) - (2)].str)));
                if(!cfg_strlist_insert(&cfg_parser->cfg->private_domain, (yyvsp[(2) - (2)].str)))
@@ -2548,8 +2564,8 @@ yyreduce:
        }
     break;
 
-  case 157:
-#line 709 "util/configparser.y"
+  case 158:
+#line 710 "util/configparser.y"
     {
                OUTYY(("P(server_unwanted_reply_threshold:%s)\n", (yyvsp[(2) - (2)].str)));
                if(atoi((yyvsp[(2) - (2)].str)) == 0 && strcmp((yyvsp[(2) - (2)].str), "0") != 0)
@@ -2559,8 +2575,8 @@ yyreduce:
        }
     break;
 
-  case 158:
-#line 718 "util/configparser.y"
+  case 159:
+#line 719 "util/configparser.y"
     {
                OUTYY(("P(server_do_not_query_address:%s)\n", (yyvsp[(2) - (2)].str)));
                if(!cfg_strlist_insert(&cfg_parser->cfg->donotqueryaddrs, (yyvsp[(2) - (2)].str)))
@@ -2568,8 +2584,8 @@ yyreduce:
        }
     break;
 
-  case 159:
-#line 725 "util/configparser.y"
+  case 160:
+#line 726 "util/configparser.y"
     {
                OUTYY(("P(server_do_not_query_localhost:%s)\n", (yyvsp[(2) - (2)].str)));
                if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0)
@@ -2580,8 +2596,8 @@ yyreduce:
        }
     break;
 
-  case 160:
-#line 735 "util/configparser.y"
+  case 161:
+#line 736 "util/configparser.y"
     {
                OUTYY(("P(server_access_control:%s %s)\n", (yyvsp[(2) - (3)].str), (yyvsp[(3) - (3)].str)));
                if(strcmp((yyvsp[(3) - (3)].str), "deny")!=0 && strcmp((yyvsp[(3) - (3)].str), "refuse")!=0 &&
@@ -2596,8 +2612,8 @@ yyreduce:
        }
     break;
 
-  case 161:
-#line 749 "util/configparser.y"
+  case 162:
+#line 750 "util/configparser.y"
     {
                OUTYY(("P(server_module_conf:%s)\n", (yyvsp[(2) - (2)].str)));
                free(cfg_parser->cfg->module_conf);
@@ -2605,8 +2621,8 @@ yyreduce:
        }
     break;
 
-  case 162:
-#line 756 "util/configparser.y"
+  case 163:
+#line 757 "util/configparser.y"
     {
                OUTYY(("P(server_val_override_date:%s)\n", (yyvsp[(2) - (2)].str)));
                if(strlen((yyvsp[(2) - (2)].str)) == 0 || strcmp((yyvsp[(2) - (2)].str), "0") == 0) {
@@ -2625,8 +2641,8 @@ yyreduce:
        }
     break;
 
-  case 163:
-#line 774 "util/configparser.y"
+  case 164:
+#line 775 "util/configparser.y"
     {
                OUTYY(("P(server_cache_max_ttl:%s)\n", (yyvsp[(2) - (2)].str)));
                if(atoi((yyvsp[(2) - (2)].str)) == 0 && strcmp((yyvsp[(2) - (2)].str), "0") != 0)
@@ -2636,8 +2652,8 @@ yyreduce:
        }
     break;
 
-  case 164:
-#line 783 "util/configparser.y"
+  case 165:
+#line 784 "util/configparser.y"
     {
                OUTYY(("P(server_bogus_ttl:%s)\n", (yyvsp[(2) - (2)].str)));
                if(atoi((yyvsp[(2) - (2)].str)) == 0 && strcmp((yyvsp[(2) - (2)].str), "0") != 0)
@@ -2647,8 +2663,8 @@ yyreduce:
        }
     break;
 
-  case 165:
-#line 792 "util/configparser.y"
+  case 166:
+#line 793 "util/configparser.y"
     {
                OUTYY(("P(server_val_clean_additional:%s)\n", (yyvsp[(2) - (2)].str)));
                if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0)
@@ -2659,8 +2675,8 @@ yyreduce:
        }
     break;
 
-  case 166:
-#line 802 "util/configparser.y"
+  case 167:
+#line 803 "util/configparser.y"
     {
                OUTYY(("P(server_val_permissive_mode:%s)\n", (yyvsp[(2) - (2)].str)));
                if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0)
@@ -2671,8 +2687,8 @@ yyreduce:
        }
     break;
 
-  case 167:
-#line 812 "util/configparser.y"
+  case 168:
+#line 813 "util/configparser.y"
     {
                OUTYY(("P(server_val_nsec3_keysize_iterations:%s)\n", (yyvsp[(2) - (2)].str)));
                free(cfg_parser->cfg->val_nsec3_key_iterations);
@@ -2680,8 +2696,8 @@ yyreduce:
        }
     break;
 
-  case 168:
-#line 819 "util/configparser.y"
+  case 169:
+#line 820 "util/configparser.y"
     {
                OUTYY(("P(server_key_cache_size:%s)\n", (yyvsp[(2) - (2)].str)));
                if(!cfg_parse_memsize((yyvsp[(2) - (2)].str), &cfg_parser->cfg->key_cache_size))
@@ -2690,8 +2706,8 @@ yyreduce:
        }
     break;
 
-  case 169:
-#line 827 "util/configparser.y"
+  case 170:
+#line 828 "util/configparser.y"
     {
                OUTYY(("P(server_key_cache_slabs:%s)\n", (yyvsp[(2) - (2)].str)));
                if(atoi((yyvsp[(2) - (2)].str)) == 0)
@@ -2705,8 +2721,8 @@ yyreduce:
        }
     break;
 
-  case 170:
-#line 840 "util/configparser.y"
+  case 171:
+#line 841 "util/configparser.y"
     {
                OUTYY(("P(server_neg_cache_size:%s)\n", (yyvsp[(2) - (2)].str)));
                if(!cfg_parse_memsize((yyvsp[(2) - (2)].str), &cfg_parser->cfg->neg_cache_size))
@@ -2715,8 +2731,8 @@ yyreduce:
        }
     break;
 
-  case 171:
-#line 848 "util/configparser.y"
+  case 172:
+#line 849 "util/configparser.y"
     {
                OUTYY(("P(server_local_zone:%s %s)\n", (yyvsp[(2) - (3)].str), (yyvsp[(3) - (3)].str)));
                if(strcmp((yyvsp[(3) - (3)].str), "static")!=0 && strcmp((yyvsp[(3) - (3)].str), "deny")!=0 &&
@@ -2737,8 +2753,8 @@ yyreduce:
        }
     break;
 
-  case 172:
-#line 868 "util/configparser.y"
+  case 173:
+#line 869 "util/configparser.y"
     {
                OUTYY(("P(server_local_data:%s)\n", (yyvsp[(2) - (2)].str)));
                if(!cfg_strlist_insert(&cfg_parser->cfg->local_data, (yyvsp[(2) - (2)].str)))
@@ -2746,8 +2762,8 @@ yyreduce:
        }
     break;
 
-  case 173:
-#line 875 "util/configparser.y"
+  case 174:
+#line 876 "util/configparser.y"
     {
                char* ptr;
                OUTYY(("P(server_local_data_ptr:%s)\n", (yyvsp[(2) - (2)].str)));
@@ -2763,8 +2779,8 @@ yyreduce:
        }
     break;
 
-  case 174:
-#line 890 "util/configparser.y"
+  case 175:
+#line 891 "util/configparser.y"
     {
                OUTYY(("P(name:%s)\n", (yyvsp[(2) - (2)].str)));
                free(cfg_parser->cfg->stubs->name);
@@ -2772,8 +2788,8 @@ yyreduce:
        }
     break;
 
-  case 175:
-#line 897 "util/configparser.y"
+  case 176:
+#line 898 "util/configparser.y"
     {
                OUTYY(("P(stub-host:%s)\n", (yyvsp[(2) - (2)].str)));
                if(!cfg_strlist_insert(&cfg_parser->cfg->stubs->hosts, (yyvsp[(2) - (2)].str)))
@@ -2781,8 +2797,8 @@ yyreduce:
        }
     break;
 
-  case 176:
-#line 904 "util/configparser.y"
+  case 177:
+#line 905 "util/configparser.y"
     {
                OUTYY(("P(stub-addr:%s)\n", (yyvsp[(2) - (2)].str)));
                if(!cfg_strlist_insert(&cfg_parser->cfg->stubs->addrs, (yyvsp[(2) - (2)].str)))
@@ -2790,8 +2806,8 @@ yyreduce:
        }
     break;
 
-  case 177:
-#line 911 "util/configparser.y"
+  case 178:
+#line 912 "util/configparser.y"
     {
                OUTYY(("P(stub-prime:%s)\n", (yyvsp[(2) - (2)].str)));
                if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0)
@@ -2802,8 +2818,8 @@ yyreduce:
        }
     break;
 
-  case 178:
-#line 921 "util/configparser.y"
+  case 179:
+#line 922 "util/configparser.y"
     {
                OUTYY(("P(name:%s)\n", (yyvsp[(2) - (2)].str)));
                free(cfg_parser->cfg->forwards->name);
@@ -2811,8 +2827,8 @@ yyreduce:
        }
     break;
 
-  case 179:
-#line 928 "util/configparser.y"
+  case 180:
+#line 929 "util/configparser.y"
     {
                OUTYY(("P(forward-host:%s)\n", (yyvsp[(2) - (2)].str)));
                if(!cfg_strlist_insert(&cfg_parser->cfg->forwards->hosts, (yyvsp[(2) - (2)].str)))
@@ -2820,8 +2836,8 @@ yyreduce:
        }
     break;
 
-  case 180:
-#line 935 "util/configparser.y"
+  case 181:
+#line 936 "util/configparser.y"
     {
                OUTYY(("P(forward-addr:%s)\n", (yyvsp[(2) - (2)].str)));
                if(!cfg_strlist_insert(&cfg_parser->cfg->forwards->addrs, (yyvsp[(2) - (2)].str)))
@@ -2829,15 +2845,15 @@ yyreduce:
        }
     break;
 
-  case 181:
-#line 942 "util/configparser.y"
+  case 182:
+#line 943 "util/configparser.y"
     { 
                OUTYY(("\nP(remote-control:)\n")); 
        }
     break;
 
-  case 191:
-#line 953 "util/configparser.y"
+  case 192:
+#line 954 "util/configparser.y"
     {
                OUTYY(("P(control_enable:%s)\n", (yyvsp[(2) - (2)].str)));
                if(strcmp((yyvsp[(2) - (2)].str), "yes") != 0 && strcmp((yyvsp[(2) - (2)].str), "no") != 0)
@@ -2848,8 +2864,8 @@ yyreduce:
        }
     break;
 
-  case 192:
-#line 963 "util/configparser.y"
+  case 193:
+#line 964 "util/configparser.y"
     {
                OUTYY(("P(control_port:%s)\n", (yyvsp[(2) - (2)].str)));
                if(atoi((yyvsp[(2) - (2)].str)) == 0)
@@ -2859,8 +2875,8 @@ yyreduce:
        }
     break;
 
-  case 193:
-#line 972 "util/configparser.y"
+  case 194:
+#line 973 "util/configparser.y"
     {
                OUTYY(("P(control_interface:%s)\n", (yyvsp[(2) - (2)].str)));
                if(!cfg_strlist_insert(&cfg_parser->cfg->control_ifs, (yyvsp[(2) - (2)].str)))
@@ -2868,8 +2884,8 @@ yyreduce:
        }
     break;
 
-  case 194:
-#line 979 "util/configparser.y"
+  case 195:
+#line 980 "util/configparser.y"
     {
                OUTYY(("P(rc_server_key_file:%s)\n", (yyvsp[(2) - (2)].str)));
                free(cfg_parser->cfg->server_key_file);
@@ -2877,8 +2893,8 @@ yyreduce:
        }
     break;
 
-  case 195:
-#line 986 "util/configparser.y"
+  case 196:
+#line 987 "util/configparser.y"
     {
                OUTYY(("P(rc_server_cert_file:%s)\n", (yyvsp[(2) - (2)].str)));
                free(cfg_parser->cfg->server_cert_file);
@@ -2886,8 +2902,8 @@ yyreduce:
        }
     break;
 
-  case 196:
-#line 993 "util/configparser.y"
+  case 197:
+#line 994 "util/configparser.y"
     {
                OUTYY(("P(rc_control_key_file:%s)\n", (yyvsp[(2) - (2)].str)));
                free(cfg_parser->cfg->control_key_file);
@@ -2895,8 +2911,8 @@ yyreduce:
        }
     break;
 
-  case 197:
-#line 1000 "util/configparser.y"
+  case 198:
+#line 1001 "util/configparser.y"
     {
                OUTYY(("P(rc_control_cert_file:%s)\n", (yyvsp[(2) - (2)].str)));
                free(cfg_parser->cfg->control_cert_file);
@@ -2904,9 +2920,25 @@ yyreduce:
        }
     break;
 
+  case 199:
+#line 1008 "util/configparser.y"
+    { 
+               OUTYY(("\nP(python:)\n")); 
+       }
+    break;
+
+  case 203:
+#line 1017 "util/configparser.y"
+    {
+               OUTYY(("P(python-script:%s)\n", (yyvsp[(2) - (2)].str)));
+               free(cfg_parser->cfg->python_script);
+               cfg_parser->cfg->python_script = (yyvsp[(2) - (2)].str);
+       }
+    break;
+
 
 /* Line 1267 of yacc.c.  */
-#line 2910 "util/configparser.c"
+#line 2942 "util/configparser.c"
       default: break;
     }
   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -3120,7 +3152,7 @@ yyreturn:
 }
 
 
-#line 1006 "util/configparser.y"
+#line 1022 "util/configparser.y"
 
 
 /* parse helper routines could be here */
index 47f8a887f131c193c32302784712f19eaec99540..1112a9f3498510cdaf69ae613aa173fa6c3ecf47 100644 (file)
      VAR_STUB_PRIME = 354,
      VAR_UNWANTED_REPLY_THRESHOLD = 355,
      VAR_LOG_TIME_ASCII = 356,
-     VAR_DOMAIN_INSECURE = 357
+     VAR_DOMAIN_INSECURE = 357,
+     VAR_PYTHON = 358,
+     VAR_PYTHON_SCRIPT = 359
    };
 #endif
 /* Tokens.  */
 #define VAR_UNWANTED_REPLY_THRESHOLD 355
 #define VAR_LOG_TIME_ASCII 356
 #define VAR_DOMAIN_INSECURE 357
+#define VAR_PYTHON 358
+#define VAR_PYTHON_SCRIPT 359
 
 
 
@@ -253,7 +257,7 @@ typedef union YYSTYPE
        char*   str;
 }
 /* Line 1489 of yacc.c.  */
-#line 257 "util/configparser.h"
+#line 261 "util/configparser.h"
        YYSTYPE;
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
index 230c3d83853dfed045f4e78cfc28b0aff103e2b1..85c9e78a5daca4b65df891ba9e9c3608ab6b19ed 100644 (file)
@@ -97,12 +97,13 @@ extern struct config_parser_state* cfg_parser;
 %token VAR_SERVER_CERT_FILE VAR_CONTROL_KEY_FILE VAR_CONTROL_CERT_FILE
 %token VAR_EXTENDED_STATISTICS VAR_LOCAL_DATA_PTR VAR_JOSTLE_TIMEOUT
 %token VAR_STUB_PRIME VAR_UNWANTED_REPLY_THRESHOLD VAR_LOG_TIME_ASCII
-%token VAR_DOMAIN_INSECURE
+%token VAR_DOMAIN_INSECURE VAR_PYTHON VAR_PYTHON_SCRIPT
 
 %%
 toplevelvars: /* empty */ | toplevelvars toplevelvar ;
 toplevelvar: serverstart contents_server | stubstart contents_stub |
-       forwardstart contents_forward | rcstart contents_rc
+       forwardstart contents_forward | pythonstart contents_py | 
+       rcstart contents_rc
        ;
 
 /* server: declaration */
@@ -1003,6 +1004,21 @@ rc_control_cert_file: VAR_CONTROL_CERT_FILE STRING
                cfg_parser->cfg->control_cert_file = $2;
        }
        ;
+pythonstart: VAR_PYTHON
+       { 
+               OUTYY(("\nP(python:)\n")); 
+       }
+       ;
+contents_py: contents_py content_py
+       | ;
+content_py: py_script
+       ;
+py_script: VAR_PYTHON_SCRIPT STRING
+       {
+               OUTYY(("P(python-script:%s)\n", $2));
+               free(cfg_parser->cfg->python_script);
+               cfg_parser->cfg->python_script = $2;
+       }
 %%
 
 /* parse helper routines could be here */
index b46818a934cf841ef1066f64afb822fadbe08ff6..b98719843d5b545887fb21adf2751501ca4f8a9f 100644 (file)
@@ -719,7 +719,7 @@ reply_info_answer_encode(struct query_info* qinf, struct reply_info* rep,
        uint16_t flags;
        int attach_edns = 1;
 
-       if(!cached) {
+       if(!cached || rep->authoritative) {
                /* original flags, copy RD and CD bits from query. */
                flags = rep->flags | (qflags & (BIT_RD|BIT_CD)); 
        } else {
index 888571e3e473a10f2ba873b7f53eecf86fc9837b..1d02c38db76f86947ca45fc6ef1983379c145af7 100644 (file)
@@ -97,6 +97,7 @@ construct_reply_info_base(struct regional* region, uint16_t flags, size_t qd,
        rep->ar_numrrsets = ar;
        rep->rrset_count = total;
        rep->security = sec;
+       rep->authoritative = 0;
        /* array starts after the refs */
        if(region)
                rep->rrsets = (struct ub_packed_rrset_key**)&(rep->ref[0]);
index 3d17cbe4088e4c8904379f4b26830bafefc61796..87570e6226c312258a9ba32b25e4fc1b97663781 100644 (file)
@@ -98,13 +98,19 @@ struct reply_info {
        /** the flags for the answer, host byte order. */
        uint16_t flags;
 
+       /**
+        * This flag informs unbound the answer is authoritative and 
+        * the AA flag should be preserved. 
+        */
+       uint8_t authoritative;
+
        /**
         * Number of RRs in the query section.
         * If qdcount is not 0, then it is 1, and the data that appears
         * in the reply is the same as the query_info.
         * Host byte order.
         */
-       uint16_t qdcount;
+       uint8_t qdcount;
 
        /** 
         * TTL of the entire reply (for negative caching).
@@ -127,8 +133,7 @@ struct reply_info {
        size_t an_numrrsets;
 
        /** Count of authority section RRsets */
-       size_t ns_numrrsets;
-
+       size_t ns_numrrsets; 
        /** Count of additional section RRsets */
        size_t ar_numrrsets;
 
index 6bae9fb3f70daebe4164014fe503b45509bcce6f..189809b22a4bd3ac080506783ac44feb526464a5 100644 (file)
 #include "winrc/win_svc.h"
 #endif
 
+#ifdef WITH_PYTHONMODULE
+#include "pythonmod/pythonmod.h"
+#endif
+
 int 
 fptr_whitelist_comm_point(comm_point_callback_t *fptr)
 {
@@ -295,6 +299,9 @@ fptr_whitelist_mod_init(int (*fptr)(struct module_env* env, int id))
 {
        if(fptr == &iter_init) return 1;
        else if(fptr == &val_init) return 1;
+#ifdef WITH_PYTHONMODULE
+       else if(fptr == &pythonmod_init) return 1;
+#endif
        return 0;
 }
 
@@ -303,6 +310,9 @@ fptr_whitelist_mod_deinit(void (*fptr)(struct module_env* env, int id))
 {
        if(fptr == &iter_deinit) return 1;
        else if(fptr == &val_deinit) return 1;
+#ifdef WITH_PYTHONMODULE
+       else if(fptr == &pythonmod_deinit) return 1;
+#endif
        return 0;
 }
 
@@ -312,6 +322,9 @@ fptr_whitelist_mod_operate(void (*fptr)(struct module_qstate* qstate,
 {
        if(fptr == &iter_operate) return 1;
        else if(fptr == &val_operate) return 1;
+#ifdef WITH_PYTHONMODULE
+       else if(fptr == &pythonmod_operate) return 1;
+#endif
        return 0;
 }
 
@@ -321,6 +334,9 @@ fptr_whitelist_mod_inform_super(void (*fptr)(
 {
        if(fptr == &iter_inform_super) return 1;
        else if(fptr == &val_inform_super) return 1;
+#ifdef WITH_PYTHONMODULE
+       else if(fptr == &pythonmod_inform_super) return 1;
+#endif
        return 0;
 }
 
@@ -330,6 +346,9 @@ fptr_whitelist_mod_clear(void (*fptr)(struct module_qstate* qstate,
 {
        if(fptr == &iter_clear) return 1;
        else if(fptr == &val_clear) return 1;
+#ifdef WITH_PYTHONMODULE
+       else if(fptr == &pythonmod_clear) return 1;
+#endif
        return 0;
 }
 
@@ -338,6 +357,9 @@ fptr_whitelist_mod_get_mem(size_t (*fptr)(struct module_env* env, int id))
 {
        if(fptr == &iter_get_mem) return 1;
        else if(fptr == &val_get_mem) return 1;
+#ifdef WITH_PYTHONMODULE
+       else if(fptr == &pythonmod_get_mem) return 1;
+#endif
        return 0;
 }