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