Coverage Report

Created: 2026-04-05 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/bind9/lib/dns/rdata/generic/nxt_30.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
/* RFC2535 */
15
16
#ifndef RDATA_GENERIC_NXT_30_C
17
#define RDATA_GENERIC_NXT_30_C
18
19
/*
20
 * The attributes do not include DNS_RDATATYPEATTR_SINGLETON
21
 * because we must be able to handle a parent/child NXT pair.
22
 */
23
23.0k
#define RRTYPE_NXT_ATTRIBUTES (0)
24
25
static isc_result_t
26
98.9k
fromtext_nxt(ARGS_FROMTEXT) {
27
98.9k
  isc_token_t token;
28
98.9k
  isc_buffer_t buffer;
29
98.9k
  char *e;
30
98.9k
  unsigned char bm[8 * 1024]; /* 64k bits */
31
98.9k
  dns_rdatatype_t covered;
32
98.9k
  dns_rdatatype_t maxcovered = 0;
33
98.9k
  bool first = true;
34
98.9k
  long n;
35
36
98.9k
  REQUIRE(type == dns_rdatatype_nxt);
37
38
98.9k
  UNUSED(type);
39
98.9k
  UNUSED(rdclass);
40
98.9k
  UNUSED(callbacks);
41
42
  /*
43
   * Next domain.
44
   */
45
98.9k
  RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
46
98.9k
              false));
47
98.9k
  buffer_fromregion(&buffer, &token.value.as_region);
48
98.9k
  if (origin == NULL) {
49
492
    origin = dns_rootname;
50
492
  }
51
98.9k
  RETTOK(dns_name_wirefromtext(&buffer, origin, options, target));
52
53
98.9k
  memset(bm, 0, sizeof(bm));
54
222k
  do {
55
222k
    RETERR(isc_lex_getmastertoken(lexer, &token,
56
222k
                isc_tokentype_string, true));
57
222k
    if (token.type != isc_tokentype_string) {
58
98.5k
      break;
59
98.5k
    }
60
124k
    n = strtol(DNS_AS_STR(token), &e, 10);
61
124k
    if (e != DNS_AS_STR(token) && *e == '\0') {
62
8.77k
      covered = (dns_rdatatype_t)n;
63
115k
    } else if (dns_rdatatype_fromtext(&covered,
64
115k
              &token.value.as_textregion) ==
65
115k
         DNS_R_UNKNOWN)
66
133
    {
67
133
      RETTOK(DNS_R_UNKNOWN);
68
133
    }
69
    /*
70
     * NXT is only specified for types 1..127.
71
     */
72
124k
    if (covered < 1 || covered > 127) {
73
28
      return ISC_R_RANGE;
74
28
    }
75
124k
    if (first || covered > maxcovered) {
76
104k
      maxcovered = covered;
77
104k
    }
78
124k
    first = false;
79
124k
    bm[covered / 8] |= (0x80 >> (covered % 8));
80
124k
  } while (1);
81
98.5k
  isc_lex_ungettoken(lexer, &token);
82
98.5k
  if (first) {
83
2.24k
    return ISC_R_SUCCESS;
84
2.24k
  }
85
96.3k
  n = (maxcovered + 8) / 8;
86
96.3k
  return mem_tobuffer(target, bm, n);
