]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - testcode/fake_event.c
import unbound 1.4.21
[FreeBSD/FreeBSD.git] / testcode / fake_event.c
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 LIMITED
25  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
27  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * 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/config_file.h"
56 #include "services/listen_dnsport.h"
57 #include "services/outside_network.h"
58 #include "services/cache/infra.h"
59 #include "testcode/replay.h"
60 #include "testcode/ldns-testpkts.h"
61 #include "util/log.h"
62 #include "util/fptr_wlist.h"
63 #include <signal.h>
64 struct worker;
65 struct daemon_remote;
66
67 /** Global variable: the scenario. Saved here for when event_init is done. */
68 static struct replay_scenario* saved_scenario = NULL;
69
70 /** add timers and the values do not overflow or become negative */
71 static void
72 timeval_add(struct timeval* d, const struct timeval* add)
73 {
74 #ifndef S_SPLINT_S
75         d->tv_sec += add->tv_sec;
76         d->tv_usec += add->tv_usec;
77         if(d->tv_usec > 1000000) {
78                 d->tv_usec -= 1000000;
79                 d->tv_sec++;
80         }
81 #endif
82 }
83
84 void 
85 fake_temp_file(const char* adj, const char* id, char* buf, size_t len)
86 {
87 #ifdef USE_WINSOCK
88         snprintf(buf, len, "testbound_%u%s%s.tmp",
89                 (unsigned)getpid(), adj, id);
90 #else
91         snprintf(buf, len, "/tmp/testbound_%u%s%s.tmp",
92                 (unsigned)getpid(), adj, id);
93 #endif
94 }
95
96 void 
97 fake_event_init(struct replay_scenario* scen)
98 {
99         saved_scenario = scen;
100 }
101
102 void 
103 fake_event_cleanup(void)
104 {
105         replay_scenario_delete(saved_scenario);
106         saved_scenario = NULL;
107 }
108
109 /** helper function that logs a ldns_pkt packet to logfile */
110 static void
111 log_pkt(const char* desc, ldns_pkt* pkt)
112 {
113         char* str = ldns_pkt2str(pkt);
114         if(!str)
115                 log_info("%s: (failed)", desc);
116         else {
117                 log_info("%s%s", desc, str);
118                 free(str);
119         }
120 }
121
122 /**
123  * Returns a string describing the event type.
124  */
125 static const char*
126 repevt_string(enum replay_event_type t)
127 {
128         switch(t) {
129         case repevt_nothing:     return "NOTHING";
130         case repevt_front_query: return "QUERY";
131         case repevt_front_reply: return "CHECK_ANSWER";
132         case repevt_timeout:     return "TIMEOUT";
133         case repevt_time_passes: return "TIME_PASSES";
134         case repevt_back_reply:  return "REPLY";
135         case repevt_back_query:  return "CHECK_OUT_QUERY";
136         case repevt_autotrust_check: return "CHECK_AUTOTRUST";
137         case repevt_error:       return "ERROR";
138         case repevt_assign:      return "ASSIGN";
139         case repevt_traffic:     return "TRAFFIC";
140         case repevt_infra_rtt:   return "INFRA_RTT";
141         default:                 return "UNKNOWN";
142         }
143 }
144
145 /** delete a fake pending */
146 static void 
147 delete_fake_pending(struct fake_pending* pend)
148 {
149         if(!pend)
150                 return;
151         free(pend->zone);
152         ldns_buffer_free(pend->buffer);
153         ldns_pkt_free(pend->pkt);
154         free(pend);
155 }
156
157 /** delete a replay answer */
158 static void
159 delete_replay_answer(struct replay_answer* a)
160 {
161         if(!a)
162                 return;
163         if(a->repinfo.c) {
164                 ldns_buffer_free(a->repinfo.c->buffer);
165                 free(a->repinfo.c);
166         }
167         ldns_pkt_free(a->pkt);
168         free(a);
169 }
170
171 /**
172  * return: true if pending query matches the now event.
173  */
174 static int 
175 pending_matches_current(struct replay_runtime* runtime, 
176         struct entry** entry, struct fake_pending **pend)
177 {
178         struct fake_pending* p;
179         struct entry* e;
180         if(!runtime->now || runtime->now->evt_type != repevt_back_query
181                 || !runtime->pending_list)
182                 return 0;
183         /* see if any of the pending queries matches */
184         for(p = runtime->pending_list; p; p = p->next) {
185                 if(runtime->now->addrlen != 0 &&
186                         sockaddr_cmp(&p->addr, p->addrlen, &runtime->now->addr,
187                         runtime->now->addrlen) != 0)
188                         continue;
189                 if((e=find_match(runtime->now->match, p->pkt, p->transport))) {
190                         *entry = e;
191                         *pend = p;
192                         return 1;
193                 }
194         }
195         return 0;
196 }
197
198 /**
199  * Find the range that matches this pending message.
200  * @param runtime: runtime with current moment, and range list.
201  * @param entry: returns the pointer to entry that matches.
202  * @param pend: the pending that the entry must match.
203  * @return: true if a match is found.
204  */
205 static int
206 pending_find_match(struct replay_runtime* runtime, struct entry** entry, 
207         struct fake_pending* pend)
208 {
209         int timenow = runtime->now->time_step;
210         struct replay_range* p = runtime->scenario->range_list;
211         while(p) {
212                 if(p->start_step <= timenow && timenow <= p->end_step &&
213                   (p->addrlen == 0 || sockaddr_cmp(&p->addr, p->addrlen,
214                         &pend->addr, pend->addrlen) == 0) &&
215                   (*entry = find_match(p->match, pend->pkt, pend->transport))) {
216                         log_info("matched query time %d in range [%d, %d] "
217                                 "with entry line %d", timenow, 
218                                 p->start_step, p->end_step, (*entry)->lineno);
219                         if(p->addrlen != 0)
220                                 log_addr(0, "matched ip", &p->addr, p->addrlen);
221                         log_pkt("matched pkt: ", (*entry)->reply_list->reply);
222                         return 1;
223                 }
224                 p = p->next_range;
225         }
226         return 0;
227 }
228
229 /**
230  * See if outgoing pending query matches an entry.
231  * @param runtime: runtime.
232  * @param entry: if true, the entry that matches is returned.
233  * @param pend: if true, the outgoing message that matches is returned.
234  * @return: true if pending query matches the now event.
235  */
236 static int 
237 pending_matches_range(struct replay_runtime* runtime, 
238         struct entry** entry, struct fake_pending** pend)
239 {
240         struct fake_pending* p = runtime->pending_list;
241         /* slow, O(N*N), but it works as advertised with weird matching */
242         while(p) {
243                 log_info("check of pending");
244                 if(pending_find_match(runtime, entry, p)) {
245                         *pend = p;
246                         return 1;
247                 }
248                 p = p->next;
249         }
250         return 0;
251 }
252
253 /**
254  * Remove the item from the pending list.
255  */
256 static void
257 pending_list_delete(struct replay_runtime* runtime, struct fake_pending* pend)
258 {
259         struct fake_pending** prev = &runtime->pending_list;
260         struct fake_pending* p = runtime->pending_list;
261
262         while(p) {
263                 if(p == pend) {
264                         *prev = p->next;
265                         delete_fake_pending(pend);
266                         return;
267                 }
268
269                 prev = &p->next;
270                 p = p->next;
271         }
272 }
273
274 /**
275  * Fill buffer with reply from the entry.
276  */
277 static void
278 fill_buffer_with_reply(ldns_buffer* buffer, struct entry* entry, ldns_pkt* q)
279 {
280         ldns_status status;
281         ldns_pkt* answer_pkt = NULL;
282         log_assert(entry && entry->reply_list);
283         ldns_buffer_clear(buffer);
284         if(entry->reply_list->reply_from_hex) {
285                 status = ldns_buffer2pkt_wire(&answer_pkt, 
286                         entry->reply_list->reply_from_hex);
287                 if(status != LDNS_STATUS_OK) {
288                         log_err("testbound: hex packet unparsable, used asis.");
289                         ldns_buffer_write(buffer, 
290                         ldns_buffer_begin(entry->reply_list->reply_from_hex), 
291                         ldns_buffer_limit(entry->reply_list->reply_from_hex));
292                 }
293         } else {
294                 answer_pkt = ldns_pkt_clone(entry->reply_list->reply);
295         }
296         if(answer_pkt) {
297                 if(q) adjust_packet(entry, answer_pkt, q);
298                 status = ldns_pkt2buffer_wire(buffer, answer_pkt);
299                 if(status != LDNS_STATUS_OK)
300                         fatal_exit("ldns: cannot pkt2buffer_wire parsed pkt");
301         }
302         ldns_pkt_free(answer_pkt);
303         ldns_buffer_flip(buffer);
304 }
305
306 /**
307  * Perform range entry on pending message.
308  * @param runtime: runtime buffer size preference.
309  * @param entry: entry that codes for the reply to do.
310  * @param pend: pending query that is answered, callback called.
311  */
312 static void
313 answer_callback_from_entry(struct replay_runtime* runtime,
314         struct entry* entry, struct fake_pending* pend)
315 {
316         struct comm_point c;
317         struct comm_reply repinfo;
318         void* cb_arg = pend->cb_arg;
319         comm_point_callback_t* cb = pend->callback;
320
321         memset(&c, 0, sizeof(c));
322         c.fd = -1;
323         c.buffer = ldns_buffer_new(runtime->bufsize);
324         c.type = comm_udp;
325         if(pend->transport == transport_tcp)
326                 c.type = comm_tcp;
327         fill_buffer_with_reply(c.buffer, entry, pend->pkt);
328         repinfo.c = &c;
329         repinfo.addrlen = pend->addrlen;
330         memcpy(&repinfo.addr, &pend->addr, pend->addrlen);
331         if(!pend->serviced)
332                 pending_list_delete(runtime, pend);
333         if((*cb)(&c, cb_arg, NETEVENT_NOERROR, &repinfo)) {
334                 fatal_exit("testbound: unexpected: callback returned 1");
335         }
336         ldns_buffer_free(c.buffer);
337 }
338
339 /** Check the now moment answer check event */
340 static void
341 answer_check_it(struct replay_runtime* runtime)
342 {
343         struct replay_answer* ans = runtime->answer_list, 
344                 *prev = NULL;
345         log_assert(runtime && runtime->now && 
346                 runtime->now->evt_type == repevt_front_reply);
347         while(ans) {
348                 enum transport_type tr = transport_tcp;
349                 if(ans->repinfo.c->type == comm_udp)
350                         tr = transport_udp;
351                 if((runtime->now->addrlen == 0 || sockaddr_cmp(
352                         &runtime->now->addr, runtime->now->addrlen,
353                         &ans->repinfo.addr, ans->repinfo.addrlen) == 0) &&
354                         find_match(runtime->now->match, ans->pkt, tr)) {
355                         log_info("testbound matched event entry from line %d",
356                                 runtime->now->match->lineno);
357                         log_info("testbound: do STEP %d %s", 
358                                 runtime->now->time_step,
359                                 repevt_string(runtime->now->evt_type));
360                         if(prev)
361                                 prev->next = ans->next;
362                         else    runtime->answer_list = ans->next;
363                         if(!ans->next)
364                                 runtime->answer_last = prev;
365                         delete_replay_answer(ans);
366                         return;
367                 } else {
368                         prev = ans;
369                         ans = ans->next;
370                 }
371         }
372         log_info("testbound: do STEP %d %s", runtime->now->time_step,
373                 repevt_string(runtime->now->evt_type));
374         fatal_exit("testbound: not matched");
375 }
376
377 /**
378  * Create commpoint (as return address) for a fake incoming query.
379  */
380 static void
381 fake_front_query(struct replay_runtime* runtime, struct replay_moment *todo)
382 {
383         struct comm_reply repinfo;
384         memset(&repinfo, 0, sizeof(repinfo));
385         repinfo.c = (struct comm_point*)calloc(1, sizeof(struct comm_point));
386         repinfo.addrlen = (socklen_t)sizeof(struct sockaddr_in);
387         if(todo->addrlen != 0) {
388                 repinfo.addrlen = todo->addrlen;
389                 memcpy(&repinfo.addr, &todo->addr, todo->addrlen);
390         }
391         repinfo.c->fd = -1;
392         repinfo.c->ev = (struct internal_event*)runtime;
393         repinfo.c->buffer = ldns_buffer_new(runtime->bufsize);
394         if(todo->match->match_transport == transport_tcp)
395                 repinfo.c->type = comm_tcp;
396         else    repinfo.c->type = comm_udp;
397         fill_buffer_with_reply(repinfo.c->buffer, todo->match, NULL);
398         log_info("testbound: incoming QUERY");
399         log_pkt("query pkt", todo->match->reply_list->reply);
400         /* call the callback for incoming queries */
401         if((*runtime->callback_query)(repinfo.c, runtime->cb_arg, 
402                 NETEVENT_NOERROR, &repinfo)) {
403                 /* send immediate reply */
404                 comm_point_send_reply(&repinfo);
405         }
406         /* clear it again, in case copy not done properly */
407         memset(&repinfo, 0, sizeof(repinfo));
408 }
409
410 /**
411  * Perform callback for fake pending message.
412  */
413 static void
414 fake_pending_callback(struct replay_runtime* runtime, 
415         struct replay_moment* todo, int error)
416 {
417         struct fake_pending* p = runtime->pending_list;
418         struct comm_reply repinfo;
419         struct comm_point c;
420         void* cb_arg;
421         comm_point_callback_t* cb;
422
423         memset(&c, 0, sizeof(c));
424         if(!p) fatal_exit("No pending queries.");
425         cb_arg = p->cb_arg;
426         cb = p->callback;
427         log_assert(todo->qname == NULL); /* or find that one */
428         c.buffer = ldns_buffer_new(runtime->bufsize);
429         c.type = comm_udp;
430         if(p->transport == transport_tcp)
431                 c.type = comm_tcp;
432         if(todo->evt_type == repevt_back_reply && todo->match) {
433                 fill_buffer_with_reply(c.buffer, todo->match, p->pkt);
434         }
435         repinfo.c = &c;
436         repinfo.addrlen = p->addrlen;
437         memcpy(&repinfo.addr, &p->addr, p->addrlen);
438         if(!p->serviced)
439                 pending_list_delete(runtime, p);
440         if((*cb)(&c, cb_arg, error, &repinfo)) {
441                 fatal_exit("unexpected: pending callback returned 1");
442         }
443         /* delete the pending item. */
444         ldns_buffer_free(c.buffer);
445 }
446
447 /** pass time */
448 static void
449 moment_assign(struct replay_runtime* runtime, struct replay_moment* mom)
450 {
451         char* value = macro_process(runtime->vars, runtime, mom->string);
452         if(!value)
453                 fatal_exit("could not process macro step %d", mom->time_step);
454         log_info("assign %s = %s", mom->variable, value);
455         if(!macro_assign(runtime->vars, mom->variable, value))
456                 fatal_exit("out of memory storing macro");
457         free(value);
458         if(verbosity >= VERB_ALGO)
459                 macro_print_debug(runtime->vars);
460 }
461
462 /** pass time */
463 static void
464 time_passes(struct replay_runtime* runtime, struct replay_moment* mom)
465 {
466         struct fake_timer *t;
467         struct timeval tv = mom->elapse;
468         if(mom->string) {
469                 char* xp = macro_process(runtime->vars, runtime, mom->string);
470                 double sec;
471                 if(!xp) fatal_exit("could not macro expand %s", mom->string);
472                 verbose(VERB_ALGO, "EVAL %s", mom->string);
473                 sec = atof(xp);
474                 free(xp);
475 #ifndef S_SPLINT_S
476                 tv.tv_sec = sec;
477                 tv.tv_usec = (int)((sec - (double)tv.tv_sec) *1000000. + 0.5);
478 #endif
479         }
480         timeval_add(&runtime->now_tv, &tv);
481         runtime->now_secs = (time_t)runtime->now_tv.tv_sec;
482 #ifndef S_SPLINT_S
483         log_info("elapsed %d.%6.6d  now %d.%6.6d", 
484                 (int)tv.tv_sec, (int)tv.tv_usec,
485                 (int)runtime->now_tv.tv_sec, (int)runtime->now_tv.tv_usec);
486 #endif
487         /* see if any timers have fired; and run them */
488         while( (t=replay_get_oldest_timer(runtime)) ) {
489                 t->enabled = 0;
490                 log_info("fake_timer callback");
491                 fptr_ok(fptr_whitelist_comm_timer(t->cb));
492                 (*t->cb)(t->cb_arg);
493         }
494 }
495
496 /** check autotrust file contents */
497 static void
498 autotrust_check(struct replay_runtime* runtime, struct replay_moment* mom)
499 {
500         char name[1024], line[1024];
501         FILE *in;
502         int lineno = 0, oke=1;
503         char* expanded;
504         struct config_strlist* p;
505         line[sizeof(line)-1] = 0;
506         log_assert(mom->autotrust_id);
507         fake_temp_file("_auto_", mom->autotrust_id, name, sizeof(name));
508         in = fopen(name, "r");
509         if(!in) fatal_exit("could not open %s: %s", name, strerror(errno));
510         for(p=mom->file_content; p; p=p->next) {
511                 lineno++;
512                 if(!fgets(line, (int)sizeof(line)-1, in)) {
513                         log_err("autotrust check failed, could not read line");
514                         log_err("file %s, line %d", name, lineno);
515                         log_err("should be: %s", p->str);
516                         fatal_exit("autotrust_check failed");
517                 }
518                 if(line[0]) line[strlen(line)-1] = 0; /* remove newline */
519                 expanded = macro_process(runtime->vars, runtime, p->str);
520                 if(!expanded) 
521                         fatal_exit("could not expand macro line %d", lineno);
522                 if(verbosity >= 7 && strcmp(p->str, expanded) != 0)
523                         log_info("expanded '%s' to '%s'", p->str, expanded);
524                 if(strcmp(expanded, line) != 0) {
525                         log_err("mismatch in file %s, line %d", name, lineno);
526                         log_err("file has : %s", line);
527                         log_err("should be: %s", expanded);
528                         free(expanded);
529                         oke = 0;
530                         continue;
531                 }
532                 free(expanded);
533                 fprintf(stderr, "%s:%2d ok : %s\n", name, lineno, line);
534         }
535         if(fgets(line, (int)sizeof(line)-1, in)) {
536                 log_err("autotrust check failed, extra lines in %s after %d",
537                         name, lineno);
538                 do {
539                         fprintf(stderr, "file has: %s", line);
540                 } while(fgets(line, (int)sizeof(line)-1, in));
541                 oke = 0;
542         }
543         fclose(in);
544         if(!oke)
545                 fatal_exit("autotrust_check STEP %d failed", mom->time_step);
546         log_info("autotrust %s is OK", mom->autotrust_id);
547 }
548
549 /** Store RTT in infra cache */
550 static void
551 do_infra_rtt(struct replay_runtime* runtime)
552 {
553         struct replay_moment* now = runtime->now;
554         int rto;
555         ldns_rdf* dp = ldns_dname_new_frm_str(now->variable);
556         if(!dp) fatal_exit("cannot parse %s", now->variable);
557         rto = infra_rtt_update(runtime->infra, &now->addr,
558                 now->addrlen, ldns_rdf_data(dp), ldns_rdf_size(dp),
559                 LDNS_RR_TYPE_A, atoi(now->string), -1, runtime->now_secs);
560         log_addr(0, "INFRA_RTT for", &now->addr, now->addrlen);
561         log_info("INFRA_RTT(%s roundtrip %d): rto of %d", now->variable,
562                 atoi(now->string), rto);
563         if(rto == 0) fatal_exit("infra_rtt_update failed");
564         ldns_rdf_deep_free(dp);
565 }
566
567 /** perform exponential backoff on the timout */
568 static void
569 expon_timeout_backoff(struct replay_runtime* runtime)
570 {
571         struct fake_pending* p = runtime->pending_list;
572         int rtt, vs;
573         uint8_t edns_lame_known;
574         int last_rtt, rto;
575         if(!p) return; /* no pending packet to backoff */
576         if(!infra_host(runtime->infra, &p->addr, p->addrlen, p->zone,
577                 p->zonelen, runtime->now_secs, &vs, &edns_lame_known, &rtt))
578                 return;
579         last_rtt = rtt;
580         rto = infra_rtt_update(runtime->infra, &p->addr, p->addrlen, p->zone,
581                 p->zonelen, p->qtype, -1, last_rtt, runtime->now_secs);
582         log_info("infra_rtt_update returned rto %d", rto);
583 }
584
585 /**
586  * Advance to the next moment.
587  */
588 static void
589 advance_moment(struct replay_runtime* runtime)
590 {
591         if(!runtime->now)
592                 runtime->now = runtime->scenario->mom_first;
593         else    runtime->now = runtime->now->mom_next;
594 }
595
596 /**
597  * Perform actions or checks determined by the moment.
598  * Also advances the time by one step.
599  * @param runtime: scenario runtime information.
600  */
601 static void
602 do_moment_and_advance(struct replay_runtime* runtime)
603 {
604         struct replay_moment* mom;
605         if(!runtime->now) {
606                 advance_moment(runtime);
607                 return;
608         }
609         log_info("testbound: do STEP %d %s", runtime->now->time_step, 
610                 repevt_string(runtime->now->evt_type));
611         switch(runtime->now->evt_type) {
612         case repevt_nothing:
613                 advance_moment(runtime);
614                 break;
615         case repevt_front_query:
616                 /* advance moment before doing the step, so that the next
617                    moment which may check some result of the mom step
618                    can catch those results. */
619                 mom = runtime->now;
620                 advance_moment(runtime);
621                 fake_front_query(runtime, mom);
622                 break;
623         case repevt_front_reply:
624                 if(runtime->answer_list) 
625                         log_err("testbound: There are unmatched answers.");
626                 fatal_exit("testbound: query answer not matched");
627                 break;
628         case repevt_timeout:
629                 mom = runtime->now;
630                 advance_moment(runtime);
631                 expon_timeout_backoff(runtime);
632                 fake_pending_callback(runtime, mom, NETEVENT_TIMEOUT);
633                 break;
634         case repevt_back_reply:
635                 mom = runtime->now;
636                 advance_moment(runtime);
637                 fake_pending_callback(runtime, mom, NETEVENT_NOERROR);
638                 break;
639         case repevt_back_query:
640                 /* Back queries are matched when they are sent out. */
641                 log_err("No query matching the current moment was sent.");
642                 fatal_exit("testbound: back query not matched");
643                 break;
644         case repevt_error:
645                 mom = runtime->now;
646                 advance_moment(runtime);
647                 fake_pending_callback(runtime, mom, NETEVENT_CLOSED);
648                 break;
649         case repevt_time_passes:
650                 time_passes(runtime, runtime->now);
651                 advance_moment(runtime);
652                 break;
653         case repevt_autotrust_check:
654                 autotrust_check(runtime, runtime->now);
655                 advance_moment(runtime);
656                 break;
657         case repevt_assign:
658                 moment_assign(runtime, runtime->now);
659                 advance_moment(runtime);
660                 break;
661         case repevt_traffic:
662                 advance_moment(runtime);
663                 break;
664         case repevt_infra_rtt:
665                 do_infra_rtt(runtime);
666                 advance_moment(runtime);
667                 break;
668         default:
669                 fatal_exit("testbound: unknown event type %d", 
670                         runtime->now->evt_type);
671         }
672 }
673
674 /** run the scenario in event callbacks */
675 static void
676 run_scenario(struct replay_runtime* runtime)
677 {
678         struct entry* entry = NULL;
679         struct fake_pending* pending = NULL;
680         int max_rounds = 5000;
681         int rounds = 0;
682         runtime->now = runtime->scenario->mom_first;
683         log_info("testbound: entering fake runloop");
684         do {
685                 /* if moment matches pending query do it. */
686                 /* else if moment matches given answer, do it */
687                 /* else if precoded_range matches pending, do it */
688                 /* else do the current moment */
689                 if(pending_matches_current(runtime, &entry, &pending)) {
690                         log_info("testbound: do STEP %d CHECK_OUT_QUERY", 
691                                 runtime->now->time_step);
692                         advance_moment(runtime);
693                         if(entry->copy_id)
694                                 answer_callback_from_entry(runtime, entry, 
695                                 pending);
696                 } else if(runtime->answer_list && runtime->now && 
697                         runtime->now->evt_type == repevt_front_reply) {
698                         answer_check_it(runtime);                       
699                         advance_moment(runtime);
700                 } else if(pending_matches_range(runtime, &entry, &pending)) {
701                         answer_callback_from_entry(runtime, entry, pending);
702                 } else {
703                         do_moment_and_advance(runtime);
704                 }
705                 log_info("testbound: end of event stage");
706                 rounds++;
707                 if(rounds > max_rounds)
708                         fatal_exit("testbound: too many rounds, it loops.");
709         } while(runtime->now);
710
711         if(runtime->pending_list) {
712                 struct fake_pending* p;
713                 log_err("testbound: there are still messages pending.");
714                 for(p = runtime->pending_list; p; p=p->next) {
715                         log_pkt("pending msg", p->pkt);
716                         log_addr(0, "pending to", &p->addr, p->addrlen);
717                 }
718                 fatal_exit("testbound: there are still messages pending.");
719         }
720         if(runtime->answer_list) {
721                 fatal_exit("testbound: there are unmatched answers.");
722         }
723         log_info("testbound: exiting fake runloop.");
724         runtime->exit_cleanly = 1;
725 }
726
727 /*********** Dummy routines ***********/
728
729 struct listen_dnsport* 
730 listen_create(struct comm_base* base, struct listen_port* ATTR_UNUSED(ports),
731         size_t bufsize, int ATTR_UNUSED(tcp_accept_count),
732         void* ATTR_UNUSED(sslctx), comm_point_callback_t* cb, void* cb_arg)
733 {
734         struct replay_runtime* runtime = (struct replay_runtime*)base;
735         struct listen_dnsport* l= calloc(1, sizeof(struct listen_dnsport));
736         if(!l)
737                 return NULL;
738         l->base = base;
739         l->udp_buff = ldns_buffer_new(bufsize);
740         if(!l->udp_buff) {
741                 free(l);
742                 return NULL;
743         }
744         runtime->callback_query = cb;
745         runtime->cb_arg = cb_arg;
746         runtime->bufsize = bufsize;
747         return l;
748 }
749
750 void 
751 listen_delete(struct listen_dnsport* listen)
752 {
753         if(!listen)
754                 return;
755         ldns_buffer_free(listen->udp_buff);
756         free(listen);
757 }
758
759 struct comm_base* 
760 comm_base_create(int ATTR_UNUSED(sigs))
761 {
762         /* we return the runtime structure instead. */
763         struct replay_runtime* runtime = (struct replay_runtime*)
764                 calloc(1, sizeof(struct replay_runtime));
765         runtime->scenario = saved_scenario;
766         runtime->vars = macro_store_create();
767         if(!runtime->vars) fatal_exit("out of memory");
768         return (struct comm_base*)runtime;
769 }
770
771 void 
772 comm_base_delete(struct comm_base* b)
773 {
774         struct replay_runtime* runtime = (struct replay_runtime*)b;
775         struct fake_pending* p, *np;
776         struct replay_answer* a, *na;
777         struct fake_timer* t, *nt;
778         if(!runtime)
779                 return;
780         runtime->scenario= NULL;
781         p = runtime->pending_list;
782         while(p) {
783                 np = p->next;
784                 delete_fake_pending(p);
785                 p = np;
786         }
787         a = runtime->answer_list;
788         while(a) {
789                 na = a->next;
790                 delete_replay_answer(a);
791                 a = na;
792         }
793         t = runtime->timer_list;
794         while(t) {
795                 nt = t->next;
796                 free(t);
797                 t = nt;
798         }
799         macro_store_delete(runtime->vars);
800         free(runtime);
801 }
802
803 void
804 comm_base_timept(struct comm_base* b, time_t** tt, struct timeval** tv)
805 {
806         struct replay_runtime* runtime = (struct replay_runtime*)b;
807         *tt = &runtime->now_secs;
808         *tv = &runtime->now_tv;
809 }
810
811 void 
812 comm_base_dispatch(struct comm_base* b)
813 {
814         struct replay_runtime* runtime = (struct replay_runtime*)b;
815         run_scenario(runtime);
816         if(runtime->sig_cb)
817                 (*runtime->sig_cb)(SIGTERM, runtime->sig_cb_arg);
818         else    exit(0); /* OK exit when LIBEVENT_SIGNAL_PROBLEM exists */
819 }
820
821 void 
822 comm_base_exit(struct comm_base* b)
823 {
824         struct replay_runtime* runtime = (struct replay_runtime*)b;
825         if(!runtime->exit_cleanly) {
826                 /* some sort of failure */
827                 fatal_exit("testbound: comm_base_exit was called.");
828         }
829 }
830
831 struct comm_signal* 
832 comm_signal_create(struct comm_base* base,
833         void (*callback)(int, void*), void* cb_arg)
834 {
835         struct replay_runtime* runtime = (struct replay_runtime*)base;
836         runtime->sig_cb = callback;
837         runtime->sig_cb_arg = cb_arg;
838         return calloc(1, sizeof(struct comm_signal));
839 }
840
841 int 
842 comm_signal_bind(struct comm_signal* ATTR_UNUSED(comsig), int 
843         ATTR_UNUSED(sig))
844 {
845         return 1;
846 }
847
848 void 
849 comm_signal_delete(struct comm_signal* comsig)
850 {
851         free(comsig);
852 }
853
854 void 
855 comm_point_send_reply(struct comm_reply* repinfo)
856 {
857         struct replay_answer* ans = (struct replay_answer*)calloc(1,
858                 sizeof(struct replay_answer));
859         ldns_status status;
860         struct replay_runtime* runtime = (struct replay_runtime*)repinfo->c->ev;
861         log_info("testbound: comm_point_send_reply fake");
862         /* dump it into the todo list */
863         log_assert(ans);
864         memcpy(&ans->repinfo, repinfo, sizeof(struct comm_reply));
865         ans->next = NULL;
866         if(runtime->answer_last)
867                 runtime->answer_last->next = ans;
868         else    runtime->answer_list = ans;
869         runtime->answer_last = ans;
870
871         /* try to parse packet */
872         status = ldns_buffer2pkt_wire(&ans->pkt, ans->repinfo.c->buffer);
873         if(status != LDNS_STATUS_OK) {
874                 log_err("ldns error parsing packet: %s",
875                         ldns_get_errorstr_by_id(status));
876                 fatal_exit("Sending unparseable DNS replies to clients!");
877         }
878         log_pkt("reply pkt: ", ans->pkt);
879 }
880
881 void 
882 comm_point_drop_reply(struct comm_reply* repinfo)
883 {
884         log_info("comm_point_drop_reply fake");
885         if(repinfo->c) {
886                 ldns_buffer_free(repinfo->c->buffer);
887                 free(repinfo->c);
888         }
889 }
890
891 struct outside_network* 
892 outside_network_create(struct comm_base* base, size_t bufsize, 
893         size_t ATTR_UNUSED(num_ports), char** ATTR_UNUSED(ifs), 
894         int ATTR_UNUSED(num_ifs), int ATTR_UNUSED(do_ip4), 
895         int ATTR_UNUSED(do_ip6), size_t ATTR_UNUSED(num_tcp), 
896         struct infra_cache* infra,
897         struct ub_randstate* ATTR_UNUSED(rnd), 
898         int ATTR_UNUSED(use_caps_for_id), int* ATTR_UNUSED(availports),
899         int ATTR_UNUSED(numavailports), size_t ATTR_UNUSED(unwanted_threshold),
900         void (*unwanted_action)(void*), void* ATTR_UNUSED(unwanted_param),
901         int ATTR_UNUSED(do_udp), void* ATTR_UNUSED(sslctx))
902 {
903         struct replay_runtime* runtime = (struct replay_runtime*)base;
904         struct outside_network* outnet =  calloc(1, 
905                 sizeof(struct outside_network));
906         (void)unwanted_action;
907         if(!outnet)
908                 return NULL;
909         runtime->infra = infra;
910         outnet->base = base;
911         outnet->udp_buff = ldns_buffer_new(bufsize);
912         if(!outnet->udp_buff) {
913                 free(outnet);
914                 return NULL;
915         }
916         return outnet;
917 }
918
919 void 
920 outside_network_delete(struct outside_network* outnet)
921 {
922         if(!outnet)
923                 return;
924         ldns_buffer_free(outnet->udp_buff);
925         free(outnet);
926 }
927
928 void 
929 outside_network_quit_prepare(struct outside_network* ATTR_UNUSED(outnet))
930 {
931 }
932
933 struct pending* 
934 pending_udp_query(struct outside_network* outnet, ldns_buffer* packet,
935         struct sockaddr_storage* addr, socklen_t addrlen, int timeout,
936         comm_point_callback_t* callback, void* callback_arg)
937 {
938         struct replay_runtime* runtime = (struct replay_runtime*)outnet->base;
939         struct fake_pending* pend = (struct fake_pending*)calloc(1,
940                 sizeof(struct fake_pending));
941         ldns_status status;
942         log_assert(pend);
943         pend->buffer = ldns_buffer_new(ldns_buffer_capacity(packet));
944         log_assert(pend->buffer);
945         ldns_buffer_write(pend->buffer, ldns_buffer_begin(packet),
946                 ldns_buffer_limit(packet));
947         ldns_buffer_flip(pend->buffer);
948         memcpy(&pend->addr, addr, addrlen);
949         pend->addrlen = addrlen;
950         pend->callback = callback;
951         pend->cb_arg = callback_arg;
952         pend->timeout = timeout/1000;
953         pend->transport = transport_udp;
954         pend->pkt = NULL;
955         pend->zone = NULL;
956         pend->serviced = 0;
957         pend->runtime = runtime;
958         status = ldns_buffer2pkt_wire(&pend->pkt, packet);
959         if(status != LDNS_STATUS_OK) {
960                 log_err("ldns error parsing udp output packet: %s",
961                         ldns_get_errorstr_by_id(status));
962                 fatal_exit("Sending unparseable DNS packets to servers!");
963         }
964         log_pkt("pending udp pkt: ", pend->pkt);
965
966         /* see if it matches the current moment */
967         if(runtime->now && runtime->now->evt_type == repevt_back_query &&
968                 (runtime->now->addrlen == 0 || sockaddr_cmp(
969                         &runtime->now->addr, runtime->now->addrlen,
970                         &pend->addr, pend->addrlen) == 0) &&
971                 find_match(runtime->now->match, pend->pkt, pend->transport)) {
972                 log_info("testbound: matched pending to event. "
973                         "advance time between events.");
974                 log_info("testbound: do STEP %d %s", runtime->now->time_step,
975                         repevt_string(runtime->now->evt_type));
976                 advance_moment(runtime);
977                 /* still create the pending, because we need it to callback */
978         } 
979         log_info("testbound: created fake pending");
980         /* add to list */
981         pend->next = runtime->pending_list;
982         runtime->pending_list = pend;
983         return (struct pending*)pend;
984 }
985
986 struct waiting_tcp* 
987 pending_tcp_query(struct outside_network* outnet, ldns_buffer* packet,
988         struct sockaddr_storage* addr, socklen_t addrlen, int timeout,
989         comm_point_callback_t* callback, void* callback_arg,
990         int ATTR_UNUSED(ssl_upstream))
991 {
992         struct replay_runtime* runtime = (struct replay_runtime*)outnet->base;
993         struct fake_pending* pend = (struct fake_pending*)calloc(1,
994                 sizeof(struct fake_pending));
995         ldns_status status;
996         log_assert(pend);
997         pend->buffer = ldns_buffer_new(ldns_buffer_capacity(packet));
998         log_assert(pend->buffer);
999         ldns_buffer_write(pend->buffer, ldns_buffer_begin(packet),
1000                 ldns_buffer_limit(packet));
1001         ldns_buffer_flip(pend->buffer);
1002         memcpy(&pend->addr, addr, addrlen);
1003         pend->addrlen = addrlen;
1004         pend->callback = callback;
1005         pend->cb_arg = callback_arg;
1006         pend->timeout = timeout;
1007         pend->transport = transport_tcp;
1008         pend->pkt = NULL;
1009         pend->zone = NULL;
1010         pend->runtime = runtime;
1011         pend->serviced = 0;
1012         status = ldns_buffer2pkt_wire(&pend->pkt, packet);
1013         if(status != LDNS_STATUS_OK) {
1014                 log_err("ldns error parsing tcp output packet: %s",
1015                         ldns_get_errorstr_by_id(status));
1016                 fatal_exit("Sending unparseable DNS packets to servers!");
1017         }
1018         log_pkt("pending tcp pkt: ", pend->pkt);
1019
1020         /* see if it matches the current moment */
1021         if(runtime->now && runtime->now->evt_type == repevt_back_query &&
1022                 (runtime->now->addrlen == 0 || sockaddr_cmp(
1023                         &runtime->now->addr, runtime->now->addrlen,
1024                         &pend->addr, pend->addrlen) == 0) &&
1025                 find_match(runtime->now->match, pend->pkt, pend->transport)) {
1026                 log_info("testbound: matched pending to event. "
1027                         "advance time between events.");
1028                 log_info("testbound: do STEP %d %s", runtime->now->time_step,
1029                         repevt_string(runtime->now->evt_type));
1030                 advance_moment(runtime);
1031                 /* still create the pending, because we need it to callback */
1032         } 
1033         log_info("testbound: created fake pending");
1034         /* add to list */
1035         pend->next = runtime->pending_list;
1036         runtime->pending_list = pend;
1037         return (struct waiting_tcp*)pend;
1038 }
1039
1040 struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
1041         uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
1042         uint16_t flags, int dnssec, int ATTR_UNUSED(want_dnssec),
1043         int ATTR_UNUSED(tcp_upstream), int ATTR_UNUSED(ssl_upstream),
1044         struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
1045         size_t zonelen, comm_point_callback_t* callback, void* callback_arg,
1046         ldns_buffer* ATTR_UNUSED(buff))
1047 {
1048         struct replay_runtime* runtime = (struct replay_runtime*)outnet->base;
1049         struct fake_pending* pend = (struct fake_pending*)calloc(1,
1050                 sizeof(struct fake_pending));
1051         char z[256];
1052         ldns_status status;
1053         log_assert(pend);
1054         log_nametypeclass(VERB_OPS, "pending serviced query", 
1055                 qname, qtype, qclass);
1056         dname_str(zone, z);
1057         verbose(VERB_OPS, "pending serviced query zone %s flags%s%s%s%s", 
1058                 z, (flags&BIT_RD)?" RD":"", (flags&BIT_CD)?" CD":"",
1059                 (flags&~(BIT_RD|BIT_CD))?" MORE":"", (dnssec)?" DO":"");
1060
1061         /* create packet with EDNS */
1062         pend->buffer = ldns_buffer_new(512);
1063         log_assert(pend->buffer);
1064         ldns_buffer_write_u16(pend->buffer, 0); /* id */
1065         ldns_buffer_write_u16(pend->buffer, flags);
1066         ldns_buffer_write_u16(pend->buffer, 1); /* qdcount */
1067         ldns_buffer_write_u16(pend->buffer, 0); /* ancount */
1068         ldns_buffer_write_u16(pend->buffer, 0); /* nscount */
1069         ldns_buffer_write_u16(pend->buffer, 0); /* arcount */
1070         ldns_buffer_write(pend->buffer, qname, qnamelen);
1071         ldns_buffer_write_u16(pend->buffer, qtype);
1072         ldns_buffer_write_u16(pend->buffer, qclass);
1073         ldns_buffer_flip(pend->buffer);
1074         if(1) {
1075                 /* add edns */
1076                 struct edns_data edns;
1077                 edns.edns_present = 1;
1078                 edns.ext_rcode = 0;
1079                 edns.edns_version = EDNS_ADVERTISED_VERSION;
1080                 edns.udp_size = EDNS_ADVERTISED_SIZE;
1081                 edns.bits = 0;
1082                 if(dnssec)
1083                         edns.bits = EDNS_DO;
1084                 attach_edns_record(pend->buffer, &edns);
1085         }
1086         memcpy(&pend->addr, addr, addrlen);
1087         pend->addrlen = addrlen;
1088         pend->zone = memdup(zone, zonelen);
1089         pend->zonelen = zonelen;
1090         pend->qtype = (int)qtype;
1091         log_assert(pend->zone);
1092         pend->callback = callback;
1093         pend->cb_arg = callback_arg;
1094         pend->timeout = UDP_AUTH_QUERY_TIMEOUT;
1095         pend->transport = transport_udp; /* pretend UDP */
1096         pend->pkt = NULL;
1097         pend->runtime = runtime;
1098         pend->serviced = 1;
1099         status = ldns_buffer2pkt_wire(&pend->pkt, pend->buffer);
1100         if(status != LDNS_STATUS_OK) {
1101                 log_err("ldns error parsing serviced output packet: %s",
1102                         ldns_get_errorstr_by_id(status));
1103                 fatal_exit("internal error");
1104         }
1105         /*log_pkt("pending serviced query: ", pend->pkt);*/
1106
1107         /* see if it matches the current moment */
1108         if(runtime->now && runtime->now->evt_type == repevt_back_query &&
1109                 (runtime->now->addrlen == 0 || sockaddr_cmp(
1110                         &runtime->now->addr, runtime->now->addrlen,
1111                         &pend->addr, pend->addrlen) == 0) &&
1112                 find_match(runtime->now->match, pend->pkt, pend->transport)) {
1113                 log_info("testbound: matched pending to event. "
1114                         "advance time between events.");
1115                 log_info("testbound: do STEP %d %s", runtime->now->time_step,
1116                         repevt_string(runtime->now->evt_type));
1117                 advance_moment(runtime);
1118                 /* still create the pending, because we need it to callback */
1119         } 
1120         log_info("testbound: created fake pending");
1121         /* add to list */
1122         pend->next = runtime->pending_list;
1123         runtime->pending_list = pend;
1124         return (struct serviced_query*)pend;
1125 }
1126
1127 void outnet_serviced_query_stop(struct serviced_query* sq, void* cb_arg)
1128 {
1129         struct fake_pending* pend = (struct fake_pending*)sq;
1130         struct replay_runtime* runtime = pend->runtime;
1131         /* delete from the list */
1132         struct fake_pending* p = runtime->pending_list, *prev=NULL;
1133         while(p) {
1134                 if(p == pend) {
1135                         log_assert(p->cb_arg == cb_arg);
1136                         log_info("serviced pending delete");
1137                         if(prev)
1138                                 prev->next = p->next;
1139                         else    runtime->pending_list = p->next;
1140                         ldns_buffer_free(p->buffer);
1141                         ldns_pkt_free(p->pkt);
1142                         free(p->zone);
1143                         free(p);
1144                         return;
1145                 }
1146                 prev = p;
1147                 p = p->next;
1148         }
1149         log_info("double delete of pending serviced query");
1150 }
1151
1152 struct listen_port* listening_ports_open(struct config_file* ATTR_UNUSED(cfg))
1153 {
1154         return calloc(1, 1);
1155 }
1156
1157 void listening_ports_free(struct listen_port* list)
1158 {
1159         free(list);
1160 }
1161
1162 struct comm_point* comm_point_create_local(struct comm_base* ATTR_UNUSED(base),
1163         int ATTR_UNUSED(fd), size_t ATTR_UNUSED(bufsize),
1164         comm_point_callback_t* ATTR_UNUSED(callback), 
1165         void* ATTR_UNUSED(callback_arg))
1166 {
1167         return calloc(1, 1);
1168 }
1169
1170 struct comm_point* comm_point_create_raw(struct comm_base* ATTR_UNUSED(base),
1171         int ATTR_UNUSED(fd), int ATTR_UNUSED(writing),
1172         comm_point_callback_t* ATTR_UNUSED(callback), 
1173         void* ATTR_UNUSED(callback_arg))
1174 {
1175         /* no pipe comm possible */
1176         return calloc(1, 1);
1177 }
1178
1179 void comm_point_start_listening(struct comm_point* ATTR_UNUSED(c), 
1180         int ATTR_UNUSED(newfd), int ATTR_UNUSED(sec))
1181 {
1182         /* no bg write pipe comm possible */
1183 }
1184
1185 void comm_point_stop_listening(struct comm_point* ATTR_UNUSED(c))
1186 {
1187         /* no bg write pipe comm possible */
1188 }
1189
1190 /* only cmd com _local gets deleted */
1191 void comm_point_delete(struct comm_point* c)
1192 {
1193         free(c);
1194 }
1195
1196 size_t listen_get_mem(struct listen_dnsport* ATTR_UNUSED(listen))
1197 {
1198         return 0;
1199 }
1200
1201 size_t outnet_get_mem(struct outside_network* ATTR_UNUSED(outnet))
1202 {
1203         return 0;
1204 }
1205
1206 size_t comm_point_get_mem(struct comm_point* ATTR_UNUSED(c))
1207 {
1208         return 0;
1209 }
1210
1211 size_t serviced_get_mem(struct serviced_query* ATTR_UNUSED(c))
1212 {
1213         return 0;
1214 }
1215
1216 /* fake for fptr wlist */
1217 int outnet_udp_cb(struct comm_point* ATTR_UNUSED(c), 
1218         void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
1219         struct comm_reply *ATTR_UNUSED(reply_info))
1220 {
1221         log_assert(0);
1222         return 0;
1223 }
1224
1225 int outnet_tcp_cb(struct comm_point* ATTR_UNUSED(c), 
1226         void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
1227         struct comm_reply *ATTR_UNUSED(reply_info))
1228 {
1229         log_assert(0);
1230         return 0;
1231 }
1232
1233 void pending_udp_timer_cb(void *ATTR_UNUSED(arg))
1234 {
1235         log_assert(0);
1236 }
1237
1238 void outnet_tcptimer(void* ATTR_UNUSED(arg))
1239 {
1240         log_assert(0);
1241 }
1242
1243 void comm_point_udp_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(event), 
1244         void* ATTR_UNUSED(arg))
1245 {
1246         log_assert(0);
1247 }
1248
1249 void comm_point_udp_ancil_callback(int ATTR_UNUSED(fd), 
1250         short ATTR_UNUSED(event), void* ATTR_UNUSED(arg))
1251 {
1252         log_assert(0);
1253 }
1254
1255 void comm_point_tcp_accept_callback(int ATTR_UNUSED(fd), 
1256         short ATTR_UNUSED(event), void* ATTR_UNUSED(arg))
1257 {
1258         log_assert(0);
1259 }
1260
1261 void comm_point_tcp_handle_callback(int ATTR_UNUSED(fd), 
1262         short ATTR_UNUSED(event), void* ATTR_UNUSED(arg))
1263 {
1264         log_assert(0);
1265 }
1266
1267 void comm_timer_callback(int ATTR_UNUSED(fd), 
1268         short ATTR_UNUSED(event), void* ATTR_UNUSED(arg))
1269 {
1270         log_assert(0);
1271 }
1272
1273 void comm_signal_callback(int ATTR_UNUSED(fd), 
1274         short ATTR_UNUSED(event), void* ATTR_UNUSED(arg))
1275 {
1276         log_assert(0);
1277 }
1278
1279 void comm_point_local_handle_callback(int ATTR_UNUSED(fd), 
1280         short ATTR_UNUSED(event), void* ATTR_UNUSED(arg))
1281 {
1282         log_assert(0);
1283 }
1284
1285 void comm_point_raw_handle_callback(int ATTR_UNUSED(fd), 
1286         short ATTR_UNUSED(event), void* ATTR_UNUSED(arg))
1287 {
1288         log_assert(0);
1289 }
1290
1291 void comm_base_handle_slow_accept(int ATTR_UNUSED(fd), 
1292         short ATTR_UNUSED(event), void* ATTR_UNUSED(arg))
1293 {
1294         log_assert(0);
1295 }
1296
1297 int serviced_udp_callback(struct comm_point* ATTR_UNUSED(c), 
1298         void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
1299         struct comm_reply* ATTR_UNUSED(reply_info))
1300 {
1301         log_assert(0);
1302         return 0;
1303 }
1304
1305 int serviced_tcp_callback(struct comm_point* ATTR_UNUSED(c), 
1306         void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
1307         struct comm_reply* ATTR_UNUSED(reply_info))
1308 {
1309         log_assert(0);
1310         return 0;
1311 }
1312
1313 int pending_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
1314 {
1315         log_assert(0);
1316         return 0;
1317 }
1318
1319 int serviced_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
1320 {
1321         log_assert(0);
1322         return 0;
1323 }
1324
1325 /* timers in testbound for autotrust. statistics tested in tpkg. */
1326 struct comm_timer* comm_timer_create(struct comm_base* base, 
1327         void (*cb)(void*), void* cb_arg)
1328 {
1329         struct replay_runtime* runtime = (struct replay_runtime*)base;
1330         struct fake_timer* t = (struct fake_timer*)calloc(1, sizeof(*t));
1331         t->cb = cb;
1332         t->cb_arg = cb_arg;
1333         fptr_ok(fptr_whitelist_comm_timer(t->cb)); /* check in advance */
1334         t->runtime = runtime;
1335         t->next = runtime->timer_list;
1336         runtime->timer_list = t;
1337         return (struct comm_timer*)t;
1338 }
1339
1340 void comm_timer_disable(struct comm_timer* timer)
1341 {
1342         struct fake_timer* t = (struct fake_timer*)timer;
1343         log_info("fake timer disabled");
1344         t->enabled = 0;
1345 }
1346
1347 void comm_timer_set(struct comm_timer* timer, struct timeval* tv)
1348 {
1349         struct fake_timer* t = (struct fake_timer*)timer;
1350         t->enabled = 1;
1351         t->tv = *tv;
1352         log_info("fake timer set %d.%6.6d", 
1353                 (int)t->tv.tv_sec, (int)t->tv.tv_usec);
1354         timeval_add(&t->tv, &t->runtime->now_tv);
1355 }
1356
1357 void comm_timer_delete(struct comm_timer* timer)
1358 {
1359         struct fake_timer* t = (struct fake_timer*)timer;
1360         struct fake_timer** pp, *p;
1361         if(!t) return;
1362
1363         /* remove from linked list */
1364         pp = &t->runtime->timer_list;
1365         p = t->runtime->timer_list;
1366         while(p) {
1367                 if(p == t) {
1368                         /* snip from list */
1369                         *pp = p->next;
1370                         break;
1371                 }
1372                 pp = &p->next;
1373                 p = p->next;
1374         }
1375
1376         free(timer);
1377 }
1378
1379 void comm_base_set_slow_accept_handlers(struct comm_base* ATTR_UNUSED(b),
1380         void (*stop_acc)(void*), void (*start_acc)(void*),
1381         void* ATTR_UNUSED(arg))
1382 {
1383         /* ignore this */
1384         (void)stop_acc;
1385         (void)start_acc;
1386 }
1387
1388 struct event_base* comm_base_internal(struct comm_base* ATTR_UNUSED(b))
1389 {
1390         /* no pipe comm possible in testbound */
1391         return NULL;
1392 }
1393
1394 void daemon_remote_exec(struct worker* ATTR_UNUSED(worker))
1395 {
1396 }
1397
1398 void listen_start_accept(struct listen_dnsport* ATTR_UNUSED(listen))
1399 {
1400 }
1401
1402 void listen_stop_accept(struct listen_dnsport* ATTR_UNUSED(listen))
1403 {
1404 }
1405
1406 void daemon_remote_start_accept(struct daemon_remote* ATTR_UNUSED(rc))
1407 {
1408 }
1409
1410 void daemon_remote_stop_accept(struct daemon_remote* ATTR_UNUSED(rc))
1411 {
1412 }
1413
1414 /*********** End of Dummy routines ***********/