1238106Sdes/* 2238106Sdes * libunbound/context.h - validating context for unbound internal use 3238106Sdes * 4238106Sdes * Copyright (c) 2007, NLnet Labs. All rights reserved. 5238106Sdes * 6238106Sdes * This software is open source. 7238106Sdes * 8238106Sdes * Redistribution and use in source and binary forms, with or without 9238106Sdes * modification, are permitted provided that the following conditions 10238106Sdes * are met: 11238106Sdes * 12238106Sdes * Redistributions of source code must retain the above copyright notice, 13238106Sdes * this list of conditions and the following disclaimer. 14238106Sdes * 15238106Sdes * Redistributions in binary form must reproduce the above copyright notice, 16238106Sdes * this list of conditions and the following disclaimer in the documentation 17238106Sdes * and/or other materials provided with the distribution. 18238106Sdes * 19238106Sdes * Neither the name of the NLNET LABS nor the names of its contributors may 20238106Sdes * be used to endorse or promote products derived from this software without 21238106Sdes * specific prior written permission. 22238106Sdes * 23238106Sdes * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24266114Sdes * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25266114Sdes * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26266114Sdes * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27266114Sdes * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28266114Sdes * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29266114Sdes * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30266114Sdes * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31266114Sdes * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32266114Sdes * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33266114Sdes * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34238106Sdes */ 35238106Sdes 36238106Sdes/** 37238106Sdes * \file 38238106Sdes * 39238106Sdes * This file contains the validator context structure. 40238106Sdes */ 41238106Sdes#ifndef LIBUNBOUND_CONTEXT_H 42238106Sdes#define LIBUNBOUND_CONTEXT_H 43238106Sdes#include "util/locks.h" 44238106Sdes#include "util/alloc.h" 45238106Sdes#include "util/rbtree.h" 46238106Sdes#include "services/modstack.h" 47238106Sdes#include "libunbound/unbound.h" 48356345Scy#include "libunbound/unbound-event.h" 49238106Sdes#include "util/data/packed_rrset.h" 50238106Sdesstruct libworker; 51238106Sdesstruct tube; 52266114Sdesstruct sldns_buffer; 53307729Sdesstruct ub_event_base; 54238106Sdes 55356345Scy/** store that the logfile has a debug override */ 56356345Scyextern int ctx_logfile_overridden; 57356345Scy 58238106Sdes/** 59238106Sdes * The context structure 60238106Sdes * 61238106Sdes * Contains two pipes for async service 62238106Sdes * qq : write queries to the async service pid/tid. 63238106Sdes * rr : read results from the async service pid/tid. 64238106Sdes */ 65238106Sdesstruct ub_ctx { 66238106Sdes /* --- pipes --- */ 67238106Sdes /** mutex on query write pipe */ 68356345Scy lock_basic_type qqpipe_lock; 69238106Sdes /** the query write pipe */ 70238106Sdes struct tube* qq_pipe; 71238106Sdes /** mutex on result read pipe */ 72356345Scy lock_basic_type rrpipe_lock; 73238106Sdes /** the result read pipe */ 74238106Sdes struct tube* rr_pipe; 75238106Sdes 76238106Sdes /* --- shared data --- */ 77238106Sdes /** mutex for access to env.cfg, finalized and dothread */ 78356345Scy lock_basic_type cfglock; 79238106Sdes /** 80238106Sdes * The context has been finalized 81238106Sdes * This is after config when the first resolve is done. 82238106Sdes * The modules are inited (module-init()) and shared caches created. 83238106Sdes */ 84238106Sdes int finalized; 85238106Sdes 86238106Sdes /** is bg worker created yet ? */ 87238106Sdes int created_bg; 88238106Sdes /** pid of bg worker process */ 89238106Sdes pid_t bg_pid; 90238106Sdes /** tid of bg worker thread */ 91356345Scy ub_thread_type bg_tid; 92238106Sdes 93238106Sdes /** do threading (instead of forking) for async resolution */ 94238106Sdes int dothread; 95238106Sdes /** next thread number for new threads */ 96238106Sdes int thr_next_num; 97356345Scy /** if logfile is overridden */ 98238106Sdes int logfile_override; 99238106Sdes /** what logfile to use instead */ 100238106Sdes FILE* log_out; 101238106Sdes /** 102238106Sdes * List of alloc-cache-id points per threadnum for notinuse threads. 103238106Sdes * Simply the entire struct alloc_cache with the 'super' member used 104238106Sdes * to link a simply linked list. Reset super member to the superalloc 105238106Sdes * before use. 106238106Sdes */ 107238106Sdes struct alloc_cache* alloc_list; 108238106Sdes 109238106Sdes /** shared caches, and so on */ 110238106Sdes struct alloc_cache superalloc; 111238106Sdes /** module env master value */ 112238106Sdes struct module_env* env; 113238106Sdes /** module stack */ 114238106Sdes struct module_stack mods; 115238106Sdes /** local authority zones */ 116238106Sdes struct local_zones* local_zones; 117238106Sdes /** random state used to seed new random state structures */ 118238106Sdes struct ub_randstate* seed_rnd; 119238106Sdes 120266114Sdes /** event base for event oriented interface */ 121307729Sdes struct ub_event_base* event_base; 122356345Scy /** true if the event_base is a pluggable base that is malloced 123356345Scy * with a user event base inside, if so, clean up the pluggable alloc*/ 124356345Scy int event_base_malloced; 125266114Sdes /** libworker for event based interface */ 126266114Sdes struct libworker* event_worker; 127266114Sdes 128238106Sdes /** next query number (to try) to use */ 129238106Sdes int next_querynum; 130238106Sdes /** number of async queries outstanding */ 131238106Sdes size_t num_async; 132238106Sdes /** 133238106Sdes * Tree of outstanding queries. Indexed by querynum 134238106Sdes * Used when results come in for async to lookup. 135238106Sdes * Used when cancel is done for lookup (and delete). 136238106Sdes * Used to see if querynum is free for use. 137238106Sdes * Content of type ctx_query. 138238106Sdes */ 139356345Scy rbtree_type queries; 140238106Sdes}; 141238106Sdes 142238106Sdes/** 143238106Sdes * The queries outstanding for the libunbound resolver. 144238106Sdes * These are outstanding for async resolution. 145238106Sdes * But also, outstanding for sync resolution by one of the threads that 146238106Sdes * has joined the threadpool. 147238106Sdes */ 148238106Sdesstruct ctx_query { 149238106Sdes /** node in rbtree, must be first entry, key is ptr to the querynum */ 150356345Scy struct rbnode_type node; 151238106Sdes /** query id number, key for node */ 152238106Sdes int querynum; 153238106Sdes /** was this an async query? */ 154238106Sdes int async; 155238106Sdes /** was this query cancelled (for bg worker) */ 156238106Sdes int cancelled; 157238106Sdes 158356345Scy /** for async query, the callback function of type ub_callback_type */ 159356345Scy ub_callback_type cb; 160356345Scy /** for event callbacks the type is ub_event_callback_type */ 161356345Scy ub_event_callback_type cb_event; 162238106Sdes /** for async query, the callback user arg */ 163238106Sdes void* cb_arg; 164238106Sdes 165238106Sdes /** answer message, result from resolver lookup. */ 166238106Sdes uint8_t* msg; 167238106Sdes /** resulting message length. */ 168238106Sdes size_t msg_len; 169238106Sdes /** validation status on security */ 170238106Sdes enum sec_status msg_security; 171238106Sdes /** store libworker that is handling this query */ 172238106Sdes struct libworker* w; 173238106Sdes 174238106Sdes /** result structure, also contains original query, type, class. 175238106Sdes * malloced ptr ready to hand to the client. */ 176238106Sdes struct ub_result* res; 177238106Sdes}; 178238106Sdes 179238106Sdes/** 180238106Sdes * The error constants 181238106Sdes */ 182238106Sdesenum ub_ctx_err { 183238106Sdes /** no error */ 184238106Sdes UB_NOERROR = 0, 185238106Sdes /** socket operation. Set to -1, so that if an error from _fd() is 186238106Sdes * passed (-1) it gives a socket error. */ 187238106Sdes UB_SOCKET = -1, 188238106Sdes /** alloc failure */ 189238106Sdes UB_NOMEM = -2, 190238106Sdes /** syntax error */ 191238106Sdes UB_SYNTAX = -3, 192238106Sdes /** DNS service failed */ 193238106Sdes UB_SERVFAIL = -4, 194238106Sdes /** fork() failed */ 195238106Sdes UB_FORKFAIL = -5, 196238106Sdes /** cfg change after finalize() */ 197238106Sdes UB_AFTERFINAL = -6, 198238106Sdes /** initialization failed (bad settings) */ 199238106Sdes UB_INITFAIL = -7, 200238106Sdes /** error in pipe communication with async bg worker */ 201238106Sdes UB_PIPE = -8, 202238106Sdes /** error reading from file (resolv.conf) */ 203238106Sdes UB_READFILE = -9, 204238106Sdes /** error async_id does not exist or result already been delivered */ 205238106Sdes UB_NOID = -10 206238106Sdes}; 207238106Sdes 208238106Sdes/** 209238106Sdes * Command codes for libunbound pipe. 210238106Sdes * 211238106Sdes * Serialization looks like this: 212238106Sdes * o length (of remainder) uint32. 213238106Sdes * o uint32 command code. 214238106Sdes * o per command format. 215238106Sdes */ 216238106Sdesenum ub_ctx_cmd { 217238106Sdes /** QUIT */ 218238106Sdes UB_LIBCMD_QUIT = 0, 219238106Sdes /** New query, sent to bg worker */ 220238106Sdes UB_LIBCMD_NEWQUERY, 221238106Sdes /** Cancel query, sent to bg worker */ 222238106Sdes UB_LIBCMD_CANCEL, 223238106Sdes /** Query result, originates from bg worker */ 224238106Sdes UB_LIBCMD_ANSWER 225238106Sdes}; 226238106Sdes 227238106Sdes/** 228238106Sdes * finalize a context. 229238106Sdes * @param ctx: context to finalize. creates shared data. 230238106Sdes * @return 0 if OK, or errcode. 231238106Sdes */ 232238106Sdesint context_finalize(struct ub_ctx* ctx); 233238106Sdes 234238106Sdes/** compare two ctx_query elements */ 235238106Sdesint context_query_cmp(const void* a, const void* b); 236238106Sdes 237238106Sdes/** 238238106Sdes * delete context query 239238106Sdes * @param q: query to delete, including message packet and prealloc result 240238106Sdes */ 241238106Sdesvoid context_query_delete(struct ctx_query* q); 242238106Sdes 243238106Sdes/** 244238106Sdes * Create new query in context, add to querynum list. 245238106Sdes * @param ctx: context 246238106Sdes * @param name: query name 247238106Sdes * @param rrtype: type 248238106Sdes * @param rrclass: class 249238106Sdes * @param cb: callback for async, or NULL for sync. 250356345Scy * @param cb_event: event callback for async, or NULL for sync. 251238106Sdes * @param cbarg: user arg for async queries. 252238106Sdes * @return new ctx_query or NULL for malloc failure. 253238106Sdes */ 254266114Sdesstruct ctx_query* context_new(struct ub_ctx* ctx, const char* name, int rrtype, 255356345Scy int rrclass, ub_callback_type cb, ub_event_callback_type cb_event, 256356345Scy void* cbarg); 257238106Sdes 258238106Sdes/** 259238106Sdes * Get a new alloc. Creates a new one or uses a cached one. 260238106Sdes * @param ctx: context 261238106Sdes * @param locking: if true, cfglock is locked while getting alloc. 262238106Sdes * @return an alloc, or NULL on mem error. 263238106Sdes */ 264238106Sdesstruct alloc_cache* context_obtain_alloc(struct ub_ctx* ctx, int locking); 265238106Sdes 266238106Sdes/** 267238106Sdes * Release an alloc. Puts it into the cache. 268238106Sdes * @param ctx: context 269238106Sdes * @param locking: if true, cfglock is locked while releasing alloc. 270238106Sdes * @param alloc: alloc to relinquish. 271238106Sdes */ 272238106Sdesvoid context_release_alloc(struct ub_ctx* ctx, struct alloc_cache* alloc, 273238106Sdes int locking); 274238106Sdes 275238106Sdes/** 276238106Sdes * Serialize a context query that questions data. 277238106Sdes * This serializes the query name, type, ... 278238106Sdes * As well as command code 'new_query'. 279238106Sdes * @param q: context query 280238106Sdes * @param len: the length of the allocation is returned. 281238106Sdes * @return: an alloc, or NULL on mem error. 282238106Sdes */ 283238106Sdesuint8_t* context_serialize_new_query(struct ctx_query* q, uint32_t* len); 284238106Sdes 285238106Sdes/** 286238106Sdes * Serialize a context_query result to hand back to user. 287238106Sdes * This serializes the query name, type, ..., and result. 288238106Sdes * As well as command code 'answer'. 289238106Sdes * @param q: context query 290238106Sdes * @param err: error code to pass to client. 291238106Sdes * @param pkt: the packet to add, can be NULL. 292238106Sdes * @param len: the length of the allocation is returned. 293238106Sdes * @return: an alloc, or NULL on mem error. 294238106Sdes */ 295238106Sdesuint8_t* context_serialize_answer(struct ctx_query* q, int err, 296266114Sdes struct sldns_buffer* pkt, uint32_t* len); 297238106Sdes 298238106Sdes/** 299238106Sdes * Serialize a query cancellation. Serializes query async id 300238106Sdes * as well as command code 'cancel' 301238106Sdes * @param q: context query 302238106Sdes * @param len: the length of the allocation is returned. 303238106Sdes * @return: an alloc, or NULL on mem error. 304238106Sdes */ 305238106Sdesuint8_t* context_serialize_cancel(struct ctx_query* q, uint32_t* len); 306238106Sdes 307238106Sdes/** 308238106Sdes * Serialize a 'quit' command. 309238106Sdes * @param len: the length of the allocation is returned. 310238106Sdes * @return: an alloc, or NULL on mem error. 311238106Sdes */ 312238106Sdesuint8_t* context_serialize_quit(uint32_t* len); 313238106Sdes 314238106Sdes/** 315238106Sdes * Obtain command code from serialized buffer 316238106Sdes * @param p: buffer serialized. 317238106Sdes * @param len: length of buffer. 318238106Sdes * @return command code or QUIT on error. 319238106Sdes */ 320238106Sdesenum ub_ctx_cmd context_serial_getcmd(uint8_t* p, uint32_t len); 321238106Sdes 322238106Sdes/** 323238106Sdes * Lookup query from new_query buffer. 324238106Sdes * @param ctx: context 325238106Sdes * @param p: buffer serialized. 326238106Sdes * @param len: length of buffer. 327238106Sdes * @return looked up ctx_query or NULL for malloc failure. 328238106Sdes */ 329238106Sdesstruct ctx_query* context_lookup_new_query(struct ub_ctx* ctx, 330238106Sdes uint8_t* p, uint32_t len); 331238106Sdes 332238106Sdes/** 333238106Sdes * Deserialize a new_query buffer. 334238106Sdes * @param ctx: context 335238106Sdes * @param p: buffer serialized. 336238106Sdes * @param len: length of buffer. 337238106Sdes * @return new ctx_query or NULL for malloc failure. 338238106Sdes */ 339238106Sdesstruct ctx_query* context_deserialize_new_query(struct ub_ctx* ctx, 340238106Sdes uint8_t* p, uint32_t len); 341238106Sdes 342238106Sdes/** 343238106Sdes * Deserialize an answer buffer. 344238106Sdes * @param ctx: context 345238106Sdes * @param p: buffer serialized. 346238106Sdes * @param len: length of buffer. 347238106Sdes * @param err: error code to be returned to client is passed. 348238106Sdes * @return ctx_query with answer added or NULL for malloc failure. 349238106Sdes */ 350238106Sdesstruct ctx_query* context_deserialize_answer(struct ub_ctx* ctx, 351238106Sdes uint8_t* p, uint32_t len, int* err); 352238106Sdes 353238106Sdes/** 354238106Sdes * Deserialize a cancel buffer. 355238106Sdes * @param ctx: context 356238106Sdes * @param p: buffer serialized. 357238106Sdes * @param len: length of buffer. 358238106Sdes * @return ctx_query to cancel or NULL for failure. 359238106Sdes */ 360238106Sdesstruct ctx_query* context_deserialize_cancel(struct ub_ctx* ctx, 361238106Sdes uint8_t* p, uint32_t len); 362238106Sdes 363238106Sdes#endif /* LIBUNBOUND_CONTEXT_H */ 364