From: Marek VavruĊĦa Date: Tue, 27 Oct 2015 09:06:53 +0000 (+0100) Subject: lib: request holds authority/additional RRs for finalization X-Git-Tag: v1.0.0-beta2~50 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cd46e9fe911cce4e878e27b9d9fdd5cfaec6162c;p=thirdparty%2Fknot-resolver.git 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 --- diff --git a/daemon/lua/kres.lua b/daemon/lua/kres.lua index 1febe0a5f..194fd210d 100644 --- a/daemon/lua/kres.lua +++ b/daemon/lua/kres.lua @@ -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, diff --git a/lib/layer/iterate.c b/lib/layer/iterate.c index f2d7f36fc..23fc15829 100644 --- a/lib/layer/iterate.c +++ b/lib/layer/iterate.c @@ -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); } } } diff --git a/lib/resolve.c b/lib/resolve.c index e8df821ef..0a9aefcb1 100644 --- a/lib/resolve.c +++ b/lib/resolve.c @@ -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; +} diff --git a/lib/resolve.h b/lib/resolve.h index e5665f3e5..20d589d5b 100644 --- a/lib/resolve.h +++ b/lib/resolve.h @@ -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); + diff --git a/lib/utils.c b/lib/utils.c index ff7e4cbf3..a10ca31d8 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -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) { diff --git a/lib/utils.h b/lib/utils.h index d6cce398c..279ab1f7b 100644 --- a/lib/utils.h +++ b/lib/utils.h @@ -21,7 +21,7 @@ #include #include #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. */