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