mirror of
https://github.com/monero-project/monero.git
synced 2025-05-07 22:35:02 -04:00
added unbound to external deps
This commit is contained in:
parent
732493c5cb
commit
9ef094b356
394 changed files with 199264 additions and 0 deletions
28
external/unbound/pythonmod/LICENSE
vendored
Normal file
28
external/unbound/pythonmod/LICENSE
vendored
Normal file
|
@ -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.
|
58
external/unbound/pythonmod/Makefile
vendored
Normal file
58
external/unbound/pythonmod/Makefile
vendored
Normal file
|
@ -0,0 +1,58 @@
|
|||
# Makefile: tests unbound python module (please edit SCRIPT variable)
|
||||
#
|
||||
# Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
|
||||
# Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz)
|
||||
#
|
||||
# This software is open source.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
#
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
#
|
||||
# * Neither the name of the organization nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from this
|
||||
# software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
SUEXEC = sudo
|
||||
UNBOUND = ../unbound
|
||||
SCRIPT = ./test-resip.conf
|
||||
|
||||
UNBOUND_OPTS = -dv -c $(SCRIPT)
|
||||
|
||||
.PHONY: test sudo suexec doc
|
||||
|
||||
all: test
|
||||
|
||||
$(UNBOUND):
|
||||
make -C ..
|
||||
|
||||
test: $(UNBOUND)
|
||||
$(UNBOUND) $(UNBOUND_OPTS)
|
||||
|
||||
sudo: $(UNBOUND)
|
||||
sudo $(UNBOUND) $(UNBOUND_OPTS)
|
||||
|
||||
suexec: $(UNBOUND)
|
||||
su -c "$(UNBOUND) $(UNBOUND_OPTS)"
|
||||
|
||||
doc:
|
||||
$(MAKE) -C doc html
|
1
external/unbound/pythonmod/doc/_static/readme
vendored
Normal file
1
external/unbound/pythonmod/doc/_static/readme
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
this directory exists to pacify sphinx-build.
|
179
external/unbound/pythonmod/doc/conf.py
vendored
Normal file
179
external/unbound/pythonmod/doc/conf.py
vendored
Normal 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
|
34
external/unbound/pythonmod/doc/examples/example0-1.py
vendored
Normal file
34
external/unbound/pythonmod/doc/examples/example0-1.py
vendored
Normal 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.")
|
129
external/unbound/pythonmod/doc/examples/example0.rst
vendored
Normal file
129
external/unbound/pythonmod/doc/examples/example0.rst
vendored
Normal 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.
|
||||
|
42
external/unbound/pythonmod/doc/examples/example1.rst
vendored
Normal file
42
external/unbound/pythonmod/doc/examples/example1.rst
vendored
Normal 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 .
|
||||
|
46
external/unbound/pythonmod/doc/examples/example2.rst
vendored
Normal file
46
external/unbound/pythonmod/doc/examples/example2.rst
vendored
Normal 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.
|
63
external/unbound/pythonmod/doc/examples/example3.rst
vendored
Normal file
63
external/unbound/pythonmod/doc/examples/example3.rst
vendored
Normal 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.
|
164
external/unbound/pythonmod/doc/examples/example4.rst
vendored
Normal file
164
external/unbound/pythonmod/doc/examples/example4.rst
vendored
Normal 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
|
15
external/unbound/pythonmod/doc/examples/index.rst
vendored
Normal file
15
external/unbound/pythonmod/doc/examples/index.rst
vendored
Normal 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*
|
34
external/unbound/pythonmod/doc/index.rst
vendored
Normal file
34
external/unbound/pythonmod/doc/index.rst
vendored
Normal 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`
|
||||
|
59
external/unbound/pythonmod/doc/install.rst
vendored
Normal file
59
external/unbound/pythonmod/doc/install.rst
vendored
Normal 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.
|
350
external/unbound/pythonmod/doc/modules/config.rst
vendored
Normal file
350
external/unbound/pythonmod/doc/modules/config.rst
vendored
Normal 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.
|
412
external/unbound/pythonmod/doc/modules/env.rst
vendored
Normal file
412
external/unbound/pythonmod/doc/modules/env.rst
vendored
Normal 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.
|
120
external/unbound/pythonmod/doc/modules/functions.rst
vendored
Normal file
120
external/unbound/pythonmod/doc/modules/functions.rst
vendored
Normal 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.
|
11
external/unbound/pythonmod/doc/modules/index.rst
vendored
Normal file
11
external/unbound/pythonmod/doc/modules/index.rst
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
Unbound module documentation
|
||||
=======================================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
env
|
||||
struct
|
||||
functions
|
||||
config
|
||||
|
427
external/unbound/pythonmod/doc/modules/struct.rst
vendored
Normal file
427
external/unbound/pythonmod/doc/modules/struct.rst
vendored
Normal 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).
|
||||
|
38
external/unbound/pythonmod/doc/usecase.rst
vendored
Normal file
38
external/unbound/pythonmod/doc/usecase.rst
vendored
Normal 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.
|
77
external/unbound/pythonmod/examples/calc.py
vendored
Normal file
77
external/unbound/pythonmod/examples/calc.py
vendored
Normal file
|
@ -0,0 +1,77 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
calc.py: DNS-based calculator
|
||||
|
||||
Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
|
||||
Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz)
|
||||
|
||||
This software is open source.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the organization nor the names of its
|
||||
contributors may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
'''
|
||||
|
||||
#Try: dig @localhost 1*25._calc_.cz.
|
||||
|
||||
def init(id, cfg): return True
|
||||
def deinit(id): return True
|
||||
def inform_super(id, qstate, superqstate, qdata): return True
|
||||
|
||||
def operate(id, event, qstate, qdata):
|
||||
|
||||
if (event == MODULE_EVENT_NEW) or (event == MODULE_EVENT_PASS):
|
||||
|
||||
if qstate.qinfo.qname_str.endswith("._calc_.cz."):
|
||||
try:
|
||||
res = eval(''.join(qstate.qinfo.qname_list[0:-3]))
|
||||
except:
|
||||
res = "exception"
|
||||
|
||||
msg = DNSMessage(qstate.qinfo.qname_str, RR_TYPE_TXT, RR_CLASS_IN, PKT_QR | PKT_RA | PKT_AA) #, 300)
|
||||
msg.answer.append("%s 300 IN TXT \"%s\"" % (qstate.qinfo.qname_str,res))
|
||||
if not msg.set_return_msg(qstate):
|
||||
qstate.ext_state[id] = MODULE_ERROR
|
||||
return True
|
||||
|
||||
qstate.return_rcode = RCODE_NOERROR
|
||||
qstate.ext_state[id] = MODULE_FINISHED
|
||||
return True
|
||||
|
||||
else:
|
||||
#Pass on the unknown query to the iterator
|
||||
qstate.ext_state[id] = MODULE_WAIT_MODULE
|
||||
return True
|
||||
|
||||
elif event == MODULE_EVENT_MODDONE:
|
||||
#the iterator has finished
|
||||
qstate.ext_state[id] = MODULE_FINISHED
|
||||
return True
|
||||
|
||||
log_err("pythonmod: Unknown event")
|
||||
qstate.ext_state[id] = MODULE_ERROR
|
||||
return True
|
||||
|
121
external/unbound/pythonmod/examples/dict.py
vendored
Normal file
121
external/unbound/pythonmod/examples/dict.py
vendored
Normal file
|
@ -0,0 +1,121 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
calc.py: DNS-based czech-english dictionary
|
||||
|
||||
Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
|
||||
Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz)
|
||||
|
||||
This software is open source.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the organization nor the names of its
|
||||
contributors may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
'''
|
||||
import os
|
||||
cz_dict = {}
|
||||
en_dict = {}
|
||||
|
||||
def init(id, cfg):
|
||||
log_info("pythonmod: dict init")
|
||||
f = open("examples/dict_data.txt", "r")
|
||||
try:
|
||||
for line in f:
|
||||
if line.startswith('#'):
|
||||
continue
|
||||
itm = line.split("\t", 3)
|
||||
if len(itm) < 2:
|
||||
continue
|
||||
en,cs = itm[0:2]
|
||||
|
||||
if not (cs in cz_dict):
|
||||
cz_dict[cs] = [en] # [cs] = en
|
||||
else:
|
||||
cz_dict[cs].append(en) # [cs] = en
|
||||
|
||||
if not (en in en_dict):
|
||||
en_dict[en] = [cs] # [en] = cs
|
||||
else:
|
||||
en_dict[en].append(cs) # [en] = cs
|
||||
|
||||
finally:
|
||||
f.close()
|
||||
return True
|
||||
|
||||
def deinit(id):
|
||||
log_info("pythonmod: dict deinit")
|
||||
return True
|
||||
|
||||
def operate(id, event, qstate, qdata):
|
||||
if (event == MODULE_EVENT_NEW) or (event == MODULE_EVENT_PASS):
|
||||
|
||||
if qstate.qinfo.qname_str.endswith("._dict_.cz."):
|
||||
|
||||
aword = ' '.join(qstate.qinfo.qname_list[0:-4])
|
||||
adict = qstate.qinfo.qname_list[-4]
|
||||
|
||||
log_info("pythonmod: dictionary look up; word:%s dict:%s" % (aword,adict))
|
||||
|
||||
words = []
|
||||
if (adict == "en") and (aword in en_dict):
|
||||
words = en_dict[aword] # EN -> CS
|
||||
if (adict == "cs") and (aword in cz_dict):
|
||||
words = cz_dict[aword] # CS -> EN
|
||||
|
||||
if len(words) and ((qstate.qinfo.qtype == RR_TYPE_TXT) or (qstate.qinfo.qtype == RR_TYPE_ANY)):
|
||||
|
||||
msg = DNSMessage(qstate.qinfo.qname_str, RR_TYPE_TXT, RR_CLASS_IN, PKT_RD | PKT_RA | PKT_AA)
|
||||
for w in words:
|
||||
msg.answer.append("%s 300 IN TXT \"%s\"" % (qstate.qinfo.qname_str,w.replace("\"","\\\"")))
|
||||
|
||||
if not msg.set_return_msg(qstate):
|
||||
qstate.ext_state[id] = MODULE_ERROR
|
||||
return True
|
||||
|
||||
qstate.return_rcode = RCODE_NOERROR
|
||||
qstate.ext_state[id] = MODULE_FINISHED
|
||||
return True
|
||||
|
||||
else:
|
||||
qstate.return_rcode = RCODE_SERVFAIL
|
||||
qstate.ext_state[id] = MODULE_FINISHED
|
||||
return True
|
||||
|
||||
else: #Pass on the unknown query to the iterator
|
||||
qstate.ext_state[id] = MODULE_WAIT_MODULE
|
||||
return True
|
||||
|
||||
elif event == MODULE_EVENT_MODDONE: #the iterator has finished
|
||||
#we don't need modify result
|
||||
qstate.ext_state[id] = MODULE_FINISHED
|
||||
return True
|
||||
|
||||
log_err("pythonmod: Unknown event")
|
||||
qstate.ext_state[id] = MODULE_ERROR
|
||||
return True
|
||||
|
||||
def inform_super(id, qstate, superqstate, qdata):
|
||||
return True
|
||||
|
6
external/unbound/pythonmod/examples/dict_data.txt
vendored
Normal file
6
external/unbound/pythonmod/examples/dict_data.txt
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
* * web
|
||||
computer poèítaèový adj: Zdenìk Bro¾
|
||||
computer poèítaè n:
|
||||
domain doména n: Zdenìk Bro¾
|
||||
query otazník n: Zdenìk Bro¾
|
||||
network sí» n: [it.] poèítaèová
|
119
external/unbound/pythonmod/examples/log.py
vendored
Normal file
119
external/unbound/pythonmod/examples/log.py
vendored
Normal file
|
@ -0,0 +1,119 @@
|
|||
import os
|
||||
'''
|
||||
calc.py: Response packet logger
|
||||
|
||||
Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
|
||||
Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz)
|
||||
|
||||
This software is open source.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the organization nor the names of its
|
||||
contributors may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
'''
|
||||
|
||||
def dataHex(data, prefix=""):
|
||||
"""Converts binary string data to display representation form"""
|
||||
res = ""
|
||||
for i in range(0, (len(data)+15)/16):
|
||||
res += "%s0x%02X | " % (prefix, i*16)
|
||||
d = map(lambda x:ord(x), data[i*16:i*16+17])
|
||||
for ch in d:
|
||||
res += "%02X " % ch
|
||||
for i in range(0,17-len(d)):
|
||||
res += " "
|
||||
res += "| "
|
||||
for ch in d:
|
||||
if (ch < 32) or (ch > 127):
|
||||
res += ". "
|
||||
else:
|
||||
res += "%c " % ch
|
||||
res += "\n"
|
||||
return res
|
||||
|
||||
def logDnsMsg(qstate):
|
||||
"""Logs response"""
|
||||
|
||||
r = qstate.return_msg.rep
|
||||
q = qstate.return_msg.qinfo
|
||||
|
||||
print "-"*100
|
||||
print("Query: %s, type: %s (%d), class: %s (%d) " % (
|
||||
qstate.qinfo.qname_str, qstate.qinfo.qtype_str, qstate.qinfo.qtype,
|
||||
qstate.qinfo.qclass_str, qstate.qinfo.qclass))
|
||||
print "-"*100
|
||||
print "Return reply :: flags: %04X, QDcount: %d, Security:%d, TTL=%d" % (r.flags, r.qdcount, r.security, r.ttl)
|
||||
print " qinfo :: qname: %s %s, qtype: %s, qclass: %s" % (str(q.qname_list), q.qname_str, q.qtype_str, q.qclass_str)
|
||||
|
||||
if (r):
|
||||
print "Reply:"
|
||||
for i in range(0, r.rrset_count):
|
||||
rr = r.rrsets[i]
|
||||
|
||||
rk = rr.rk
|
||||
print i,":",rk.dname_list, rk.dname_str, "flags: %04X" % rk.flags,
|
||||
print "type:",rk.type_str,"(%d)" % ntohs(rk.type), "class:",rk.rrset_class_str,"(%d)" % ntohs(rk.rrset_class)
|
||||
|
||||
d = rr.entry.data
|
||||
for j in range(0,d.count+d.rrsig_count):
|
||||
print " ",j,":","TTL=",d.rr_ttl[j],
|
||||
if (j >= d.count): print "rrsig",
|
||||
print
|
||||
print dataHex(d.rr_data[j]," ")
|
||||
|
||||
print "-"*100
|
||||
|
||||
def init(id, cfg):
|
||||
log_info("pythonmod: init called, module id is %d port: %d script: %s" % (id, cfg.port, cfg.python_script))
|
||||
return True
|
||||
|
||||
def deinit(id):
|
||||
log_info("pythonmod: deinit called, module id is %d" % id)
|
||||
return True
|
||||
|
||||
def inform_super(id, qstate, superqstate, qdata):
|
||||
return True
|
||||
|
||||
def operate(id, event, qstate, qdata):
|
||||
log_info("pythonmod: operate called, id: %d, event:%s" % (id, strmodulevent(event)))
|
||||
|
||||
if (event == MODULE_EVENT_NEW) or (event == MODULE_EVENT_PASS):
|
||||
#Pass on the new event to the iterator
|
||||
qstate.ext_state[id] = MODULE_WAIT_MODULE
|
||||
return True
|
||||
|
||||
if event == MODULE_EVENT_MODDONE:
|
||||
#Iterator finished, show response (if any)
|
||||
|
||||
if (qstate.return_msg):
|
||||
logDnsMsg(qstate)
|
||||
|
||||
qstate.ext_state[id] = MODULE_FINISHED
|
||||
return True
|
||||
|
||||
qstate.ext_state[id] = MODULE_ERROR
|
||||
return True
|
||||
|
73
external/unbound/pythonmod/examples/resgen.py
vendored
Normal file
73
external/unbound/pythonmod/examples/resgen.py
vendored
Normal file
|
@ -0,0 +1,73 @@
|
|||
'''
|
||||
resgen.py: This example shows how to generate authoritative response
|
||||
|
||||
Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
|
||||
Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz)
|
||||
|
||||
This software is open source.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the organization nor the names of its
|
||||
contributors may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
'''
|
||||
def init(id, cfg): return True
|
||||
|
||||
def deinit(id): return True
|
||||
|
||||
def inform_super(id, qstate, superqstate, qdata): return True
|
||||
|
||||
def operate(id, event, qstate, qdata):
|
||||
if (event == MODULE_EVENT_NEW) or (event == MODULE_EVENT_PASS):
|
||||
if (qstate.qinfo.qname_str.endswith(".localdomain.")): #query name ends with localdomain
|
||||
#create instance of DNS message (packet) with given parameters
|
||||
msg = DNSMessage(qstate.qinfo.qname_str, RR_TYPE_A, RR_CLASS_IN, PKT_QR | PKT_RA | PKT_AA)
|
||||
#append RR
|
||||
if (qstate.qinfo.qtype == RR_TYPE_A) or (qstate.qinfo.qtype == RR_TYPE_ANY):
|
||||
msg.answer.append("%s 10 IN A 127.0.0.1" % qstate.qinfo.qname_str)
|
||||
#set qstate.return_msg
|
||||
if not msg.set_return_msg(qstate):
|
||||
qstate.ext_state[id] = MODULE_ERROR
|
||||
return True
|
||||
|
||||
#we don't need validation, result is valid
|
||||
qstate.return_msg.rep.security = 2
|
||||
|
||||
qstate.return_rcode = RCODE_NOERROR
|
||||
qstate.ext_state[id] = MODULE_FINISHED
|
||||
return True
|
||||
else:
|
||||
#pass the query to validator
|
||||
qstate.ext_state[id] = MODULE_WAIT_MODULE
|
||||
return True
|
||||
|
||||
if event == MODULE_EVENT_MODDONE:
|
||||
log_info("pythonmod: iterator module done")
|
||||
qstate.ext_state[id] = MODULE_FINISHED
|
||||
return True
|
||||
|
||||
log_err("pythonmod: bad event")
|
||||
qstate.ext_state[id] = MODULE_ERROR
|
||||
return True
|
96
external/unbound/pythonmod/examples/resip.py
vendored
Normal file
96
external/unbound/pythonmod/examples/resip.py
vendored
Normal file
|
@ -0,0 +1,96 @@
|
|||
'''
|
||||
resip.py: This example shows how to generate authoritative response
|
||||
and how to find out the IP address of a client
|
||||
|
||||
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.
|
||||
|
||||
|
||||
Usage:
|
||||
|
||||
dig @127.0.0.1 -t TXT what.is.my.ip.
|
||||
'''
|
||||
|
||||
def init(id, cfg): return True
|
||||
|
||||
def deinit(id): return True
|
||||
|
||||
def inform_super(id, qstate, superqstate, qdata): return True
|
||||
|
||||
def operate(id, event, qstate, qdata):
|
||||
print "Operate", event,"state:",qstate
|
||||
|
||||
# Please note that if this module blocks, by moving to the validator
|
||||
# to validate or iterator to lookup or spawn a subquery to look up,
|
||||
# then, other incoming queries are queued up onto this module and
|
||||
# all of them receive the same reply.
|
||||
# You can inspect the cache.
|
||||
|
||||
if (event == MODULE_EVENT_NEW) or (event == MODULE_EVENT_PASS):
|
||||
if (qstate.qinfo.qname_str.endswith("what.is.my.ip.")): #query name ends with localdomain
|
||||
#create instance of DNS message (packet) with given parameters
|
||||
msg = DNSMessage(qstate.qinfo.qname_str, RR_TYPE_TXT, RR_CLASS_IN, PKT_QR | PKT_RA | PKT_AA)
|
||||
#append RR
|
||||
if (qstate.qinfo.qtype == RR_TYPE_TXT) or (qstate.qinfo.qtype == RR_TYPE_ANY):
|
||||
rl = qstate.mesh_info.reply_list
|
||||
while (rl):
|
||||
if rl.query_reply:
|
||||
q = rl.query_reply
|
||||
# The TTL of 0 is mandatory, otherwise it ends up in
|
||||
# the cache, and is returned to other IP addresses.
|
||||
msg.answer.append("%s 0 IN TXT \"%s %d (%s)\"" % (qstate.qinfo.qname_str, q.addr,q.port,q.family))
|
||||
rl = rl.next
|
||||
|
||||
#set qstate.return_msg
|
||||
if not msg.set_return_msg(qstate):
|
||||
qstate.ext_state[id] = MODULE_ERROR
|
||||
return True
|
||||
|
||||
#we don't need validation, result is valid
|
||||
qstate.return_msg.rep.security = 2
|
||||
|
||||
qstate.return_rcode = RCODE_NOERROR
|
||||
qstate.ext_state[id] = MODULE_FINISHED
|
||||
return True
|
||||
else:
|
||||
#pass the query to validator
|
||||
qstate.ext_state[id] = MODULE_WAIT_MODULE
|
||||
return True
|
||||
|
||||
if event == MODULE_EVENT_MODDONE:
|
||||
log_info("pythonmod: iterator module done")
|
||||
qstate.ext_state[id] = MODULE_FINISHED
|
||||
return True
|
||||
|
||||
log_err("pythonmod: bad event")
|
||||
qstate.ext_state[id] = MODULE_ERROR
|
||||
return True
|
88
external/unbound/pythonmod/examples/resmod.py
vendored
Normal file
88
external/unbound/pythonmod/examples/resmod.py
vendored
Normal file
|
@ -0,0 +1,88 @@
|
|||
'''
|
||||
resmod.py: This example shows how to modify the response from iterator
|
||||
|
||||
Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
|
||||
Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz)
|
||||
|
||||
This software is open source.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the organization nor the names of its
|
||||
contributors may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
'''
|
||||
|
||||
def init(id, cfg): return True
|
||||
|
||||
def deinit(id): return True
|
||||
|
||||
def inform_super(id, qstate, superqstate, qdata): return True
|
||||
|
||||
def setTTL(qstate, ttl):
|
||||
"""Updates return_msg TTL and the TTL of all the RRs"""
|
||||
if qstate.return_msg:
|
||||
qstate.return_msg.rep.ttl = ttl
|
||||
if (qstate.return_msg.rep):
|
||||
for i in range(0,qstate.return_msg.rep.rrset_count):
|
||||
d = qstate.return_msg.rep.rrsets[i].entry.data
|
||||
for j in range(0,d.count+d.rrsig_count):
|
||||
d.rr_ttl[j] = ttl
|
||||
|
||||
def operate(id, event, qstate, qdata):
|
||||
if (event == MODULE_EVENT_NEW) or (event == MODULE_EVENT_PASS):
|
||||
#pass the query to validator
|
||||
qstate.ext_state[id] = MODULE_WAIT_MODULE
|
||||
return True
|
||||
|
||||
if event == MODULE_EVENT_MODDONE:
|
||||
log_info("pythonmod: iterator module done")
|
||||
|
||||
if not qstate.return_msg:
|
||||
qstate.ext_state[id] = MODULE_FINISHED
|
||||
return True
|
||||
|
||||
#modify the response
|
||||
|
||||
qdn = qstate.qinfo.qname_str
|
||||
if qdn.endswith(".nic.cz."):
|
||||
#invalidate response in cache added by iterator
|
||||
#invalidateQueryInCache(qstate, qstate.return_msg.qinfo)
|
||||
|
||||
#modify TTL to 10 secs and store response in cache
|
||||
#setTTL(qstate, 5)
|
||||
#if not storeQueryInCache(qstate, qstate.return_msg.qinfo, qstate.return_msg.rep, 0):
|
||||
# qstate.ext_state[id] = MODULE_ERROR
|
||||
# return False
|
||||
|
||||
#modify TTL of response, which will be send to a) validator and then b) client
|
||||
setTTL(qstate, 10)
|
||||
qstate.return_rcode = RCODE_NOERROR
|
||||
|
||||
qstate.ext_state[id] = MODULE_FINISHED
|
||||
return True
|
||||
|
||||
log_err("pythonmod: bad event")
|
||||
qstate.ext_state[id] = MODULE_ERROR
|
||||
return True
|
916
external/unbound/pythonmod/interface.i
vendored
Normal file
916
external/unbound/pythonmod/interface.i
vendored
Normal file
|
@ -0,0 +1,916 @@
|
|||
/*
|
||||
* interface.i: unbound python module
|
||||
*/
|
||||
|
||||
%module unboundmodule
|
||||
%{
|
||||
/**
|
||||
* \file
|
||||
* This is the interface between the unbound server and a python module
|
||||
* called to perform operations on queries.
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <stdarg.h>
|
||||
#include "config.h"
|
||||
#include "util/log.h"
|
||||
#include "util/module.h"
|
||||
#include "util/netevent.h"
|
||||
#include "util/regional.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/data/msgreply.h"
|
||||
#include "util/data/packed_rrset.h"
|
||||
#include "util/data/dname.h"
|
||||
#include "util/storage/lruhash.h"
|
||||
#include "services/cache/dns.h"
|
||||
#include "services/mesh.h"
|
||||
#include "ldns/wire2str.h"
|
||||
#include "ldns/str2wire.h"
|
||||
#include "ldns/pkthdr.h"
|
||||
%}
|
||||
|
||||
%include "stdint.i" // uint_16_t can be known type now
|
||||
|
||||
%inline %{
|
||||
//converts [len][data][len][data][0] string to a List of labels (PyStrings)
|
||||
PyObject* GetNameAsLabelList(const char* name, int len) {
|
||||
PyObject* list;
|
||||
int cnt=0, i;
|
||||
|
||||
i = 0;
|
||||
while (i < len) {
|
||||
i += name[i] + 1;
|
||||
cnt++;
|
||||
}
|
||||
|
||||
list = PyList_New(cnt);
|
||||
i = 0; cnt = 0;
|
||||
while (i < len) {
|
||||
PyList_SetItem(list, cnt, PyBytes_FromStringAndSize(name + i + 1, name[i]));
|
||||
i += name[i] + 1;
|
||||
cnt++;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
%}
|
||||
|
||||
/* ************************************************************************************ *
|
||||
Structure query_info
|
||||
* ************************************************************************************ */
|
||||
/* Query info */
|
||||
%ignore query_info::qname;
|
||||
%ignore query_info::qname_len;
|
||||
|
||||
|
||||
struct query_info {
|
||||
%immutable;
|
||||
char* qname;
|
||||
size_t qname_len;
|
||||
uint16_t qtype;
|
||||
uint16_t qclass;
|
||||
%mutable;
|
||||
};
|
||||
|
||||
%inline %{
|
||||
enum enum_rr_class {
|
||||
RR_CLASS_IN = 1,
|
||||
RR_CLASS_CH = 3,
|
||||
RR_CLASS_HS = 4,
|
||||
RR_CLASS_NONE = 254,
|
||||
RR_CLASS_ANY = 255,
|
||||
};
|
||||
|
||||
enum enum_rr_type {
|
||||
RR_TYPE_A = 1,
|
||||
RR_TYPE_NS = 2,
|
||||
RR_TYPE_MD = 3,
|
||||
RR_TYPE_MF = 4,
|
||||
RR_TYPE_CNAME = 5,
|
||||
RR_TYPE_SOA = 6,
|
||||
RR_TYPE_MB = 7,
|
||||
RR_TYPE_MG = 8,
|
||||
RR_TYPE_MR = 9,
|
||||
RR_TYPE_NULL = 10,
|
||||
RR_TYPE_WKS = 11,
|
||||
RR_TYPE_PTR = 12,
|
||||
RR_TYPE_HINFO = 13,
|
||||
RR_TYPE_MINFO = 14,
|
||||
RR_TYPE_MX = 15,
|
||||
RR_TYPE_TXT = 16,
|
||||
RR_TYPE_RP = 17,
|
||||
RR_TYPE_AFSDB = 18,
|
||||
RR_TYPE_X25 = 19,
|
||||
RR_TYPE_ISDN = 20,
|
||||
RR_TYPE_RT = 21,
|
||||
RR_TYPE_NSAP = 22,
|
||||
RR_TYPE_NSAP_PTR = 23,
|
||||
RR_TYPE_SIG = 24,
|
||||
RR_TYPE_KEY = 25,
|
||||
RR_TYPE_PX = 26,
|
||||
RR_TYPE_GPOS = 27,
|
||||
RR_TYPE_AAAA = 28,
|
||||
RR_TYPE_LOC = 29,
|
||||
RR_TYPE_NXT = 30,
|
||||
RR_TYPE_EID = 31,
|
||||
RR_TYPE_NIMLOC = 32,
|
||||
RR_TYPE_SRV = 33,
|
||||
RR_TYPE_ATMA = 34,
|
||||
RR_TYPE_NAPTR = 35,
|
||||
RR_TYPE_KX = 36,
|
||||
RR_TYPE_CERT = 37,
|
||||
RR_TYPE_A6 = 38,
|
||||
RR_TYPE_DNAME = 39,
|
||||
RR_TYPE_SINK = 40,
|
||||
RR_TYPE_OPT = 41,
|
||||
RR_TYPE_APL = 42,
|
||||
RR_TYPE_DS = 43,
|
||||
RR_TYPE_SSHFP = 44,
|
||||
RR_TYPE_IPSECKEY = 45,
|
||||
RR_TYPE_RRSIG = 46,
|
||||
RR_TYPE_NSEC = 47,
|
||||
RR_TYPE_DNSKEY = 48,
|
||||
RR_TYPE_DHCID = 49,
|
||||
RR_TYPE_NSEC3 = 50,
|
||||
RR_TYPE_NSEC3PARAMS = 51,
|
||||
RR_TYPE_UINFO = 100,
|
||||
RR_TYPE_UID = 101,
|
||||
RR_TYPE_GID = 102,
|
||||
RR_TYPE_UNSPEC = 103,
|
||||
RR_TYPE_TSIG = 250,
|
||||
RR_TYPE_IXFR = 251,
|
||||
RR_TYPE_AXFR = 252,
|
||||
RR_TYPE_MAILB = 253,
|
||||
RR_TYPE_MAILA = 254,
|
||||
RR_TYPE_ANY = 255,
|
||||
RR_TYPE_DLV = 32769,
|
||||
};
|
||||
|
||||
PyObject* _get_qname(struct query_info* q) {
|
||||
return PyBytes_FromStringAndSize((char*)q->qname, q->qname_len);
|
||||
}
|
||||
|
||||
PyObject* _get_qname_components(struct query_info* q) {
|
||||
return GetNameAsLabelList((const char*)q->qname, q->qname_len);
|
||||
}
|
||||
%}
|
||||
|
||||
%inline %{
|
||||
PyObject* dnameAsStr(const char* dname) {
|
||||
char buf[LDNS_MAX_DOMAINLEN+1];
|
||||
buf[0] = '\0';
|
||||
dname_str((uint8_t*)dname, buf);
|
||||
return PyString_FromString(buf);
|
||||
}
|
||||
%}
|
||||
|
||||
%extend query_info {
|
||||
%pythoncode %{
|
||||
def _get_qtype_str(self): return sldns_wire2str_type(self.qtype)
|
||||
__swig_getmethods__["qtype_str"] = _get_qtype_str
|
||||
if _newclass:qtype_str = _swig_property(_get_qtype_str)
|
||||
|
||||
def _get_qclass_str(self): return sldns_wire2str_class(self.qclass)
|
||||
__swig_getmethods__["qclass_str"] = _get_qclass_str
|
||||
if _newclass:qclass_str = _swig_property(_get_qclass_str)
|
||||
|
||||
__swig_getmethods__["qname"] = _unboundmodule._get_qname
|
||||
if _newclass:qname = _swig_property(_unboundmodule._get_qname)
|
||||
|
||||
__swig_getmethods__["qname_list"] = _unboundmodule._get_qname_components
|
||||
if _newclass:qname_list = _swig_property(_unboundmodule._get_qname_components)
|
||||
|
||||
def _get_qname_str(self): return dnameAsStr(self.qname)
|
||||
__swig_getmethods__["qname_str"] = _get_qname_str
|
||||
if _newclass:qname_str = _swig_property(_get_qname_str)
|
||||
%}
|
||||
}
|
||||
|
||||
/* ************************************************************************************ *
|
||||
Structure packed_rrset_key
|
||||
* ************************************************************************************ */
|
||||
%ignore packed_rrset_key::dname;
|
||||
%ignore packed_rrset_key::dname_len;
|
||||
|
||||
/* RRsets */
|
||||
struct packed_rrset_key {
|
||||
%immutable;
|
||||
char* dname;
|
||||
size_t dname_len;
|
||||
uint32_t flags;
|
||||
uint16_t type; //rrset type in network format
|
||||
uint16_t rrset_class; //rrset class in network format
|
||||
%mutable;
|
||||
};
|
||||
|
||||
//This subroutine converts values between the host and network byte order.
|
||||
//Specifically, ntohs() converts 16-bit quantities from network byte order to host byte order.
|
||||
uint16_t ntohs(uint16_t netshort);
|
||||
|
||||
%inline %{
|
||||
PyObject* _get_dname(struct packed_rrset_key* k) {
|
||||
return PyBytes_FromStringAndSize((char*)k->dname, k->dname_len);
|
||||
}
|
||||
PyObject* _get_dname_components(struct packed_rrset_key* k) {
|
||||
return GetNameAsLabelList((char*)k->dname, k->dname_len);
|
||||
}
|
||||
%}
|
||||
|
||||
%extend packed_rrset_key {
|
||||
%pythoncode %{
|
||||
def _get_type_str(self): return sldns_wire2str_type(_unboundmodule.ntohs(self.type))
|
||||
__swig_getmethods__["type_str"] = _get_type_str
|
||||
if _newclass:type_str = _swig_property(_get_type_str)
|
||||
|
||||
def _get_class_str(self): return sldns_wire2str_class(_unboundmodule.ntohs(self.rrset_class))
|
||||
__swig_getmethods__["rrset_class_str"] = _get_class_str
|
||||
if _newclass:rrset_class_str = _swig_property(_get_class_str)
|
||||
|
||||
__swig_getmethods__["dname"] = _unboundmodule._get_dname
|
||||
if _newclass:dname = _swig_property(_unboundmodule._get_dname)
|
||||
|
||||
__swig_getmethods__["dname_list"] = _unboundmodule._get_dname_components
|
||||
if _newclass:dname_list = _swig_property(_unboundmodule._get_dname_components)
|
||||
|
||||
def _get_dname_str(self): return dnameAsStr(self.dname)
|
||||
__swig_getmethods__["dname_str"] = _get_dname_str
|
||||
if _newclass:dname_str = _swig_property(_get_dname_str)
|
||||
%}
|
||||
}
|
||||
|
||||
#if defined(SWIGWORDSIZE64)
|
||||
typedef long int rrset_id_t;
|
||||
#else
|
||||
typedef long long int rrset_id_t;
|
||||
#endif
|
||||
|
||||
struct ub_packed_rrset_key {
|
||||
struct lruhash_entry entry;
|
||||
rrset_id_t id;
|
||||
struct packed_rrset_key rk;
|
||||
};
|
||||
|
||||
struct lruhash_entry {
|
||||
lock_rw_t lock;
|
||||
struct lruhash_entry* overflow_next;
|
||||
struct lruhash_entry* lru_next;
|
||||
struct lruhash_entry* lru_prev;
|
||||
hashvalue_t hash;
|
||||
void* key;
|
||||
struct packed_rrset_data* data;
|
||||
};
|
||||
|
||||
%ignore packed_rrset_data::rr_len;
|
||||
%ignore packed_rrset_data::rr_ttl;
|
||||
%ignore packed_rrset_data::rr_data;
|
||||
|
||||
struct packed_rrset_data {
|
||||
uint32_t ttl; //TTL (in seconds like time())
|
||||
|
||||
size_t count; //number of rrs
|
||||
size_t rrsig_count; //number of rrsigs
|
||||
|
||||
enum rrset_trust trust;
|
||||
enum sec_status security;
|
||||
|
||||
size_t* rr_len; //length of every rr's rdata
|
||||
uint32_t *rr_ttl; //ttl of every rr
|
||||
uint8_t** rr_data; //array of pointers to every rr's rdata; The rr_data[i] rdata is stored in uncompressed wireformat.
|
||||
};
|
||||
|
||||
%pythoncode %{
|
||||
class RRSetData_RRLen:
|
||||
def __init__(self, obj): self.obj = obj
|
||||
def __getitem__(self, index): return _unboundmodule._get_data_rr_len(self.obj, index)
|
||||
def __len__(self): return obj.count + obj.rrsig_count
|
||||
class RRSetData_RRTTL:
|
||||
def __init__(self, obj): self.obj = obj
|
||||
def __getitem__(self, index): return _unboundmodule._get_data_rr_ttl(self.obj, index)
|
||||
def __setitem__(self, index, value): _unboundmodule._set_data_rr_ttl(self.obj, index, value)
|
||||
def __len__(self): return obj.count + obj.rrsig_count
|
||||
class RRSetData_RRData:
|
||||
def __init__(self, obj): self.obj = obj
|
||||
def __getitem__(self, index): return _unboundmodule._get_data_rr_data(self.obj, index)
|
||||
def __len__(self): return obj.count + obj.rrsig_count
|
||||
%}
|
||||
|
||||
%inline %{
|
||||
PyObject* _get_data_rr_len(struct packed_rrset_data* d, int idx) {
|
||||
if ((d != NULL) && (idx >= 0) &&
|
||||
((size_t)idx < (d->count+d->rrsig_count)))
|
||||
return PyInt_FromLong(d->rr_len[idx]);
|
||||
return Py_None;
|
||||
}
|
||||
void _set_data_rr_ttl(struct packed_rrset_data* d, int idx, uint32_t ttl)
|
||||
{
|
||||
if ((d != NULL) && (idx >= 0) &&
|
||||
((size_t)idx < (d->count+d->rrsig_count)))
|
||||
d->rr_ttl[idx] = ttl;
|
||||
}
|
||||
PyObject* _get_data_rr_ttl(struct packed_rrset_data* d, int idx) {
|
||||
if ((d != NULL) && (idx >= 0) &&
|
||||
((size_t)idx < (d->count+d->rrsig_count)))
|
||||
return PyInt_FromLong(d->rr_ttl[idx]);
|
||||
return Py_None;
|
||||
}
|
||||
PyObject* _get_data_rr_data(struct packed_rrset_data* d, int idx) {
|
||||
if ((d != NULL) && (idx >= 0) &&
|
||||
((size_t)idx < (d->count+d->rrsig_count)))
|
||||
return PyBytes_FromStringAndSize((char*)d->rr_data[idx],
|
||||
d->rr_len[idx]);
|
||||
return Py_None;
|
||||
}
|
||||
%}
|
||||
|
||||
%extend packed_rrset_data {
|
||||
%pythoncode %{
|
||||
def _get_data_rr_len(self): return RRSetData_RRLen(self)
|
||||
__swig_getmethods__["rr_len"] = _get_data_rr_len
|
||||
if _newclass:rr_len = _swig_property(_get_data_rr_len)
|
||||
def _get_data_rr_ttl(self): return RRSetData_RRTTL(self)
|
||||
__swig_getmethods__["rr_ttl"] =_get_data_rr_ttl
|
||||
if _newclass:rr_len = _swig_property(_get_data_rr_ttl)
|
||||
def _get_data_rr_data(self): return RRSetData_RRData(self)
|
||||
__swig_getmethods__["rr_data"] = _get_data_rr_data
|
||||
if _newclass:rr_len = _swig_property(_get_data_rr_data)
|
||||
%}
|
||||
}
|
||||
|
||||
/* ************************************************************************************ *
|
||||
Structure reply_info
|
||||
* ************************************************************************************ */
|
||||
/* Messages */
|
||||
%ignore reply_info::rrsets;
|
||||
%ignore reply_info::ref;
|
||||
|
||||
struct reply_info {
|
||||
uint16_t flags;
|
||||
uint16_t qdcount;
|
||||
uint32_t ttl;
|
||||
uint32_t prefetch_ttl;
|
||||
|
||||
uint16_t authoritative;
|
||||
enum sec_status security;
|
||||
|
||||
size_t an_numrrsets;
|
||||
size_t ns_numrrsets;
|
||||
size_t ar_numrrsets;
|
||||
size_t rrset_count; // an_numrrsets + ns_numrrsets + ar_numrrsets
|
||||
|
||||
struct ub_packed_rrset_key** rrsets;
|
||||
struct rrset_ref ref[1]; //?
|
||||
};
|
||||
|
||||
struct rrset_ref {
|
||||
struct ub_packed_rrset_key* key;
|
||||
rrset_id_t id;
|
||||
};
|
||||
|
||||
struct dns_msg {
|
||||
struct query_info qinfo;
|
||||
struct reply_info *rep;
|
||||
};
|
||||
|
||||
%pythoncode %{
|
||||
class ReplyInfo_RRSet:
|
||||
def __init__(self, obj): self.obj = obj
|
||||
def __getitem__(self, index): return _unboundmodule._rrset_rrsets_get(self.obj, index)
|
||||
def __len__(self): return obj.rrset_count
|
||||
|
||||
class ReplyInfo_Ref:
|
||||
def __init__(self, obj): self.obj = obj
|
||||
def __getitem__(self, index): return _unboundmodule._rrset_ref_get(self.obj, index)
|
||||
def __len__(self): return obj.rrset_count
|
||||
%}
|
||||
|
||||
%inline %{
|
||||
struct ub_packed_rrset_key* _rrset_rrsets_get(struct reply_info* r, int idx) {
|
||||
if ((r != NULL) && (idx >= 0) && ((size_t)idx < r->rrset_count))
|
||||
return r->rrsets[idx];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct rrset_ref* _rrset_ref_get(struct reply_info* r, int idx) {
|
||||
if ((r != NULL) && (idx >= 0) && ((size_t)idx < r->rrset_count)) {
|
||||
//printf("_rrset_ref_get: %lX key:%lX\n", r->ref + idx, r->ref[idx].key);
|
||||
return &(r->ref[idx]);
|
||||
// return &(r->ref[idx]);
|
||||
}
|
||||
//printf("_rrset_ref_get: NULL\n");
|
||||
return NULL;
|
||||
}
|
||||
%}
|
||||
|
||||
%extend reply_info {
|
||||
%pythoncode %{
|
||||
def _rrset_ref_get(self): return ReplyInfo_Ref(self)
|
||||
__swig_getmethods__["ref"] = _rrset_ref_get
|
||||
if _newclass:ref = _swig_property(_rrset_ref_get)
|
||||
|
||||
def _rrset_rrsets_get(self): return ReplyInfo_RRSet(self)
|
||||
__swig_getmethods__["rrsets"] = _rrset_rrsets_get
|
||||
if _newclass:rrsets = _swig_property(_rrset_rrsets_get)
|
||||
%}
|
||||
}
|
||||
|
||||
/* ************************************************************************************ *
|
||||
Structure mesh_state
|
||||
* ************************************************************************************ */
|
||||
struct mesh_state {
|
||||
struct mesh_reply* reply_list;
|
||||
};
|
||||
|
||||
struct mesh_reply {
|
||||
struct mesh_reply* next;
|
||||
struct comm_reply query_reply;
|
||||
};
|
||||
|
||||
struct comm_reply {
|
||||
|
||||
};
|
||||
|
||||
%inline %{
|
||||
|
||||
PyObject* _comm_reply_addr_get(struct comm_reply* reply) {
|
||||
char dest[64];
|
||||
reply_addr2str(reply, dest, 64);
|
||||
if (dest[0] == 0)
|
||||
return Py_None;
|
||||
return PyString_FromString(dest);
|
||||
}
|
||||
|
||||
PyObject* _comm_reply_family_get(struct comm_reply* reply) {
|
||||
|
||||
int af = (int)((struct sockaddr_in*) &(reply->addr))->sin_family;
|
||||
|
||||
switch(af) {
|
||||
case AF_INET: return PyString_FromString("ip4");
|
||||
case AF_INET6: return PyString_FromString("ip6");
|
||||
case AF_UNIX: return PyString_FromString("unix");
|
||||
}
|
||||
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject* _comm_reply_port_get(struct comm_reply* reply) {
|
||||
uint16_t port;
|
||||
port = ntohs(((struct sockaddr_in*)&(reply->addr))->sin_port);
|
||||
return PyInt_FromLong(port);
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
%extend comm_reply {
|
||||
%pythoncode %{
|
||||
def _addr_get(self): return _comm_reply_addr_get(self)
|
||||
__swig_getmethods__["addr"] = _addr_get
|
||||
if _newclass:addr = _swig_property(_addr_get)
|
||||
|
||||
def _port_get(self): return _comm_reply_port_get(self)
|
||||
__swig_getmethods__["port"] = _port_get
|
||||
if _newclass:port = _swig_property(_port_get)
|
||||
|
||||
def _family_get(self): return _comm_reply_family_get(self)
|
||||
__swig_getmethods__["family"] = _family_get
|
||||
if _newclass:family = _swig_property(_family_get)
|
||||
%}
|
||||
}
|
||||
/* ************************************************************************************ *
|
||||
Structure module_qstate
|
||||
* ************************************************************************************ */
|
||||
%ignore module_qstate::ext_state;
|
||||
%ignore module_qstate::minfo;
|
||||
|
||||
/* Query state */
|
||||
struct module_qstate {
|
||||
struct query_info qinfo;
|
||||
uint16_t query_flags; //See QF_BIT_xx constants
|
||||
int is_priming;
|
||||
|
||||
struct comm_reply* reply;
|
||||
struct dns_msg* return_msg;
|
||||
int return_rcode;
|
||||
struct regional* region; /* unwrapped */
|
||||
|
||||
int curmod;
|
||||
|
||||
enum module_ext_state ext_state[MAX_MODULE];
|
||||
void* minfo[MAX_MODULE];
|
||||
|
||||
struct module_env* env; /* unwrapped */
|
||||
struct mesh_state* mesh_info;
|
||||
};
|
||||
|
||||
%constant int MODULE_COUNT = MAX_MODULE;
|
||||
|
||||
%constant int QF_BIT_CD = 0x0010;
|
||||
%constant int QF_BIT_AD = 0x0020;
|
||||
%constant int QF_BIT_Z = 0x0040;
|
||||
%constant int QF_BIT_RA = 0x0080;
|
||||
%constant int QF_BIT_RD = 0x0100;
|
||||
%constant int QF_BIT_TC = 0x0200;
|
||||
%constant int QF_BIT_AA = 0x0400;
|
||||
%constant int QF_BIT_QR = 0x8000;
|
||||
|
||||
%inline %{
|
||||
enum enum_return_rcode {
|
||||
RCODE_NOERROR = 0,
|
||||
RCODE_FORMERR = 1,
|
||||
RCODE_SERVFAIL = 2,
|
||||
RCODE_NXDOMAIN = 3,
|
||||
RCODE_NOTIMPL = 4,
|
||||
RCODE_REFUSED = 5,
|
||||
RCODE_YXDOMAIN = 6,
|
||||
RCODE_YXRRSET = 7,
|
||||
RCODE_NXRRSET = 8,
|
||||
RCODE_NOTAUTH = 9,
|
||||
RCODE_NOTZONE = 10
|
||||
};
|
||||
%}
|
||||
|
||||
%pythoncode %{
|
||||
class ExtState:
|
||||
def __init__(self, obj): self.obj = obj
|
||||
def __str__(self):
|
||||
return ", ".join([_unboundmodule.strextstate(_unboundmodule._ext_state_get(self.obj,a)) for a in range(0, _unboundmodule.MODULE_COUNT)])
|
||||
def __getitem__(self, index): return _unboundmodule._ext_state_get(self.obj, index)
|
||||
def __setitem__(self, index, value): _unboundmodule._ext_state_set(self.obj, index, value)
|
||||
def __len__(self): return _unboundmodule.MODULE_COUNT
|
||||
%}
|
||||
|
||||
%inline %{
|
||||
enum module_ext_state _ext_state_get(struct module_qstate* q, int idx) {
|
||||
if ((q != NULL) && (idx >= 0) && (idx < MAX_MODULE)) {
|
||||
return q->ext_state[idx];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void _ext_state_set(struct module_qstate* q, int idx, enum module_ext_state state) {
|
||||
if ((q != NULL) && (idx >= 0) && (idx < MAX_MODULE)) {
|
||||
q->ext_state[idx] = state;
|
||||
}
|
||||
}
|
||||
%}
|
||||
|
||||
%extend module_qstate {
|
||||
%pythoncode %{
|
||||
def set_ext_state(self, id, state):
|
||||
"""Sets the ext state"""
|
||||
_unboundmodule._ext_state_set(self, id, state)
|
||||
|
||||
def __ext_state_get(self): return ExtState(self)
|
||||
__swig_getmethods__["ext_state"] = __ext_state_get
|
||||
if _newclass:ext_state = _swig_property(__ext_state_get)#, __ext_state_set)
|
||||
%}
|
||||
}
|
||||
|
||||
/* ************************************************************************************ *
|
||||
Structure config_strlist
|
||||
* ************************************************************************************ */
|
||||
struct config_strlist {
|
||||
struct config_strlist* next;
|
||||
char* str;
|
||||
};
|
||||
|
||||
/* ************************************************************************************ *
|
||||
Structure config_str2list
|
||||
* ************************************************************************************ */
|
||||
struct config_str2list {
|
||||
struct config_str2list* next;
|
||||
char* str;
|
||||
char* str2;
|
||||
};
|
||||
|
||||
/* ************************************************************************************ *
|
||||
Structure config_file
|
||||
* ************************************************************************************ */
|
||||
struct config_file {
|
||||
int verbosity;
|
||||
int stat_interval;
|
||||
int stat_cumulative;
|
||||
int stat_extended;
|
||||
int num_threads;
|
||||
int port;
|
||||
int do_ip4;
|
||||
int do_ip6;
|
||||
int do_udp;
|
||||
int do_tcp;
|
||||
int outgoing_num_ports;
|
||||
size_t outgoing_num_tcp;
|
||||
size_t incoming_num_tcp;
|
||||
int* outgoing_avail_ports;
|
||||
size_t msg_buffer_size;
|
||||
size_t msg_cache_size;
|
||||
size_t msg_cache_slabs;
|
||||
size_t num_queries_per_thread;
|
||||
size_t jostle_time;
|
||||
size_t rrset_cache_size;
|
||||
size_t rrset_cache_slabs;
|
||||
int host_ttl;
|
||||
size_t infra_cache_slabs;
|
||||
size_t infra_cache_numhosts;
|
||||
char* target_fetch_policy;
|
||||
int if_automatic;
|
||||
int num_ifs;
|
||||
char **ifs;
|
||||
int num_out_ifs;
|
||||
char **out_ifs;
|
||||
struct config_strlist* root_hints;
|
||||
struct config_stub* stubs;
|
||||
struct config_stub* forwards;
|
||||
struct config_strlist* donotqueryaddrs;
|
||||
struct config_str2list* acls;
|
||||
int donotquery_localhost;
|
||||
int harden_short_bufsize;
|
||||
int harden_large_queries;
|
||||
int harden_glue;
|
||||
int harden_dnssec_stripped;
|
||||
int harden_referral_path;
|
||||
int use_caps_bits_for_id;
|
||||
struct config_strlist* private_address;
|
||||
struct config_strlist* private_domain;
|
||||
size_t unwanted_threshold;
|
||||
char* chrootdir;
|
||||
char* username;
|
||||
char* directory;
|
||||
char* logfile;
|
||||
char* pidfile;
|
||||
int use_syslog;
|
||||
int hide_identity;
|
||||
int hide_version;
|
||||
char* identity;
|
||||
char* version;
|
||||
char* module_conf;
|
||||
struct config_strlist* trust_anchor_file_list;
|
||||
struct config_strlist* trust_anchor_list;
|
||||
struct config_strlist* trusted_keys_file_list;
|
||||
char* dlv_anchor_file;
|
||||
struct config_strlist* dlv_anchor_list;
|
||||
int max_ttl;
|
||||
int32_t val_date_override;
|
||||
int bogus_ttl;
|
||||
int val_clean_additional;
|
||||
int val_permissive_mode;
|
||||
char* val_nsec3_key_iterations;
|
||||
size_t key_cache_size;
|
||||
size_t key_cache_slabs;
|
||||
size_t neg_cache_size;
|
||||
struct config_str2list* local_zones;
|
||||
struct config_strlist* local_zones_nodefault;
|
||||
struct config_strlist* local_data;
|
||||
int remote_control_enable;
|
||||
struct config_strlist* control_ifs;
|
||||
int control_port;
|
||||
char* server_key_file;
|
||||
char* server_cert_file;
|
||||
char* control_key_file;
|
||||
char* control_cert_file;
|
||||
int do_daemonize;
|
||||
char* python_script;
|
||||
};
|
||||
|
||||
/* ************************************************************************************ *
|
||||
Enums
|
||||
* ************************************************************************************ */
|
||||
%rename ("MODULE_STATE_INITIAL") "module_state_initial";
|
||||
%rename ("MODULE_WAIT_REPLY") "module_wait_reply";
|
||||
%rename ("MODULE_WAIT_MODULE") "module_wait_module";
|
||||
%rename ("MODULE_WAIT_SUBQUERY") "module_wait_subquery";
|
||||
%rename ("MODULE_ERROR") "module_error";
|
||||
%rename ("MODULE_FINISHED") "module_finished";
|
||||
|
||||
enum module_ext_state {
|
||||
module_state_initial = 0,
|
||||
module_wait_reply,
|
||||
module_wait_module,
|
||||
module_wait_subquery,
|
||||
module_error,
|
||||
module_finished
|
||||
};
|
||||
|
||||
%rename ("MODULE_EVENT_NEW") "module_event_new";
|
||||
%rename ("MODULE_EVENT_PASS") "module_event_pass";
|
||||
%rename ("MODULE_EVENT_REPLY") "module_event_reply";
|
||||
%rename ("MODULE_EVENT_NOREPLY") "module_event_noreply";
|
||||
%rename ("MODULE_EVENT_CAPSFAIL") "module_event_capsfail";
|
||||
%rename ("MODULE_EVENT_MODDONE") "module_event_moddone";
|
||||
%rename ("MODULE_EVENT_ERROR") "module_event_error";
|
||||
|
||||
enum module_ev {
|
||||
module_event_new = 0,
|
||||
module_event_pass,
|
||||
module_event_reply,
|
||||
module_event_noreply,
|
||||
module_event_capsfail,
|
||||
module_event_moddone,
|
||||
module_event_error
|
||||
};
|
||||
|
||||
enum sec_status {
|
||||
sec_status_unchecked = 0,
|
||||
sec_status_bogus,
|
||||
sec_status_indeterminate,
|
||||
sec_status_insecure,
|
||||
sec_status_secure
|
||||
};
|
||||
|
||||
enum verbosity_value {
|
||||
NO_VERBOSE = 0,
|
||||
VERB_OPS,
|
||||
VERB_DETAIL,
|
||||
VERB_QUERY,
|
||||
VERB_ALGO
|
||||
};
|
||||
|
||||
%constant uint16_t PKT_QR = 1; /* QueRy - query flag */
|
||||
%constant uint16_t PKT_AA = 2; /* Authoritative Answer - server flag */
|
||||
%constant uint16_t PKT_TC = 4; /* TrunCated - server flag */
|
||||
%constant uint16_t PKT_RD = 8; /* Recursion Desired - query flag */
|
||||
%constant uint16_t PKT_CD = 16; /* Checking Disabled - query flag */
|
||||
%constant uint16_t PKT_RA = 32; /* Recursion Available - server flag */
|
||||
%constant uint16_t PKT_AD = 64; /* Authenticated Data - server flag */
|
||||
|
||||
%{
|
||||
int checkList(PyObject *l)
|
||||
{
|
||||
PyObject* item;
|
||||
int i;
|
||||
|
||||
if (l == Py_None)
|
||||
return 1;
|
||||
|
||||
if (PyList_Check(l))
|
||||
{
|
||||
for (i=0; i < PyList_Size(l); i++)
|
||||
{
|
||||
item = PyList_GetItem(l, i);
|
||||
if (!PyString_Check(item))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pushRRList(sldns_buffer* qb, PyObject *l, uint32_t default_ttl, int qsec,
|
||||
size_t count_offset)
|
||||
{
|
||||
PyObject* item;
|
||||
int i;
|
||||
size_t len;
|
||||
|
||||
for (i=0; i < PyList_Size(l); i++)
|
||||
{
|
||||
item = PyList_GetItem(l, i);
|
||||
|
||||
len = sldns_buffer_remaining(qb);
|
||||
if(qsec) {
|
||||
if(sldns_str2wire_rr_question_buf(PyString_AsString(item),
|
||||
sldns_buffer_current(qb), &len, NULL, NULL, 0, NULL, 0)
|
||||
!= 0)
|
||||
return 0;
|
||||
} else {
|
||||
if(sldns_str2wire_rr_buf(PyString_AsString(item),
|
||||
sldns_buffer_current(qb), &len, NULL, default_ttl,
|
||||
NULL, 0, NULL, 0) != 0)
|
||||
return 0;
|
||||
}
|
||||
sldns_buffer_skip(qb, len);
|
||||
|
||||
sldns_buffer_write_u16_at(qb, count_offset,
|
||||
sldns_buffer_read_u16_at(qb, count_offset)+1);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int set_return_msg(struct module_qstate* qstate,
|
||||
const char* rr_name, sldns_rr_type rr_type, sldns_rr_class rr_class , uint16_t flags, uint32_t default_ttl,
|
||||
PyObject* question, PyObject* answer, PyObject* authority, PyObject* additional)
|
||||
{
|
||||
sldns_buffer *qb = 0;
|
||||
int res = 1;
|
||||
size_t l;
|
||||
uint16_t PKT_QR = 1;
|
||||
uint16_t PKT_AA = 2;
|
||||
uint16_t PKT_TC = 4;
|
||||
uint16_t PKT_RD = 8;
|
||||
uint16_t PKT_CD = 16;
|
||||
uint16_t PKT_RA = 32;
|
||||
uint16_t PKT_AD = 64;
|
||||
|
||||
if ((!checkList(question)) || (!checkList(answer)) || (!checkList(authority)) || (!checkList(additional)))
|
||||
return 0;
|
||||
if ((qb = sldns_buffer_new(LDNS_RR_BUF_SIZE)) == 0) return 0;
|
||||
|
||||
/* write header */
|
||||
sldns_buffer_write_u16(qb, 0); /* ID */
|
||||
sldns_buffer_write_u16(qb, 0); /* flags */
|
||||
sldns_buffer_write_u16(qb, 1); /* qdcount */
|
||||
sldns_buffer_write_u16(qb, 0); /* ancount */
|
||||
sldns_buffer_write_u16(qb, 0); /* nscount */
|
||||
sldns_buffer_write_u16(qb, 0); /* arcount */
|
||||
if ((flags&PKT_QR)) LDNS_QR_SET(sldns_buffer_begin(qb));
|
||||
if ((flags&PKT_AA)) LDNS_AA_SET(sldns_buffer_begin(qb));
|
||||
if ((flags&PKT_TC)) LDNS_TC_SET(sldns_buffer_begin(qb));
|
||||
if ((flags&PKT_RD)) LDNS_RD_SET(sldns_buffer_begin(qb));
|
||||
if ((flags&PKT_CD)) LDNS_CD_SET(sldns_buffer_begin(qb));
|
||||
if ((flags&PKT_RA)) LDNS_RA_SET(sldns_buffer_begin(qb));
|
||||
if ((flags&PKT_AD)) LDNS_AD_SET(sldns_buffer_begin(qb));
|
||||
|
||||
/* write the query */
|
||||
l = sldns_buffer_remaining(qb);
|
||||
if(sldns_str2wire_dname_buf(rr_name, sldns_buffer_current(qb), &l) != 0) {
|
||||
sldns_buffer_free(qb);
|
||||
return 0;
|
||||
}
|
||||
sldns_buffer_skip(qb, l);
|
||||
if (rr_type == 0) { rr_type = LDNS_RR_TYPE_A; }
|
||||
if (rr_class == 0) { rr_class = LDNS_RR_CLASS_IN; }
|
||||
sldns_buffer_write_u16(qb, rr_type);
|
||||
sldns_buffer_write_u16(qb, rr_class);
|
||||
|
||||
/* write RR sections */
|
||||
if(res && !pushRRList(qb, question, default_ttl, 1, LDNS_QDCOUNT_OFF))
|
||||
res = 0;
|
||||
if(res && !pushRRList(qb, answer, default_ttl, 0, LDNS_ANCOUNT_OFF))
|
||||
res = 0;
|
||||
if(res && !pushRRList(qb, authority, default_ttl, 0, LDNS_NSCOUNT_OFF))
|
||||
res = 0;
|
||||
if(res && !pushRRList(qb, additional, default_ttl, 0, LDNS_ARCOUNT_OFF))
|
||||
res = 0;
|
||||
|
||||
if (res) res = createResponse(qstate, qb);
|
||||
|
||||
if (qb) sldns_buffer_free(qb);
|
||||
return res;
|
||||
}
|
||||
%}
|
||||
|
||||
int set_return_msg(struct module_qstate* qstate,
|
||||
const char* rr_name, int rr_type, int rr_class , uint16_t flags, uint32_t default_ttl,
|
||||
PyObject* question, PyObject* answer, PyObject* authority, PyObject* additional);
|
||||
|
||||
%pythoncode %{
|
||||
class DNSMessage:
|
||||
def __init__(self, rr_name, rr_type, rr_class = RR_CLASS_IN, query_flags = 0, default_ttl = 0):
|
||||
"""Query flags is a combination of PKT_xx contants"""
|
||||
self.rr_name = rr_name
|
||||
self.rr_type = rr_type
|
||||
self.rr_class = rr_class
|
||||
self.default_ttl = default_ttl
|
||||
self.query_flags = query_flags
|
||||
self.question = []
|
||||
self.answer = []
|
||||
self.authority = []
|
||||
self.additional = []
|
||||
|
||||
def set_return_msg(self, qstate):
|
||||
"""Returns 1 if OK"""
|
||||
status = _unboundmodule.set_return_msg(qstate, self.rr_name, self.rr_type, self.rr_class,
|
||||
self.query_flags, self.default_ttl,
|
||||
self.question, self.answer, self.authority, self.additional)
|
||||
|
||||
if (status) and (PKT_AA & self.query_flags):
|
||||
qstate.return_msg.rep.authoritative = 1
|
||||
|
||||
return status
|
||||
|
||||
%}
|
||||
/* ************************************************************************************ *
|
||||
Functions
|
||||
* ************************************************************************************ */
|
||||
|
||||
// Various debuging functions
|
||||
void verbose(enum verbosity_value level, const char* format, ...);
|
||||
void log_info(const char* format, ...);
|
||||
void log_err(const char* format, ...);
|
||||
void log_warn(const char* format, ...);
|
||||
void log_hex(const char* msg, void* data, size_t length);
|
||||
void log_dns_msg(const char* str, struct query_info* qinfo, struct reply_info* rep);
|
||||
void log_query_info(enum verbosity_value v, const char* str, struct query_info* qinf);
|
||||
void regional_log_stats(struct regional *r);
|
||||
|
||||
// Free allocated memory from marked sources returning corresponding types
|
||||
%typemap(newfree, noblock = 1) char * {
|
||||
free($1);
|
||||
}
|
||||
|
||||
// Mark as source returning newly allocated memory
|
||||
%newobject sldns_wire2str_type;
|
||||
%newobject sldns_wire2str_class;
|
||||
|
||||
// LDNS functions
|
||||
char *sldns_wire2str_type(const uint16_t atype);
|
||||
char *sldns_wire2str_class(const uint16_t aclass);
|
||||
|
||||
// Functions from pythonmod_utils
|
||||
int storeQueryInCache(struct module_qstate* qstate, struct query_info* qinfo, struct reply_info* msgrep, int is_referral);
|
||||
void invalidateQueryInCache(struct module_qstate* qstate, struct query_info* qinfo);
|
||||
|
||||
// Module conversion functions
|
||||
const char* strextstate(enum module_ext_state s);
|
||||
const char* strmodulevent(enum module_ev e);
|
||||
|
384
external/unbound/pythonmod/pythonmod.c
vendored
Normal file
384
external/unbound/pythonmod/pythonmod.c
vendored
Normal file
|
@ -0,0 +1,384 @@
|
|||
/*
|
||||
* pythonmod.c: unbound module C wrapper
|
||||
*
|
||||
* Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
|
||||
* Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz)
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the organization nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* Python module for unbound. Calls python script.
|
||||
*/
|
||||
|
||||
/* ignore the varargs unused warning from SWIGs internal vararg support */
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
|
||||
#endif
|
||||
|
||||
#include "config.h"
|
||||
#include "ldns/sbuffer.h"
|
||||
|
||||
#undef _POSIX_C_SOURCE
|
||||
#undef _XOPEN_SOURCE
|
||||
#include <Python.h>
|
||||
|
||||
#include "pythonmod/pythonmod.h"
|
||||
#include "util/module.h"
|
||||
#include "util/config_file.h"
|
||||
#include "pythonmod_utils.h"
|
||||
|
||||
#ifdef S_SPLINT_S
|
||||
typedef struct PyObject PyObject;
|
||||
typedef struct PyThreadState PyThreadState;
|
||||
typedef void* PyGILState_STATE;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Global state for the module.
|
||||
*/
|
||||
struct pythonmod_env {
|
||||
|
||||
/** Python script filename. */
|
||||
const char* fname;
|
||||
|
||||
/** Python main thread */
|
||||
PyThreadState* mainthr;
|
||||
/** Python module. */
|
||||
PyObject* module;
|
||||
|
||||
/** Module init function */
|
||||
PyObject* func_init;
|
||||
/** Module deinit function */
|
||||
PyObject* func_deinit;
|
||||
/** Module operate function */
|
||||
PyObject* func_operate;
|
||||
/** Module super_inform function */
|
||||
PyObject* func_inform;
|
||||
|
||||
/** Python dictionary. */
|
||||
PyObject* dict;
|
||||
|
||||
/** Module data. */
|
||||
PyObject* data;
|
||||
|
||||
/** Module qstate. */
|
||||
struct module_qstate* qstate;
|
||||
};
|
||||
|
||||
/**
|
||||
* Per query state for the iterator module.
|
||||
*/
|
||||
struct pythonmod_qstate {
|
||||
|
||||
/** Module per query data. */
|
||||
PyObject* data;
|
||||
};
|
||||
|
||||
/* Generated */
|
||||
#ifndef S_SPLINT_S
|
||||
#include "pythonmod/interface.h"
|
||||
#endif
|
||||
|
||||
int pythonmod_init(struct module_env* env, int id)
|
||||
{
|
||||
/* Initialize module */
|
||||
FILE* script_py = NULL;
|
||||
PyObject* py_cfg, *res;
|
||||
PyGILState_STATE gil;
|
||||
struct pythonmod_env* pe = (struct pythonmod_env*)calloc(1, sizeof(struct pythonmod_env));
|
||||
if (!pe)
|
||||
{
|
||||
log_err("pythonmod: malloc failure");
|
||||
return 0;
|
||||
}
|
||||
|
||||
env->modinfo[id] = (void*) pe;
|
||||
|
||||
/* Initialize module */
|
||||
pe->fname = env->cfg->python_script;
|
||||
if(pe->fname==NULL || pe->fname[0]==0) {
|
||||
log_err("pythonmod: no script given.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Initialize Python libraries */
|
||||
if (!Py_IsInitialized())
|
||||
{
|
||||
Py_SetProgramName("unbound");
|
||||
Py_NoSiteFlag = 1;
|
||||
Py_Initialize();
|
||||
PyEval_InitThreads();
|
||||
SWIG_init();
|
||||
pe->mainthr = PyEval_SaveThread();
|
||||
}
|
||||
|
||||
gil = PyGILState_Ensure();
|
||||
|
||||
/* Initialize Python */
|
||||
PyRun_SimpleString("import sys \n");
|
||||
PyRun_SimpleString("sys.path.append('.') \n");
|
||||
if(env->cfg->directory && env->cfg->directory[0]) {
|
||||
char wdir[1524];
|
||||
snprintf(wdir, sizeof(wdir), "sys.path.append('%s') \n",
|
||||
env->cfg->directory);
|
||||
PyRun_SimpleString(wdir);
|
||||
}
|
||||
PyRun_SimpleString("sys.path.append('"RUN_DIR"') \n");
|
||||
PyRun_SimpleString("sys.path.append('"SHARE_DIR"') \n");
|
||||
PyRun_SimpleString("import distutils.sysconfig \n");
|
||||
PyRun_SimpleString("sys.path.append(distutils.sysconfig.get_python_lib(1,0)) \n");
|
||||
if (PyRun_SimpleString("from unboundmodule import *\n") < 0)
|
||||
{
|
||||
log_err("pythonmod: cannot initialize core module: unboundmodule.py");
|
||||
PyGILState_Release(gil);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check Python file load */
|
||||
if ((script_py = fopen(pe->fname, "r")) == NULL)
|
||||
{
|
||||
log_err("pythonmod: can't open file %s for reading", pe->fname);
|
||||
PyGILState_Release(gil);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Load file */
|
||||
pe->module = PyImport_AddModule("__main__");
|
||||
pe->dict = PyModule_GetDict(pe->module);
|
||||
pe->data = Py_None;
|
||||
Py_INCREF(pe->data);
|
||||
PyModule_AddObject(pe->module, "mod_env", pe->data);
|
||||
|
||||
/* TODO: deallocation of pe->... if an error occurs */
|
||||
|
||||
if (PyRun_SimpleFile(script_py, pe->fname) < 0)
|
||||
{
|
||||
log_err("pythonmod: can't parse Python script %s", pe->fname);
|
||||
PyGILState_Release(gil);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fclose(script_py);
|
||||
|
||||
if ((pe->func_init = PyDict_GetItemString(pe->dict, "init")) == NULL)
|
||||
{
|
||||
log_err("pythonmod: function init is missing in %s", pe->fname);
|
||||
PyGILState_Release(gil);
|
||||
return 0;
|
||||
}
|
||||
if ((pe->func_deinit = PyDict_GetItemString(pe->dict, "deinit")) == NULL)
|
||||
{
|
||||
log_err("pythonmod: function deinit is missing in %s", pe->fname);
|
||||
PyGILState_Release(gil);
|
||||
return 0;
|
||||
}
|
||||
if ((pe->func_operate = PyDict_GetItemString(pe->dict, "operate")) == NULL)
|
||||
{
|
||||
log_err("pythonmod: function operate is missing in %s", pe->fname);
|
||||
PyGILState_Release(gil);
|
||||
return 0;
|
||||
}
|
||||
if ((pe->func_inform = PyDict_GetItemString(pe->dict, "inform_super")) == NULL)
|
||||
{
|
||||
log_err("pythonmod: function inform_super is missing in %s", pe->fname);
|
||||
PyGILState_Release(gil);
|
||||
return 0;
|
||||
}
|
||||
|
||||
py_cfg = SWIG_NewPointerObj((void*) env->cfg, SWIGTYPE_p_config_file, 0);
|
||||
res = PyObject_CallFunction(pe->func_init, "iO", id, py_cfg);
|
||||
if (PyErr_Occurred())
|
||||
{
|
||||
log_err("pythonmod: Exception occurred in function init");
|
||||
PyErr_Print();
|
||||
}
|
||||
|
||||
Py_XDECREF(res);
|
||||
Py_XDECREF(py_cfg);
|
||||
PyGILState_Release(gil);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void pythonmod_deinit(struct module_env* env, int id)
|
||||
{
|
||||
struct pythonmod_env* pe = env->modinfo[id];
|
||||
if(pe == NULL)
|
||||
return;
|
||||
|
||||
/* Free Python resources */
|
||||
if(pe->module != NULL)
|
||||
{
|
||||
PyObject* res;
|
||||
PyGILState_STATE gil = PyGILState_Ensure();
|
||||
|
||||
/* Deinit module */
|
||||
res = PyObject_CallFunction(pe->func_deinit, "i", id);
|
||||
if (PyErr_Occurred()) {
|
||||
log_err("pythonmod: Exception occurred in function deinit");
|
||||
PyErr_Print();
|
||||
}
|
||||
/* Free result if any */
|
||||
Py_XDECREF(res);
|
||||
/* Free shared data if any */
|
||||
Py_XDECREF(pe->data);
|
||||
PyGILState_Release(gil);
|
||||
|
||||
PyEval_RestoreThread(pe->mainthr);
|
||||
Py_Finalize();
|
||||
pe->mainthr = NULL;
|
||||
}
|
||||
pe->fname = NULL;
|
||||
free(pe);
|
||||
|
||||
/* Module is deallocated in Python */
|
||||
env->modinfo[id] = NULL;
|
||||
}
|
||||
|
||||
void pythonmod_inform_super(struct module_qstate* qstate, int id, struct module_qstate* super)
|
||||
{
|
||||
struct pythonmod_env* pe = (struct pythonmod_env*)qstate->env->modinfo[id];
|
||||
struct pythonmod_qstate* pq = (struct pythonmod_qstate*)qstate->minfo[id];
|
||||
PyObject* py_qstate, *py_sqstate, *res;
|
||||
PyGILState_STATE gil = PyGILState_Ensure();
|
||||
|
||||
log_query_info(VERB_ALGO, "pythonmod: inform_super, sub is", &qstate->qinfo);
|
||||
log_query_info(VERB_ALGO, "super is", &super->qinfo);
|
||||
|
||||
py_qstate = SWIG_NewPointerObj((void*) qstate, SWIGTYPE_p_module_qstate, 0);
|
||||
py_sqstate = SWIG_NewPointerObj((void*) super, SWIGTYPE_p_module_qstate, 0);
|
||||
|
||||
res = PyObject_CallFunction(pe->func_inform, "iOOO", id, py_qstate,
|
||||
py_sqstate, pq->data);
|
||||
|
||||
if (PyErr_Occurred())
|
||||
{
|
||||
log_err("pythonmod: Exception occurred in function inform_super");
|
||||
PyErr_Print();
|
||||
qstate->ext_state[id] = module_error;
|
||||
}
|
||||
else if ((res == NULL) || (!PyObject_IsTrue(res)))
|
||||
{
|
||||
log_err("pythonmod: python returned bad code in inform_super");
|
||||
qstate->ext_state[id] = module_error;
|
||||
}
|
||||
|
||||
Py_XDECREF(res);
|
||||
Py_XDECREF(py_sqstate);
|
||||
Py_XDECREF(py_qstate);
|
||||
|
||||
PyGILState_Release(gil);
|
||||
}
|
||||
|
||||
void pythonmod_operate(struct module_qstate* qstate, enum module_ev event,
|
||||
int id, struct outbound_entry* ATTR_UNUSED(outbound))
|
||||
{
|
||||
struct pythonmod_env* pe = (struct pythonmod_env*)qstate->env->modinfo[id];
|
||||
struct pythonmod_qstate* pq = (struct pythonmod_qstate*)qstate->minfo[id];
|
||||
PyObject* py_qstate, *res;
|
||||
PyGILState_STATE gil = PyGILState_Ensure();
|
||||
|
||||
if ( pq == NULL)
|
||||
{
|
||||
/* create qstate */
|
||||
pq = qstate->minfo[id] = malloc(sizeof(struct pythonmod_qstate));
|
||||
|
||||
/* Initialize per query data */
|
||||
pq->data = Py_None;
|
||||
Py_INCREF(pq->data);
|
||||
}
|
||||
|
||||
/* Call operate */
|
||||
py_qstate = SWIG_NewPointerObj((void*) qstate, SWIGTYPE_p_module_qstate, 0);
|
||||
res = PyObject_CallFunction(pe->func_operate, "iiOO", id, (int) event,
|
||||
py_qstate, pq->data);
|
||||
if (PyErr_Occurred())
|
||||
{
|
||||
log_err("pythonmod: Exception occurred in function operate, event: %s", strmodulevent(event));
|
||||
PyErr_Print();
|
||||
qstate->ext_state[id] = module_error;
|
||||
}
|
||||
else if ((res == NULL) || (!PyObject_IsTrue(res)))
|
||||
{
|
||||
log_err("pythonmod: python returned bad code, event: %s", strmodulevent(event));
|
||||
qstate->ext_state[id] = module_error;
|
||||
}
|
||||
Py_XDECREF(res);
|
||||
Py_XDECREF(py_qstate);
|
||||
|
||||
PyGILState_Release(gil);
|
||||
}
|
||||
|
||||
void pythonmod_clear(struct module_qstate* qstate, int id)
|
||||
{
|
||||
struct pythonmod_qstate* pq;
|
||||
if (qstate == NULL)
|
||||
return;
|
||||
|
||||
pq = (struct pythonmod_qstate*)qstate->minfo[id];
|
||||
verbose(VERB_ALGO, "pythonmod: clear, id: %d, pq:%lX", id,
|
||||
(unsigned long int)pq);
|
||||
if(pq != NULL)
|
||||
{
|
||||
PyGILState_STATE gil = PyGILState_Ensure();
|
||||
Py_DECREF(pq->data);
|
||||
PyGILState_Release(gil);
|
||||
/* Free qstate */
|
||||
free(pq);
|
||||
}
|
||||
|
||||
qstate->minfo[id] = NULL;
|
||||
}
|
||||
|
||||
size_t pythonmod_get_mem(struct module_env* env, int id)
|
||||
{
|
||||
struct pythonmod_env* pe = (struct pythonmod_env*)env->modinfo[id];
|
||||
verbose(VERB_ALGO, "pythonmod: get_mem, id: %d, pe:%lX", id,
|
||||
(unsigned long int)pe);
|
||||
if(!pe)
|
||||
return 0;
|
||||
return sizeof(*pe);
|
||||
}
|
||||
|
||||
/**
|
||||
* The module function block
|
||||
*/
|
||||
static struct module_func_block pythonmod_block = {
|
||||
"python",
|
||||
&pythonmod_init, &pythonmod_deinit, &pythonmod_operate, &pythonmod_inform_super,
|
||||
&pythonmod_clear, &pythonmod_get_mem
|
||||
};
|
||||
|
||||
struct module_func_block* pythonmod_get_funcblock(void)
|
||||
{
|
||||
return &pythonmod_block;
|
||||
}
|
68
external/unbound/pythonmod/pythonmod.h
vendored
Normal file
68
external/unbound/pythonmod/pythonmod.h
vendored
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* pythonmod.h: module header file
|
||||
*
|
||||
* Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
|
||||
* Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz)
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the organization nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* Python module for unbound. Calls python script.
|
||||
*/
|
||||
#ifndef PYTHONMOD_H
|
||||
#define PYTHONMOD_H
|
||||
#include "util/module.h"
|
||||
#include "services/outbound_list.h"
|
||||
|
||||
/**
|
||||
* Get the module function block.
|
||||
* @return: function block with function pointers to module methods.
|
||||
*/
|
||||
struct module_func_block* pythonmod_get_funcblock(void);
|
||||
|
||||
/** python module init */
|
||||
int pythonmod_init(struct module_env* env, int id);
|
||||
|
||||
/** python module deinit */
|
||||
void pythonmod_deinit(struct module_env* env, int id);
|
||||
|
||||
/** python module operate on a query */
|
||||
void pythonmod_operate(struct module_qstate* qstate, enum module_ev event, int id, struct outbound_entry* outbound);
|
||||
|
||||
/** python module */
|
||||
void pythonmod_inform_super(struct module_qstate* qstate, int id, struct module_qstate* super);
|
||||
|
||||
/** python module cleanup query state */
|
||||
void pythonmod_clear(struct module_qstate* qstate, int id);
|
||||
|
||||
/** python module alloc size routine */
|
||||
size_t pythonmod_get_mem(struct module_env* env, int id);
|
||||
#endif /* PYTHONMOD_H */
|
178
external/unbound/pythonmod/pythonmod_utils.c
vendored
Normal file
178
external/unbound/pythonmod/pythonmod_utils.c
vendored
Normal file
|
@ -0,0 +1,178 @@
|
|||
/*
|
||||
* pythonmod_utils.c: utilities used by wrapper
|
||||
*
|
||||
* Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
|
||||
* Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz)
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the organization nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* Utility functions for the python module that perform stores and loads and
|
||||
* conversions.
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "util/module.h"
|
||||
#include "util/netevent.h"
|
||||
#include "util/net_help.h"
|
||||
#include "services/cache/dns.h"
|
||||
#include "services/cache/rrset.h"
|
||||
#include "util/data/msgparse.h"
|
||||
#include "util/data/msgreply.h"
|
||||
#include "util/storage/slabhash.h"
|
||||
#include "util/regional.h"
|
||||
#include "ldns/sbuffer.h"
|
||||
|
||||
#undef _POSIX_C_SOURCE
|
||||
#undef _XOPEN_SOURCE
|
||||
#include <Python.h>
|
||||
|
||||
/* Store the reply_info and query_info pair in message cache (qstate->msg_cache) */
|
||||
int storeQueryInCache(struct module_qstate* qstate, struct query_info* qinfo, struct reply_info* msgrep, int is_referral)
|
||||
{
|
||||
if (!msgrep)
|
||||
return 0;
|
||||
|
||||
if (msgrep->authoritative) /*authoritative answer can't be stored in cache*/
|
||||
{
|
||||
PyErr_SetString(PyExc_ValueError, "Authoritative answer can't be stored");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return dns_cache_store(qstate->env, qinfo, msgrep, is_referral,
|
||||
qstate->prefetch_leeway, 0, NULL);
|
||||
}
|
||||
|
||||
/* Invalidate the message associated with query_info stored in message cache */
|
||||
void invalidateQueryInCache(struct module_qstate* qstate, struct query_info* qinfo)
|
||||
{
|
||||
hashvalue_t h;
|
||||
struct lruhash_entry* e;
|
||||
struct reply_info *r;
|
||||
size_t i, j;
|
||||
|
||||
h = query_info_hash(qinfo);
|
||||
if ((e=slabhash_lookup(qstate->env->msg_cache, h, qinfo, 0)))
|
||||
{
|
||||
r = (struct reply_info*)(e->data);
|
||||
if (r)
|
||||
{
|
||||
r->ttl = 0;
|
||||
if(rrset_array_lock(r->ref, r->rrset_count, *qstate->env->now)) {
|
||||
for(i=0; i< r->rrset_count; i++)
|
||||
{
|
||||
struct packed_rrset_data* data =
|
||||
(struct packed_rrset_data*) r->ref[i].key->entry.data;
|
||||
if(i>0 && r->ref[i].key == r->ref[i-1].key)
|
||||
continue;
|
||||
|
||||
data->ttl = r->ttl;
|
||||
for(j=0; j<data->count + data->rrsig_count; j++)
|
||||
data->rr_ttl[j] = r->ttl;
|
||||
}
|
||||
rrset_array_unlock(r->ref, r->rrset_count);
|
||||
}
|
||||
}
|
||||
lock_rw_unlock(&e->lock);
|
||||
} else {
|
||||
log_info("invalidateQueryInCache: qinfo is not in cache");
|
||||
}
|
||||
}
|
||||
|
||||
/* Create response according to the ldns packet content */
|
||||
int createResponse(struct module_qstate* qstate, sldns_buffer* pkt)
|
||||
{
|
||||
struct msg_parse* prs;
|
||||
struct edns_data edns;
|
||||
|
||||
/* parse message */
|
||||
prs = (struct msg_parse*) regional_alloc(qstate->env->scratch, sizeof(struct msg_parse));
|
||||
if (!prs) {
|
||||
log_err("storeResponse: out of memory on incoming message");
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(prs, 0, sizeof(*prs));
|
||||
memset(&edns, 0, sizeof(edns));
|
||||
|
||||
sldns_buffer_set_position(pkt, 0);
|
||||
if (parse_packet(pkt, prs, qstate->env->scratch) != LDNS_RCODE_NOERROR) {
|
||||
verbose(VERB_ALGO, "storeResponse: parse error on reply packet");
|
||||
return 0;
|
||||
}
|
||||
/* edns is not examined, but removed from message to help cache */
|
||||
if(parse_extract_edns(prs, &edns) != LDNS_RCODE_NOERROR)
|
||||
return 0;
|
||||
|
||||
/* remove CD-bit, we asked for in case we handle validation ourself */
|
||||
prs->flags &= ~BIT_CD;
|
||||
|
||||
/* allocate response dns_msg in region */
|
||||
qstate->return_msg = (struct dns_msg*)regional_alloc(qstate->region, sizeof(struct dns_msg));
|
||||
if (!qstate->return_msg)
|
||||
return 0;
|
||||
|
||||
memset(qstate->return_msg, 0, sizeof(*qstate->return_msg));
|
||||
if(!parse_create_msg(pkt, prs, NULL, &(qstate->return_msg)->qinfo, &(qstate->return_msg)->rep, qstate->region)) {
|
||||
log_err("storeResponse: malloc failure: allocating incoming dns_msg");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Make sure that the RA flag is set (since the presence of
|
||||
* this module means that recursion is available) */
|
||||
/* qstate->return_msg->rep->flags |= BIT_RA; */
|
||||
|
||||
/* Clear the AA flag */
|
||||
/* FIXME: does this action go here or in some other module? */
|
||||
/*qstate->return_msg->rep->flags &= ~BIT_AA; */
|
||||
|
||||
/* make sure QR flag is on */
|
||||
/*qstate->return_msg->rep->flags |= BIT_QR; */
|
||||
|
||||
if(verbosity >= VERB_ALGO)
|
||||
log_dns_msg("storeResponse: packet:", &qstate->return_msg->qinfo, qstate->return_msg->rep);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Convert reply->addr to string */
|
||||
void reply_addr2str(struct comm_reply* reply, char* dest, int maxlen)
|
||||
{
|
||||
int af = (int)((struct sockaddr_in*) &(reply->addr))->sin_family;
|
||||
void* sinaddr = &((struct sockaddr_in*) &(reply->addr))->sin_addr;
|
||||
|
||||
if(af == AF_INET6)
|
||||
sinaddr = &((struct sockaddr_in6*)&(reply->addr))->sin6_addr;
|
||||
dest[0] = 0;
|
||||
if (inet_ntop(af, sinaddr, dest, (socklen_t)maxlen) == 0)
|
||||
return;
|
||||
dest[maxlen-1] = 0;
|
||||
}
|
89
external/unbound/pythonmod/pythonmod_utils.h
vendored
Normal file
89
external/unbound/pythonmod/pythonmod_utils.h
vendored
Normal file
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* pythonmod_utils.h: utils header file
|
||||
*
|
||||
* Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
|
||||
* Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz)
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the organization nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* Utility functions for the python module that perform stores and loads and
|
||||
* conversions.
|
||||
*/
|
||||
#ifndef PYTHONMOD_UTILS_H
|
||||
#define PYTHONMOD_UTILS_H
|
||||
|
||||
#include "util/module.h"
|
||||
|
||||
/**
|
||||
* Store the reply_info and query_info pair in message cache (qstate->msg_cache)
|
||||
*
|
||||
* @param qstate: module environment
|
||||
* @param qinfo: query info, the query for which answer is stored.
|
||||
* @param msgrep: reply in dns_msg
|
||||
* @param is_referral: If true, then the given message to be stored is a
|
||||
* referral. The cache implementation may use this as a hint.
|
||||
* It will store only the RRsets, not the message.
|
||||
* @return 0 on alloc error (out of memory).
|
||||
*/
|
||||
int storeQueryInCache(struct module_qstate* qstate, struct query_info* qinfo, struct reply_info* msgrep, int is_referral);
|
||||
|
||||
|
||||
/**
|
||||
* Invalidate the message associated with query_info stored in message cache.
|
||||
*
|
||||
* This function invalidates the record in message cache associated with the given query only if such a record exists.
|
||||
*
|
||||
* @param qstate: module environment
|
||||
* @param qinfo: query info, the query for which answer is stored.
|
||||
*/
|
||||
void invalidateQueryInCache(struct module_qstate* qstate, struct query_info* qinfo);
|
||||
|
||||
/**
|
||||
* Create response according to the ldns packet content
|
||||
*
|
||||
* This function fills qstate.return_msg up with data of a given packet
|
||||
*
|
||||
* @param qstate: module environment
|
||||
* @param pkt: a sldns_buffer which contains sldns_packet data
|
||||
* @return 0 on failure, out of memory or parse error.
|
||||
*/
|
||||
int createResponse(struct module_qstate* qstate, sldns_buffer* pkt);
|
||||
|
||||
/**
|
||||
* Convert reply->addr to string
|
||||
* @param reply: comm reply with address in it.
|
||||
* @param dest: destination string.
|
||||
* @param maxlen: length of string buffer.
|
||||
*/
|
||||
void reply_addr2str(struct comm_reply* reply, char* dest, int maxlen);
|
||||
|
||||
#endif /* PYTHONMOD_UTILS_H */
|
18
external/unbound/pythonmod/test-calc.conf
vendored
Normal file
18
external/unbound/pythonmod/test-calc.conf
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
# Example configuration file for calc.py
|
||||
server:
|
||||
verbosity: 1
|
||||
interface: 0.0.0.0
|
||||
do-daemonize: no
|
||||
access-control: 0.0.0.0/0 allow
|
||||
chroot: ""
|
||||
username: ""
|
||||
directory: ""
|
||||
logfile: ""
|
||||
pidfile: "unbound.pid"
|
||||
module-config: "validator python iterator"
|
||||
|
||||
# Python config section
|
||||
python:
|
||||
# Script file to load
|
||||
python-script: "./examples/calc.py"
|
||||
|
18
external/unbound/pythonmod/test-dict.conf
vendored
Normal file
18
external/unbound/pythonmod/test-dict.conf
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
# Example configuration file for dict.py
|
||||
server:
|
||||
verbosity: 1
|
||||
interface: 0.0.0.0
|
||||
do-daemonize: no
|
||||
access-control: 0.0.0.0/0 allow
|
||||
chroot: ""
|
||||
username: ""
|
||||
directory: ""
|
||||
logfile: ""
|
||||
pidfile: "unbound.pid"
|
||||
module-config: "validator python iterator"
|
||||
|
||||
# Python config section
|
||||
python:
|
||||
# Script file to load
|
||||
python-script: "./examples/dict.py"
|
||||
|
17
external/unbound/pythonmod/test-log.conf
vendored
Normal file
17
external/unbound/pythonmod/test-log.conf
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
# Example configuration file for log.py
|
||||
server:
|
||||
verbosity: 1
|
||||
interface: 0.0.0.0
|
||||
do-daemonize: no
|
||||
access-control: 0.0.0.0/0 allow
|
||||
chroot: ""
|
||||
username: ""
|
||||
directory: ""
|
||||
logfile: ""
|
||||
pidfile: "unbound.pid"
|
||||
module-config: "validator python iterator"
|
||||
|
||||
# Python config section
|
||||
python:
|
||||
# Script file to load
|
||||
python-script: "./examples/log.py"
|
18
external/unbound/pythonmod/test-resgen.conf
vendored
Normal file
18
external/unbound/pythonmod/test-resgen.conf
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
# Example configuration file for resgen.py
|
||||
server:
|
||||
verbosity: 1
|
||||
interface: 0.0.0.0
|
||||
do-daemonize: no
|
||||
access-control: 0.0.0.0/0 allow
|
||||
chroot: ""
|
||||
username: ""
|
||||
directory: ""
|
||||
logfile: ""
|
||||
pidfile: "unbound.pid"
|
||||
module-config: "validator python iterator"
|
||||
|
||||
# Python config section
|
||||
python:
|
||||
# Script file to load
|
||||
python-script: "./examples/resgen.py"
|
||||
|
18
external/unbound/pythonmod/test-resip.conf
vendored
Normal file
18
external/unbound/pythonmod/test-resip.conf
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
# Example configuration file for resip.py
|
||||
server:
|
||||
verbosity: 1
|
||||
#interface: 0.0.0.0
|
||||
do-daemonize: no
|
||||
#access-control: 0.0.0.0/0 allow
|
||||
chroot: ""
|
||||
username: ""
|
||||
directory: ""
|
||||
logfile: ""
|
||||
pidfile: "unbound.pid"
|
||||
module-config: "validator python iterator"
|
||||
|
||||
# Python config section
|
||||
python:
|
||||
# Script file to load
|
||||
python-script: "./examples/resip.py"
|
||||
|
19
external/unbound/pythonmod/test-resmod.conf
vendored
Normal file
19
external/unbound/pythonmod/test-resmod.conf
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
# Example configuration file for resmod.py
|
||||
server:
|
||||
verbosity: 1
|
||||
interface: 0.0.0.0
|
||||
do-daemonize: no
|
||||
access-control: 0.0.0.0/0 allow
|
||||
chroot: ""
|
||||
username: ""
|
||||
directory: ""
|
||||
logfile: ""
|
||||
pidfile: "unbound.pid"
|
||||
#module-config: "python iterator"
|
||||
module-config: "validator python iterator"
|
||||
|
||||
# Python config section
|
||||
python:
|
||||
# Script file to load
|
||||
python-script: "./examples/resmod.py"
|
||||
|
156
external/unbound/pythonmod/ubmodule-msg.py
vendored
Normal file
156
external/unbound/pythonmod/ubmodule-msg.py
vendored
Normal file
|
@ -0,0 +1,156 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
ubmodule-msg.py: simple response packet logger
|
||||
|
||||
Authors: Zdenek Vasicek (vasicek AT fit.vutbr.cz)
|
||||
Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz)
|
||||
|
||||
Copyright (c) 2008. All rights reserved.
|
||||
|
||||
This software is open source.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
'''
|
||||
import os
|
||||
|
||||
def init(id, cfg):
|
||||
log_info("pythonmod: init called, module id is %d port: %d script: %s" % (id, cfg.port, cfg.python_script))
|
||||
return True
|
||||
|
||||
def deinit(id):
|
||||
log_info("pythonmod: deinit called, module id is %d" % id)
|
||||
return True
|
||||
|
||||
def inform_super(id, qstate, superqstate, qdata):
|
||||
return True
|
||||
|
||||
def setTTL(qstate, ttl):
|
||||
"""Sets return_msg TTL and all the RRs TTL"""
|
||||
if qstate.return_msg:
|
||||
qstate.return_msg.rep.ttl = ttl
|
||||
if (qstate.return_msg.rep):
|
||||
for i in range(0,qstate.return_msg.rep.rrset_count):
|
||||
d = qstate.return_msg.rep.rrsets[i].entry.data
|
||||
for j in range(0,d.count+d.rrsig_count):
|
||||
d.rr_ttl[j] = ttl
|
||||
|
||||
def dataHex(data, prefix=""):
|
||||
res = ""
|
||||
for i in range(0, (len(data)+15)/16):
|
||||
res += "%s0x%02X | " % (prefix, i*16)
|
||||
d = map(lambda x:ord(x), data[i*16:i*16+17])
|
||||
for ch in d:
|
||||
res += "%02X " % ch
|
||||
for i in range(0,17-len(d)):
|
||||
res += " "
|
||||
res += "| "
|
||||
for ch in d:
|
||||
if (ch < 32) or (ch > 127):
|
||||
res += ". "
|
||||
else:
|
||||
res += "%c " % ch
|
||||
res += "\n"
|
||||
return res
|
||||
|
||||
def printReturnMsg(qstate):
|
||||
print "Return MSG rep :: flags: %04X, QDcount: %d, Security:%d, TTL=%d" % (qstate.return_msg.rep.flags, qstate.return_msg.rep.qdcount,qstate.return_msg.rep.security, qstate.return_msg.rep.ttl)
|
||||
print " qinfo :: qname:",qstate.return_msg.qinfo.qname_list, qstate.return_msg.qinfo.qname_str, "type:",qstate.return_msg.qinfo.qtype_str, "class:",qstate.return_msg.qinfo.qclass_str
|
||||
if (qstate.return_msg.rep):
|
||||
print "RRSets:",qstate.return_msg.rep.rrset_count
|
||||
prevkey = None
|
||||
for i in range(0,qstate.return_msg.rep.rrset_count):
|
||||
r = qstate.return_msg.rep.rrsets[i]
|
||||
rk = r.rk
|
||||
print i,":",rk.dname_list, rk.dname_str, "flags: %04X" % rk.flags,
|
||||
print "type:",rk.type_str,"(%d)" % ntohs(rk.type), "class:",rk.rrset_class_str,"(%d)" % ntohs(rk.rrset_class)
|
||||
|
||||
d = r.entry.data
|
||||
print " RRDatas:",d.count+d.rrsig_count
|
||||
for j in range(0,d.count+d.rrsig_count):
|
||||
print " ",j,":","TTL=",d.rr_ttl[j],"RR data:"
|
||||
print dataHex(d.rr_data[j]," ")
|
||||
|
||||
|
||||
def operate(id, event, qstate, qdata):
|
||||
log_info("pythonmod: operate called, id: %d, event:%s" % (id, strmodulevent(event)))
|
||||
#print "pythonmod: per query data", qdata
|
||||
|
||||
print "Query:", ''.join(map(lambda x:chr(max(32,ord(x))),qstate.qinfo.qname)), qstate.qinfo.qname_list, qstate.qinfo.qname_str,
|
||||
print "Type:",qstate.qinfo.qtype_str,"(%d)" % qstate.qinfo.qtype,
|
||||
print "Class:",qstate.qinfo.qclass_str,"(%d)" % qstate.qinfo.qclass
|
||||
print
|
||||
|
||||
#if event == MODULE_EVENT_PASS: #pokud mame "validator python iterator"
|
||||
if (event == MODULE_EVENT_NEW) and (qstate.qinfo.qname_str.endswith(".seznam.cz.")): #pokud mame "python validator iterator"
|
||||
print qstate.qinfo.qname_str
|
||||
|
||||
qstate.ext_state[id] = MODULE_FINISHED
|
||||
|
||||
msg = DNSMessage(qstate.qinfo.qname_str, RR_TYPE_A, RR_CLASS_IN, PKT_QR | PKT_RA | PKT_AA) #, 300)
|
||||
#msg.authority.append("xxx.seznam.cz. 10 IN A 192.168.1.1")
|
||||
#msg.additional.append("yyy.seznam.cz. 10 IN A 1.1.1.2.")
|
||||
|
||||
if qstate.qinfo.qtype == RR_TYPE_A:
|
||||
msg.answer.append("%s 10 IN A 192.168.1.1" % qstate.qinfo.qname_str)
|
||||
if (qstate.qinfo.qtype == RR_TYPE_SRV) or (qstate.qinfo.qtype == RR_TYPE_ANY):
|
||||
msg.answer.append("%s 10 IN SRV 0 0 80 neinfo.example.com." % qstate.qinfo.qname_str)
|
||||
if (qstate.qinfo.qtype == RR_TYPE_TXT) or (qstate.qinfo.qtype == RR_TYPE_ANY):
|
||||
msg.answer.append("%s 10 IN TXT path=/" % qstate.qinfo.qname_str)
|
||||
|
||||
if not msg.set_return_msg(qstate):
|
||||
qstate.ext_state[id] = MODULE_ERROR
|
||||
return True
|
||||
|
||||
#qstate.return_msg.rep.security = 2 #pokud nebude nasledovat validator, je zapotrebi nastavit security, aby nebyl paket zahozen v mesh_send_reply
|
||||
printReturnMsg(qstate)
|
||||
|
||||
#Authoritative result can't be stored in cache
|
||||
#if (not storeQueryInCache(qstate, qstate.return_msg.qinfo, qstate.return_msg.rep, 0)):
|
||||
# print "Can't store in cache"
|
||||
# qstate.ext_state[id] = MODULE_ERROR
|
||||
# return False
|
||||
#print "Store OK"
|
||||
|
||||
qstate.return_rcode = RCODE_NOERROR
|
||||
return True
|
||||
|
||||
if event == MODULE_EVENT_NEW:
|
||||
qstate.ext_state[id] = MODULE_WAIT_MODULE
|
||||
return True
|
||||
|
||||
if event == MODULE_EVENT_MODDONE:
|
||||
log_info("pythonmod: previous module done")
|
||||
qstate.ext_state[id] = MODULE_FINISHED
|
||||
return True
|
||||
|
||||
if event == MODULE_EVENT_PASS:
|
||||
log_info("pythonmod: event_pass")
|
||||
qstate.ext_state[id] = MODULE_WAIT_MODULE
|
||||
return True
|
||||
|
||||
log_err("pythonmod: BAD event")
|
||||
qstate.ext_state[id] = MODULE_ERROR
|
||||
return True
|
||||
|
||||
log_info("pythonmod: script loaded.")
|
149
external/unbound/pythonmod/ubmodule-tst.py
vendored
Normal file
149
external/unbound/pythonmod/ubmodule-tst.py
vendored
Normal file
|
@ -0,0 +1,149 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
ubmodule-tst.py:
|
||||
|
||||
Authors: Zdenek Vasicek (vasicek AT fit.vutbr.cz)
|
||||
Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz)
|
||||
|
||||
Copyright (c) 2008. All rights reserved.
|
||||
|
||||
This software is open source.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
'''
|
||||
def init(id, cfg):
|
||||
log_info("pythonmod: init called, module id is %d port: %d script: %s" % (id, cfg.port, cfg.python_script))
|
||||
return True
|
||||
|
||||
def deinit(id):
|
||||
log_info("pythonmod: deinit called, module id is %d" % id)
|
||||
return True
|
||||
|
||||
def inform_super(id, qstate, superqstate, qdata):
|
||||
return True
|
||||
|
||||
def setTTL(qstate, ttl):
|
||||
"""Sets return_msg TTL and all the RRs TTL"""
|
||||
if qstate.return_msg:
|
||||
qstate.return_msg.rep.ttl = ttl
|
||||
if (qstate.return_msg.rep):
|
||||
for i in range(0,qstate.return_msg.rep.rrset_count):
|
||||
d = qstate.return_msg.rep.rrsets[i].entry.data
|
||||
for j in range(0,d.count+d.rrsig_count):
|
||||
d.rr_ttl[j] = ttl
|
||||
|
||||
def dataHex(data, prefix=""):
|
||||
res = ""
|
||||
for i in range(0, (len(data)+15)/16):
|
||||
res += "%s0x%02X | " % (prefix, i*16)
|
||||
d = map(lambda x:ord(x), data[i*16:i*16+17])
|
||||
for ch in d:
|
||||
res += "%02X " % ch
|
||||
for i in range(0,17-len(d)):
|
||||
res += " "
|
||||
res += "| "
|
||||
for ch in d:
|
||||
if (ch < 32) or (ch > 127):
|
||||
res += ". "
|
||||
else:
|
||||
res += "%c " % ch
|
||||
res += "\n"
|
||||
return res
|
||||
|
||||
def printReturnMsg(qstate):
|
||||
print "Return MSG rep :: flags: %04X, QDcount: %d, Security:%d, TTL=%d" % (qstate.return_msg.rep.flags, qstate.return_msg.rep.qdcount,qstate.return_msg.rep.security, qstate.return_msg.rep.ttl)
|
||||
print " qinfo :: qname:",qstate.return_msg.qinfo.qname_list, qstate.return_msg.qinfo.qname_str, "type:",qstate.return_msg.qinfo.qtype_str, "class:",qstate.return_msg.qinfo.qclass_str
|
||||
if (qstate.return_msg.rep):
|
||||
print "RRSets:",qstate.return_msg.rep.rrset_count
|
||||
prevkey = None
|
||||
for i in range(0,qstate.return_msg.rep.rrset_count):
|
||||
r = qstate.return_msg.rep.rrsets[i]
|
||||
rk = r.rk
|
||||
print i,":",rk.dname_list, rk.dname_str, "flags: %04X" % rk.flags,
|
||||
print "type:",rk.type_str,"(%d)" % ntohs(rk.type), "class:",rk.rrset_class_str,"(%d)" % ntohs(rk.rrset_class)
|
||||
|
||||
d = r.entry.data
|
||||
print " RRDatas:",d.count+d.rrsig_count
|
||||
for j in range(0,d.count+d.rrsig_count):
|
||||
print " ",j,":","TTL=",d.rr_ttl[j],"RR data:"
|
||||
print dataHex(d.rr_data[j]," ")
|
||||
|
||||
def operate(id, event, qstate, qdata):
|
||||
log_info("pythonmod: operate called, id: %d, event:%s" % (id, strmodulevent(event)))
|
||||
#print "pythonmod: per query data", qdata
|
||||
|
||||
print "Query:", ''.join(map(lambda x:chr(max(32,ord(x))),qstate.qinfo.qname)), qstate.qinfo.qname_list,
|
||||
print "Type:",qstate.qinfo.qtype_str,"(%d)" % qstate.qinfo.qtype,
|
||||
print "Class:",qstate.qinfo.qclass_str,"(%d)" % qstate.qinfo.qclass
|
||||
print
|
||||
|
||||
# TEST:
|
||||
# > dig @127.0.0.1 www.seznam.cz A
|
||||
# > dig @127.0.0.1 3.76.75.77.in-addr.arpa. PTR
|
||||
# prvni dva dotazy vrati TTL 100
|
||||
# > dig @127.0.0.1 www.seznam.cz A
|
||||
# > dig @127.0.0.1 3.76.75.77.in-addr.arpa. PTR
|
||||
# dalsi dva dotazy vrati TTL 10, ktere se bude s dalsimi dotazy snizovat, nez vyprsi a znovu se zaktivuje mesh
|
||||
|
||||
if qstate.return_msg:
|
||||
printReturnMsg(qstate)
|
||||
|
||||
#qdn = '.'.join(qstate.qinfo.qname_list)
|
||||
qdn = qstate.qinfo.qname_str
|
||||
|
||||
#Pokud dotaz konci na nasledujici, pozmenime TTL zpravy, ktera se posle klientovi (return_msg) i zpravy v CACHE
|
||||
if qdn.endswith(".seznam.cz.") or qdn.endswith('.in-addr.arpa.'):
|
||||
#pokud je v cache odpoved z iteratoru, pak ji zneplatnime, jinak se moduly nazavolaji do te doby, nez vyprsi TTL
|
||||
invalidateQueryInCache(qstate, qstate.return_msg.qinfo)
|
||||
|
||||
if (qstate.return_msg.rep.authoritative):
|
||||
print "X"*300
|
||||
|
||||
setTTL(qstate, 10) #do cache nastavime TTL na 10
|
||||
if not storeQueryInCache(qstate, qstate.return_msg.qinfo, qstate.return_msg.rep, 0):
|
||||
qstate.ext_state[id] = MODULE_ERROR
|
||||
return False
|
||||
|
||||
setTTL(qstate, 100) #odpoved klientovi prijde s TTL 100
|
||||
qstate.return_rcode = RCODE_NOERROR
|
||||
|
||||
if event == MODULE_EVENT_NEW:
|
||||
qstate.ext_state[id] = MODULE_WAIT_MODULE
|
||||
return True
|
||||
|
||||
if event == MODULE_EVENT_MODDONE:
|
||||
log_info("pythonmod: previous module done")
|
||||
qstate.ext_state[id] = MODULE_FINISHED
|
||||
return True
|
||||
|
||||
if event == MODULE_EVENT_PASS:
|
||||
log_info("pythonmod: event_pass")
|
||||
qstate.ext_state[id] = MODULE_WAIT_MODULE
|
||||
return True
|
||||
|
||||
log_err("pythonmod: BAD event")
|
||||
qstate.ext_state[id] = MODULE_ERROR
|
||||
return True
|
||||
|
||||
log_info("pythonmod: script loaded.")
|
Loading…
Add table
Add a link
Reference in a new issue