]>
git.saurik.com Git - apple/network_cmds.git/blob - unbound/testcode/fake_event.c
2 * testcode/fake_event.c - fake event handling that replays existing scenario.
4 * Copyright (c) 2007, NLnet Labs. All rights reserved.
6 * This software is open source.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
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.
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.
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.
38 * Event service that replays a scenario.
39 * This implements the same exported symbols as the files:
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.
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/testpkts.h"
62 #include "util/fptr_wlist.h"
63 #include "ldns/sbuffer.h"
64 #include "ldns/wire2str.h"
65 #include "ldns/str2wire.h"
70 /** Global variable: the scenario. Saved here for when event_init is done. */
71 static struct replay_scenario
* saved_scenario
= NULL
;
73 /** add timers and the values do not overflow or become negative */
75 timeval_add(struct timeval
* d
, const struct timeval
* add
)
78 d
->tv_sec
+= add
->tv_sec
;
79 d
->tv_usec
+= add
->tv_usec
;
80 if(d
->tv_usec
> 1000000) {
81 d
->tv_usec
-= 1000000;
88 fake_temp_file(const char* adj
, const char* id
, char* buf
, size_t len
)
91 snprintf(buf
, len
, "testbound_%u%s%s.tmp",
92 (unsigned)getpid(), adj
, id
);
94 snprintf(buf
, len
, "/tmp/testbound_%u%s%s.tmp",
95 (unsigned)getpid(), adj
, id
);
100 fake_event_init(struct replay_scenario
* scen
)
102 saved_scenario
= scen
;
106 fake_event_cleanup(void)
108 replay_scenario_delete(saved_scenario
);
109 saved_scenario
= NULL
;
112 /** helper function that logs a sldns_pkt packet to logfile */
114 log_pkt(const char* desc
, uint8_t* pkt
, size_t len
)
116 char* str
= sldns_wire2str_pkt(pkt
, len
);
118 fatal_exit("%s: (failed out of memory wire2str_pkt)", desc
);
120 log_info("%s%s", desc
, str
);
126 * Returns a string describing the event type.
129 repevt_string(enum replay_event_type t
)
132 case repevt_nothing
: return "NOTHING";
133 case repevt_front_query
: return "QUERY";
134 case repevt_front_reply
: return "CHECK_ANSWER";
135 case repevt_timeout
: return "TIMEOUT";
136 case repevt_time_passes
: return "TIME_PASSES";
137 case repevt_back_reply
: return "REPLY";
138 case repevt_back_query
: return "CHECK_OUT_QUERY";
139 case repevt_autotrust_check
: return "CHECK_AUTOTRUST";
140 case repevt_error
: return "ERROR";
141 case repevt_assign
: return "ASSIGN";
142 case repevt_traffic
: return "TRAFFIC";
143 case repevt_infra_rtt
: return "INFRA_RTT";
144 default: return "UNKNOWN";
148 /** delete a fake pending */
150 delete_fake_pending(struct fake_pending
* pend
)
155 sldns_buffer_free(pend
->buffer
);
160 /** delete a replay answer */
162 delete_replay_answer(struct replay_answer
* a
)
167 sldns_buffer_free(a
->repinfo
.c
->buffer
);
175 * return: true if pending query matches the now event.
178 pending_matches_current(struct replay_runtime
* runtime
,
179 struct entry
** entry
, struct fake_pending
**pend
)
181 struct fake_pending
* p
;
183 if(!runtime
->now
|| runtime
->now
->evt_type
!= repevt_back_query
184 || !runtime
->pending_list
)
186 /* see if any of the pending queries matches */
187 for(p
= runtime
->pending_list
; p
; p
= p
->next
) {
188 if(runtime
->now
->addrlen
!= 0 &&
189 sockaddr_cmp(&p
->addr
, p
->addrlen
, &runtime
->now
->addr
,
190 runtime
->now
->addrlen
) != 0)
192 if((e
=find_match(runtime
->now
->match
, p
->pkt
, p
->pkt_len
,
203 * Find the range that matches this pending message.
204 * @param runtime: runtime with current moment, and range list.
205 * @param entry: returns the pointer to entry that matches.
206 * @param pend: the pending that the entry must match.
207 * @return: true if a match is found.
210 pending_find_match(struct replay_runtime
* runtime
, struct entry
** entry
,
211 struct fake_pending
* pend
)
213 int timenow
= runtime
->now
->time_step
;
214 struct replay_range
* p
= runtime
->scenario
->range_list
;
216 if(p
->start_step
<= timenow
&& timenow
<= p
->end_step
&&
217 (p
->addrlen
== 0 || sockaddr_cmp(&p
->addr
, p
->addrlen
,
218 &pend
->addr
, pend
->addrlen
) == 0) &&
219 (*entry
= find_match(p
->match
, pend
->pkt
, pend
->pkt_len
,
221 log_info("matched query time %d in range [%d, %d] "
222 "with entry line %d", timenow
,
223 p
->start_step
, p
->end_step
, (*entry
)->lineno
);
225 log_addr(0, "matched ip", &p
->addr
, p
->addrlen
);
226 log_pkt("matched pkt: ",
227 (*entry
)->reply_list
->reply_pkt
,
228 (*entry
)->reply_list
->reply_len
);
237 * See if outgoing pending query matches an entry.
238 * @param runtime: runtime.
239 * @param entry: if true, the entry that matches is returned.
240 * @param pend: if true, the outgoing message that matches is returned.
241 * @return: true if pending query matches the now event.
244 pending_matches_range(struct replay_runtime
* runtime
,
245 struct entry
** entry
, struct fake_pending
** pend
)
247 struct fake_pending
* p
= runtime
->pending_list
;
248 /* slow, O(N*N), but it works as advertised with weird matching */
250 log_info("check of pending");
251 if(pending_find_match(runtime
, entry
, p
)) {
261 * Remove the item from the pending list.
264 pending_list_delete(struct replay_runtime
* runtime
, struct fake_pending
* pend
)
266 struct fake_pending
** prev
= &runtime
->pending_list
;
267 struct fake_pending
* p
= runtime
->pending_list
;
272 delete_fake_pending(pend
);
282 * Fill buffer with reply from the entry.
285 fill_buffer_with_reply(sldns_buffer
* buffer
, struct entry
* entry
, uint8_t* q
,
290 log_assert(entry
&& entry
->reply_list
);
291 sldns_buffer_clear(buffer
);
292 if(entry
->reply_list
->reply_from_hex
) {
293 c
= sldns_buffer_begin(entry
->reply_list
->reply_from_hex
);
294 clen
= sldns_buffer_limit(entry
->reply_list
->reply_from_hex
);
295 if(!c
) fatal_exit("out of memory");
297 c
= entry
->reply_list
->reply_pkt
;
298 clen
= entry
->reply_list
->reply_len
;
301 if(q
) adjust_packet(entry
, &c
, &clen
, q
, qlen
);
302 sldns_buffer_write(buffer
, c
, clen
);
305 sldns_buffer_flip(buffer
);
309 * Perform range entry on pending message.
310 * @param runtime: runtime buffer size preference.
311 * @param entry: entry that codes for the reply to do.
312 * @param pend: pending query that is answered, callback called.
315 answer_callback_from_entry(struct replay_runtime
* runtime
,
316 struct entry
* entry
, struct fake_pending
* pend
)
319 struct comm_reply repinfo
;
320 void* cb_arg
= pend
->cb_arg
;
321 comm_point_callback_t
* cb
= pend
->callback
;
323 memset(&c
, 0, sizeof(c
));
325 c
.buffer
= sldns_buffer_new(runtime
->bufsize
);
327 if(pend
->transport
== transport_tcp
)
329 fill_buffer_with_reply(c
.buffer
, entry
, pend
->pkt
, pend
->pkt_len
);
331 repinfo
.addrlen
= pend
->addrlen
;
332 memcpy(&repinfo
.addr
, &pend
->addr
, pend
->addrlen
);
334 pending_list_delete(runtime
, pend
);
335 if((*cb
)(&c
, cb_arg
, NETEVENT_NOERROR
, &repinfo
)) {
336 fatal_exit("testbound: unexpected: callback returned 1");
338 sldns_buffer_free(c
.buffer
);
341 /** Check the now moment answer check event */
343 answer_check_it(struct replay_runtime
* runtime
)
345 struct replay_answer
* ans
= runtime
->answer_list
,
347 log_assert(runtime
&& runtime
->now
&&
348 runtime
->now
->evt_type
== repevt_front_reply
);
350 enum transport_type tr
= transport_tcp
;
351 if(ans
->repinfo
.c
->type
== comm_udp
)
353 if((runtime
->now
->addrlen
== 0 || sockaddr_cmp(
354 &runtime
->now
->addr
, runtime
->now
->addrlen
,
355 &ans
->repinfo
.addr
, ans
->repinfo
.addrlen
) == 0) &&
356 find_match(runtime
->now
->match
, ans
->pkt
,
358 log_info("testbound matched event entry from line %d",
359 runtime
->now
->match
->lineno
);
360 log_info("testbound: do STEP %d %s",
361 runtime
->now
->time_step
,
362 repevt_string(runtime
->now
->evt_type
));
364 prev
->next
= ans
->next
;
365 else runtime
->answer_list
= ans
->next
;
367 runtime
->answer_last
= prev
;
368 delete_replay_answer(ans
);
375 log_info("testbound: do STEP %d %s", runtime
->now
->time_step
,
376 repevt_string(runtime
->now
->evt_type
));
377 fatal_exit("testbound: not matched");
381 * Create commpoint (as return address) for a fake incoming query.
384 fake_front_query(struct replay_runtime
* runtime
, struct replay_moment
*todo
)
386 struct comm_reply repinfo
;
387 memset(&repinfo
, 0, sizeof(repinfo
));
388 repinfo
.c
= (struct comm_point
*)calloc(1, sizeof(struct comm_point
));
389 repinfo
.addrlen
= (socklen_t
)sizeof(struct sockaddr_in
);
390 if(todo
->addrlen
!= 0) {
391 repinfo
.addrlen
= todo
->addrlen
;
392 memcpy(&repinfo
.addr
, &todo
->addr
, todo
->addrlen
);
395 repinfo
.c
->ev
= (struct internal_event
*)runtime
;
396 repinfo
.c
->buffer
= sldns_buffer_new(runtime
->bufsize
);
397 if(todo
->match
->match_transport
== transport_tcp
)
398 repinfo
.c
->type
= comm_tcp
;
399 else repinfo
.c
->type
= comm_udp
;
400 fill_buffer_with_reply(repinfo
.c
->buffer
, todo
->match
, NULL
, 0);
401 log_info("testbound: incoming QUERY");
402 log_pkt("query pkt", todo
->match
->reply_list
->reply_pkt
,
403 todo
->match
->reply_list
->reply_len
);
404 /* call the callback for incoming queries */
405 if((*runtime
->callback_query
)(repinfo
.c
, runtime
->cb_arg
,
406 NETEVENT_NOERROR
, &repinfo
)) {
407 /* send immediate reply */
408 comm_point_send_reply(&repinfo
);
410 /* clear it again, in case copy not done properly */
411 memset(&repinfo
, 0, sizeof(repinfo
));
415 * Perform callback for fake pending message.
418 fake_pending_callback(struct replay_runtime
* runtime
,
419 struct replay_moment
* todo
, int error
)
421 struct fake_pending
* p
= runtime
->pending_list
;
422 struct comm_reply repinfo
;
425 comm_point_callback_t
* cb
;
427 memset(&c
, 0, sizeof(c
));
428 if(!p
) fatal_exit("No pending queries.");
431 c
.buffer
= sldns_buffer_new(runtime
->bufsize
);
433 if(p
->transport
== transport_tcp
)
435 if(todo
->evt_type
== repevt_back_reply
&& todo
->match
) {
436 fill_buffer_with_reply(c
.buffer
, todo
->match
, p
->pkt
,
440 repinfo
.addrlen
= p
->addrlen
;
441 memcpy(&repinfo
.addr
, &p
->addr
, p
->addrlen
);
443 pending_list_delete(runtime
, p
);
444 if((*cb
)(&c
, cb_arg
, error
, &repinfo
)) {
445 fatal_exit("unexpected: pending callback returned 1");
447 /* delete the pending item. */
448 sldns_buffer_free(c
.buffer
);
453 moment_assign(struct replay_runtime
* runtime
, struct replay_moment
* mom
)
455 char* value
= macro_process(runtime
->vars
, runtime
, mom
->string
);
457 fatal_exit("could not process macro step %d", mom
->time_step
);
458 log_info("assign %s = %s", mom
->variable
, value
);
459 if(!macro_assign(runtime
->vars
, mom
->variable
, value
))
460 fatal_exit("out of memory storing macro");
462 if(verbosity
>= VERB_ALGO
)
463 macro_print_debug(runtime
->vars
);
468 time_passes(struct replay_runtime
* runtime
, struct replay_moment
* mom
)
470 struct fake_timer
*t
;
471 struct timeval tv
= mom
->elapse
;
473 char* xp
= macro_process(runtime
->vars
, runtime
, mom
->string
);
475 if(!xp
) fatal_exit("could not macro expand %s", mom
->string
);
476 verbose(VERB_ALGO
, "EVAL %s", mom
->string
);
481 tv
.tv_usec
= (int)((sec
- (double)tv
.tv_sec
) *1000000. + 0.5);
484 timeval_add(&runtime
->now_tv
, &tv
);
485 runtime
->now_secs
= (time_t)runtime
->now_tv
.tv_sec
;
487 log_info("elapsed %d.%6.6d now %d.%6.6d",
488 (int)tv
.tv_sec
, (int)tv
.tv_usec
,
489 (int)runtime
->now_tv
.tv_sec
, (int)runtime
->now_tv
.tv_usec
);
491 /* see if any timers have fired; and run them */
492 while( (t
=replay_get_oldest_timer(runtime
)) ) {
494 log_info("fake_timer callback");
495 fptr_ok(fptr_whitelist_comm_timer(t
->cb
));
500 /** check autotrust file contents */
502 autotrust_check(struct replay_runtime
* runtime
, struct replay_moment
* mom
)
504 char name
[1024], line
[1024];
506 int lineno
= 0, oke
=1;
508 struct config_strlist
* p
;
509 line
[sizeof(line
)-1] = 0;
510 log_assert(mom
->autotrust_id
);
511 fake_temp_file("_auto_", mom
->autotrust_id
, name
, sizeof(name
));
512 in
= fopen(name
, "r");
513 if(!in
) fatal_exit("could not open %s: %s", name
, strerror(errno
));
514 for(p
=mom
->file_content
; p
; p
=p
->next
) {
516 if(!fgets(line
, (int)sizeof(line
)-1, in
)) {
517 log_err("autotrust check failed, could not read line");
518 log_err("file %s, line %d", name
, lineno
);
519 log_err("should be: %s", p
->str
);
520 fatal_exit("autotrust_check failed");
522 if(line
[0]) line
[strlen(line
)-1] = 0; /* remove newline */
523 expanded
= macro_process(runtime
->vars
, runtime
, p
->str
);
525 fatal_exit("could not expand macro line %d", lineno
);
526 if(verbosity
>= 7 && strcmp(p
->str
, expanded
) != 0)
527 log_info("expanded '%s' to '%s'", p
->str
, expanded
);
528 if(strcmp(expanded
, line
) != 0) {
529 log_err("mismatch in file %s, line %d", name
, lineno
);
530 log_err("file has : %s", line
);
531 log_err("should be: %s", expanded
);
537 fprintf(stderr
, "%s:%2d ok : %s\n", name
, lineno
, line
);
539 if(fgets(line
, (int)sizeof(line
)-1, in
)) {
540 log_err("autotrust check failed, extra lines in %s after %d",
543 fprintf(stderr
, "file has: %s", line
);
544 } while(fgets(line
, (int)sizeof(line
)-1, in
));
549 fatal_exit("autotrust_check STEP %d failed", mom
->time_step
);
550 log_info("autotrust %s is OK", mom
->autotrust_id
);
553 /** Store RTT in infra cache */
555 do_infra_rtt(struct replay_runtime
* runtime
)
557 struct replay_moment
* now
= runtime
->now
;
560 uint8_t* dp
= sldns_str2wire_dname(now
->variable
, &dplen
);
561 if(!dp
) fatal_exit("cannot parse %s", now
->variable
);
562 rto
= infra_rtt_update(runtime
->infra
, &now
->addr
, now
->addrlen
,
563 dp
, dplen
, LDNS_RR_TYPE_A
, atoi(now
->string
),
564 -1, runtime
->now_secs
);
565 log_addr(0, "INFRA_RTT for", &now
->addr
, now
->addrlen
);
566 log_info("INFRA_RTT(%s roundtrip %d): rto of %d", now
->variable
,
567 atoi(now
->string
), rto
);
568 if(rto
== 0) fatal_exit("infra_rtt_update failed");
572 /** perform exponential backoff on the timout */
574 expon_timeout_backoff(struct replay_runtime
* runtime
)
576 struct fake_pending
* p
= runtime
->pending_list
;
578 uint8_t edns_lame_known
;
580 if(!p
) return; /* no pending packet to backoff */
581 if(!infra_host(runtime
->infra
, &p
->addr
, p
->addrlen
, p
->zone
,
582 p
->zonelen
, runtime
->now_secs
, &vs
, &edns_lame_known
, &rtt
))
585 rto
= infra_rtt_update(runtime
->infra
, &p
->addr
, p
->addrlen
, p
->zone
,
586 p
->zonelen
, p
->qtype
, -1, last_rtt
, runtime
->now_secs
);
587 log_info("infra_rtt_update returned rto %d", rto
);
591 * Advance to the next moment.
594 advance_moment(struct replay_runtime
* runtime
)
597 runtime
->now
= runtime
->scenario
->mom_first
;
598 else runtime
->now
= runtime
->now
->mom_next
;
602 * Perform actions or checks determined by the moment.
603 * Also advances the time by one step.
604 * @param runtime: scenario runtime information.
607 do_moment_and_advance(struct replay_runtime
* runtime
)
609 struct replay_moment
* mom
;
611 advance_moment(runtime
);
614 log_info("testbound: do STEP %d %s", runtime
->now
->time_step
,
615 repevt_string(runtime
->now
->evt_type
));
616 switch(runtime
->now
->evt_type
) {
618 advance_moment(runtime
);
620 case repevt_front_query
:
621 /* advance moment before doing the step, so that the next
622 moment which may check some result of the mom step
623 can catch those results. */
625 advance_moment(runtime
);
626 fake_front_query(runtime
, mom
);
628 case repevt_front_reply
:
629 if(runtime
->answer_list
)
630 log_err("testbound: There are unmatched answers.");
631 fatal_exit("testbound: query answer not matched");
635 advance_moment(runtime
);
636 expon_timeout_backoff(runtime
);
637 fake_pending_callback(runtime
, mom
, NETEVENT_TIMEOUT
);
639 case repevt_back_reply
:
641 advance_moment(runtime
);
642 fake_pending_callback(runtime
, mom
, NETEVENT_NOERROR
);
644 case repevt_back_query
:
645 /* Back queries are matched when they are sent out. */
646 log_err("No query matching the current moment was sent.");
647 fatal_exit("testbound: back query not matched");
651 advance_moment(runtime
);
652 fake_pending_callback(runtime
, mom
, NETEVENT_CLOSED
);
654 case repevt_time_passes
:
655 time_passes(runtime
, runtime
->now
);
656 advance_moment(runtime
);
658 case repevt_autotrust_check
:
659 autotrust_check(runtime
, runtime
->now
);
660 advance_moment(runtime
);
663 moment_assign(runtime
, runtime
->now
);
664 advance_moment(runtime
);
667 advance_moment(runtime
);
669 case repevt_infra_rtt
:
670 do_infra_rtt(runtime
);
671 advance_moment(runtime
);
674 fatal_exit("testbound: unknown event type %d",
675 runtime
->now
->evt_type
);
679 /** run the scenario in event callbacks */
681 run_scenario(struct replay_runtime
* runtime
)
683 struct entry
* entry
= NULL
;
684 struct fake_pending
* pending
= NULL
;
685 int max_rounds
= 5000;
687 runtime
->now
= runtime
->scenario
->mom_first
;
688 log_info("testbound: entering fake runloop");
690 /* if moment matches pending query do it. */
691 /* else if moment matches given answer, do it */
692 /* else if precoded_range matches pending, do it */
693 /* else do the current moment */
694 if(pending_matches_current(runtime
, &entry
, &pending
)) {
695 log_info("testbound: do STEP %d CHECK_OUT_QUERY",
696 runtime
->now
->time_step
);
697 advance_moment(runtime
);
699 answer_callback_from_entry(runtime
, entry
,
701 } else if(runtime
->answer_list
&& runtime
->now
&&
702 runtime
->now
->evt_type
== repevt_front_reply
) {
703 answer_check_it(runtime
);
704 advance_moment(runtime
);
705 } else if(pending_matches_range(runtime
, &entry
, &pending
)) {
706 answer_callback_from_entry(runtime
, entry
, pending
);
708 do_moment_and_advance(runtime
);
710 log_info("testbound: end of event stage");
712 if(rounds
> max_rounds
)
713 fatal_exit("testbound: too many rounds, it loops.");
714 } while(runtime
->now
);
716 if(runtime
->pending_list
) {
717 struct fake_pending
* p
;
718 log_err("testbound: there are still messages pending.");
719 for(p
= runtime
->pending_list
; p
; p
=p
->next
) {
720 log_pkt("pending msg", p
->pkt
, p
->pkt_len
);
721 log_addr(0, "pending to", &p
->addr
, p
->addrlen
);
723 fatal_exit("testbound: there are still messages pending.");
725 if(runtime
->answer_list
) {
726 fatal_exit("testbound: there are unmatched answers.");
728 log_info("testbound: exiting fake runloop.");
729 runtime
->exit_cleanly
= 1;
732 /*********** Dummy routines ***********/
734 struct listen_dnsport
*
735 listen_create(struct comm_base
* base
, struct listen_port
* ATTR_UNUSED(ports
),
736 size_t bufsize
, int ATTR_UNUSED(tcp_accept_count
),
737 void* ATTR_UNUSED(sslctx
), struct dt_env
* ATTR_UNUSED(dtenv
),
738 comm_point_callback_t
* cb
, void* cb_arg
)
740 struct replay_runtime
* runtime
= (struct replay_runtime
*)base
;
741 struct listen_dnsport
* l
= calloc(1, sizeof(struct listen_dnsport
));
745 l
->udp_buff
= sldns_buffer_new(bufsize
);
750 runtime
->callback_query
= cb
;
751 runtime
->cb_arg
= cb_arg
;
752 runtime
->bufsize
= bufsize
;
757 listen_delete(struct listen_dnsport
* listen
)
761 sldns_buffer_free(listen
->udp_buff
);
766 comm_base_create(int ATTR_UNUSED(sigs
))
768 /* we return the runtime structure instead. */
769 struct replay_runtime
* runtime
= (struct replay_runtime
*)
770 calloc(1, sizeof(struct replay_runtime
));
771 runtime
->scenario
= saved_scenario
;
772 runtime
->vars
= macro_store_create();
773 if(!runtime
->vars
) fatal_exit("out of memory");
774 return (struct comm_base
*)runtime
;
778 comm_base_delete(struct comm_base
* b
)
780 struct replay_runtime
* runtime
= (struct replay_runtime
*)b
;
781 struct fake_pending
* p
, *np
;
782 struct replay_answer
* a
, *na
;
783 struct fake_timer
* t
, *nt
;
786 runtime
->scenario
= NULL
;
787 p
= runtime
->pending_list
;
790 delete_fake_pending(p
);
793 a
= runtime
->answer_list
;
796 delete_replay_answer(a
);
799 t
= runtime
->timer_list
;
805 macro_store_delete(runtime
->vars
);
810 comm_base_timept(struct comm_base
* b
, time_t** tt
, struct timeval
** tv
)
812 struct replay_runtime
* runtime
= (struct replay_runtime
*)b
;
813 *tt
= &runtime
->now_secs
;
814 *tv
= &runtime
->now_tv
;
818 comm_base_dispatch(struct comm_base
* b
)
820 struct replay_runtime
* runtime
= (struct replay_runtime
*)b
;
821 run_scenario(runtime
);
823 (*runtime
->sig_cb
)(SIGTERM
, runtime
->sig_cb_arg
);
824 else exit(0); /* OK exit when LIBEVENT_SIGNAL_PROBLEM exists */
828 comm_base_exit(struct comm_base
* b
)
830 struct replay_runtime
* runtime
= (struct replay_runtime
*)b
;
831 if(!runtime
->exit_cleanly
) {
832 /* some sort of failure */
833 fatal_exit("testbound: comm_base_exit was called.");
838 comm_signal_create(struct comm_base
* base
,
839 void (*callback
)(int, void*), void* cb_arg
)
841 struct replay_runtime
* runtime
= (struct replay_runtime
*)base
;
842 runtime
->sig_cb
= callback
;
843 runtime
->sig_cb_arg
= cb_arg
;
844 return calloc(1, sizeof(struct comm_signal
));
848 comm_signal_bind(struct comm_signal
* ATTR_UNUSED(comsig
), int
855 comm_signal_delete(struct comm_signal
* comsig
)
861 comm_point_send_reply(struct comm_reply
* repinfo
)
863 struct replay_answer
* ans
= (struct replay_answer
*)calloc(1,
864 sizeof(struct replay_answer
));
865 struct replay_runtime
* runtime
= (struct replay_runtime
*)repinfo
->c
->ev
;
866 log_info("testbound: comm_point_send_reply fake");
867 /* dump it into the todo list */
869 memcpy(&ans
->repinfo
, repinfo
, sizeof(struct comm_reply
));
871 if(runtime
->answer_last
)
872 runtime
->answer_last
->next
= ans
;
873 else runtime
->answer_list
= ans
;
874 runtime
->answer_last
= ans
;
876 /* try to parse packet */
877 ans
->pkt
= memdup(sldns_buffer_begin(ans
->repinfo
.c
->buffer
),
878 sldns_buffer_limit(ans
->repinfo
.c
->buffer
));
879 ans
->pkt_len
= sldns_buffer_limit(ans
->repinfo
.c
->buffer
);
880 if(!ans
->pkt
) fatal_exit("out of memory");
881 log_pkt("reply pkt: ", ans
->pkt
, ans
->pkt_len
);
885 comm_point_drop_reply(struct comm_reply
* repinfo
)
887 log_info("comm_point_drop_reply fake");
889 sldns_buffer_free(repinfo
->c
->buffer
);
894 struct outside_network
*
895 outside_network_create(struct comm_base
* base
, size_t bufsize
,
896 size_t ATTR_UNUSED(num_ports
), char** ATTR_UNUSED(ifs
),
897 int ATTR_UNUSED(num_ifs
), int ATTR_UNUSED(do_ip4
),
898 int ATTR_UNUSED(do_ip6
), size_t ATTR_UNUSED(num_tcp
),
899 struct infra_cache
* infra
,
900 struct ub_randstate
* ATTR_UNUSED(rnd
),
901 int ATTR_UNUSED(use_caps_for_id
), int* ATTR_UNUSED(availports
),
902 int ATTR_UNUSED(numavailports
), size_t ATTR_UNUSED(unwanted_threshold
),
903 void (*unwanted_action
)(void*), void* ATTR_UNUSED(unwanted_param
),
904 int ATTR_UNUSED(do_udp
), void* ATTR_UNUSED(sslctx
),
905 int ATTR_UNUSED(delayclose
), struct dt_env
* ATTR_UNUSED(dtenv
))
907 struct replay_runtime
* runtime
= (struct replay_runtime
*)base
;
908 struct outside_network
* outnet
= calloc(1,
909 sizeof(struct outside_network
));
910 (void)unwanted_action
;
913 runtime
->infra
= infra
;
915 outnet
->udp_buff
= sldns_buffer_new(bufsize
);
916 if(!outnet
->udp_buff
) {
924 outside_network_delete(struct outside_network
* outnet
)
928 sldns_buffer_free(outnet
->udp_buff
);
933 outside_network_quit_prepare(struct outside_network
* ATTR_UNUSED(outnet
))
938 pending_udp_query(struct serviced_query
* sq
, sldns_buffer
* packet
,
939 int timeout
, comm_point_callback_t
* callback
, void* callback_arg
)
941 struct replay_runtime
* runtime
= (struct replay_runtime
*)
943 struct fake_pending
* pend
= (struct fake_pending
*)calloc(1,
944 sizeof(struct fake_pending
));
946 pend
->buffer
= sldns_buffer_new(sldns_buffer_capacity(packet
));
947 log_assert(pend
->buffer
);
948 sldns_buffer_write(pend
->buffer
, sldns_buffer_begin(packet
),
949 sldns_buffer_limit(packet
));
950 sldns_buffer_flip(pend
->buffer
);
951 memcpy(&pend
->addr
, &sq
->addr
, sq
->addrlen
);
952 pend
->addrlen
= sq
->addrlen
;
953 pend
->callback
= callback
;
954 pend
->cb_arg
= callback_arg
;
955 pend
->timeout
= timeout
/1000;
956 pend
->transport
= transport_udp
;
960 pend
->runtime
= runtime
;
961 pend
->pkt_len
= sldns_buffer_limit(packet
);
962 pend
->pkt
= memdup(sldns_buffer_begin(packet
), pend
->pkt_len
);
963 if(!pend
->pkt
) fatal_exit("out of memory");
964 log_pkt("pending udp pkt: ", pend
->pkt
, pend
->pkt_len
);
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
->pkt_len
,
973 log_info("testbound: matched pending to event. "
974 "advance time between events.");
975 log_info("testbound: do STEP %d %s", runtime
->now
->time_step
,
976 repevt_string(runtime
->now
->evt_type
));
977 advance_moment(runtime
);
978 /* still create the pending, because we need it to callback */
980 log_info("testbound: created fake pending");
982 pend
->next
= runtime
->pending_list
;
983 runtime
->pending_list
= pend
;
984 return (struct pending
*)pend
;
988 pending_tcp_query(struct serviced_query
* sq
, sldns_buffer
* packet
,
989 int timeout
, comm_point_callback_t
* callback
, void* callback_arg
)
991 struct replay_runtime
* runtime
= (struct replay_runtime
*)
993 struct fake_pending
* pend
= (struct fake_pending
*)calloc(1,
994 sizeof(struct fake_pending
));
996 pend
->buffer
= sldns_buffer_new(sldns_buffer_capacity(packet
));
997 log_assert(pend
->buffer
);
998 sldns_buffer_write(pend
->buffer
, sldns_buffer_begin(packet
),
999 sldns_buffer_limit(packet
));
1000 sldns_buffer_flip(pend
->buffer
);
1001 memcpy(&pend
->addr
, &sq
->addr
, sq
->addrlen
);
1002 pend
->addrlen
= sq
->addrlen
;
1003 pend
->callback
= callback
;
1004 pend
->cb_arg
= callback_arg
;
1005 pend
->timeout
= timeout
;
1006 pend
->transport
= transport_tcp
;
1009 pend
->runtime
= runtime
;
1011 pend
->pkt_len
= sldns_buffer_limit(packet
);
1012 pend
->pkt
= memdup(sldns_buffer_begin(packet
), pend
->pkt_len
);
1013 if(!pend
->pkt
) fatal_exit("out of memory");
1014 log_pkt("pending tcp pkt: ", pend
->pkt
, pend
->pkt_len
);
1016 /* see if it matches the current moment */
1017 if(runtime
->now
&& runtime
->now
->evt_type
== repevt_back_query
&&
1018 (runtime
->now
->addrlen
== 0 || sockaddr_cmp(
1019 &runtime
->now
->addr
, runtime
->now
->addrlen
,
1020 &pend
->addr
, pend
->addrlen
) == 0) &&
1021 find_match(runtime
->now
->match
, pend
->pkt
, pend
->pkt_len
,
1023 log_info("testbound: matched pending to event. "
1024 "advance time between events.");
1025 log_info("testbound: do STEP %d %s", runtime
->now
->time_step
,
1026 repevt_string(runtime
->now
->evt_type
));
1027 advance_moment(runtime
);
1028 /* still create the pending, because we need it to callback */
1030 log_info("testbound: created fake pending");
1032 pend
->next
= runtime
->pending_list
;
1033 runtime
->pending_list
= pend
;
1034 return (struct waiting_tcp
*)pend
;
1037 struct serviced_query
* outnet_serviced_query(struct outside_network
* outnet
,
1038 uint8_t* qname
, size_t qnamelen
, uint16_t qtype
, uint16_t qclass
,
1039 uint16_t flags
, int dnssec
, int ATTR_UNUSED(want_dnssec
),
1040 int ATTR_UNUSED(nocaps
), int ATTR_UNUSED(tcp_upstream
),
1041 int ATTR_UNUSED(ssl_upstream
), struct sockaddr_storage
* addr
,
1042 socklen_t addrlen
, uint8_t* zone
, size_t zonelen
,
1043 comm_point_callback_t
* callback
, void* callback_arg
,
1044 sldns_buffer
* ATTR_UNUSED(buff
))
1046 struct replay_runtime
* runtime
= (struct replay_runtime
*)outnet
->base
;
1047 struct fake_pending
* pend
= (struct fake_pending
*)calloc(1,
1048 sizeof(struct fake_pending
));
1051 log_nametypeclass(VERB_OPS
, "pending serviced query",
1052 qname
, qtype
, qclass
);
1054 verbose(VERB_OPS
, "pending serviced query zone %s flags%s%s%s%s",
1055 z
, (flags
&BIT_RD
)?" RD":"", (flags
&BIT_CD
)?" CD":"",
1056 (flags
&~(BIT_RD
|BIT_CD
))?" MORE":"", (dnssec
)?" DO":"");
1058 /* create packet with EDNS */
1059 pend
->buffer
= sldns_buffer_new(512);
1060 log_assert(pend
->buffer
);
1061 sldns_buffer_write_u16(pend
->buffer
, 0); /* id */
1062 sldns_buffer_write_u16(pend
->buffer
, flags
);
1063 sldns_buffer_write_u16(pend
->buffer
, 1); /* qdcount */
1064 sldns_buffer_write_u16(pend
->buffer
, 0); /* ancount */
1065 sldns_buffer_write_u16(pend
->buffer
, 0); /* nscount */
1066 sldns_buffer_write_u16(pend
->buffer
, 0); /* arcount */
1067 sldns_buffer_write(pend
->buffer
, qname
, qnamelen
);
1068 sldns_buffer_write_u16(pend
->buffer
, qtype
);
1069 sldns_buffer_write_u16(pend
->buffer
, qclass
);
1070 sldns_buffer_flip(pend
->buffer
);
1073 struct edns_data edns
;
1074 edns
.edns_present
= 1;
1076 edns
.edns_version
= EDNS_ADVERTISED_VERSION
;
1077 edns
.udp_size
= EDNS_ADVERTISED_SIZE
;
1080 edns
.bits
= EDNS_DO
;
1081 attach_edns_record(pend
->buffer
, &edns
);
1083 memcpy(&pend
->addr
, addr
, addrlen
);
1084 pend
->addrlen
= addrlen
;
1085 pend
->zone
= memdup(zone
, zonelen
);
1086 pend
->zonelen
= zonelen
;
1087 pend
->qtype
= (int)qtype
;
1088 log_assert(pend
->zone
);
1089 pend
->callback
= callback
;
1090 pend
->cb_arg
= callback_arg
;
1091 pend
->timeout
= UDP_AUTH_QUERY_TIMEOUT
;
1092 pend
->transport
= transport_udp
; /* pretend UDP */
1094 pend
->runtime
= runtime
;
1096 pend
->pkt_len
= sldns_buffer_limit(pend
->buffer
);
1097 pend
->pkt
= memdup(sldns_buffer_begin(pend
->buffer
), pend
->pkt_len
);
1098 if(!pend
->pkt
) fatal_exit("out of memory");
1099 /*log_pkt("pending serviced query: ", pend->pkt, pend->pkt_len);*/
1101 /* see if it matches the current moment */
1102 if(runtime
->now
&& runtime
->now
->evt_type
== repevt_back_query
&&
1103 (runtime
->now
->addrlen
== 0 || sockaddr_cmp(
1104 &runtime
->now
->addr
, runtime
->now
->addrlen
,
1105 &pend
->addr
, pend
->addrlen
) == 0) &&
1106 find_match(runtime
->now
->match
, pend
->pkt
, pend
->pkt_len
,
1108 log_info("testbound: matched pending to event. "
1109 "advance time between events.");
1110 log_info("testbound: do STEP %d %s", runtime
->now
->time_step
,
1111 repevt_string(runtime
->now
->evt_type
));
1112 advance_moment(runtime
);
1113 /* still create the pending, because we need it to callback */
1115 log_info("testbound: created fake pending");
1117 pend
->next
= runtime
->pending_list
;
1118 runtime
->pending_list
= pend
;
1119 return (struct serviced_query
*)pend
;
1122 void outnet_serviced_query_stop(struct serviced_query
* sq
, void* cb_arg
)
1124 struct fake_pending
* pend
= (struct fake_pending
*)sq
;
1125 struct replay_runtime
* runtime
= pend
->runtime
;
1126 /* delete from the list */
1127 struct fake_pending
* p
= runtime
->pending_list
, *prev
=NULL
;
1130 log_assert(p
->cb_arg
== cb_arg
);
1131 log_info("serviced pending delete");
1133 prev
->next
= p
->next
;
1134 else runtime
->pending_list
= p
->next
;
1135 sldns_buffer_free(p
->buffer
);
1144 log_info("double delete of pending serviced query");
1147 struct listen_port
* listening_ports_open(struct config_file
* ATTR_UNUSED(cfg
),
1148 int* ATTR_UNUSED(reuseport
))
1150 return calloc(1, 1);
1153 void listening_ports_free(struct listen_port
* list
)
1158 struct comm_point
* comm_point_create_local(struct comm_base
* ATTR_UNUSED(base
),
1159 int ATTR_UNUSED(fd
), size_t ATTR_UNUSED(bufsize
),
1160 comm_point_callback_t
* ATTR_UNUSED(callback
),
1161 void* ATTR_UNUSED(callback_arg
))
1163 return calloc(1, 1);
1166 struct comm_point
* comm_point_create_raw(struct comm_base
* ATTR_UNUSED(base
),
1167 int ATTR_UNUSED(fd
), int ATTR_UNUSED(writing
),
1168 comm_point_callback_t
* ATTR_UNUSED(callback
),
1169 void* ATTR_UNUSED(callback_arg
))
1171 /* no pipe comm possible */
1172 return calloc(1, 1);
1175 void comm_point_start_listening(struct comm_point
* ATTR_UNUSED(c
),
1176 int ATTR_UNUSED(newfd
), int ATTR_UNUSED(sec
))
1178 /* no bg write pipe comm possible */
1181 void comm_point_stop_listening(struct comm_point
* ATTR_UNUSED(c
))
1183 /* no bg write pipe comm possible */
1186 /* only cmd com _local gets deleted */
1187 void comm_point_delete(struct comm_point
* c
)
1192 size_t listen_get_mem(struct listen_dnsport
* ATTR_UNUSED(listen
))
1197 size_t outnet_get_mem(struct outside_network
* ATTR_UNUSED(outnet
))
1202 size_t comm_point_get_mem(struct comm_point
* ATTR_UNUSED(c
))
1207 size_t serviced_get_mem(struct serviced_query
* ATTR_UNUSED(c
))
1212 /* fake for fptr wlist */
1213 int outnet_udp_cb(struct comm_point
* ATTR_UNUSED(c
),
1214 void* ATTR_UNUSED(arg
), int ATTR_UNUSED(error
),
1215 struct comm_reply
*ATTR_UNUSED(reply_info
))
1221 int outnet_tcp_cb(struct comm_point
* ATTR_UNUSED(c
),
1222 void* ATTR_UNUSED(arg
), int ATTR_UNUSED(error
),
1223 struct comm_reply
*ATTR_UNUSED(reply_info
))
1229 void pending_udp_timer_cb(void *ATTR_UNUSED(arg
))
1234 void pending_udp_timer_delay_cb(void *ATTR_UNUSED(arg
))
1239 void outnet_tcptimer(void* ATTR_UNUSED(arg
))
1244 void comm_point_udp_callback(int ATTR_UNUSED(fd
), short ATTR_UNUSED(event
),
1245 void* ATTR_UNUSED(arg
))
1250 void comm_point_udp_ancil_callback(int ATTR_UNUSED(fd
),
1251 short ATTR_UNUSED(event
), void* ATTR_UNUSED(arg
))
1256 void comm_point_tcp_accept_callback(int ATTR_UNUSED(fd
),
1257 short ATTR_UNUSED(event
), void* ATTR_UNUSED(arg
))
1262 void comm_point_tcp_handle_callback(int ATTR_UNUSED(fd
),
1263 short ATTR_UNUSED(event
), void* ATTR_UNUSED(arg
))
1268 void comm_timer_callback(int ATTR_UNUSED(fd
),
1269 short ATTR_UNUSED(event
), void* ATTR_UNUSED(arg
))
1274 void comm_signal_callback(int ATTR_UNUSED(fd
),
1275 short ATTR_UNUSED(event
), void* ATTR_UNUSED(arg
))
1280 void comm_point_local_handle_callback(int ATTR_UNUSED(fd
),
1281 short ATTR_UNUSED(event
), void* ATTR_UNUSED(arg
))
1286 void comm_point_raw_handle_callback(int ATTR_UNUSED(fd
),
1287 short ATTR_UNUSED(event
), void* ATTR_UNUSED(arg
))
1292 void comm_base_handle_slow_accept(int ATTR_UNUSED(fd
),
1293 short ATTR_UNUSED(event
), void* ATTR_UNUSED(arg
))
1298 int serviced_udp_callback(struct comm_point
* ATTR_UNUSED(c
),
1299 void* ATTR_UNUSED(arg
), int ATTR_UNUSED(error
),
1300 struct comm_reply
* ATTR_UNUSED(reply_info
))
1306 int serviced_tcp_callback(struct comm_point
* ATTR_UNUSED(c
),
1307 void* ATTR_UNUSED(arg
), int ATTR_UNUSED(error
),
1308 struct comm_reply
* ATTR_UNUSED(reply_info
))
1314 int pending_cmp(const void* ATTR_UNUSED(a
), const void* ATTR_UNUSED(b
))
1320 int serviced_cmp(const void* ATTR_UNUSED(a
), const void* ATTR_UNUSED(b
))
1326 /* timers in testbound for autotrust. statistics tested in tpkg. */
1327 struct comm_timer
* comm_timer_create(struct comm_base
* base
,
1328 void (*cb
)(void*), void* cb_arg
)
1330 struct replay_runtime
* runtime
= (struct replay_runtime
*)base
;
1331 struct fake_timer
* t
= (struct fake_timer
*)calloc(1, sizeof(*t
));
1334 fptr_ok(fptr_whitelist_comm_timer(t
->cb
)); /* check in advance */
1335 t
->runtime
= runtime
;
1336 t
->next
= runtime
->timer_list
;
1337 runtime
->timer_list
= t
;
1338 return (struct comm_timer
*)t
;
1341 void comm_timer_disable(struct comm_timer
* timer
)
1343 struct fake_timer
* t
= (struct fake_timer
*)timer
;
1344 log_info("fake timer disabled");
1348 void comm_timer_set(struct comm_timer
* timer
, struct timeval
* tv
)
1350 struct fake_timer
* t
= (struct fake_timer
*)timer
;
1353 log_info("fake timer set %d.%6.6d",
1354 (int)t
->tv
.tv_sec
, (int)t
->tv
.tv_usec
);
1355 timeval_add(&t
->tv
, &t
->runtime
->now_tv
);
1358 void comm_timer_delete(struct comm_timer
* timer
)
1360 struct fake_timer
* t
= (struct fake_timer
*)timer
;
1361 struct fake_timer
** pp
, *p
;
1364 /* remove from linked list */
1365 pp
= &t
->runtime
->timer_list
;
1366 p
= t
->runtime
->timer_list
;
1369 /* snip from list */
1380 void comm_base_set_slow_accept_handlers(struct comm_base
* ATTR_UNUSED(b
),
1381 void (*stop_acc
)(void*), void (*start_acc
)(void*),
1382 void* ATTR_UNUSED(arg
))
1389 struct event_base
* comm_base_internal(struct comm_base
* ATTR_UNUSED(b
))
1391 /* no pipe comm possible in testbound */
1395 void daemon_remote_exec(struct worker
* ATTR_UNUSED(worker
))
1399 void listen_start_accept(struct listen_dnsport
* ATTR_UNUSED(listen
))
1403 void listen_stop_accept(struct listen_dnsport
* ATTR_UNUSED(listen
))
1407 void daemon_remote_start_accept(struct daemon_remote
* ATTR_UNUSED(rc
))
1411 void daemon_remote_stop_accept(struct daemon_remote
* ATTR_UNUSED(rc
))
1415 /*********** End of Dummy routines ***********/