diff options
Diffstat (limited to 'external/unbound/libunbound/python')
32 files changed, 2321 insertions, 0 deletions
diff --git a/external/unbound/libunbound/python/LICENSE b/external/unbound/libunbound/python/LICENSE new file mode 100644 index 000000000..7b769d091 --- /dev/null +++ b/external/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/external/unbound/libunbound/python/Makefile b/external/unbound/libunbound/python/Makefile new file mode 100644 index 000000000..86ba17747 --- /dev/null +++ b/external/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/external/unbound/libunbound/python/doc/_static/readme b/external/unbound/libunbound/python/doc/_static/readme new file mode 100644 index 000000000..db676aebb --- /dev/null +++ b/external/unbound/libunbound/python/doc/_static/readme @@ -0,0 +1 @@ +this directory exists to pacify sphinx-build. diff --git a/external/unbound/libunbound/python/doc/conf.py b/external/unbound/libunbound/python/doc/conf.py new file mode 100644 index 000000000..97fca2125 --- /dev/null +++ b/external/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/external/unbound/libunbound/python/doc/examples/example1a.rst b/external/unbound/libunbound/python/doc/examples/example1a.rst new file mode 100644 index 000000000..3c81547f2 --- /dev/null +++ b/external/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/external/unbound/libunbound/python/doc/examples/example1b.rst b/external/unbound/libunbound/python/doc/examples/example1b.rst new file mode 100644 index 000000000..ea1e6f57d --- /dev/null +++ b/external/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/external/unbound/libunbound/python/doc/examples/example2.rst b/external/unbound/libunbound/python/doc/examples/example2.rst new file mode 100644 index 000000000..c009ec1f5 --- /dev/null +++ b/external/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/external/unbound/libunbound/python/doc/examples/example3.rst b/external/unbound/libunbound/python/doc/examples/example3.rst new file mode 100644 index 000000000..91360335c --- /dev/null +++ b/external/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/external/unbound/libunbound/python/doc/examples/example4.rst b/external/unbound/libunbound/python/doc/examples/example4.rst new file mode 100644 index 000000000..996ef4ede --- /dev/null +++ b/external/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/external/unbound/libunbound/python/doc/examples/example5.rst b/external/unbound/libunbound/python/doc/examples/example5.rst new file mode 100644 index 000000000..0a31d9a57 --- /dev/null +++ b/external/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/external/unbound/libunbound/python/doc/examples/example6-1.py b/external/unbound/libunbound/python/doc/examples/example6-1.py new file mode 100644 index 000000000..0f405448c --- /dev/null +++ b/external/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/external/unbound/libunbound/python/doc/examples/example6.rst b/external/unbound/libunbound/python/doc/examples/example6.rst new file mode 100644 index 000000000..478e13909 --- /dev/null +++ b/external/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/external/unbound/libunbound/python/doc/examples/example7-1.py b/external/unbound/libunbound/python/doc/examples/example7-1.py new file mode 100644 index 000000000..802bd1c35 --- /dev/null +++ b/external/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/external/unbound/libunbound/python/doc/examples/example7-2.py b/external/unbound/libunbound/python/doc/examples/example7-2.py new file mode 100644 index 000000000..5a41f8dc9 --- /dev/null +++ b/external/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/external/unbound/libunbound/python/doc/examples/example7.rst b/external/unbound/libunbound/python/doc/examples/example7.rst new file mode 100644 index 000000000..d4050215e --- /dev/null +++ b/external/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/external/unbound/libunbound/python/doc/examples/example8-1.py b/external/unbound/libunbound/python/doc/examples/example8-1.py new file mode 100644 index 000000000..79060167d --- /dev/null +++ b/external/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/external/unbound/libunbound/python/doc/examples/example8.rst b/external/unbound/libunbound/python/doc/examples/example8.rst new file mode 100644 index 000000000..8cdfcdc0a --- /dev/null +++ b/external/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/external/unbound/libunbound/python/doc/examples/index.rst b/external/unbound/libunbound/python/doc/examples/index.rst new file mode 100644 index 000000000..c2c9cf457 --- /dev/null +++ b/external/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/external/unbound/libunbound/python/doc/index.rst b/external/unbound/libunbound/python/doc/index.rst new file mode 100644 index 000000000..b42e05262 --- /dev/null +++ b/external/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/external/unbound/libunbound/python/doc/install.rst b/external/unbound/libunbound/python/doc/install.rst new file mode 100644 index 000000000..f638ed18e --- /dev/null +++ b/external/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/external/unbound/libunbound/python/doc/intro.rst b/external/unbound/libunbound/python/doc/intro.rst new file mode 100644 index 000000000..f751f54c0 --- /dev/null +++ b/external/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/external/unbound/libunbound/python/doc/modules/unbound.rst b/external/unbound/libunbound/python/doc/modules/unbound.rst new file mode 100644 index 000000000..21f4a12d8 --- /dev/null +++ b/external/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/external/unbound/libunbound/python/examples/async-lookup.py b/external/unbound/libunbound/python/examples/async-lookup.py new file mode 100644 index 000000000..cbb8ea02d --- /dev/null +++ b/external/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/external/unbound/libunbound/python/examples/dns-lookup.py b/external/unbound/libunbound/python/examples/dns-lookup.py new file mode 100644 index 000000000..b3f4008fd --- /dev/null +++ b/external/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/external/unbound/libunbound/python/examples/dnssec-valid.py b/external/unbound/libunbound/python/examples/dnssec-valid.py new file mode 100644 index 000000000..5c3cad9e9 --- /dev/null +++ b/external/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/external/unbound/libunbound/python/examples/dnssec_test.py b/external/unbound/libunbound/python/examples/dnssec_test.py new file mode 100644 index 000000000..0d62b9ff2 --- /dev/null +++ b/external/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/external/unbound/libunbound/python/examples/example8-1.py b/external/unbound/libunbound/python/examples/example8-1.py new file mode 100644 index 000000000..ca868e510 --- /dev/null +++ b/external/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/external/unbound/libunbound/python/examples/idn-lookup.py b/external/unbound/libunbound/python/examples/idn-lookup.py new file mode 100644 index 000000000..2170637d3 --- /dev/null +++ b/external/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/external/unbound/libunbound/python/examples/mx-lookup.py b/external/unbound/libunbound/python/examples/mx-lookup.py new file mode 100644 index 000000000..f83f690f8 --- /dev/null +++ b/external/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/external/unbound/libunbound/python/examples/ns-lookup.py b/external/unbound/libunbound/python/examples/ns-lookup.py new file mode 100644 index 000000000..bcd51de6d --- /dev/null +++ b/external/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/external/unbound/libunbound/python/examples/reverse-lookup.py b/external/unbound/libunbound/python/examples/reverse-lookup.py new file mode 100644 index 000000000..7e06844ec --- /dev/null +++ b/external/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/external/unbound/libunbound/python/libunbound.i b/external/unbound/libunbound/python/libunbound.i new file mode 100644 index 000000000..313c74862 --- /dev/null +++ b/external/unbound/libunbound/python/libunbound.i @@ -0,0 +1,951 @@ +/* + * 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 + + # Ensure compatibility with older python versions + if 'bytes' not in vars(): + bytes = str + + def ord(s): + if isinstance(s, int): + return s + return __builtins__.ord(s) +%} + +//%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, bytes): #probably IDN + return _unbound.ub_resolve(self,name,rrtype,rrclass) + else: + return _unbound.ub_resolve(self,idn2dname(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, bytes): #probably IDN + return _unbound._ub_resolve_async(self,name,rrtype,rrclass,mydata,callback) + else: + return _unbound._ub_resolve_async(self,idn2dname(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]) + # In python 3.x `str()` converts the string to unicode which is the expected text string type + res.append(str(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, PyBytes_FromStringAndSize(result->data[i],result->len[i])); + + return list; + } + + PyObject* _packet() { + return PyBytes_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('.')]) + +%} + |