]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
improve handling of SERVFAIL from forwarders
authorVladimír Čunát <vladimir.cunat@nic.cz>
Wed, 8 Mar 2023 16:18:16 +0000 (17:18 +0100)
committerVladimír Čunát <vladimir.cunat@nic.cz>
Fri, 10 Mar 2023 13:37:30 +0000 (14:37 +0100)
- selection: utilize address_state::broken also when forwarding
- selection: drop fallbacks that don't make sense when forwarding
- iterate: copy EDE codes on DNSSEC SERVFAILs

lib/layer/iterate.c
lib/selection.c
lib/selection_forward.c

index edc666ebd96aa125e7db33cfc236f9d14cfcb38f..dfb7c8762f4bbdf714d30eb1f356edf66d99de14 100644 (file)
@@ -1026,6 +1026,21 @@ static void bound_ttls(ranked_rr_array_t *array, uint32_t qry_uid,
        }
 }
 
+static void ede_passthru(const knot_pkt_t *pkt, struct kr_request *req)
+{
+       const uint8_t *ede_raw = pkt->edns_opts ?
+                       pkt->edns_opts->ptr[KNOT_EDNS_OPTION_EDE] : NULL;
+       if (!ede_raw) return;
+       kr_require(ede_raw[0] * 256 + ede_raw[1] == KNOT_EDNS_OPTION_EDE);
+       uint16_t ede_len = ede_raw[2] * 256 + ede_raw[3];
+       if (ede_len < 2) return;
+       uint16_t ede_code = ede_raw[4] * 256 + ede_raw[5];
+       if (ede_code >= KNOT_EDNS_EDE_INDETERMINATE // long range of DNSSEC codes
+                       && ede_code <= KNOT_EDNS_EDE_NSEC_MISS) {
+               kr_request_set_extended_error(req, ede_code, "V5T7: forwarded EDE code");
+       }
+}
+
 /** Resolve input query or continue resolution with followups.
  *
  *  This roughly corresponds to RFC1034, 5.3.3 4a-d.
@@ -1129,6 +1144,10 @@ static int resolve(kr_layer_t *ctx, knot_pkt_t *pkt)
                }
                ret = KR_STATE_FAIL;
                selection_error = KR_SELECTION_SERVFAIL;
+               if (query->flags.FORWARD) {
+                       /* additionally pass some of the EDE codes through */
+                       ede_passthru(pkt, req);
+               }
                break;
        case KNOT_RCODE_FORMERR:
                ret = KR_STATE_FAIL;
index 5aa2992c93616911959f623f6e0fce7cd9e66e6c..c25782e62aafa9e06e06ddafe2efafdba74a7379 100644 (file)
@@ -686,6 +686,13 @@ void error(struct kr_query *qry, struct address_state *addr_state,
                break;
        case KR_SELECTION_REFUSED:
        case KR_SELECTION_SERVFAIL:
+               if (qry->flags.FORWARD || qry->flags.STUB) {
+                       /* The NS might not be broken, but this state is just for this query
+                        * and it doesn't make sense to retry on the same NS immediately. */
+                       addr_state->broken = true;
+                       break;
+               }
+               /* For authoritative servers we try some fallback workarounds. */
                if (qry->flags.NO_MINIMIZE && qry->flags.NO_0X20 && qry->flags.TCP) {
                        addr_state->broken = true;
                } else if (qry->flags.NO_MINIMIZE) {
index 54f9a12262562c9f8f1efc064a665e4d4ab439e3..3fcfc75454a52bc14ec2c8ce71ef56ce936eb737 100644 (file)
@@ -66,7 +66,7 @@ void forward_choose_transport(struct kr_query *qry,
 
                update_address_state(addr_state, address, addr_len, qry);
 
-               if (addr_state->generation == -1) {
+               if (addr_state->generation == -1 || addr_state->broken) {
                        continue;
                }
                addr_state->choice_array_index = i;