aboutsummaryrefslogtreecommitdiff
path: root/contrib/unbound/libunbound/python
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/unbound/libunbound/python')
-rw-r--r--contrib/unbound/libunbound/python/LICENSE28
-rw-r--r--contrib/unbound/libunbound/python/Makefile75
-rw-r--r--contrib/unbound/libunbound/python/doc/_static/readme1
-rw-r--r--contrib/unbound/libunbound/python/doc/conf.py181
-rw-r--r--contrib/unbound/libunbound/python/doc/examples/example1a.rst26
-rw-r--r--contrib/unbound/libunbound/python/doc/examples/example1b.rst33
-rw-r--r--contrib/unbound/libunbound/python/doc/examples/example2.rst41
-rw-r--r--contrib/unbound/libunbound/python/doc/examples/example3.rst36
-rw-r--r--contrib/unbound/libunbound/python/doc/examples/example4.rst34
-rw-r--r--contrib/unbound/libunbound/python/doc/examples/example5.rst29
-rw-r--r--contrib/unbound/libunbound/python/doc/examples/example6-1.py27
-rw-r--r--contrib/unbound/libunbound/python/doc/examples/example6.rst11
-rw-r--r--contrib/unbound/libunbound/python/doc/examples/example7-1.py17
-rw-r--r--contrib/unbound/libunbound/python/doc/examples/example7-2.py16
-rw-r--r--contrib/unbound/libunbound/python/doc/examples/example7.rst18
-rw-r--r--contrib/unbound/libunbound/python/doc/examples/example8-1.py31
-rw-r--r--contrib/unbound/libunbound/python/doc/examples/example8.rst28
-rw-r--r--contrib/unbound/libunbound/python/doc/examples/index.rst14
-rw-r--r--contrib/unbound/libunbound/python/doc/index.rst27
-rw-r--r--contrib/unbound/libunbound/python/doc/install.rst31
-rw-r--r--contrib/unbound/libunbound/python/doc/intro.rst39
-rw-r--r--contrib/unbound/libunbound/python/doc/modules/unbound.rst167
-rw-r--r--contrib/unbound/libunbound/python/examples/async-lookup.py56
-rw-r--r--contrib/unbound/libunbound/python/examples/dns-lookup.py44
-rw-r--r--contrib/unbound/libunbound/python/examples/dnssec-valid.py59
-rw-r--r--contrib/unbound/libunbound/python/examples/dnssec_test.py35
-rw-r--r--contrib/unbound/libunbound/python/examples/example8-1.py61
-rw-r--r--contrib/unbound/libunbound/python/examples/idn-lookup.py62
-rw-r--r--contrib/unbound/libunbound/python/examples/mx-lookup.py53
-rw-r--r--contrib/unbound/libunbound/python/examples/ns-lookup.py47
-rw-r--r--contrib/unbound/libunbound/python/examples/reverse-lookup.py43
-rw-r--r--contrib/unbound/libunbound/python/libunbound.i941
32 files changed, 2311 insertions, 0 deletions
diff --git a/contrib/unbound/libunbound/python/LICENSE b/contrib/unbound/libunbound/python/LICENSE
new file mode 100644
index 000000000000..7b769d091201
--- /dev/null
+++ b/contrib/unbound/libunbound/python/LICENSE
@@ -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/unbound/libunbound/python/Makefile b/contrib/unbound/libunbound/python/Makefile
new file mode 100644
index 000000000000..86ba1774707a
--- /dev/null
+++ b/contrib/unbound/libunbound/python/Makefile
@@ -0,0 +1,75 @@
+#
+# 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.2 ../../ldns-src/lib/libldns.so ../../.libs/_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.2 unbound/libunbound.so.2 && ln -s ../../../../ldns-src/lib/libldns.so.1 unbound/libldns.so.1 && ls -la
+ cd examples && if test -f ../../../.libs/_unbound.so; then cp ../../../.libs/_unbound.so . ; fi
+ @echo "Run a script by typing ./script_name.py"
+ cd examples && LD_LIBRARY_PATH=unbound bash
+ rm -rdf examples/unbound examples/_unbound.so
+
+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
+ gcc -shared libunbound_wrap.o -L../../.libs -lunbound -o _unbound.so
+
diff --git a/contrib/unbound/libunbound/python/doc/_static/readme b/contrib/unbound/libunbound/python/doc/_static/readme
new file mode 100644
index 000000000000..db676aebbde9
--- /dev/null
+++ b/contrib/unbound/libunbound/python/doc/_static/readme
@@ -0,0 +1 @@
+this directory exists to pacify sphinx-build.
diff --git a/contrib/unbound/libunbound/python/doc/conf.py b/contrib/unbound/libunbound/python/doc/conf.py
new file mode 100644
index 000000000000..97fca2125f83
--- /dev/null
+++ b/contrib/unbound/libunbound/python/doc/conf.py
@@ -0,0 +1,181 @@
+# -*- 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__),'../')))
+sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__),'../../../')))
+sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__),'../../../.libs/')))
+#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/unbound/libunbound/python/doc/examples/example1a.rst b/contrib/unbound/libunbound/python/doc/examples/example1a.rst
new file mode 100644
index 000000000000..3c81547f2948
--- /dev/null
+++ b/contrib/unbound/libunbound/python/doc/examples/example1a.rst
@@ -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/unbound/libunbound/python/doc/examples/example1b.rst b/contrib/unbound/libunbound/python/doc/examples/example1b.rst
new file mode 100644
index 000000000000..ea1e6f57de65
--- /dev/null
+++ b/contrib/unbound/libunbound/python/doc/examples/example1b.rst
@@ -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/unbound/libunbound/python/doc/examples/example2.rst b/contrib/unbound/libunbound/python/doc/examples/example2.rst
new file mode 100644
index 000000000000..c009ec1f5ae7
--- /dev/null
+++ b/contrib/unbound/libunbound/python/doc/examples/example2.rst
@@ -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/unbound/libunbound/python/doc/examples/example3.rst b/contrib/unbound/libunbound/python/doc/examples/example3.rst
new file mode 100644
index 000000000000..91360335c63a
--- /dev/null
+++ b/contrib/unbound/libunbound/python/doc/examples/example3.rst
@@ -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/unbound/libunbound/python/doc/examples/example4.rst b/contrib/unbound/libunbound/python/doc/examples/example4.rst
new file mode 100644
index 000000000000..996ef4ede924
--- /dev/null
+++ b/contrib/unbound/libunbound/python/doc/examples/example4.rst
@@ -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/unbound/libunbound/python/doc/examples/example5.rst b/contrib/unbound/libunbound/python/doc/examples/example5.rst
new file mode 100644
index 000000000000..0a31d9a57e76
--- /dev/null
+++ b/contrib/unbound/libunbound/python/doc/examples/example5.rst
@@ -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/unbound/libunbound/python/doc/examples/example6-1.py b/contrib/unbound/libunbound/python/doc/examples/example6-1.py
new file mode 100644
index 000000000000..0f405448c513
--- /dev/null
+++ b/contrib/unbound/libunbound/python/doc/examples/example6-1.py
@@ -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/unbound/libunbound/python/doc/examples/example6.rst b/contrib/unbound/libunbound/python/doc/examples/example6.rst
new file mode 100644
index 000000000000..478e13909277
--- /dev/null
+++ b/contrib/unbound/libunbound/python/doc/examples/example6.rst
@@ -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/unbound/libunbound/python/doc/examples/example7-1.py b/contrib/unbound/libunbound/python/doc/examples/example7-1.py
new file mode 100644
index 000000000000..802bd1c35baf
--- /dev/null
+++ b/contrib/unbound/libunbound/python/doc/examples/example7-1.py
@@ -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/unbound/libunbound/python/doc/examples/example7-2.py b/contrib/unbound/libunbound/python/doc/examples/example7-2.py
new file mode 100644
index 000000000000..5a41f8dc9333
--- /dev/null
+++ b/contrib/unbound/libunbound/python/doc/examples/example7-2.py
@@ -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/unbound/libunbound/python/doc/examples/example7.rst b/contrib/unbound/libunbound/python/doc/examples/example7.rst
new file mode 100644
index 000000000000..d4050215e435
--- /dev/null
+++ b/contrib/unbound/libunbound/python/doc/examples/example7.rst
@@ -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/unbound/libunbound/python/doc/examples/example8-1.py b/contrib/unbound/libunbound/python/doc/examples/example8-1.py
new file mode 100644
index 000000000000..79060167d83c
--- /dev/null
+++ b/contrib/unbound/libunbound/python/doc/examples/example8-1.py
@@ -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/unbound/libunbound/python/doc/examples/example8.rst b/contrib/unbound/libunbound/python/doc/examples/example8.rst
new file mode 100644
index 000000000000..8cdfcdc0a904
--- /dev/null
+++ b/contrib/unbound/libunbound/python/doc/examples/example8.rst
@@ -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/unbound/libunbound/python/doc/examples/index.rst b/contrib/unbound/libunbound/python/doc/examples/index.rst
new file mode 100644
index 000000000000..c2c9cf457117
--- /dev/null
+++ b/contrib/unbound/libunbound/python/doc/examples/index.rst
@@ -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/unbound/libunbound/python/doc/index.rst b/contrib/unbound/libunbound/python/doc/index.rst
new file mode 100644
index 000000000000..b42e05262237
--- /dev/null
+++ b/contrib/unbound/libunbound/python/doc/index.rst
@@ -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/unbound/libunbound/python/doc/install.rst b/contrib/unbound/libunbound/python/doc/install.rst
new file mode 100644
index 000000000000..f638ed18e705
--- /dev/null
+++ b/contrib/unbound/libunbound/python/doc/install.rst
@@ -0,0 +1,31 @@
+Installation
+===================================
+
+**Prerequisites**
+
+Python 2.4 or higher, SWIG 1.3 or higher, GNU make
+
+**Compiling**
+
+After downloading, you can compile the pyUnbound library by doing::
+
+ > tar -xzf unbound-x.x.x-py.tar.gz
+ > cd unbound-x.x.x
+ > ./configure --with-pyunbound
+ > make
+
+You may want to --with-pythonmodule as well if you want to use python as
+a module in the resolver.
+
+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
+
+You may want to make install in the main directory since make testenv is for debugging. In contrib/examples you can find simple applications written in Python using the Unbound extension.
diff --git a/contrib/unbound/libunbound/python/doc/intro.rst b/contrib/unbound/libunbound/python/doc/intro.rst
new file mode 100644
index 000000000000..f751f54c07be
--- /dev/null
+++ b/contrib/unbound/libunbound/python/doc/intro.rst
@@ -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/unbound/libunbound/python/doc/modules/unbound.rst b/contrib/unbound/libunbound/python/doc/modules/unbound.rst
new file mode 100644
index 000000000000..21f4a12d8440
--- /dev/null
+++ b/contrib/unbound/libunbound/python/doc/modules/unbound.rst
@@ -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/unbound/libunbound/python/examples/async-lookup.py b/contrib/unbound/libunbound/python/examples/async-lookup.py
new file mode 100644
index 000000000000..52a2d3c75c51
--- /dev/null
+++ b/contrib/unbound/libunbound/python/examples/async-lookup.py
@@ -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/unbound/libunbound/python/examples/dns-lookup.py b/contrib/unbound/libunbound/python/examples/dns-lookup.py
new file mode 100644
index 000000000000..2821ed3ba363
--- /dev/null
+++ b/contrib/unbound/libunbound/python/examples/dns-lookup.py
@@ -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/unbound/libunbound/python/examples/dnssec-valid.py b/contrib/unbound/libunbound/python/examples/dnssec-valid.py
new file mode 100644
index 000000000000..3e05ddd7a28e
--- /dev/null
+++ b/contrib/unbound/libunbound/python/examples/dnssec-valid.py
@@ -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/unbound/libunbound/python/examples/dnssec_test.py b/contrib/unbound/libunbound/python/examples/dnssec_test.py
new file mode 100644
index 000000000000..138e19b51a12
--- /dev/null
+++ b/contrib/unbound/libunbound/python/examples/dnssec_test.py
@@ -0,0 +1,35 @@
+#!/usr/bin/env python
+from unbound import ub_ctx, RR_TYPE_A, RR_TYPE_RRSIG, RR_TYPE_NSEC, RR_TYPE_NSEC3
+import ldns
+
+def dnssecParse(domain, rrType=RR_TYPE_A):
+ print "Resolving domain", domain
+ s, r = resolver.resolve(domain)
+ print "status: %s, secure: %s, rcode: %s, havedata: %s, answer_len; %s" % (s, r.secure, r.rcode_str, r.havedata, r.answer_len)
+
+ s, pkt = ldns.ldns_wire2pkt(r.packet)
+ if s != 0:
+ raise RuntimeError("Error parsing DNS packet")
+
+ rrsigs = pkt.rr_list_by_type(RR_TYPE_RRSIG, ldns.LDNS_SECTION_ANSWER)
+ print "RRSIGs from answer:", rrsigs
+
+ rrsigs = pkt.rr_list_by_type(RR_TYPE_RRSIG, ldns.LDNS_SECTION_AUTHORITY)
+ print "RRSIGs from authority:", rrsigs
+
+ nsecs = pkt.rr_list_by_type(RR_TYPE_NSEC, ldns.LDNS_SECTION_AUTHORITY)
+ print "NSECs:", nsecs
+
+ nsec3s = pkt.rr_list_by_type(RR_TYPE_NSEC3, ldns.LDNS_SECTION_AUTHORITY)
+ print "NSEC3s:", nsec3s
+
+ print "---"
+
+
+resolver = ub_ctx()
+resolver.add_ta(". IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5")
+
+dnssecParse("nic.cz")
+dnssecParse("nonexistent-domain-blablabla.cz")
+dnssecParse("nonexistent-domain-blablabla.root.cz")
+
diff --git a/contrib/unbound/libunbound/python/examples/example8-1.py b/contrib/unbound/libunbound/python/examples/example8-1.py
new file mode 100644
index 000000000000..6816da0c2df2
--- /dev/null
+++ b/contrib/unbound/libunbound/python/examples/example8-1.py
@@ -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/unbound/libunbound/python/examples/idn-lookup.py b/contrib/unbound/libunbound/python/examples/idn-lookup.py
new file mode 100644
index 000000000000..7cfdc9e9479c
--- /dev/null
+++ b/contrib/unbound/libunbound/python/examples/idn-lookup.py
@@ -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/unbound/libunbound/python/examples/mx-lookup.py b/contrib/unbound/libunbound/python/examples/mx-lookup.py
new file mode 100644
index 000000000000..cdcd1b166b45
--- /dev/null
+++ b/contrib/unbound/libunbound/python/examples/mx-lookup.py
@@ -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/unbound/libunbound/python/examples/ns-lookup.py b/contrib/unbound/libunbound/python/examples/ns-lookup.py
new file mode 100644
index 000000000000..f9eafb28aa3c
--- /dev/null
+++ b/contrib/unbound/libunbound/python/examples/ns-lookup.py
@@ -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/unbound/libunbound/python/examples/reverse-lookup.py b/contrib/unbound/libunbound/python/examples/reverse-lookup.py
new file mode 100644
index 000000000000..4d3e0bb36dff
--- /dev/null
+++ b/contrib/unbound/libunbound/python/examples/reverse-lookup.py
@@ -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/unbound/libunbound/python/libunbound.i b/contrib/unbound/libunbound/python/libunbound.i
new file mode 100644
index 000000000000..4f9279957fac
--- /dev/null
+++ b/contrib/unbound/libunbound/python/libunbound.i
@@ -0,0 +1,941 @@
+/*
+ * 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)
+{
+ if(1) { /* new code block for variable on stack */
+ 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,cnt;
+ (void)self;
+ 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;
+ }
+
+ PyObject* _packet() {
+ return PyString_FromStringAndSize($self->answer_packet, $self->answer_len);
+ }
+
+ %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
+ __swig_getmethods__["packet"] = _packet
+ 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)
+{
+ if(1) { /* new code block for variable on stack */
+ 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 *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) {
+ int r;
+ struct cb_data* id;
+ id = (struct cb_data*) malloc(sizeof(struct cb_data));
+ id->data = mydata;
+ id->func = pyfunc;
+
+ r = ub_resolve_async(ctx,name,rrtype,rrclass, (void *) id, PythonCallBack, async_id);
+ Py_INCREF(mydata);
+ Py_INCREF(pyfunc);
+ return r;
+ }
+
+%}
+
+%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('.')])
+
+%}
+