Coverage Report

Created: 2025-11-24 06:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/bind9/lib/dns/ede.c
Line
Count
Source
1
/*
2
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3
 *
4
 * SPDX-License-Identifier: MPL-2.0
5
 *
6
 * This Source Code Form is subject to the terms of the Mozilla Public
7
 * License, v. 2.0. If a copy of the MPL was not distributed with this
8
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
9
 *
10
 * See the COPYRIGHT file distributed with this work for additional
11
 * information regarding copyright ownership.
12
 */
13
14
/*! \file */
15
16
#include <isc/mem.h>
17
#include <isc/util.h>
18
19
#include <dns/ede.h>
20
21
0
#define DNS_EDE_MAGIC  ISC_MAGIC('E', 'D', 'E', '!')
22
#define DNS_EDE_VALID(v) ISC_MAGIC_VALID(v, DNS_EDE_MAGIC)
23
24
static bool
25
0
dns__ede_checkandupdateedeused(dns_edectx_t *edectx, uint16_t code) {
26
0
  if (edectx->edeused & (1 << code)) {
27
0
    return true;
28
0
  }
29
30
0
  edectx->edeused |= 1 << code;
31
0
  return false;
32
0
}
33
34
void
35
0
dns_ede_add(dns_edectx_t *edectx, uint16_t code, const char *text) {
36
0
  REQUIRE(DNS_EDE_VALID(edectx));
37
0
  REQUIRE(code < DNS_EDE_MAX_CODE);
38
39
0
  uint16_t becode = htobe16(code);
40
0
  dns_ednsopt_t *edns = NULL;
41
0
  size_t textlen = 0;
42
43
0
  if (dns__ede_checkandupdateedeused(edectx, code)) {
44
0
    isc_log_write(DNS_LOGCATEGORY_RESOLVER, DNS_LOGMODULE_RESOLVER,
45
0
            ISC_LOG_DEBUG(1), "ignoring duplicate ede %u %s",
46
0
            code, text == NULL ? "(null)" : text);
47
0
    return;
48
0
  }
49
50
0
  if (edectx->nextede >= DNS_EDE_MAX_ERRORS) {
51
0
    isc_log_write(DNS_LOGCATEGORY_RESOLVER, DNS_LOGMODULE_RESOLVER,
52
0
            ISC_LOG_DEBUG(1), "too many ede, ignoring %u %s",
53
0
            code, text == NULL ? "(null)" : text);
54
0
    return;
55
0
  }
56
0
  INSIST(edectx->ede[edectx->nextede] == NULL);
57
58
0
  isc_log_write(DNS_LOGCATEGORY_RESOLVER, DNS_LOGMODULE_RESOLVER,
59
0
          ISC_LOG_DEBUG(1), "set ede: info-code %u extra-text %s",
60
0
          code, text == NULL ? "(null)" : text);
61
62
0
  if (text != NULL) {
63
0
    textlen = strlen(text);
64
65
0
    if (textlen > DNS_EDE_EXTRATEXT_LEN) {
66
0
      isc_log_write(DNS_LOGCATEGORY_RESOLVER,
67
0
              DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(1),
68
0
              "truncate EDE code %hu text: %s", code,
69
0
              text);
70
0
      textlen = DNS_EDE_EXTRATEXT_LEN;
71
0
    }
72
0
  }
73
74
0
  edns = isc_mem_get(edectx->mctx,
75
0
         sizeof(*edns) + sizeof(becode) + textlen);
76
0
  *edns = (dns_ednsopt_t){
77
0
    .code = DNS_OPT_EDE,
78
0
    .length = sizeof(becode) + textlen,
79
0
    .value = (uint8_t *)edns + sizeof(*edns),
80
0
  };
81
82
0
  memmove(edns->value, &becode, sizeof(becode));
83
0
  if (textlen > 0) {
84
0
    memmove(edns->value + sizeof(becode), text, textlen);
85
0
  }
86
87
0
  edectx->ede[edectx->nextede] = edns;
88
0
  edectx->nextede++;
89
0
}
90
91
void
92
0
dns_ede_init(isc_mem_t *mctx, dns_edectx_t *edectx) {
93
0
  REQUIRE(mctx != NULL);
94
95
  /*
96
   * Memory context is assigned, not attached here,
97
   * thus there's no detach in dns_ede_reset().
98
   */
99
0
  *edectx = (dns_edectx_t){
100
0
    .magic = DNS_EDE_MAGIC,
101
0
    .mctx = mctx,
102
0
  };
103
0
}
104
105
void
106
0
dns_ede_reset(dns_edectx_t *edectx) {
107
0
  REQUIRE(DNS_EDE_VALID(edectx));
108
109
0
  for (size_t i = 0; i < DNS_EDE_MAX_ERRORS; i++) {
110
0
    dns_ednsopt_t *edns = edectx->ede[i];
111
0
    if (edns == NULL) {
112
0
      break;
113
0
    }
114
115
0
    isc_mem_put(edectx->mctx, edns, sizeof(*edns) + edns->length);
116
0
    edectx->ede[i] = NULL;
117
0
  }
118
119
0
  dns_ede_init(edectx->mctx, edectx);
120
0
}
121
122
void
123
0
dns_ede_invalidate(dns_edectx_t *edectx) {
124
0
  REQUIRE(DNS_EDE_VALID(edectx));
125
126
0
  dns_ede_reset(edectx);
127
128
0
  edectx->magic = 0;
129
0
  edectx->mctx = NULL;
130
0
}
131
132
void
133
0
dns_ede_copy(dns_edectx_t *edectx_to, const dns_edectx_t *edectx_from) {
134
0
  REQUIRE(DNS_EDE_VALID(edectx_to));
135
0
  REQUIRE(DNS_EDE_VALID(edectx_from));
136
137
0
  if (edectx_to == edectx_from) {
138
0
    return;
139
0
  }
140
141
0
  for (size_t pos = 0; pos < DNS_EDE_MAX_ERRORS; pos++) {
142
0
    uint16_t fromcode;
143
144
0
    if (edectx_from->ede[pos] == NULL) {
145
0
      break;
146
0
    }
147
148
0
    fromcode = ISC_U8TO16_BE(edectx_from->ede[pos]->value);
149
0
    if (dns__ede_checkandupdateedeused(edectx_to, fromcode)) {
150
0
      continue;
151
0
    }
152
153
0
    if (edectx_to->nextede >= DNS_EDE_MAX_ERRORS) {
154
0
      isc_log_write(DNS_LOGCATEGORY_RESOLVER,
155
0
              DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(1),
156
0
              "too many ede from subfetch");
157
0
      break;
158
0
    }
159
160
0
    INSIST(edectx_to->ede[edectx_to->nextede] == NULL);
161
162
0
    dns_ednsopt_t *edns = isc_mem_get(
163
0
      edectx_to->mctx,
164
0
      sizeof(*edns) + edectx_from->ede[pos]->length);
165
0
    *edns = (dns_ednsopt_t){
166
0
      .code = DNS_OPT_EDE,
167
0
      .length = edectx_from->ede[pos]->length,
168
0
      .value = (uint8_t *)edns + sizeof(*edns),
169
0
    };
170
0
    memmove(edns->value, edectx_from->ede[pos]->value,
171
0
      edectx_from->ede[pos]->length);
172
173
0
    edectx_to->ede[edectx_to->nextede] = edns;
174
0
    edectx_to->nextede++;
175
0
  }
176
0
}