Coverage Report

Created: 2026-10-28 06:55

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/bind9/lib/dns/rdata/generic/soa_6.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
#ifndef RDATA_GENERIC_SOA_6_C
15
#define RDATA_GENERIC_SOA_6_C
16
17
16.0k
#define RRTYPE_SOA_ATTRIBUTES (DNS_RDATATYPEATTR_SINGLETON)
18
19
static isc_result_t
20
1.49k
fromtext_soa(ARGS_FROMTEXT) {
21
1.49k
  isc_token_t token;
22
1.49k
  isc_buffer_t buffer;
23
1.49k
  int i;
24
1.49k
  uint32_t n;
25
1.49k
  bool ok;
26
27
1.49k
  REQUIRE(type == dns_rdatatype_soa);
28
29
1.49k
  UNUSED(type);
30
1.49k
  UNUSED(rdclass);
31
1.49k
  UNUSED(callbacks);
32
33
1.49k
  if (origin == NULL) {
34
282
    origin = dns_rootname;
35
282
  }
36
37
4.35k
  for (i = 0; i < 2; i++) {
38
2.95k
    dns_fixedname_t fn;
39
2.95k
    dns_name_t *name = dns_fixedname_initname(&fn);
40
41
2.95k
    RETERR(isc_lex_getmastertoken(lexer, &token,
42
2.95k
                isc_tokentype_string, false));
43
44
2.88k
    buffer_fromregion(&buffer, &token.value.as_region);
45
2.88k
    RETTOK(dns_name_fromtext(name, &buffer, origin, options));
46
2.86k
    RETTOK(dns_name_towire(name, NULL, target));
47
2.86k
    ok = true;
48
2.86k
    if ((options & DNS_RDATA_CHECKNAMES) != 0) {
49
0
      switch (i) {
50
0
      case 0:
51
0
        ok = dns_name_ishostname(name, false);
52
0
        break;
53
0
      case 1:
54
0
        ok = dns_name_ismailbox(name);
55
0
        break;
56
0
      }
57
0
    }
58
2.86k
    if (!ok && (options & DNS_RDATA_CHECKNAMESFAIL) != 0) {
59
0
      RETTOK(DNS_R_BADNAME);
60
0
    }
61
2.86k
    if (!ok && callbacks != NULL) {
62
0
      warn_badname(name, lexer, callbacks);
63
0
    }
64
2.86k
  }
65
66
1.40k
  RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
67
1.40k
              false));
68
1.38k
  RETERR(uint32_tobuffer(token.value.as_ulong, target));
69
70
6.26k
  for (i = 0; i < 4; i++) {
71
5.08k
    RETERR(isc_lex_getmastertoken(lexer, &token,
72
5.08k
                isc_tokentype_string, false));
73
4.96k
    RETTOK(dns_counter_fromtext(&token.value.as_textregion, &n));
74
4.88k
    RETERR(uint32_tobuffer(n, target));
75
4.88k
  }
76
77
1.18k
  return ISC_R_SUCCESS;
78
1.38k
}
79
80
static const char *soa_fieldnames[5] = { "serial", "refresh", "retry", "expire",
81
           "minimum" };
82
83
static isc_result_t
84
1.79k
totext_soa(ARGS_TOTEXT) {
85
1.79k
  isc_region_t dregion;
86
1.79k
  dns_name_t mname;
87
1.79k
  dns_name_t rname;
88
1.79k
  dns_name_t prefix;
89
1.79k
  unsigned int opts;
90
1.79k
  int i;
91
1.79k
  bool multiline;
92
1.79k
  bool comm;
93
94
1.79k
  REQUIRE(rdata->type == dns_rdatatype_soa);
95
1.79k
  REQUIRE(rdata->length != 0);
96
97
1.79k
  multiline = ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0);
98
1.79k
  if (multiline) {
99
71
    comm = ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0);
100
1.72k
  } else {
101
1.72k
    comm = false;
102
1.72k
  }
103
104
1.79k
  dns_name_init(&mname);
