added unbound to external deps

This commit is contained in:
Riccardo Spagni 2014-10-05 23:44:31 +02:00
parent 732493c5cb
commit 9ef094b356
No known key found for this signature in database
GPG key ID: 55432DF31CCD4FCD
394 changed files with 199264 additions and 0 deletions

View file

@ -0,0 +1 @@
this directory exists to pacify sphinx-build.

179
external/unbound/pythonmod/doc/conf.py vendored Normal file
View file

@ -0,0 +1,179 @@
# -*- coding: utf-8 -*-
#
# Unbound scripting interface documentation build configuration file
#
# This file is execfile()d with the current directory set to its containing dir.
#
# The contents of this file are pickled, so don't put values in the namespace
# that aren't pickleable (module imports are okay, they're removed automatically).
#
# All configuration values have a default value; values that are commented out
# serve to show the default value.
import sys, os
# If your extensions are in another directory, add it here. If the directory
# is relative to the documentation root, use os.path.abspath to make it
# absolute, like shown here.
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__),'../..')))
#print sys.path
# General configuration
# ---------------------
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix of source filenames.
source_suffix = '.rst'
# The master toctree document.
master_doc = 'index'
# General substitutions.
project = 'Unbound scriptable interface'
copyright = '2009, Zdenek Vasicek, Marek Vavrusa'
# The default replacements for |version| and |release|, also used in various
# other places throughout the built documents.
#
# The short X.Y version.
version = '1.0'
# The full version, including alpha/beta/rc tags.
release = '1.0.0'
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
today_fmt = '%B %d, %Y'
# List of documents that shouldn't be included in the build.
#unused_docs = []
# List of directories, relative to source directories, that shouldn't be searched
# for source files.
#exclude_dirs = []
# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# Options for HTML output
# -----------------------
# The style sheet to use for HTML and HTML Help pages. A file of that name
# must exist either in Sphinx' static/ path, or in one of the custom paths
# given in html_static_path.
html_style = 'default.css'
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (within the static path) to place at the top of
# the sidebar.
#html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
html_use_modindex = False
# If false, no index is generated.
html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, the reST sources are included in the HTML build as _sources/<name>.
html_copy_source = False
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = ''
# Output file base name for HTML help builder.
htmlhelp_basename = 'unbound_interface'
# Options for LaTeX output
# ------------------------
# The paper size ('letter' or 'a4').
#latex_paper_size = 'letter'
# The font size ('10pt', '11pt' or '12pt').
#latex_font_size = '10pt'
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, document class [howto/manual]).
latex_documents = [
('index', 'Unbound_interface.tex', 'Unbound scriptable interface',
'Zdenek Vasicek, Marek Vavrusa', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# Additional stuff for the LaTeX preamble.
#latex_preamble = ''
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_use_modindex = True

View file

@ -0,0 +1,34 @@
def init(id, cfg):
log_info("pythonmod: init called, module id is %d port: %d script: %s" % (id, cfg.port, cfg.python_script))
return True
def deinit(id):
log_info("pythonmod: deinit called, module id is %d" % id)
return True
def inform_super(id, qstate, superqstate, qdata):
return True
def operate(id, event, qstate, qdata):
log_info("pythonmod: operate called, id: %d, event:%s" % (id, strmodulevent(event)))
if event == MODULE_EVENT_NEW:
qstate.ext_state[id] = MODULE_WAIT_MODULE
return True
if event == MODULE_EVENT_MODDONE:
log_info("pythonmod: module we are waiting for is done")
qstate.ext_state[id] = MODULE_FINISHED
return True
if event == MODULE_EVENT_PASS:
log_info("pythonmod: event_pass")
qstate.ext_state[id] = MODULE_ERROR
return True
log_err("pythonmod: BAD event")
qstate.ext_state[id] = MODULE_ERROR
return True
log_info("pythonmod: script loaded.")

View file

@ -0,0 +1,129 @@
.. _example_handler:
Fundamentals
================
This basic example shows how to create simple python module which will pass on the requests to the iterator.
How to enable python module
----------------------------
If you look into unbound configuration file, you can find the option `module-config` which specifies the names and the order of modules to be used.
Example configuration::
module-config: "validator python iterator"
As soon as the DNS query arrives, Unbound calls modules starting from leftmost - the validator *(it is the first module on the list)*.
The validator does not know the answer *(it can only validate)*, thus it will pass on the event to the next module.
Next module is python which can
a) generate answer *(response)*
When python module generates the response unbound calls validator. Validator grabs the answer and determines the security flag.
b) pass on the event to the iterator.
When iterator resolves the query, Unbound informs python module (event :data:`module_event_moddone`). In the end, when the python module is done, validator is called.
Note that the python module is called with :data:`module_event_pass` event, because new DNS event was already handled by validator.
Another situation occurs when we use the following configuration::
module-config: "python validator iterator"
Python module is the first module here, so it's invoked with :data:`module_event_new` event *(new query)*.
On Python module initialization, module loads script from `python-script` option::
python-script: "/unbound/test/ubmodule.py"
Simple python module step by step
---------------------------------
Script file must contain four compulsory functions:
.. function:: init(id, cfg)
Initialize module internals, like database etc.
Called just once on module load.
:param id: module identifier (integer)
:param cfg: :class:`config_file` configuration structure
::
def init(id, cfg):
log_info("pythonmod: init called, module id is %d port: %d script: %s" % (id, cfg.port, cfg.python_script))
return True
.. function:: deinit(id)
Deinitialize module internals.
Called just once on module unload.
:param id: module identifier (integer)
::
def deinit(id):
log_info("pythonmod: deinit called, module id is %d" % id)
return True
.. function:: inform_super(id, qstate, superqstate, qdata)
Inform super querystate about the results from this subquerystate.
Is called when the querystate is finished.
:param id: module identifier (integer)
:param qstate: :class:`module_qstate` Query state
:param superqstate: :class:`pythonmod_qstate` Mesh state
:param qdata: :class:`query_info` Query data
::
def inform_super(id, qstate, superqstate, qdata):
return True
.. function:: operate(id, event, qstate, qdata)
Perform action on pending query. Accepts a new query, or work on pending query.
You have to set qstate.ext_state on exit.
The state informs unbound about result and controls the following states.
:param id: module identifier (integer)
:param qstate: :class:`module_qstate` query state structure
:param qdata: :class:`query_info` per query data, here you can store your own data
::
def operate(id, event, qstate, qdata):
log_info("pythonmod: operate called, id: %d, event:%s" % (id, strmodulevent(event)))
if event == MODULE_EVENT_NEW:
qstate.ext_state[id] = MODULE_WAIT_MODULE
return True
if event == MODULE_EVENT_MODDONE:
qstate.ext_state[id] = MODULE_FINISHED
return True
if event == MODULE_EVENT_PASS:
qstate.ext_state[id] = MODULE_ERROR
return True
log_err("pythonmod: BAD event")
qstate.ext_state[id] = MODULE_ERROR
return True
Complete source code
--------------------
.. literalinclude:: example0-1.py
:language: python
As you can see, the source code is much more flexible in contrast to C modules.
Moreover, compulsory functions called on appropriate module events allows to handle almost
anything from web control to query analysis.

