2007-02-08 14:55:53 +00:00
|
|
|
/*
|
|
|
|
* 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 REGENTS 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.
|
|
|
|
*
|
|
|
|
* ; comment line.
|
2007-02-09 13:46:11 +00:00
|
|
|
* SCENARIO_BEGIN name_of_scenario
|
|
|
|
* RANGE_BEGIN start_time end_time
|
2007-02-08 14:55:53 +00:00
|
|
|
* match_entries
|
2007-02-09 13:46:11 +00:00
|
|
|
* RANGE_END
|
2007-02-08 16:03:26 +00:00
|
|
|
* ; more RANGE items.
|
2007-02-08 14:55:53 +00:00
|
|
|
* ; go to the next moment
|
|
|
|
* STEP time_step event_type
|
|
|
|
* ; 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
|
|
|
|
* o REPLY - followed by entry
|
|
|
|
* o TIMEOUT
|
2007-02-08 16:03:26 +00:00
|
|
|
* o ERROR
|
2007-02-08 14:55:53 +00:00
|
|
|
* ; following entry starts on the next line, ENTRY_BEGIN.
|
2007-02-08 16:03:26 +00:00
|
|
|
* SCENARIO_END
|
2007-02-08 14:55:53 +00:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* ; Example file
|
2007-02-09 13:46:11 +00:00
|
|
|
* SCENARIO_BEGIN Example scenario
|
|
|
|
* RANGE_BEGIN 0 100
|
2007-02-08 14:55:53 +00:00
|
|
|
* 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 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).
|
2007-02-08 16:03:26 +00:00
|
|
|
* SCENARIO_END
|
2007-02-08 14:55:53 +00:00
|
|
|
*
|
|
|
|
* </pre>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef TESTCODE_REPLAY_H
|
|
|
|
#define TESTCODE_REPLAY_H
|
|
|
|
#include "config.h"
|
|
|
|
#include "util/netevent.h"
|
2007-02-09 16:39:47 +00:00
|
|
|
#include "testcode/ldns-testpkts.h"
|
2007-02-08 14:55:53 +00:00
|
|
|
struct replay_moment;
|
|
|
|
struct fake_pending;
|
|
|
|
struct replay_answer;
|
|
|
|
struct replay_range;
|
|
|
|
struct entry;
|
|
|
|
|
2007-02-08 16:03:26 +00:00
|
|
|
|
2007-02-08 14:55:53 +00:00
|
|
|
/**
|
|
|
|
* A replay scenario.
|
|
|
|
*/
|
|
|
|
struct replay_scenario {
|
2007-02-08 16:03:26 +00:00
|
|
|
/** name of replay scenario. malloced string. */
|
2007-02-09 13:46:11 +00:00
|
|
|
char* title;
|
2007-02-08 14:55:53 +00:00
|
|
|
|
|
|
|
/** 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.
|
|
|
|
*/
|
2007-02-09 13:46:11 +00:00
|
|
|
int time_step;
|
2007-02-08 14:55:53 +00:00
|
|
|
/** 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,
|
|
|
|
/** reply arrives from the network */
|
|
|
|
repevt_back_reply,
|
|
|
|
/** test fails if query to the network does not match */
|
|
|
|
repevt_back_query,
|
2007-02-08 16:03:26 +00:00
|
|
|
/** an error happens to outbound query */
|
2007-02-09 13:46:11 +00:00
|
|
|
repevt_error
|
2007-02-08 14:55:53 +00:00
|
|
|
} evt_type;
|
|
|
|
|
|
|
|
/** The sent packet must match this. Incoming events, the data. */
|
|
|
|
struct entry* match;
|
|
|
|
|
|
|
|
/** what pending query should timeout or is answered. or
|
|
|
|
* NULL for last sent query. */
|
|
|
|
ldns_rr* qname;
|
|
|
|
};
|
|
|
|
|
2007-02-08 16:03:26 +00:00
|
|
|
/**
|
|
|
|
* Range of timesteps, and canned replies to matching queries.
|
|
|
|
*/
|
|
|
|
struct replay_range {
|
|
|
|
/** time range when this is valid. Including start and end step. */
|
2007-02-09 13:46:11 +00:00
|
|
|
int start_step;
|
2007-02-08 16:03:26 +00:00
|
|
|
/** end step of time range. */
|
2007-02-09 13:46:11 +00:00
|
|
|
int end_step;
|
2007-02-08 16:03:26 +00:00
|
|
|
|
|
|
|
/** Matching list */
|
|
|
|
struct entry* match;
|
|
|
|
|
|
|
|
/** next in list of time ranges. */
|
|
|
|
struct replay_range* next_range;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Replay storage of runtime information.
|
|
|
|
*/
|
|
|
|
struct replay_runtime {
|
2007-02-09 16:39:47 +00:00
|
|
|
/**
|
|
|
|
* The scenario
|
|
|
|
*/
|
|
|
|
struct replay_scenario* scenario;
|
|
|
|
/**
|
|
|
|
* Current moment.
|
|
|
|
*/
|
|
|
|
struct replay_moment* now;
|
|
|
|
|
2007-02-08 16:03:26 +00:00
|
|
|
/**
|
|
|
|
* 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 from the matching list, that need to be returned
|
|
|
|
* to the program.
|
|
|
|
*/
|
|
|
|
struct replay_answer* answer_list;
|
|
|
|
|
|
|
|
/** callback for incoming queries */
|
|
|
|
comm_point_callback_t* callback_query;
|
|
|
|
/** user argument for incoming query callback */
|
|
|
|
void *cb_arg;
|
2007-02-09 16:39:47 +00:00
|
|
|
|
|
|
|
/** signal handler callback */
|
|
|
|
void (*sig_cb)(int, void*);
|
|
|
|
/** signal handler user arg */
|
|
|
|
void *sig_cb_arg;
|
2007-02-08 16:03:26 +00:00
|
|
|
};
|
|
|
|
|
2007-02-08 14:55:53 +00:00
|
|
|
/**
|
|
|
|
* Pending queries to network, fake replay version.
|
|
|
|
*/
|
|
|
|
struct fake_pending {
|
|
|
|
/** what is important only that we remember the query, copied here. */
|
|
|
|
ldns_buffer* buffer;
|
|
|
|
/** and to what address this is sent to. */
|
|
|
|
struct sockaddr_storage addr;
|
|
|
|
/** len of addr */
|
|
|
|
socklen_t addrlen;
|
2007-02-08 16:03:26 +00:00
|
|
|
/** The callback function to call when answer arrives (or timeout) */
|
2007-02-08 14:55:53 +00:00
|
|
|
comm_point_callback_t* callback;
|
|
|
|
/** callback user argument */
|
|
|
|
void* cb_arg;
|
2007-02-09 16:39:47 +00:00
|
|
|
|
|
|
|
/** next in pending list */
|
|
|
|
struct fake_pending* next;
|
|
|
|
/** the buffer parsed into a ldns_pkt */
|
|
|
|
ldns_pkt* pkt;
|
|
|
|
/** by what transport was the query sent out */
|
|
|
|
enum transport_type transport;
|
2007-02-08 14:55:53 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* An answer to a back-query, stored so it can be provided as an event.
|
|
|
|
*/
|
|
|
|
struct replay_answer {
|
|
|
|
/** Next in list */
|
|
|
|
struct replay_answer* next;
|
|
|
|
/** pending question this is an answer to */
|
|
|
|
struct fake_pending* question;
|
|
|
|
/** The answer. */
|
|
|
|
ldns_buffer* buf;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2007-02-08 16:03:26 +00:00
|
|
|
* Read a replay scenario from the file.
|
|
|
|
* @param in: file to read from.
|
|
|
|
* @return: Scenario. NULL if no scenario read.
|
2007-02-08 14:55:53 +00:00
|
|
|
*/
|
2007-02-08 16:03:26 +00:00
|
|
|
struct replay_scenario* replay_scenario_read(FILE* in);
|
2007-02-08 14:55:53 +00:00
|
|
|
|
2007-02-08 16:03:26 +00:00
|
|
|
/**
|
|
|
|
* Delete scenario.
|
|
|
|
* @param scen: to delete.
|
|
|
|
*/
|
|
|
|
void replay_scenario_delete(struct replay_scenario* scen);
|
2007-02-08 14:55:53 +00:00
|
|
|
|
|
|
|
#endif /* TESTCODE_REPLAY_H */
|