mirror of
https://github.com/monero-project/monero.git
synced 2025-05-05 14:04:59 -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
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*
|
Loading…
Add table
Add a link
Reference in a new issue