]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
Start of EDNS client tags implementation.
authorRalph Dolmans <ralph@nlnetlabs.nl>
Thu, 23 Jul 2020 15:17:44 +0000 (17:17 +0200)
committerRalph Dolmans <ralph@nlnetlabs.nl>
Thu, 23 Jul 2020 15:17:44 +0000 (17:17 +0200)
daemon/daemon.c
services/outside_network.c
sldns/rrdef.h
util/edns.c
util/edns.h
util/module.h

index 5d4279259ed6b926fdbff459fea746899dd1e22a..34f7bfda1a5fe1ede913255b04d7890f14c12846 100644 (file)
@@ -77,6 +77,7 @@
 #include "util/storage/lookup3.h"
 #include "util/storage/slabhash.h"
 #include "util/tcp_conn_limit.h"
+#include "util/edns.h"
 #include "services/listen_dnsport.h"
 #include "services/cache/rrset.h"
 #include "services/cache/infra.h"
@@ -290,6 +291,15 @@ daemon_init(void)
                free(daemon);
                return NULL;
        }
+       if(!(daemon->env->edns_tags = edns_tags_create())) {
+               auth_zones_delete(daemon->env->auth_zones);
+               acl_list_delete(daemon->acl);
+               tcl_list_delete(daemon->tcl);
+               edns_known_options_delete(daemon->env);
+               free(daemon->env);
+               free(daemon);
+               return NULL;
+       }
        return daemon;  
 }
 
@@ -619,6 +629,10 @@ daemon_fork(struct daemon* daemon)
                &daemon->use_rpz))
                fatal_exit("auth_zones could not be setup");
 
+       /* Set-up EDNS tags */
+       if(!edns_tags_apply_cfg(daemon->env->edns_tags, daemon->cfg))
+               fatal_exit("Could not set up EDNS tags");
+
        /* setup modules */
        daemon_setup_modules(daemon);
 
@@ -750,6 +764,7 @@ daemon_delete(struct daemon* daemon)
                rrset_cache_delete(daemon->env->rrset_cache);
                infra_delete(daemon->env->infra_cache);
                edns_known_options_delete(daemon->env);
+               edns_tags_delete(daemon->env->edns_tags);
                auth_zones_delete(daemon->env->auth_zones);
        }
        ub_randfree(daemon->rand);
index 44e01d7450cba752c4cbc8560a300ef42b28ab35..b7ac5ef60b6ef7ff0f09a2e430e7d1eecf6d3116 100644 (file)
@@ -58,6 +58,7 @@
 #include "util/net_help.h"
 #include "util/random.h"
 #include "util/fptr_wlist.h"
+#include "util/edns.h"
 #include "sldns/sbuffer.h"
 #include "dnstap/dnstap.h"
 #ifdef HAVE_OPENSSL_SSL_H