View file

@ -0,0 +1,42 @@
.. _log_handler:
Packet logger
=========================
This example shows how to log and print details about query and response.
As soon as the ``iterator`` has finished (event is :data:`module_event_moddone`), ``qstate.return_msg`` contains response packet or ``None``.
This packet will be send to a client that asked for it.
Complete source code
--------------------
.. literalinclude:: ../../examples/log.py
:language: python
Testing
------------------
Run the unbound server:
``root@localhost>unbound -dv -c ./test-log.conf``
In case you use own configuration file, don't forget to enable python module: ``module-config: "validator python iterator"`` and use valid script path: ``python-script: "./examples/log.py"``.
Example of output::
[1231790168] unbound[7941:0] info: response for <f.gtld-servers.NET. AAAA IN>
[1231790168] unbound[7941:0] info: reply from <gtld-servers.NET.> 192.5.6.31#53
[1231790168] unbound[7941:0] info: query response was ANSWER
[1231790168] unbound[7941:0] info: pythonmod: operate called, id: 1, event:module_event_moddone
----------------------------------------------------------------------------------------------------
Query: f.gtld-servers.NET., type: AAAA (28), class: IN (1)
----------------------------------------------------------------------------------------------------
Return reply :: flags: 8080, QDcount: 1, Security:0, TTL=86400
qinfo :: qname: ['f', 'gtld-servers', 'NET', ''] f.gtld-servers.NET., qtype: AAAA, qclass: IN
Reply:
0 : ['gtld-servers', 'NET', ''] gtld-servers.NET. flags: 0000 type: SOA (6) class: IN (1)
0 : TTL= 86400
0x00 | 00 3A 02 41 32 05 4E 53 54 4C 44 03 43 4F 4D 00 05 | . : . A 2 . N S T L D . C O M . .
0x10 | 05 6E 73 74 6C 64 0C 76 65 72 69 73 69 67 6E 2D 67 | . n s t l d . v e r i s i g n - g
0x20 | 67 72 73 03 43 4F 4D 00 77 74 2D 64 00 00 0E 10 00 | g r s . C O M . w t - d . . . . .
0x30 | 00 00 03 84 00 12 75 00 00 01 51 80 | . . . . . . u . . . Q .

View file

@ -0,0 +1,46 @@
Response generation
=====================
This example shows how to handle queries and generate response packet.
.. note::
If the python module is the first module and validator module is enabled (``module-config: "python validator iterator"``),
a return_msg security flag has to be set at least to 2. Leaving security flag untouched causes that the
response will be refused by unbound worker as unbound will consider it as non-valid response.
Complete source code
--------------------
.. literalinclude:: ../../examples/resgen.py
:language: python
Testing
-------
Run the unbound server:
``root@localhost>unbound -dv -c ./test-resgen.conf``
Query for a A record ending with .localdomain
``dig A test.xxx.localdomain @127.0.0.1``
Dig produces the following output::
;; global options: printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48426
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;test.xxx.localdomain. IN A
;; ANSWER SECTION:
test.xxx.localdomain. 10 IN A 127.0.0.1
;; Query time: 2 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Mon Jan 01 12:46:02 2009
;; MSG SIZE rcvd: 54
As we handle (override) in python module only queries ending with "localdomain.", the unboud can still resolve host names.

View file

@ -0,0 +1,63 @@
Response modification
=====================
This example shows how to modify the response produced by the ``iterator`` module.
As soon as the iterator module returns the response, we :
1. invalidate the data in cache
2. modify the response *TTL*
3. rewrite the data in cache
4. return modified packet
Note that the steps 1 and 3 are neccessary only in case, the python module is the first module in the processing chain.
In other cases, the validator module guarantees updating data which are produced by iterator module.
Complete source code
--------------------
.. literalinclude:: ../../examples/resmod.py
:language: python
Testing
-------
Run Unbound server:
``root@localhost>unbound -dv -c ./test-resmod.conf``
Issue a query for name ending with "nic.cz."
``>>>dig A @127.0.0.1 www.nic.cz``
::
;; global options: printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48831
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 3, ADDITIONAL: 5
;; QUESTION SECTION:
;www.nic.cz. IN A
;; ANSWER SECTION:
www.nic.cz. 10 IN A 217.31.205.50
;; AUTHORITY SECTION:
nic.cz. 10 IN NS e.ns.nic.cz.
nic.cz. 10 IN NS a.ns.nic.cz.
nic.cz. 10 IN NS c.ns.nic.cz.
;; ADDITIONAL SECTION:
a.ns.nic.cz. 10 IN A 217.31.205.180
a.ns.nic.cz. 10 IN AAAA 2001:1488:dada:176::180
c.ns.nic.cz. 10 IN A 195.66.241.202
c.ns.nic.cz. 10 IN AAAA 2a01:40:1000::2
e.ns.nic.cz. 10 IN A 194.146.105.38
;; Query time: 166 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Mon Jan 02 13:39:43 2009
;; MSG SIZE rcvd: 199
As you can see, TTL of all the records is set to 10.

