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 records. 6 7Key parts 8----------- 9 10Initialization 11~~~~~~~~~~~~~~~~~~~~~~~ 12On **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 20The suitable file can be found at http://slovnik.zcu.cz 21 22DNS query and word lookup 23~~~~~~~~~~~~~~~~~~~~~~~~~~~ 24 25Let's define the following format od DNS queries: ``word1[.]word2[.] ... wordN[.]{en,cs}[._dict_.cz.]``. 26Word lookup is done by simple ``dict`` lookup from broken DNS request. 27Query 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 40In the first step, we get a string in the form: ``word1[space]word2[space]...word[space]``. 41In the second assignment, fourth label from the end is obtained. This label should contains *"cs"* or *"en"*. 42This label determines the direction of translation. 43 44 45Forming of a DNS reply 46~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 47 48DNS 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 64In the first step, a :class:`DNSMessage` instance is created for a given query *(type TXT)*. 65The fourth argument specifies the flags *(authoritative answer)*. 66In the second step, we append TXT records containing the translation *(on the right side of RR)*. 67Then, the response is finished and ``qstate.return_msg`` contains new response. 68If no error, the module sets :attr:`module_qstate.return_rcode` and :attr:`module_qstate.ext_state`. 69 70**Steps:** 71 721. create :class:`DNSMessage` instance 732. append TXT records containing the translation 743. set response to ``qstate.return_msg`` 75 76Testing 77------- 78 79Run the Unbound server: 80 81``root@localhost>unbound -dv -c ./test-dict.conf`` 82 83In case you use own configuration file, don't forget to enable Python module:: 84 85 module-config: "validator python iterator" 86 87and use valid script path:: 88 89 python-script: "./examples/dict.py" 90 91The 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 140Proof 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 160Complete source code 161-------------------- 162 163.. literalinclude:: ../../examples/dict.py 164 :language: python 165