]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - testcode/replay.h
Apply upstream fix 08968baec1122a58bb90d8f97ad948a75f8a5d69:
[FreeBSD/FreeBSD.git] / testcode / replay.h
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 ERROR
89  * ; following entry starts on the next line, ENTRY_BEGIN.
90  * ; more STEP items
91  * SCENARIO_END
92  *
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.
109  *
110  * ; Example file
111  * SCENARIO_BEGIN Example scenario
112  * RANGE_BEGIN 0 100
113  *   ENTRY_BEGIN
114  *   ; precoded answers to queries.
115  *   ENTRY_END
116  * END_RANGE
117  * STEP 0 QUERY
118  *   ENTRY_BEGIN
119  *   ; query
120  *   ENTRY_END
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
127  *   ENTRY_BEGIN
128  *   ; what the reply should look like
129  *   ENTRY_END
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).
133  * SCENARIO_END
134  * 
135  * </pre>
136  */
137
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;
145 struct replay_range;
146 struct fake_pending;
147 struct fake_timer;
148 struct replay_var;
149 struct infra_cache;
150 struct sldns_buffer;
151
152 /**
153  * A replay scenario.
154  */
155 struct replay_scenario {
156         /** name of replay scenario. malloced string. */
157         char* title;
158
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;
163
164         /** 
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
168          * of time steps. 
169          * So: timestep, parts of query, destination --> answer.
170          */
171         struct replay_range* range_list;
172 };
173
174 /**
175  * A replay moment.
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.
179  */
180 struct replay_moment {
181         /** 
182          * The replay time step number. Starts at 0, time is incremented 
183          * every time the fake select() is run. 
184          */
185         int time_step;
186         /** Next replay moment in list of replay moments. */
187         struct replay_moment* mom_next;
188
189         /** what happens this moment? */
190         enum replay_event_type {
191                 /** nothing happens, as if this event is not there. */
192                 repevt_nothing,
193                 /** incoming query */
194                 repevt_front_query,
195                 /** test fails if reply to query does not match */
196                 repevt_front_reply,
197                 /** timeout */
198                 repevt_timeout,
199                 /** time passes */
200                 repevt_time_passes,
201                 /** reply arrives from the network */
202                 repevt_back_reply,
203                 /** test fails if query to the network does not match */
204                 repevt_back_query,
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 */
210                 repevt_error,
211                 /** assignment to a variable */
212                 repevt_assign,
213                 /** store infra rtt cache entry: addr and string (int) */
214                 repevt_infra_rtt,
215                 /** cause traffic to flow */
216                 repevt_traffic
217         }
218                 /** variable with what is to happen this moment */
219                 evt_type;
220
221         /** The sent packet must match this. Incoming events, the data. */
222         struct entry* match;
223
224         /** the amount of time that passes */
225         struct timeval elapse;
226
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 */
230         socklen_t addrlen;
231
232         /** macro name, for assign. */
233         char* variable;
234         /** string argument, for assign. */
235         char* string;
236
237         /** the autotrust file id to check */
238         char* autotrust_id;
239         /** file contents to match, one string per line */
240         struct config_strlist* file_content;
241 };
242
243 /**
244  * Range of timesteps, and canned replies to matching queries.
245  */
246 struct replay_range {
247         /** time range when this is valid. Including start and end step. */
248         int start_step;
249         /** end step of time range. */
250         int end_step;
251         /** address of where this range is served. */
252         struct sockaddr_storage addr;
253         /** length of addr, if 0, then any address will do */
254         socklen_t addrlen;
255
256         /** Matching list */
257         struct entry* match;
258
259         /** next in list of time ranges. */
260         struct replay_range* next_range;
261 };
262
263 /**
264  * Replay storage of runtime information.
265  */
266 struct replay_runtime {
267         /**
268          * The scenario
269          */
270         struct replay_scenario* scenario;
271         /**
272          * Current moment.
273          */
274         struct replay_moment* now;
275
276         /** 
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. 
279          */
280         struct fake_pending* pending_list;
281
282         /**
283          * List of answers to queries from clients. These need to be checked.
284          */
285         struct replay_answer* answer_list;
286         
287         /** last element in answer list. */
288         struct replay_answer* answer_last;
289
290         /** list of fake timer callbacks that are pending */
291         struct fake_timer* timer_list;
292
293         /** callback to call for incoming queries */
294         comm_point_callback_type* callback_query;
295         /** user argument for incoming query callback */
296         void *cb_arg;
297
298         /** ref the infra cache (was passed to outside_network_create) */
299         struct infra_cache* infra;
300
301         /** the current time in seconds */
302         time_t now_secs;
303         /** the current time in microseconds */
304         struct timeval now_tv;
305
306         /** has TCP connection seen a keepalive? */
307         int tcp_seen_keepalive;
308
309         /** signal handler callback */
310         void (*sig_cb)(int, void*);
311         /** signal handler user arg */
312         void *sig_cb_arg;
313         /** time to exit cleanly */
314         int exit_cleanly;
315
316         /** size of buffers */
317         size_t bufsize;
318
319         /**
320          * Tree of macro values. Of type replay_var
321          */
322         rbtree_type* vars;
323 };
324
325 /**
326  * Pending queries to network, fake replay version.
327  */
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;
333         /** len of addr */
334         socklen_t addrlen;
335         /** zone name, uncompressed wire format (as used when sent) */
336         uint8_t* zone;
337         /** length of zone name */
338         size_t zonelen;
339         /** qtype */
340         int qtype;
341         /** The callback function to call when answer arrives (or timeout) */
342         comm_point_callback_type* callback;
343         /** callback user argument */
344         void* cb_arg;
345         /** original timeout in seconds from 'then' */
346         int timeout;
347
348         /** next in pending list */
349         struct fake_pending* next;
350         /** the buffer parsed into a sldns_pkt */
351         uint8_t* pkt;
352         size_t pkt_len;
353         /** by what transport was the query sent out */
354         enum transport_type transport;
355         /** if this is a serviced query */
356         int serviced;
357         /** if we are handling a multi pkt tcp stream, non 0 and the pkt nr*/
358         int tcp_pkt_counter;
359         /** the runtime structure this is part of */
360         struct replay_runtime* runtime;
361 };
362
363 /**
364  * An answer that is pending to happen.
365  */
366 struct replay_answer {
367         /** Next in list */
368         struct replay_answer* next;
369         /** reply information */
370         struct comm_reply repinfo;
371         /** the answer preparsed as ldns pkt */
372         uint8_t* pkt;
373         size_t pkt_len;
374 };
375
376 /**
377  * Timers with callbacks, fake replay version.
378  */
379 struct fake_timer {
380         /** next in list */
381         struct fake_timer* next;
382         /** the runtime structure this is part of */
383         struct replay_runtime* runtime;
384         /** the callback to call */
385         void (*cb)(void*);
386         /** the callback user argument */
387         void* cb_arg;
388         /** if timer is enabled */
389         int enabled;
390         /** when the timer expires */
391         struct timeval tv;
392 };
393
394 /**
395  * Replay macro variable.  And its value.
396  */
397 struct replay_var {
398         /** rbtree node. Key is this structure. Sorted by name. */
399         rbnode_type node;
400         /** the variable name */
401         char* name;
402         /** the variable value */
403         char* value;
404 };
405
406 /**
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.
412  */
413 struct replay_scenario* replay_scenario_read(FILE* in, const char* name, 
414         int* lineno);
415
416 /**
417  * Delete scenario.
418  * @param scen: to delete.
419  */
420 void replay_scenario_delete(struct replay_scenario* scen);
421
422 /** compare two replay_vars */
423 int replay_var_compare(const void* a, const void* b);
424
425 /** get oldest enabled fake timer */
426 struct fake_timer* replay_get_oldest_timer(struct replay_runtime* runtime);
427
428 /**
429  * Create variable storage
430  * @return new or NULL on failure.
431  */
432 rbtree_type* macro_store_create(void);
433
434 /**
435  * Delete variable storage
436  * @param store: the macro storage to free up.
437  */
438 void macro_store_delete(rbtree_type* store);
439
440 /**
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.
446  */
447 char* macro_process(rbtree_type* store, struct replay_runtime* runtime, 
448         char* text);
449
450 /**
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.
456  */
457 char* macro_lookup(rbtree_type* store, char* name);
458
459 /**
460  * Set macro value.
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.
465  */
466 int macro_assign(rbtree_type* store, char* name, char* value);
467
468 /** Print macro variables stored as debug info */
469 void macro_print_debug(rbtree_type* store);
470
471 /** testbounds self test */
472 void testbound_selftest(void);
473
474 #endif /* TESTCODE_REPLAY_H */