View file

@ -0,0 +1,164 @@
DNS-based language dictionary
===============================
This example shows how to create a simple language dictionary based on **DNS**
service within 15 minutes. The translation will be performed using TXT resource records.
Key parts
-----------
Initialization
~~~~~~~~~~~~~~~~~~~~~~~
On **init()** module loads dictionary from a text file containing records in ``word [tab] translation`` format.
::
def init(id, cfg):
log_info("pythonmod: dict init")
f = open("examples/dict_data.txt", "r")
...
The suitable file can be found at http://slovnik.zcu.cz
DNS query and word lookup
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Let's define the following format od DNS queries: ``word1[.]word2[.] ... wordN[.]{en,cs}[._dict_.cz.]``.
Word lookup is done by simple ``dict`` lookup from broken DNS request.
Query name is divided into a list of labels. This list is accesible as qname_list attribute.
::
aword = ' '.join(qstate.qinfo.qname_list[0:-4]) #skip last four labels
adict = qstate.qinfo.qname_list[-4] #get 4th label from the end
words = [] #list of words
if (adict == "en") and (aword in en_dict):
words = en_dict[aword]
if (adict == "cs") and (aword in cz_dict):
words = cz_dict[aword] # CS -> EN
In the first step, we get a string in the form: ``word1[space]word2[space]...word[space]``.
In the second assignment, fourth label from the end is obtained. This label should contains *"cs"* or *"en"*.
This label determines the direction of translation.
Forming of a DNS reply
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DNS reply is formed only on valid match and added as TXT answer.
::
msg = DNSMessage(qstate.qinfo.qname_str, RR_TYPE_TXT, RR_CLASS_IN, PKT_AA)
for w in words:
msg.answer.append("%s 300 IN TXT \"%s\"" % (qstate.qinfo.qname_str, w.replace("\"", "\\\"")))
if not msg.set_return_msg(qstate):
qstate.ext_state[id] = MODULE_ERROR
return True
qstate.return_rcode = RCODE_NOERROR
qstate.ext_state[id] = MODULE_FINISHED
return True
In the first step, a :class:`DNSMessage` instance is created for a given query *(type TXT)*.
The fourth argument specifies the flags *(authoritative answer)*.
In the second step, we append TXT records containing the translation *(on the right side of RR)*.
Then, the response is finished and ``qstate.return_msg`` contains new response.
If no error, the module sets :attr:`module_qstate.return_rcode` and :attr:`module_qstate.ext_state`.
**Steps:**
1. create :class:`DNSMessage` instance
2. append TXT records containing the translation
3. set response to ``qstate.return_msg``
Testing
-------
Run the Unbound server:
``root@localhost>unbound -dv -c ./test-dict.conf``
In case you use own configuration file, don't forget to enable Python module::
module-config: "validator python iterator"
and use valid script path::
python-script: "./examples/dict.py"
The translation from english word *"a bar fly"* to Czech can be done by doing:
``>>>dig TXT @127.0.0.1 a.bar.fly.en._dict_.cz``
::
; (1 server found)
;; global options: printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48691
;; flags: aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;a.bar.fly.en._dict_.cz. IN TXT
;; ANSWER SECTION:
a.bar.fly.en._dict_.cz. 300 IN TXT "barov\253 povale\232"
;; Query time: 5 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Mon Jan 01 17:44:18 2009
;; MSG SIZE rcvd: 67
``>>>dig TXT @127.0.0.1 nic.cs._dict_.cz``
::
; <<>> DiG 9.5.0-P2 <<>> TXT @127.0.0.1 nic.cs._dict_.cz
; (1 server found)
;; global options: printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 58710
;; flags: aa rd ra; QUERY: 1, ANSWER: 6, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;nic.cs._dict_.cz. IN TXT
;; ANSWER SECTION:
nic.cs._dict_.cz. 300 IN TXT "aught"
nic.cs._dict_.cz. 300 IN TXT "naught"
nic.cs._dict_.cz. 300 IN TXT "nihil"
nic.cs._dict_.cz. 300 IN TXT "nix"
nic.cs._dict_.cz. 300 IN TXT "nothing"
nic.cs._dict_.cz. 300 IN TXT "zilch"
;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Mon Jan 01 17:45:39 2009
;; MSG SIZE rcvd: 143
Proof that the unbound still works as resolver.
``>>>dig A @127.0.0.1 www.nic.cz``
::
; (1 server found)
;; global options: printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 19996
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 3, ADDITIONAL: 5
;; QUESTION SECTION:
;www.nic.cz. IN A
;; ANSWER SECTION:
www.nic.cz. 1662 IN A 217.31.205.50
;; AUTHORITY SECTION:
...
Complete source code
--------------------
.. literalinclude:: ../../examples/dict.py
:language: python

View file

@ -0,0 +1,15 @@
.. _Tutorials:
==============================
Tutorials
==============================
Here you can find several tutorials which clarify the usage and capabilities of Unbound scriptable interface.
`Tutorials`
.. toctree::
:maxdepth: 2
:glob:
example*

View file

