store complete cookie when receiving from downstream. Add function through search through an edns_option list

This commit is contained in:
TCY16
2022-05-19 13:24:00 +02:00
parent 23e04d7f39
commit 44af84dfc9
6 changed files with 97 additions and 17 deletions
+17
View File
@@ -3764,6 +3764,7 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
{
struct msg_parse* prs;
struct edns_data edns;
struct edns_option* cookie;
sldns_buffer* pkt;
verbose(VERB_ALGO, "process_response: new external response event");
@@ -3823,6 +3824,22 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
goto handle_it;
}
if((cookie = edns_list_get_option(edns.opt_list_in, 10 /*@TODO change to cookie with downstream merge*/))) {
/* verify this is a 'complete cookie' (RFC9018) with the length */
if (cookie->opt_len == 24) {
/* store the complete cookie in the infra_cache */
infra_set_server_cookie(qstate->env->infra_cache,
&qstate->reply->addr, qstate->reply->addrlen,
iq->dp->name, iq->dp->namelen, cookie);
log_hex("complete cookie: ", cookie->opt_data,
cookie->opt_len);
} else {
// @TODO just log error? set state to COOKIE_NOT_SUPPORTED?
}
}
/* Copy the edns options we may got from the back end */
if(edns.opt_list_in) {
qstate->edns_opts_back_in = edns_opt_copy_region(edns.opt_list_in,
+33 -5
View File
@@ -697,16 +697,16 @@ infra_edns_update(struct infra_cache* infra, struct sockaddr_storage* addr,
struct edns_cookie*
infra_get_cookie(struct infra_cache* infra, struct sockaddr_storage* addr,
socklen_t addrlen, uint8_t* nm, size_t nmlen,
socklen_t addrlen, uint8_t* name, size_t namelen,
time_t timenow)
{
struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
nm, nmlen, 1);
name, namelen, 1);
struct infra_data* data;
int needtoinsert = 0;
if(!e) {
if(!(e = new_entry(infra, addr, addrlen, nm, nmlen, timenow))) {
if(!(e = new_entry(infra, addr, addrlen, name, namelen, timenow))) {
return 0;
}
needtoinsert = 1;
@@ -717,8 +717,7 @@ infra_get_cookie(struct infra_cache* infra, struct sockaddr_storage* addr,
data_entry_init(infra, e, timenow);
}
/* we have an entry; update the rtt, and the ttl */
data = (struct infra_data*)e->data;
data = (struct infra_data*) e->data;
if(needtoinsert) {
slabhash_insert(infra->hosts, e->hash, e, e->data, NULL);
@@ -729,6 +728,35 @@ infra_get_cookie(struct infra_cache* infra, struct sockaddr_storage* addr,
return &data->cookie;
}
void
infra_set_server_cookie(struct infra_cache* infra, struct sockaddr_storage* addr,
socklen_t addrlen, uint8_t* name, size_t namelen, struct edns_option* cookie)
{
struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
name, namelen, 1);
struct infra_data* data;
/* cookie length verification should be checked and handled by caller */
assert(cookie->opt_len == 24);
/* the client cookie was set on the outgoing upstream, so the entry
* must exists here */
assert(e);
data = (struct infra_data*) e->data;
/* check if we already know the complete cookie */
if (data->cookie.state == SERVER_COOKIE_UNKNOWN) {
memcpy(data->cookie.data.complete, cookie->opt_data, 24);
data->cookie.state = SERVER_COOKIE_LEARNED;
}
else {
lock_rw_unlock(&e->lock);
}
}
int
infra_get_lame_rtt(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen,
+23 -8
View File
@@ -55,7 +55,7 @@ struct config_file;
/* COOKIE @TODO move this to correct spot */
/**
* @TODO write this
* The actual EDNS cookie data
*/
union edns_cookie_data {
uint8_t complete[24];
@@ -69,17 +69,17 @@ union edns_cookie_data {
};
/**
* @TODO write this
* The different states the EDNS cookie can be in
*/
enum edns_cookie_state
{
SERVER_COOKIE_UNKNOWN = 0, /* server cookie unknown, client cookie known */
SERVER_COOKIE_LEARNED = 1, /* server (and client) cookie learned */
SERVER_COOKIE_LEARNED = 1, /* server (and client) cookie known */
COOKIE_NOT_SUPPORTED = 2, /* upstream does not supported EDNS/cookies */
};
/**
* @TODO write this
* Structure for an EDNS cookie (RFC9018) and it's internal state
*/
struct edns_cookie {
enum edns_cookie_state state;
@@ -125,7 +125,7 @@ struct infra_data {
* and cause a timeout */
uint8_t edns_lame_known;
/* The EDNS cookie containing both the client and server cookie */
/* The EDNS cookie containing the cookie and the internal state */
struct edns_cookie cookie;
/** is the host lame (does not serve the zone authoritatively),
@@ -366,16 +366,31 @@ int infra_edns_update(struct infra_cache* infra,
* @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,
socklen_t addrlen, uint8_t* name, size_t namelen,
time_t timenow);
/**
* Find the cookie entry in the cache and update it with to make a complete
* cookie (RFC9018). This function assumes that the cookie param contains a
* complete cookie with a length of 24 bytes. It also assumes that a previous
* entry in the cache already exists, as it will update the entry.
* @param infra: infrastructure cache.
* @param addr: host address.
* @param addrlen: length of addr.
* @param name: name of zone
* @param namelen: length of name
* @param timenow: what time it is now.
* @param cookie: the EDNS cookie option we want to store.
*/
void infra_set_server_cookie(struct infra_cache* infra, struct sockaddr_storage* addr,
socklen_t addrlen, uint8_t* name, size_t namelen, struct edns_option* cookie);
/**
* Get Lameness information and average RTT if host is in the cache.
* This information is to be used for server selection.
+2 -4
View File
@@ -3392,20 +3392,18 @@ outnet_serviced_query(struct outside_network* outnet,
// @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 */
/* We know 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);
}
} /* We ignore COOKIE_NOT_SUPPORTED */
serviced_gen_query(buff, qinfo->qname, qinfo->qname_len, qinfo->qtype,
qinfo->qclass, flags);
+13
View File
@@ -597,6 +597,19 @@ parse_query_section(sldns_buffer* pkt, struct msg_parse* msg)
return 0;
}
struct edns_option*
edns_list_get_option(struct edns_option* option, uint16_t code)
{
while (option) {
if (option->opt_code == code) {
return option;
}
option = option->next;
}
return NULL;
}
size_t
get_rdf_size(sldns_rdf_type rdf)
{
+9
View File
@@ -254,6 +254,15 @@ struct edns_option {
uint8_t* opt_data;
};
/**
* Search through an EDNS list to find if the specified option.
* @param option: The EDNS list which we search in
* @param code: the option code that we search for
* @return: returns the option if it is there, and NULL when it is not
*/
struct edns_option* edns_list_get_option(struct edns_option* option, uint16_t code);
/**
* Obtain size in the packet of an rr type, that is before dname type.
* Do TYPE_DNAME, and type STR, yourself. Gives size for most regular types.