353 lines
10 KiB
C
353 lines
10 KiB
C
/*
|
|
* libunbound/context.h - validating context for unbound internal use
|
|
*
|
|
* Copyright (c) 2007, NLnet Labs. All rights reserved.
|
|
*
|
|
* This software is open source.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* Redistributions of source code must retain the above copyright notice,
|
|
* this list of conditions and the following disclaimer.
|
|
*
|
|
* Redistributions in binary form must reproduce the above copyright notice,
|
|
* this list of conditions and the following disclaimer in the documentation
|
|
* and/or other materials provided with the distribution.
|
|
*
|
|
* Neither the name of the NLNET LABS nor the names of its contributors may
|
|
* be used to endorse or promote products derived from this software without
|
|
* specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
/**
|
|
* \file
|
|
*
|
|
* This file contains the validator context structure.
|
|
*/
|
|
#ifndef LIBUNBOUND_CONTEXT_H
|
|
#define LIBUNBOUND_CONTEXT_H
|
|
#include "util/locks.h"
|
|
#include "util/alloc.h"
|
|
#include "util/rbtree.h"
|
|
#include "services/modstack.h"
|
|
#include "libunbound/unbound.h"
|
|
#include "util/data/packed_rrset.h"
|
|
struct libworker;
|
|
struct tube;
|
|
struct sldns_buffer;
|
|
struct event_base;
|
|
|
|
/**
|
|
* The context structure
|
|
*
|
|
* Contains two pipes for async service
|
|
* qq : write queries to the async service pid/tid.
|
|
* rr : read results from the async service pid/tid.
|
|
*/
|
|
struct ub_ctx {
|
|
/* --- pipes --- */
|
|
/** mutex on query write pipe */
|
|
lock_basic_t qqpipe_lock;
|
|
/** the query write pipe */
|
|
struct tube* qq_pipe;
|
|
/** mutex on result read pipe */
|
|
lock_basic_t rrpipe_lock;
|
|
/** the result read pipe */
|
|
struct tube* rr_pipe;
|
|
|
|
/* --- shared data --- */
|
|
/** mutex for access to env.cfg, finalized and dothread */
|
|
lock_basic_t cfglock;
|
|
/**
|
|
* The context has been finalized
|
|
* This is after config when the first resolve is done.
|
|
* The modules are inited (module-init()) and shared caches created.
|
|
*/
|
|
int finalized;
|
|
|
|
/** is bg worker created yet ? */
|
|
int created_bg;
|
|
/** pid of bg worker process */
|
|
pid_t bg_pid;
|
|
/** tid of bg worker thread */
|
|
ub_thread_t bg_tid;
|
|
|
|
/** do threading (instead of forking) for async resolution */
|
|
int dothread;
|
|
/** next thread number for new threads */
|
|
int thr_next_num;
|
|
/** if logfile is overriden */
|
|
int logfile_override;
|
|
/** what logfile to use instead */
|
|
FILE* log_out;
|
|
/**
|
|
* List of alloc-cache-id points per threadnum for notinuse threads.
|
|
* Simply the entire struct alloc_cache with the 'super' member used
|
|
* to link a simply linked list. Reset super member to the superalloc
|
|
* before use.
|
|
*/
|
|
struct alloc_cache* alloc_list;
|
|
|
|
/** shared caches, and so on */
|
|
struct alloc_cache superalloc;
|
|
/** module env master value */
|
|
struct module_env* env;
|
|
/** module stack */
|
|
struct module_stack mods;
|
|
/** local authority zones */
|
|
struct local_zones* local_zones;
|
|
/** random state used to seed new random state structures */
|
|
struct ub_randstate* seed_rnd;
|
|
|
|
/** event base for event oriented interface */
|
|
struct event_base* event_base;
|
|
/** libworker for event based interface */
|
|
struct libworker* event_worker;
|
|
|
|
/** next query number (to try) to use */
|
|
int next_querynum;
|
|
/** number of async queries outstanding */
|
|
size_t num_async;
|
|
/**
|
|
* Tree of outstanding queries. Indexed by querynum
|
|
* Used when results come in for async to lookup.
|
|
* Used when cancel is done for lookup (and delete).
|
|
* Used to see if querynum is free for use.
|
|
* Content of type ctx_query.
|
|
*/
|
|
rbtree_t queries;
|
|
};
|
|
|
|
/**
|
|
* The queries outstanding for the libunbound resolver.
|
|
* These are outstanding for async resolution.
|
|
* But also, outstanding for sync resolution by one of the threads that
|
|
* has joined the threadpool.
|
|
*/
|
|
struct ctx_query {
|
|
/** node in rbtree, must be first entry, key is ptr to the querynum */
|
|
struct rbnode_t node;
|
|
/** query id number, key for node */
|
|
int querynum;
|
|
/** was this an async query? */
|
|
int async;
|
|
/** was this query cancelled (for bg worker) */
|
|
int cancelled;
|
|
|
|
/** for async query, the callback function */
|
|
ub_callback_t cb;
|
|
/** for async query, the callback user arg */
|
|
void* cb_arg;
|
|
|
|
/** answer message, result from resolver lookup. */
|
|
uint8_t* msg;
|
|
/** resulting message length. */
|
|
size_t msg_len;
|
|
/** validation status on security */
|
|
enum sec_status msg_security;
|
|
/** store libworker that is handling this query */
|
|
struct libworker* w;
|
|
|
|
/** result structure, also contains original query, type, class.
|
|
* malloced ptr ready to hand to the client. */
|
|
struct ub_result* res;
|
|
};
|
|
|
|
/**
|
|
* The error constants
|
|
*/
|
|
enum ub_ctx_err {
|
|
/** no error */
|
|
UB_NOERROR = 0,
|
|
/** socket operation. Set to -1, so that if an error from _fd() is
|
|
* passed (-1) it gives a socket error. */
|
|
UB_SOCKET = -1,
|
|
/** alloc failure */
|
|
UB_NOMEM = -2,
|
|
/** syntax error */
|
|
UB_SYNTAX = -3,
|
|
/** DNS service failed */
|
|
UB_SERVFAIL = -4,
|
|
/** fork() failed */
|
|
UB_FORKFAIL = -5,
|
|
/** cfg change after finalize() */
|
|
UB_AFTERFINAL = -6,
|
|
/** initialization failed (bad settings) */
|
|
UB_INITFAIL = -7,
|
|
/** error in pipe communication with async bg worker */
|
|
UB_PIPE = -8,
|
|
/** error reading from file (resolv.conf) */
|
|
UB_READFILE = -9,
|
|
/** error async_id does not exist or result already been delivered */
|
|
UB_NOID = -10
|
|
};
|
|
|
|
/**
|
|
* Command codes for libunbound pipe.
|
|
*
|
|
* Serialization looks like this:
|
|
* o length (of remainder) uint32.
|
|
* o uint32 command code.
|
|
* o per command format.
|
|
*/
|
|
enum ub_ctx_cmd {
|
|
/** QUIT */
|
|
UB_LIBCMD_QUIT = 0,
|
|
/** New query, sent to bg worker */
|
|
UB_LIBCMD_NEWQUERY,
|
|
/** Cancel query, sent to bg worker */
|
|
UB_LIBCMD_CANCEL,
|
|
/** Query result, originates from bg worker */
|
|
UB_LIBCMD_ANSWER
|
|
};
|
|
|
|
/**
|
|
* finalize a context.
|
|
* @param ctx: context to finalize. creates shared data.
|
|
* @return 0 if OK, or errcode.
|
|
*/
|
|
int context_finalize(struct ub_ctx* ctx);
|
|
|
|
/** compare two ctx_query elements */
|
|
int context_query_cmp(const void* a, const void* b);
|
|
|
|
/**
|
|
* delete context query
|
|
* @param q: query to delete, including message packet and prealloc result
|
|
*/
|
|
void context_query_delete(struct ctx_query* q);
|
|
|
|
/**
|
|
* Create new query in context, add to querynum list.
|
|
* @param ctx: context
|
|
* @param name: query name
|
|
* @param rrtype: type
|
|
* @param rrclass: class
|
|
* @param cb: callback for async, or NULL for sync.
|
|
* @param cbarg: user arg for async queries.
|
|
* @return new ctx_query or NULL for malloc failure.
|
|
*/
|
|
struct ctx_query* context_new(struct ub_ctx* ctx, const char* name, int rrtype,
|
|
int rrclass, ub_callback_t cb, void* cbarg);
|
|
|
|
/**
|
|
* Get a new alloc. Creates a new one or uses a cached one.
|
|
* @param ctx: context
|
|
* @param locking: if true, cfglock is locked while getting alloc.
|
|
* @return an alloc, or NULL on mem error.
|
|
*/
|
|
struct alloc_cache* context_obtain_alloc(struct ub_ctx* ctx, int locking);
|
|
|
|
/**
|
|
* Release an alloc. Puts it into the cache.
|
|
* @param ctx: context
|
|
* @param locking: if true, cfglock is locked while releasing alloc.
|
|
* @param alloc: alloc to relinquish.
|
|
*/
|
|
void context_release_alloc(struct ub_ctx* ctx, struct alloc_cache* alloc,
|
|
int locking);
|
|
|
|
/**
|
|
* Serialize a context query that questions data.
|
|
* This serializes the query name, type, ...
|
|
* As well as command code 'new_query'.
|
|
* @param q: context query
|
|
* @param len: the length of the allocation is returned.
|
|
* @return: an alloc, or NULL on mem error.
|
|
*/
|
|
uint8_t* context_serialize_new_query(struct ctx_query* q, uint32_t* len);
|
|
|
|
/**
|
|
* Serialize a context_query result to hand back to user.
|
|
* This serializes the query name, type, ..., and result.
|
|
* As well as command code 'answer'.
|
|
* @param q: context query
|
|
* @param err: error code to pass to client.
|
|
* @param pkt: the packet to add, can be NULL.
|
|
* @param len: the length of the allocation is returned.
|
|
* @return: an alloc, or NULL on mem error.
|
|
*/
|
|
uint8_t* context_serialize_answer(struct ctx_query* q, int err,
|
|
struct sldns_buffer* pkt, uint32_t* len);
|
|
|
|
/**
|
|
* Serialize a query cancellation. Serializes query async id
|
|
* as well as command code 'cancel'
|
|
* @param q: context query
|
|
* @param len: the length of the allocation is returned.
|
|
* @return: an alloc, or NULL on mem error.
|
|
*/
|
|
uint8_t* context_serialize_cancel(struct ctx_query* q, uint32_t* len);
|
|
|
|
/**
|
|
* Serialize a 'quit' command.
|
|
* @param len: the length of the allocation is returned.
|
|
* @return: an alloc, or NULL on mem error.
|
|
*/
|
|
uint8_t* context_serialize_quit(uint32_t* len);
|
|
|
|
/**
|
|
* Obtain command code from serialized buffer
|
|
* @param p: buffer serialized.
|
|
* @param len: length of buffer.
|
|
* @return command code or QUIT on error.
|
|
*/
|
|
enum ub_ctx_cmd context_serial_getcmd(uint8_t* p, uint32_t len);
|
|
|
|
/**
|
|
* Lookup query from new_query buffer.
|
|
* @param ctx: context
|
|
* @param p: buffer serialized.
|
|
* @param len: length of buffer.
|
|
* @return looked up ctx_query or NULL for malloc failure.
|
|
*/
|
|
struct ctx_query* context_lookup_new_query(struct ub_ctx* ctx,
|
|
uint8_t* p, uint32_t len);
|
|
|
|
/**
|
|
* Deserialize a new_query buffer.
|
|
* @param ctx: context
|
|
* @param p: buffer serialized.
|
|
* @param len: length of buffer.
|
|
* @return new ctx_query or NULL for malloc failure.
|
|
*/
|
|
struct ctx_query* context_deserialize_new_query(struct ub_ctx* ctx,
|
|
uint8_t* p, uint32_t len);
|
|
|
|
/**
|
|
* Deserialize an answer buffer.
|
|
* @param ctx: context
|
|
* @param p: buffer serialized.
|
|
* @param len: length of buffer.
|
|
* @param err: error code to be returned to client is passed.
|
|
* @return ctx_query with answer added or NULL for malloc failure.
|
|
*/
|
|
struct ctx_query* context_deserialize_answer(struct ub_ctx* ctx,
|
|
uint8_t* p, uint32_t len, int* err);
|
|
|
|
/**
|
|
* Deserialize a cancel buffer.
|
|
* @param ctx: context
|
|
* @param p: buffer serialized.
|
|
* @param len: length of buffer.
|
|
* @return ctx_query to cancel or NULL for failure.
|
|
*/
|
|
struct ctx_query* context_deserialize_cancel(struct ub_ctx* ctx,
|
|
uint8_t* p, uint32_t len);
|
|
|
|
#endif /* LIBUNBOUND_CONTEXT_H */
|