From 8200e4700f15a5b14f20d3e06e3495ba0fca1541 Mon Sep 17 00:00:00 2001 From: Karel Slany Date: Thu, 4 Aug 2016 16:29:05 +0200 Subject: [PATCH] Function kr_rplan_push() fails again with null name. Introduced kr_rplan_push_empty() to create empty query for DNS cookies. --- lib/resolve.c | 11 ++++++++++- lib/rplan.c | 43 +++++++++++++++++++++++++++++++++++++++---- lib/rplan.h | 11 +++++++++++ tests/test_rplan.c | 3 +-- 4 files changed, 61 insertions(+), 7 deletions(-) diff --git a/lib/resolve.c b/lib/resolve.c index 498b43218..e4f61e431 100644 --- a/lib/resolve.c +++ b/lib/resolve.c @@ -396,7 +396,16 @@ static int resolve_query(struct kr_request *request, const knot_pkt_t *packet) const knot_dname_t *qname = knot_pkt_qname(packet); uint16_t qclass = knot_pkt_qclass(packet); uint16_t qtype = knot_pkt_qtype(packet); - struct kr_query *qry = kr_rplan_push(rplan, NULL, qname, qclass, qtype); + struct kr_query *qry = NULL; + + if (qname != NULL) { + qry = kr_rplan_push(rplan, NULL, qname, qclass, qtype); + } else if (knot_wire_get_qdcount(packet->wire) == 0 && + knot_pkt_has_edns(packet) && + knot_edns_has_option(packet->opt_rr, KNOT_EDNS_OPTION_COOKIE)) { + /* Plan empty query only for cookies. */ + qry = kr_rplan_push_empty(rplan, NULL); + } if (!qry) { return KNOT_STATE_FAIL; } diff --git a/lib/rplan.c b/lib/rplan.c index bc6ff7c37..4a610c6c0 100644 --- a/lib/rplan.c +++ b/lib/rplan.c @@ -107,8 +107,9 @@ bool kr_rplan_empty(struct kr_rplan *rplan) return rplan->pending.len == 0; } -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) +static struct kr_query *kr_rplan_push_query(struct kr_rplan *rplan, + struct kr_query *parent, + const knot_dname_t *name) { if (rplan == NULL) { return NULL; @@ -124,8 +125,7 @@ struct kr_query *kr_rplan_push(struct kr_rplan *rplan, struct kr_query *parent, if (qry == NULL) { return NULL; } - qry->sclass = cls; - qry->stype = type; + /* Class and type must be set outside this function. */ qry->flags = rplan->request->options; qry->parent = parent; qry->ns.addr[0].ip.sa_family = AF_UNSPEC; @@ -133,6 +133,41 @@ struct kr_query *kr_rplan_push(struct kr_rplan *rplan, struct kr_query *parent, kr_zonecut_init(&qry->zone_cut, (const uint8_t *)"", rplan->pool); array_push(rplan->pending, qry); + return qry; +} + +struct kr_query *kr_rplan_push_empty(struct kr_rplan *rplan, struct kr_query *parent) +{ + if (rplan == NULL) { + return NULL; + } + + struct kr_query *qry = kr_rplan_push_query(rplan, parent, NULL); + if (qry == NULL) { + return NULL; + } + + WITH_DEBUG { + DEBUG_MSG(parent, "plan '%s' type '%s'\n", "", ""); + } + return qry; +} + +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) +{ + if (rplan == NULL || name == NULL) { + return NULL; + } + + struct kr_query *qry = kr_rplan_push_query(rplan, parent, name); + if (qry == NULL) { + return NULL; + } + + qry->sclass = cls; + qry->stype = type; + WITH_DEBUG { char name_str[KNOT_DNAME_MAXLEN], type_str[16]; knot_dname_to_str(name_str, name, sizeof(name_str)); diff --git a/lib/rplan.h b/lib/rplan.h index aa6fa5fe3..80a675c0c 100644 --- a/lib/rplan.h +++ b/lib/rplan.h @@ -120,6 +120,17 @@ void kr_rplan_deinit(struct kr_rplan *rplan); KR_EXPORT KR_PURE bool kr_rplan_empty(struct kr_rplan *rplan); +/** + * Push empty query to the top of the resolution plan. + * @note This query serves as a cookie query only. + * @param rplan plan instance + * @param parent query parent (or NULL) + * @return query instance or NULL + */ +KR_EXPORT +struct kr_query *kr_rplan_push_empty(struct kr_rplan *rplan, + struct kr_query *parent); + /** * Push a query to the top of the resolution plan. * @note This means that this query takes precedence before all pending queries. diff --git a/tests/test_rplan.c b/tests/test_rplan.c index f628b2954..0374fe1b9 100644 --- a/tests/test_rplan.c +++ b/tests/test_rplan.c @@ -32,8 +32,7 @@ static void test_rplan_params(void **state) struct kr_rplan rplan; assert_int_equal(kr_rplan_init(&rplan, NULL, NULL), KNOT_EOK); - // TODO: add test for empty dname -// assert_null((void *)kr_rplan_push(&rplan, NULL, NULL, 0, 0)); + assert_null((void *)kr_rplan_push(&rplan, NULL, NULL, 0, 0)); assert_int_equal(kr_rplan_pop(&rplan, NULL), KNOT_EINVAL); assert_true(kr_rplan_empty(&rplan) == true); kr_rplan_deinit(&rplan); -- 2.47.3