diff --git a/Makefile.in b/Makefile.in index 22fb75c12..d1da0f375 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1355,7 +1355,7 @@ testbound.lo testbound.o: $(srcdir)/testcode/testbound.c config.h $(srcdir)/test $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h \ $(srcdir)/services/mesh.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h $(srcdir)/services/view.h \ $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h \ - $(srcdir)/respip/respip.h $(srcdir)/util/net_help.h $(srcdir)/util/ub_event.h + $(srcdir)/respip/respip.h $(srcdir)/util/net_help.h $(srcdir)/util/ub_event.h $(srcdir)/daemon/worker.h testpkts.lo testpkts.o: $(srcdir)/testcode/testpkts.c config.h $(srcdir)/testcode/testpkts.h \ $(srcdir)/util/net_help.h $(srcdir)/util/log.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/pkthdr.h \ $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/wire2str.h @@ -1428,7 +1428,7 @@ fake_event.lo fake_event.o: $(srcdir)/testcode/fake_event.c config.h $(srcdir)/t $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h \ $(srcdir)/services/localzone.h $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h $(srcdir)/services/authzone.h \ $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h \ - $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h $(srcdir)/daemon/remote.h + $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h $(srcdir)/daemon/remote.h $(srcdir)/storage/slabhash.h $(srcdir)/daemon/daemon.h lock_verify.lo lock_verify.o: $(srcdir)/testcode/lock_verify.c config.h $(srcdir)/util/log.h $(srcdir)/util/rbtree.h \ $(srcdir)/util/locks.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \ $(srcdir)/util/storage/lruhash.h $(srcdir)/util/module.h \ diff --git a/doc/Changelog b/doc/Changelog index 421505d96..c28d2517c 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -3,6 +3,7 @@ is enabled. When serve expired is enabled with cachedb, it first checks cachedb before serving the expired response. - Fixup compile without cachedb. + - Add test for cachedb serve expired. 9 April 2024: Yorgos - Merge #1043 from xiaoxiaoafeifei: Add loongarch support; updates diff --git a/testcode/fake_event.c b/testcode/fake_event.c index 13970c377..053f88569 100644 --- a/testcode/fake_event.c +++ b/testcode/fake_event.c @@ -52,6 +52,7 @@ #include "util/data/msgreply.h" #include "util/data/msgencode.h" #include "util/data/dname.h" +#include "util/storage/slabhash.h" #include "util/edns.h" #include "util/config_file.h" #include "services/listen_dnsport.h" @@ -65,6 +66,7 @@ #include "sldns/wire2str.h" #include "sldns/str2wire.h" #include "daemon/remote.h" +#include "daemon/daemon.h" #include "util/timeval_func.h" #include struct worker; @@ -154,6 +156,7 @@ repevt_string(enum replay_event_type t) case repevt_assign: return "ASSIGN"; case repevt_traffic: return "TRAFFIC"; case repevt_infra_rtt: return "INFRA_RTT"; + case repevt_flush_message: return "FLUSH_MESSAGE"; default: return "UNKNOWN"; } } @@ -691,6 +694,30 @@ do_infra_rtt(struct replay_runtime* runtime) free(dp); } +/** Flush message from message cache. */ +static void +do_flush_message(struct replay_runtime* runtime) +{ + struct replay_moment* now = runtime->now; + uint8_t rr[1024]; + size_t rr_len = sizeof(rr), dname_len = 0; + hashvalue_type h; + struct query_info k; + + if(sldns_str2wire_rr_question_buf(now->string, rr, &rr_len, + &dname_len, NULL, 0, NULL, 0) != 0) + fatal_exit("could not parse '%s'", now->string); + + log_info("remove message %s", now->string); + k.qname = rr; + k.qname_len = dname_len; + k.qtype = sldns_wirerr_get_type(rr, rr_len, dname_len); + k.qclass = sldns_wirerr_get_class(rr, rr_len, dname_len); + k.local_alias = NULL; + h = query_info_hash(&k, 0); + slabhash_remove(runtime->daemon->env->msg_cache, h, &k); +} + /** perform exponential backoff on the timeout */ static void expon_timeout_backoff(struct replay_runtime* runtime) @@ -796,6 +823,10 @@ do_moment_and_advance(struct replay_runtime* runtime) do_infra_rtt(runtime); advance_moment(runtime); break; + case repevt_flush_message: + do_flush_message(runtime); + advance_moment(runtime); + break; default: fatal_exit("testbound: unknown event type %d", runtime->now->evt_type); diff --git a/testcode/replay.c b/testcode/replay.c index f896a5512..813e74ca4 100644 --- a/testcode/replay.c +++ b/testcode/replay.c @@ -348,6 +348,13 @@ replay_moment_read(char* remain, FILE* in, const char* name, mom->string = strdup(m); if(!mom->string) fatal_exit("out of memory"); if(!mom->variable) fatal_exit("out of memory"); + } else if(parse_keyword(&remain, "FLUSH_MESSAGE")) { + mom->evt_type = repevt_flush_message; + while(isspace((unsigned char)*remain)) + remain++; + strip_end_white(remain); + mom->string = strdup(remain); + if(!mom->string) fatal_exit("out of memory"); } else { log_err("%d: unknown event type %s", pstate->lineno, remain); free(mom); diff --git a/testcode/replay.h b/testcode/replay.h index 0271dff03..5f5d410b8 100644 --- a/testcode/replay.h +++ b/testcode/replay.h @@ -85,6 +85,7 @@ * The file contents is macro expanded before match. * o CHECK_TEMPFILE [fname] - followed by FILE_BEGIN [to match] FILE_END * o INFRA_RTT [ip] [dp] [rtt] - update infra cache entry with rtt. + * o FLUSH_MESSAGE name type class - flushes entry in message cache. * o ERROR * ; following entry starts on the next line, ENTRY_BEGIN. * ; more STEP items @@ -148,6 +149,7 @@ struct fake_timer; struct replay_var; struct infra_cache; struct sldns_buffer; +struct daemon; /** * A replay scenario. @@ -212,6 +214,8 @@ struct replay_moment { repevt_assign, /** store infra rtt cache entry: addr and string (int) */ repevt_infra_rtt, + /** flush message cache entry */ + repevt_flush_message, /** cause traffic to flow */ repevt_traffic } @@ -297,6 +301,8 @@ struct replay_runtime { /** ref the infra cache (was passed to outside_network_create) */ struct infra_cache* infra; + /** the daemon structure passed in worker call to remote accept open */ + struct daemon* daemon; /** the current time in seconds */ time_t now_secs; diff --git a/testcode/testbound.c b/testcode/testbound.c index ec627cc8d..f023860e0 100644 --- a/testcode/testbound.c +++ b/testcode/testbound.c @@ -48,6 +48,7 @@ #include "testcode/fake_event.h" #include "daemon/remote.h" #include "libunbound/worker.h" +#include "daemon/worker.h" #include "util/config_file.h" #include "sldns/keyraw.h" #ifdef UB_ON_WINDOWS @@ -532,9 +533,10 @@ void daemon_remote_clear(struct daemon_remote* ATTR_UNUSED(rc)) } int daemon_remote_open_accept(struct daemon_remote* ATTR_UNUSED(rc), - struct listen_port* ATTR_UNUSED(ports), - struct worker* ATTR_UNUSED(worker)) + struct listen_port* ATTR_UNUSED(ports), struct worker* worker) { + struct replay_runtime* runtime = (struct replay_runtime*)worker->base; + runtime->daemon = worker->daemon; return 1; } diff --git a/testdata/cachedb_expired.crpl b/testdata/cachedb_expired.crpl new file mode 100644 index 000000000..8f9c12694 --- /dev/null +++ b/testdata/cachedb_expired.crpl @@ -0,0 +1,259 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + qname-minimisation: no + minimal-responses: no + serve-expired: yes + module-config: "cachedb iterator" + +cachedb: + backend: "testframe" + secret-seed: "testvalue" + cachedb-check-when-serve-expired: yes + +stub-zone: + name: "." + stub-addr: 193.0.14.129 +CONFIG_END + +SCENARIO_BEGIN Test cachedb and serve expired. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 300 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 300 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns2.example.com. +SECTION ADDITIONAL +ns2.example.com. IN A 1.2.3.5 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +foo.com. IN NS +SECTION AUTHORITY +foo.com. IN NS ns.example.com. +ENTRY_END +RANGE_END + +; ns2.example.com. +RANGE_BEGIN 0 300 + ADDRESS 1.2.3.5 +ENTRY_BEGIN +MATCH opcode qname qtype +REPLY QR AA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 10 IN A 1.2.3.4 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +REPLY QR AA NOERROR +SECTION QUESTION +www2.example.com. IN A +SECTION ANSWER +www2.example.com. 10 IN A 1.2.3.5 +ENTRY_END +RANGE_END + +; Get an entry in cache, to make it expired. +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; get the answer for it +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 10 IN A 1.2.3.4 +ENTRY_END + +; Get another query in cache to make it expired. +STEP 20 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www2.example.com. IN A +ENTRY_END + +; get the answer for it +STEP 30 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www2.example.com. IN A +SECTION ANSWER +www2.example.com. 10 IN A 1.2.3.5 +ENTRY_END + +; it is now expired +STEP 40 TIME_PASSES ELAPSE 20 + +; cache is expired, and cachedb is expired. +STEP 50 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www2.example.com. IN A +ENTRY_END + +STEP 60 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www2.example.com. IN A +SECTION ANSWER +www2.example.com. 0 IN A 1.2.3.5 +ENTRY_END + +; cache is expired, cachedb has no answer +STEP 70 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +STEP 80 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 30 IN A 1.2.3.4 +ENTRY_END + +STEP 90 TRAFFIC +; the entry should be refreshed in cache now. +; cache is valid and cachedb is valid. +STEP 100 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +STEP 110 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 10 IN A 1.2.3.4 +ENTRY_END + +; flush the entry from cache +STEP 120 FLUSH_MESSAGE www.example.com. IN A + +; cache has no answer, cachedb valid +STEP 130 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +STEP 140 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 10 IN A 1.2.3.4 +ENTRY_END + +; it is now expired +STEP 150 TIME_PASSES ELAPSE 20 +; flush the entry from cache +STEP 160 FLUSH_MESSAGE www.example.com. IN A + +; cache has no answer, cachedb is expired +STEP 170 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +STEP 180 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 0 IN A 1.2.3.4 +ENTRY_END + +STEP 190 TRAFFIC +; the expired message is updated. + +; cache is valid, cachedb is valid +STEP 200 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +STEP 210 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 10 IN A 1.2.3.4 +ENTRY_END + +SCENARIO_END