1/* 2 * testcode/fake_event.c - fake event handling that replays existing scenario. 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 * Event service that replays a scenario. 39 * This implements the same exported symbols as the files: 40 * util/netevent.c 41 * services/listen_dnsport.c 42 * services/outside_network.c 43 * But these do not actually access the network or events, instead 44 * the scenario is played. 45 */ 46 47#include "config.h" 48#include "testcode/fake_event.h" 49#include "util/netevent.h" 50#include "util/net_help.h" 51#include "util/data/msgparse.h" 52#include "util/data/msgreply.h" 53#include "util/data/msgencode.h" 54#include "util/data/dname.h" 55#include "util/edns.h" 56#include "util/config_file.h" 57#include "services/listen_dnsport.h" 58#include "services/outside_network.h" 59#include "services/cache/infra.h" 60#include "testcode/replay.h" 61#include "testcode/testpkts.h" 62#include "util/log.h" 63#include "util/fptr_wlist.h" 64#include "sldns/sbuffer.h" 65#include "sldns/wire2str.h" 66#include "sldns/str2wire.h" 67#include <signal.h> 68struct worker; 69struct daemon_remote; 70 71/** unique code to check that fake_commpoint is that structure */ 72#define FAKE_COMMPOINT_TYPECODE 97347923 73/** fake commpoint, stores information */ 74struct fake_commpoint { 75 /** typecode */ 76 int typecode; 77 /** if this is a udp outgoing type of commpoint */ 78 int type_udp_out; 79 /** if this is a tcp outgoing type of commpoint */ 80 int type_tcp_out; 81 /** if this is a http outgoing type of commpoint. */ 82 int type_http_out; 83 84 /** the callback, stored for usage */ 85 comm_point_callback_type* cb; 86 /** the callback userarg, stored for usage */ 87 void* cb_arg; 88 /** runtime ptr */ 89 struct replay_runtime* runtime; 90 /** the pending entry for this commpoint (if any) */ 91 struct fake_pending* pending; 92}; 93 94/** Global variable: the scenario. Saved here for when event_init is done. */ 95static struct replay_scenario* saved_scenario = NULL; 96 97/** add timers and the values do not overflow or become negative */ 98static void 99timeval_add(struct timeval* d, const struct timeval* add) 100{ 101#ifndef S_SPLINT_S 102 d->tv_sec += add->tv_sec; 103 d->tv_usec += add->tv_usec; 104 if(d->tv_usec >= 1000000) { 105 d->tv_usec -= 1000000; 106 d->tv_sec++; 107 } 108#endif 109} 110 111void 112fake_temp_file(const char* adj, const char* id, char* buf, size_t len) 113{ 114#ifdef USE_WINSOCK 115 snprintf(buf, len, "testbound_%u%s%s.tmp", 116 (unsigned)getpid(), adj, id); 117#else 118 snprintf(buf, len, "/tmp/testbound_%u%s%s.tmp", 119 (unsigned)getpid(), adj, id); 120#endif 121} 122 123void 124fake_event_init(struct replay_scenario* scen) 125{ 126 saved_scenario = scen; 127} 128 129void 130fake_event_cleanup(void) 131{ 132 replay_scenario_delete(saved_scenario); 133 saved_scenario = NULL; 134} 135 136/** helper function that logs a sldns_pkt packet to logfile */ 137static void 138log_pkt(const char* desc, uint8_t* pkt, size_t len) 139{ 140 char* str = sldns_wire2str_pkt(pkt, len); 141 if(!str) 142 fatal_exit("%s: (failed out of memory wire2str_pkt)", desc); 143 else { 144 log_info("%s%s", desc, str); 145 free(str); 146 } 147} 148 149/** 150 * Returns a string describing the event type. 151 */ 152static const char* 153repevt_string(enum replay_event_type t) 154{ 155 switch(t) { 156 case repevt_nothing: return "NOTHING"; 157 case repevt_front_query: return "QUERY"; 158 case repevt_front_reply: return "CHECK_ANSWER"; 159 case repevt_timeout: return "TIMEOUT"; 160 case repevt_time_passes: return "TIME_PASSES"; 161 case repevt_back_reply: return "REPLY"; 162 case repevt_back_query: return "CHECK_OUT_QUERY"; 163 case repevt_autotrust_check: return "CHECK_AUTOTRUST"; 164 case repevt_tempfile_check: return "CHECK_TEMPFILE"; 165 case repevt_error: return "ERROR"; 166 case repevt_assign: return "ASSIGN"; 167 case repevt_traffic: return "TRAFFIC"; 168 case repevt_infra_rtt: return "INFRA_RTT"; 169 default: return "UNKNOWN"; 170 } 171} 172 173/** delete a fake pending */ 174static void 175delete_fake_pending(struct fake_pending* pend) 176{ 177 if(!pend) 178 return; 179 free(pend->zone); 180 sldns_buffer_free(pend->buffer); 181 free(pend->pkt); 182 free(pend); 183} 184 185/** delete a replay answer */ 186static void 187delete_replay_answer(struct replay_answer* a) 188{ 189 if(!a) 190 return; 191 if(a->repinfo.c) { 192 sldns_buffer_free(a->repinfo.c->buffer); 193 free(a->repinfo.c); 194 } 195 free(a->pkt); 196 free(a); 197} 198 199/** 200 * return: true if pending query matches the now event. 201 */ 202static int 203pending_matches_current(struct replay_runtime* runtime, 204 struct entry** entry, struct fake_pending **pend) 205{ 206 struct fake_pending* p; 207 struct entry* e; 208 if(!runtime->now || runtime->now->evt_type != repevt_back_query 209 || !runtime->pending_list) 210 return 0; 211 /* see if any of the pending queries matches */ 212 for(p = runtime->pending_list; p; p = p->next) { 213 if(runtime->now->addrlen != 0 && 214 sockaddr_cmp(&p->addr, p->addrlen, &runtime->now->addr, 215 runtime->now->addrlen) != 0) 216 continue; 217 if((e=find_match(runtime->now->match, p->pkt, p->pkt_len, 218 p->transport))) { 219 *entry = e; 220 *pend = p; 221 return 1; 222 } 223 } 224 return 0; 225} 226 227/** 228 * Find the range that matches this pending message. 229 * @param runtime: runtime with current moment, and range list. 230 * @param entry: returns the pointer to entry that matches. 231 * @param pend: the pending that the entry must match. 232 * @return: true if a match is found. 233 */ 234static int 235pending_find_match(struct replay_runtime* runtime, struct entry** entry, 236 struct fake_pending* pend) 237{ 238 int timenow = runtime->now->time_step; 239 struct replay_range* p = runtime->scenario->range_list; 240 while(p) { 241 if(p->start_step <= timenow && timenow <= p->end_step && 242 (p->addrlen == 0 || sockaddr_cmp(&p->addr, p->addrlen, 243 &pend->addr, pend->addrlen) == 0) && 244 (*entry = find_match(p->match, pend->pkt, pend->pkt_len, 245 pend->transport))) { 246 log_info("matched query time %d in range [%d, %d] " 247 "with entry line %d", timenow, 248 p->start_step, p->end_step, (*entry)->lineno); 249 if(p->addrlen != 0) 250 log_addr(0, "matched ip", &p->addr, p->addrlen); 251 log_pkt("matched pkt: ", 252 (*entry)->reply_list->reply_pkt, 253 (*entry)->reply_list->reply_len); 254 return 1; 255 } 256 p = p->next_range; 257 } 258 return 0; 259} 260 261/** 262 * See if outgoing pending query matches an entry. 263 * @param runtime: runtime. 264 * @param entry: if true, the entry that matches is returned. 265 * @param pend: if true, the outgoing message that matches is returned. 266 * @return: true if pending query matches the now event. 267 */ 268static int 269pending_matches_range(struct replay_runtime* runtime, 270 struct entry** entry, struct fake_pending** pend) 271{ 272 struct fake_pending* p = runtime->pending_list; 273 /* slow, O(N*N), but it works as advertised with weird matching */ 274 while(p) { 275 if(p->tcp_pkt_counter != 0) { 276 /* continue tcp transfer */ 277 *pend = p; 278 return 1; 279 } 280 if(pending_find_match(runtime, entry, p)) { 281 *pend = p; 282 return 1; 283 } 284 p = p->next; 285 } 286 return 0; 287} 288 289/** 290 * Remove the item from the pending list. 291 */ 292static void 293pending_list_delete(struct replay_runtime* runtime, struct fake_pending* pend) 294{ 295 struct fake_pending** prev = &runtime->pending_list; 296 struct fake_pending* p = runtime->pending_list; 297 298 while(p) { 299 if(p == pend) { 300 *prev = p->next; 301 delete_fake_pending(pend); 302 return; 303 } 304 305 prev = &p->next; 306 p = p->next; 307 } 308} 309 310/** number of replies in entry */ 311static int 312count_reply_packets(struct entry* entry) 313{ 314 int count = 0; 315 struct reply_packet* reppkt = entry->reply_list; 316 while(reppkt) { 317 count++; 318 reppkt = reppkt->next; 319 } 320 return count; 321} 322 323/** 324 * Fill buffer with reply from the entry. 325 */ 326static void 327fill_buffer_with_reply(sldns_buffer* buffer, struct entry* entry, uint8_t* q, 328 size_t qlen, int tcp_pkt_counter) 329{ 330 struct reply_packet* reppkt; 331 uint8_t* c; 332 size_t clen; 333 log_assert(entry && entry->reply_list); 334 sldns_buffer_clear(buffer); 335 reppkt = entry->reply_list; 336 if(tcp_pkt_counter > 0) { 337 int i = tcp_pkt_counter; 338 while(reppkt && i--) 339 reppkt = reppkt->next; 340 if(!reppkt) fatal_exit("extra packet read from TCP stream but none is available"); 341 log_pkt("extra_packet ", reppkt->reply_pkt, reppkt->reply_len); 342 } 343 if(reppkt->reply_from_hex) { 344 c = sldns_buffer_begin(reppkt->reply_from_hex); 345 clen = sldns_buffer_limit(reppkt->reply_from_hex); 346 if(!c) fatal_exit("out of memory"); 347 } else { 348 c = reppkt->reply_pkt; 349 clen = reppkt->reply_len; 350 } 351 if(c) { 352 if(q) adjust_packet(entry, &c, &clen, q, qlen); 353 sldns_buffer_write(buffer, c, clen); 354 if(q) free(c); 355 } 356 sldns_buffer_flip(buffer); 357} 358 359/** 360 * Perform range entry on pending message. 361 * @param runtime: runtime buffer size preference. 362 * @param entry: entry that codes for the reply to do. 363 * @param pend: pending query that is answered, callback called. 364 */ 365static void 366answer_callback_from_entry(struct replay_runtime* runtime, 367 struct entry* entry, struct fake_pending* pend) 368{ 369 struct comm_point c; 370 struct comm_reply repinfo; 371 void* cb_arg = pend->cb_arg; 372 comm_point_callback_type* cb = pend->callback; 373 374 memset(&c, 0, sizeof(c)); 375 c.fd = -1; 376 c.buffer = sldns_buffer_new(runtime->bufsize); 377 c.type = comm_udp; 378 if(pend->transport == transport_tcp) { 379 c.type = comm_tcp; 380 c.tcp_timeout_msec = 30000; 381 c.tcp_keepalive = runtime->tcp_seen_keepalive; 382 } 383 fill_buffer_with_reply(c.buffer, entry, pend->pkt, pend->pkt_len, 384 pend->tcp_pkt_counter); 385 repinfo.c = &c; 386 repinfo.addrlen = pend->addrlen; 387 memcpy(&repinfo.addr, &pend->addr, pend->addrlen); 388 if(!pend->serviced) { 389 if(entry && entry->reply_list->next && 390 pend->tcp_pkt_counter < count_reply_packets(entry)) { 391 /* go to next packet next time */ 392 pend->tcp_pkt_counter++; 393 } else { 394 pending_list_delete(runtime, pend); 395 } 396 } 397 if((*cb)(&c, cb_arg, NETEVENT_NOERROR, &repinfo)) { 398 fatal_exit("testbound: unexpected: callback returned 1"); 399 } 400 sldns_buffer_free(c.buffer); 401} 402 403/** Check the now moment answer check event */ 404static void 405answer_check_it(struct replay_runtime* runtime) 406{ 407 struct replay_answer* ans = runtime->answer_list, 408 *prev = NULL; 409 log_assert(runtime && runtime->now && 410 runtime->now->evt_type == repevt_front_reply); 411 while(ans) { 412 enum transport_type tr = transport_tcp; 413 if(ans->repinfo.c->type == comm_udp) 414 tr = transport_udp; 415 if((runtime->now->addrlen == 0 || sockaddr_cmp( 416 &runtime->now->addr, runtime->now->addrlen, 417 &ans->repinfo.addr, ans->repinfo.addrlen) == 0) && 418 find_match(runtime->now->match, ans->pkt, 419 ans->pkt_len, tr)) { 420 log_info("testbound matched event entry from line %d", 421 runtime->now->match->lineno); 422 log_info("testbound: do STEP %d %s", 423 runtime->now->time_step, 424 repevt_string(runtime->now->evt_type)); 425 if(prev) 426 prev->next = ans->next; 427 else runtime->answer_list = ans->next; 428 if(!ans->next) 429 runtime->answer_last = prev; 430 if(ans->repinfo.c->tcp_keepalive) 431 runtime->tcp_seen_keepalive = 1; 432 delete_replay_answer(ans); 433 return; 434 } else { 435 prev = ans; 436 ans = ans->next; 437 } 438 } 439 log_info("testbound: do STEP %d %s", runtime->now->time_step, 440 repevt_string(runtime->now->evt_type)); 441 fatal_exit("testbound: not matched"); 442} 443 444/** 445 * Create commpoint (as return address) for a fake incoming query. 446 */ 447static void 448fake_front_query(struct replay_runtime* runtime, struct replay_moment *todo) 449{ 450 struct comm_reply repinfo; 451 memset(&repinfo, 0, sizeof(repinfo)); 452 repinfo.c = (struct comm_point*)calloc(1, sizeof(struct comm_point)); 453 repinfo.addrlen = (socklen_t)sizeof(struct sockaddr_in); 454 if(todo->addrlen != 0) { 455 repinfo.addrlen = todo->addrlen; 456 memcpy(&repinfo.addr, &todo->addr, todo->addrlen); 457 } 458 repinfo.c->fd = -1; 459 repinfo.c->ev = (struct internal_event*)runtime; 460 repinfo.c->buffer = sldns_buffer_new(runtime->bufsize); 461 if(todo->match->match_transport == transport_tcp) { 462 repinfo.c->type = comm_tcp; 463 repinfo.c->tcp_timeout_msec = 30000; 464 repinfo.c->tcp_keepalive = runtime->tcp_seen_keepalive; 465 } else 466 repinfo.c->type = comm_udp; 467 fill_buffer_with_reply(repinfo.c->buffer, todo->match, NULL, 0, 0); 468 log_info("testbound: incoming QUERY"); 469 log_pkt("query pkt", todo->match->reply_list->reply_pkt, 470 todo->match->reply_list->reply_len); 471 /* call the callback for incoming queries */ 472 if((*runtime->callback_query)(repinfo.c, runtime->cb_arg, 473 NETEVENT_NOERROR, &repinfo)) { 474 /* send immediate reply */ 475 comm_point_send_reply(&repinfo); 476 } 477 /* clear it again, in case copy not done properly */ 478 memset(&repinfo, 0, sizeof(repinfo)); 479} 480 481/** 482 * Perform callback for fake pending message. 483 */ 484static void 485fake_pending_callback(struct replay_runtime* runtime, 486 struct replay_moment* todo, int error) 487{ 488 struct fake_pending* p = runtime->pending_list; 489 struct comm_reply repinfo; 490 struct comm_point c; 491 void* cb_arg; 492 comm_point_callback_type* cb; 493 494 memset(&c, 0, sizeof(c)); 495 if(!p) fatal_exit("No pending queries."); 496 cb_arg = p->cb_arg; 497 cb = p->callback; 498 c.buffer = sldns_buffer_new(runtime->bufsize); 499 c.type = comm_udp; 500 if(p->transport == transport_tcp) { 501 c.type = comm_tcp; 502 c.tcp_timeout_msec = 30000; 503 c.tcp_keepalive = runtime->tcp_seen_keepalive; 504 } 505 if(todo->evt_type == repevt_back_reply && todo->match) { 506 fill_buffer_with_reply(c.buffer, todo->match, p->pkt, 507 p->pkt_len, p->tcp_pkt_counter); 508 } 509 repinfo.c = &c; 510 repinfo.addrlen = p->addrlen; 511 memcpy(&repinfo.addr, &p->addr, p->addrlen); 512 if(!p->serviced) { 513 if(todo->match && todo->match->reply_list->next && !error && 514 p->tcp_pkt_counter < count_reply_packets(todo->match)) { 515 /* go to next packet next time */ 516 p->tcp_pkt_counter++; 517 } else { 518 pending_list_delete(runtime, p); 519 } 520 } 521 if((*cb)(&c, cb_arg, error, &repinfo)) { 522 fatal_exit("unexpected: pending callback returned 1"); 523 } 524 /* delete the pending item. */ 525 sldns_buffer_free(c.buffer); 526} 527 528/** pass time */ 529static void 530moment_assign(struct replay_runtime* runtime, struct replay_moment* mom) 531{ 532 char* value = macro_process(runtime->vars, runtime, mom->string); 533 if(!value) 534 fatal_exit("could not process macro step %d", mom->time_step); 535 log_info("assign %s = %s", mom->variable, value); 536 if(!macro_assign(runtime->vars, mom->variable, value)) 537 fatal_exit("out of memory storing macro"); 538 free(value); 539 if(verbosity >= VERB_ALGO) 540 macro_print_debug(runtime->vars); 541} 542 543/** pass time */ 544static void 545time_passes(struct replay_runtime* runtime, struct replay_moment* mom) 546{ 547 struct fake_timer *t; 548 struct timeval tv = mom->elapse; 549 if(mom->string) { 550 char* xp = macro_process(runtime->vars, runtime, mom->string); 551 double sec; 552 if(!xp) fatal_exit("could not macro expand %s", mom->string); 553 verbose(VERB_ALGO, "EVAL %s", mom->string); 554 sec = atof(xp); 555 free(xp); 556#ifndef S_SPLINT_S 557 tv.tv_sec = sec; 558 tv.tv_usec = (int)((sec - (double)tv.tv_sec) *1000000. + 0.5); 559#endif 560 } 561 timeval_add(&runtime->now_tv, &tv); 562 runtime->now_secs = (time_t)runtime->now_tv.tv_sec; 563#ifndef S_SPLINT_S 564 log_info("elapsed %d.%6.6d now %d.%6.6d", 565 (int)tv.tv_sec, (int)tv.tv_usec, 566 (int)runtime->now_tv.tv_sec, (int)runtime->now_tv.tv_usec); 567#endif 568 /* see if any timers have fired; and run them */ 569 while( (t=replay_get_oldest_timer(runtime)) ) { 570 t->enabled = 0; 571 log_info("fake_timer callback"); 572 fptr_ok(fptr_whitelist_comm_timer(t->cb)); 573 (*t->cb)(t->cb_arg); 574 } 575} 576 577/** check autotrust file contents */ 578static void 579autotrust_check(struct replay_runtime* runtime, struct replay_moment* mom) 580{ 581 char name[1024], line[1024]; 582 FILE *in; 583 int lineno = 0, oke=1; 584 char* expanded; 585 struct config_strlist* p; 586 line[sizeof(line)-1] = 0; 587 log_assert(mom->autotrust_id); 588 fake_temp_file("_auto_", mom->autotrust_id, name, sizeof(name)); 589 in = fopen(name, "r"); 590 if(!in) fatal_exit("could not open %s: %s", name, strerror(errno)); 591 for(p=mom->file_content; p; p=p->next) { 592 lineno++; 593 if(!fgets(line, (int)sizeof(line)-1, in)) { 594 log_err("autotrust check failed, could not read line"); 595 log_err("file %s, line %d", name, lineno); 596 log_err("should be: %s", p->str); 597 fatal_exit("autotrust_check failed"); 598 } 599 if(line[0]) line[strlen(line)-1] = 0; /* remove newline */ 600 expanded = macro_process(runtime->vars, runtime, p->str); 601 if(!expanded) 602 fatal_exit("could not expand macro line %d", lineno); 603 if(verbosity >= 7 && strcmp(p->str, expanded) != 0) 604 log_info("expanded '%s' to '%s'", p->str, expanded); 605 if(strcmp(expanded, line) != 0) { 606 log_err("mismatch in file %s, line %d", name, lineno); 607 log_err("file has : %s", line); 608 log_err("should be: %s", expanded); 609 free(expanded); 610 oke = 0; 611 continue; 612 } 613 free(expanded); 614 fprintf(stderr, "%s:%2d ok : %s\n", name, lineno, line); 615 } 616 if(fgets(line, (int)sizeof(line)-1, in)) { 617 log_err("autotrust check failed, extra lines in %s after %d", 618 name, lineno); 619 do { 620 fprintf(stderr, "file has: %s", line); 621 } while(fgets(line, (int)sizeof(line)-1, in)); 622 oke = 0; 623 } 624 fclose(in); 625 if(!oke) 626 fatal_exit("autotrust_check STEP %d failed", mom->time_step); 627 log_info("autotrust %s is OK", mom->autotrust_id); 628} 629 630/** check tempfile file contents */ 631static void 632tempfile_check(struct replay_runtime* runtime, struct replay_moment* mom) 633{ 634 char name[1024], line[1024]; 635 FILE *in; 636 int lineno = 0, oke=1; 637 char* expanded; 638 struct config_strlist* p; 639 line[sizeof(line)-1] = 0; 640 log_assert(mom->autotrust_id); 641 fake_temp_file("_temp_", mom->autotrust_id, name, sizeof(name)); 642 in = fopen(name, "r"); 643 if(!in) fatal_exit("could not open %s: %s", name, strerror(errno)); 644 for(p=mom->file_content; p; p=p->next) { 645 lineno++; 646 if(!fgets(line, (int)sizeof(line)-1, in)) { 647 log_err("tempfile check failed, could not read line"); 648 log_err("file %s, line %d", name, lineno); 649 log_err("should be: %s", p->str); 650 fatal_exit("tempfile_check failed"); 651 } 652 if(line[0]) line[strlen(line)-1] = 0; /* remove newline */ 653 expanded = macro_process(runtime->vars, runtime, p->str); 654 if(!expanded) 655 fatal_exit("could not expand macro line %d", lineno); 656 if(verbosity >= 7 && strcmp(p->str, expanded) != 0) 657 log_info("expanded '%s' to '%s'", p->str, expanded); 658 if(strcmp(expanded, line) != 0) { 659 log_err("mismatch in file %s, line %d", name, lineno); 660 log_err("file has : %s", line); 661 log_err("should be: %s", expanded); 662 free(expanded); 663 oke = 0; 664 continue; 665 } 666 free(expanded); 667 fprintf(stderr, "%s:%2d ok : %s\n", name, lineno, line); 668 } 669 if(fgets(line, (int)sizeof(line)-1, in)) { 670 log_err("tempfile check failed, extra lines in %s after %d", 671 name, lineno); 672 do { 673 fprintf(stderr, "file has: %s", line); 674 } while(fgets(line, (int)sizeof(line)-1, in)); 675 oke = 0; 676 } 677 fclose(in); 678 if(!oke) 679 fatal_exit("tempfile_check STEP %d failed", mom->time_step); 680 log_info("tempfile %s is OK", mom->autotrust_id); 681} 682 683/** Store RTT in infra cache */ 684static void 685do_infra_rtt(struct replay_runtime* runtime) 686{ 687 struct replay_moment* now = runtime->now; 688 int rto; 689 size_t dplen = 0; 690 uint8_t* dp = sldns_str2wire_dname(now->variable, &dplen); 691 if(!dp) fatal_exit("cannot parse %s", now->variable); 692 rto = infra_rtt_update(runtime->infra, &now->addr, now->addrlen, 693 dp, dplen, LDNS_RR_TYPE_A, atoi(now->string), 694 -1, runtime->now_secs); 695 log_addr(0, "INFRA_RTT for", &now->addr, now->addrlen); 696 log_info("INFRA_RTT(%s roundtrip %d): rto of %d", now->variable, 697 atoi(now->string), rto); 698 if(rto == 0) fatal_exit("infra_rtt_update failed"); 699 free(dp); 700} 701 702/** perform exponential backoff on the timeout */ 703static void 704expon_timeout_backoff(struct replay_runtime* runtime) 705{ 706 struct fake_pending* p = runtime->pending_list; 707 int rtt, vs; 708 uint8_t edns_lame_known; 709 int last_rtt, rto; 710 if(!p) return; /* no pending packet to backoff */ 711 if(!infra_host(runtime->infra, &p->addr, p->addrlen, p->zone, 712 p->zonelen, runtime->now_secs, &vs, &edns_lame_known, &rtt)) 713 return; 714 last_rtt = rtt; 715 rto = infra_rtt_update(runtime->infra, &p->addr, p->addrlen, p->zone, 716 p->zonelen, p->qtype, -1, last_rtt, runtime->now_secs); 717 log_info("infra_rtt_update returned rto %d", rto); 718} 719 720/** 721 * Advance to the next moment. 722 */ 723static void 724advance_moment(struct replay_runtime* runtime) 725{ 726 if(!runtime->now) 727 runtime->now = runtime->scenario->mom_first; 728 else runtime->now = runtime->now->mom_next; 729} 730 731/** 732 * Perform actions or checks determined by the moment. 733 * Also advances the time by one step. 734 * @param runtime: scenario runtime information. 735 */ 736static void 737do_moment_and_advance(struct replay_runtime* runtime) 738{ 739 struct replay_moment* mom; 740 if(!runtime->now) { 741 advance_moment(runtime); 742 return; 743 } 744 log_info("testbound: do STEP %d %s", runtime->now->time_step, 745 repevt_string(runtime->now->evt_type)); 746 switch(runtime->now->evt_type) { 747 case repevt_nothing: 748 advance_moment(runtime); 749 break; 750 case repevt_front_query: 751 /* advance moment before doing the step, so that the next 752 moment which may check some result of the mom step 753 can catch those results. */ 754 mom = runtime->now; 755 advance_moment(runtime); 756 fake_front_query(runtime, mom); 757 break; 758 case repevt_front_reply: 759 if(runtime->answer_list) 760 log_err("testbound: There are unmatched answers."); 761 fatal_exit("testbound: query answer not matched"); 762 break; 763 case repevt_timeout: 764 mom = runtime->now; 765 advance_moment(runtime); 766 expon_timeout_backoff(runtime); 767 fake_pending_callback(runtime, mom, NETEVENT_TIMEOUT); 768 break; 769 case repevt_back_reply: 770 mom = runtime->now; 771 advance_moment(runtime); 772 fake_pending_callback(runtime, mom, NETEVENT_NOERROR); 773 break; 774 case repevt_back_query: 775 /* Back queries are matched when they are sent out. */ 776 log_err("No query matching the current moment was sent."); 777 fatal_exit("testbound: back query not matched"); 778 break; 779 case repevt_error: 780 mom = runtime->now; 781 advance_moment(runtime); 782 fake_pending_callback(runtime, mom, NETEVENT_CLOSED); 783 break; 784 case repevt_time_passes: 785 time_passes(runtime, runtime->now); 786 advance_moment(runtime); 787 break; 788 case repevt_autotrust_check: 789 autotrust_check(runtime, runtime->now); 790 advance_moment(runtime); 791 break; 792 case repevt_tempfile_check: 793 tempfile_check(runtime, runtime->now); 794 advance_moment(runtime); 795 break; 796 case repevt_assign: 797 moment_assign(runtime, runtime->now); 798 advance_moment(runtime); 799 break; 800 case repevt_traffic: 801 advance_moment(runtime); 802 break; 803 case repevt_infra_rtt: 804 do_infra_rtt(runtime); 805 advance_moment(runtime); 806 break; 807 default: 808 fatal_exit("testbound: unknown event type %d", 809 runtime->now->evt_type); 810 } 811} 812 813/** run the scenario in event callbacks */ 814static void 815run_scenario(struct replay_runtime* runtime) 816{ 817 struct entry* entry = NULL; 818 struct fake_pending* pending = NULL; 819 int max_rounds = 5000; 820 int rounds = 0; 821 runtime->now = runtime->scenario->mom_first; 822 log_info("testbound: entering fake runloop"); 823 do { 824 /* if moment matches pending query do it. */ 825 /* else if moment matches given answer, do it */ 826 /* else if precoded_range matches pending, do it */ 827 /* else do the current moment */ 828 if(pending_matches_current(runtime, &entry, &pending)) { 829 log_info("testbound: do STEP %d CHECK_OUT_QUERY", 830 runtime->now->time_step); 831 advance_moment(runtime); 832 if(entry->copy_id) 833 answer_callback_from_entry(runtime, entry, 834 pending); 835 } else if(runtime->answer_list && runtime->now && 836 runtime->now->evt_type == repevt_front_reply) { 837 answer_check_it(runtime); 838 advance_moment(runtime); 839 } else if(pending_matches_range(runtime, &entry, &pending)) { 840 answer_callback_from_entry(runtime, entry, pending); 841 } else { 842 do_moment_and_advance(runtime); 843 } 844 log_info("testbound: end of event stage"); 845 rounds++; 846 if(rounds > max_rounds) 847 fatal_exit("testbound: too many rounds, it loops."); 848 } while(runtime->now); 849 850 if(runtime->pending_list) { 851 struct fake_pending* p; 852 log_err("testbound: there are still messages pending."); 853 for(p = runtime->pending_list; p; p=p->next) { 854 log_pkt("pending msg", p->pkt, p->pkt_len); 855 log_addr(0, "pending to", &p->addr, p->addrlen); 856 } 857 fatal_exit("testbound: there are still messages pending."); 858 } 859 if(runtime->answer_list) { 860 fatal_exit("testbound: there are unmatched answers."); 861 } 862 log_info("testbound: exiting fake runloop."); 863 runtime->exit_cleanly = 1; 864} 865 866/*********** Dummy routines ***********/ 867 868struct listen_dnsport* 869listen_create(struct comm_base* base, struct listen_port* ATTR_UNUSED(ports), 870 size_t bufsize, int ATTR_UNUSED(tcp_accept_count), 871 int ATTR_UNUSED(tcp_idle_timeout), 872 int ATTR_UNUSED(harden_large_queries), 873 uint32_t ATTR_UNUSED(http_max_streams), 874 char* ATTR_UNUSED(http_endpoint), 875 int ATTR_UNUSED(http_notls), 876 struct tcl_list* ATTR_UNUSED(tcp_conn_limit), 877 void* ATTR_UNUSED(sslctx), struct dt_env* ATTR_UNUSED(dtenv), 878 comm_point_callback_type* cb, void *cb_arg) 879{ 880 struct replay_runtime* runtime = (struct replay_runtime*)base; 881 struct listen_dnsport* l= calloc(1, sizeof(struct listen_dnsport)); 882 if(!l) 883 return NULL; 884 l->base = base; 885 l->udp_buff = sldns_buffer_new(bufsize); 886 if(!l->udp_buff) { 887 free(l); 888 return NULL; 889 } 890 runtime->callback_query = cb; 891 runtime->cb_arg = cb_arg; 892 runtime->bufsize = bufsize; 893 return l; 894} 895 896void 897listen_delete(struct listen_dnsport* listen) 898{ 899 if(!listen) 900 return; 901 sldns_buffer_free(listen->udp_buff); 902 free(listen); 903} 904 905struct comm_base* 906comm_base_create(int ATTR_UNUSED(sigs)) 907{ 908 /* we return the runtime structure instead. */ 909 struct replay_runtime* runtime = (struct replay_runtime*) 910 calloc(1, sizeof(struct replay_runtime)); 911 runtime->scenario = saved_scenario; 912 runtime->vars = macro_store_create(); 913 if(!runtime->vars) fatal_exit("out of memory"); 914 return (struct comm_base*)runtime; 915} 916 917void 918comm_base_delete(struct comm_base* b) 919{ 920 struct replay_runtime* runtime = (struct replay_runtime*)b; 921 struct fake_pending* p, *np; 922 struct replay_answer* a, *na; 923 struct fake_timer* t, *nt; 924 if(!runtime) 925 return; 926 runtime->scenario= NULL; 927 p = runtime->pending_list; 928 while(p) { 929 np = p->next; 930 delete_fake_pending(p); 931 p = np; 932 } 933 a = runtime->answer_list; 934 while(a) { 935 na = a->next; 936 delete_replay_answer(a); 937 a = na; 938 } 939 t = runtime->timer_list; 940 while(t) { 941 nt = t->next; 942 free(t); 943 t = nt; 944 } 945 macro_store_delete(runtime->vars); 946 free(runtime); 947} 948 949void 950comm_base_timept(struct comm_base* b, time_t** tt, struct timeval** tv) 951{ 952 struct replay_runtime* runtime = (struct replay_runtime*)b; 953 *tt = &runtime->now_secs; 954 *tv = &runtime->now_tv; 955} 956 957void 958comm_base_dispatch(struct comm_base* b) 959{ 960 struct replay_runtime* runtime = (struct replay_runtime*)b; 961 run_scenario(runtime); 962 if(runtime->sig_cb) 963 (*runtime->sig_cb)(SIGTERM, runtime->sig_cb_arg); 964 else exit(0); /* OK exit when LIBEVENT_SIGNAL_PROBLEM exists */ 965} 966 967void 968comm_base_exit(struct comm_base* b) 969{ 970 struct replay_runtime* runtime = (struct replay_runtime*)b; 971 if(!runtime->exit_cleanly) { 972 /* some sort of failure */ 973 fatal_exit("testbound: comm_base_exit was called."); 974 } 975} 976 977struct comm_signal* 978comm_signal_create(struct comm_base* base, 979 void (*callback)(int, void*), void* cb_arg) 980{ 981 struct replay_runtime* runtime = (struct replay_runtime*)base; 982 runtime->sig_cb = callback; 983 runtime->sig_cb_arg = cb_arg; 984 return calloc(1, sizeof(struct comm_signal)); 985} 986 987int 988comm_signal_bind(struct comm_signal* ATTR_UNUSED(comsig), int 989 ATTR_UNUSED(sig)) 990{ 991 return 1; 992} 993 994void 995comm_signal_delete(struct comm_signal* comsig) 996{ 997 free(comsig); 998} 999 1000void 1001comm_point_send_reply(struct comm_reply* repinfo) 1002{ 1003 struct replay_answer* ans = (struct replay_answer*)calloc(1, 1004 sizeof(struct replay_answer)); 1005 struct replay_runtime* runtime = (struct replay_runtime*)repinfo->c->ev; 1006 log_info("testbound: comm_point_send_reply fake"); 1007 /* dump it into the todo list */ 1008 log_assert(ans); 1009 memcpy(&ans->repinfo, repinfo, sizeof(struct comm_reply)); 1010 ans->next = NULL; 1011 if(runtime->answer_last) 1012 runtime->answer_last->next = ans; 1013 else runtime->answer_list = ans; 1014 runtime->answer_last = ans; 1015 1016 /* try to parse packet */ 1017 ans->pkt = memdup(sldns_buffer_begin(ans->repinfo.c->buffer), 1018 sldns_buffer_limit(ans->repinfo.c->buffer)); 1019 ans->pkt_len = sldns_buffer_limit(ans->repinfo.c->buffer); 1020 if(!ans->pkt) fatal_exit("out of memory"); 1021 log_pkt("reply pkt: ", ans->pkt, ans->pkt_len); 1022} 1023 1024void 1025comm_point_drop_reply(struct comm_reply* repinfo) 1026{ 1027 log_info("comm_point_drop_reply fake"); 1028 if(repinfo->c) { 1029 sldns_buffer_free(repinfo->c->buffer); 1030 free(repinfo->c); 1031 } 1032} 1033 1034struct outside_network* 1035outside_network_create(struct comm_base* base, size_t bufsize, 1036 size_t ATTR_UNUSED(num_ports), char** ATTR_UNUSED(ifs), 1037 int ATTR_UNUSED(num_ifs), int ATTR_UNUSED(do_ip4), 1038 int ATTR_UNUSED(do_ip6), size_t ATTR_UNUSED(num_tcp), 1039 int ATTR_UNUSED(dscp), 1040 struct infra_cache* infra, 1041 struct ub_randstate* ATTR_UNUSED(rnd), 1042 int ATTR_UNUSED(use_caps_for_id), int* ATTR_UNUSED(availports), 1043 int ATTR_UNUSED(numavailports), size_t ATTR_UNUSED(unwanted_threshold), 1044 int ATTR_UNUSED(outgoing_tcp_mss), 1045 void (*unwanted_action)(void*), void* ATTR_UNUSED(unwanted_param), 1046 int ATTR_UNUSED(do_udp), void* ATTR_UNUSED(sslctx), 1047 int ATTR_UNUSED(delayclose), int ATTR_UNUSED(tls_use_sni), 1048 struct dt_env* ATTR_UNUSED(dtenv), int ATTR_UNUSED(udp_connect)) 1049{ 1050 struct replay_runtime* runtime = (struct replay_runtime*)base; 1051 struct outside_network* outnet = calloc(1, 1052 sizeof(struct outside_network)); 1053 (void)unwanted_action; 1054 if(!outnet) 1055 return NULL; 1056 runtime->infra = infra; 1057 outnet->base = base; 1058 outnet->udp_buff = sldns_buffer_new(bufsize); 1059 if(!outnet->udp_buff) { 1060 free(outnet); 1061 return NULL; 1062 } 1063 return outnet; 1064} 1065 1066void 1067outside_network_delete(struct outside_network* outnet) 1068{ 1069 if(!outnet) 1070 return; 1071 sldns_buffer_free(outnet->udp_buff); 1072 free(outnet); 1073} 1074 1075void 1076outside_network_quit_prepare(struct outside_network* ATTR_UNUSED(outnet)) 1077{ 1078} 1079 1080struct pending* 1081pending_udp_query(struct serviced_query* sq, sldns_buffer* packet, 1082 int timeout, comm_point_callback_type* callback, void* callback_arg) 1083{ 1084 struct replay_runtime* runtime = (struct replay_runtime*) 1085 sq->outnet->base; 1086 struct fake_pending* pend = (struct fake_pending*)calloc(1, 1087 sizeof(struct fake_pending)); 1088 log_assert(pend); 1089 pend->buffer = sldns_buffer_new(sldns_buffer_capacity(packet)); 1090 log_assert(pend->buffer); 1091 sldns_buffer_write(pend->buffer, sldns_buffer_begin(packet), 1092 sldns_buffer_limit(packet)); 1093 sldns_buffer_flip(pend->buffer); 1094 memcpy(&pend->addr, &sq->addr, sq->addrlen); 1095 pend->addrlen = sq->addrlen; 1096 pend->callback = callback; 1097 pend->cb_arg = callback_arg; 1098 pend->timeout = timeout/1000; 1099 pend->transport = transport_udp; 1100 pend->pkt = NULL; 1101 pend->zone = NULL; 1102 pend->serviced = 0; 1103 pend->runtime = runtime; 1104 pend->pkt_len = sldns_buffer_limit(packet); 1105 pend->pkt = memdup(sldns_buffer_begin(packet), pend->pkt_len); 1106 if(!pend->pkt) fatal_exit("out of memory"); 1107 log_pkt("pending udp pkt: ", pend->pkt, pend->pkt_len); 1108 1109 /* see if it matches the current moment */ 1110 if(runtime->now && runtime->now->evt_type == repevt_back_query && 1111 (runtime->now->addrlen == 0 || sockaddr_cmp( 1112 &runtime->now->addr, runtime->now->addrlen, 1113 &pend->addr, pend->addrlen) == 0) && 1114 find_match(runtime->now->match, pend->pkt, pend->pkt_len, 1115 pend->transport)) { 1116 log_info("testbound: matched pending to event. " 1117 "advance time between events."); 1118 log_info("testbound: do STEP %d %s", runtime->now->time_step, 1119 repevt_string(runtime->now->evt_type)); 1120 advance_moment(runtime); 1121 /* still create the pending, because we need it to callback */ 1122 } 1123 log_info("testbound: created fake pending"); 1124 /* add to list */ 1125 pend->next = runtime->pending_list; 1126 runtime->pending_list = pend; 1127 return (struct pending*)pend; 1128} 1129 1130struct waiting_tcp* 1131pending_tcp_query(struct serviced_query* sq, sldns_buffer* packet, 1132 int timeout, comm_point_callback_type* callback, void* callback_arg) 1133{ 1134 struct replay_runtime* runtime = (struct replay_runtime*) 1135 sq->outnet->base; 1136 struct fake_pending* pend = (struct fake_pending*)calloc(1, 1137 sizeof(struct fake_pending)); 1138 log_assert(pend); 1139 pend->buffer = sldns_buffer_new(sldns_buffer_capacity(packet)); 1140 log_assert(pend->buffer); 1141 sldns_buffer_write(pend->buffer, sldns_buffer_begin(packet), 1142 sldns_buffer_limit(packet)); 1143 sldns_buffer_flip(pend->buffer); 1144 memcpy(&pend->addr, &sq->addr, sq->addrlen); 1145 pend->addrlen = sq->addrlen; 1146 pend->callback = callback; 1147 pend->cb_arg = callback_arg; 1148 pend->timeout = timeout/1000; 1149 pend->transport = transport_tcp; 1150 pend->pkt = NULL; 1151 pend->zone = NULL; 1152 pend->runtime = runtime; 1153 pend->serviced = 0; 1154 pend->pkt_len = sldns_buffer_limit(packet); 1155 pend->pkt = memdup(sldns_buffer_begin(packet), pend->pkt_len); 1156 if(!pend->pkt) fatal_exit("out of memory"); 1157 log_pkt("pending tcp pkt: ", pend->pkt, pend->pkt_len); 1158 1159 /* see if it matches the current moment */ 1160 if(runtime->now && runtime->now->evt_type == repevt_back_query && 1161 (runtime->now->addrlen == 0 || sockaddr_cmp( 1162 &runtime->now->addr, runtime->now->addrlen, 1163 &pend->addr, pend->addrlen) == 0) && 1164 find_match(runtime->now->match, pend->pkt, pend->pkt_len, 1165 pend->transport)) { 1166 log_info("testbound: matched pending to event. " 1167 "advance time between events."); 1168 log_info("testbound: do STEP %d %s", runtime->now->time_step, 1169 repevt_string(runtime->now->evt_type)); 1170 advance_moment(runtime); 1171 /* still create the pending, because we need it to callback */ 1172 } 1173 log_info("testbound: created fake pending"); 1174 /* add to list */ 1175 pend->next = runtime->pending_list; 1176 runtime->pending_list = pend; 1177 return (struct waiting_tcp*)pend; 1178} 1179 1180struct serviced_query* outnet_serviced_query(struct outside_network* outnet, 1181 struct query_info* qinfo, uint16_t flags, int dnssec, 1182 int ATTR_UNUSED(want_dnssec), int ATTR_UNUSED(nocaps), 1183 int ATTR_UNUSED(tcp_upstream), int ATTR_UNUSED(ssl_upstream), 1184 char* ATTR_UNUSED(tls_auth_name), struct sockaddr_storage* addr, 1185 socklen_t addrlen, uint8_t* zone, size_t zonelen, 1186 struct module_qstate* qstate, comm_point_callback_type* callback, 1187 void* callback_arg, sldns_buffer* ATTR_UNUSED(buff), 1188 struct module_env* env) 1189{ 1190 struct replay_runtime* runtime = (struct replay_runtime*)outnet->base; 1191 struct fake_pending* pend = (struct fake_pending*)calloc(1, 1192 sizeof(struct fake_pending)); 1193 char z[256]; 1194 log_assert(pend); 1195 log_nametypeclass(VERB_OPS, "pending serviced query", 1196 qinfo->qname, qinfo->qtype, qinfo->qclass); 1197 dname_str(zone, z); 1198 verbose(VERB_OPS, "pending serviced query zone %s flags%s%s%s%s", 1199 z, (flags&BIT_RD)?" RD":"", (flags&BIT_CD)?" CD":"", 1200 (flags&~(BIT_RD|BIT_CD))?" MORE":"", (dnssec)?" DO":""); 1201 1202 /* create packet with EDNS */ 1203 pend->buffer = sldns_buffer_new(512); 1204 log_assert(pend->buffer); 1205 sldns_buffer_write_u16(pend->buffer, 0); /* id */ 1206 sldns_buffer_write_u16(pend->buffer, flags); 1207 sldns_buffer_write_u16(pend->buffer, 1); /* qdcount */ 1208 sldns_buffer_write_u16(pend->buffer, 0); /* ancount */ 1209 sldns_buffer_write_u16(pend->buffer, 0); /* nscount */ 1210 sldns_buffer_write_u16(pend->buffer, 0); /* arcount */ 1211 sldns_buffer_write(pend->buffer, qinfo->qname, qinfo->qname_len); 1212 sldns_buffer_write_u16(pend->buffer, qinfo->qtype); 1213 sldns_buffer_write_u16(pend->buffer, qinfo->qclass); 1214 sldns_buffer_flip(pend->buffer); 1215 if(1) { 1216 struct edns_data edns; 1217 struct edns_string_addr* client_string_addr; 1218 if(!inplace_cb_query_call(env, qinfo, flags, addr, addrlen, 1219 zone, zonelen, qstate, qstate->region)) { 1220 free(pend); 1221 return NULL; 1222 } 1223 /* add edns */ 1224 edns.edns_present = 1; 1225 edns.ext_rcode = 0; 1226 edns.edns_version = EDNS_ADVERTISED_VERSION; 1227 edns.udp_size = EDNS_ADVERTISED_SIZE; 1228 edns.bits = 0; 1229 if(dnssec) 1230 edns.bits = EDNS_DO; 1231 if((client_string_addr = edns_string_addr_lookup( 1232 &env->edns_strings->client_strings, 1233 addr, addrlen))) { 1234 edns_opt_list_append(&qstate->edns_opts_back_out, 1235 env->edns_strings->client_string_opcode, 1236 client_string_addr->string_len, 1237 client_string_addr->string, qstate->region); 1238 } 1239 edns.opt_list = qstate->edns_opts_back_out; 1240 attach_edns_record(pend->buffer, &edns); 1241 } 1242 memcpy(&pend->addr, addr, addrlen); 1243 pend->addrlen = addrlen; 1244 pend->zone = memdup(zone, zonelen); 1245 pend->zonelen = zonelen; 1246 pend->qtype = (int)qinfo->qtype; 1247 log_assert(pend->zone); 1248 pend->callback = callback; 1249 pend->cb_arg = callback_arg; 1250 pend->timeout = UDP_AUTH_QUERY_TIMEOUT/1000; 1251 pend->transport = transport_udp; /* pretend UDP */ 1252 pend->pkt = NULL; 1253 pend->runtime = runtime; 1254 pend->serviced = 1; 1255 pend->pkt_len = sldns_buffer_limit(pend->buffer); 1256 pend->pkt = memdup(sldns_buffer_begin(pend->buffer), pend->pkt_len); 1257 if(!pend->pkt) fatal_exit("out of memory"); 1258 /*log_pkt("pending serviced query: ", pend->pkt, pend->pkt_len);*/ 1259 1260 /* see if it matches the current moment */ 1261 if(runtime->now && runtime->now->evt_type == repevt_back_query && 1262 (runtime->now->addrlen == 0 || sockaddr_cmp( 1263 &runtime->now->addr, runtime->now->addrlen, 1264 &pend->addr, pend->addrlen) == 0) && 1265 find_match(runtime->now->match, pend->pkt, pend->pkt_len, 1266 pend->transport)) { 1267 log_info("testbound: matched pending to event. " 1268 "advance time between events."); 1269 log_info("testbound: do STEP %d %s", runtime->now->time_step, 1270 repevt_string(runtime->now->evt_type)); 1271 advance_moment(runtime); 1272 /* still create the pending, because we need it to callback */ 1273 } 1274 log_info("testbound: created fake pending"); 1275 /* add to list */ 1276 pend->next = runtime->pending_list; 1277 runtime->pending_list = pend; 1278 return (struct serviced_query*)pend; 1279} 1280 1281void outnet_serviced_query_stop(struct serviced_query* sq, void* cb_arg) 1282{ 1283 struct fake_pending* pend = (struct fake_pending*)sq; 1284 struct replay_runtime* runtime = pend->runtime; 1285 /* delete from the list */ 1286 struct fake_pending* p = runtime->pending_list, *prev=NULL; 1287 while(p) { 1288 if(p == pend) { 1289 log_assert(p->cb_arg == cb_arg); 1290 (void)cb_arg; 1291 log_info("serviced pending delete"); 1292 if(prev) 1293 prev->next = p->next; 1294 else runtime->pending_list = p->next; 1295 sldns_buffer_free(p->buffer); 1296 free(p->pkt); 1297 free(p->zone); 1298 free(p); 1299 return; 1300 } 1301 prev = p; 1302 p = p->next; 1303 } 1304 log_info("double delete of pending serviced query"); 1305} 1306 1307int resolve_interface_names(struct config_file* ATTR_UNUSED(cfg), 1308 char*** ATTR_UNUSED(resif), int* ATTR_UNUSED(num_resif)) 1309{ 1310 return 1; 1311} 1312 1313struct listen_port* listening_ports_open(struct config_file* ATTR_UNUSED(cfg), 1314 char** ATTR_UNUSED(ifs), int ATTR_UNUSED(num_ifs), 1315 int* ATTR_UNUSED(reuseport)) 1316{ 1317 return calloc(1, 1); 1318} 1319 1320void listening_ports_free(struct listen_port* list) 1321{ 1322 free(list); 1323} 1324 1325struct comm_point* comm_point_create_local(struct comm_base* ATTR_UNUSED(base), 1326 int ATTR_UNUSED(fd), size_t ATTR_UNUSED(bufsize), 1327 comm_point_callback_type* ATTR_UNUSED(callback), 1328 void* ATTR_UNUSED(callback_arg)) 1329{ 1330 struct fake_commpoint* fc = (struct fake_commpoint*)calloc(1, 1331 sizeof(*fc)); 1332 if(!fc) return NULL; 1333 fc->typecode = FAKE_COMMPOINT_TYPECODE; 1334 return (struct comm_point*)fc; 1335} 1336 1337struct comm_point* comm_point_create_raw(struct comm_base* ATTR_UNUSED(base), 1338 int ATTR_UNUSED(fd), int ATTR_UNUSED(writing), 1339 comm_point_callback_type* ATTR_UNUSED(callback), 1340 void* ATTR_UNUSED(callback_arg)) 1341{ 1342 /* no pipe comm possible */ 1343 struct fake_commpoint* fc = (struct fake_commpoint*)calloc(1, 1344 sizeof(*fc)); 1345 if(!fc) return NULL; 1346 fc->typecode = FAKE_COMMPOINT_TYPECODE; 1347 return (struct comm_point*)fc; 1348} 1349 1350void comm_point_start_listening(struct comm_point* ATTR_UNUSED(c), 1351 int ATTR_UNUSED(newfd), int ATTR_UNUSED(sec)) 1352{ 1353 /* no bg write pipe comm possible */ 1354} 1355 1356void comm_point_stop_listening(struct comm_point* ATTR_UNUSED(c)) 1357{ 1358 /* no bg write pipe comm possible */ 1359} 1360 1361/* only cmd com _local gets deleted */ 1362void comm_point_delete(struct comm_point* c) 1363{ 1364 struct fake_commpoint* fc = (struct fake_commpoint*)c; 1365 if(c == NULL) return; 1366 log_assert(fc->typecode == FAKE_COMMPOINT_TYPECODE); 1367 if(fc->type_tcp_out) { 1368 /* remove tcp pending, so no more callbacks to it */ 1369 pending_list_delete(fc->runtime, fc->pending); 1370 } 1371 free(c); 1372} 1373 1374size_t listen_get_mem(struct listen_dnsport* ATTR_UNUSED(listen)) 1375{ 1376 return 0; 1377} 1378 1379size_t outnet_get_mem(struct outside_network* ATTR_UNUSED(outnet)) 1380{ 1381 return 0; 1382} 1383 1384size_t comm_point_get_mem(struct comm_point* ATTR_UNUSED(c)) 1385{ 1386 return 0; 1387} 1388 1389size_t serviced_get_mem(struct serviced_query* ATTR_UNUSED(c)) 1390{ 1391 return 0; 1392} 1393 1394/* fake for fptr wlist */ 1395int outnet_udp_cb(struct comm_point* ATTR_UNUSED(c), 1396 void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), 1397 struct comm_reply *ATTR_UNUSED(reply_info)) 1398{ 1399 log_assert(0); 1400 return 0; 1401} 1402 1403int outnet_tcp_cb(struct comm_point* ATTR_UNUSED(c), 1404 void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), 1405 struct comm_reply *ATTR_UNUSED(reply_info)) 1406{ 1407 log_assert(0); 1408 return 0; 1409} 1410 1411void pending_udp_timer_cb(void *ATTR_UNUSED(arg)) 1412{ 1413 log_assert(0); 1414} 1415 1416void pending_udp_timer_delay_cb(void *ATTR_UNUSED(arg)) 1417{ 1418 log_assert(0); 1419} 1420 1421void outnet_tcptimer(void* ATTR_UNUSED(arg)) 1422{ 1423 log_assert(0); 1424} 1425 1426void comm_point_udp_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(event), 1427 void* ATTR_UNUSED(arg)) 1428{ 1429 log_assert(0); 1430} 1431 1432void comm_point_udp_ancil_callback(int ATTR_UNUSED(fd), 1433 short ATTR_UNUSED(event), void* ATTR_UNUSED(arg)) 1434{ 1435 log_assert(0); 1436} 1437 1438void comm_point_tcp_accept_callback(int ATTR_UNUSED(fd), 1439 short ATTR_UNUSED(event), void* ATTR_UNUSED(arg)) 1440{ 1441 log_assert(0); 1442} 1443 1444void comm_point_tcp_handle_callback(int ATTR_UNUSED(fd), 1445 short ATTR_UNUSED(event), void* ATTR_UNUSED(arg)) 1446{ 1447 log_assert(0); 1448} 1449 1450void comm_timer_callback(int ATTR_UNUSED(fd), 1451 short ATTR_UNUSED(event), void* ATTR_UNUSED(arg)) 1452{ 1453 log_assert(0); 1454} 1455 1456void comm_signal_callback(int ATTR_UNUSED(fd), 1457 short ATTR_UNUSED(event), void* ATTR_UNUSED(arg)) 1458{ 1459 log_assert(0); 1460} 1461 1462void comm_point_http_handle_callback(int ATTR_UNUSED(fd), 1463 short ATTR_UNUSED(event), void* ATTR_UNUSED(arg)) 1464{ 1465 log_assert(0); 1466} 1467 1468void comm_point_local_handle_callback(int ATTR_UNUSED(fd), 1469 short ATTR_UNUSED(event), void* ATTR_UNUSED(arg)) 1470{ 1471 log_assert(0); 1472} 1473 1474void comm_point_raw_handle_callback(int ATTR_UNUSED(fd), 1475 short ATTR_UNUSED(event), void* ATTR_UNUSED(arg)) 1476{ 1477 log_assert(0); 1478} 1479 1480void comm_base_handle_slow_accept(int ATTR_UNUSED(fd), 1481 short ATTR_UNUSED(event), void* ATTR_UNUSED(arg)) 1482{ 1483 log_assert(0); 1484} 1485 1486int serviced_udp_callback(struct comm_point* ATTR_UNUSED(c), 1487 void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), 1488 struct comm_reply* ATTR_UNUSED(reply_info)) 1489{ 1490 log_assert(0); 1491 return 0; 1492} 1493 1494int serviced_tcp_callback(struct comm_point* ATTR_UNUSED(c), 1495 void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), 1496 struct comm_reply* ATTR_UNUSED(reply_info)) 1497{ 1498 log_assert(0); 1499 return 0; 1500} 1501 1502int pending_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b)) 1503{ 1504 log_assert(0); 1505 return 0; 1506} 1507 1508int serviced_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b)) 1509{ 1510 log_assert(0); 1511 return 0; 1512} 1513 1514int reuse_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b)) 1515{ 1516 log_assert(0); 1517 return 0; 1518} 1519 1520int reuse_id_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b)) 1521{ 1522 log_assert(0); 1523 return 0; 1524} 1525 1526/* timers in testbound for autotrust. statistics tested in tdir. */ 1527struct comm_timer* comm_timer_create(struct comm_base* base, 1528 void (*cb)(void*), void* cb_arg) 1529{ 1530 struct replay_runtime* runtime = (struct replay_runtime*)base; 1531 struct fake_timer* t = (struct fake_timer*)calloc(1, sizeof(*t)); 1532 t->cb = cb; 1533 t->cb_arg = cb_arg; 1534 fptr_ok(fptr_whitelist_comm_timer(t->cb)); /* check in advance */ 1535 t->runtime = runtime; 1536 t->next = runtime->timer_list; 1537 runtime->timer_list = t; 1538 return (struct comm_timer*)t; 1539} 1540 1541void comm_timer_disable(struct comm_timer* timer) 1542{ 1543 struct fake_timer* t = (struct fake_timer*)timer; 1544 log_info("fake timer disabled"); 1545 t->enabled = 0; 1546} 1547 1548void comm_timer_set(struct comm_timer* timer, struct timeval* tv) 1549{ 1550 struct fake_timer* t = (struct fake_timer*)timer; 1551 t->enabled = 1; 1552 t->tv = *tv; 1553 log_info("fake timer set %d.%6.6d", 1554 (int)t->tv.tv_sec, (int)t->tv.tv_usec); 1555 timeval_add(&t->tv, &t->runtime->now_tv); 1556} 1557 1558void comm_timer_delete(struct comm_timer* timer) 1559{ 1560 struct fake_timer* t = (struct fake_timer*)timer; 1561 struct fake_timer** pp, *p; 1562 if(!t) return; 1563 1564 /* remove from linked list */ 1565 pp = &t->runtime->timer_list; 1566 p = t->runtime->timer_list; 1567 while(p) { 1568 if(p == t) { 1569 /* snip from list */ 1570 *pp = p->next; 1571 break; 1572 } 1573 pp = &p->next; 1574 p = p->next; 1575 } 1576 1577 free(timer); 1578} 1579 1580void comm_base_set_slow_accept_handlers(struct comm_base* ATTR_UNUSED(b), 1581 void (*stop_acc)(void*), void (*start_acc)(void*), 1582 void* ATTR_UNUSED(arg)) 1583{ 1584 /* ignore this */ 1585 (void)stop_acc; 1586 (void)start_acc; 1587} 1588 1589struct ub_event_base* comm_base_internal(struct comm_base* ATTR_UNUSED(b)) 1590{ 1591 /* no pipe comm possible in testbound */ 1592 return NULL; 1593} 1594 1595void daemon_remote_exec(struct worker* ATTR_UNUSED(worker)) 1596{ 1597} 1598 1599void listen_start_accept(struct listen_dnsport* ATTR_UNUSED(listen)) 1600{ 1601} 1602 1603void listen_stop_accept(struct listen_dnsport* ATTR_UNUSED(listen)) 1604{ 1605} 1606 1607void daemon_remote_start_accept(struct daemon_remote* ATTR_UNUSED(rc)) 1608{ 1609} 1610 1611void daemon_remote_stop_accept(struct daemon_remote* ATTR_UNUSED(rc)) 1612{ 1613} 1614 1615int create_udp_sock(int ATTR_UNUSED(family), int ATTR_UNUSED(socktype), 1616 struct sockaddr* ATTR_UNUSED(addr), socklen_t ATTR_UNUSED(addrlen), 1617 int ATTR_UNUSED(v6only), int* ATTR_UNUSED(inuse), 1618 int* ATTR_UNUSED(noproto), int ATTR_UNUSED(rcv), int ATTR_UNUSED(snd), 1619 int ATTR_UNUSED(listen), int* ATTR_UNUSED(reuseport), 1620 int ATTR_UNUSED(transparent), int ATTR_UNUSED(freebind), 1621 int ATTR_UNUSED(use_systemd), int ATTR_UNUSED(dscp)) 1622{ 1623 /* if you actually print to this, it'll be stdout during test */ 1624 return 1; 1625} 1626 1627struct comm_point* comm_point_create_udp(struct comm_base *ATTR_UNUSED(base), 1628 int ATTR_UNUSED(fd), sldns_buffer* ATTR_UNUSED(buffer), 1629 comm_point_callback_type* ATTR_UNUSED(callback), 1630 void* ATTR_UNUSED(callback_arg)) 1631{ 1632 log_assert(0); 1633 return NULL; 1634} 1635 1636struct comm_point* comm_point_create_tcp_out(struct comm_base* 1637 ATTR_UNUSED(base), size_t ATTR_UNUSED(bufsize), 1638 comm_point_callback_type* ATTR_UNUSED(callback), 1639 void* ATTR_UNUSED(callback_arg)) 1640{ 1641 log_assert(0); 1642 return NULL; 1643} 1644 1645struct comm_point* outnet_comm_point_for_udp(struct outside_network* outnet, 1646 comm_point_callback_type* cb, void* cb_arg, 1647 struct sockaddr_storage* ATTR_UNUSED(to_addr), 1648 socklen_t ATTR_UNUSED(to_addrlen)) 1649{ 1650 struct replay_runtime* runtime = (struct replay_runtime*) 1651 outnet->base; 1652 struct fake_commpoint* fc = (struct fake_commpoint*)calloc(1, 1653 sizeof(*fc)); 1654 if(!fc) return NULL; 1655 fc->typecode = FAKE_COMMPOINT_TYPECODE; 1656 fc->type_udp_out = 1; 1657 fc->cb = cb; 1658 fc->cb_arg = cb_arg; 1659 fc->runtime = runtime; 1660 /* used by authzone transfers */ 1661 return (struct comm_point*)fc; 1662} 1663 1664struct comm_point* outnet_comm_point_for_tcp(struct outside_network* outnet, 1665 comm_point_callback_type* cb, void* cb_arg, 1666 struct sockaddr_storage* to_addr, socklen_t to_addrlen, 1667 struct sldns_buffer* query, int timeout, int ATTR_UNUSED(ssl), 1668 char* ATTR_UNUSED(host)) 1669{ 1670 struct replay_runtime* runtime = (struct replay_runtime*) 1671 outnet->base; 1672 struct fake_commpoint* fc = (struct fake_commpoint*)calloc(1, 1673 sizeof(*fc)); 1674 struct fake_pending* pend = (struct fake_pending*)calloc(1, 1675 sizeof(struct fake_pending)); 1676 if(!fc || !pend) { 1677 free(fc); 1678 free(pend); 1679 return NULL; 1680 } 1681 fc->typecode = FAKE_COMMPOINT_TYPECODE; 1682 fc->type_tcp_out = 1; 1683 fc->cb = cb; 1684 fc->cb_arg = cb_arg; 1685 fc->runtime = runtime; 1686 fc->pending = pend; 1687 1688 /* used by authzone transfers */ 1689 /* create pending item */ 1690 pend->buffer = sldns_buffer_new(sldns_buffer_limit(query)+10); 1691 if(!pend->buffer) { 1692 free(fc); 1693 free(pend); 1694 return NULL; 1695 } 1696 sldns_buffer_copy(pend->buffer, query); 1697 memcpy(&pend->addr, to_addr, to_addrlen); 1698 pend->addrlen = to_addrlen; 1699 pend->zone = NULL; 1700 pend->zonelen = 0; 1701 if(LDNS_QDCOUNT(sldns_buffer_begin(query)) > 0) { 1702 char buf[512]; 1703 char addrbuf[128]; 1704 (void)sldns_wire2str_rrquestion_buf(sldns_buffer_at(query, LDNS_HEADER_SIZE), sldns_buffer_limit(query)-LDNS_HEADER_SIZE, buf, sizeof(buf)); 1705 addr_to_str((struct sockaddr_storage*)to_addr, to_addrlen, 1706 addrbuf, sizeof(addrbuf)); 1707 if(verbosity >= VERB_ALGO) { 1708 if(buf[0] != 0) buf[strlen(buf)-1] = 0; /* del newline*/ 1709 log_info("tcp to %s: %s", addrbuf, buf); 1710 } 1711 log_assert(sldns_buffer_limit(query)-LDNS_HEADER_SIZE >= 2); 1712 pend->qtype = (int)sldns_buffer_read_u16_at(query, 1713 LDNS_HEADER_SIZE+ 1714 dname_valid(sldns_buffer_at(query, LDNS_HEADER_SIZE), 1715 sldns_buffer_limit(query)-LDNS_HEADER_SIZE)); 1716 } 1717 pend->callback = cb; 1718 pend->cb_arg = cb_arg; 1719 pend->timeout = timeout; 1720 pend->transport = transport_tcp; 1721 pend->pkt = NULL; 1722 pend->runtime = runtime; 1723 pend->serviced = 0; 1724 pend->pkt_len = sldns_buffer_limit(pend->buffer); 1725 pend->pkt = memdup(sldns_buffer_begin(pend->buffer), pend->pkt_len); 1726 if(!pend->pkt) fatal_exit("out of memory"); 1727 1728 log_info("testbound: created fake pending for tcp_out"); 1729 1730 /* add to list */ 1731 pend->next = runtime->pending_list; 1732 runtime->pending_list = pend; 1733 1734 return (struct comm_point*)fc; 1735} 1736 1737struct comm_point* outnet_comm_point_for_http(struct outside_network* outnet, 1738 comm_point_callback_type* cb, void* cb_arg, 1739 struct sockaddr_storage* to_addr, socklen_t to_addrlen, int timeout, 1740 int ssl, char* host, char* path) 1741{ 1742 struct replay_runtime* runtime = (struct replay_runtime*) 1743 outnet->base; 1744 struct fake_commpoint* fc = (struct fake_commpoint*)calloc(1, 1745 sizeof(*fc)); 1746 if(!fc) { 1747 return NULL; 1748 } 1749 fc->typecode = FAKE_COMMPOINT_TYPECODE; 1750 fc->type_http_out = 1; 1751 fc->cb = cb; 1752 fc->cb_arg = cb_arg; 1753 fc->runtime = runtime; 1754 1755 (void)to_addr; 1756 (void)to_addrlen; 1757 (void)timeout; 1758 1759 (void)ssl; 1760 (void)host; 1761 (void)path; 1762 1763 /* handle http comm point and return contents from test script */ 1764 return (struct comm_point*)fc; 1765} 1766 1767int comm_point_send_udp_msg(struct comm_point *c, sldns_buffer* packet, 1768 struct sockaddr* addr, socklen_t addrlen, int ATTR_UNUSED(is_connected)) 1769{ 1770 struct fake_commpoint* fc = (struct fake_commpoint*)c; 1771 struct replay_runtime* runtime = fc->runtime; 1772 struct fake_pending* pend = (struct fake_pending*)calloc(1, 1773 sizeof(struct fake_pending)); 1774 if(!pend) { 1775 log_err("malloc failure"); 1776 return 0; 1777 } 1778 fc->pending = pend; 1779 /* used by authzone transfers */ 1780 /* create pending item */ 1781 pend->buffer = sldns_buffer_new(sldns_buffer_limit(packet) + 10); 1782 if(!pend->buffer) { 1783 free(pend); 1784 return 0; 1785 } 1786 sldns_buffer_copy(pend->buffer, packet); 1787 memcpy(&pend->addr, addr, addrlen); 1788 pend->addrlen = addrlen; 1789 pend->zone = NULL; 1790 pend->zonelen = 0; 1791 if(LDNS_QDCOUNT(sldns_buffer_begin(packet)) > 0) { 1792 char buf[512]; 1793 char addrbuf[128]; 1794 (void)sldns_wire2str_rrquestion_buf(sldns_buffer_at(packet, LDNS_HEADER_SIZE), sldns_buffer_limit(packet)-LDNS_HEADER_SIZE, buf, sizeof(buf)); 1795 addr_to_str((struct sockaddr_storage*)addr, addrlen, 1796 addrbuf, sizeof(addrbuf)); 1797 if(verbosity >= VERB_ALGO) { 1798 if(buf[0] != 0) buf[strlen(buf)-1] = 0; /* del newline*/ 1799 log_info("udp to %s: %s", addrbuf, buf); 1800 } 1801 log_assert(sldns_buffer_limit(packet)-LDNS_HEADER_SIZE >= 2); 1802 pend->qtype = (int)sldns_buffer_read_u16_at(packet, 1803 LDNS_HEADER_SIZE+ 1804 dname_valid(sldns_buffer_at(packet, LDNS_HEADER_SIZE), 1805 sldns_buffer_limit(packet)-LDNS_HEADER_SIZE)); 1806 } 1807 pend->callback = fc->cb; 1808 pend->cb_arg = fc->cb_arg; 1809 pend->timeout = UDP_AUTH_QUERY_TIMEOUT/1000; 1810 pend->transport = transport_udp; 1811 pend->pkt = NULL; 1812 pend->runtime = runtime; 1813 pend->serviced = 0; 1814 pend->pkt_len = sldns_buffer_limit(pend->buffer); 1815 pend->pkt = memdup(sldns_buffer_begin(pend->buffer), pend->pkt_len); 1816 if(!pend->pkt) fatal_exit("out of memory"); 1817 1818 log_info("testbound: created fake pending for send_udp_msg"); 1819 1820 /* add to list */ 1821 pend->next = runtime->pending_list; 1822 runtime->pending_list = pend; 1823 1824 return 1; 1825} 1826 1827int outnet_get_tcp_fd(struct sockaddr_storage* ATTR_UNUSED(addr), 1828 socklen_t ATTR_UNUSED(addrlen), int ATTR_UNUSED(tcp_mss), int ATTR_UNUSED(dscp)) 1829{ 1830 log_assert(0); 1831 return -1; 1832} 1833 1834int outnet_tcp_connect(int ATTR_UNUSED(s), struct sockaddr_storage* ATTR_UNUSED(addr), 1835 socklen_t ATTR_UNUSED(addrlen)) 1836{ 1837 log_assert(0); 1838 return 0; 1839} 1840 1841int tcp_req_info_add_meshstate(struct tcp_req_info* ATTR_UNUSED(req), 1842 struct mesh_area* ATTR_UNUSED(mesh), struct mesh_state* ATTR_UNUSED(m)) 1843{ 1844 log_assert(0); 1845 return 0; 1846} 1847 1848void 1849tcp_req_info_remove_mesh_state(struct tcp_req_info* ATTR_UNUSED(req), 1850 struct mesh_state* ATTR_UNUSED(m)) 1851{ 1852 log_assert(0); 1853} 1854 1855size_t 1856tcp_req_info_get_stream_buffer_size(void) 1857{ 1858 return 0; 1859} 1860 1861size_t 1862http2_get_query_buffer_size(void) 1863{ 1864 return 0; 1865} 1866 1867size_t 1868http2_get_response_buffer_size(void) 1869{ 1870 return 0; 1871} 1872 1873void http2_stream_add_meshstate(struct http2_stream* ATTR_UNUSED(h2_stream), 1874 struct mesh_area* ATTR_UNUSED(mesh), struct mesh_state* ATTR_UNUSED(m)) 1875{ 1876} 1877 1878/*********** End of Dummy routines ***********/ 1879