danicoin/external/unbound/pythonmod/doc/examples/example4.rst
Erik de Castro Lopo a85b5759f3 Upgrade unbound library
These files were pulled from the 1.6.3 release tarball.

This new version builds against OpenSSL version 1.1 which will be
the default in the new Debian Stable which is due to be released
RealSoonNow (tm).
2017-06-17 23:04:00 +10:00

179 lines
4.8 KiB
ReStructuredText

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 accessible 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