]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - pythonmod/doc/examples/example4.rst
import unbound 1.5.7
[FreeBSD/FreeBSD.git] / pythonmod / doc / examples / example4.rst
1 DNS-based language dictionary
2 ===============================
3
4 This example shows how to create a simple language dictionary based on **DNS**
5 service within 15 minutes. The translation will be performed using TXT resource records.
6
7 Key parts
8 -----------
9
10 Initialization
11 ~~~~~~~~~~~~~~~~~~~~~~~
12 On **init()** module loads dictionary from a text file containing records in ``word [tab] translation`` format.
13 ::
14
15    def init(id, cfg):
16       log_info("pythonmod: dict init")
17       f = open("examples/dict_data.txt", "r")
18       ...
19
20 The suitable file can be found at http://slovnik.zcu.cz
21
22 DNS query and word lookup
23 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
24
25 Let's define the following format od DNS queries: ``word1[.]word2[.] ... wordN[.]{en,cs}[._dict_.cz.]``.
26 Word lookup is done by simple ``dict`` lookup from broken DNS request.
27 Query name is divided into a list of labels. This list is accessible as qname_list attribute.
28 ::
29
30    aword = ' '.join(qstate.qinfo.qname_list[0:-4]) #skip last four labels
31    adict = qstate.qinfo.qname_list[-4] #get 4th label from the end
32
33    words = [] #list of words
34    if (adict == "en") and (aword in en_dict):
35       words = en_dict[aword] 
36
37    if (adict == "cs") and (aword in cz_dict):
38       words = cz_dict[aword] # CS -> EN
39
40 In the first step, we get a string in the form: ``word1[space]word2[space]...word[space]``.
41 In the second assignment, fourth label from the end is obtained. This label should contains *"cs"* or *"en"*.
42 This label determines the direction of translation.
43
44
45 Forming of a DNS reply
46 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
47
48 DNS reply is formed only on valid match and added as TXT answer.
49 ::
50
51         msg = DNSMessage(qstate.qinfo.qname_str, RR_TYPE_TXT, RR_CLASS_IN, PKT_AA)
52
53         for w in words:
54                 msg.answer.append("%s 300 IN TXT \"%s\"" % (qstate.qinfo.qname_str, w.replace("\"", "\\\"")))
55
56         if not msg.set_return_msg(qstate):
57                 qstate.ext_state[id] = MODULE_ERROR 
58                 return True
59
60         qstate.return_rcode = RCODE_NOERROR
61         qstate.ext_state[id] = MODULE_FINISHED 
62         return True
63
64 In the first step, a :class:`DNSMessage` instance is created for a given query *(type TXT)*.
65 The fourth argument specifies the flags *(authoritative answer)*.
66 In the second step, we append TXT records containing the translation *(on the right side of RR)*.
67 Then, the response is finished and ``qstate.return_msg`` contains new response.
68 If no error, the module sets :attr:`module_qstate.return_rcode` and :attr:`module_qstate.ext_state`.
69
70 **Steps:**
71
72 1. create :class:`DNSMessage` instance
73 2. append TXT records containing the translation
74 3. set response to ``qstate.return_msg``
75
76 Testing
77 -------
78
79 Run the Unbound server:
80
81 ``root@localhost>unbound -dv -c ./test-dict.conf``
82
83 In case you use own configuration file, don't forget to enable Python module::
84
85         module-config: "validator python iterator"
86
87 and use valid script path::
88
89         python-script: "./examples/dict.py"
90
91 The translation from english word *"a bar fly"* to Czech can be done by doing:
92
93 ``>>>dig TXT @127.0.0.1 a.bar.fly.en._dict_.cz``
94
95 ::      
96
97         ; (1 server found)
98         ;; global options:  printcmd
99         ;; Got answer:
100         ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48691
101         ;; flags: aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
102         
103         ;; QUESTION SECTION:
104         ;a.bar.fly.en._dict_.cz.                IN      TXT
105         
106         ;; ANSWER SECTION:
107         a.bar.fly.en._dict_.cz. 300     IN      TXT     "barov\253 povale\232"
108         
109         ;; Query time: 5 msec
110         ;; SERVER: 127.0.0.1#53(127.0.0.1)
111         ;; WHEN: Mon Jan 01 17:44:18 2009
112         ;; MSG SIZE  rcvd: 67
113         
114 ``>>>dig TXT @127.0.0.1 nic.cs._dict_.cz``
115 ::
116         
117         ; <<>> DiG 9.5.0-P2 <<>> TXT @127.0.0.1 nic.cs._dict_.cz
118         ; (1 server found)
119         ;; global options:  printcmd
120         ;; Got answer:
121         ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 58710
122         ;; flags: aa rd ra; QUERY: 1, ANSWER: 6, AUTHORITY: 0, ADDITIONAL: 0
123         
124         ;; QUESTION SECTION:
125         ;nic.cs._dict_.cz.              IN      TXT
126         
127         ;; ANSWER SECTION:
128         nic.cs._dict_.cz.       300     IN      TXT     "aught"
129         nic.cs._dict_.cz.       300     IN      TXT     "naught"
130         nic.cs._dict_.cz.       300     IN      TXT     "nihil"
131         nic.cs._dict_.cz.       300     IN      TXT     "nix"
132         nic.cs._dict_.cz.       300     IN      TXT     "nothing"
133         nic.cs._dict_.cz.       300     IN      TXT     "zilch"
134         
135         ;; Query time: 0 msec
136         ;; SERVER: 127.0.0.1#53(127.0.0.1)
137         ;; WHEN: Mon Jan 01 17:45:39 2009
138         ;; MSG SIZE  rcvd: 143
139
140 Proof that the unbound still works as resolver.
141
142 ``>>>dig A @127.0.0.1 www.nic.cz``
143 ::
144
145         ; (1 server found)
146         ;; global options:  printcmd
147         ;; Got answer:
148         ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 19996
149         ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 3, ADDITIONAL: 5
150         
151         ;; QUESTION SECTION:
152         ;www.nic.cz.                    IN      A
153         
154         ;; ANSWER SECTION:
155         www.nic.cz.             1662    IN      A       217.31.205.50
156         
157         ;; AUTHORITY SECTION:
158         ...
159
160 Complete source code
161 --------------------
162
163 .. literalinclude:: ../../examples/dict.py
164    :language: python