Introduced kr_rplan_push_empty() to create empty query for DNS cookies.
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;
}
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;
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;
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));
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.
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);