87
98.5k
}
88
89
static isc_result_t
90
2.19k
totext_nxt(ARGS_TOTEXT) {
91
2.19k
  isc_region_t sr;
92
2.19k
  unsigned int i, j, opts;
93
2.19k
  dns_name_t name;
94
2.19k
  dns_name_t prefix;
95
96
2.19k
  REQUIRE(rdata->type == dns_rdatatype_nxt);
97
2.19k
  REQUIRE(rdata->length != 0);
98
99
2.19k
  dns_name_init(&name);
100
2.19k
  dns_name_init(&prefix);
101
2.19k
  dns_rdata_toregion(rdata, &sr);
102
2.19k
  dns_name_fromregion(&name, &sr);
103
2.19k
  isc_region_consume(&sr, name_length(&name));
104
2.19k
  opts = name_prefix(&name, tctx->origin, &prefix) ? DNS_NAME_OMITFINALDOT
105
2.19k
               : 0;
106
2.19k
  RETERR(dns_name_totext(&prefix, opts, target));
107
108
12.0k
  for (i = 0; i < sr.length; i++) {
109
9.84k
    if (sr.base[i] != 0) {
110
68.8k
      for (j = 0; j < 8; j++) {
111
61.1k
        if ((sr.base[i] & (0x80 >> j)) != 0) {
112
27.6k
          {
113
27.6k
            dns_rdatatype_t t = i * 8 + j;
114
27.6k
            RETERR(str_totext(" ", target));
115
27.6k
            if (dns_rdatatype_isknown(t)) {
116
20.7k
              RETERR(dns_rdatatype_totext(
117
20.7k
                t, target));
118
20.7k
            } else {
119
6.86k
              char buf[sizeof("6553"
120
6.86k
                  "5")];
121
6.86k
              snprintf(buf,
122
6.86k
                 sizeof(buf),
123
6.86k
                 "%u", t);
124
6.86k
              RETERR(str_totext(
125
6.86k
                buf, target));
126
6.86k
            }
127
27.6k
          }
128
27.6k
        }
129
61.1k
      }
130
7.64k
    }
131
9.84k
  }
132
2.19k
  return ISC_R_SUCCESS;
133
2.19k
}
134
135
static isc_result_t
136
4.11k
fromwire_nxt(ARGS_FROMWIRE) {
137
4.11k
  isc_region_t sr;
138
4.11k
  dns_name_t name;
139
140
4.11k
  REQUIRE(type == dns_rdatatype_nxt);
141
142
4.11k
  UNUSED(type);
143
4.11k
  UNUSED(rdclass);
144
145
4.11k
  dctx = dns_decompress_setpermitted(dctx, false);
146
147
4.11k
  dns_name_init(&name);
148
4.11k
  RETERR(dns_name_fromwire(&name, source, dctx, target));
149
150
4.03k
  isc_buffer_activeregion(source, &sr);
151
4.03k
  if (sr.length > 0 && ((sr.base[0] & 0x80) != 0 || sr.length > 16 ||
152
3.11k
            sr.base[sr.length - 1] == 0))
153
46
  {
154
46
    return DNS_R_BADBITMAP;
155
46
  }
156
3.98k
  RETERR(mem_tobuffer(target, sr.base, sr.length));
157
3.91k
  isc_buffer_forward(source, sr.length);
158
3.91k
  return ISC_R_SUCCESS;
159
3.98k
}
160
161
static isc_result_t
162
1.12k
towire_nxt(ARGS_TOWIRE) {
163
1.12k
  isc_region_t sr;
164
1.12k
  dns_name_t name;
165
166
1.12k
  REQUIRE(rdata->type == dns_rdatatype_nxt);
167
1.12k
  REQUIRE(rdata->length != 0);
168
169
1.12k
  dns_compress_setpermitted(cctx, false);
170
1.12k
  dns_name_init(&name);
171
1.12k
  dns_rdata_toregion(rdata, &sr);
172
1.12k
  dns_name_fromregion(&name, &sr);
173
1.12k
  isc_region_consume(&sr, name_length(&name));
174
1.12k
  RETERR(dns_name_towire(&name, cctx, target));
175
176
1.12k
  return mem_tobuffer(target, sr.base, sr.length);
177
1.12k
}
178
179
static int
180
3.20M
compare_nxt(ARGS_COMPARE) {
181
3.20M
  isc_region_t r1;
182
3.20M
  isc_region_t r2;
183
3.20M
  dns_name_t name1;
184
3.20M
  dns_name_t name2;
185
3.20M
  int order;
186
187
3.20M
  REQUIRE(rdata1->type == rdata2->type);
188
3.20M
  REQUIRE(rdata1->rdclass == rdata2->rdclass);
189
3.20M
  REQUIRE(rdata1->type == dns_rdatatype_nxt);
190
3.20M
  REQUIRE(rdata1->length != 0);
191
3.20M
  REQUIRE(rdata2->length != 0);
192
193
3.20M
  dns_name_init(&name1);
194
3.20M
  dns_name_init(&name2);
195
3.20M
  dns_rdata_toregion(rdata1, &r1);
196
3.20M
  dns_rdata_toregion(rdata2, &r2);
197
3.20M
  dns_name_fromregion(&name1, &r1);
198
3.20M
  dns_name_fromregion(&name2, &r2);
199
3.20M
  order = dns_name_rdatacompare(&name1, &name2);
200
3.20M
  if (order != 0) {
201
3.10M
    return order;
202
3.10M
  }
203
204
93.9k
  isc_region_consume(&r1, name_length(&name1));
205
93.9k
  isc_region_consume(&r2, name_length(&name2));
206
207
93.9k
  return isc_region_compare(&r1, &r2);
208
3.20M
}
209
210
static isc_result_t
211
0
fromstruct_nxt(ARGS_FROMSTRUCT) {
212
0
  dns_rdata_nxt_t *nxt = source;
213
0
  isc_region_t region;
214
215
0
  REQUIRE(type == dns_rdatatype_nxt);
216
0
  REQUIRE(nxt != NULL);
217
0
  REQUIRE(nxt->common.rdtype == type);
218
0
  REQUIRE(nxt->common.rdclass == rdclass);
219
0
  REQUIRE(nxt->typebits != NULL || nxt->len == 0);
220
0
  if (nxt->typebits != NULL && (nxt->typebits[0] & 0x80) == 0) {
221
0
    REQUIRE(nxt->len <= 16);
222
0
    REQUIRE(nxt->typebits[nxt->len - 1] != 0);
223
0
  }
224
225
0
  UNUSED(type);
226
0
  UNUSED(rdclass);
227
228
0
  dns_name_toregion(&nxt->next, &region);
229
0
  RETERR(isc_buffer_copyregion(target, &region));
230
231
0
  return mem_tobuffer(target, nxt->typebits, nxt->len);
232
0
}
233
234
static isc_result_t
235
0
tostruct_nxt(ARGS_TOSTRUCT) {
236
0
  isc_region_t region;
237
0
  dns_rdata_nxt_t *nxt = target;
238
0
  dns_name_t name;
239
240
0
  REQUIRE(rdata->type == dns_rdatatype_nxt);
241
0
  REQUIRE(nxt != NULL);
242
0
  REQUIRE(rdata->length != 0);
243
244
0
  DNS_RDATACOMMON_INIT(nxt, rdata->type, rdata->rdclass);
245
246
0
  dns_name_init(&name);
247
0
  dns_rdata_toregion(rdata, &region);
248
0
  dns_name_fromregion(&name, &region);
249
0
  isc_region_consume(&region, name_length(&name));
250
0
  dns_name_init(&nxt->next);
251
0
  name_duporclone(&name, mctx, &nxt->next);
252
253
0
  nxt->len = region.length;
254
0
  nxt->typebits = mem_maybedup(mctx, region.base, region.length);
255
0
  nxt->mctx = mctx;
256
0
  return ISC_R_SUCCESS;
257
0
}
258
259
static void
260
0
freestruct_nxt(ARGS_FREESTRUCT) {
261
0
  dns_rdata_nxt_t *nxt = source;
262
263
0
  REQUIRE(nxt != NULL);
264
0
  REQUIRE(nxt->common.rdtype == dns_rdatatype_nxt);
265
266
0
  if (nxt->mctx == NULL) {
267
0
    return;
268
0
  }
269
270
0
  dns_name_free(&nxt->next, nxt->mctx);
271
0
  if (nxt->typebits != NULL) {
272
0
    isc_mem_free(nxt->mctx, nxt->typebits);
273
0
  }
274
0
  nxt->mctx = NULL;
275
0
}
276
277
static isc_result_t
278
0
additionaldata_nxt(ARGS_ADDLDATA) {
279
0
  REQUIRE(rdata->type == dns_rdatatype_nxt);
280
281
0
  UNUSED(rdata);
282
0
  UNUSED(owner);
283
0
  UNUSED(add);
284
0
  UNUSED(arg);
285
286
0
  return ISC_R_SUCCESS;
287
0
}
288
289
static isc_result_t
290
0
digest_nxt(ARGS_DIGEST) {
291
0
  isc_region_t r;
292
0
  dns_name_t name;
293
294
0
  REQUIRE(rdata->type == dns_rdatatype_nxt);
295
296
0
  dns_rdata_toregion(rdata, &r);
297
0
  dns_name_init(&name);
298
0
  dns_name_fromregion(&name, &r);
299
0
  RETERR(dns_name_digest(&name, digest, arg));
300
0
  isc_region_consume(&r, name_length(&name));
301
302
0
  return (digest)(arg, &r);
303
0
}
304
305
static bool
306
0
checkowner_nxt(ARGS_CHECKOWNER) {
307
0
  REQUIRE(type == dns_rdatatype_nxt);
308
309
0
  UNUSED(name);
310
0
  UNUSED(type);
311
0
  UNUSED(rdclass);
312
0
  UNUSED(wildcard);
313
314
0
  return true;
315
0
}
316
317
static bool
318
0
checknames_nxt(ARGS_CHECKNAMES) {
319
0
  REQUIRE(rdata->type == dns_rdatatype_nxt);
320
321
0
  UNUSED(rdata);
322
0
  UNUSED(owner);
323
0
  UNUSED(bad);
324
325
0
  return true;
326
0
}
327
328
static int
329
0
casecompare_nxt(ARGS_COMPARE) {
330
0
  return compare_nxt(rdata1, rdata2);
331
0
}
332
#endif /* RDATA_GENERIC_NXT_30_C */