Skip to content
Snippets Groups Projects
Commit cd46e9fe authored by Marek Vavruša's avatar Marek Vavruša
Browse files

lib: request holds authority/additional RRs for finalization

as the libknot packet interface disallows out-of-order packet
writes, authority and additional records must be written after
the answer is complete; records in the rr arrays will be written to final answer during finalization
parent a7667235
Branches
Tags
No related merge requests found
......@@ -161,6 +161,11 @@ typedef struct {
} map_t;
/* libkres */
typedef struct {
knot_rrset_t *at;
size_t len;
size_t cap;
} rr_array_t;
struct kr_query {
node_t _node;
struct kr_query *parent;
......@@ -185,6 +190,8 @@ struct kr_request {
} qsource;
uint32_t options;
int state;
rr_array_t authority;
rr_array_t additional;
uint8_t _stub[]; /* Do not touch */
};
struct kr_context
......@@ -228,6 +235,7 @@ const knot_pktsection_t *knot_pkt_section(const knot_pkt_t *pkt,
*/
/* Resolution request */
struct kr_rplan *kr_resolve_plan(struct kr_request *request);
void *kr_resolve_pool(struct kr_request *request);
/* Resolution plan */
struct kr_query *kr_rplan_push(struct kr_rplan *rplan, struct kr_query *parent,
const knot_dname_t *name, uint16_t cls, uint16_t type);
......@@ -240,6 +248,9 @@ int kr_pkt_put(knot_pkt_t *pkt, const knot_dname_t *name, uint32_t ttl,
uint16_t rclass, uint16_t rtype, const uint8_t *rdata, uint16_t rdlen);
const char *kr_inaddr(const struct sockaddr *addr);
int kr_inaddr_len(const struct sockaddr *addr);
int kr_straddr_family(const char *addr);
int kr_family_len(int family);
int kr_rrarray_add(rr_array_t *array, const knot_rrset_t *rr, void *pool);
/* Trust anchors */
knot_rrset_t *kr_ta_get(map_t *trust_anchors, const knot_dname_t *name);
int kr_ta_add(map_t *trust_anchors, const knot_dname_t *name, uint16_t type,
......
......@@ -305,14 +305,14 @@ static void finalize_answer(knot_pkt_t *pkt, struct kr_query *qry, struct kr_req
/* Fill in bailiwick records in authority */
struct kr_zonecut *cut = &qry->zone_cut;
knot_pkt_begin(answer, KNOT_AUTHORITY);
int pkt_class = kr_response_classify(pkt);
if (pkt_class & (PKT_NXDOMAIN|PKT_NODATA)) {
const knot_pktsection_t *ns = knot_pkt_section(pkt, KNOT_AUTHORITY);
for (unsigned i = 0; i < ns->count; ++i) {
const knot_rrset_t *rr = knot_pkt_rr(ns, i);
/* Stash the authority records, they will be written to wire on answer finalization. */
if (knot_dname_in(cut->name, rr->owner)) {
update_answer(rr, 0, answer);
kr_rrarray_add(&req->authority, rr, &answer->mm);
}
}
}
......
......@@ -277,11 +277,24 @@ static int answer_prepare(knot_pkt_t *answer, knot_pkt_t *query, struct kr_reque
return kr_ok();
}
static void write_extra_records(rr_array_t *arr, knot_pkt_t *answer)
{
for (size_t i = 0; i < arr->len; ++i) {
knot_pkt_put(answer, 0, arr->at[i], 0);
}
}
static int answer_finalize(struct kr_request *request, int state)
{
/* Write EDNS information */
/* Write authority records. */
knot_pkt_t *answer = request->answer;
if (answer->current < KNOT_AUTHORITY)
knot_pkt_begin(answer, KNOT_AUTHORITY);
write_extra_records(&request->authority, answer);
/* Write additional records. */
knot_pkt_begin(answer, KNOT_ADDITIONAL);
write_extra_records(&request->additional, answer);
/* Write EDNS information */
if (answer->opt_rr) {
int ret = edns_put(answer);
if (ret != 0) {
......@@ -331,6 +344,8 @@ int kr_resolve_begin(struct kr_request *request, struct kr_context *ctx, knot_pk
request->options = ctx->options;
request->state = KNOT_STATE_CONSUME;
request->current_query = NULL;
array_init(request->authority);
array_init(request->additional);
/* Expect first query */
kr_rplan_init(&request->rplan, request, &request->pool);
......@@ -724,3 +739,11 @@ struct kr_rplan *kr_resolve_plan(struct kr_request *request)
}
return NULL;
}
mm_ctx_t *kr_resolve_pool(struct kr_request *request)
{
if (request) {
return &request->pool;
}
return NULL;
}
......@@ -115,6 +115,8 @@ struct kr_request {
} qsource;
uint32_t options;
int state;
rr_array_t authority;
rr_array_t additional;
struct kr_rplan rplan;
mm_ctx_t pool;
};
......@@ -178,3 +180,10 @@ int kr_resolve_finish(struct kr_request *request, int state);
*/
struct kr_rplan *kr_resolve_plan(struct kr_request *request);
/**
* Return memory pool associated with request.
* @param request request state
* @return mempool
*/
mm_ctx_t *kr_resolve_pool(struct kr_request *request);
......@@ -31,6 +31,7 @@
#include "lib/generic/array.h"
#include "lib/nsrep.h"
#include "lib/module.h"
#include "lib/resolve.h"
/* Logging & debugging */
bool _env_debug = false;
......@@ -200,7 +201,7 @@ int kr_inaddr_len(const struct sockaddr *addr)
if (!addr) {
return kr_error(EINVAL);
}
return addr->sa_family == AF_INET ? sizeof(struct in_addr) : sizeof(struct in6_addr);
return kr_family_len(addr->sa_family);
}
int kr_straddr_family(const char *addr)
......@@ -214,6 +215,11 @@ int kr_straddr_family(const char *addr)
return AF_INET;
}
int kr_family_len(int family)
{
return (family == AF_INET) ? sizeof(struct in_addr) : sizeof(struct in6_addr);
}
int kr_straddr_subnet(void *dst, const char *addr)
{
if (!dst || !addr) {
......@@ -308,6 +314,20 @@ int kr_rrmap_add(map_t *stash, const knot_rrset_t *rr, uint8_t rank, mm_ctx_t *p
return knot_rdataset_merge(&stashed->rrs, &rr->rrs, pool);
}
int kr_rrarray_add(rr_array_t *array, const knot_rrset_t *rr, mm_ctx_t *pool)
{
int ret = array_reserve_mm(*array, array->len + 1, mm_reserve, pool);
if (ret != 0) {
return kr_error(ENOMEM);
}
knot_rrset_t *copy = knot_rrset_copy(rr, pool);
if (!copy) {
return kr_error(ENOMEM);
}
array_push(*array, copy);
return kr_ok();
}
static char *callprop(struct kr_module *module, const char *prop, const char *input, void *env)
{
if (!module || !prop) {
......
......@@ -21,7 +21,7 @@
#include <netinet/in.h>
#include <libknot/packet/pkt.h>
#include "lib/generic/map.h"
#include "lib/resolve.h"
#include "lib/generic/array.h"
/*
* General-purpose attributes.
......@@ -72,6 +72,10 @@ static inline long time_diff(struct timeval *begin, struct timeval *end) {
return res.tv_sec * 1000 + res.tv_usec / 1000;
}
/** @internal Array types */
struct kr_context;
typedef array_t(knot_rrset_t *) rr_array_t;
/** @internal Next RDATA shortcut. */
#define kr_rdataset_next(rd) (rd + knot_rdata_array_size(knot_rdata_rdlen(rd)))
......@@ -107,6 +111,8 @@ const char *kr_inaddr(const struct sockaddr *addr);
int kr_inaddr_len(const struct sockaddr *addr);
/** Return address type for string. */
int kr_straddr_family(const char *addr);
/** Return address length in given family. */
int kr_family_len(int family);
/** Parse address and return subnet length (bits).
* @warning 'dst' must be at least `sizeof(struct in6_addr)` long. */
int kr_straddr_subnet(void *dst, const char *addr);
......@@ -124,6 +130,9 @@ int kr_bitcmp(const char *a, const char *b, int bits);
*/
int kr_rrmap_add(map_t *stash, const knot_rrset_t *rr, uint8_t rank, mm_ctx_t *pool);
/** @internal Add RRSet copy to RR array. */
int kr_rrarray_add(rr_array_t *array, const knot_rrset_t *rr, mm_ctx_t *pool);
/**
* Call module property.
*/
......
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