@ -0,0 +1,34 @@
Unbound scriptable interface
=======================================
Python module for **Unbound** provides easy-to-use flexible solution,
for scripting query events and much more!
Along with extensible **SWIG** interface, it turns **Unbound** into dynamic *DNS* service
designed for rapid development of *DNS* based applications, like detailed *(per query/domain)* statistics,
monitoring with anything Python can offer *(database backend, http server)*.
**Key features**
* Rapid dynamic DNS-based application development in **Python**
* Extensible interface with **SWIG**
* Easy to use debugging and analysis tool
* Capable to produce authoritative answers
* Support for logging or doing detailed statistics
* Allows to manipulate with content of cache memory
Contents
--------
.. toctree::
:maxdepth: 2
install
examples/index
usecase
modules/index
Indices and tables
-------------------
* :ref:`genindex`
* :ref:`search`

View file

@ -0,0 +1,59 @@
Installation
===================================
**Prerequisites**
Python 2.4 or higher, SWIG 1.3 or higher, GNU make
**Download**
You can download the source codes `here`_.
The latest release is 1.1.1, Jan 15, 2009.
.. _here: unbound-1.1.1-py.tar.gz
**Compiling**
After downloading, you can compile the Unbound library by doing::
> tar -xzf unbound-1.1.1-py.tar.gz
> cd unbound-1.1.1
> ./configure --with-pythonmodule
> make
You need GNU make to compile sources.
SWIG and Python devel libraries to compile extension module.
**Testing**
If the compilation is successful, you can test the extension module by::
> cd pythonmod
> make sudo # or "make test" or "make suexec"
This will start unbound server with language dictionary service (see :ref:`Tutorials`).
In order to test this service, type::
> dig TXT @127.0.0.1 aught.en._dict_.cz
Dig should print this message (czech equivalent of aught)::
; <<>> DiG 9.5.0-P2 <<>> TXT @127.0.0.1 aught.en._dict_.cz
; (1 server found)
;; global options: printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 30085
;; flags: aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;aught.en._dict_.cz. IN TXT
;; ANSWER SECTION:
aught.en._dict_.cz. 300 IN TXT "nic"
;; Query time: 11 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Thu Jan 10 16:45:58 2009
;; MSG SIZE rcvd: 52
The ``pythonmod/examples`` directory contains simple applications written in Python.

View file

@ -0,0 +1,350 @@
Configuration interface
=======================
Currently passed to Python module in init(module_id, cfg).
config_file
--------------------
.. class:: config_file
This class provides these data attributes:
.. attribute:: verbosity
Verbosity level as specified in the config file.
.. attribute:: stat_interval
Statistics interval (in seconds).
.. attribute:: stat_cumulative
If false, statistics values are reset after printing them.
.. attribute:: stat_extended
If true, the statistics are kept in greater detail.
.. attribute:: num_threads
Number of threads to create.
.. attribute:: port
Port on which queries are answered.
.. attribute:: do_ip4
Do ip4 query support.
.. attribute:: do_ip6
Do ip6 query support.
.. attribute:: do_udp
Do udp query support.
.. attribute:: do_tcp
Do tcp query support.
.. attribute:: outgoing_num_ports
Outgoing port range number of ports (per thread).
.. attribute:: outgoing_num_tcp
Number of outgoing tcp buffers per (per thread).
.. attribute:: incoming_num_tcp
Number of incoming tcp buffers per (per thread).
.. attribute:: outgoing_avail_ports
Allowed udp port numbers, array with 0 if not allowed.
.. attribute:: msg_buffer_size
Number of bytes buffer size for DNS messages.
.. attribute:: msg_cache_size
Size of the message cache.
.. attribute:: msg_cache_slabs
Slabs in the message cache.
.. attribute:: num_queries_per_thread
Number of queries every thread can service.
.. attribute:: jostle_time
Number of msec to wait before items can be jostled out.
.. attribute:: rrset_cache_size
Size of the rrset cache.
.. attribute:: rrset_cache_slabs
Slabs in the rrset cache.
.. attribute:: host_ttl
Host cache ttl in seconds.
.. attribute:: lame_ttl
Host is lame for a zone ttl, in seconds.
.. attribute:: infra_cache_slabs
Number of slabs in the infra host cache.
.. attribute:: infra_cache_numhosts
Max number of hosts in the infra cache.
.. attribute:: infra_cache_lame_size
Max size of lame zones per host in the infra cache.
.. attribute:: target_fetch_policy
The target fetch policy for the iterator.
.. attribute:: if_automatic
Automatic interface for incoming messages. Uses ipv6 remapping,
and recvmsg/sendmsg ancillary data to detect interfaces, boolean.
.. attribute:: num_ifs
Number of interfaces to open. If 0 default all interfaces.
.. attribute:: ifs
Interface description strings (IP addresses).
.. attribute:: num_out_ifs
Number of outgoing interfaces to open.
If 0 default all interfaces.
.. attribute:: out_ifs
Outgoing interface description strings (IP addresses).
.. attribute:: root_hints
The root hints.
.. attribute:: stubs
The stub definitions, linked list.
.. attribute:: forwards
The forward zone definitions, linked list.
.. attribute:: donotqueryaddrs
List of donotquery addresses, linked list.
.. attribute:: acls
List of access control entries, linked list.
.. attribute:: donotquery_localhost
Use default localhost donotqueryaddr entries.
.. attribute:: harden_short_bufsize
Harden against very small edns buffer sizes.
.. attribute:: harden_large_queries
Harden against very large query sizes.
.. attribute:: harden_glue
Harden against spoofed glue (out of zone data).
.. attribute:: harden_dnssec_stripped
Harden against receiving no DNSSEC data for trust anchor.
.. attribute:: harden_referral_path
Harden the referral path, query for NS,A,AAAA and validate.
.. attribute:: use_caps_bits_for_id
Use 0x20 bits in query as random ID bits.
.. attribute:: private_address
Strip away these private addrs from answers, no DNS Rebinding.
.. attribute:: private_domain
Allow domain (and subdomains) to use private address space.
.. attribute:: unwanted_threshold
What threshold for unwanted action.
.. attribute:: chrootdir
Chrootdir, if not "" or chroot will be done.
.. attribute:: username
Username to change to, if not "".
.. attribute:: directory
Working directory.
.. attribute:: logfile
Filename to log to.
.. attribute:: pidfile
Pidfile to write pid to.
.. attribute:: use_syslog
Should log messages be sent to syslogd.
.. attribute:: hide_identity
Do not report identity (id.server, hostname.bind).
.. attribute:: hide_version
Do not report version (version.server, version.bind).
.. attribute:: identity
Identity, hostname is returned if "".
.. attribute:: version
Version, package version returned if "".
.. attribute:: module_conf
The module configuration string.
.. attribute:: trust_anchor_file_list
Files with trusted DS and DNSKEYs in zonefile format, list.
.. attribute:: trust_anchor_list
List of trustanchor keys, linked list.
.. attribute:: trusted_keys_file_list
Files with trusted DNSKEYs in named.conf format, list.
.. attribute:: dlv_anchor_file
DLV anchor file.
.. attribute:: dlv_anchor_list
DLV anchor inline.
.. attribute:: max_ttl
The number of seconds maximal TTL used for RRsets and messages.
.. attribute:: val_date_override
If not 0, this value is the validation date for RRSIGs.
.. attribute:: bogus_ttl
This value sets the number of seconds before revalidating bogus.
.. attribute:: val_clean_additional
Should validator clean additional section for secure msgs.
.. attribute:: val_permissive_mode
Should validator allow bogus messages to go through.
.. attribute:: val_nsec3_key_iterations
Nsec3 maximum iterations per key size, string.
.. attribute:: key_cache_size
Size of the key cache.
.. attribute:: key_cache_slabs
Slabs in the key cache.
.. attribute:: neg_cache_size
Size of the neg cache.
.. attribute:: local_zones
Local zones config.
.. attribute:: local_zones_nodefault
Local zones nodefault list.
.. attribute:: local_data
Local data RRs configged.
.. attribute:: remote_control_enable
Remote control section. enable toggle.
.. attribute:: control_ifs
The interfaces the remote control should listen on.
.. attribute:: control_port
Port number for the control port.
.. attribute:: server_key_file
Private key file for server.
.. attribute:: server_cert_file
Certificate file for server.
.. attribute:: control_key_file
Private key file for unbound-control.
.. attribute:: control_cert_file
Certificate file for unbound-control.
.. attribute:: do_daemonize
Daemonize, i.e. fork into the background.
.. attribute:: python_script
Python script file.

