1 DNS-based language dictionary
 
   2 ===============================
 
   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.
 
  11 ~~~~~~~~~~~~~~~~~~~~~~~
 
  12 On **init()** module loads dictionary from a text file containing records in ``word [tab] translation`` format.
 
  16       log_info("pythonmod: dict init")
 
  17       f = open("examples/dict_data.txt", "r")
 
  20 The suitable file can be found at http://slovnik.zcu.cz
 
  22 DNS query and word lookup
 
  23 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
  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 accesible as qname_list attribute.
 
  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
 
  33    words = [] #list of words
 
  34    if (adict == "en") and (aword in en_dict):
 
  35       words = en_dict[aword] 
 
  37    if (adict == "cs") and (aword in cz_dict):
 
  38       words = cz_dict[aword] # CS -> EN
 
  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.
 
  45 Forming of a DNS reply
 
  46 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
  48 DNS reply is formed only on valid match and added as TXT answer.
 
  51         msg = DNSMessage(qstate.qinfo.qname_str, RR_TYPE_TXT, RR_CLASS_IN, PKT_AA)
 
  54                 msg.answer.append("%s 300 IN TXT \"%s\"" % (qstate.qinfo.qname_str, w.replace("\"", "\\\"")))
 
  56         if not msg.set_return_msg(qstate):
 
  57                 qstate.ext_state[id] = MODULE_ERROR 
 
  60         qstate.return_rcode = RCODE_NOERROR
 
  61         qstate.ext_state[id] = MODULE_FINISHED 
 
  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`.
 
  72 1. create :class:`DNSMessage` instance
 
  73 2. append TXT records containing the translation
 
  74 3. set response to ``qstate.return_msg``
 
  79 Run the Unbound server:
 
  81 ``root@localhost>unbound -dv -c ./test-dict.conf``
 
  83 In case you use own configuration file, don't forget to enable Python module::
 
  85         module-config: "validator python iterator"
 
  87 and use valid script path::
 
  89         python-script: "./examples/dict.py"
 
  91 The translation from english word *"a bar fly"* to Czech can be done by doing:
 
  93 ``>>>dig TXT @127.0.0.1 a.bar.fly.en._dict_.cz``
 
  98         ;; global options:  printcmd
 
 100         ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48691
 
 101         ;; flags: aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
 
 104         ;a.bar.fly.en._dict_.cz.                IN      TXT
 
 107         a.bar.fly.en._dict_.cz. 300     IN      TXT     "barov\253 povale\232"
 
 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
 
 114 ``>>>dig TXT @127.0.0.1 nic.cs._dict_.cz``
 
 117         ; <<>> DiG 9.5.0-P2 <<>> TXT @127.0.0.1 nic.cs._dict_.cz
 
 119         ;; global options:  printcmd
 
 121         ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 58710
 
 122         ;; flags: aa rd ra; QUERY: 1, ANSWER: 6, AUTHORITY: 0, ADDITIONAL: 0
 
 125         ;nic.cs._dict_.cz.              IN      TXT
 
 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"
 
 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
 
 140 Proof that the unbound still works as resolver.
 
 142 ``>>>dig A @127.0.0.1 www.nic.cz``
 
 146         ;; global options:  printcmd
 
 148         ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 19996
 
 149         ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 3, ADDITIONAL: 5
 
 155         www.nic.cz.             1662    IN      A       217.31.205.50
 
 157         ;; AUTHORITY SECTION:
 
 163 .. literalinclude:: ../../examples/dict.py