13b6c3722Schristos /*
23b6c3722Schristos * libunbound/context.c - validating context for unbound internal use
33b6c3722Schristos *
43b6c3722Schristos * Copyright (c) 2007, NLnet Labs. All rights reserved.
53b6c3722Schristos *
63b6c3722Schristos * This software is open source.
73b6c3722Schristos *
83b6c3722Schristos * Redistribution and use in source and binary forms, with or without
93b6c3722Schristos * modification, are permitted provided that the following conditions
103b6c3722Schristos * are met:
113b6c3722Schristos *
123b6c3722Schristos * Redistributions of source code must retain the above copyright notice,
133b6c3722Schristos * this list of conditions and the following disclaimer.
143b6c3722Schristos *
153b6c3722Schristos * Redistributions in binary form must reproduce the above copyright notice,
163b6c3722Schristos * this list of conditions and the following disclaimer in the documentation
173b6c3722Schristos * and/or other materials provided with the distribution.
183b6c3722Schristos *
193b6c3722Schristos * Neither the name of the NLNET LABS nor the names of its contributors may
203b6c3722Schristos * be used to endorse or promote products derived from this software without
213b6c3722Schristos * specific prior written permission.
223b6c3722Schristos *
233b6c3722Schristos * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
243b6c3722Schristos * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
253b6c3722Schristos * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
263b6c3722Schristos * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
273b6c3722Schristos * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
283b6c3722Schristos * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
293b6c3722Schristos * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
303b6c3722Schristos * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
313b6c3722Schristos * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
323b6c3722Schristos * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
333b6c3722Schristos * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
343b6c3722Schristos */
353b6c3722Schristos
363b6c3722Schristos /**
373b6c3722Schristos * \file
383b6c3722Schristos *
393b6c3722Schristos * This file contains the validator context structure.
403b6c3722Schristos */
413b6c3722Schristos #include "config.h"
423b6c3722Schristos #include "libunbound/context.h"
433b6c3722Schristos #include "util/module.h"
443b6c3722Schristos #include "util/config_file.h"
453b6c3722Schristos #include "util/net_help.h"
463b6c3722Schristos #include "services/modstack.h"
473b6c3722Schristos #include "services/localzone.h"
483b6c3722Schristos #include "services/cache/rrset.h"
493b6c3722Schristos #include "services/cache/infra.h"
507cd94d69Schristos #include "services/authzone.h"
517a540f2bSchristos #include "services/listen_dnsport.h"
523b6c3722Schristos #include "util/data/msgreply.h"
533b6c3722Schristos #include "util/storage/slabhash.h"
54d0eba39bSchristos #include "util/edns.h"
553b6c3722Schristos #include "sldns/sbuffer.h"
563b6c3722Schristos
573b6c3722Schristos int
context_finalize(struct ub_ctx * ctx)583b6c3722Schristos context_finalize(struct ub_ctx* ctx)
593b6c3722Schristos {
60d0eba39bSchristos int is_rpz = 0;
613b6c3722Schristos struct config_file* cfg = ctx->env->cfg;
623b6c3722Schristos verbosity = cfg->verbosity;
6301049ae6Schristos if(ctx_logfile_overridden && !ctx->logfile_override) {
6401049ae6Schristos log_file(NULL); /* clear that override */
6501049ae6Schristos ctx_logfile_overridden = 0;
6601049ae6Schristos }
6701049ae6Schristos if(ctx->logfile_override) {
6801049ae6Schristos ctx_logfile_overridden = 1;
693b6c3722Schristos log_file(ctx->log_out);
7001049ae6Schristos } else {
7101049ae6Schristos log_init(cfg->logfile, cfg->use_syslog, NULL);
7201049ae6Schristos }
73*91f7d55fSchristos ctx->pipe_pid = getpid();
747a540f2bSchristos cfg_apply_local_port_policy(cfg, 65536);
753b6c3722Schristos config_apply(cfg);
763b6c3722Schristos if(!modstack_setup(&ctx->mods, cfg->module_conf, ctx->env))
773b6c3722Schristos return UB_INITFAIL;
787a540f2bSchristos listen_setup_locks();
790cd9f4ecSchristos log_edns_known_options(VERB_ALGO, ctx->env);
803b6c3722Schristos ctx->local_zones = local_zones_create();
813b6c3722Schristos if(!ctx->local_zones)
823b6c3722Schristos return UB_NOMEM;
833b6c3722Schristos if(!local_zones_apply_cfg(ctx->local_zones, cfg))
843b6c3722Schristos return UB_INITFAIL;
857a540f2bSchristos if(!auth_zones_apply_cfg(ctx->env->auth_zones, cfg, 1, &is_rpz,
867a540f2bSchristos ctx->env, &ctx->mods))
87d0eba39bSchristos return UB_INITFAIL;
88d0eba39bSchristos if(!edns_strings_apply_cfg(ctx->env->edns_strings, cfg))
897cd94d69Schristos return UB_INITFAIL;
90f42d8de7Schristos if(!slabhash_is_size(ctx->env->msg_cache, cfg->msg_cache_size,
91f42d8de7Schristos cfg->msg_cache_slabs)) {
923b6c3722Schristos slabhash_delete(ctx->env->msg_cache);
933b6c3722Schristos ctx->env->msg_cache = slabhash_create(cfg->msg_cache_slabs,
943b6c3722Schristos HASH_DEFAULT_STARTARRAY, cfg->msg_cache_size,
953b6c3722Schristos msgreply_sizefunc, query_info_compare,
963b6c3722Schristos query_entry_delete, reply_info_delete, NULL);
973b6c3722Schristos if(!ctx->env->msg_cache)
983b6c3722Schristos return UB_NOMEM;
993b6c3722Schristos }
1003b6c3722Schristos ctx->env->rrset_cache = rrset_cache_adjust(ctx->env->rrset_cache,
1013b6c3722Schristos ctx->env->cfg, ctx->env->alloc);
1023b6c3722Schristos if(!ctx->env->rrset_cache)
1033b6c3722Schristos return UB_NOMEM;
1043b6c3722Schristos ctx->env->infra_cache = infra_adjust(ctx->env->infra_cache, cfg);
1053b6c3722Schristos if(!ctx->env->infra_cache)
1063b6c3722Schristos return UB_NOMEM;
1073b6c3722Schristos ctx->finalized = 1;
1083b6c3722Schristos return UB_NOERROR;
1093b6c3722Schristos }
1103b6c3722Schristos
context_query_cmp(const void * a,const void * b)1113b6c3722Schristos int context_query_cmp(const void* a, const void* b)
1123b6c3722Schristos {
1133b6c3722Schristos if( *(int*)a < *(int*)b )
1143b6c3722Schristos return -1;
1153b6c3722Schristos if( *(int*)a > *(int*)b )
1163b6c3722Schristos return 1;
1173b6c3722Schristos return 0;
1183b6c3722Schristos }
1193b6c3722Schristos
1203b6c3722Schristos void
context_query_delete(struct ctx_query * q)1213b6c3722Schristos context_query_delete(struct ctx_query* q)
1223b6c3722Schristos {
1233b6c3722Schristos if(!q) return;
1243b6c3722Schristos ub_resolve_free(q->res);
1253b6c3722Schristos free(q->msg);
1263b6c3722Schristos free(q);
1273b6c3722Schristos }
1283b6c3722Schristos
1293b6c3722Schristos /** How many times to try to find an unused query-id-number for async */
1303b6c3722Schristos #define NUM_ID_TRIES 100000
1313b6c3722Schristos /** find next useful id number of 0 on error */
1323b6c3722Schristos static int
find_id(struct ub_ctx * ctx,int * id)1333b6c3722Schristos find_id(struct ub_ctx* ctx, int* id)
1343b6c3722Schristos {
1353b6c3722Schristos size_t tries = 0;
1363b6c3722Schristos ctx->next_querynum++;
1373b6c3722Schristos while(rbtree_search(&ctx->queries, &ctx->next_querynum)) {
1383b6c3722Schristos ctx->next_querynum++; /* numerical wraparound is fine */
1393b6c3722Schristos if(tries++ > NUM_ID_TRIES)
1403b6c3722Schristos return 0;
1413b6c3722Schristos }
1423b6c3722Schristos *id = ctx->next_querynum;
1433b6c3722Schristos return 1;
1443b6c3722Schristos }
1453b6c3722Schristos
1463b6c3722Schristos struct ctx_query*
context_new(struct ub_ctx * ctx,const char * name,int rrtype,int rrclass,ub_callback_type cb,ub_event_callback_type cb_event,void * cbarg)1473b6c3722Schristos context_new(struct ub_ctx* ctx, const char* name, int rrtype, int rrclass,
1487cd94d69Schristos ub_callback_type cb, ub_event_callback_type cb_event, void* cbarg)
1493b6c3722Schristos {
1503b6c3722Schristos struct ctx_query* q = (struct ctx_query*)calloc(1, sizeof(*q));
1513b6c3722Schristos if(!q) return NULL;
1523b6c3722Schristos lock_basic_lock(&ctx->cfglock);
1533b6c3722Schristos if(!find_id(ctx, &q->querynum)) {
1543b6c3722Schristos lock_basic_unlock(&ctx->cfglock);
1553b6c3722Schristos free(q);
1563b6c3722Schristos return NULL;
1573b6c3722Schristos }
1583b6c3722Schristos lock_basic_unlock(&ctx->cfglock);
1593b6c3722Schristos q->node.key = &q->querynum;
1607cd94d69Schristos q->async = (cb != NULL || cb_event != NULL);
1613b6c3722Schristos q->cb = cb;
1627cd94d69Schristos q->cb_event = cb_event;
1633b6c3722Schristos q->cb_arg = cbarg;
1643b6c3722Schristos q->res = (struct ub_result*)calloc(1, sizeof(*q->res));
1653b6c3722Schristos if(!q->res) {
1663b6c3722Schristos free(q);
1673b6c3722Schristos return NULL;
1683b6c3722Schristos }
1693b6c3722Schristos q->res->qname = strdup(name);
1703b6c3722Schristos if(!q->res->qname) {
1713b6c3722Schristos free(q->res);
1723b6c3722Schristos free(q);
1733b6c3722Schristos return NULL;
1743b6c3722Schristos }
1753b6c3722Schristos q->res->qtype = rrtype;
1763b6c3722Schristos q->res->qclass = rrclass;
1773b6c3722Schristos
1783b6c3722Schristos /* add to query list */
1793b6c3722Schristos lock_basic_lock(&ctx->cfglock);
1803b6c3722Schristos if(q->async)
1813b6c3722Schristos ctx->num_async ++;
1823b6c3722Schristos (void)rbtree_insert(&ctx->queries, &q->node);
1833b6c3722Schristos lock_basic_unlock(&ctx->cfglock);
1843b6c3722Schristos return q;
1853b6c3722Schristos }
1863b6c3722Schristos
1873b6c3722Schristos struct alloc_cache*
context_obtain_alloc(struct ub_ctx * ctx,int locking)1883b6c3722Schristos context_obtain_alloc(struct ub_ctx* ctx, int locking)
1893b6c3722Schristos {
1903b6c3722Schristos struct alloc_cache* a;
1913b6c3722Schristos int tnum = 0;
1923b6c3722Schristos if(locking) {
1933b6c3722Schristos lock_basic_lock(&ctx->cfglock);
1943b6c3722Schristos }
1953b6c3722Schristos a = ctx->alloc_list;
1963b6c3722Schristos if(a)
1973b6c3722Schristos ctx->alloc_list = a->super; /* snip off list */
1983b6c3722Schristos else tnum = ctx->thr_next_num++;
1993b6c3722Schristos if(locking) {
2003b6c3722Schristos lock_basic_unlock(&ctx->cfglock);
2013b6c3722Schristos }
2023b6c3722Schristos if(a) {
2033b6c3722Schristos a->super = &ctx->superalloc;
2043b6c3722Schristos return a;
2053b6c3722Schristos }
2063b6c3722Schristos a = (struct alloc_cache*)calloc(1, sizeof(*a));
2073b6c3722Schristos if(!a)
2083b6c3722Schristos return NULL;
2093b6c3722Schristos alloc_init(a, &ctx->superalloc, tnum);
2103b6c3722Schristos return a;
2113b6c3722Schristos }
2123b6c3722Schristos
2133b6c3722Schristos void
context_release_alloc(struct ub_ctx * ctx,struct alloc_cache * alloc,int locking)2143b6c3722Schristos context_release_alloc(struct ub_ctx* ctx, struct alloc_cache* alloc,
2153b6c3722Schristos int locking)
2163b6c3722Schristos {
2173b6c3722Schristos if(!ctx || !alloc)
2183b6c3722Schristos return;
2193b6c3722Schristos if(locking) {
2203b6c3722Schristos lock_basic_lock(&ctx->cfglock);
2213b6c3722Schristos }
2223b6c3722Schristos alloc->super = ctx->alloc_list;
2233b6c3722Schristos ctx->alloc_list = alloc;
2243b6c3722Schristos if(locking) {
2253b6c3722Schristos lock_basic_unlock(&ctx->cfglock);
2263b6c3722Schristos }
2273b6c3722Schristos }
2283b6c3722Schristos
2293b6c3722Schristos uint8_t*
context_serialize_new_query(struct ctx_query * q,uint32_t * len)2303b6c3722Schristos context_serialize_new_query(struct ctx_query* q, uint32_t* len)
2313b6c3722Schristos {
2323b6c3722Schristos /* format for new query is
2333b6c3722Schristos * o uint32 cmd
2343b6c3722Schristos * o uint32 id
2353b6c3722Schristos * o uint32 type
2363b6c3722Schristos * o uint32 class
2373b6c3722Schristos * o rest queryname (string)
2383b6c3722Schristos */
2393b6c3722Schristos uint8_t* p;
2403b6c3722Schristos size_t slen = strlen(q->res->qname) + 1/*end of string*/;
2413b6c3722Schristos *len = sizeof(uint32_t)*4 + slen;
2423b6c3722Schristos p = (uint8_t*)malloc(*len);
2433b6c3722Schristos if(!p) return NULL;
2443b6c3722Schristos sldns_write_uint32(p, UB_LIBCMD_NEWQUERY);
2453b6c3722Schristos sldns_write_uint32(p+sizeof(uint32_t), (uint32_t)q->querynum);
2463b6c3722Schristos sldns_write_uint32(p+2*sizeof(uint32_t), (uint32_t)q->res->qtype);
2473b6c3722Schristos sldns_write_uint32(p+3*sizeof(uint32_t), (uint32_t)q->res->qclass);
2483b6c3722Schristos memmove(p+4*sizeof(uint32_t), q->res->qname, slen);
2493b6c3722Schristos return p;
2503b6c3722Schristos }
2513b6c3722Schristos
2523b6c3722Schristos struct ctx_query*
context_deserialize_new_query(struct ub_ctx * ctx,uint8_t * p,uint32_t len)2533b6c3722Schristos context_deserialize_new_query(struct ub_ctx* ctx, uint8_t* p, uint32_t len)
2543b6c3722Schristos {
2553b6c3722Schristos struct ctx_query* q = (struct ctx_query*)calloc(1, sizeof(*q));
2563b6c3722Schristos if(!q) return NULL;
2573b6c3722Schristos if(len < 4*sizeof(uint32_t)+1) {
2583b6c3722Schristos free(q);
2593b6c3722Schristos return NULL;
2603b6c3722Schristos }
2613b6c3722Schristos log_assert( sldns_read_uint32(p) == UB_LIBCMD_NEWQUERY);
2623b6c3722Schristos q->querynum = (int)sldns_read_uint32(p+sizeof(uint32_t));
2633b6c3722Schristos q->node.key = &q->querynum;
2643b6c3722Schristos q->async = 1;
2653b6c3722Schristos q->res = (struct ub_result*)calloc(1, sizeof(*q->res));
2663b6c3722Schristos if(!q->res) {
2673b6c3722Schristos free(q);
2683b6c3722Schristos return NULL;
2693b6c3722Schristos }
2703b6c3722Schristos q->res->qtype = (int)sldns_read_uint32(p+2*sizeof(uint32_t));
2713b6c3722Schristos q->res->qclass = (int)sldns_read_uint32(p+3*sizeof(uint32_t));
2723b6c3722Schristos q->res->qname = strdup((char*)(p+4*sizeof(uint32_t)));
2733b6c3722Schristos if(!q->res->qname) {
2743b6c3722Schristos free(q->res);
2753b6c3722Schristos free(q);
2763b6c3722Schristos return NULL;
2773b6c3722Schristos }
2783b6c3722Schristos
2793b6c3722Schristos /** add to query list */
2803b6c3722Schristos ctx->num_async++;
2813b6c3722Schristos (void)rbtree_insert(&ctx->queries, &q->node);
2823b6c3722Schristos return q;
2833b6c3722Schristos }
2843b6c3722Schristos
2853b6c3722Schristos struct ctx_query*
context_lookup_new_query(struct ub_ctx * ctx,uint8_t * p,uint32_t len)2863b6c3722Schristos context_lookup_new_query(struct ub_ctx* ctx, uint8_t* p, uint32_t len)
2873b6c3722Schristos {
2883b6c3722Schristos struct ctx_query* q;
2893b6c3722Schristos int querynum;
2903b6c3722Schristos if(len < 4*sizeof(uint32_t)+1) {
2913b6c3722Schristos return NULL;
2923b6c3722Schristos }
2933b6c3722Schristos log_assert( sldns_read_uint32(p) == UB_LIBCMD_NEWQUERY);
2943b6c3722Schristos querynum = (int)sldns_read_uint32(p+sizeof(uint32_t));
2953b6c3722Schristos q = (struct ctx_query*)rbtree_search(&ctx->queries, &querynum);
2963b6c3722Schristos if(!q) {
2973b6c3722Schristos return NULL;
2983b6c3722Schristos }
2993b6c3722Schristos log_assert(q->async);
3003b6c3722Schristos return q;
3013b6c3722Schristos }
3023b6c3722Schristos
3033b6c3722Schristos uint8_t*
context_serialize_answer(struct ctx_query * q,int err,sldns_buffer * pkt,uint32_t * len)3043b6c3722Schristos context_serialize_answer(struct ctx_query* q, int err, sldns_buffer* pkt,
3053b6c3722Schristos uint32_t* len)
3063b6c3722Schristos {
3073b6c3722Schristos /* answer format
3083b6c3722Schristos * o uint32 cmd
3093b6c3722Schristos * o uint32 id
3103b6c3722Schristos * o uint32 error_code
3113b6c3722Schristos * o uint32 msg_security
312f42d8de7Schristos * o uint32 was_ratelimited
3133b6c3722Schristos * o uint32 length of why_bogus string (+1 for eos); 0 absent.
3143b6c3722Schristos * o why_bogus_string
3153b6c3722Schristos * o the remainder is the answer msg from resolver lookup.
3163b6c3722Schristos * remainder can be length 0.
3173b6c3722Schristos */
318f42d8de7Schristos size_t size_of_uint32s = 6 * sizeof(uint32_t);
3193b6c3722Schristos size_t pkt_len = pkt?sldns_buffer_remaining(pkt):0;
3203b6c3722Schristos size_t wlen = (pkt&&q->res->why_bogus)?strlen(q->res->why_bogus)+1:0;
3213b6c3722Schristos uint8_t* p;
322f42d8de7Schristos *len = size_of_uint32s + pkt_len + wlen;
3233b6c3722Schristos p = (uint8_t*)malloc(*len);
3243b6c3722Schristos if(!p) return NULL;
3253b6c3722Schristos sldns_write_uint32(p, UB_LIBCMD_ANSWER);
3263b6c3722Schristos sldns_write_uint32(p+sizeof(uint32_t), (uint32_t)q->querynum);
3273b6c3722Schristos sldns_write_uint32(p+2*sizeof(uint32_t), (uint32_t)err);
3283b6c3722Schristos sldns_write_uint32(p+3*sizeof(uint32_t), (uint32_t)q->msg_security);
329f42d8de7Schristos sldns_write_uint32(p+4*sizeof(uint32_t), (uint32_t)q->res->was_ratelimited);
330f42d8de7Schristos sldns_write_uint32(p+5*sizeof(uint32_t), (uint32_t)wlen);
3313b6c3722Schristos if(wlen > 0)
332f42d8de7Schristos memmove(p+size_of_uint32s, q->res->why_bogus, wlen);
3333b6c3722Schristos if(pkt_len > 0)
334f42d8de7Schristos memmove(p+size_of_uint32s+wlen,
3353b6c3722Schristos sldns_buffer_begin(pkt), pkt_len);
3363b6c3722Schristos return p;
3373b6c3722Schristos }
3383b6c3722Schristos
3393b6c3722Schristos struct ctx_query*
context_deserialize_answer(struct ub_ctx * ctx,uint8_t * p,uint32_t len,int * err)3403b6c3722Schristos context_deserialize_answer(struct ub_ctx* ctx,
3413b6c3722Schristos uint8_t* p, uint32_t len, int* err)
3423b6c3722Schristos {
343f42d8de7Schristos size_t size_of_uint32s = 6 * sizeof(uint32_t);
3443b6c3722Schristos struct ctx_query* q = NULL ;
3453b6c3722Schristos int id;
3463b6c3722Schristos size_t wlen;
347f42d8de7Schristos if(len < size_of_uint32s) return NULL;
3483b6c3722Schristos log_assert( sldns_read_uint32(p) == UB_LIBCMD_ANSWER);
3493b6c3722Schristos id = (int)sldns_read_uint32(p+sizeof(uint32_t));
3503b6c3722Schristos q = (struct ctx_query*)rbtree_search(&ctx->queries, &id);
3513b6c3722Schristos if(!q) return NULL;
3523b6c3722Schristos *err = (int)sldns_read_uint32(p+2*sizeof(uint32_t));
3533b6c3722Schristos q->msg_security = sldns_read_uint32(p+3*sizeof(uint32_t));
354f42d8de7Schristos q->res->was_ratelimited = (int)sldns_read_uint32(p+4*sizeof(uint32_t));
355f42d8de7Schristos wlen = (size_t)sldns_read_uint32(p+5*sizeof(uint32_t));
356f42d8de7Schristos if(len > size_of_uint32s && wlen > 0) {
357f42d8de7Schristos if(len >= size_of_uint32s+wlen)
3583b6c3722Schristos q->res->why_bogus = (char*)memdup(
359f42d8de7Schristos p+size_of_uint32s, wlen);
3603b6c3722Schristos if(!q->res->why_bogus) {
3613b6c3722Schristos /* pass malloc failure to the user callback */
3623b6c3722Schristos q->msg_len = 0;
3633b6c3722Schristos *err = UB_NOMEM;
3643b6c3722Schristos return q;
3653b6c3722Schristos }
3663b6c3722Schristos q->res->why_bogus[wlen-1] = 0; /* zero terminated for sure */
3673b6c3722Schristos }
368f42d8de7Schristos if(len > size_of_uint32s+wlen) {
369f42d8de7Schristos q->msg_len = len - size_of_uint32s - wlen;
370f42d8de7Schristos q->msg = (uint8_t*)memdup(p+size_of_uint32s+wlen,
3713b6c3722Schristos q->msg_len);
3723b6c3722Schristos if(!q->msg) {
3733b6c3722Schristos /* pass malloc failure to the user callback */
3743b6c3722Schristos q->msg_len = 0;
3753b6c3722Schristos *err = UB_NOMEM;
3763b6c3722Schristos return q;
3773b6c3722Schristos }
3783b6c3722Schristos }
3793b6c3722Schristos return q;
3803b6c3722Schristos }
3813b6c3722Schristos
3823b6c3722Schristos uint8_t*
context_serialize_cancel(struct ctx_query * q,uint32_t * len)3833b6c3722Schristos context_serialize_cancel(struct ctx_query* q, uint32_t* len)
3843b6c3722Schristos {
3853b6c3722Schristos /* format of cancel:
3863b6c3722Schristos * o uint32 cmd
3873b6c3722Schristos * o uint32 async-id */
3883b6c3722Schristos uint8_t* p = (uint8_t*)reallocarray(NULL, sizeof(uint32_t), 2);
3893b6c3722Schristos if(!p) return NULL;
3903b6c3722Schristos *len = 2*sizeof(uint32_t);
3913b6c3722Schristos sldns_write_uint32(p, UB_LIBCMD_CANCEL);
3923b6c3722Schristos sldns_write_uint32(p+sizeof(uint32_t), (uint32_t)q->querynum);
3933b6c3722Schristos return p;
3943b6c3722Schristos }
3953b6c3722Schristos
context_deserialize_cancel(struct ub_ctx * ctx,uint8_t * p,uint32_t len)3963b6c3722Schristos struct ctx_query* context_deserialize_cancel(struct ub_ctx* ctx,
3973b6c3722Schristos uint8_t* p, uint32_t len)
3983b6c3722Schristos {
3993b6c3722Schristos struct ctx_query* q;
4003b6c3722Schristos int id;
4013b6c3722Schristos if(len != 2*sizeof(uint32_t)) return NULL;
4023b6c3722Schristos log_assert( sldns_read_uint32(p) == UB_LIBCMD_CANCEL);
4033b6c3722Schristos id = (int)sldns_read_uint32(p+sizeof(uint32_t));
4043b6c3722Schristos q = (struct ctx_query*)rbtree_search(&ctx->queries, &id);
4053b6c3722Schristos return q;
4063b6c3722Schristos }
4073b6c3722Schristos
4083b6c3722Schristos uint8_t*
context_serialize_quit(uint32_t * len)4093b6c3722Schristos context_serialize_quit(uint32_t* len)
4103b6c3722Schristos {
411f42d8de7Schristos uint32_t* p = (uint32_t*)malloc(sizeof(uint32_t));
4123b6c3722Schristos if(!p)
4133b6c3722Schristos return NULL;
4143b6c3722Schristos *len = sizeof(uint32_t);
4153b6c3722Schristos sldns_write_uint32(p, UB_LIBCMD_QUIT);
416f42d8de7Schristos return (uint8_t*)p;
4173b6c3722Schristos }
4183b6c3722Schristos
context_serial_getcmd(uint8_t * p,uint32_t len)4193b6c3722Schristos enum ub_ctx_cmd context_serial_getcmd(uint8_t* p, uint32_t len)
4203b6c3722Schristos {
4213b6c3722Schristos uint32_t v;
4223b6c3722Schristos if((size_t)len < sizeof(v))
4233b6c3722Schristos return UB_LIBCMD_QUIT;
4243b6c3722Schristos v = sldns_read_uint32(p);
4253b6c3722Schristos return v;
4263b6c3722Schristos }
427