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