--- iterator/iter_delegpt.h.orig 2018-04-19 12:10:05.000000000 +0000 +++ iterator/iter_delegpt.h 2018-08-02 13:00:37.379081000 +0000 @@ -85,6 +85,8 @@ struct delegpt { uint8_t ssl_upstream; /** delegpt from authoritative zone that is locally hosted */ uint8_t auth_dp; + /*** no cache */ + int no_cache; }; /** --- iterator/iter_fwd.c.orig 2018-04-19 12:10:05.000000000 +0000 +++ iterator/iter_fwd.c 2018-08-02 12:26:05.772596000 +0000 @@ -267,6 +267,8 @@ read_forwards(struct iter_forwards* fwd, struct config * last resort will ask for parent-side NS record and thus * fallback to the internet name servers on a failure */ dp->has_parent_side_NS = (uint8_t)!s->isfirst; + /* Do not cache if set. */ + dp->no_cache = s->no_cache; /* use SSL for queries to this forwarder */ dp->ssl_upstream = (uint8_t)s->ssl_upstream; verbose(VERB_QUERY, "Forward zone server list:"); --- iterator/iter_hints.c.orig 2018-04-19 12:10:05.000000000 +0000 +++ iterator/iter_hints.c 2018-08-02 12:25:47.688275000 +0000 @@ -278,6 +278,8 @@ read_stubs(struct iter_hints* hints, struct config_fil * last resort will ask for parent-side NS record and thus * fallback to the internet name servers on a failure */ dp->has_parent_side_NS = (uint8_t)!s->isfirst; + /* Do not cache if set. */ + dp->no_cache = s->no_cache; /* ssl_upstream */ dp->ssl_upstream = (uint8_t)s->ssl_upstream; delegpt_log(VERB_QUERY, dp); --- iterator/iterator.c.orig 2018-06-12 13:09:14.000000000 +0000 +++ iterator/iterator.c 2018-08-02 21:20:40.705103000 +0000 @@ -1125,6 +1125,36 @@ forward_request(struct module_qstate* qstate, struct i return 1; } +static int +iter_stub_fwd_no_cache(struct module_qstate *qstate, struct iter_qstate *iq) +{ + struct iter_hints_stub *stub; + struct delegpt *dp; + + /* Check for stub. */ + stub = hints_lookup_stub(qstate->env->hints, iq->qchase.qname, + iq->qchase.qclass, iq->dp); + if (stub != NULL && stub->dp != NULL) { + verbose(VERB_ALGO, "%s: stub for '%s'/'%s' no_cache %d", __func__, + iq->qchase.qname, stub->dp->name, stub->dp->no_cache); + return (stub->dp->no_cache); + } + + /* Check for forward. */ + dp = forwards_lookup(qstate->env->fwds, iq->qchase.qname, iq->qchase.qclass); + if (dp) { + verbose(VERB_ALGO, "%s: fwd for '%s'/'%s' no_cache %d", __func__, + iq->qchase.qname, dp->name, dp->no_cache); + return (dp->no_cache); + } + +#if 0 + verbose(VERB_ALGO, "%s: no stub or fwd for '%s' found no_cache 0", + __func__, iq->qchase.qname); +#endif + return (0); +} + /** * Process the initial part of the request handling. This state roughly * corresponds to resolver algorithms steps 1 (find answer in cache) and 2 @@ -1196,7 +1226,13 @@ processInitRequest(struct module_qstate* qstate, struc /* This either results in a query restart (CNAME cache response), a * terminating response (ANSWER), or a cache miss (null). */ - if(qstate->blacklist) { + if (iter_stub_fwd_no_cache(qstate, iq)) { + /* Asked to not query cache. */ + verbose(VERB_ALGO, "no-cache set, going to the network"); + qstate->no_cache_lookup = 1; + qstate->no_cache_store = 1; + msg = NULL; + } else if(qstate->blacklist) { /* if cache, or anything else, was blacklisted then * getting older results from cache is a bad idea, no cache */ verbose(VERB_ALGO, "cache blacklisted, going to the network"); --- util/config_file.h.orig 2018-06-18 09:46:01.000000000 +0000 +++ util/config_file.h 2018-08-02 12:19:08.693167000 +0000 @@ -561,6 +561,8 @@ struct config_stub { int isfirst; /** use SSL for queries to this stub */ int ssl_upstream; + /*** no cache */ + int no_cache; }; /** --- util/configlexer.lex.orig 2018-06-12 08:45:57.000000000 +0000 +++ util/configlexer.lex 2018-08-02 14:03:35.546148000 +0000 @@ -299,12 +299,14 @@ stub-addr{COLON} { YDVAR(1, VAR_STUB_ADDR) } stub-host{COLON} { YDVAR(1, VAR_STUB_HOST) } stub-prime{COLON} { YDVAR(1, VAR_STUB_PRIME) } stub-first{COLON} { YDVAR(1, VAR_STUB_FIRST) } +stub-no-cache{COLON} { YDVAR(1, VAR_STUB_NO_CACHE) } stub-ssl-upstream{COLON} { YDVAR(1, VAR_STUB_SSL_UPSTREAM) } stub-tls-upstream{COLON} { YDVAR(1, VAR_STUB_SSL_UPSTREAM) } forward-zone{COLON} { YDVAR(0, VAR_FORWARD_ZONE) } forward-addr{COLON} { YDVAR(1, VAR_FORWARD_ADDR) } forward-host{COLON} { YDVAR(1, VAR_FORWARD_HOST) } forward-first{COLON} { YDVAR(1, VAR_FORWARD_FIRST) } +forward-no-cache{COLON} { YDVAR(1, VAR_FORWARD_NO_CACHE) } forward-ssl-upstream{COLON} { YDVAR(1, VAR_FORWARD_SSL_UPSTREAM) } forward-tls-upstream{COLON} { YDVAR(1, VAR_FORWARD_SSL_UPSTREAM) } auth-zone{COLON} { YDVAR(0, VAR_AUTH_ZONE) } --- util/configparser.y.orig 2018-06-18 09:46:01.000000000 +0000 +++ util/configparser.y 2018-08-02 14:24:56.550864000 +0000 @@ -158,6 +158,7 @@ extern struct config_parser_state* cfg_parser; %token VAR_AUTH_ZONE VAR_ZONEFILE VAR_MASTER VAR_URL VAR_FOR_DOWNSTREAM %token VAR_FALLBACK_ENABLED VAR_TLS_ADDITIONAL_PORT VAR_LOW_RTT VAR_LOW_RTT_PERMIL %token VAR_ALLOW_NOTIFY VAR_TLS_WIN_CERT +%token VAR_FORWARD_NO_CACHE VAR_STUB_NO_CACHE %% toplevelvars: /* empty */ | toplevelvars toplevelvar ; @@ -266,7 +267,7 @@ stubstart: VAR_STUB_ZONE contents_stub: contents_stub content_stub | ; content_stub: stub_name | stub_host | stub_addr | stub_prime | stub_first | - stub_ssl_upstream + stub_no_cache | stub_ssl_upstream ; forwardstart: VAR_FORWARD_ZONE { @@ -283,7 +284,7 @@ forwardstart: VAR_FORWARD_ZONE contents_forward: contents_forward content_forward | ; content_forward: forward_name | forward_host | forward_addr | forward_first | - forward_ssl_upstream + forward_no_cache | forward_ssl_upstream ; viewstart: VAR_VIEW { @@ -2031,6 +2033,15 @@ stub_first: VAR_STUB_FIRST STRING_ARG free($2); } ; +stub_no_cache: VAR_STUB_NO_CACHE STRING_ARG + { + OUTYY(("P(stub-no-cache:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->stubs->no_cache=(strcmp($2, "yes")==0); + free($2); + } + ; stub_ssl_upstream: VAR_STUB_SSL_UPSTREAM STRING_ARG { OUTYY(("P(stub-ssl-upstream:%s)\n", $2)); @@ -2084,6 +2095,15 @@ forward_first: VAR_FORWARD_FIRST STRING_ARG free($2); } ; +forward_no_cache: VAR_FORWARD_NO_CACHE STRING_ARG + { + OUTYY(("P(forward-no-cache:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->forwards->no_cache=(strcmp($2, "yes")==0); + free($2); + } + ; forward_ssl_upstream: VAR_FORWARD_SSL_UPSTREAM STRING_ARG { OUTYY(("P(forward-ssl-upstream:%s)\n", $2));