mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-09-12 21:07:43 +02:00
add functionality to store the client cookie and attach both client and server cookie to the upstream query
This commit is contained in:
Vendored
+45
-1
@@ -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,
|
||||
|
||||
Vendored
+58
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user