xref: /openbsd/usr.sbin/unbound/testcode/replay.h (revision 2682a17c)
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  * ; temp file names are echoed as "tmp/xxx.fname"
53  * TEMPFILE_NAME fname
54  * ; temp file contents, inline, deleted at end of run
55  * TEMPFILE_CONTENTS fname
56  * ; contents of that file
57  * ; this creates $INCLUDE /tmp/xxx.fname
58  * $INCLUDE_TEMPFILE fname
59  * TEMPFILE_END
60  * CONFIG_END
61  * ; comment line.
62  * SCENARIO_BEGIN name_of_scenario
63  * RANGE_BEGIN start_time end_time
64  *    ; give ip of the virtual server, it matches any ip if not present.
65  *    ADDRESS ip_address
66  *    match_entries
67  * RANGE_END
68  * ; more RANGE items.
69  * ; go to the next moment
70  * STEP time_step event_type [ADDRESS ip_address]
71  * ; event_type can be:
72  *	o NOTHING - nothing
73  *	o QUERY - followed by entry
74  *	o CHECK_ANSWER - followed by entry
75  *	o CHECK_OUT_QUERY - followed by entry (if copy-id it is also reply).
76  *	o REPLY - followed by entry
77  *	o TIMEOUT
78  *	o TIME_PASSES ELAPSE [seconds] - increase 'now' time counter, can be
79  *		a floating point number.
80  *	  TIME_PASSES EVAL [macro] - expanded for seconds to move time.
81  *	o TRAFFIC - like CHECK_ANSWER, causes traffic to flow.
82  *		actually the traffic flows before this step is taken.
83  *		the step waits for traffic to stop.
84  *	o CHECK_AUTOTRUST [id] - followed by FILE_BEGIN [to match] FILE_END.
85  *		The file contents is macro expanded before match.
86  *	o CHECK_TEMPFILE [fname] - followed by FILE_BEGIN [to match] FILE_END
87  *	o INFRA_RTT [ip] [dp] [rtt] - update infra cache entry with rtt.
88  *	o FLUSH_MESSAGE name type class - flushes entry in message cache.
89  *	o EXPIRE_MESSAGE name type class - expires entry in message cache.
90  *	o ERROR
91  * ; following entry starts on the next line, ENTRY_BEGIN.
92  * ; more STEP items
93  * SCENARIO_END
94  *
95  * Calculations, a macro-like system: ${$myvar + 3600}
96  * STEP 10 ASSIGN myvar = 3600
97  * 	; ASSIGN event. '=' is syntactic sugar here. 3600 is some expression.
98  * ${..} is macro expanded from its expression.  Text substitution.
99  * 	o $var replaced with its value.  var is identifier [azAZ09_]*
100  * 	o number is that number.
101  * 	o ${variables and arithmetic }
102  * 	o +, -, / and *.  Note, evaluated left-to-right. Use ${} for brackets.
103  * 	  So again, no precedence rules, so 2+3*4 == ${2+3}*4 = 20.
104  * 	  Do 2+${3*4} to get 24.
105  * 	o ${function params}
106  *		o ${time} is the current time for the simulated unbound.
107  *		o ${ctime value} is the text ctime(value), Fri 3 Aug 2009, ...
108  *		o ${timeout} is the time until next timeout in comm_timer list.
109  *		o ${range lower value upper} checks if lower<=value<=upper
110  *			returns value if check succeeds.
111  *
112  * ; Example file
113  * SCENARIO_BEGIN Example scenario
114  * RANGE_BEGIN 0 100
115  *   ENTRY_BEGIN
116  *   ; precoded answers to queries.
117  *   ENTRY_END
118  * END_RANGE
119  * STEP 0 QUERY
120  *   ENTRY_BEGIN
121  *   ; query
122  *   ENTRY_END
123  * ; a query is sent out to the network by resolver.
124  * ; precoded answer from range is returned.
125  * ; algorithm will do precoded answers from RANGE immediately, except if
126  * ; the next step specifically checks for that OUT_QUERY.
127  * ; or if none of the precoded answers match.
128  * STEP 1 CHECK_ANSWER
129  *   ENTRY_BEGIN
130  *   ; what the reply should look like
131  *   ENTRY_END
132  * ; successful termination. (if the answer was OK).
133  * ; also, all answers must have been checked with CHECK_ANSWER.
134  * ; and, no more pending out_queries (that have not been checked).
135  * SCENARIO_END
136  *
137  * </pre>
138  */
139 
140 #ifndef TESTCODE_REPLAY_H
141 #define TESTCODE_REPLAY_H
142 #include "util/netevent.h"
143 #include "testcode/testpkts.h"
144 #include "util/rbtree.h"
145 struct replay_answer;
146 struct replay_moment;
147 struct replay_range;
148 struct fake_pending;
149 struct fake_timer;
150 struct replay_var;
151 struct infra_cache;
152 struct sldns_buffer;
153 struct daemon;
154 
155 /**
156  * A replay scenario.
157  */
158 struct replay_scenario {
159 	/** name of replay scenario. malloced string. */
160 	char* title;
161 
162 	/** The list of replay moments. Linked list. Time increases in list. */
163 	struct replay_moment* mom_first;
164 	/** The last element in list of replay moments. */
165 	struct replay_moment* mom_last;
166 
167 	/**
168 	 * List of matching answers. This is to ease replay scenario
169 	 * creation. It lists queries (to the network) and what answer
170 	 * should be returned. The matching answers are valid for a range
171 	 * of time steps.
172 	 * So: timestep, parts of query, destination --> answer.
173 	 */
174 	struct replay_range* range_list;
175 };
176 
177 /**
178  * A replay moment.
179  * Basically, it consists of events to a fake select() call.
180  * This is a recording of an event that happens.
181  * And if output is presented, what is done with that.
182  */
183 struct replay_moment {
184 	/**
185 	 * The replay time step number. Starts at 0, time is incremented
186 	 * every time the fake select() is run.
187 	 */
188 	int time_step;
189 	/** Next replay moment in list of replay moments. */
190 	struct replay_moment* mom_next;
191 
192 	/** what happens this moment? */
193 	enum replay_event_type {
194 		/** nothing happens, as if this event is not there. */
195 		repevt_nothing,
196 		/** incoming query */
197 		repevt_front_query,
198 		/** test fails if reply to query does not match */
199 		repevt_front_reply,
200 		/** timeout */
201 		repevt_timeout,
202 		/** time passes */
203 		repevt_time_passes,
204 		/** reply arrives from the network */
205 		repevt_back_reply,
206 		/** test fails if query to the network does not match */
207 		repevt_back_query,
208 		/** check autotrust key file */
209 		repevt_autotrust_check,
210 		/** check a temp file */
211 		repevt_tempfile_check,
212 		/** an error happens to outbound query */
213 		repevt_error,
214 		/** assignment to a variable */
215 		repevt_assign,
216 		/** store infra rtt cache entry: addr and string (int) */
217 		repevt_infra_rtt,
218 		/** flush message cache entry */
219 		repevt_flush_message,
220 		/** expire message cache entry */
221 		repevt_expire_message,
222 		/** cause traffic to flow */
223 		repevt_traffic
224 	}
225 		/** variable with what is to happen this moment */
226 		evt_type;
227 
228 	/** The sent packet must match this. Incoming events, the data. */
229 	struct entry* match;
230 
231 	/** the amount of time that passes */
232 	struct timeval elapse;
233 
234 	/** address that must be matched, or packet remote host address. */
235 	struct sockaddr_storage addr;
236 	/** length of addr, if 0, then any address will do */
237 	socklen_t addrlen;
238 
239 	/** macro name, for assign. */
240 	char* variable;
241 	/** string argument, for assign. */
242 	char* string;
243 
244 	/** the autotrust file id to check */
245 	char* autotrust_id;
246 	/** file contents to match, one string per line */
247 	struct config_strlist* file_content;
248 };
249 
250 /**
251  * Range of timesteps, and canned replies to matching queries.
252  */
253 struct replay_range {
254 	/** time range when this is valid. Including start and end step. */
255 	int start_step;
256 	/** end step of time range. */
257 	int end_step;
258 	/** address of where this range is served. */
259 	struct sockaddr_storage addr;
260 	/** length of addr, if 0, then any address will do */
261 	socklen_t addrlen;
262 
263 	/** Matching list */
264 	struct entry* match;
265 
266 	/** next in list of time ranges. */
267 	struct replay_range* next_range;
268 };
269 
270 /**
271  * Replay storage of runtime information.
272  */
273 struct replay_runtime {
274 	/**
275 	 * The scenario
276 	 */
277 	struct replay_scenario* scenario;
278 	/**
279 	 * Current moment.
280 	 */
281 	struct replay_moment* now;
282 
283 	/**
284 	 * List of pending queries in order they were sent out. First
285 	 * one has been sent out most recently. Last one in list is oldest.
286 	 */
287 	struct fake_pending* pending_list;
288 
289 	/**
290 	 * List of answers to queries from clients. These need to be checked.
291 	 */
292 	struct replay_answer* answer_list;
293 
294 	/** last element in answer list. */
295 	struct replay_answer* answer_last;
296 
297 	/** list of fake timer callbacks that are pending */
298 	struct fake_timer* timer_list;
299 
300 	/** callback to call for incoming queries */
301 	comm_point_callback_type* callback_query;
302 	/** user argument for incoming query callback */
303 	void *cb_arg;
304 
305 	/** ref the infra cache (was passed to outside_network_create) */
306 	struct infra_cache* infra;
307 	/** the daemon structure passed in worker call to remote accept open */
308 	struct daemon* daemon;
309 
310 	/** the current time in seconds */
311 	time_t now_secs;
312 	/** the current time in microseconds */
313 	struct timeval now_tv;
314 
315 	/** has TCP connection seen a keepalive? */
316 	int tcp_seen_keepalive;
317 
318 	/** signal handler callback */
319 	void (*sig_cb)(int, void*);
320 	/** signal handler user arg */
321 	void *sig_cb_arg;
322 	/** time to exit cleanly */
323 	int exit_cleanly;
324 
325 	/** size of buffers */
326 	size_t bufsize;
327 
328 	/**
329 	 * Tree of macro values. Of type replay_var
330 	 */
331 	rbtree_type* vars;
332 };
333 
334 /**
335  * Pending queries to network, fake replay version.
336  */
337 struct fake_pending {
338 	/** what is important only that we remember the query, copied here. */
339 	struct sldns_buffer* buffer;
340 	/** and to what address this is sent to. */
341 	struct sockaddr_storage addr;
342 	/** len of addr */
343 	socklen_t addrlen;
344 	/** zone name, uncompressed wire format (as used when sent) */
345 	uint8_t* zone;
346 	/** length of zone name */
347 	size_t zonelen;
348 	/** qtype */
349 	int qtype;
350 	/** The callback function to call when answer arrives (or timeout) */
351 	comm_point_callback_type* callback;
352 	/** callback user argument */
353 	void* cb_arg;
354 	/** original timeout in seconds from 'then' */
355 	int timeout;
356 
357 	/** next in pending list */
358 	struct fake_pending* next;
359 	/** the buffer parsed into a sldns_pkt */
360 	uint8_t* pkt;
361 	size_t pkt_len;
362 	/** by what transport was the query sent out */
363 	enum transport_type transport;
364 	/** if this is a serviced query */
365 	int serviced;
366 	/** if we are handling a multi pkt tcp stream, non 0 and the pkt nr*/
367 	int tcp_pkt_counter;
368 	/** the runtime structure this is part of */
369 	struct replay_runtime* runtime;
370 };
371 
372 /**
373  * An answer that is pending to happen.
374  */
375 struct replay_answer {
376 	/** Next in list */
377 	struct replay_answer* next;
378 	/** reply information */
379 	struct comm_reply repinfo;
380 	/** the answer preparsed as ldns pkt */
381 	uint8_t* pkt;
382 	size_t pkt_len;
383 };
384 
385 /**
386  * Timers with callbacks, fake replay version.
387  */
388 struct fake_timer {
389 	/** next in list */
390 	struct fake_timer* next;
391 	/** the runtime structure this is part of */
392 	struct replay_runtime* runtime;
393 	/** the callback to call */
394 	void (*cb)(void*);
395 	/** the callback user argument */
396 	void* cb_arg;
397 	/** if timer is enabled */
398 	int enabled;
399 	/** when the timer expires */
400 	struct timeval tv;
401 };
402 
403 /**
404  * Replay macro variable.  And its value.
405  */
406 struct replay_var {
407 	/** rbtree node. Key is this structure. Sorted by name. */
408 	rbnode_type node;
409 	/** the variable name */
410 	char* name;
411 	/** the variable value */
412 	char* value;
413 };
414 
415 /**
416  * Read a replay scenario from the file.
417  * @param in: file to read from.
418  * @param name: name to print in errors.
419  * @param lineno: incremented for every line read.
420  * @return: Scenario. NULL if no scenario read.
421  */
422 struct replay_scenario* replay_scenario_read(FILE* in, const char* name,
423 	int* lineno);
424 
425 /**
426  * Delete scenario.
427  * @param scen: to delete.
428  */
429 void replay_scenario_delete(struct replay_scenario* scen);
430 
431 /** compare two replay_vars */
432 int replay_var_compare(const void* a, const void* b);
433 
434 /** get oldest enabled fake timer */
435 struct fake_timer* replay_get_oldest_timer(struct replay_runtime* runtime);
436 
437 /** strip whitespace from end of string */
438 void strip_end_white(char* p);
439 
440 /**
441  * Create variable storage
442  * @return new or NULL on failure.
443  */
444 rbtree_type* macro_store_create(void);
445 
446 /**
447  * Delete variable storage
448  * @param store: the macro storage to free up.
449  */
450 void macro_store_delete(rbtree_type* store);
451 
452 /**
453  * Apply macro substitution to string.
454  * @param store: variable store.
455  * @param runtime: the runtime to look up values as needed.
456  * @param text: string to work on.
457  * @return newly malloced string with result.
458  */
459 char* macro_process(rbtree_type* store, struct replay_runtime* runtime,
460 	char* text);
461 
462 /**
463  * Look up a macro value. Like calling ${$name}.
464  * @param store: variable store
465  * @param name: macro name
466  * @return newly malloced string with result or strdup("") if not found.
467  * 	or NULL on malloc failure.
468  */
469 char* macro_lookup(rbtree_type* store, char* name);
470 
471 /**
472  * Set macro value.
473  * @param store: variable store
474  * @param name: macro name
475  * @param value: text to set it to.  Not expanded.
476  * @return false on failure.
477  */
478 int macro_assign(rbtree_type* store, char* name, char* value);
479 
480 /** Print macro variables stored as debug info */
481 void macro_print_debug(rbtree_type* store);
482 
483 /** testbounds self test */
484 void testbound_selftest(void);
485 
486 #endif /* TESTCODE_REPLAY_H */
487