aboutsummaryrefslogtreecommitdiff
path: root/external/unbound/testcode/replay.h
diff options
context:
space:
mode:
Diffstat (limited to 'external/unbound/testcode/replay.h')
-rw-r--r--external/unbound/testcode/replay.h458
1 files changed, 458 insertions, 0 deletions
diff --git a/external/unbound/testcode/replay.h b/external/unbound/testcode/replay.h
new file mode 100644
index 000000000..05bd442f5
--- /dev/null
+++ b/external/unbound/testcode/replay.h
@@ -0,0 +1,458 @@
+/*
+ * testcode/replay.h - store and use a replay of events for the DNS resolver.
+ *
+ * Copyright (c) 2007, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file
+ * Store and use a replay of events for the DNS resolver.
+ * Used to test known scenarios to get known outcomes.
+ *
+ * <pre>
+ * File format for replay files.
+ *
+ * ; unbound.conf options.
+ * ; ...
+ * ; additional commandline options to pass to unbound
+ * COMMANDLINE cmdline_option
+ * ; autotrust key file contents, also adds auto-trust-anchor-file: "x" to cfg
+ * AUTOTRUST_FILE id
+ * ; contents of that file
+ * AUTOTRUST_END
+ * CONFIG_END
+ * ; comment line.
+ * SCENARIO_BEGIN name_of_scenario
+ * RANGE_BEGIN start_time end_time
+ * ; give ip of the virtual server, it matches any ip if not present.
+ * ADDRESS ip_address
+ * match_entries
+ * RANGE_END
+ * ; more RANGE items.
+ * ; go to the next moment
+ * STEP time_step event_type [ADDRESS ip_address]
+ * ; event_type can be:
+ * o NOTHING - nothing
+ * o QUERY - followed by entry
+ * o CHECK_ANSWER - followed by entry
+ * o CHECK_OUT_QUERY - followed by entry (if copy-id it is also reply).
+ * o REPLY - followed by entry
+ * o TIMEOUT
+ * o TIME_PASSES ELAPSE [seconds] - increase 'now' time counter, can be
+ * a floating point number.
+ * TIME_PASSES EVAL [macro] - expanded for seconds to move time.
+ * o TRAFFIC - like CHECK_ANSWER, causes traffic to flow.
+ * actually the traffic flows before this step is taken.
+ * the step waits for traffic to stop.
+ * o CHECK_AUTOTRUST [id] - followed by FILE_BEGIN [to match] FILE_END.
+ * The file contents is macro expanded before match.
+ * o INFRA_RTT [ip] [dp] [rtt] - update infra cache entry with rtt.
+ * o ERROR
+ * ; following entry starts on the next line, ENTRY_BEGIN.
+ * ; more STEP items
+ * SCENARIO_END
+ *
+ * Calculations, a macro-like system: ${$myvar + 3600}
+ * STEP 10 ASSIGN myvar = 3600
+ * ; ASSIGN event. '=' is syntactic sugar here. 3600 is some expression.
+ * ${..} is macro expanded from its expression. Text substitution.
+ * o $var replaced with its value. var is identifier [azAZ09_]*
+ * o number is that number.
+ * o ${variables and arithmetic }
+ * o +, -, / and *. Note, evaluated left-to-right. Use ${} for brackets.
+ * So again, no precedence rules, so 2+3*4 == ${2+3}*4 = 20.
+ * Do 2+${3*4} to get 24.
+ * o ${function params}
+ * o ${time} is the current time for the simulated unbound.
+ * o ${ctime value} is the text ctime(value), Fri 3 Aug 2009, ...
+ * o ${timeout} is the time until next timeout in comm_timer list.
+ * o ${range lower value upper} checks if lower<=value<=upper
+ * returns value if check succeeds.
+ *
+ * ; Example file
+ * SCENARIO_BEGIN Example scenario
+ * RANGE_BEGIN 0 100
+ * ENTRY_BEGIN
+ * ; precoded answers to queries.
+ * ENTRY_END
+ * END_RANGE
+ * STEP 0 QUERY
+ * ENTRY_BEGIN
+ * ; query
+ * ENTRY_END
+ * ; a query is sent out to the network by resolver.
+ * ; precoded answer from range is returned.
+ * ; algorithm will do precoded answers from RANGE immediately, except if
+ * ; the next step specifically checks for that OUT_QUERY.
+ * ; or if none of the precoded answers match.
+ * STEP 1 CHECK_ANSWER
+ * ENTRY_BEGIN
+ * ; what the reply should look like
+ * ENTRY_END
+ * ; successful termination. (if the answer was OK).
+ * ; also, all answers must have been checked with CHECK_ANSWER.
+ * ; and, no more pending out_queries (that have not been checked).
+ * SCENARIO_END
+ *
+ * </pre>
+ */
+
+#ifndef TESTCODE_REPLAY_H
+#define TESTCODE_REPLAY_H
+#include "util/netevent.h"
+#include "testcode/testpkts.h"
+#include "util/rbtree.h"
+struct replay_answer;
+struct replay_moment;
+struct replay_range;
+struct fake_pending;
+struct fake_timer;
+struct replay_var;
+struct infra_cache;
+struct sldns_buffer;
+
+/**
+ * A replay scenario.
+ */
+struct replay_scenario {
+ /** name of replay scenario. malloced string. */
+ char* title;
+
+ /** The list of replay moments. Linked list. Time increases in list. */
+ struct replay_moment* mom_first;
+ /** The last element in list of replay moments. */
+ struct replay_moment* mom_last;
+
+ /**
+ * List of matching answers. This is to ease replay scenario
+ * creation. It lists queries (to the network) and what answer
+ * should be returned. The matching answers are valid for a range
+ * of time steps.
+ * So: timestep, parts of query, destination --> answer.
+ */
+ struct replay_range* range_list;
+};
+
+/**
+ * A replay moment.
+ * Basically, it consists of events to a fake select() call.
+ * This is a recording of an event that happens.
+ * And if output is presented, what is done with that.
+ */
+struct replay_moment {
+ /**
+ * The replay time step number. Starts at 0, time is incremented
+ * every time the fake select() is run.
+ */
+ int time_step;
+ /** Next replay moment in list of replay moments. */
+ struct replay_moment* mom_next;
+
+ /** what happens this moment? */
+ enum replay_event_type {
+ /** nothing happens, as if this event is not there. */
+ repevt_nothing,
+ /** incoming query */
+ repevt_front_query,
+ /** test fails if reply to query does not match */
+ repevt_front_reply,
+ /** timeout */
+ repevt_timeout,
+ /** time passes */
+ repevt_time_passes,
+ /** reply arrives from the network */
+ repevt_back_reply,
+ /** test fails if query to the network does not match */
+ repevt_back_query,
+ /** check autotrust key file */
+ repevt_autotrust_check,
+ /** an error happens to outbound query */
+ repevt_error,
+ /** assignment to a variable */
+ repevt_assign,
+ /** store infra rtt cache entry: addr and string (int) */
+ repevt_infra_rtt,
+ /** cause traffic to flow */
+ repevt_traffic
+ }
+ /** variable with what is to happen this moment */
+ evt_type;
+
+ /** The sent packet must match this. Incoming events, the data. */
+ struct entry* match;
+
+ /** the amount of time that passes */
+ struct timeval elapse;
+
+ /** address that must be matched, or packet remote host address. */
+ struct sockaddr_storage addr;
+ /** length of addr, if 0, then any address will do */
+ socklen_t addrlen;
+
+ /** macro name, for assign. */
+ char* variable;
+ /** string argument, for assign. */
+ char* string;
+
+ /** the autotrust file id to check */
+ char* autotrust_id;
+ /** file contents to match, one string per line */
+ struct config_strlist* file_content;
+};
+
+/**
+ * Range of timesteps, and canned replies to matching queries.
+ */
+struct replay_range {
+ /** time range when this is valid. Including start and end step. */
+ int start_step;
+ /** end step of time range. */
+ int end_step;
+ /** address of where this range is served. */
+ struct sockaddr_storage addr;
+ /** length of addr, if 0, then any address will do */
+ socklen_t addrlen;
+
+ /** Matching list */
+ struct entry* match;
+
+ /** next in list of time ranges. */
+ struct replay_range* next_range;
+};
+
+/**
+ * Replay storage of runtime information.
+ */
+struct replay_runtime {
+ /**
+ * The scenario
+ */
+ struct replay_scenario* scenario;
+ /**
+ * Current moment.
+ */
+ struct replay_moment* now;
+
+ /**
+ * List of pending queries in order they were sent out. First
+ * one has been sent out most recently. Last one in list is oldest.
+ */
+ struct fake_pending* pending_list;
+
+ /**
+ * List of answers to queries from clients. These need to be checked.
+ */
+ struct replay_answer* answer_list;
+
+ /** last element in answer list. */
+ struct replay_answer* answer_last;
+
+ /** list of fake timer callbacks that are pending */
+ struct fake_timer* timer_list;
+
+ /** callback to call for incoming queries */
+ comm_point_callback_t* callback_query;
+ /** user argument for incoming query callback */
+ void *cb_arg;
+
+ /** ref the infra cache (was passed to outside_network_create) */
+ struct infra_cache* infra;
+
+ /** the current time in seconds */
+ time_t now_secs;
+ /** the current time in microseconds */
+ struct timeval now_tv;
+
+ /** signal handler callback */
+ void (*sig_cb)(int, void*);
+ /** signal handler user arg */
+ void *sig_cb_arg;
+ /** time to exit cleanly */
+ int exit_cleanly;
+
+ /** size of buffers */
+ size_t bufsize;
+
+ /**
+ * Tree of macro values. Of type replay_var
+ */
+ rbtree_t* vars;
+};
+
+/**
+ * Pending queries to network, fake replay version.
+ */
+struct fake_pending {
+ /** what is important only that we remember the query, copied here. */
+ struct sldns_buffer* buffer;
+ /** and to what address this is sent to. */
+ struct sockaddr_storage addr;
+ /** len of addr */
+ socklen_t addrlen;
+ /** zone name, uncompressed wire format (as used when sent) */
+ uint8_t* zone;
+ /** length of zone name */
+ size_t zonelen;
+ /** qtype */
+ int qtype;
+ /** The callback function to call when answer arrives (or timeout) */
+ comm_point_callback_t* callback;
+ /** callback user argument */
+ void* cb_arg;
+ /** original timeout in seconds from 'then' */
+ int timeout;
+
+ /** next in pending list */
+ struct fake_pending* next;
+ /** the buffer parsed into a sldns_pkt */
+ uint8_t* pkt;
+ size_t pkt_len;
+ /** by what transport was the query sent out */
+ enum transport_type transport;
+ /** if this is a serviced query */
+ int serviced;
+ /** the runtime structure this is part of */
+ struct replay_runtime* runtime;
+};
+
+/**
+ * An answer that is pending to happen.
+ */
+struct replay_answer {
+ /** Next in list */
+ struct replay_answer* next;
+ /** reply information */
+ struct comm_reply repinfo;
+ /** the answer preparsed as ldns pkt */
+ uint8_t* pkt;
+ size_t pkt_len;
+};
+
+/**
+ * Timers with callbacks, fake replay version.
+ */
+struct fake_timer {
+ /** next in list */
+ struct fake_timer* next;
+ /** the runtime structure this is part of */
+ struct replay_runtime* runtime;
+ /** the callback to call */
+ void (*cb)(void*);
+ /** the callback user argument */
+ void* cb_arg;
+ /** if timer is enabled */
+ int enabled;
+ /** when the timer expires */
+ struct timeval tv;
+};
+
+/**
+ * Replay macro variable. And its value.
+ */
+struct replay_var {
+ /** rbtree node. Key is this structure. Sorted by name. */
+ rbnode_t node;
+ /** the variable name */
+ char* name;
+ /** the variable value */
+ char* value;
+};
+
+/**
+ * Read a replay scenario from the file.
+ * @param in: file to read from.
+ * @param name: name to print in errors.
+ * @param lineno: incremented for every line read.
+ * @return: Scenario. NULL if no scenario read.
+ */
+struct replay_scenario* replay_scenario_read(FILE* in, const char* name,
+ int* lineno);
+
+/**
+ * Delete scenario.
+ * @param scen: to delete.
+ */
+void replay_scenario_delete(struct replay_scenario* scen);
+
+/** compare two replay_vars */
+int replay_var_compare(const void* a, const void* b);
+
+/** get oldest enabled fake timer */
+struct fake_timer* replay_get_oldest_timer(struct replay_runtime* runtime);
+
+/**
+ * Create variable storage
+ * @return new or NULL on failure.
+ */
+rbtree_t* macro_store_create(void);
+
+/**
+ * Delete variable storage
+ * @param store: the macro storage to free up.
+ */
+void macro_store_delete(rbtree_t* store);
+
+/**
+ * Apply macro substitution to string.
+ * @param store: variable store.
+ * @param runtime: the runtime to look up values as needed.
+ * @param text: string to work on.
+ * @return newly malloced string with result.
+ */
+char* macro_process(rbtree_t* store, struct replay_runtime* runtime,
+ char* text);
+
+/**
+ * Look up a macro value. Like calling ${$name}.
+ * @param store: variable store
+ * @param name: macro name
+ * @return newly malloced string with result or strdup("") if not found.
+ * or NULL on malloc failure.
+ */
+char* macro_lookup(rbtree_t* store, char* name);
+
+/**
+ * Set macro value.
+ * @param store: variable store
+ * @param name: macro name
+ * @param value: text to set it to. Not expanded.
+ * @return false on failure.
+ */
+int macro_assign(rbtree_t* store, char* name, char* value);
+
+/** Print macro variables stored as debug info */
+void macro_print_debug(rbtree_t* store);
+
+/** testbounds self test */
+void testbound_selftest(void);
+
+#endif /* TESTCODE_REPLAY_H */