1b7579f77SDag-Erling Smørgrav /* 2b7579f77SDag-Erling Smørgrav * libunbound/context.c - validating context for unbound internal use 3b7579f77SDag-Erling Smørgrav * 4b7579f77SDag-Erling Smørgrav * Copyright (c) 2007, NLnet Labs. All rights reserved. 5b7579f77SDag-Erling Smørgrav * 6b7579f77SDag-Erling Smørgrav * This software is open source. 7b7579f77SDag-Erling Smørgrav * 8b7579f77SDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without 9b7579f77SDag-Erling Smørgrav * modification, are permitted provided that the following conditions 10b7579f77SDag-Erling Smørgrav * are met: 11b7579f77SDag-Erling Smørgrav * 12b7579f77SDag-Erling Smørgrav * Redistributions of source code must retain the above copyright notice, 13b7579f77SDag-Erling Smørgrav * this list of conditions and the following disclaimer. 14b7579f77SDag-Erling Smørgrav * 15b7579f77SDag-Erling Smørgrav * Redistributions in binary form must reproduce the above copyright notice, 16b7579f77SDag-Erling Smørgrav * this list of conditions and the following disclaimer in the documentation 17b7579f77SDag-Erling Smørgrav * and/or other materials provided with the distribution. 18b7579f77SDag-Erling Smørgrav * 19b7579f77SDag-Erling Smørgrav * Neither the name of the NLNET LABS nor the names of its contributors may 20b7579f77SDag-Erling Smørgrav * be used to endorse or promote products derived from this software without 21b7579f77SDag-Erling Smørgrav * specific prior written permission. 22b7579f77SDag-Erling Smørgrav * 23b7579f77SDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2417d15b25SDag-Erling Smørgrav * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2517d15b25SDag-Erling Smørgrav * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2617d15b25SDag-Erling Smørgrav * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2717d15b25SDag-Erling Smørgrav * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2817d15b25SDag-Erling Smørgrav * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 2917d15b25SDag-Erling Smørgrav * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 3017d15b25SDag-Erling Smørgrav * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 3117d15b25SDag-Erling Smørgrav * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 3217d15b25SDag-Erling Smørgrav * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 3317d15b25SDag-Erling Smørgrav * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34b7579f77SDag-Erling Smørgrav */ 35b7579f77SDag-Erling Smørgrav 36b7579f77SDag-Erling Smørgrav /** 37b7579f77SDag-Erling Smørgrav * \file 38b7579f77SDag-Erling Smørgrav * 39b7579f77SDag-Erling Smørgrav * This file contains the validator context structure. 40b7579f77SDag-Erling Smørgrav */ 41b7579f77SDag-Erling Smørgrav #include "config.h" 42b7579f77SDag-Erling Smørgrav #include "libunbound/context.h" 43b7579f77SDag-Erling Smørgrav #include "util/module.h" 44b7579f77SDag-Erling Smørgrav #include "util/config_file.h" 45b7579f77SDag-Erling Smørgrav #include "util/net_help.h" 46b7579f77SDag-Erling Smørgrav #include "services/modstack.h" 47b7579f77SDag-Erling Smørgrav #include "services/localzone.h" 48b7579f77SDag-Erling Smørgrav #include "services/cache/rrset.h" 49b7579f77SDag-Erling Smørgrav #include "services/cache/infra.h" 5057bddd21SDag-Erling Smørgrav #include "services/authzone.h" 5124e36522SCy Schubert #include "services/listen_dnsport.h" 52b7579f77SDag-Erling Smørgrav #include "util/data/msgreply.h" 53b7579f77SDag-Erling Smørgrav #include "util/storage/slabhash.h" 54c0caa2e2SCy Schubert #include "util/edns.h" 5509a3aaf3SDag-Erling Smørgrav #include "sldns/sbuffer.h" 56335c7cdaSCy Schubert #include "iterator/iter_fwd.h" 57335c7cdaSCy Schubert #include "iterator/iter_hints.h" 58b7579f77SDag-Erling Smørgrav 59b7579f77SDag-Erling Smørgrav int 60b7579f77SDag-Erling Smørgrav context_finalize(struct ub_ctx* ctx) 61b7579f77SDag-Erling Smørgrav { 62091e9e46SCy Schubert int is_rpz = 0; 63b7579f77SDag-Erling Smørgrav struct config_file* cfg = ctx->env->cfg; 64b7579f77SDag-Erling Smørgrav verbosity = cfg->verbosity; 650eefd307SCy Schubert if(ctx_logfile_overridden && !ctx->logfile_override) { 660eefd307SCy Schubert log_file(NULL); /* clear that override */ 670eefd307SCy Schubert ctx_logfile_overridden = 0; 680eefd307SCy Schubert } 690eefd307SCy Schubert if(ctx->logfile_override) { 700eefd307SCy Schubert ctx_logfile_overridden = 1; 71b7579f77SDag-Erling Smørgrav log_file(ctx->log_out); 720eefd307SCy Schubert } else { 730eefd307SCy Schubert log_init(cfg->logfile, cfg->use_syslog, NULL); 740eefd307SCy Schubert } 751838dec3SCy Schubert ctx->pipe_pid = getpid(); 765469a995SCy Schubert cfg_apply_local_port_policy(cfg, 65536); 77b7579f77SDag-Erling Smørgrav config_apply(cfg); 7856850988SCy Schubert if(!modstack_call_startup(&ctx->mods, cfg->module_conf, ctx->env)) 7956850988SCy Schubert return UB_INITFAIL; 8056850988SCy Schubert if(!modstack_call_init(&ctx->mods, cfg->module_conf, ctx->env)) 81b7579f77SDag-Erling Smørgrav return UB_INITFAIL; 8224e36522SCy Schubert listen_setup_locks(); 83bc892140SDag-Erling Smørgrav log_edns_known_options(VERB_ALGO, ctx->env); 84b7579f77SDag-Erling Smørgrav ctx->local_zones = local_zones_create(); 85b7579f77SDag-Erling Smørgrav if(!ctx->local_zones) 86b7579f77SDag-Erling Smørgrav return UB_NOMEM; 87b7579f77SDag-Erling Smørgrav if(!local_zones_apply_cfg(ctx->local_zones, cfg)) 88b7579f77SDag-Erling Smørgrav return UB_INITFAIL; 895469a995SCy Schubert if(!auth_zones_apply_cfg(ctx->env->auth_zones, cfg, 1, &is_rpz, 905469a995SCy Schubert ctx->env, &ctx->mods)) 9157bddd21SDag-Erling Smørgrav return UB_INITFAIL; 92335c7cdaSCy Schubert if(!(ctx->env->fwds = forwards_create()) || 93335c7cdaSCy Schubert !forwards_apply_cfg(ctx->env->fwds, cfg)) 94335c7cdaSCy Schubert return UB_INITFAIL; 95335c7cdaSCy Schubert if(!(ctx->env->hints = hints_create()) || 96335c7cdaSCy Schubert !hints_apply_cfg(ctx->env->hints, cfg)) 97335c7cdaSCy Schubert return UB_INITFAIL; 98369c6923SCy Schubert if(!edns_strings_apply_cfg(ctx->env->edns_strings, cfg)) 99c0caa2e2SCy Schubert return UB_INITFAIL; 1004c75e3aaSDag-Erling Smørgrav if(!slabhash_is_size(ctx->env->msg_cache, cfg->msg_cache_size, 1014c75e3aaSDag-Erling Smørgrav cfg->msg_cache_slabs)) { 102b7579f77SDag-Erling Smørgrav slabhash_delete(ctx->env->msg_cache); 103b7579f77SDag-Erling Smørgrav ctx->env->msg_cache = slabhash_create(cfg->msg_cache_slabs, 104b7579f77SDag-Erling Smørgrav HASH_DEFAULT_STARTARRAY, cfg->msg_cache_size, 105b7579f77SDag-Erling Smørgrav msgreply_sizefunc, query_info_compare, 106b7579f77SDag-Erling Smørgrav query_entry_delete, reply_info_delete, NULL); 107b7579f77SDag-Erling Smørgrav if(!ctx->env->msg_cache) 108b7579f77SDag-Erling Smørgrav return UB_NOMEM; 109b7579f77SDag-Erling Smørgrav } 110b7579f77SDag-Erling Smørgrav ctx->env->rrset_cache = rrset_cache_adjust(ctx->env->rrset_cache, 111b7579f77SDag-Erling Smørgrav ctx->env->cfg, ctx->env->alloc); 112b7579f77SDag-Erling Smørgrav if(!ctx->env->rrset_cache) 113b7579f77SDag-Erling Smørgrav return UB_NOMEM; 114b7579f77SDag-Erling Smørgrav ctx->env->infra_cache = infra_adjust(ctx->env->infra_cache, cfg); 115b7579f77SDag-Erling Smørgrav if(!ctx->env->infra_cache) 116b7579f77SDag-Erling Smørgrav return UB_NOMEM; 117b7579f77SDag-Erling Smørgrav ctx->finalized = 1; 118b7579f77SDag-Erling Smørgrav return UB_NOERROR; 119b7579f77SDag-Erling Smørgrav } 120b7579f77SDag-Erling Smørgrav 121b7579f77SDag-Erling Smørgrav int context_query_cmp(const void* a, const void* b) 122b7579f77SDag-Erling Smørgrav { 123b7579f77SDag-Erling Smørgrav if( *(int*)a < *(int*)b ) 124b7579f77SDag-Erling Smørgrav return -1; 125b7579f77SDag-Erling Smørgrav if( *(int*)a > *(int*)b ) 126b7579f77SDag-Erling Smørgrav return 1; 127b7579f77SDag-Erling Smørgrav return 0; 128b7579f77SDag-Erling Smørgrav } 129b7579f77SDag-Erling Smørgrav 130b7579f77SDag-Erling Smørgrav void 131b7579f77SDag-Erling Smørgrav context_query_delete(struct ctx_query* q) 132b7579f77SDag-Erling Smørgrav { 133b7579f77SDag-Erling Smørgrav if(!q) return; 134b7579f77SDag-Erling Smørgrav ub_resolve_free(q->res); 135b7579f77SDag-Erling Smørgrav free(q->msg); 136b7579f77SDag-Erling Smørgrav free(q); 137b7579f77SDag-Erling Smørgrav } 138b7579f77SDag-Erling Smørgrav 139b7579f77SDag-Erling Smørgrav /** How many times to try to find an unused query-id-number for async */ 140b7579f77SDag-Erling Smørgrav #define NUM_ID_TRIES 100000 141b7579f77SDag-Erling Smørgrav /** find next useful id number of 0 on error */ 142b7579f77SDag-Erling Smørgrav static int 143b7579f77SDag-Erling Smørgrav find_id(struct ub_ctx* ctx, int* id) 144b7579f77SDag-Erling Smørgrav { 145b7579f77SDag-Erling Smørgrav size_t tries = 0; 146b7579f77SDag-Erling Smørgrav ctx->next_querynum++; 147b7579f77SDag-Erling Smørgrav while(rbtree_search(&ctx->queries, &ctx->next_querynum)) { 148b7579f77SDag-Erling Smørgrav ctx->next_querynum++; /* numerical wraparound is fine */ 149b7579f77SDag-Erling Smørgrav if(tries++ > NUM_ID_TRIES) 150b7579f77SDag-Erling Smørgrav return 0; 151b7579f77SDag-Erling Smørgrav } 152b7579f77SDag-Erling Smørgrav *id = ctx->next_querynum; 153b7579f77SDag-Erling Smørgrav return 1; 154b7579f77SDag-Erling Smørgrav } 155b7579f77SDag-Erling Smørgrav 156b7579f77SDag-Erling Smørgrav struct ctx_query* 1575d649f2dSDag-Erling Smørgrav context_new(struct ub_ctx* ctx, const char* name, int rrtype, int rrclass, 1583bd4df0aSDag-Erling Smørgrav ub_callback_type cb, ub_event_callback_type cb_event, void* cbarg) 159b7579f77SDag-Erling Smørgrav { 160b7579f77SDag-Erling Smørgrav struct ctx_query* q = (struct ctx_query*)calloc(1, sizeof(*q)); 161b7579f77SDag-Erling Smørgrav if(!q) return NULL; 162b7579f77SDag-Erling Smørgrav lock_basic_lock(&ctx->cfglock); 163b7579f77SDag-Erling Smørgrav if(!find_id(ctx, &q->querynum)) { 164b7579f77SDag-Erling Smørgrav lock_basic_unlock(&ctx->cfglock); 165b7579f77SDag-Erling Smørgrav free(q); 166b7579f77SDag-Erling Smørgrav return NULL; 167b7579f77SDag-Erling Smørgrav } 168b7579f77SDag-Erling Smørgrav lock_basic_unlock(&ctx->cfglock); 169b7579f77SDag-Erling Smørgrav q->node.key = &q->querynum; 1703bd4df0aSDag-Erling Smørgrav q->async = (cb != NULL || cb_event != NULL); 171b7579f77SDag-Erling Smørgrav q->cb = cb; 1723bd4df0aSDag-Erling Smørgrav q->cb_event = cb_event; 173b7579f77SDag-Erling Smørgrav q->cb_arg = cbarg; 174b7579f77SDag-Erling Smørgrav q->res = (struct ub_result*)calloc(1, sizeof(*q->res)); 175b7579f77SDag-Erling Smørgrav if(!q->res) { 176b7579f77SDag-Erling Smørgrav free(q); 177b7579f77SDag-Erling Smørgrav return NULL; 178b7579f77SDag-Erling Smørgrav } 179b7579f77SDag-Erling Smørgrav q->res->qname = strdup(name); 180b7579f77SDag-Erling Smørgrav if(!q->res->qname) { 181b7579f77SDag-Erling Smørgrav free(q->res); 182b7579f77SDag-Erling Smørgrav free(q); 183b7579f77SDag-Erling Smørgrav return NULL; 184b7579f77SDag-Erling Smørgrav } 185b7579f77SDag-Erling Smørgrav q->res->qtype = rrtype; 186b7579f77SDag-Erling Smørgrav q->res->qclass = rrclass; 187b7579f77SDag-Erling Smørgrav 188b7579f77SDag-Erling Smørgrav /* add to query list */ 189b7579f77SDag-Erling Smørgrav lock_basic_lock(&ctx->cfglock); 190b7579f77SDag-Erling Smørgrav if(q->async) 191b7579f77SDag-Erling Smørgrav ctx->num_async ++; 192b7579f77SDag-Erling Smørgrav (void)rbtree_insert(&ctx->queries, &q->node); 193b7579f77SDag-Erling Smørgrav lock_basic_unlock(&ctx->cfglock); 194b7579f77SDag-Erling Smørgrav return q; 195b7579f77SDag-Erling Smørgrav } 196b7579f77SDag-Erling Smørgrav 197b7579f77SDag-Erling Smørgrav struct alloc_cache* 198b7579f77SDag-Erling Smørgrav context_obtain_alloc(struct ub_ctx* ctx, int locking) 199b7579f77SDag-Erling Smørgrav { 200b7579f77SDag-Erling Smørgrav struct alloc_cache* a; 201b7579f77SDag-Erling Smørgrav int tnum = 0; 202b7579f77SDag-Erling Smørgrav if(locking) { 203b7579f77SDag-Erling Smørgrav lock_basic_lock(&ctx->cfglock); 204b7579f77SDag-Erling Smørgrav } 205b7579f77SDag-Erling Smørgrav a = ctx->alloc_list; 206b7579f77SDag-Erling Smørgrav if(a) 207b7579f77SDag-Erling Smørgrav ctx->alloc_list = a->super; /* snip off list */ 208b7579f77SDag-Erling Smørgrav else tnum = ctx->thr_next_num++; 209b7579f77SDag-Erling Smørgrav if(locking) { 210b7579f77SDag-Erling Smørgrav lock_basic_unlock(&ctx->cfglock); 211b7579f77SDag-Erling Smørgrav } 212b7579f77SDag-Erling Smørgrav if(a) { 213b7579f77SDag-Erling Smørgrav a->super = &ctx->superalloc; 214b7579f77SDag-Erling Smørgrav return a; 215b7579f77SDag-Erling Smørgrav } 216b7579f77SDag-Erling Smørgrav a = (struct alloc_cache*)calloc(1, sizeof(*a)); 217b7579f77SDag-Erling Smørgrav if(!a) 218b7579f77SDag-Erling Smørgrav return NULL; 219b7579f77SDag-Erling Smørgrav alloc_init(a, &ctx->superalloc, tnum); 220b7579f77SDag-Erling Smørgrav return a; 221b7579f77SDag-Erling Smørgrav } 222b7579f77SDag-Erling Smørgrav 223b7579f77SDag-Erling Smørgrav void 224b7579f77SDag-Erling Smørgrav context_release_alloc(struct ub_ctx* ctx, struct alloc_cache* alloc, 225b7579f77SDag-Erling Smørgrav int locking) 226b7579f77SDag-Erling Smørgrav { 227b7579f77SDag-Erling Smørgrav if(!ctx || !alloc) 228b7579f77SDag-Erling Smørgrav return; 229b7579f77SDag-Erling Smørgrav if(locking) { 230b7579f77SDag-Erling Smørgrav lock_basic_lock(&ctx->cfglock); 231b7579f77SDag-Erling Smørgrav } 232b7579f77SDag-Erling Smørgrav alloc->super = ctx->alloc_list; 233b7579f77SDag-Erling Smørgrav ctx->alloc_list = alloc; 234b7579f77SDag-Erling Smørgrav if(locking) { 235b7579f77SDag-Erling Smørgrav lock_basic_unlock(&ctx->cfglock); 236b7579f77SDag-Erling Smørgrav } 237b7579f77SDag-Erling Smørgrav } 238b7579f77SDag-Erling Smørgrav 239b7579f77SDag-Erling Smørgrav uint8_t* 240b7579f77SDag-Erling Smørgrav context_serialize_new_query(struct ctx_query* q, uint32_t* len) 241b7579f77SDag-Erling Smørgrav { 242b7579f77SDag-Erling Smørgrav /* format for new query is 243b7579f77SDag-Erling Smørgrav * o uint32 cmd 244b7579f77SDag-Erling Smørgrav * o uint32 id 245b7579f77SDag-Erling Smørgrav * o uint32 type 246b7579f77SDag-Erling Smørgrav * o uint32 class 247b7579f77SDag-Erling Smørgrav * o rest queryname (string) 248b7579f77SDag-Erling Smørgrav */ 249b7579f77SDag-Erling Smørgrav uint8_t* p; 250b7579f77SDag-Erling Smørgrav size_t slen = strlen(q->res->qname) + 1/*end of string*/; 251b7579f77SDag-Erling Smørgrav *len = sizeof(uint32_t)*4 + slen; 252b7579f77SDag-Erling Smørgrav p = (uint8_t*)malloc(*len); 253b7579f77SDag-Erling Smørgrav if(!p) return NULL; 25417d15b25SDag-Erling Smørgrav sldns_write_uint32(p, UB_LIBCMD_NEWQUERY); 25517d15b25SDag-Erling Smørgrav sldns_write_uint32(p+sizeof(uint32_t), (uint32_t)q->querynum); 25617d15b25SDag-Erling Smørgrav sldns_write_uint32(p+2*sizeof(uint32_t), (uint32_t)q->res->qtype); 25717d15b25SDag-Erling Smørgrav sldns_write_uint32(p+3*sizeof(uint32_t), (uint32_t)q->res->qclass); 258b7579f77SDag-Erling Smørgrav memmove(p+4*sizeof(uint32_t), q->res->qname, slen); 259b7579f77SDag-Erling Smørgrav return p; 260b7579f77SDag-Erling Smørgrav } 261b7579f77SDag-Erling Smørgrav 262b7579f77SDag-Erling Smørgrav struct ctx_query* 263b7579f77SDag-Erling Smørgrav context_deserialize_new_query(struct ub_ctx* ctx, uint8_t* p, uint32_t len) 264b7579f77SDag-Erling Smørgrav { 265b7579f77SDag-Erling Smørgrav struct ctx_query* q = (struct ctx_query*)calloc(1, sizeof(*q)); 266b7579f77SDag-Erling Smørgrav if(!q) return NULL; 267b7579f77SDag-Erling Smørgrav if(len < 4*sizeof(uint32_t)+1) { 268b7579f77SDag-Erling Smørgrav free(q); 269b7579f77SDag-Erling Smørgrav return NULL; 270b7579f77SDag-Erling Smørgrav } 27117d15b25SDag-Erling Smørgrav log_assert( sldns_read_uint32(p) == UB_LIBCMD_NEWQUERY); 27217d15b25SDag-Erling Smørgrav q->querynum = (int)sldns_read_uint32(p+sizeof(uint32_t)); 273b7579f77SDag-Erling Smørgrav q->node.key = &q->querynum; 274b7579f77SDag-Erling Smørgrav q->async = 1; 275b7579f77SDag-Erling Smørgrav q->res = (struct ub_result*)calloc(1, sizeof(*q->res)); 276b7579f77SDag-Erling Smørgrav if(!q->res) { 277b7579f77SDag-Erling Smørgrav free(q); 278b7579f77SDag-Erling Smørgrav return NULL; 279b7579f77SDag-Erling Smørgrav } 28017d15b25SDag-Erling Smørgrav q->res->qtype = (int)sldns_read_uint32(p+2*sizeof(uint32_t)); 28117d15b25SDag-Erling Smørgrav q->res->qclass = (int)sldns_read_uint32(p+3*sizeof(uint32_t)); 282b7579f77SDag-Erling Smørgrav q->res->qname = strdup((char*)(p+4*sizeof(uint32_t))); 283b7579f77SDag-Erling Smørgrav if(!q->res->qname) { 284b7579f77SDag-Erling Smørgrav free(q->res); 285b7579f77SDag-Erling Smørgrav free(q); 286b7579f77SDag-Erling Smørgrav return NULL; 287b7579f77SDag-Erling Smørgrav } 288b7579f77SDag-Erling Smørgrav 289b7579f77SDag-Erling Smørgrav /** add to query list */ 290b7579f77SDag-Erling Smørgrav ctx->num_async++; 291b7579f77SDag-Erling Smørgrav (void)rbtree_insert(&ctx->queries, &q->node); 292b7579f77SDag-Erling Smørgrav return q; 293b7579f77SDag-Erling Smørgrav } 294b7579f77SDag-Erling Smørgrav 295b7579f77SDag-Erling Smørgrav struct ctx_query* 296b7579f77SDag-Erling Smørgrav context_lookup_new_query(struct ub_ctx* ctx, uint8_t* p, uint32_t len) 297b7579f77SDag-Erling Smørgrav { 298b7579f77SDag-Erling Smørgrav struct ctx_query* q; 299b7579f77SDag-Erling Smørgrav int querynum; 300b7579f77SDag-Erling Smørgrav if(len < 4*sizeof(uint32_t)+1) { 301b7579f77SDag-Erling Smørgrav return NULL; 302b7579f77SDag-Erling Smørgrav } 30317d15b25SDag-Erling Smørgrav log_assert( sldns_read_uint32(p) == UB_LIBCMD_NEWQUERY); 30417d15b25SDag-Erling Smørgrav querynum = (int)sldns_read_uint32(p+sizeof(uint32_t)); 305b7579f77SDag-Erling Smørgrav q = (struct ctx_query*)rbtree_search(&ctx->queries, &querynum); 306b7579f77SDag-Erling Smørgrav if(!q) { 307b7579f77SDag-Erling Smørgrav return NULL; 308b7579f77SDag-Erling Smørgrav } 309b7579f77SDag-Erling Smørgrav log_assert(q->async); 310b7579f77SDag-Erling Smørgrav return q; 311b7579f77SDag-Erling Smørgrav } 312b7579f77SDag-Erling Smørgrav 313b7579f77SDag-Erling Smørgrav uint8_t* 31417d15b25SDag-Erling Smørgrav context_serialize_answer(struct ctx_query* q, int err, sldns_buffer* pkt, 315b7579f77SDag-Erling Smørgrav uint32_t* len) 316b7579f77SDag-Erling Smørgrav { 317b7579f77SDag-Erling Smørgrav /* answer format 318b7579f77SDag-Erling Smørgrav * o uint32 cmd 319b7579f77SDag-Erling Smørgrav * o uint32 id 320b7579f77SDag-Erling Smørgrav * o uint32 error_code 321b7579f77SDag-Erling Smørgrav * o uint32 msg_security 3224c75e3aaSDag-Erling Smørgrav * o uint32 was_ratelimited 323b7579f77SDag-Erling Smørgrav * o uint32 length of why_bogus string (+1 for eos); 0 absent. 324b7579f77SDag-Erling Smørgrav * o why_bogus_string 325b7579f77SDag-Erling Smørgrav * o the remainder is the answer msg from resolver lookup. 326b7579f77SDag-Erling Smørgrav * remainder can be length 0. 327b7579f77SDag-Erling Smørgrav */ 3284c75e3aaSDag-Erling Smørgrav size_t size_of_uint32s = 6 * sizeof(uint32_t); 32917d15b25SDag-Erling Smørgrav size_t pkt_len = pkt?sldns_buffer_remaining(pkt):0; 330b7579f77SDag-Erling Smørgrav size_t wlen = (pkt&&q->res->why_bogus)?strlen(q->res->why_bogus)+1:0; 331b7579f77SDag-Erling Smørgrav uint8_t* p; 3324c75e3aaSDag-Erling Smørgrav *len = size_of_uint32s + pkt_len + wlen; 333b7579f77SDag-Erling Smørgrav p = (uint8_t*)malloc(*len); 334b7579f77SDag-Erling Smørgrav if(!p) return NULL; 33517d15b25SDag-Erling Smørgrav sldns_write_uint32(p, UB_LIBCMD_ANSWER); 33617d15b25SDag-Erling Smørgrav sldns_write_uint32(p+sizeof(uint32_t), (uint32_t)q->querynum); 33717d15b25SDag-Erling Smørgrav sldns_write_uint32(p+2*sizeof(uint32_t), (uint32_t)err); 33817d15b25SDag-Erling Smørgrav sldns_write_uint32(p+3*sizeof(uint32_t), (uint32_t)q->msg_security); 3394c75e3aaSDag-Erling Smørgrav sldns_write_uint32(p+4*sizeof(uint32_t), (uint32_t)q->res->was_ratelimited); 3404c75e3aaSDag-Erling Smørgrav sldns_write_uint32(p+5*sizeof(uint32_t), (uint32_t)wlen); 341b7579f77SDag-Erling Smørgrav if(wlen > 0) 3424c75e3aaSDag-Erling Smørgrav memmove(p+size_of_uint32s, q->res->why_bogus, wlen); 343b7579f77SDag-Erling Smørgrav if(pkt_len > 0) 3444c75e3aaSDag-Erling Smørgrav memmove(p+size_of_uint32s+wlen, 34517d15b25SDag-Erling Smørgrav sldns_buffer_begin(pkt), pkt_len); 346b7579f77SDag-Erling Smørgrav return p; 347b7579f77SDag-Erling Smørgrav } 348b7579f77SDag-Erling Smørgrav 349b7579f77SDag-Erling Smørgrav struct ctx_query* 350b7579f77SDag-Erling Smørgrav context_deserialize_answer(struct ub_ctx* ctx, 351b7579f77SDag-Erling Smørgrav uint8_t* p, uint32_t len, int* err) 352b7579f77SDag-Erling Smørgrav { 3534c75e3aaSDag-Erling Smørgrav size_t size_of_uint32s = 6 * sizeof(uint32_t); 354b7579f77SDag-Erling Smørgrav struct ctx_query* q = NULL ; 355b7579f77SDag-Erling Smørgrav int id; 356b7579f77SDag-Erling Smørgrav size_t wlen; 3574c75e3aaSDag-Erling Smørgrav if(len < size_of_uint32s) return NULL; 35817d15b25SDag-Erling Smørgrav log_assert( sldns_read_uint32(p) == UB_LIBCMD_ANSWER); 35917d15b25SDag-Erling Smørgrav id = (int)sldns_read_uint32(p+sizeof(uint32_t)); 360b7579f77SDag-Erling Smørgrav q = (struct ctx_query*)rbtree_search(&ctx->queries, &id); 361b7579f77SDag-Erling Smørgrav if(!q) return NULL; 36217d15b25SDag-Erling Smørgrav *err = (int)sldns_read_uint32(p+2*sizeof(uint32_t)); 36317d15b25SDag-Erling Smørgrav q->msg_security = sldns_read_uint32(p+3*sizeof(uint32_t)); 3644c75e3aaSDag-Erling Smørgrav q->res->was_ratelimited = (int)sldns_read_uint32(p+4*sizeof(uint32_t)); 3654c75e3aaSDag-Erling Smørgrav wlen = (size_t)sldns_read_uint32(p+5*sizeof(uint32_t)); 3664c75e3aaSDag-Erling Smørgrav if(len > size_of_uint32s && wlen > 0) { 3674c75e3aaSDag-Erling Smørgrav if(len >= size_of_uint32s+wlen) 368b7579f77SDag-Erling Smørgrav q->res->why_bogus = (char*)memdup( 3694c75e3aaSDag-Erling Smørgrav p+size_of_uint32s, wlen); 370b7579f77SDag-Erling Smørgrav if(!q->res->why_bogus) { 371b7579f77SDag-Erling Smørgrav /* pass malloc failure to the user callback */ 372b7579f77SDag-Erling Smørgrav q->msg_len = 0; 373b7579f77SDag-Erling Smørgrav *err = UB_NOMEM; 374b7579f77SDag-Erling Smørgrav return q; 375b7579f77SDag-Erling Smørgrav } 376b7579f77SDag-Erling Smørgrav q->res->why_bogus[wlen-1] = 0; /* zero terminated for sure */ 377b7579f77SDag-Erling Smørgrav } 3784c75e3aaSDag-Erling Smørgrav if(len > size_of_uint32s+wlen) { 3794c75e3aaSDag-Erling Smørgrav q->msg_len = len - size_of_uint32s - wlen; 3804c75e3aaSDag-Erling Smørgrav q->msg = (uint8_t*)memdup(p+size_of_uint32s+wlen, 381b7579f77SDag-Erling Smørgrav q->msg_len); 382b7579f77SDag-Erling Smørgrav if(!q->msg) { 383b7579f77SDag-Erling Smørgrav /* pass malloc failure to the user callback */ 384b7579f77SDag-Erling Smørgrav q->msg_len = 0; 385b7579f77SDag-Erling Smørgrav *err = UB_NOMEM; 386b7579f77SDag-Erling Smørgrav return q; 387b7579f77SDag-Erling Smørgrav } 388b7579f77SDag-Erling Smørgrav } 389b7579f77SDag-Erling Smørgrav return q; 390b7579f77SDag-Erling Smørgrav } 391b7579f77SDag-Erling Smørgrav 392b7579f77SDag-Erling Smørgrav uint8_t* 393b7579f77SDag-Erling Smørgrav context_serialize_cancel(struct ctx_query* q, uint32_t* len) 394b7579f77SDag-Erling Smørgrav { 395b7579f77SDag-Erling Smørgrav /* format of cancel: 396b7579f77SDag-Erling Smørgrav * o uint32 cmd 397b7579f77SDag-Erling Smørgrav * o uint32 async-id */ 398*46d2f618SCy Schubert uint8_t* p = (uint8_t*)reallocarray(NULL, 2, sizeof(uint32_t)); 399b7579f77SDag-Erling Smørgrav if(!p) return NULL; 400b7579f77SDag-Erling Smørgrav *len = 2*sizeof(uint32_t); 40117d15b25SDag-Erling Smørgrav sldns_write_uint32(p, UB_LIBCMD_CANCEL); 40217d15b25SDag-Erling Smørgrav sldns_write_uint32(p+sizeof(uint32_t), (uint32_t)q->querynum); 403b7579f77SDag-Erling Smørgrav return p; 404b7579f77SDag-Erling Smørgrav } 405b7579f77SDag-Erling Smørgrav 406b7579f77SDag-Erling Smørgrav struct ctx_query* context_deserialize_cancel(struct ub_ctx* ctx, 407b7579f77SDag-Erling Smørgrav uint8_t* p, uint32_t len) 408b7579f77SDag-Erling Smørgrav { 409b7579f77SDag-Erling Smørgrav struct ctx_query* q; 410b7579f77SDag-Erling Smørgrav int id; 411b7579f77SDag-Erling Smørgrav if(len != 2*sizeof(uint32_t)) return NULL; 41217d15b25SDag-Erling Smørgrav log_assert( sldns_read_uint32(p) == UB_LIBCMD_CANCEL); 41317d15b25SDag-Erling Smørgrav id = (int)sldns_read_uint32(p+sizeof(uint32_t)); 414b7579f77SDag-Erling Smørgrav q = (struct ctx_query*)rbtree_search(&ctx->queries, &id); 415b7579f77SDag-Erling Smørgrav return q; 416b7579f77SDag-Erling Smørgrav } 417b7579f77SDag-Erling Smørgrav 418b7579f77SDag-Erling Smørgrav uint8_t* 419b7579f77SDag-Erling Smørgrav context_serialize_quit(uint32_t* len) 420b7579f77SDag-Erling Smørgrav { 421a755b6f6SDag-Erling Smørgrav uint32_t* p = (uint32_t*)malloc(sizeof(uint32_t)); 422b7579f77SDag-Erling Smørgrav if(!p) 423b7579f77SDag-Erling Smørgrav return NULL; 424b7579f77SDag-Erling Smørgrav *len = sizeof(uint32_t); 42517d15b25SDag-Erling Smørgrav sldns_write_uint32(p, UB_LIBCMD_QUIT); 426a755b6f6SDag-Erling Smørgrav return (uint8_t*)p; 427b7579f77SDag-Erling Smørgrav } 428b7579f77SDag-Erling Smørgrav 429b7579f77SDag-Erling Smørgrav enum ub_ctx_cmd context_serial_getcmd(uint8_t* p, uint32_t len) 430b7579f77SDag-Erling Smørgrav { 431b7579f77SDag-Erling Smørgrav uint32_t v; 432b7579f77SDag-Erling Smørgrav if((size_t)len < sizeof(v)) 433b7579f77SDag-Erling Smørgrav return UB_LIBCMD_QUIT; 43417d15b25SDag-Erling Smørgrav v = sldns_read_uint32(p); 435b7579f77SDag-Erling Smørgrav return v; 436b7579f77SDag-Erling Smørgrav } 437