static int init_resolver(struct engine *engine)
{
/* Open resolution context */
+ engine->resolver.pool = engine->pool;
engine->resolver.modules = &engine->modules;
+ /* Create OPT RR */
+ engine->resolver.opt_rr = mm_alloc(engine->pool, sizeof(knot_rrset_t));
+ if (!engine->resolver.opt_rr) {
+ return kr_error(ENOMEM);
+ }
+ knot_edns_init(engine->resolver.opt_rr, KR_EDNS_PAYLOAD, 0, KR_EDNS_VERSION, engine->pool);
/* Set default root hints */
kr_zonecut_init(&engine->resolver.root_hints, (const uint8_t *)"", engine->pool);
kr_zonecut_set_sbelt(&engine->resolver, &engine->resolver.root_hints);
/* Open NS rtt + reputation cache */
- engine->resolver.cache_rtt = malloc(lru_size(kr_nsrep_lru_t, LRU_RTT_SIZE));
+ engine->resolver.cache_rtt = mm_alloc(engine->pool, lru_size(kr_nsrep_lru_t, LRU_RTT_SIZE));
if (engine->resolver.cache_rtt) {
lru_init(engine->resolver.cache_rtt, LRU_RTT_SIZE);
}
- engine->resolver.cache_rep = malloc(lru_size(kr_nsrep_lru_t, LRU_REP_SIZE));
+ engine->resolver.cache_rep = mm_alloc(engine->pool, lru_size(kr_nsrep_lru_t, LRU_REP_SIZE));
if (engine->resolver.cache_rep) {
lru_init(engine->resolver.cache_rep, LRU_REP_SIZE);
}
/* Initialize resolver */
ret = init_resolver(engine);
if (ret != 0) {
+ engine_deinit(engine);
return ret;
}
/* Initialize network */
return;
}
+ /* Only close sockets and services,
+ * no need to clean up mempool. */
network_deinit(&engine->net);
kr_zonecut_deinit(&engine->resolver.root_hints);
kr_cache_close(&engine->resolver.cache);
lru_deinit(engine->resolver.cache_rtt);
- free(engine->resolver.cache_rtt);
lru_deinit(engine->resolver.cache_rep);
- free(engine->resolver.cache_rep);
/* Unload modules. */
for (size_t i = 0; i < engine->modules.len; ++i) {
{
/* How much can client handle? */
size_t answer_max = KNOT_WIRE_MIN_PKTSIZE;
+ size_t pktbuf_max = KR_EDNS_PAYLOAD;
if (!addr && handle) { /* TCP */
answer_max = KNOT_WIRE_MAX_PKTSIZE;
+ pktbuf_max = KNOT_WIRE_MAX_PKTSIZE;
} else if (knot_pkt_has_edns(query)) { /* EDNS */
answer_max = MAX(knot_edns_get_payload(query->opt_rr), KNOT_WIRE_MIN_PKTSIZE);
}
- size_t pktbuf_max = MAX(KNOT_EDNS_MAX_UDP_PAYLOAD, answer_max);
/* Recycle available mempool if possible */
mm_ctx_t pool = {
static int edns_put(knot_pkt_t *pkt)
{
+ if (!pkt->opt_rr) {
+ return kr_ok();
+ }
/* Reclaim reserved size. */
int ret = knot_pkt_reclaim(pkt, knot_edns_wire_size(pkt->opt_rr));
if (ret != 0) {
return knot_pkt_put(pkt, KNOT_COMPR_HINT_NONE, pkt->opt_rr, KNOT_PF_FREE);
}
-static int edns_create(knot_pkt_t *pkt, knot_pkt_t *template)
+static int edns_create(knot_pkt_t *pkt, knot_pkt_t *template, struct kr_request *req)
{
- /* Create empty OPT RR */
- pkt->opt_rr = mm_alloc(&pkt->mm, sizeof(*pkt->opt_rr));
- if (!pkt->opt_rr) {
- return kr_error(ENOMEM);
- }
- int ret = knot_edns_init(pkt->opt_rr, KR_EDNS_PAYLOAD, 0, KR_EDNS_VERSION, &pkt->mm);
- if (ret != 0) {
- return ret;
- }
+ pkt->opt_rr = knot_rrset_copy(req->ctx->opt_rr, &pkt->mm);
/* Set DO bit if set (DNSSEC requested). */
if (knot_pkt_has_dnssec(template)) {
knot_edns_set_do(pkt->opt_rr);
return knot_pkt_reserve(pkt, knot_edns_wire_size(pkt->opt_rr));
}
-static int answer_prepare(knot_pkt_t *answer, knot_pkt_t *query)
+static int answer_prepare(knot_pkt_t *answer, knot_pkt_t *query, struct kr_request *req)
{
if (!knot_wire_get_rd(query->wire)) {
return kr_error(ENOSYS); /* Only recursive service */
}
/* Handle EDNS in the query */
if (knot_pkt_has_edns(query)) {
- int ret = edns_create(answer, query);
+ int ret = edns_create(answer, query, req);
if (ret != 0){
return ret;
}
int ret = 0;
knot_pkt_begin(pkt, KNOT_ADDITIONAL);
if (!(qry->flags & QUERY_SAFEMODE)) {
- ret = edns_create(pkt, request->answer);
+ ret = edns_create(pkt, request->answer, request);
if (ret == 0) {
ret = edns_put(pkt);
}
/* Empty resolution plan, push packet as the new query */
if (packet && kr_rplan_empty(rplan)) {
- if (answer_prepare(request->answer, packet) != 0) {
+ if (answer_prepare(request->answer, packet, request) != 0) {
return KNOT_STATE_FAIL;
}
/* Start query resolution */
kr_nsrep_lru_t *cache_rtt;
kr_nsrep_lru_t *cache_rep;
module_array_t *modules;
+ knot_rrset_t *opt_rr;
uint32_t options;
};