]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
lib: request holds authority/additional RRs for finalization
authorMarek Vavruša <marek.vavrusa@nic.cz>
Tue, 27 Oct 2015 09:06:53 +0000 (10:06 +0100)
committerMarek Vavruša <marek.vavrusa@nic.cz>
Tue, 27 Oct 2015 09:06:53 +0000 (10:06 +0100)
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

daemon/lua/kres.lua
lib/layer/iterate.c
lib/resolve.c
lib/resolve.h
lib/utils.c
lib/utils.h

index 1febe0a5f32336e5291f0b81a0e862fc0a111ed9..194fd210da2c661bc052d430b41987ff2e2d92e5 100644 (file)
@@ -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,
index f2d7f36fcd07821b95c723ded1b39c8920571f64..23fc15829ee66487ada0115efcdafe9d3be49b44 100644 (file)
@@ -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);
                        }
                }
        }
index e8df821ef4bcb26ab574e797926c0972a0aa54db..0a9aefcb11062fa58bfff3e761708428f7141dee 100644 (file)
@@ -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;
+}
index e5665f3e55ae6459cee0be205150b53552fa4654..20d589d5bb7c0c68a45211665232902681f0afb7 100644 (file)
@@ -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);
+
index ff7e4cbf3e1f30c3465fcb3c237215fd59e718dc..a10ca31d88f76c56a9b97a37c03ffc5fb4aa1790 100644 (file)
@@ -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) {
index d6cce398ce6c71e4174432c5884a9472cbbc895a..279ab1f7bd1e32fbdc2f0599f4236e9dccda27e8 100644 (file)
@@ -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.
  */