Commit 6379e459 authored by Karel Slaný's avatar Karel Slaný Committed by Ondřej Surý
Browse files

Added support for TTL in cookies cache.

parent 5fbbf97b
......@@ -116,8 +116,9 @@ static void entry_write(struct kr_cache_entry *dst, struct kr_cache_entry *heade
{
assert(dst && header);
memcpy(dst, header, sizeof(*header));
if (data.data)
if (data.data) {
memcpy(dst->data, data.data, data.len);
}
}
int kr_cookie_cache_insert(struct kr_cache_txn *txn,
......@@ -164,9 +165,9 @@ int kr_cookie_cache_insert(struct kr_cache_txn *txn,
}
int kr_cookie_cache_peek_cookie(struct kr_cache_txn *txn, const void *sockaddr,
const uint8_t **cookie_opt, uint32_t *timestamp)
struct timed_cookie *cookie, uint32_t *timestamp)
{
if (!txn_is_valid(txn) || !sockaddr || !cookie_opt || !timestamp) {
if (!txn_is_valid(txn) || !sockaddr || !cookie || !timestamp) {
return kr_error(EINVAL);
}
......@@ -176,34 +177,36 @@ int kr_cookie_cache_peek_cookie(struct kr_cache_txn *txn, const void *sockaddr,
if (ret != 0) {
return ret;
}
*cookie_opt = entry->data;
cookie->ttl = entry->ttl;
cookie->cookie_opt = entry->data;
return kr_ok();
}
int kr_cookie_cache_insert_cookie(struct kr_cache_txn *txn, const void *sockaddr,
uint8_t *cookie_opt, uint32_t timestamp)
const struct timed_cookie *cookie,
uint32_t timestamp)
{
if (!txn_is_valid(txn) || !sockaddr) {
return kr_error(EINVAL);
}
/* Ignore empty cookie data. */
if (!cookie_opt) {
if (!cookie || !cookie->cookie_opt) {
return kr_ok();
}
/* Prepare header to write. */
struct kr_cache_entry header = {
.timestamp = timestamp,
.ttl = 72000,
.ttl = cookie->ttl,
.rank = KR_RANK_BAD,
.flags = KR_CACHE_FLAG_NONE,
.count = 1
.count = 1 /* Only one entry. */
};
size_t cookie_opt_size = knot_edns_opt_get_length(cookie_opt) + KNOT_EDNS_OPTION_HDRLEN;
size_t cookie_opt_size = knot_edns_opt_get_length(cookie->cookie_opt) + KNOT_EDNS_OPTION_HDRLEN;
knot_db_val_t data = { cookie_opt, cookie_opt_size };
knot_db_val_t data = { (uint8_t *) cookie->cookie_opt, cookie_opt_size };
return kr_cookie_cache_insert(txn, KR_CACHE_COOKIE, sockaddr, &header,
data);
}
......@@ -20,28 +20,69 @@
#define KR_CACHE_COOKIE (KR_CACHE_USER + 'C')
#define COOKIE_TTL 72000
/**
* Peek the cache for asset (tag, socket address).
* @note The 'drift' is the time passed between the inception time and now (in seconds).
* @param txn transaction instance
* @param tag asset tag
* @param sockaddr asset socket address
* @param entry cache entry, will be set to valid pointer or NULL
* @param timestamp current time (will be replaced with drift if successful)
* @return 0 or an error code
*/
KR_EXPORT
int kr_cookie_cache_peek(struct kr_cache_txn *txn, uint8_t tag, const void *sockaddr,
int kr_cookie_cache_peek(struct kr_cache_txn *txn,
uint8_t tag, const void *sockaddr,
struct kr_cache_entry **entry, uint32_t *timestamp);
/**
* Insert asset into cache, replacing any existing data.
* @param txn transaction instance
* @param tag asset tag
* @param sockaddr asset socket address
* @param header filled entry header (ttl and time stamp)
* @param data inserted data
* @return 0 or an error code
*/
KR_EXPORT
int kr_cookie_cache_insert(struct kr_cache_txn *txn,
uint8_t tag, const void *sockaddr,
struct kr_cache_entry *header, knot_db_val_t data);
/**
* Structure used for cookie cache interface.
* @note There is no other way how to pass a ttl into a cookie.
*/
struct timed_cookie {
uint32_t ttl;
const uint8_t *cookie_opt;
};
/**
* Peek the cache for given cookie (socket address)
* @note The 'drift' is the time passed between the cache time of the cookie and now (in seconds).
* @param txn transaction instance
* @param sockaddr socket address
* @param cookie asset
* @param timestamp current time (will be replaced with drift if successful)
* @return 0 or an error code
*/
KR_EXPORT
int kr_cookie_cache_peek_cookie(struct kr_cache_txn *txn, const void *sockaddr,
const uint8_t **cookie_opt, uint32_t *timestamp);
struct timed_cookie *cookie, uint32_t *timestamp);
/**
* Insert a DNS cookie (client and server) entry for the given server signature (IP address).
* @param txn transaction instance
* @param sockaddr server IP address
* @param cookie_opt whole EDNS cookie option (header, client and server)
* @param cookie_size size of the cookie
* @param cookie ttl and whole EDNS cookie option (header, client and server cookies)
* @param timestamp current time
* @return 0 or an errcode
* @return 0 or an error code
*/
KR_EXPORT
int kr_cookie_cache_insert_cookie(struct kr_cache_txn *txn, const void *sockaddr,
uint8_t *cookie_opt, uint32_t timestamp);
const struct timed_cookie *cookie,
uint32_t timestamp);
......@@ -184,20 +184,24 @@ static const uint8_t *peek_and_check_cc(struct kr_cache_txn *txn,
{
assert(txn && sockaddr && cc);
const uint8_t *cached_opt = NULL;
uint32_t timestamp = 0;
struct timed_cookie timed_cookie = { 0, };
int ret = kr_cookie_cache_peek_cookie(txn, sockaddr, &cached_opt,
int ret = kr_cookie_cache_peek_cookie(txn, sockaddr, &timed_cookie,
&timestamp);
if (ret != kr_ok()) {
return NULL;
}
assert(cached_opt);
assert(timed_cookie.cookie_opt);
const uint8_t *cached_cc = knot_edns_opt_get_data((uint8_t *) cached_opt);
/* Ignore the timestamp and time to leave. If the cookie is in cache
* then just use it. The cookie control should be prerformed in the
* cookie module/layer. */
const uint8_t *cached_cc = knot_edns_opt_get_data((uint8_t *) timed_cookie.cookie_opt);
if (0 == memcmp(cc, cached_cc, KNOT_OPT_COOKIE_CLNT)) {
return cached_opt;
return timed_cookie.cookie_opt;
}
return NULL;
......@@ -230,7 +234,8 @@ int kr_request_put_cookie(const struct cookies_control *cntrl,
struct kr_cache_txn txn;
kr_cache_txn_begin(&kr_cookies_control.cache, &txn, KNOT_DB_RDONLY);
const uint8_t *cached_cookie = peek_and_check_cc(&txn, srvr_sockaddr, cc);
const uint8_t *cached_cookie = peek_and_check_cc(&txn, srvr_sockaddr,
cc);
/* This is a very nasty hack that prevents the packet to be corrupted
* when using contemporary 'Cookie interface'. */
......
......@@ -180,34 +180,36 @@ static int server_sockaddr(const struct sockaddr **sockaddr, bool *is_current,
static bool is_cookie_cached(struct kr_cache *cache,
const struct sockaddr *sockaddr,
uint8_t *cookie_opt)
const uint8_t *cookie_opt)
{
assert(cache && sockaddr && cookie_opt);
const uint8_t *cached_cookie = NULL;
struct timed_cookie timed_cookie = { 0, };
uint32_t timestamp = 0;
struct kr_cache_txn txn;
kr_cache_txn_begin(&kr_cookies_control.cache, &txn, KNOT_DB_RDONLY);
int ret = kr_cookie_cache_peek_cookie(&txn, sockaddr, &cached_cookie,
int ret = kr_cookie_cache_peek_cookie(&txn, sockaddr, &timed_cookie,
&timestamp);
if (ret != kr_ok()) {
/* Not cached or error. */
kr_cache_txn_abort(&txn);
return false;
}
assert(cached_cookie);
assert(timed_cookie.cookie_opt);
/* TODO -- Check ttl and drift, if not present then delete cookie. */
uint16_t cookie_opt_size = knot_edns_opt_get_length(cookie_opt) + KNOT_EDNS_OPTION_HDRLEN;
uint16_t cached_cookie_size = knot_edns_opt_get_length((uint8_t *) cached_cookie) + KNOT_EDNS_OPTION_HDRLEN;
uint16_t cached_cookie_size = knot_edns_opt_get_length(timed_cookie.cookie_opt) + KNOT_EDNS_OPTION_HDRLEN;
if (cookie_opt_size != cached_cookie_size) {
kr_cache_txn_abort(&txn);
return false;
}
bool equal = (memcmp(cookie_opt, cached_cookie, cookie_opt_size) == 0);
bool equal = (memcmp(cookie_opt, timed_cookie.cookie_opt, cookie_opt_size) == 0);
kr_cache_txn_abort(&txn);
return equal;
......@@ -279,8 +281,10 @@ static int check_response(knot_layer_t *ctx, knot_pkt_t *pkt)
return ctx->state;
}
struct timed_cookie timed_cookie = { COOKIE_TTL, cookie_opt };
ret = kr_cookie_cache_insert_cookie(&txn, srvr_sockaddr,
cookie_opt,
&timed_cookie,
qry->timestamp.tv_sec);
if (ret != kr_ok()) {
kr_cache_txn_abort(&txn);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment