2 * testcode/replay.h - store and use a replay of events for the DNS resolver.
4 * Copyright (c) 2007, NLnet Labs. All rights reserved.
6 * This software is open source.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
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.
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.
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.
38 * Store and use a replay of events for the DNS resolver.
39 * Used to test known scenarios to get known outcomes.
42 * File format for replay files.
44 * ; unbound.conf options.
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
50 * ; contents of that file
52 * ; temp file names are echoed as "tmp/xxx.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
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.
69 * ; go to the next moment
70 * STEP time_step event_type [ADDRESS ip_address]
71 * ; event_type can be:
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
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.
89 * ; following entry starts on the next line, ENTRY_BEGIN.
93 * Calculations, a macro-like system: ${$myvar + 3600}
94 * STEP 10 ASSIGN myvar = 3600
95 * ; ASSIGN event. '=' is syntactic sugar here. 3600 is some expression.
96 * ${..} is macro expanded from its expression. Text substitution.
97 * o $var replaced with its value. var is identifier [azAZ09_]*
98 * o number is that number.
99 * o ${variables and arithmetic }
100 * o +, -, / and *. Note, evaluated left-to-right. Use ${} for brackets.
101 * So again, no precedence rules, so 2+3*4 == ${2+3}*4 = 20.
102 * Do 2+${3*4} to get 24.
103 * o ${function params}
104 * o ${time} is the current time for the simulated unbound.
105 * o ${ctime value} is the text ctime(value), Fri 3 Aug 2009, ...
106 * o ${timeout} is the time until next timeout in comm_timer list.
107 * o ${range lower value upper} checks if lower<=value<=upper
108 * returns value if check succeeds.
111 * SCENARIO_BEGIN Example scenario
114 * ; precoded answers to queries.
121 * ; a query is sent out to the network by resolver.
122 * ; precoded answer from range is returned.
123 * ; algorithm will do precoded answers from RANGE immediately, except if
124 * ; the next step specifically checks for that OUT_QUERY.
125 * ; or if none of the precoded answers match.
126 * STEP 1 CHECK_ANSWER
128 * ; what the reply should look like
130 * ; successful termination. (if the answer was OK).
131 * ; also, all answers must have been checked with CHECK_ANSWER.
132 * ; and, no more pending out_queries (that have not been checked).
138 #ifndef TESTCODE_REPLAY_H
139 #define TESTCODE_REPLAY_H
140 #include "util/netevent.h"
141 #include "testcode/testpkts.h"
142 #include "util/rbtree.h"
143 struct replay_answer;
144 struct replay_moment;
155 struct replay_scenario {
156 /** name of replay scenario. malloced string. */
159 /** The list of replay moments. Linked list. Time increases in list. */
160 struct replay_moment* mom_first;
161 /** The last element in list of replay moments. */
162 struct replay_moment* mom_last;
165 * List of matching answers. This is to ease replay scenario
166 * creation. It lists queries (to the network) and what answer
167 * should be returned. The matching answers are valid for a range
169 * So: timestep, parts of query, destination --> answer.
171 struct replay_range* range_list;
176 * Basically, it consists of events to a fake select() call.
177 * This is a recording of an event that happens.
178 * And if output is presented, what is done with that.
180 struct replay_moment {
182 * The replay time step number. Starts at 0, time is incremented
183 * every time the fake select() is run.
186 /** Next replay moment in list of replay moments. */
187 struct replay_moment* mom_next;
189 /** what happens this moment? */
190 enum replay_event_type {
191 /** nothing happens, as if this event is not there. */
193 /** incoming query */
195 /** test fails if reply to query does not match */
201 /** reply arrives from the network */
203 /** test fails if query to the network does not match */
205 /** check autotrust key file */
206 repevt_autotrust_check,
207 /** check a temp file */
208 repevt_tempfile_check,
209 /** an error happens to outbound query */
211 /** assignment to a variable */
213 /** store infra rtt cache entry: addr and string (int) */
215 /** cause traffic to flow */
218 /** variable with what is to happen this moment */
221 /** The sent packet must match this. Incoming events, the data. */
224 /** the amount of time that passes */
225 struct timeval elapse;
227 /** address that must be matched, or packet remote host address. */
228 struct sockaddr_storage addr;
229 /** length of addr, if 0, then any address will do */
232 /** macro name, for assign. */
234 /** string argument, for assign. */
237 /** the autotrust file id to check */
239 /** file contents to match, one string per line */
240 struct config_strlist* file_content;
244 * Range of timesteps, and canned replies to matching queries.
246 struct replay_range {
247 /** time range when this is valid. Including start and end step. */
249 /** end step of time range. */
251 /** address of where this range is served. */
252 struct sockaddr_storage addr;
253 /** length of addr, if 0, then any address will do */
259 /** next in list of time ranges. */
260 struct replay_range* next_range;
264 * Replay storage of runtime information.
266 struct replay_runtime {
270 struct replay_scenario* scenario;
274 struct replay_moment* now;
277 * List of pending queries in order they were sent out. First
278 * one has been sent out most recently. Last one in list is oldest.
280 struct fake_pending* pending_list;
283 * List of answers to queries from clients. These need to be checked.
285 struct replay_answer* answer_list;
287 /** last element in answer list. */
288 struct replay_answer* answer_last;
290 /** list of fake timer callbacks that are pending */
291 struct fake_timer* timer_list;
293 /** callback to call for incoming queries */
294 comm_point_callback_type* callback_query;
295 /** user argument for incoming query callback */
298 /** ref the infra cache (was passed to outside_network_create) */
299 struct infra_cache* infra;
301 /** the current time in seconds */
303 /** the current time in microseconds */
304 struct timeval now_tv;
306 /** has TCP connection seen a keepalive? */
307 int tcp_seen_keepalive;
309 /** signal handler callback */
310 void (*sig_cb)(int, void*);
311 /** signal handler user arg */
313 /** time to exit cleanly */
316 /** size of buffers */
320 * Tree of macro values. Of type replay_var
326 * Pending queries to network, fake replay version.
328 struct fake_pending {
329 /** what is important only that we remember the query, copied here. */
330 struct sldns_buffer* buffer;
331 /** and to what address this is sent to. */
332 struct sockaddr_storage addr;
335 /** zone name, uncompressed wire format (as used when sent) */
337 /** length of zone name */
341 /** The callback function to call when answer arrives (or timeout) */
342 comm_point_callback_type* callback;
343 /** callback user argument */
345 /** original timeout in seconds from 'then' */
348 /** next in pending list */
349 struct fake_pending* next;
350 /** the buffer parsed into a sldns_pkt */
353 /** by what transport was the query sent out */
354 enum transport_type transport;
355 /** if this is a serviced query */
357 /** if we are handling a multi pkt tcp stream, non 0 and the pkt nr*/
359 /** the runtime structure this is part of */
360 struct replay_runtime* runtime;
364 * An answer that is pending to happen.
366 struct replay_answer {
368 struct replay_answer* next;
369 /** reply information */
370 struct comm_reply repinfo;
371 /** the answer preparsed as ldns pkt */
377 * Timers with callbacks, fake replay version.
381 struct fake_timer* next;
382 /** the runtime structure this is part of */
383 struct replay_runtime* runtime;
384 /** the callback to call */
386 /** the callback user argument */
388 /** if timer is enabled */
390 /** when the timer expires */
395 * Replay macro variable. And its value.
398 /** rbtree node. Key is this structure. Sorted by name. */
400 /** the variable name */
402 /** the variable value */
407 * Read a replay scenario from the file.
408 * @param in: file to read from.
409 * @param name: name to print in errors.
410 * @param lineno: incremented for every line read.
411 * @return: Scenario. NULL if no scenario read.
413 struct replay_scenario* replay_scenario_read(FILE* in, const char* name,
418 * @param scen: to delete.
420 void replay_scenario_delete(struct replay_scenario* scen);
422 /** compare two replay_vars */
423 int replay_var_compare(const void* a, const void* b);
425 /** get oldest enabled fake timer */
426 struct fake_timer* replay_get_oldest_timer(struct replay_runtime* runtime);
429 * Create variable storage
430 * @return new or NULL on failure.
432 rbtree_type* macro_store_create(void);
435 * Delete variable storage
436 * @param store: the macro storage to free up.
438 void macro_store_delete(rbtree_type* store);
441 * Apply macro substitution to string.
442 * @param store: variable store.
443 * @param runtime: the runtime to look up values as needed.
444 * @param text: string to work on.
445 * @return newly malloced string with result.
447 char* macro_process(rbtree_type* store, struct replay_runtime* runtime,
451 * Look up a macro value. Like calling ${$name}.
452 * @param store: variable store
453 * @param name: macro name
454 * @return newly malloced string with result or strdup("") if not found.
455 * or NULL on malloc failure.
457 char* macro_lookup(rbtree_type* store, char* name);
461 * @param store: variable store
462 * @param name: macro name
463 * @param value: text to set it to. Not expanded.
464 * @return false on failure.
466 int macro_assign(rbtree_type* store, char* name, char* value);
468 /** Print macro variables stored as debug info */
469 void macro_print_debug(rbtree_type* store);
471 /** testbounds self test */
472 void testbound_selftest(void);
474 #endif /* TESTCODE_REPLAY_H */