Start of EDNS client tags implementation.

This commit is contained in:
Ralph Dolmans 2020-07-23 17:17:44 +02:00
parent 753487ff7f
commit 16029281a8
6 changed files with 123 additions and 1 deletions

View 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);

View 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,

View 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;

View file

@ -47,6 +47,44 @@
#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)
{

View file

@ -42,11 +42,66 @@
#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.
*

View 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;