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;
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 */
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,
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.
*/
* 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;
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.
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
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.");
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;
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,
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);
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);