View file

@ -0,0 +1,412 @@
Global environment
==================
Global variables
----------------
.. envvar:: mod_env
Module environment, contains data pointer for module-specific data.
See :class:`pythonmod_env`.
Predefined constants
-----------------------
Module extended state
~~~~~~~~~~~~~~~~~~~~~~~
.. data:: module_state_initial
Initial state - new DNS query.
.. data:: module_wait_reply
Waiting for reply to outgoing network query.
.. data:: module_wait_module
Module is waiting for another module.
.. data:: module_wait_subquery
Module is waiting for sub-query.
.. data:: module_error
Module could not finish the query.
.. data:: module_finished
Module is finished with query.
Module event
~~~~~~~~~~~~~
.. data:: module_event_new
New DNS query.
.. data:: module_event_pass
Query passed by other module.
.. data:: module_event_reply
Reply inbound from server.
.. data:: module_event_noreply
No reply, timeout or other error.
.. data:: module_event_capsfail
Reply is there, but capitalisation check failed.
.. data:: module_event_moddone
Next module is done, and its reply is awaiting you.
.. data:: module_event_error
Error occured.
Security status
~~~~~~~~~~~~~~~~
.. data:: sec_status_unchecked
Means that object has yet to be validated.
.. data:: sec_status_bogus
Means that the object *(RRset or message)* failed to validate
*(according to local policy)*, but should have validated.
.. data:: sec_status_indeterminate
Means that the object is insecure, but not
authoritatively so. Generally this means that the RRset is not
below a configured trust anchor.
.. data:: sec_status_insecure
Means that the object is authoritatively known to be
insecure. Generally this means that this RRset is below a trust
anchor, but also below a verified, insecure delegation.
.. data:: sec_status_secure
Means that the object (RRset or message) validated according to local policy.
Resource records (RR sets)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The different RR classes.
.. data:: RR_CLASS_IN
Internet.
.. data:: RR_CLASS_CH
Chaos.
.. data:: RR_CLASS_HS
Hesiod (Dyer 87)
.. data:: RR_CLASS_NONE
None class, dynamic update.
.. data:: RR_CLASS_ANY
Any class.
The different RR types.
.. data:: RR_TYPE_A
A host address.
.. data:: RR_TYPE_NS
An authoritative name server.
.. data:: RR_TYPE_MD
A mail destination (Obsolete - use MX).
.. data:: RR_TYPE_MF
A mail forwarder (Obsolete - use MX).
.. data:: RR_TYPE_CNAME
The canonical name for an alias.
.. data:: RR_TYPE_SOA
Marks the start of a zone of authority.
.. data:: RR_TYPE_MB
A mailbox domain name (EXPERIMENTAL).
.. data:: RR_TYPE_MG
A mail group member (EXPERIMENTAL).
.. data:: RR_TYPE_MR
A mail rename domain name (EXPERIMENTAL).
.. data:: RR_TYPE_NULL
A null RR (EXPERIMENTAL).
.. data:: RR_TYPE_WKS
A well known service description.
.. data:: RR_TYPE_PTR
A domain name pointer.
.. data:: RR_TYPE_HINFO
Host information.
.. data:: RR_TYPE_MINFO
Mailbox or mail list information.
.. data:: RR_TYPE_MX
Mail exchange.
.. data:: RR_TYPE_TXT
Text strings.
.. data:: RR_TYPE_RP
RFC1183.
.. data:: RR_TYPE_AFSDB
RFC1183.
.. data:: RR_TYPE_X25
RFC1183.
.. data:: RR_TYPE_ISDN
RFC1183.
.. data:: RR_TYPE_RT
RFC1183.
.. data:: RR_TYPE_NSAP
RFC1706.
.. data:: RR_TYPE_NSAP_PTR
RFC1348.
.. data:: RR_TYPE_SIG
2535typecode.
.. data:: RR_TYPE_KEY
2535typecode.
.. data:: RR_TYPE_PX
RFC2163.
.. data:: RR_TYPE_GPOS
RFC1712.
.. data:: RR_TYPE_AAAA
IPv6 address.
.. data:: RR_TYPE_LOC
LOC record RFC1876.
.. data:: RR_TYPE_NXT
2535typecode.
.. data:: RR_TYPE_EID
draft-ietf-nimrod-dns-01.txt.
.. data:: RR_TYPE_NIMLOC
draft-ietf-nimrod-dns-01.txt.
.. data:: RR_TYPE_SRV
SRV record RFC2782.
.. data:: RR_TYPE_ATMA
http://www.jhsoft.com/rfc/af-saa-0069.000.rtf.
.. data:: RR_TYPE_NAPTR
RFC2915.
.. data:: RR_TYPE_KX
RFC2230.
.. data:: RR_TYPE_CERT
RFC2538.
.. data:: RR_TYPE_A6
RFC2874.
.. data:: RR_TYPE_DNAME
RFC2672.
.. data:: RR_TYPE_SINK
dnsind-kitchen-sink-02.txt.
.. data:: RR_TYPE_OPT
Pseudo OPT record.
.. data:: RR_TYPE_APL
RFC3123.
.. data:: RR_TYPE_DS
draft-ietf-dnsext-delegation.
.. data:: RR_TYPE_SSHFP
SSH Key Fingerprint.
.. data:: RR_TYPE_IPSECKEY
draft-richardson-ipseckey-rr-11.txt.
.. data:: RR_TYPE_RRSIG
draft-ietf-dnsext-dnssec-25.
.. data:: RR_TYPE_NSEC
.. data:: RR_TYPE_DNSKEY
.. data:: RR_TYPE_DHCID
.. data:: RR_TYPE_NSEC3
.. data:: RR_TYPE_NSEC3PARAMS
.. data:: RR_TYPE_UINFO
.. data:: RR_TYPE_UID
.. data:: RR_TYPE_GID
.. data:: RR_TYPE_UNSPEC
.. data:: RR_TYPE_TSIG
.. data:: RR_TYPE_IXFR
.. data:: RR_TYPE_AXFR
.. data:: RR_TYPE_MAILB
A request for mailbox-related records (MB, MG or MR).
.. data:: RR_TYPE_MAILA
A request for mail agent RRs (Obsolete - see MX).
.. data:: RR_TYPE_ANY
Any type *(wildcard)*.
.. data:: RR_TYPE_DLV
RFC 4431, 5074, DNSSEC Lookaside Validation.
Return codes
~~~~~~~~~~~~
Return codes for packets.
.. data:: RCODE_NOERROR
.. data:: RCODE_FORMERR
.. data:: RCODE_SERVFAIL
.. data:: RCODE_NXDOMAIN
.. data:: RCODE_NOTIMPL
.. data:: RCODE_REFUSED
.. data:: RCODE_YXDOMAIN
.. data:: RCODE_YXRRSET
.. data:: RCODE_NXRRSET
.. data:: RCODE_NOTAUTH
.. data:: RCODE_NOTZONE
Packet data
~~~~~~~~~~~~
.. data:: PKT_QR
Query - query flag.
.. data:: PKT_AA
Authoritative Answer - server flag.
.. data:: PKT_TC
Truncated - server flag.
.. data:: PKT_RD
Recursion desired - query flag.
.. data:: PKT_CD
Checking disabled - query flag.
.. data:: PKT_RA
Recursion available - server flag.
.. data:: PKT_AD
Authenticated data - server flag.
Verbosity value
~~~~~~~~~~~~~~~~
.. data:: NO_VERBOSE
No verbose messages.
.. data:: VERB_OPS
Operational information.
.. data:: VERB_DETAIL
Detailed information.
.. data:: VERB_QUERY
Query level information.
.. data:: VERB_ALGO
Algorithm level information.

