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