xref: /openbsd-src/usr.sbin/unbound/libunbound/context.h (revision 8b7325af55f9372784d083aa385d31c4cebf9890)
1933707f3Ssthen /*
2933707f3Ssthen  * libunbound/context.h - validating context for unbound internal use
3933707f3Ssthen  *
4933707f3Ssthen  * Copyright (c) 2007, NLnet Labs. All rights reserved.
5933707f3Ssthen  *
6933707f3Ssthen  * This software is open source.
7933707f3Ssthen  *
8933707f3Ssthen  * Redistribution and use in source and binary forms, with or without
9933707f3Ssthen  * modification, are permitted provided that the following conditions
10933707f3Ssthen  * are met:
11933707f3Ssthen  *
12933707f3Ssthen  * Redistributions of source code must retain the above copyright notice,
13933707f3Ssthen  * this list of conditions and the following disclaimer.
14933707f3Ssthen  *
15933707f3Ssthen  * Redistributions in binary form must reproduce the above copyright notice,
16933707f3Ssthen  * this list of conditions and the following disclaimer in the documentation
17933707f3Ssthen  * and/or other materials provided with the distribution.
18933707f3Ssthen  *
19933707f3Ssthen  * Neither the name of the NLNET LABS nor the names of its contributors may
20933707f3Ssthen  * be used to endorse or promote products derived from this software without
21933707f3Ssthen  * specific prior written permission.
22933707f3Ssthen  *
23933707f3Ssthen  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
245d76a658Ssthen  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
255d76a658Ssthen  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
265d76a658Ssthen  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
275d76a658Ssthen  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
285d76a658Ssthen  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
295d76a658Ssthen  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
305d76a658Ssthen  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
315d76a658Ssthen  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
325d76a658Ssthen  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
335d76a658Ssthen  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34933707f3Ssthen  */
35933707f3Ssthen 
36933707f3Ssthen /**
37933707f3Ssthen  * \file
38933707f3Ssthen  *
39933707f3Ssthen  * This file contains the validator context structure.
40933707f3Ssthen  */
41933707f3Ssthen #ifndef LIBUNBOUND_CONTEXT_H
42933707f3Ssthen #define LIBUNBOUND_CONTEXT_H
43933707f3Ssthen #include "util/locks.h"
44933707f3Ssthen #include "util/alloc.h"
45933707f3Ssthen #include "util/rbtree.h"
46933707f3Ssthen #include "services/modstack.h"
47933707f3Ssthen #include "libunbound/unbound.h"
4820237c55Ssthen #include "libunbound/unbound-event.h"
49933707f3Ssthen #include "util/data/packed_rrset.h"
50933707f3Ssthen struct libworker;
51933707f3Ssthen struct tube;
525d76a658Ssthen struct sldns_buffer;
532ee382b6Ssthen struct ub_event_base;
54933707f3Ssthen 
558240c1b9Ssthen /** store that the logfile has a debug override */
568240c1b9Ssthen extern int ctx_logfile_overridden;
578240c1b9Ssthen 
58933707f3Ssthen /**
59933707f3Ssthen  * The context structure
60933707f3Ssthen  *
61933707f3Ssthen  * Contains two pipes for async service
62933707f3Ssthen  *	qq : write queries to the async service pid/tid.
63933707f3Ssthen  *	rr : read results from the async service pid/tid.
64933707f3Ssthen  */
65933707f3Ssthen struct ub_ctx {
66933707f3Ssthen 	/* --- pipes --- */
67933707f3Ssthen 	/** mutex on query write pipe */
6877079be7Ssthen 	lock_basic_type qqpipe_lock;
69933707f3Ssthen 	/** the query write pipe */
70933707f3Ssthen 	struct tube* qq_pipe;
71933707f3Ssthen 	/** mutex on result read pipe */
7277079be7Ssthen 	lock_basic_type rrpipe_lock;
73933707f3Ssthen 	/** the result read pipe */
74933707f3Ssthen 	struct tube* rr_pipe;
75933707f3Ssthen 
76933707f3Ssthen 	/* --- shared data --- */
77933707f3Ssthen 	/** mutex for access to env.cfg, finalized and dothread */
7877079be7Ssthen 	lock_basic_type cfglock;
79933707f3Ssthen 	/**
80933707f3Ssthen 	 * The context has been finalized
81933707f3Ssthen 	 * This is after config when the first resolve is done.
82933707f3Ssthen 	 * The modules are inited (module-init()) and shared caches created.
83933707f3Ssthen 	 */
84933707f3Ssthen 	int finalized;
85933707f3Ssthen 
86933707f3Ssthen 	/** is bg worker created yet ? */
87933707f3Ssthen 	int created_bg;
88933707f3Ssthen 	/** pid of bg worker process */
89933707f3Ssthen 	pid_t bg_pid;
90933707f3Ssthen 	/** tid of bg worker thread */
9177079be7Ssthen 	ub_thread_type bg_tid;
92*8b7325afSsthen 	/** pid when pipes are created. This was the process when the
93*8b7325afSsthen 	 * setup was called. Helps with clean up, so we can tell after a fork
94*8b7325afSsthen 	 * which side of the fork the delete is on. */
95*8b7325afSsthen 	pid_t pipe_pid;
96*8b7325afSsthen 	/** when threaded, the worker that exists in the created thread. */
97*8b7325afSsthen 	struct libworker* thread_worker;
98933707f3Ssthen 
99933707f3Ssthen 	/** do threading (instead of forking) for async resolution */
100933707f3Ssthen 	int dothread;
101933707f3Ssthen 	/** next thread number for new threads */
102933707f3Ssthen 	int thr_next_num;
103bdfc4d55Sflorian 	/** if logfile is overridden */
104933707f3Ssthen 	int logfile_override;
105933707f3Ssthen 	/** what logfile to use instead */
106933707f3Ssthen 	FILE* log_out;
107933707f3Ssthen 	/**
108933707f3Ssthen 	 * List of alloc-cache-id points per threadnum for notinuse threads.
109933707f3Ssthen 	 * Simply the entire struct alloc_cache with the 'super' member used
110933707f3Ssthen 	 * to link a simply linked list. Reset super member to the superalloc
111933707f3Ssthen 	 * before use.
112933707f3Ssthen 	 */
113933707f3Ssthen 	struct alloc_cache* alloc_list;
114933707f3Ssthen 
115933707f3Ssthen 	/** shared caches, and so on */
116933707f3Ssthen 	struct alloc_cache superalloc;
117933707f3Ssthen 	/** module env master value */
118933707f3Ssthen 	struct module_env* env;
119933707f3Ssthen 	/** module stack */
120933707f3Ssthen 	struct module_stack mods;
121933707f3Ssthen 	/** local authority zones */
122933707f3Ssthen 	struct local_zones* local_zones;
123933707f3Ssthen 	/** random state used to seed new random state structures */
124933707f3Ssthen 	struct ub_randstate* seed_rnd;
125933707f3Ssthen 
1265d76a658Ssthen 	/** event base for event oriented interface */
1272ee382b6Ssthen 	struct ub_event_base* event_base;
128ebf5bb73Ssthen 	/** true if the event_base is a pluggable base that is malloced
129ebf5bb73Ssthen 	 * with a user event base inside, if so, clean up the pluggable alloc*/
130ebf5bb73Ssthen 	int event_base_malloced;
1315d76a658Ssthen 	/** libworker for event based interface */
1325d76a658Ssthen 	struct libworker* event_worker;
1335d76a658Ssthen 
134933707f3Ssthen 	/** next query number (to try) to use */
135933707f3Ssthen 	int next_querynum;
136933707f3Ssthen 	/** number of async queries outstanding */
137933707f3Ssthen 	size_t num_async;
138933707f3Ssthen 	/**
139933707f3Ssthen 	 * Tree of outstanding queries. Indexed by querynum
140933707f3Ssthen 	 * Used when results come in for async to lookup.
141933707f3Ssthen 	 * Used when cancel is done for lookup (and delete).
142933707f3Ssthen 	 * Used to see if querynum is free for use.
143933707f3Ssthen 	 * Content of type ctx_query.
144933707f3Ssthen 	 */
14577079be7Ssthen 	rbtree_type queries;
146933707f3Ssthen };
147933707f3Ssthen 
148933707f3Ssthen /**
149933707f3Ssthen  * The queries outstanding for the libunbound resolver.
150933707f3Ssthen  * These are outstanding for async resolution.
151933707f3Ssthen  * But also, outstanding for sync resolution by one of the threads that
152933707f3Ssthen  * has joined the threadpool.
153933707f3Ssthen  */
154933707f3Ssthen struct ctx_query {
155933707f3Ssthen 	/** node in rbtree, must be first entry, key is ptr to the querynum */
15677079be7Ssthen 	struct rbnode_type node;
157933707f3Ssthen 	/** query id number, key for node */
158933707f3Ssthen 	int querynum;
159933707f3Ssthen 	/** was this an async query? */
160933707f3Ssthen 	int async;
161933707f3Ssthen 	/** was this query cancelled (for bg worker) */
162933707f3Ssthen 	int cancelled;
163933707f3Ssthen 
16420237c55Ssthen 	/** for async query, the callback function of type ub_callback_type */
16577079be7Ssthen 	ub_callback_type cb;
16620237c55Ssthen 	/** for event callbacks the type is ub_event_callback_type */
16720237c55Ssthen         ub_event_callback_type cb_event;
168933707f3Ssthen 	/** for async query, the callback user arg */
169933707f3Ssthen 	void* cb_arg;
170933707f3Ssthen 
171933707f3Ssthen 	/** answer message, result from resolver lookup. */
172933707f3Ssthen 	uint8_t* msg;
173933707f3Ssthen 	/** resulting message length. */
174933707f3Ssthen 	size_t msg_len;
175933707f3Ssthen 	/** validation status on security */
176933707f3Ssthen 	enum sec_status msg_security;
177933707f3Ssthen 	/** store libworker that is handling this query */
178933707f3Ssthen 	struct libworker* w;
179933707f3Ssthen 
180933707f3Ssthen 	/** result structure, also contains original query, type, class.
181933707f3Ssthen 	 * malloced ptr ready to hand to the client. */
182933707f3Ssthen 	struct ub_result* res;
183933707f3Ssthen };
184933707f3Ssthen 
185933707f3Ssthen /**
186933707f3Ssthen  * Command codes for libunbound pipe.
187933707f3Ssthen  *
188933707f3Ssthen  * Serialization looks like this:
189933707f3Ssthen  * 	o length (of remainder) uint32.
190933707f3Ssthen  * 	o uint32 command code.
191933707f3Ssthen  * 	o per command format.
192933707f3Ssthen  */
193933707f3Ssthen enum ub_ctx_cmd {
194933707f3Ssthen 	/** QUIT */
195933707f3Ssthen 	UB_LIBCMD_QUIT = 0,
196933707f3Ssthen 	/** New query, sent to bg worker */
197933707f3Ssthen 	UB_LIBCMD_NEWQUERY,
198933707f3Ssthen 	/** Cancel query, sent to bg worker */
199933707f3Ssthen 	UB_LIBCMD_CANCEL,
200933707f3Ssthen 	/** Query result, originates from bg worker */
201933707f3Ssthen 	UB_LIBCMD_ANSWER
202933707f3Ssthen };
203933707f3Ssthen 
204933707f3Ssthen /**
205933707f3Ssthen  * finalize a context.
206933707f3Ssthen  * @param ctx: context to finalize. creates shared data.
207933707f3Ssthen  * @return 0 if OK, or errcode.
208933707f3Ssthen  */
209933707f3Ssthen int context_finalize(struct ub_ctx* ctx);
210933707f3Ssthen 
211933707f3Ssthen /** compare two ctx_query elements */
212933707f3Ssthen int context_query_cmp(const void* a, const void* b);
213933707f3Ssthen 
214933707f3Ssthen /**
215933707f3Ssthen  * delete context query
216933707f3Ssthen  * @param q: query to delete, including message packet and prealloc result
217933707f3Ssthen  */
218933707f3Ssthen void context_query_delete(struct ctx_query* q);
219933707f3Ssthen 
220933707f3Ssthen /**
221933707f3Ssthen  * Create new query in context, add to querynum list.
222933707f3Ssthen  * @param ctx: context
223933707f3Ssthen  * @param name: query name
224933707f3Ssthen  * @param rrtype: type
225933707f3Ssthen  * @param rrclass: class
226933707f3Ssthen  * @param cb: callback for async, or NULL for sync.
22720237c55Ssthen  * @param cb_event: event callback for async, or NULL for sync.
228933707f3Ssthen  * @param cbarg: user arg for async queries.
229933707f3Ssthen  * @return new ctx_query or NULL for malloc failure.
230933707f3Ssthen  */
231229e174cSsthen struct ctx_query* context_new(struct ub_ctx* ctx, const char* name, int rrtype,
23220237c55Ssthen         int rrclass,  ub_callback_type cb, ub_event_callback_type cb_event,
23320237c55Ssthen 	void* cbarg);
234933707f3Ssthen 
235933707f3Ssthen /**
236933707f3Ssthen  * Get a new alloc. Creates a new one or uses a cached one.
237933707f3Ssthen  * @param ctx: context
238933707f3Ssthen  * @param locking: if true, cfglock is locked while getting alloc.
239933707f3Ssthen  * @return an alloc, or NULL on mem error.
240933707f3Ssthen  */
241933707f3Ssthen struct alloc_cache* context_obtain_alloc(struct ub_ctx* ctx, int locking);
242933707f3Ssthen 
243933707f3Ssthen /**
244933707f3Ssthen  * Release an alloc. Puts it into the cache.
245933707f3Ssthen  * @param ctx: context
246933707f3Ssthen  * @param locking: if true, cfglock is locked while releasing alloc.
247933707f3Ssthen  * @param alloc: alloc to relinquish.
248933707f3Ssthen  */
249933707f3Ssthen void context_release_alloc(struct ub_ctx* ctx, struct alloc_cache* alloc,
250933707f3Ssthen 	int locking);
251933707f3Ssthen 
252933707f3Ssthen /**
253933707f3Ssthen  * Serialize a context query that questions data.
254933707f3Ssthen  * This serializes the query name, type, ...
255933707f3Ssthen  * As well as command code 'new_query'.
256933707f3Ssthen  * @param q: context query
257933707f3Ssthen  * @param len: the length of the allocation is returned.
258933707f3Ssthen  * @return: an alloc, or NULL on mem error.
259933707f3Ssthen  */
260933707f3Ssthen uint8_t* context_serialize_new_query(struct ctx_query* q, uint32_t* len);
261933707f3Ssthen 
262933707f3Ssthen /**
263933707f3Ssthen  * Serialize a context_query result to hand back to user.
264933707f3Ssthen  * This serializes the query name, type, ..., and result.
265933707f3Ssthen  * As well as command code 'answer'.
266933707f3Ssthen  * @param q: context query
267933707f3Ssthen  * @param err: error code to pass to client.
268933707f3Ssthen  * @param pkt: the packet to add, can be NULL.
269933707f3Ssthen  * @param len: the length of the allocation is returned.
270933707f3Ssthen  * @return: an alloc, or NULL on mem error.
271933707f3Ssthen  */
272933707f3Ssthen uint8_t* context_serialize_answer(struct ctx_query* q, int err,
2735d76a658Ssthen 	struct sldns_buffer* pkt, uint32_t* len);
274933707f3Ssthen 
275933707f3Ssthen /**
276933707f3Ssthen  * Serialize a query cancellation. Serializes query async id
277933707f3Ssthen  * as well as command code 'cancel'
278933707f3Ssthen  * @param q: context query
279933707f3Ssthen  * @param len: the length of the allocation is returned.
280933707f3Ssthen  * @return: an alloc, or NULL on mem error.
281933707f3Ssthen  */
282933707f3Ssthen uint8_t* context_serialize_cancel(struct ctx_query* q, uint32_t* len);
283933707f3Ssthen 
284933707f3Ssthen /**
285933707f3Ssthen  * Serialize a 'quit' command.
286933707f3Ssthen  * @param len: the length of the allocation is returned.
287933707f3Ssthen  * @return: an alloc, or NULL on mem error.
288933707f3Ssthen  */
289933707f3Ssthen uint8_t* context_serialize_quit(uint32_t* len);
290933707f3Ssthen 
291933707f3Ssthen /**
292933707f3Ssthen  * Obtain command code from serialized buffer
293933707f3Ssthen  * @param p: buffer serialized.
294933707f3Ssthen  * @param len: length of buffer.
295933707f3Ssthen  * @return command code or QUIT on error.
296933707f3Ssthen  */
297933707f3Ssthen enum ub_ctx_cmd context_serial_getcmd(uint8_t* p, uint32_t len);
298933707f3Ssthen 
299933707f3Ssthen /**
300933707f3Ssthen  * Lookup query from new_query buffer.
301933707f3Ssthen  * @param ctx: context
302933707f3Ssthen  * @param p: buffer serialized.
303933707f3Ssthen  * @param len: length of buffer.
304933707f3Ssthen  * @return looked up ctx_query or NULL for malloc failure.
305933707f3Ssthen  */
306933707f3Ssthen struct ctx_query* context_lookup_new_query(struct ub_ctx* ctx,
307933707f3Ssthen 	uint8_t* p, uint32_t len);
308933707f3Ssthen 
309933707f3Ssthen /**
310933707f3Ssthen  * Deserialize a new_query buffer.
311933707f3Ssthen  * @param ctx: context
312933707f3Ssthen  * @param p: buffer serialized.
313933707f3Ssthen  * @param len: length of buffer.
314933707f3Ssthen  * @return new ctx_query or NULL for malloc failure.
315933707f3Ssthen  */
316933707f3Ssthen struct ctx_query* context_deserialize_new_query(struct ub_ctx* ctx,
317933707f3Ssthen 	uint8_t* p, uint32_t len);
318933707f3Ssthen 
319933707f3Ssthen /**
320933707f3Ssthen  * Deserialize an answer buffer.
321933707f3Ssthen  * @param ctx: context
322933707f3Ssthen  * @param p: buffer serialized.
323933707f3Ssthen  * @param len: length of buffer.
324933707f3Ssthen  * @param err: error code to be returned to client is passed.
325933707f3Ssthen  * @return ctx_query with answer added or NULL for malloc failure.
326933707f3Ssthen  */
327933707f3Ssthen struct ctx_query* context_deserialize_answer(struct ub_ctx* ctx,
328933707f3Ssthen 	uint8_t* p, uint32_t len, int* err);
329933707f3Ssthen 
330933707f3Ssthen /**
331933707f3Ssthen  * Deserialize a cancel buffer.
332933707f3Ssthen  * @param ctx: context
333933707f3Ssthen  * @param p: buffer serialized.
334933707f3Ssthen  * @param len: length of buffer.
335933707f3Ssthen  * @return ctx_query to cancel or NULL for failure.
336933707f3Ssthen  */
337933707f3Ssthen struct ctx_query* context_deserialize_cancel(struct ub_ctx* ctx,
338933707f3Ssthen 	uint8_t* p, uint32_t len);
339933707f3Ssthen 
340933707f3Ssthen #endif /* LIBUNBOUND_CONTEXT_H */
341