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