} 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;
} qsource;
uint32_t options;
int state;
+ rr_array_t authority;
+ rr_array_t additional;
uint8_t _stub[]; /* Do not touch */
};
struct kr_context
*/
/* 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);
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,
/* 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);
}
}
}
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) {
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);
}
return NULL;
}
+
+mm_ctx_t *kr_resolve_pool(struct kr_request *request)
+{
+ if (request) {
+ return &request->pool;
+ }
+ return NULL;
+}
} qsource;
uint32_t options;
int state;
+ rr_array_t authority;
+ rr_array_t additional;
struct kr_rplan rplan;
mm_ctx_t pool;
};
*/
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);
+
#include "lib/generic/array.h"
#include "lib/nsrep.h"
#include "lib/module.h"
+#include "lib/resolve.h"
/* Logging & debugging */
bool _env_debug = false;
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)
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) {
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) {
#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.
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)))
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);
*/
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.
*/