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 24238106Sdes * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 25238106Sdes * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26238106Sdes * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 27238106Sdes * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28238106Sdes * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29238106Sdes * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 30238106Sdes * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 31238106Sdes * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32238106Sdes * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33238106Sdes * 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" 48238106Sdes#include "util/data/packed_rrset.h" 49238106Sdesstruct libworker; 50238106Sdesstruct tube; 51238106Sdes 52238106Sdes/** 53238106Sdes * The context structure 54238106Sdes * 55238106Sdes * Contains two pipes for async service 56238106Sdes * qq : write queries to the async service pid/tid. 57238106Sdes * rr : read results from the async service pid/tid. 58238106Sdes */ 59238106Sdesstruct ub_ctx { 60238106Sdes /* --- pipes --- */ 61238106Sdes /** mutex on query write pipe */ 62238106Sdes lock_basic_t qqpipe_lock; 63238106Sdes /** the query write pipe */ 64238106Sdes struct tube* qq_pipe; 65238106Sdes /** mutex on result read pipe */ 66238106Sdes lock_basic_t rrpipe_lock; 67238106Sdes /** the result read pipe */ 68238106Sdes struct tube* rr_pipe; 69238106Sdes 70238106Sdes /* --- shared data --- */ 71238106Sdes /** mutex for access to env.cfg, finalized and dothread */ 72238106Sdes lock_basic_t cfglock; 73238106Sdes /** 74238106Sdes * The context has been finalized 75238106Sdes * This is after config when the first resolve is done. 76238106Sdes * The modules are inited (module-init()) and shared caches created. 77238106Sdes */ 78238106Sdes int finalized; 79238106Sdes 80238106Sdes /** is bg worker created yet ? */ 81238106Sdes int created_bg; 82238106Sdes /** pid of bg worker process */ 83238106Sdes pid_t bg_pid; 84238106Sdes /** tid of bg worker thread */ 85238106Sdes ub_thread_t bg_tid; 86238106Sdes 87238106Sdes /** do threading (instead of forking) for async resolution */ 88238106Sdes int dothread; 89238106Sdes /** next thread number for new threads */ 90238106Sdes int thr_next_num; 91238106Sdes /** if logfile is overriden */ 92238106Sdes int logfile_override; 93238106Sdes /** what logfile to use instead */ 94238106Sdes FILE* log_out; 95238106Sdes /** 96238106Sdes * List of alloc-cache-id points per threadnum for notinuse threads. 97238106Sdes * Simply the entire struct alloc_cache with the 'super' member used 98238106Sdes * to link a simply linked list. Reset super member to the superalloc 99238106Sdes * before use. 100238106Sdes */ 101238106Sdes struct alloc_cache* alloc_list; 102238106Sdes 103238106Sdes /** shared caches, and so on */ 104238106Sdes struct alloc_cache superalloc; 105238106Sdes /** module env master value */ 106238106Sdes struct module_env* env; 107238106Sdes /** module stack */ 108238106Sdes struct module_stack mods; 109238106Sdes /** local authority zones */ 110238106Sdes struct local_zones* local_zones; 111238106Sdes /** random state used to seed new random state structures */ 112238106Sdes struct ub_randstate* seed_rnd; 113238106Sdes 114238106Sdes /** next query number (to try) to use */ 115238106Sdes int next_querynum; 116238106Sdes /** number of async queries outstanding */ 117238106Sdes size_t num_async; 118238106Sdes /** 119238106Sdes * Tree of outstanding queries. Indexed by querynum 120238106Sdes * Used when results come in for async to lookup. 121238106Sdes * Used when cancel is done for lookup (and delete). 122238106Sdes * Used to see if querynum is free for use. 123238106Sdes * Content of type ctx_query. 124238106Sdes */ 125238106Sdes rbtree_t queries; 126238106Sdes}; 127238106Sdes 128238106Sdes/** 129238106Sdes * The queries outstanding for the libunbound resolver. 130238106Sdes * These are outstanding for async resolution. 131238106Sdes * But also, outstanding for sync resolution by one of the threads that 132238106Sdes * has joined the threadpool. 133238106Sdes */ 134238106Sdesstruct ctx_query { 135238106Sdes /** node in rbtree, must be first entry, key is ptr to the querynum */ 136238106Sdes struct rbnode_t node; 137238106Sdes /** query id number, key for node */ 138238106Sdes int querynum; 139238106Sdes /** was this an async query? */ 140238106Sdes int async; 141238106Sdes /** was this query cancelled (for bg worker) */ 142238106Sdes int cancelled; 143238106Sdes 144238106Sdes /** for async query, the callback function */ 145238106Sdes ub_callback_t cb; 146238106Sdes /** for async query, the callback user arg */ 147238106Sdes void* cb_arg; 148238106Sdes 149238106Sdes /** answer message, result from resolver lookup. */ 150238106Sdes uint8_t* msg; 151238106Sdes /** resulting message length. */ 152238106Sdes size_t msg_len; 153238106Sdes /** validation status on security */ 154238106Sdes enum sec_status msg_security; 155238106Sdes /** store libworker that is handling this query */ 156238106Sdes struct libworker* w; 157238106Sdes 158238106Sdes /** result structure, also contains original query, type, class. 159238106Sdes * malloced ptr ready to hand to the client. */ 160238106Sdes struct ub_result* res; 161238106Sdes}; 162238106Sdes 163238106Sdes/** 164238106Sdes * The error constants 165238106Sdes */ 166238106Sdesenum ub_ctx_err { 167238106Sdes /** no error */ 168238106Sdes UB_NOERROR = 0, 169238106Sdes /** socket operation. Set to -1, so that if an error from _fd() is 170238106Sdes * passed (-1) it gives a socket error. */ 171238106Sdes UB_SOCKET = -1, 172238106Sdes /** alloc failure */ 173238106Sdes UB_NOMEM = -2, 174238106Sdes /** syntax error */ 175238106Sdes UB_SYNTAX = -3, 176238106Sdes /** DNS service failed */ 177238106Sdes UB_SERVFAIL = -4, 178238106Sdes /** fork() failed */ 179238106Sdes UB_FORKFAIL = -5, 180238106Sdes /** cfg change after finalize() */ 181238106Sdes UB_AFTERFINAL = -6, 182238106Sdes /** initialization failed (bad settings) */ 183238106Sdes UB_INITFAIL = -7, 184238106Sdes /** error in pipe communication with async bg worker */ 185238106Sdes UB_PIPE = -8, 186238106Sdes /** error reading from file (resolv.conf) */ 187238106Sdes UB_READFILE = -9, 188238106Sdes /** error async_id does not exist or result already been delivered */ 189238106Sdes UB_NOID = -10 190238106Sdes}; 191238106Sdes 192238106Sdes/** 193238106Sdes * Command codes for libunbound pipe. 194238106Sdes * 195238106Sdes * Serialization looks like this: 196238106Sdes * o length (of remainder) uint32. 197238106Sdes * o uint32 command code. 198238106Sdes * o per command format. 199238106Sdes */ 200238106Sdesenum ub_ctx_cmd { 201238106Sdes /** QUIT */ 202238106Sdes UB_LIBCMD_QUIT = 0, 203238106Sdes /** New query, sent to bg worker */ 204238106Sdes UB_LIBCMD_NEWQUERY, 205238106Sdes /** Cancel query, sent to bg worker */ 206238106Sdes UB_LIBCMD_CANCEL, 207238106Sdes /** Query result, originates from bg worker */ 208238106Sdes UB_LIBCMD_ANSWER 209238106Sdes}; 210238106Sdes 211238106Sdes/** 212238106Sdes * finalize a context. 213238106Sdes * @param ctx: context to finalize. creates shared data. 214238106Sdes * @return 0 if OK, or errcode. 215238106Sdes */ 216238106Sdesint context_finalize(struct ub_ctx* ctx); 217238106Sdes 218238106Sdes/** compare two ctx_query elements */ 219238106Sdesint context_query_cmp(const void* a, const void* b); 220238106Sdes 221238106Sdes/** 222238106Sdes * delete context query 223238106Sdes * @param q: query to delete, including message packet and prealloc result 224238106Sdes */ 225238106Sdesvoid context_query_delete(struct ctx_query* q); 226238106Sdes 227238106Sdes/** 228238106Sdes * Create new query in context, add to querynum list. 229238106Sdes * @param ctx: context 230238106Sdes * @param name: query name 231238106Sdes * @param rrtype: type 232238106Sdes * @param rrclass: class 233238106Sdes * @param cb: callback for async, or NULL for sync. 234238106Sdes * @param cbarg: user arg for async queries. 235238106Sdes * @return new ctx_query or NULL for malloc failure. 236238106Sdes */ 237255584Sdesstruct ctx_query* context_new(struct ub_ctx* ctx, const char* name, 238255584Sdes int rrtype, int rrclass, ub_callback_t cb, void* cbarg); 239238106Sdes 240238106Sdes/** 241238106Sdes * Get a new alloc. Creates a new one or uses a cached one. 242238106Sdes * @param ctx: context 243238106Sdes * @param locking: if true, cfglock is locked while getting alloc. 244238106Sdes * @return an alloc, or NULL on mem error. 245238106Sdes */ 246238106Sdesstruct alloc_cache* context_obtain_alloc(struct ub_ctx* ctx, int locking); 247238106Sdes 248238106Sdes/** 249238106Sdes * Release an alloc. Puts it into the cache. 250238106Sdes * @param ctx: context 251238106Sdes * @param locking: if true, cfglock is locked while releasing alloc. 252238106Sdes * @param alloc: alloc to relinquish. 253238106Sdes */ 254238106Sdesvoid context_release_alloc(struct ub_ctx* ctx, struct alloc_cache* alloc, 255238106Sdes int locking); 256238106Sdes 257238106Sdes/** 258238106Sdes * Serialize a context query that questions data. 259238106Sdes * This serializes the query name, type, ... 260238106Sdes * As well as command code 'new_query'. 261238106Sdes * @param q: context query 262238106Sdes * @param len: the length of the allocation is returned. 263238106Sdes * @return: an alloc, or NULL on mem error. 264238106Sdes */ 265238106Sdesuint8_t* context_serialize_new_query(struct ctx_query* q, uint32_t* len); 266238106Sdes 267238106Sdes/** 268238106Sdes * Serialize a context_query result to hand back to user. 269238106Sdes * This serializes the query name, type, ..., and result. 270238106Sdes * As well as command code 'answer'. 271238106Sdes * @param q: context query 272238106Sdes * @param err: error code to pass to client. 273238106Sdes * @param pkt: the packet to add, can be NULL. 274238106Sdes * @param len: the length of the allocation is returned. 275238106Sdes * @return: an alloc, or NULL on mem error. 276238106Sdes */ 277238106Sdesuint8_t* context_serialize_answer(struct ctx_query* q, int err, 278238106Sdes ldns_buffer* pkt, uint32_t* len); 279238106Sdes 280238106Sdes/** 281238106Sdes * Serialize a query cancellation. Serializes query async id 282238106Sdes * as well as command code 'cancel' 283238106Sdes * @param q: context query 284238106Sdes * @param len: the length of the allocation is returned. 285238106Sdes * @return: an alloc, or NULL on mem error. 286238106Sdes */ 287238106Sdesuint8_t* context_serialize_cancel(struct ctx_query* q, uint32_t* len); 288238106Sdes 289238106Sdes/** 290238106Sdes * Serialize a 'quit' command. 291238106Sdes * @param len: the length of the allocation is returned. 292238106Sdes * @return: an alloc, or NULL on mem error. 293238106Sdes */ 294238106Sdesuint8_t* context_serialize_quit(uint32_t* len); 295238106Sdes 296238106Sdes/** 297238106Sdes * Obtain command code from serialized buffer 298238106Sdes * @param p: buffer serialized. 299238106Sdes * @param len: length of buffer. 300238106Sdes * @return command code or QUIT on error. 301238106Sdes */ 302238106Sdesenum ub_ctx_cmd context_serial_getcmd(uint8_t* p, uint32_t len); 303238106Sdes 304238106Sdes/** 305238106Sdes * Lookup query from new_query buffer. 306238106Sdes * @param ctx: context 307238106Sdes * @param p: buffer serialized. 308238106Sdes * @param len: length of buffer. 309238106Sdes * @return looked up ctx_query or NULL for malloc failure. 310238106Sdes */ 311238106Sdesstruct ctx_query* context_lookup_new_query(struct ub_ctx* ctx, 312238106Sdes uint8_t* p, uint32_t len); 313238106Sdes 314238106Sdes/** 315238106Sdes * Deserialize a new_query buffer. 316238106Sdes * @param ctx: context 317238106Sdes * @param p: buffer serialized. 318238106Sdes * @param len: length of buffer. 319238106Sdes * @return new ctx_query or NULL for malloc failure. 320238106Sdes */ 321238106Sdesstruct ctx_query* context_deserialize_new_query(struct ub_ctx* ctx, 322238106Sdes uint8_t* p, uint32_t len); 323238106Sdes 324238106Sdes/** 325238106Sdes * Deserialize an answer buffer. 326238106Sdes * @param ctx: context 327238106Sdes * @param p: buffer serialized. 328238106Sdes * @param len: length of buffer. 329238106Sdes * @param err: error code to be returned to client is passed. 330238106Sdes * @return ctx_query with answer added or NULL for malloc failure. 331238106Sdes */ 332238106Sdesstruct ctx_query* context_deserialize_answer(struct ub_ctx* ctx, 333238106Sdes uint8_t* p, uint32_t len, int* err); 334238106Sdes 335238106Sdes/** 336238106Sdes * Deserialize a cancel buffer. 337238106Sdes * @param ctx: context 338238106Sdes * @param p: buffer serialized. 339238106Sdes * @param len: length of buffer. 340238106Sdes * @return ctx_query to cancel or NULL for failure. 341238106Sdes */ 342238106Sdesstruct ctx_query* context_deserialize_cancel(struct ub_ctx* ctx, 343238106Sdes uint8_t* p, uint32_t len); 344238106Sdes 345238106Sdes#endif /* LIBUNBOUND_CONTEXT_H */ 346