105
1.79k
  dns_name_init(&rname);
106
1.79k
  dns_name_init(&prefix);
107
108
1.79k
  dns_rdata_toregion(rdata, &dregion);
109
110
1.79k
  dns_name_fromregion(&mname, &dregion);
111
1.79k
  isc_region_consume(&dregion, name_length(&mname));
112
113
1.79k
  dns_name_fromregion(&rname, &dregion);
114
1.79k
  isc_region_consume(&dregion, name_length(&rname));
115
116
1.79k
  opts = name_prefix(&mname, tctx->origin, &prefix)
117
1.79k
           ? DNS_NAME_OMITFINALDOT
118
1.79k
           : 0;
119
1.79k
  RETERR(dns_name_totext(&prefix, opts, target));
120
121
1.79k
  RETERR(str_totext(" ", target));
122
123
1.79k
  opts = name_prefix(&rname, tctx->origin, &prefix)
124
1.79k
           ? DNS_NAME_OMITFINALDOT
125
1.79k
           : 0;
126
1.79k
  RETERR(dns_name_totext(&prefix, opts, target));
127
128
1.79k
  if (multiline) {
129
71
    RETERR(str_totext(" (", target));
130
71
  }
131
1.79k
  RETERR(str_totext(tctx->linebreak, target));
132
133
10.7k
  for (i = 0; i < 5; i++) {
134
8.98k
    char buf[sizeof("0123456789 ; ")];
135
8.98k
    unsigned long num;
136
8.98k
    num = uint32_fromregion(&dregion);
137
8.98k
    isc_region_consume(&dregion, 4);
138
8.98k
    snprintf(buf, sizeof(buf), comm ? "%-10lu ; " : "%lu", num);
139
8.98k
    RETERR(str_totext(buf, target));
140
8.98k
    if (comm) {
141
355
      RETERR(str_totext(soa_fieldnames[i], target));
142
      /* Print times in week/day/hour/minute/second form */
143
355
      if (i >= 1) {
144
284
        RETERR(str_totext(" (", target));
145
284
        RETERR(dns_ttl_totext(num, true, true, target));
146
284
        RETERR(str_totext(")", target));
147
284
      }
148
355
      RETERR(str_totext(tctx->linebreak, target));
149
8.63k
    } else if (i < 4) {
150
6.90k
      RETERR(str_totext(tctx->linebreak, target));
151
6.90k
    }
152
8.98k
  }
153
154
1.79k
  if (multiline) {
155
71
    RETERR(str_totext(")", target));
156
71
  }
157
158
1.79k
  return ISC_R_SUCCESS;
