add functionality to store the client cookie and attach both client and server cookie to the upstream query

This commit is contained in:
TCY16
2022-05-16 15:33:56 +02:00
parent 47ce372f13
commit 23e04d7f39
3 changed files with 129 additions and 4 deletions
+45 -1
View File
@@ -383,12 +383,18 @@ static void
data_entry_init(struct infra_cache* infra, struct lruhash_entry* e,
time_t timenow)
{
uint8_t cookie[8] = {1,2,3,4,5,6,7,8};
struct infra_data* data = (struct infra_data*)e->data;
data->ttl = timenow + infra->host_ttl;
rtt_init(&data->rtt);
data->edns_version = 0;
data->edns_lame_known = 0;
data->probedelay = 0;
// @TODO create "random" cookie
memset(&data->cookie, 0, sizeof(struct edns_cookie));
memcpy(data->cookie.data.components.client, cookie, 8);
data->isdnsseclame = 0;
data->rec_lame = 0;
data->lame_type_A = 0;
@@ -459,7 +465,11 @@ infra_host(struct infra_cache* infra, struct sockaddr_storage* addr,
if(e) {
/* if its still there we have a writelock, init */
/* re-initialise */
/* do not touch lameness, it may be valid still */
// @TODO check if "do not touch lameness" is still true
/* do not touch lameness, it may be valid still.
* Also don't touch the cookie, as the cookie logic
* will be handled by the server. */
data_entry_init(infra, e, timenow);
wr = 1;
/* TOP_TIMEOUT remains on reuse */
@@ -685,6 +695,40 @@ infra_edns_update(struct infra_cache* infra, struct sockaddr_storage* addr,
return 1;
}
struct edns_cookie*
infra_get_cookie(struct infra_cache* infra, struct sockaddr_storage* addr,
socklen_t addrlen, uint8_t* nm, size_t nmlen,
time_t timenow)
{
struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
nm, nmlen, 1);
struct infra_data* data;
int needtoinsert = 0;
if(!e) {
if(!(e = new_entry(infra, addr, addrlen, nm, nmlen, timenow))) {
return 0;
}
needtoinsert = 1;
} else if(((struct infra_data*)e->data)->ttl < timenow) {
/* @TODO create logic for saving server cookie? -> not sure, find out */
/* create new cookie if the TTL of the current one expired */
data_entry_init(infra, e, timenow);
}
/* we have an entry; update the rtt, and the ttl */
data = (struct infra_data*)e->data;
if(needtoinsert) {
slabhash_insert(infra->hosts, e->hash, e, e->data, NULL);
} else {
lock_rw_unlock(&e->lock);
}
return &data->cookie;
}
int
infra_get_lame_rtt(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen,
+58
View File
@@ -52,6 +52,43 @@
struct slabhash;
struct config_file;
/* COOKIE @TODO move this to correct spot */
/**
* @TODO write this
*/
union edns_cookie_data {
uint8_t complete[24];
struct {
uint8_t client[8];
uint8_t version;
uint8_t reserved[3];
uint32_t timestamp;
uint8_t hash[8];
} components;
};
/**
* @TODO write this
*/
enum edns_cookie_state
{
SERVER_COOKIE_UNKNOWN = 0, /* server cookie unknown, client cookie known */
SERVER_COOKIE_LEARNED = 1, /* server (and client) cookie learned */
COOKIE_NOT_SUPPORTED = 2, /* upstream does not supported EDNS/cookies */
};
/**
* @TODO write this
*/
struct edns_cookie {
enum edns_cookie_state state;
uint8_t timeout; // @TODO change this to correct value
union edns_cookie_data data;
};
/**
* Host information kept for every server, per zone.
*/
@@ -88,6 +125,9 @@ struct infra_data {
* and cause a timeout */
uint8_t edns_lame_known;
/* The EDNS cookie containing both the client and server cookie */
struct edns_cookie cookie;
/** is the host lame (does not serve the zone authoritatively),
* or is the host dnssec lame (does not serve DNSSEC data) */
uint8_t isdnsseclame;
@@ -318,6 +358,24 @@ int infra_edns_update(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen,
uint8_t* name, size_t namelen, int edns_version, time_t timenow);
/**
* Find and return the cookie from the infra cache data. Creates an entry in
* the cache if there isn't one.
* @param infra: infrastructure cache.
* @param addr: host address.
* @param addrlen: length of addr.
* @param name: name of zone
* @param namelen: length of name
* @param edns_version: the version that it publishes.
* If it is known to support EDNS then no-EDNS is not stored over it.
* @param timenow: what time it is now.
* @return: struct ends_cookie*
*/
struct edns_cookie*
infra_get_cookie(struct infra_cache* infra, struct sockaddr_storage* addr,
socklen_t addrlen, uint8_t* nm, size_t nmlen,
time_t timenow);
/**
* Get Lameness information and average RTT if host is in the cache.
* This information is to be used for server selection.
+26 -3
View File
@@ -1030,7 +1030,8 @@ reuse_tcp_remove_tree_list(struct outside_network* outnet,
char buf[256];
addr_to_str(&reuse->addr, reuse->addrlen, buf,
sizeof(buf));
log_err("reuse tcp delete: node not present, internal error, %s ssl %d lru %d", buf, reuse->is_ssl, reuse->item_on_lru_list);
log_err("reuse tcp delete: node not present, internal error, %s ssl "
"%d lru %d", buf, reuse->is_ssl, reuse->item_on_lru_list);
}
reuse->node.key = NULL;
/* defend against loops on broken tree by zeroing the
@@ -1440,6 +1441,7 @@ outnet_udp_cb(struct comm_point* c, void* arg, int error,
verbose(VERB_ALGO, "received udp reply.");
log_buf(VERB_ALGO, "udp message", c->buffer);
if(p->pc->cp != c) {
verbose(VERB_QUERY, "received reply id,addr on wrong port. "
"dropped.");
@@ -3347,6 +3349,7 @@ outnet_serviced_query(struct outside_network* outnet,
struct service_callback* cb;
struct edns_string_addr* client_string_addr;
struct regional* region;
struct edns_cookie* cookie;
struct edns_option* backed_up_opt_list = qstate->edns_opts_back_out;
struct edns_option* per_upstream_opt_list = NULL;
time_t timenow = 0;
@@ -3386,6 +3389,24 @@ outnet_serviced_query(struct outside_network* outnet,
client_string_addr->string, region);
}
// @TODO Make configurable
// 1. lookup the cookie information in the cache
cookie = infra_get_cookie(env->infra_cache, addr, addrlen, zone, zonelen,
*env->now);
// 2. attach cookie, dependent on if we know just the client or also the server
if (cookie->state == SERVER_COOKIE_LEARNED) {
/* We known the complete cookie, so we attach it */
edns_opt_list_append(&per_upstream_opt_list, 10, /* @TODO 10 == COOKIE */
24, cookie->data.complete, region);
} else if (cookie->state == SERVER_COOKIE_UNKNOWN) {
/* We known just client cookie, so we attach it */
edns_opt_list_append(&per_upstream_opt_list, 10, /* @TODO 10 == COOKIE */
8, cookie->data.components.client, region);
}
serviced_gen_query(buff, qinfo->qname, qinfo->qname_len, qinfo->qtype,
qinfo->qclass, flags);
sq = lookup_serviced(outnet, buff, dnssec, addr, addrlen,
@@ -3509,7 +3530,8 @@ fd_for_dest(struct outside_network* outnet, struct sockaddr_storage* to_addr,
if(outnet->num_ip6 == 0) {
char to[64];
addr_to_str(to_addr, to_addrlen, to, sizeof(to));
verbose(VERB_QUERY, "need ipv6 to send, but no ipv6 outgoing interfaces, for %s", to);
verbose(VERB_QUERY, "need ipv6 to send, but no ipv6 outgoing "
"interfaces, for %s", to);
return -1;
}
i = ub_random_max(outnet->rnd, outnet->num_ip6);
@@ -3518,7 +3540,8 @@ fd_for_dest(struct outside_network* outnet, struct sockaddr_storage* to_addr,
if(outnet->num_ip4 == 0) {
char to[64];
addr_to_str(to_addr, to_addrlen, to, sizeof(to));
verbose(VERB_QUERY, "need ipv4 to send, but no ipv4 outgoing interfaces, for %s", to);
verbose(VERB_QUERY, "need ipv4 to send, but no ipv4 outgoing "
"interfaces, for %s", to);
return -1;
}
i = ub_random_max(outnet->rnd, outnet->num_ip4);