1 /* 2 * testpkts. Data file parse for test packets, and query matching. 3 * 4 * Data storage for specially crafted replies for testing purposes. 5 * 6 * (c) NLnet Labs, 2005, 2006, 2007 7 * See the file LICENSE for the license 8 */ 9 10 #ifndef TESTPKTS_H 11 #define TESTPKTS_H 12 struct sldns_buffer; 13 struct sldns_file_parse_state; 14 15 /** 16 * \file 17 * 18 * This is a debugging aid. It is not efficient, especially 19 * with a long config file, but it can give any reply to any query. 20 * This can help the developer pre-script replies for queries. 21 * 22 * You can specify a packet RR by RR with header flags to return. 23 * 24 * Missing features: 25 * - matching content different from reply content. 26 * - find way to adjust mangled packets? 27 * 28 */ 29 30 /* 31 The data file format is as follows: 32 33 ; comment. 34 ; a number of entries, these are processed first to last. 35 ; a line based format. 36 37 $ORIGIN origin 38 $TTL default_ttl 39 40 ENTRY_BEGIN 41 ; first give MATCH lines, that say what queries are matched 42 ; by this entry. 43 ; 'opcode' makes the query match the opcode from the reply; 44 ; if you leave it out, any opcode matches this entry. 45 ; 'qtype' makes the query match the qtype from the reply. 46 ; 'qname' makes the query match the qname from the reply. 47 ; 'subdomain' makes the query match subdomains of qname from the reply. 48 ; 'serial=1023' makes the query match if ixfr serial is 1023. 49 ; 'all' has to match header byte for byte and all rrs in packet. 50 ; 'all_noedns' has to match header byte for byte and all rrs in packet; 51 ; ignoring EDNS. 52 ; 'ttl' used with all, rrs in packet must also have matching TTLs. 53 ; 'DO' will match only queries with DO bit set. 54 ; 'noedns' matches queries without EDNS OPT records. 55 ; 'rcode' makes the query match the rcode from the reply. 56 ; 'question' makes the query match the question section. 57 ; 'answer' makes the query match the answer section. 58 ; 'ednsdata' matches queries to HEX_EDNS section. 59 ; 'UDP' matches if the transport is UDP. 60 ; 'TCP' matches if the transport is TCP. 61 ; 'ede=2' makes the query match if the EDNS EDE info-code is 2. 62 ; It also snips the EDE record out of the packet to facilitate 63 ; other matches. 64 ; 'ede=any' makes the query match any EDNS EDE info-code. 65 ; It also snips the EDE record out of the packet to facilitate 66 ; other matches. 67 MATCH [opcode] [qtype] [qname] [serial=<value>] [all] [ttl] 68 MATCH [UDP|TCP] DO 69 MATCH ... 70 ; Then the REPLY header is specified. 71 REPLY opcode, rcode or flags. 72 (opcode) QUERY IQUERY STATUS NOTIFY UPDATE 73 (rcode) NOERROR FORMERR SERVFAIL NXDOMAIN NOTIMPL YXDOMAIN 74 YXRRSET NXRRSET NOTAUTH NOTZONE 75 (flags) QR AA TC RD CD RA AD DO 76 REPLY ... 77 ; any additional actions to do. 78 ; 'copy_id' copies the ID from the query to the answer. 79 ADJUST copy_id 80 ; 'copy_query' copies the query name, type and class to the answer. 81 ADJUST copy_query 82 ; 'sleep=10' sleeps for 10 seconds before giving the answer (TCP is open) 83 ADJUST [sleep=<num>] ; sleep before giving any reply 84 ADJUST [packet_sleep=<num>] ; sleep before this packet in sequence 85 ; 'copy_ednsdata_assume_clientsubnet' copies ednsdata to reply, assumes 86 ; it is clientsubnet and adjusts scopemask to match sourcemask. 87 ADJUST copy_ednsdata_assume_clientsubnet 88 ; 'increment_ecs_scope' increments the ECS scope copied from the 89 ; sourcemask by one. 90 ADJUST increment_ecs_scope 91 SECTION QUESTION 92 <RRs, one per line> ; the RRcount is determined automatically. 93 SECTION ANSWER 94 <RRs, one per line> 95 SECTION AUTHORITY 96 <RRs, one per line> 97 SECTION ADDITIONAL 98 <RRs, one per line> 99 EXTRA_PACKET ; follow with SECTION, REPLY for more packets. 100 HEX_ANSWER_BEGIN ; follow with hex data 101 ; this replaces any answer packet constructed 102 ; with the SECTION keywords (only SECTION QUERY 103 ; is used to match queries). If the data cannot 104 ; be parsed, ADJUST rules for the answer packet 105 ; are ignored. Only copy_id is done. 106 HEX_ANSWER_END 107 HEX_EDNS_BEGIN ; follow with hex data. 108 ; Raw EDNS data to match against. It must be an 109 ; exact match (all options are matched) and will be 110 ; evaluated only when 'MATCH ednsdata' given. 111 HEX_EDNS_END 112 ENTRY_END 113 114 115 Example data file: 116 $ORIGIN nlnetlabs.nl 117 $TTL 3600 118 119 ENTRY_BEGIN 120 MATCH qname 121 REPLY NOERROR 122 ADJUST copy_id 123 SECTION QUESTION 124 www.nlnetlabs.nl. IN A 125 SECTION ANSWER 126 www.nlnetlabs.nl. IN A 195.169.215.155 127 SECTION AUTHORITY 128 nlnetlabs.nl. IN NS www.nlnetlabs.nl. 129 ENTRY_END 130 131 ENTRY_BEGIN 132 MATCH qname 133 REPLY NOERROR 134 ADJUST copy_id 135 SECTION QUESTION 136 www2.nlnetlabs.nl. IN A 137 HEX_ANSWER_BEGIN 138 ; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 139 ;-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 140 00 bf 81 80 00 01 00 01 00 02 00 02 03 77 77 77 0b 6b 61 6e ; 1- 20 141 61 72 69 65 70 69 65 74 03 63 6f 6d 00 00 01 00 01 03 77 77 ; 21- 40 142 77 0b 6b 61 6e 61 72 69 65 70 69 65 74 03 63 6f 6d 00 00 01 ; 41- 60 143 00 01 00 01 50 8b 00 04 52 5e ed 32 0b 6b 61 6e 61 72 69 65 ; 61- 80 144 70 69 65 74 03 63 6f 6d 00 00 02 00 01 00 01 50 8b 00 11 03 ; 81- 100 145 6e 73 31 08 68 65 78 6f 6e 2d 69 73 02 6e 6c 00 0b 6b 61 6e ; 101- 120 146 61 72 69 65 70 69 65 74 03 63 6f 6d 00 00 02 00 01 00 01 50 ; 121- 140 147 8b 00 11 03 6e 73 32 08 68 65 78 6f 6e 2d 69 73 02 6e 6c 00 ; 141- 160 148 03 6e 73 31 08 68 65 78 6f 6e 2d 69 73 02 6e 6c 00 00 01 00 ; 161- 180 149 01 00 00 46 53 00 04 52 5e ed 02 03 6e 73 32 08 68 65 78 6f ; 181- 200 150 6e 2d 69 73 02 6e 6c 00 00 01 00 01 00 00 46 53 00 04 d4 cc ; 201- 220 151 db 5b 152 HEX_ANSWER_END 153 ENTRY_END 154 155 156 157 note that this file will link with your 158 void verbose(int level, char* format, ...); output function. 159 */ 160 161 /** Type of transport, since some entries match based on UDP or TCP of query */ 162 enum transport_type {transport_any = 0, transport_udp, transport_tcp }; 163 164 /** struct to keep a linked list of reply packets for a query */ 165 struct reply_packet { 166 /** next in list of reply packets, for TCP multiple pkts on wire */ 167 struct reply_packet* next; 168 /** the reply pkt */ 169 uint8_t* reply_pkt; 170 /** length of reply pkt */ 171 size_t reply_len; 172 /** Additional EDNS data for matching queries. */ 173 struct sldns_buffer* raw_ednsdata; 174 /** or reply pkt in hex if not parsable */ 175 struct sldns_buffer* reply_from_hex; 176 /** seconds to sleep before giving packet */ 177 unsigned int packet_sleep; 178 }; 179 180 /** data structure to keep the canned queries in. 181 format is the 'matching query' and the 'canned answer' */ 182 struct entry { 183 /* match */ 184 /* How to match an incoming query with this canned reply */ 185 /** match query opcode with answer opcode */ 186 uint8_t match_opcode; 187 /** match qtype with answer qtype */ 188 uint8_t match_qtype; 189 /** match qname with answer qname */ 190 uint8_t match_qname; 191 /** match rcode with answer rcode */ 192 uint8_t match_rcode; 193 /** match question section */ 194 uint8_t match_question; 195 /** match answer section */ 196 uint8_t match_answer; 197 /** match qname as subdomain of answer qname */ 198 uint8_t match_subdomain; 199 /** match SOA serial number, from auth section */ 200 uint8_t match_serial; 201 /** match EDNS EDE info-code */ 202 uint8_t match_ede; 203 /** match any EDNS EDE info-code */ 204 uint8_t match_ede_any; 205 /** match all of the packet */ 206 uint8_t match_all; 207 /** match all of the packet; ignore EDNS */ 208 uint8_t match_all_noedns; 209 /** match ttls in the packet */ 210 uint8_t match_ttl; 211 /** match DO bit */ 212 uint8_t match_do; 213 /** match absence of EDNS OPT record in query */ 214 uint8_t match_noedns; 215 /** match edns data field given in hex */ 216 uint8_t match_ednsdata_raw; 217 /** match query serial with this value. */ 218 uint32_t ixfr_soa_serial; 219 /** match on UDP/TCP */ 220 enum transport_type match_transport; 221 /** match EDNS EDE info-code with this value. */ 222 uint16_t ede_info_code; 223 224 /** pre canned reply */ 225 struct reply_packet *reply_list; 226 227 /** how to adjust the reply packet */ 228 /** copy over the ID from the query into the answer */ 229 uint8_t copy_id; 230 /** copy the query nametypeclass from query into the answer */ 231 uint8_t copy_query; 232 /** copy ednsdata to reply, assume it is clientsubnet and 233 * adjust scopemask to match sourcemask */ 234 uint8_t copy_ednsdata_assume_clientsubnet; 235 /** increment the ECS scope copied from the sourcemask by one */ 236 uint8_t increment_ecs_scope; 237 /** in seconds */ 238 unsigned int sleeptime; 239 240 /** some number that names this entry, line number in file or so */ 241 int lineno; 242 243 /** next in list */ 244 struct entry* next; 245 }; 246 247 /** 248 * reads the canned reply file and returns a list of structs 249 * does an exit on error. 250 * @param name: name of the file to read. 251 * @param skip_whitespace: skip leftside whitespace. 252 */ 253 struct entry* read_datafile(const char* name, int skip_whitespace); 254 255 /** 256 * Delete linked list of entries. 257 */ 258 void delete_entry(struct entry* list); 259 260 /** 261 * Read one entry from the data file. 262 * @param in: file to read from. Filepos must be at the start of a new line. 263 * @param name: name of the file for prettier errors. 264 * @param pstate: file parse state with lineno, default_ttl, 265 * origin and prev_rr name. 266 * @param skip_whitespace: skip leftside whitespace. 267 * @return: The entry read (malloced) or NULL if no entry could be read. 268 */ 269 struct entry* read_entry(FILE* in, const char* name, 270 struct sldns_file_parse_state* pstate, int skip_whitespace); 271 272 /** 273 * finds entry in list, or returns NULL. 274 */ 275 struct entry* find_match(struct entry* entries, uint8_t* query_pkt, 276 size_t query_pkt_len, enum transport_type transport); 277 278 /** 279 * match two packets, all must match 280 * @param q: packet 1 281 * @param qlen: length of q. 282 * @param p: packet 2 283 * @param plen: length of p. 284 * @param mttl: if true, ttls must match, if false, ttls do not need to match 285 * @param noloc: if true, rrs may be reordered in their packet-section. 286 * rrs are then matches without location of the rr being important. 287 * @param noedns: if true, edns is not compared, if false, edns must match. 288 * @return true if matched. 289 */ 290 int match_all(uint8_t* q, size_t qlen, uint8_t* p, size_t plen, int mttl, 291 int noloc, int noedns); 292 293 /** 294 * copy & adjust packet, mallocs a copy. 295 */ 296 void adjust_packet(struct entry* match, uint8_t** answer_pkt, 297 size_t* answer_pkt_len, uint8_t* query_pkt, size_t query_pkt_len); 298 299 /** 300 * Parses data buffer to a query, finds the correct answer 301 * and calls the given function for every packet to send. 302 * if verbose_out filename is given, packets are dumped there. 303 * @param inbuf: the packet that came in 304 * @param inlen: length of packet. 305 * @param entries: entries read in from datafile. 306 * @param count: is increased to count number of queries answered. 307 * @param transport: set to UDP or TCP to match some types of entries. 308 * @param sendfunc: called to send answer (buffer, size, userarg). 309 * @param userdata: userarg to give to sendfunc. 310 * @param verbose_out: if not NULL, verbose messages are printed there. 311 */ 312 void handle_query(uint8_t* inbuf, ssize_t inlen, struct entry* entries, 313 int* count, enum transport_type transport, 314 void (*sendfunc)(uint8_t*, size_t, void*), void* userdata, 315 FILE* verbose_out); 316 317 #endif /* TESTPKTS_H */ 318