159
1.79k
}
160
161
static isc_result_t
162
2.16k
fromwire_soa(ARGS_FROMWIRE) {
163
2.16k
  dns_name_t mname;
164
2.16k
  dns_name_t rname;
165
2.16k
  isc_region_t sregion;
166
2.16k
  isc_region_t tregion;
167
168
2.16k
  REQUIRE(type == dns_rdatatype_soa);
169
170
2.16k
  UNUSED(type);
171
2.16k
  UNUSED(rdclass);
172
173
2.16k
  dns_decompress_setpermitted(dctx, true);
174
175
2.16k
  dns_name_init(&mname);
176
2.16k
  dns_name_init(&rname);
177
178
2.16k
  RETERR(dns_name_fromwire(&mname, source, dctx, target));
179
2.04k
  RETERR(dns_name_fromwire(&rname, source, dctx, target));
180
181
1.86k
  isc_buffer_activeregion(source, &sregion);
182
1.86k
  isc_buffer_availableregion(target, &tregion);
183
184
1.86k
  if (sregion.length < 20) {
185
14
    return ISC_R_UNEXPECTEDEND;
186
14
  }
187
1.85k
  if (tregion.length < 20) {
188
76
    return ISC_R_NOSPACE;
189
76
  }
190
191
1.77k
  memmove(tregion.base, sregion.base, 20);
192
1.77k
  isc_buffer_forward(source, 20);
193
1.77k
  isc_buffer_add(target, 20);
194
195
1.77k
  return ISC_R_SUCCESS;
196
1.85k
}
197
198
static int
199
3.23k
compare_soa(ARGS_COMPARE) {
200
3.23k
  isc_region_t region1;
201
3.23k
  isc_region_t region2;
202
3.23k
  dns_name_t name1;
203
3.23k
  dns_name_t name2;
204
3.23k
  int order;
205
206
3.23k
  REQUIRE(rdata1->type == rdata2->type);
207
3.23k
  REQUIRE(rdata1->rdclass == rdata2->rdclass);
208
3.23k
  REQUIRE(rdata1->type == dns_rdatatype_soa);
209
3.23k
  REQUIRE(rdata1->length != 0);
210
3.23k
  REQUIRE(rdata2->length != 0);
211
212
3.23k
  dns_name_init(&name1);
213
3.23k
  dns_name_init(&name2);
214
215
3.23k
  dns_rdata_toregion(rdata1, &region1);
216
3.23k
  dns_rdata_toregion(rdata2, &region2);
217
218
3.23k
  dns_name_fromregion(&name1, &region1);
219
3.23k
  dns_name_fromregion(&name2, &region2);
220
221
3.23k
  order = dns_name_rdatacompare(&name1, &name2);
222
3.23k
  if (order != 0) {
223
677
    return order;
224
677
  }
225
226
2.56k
  isc_region_consume(&region1, name_length(&name1));
227
2.56k
  isc_region_consume(&region2, name_length(&name2));
228
229
2.56k
  dns_name_init(&name1);
230
2.56k
  dns_name_init(&name2);
231
232
2.56k
  dns_name_fromregion(&name1, &region1);
233
2.56k
  dns_name_fromregion(&name2, &region2);
234
235
2.56k
  order = dns_name_rdatacompare(&name1, &name2);
236
2.56k
  if (order != 0) {
237
235
    return order;
238
235
  }
239
240
2.32k
  isc_region_consume(&region1, name_length(&name1));
241
2.32k
  isc_region_consume(&region2, name_length(&name2));
242
243
2.32k
  return isc_region_compare(&region1, &region2);
244
2.56k
}
245
246
static isc_result_t
247
0
fromstruct_soa(ARGS_FROMSTRUCT) {
248
0
  dns_rdata_soa_t *soa = source;
249
0
  isc_region_t region;
250
251
0
  REQUIRE(type == dns_rdatatype_soa);
252
0
  REQUIRE(soa != NULL);
253
0
  REQUIRE(soa->common.rdtype == type);
254
0
  REQUIRE(soa->common.rdclass == rdclass);
255
256
0
  UNUSED(type);
257
0
  UNUSED(rdclass);
258
259
0
  dns_name_toregion(&soa->origin, &region);
260
0
  RETERR(isc_buffer_copyregion(target, &region));
261
0
  dns_name_toregion(&soa->contact, &region);
262
0
  RETERR(isc_buffer_copyregion(target, &region));
263
0
  RETERR(uint32_tobuffer(soa->serial, target));
264
0
  RETERR(uint32_tobuffer(soa->refresh, target));
265
0
  RETERR(uint32_tobuffer(soa->retry, target));
266
0
  RETERR(uint32_tobuffer(soa->expire, target));
267
0
  return uint32_tobuffer(soa->minimum, target);
268
0
}
269
270
static isc_result_t
271
2
tostruct_soa(ARGS_TOSTRUCT) {
272
2
  isc_region_t region;
273
2
  dns_rdata_soa_t *soa = target;
274
2
  dns_name_t name;
275
276
2
  REQUIRE(rdata->type == dns_rdatatype_soa);
277
2
  REQUIRE(soa != NULL);
278
2
  REQUIRE(rdata->length != 0);
279
280
2
  DNS_RDATACOMMON_INIT(soa, rdata->type, rdata->rdclass);
281
282
2
  dns_rdata_toregion(rdata, &region);
283
284
2
  dns_name_init(&name);
285
2
  dns_name_fromregion(&name, &region);
286
2
  isc_region_consume(&region, name_length(&name));
287
2
  dns_name_init(&soa->origin);
288
2
  dns_name_clone(&name, &soa->origin);
289
290
2
  dns_name_fromregion(&name, &region);
291
2
  isc_region_consume(&region, name_length(&name));
292
2
  dns_name_init(&soa->contact);
293
2
  dns_name_clone(&name, &soa->contact);
294
295
2
  soa->serial = uint32_fromregion(&region);
296
2
  isc_region_consume(&region, 4);
297
298
2
  soa->refresh = uint32_fromregion(&region);
299
2
  isc_region_consume(&region, 4);
300
301
2
  soa->retry = uint32_fromregion(&region);
302
2
  isc_region_consume(&region, 4);
303
304
2
  soa->expire = uint32_fromregion(&region);
305
2
  isc_region_consume(&region, 4);
306
307
2
  soa->minimum = uint32_fromregion(&region);
308
309
2
  return ISC_R_SUCCESS;
310
2
}
311
312
static isc_result_t
313
0
additionaldata_soa(ARGS_ADDLDATA) {
314
0
  REQUIRE(rdata->type == dns_rdatatype_soa);
315
316
0
  UNUSED(rdata);
317
0
  UNUSED(owner);
318
0
  UNUSED(add);
319
0
  UNUSED(arg);
320
321
0
  return ISC_R_SUCCESS;
322
0
}
323
324
static isc_result_t
325
0
digest_soa(ARGS_DIGEST) {
326
0
  isc_region_t r;
327
0
  dns_name_t name;
328
329
0
  REQUIRE(rdata->type == dns_rdatatype_soa);
330
331
0
  dns_rdata_toregion(rdata, &r);
332
333
0
  dns_name_init(&name);
334
0
  dns_name_fromregion(&name, &r);
335
0
  RETERR(dns_name_digest(&name, digest, arg));
336
0
  isc_region_consume(&r, name_length(&name));
337
338
0
  dns_name_init(&name);
339
0
  dns_name_fromregion(&name, &r);
340
0
  RETERR(dns_name_digest(&name, digest, arg));
341
0
  isc_region_consume(&r, name_length(&name));
342
343
0
  return (digest)(arg, &r);
344
0
}
345
346
static bool
347
0
checkowner_soa(ARGS_CHECKOWNER) {
348
0
  REQUIRE(type == dns_rdatatype_soa);
349
350
0
  UNUSED(name);
351
0
  UNUSED(type);
352
0
  UNUSED(rdclass);
353
0
  UNUSED(wildcard);
354
355
0
  return true;
356
0
}
357
358
static bool
359
0
checknames_soa(ARGS_CHECKNAMES) {
360
0
  isc_region_t region;
361
0
  dns_name_t name;
362
363
0
  REQUIRE(rdata->type == dns_rdatatype_soa);
364
365
0
  UNUSED(owner);
366
367
0
  dns_rdata_toregion(rdata, &region);
368
0
  dns_name_init(&name);
369
0
  dns_name_fromregion(&name, &region);
370
0
  if (!dns_name_ishostname(&name, false)) {
371
0
    if (bad != NULL) {
372
0
      dns_name_clone(&name, bad);
373
0
    }
374
0
    return false;
375
0
  }
376
0
  isc_region_consume(&region, name_length(&name));
377
0
  dns_name_fromregion(&name, &region);
378
0
  if (!dns_name_ismailbox(&name)) {
379
0
    if (bad != NULL) {
380
0
      dns_name_clone(&name, bad);
381
0
    }
382
0
    return false;
383
0
  }
384
0
  return true;
385
0
}
386
387
static int
388
0
casecompare_soa(ARGS_COMPARE) {
389
0
  return compare_soa(rdata1, rdata2);
390
0
}
391
392
#endif /* RDATA_GENERIC_SOA_6_C */