View file

@ -0,0 +1,120 @@
Scriptable functions
====================
Network
-------
.. function:: ntohs(netshort)
This subroutine converts values between the host and network byte order.
Specifically, **ntohs()** converts 16-bit quantities from network byte order to host byte order.
:param netshort: 16-bit short addr
:rtype: converted addr
Cache
-----
.. function:: storeQueryInCache(qstate, qinfo, msgrep, is_referral)
Store pending query in local cache.
:param qstate: :class:`module_qstate`
:param qinfo: :class:`query_info`
:param msgrep: :class:`reply_info`
:param is_referal: integer
:rtype: boolean
.. function:: invalidateQueryInCache(qstate, qinfo)
Invalidate record in local cache.
:param qstate: :class:`module_qstate`
:param qinfo: :class:`query_info`
Logging
-------
.. function:: verbose(level, msg)
Log a verbose message, pass the level for this message.
No trailing newline is needed.
:param level: verbosity level for this message, compared to global verbosity setting.
:param msg: string message
.. function:: log_info(msg)
Log informational message. No trailing newline is needed.
:param msg: string message
.. function:: log_err(msg)
Log error message. No trailing newline is needed.
:param msg: string message
.. function:: log_warn(msg)
Log warning message. No trailing newline is needed.
:param msg: string message
.. function:: log_hex(msg, data, length)
Log a hex-string to the log. Can be any length.
performs mallocs to do so, slow. But debug useful.
:param msg: string desc to accompany the hexdump.
:param data: data to dump in hex format.
:param length: length of data.
.. function:: log_dns_msg(str, qinfo, reply)
Log DNS message.
:param str: string message
:param qinfo: :class:`query_info`
:param reply: :class:`reply_info`
.. function:: log_query_info(verbosity_value, str, qinf)
Log query information.
:param verbosity_value: see constants
:param str: string message
:param qinf: :class:`query_info`
.. function:: regional_log_stats(r)
Log regional statistics.
:param r: :class:`regional`
Debugging
---------
.. function:: strextstate(module_ext_state)
Debug utility, module external qstate to string.
:param module_ext_state: the state value.
:rtype: descriptive string.
.. function:: strmodulevent(module_event)
Debug utility, module event to string.
:param module_event: the module event value.
:rtype: descriptive string.
.. function:: ldns_rr_type2str(atype)
Convert RR type to string.
.. function:: ldns_rr_class2str(aclass)
Convert RR class to string.

