xref: /netbsd-src/external/bsd/unbound/dist/pythonmod/doc/examples/example5.rst (revision 7a540f2bd4f5b968566c2607d6462c7f2fb452cf)
10cd9f4ecSchristosEDNS options
20cd9f4ecSchristos============
30cd9f4ecSchristos
40cd9f4ecSchristosThis example shows how to interact with EDNS options.
50cd9f4ecSchristos
60cd9f4ecSchristosWhen querying unbound with the EDNS option ``65001`` and data ``0xc001`` we
70cd9f4ecSchristosexpect an answer with the same EDNS option code and data ``0xdeadbeef``.
80cd9f4ecSchristos
90cd9f4ecSchristos
100cd9f4ecSchristosKey parts
110cd9f4ecSchristos~~~~~~~~~
120cd9f4ecSchristos
130cd9f4ecSchristosThis example relies on the following functionalities:
140cd9f4ecSchristos
150cd9f4ecSchristos
160cd9f4ecSchristosRegistering EDNS options
170cd9f4ecSchristos------------------------
180cd9f4ecSchristos
190cd9f4ecSchristosBy registering EDNS options we can tune unbound's behavior when encountering a
200cd9f4ecSchristosquery with a known EDNS option. The two available options are:
210cd9f4ecSchristos
220cd9f4ecSchristos- ``bypass_cache_stage``: If set to ``True`` unbound will not try to answer
230cd9f4ecSchristos  from cache. Instead execution is passed to the modules
240cd9f4ecSchristos- ``no_aggregation``: If set to ``True`` unbound will consider this query
250cd9f4ecSchristos  unique and will not aggregate it with similar queries
260cd9f4ecSchristos
270cd9f4ecSchristosBoth values default to ``False``.
280cd9f4ecSchristos
290cd9f4ecSchristos.. code-block:: python
300cd9f4ecSchristos
310cd9f4ecSchristos    if not register_edns_option(env, 65001, bypass_cache_stage=True,
320cd9f4ecSchristos                                no_aggregation=True):
330cd9f4ecSchristos        log_info("python: Could not register EDNS option {}".format(65001))
340cd9f4ecSchristos
350cd9f4ecSchristos
360cd9f4ecSchristosEDNS option lists
370cd9f4ecSchristos-----------------
380cd9f4ecSchristos
390cd9f4ecSchristosEDNS option lists can be found in the :class:`module_qstate` class. There are
400cd9f4ecSchristosfour available lists in total:
410cd9f4ecSchristos
420cd9f4ecSchristos- :class:`module_qstate.edns_opts_front_in`: options that came from the client
430cd9f4ecSchristos  side. **Should not** be changed
440cd9f4ecSchristos- :class:`module_qstate.edns_opts_back_out`: options that will be sent to the
450cd9f4ecSchristos  server side. Can be populated by edns literate modules
460cd9f4ecSchristos- :class:`module_qstate.edns_opts_back_in`: options that came from the server
470cd9f4ecSchristos  side. **Should not** be changed
480cd9f4ecSchristos- :class:`module_qstate.edns_opts_front_out`: options that will be sent to the
490cd9f4ecSchristos  client side. Can be populated by edns literate modules
500cd9f4ecSchristos
510cd9f4ecSchristosEach list element has the following members:
520cd9f4ecSchristos
530cd9f4ecSchristos- ``code``: the EDNS option code;
540cd9f4ecSchristos- ``data``: the EDNS option data.
550cd9f4ecSchristos
560cd9f4ecSchristos
570cd9f4ecSchristosReading an EDNS option list
580cd9f4ecSchristos...........................
590cd9f4ecSchristos
600cd9f4ecSchristosThe lists' contents can be accessed in python by their ``_iter`` counterpart as
610cd9f4ecSchristosan iterator:
620cd9f4ecSchristos
630cd9f4ecSchristos.. code-block:: python
640cd9f4ecSchristos
650cd9f4ecSchristos    if not edns_opt_list_is_empty(qstate.edns_opts_front_in):
660cd9f4ecSchristos        for o in qstate.edns_opts_front_in_iter:
670cd9f4ecSchristos            log_info("python:    Code: {}, Data: '{}'".format(o.code,
680cd9f4ecSchristos                            "".join('{:02x}'.format(x) for x in o.data)))
690cd9f4ecSchristos
700cd9f4ecSchristos
710cd9f4ecSchristosWriting to an EDNS option list
720cd9f4ecSchristos..............................
730cd9f4ecSchristos
740cd9f4ecSchristosBy appending to an EDNS option list we can add new EDNS options. The new
750cd9f4ecSchristoselement is going to be allocated in :class:`module_qstate.region`. The data
760cd9f4ecSchristos**must** be represented with a python ``bytearray``:
770cd9f4ecSchristos
780cd9f4ecSchristos.. code-block:: python
790cd9f4ecSchristos
800cd9f4ecSchristos    b = bytearray.fromhex("deadbeef")
810cd9f4ecSchristos    if not edns_opt_list_append(qstate.edns_opts_front_out,
820cd9f4ecSchristos                           o.code, b, qstate.region):
830cd9f4ecSchristos        log_info("python: Could not append EDNS option {}".format(o.code))
840cd9f4ecSchristos
850cd9f4ecSchristosWe can also remove an EDNS option code from an EDNS option list.
860cd9f4ecSchristos
870cd9f4ecSchristos.. code-block:: python
880cd9f4ecSchristos
890cd9f4ecSchristos    if not edns_opt_list_remove(edns_opt_list, code):
900cd9f4ecSchristos        log_info("python: Option code {} was not found in the "
910cd9f4ecSchristos                 "list.".format(code))
920cd9f4ecSchristos
93*7a540f2bSchristos.. note:: All occurrences of the EDNS option code will be removed from the list:
940cd9f4ecSchristos
950cd9f4ecSchristos
960cd9f4ecSchristosControlling other modules' cache behavior
970cd9f4ecSchristos-----------------------------------------
980cd9f4ecSchristos
990cd9f4ecSchristosDuring the modules' operation, some modules may interact with the cache
1000cd9f4ecSchristos(e.g., iterator). This behavior can be controlled by using the following
1010cd9f4ecSchristos:class:`module_qstate` flags:
1020cd9f4ecSchristos
1030cd9f4ecSchristos- :class:`module_qstate.no_cache_lookup`: Modules *operating after* this module
1040cd9f4ecSchristos  will not lookup the cache for an answer
1050cd9f4ecSchristos- :class:`module_qstate.no_cache_store`: Modules *operating after* this module
1060cd9f4ecSchristos  will not store the response in the cache
1070cd9f4ecSchristos
1080cd9f4ecSchristosBoth values default to ``0``.
1090cd9f4ecSchristos
1100cd9f4ecSchristos.. code-block:: python
1110cd9f4ecSchristos
1120cd9f4ecSchristos    def operate(id, event, qstate, qdata):
1130cd9f4ecSchristos        if (event == MODULE_EVENT_NEW) or (event == MODULE_EVENT_PASS):
1140cd9f4ecSchristos            # Detect if edns option code 56001 is present from the client side. If
1150cd9f4ecSchristos            # so turn on the flags for cache management.
1160cd9f4ecSchristos            if not edns_opt_list_is_empty(qstate.edns_opts_front_in):
1170cd9f4ecSchristos                log_info("python: searching for edns option code 65001 during NEW "
1180cd9f4ecSchristos                        "or PASS event ")
1190cd9f4ecSchristos                for o in qstate.edns_opts_front_in_iter:
1200cd9f4ecSchristos                    if o.code == 65001:
1210cd9f4ecSchristos                        log_info("python: found edns option code 65001")
1220cd9f4ecSchristos                        # Instruct other modules to not lookup for an
1230cd9f4ecSchristos                        # answer in the cache.
1240cd9f4ecSchristos                        qstate.no_cache_lookup = 1
1250cd9f4ecSchristos                        log_info("python: enabled no_cache_lookup")
1260cd9f4ecSchristos
1270cd9f4ecSchristos                        # Instruct other modules to not store the answer in
1280cd9f4ecSchristos                        # the cache.
1290cd9f4ecSchristos                        qstate.no_cache_store = 1
1300cd9f4ecSchristos                        log_info("python: enabled no_cache_store")
1310cd9f4ecSchristos
1320cd9f4ecSchristos
1330cd9f4ecSchristosTesting
1340cd9f4ecSchristos~~~~~~~
1350cd9f4ecSchristos
1360cd9f4ecSchristosRun the Unbound server: ::
1370cd9f4ecSchristos
1380cd9f4ecSchristos    root@localhost$ unbound -dv -c ./test-edns.conf
1390cd9f4ecSchristos
1400cd9f4ecSchristosIn case you use your own configuration file, don't forget to enable the Python
1410cd9f4ecSchristosmodule::
1420cd9f4ecSchristos
1430cd9f4ecSchristos    module-config: "validator python iterator"
1440cd9f4ecSchristos
1450cd9f4ecSchristosand use a valid script path::
1460cd9f4ecSchristos
1470cd9f4ecSchristos    python-script: "./examples/edns.py"
1480cd9f4ecSchristos
1490cd9f4ecSchristosQuerying with EDNS option ``65001:0xc001``:
1500cd9f4ecSchristos
1510cd9f4ecSchristos::
1520cd9f4ecSchristos
1530cd9f4ecSchristos    root@localhost$ dig @localhost nlnetlabs.nl +ednsopt=65001:c001
1540cd9f4ecSchristos
1550cd9f4ecSchristos    ; <<>> DiG 9.10.3-P4-Ubuntu <<>> @localhost nlnetlabs.nl +ednsopt=65001:c001
1560cd9f4ecSchristos    ; (1 server found)
1570cd9f4ecSchristos    ;; global options: +cmd
1580cd9f4ecSchristos    ;; Got answer:
1590cd9f4ecSchristos    ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 33450
1600cd9f4ecSchristos    ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 4, ADDITIONAL: 3
1610cd9f4ecSchristos
1620cd9f4ecSchristos    ;; OPT PSEUDOSECTION:
1630cd9f4ecSchristos    ; EDNS: version: 0, flags:; udp: 4096
1640cd9f4ecSchristos    ; OPT=65001: de ad be ef ("....")
1650cd9f4ecSchristos    ;; QUESTION SECTION:
1660cd9f4ecSchristos    ;nlnetlabs.nl.                  IN      A
1670cd9f4ecSchristos
1680cd9f4ecSchristos    ;; ANSWER SECTION:
1690cd9f4ecSchristos    nlnetlabs.nl.           10200   IN      A       185.49.140.10
1700cd9f4ecSchristos
1710cd9f4ecSchristos    ;; AUTHORITY SECTION:
1720cd9f4ecSchristos    nlnetlabs.nl.           10200   IN      NS      anyns.pch.net.
1730cd9f4ecSchristos    nlnetlabs.nl.           10200   IN      NS      ns.nlnetlabs.nl.
1740cd9f4ecSchristos    nlnetlabs.nl.           10200   IN      NS      ns-ext1.sidn.nl.
1750cd9f4ecSchristos    nlnetlabs.nl.           10200   IN      NS      sec2.authdns.ripe.net.
1760cd9f4ecSchristos
1770cd9f4ecSchristos    ;; ADDITIONAL SECTION:
1780cd9f4ecSchristos    ns.nlnetlabs.nl.        10200   IN      AAAA    2a04:b900::8:0:0:60
1790cd9f4ecSchristos    ns.nlnetlabs.nl.        10200   IN      A       185.49.140.60
1800cd9f4ecSchristos
1810cd9f4ecSchristos    ;; Query time: 10 msec
1820cd9f4ecSchristos    ;; SERVER: 127.0.0.1#53(127.0.0.1)
1830cd9f4ecSchristos    ;; WHEN: Mon Dec 05 14:50:56 CET 2016
1840cd9f4ecSchristos    ;; MSG SIZE  rcvd: 212
1850cd9f4ecSchristos
1860cd9f4ecSchristos
1870cd9f4ecSchristosComplete source code
1880cd9f4ecSchristos~~~~~~~~~~~~~~~~~~~~
1890cd9f4ecSchristos
1900cd9f4ecSchristos.. literalinclude:: ../../examples/edns.py
1910cd9f4ecSchristos    :language: python
192