1EDNS options 2============ 3 4This example shows how to interact with EDNS options. 5 6When querying unbound with the EDNS option ``65001`` and data ``0xc001`` we 7expect an answer with the same EDNS option code and data ``0xdeadbeef``. 8 9 10Key parts 11~~~~~~~~~ 12 13This example relies on the following functionalities: 14 15 16Registering EDNS options 17------------------------ 18 19By registering EDNS options we can tune unbound's behavior when encountering a 20query with a known EDNS option. The two available options are: 21 22- ``bypass_cache_stage``: If set to ``True`` unbound will not try to answer 23 from cache. Instead execution is passed to the modules 24- ``no_aggregation``: If set to ``True`` unbound will consider this query 25 unique and will not aggregate it with similar queries 26 27Both values default to ``False``. 28 29.. code-block:: python 30 31 if not register_edns_option(env, 65001, bypass_cache_stage=True, 32 no_aggregation=True): 33 log_info("python: Could not register EDNS option {}".format(65001)) 34 35 36EDNS option lists 37----------------- 38 39EDNS option lists can be found in the :class:`module_qstate` class. There are 40four available lists in total: 41 42- :class:`module_qstate.edns_opts_front_in`: options that came from the client 43 side. **Should not** be changed 44- :class:`module_qstate.edns_opts_back_out`: options that will be sent to the 45 server side. Can be populated by edns literate modules 46- :class:`module_qstate.edns_opts_back_in`: options that came from the server 47 side. **Should not** be changed 48- :class:`module_qstate.edns_opts_front_out`: options that will be sent to the 49 client side. Can be populated by edns literate modules 50 51Each list element has the following members: 52 53- ``code``: the EDNS option code; 54- ``data``: the EDNS option data. 55 56 57Reading an EDNS option list 58........................... 59 60The lists' contents can be accessed in python by their ``_iter`` counterpart as 61an iterator: 62 63.. code-block:: python 64 65 if not edns_opt_list_is_empty(qstate.edns_opts_front_in): 66 for o in qstate.edns_opts_front_in_iter: 67 log_info("python: Code: {}, Data: '{}'".format(o.code, 68 "".join('{:02x}'.format(x) for x in o.data))) 69 70 71Writing to an EDNS option list 72.............................. 73 74By appending to an EDNS option list we can add new EDNS options. The new 75element is going to be allocated in :class:`module_qstate.region`. The data 76**must** be represented with a python ``bytearray``: 77 78.. code-block:: python 79 80 b = bytearray.fromhex("deadbeef") 81 if not edns_opt_list_append(qstate.edns_opts_front_out, 82 o.code, b, qstate.region): 83 log_info("python: Could not append EDNS option {}".format(o.code)) 84 85We can also remove an EDNS option code from an EDNS option list. 86 87.. code-block:: python 88 89 if not edns_opt_list_remove(edns_opt_list, code): 90 log_info("python: Option code {} was not found in the " 91 "list.".format(code)) 92 93.. note:: All occurrences of the EDNS option code will be removed from the list: 94 95 96Controlling other modules' cache behavior 97----------------------------------------- 98 99During the modules' operation, some modules may interact with the cache 100(e.g., iterator). This behavior can be controlled by using the following 101:class:`module_qstate` flags: 102 103- :class:`module_qstate.no_cache_lookup`: Modules *operating after* this module 104 will not lookup the cache for an answer 105- :class:`module_qstate.no_cache_store`: Modules *operating after* this module 106 will not store the response in the cache 107 108Both values default to ``0``. 109 110.. code-block:: python 111 112 def operate(id, event, qstate, qdata): 113 if (event == MODULE_EVENT_NEW) or (event == MODULE_EVENT_PASS): 114 # Detect if edns option code 56001 is present from the client side. If 115 # so turn on the flags for cache management. 116 if not edns_opt_list_is_empty(qstate.edns_opts_front_in): 117 log_info("python: searching for edns option code 65001 during NEW " 118 "or PASS event ") 119 for o in qstate.edns_opts_front_in_iter: 120 if o.code == 65001: 121 log_info("python: found edns option code 65001") 122 # Instruct other modules to not lookup for an 123 # answer in the cache. 124 qstate.no_cache_lookup = 1 125 log_info("python: enabled no_cache_lookup") 126 127 # Instruct other modules to not store the answer in 128 # the cache. 129 qstate.no_cache_store = 1 130 log_info("python: enabled no_cache_store") 131 132 133Testing 134~~~~~~~ 135 136Run the Unbound server: :: 137 138 root@localhost$ unbound -dv -c ./test-edns.conf 139 140In case you use your own configuration file, don't forget to enable the Python 141module:: 142 143 module-config: "validator python iterator" 144 145and use a valid script path:: 146 147 python-script: "./examples/edns.py" 148 149Querying with EDNS option ``65001:0xc001``: 150 151:: 152 153 root@localhost$ dig @localhost nlnetlabs.nl +ednsopt=65001:c001 154 155 ; <<>> DiG 9.10.3-P4-Ubuntu <<>> @localhost nlnetlabs.nl +ednsopt=65001:c001 156 ; (1 server found) 157 ;; global options: +cmd 158 ;; Got answer: 159 ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 33450 160 ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 4, ADDITIONAL: 3 161 162 ;; OPT PSEUDOSECTION: 163 ; EDNS: version: 0, flags:; udp: 4096 164 ; OPT=65001: de ad be ef ("....") 165 ;; QUESTION SECTION: 166 ;nlnetlabs.nl. IN A 167 168 ;; ANSWER SECTION: 169 nlnetlabs.nl. 10200 IN A 185.49.140.10 170 171 ;; AUTHORITY SECTION: 172 nlnetlabs.nl. 10200 IN NS anyns.pch.net. 173 nlnetlabs.nl. 10200 IN NS ns.nlnetlabs.nl. 174 nlnetlabs.nl. 10200 IN NS ns-ext1.sidn.nl. 175 nlnetlabs.nl. 10200 IN NS sec2.authdns.ripe.net. 176 177 ;; ADDITIONAL SECTION: 178 ns.nlnetlabs.nl. 10200 IN AAAA 2a04:b900::8:0:0:60 179 ns.nlnetlabs.nl. 10200 IN A 185.49.140.60 180 181 ;; Query time: 10 msec 182 ;; SERVER: 127.0.0.1#53(127.0.0.1) 183 ;; WHEN: Mon Dec 05 14:50:56 CET 2016 184 ;; MSG SIZE rcvd: 212 185 186 187Complete source code 188~~~~~~~~~~~~~~~~~~~~ 189 190.. literalinclude:: ../../examples/edns.py 191 :language: python 192