View file

@ -0,0 +1,11 @@
Unbound module documentation
=======================================
.. toctree::
:maxdepth: 2
env
struct
functions
config

View file

@ -0,0 +1,427 @@
Scriptable structures
=====================
module_qstate
-----------------------
.. class:: module_qstate
Module state, per query.
This class provides these data attributes:
.. attribute:: qinfo
(:class:`query_info`) Informations about query being answered. Name, RR type, RR class.
.. attribute:: query_flags
(uint16) Flags for query. See QF_BIT\_ predefined constants.
.. attribute:: is_priming
If this is a (stub or root) priming query (with hints).
.. attribute:: reply
comm_reply contains server replies.
.. attribute:: return_msg
(:class:`dns_msg`) The reply message, with message for client and calling module (read-only attribute).
Note that if you want to create of modify return_msg you should use :class:`DNSMessage`.
.. attribute:: return_rcode
The rcode, in case of error, instead of a reply message. Determines whether the return_msg contains reply.
.. attribute:: region
Region for this query. Cleared when query process finishes.
.. attribute:: curmod
Which module is executing.
.. attribute:: ext_state[]
Module states.
.. attribute:: env
Environment for this query.
.. attribute:: mesh_info
Mesh related information for this query.
query_info
----------------
.. class:: query_info
This class provides these data attributes:
.. attribute:: qname
The original question in the wireformat format (e.g. \\x03www\\x03nic\\x02cz\\x00 for www.nic.cz)
.. attribute:: qname_len
Lenght of question name (number of bytes).
.. attribute:: qname_list[]
The question ``qname`` converted into list of labels (e.g. ['www','nic','cz',''] for www.nic.cz)
.. attribute:: qname_str
The question ``qname`` converted into string (e.g. www.nic.cz. for www.nic.cz)
.. attribute:: qtype
The class type asked for. See RR_TYPE\_ predefined constants.
.. attribute:: qtype_str
The ``qtype`` in display presentation format (string) (e.g 'A' for RR_TYPE_A)
.. attribute:: qclass
The question class. See RR_CLASS\_ predefined constants.
.. attribute:: qclass_str
The ``qclass`` in display presentation format (string).
reply_info
--------------------
.. class:: reply_info
This class provides these data attributes:
.. attribute:: flags
The flags for the answer, host byte order.
.. attribute:: qdcount
Number of RRs in the query section.
If qdcount is not 0, then it is 1, and the data that appears
in the reply is the same as the query_info.
Host byte order.
.. attribute:: ttl
TTL of the entire reply (for negative caching).
only for use when there are 0 RRsets in this message.
if there are RRsets, check those instead.
.. attribute:: security
The security status from DNSSEC validation of this message. See sec_status\_ predefined constants.
.. attribute:: an_numrrsets
Number of RRsets in each section.
The answer section. Add up the RRs in every RRset to calculate
the number of RRs, and the count for the dns packet.
The number of RRs in RRsets can change due to RRset updates.
.. attribute:: ns_numrrsets
Count of authority section RRsets
.. attribute:: ar_numrrsets
Count of additional section RRsets
.. attribute:: rrset_count
Number of RRsets: an_numrrsets + ns_numrrsets + ar_numrrsets
.. attribute:: rrsets[]
(:class:`ub_packed_rrset_key`) List of RR sets in the order in which they appear in the reply message.
Number of elements is ancount + nscount + arcount RRsets.
.. attribute:: ref[]
(:class:`rrset_ref`) Packed array of ids (see counts) and pointers to packed_rrset_key.
The number equals ancount + nscount + arcount RRsets.
These are sorted in ascending pointer, the locking order. So
this list can be locked (and id, ttl checked), to see if
all the data is available and recent enough.
dns_msg
--------------
.. class:: dns_msg
Region allocated message reply
This class provides these data attributes:
.. attribute:: qinfo
(:class:`query_info`) Informations about query.
.. attribute:: rep
(:class:`reply_info`) This attribute points to the packed reply structure.
packed_rrset_key
----------------------
.. class:: packed_rrset_key
The identifying information for an RRset.
This class provides these data attributes:
.. attribute:: dname
The domain name. If not empty (for ``id = None``) it is allocated, and
contains the wireformat domain name. This dname is not canonicalized.
E.g., the dname contains \\x03www\\x03nic\\x02cz\\x00 for www.nic.cz.
.. attribute:: dname_len
Length of the domain name, including last 0 root octet.
.. attribute:: dname_list[]
The domain name ``dname`` converted into list of labels (see :attr:`query_info.qname_list`).
.. attribute:: dname_str
The domain name ``dname`` converted into string (see :attr:`query_info.qname_str`).
.. attribute:: flags
Flags.
.. attribute:: type
The rrset type in network format.
.. attribute:: type_str
The rrset type in display presentation format.
.. attribute:: rrset_class
The rrset class in network format.
.. attribute:: rrset_class_str
The rrset class in display presentation format.
ub_packed_rrset_key
-------------------------
.. class:: ub_packed_rrset_key
This structure contains an RRset. A set of resource records that
share the same domain name, type and class.
Due to memory management and threading, the key structure cannot be
deleted, although the data can be. The id can be set to 0 to store and the
structure can be recycled with a new id.
The :class:`ub_packed_rrset_key` provides these data attributes:
.. attribute:: entry
(:class:`lruhash_entry`) Entry into hashtable. Note the lock is never destroyed,
even when this key is retired to the cache.
the data pointer (if not None) points to a :class:`packed_rrset`.
.. attribute:: id
The ID of this rrset. unique, based on threadid + sequenceno.
ids are not reused, except after flushing the cache.
zero is an unused entry, and never a valid id.
Check this value after getting entry.lock.
The other values in this struct may only be altered after changing
the id (which needs a writelock on entry.lock).
.. attribute:: rk
(:class:`packed_rrset_key`) RR set data.
lruhash_entry
-------------------------
.. class:: lruhash_entry
The :class:`ub_packed_rrset_key` provides these data attributes:
.. attribute:: lock
rwlock for access to the contents of the entry. Note that you cannot change hash and key, if so, you have to delete it to change hash or key.
.. attribute:: data
(:class:`packed_rrset_data`) entry data stored in wireformat (RRs and RRsigs).
packed_rrset_data
-----------------------
.. class:: packed_rrset_data
Rdata is stored in wireformat. The dname is stored in wireformat.
TTLs are stored as absolute values (and could be expired).
RRSIGs are stored in the arrays after the regular rrs.
You need the packed_rrset_key to know dname, type, class of the
resource records in this RRset. (if signed the rrsig gives the type too).
The :class:`packed_rrset_data` provides these data attributes:
.. attribute:: ttl
TTL (in seconds like time()) of the RRset.
Same for all RRs see rfc2181(5.2).
.. attribute:: count
Number of RRs.
.. attribute:: rrsig_count
Number of rrsigs, if 0 no rrsigs.
.. attribute:: trust
The trustworthiness of the RRset data.
.. attribute:: security
Security status of the RRset data. See sec_status\_ predefined constants.
.. attribute:: rr_len[]
Length of every RR's rdata, rr_len[i] is size of rr_data[i].
.. attribute:: rr_ttl[]
TTL of every rr. rr_ttl[i] ttl of rr i.
.. attribute:: rr_data[]
Array of RR's rdata (list of strings). The rdata is stored in uncompressed wireformat.
The first 16B of rr_data[i] is rdlength in network format.
DNSMessage
----------------
.. class:: DNSMessage
Abstract representation of DNS message.
**Usage**
This example shows how to create an authoritative answer response
::
msg = DNSMessage(qstate.qinfo.qname_str, RR_TYPE_A, RR_CLASS_IN, PKT_AA)
#append RR
if (qstate.qinfo.qtype == RR_TYPE_A) or (qstate.qinfo.qtype == RR_TYPE_ANY):
msg.answer.append("%s 10 IN A 127.0.0.1" % qstate.qinfo.qname_str)
#set qstate.return_msg
if not msg.set_return_msg(qstate):
raise Exception("Can't create response")
The :class:`DNSMessage` provides these methods and data attributes:
.. method:: __init__(self, rr_name, rr_type, rr_class = RR_CLASS_IN, query_flags = 0, default_ttl = 0)
Prepares an answer (DNS packet) from qiven information. Query flags are combination of PKT_xx contants.
.. method:: set_return_msg(self, qstate)
This method fills qstate return message according to the given informations.
It takes lists of RRs in each section of answer, created necessray RRsets in wire format and store the result in :attr:`qstate.return_msg`.
Returns 1 if OK.
.. attribute:: rr_name
RR name of question.
.. attribute:: rr_type
RR type of question.
.. attribute:: rr_class
RR class of question.
.. attribute:: default_ttl
Default time-to-live.
.. attribute:: query_flags
Query flags. See PKT\_ predefined constants.
.. attribute:: question[]
List of resource records that should appear (in the same order) in question section of answer.
.. attribute:: answer[]
List of resource records that should appear (in the same order) in answer section of answer.
.. attribute:: authority[]
List of resource records that should appear (in the same order) in authority section of answer.
.. attribute:: additional[]
List of resource records that should appear (in the same order) in additional section of answer.
pythonmod_env
-----------------------
.. class:: pythonmod_env
Global state for the module.
This class provides these data attributes:
.. attribute:: data
Here you can keep your own data shared across each thread.
.. attribute:: fname
Python script filename.
.. attribute:: qstate
Module query state.
pythonmod_qstate
-----------------------
.. class:: pythonmod_qstate
Per query state for the iterator module.
This class provides these data attributes:
.. attribute:: data
Here you can keep your own private data (each thread has own data object).

