xref: /netbsd-src/external/bsd/unbound/dist/testcode/replay.h (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /*
2  * testcode/replay.h - store and use a replay of events for the DNS resolver.
3  *
4  * Copyright (c) 2007, NLnet Labs. All rights reserved.
5  *
6  * This software is open source.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  *
15  * Redistributions in binary form must reproduce the above copyright notice,
16  * this list of conditions and the following disclaimer in the documentation
17  * and/or other materials provided with the distribution.
18  *
19  * Neither the name of the NLNET LABS nor the names of its contributors may
20  * be used to endorse or promote products derived from this software without
21  * specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 /**
37  * \file
38  * Store and use a replay of events for the DNS resolver.
39  * Used to test known scenarios to get known outcomes.
40  *
41  * <pre>
42  * File format for replay files.
43  *
44  * ; unbound.conf options.
45  * ; ...
46  * ; additional commandline options to pass to unbound
47  * COMMANDLINE cmdline_option
48  * ; autotrust key file contents, also adds auto-trust-anchor-file: "x" to cfg
49  * AUTOTRUST_FILE id
50  * ; contents of that file
51  * AUTOTRUST_END
52  * CONFIG_END
53  * ; comment line.
54  * SCENARIO_BEGIN name_of_scenario
55  * RANGE_BEGIN start_time end_time
56  *    ; give ip of the virtual server, it matches any ip if not present.
57  *    ADDRESS ip_address
58  *    match_entries
59  * RANGE_END
60  * ; more RANGE items.
61  * ; go to the next moment
62  * STEP time_step event_type [ADDRESS ip_address]
63  * ; event_type can be:
64  *	o NOTHING - nothing
65  *	o QUERY - followed by entry
66  *	o CHECK_ANSWER - followed by entry
67  *	o CHECK_OUT_QUERY - followed by entry (if copy-id it is also reply).
68  *	o REPLY - followed by entry
69  *      o TIMEOUT
70  *      o TIME_PASSES ELAPSE [seconds] - increase 'now' time counter, can be
71  *      			a floating point number.
72  *        TIME_PASSES EVAL [macro] - expanded for seconds to move time.
73  *      o TRAFFIC - like CHECK_ANSWER, causes traffic to flow.
74  *		actually the traffic flows before this step is taken.
75  *		the step waits for traffic to stop.
76  *      o CHECK_AUTOTRUST [id] - followed by FILE_BEGIN [to match] FILE_END.
77  *      	The file contents is macro expanded before match.
78  *      o INFRA_RTT [ip] [dp] [rtt] - update infra cache entry with rtt.
79  *      o ERROR
80  * ; following entry starts on the next line, ENTRY_BEGIN.
81  * ; more STEP items
82  * SCENARIO_END
83  *
84  * Calculations, a macro-like system: ${$myvar + 3600}
85  * STEP 10 ASSIGN myvar = 3600
86  * 	; ASSIGN event. '=' is syntactic sugar here. 3600 is some expression.
87  * ${..} is macro expanded from its expression.  Text substitution.
88  * 	o $var replaced with its value.  var is identifier [azAZ09_]*
89  * 	o number is that number.
90  * 	o ${variables and arithmetic }
91  * 	o +, -, / and *.  Note, evaluated left-to-right. Use ${} for brackets.
92  * 	  So again, no precedence rules, so 2+3*4 == ${2+3}*4 = 20.
93  * 	  Do 2+${3*4} to get 24.
94  * 	o ${function params}
95  *		o ${time} is the current time for the simulated unbound.
96  *		o ${ctime value} is the text ctime(value), Fri 3 Aug 2009, ...
97  *		o ${timeout} is the time until next timeout in comm_timer list.
98  *		o ${range lower value upper} checks if lower<=value<=upper
99  *			returns value if check succeeds.
100  *
101  * ; Example file
102  * SCENARIO_BEGIN Example scenario
103  * RANGE_BEGIN 0 100
104  *   ENTRY_BEGIN
105  *   ; precoded answers to queries.
106  *   ENTRY_END
107  * END_RANGE
108  * STEP 0 QUERY
109  *   ENTRY_BEGIN
110  *   ; query
111  *   ENTRY_END
112  * ; a query is sent out to the network by resolver.
113  * ; precoded answer from range is returned.
114  * ; algorithm will do precoded answers from RANGE immediately, except if
115  * ; the next step specifically checks for that OUT_QUERY.
116  * ; or if none of the precoded answers match.
117  * STEP 1 CHECK_ANSWER
118  *   ENTRY_BEGIN
119  *   ; what the reply should look like
120  *   ENTRY_END
121  * ; successful termination. (if the answer was OK).
122  * ; also, all answers must have been checked with CHECK_ANSWER.
123  * ; and, no more pending out_queries (that have not been checked).
124  * SCENARIO_END
125  *
126  * </pre>
127  */
128 
129 #ifndef TESTCODE_REPLAY_H
130 #define TESTCODE_REPLAY_H
131 #include "util/netevent.h"
132 #include "testcode/testpkts.h"
133 #include "util/rbtree.h"
134 struct replay_answer;
135 struct replay_moment;
136 struct replay_range;
137 struct fake_pending;
138 struct fake_timer;
139 struct replay_var;
140 struct infra_cache;
141 struct sldns_buffer;
142 
143 /**
144  * A replay scenario.
145  */
146 struct replay_scenario {
147 	/** name of replay scenario. malloced string. */
148 	char* title;
149 
150 	/** The list of replay moments. Linked list. Time increases in list. */
151 	struct replay_moment* mom_first;
152 	/** The last element in list of replay moments. */
153 	struct replay_moment* mom_last;
154 
155 	/**
156 	 * List of matching answers. This is to ease replay scenario
157 	 * creation. It lists queries (to the network) and what answer
158 	 * should be returned. The matching answers are valid for a range
159 	 * of time steps.
160 	 * So: timestep, parts of query, destination --> answer.
161 	 */
162 	struct replay_range* range_list;
163 };
164 
165 /**
166  * A replay moment.
167  * Basically, it consists of events to a fake select() call.
168  * This is a recording of an event that happens.
169  * And if output is presented, what is done with that.
170  */
171 struct replay_moment {
172 	/**
173 	 * The replay time step number. Starts at 0, time is incremented
174 	 * every time the fake select() is run.
175 	 */
176 	int time_step;
177 	/** Next replay moment in list of replay moments. */
178 	struct replay_moment* mom_next;
179 
180 	/** what happens this moment? */
181 	enum replay_event_type {
182 		/** nothing happens, as if this event is not there. */
183 		repevt_nothing,
184 		/** incoming query */
185 		repevt_front_query,
186 		/** test fails if reply to query does not match */
187 		repevt_front_reply,
188 		/** timeout */
189 		repevt_timeout,
190 		/** time passes */
191 		repevt_time_passes,
192 		/** reply arrives from the network */
193 		repevt_back_reply,
194 		/** test fails if query to the network does not match */
195 		repevt_back_query,
196 		/** check autotrust key file */
197 		repevt_autotrust_check,
198 		/** an error happens to outbound query */
199 		repevt_error,
200 		/** assignment to a variable */
201 		repevt_assign,
202 		/** store infra rtt cache entry: addr and string (int) */
203 		repevt_infra_rtt,
204 		/** cause traffic to flow */
205 		repevt_traffic
206 	}
207 		/** variable with what is to happen this moment */
208 		evt_type;
209 
210 	/** The sent packet must match this. Incoming events, the data. */
211 	struct entry* match;
212 
213 	/** the amount of time that passes */
214 	struct timeval elapse;
215 
216 	/** address that must be matched, or packet remote host address. */
217 	struct sockaddr_storage addr;
218 	/** length of addr, if 0, then any address will do */
219 	socklen_t addrlen;
220 
221 	/** macro name, for assign. */
222 	char* variable;
223 	/** string argument, for assign. */
224 	char* string;
225 
226 	/** the autotrust file id to check */
227 	char* autotrust_id;
228 	/** file contents to match, one string per line */
229 	struct config_strlist* file_content;
230 };
231 
232 /**
233  * Range of timesteps, and canned replies to matching queries.
234  */
235 struct replay_range {
236 	/** time range when this is valid. Including start and end step. */
237 	int start_step;
238 	/** end step of time range. */
239 	int end_step;
240 	/** address of where this range is served. */
241 	struct sockaddr_storage addr;
242 	/** length of addr, if 0, then any address will do */
243 	socklen_t addrlen;
244 
245 	/** Matching list */
246 	struct entry* match;
247 
248 	/** next in list of time ranges. */
249 	struct replay_range* next_range;
250 };
251 
252 /**
253  * Replay storage of runtime information.
254  */
255 struct replay_runtime {
256 	/**
257 	 * The scenario
258 	 */
259 	struct replay_scenario* scenario;
260 	/**
261 	 * Current moment.
262 	 */
263 	struct replay_moment* now;
264 
265 	/**
266 	 * List of pending queries in order they were sent out. First
267 	 * one has been sent out most recently. Last one in list is oldest.
268 	 */
269 	struct fake_pending* pending_list;
270 
271 	/**
272 	 * List of answers to queries from clients. These need to be checked.
273 	 */
274 	struct replay_answer* answer_list;
275 
276 	/** last element in answer list. */
277 	struct replay_answer* answer_last;
278 
279 	/** list of fake timer callbacks that are pending */
280 	struct fake_timer* timer_list;
281 
282 	/** callback to call for incoming queries */
283 	comm_point_callback_type* callback_query;
284 	/** user argument for incoming query callback */
285 	void *cb_arg;
286 
287 	/** ref the infra cache (was passed to outside_network_create) */
288 	struct infra_cache* infra;
289 
290 	/** the current time in seconds */
291 	time_t now_secs;
292 	/** the current time in microseconds */
293 	struct timeval now_tv;
294 
295 	/** signal handler callback */
296 	void (*sig_cb)(int, void*);
297 	/** signal handler user arg */
298 	void *sig_cb_arg;
299 	/** time to exit cleanly */
300 	int exit_cleanly;
301 
302 	/** size of buffers */
303 	size_t bufsize;
304 
305 	/**
306 	 * Tree of macro values. Of type replay_var
307 	 */
308 	rbtree_type* vars;
309 };
310 
311 /**
312  * Pending queries to network, fake replay version.
313  */
314 struct fake_pending {
315 	/** what is important only that we remember the query, copied here. */
316 	struct sldns_buffer* buffer;
317 	/** and to what address this is sent to. */
318 	struct sockaddr_storage addr;
319 	/** len of addr */
320 	socklen_t addrlen;
321 	/** zone name, uncompressed wire format (as used when sent) */
322 	uint8_t* zone;
323 	/** length of zone name */
324 	size_t zonelen;
325 	/** qtype */
326 	int qtype;
327 	/** The callback function to call when answer arrives (or timeout) */
328 	comm_point_callback_type* callback;
329 	/** callback user argument */
330 	void* cb_arg;
331 	/** original timeout in seconds from 'then' */
332 	int timeout;
333 
334 	/** next in pending list */
335 	struct fake_pending* next;
336 	/** the buffer parsed into a sldns_pkt */
337 	uint8_t* pkt;
338 	size_t pkt_len;
339 	/** by what transport was the query sent out */
340 	enum transport_type transport;
341 	/** if this is a serviced query */
342 	int serviced;
343 	/** the runtime structure this is part of */
344 	struct replay_runtime* runtime;
345 };
346 
347 /**
348  * An answer that is pending to happen.
349  */
350 struct replay_answer {
351 	/** Next in list */
352 	struct replay_answer* next;
353 	/** reply information */
354 	struct comm_reply repinfo;
355 	/** the answer preparsed as ldns pkt */
356 	uint8_t* pkt;
357 	size_t pkt_len;
358 };
359 
360 /**
361  * Timers with callbacks, fake replay version.
362  */
363 struct fake_timer {
364 	/** next in list */
365 	struct fake_timer* next;
366 	/** the runtime structure this is part of */
367 	struct replay_runtime* runtime;
368 	/** the callback to call */
369 	void (*cb)(void*);
370 	/** the callback user argument */
371 	void* cb_arg;
372 	/** if timer is enabled */
373 	int enabled;
374 	/** when the timer expires */
375 	struct timeval tv;
376 };
377 
378 /**
379  * Replay macro variable.  And its value.
380  */
381 struct replay_var {
382 	/** rbtree node. Key is this structure. Sorted by name. */
383 	rbnode_type node;
384 	/** the variable name */
385 	char* name;
386 	/** the variable value */
387 	char* value;
388 };
389 
390 /**
391  * Read a replay scenario from the file.
392  * @param in: file to read from.
393  * @param name: name to print in errors.
394  * @param lineno: incremented for every line read.
395  * @return: Scenario. NULL if no scenario read.
396  */
397 struct replay_scenario* replay_scenario_read(FILE* in, const char* name,
398 	int* lineno);
399 
400 /**
401  * Delete scenario.
402  * @param scen: to delete.
403  */
404 void replay_scenario_delete(struct replay_scenario* scen);
405 
406 /** compare two replay_vars */
407 int replay_var_compare(const void* a, const void* b);
408 
409 /** get oldest enabled fake timer */
410 struct fake_timer* replay_get_oldest_timer(struct replay_runtime* runtime);
411 
412 /**
413  * Create variable storage
414  * @return new or NULL on failure.
415  */
416 rbtree_type* macro_store_create(void);
417 
418 /**
419  * Delete variable storage
420  * @param store: the macro storage to free up.
421  */
422 void macro_store_delete(rbtree_type* store);
423 
424 /**
425  * Apply macro substitution to string.
426  * @param store: variable store.
427  * @param runtime: the runtime to look up values as needed.
428  * @param text: string to work on.
429  * @return newly malloced string with result.
430  */
431 char* macro_process(rbtree_type* store, struct replay_runtime* runtime,
432 	char* text);
433 
434 /**
435  * Look up a macro value. Like calling ${$name}.
436  * @param store: variable store
437  * @param name: macro name
438  * @return newly malloced string with result or strdup("") if not found.
439  * 	or NULL on malloc failure.
440  */
441 char* macro_lookup(rbtree_type* store, char* name);
442 
443 /**
444  * Set macro value.
445  * @param store: variable store
446  * @param name: macro name
447  * @param value: text to set it to.  Not expanded.
448  * @return false on failure.
449  */
450 int macro_assign(rbtree_type* store, char* name, char* value);
451 
452 /** Print macro variables stored as debug info */
453 void macro_print_debug(rbtree_type* store);
454 
455 /** testbounds self test */
456 void testbound_selftest(void);
457 
458 #endif /* TESTCODE_REPLAY_H */
459