@@ -2111,9 +2112,20 @@ outnet_serviced_query(struct outside_network* outnet,
 {
        struct serviced_query* sq;
        struct service_callback* cb;
+       struct edns_tag_addr* client_tag_addr;
+
        if(!inplace_cb_query_call(env, qinfo, flags, addr, addrlen, zone, zonelen,
                qstate, qstate->region))
                        return NULL;
+
+       if((client_tag_addr = edns_tag_addr_lookup(env->edns_tags->client_tags,
+               addr, addrlen))) {
+               uint16_t client_tag = htons(client_tag_addr->tag_data);
+               edns_opt_list_append(&qstate->edns_opts_back_out,
+                       LDNS_EDNS_CLIENT_TAG, 2,
+                       (uint8_t*)&client_tag, qstate->region);
+       }
+
        serviced_gen_query(buff, qinfo->qname, qinfo->qname_len, qinfo->qtype,
                qinfo->qclass, flags);
        sq = lookup_serviced(outnet, buff, dnssec, addr, addrlen,
index 4e7fef5745f2bae3a377b2324900055185b3a343..e084f354a8a12ae1bce128f8ae6b723c5657826e 100644 (file)
@@ -426,7 +426,8 @@ enum sldns_enum_edns_option
        LDNS_EDNS_N3U = 7, /* RFC6975 */
        LDNS_EDNS_CLIENT_SUBNET = 8, /* RFC7871 */
        LDNS_EDNS_KEEPALIVE = 11, /* draft-ietf-dnsop-edns-tcp-keepalive*/
-       LDNS_EDNS_PADDING = 12 /* RFC7830 */
+       LDNS_EDNS_PADDING = 12, /* RFC7830 */
+       LDNS_EDNS_CLIENT_TAG = 16 /* draft-bellis-dnsop-edns-tags-01 */
 };
 typedef enum sldns_enum_edns_option sldns_edns_option;
 
index d19952df09466e6d6d6b940f4db5c0254d2c7cc1..0ab00cf7c56dc3e1cac500ba5635d20ed3863112 100644 (file)
 #include "util/data/msgparse.h"
 #include "util/data/msgreply.h"
 
+struct edns_tags* edns_tags_create(void)
+{
+       struct edns_tags* edns_tags = calloc(1, sizeof(struct edns_tags));
+       if(!edns_tags)
+               return NULL;
+       if(!(edns_tags->region = regional_create())) {
+               edns_tags_delete(edns_tags);
+               return NULL;
+       }
+       return edns_tags;
+}
+
+void edns_tags_delete(struct edns_tags* edns_tags)
+{
+       if(!edns_tags)
+               return;
+       regional_destroy(edns_tags->region);
+       free(edns_tags);
+}
+
+int edns_tags_apply_cfg(struct edns_tags* edns_tags,
+       struct config_file* config)
+{
+       regional_free_all(edns_tags->region);
+       addr_tree_init(&edns_tags->client_tags);
+
+       /* TODO walk over config, create and insert node. */
+
+       return 1;
+}
+
+struct edns_tag_addr*
+edns_tag_addr_lookup(rbtree_type tree, struct sockaddr_storage* addr,
+       socklen_t addrlen)
+{
+       return (struct edns_tag_addr*)addr_tree_lookup(&tree, addr, addrlen);
+}
+
 static int edns_keepalive(struct edns_data* edns_out, struct edns_data* edns_in,
                struct comm_point* c, struct regional* region)
 {
index a4ee7def634ce0452d911782ba640f5ef06e4f69..310ba1cd2c9f49d0fa93142aa1dba103f25cb266 100644 (file)
 #ifndef UTIL_EDNS_H
 #define UTIL_EDNS_H
 
+#include "util/storage/dnstree.h"
+
 struct edns_data;
 struct config_file;
 struct comm_point;
 struct regional;
 
+/**
+ * Structure containing all EDNS tags.
+ */
+struct edns_tags {
+       /** Tree of EDNS client tags to use in upstream queries, per address
+        * prefix. Contains nodes of type edns_tag_addr. */
+       rbtree_type client_tags;
+       /** region to allocate tree nodes in */
+       struct regional* region;
+};
+
+/**
+ * EDNS tag. Node of rbtree, containing tag and prefix.
+ */
+struct edns_tag_addr {
+       /** node in address tree, used for tree lookups. Need to be the first
+        * member of this struct. */
+       struct addr_tree_node node;
+       /** tag data, in host byte ordering */
+       uint16_t tag_data;
+};
+
+/**
+ * Create structure to hold EDNS tags
+ * @return: newly created edns_tags, NULL on alloc failure.
+ */
+struct edns_tags* edns_tags_create(void);
+
+/** Delete ENDS tags structure
+ * @param edns_tags: struct to delete
+ */
+void edns_tags_delete(struct edns_tags* edns_tags);
+
+/**
+ * Add configured EDNS tags
+ * @param edns_tags: edns tags to apply config to
+ * @param config: struct containing EDNS tags configuration
+ * @return 0 on error
+ */
+int edns_tags_apply_cfg(struct edns_tags* edns_tags,
+       struct config_file* config);
+
+/**
+ * Find tag for address.
+ * @param tree: tree containing EDNS tags per address prefix.
+ * @param addr: address to use for tree lookup
+ * @param addrlen: length of address
+ * @return: matching tree node, NULL otherwise
+ */
+struct edns_tag_addr*
+edns_tag_addr_lookup(rbtree_type tree, struct sockaddr_storage* addr,
+       socklen_t addrlen);
+
 /**
  * Apply common EDNS options.
  *
index fa89c647e3700085c32053d28080294f13f64dfe..1d696ed0a0e47c721460379fd6d003b2960bd152 100644 (file)
@@ -520,6 +520,7 @@ struct module_env {
        struct edns_known_option* edns_known_options;
        /* Number of known edns options */
        size_t edns_known_options_num;
+       struct edns_tags* edns_tags;
 
        /* Make every mesh state unique, do not aggregate mesh states. */
        int unique_mesh;