View file

@ -0,0 +1,38 @@
Use cases (examples)
====================
Dynamic DNS Service discovery (DNS-SD_)
-------------------------------------------
Synchronized with database engine, for example *MySQL*.
.. _DNS-SD: http://www.dns-sd.org/
Firewall control
----------------
Control firewall (e.g. enable incomming SSH connection) with DNS query signed with private key.
So firewall can blocks every service during normal operation.
Scriptable DNS-based blacklist (DNS-BL_)
-------------------------------------------
Scripted in Python with already provided features, takes advantage of DNS reply, because
almost every mail server supports DNS based blacklisting.
.. _DNS-BL: http://www.dnsbl.org
DNS based Wake-On-Lan
---------------------
Controled by secured queries secured with private key.
Dynamic translation service
---------------------------
DNS request can be translated to virtualy any answer, that's easy to implement in client side
because of many DNS libraries available.
Examples :
* **Dictionary** - using *IDN* for non-ascii strings transfer, ``dig TXT slovo.en._dict_.nic.cz`` returns translation of "slovo" to EN.
* **Translation** - Extends *DNS-SD*, for example DNS to Jabber to find out people logged in.
* **Exchange rate calculator** - ``dig TXT 1000.99.czk.eur._rates_.nic.cz`` returns the given sum (1000.99 CZK) in EURs.
Dynamic ENUM service
--------------------
Support for redirection, synchronization, etc.