Coverage Report

Created: 2025-08-26 06:59

/src/bind9/lib/dns/rdata/generic/ipseckey_45.c
Line
Count
Source (jump to first uncovered line)
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_IPSECKEY_45_C
15
#define RDATA_GENERIC_IPSECKEY_45_C
16
17
#include <string.h>
18
19
#include <isc/net.h>
20
21
12.0k
#define RRTYPE_IPSECKEY_ATTRIBUTES (0)
22
23
static isc_result_t
24
597
fromtext_ipseckey(ARGS_FROMTEXT) {
25
597
  isc_token_t token;
26
597
  isc_buffer_t buffer;
27
597
  unsigned int gateway;
28
597
  struct in_addr addr;
29
597
  unsigned char addr6[16];
30
597
  isc_region_t region;
31
32
597
  REQUIRE(type == dns_rdatatype_ipseckey);
33
34
597
  UNUSED(type);
35
597
  UNUSED(rdclass);
36
597
  UNUSED(callbacks);
37
38
  /*
39
   * Precedence.
40
   */
41
597
  RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
42
597
              false));
43
592
  if (token.value.as_ulong > 0xffU) {
44
47
    RETTOK(ISC_R_RANGE);
45
47
  }
46
545
  RETERR(uint8_tobuffer(token.value.as_ulong, target));
47
48
  /*
49
   * Gateway type.
50
   */
51
545
  RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
52
545
              false));
53
525
  if (token.value.as_ulong > 0x3U) {
54
41
    RETTOK(ISC_R_RANGE);
55
41
  }
56
484
  RETERR(uint8_tobuffer(token.value.as_ulong, target));
57
484
  gateway = token.value.as_ulong;
58
59
  /*
60
   * Algorithm.
61
   */
62
484
  RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
63
484
              false));
64
482
  if (token.value.as_ulong > 0xffU) {
65
34
    RETTOK(ISC_R_RANGE);
66
34
  }
67
448
  RETERR(uint8_tobuffer(token.value.as_ulong, target));
68
69
  /*
70
   * Gateway.
71
   */
72
448
  RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
73
448
              false));
74
75
438
  switch (gateway) {
76
48
  case 0:
77
48
    if (strcmp(DNS_AS_STR(token), ".") != 0) {
78
4
      RETTOK(DNS_R_SYNTAX);
79
4
    }
80
44
    break;
81
82
44
  case 1:
83
41
    if (inet_pton(AF_INET, DNS_AS_STR(token), &addr) != 1) {
84
2
      RETTOK(DNS_R_BADDOTTEDQUAD);
85
2
    }
86
39
    isc_buffer_availableregion(target, &region);
87
39
    if (region.length < 4) {
88
0
      return ISC_R_NOSPACE;
89
0
    }
90
39
    memmove(region.base, &addr, 4);
91
39
    isc_buffer_add(target, 4);
92
39
    break;
93
94
10
  case 2:
95
10
    if (inet_pton(AF_INET6, DNS_AS_STR(token), addr6) != 1) {
96
3
      RETTOK(DNS_R_BADAAAA);
97
3
    }
98
7
    isc_buffer_availableregion(target, &region);
99
7
    if (region.length < 16) {
100
0
      return ISC_R_NOSPACE;
101
0
    }
102
7
    memmove(region.base, addr6, 16);
103
7
    isc_buffer_add(target, 16);
104
7
    break;
105
106
339
  case 3:
107
339
    buffer_fromregion(&buffer, &token.value.as_region);
108
339
    if (origin == NULL) {
109
2
      origin = dns_rootname;
110
2
    }
111
339
    RETTOK(dns_name_wirefromtext(&buffer, origin, options, target));
112
337
    break;
113
438
  }
114
115
  /*
116
   * Public key.
117
   */
118
427
  return isc_base64_tobuffer(lexer, target, -2);
119
438
}
120
121
static isc_result_t
122
2.46k
totext_ipseckey(ARGS_TOTEXT) {
123
2.46k
  isc_region_t region;
124
2.46k
  dns_name_t name;
125
2.46k
  char buf[sizeof("255 ")];
126
2.46k
  unsigned short num;
127
2.46k
  unsigned short gateway;
128
129
2.46k
  REQUIRE(rdata->type == dns_rdatatype_ipseckey);
130
2.46k
  REQUIRE(rdata->length >= 3);
131
132
2.46k
  dns_name_init(&name);
133
134
2.46k
  if (rdata->data[1] > 3U) {
135
0
    return ISC_R_NOTIMPLEMENTED;
136
0
  }
137
138
2.46k
  if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
139
62
    RETERR(str_totext("( ", target));
140
62
  }
141
142
  /*
143
   * Precedence.
144
   */
145
2.46k
  dns_rdata_toregion(rdata, &region);
146
2.46k
  num = uint8_fromregion(&region);
147
2.46k
  isc_region_consume(&region, 1);
148
2.46k
  snprintf(buf, sizeof(buf), "%u ", num);
149
2.46k
  RETERR(str_totext(buf, target));
150
151
  /*
152
   * Gateway type.
153
   */
154
2.46k
  gateway = uint8_fromregion(&region);
155
2.46k
  isc_region_consume(&region, 1);
156
2.46k
  snprintf(buf, sizeof(buf), "%u ", gateway);
157
2.46k
  RETERR(str_totext(buf, target));
158
159
  /*
160
   * Algorithm.
161
   */
162
2.46k
  num = uint8_fromregion(&region);
163
2.46k
  isc_region_consume(&region, 1);
164
2.46k
  snprintf(buf, sizeof(buf), "%u ", num);
165
2.46k
  RETERR(str_totext(buf, target));
166
167
  /*
168
   * Gateway.
169
   */
170
2.46k
  switch (gateway) {
171
1.29k
  case 0:
172
1.29k
    RETERR(str_totext(".", target));
173
1.29k
    break;
174
175
1.29k
  case 1:
176
334
    RETERR(inet_totext(AF_INET, tctx->flags, &region, target));
177
334
    isc_region_consume(&region, 4);
178
334
    break;
179
180
338
  case 2:
181
338
    RETERR(inet_totext(AF_INET6, tctx->flags, &region, target));
182
338
    isc_region_consume(&region, 16);
183
338
    break;
184
185
494
  case 3:
186
494
    dns_name_fromregion(&name, &region);
187
494
    RETERR(dns_name_totext(&name, 0, target));
188
494
    isc_region_consume(&region, name_length(&name));
189
494
    break;
190
2.46k
  }
191
192
  /*
193
   * Key.
194
   */
195
2.46k
  if (region.length > 0U) {
196
2.46k
    RETERR(str_totext(tctx->linebreak, target));
197
2.46k
    if (tctx->width == 0) { /* No splitting */
198
0
      RETERR(isc_base64_totext(&region, 60, "", target));
199
2.46k
    } else {
200
2.46k
      RETERR(isc_base64_totext(&region, tctx->width - 2,
201
2.46k
             tctx->linebreak, target));
202
2.46k
    }
203
2.46k
  }
204
205
2.46k
  if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
206
62
    RETERR(str_totext(" )", target));
207
62
  }
208
2.46k
  return ISC_R_SUCCESS;
209
2.46k
}
210
211
static isc_result_t
212
3.02k
fromwire_ipseckey(ARGS_FROMWIRE) {
213
3.02k
  dns_name_t name;
214
3.02k
  isc_region_t region;
215
216
3.02k
  REQUIRE(type == dns_rdatatype_ipseckey);
217
218
3.02k
  UNUSED(type);
219
3.02k
  UNUSED(rdclass);
220
221
3.02k
  dctx = dns_decompress_setpermitted(dctx, false);
222
223
3.02k
  dns_name_init(&name);
224
225
3.02k
  isc_buffer_activeregion(source, &region);
226
3.02k
  if (region.length < 3) {
227
10
    return ISC_R_UNEXPECTEDEND;
228
10
  }
229
230
3.01k
  switch (region.base[1]) {
231
1.45k
  case 0:
232
1.45k
    if (region.length < 4) {
233
4
      return ISC_R_UNEXPECTEDEND;
234
4
    }
235
1.45k
    isc_buffer_forward(source, region.length);
236
1.45k
    return mem_tobuffer(target, region.base, region.length);
237
238
350
  case 1:
239
350
    if (region.length < 8) {
240
5
      return ISC_R_UNEXPECTEDEND;
241
5
    }
242
345
    isc_buffer_forward(source, region.length);
243
345
    return mem_tobuffer(target, region.base, region.length);
244
245
392
  case 2:
246
392
    if (region.length < 20) {
247
10
      return ISC_R_UNEXPECTEDEND;
248
10
    }
249
382
    isc_buffer_forward(source, region.length);
250
382
    return mem_tobuffer(target, region.base, region.length);
251
252
811
  case 3:
253
811
    RETERR(mem_tobuffer(target, region.base, 3));
254
743
    isc_buffer_forward(source, 3);
255
743
    RETERR(dns_name_fromwire(&name, source, dctx, target));
256
658
    isc_buffer_activeregion(source, &region);
257
658
    isc_buffer_forward(source, region.length);
258
658
    if (region.length < 1) {
259
11
      return ISC_R_UNEXPECTEDEND;
260
11
    }
261
647
    return mem_tobuffer(target, region.base, region.length);
262
263
7
  default:
264
7
    return ISC_R_NOTIMPLEMENTED;
265
3.01k
  }
266
3.01k
}
267
268
static isc_result_t
269
1.28k
towire_ipseckey(ARGS_TOWIRE) {
270
1.28k
  isc_region_t region;
271
272
1.28k
  REQUIRE(rdata->type == dns_rdatatype_ipseckey);
273
1.28k
  REQUIRE(rdata->length != 0);
274
275
1.28k
  UNUSED(cctx);
276
277
1.28k
  dns_rdata_toregion(rdata, &region);
278
1.28k
  return mem_tobuffer(target, region.base, region.length);
279
1.28k
}
280
281
static int
282
648
compare_ipseckey(ARGS_COMPARE) {
283
648
  isc_region_t region1;
284
648
  isc_region_t region2;
285
286
648
  REQUIRE(rdata1->type == rdata2->type);
287
648
  REQUIRE(rdata1->rdclass == rdata2->rdclass);
288
648
  REQUIRE(rdata1->type == dns_rdatatype_ipseckey);
289
648
  REQUIRE(rdata1->length >= 3);
290
648
  REQUIRE(rdata2->length >= 3);
291
292
648
  dns_rdata_toregion(rdata1, &region1);
293
648
  dns_rdata_toregion(rdata2, &region2);
294
295
648
  return isc_region_compare(&region1, &region2);
296
648
}
297
298
static isc_result_t
299
0
fromstruct_ipseckey(ARGS_FROMSTRUCT) {
300
0
  dns_rdata_ipseckey_t *ipseckey = source;
301
0
  isc_region_t region;
302
0
  uint32_t n;
303
304
0
  REQUIRE(type == dns_rdatatype_ipseckey);
305
0
  REQUIRE(ipseckey != NULL);
306
0
  REQUIRE(ipseckey->common.rdtype == type);
307
0
  REQUIRE(ipseckey->common.rdclass == rdclass);
308
309
0
  UNUSED(type);
310
0
  UNUSED(rdclass);
311
312
0
  if (ipseckey->gateway_type > 3U) {
313
0
    return ISC_R_NOTIMPLEMENTED;
314
0
  }
315
316
0
  RETERR(uint8_tobuffer(ipseckey->precedence, target));
317
0
  RETERR(uint8_tobuffer(ipseckey->gateway_type, target));
318
0
  RETERR(uint8_tobuffer(ipseckey->algorithm, target));
319
320
0
  switch (ipseckey->gateway_type) {
321
0
  case 0:
322
0
    break;
323
324
0
  case 1:
325
0
    n = ntohl(ipseckey->in_addr.s_addr);
326
0
    RETERR(uint32_tobuffer(n, target));
327
0
    break;
328
329
0
  case 2:
330
0
    RETERR(mem_tobuffer(target, ipseckey->in6_addr.s6_addr, 16));
331
0
    break;
332
333
0
  case 3:
334
0
    dns_name_toregion(&ipseckey->gateway, &region);
335
0
    RETERR(isc_buffer_copyregion(target, &region));
336
0
    break;
337
0
  }
338
339
0
  return mem_tobuffer(target, ipseckey->key, ipseckey->keylength);
340
0
}
341
342
static isc_result_t
343
0
tostruct_ipseckey(ARGS_TOSTRUCT) {
344
0
  isc_region_t region;
345
0
  dns_rdata_ipseckey_t *ipseckey = target;
346
0
  dns_name_t name;
347
0
  uint32_t n;
348
349
0
  REQUIRE(rdata->type == dns_rdatatype_ipseckey);
350
0
  REQUIRE(ipseckey != NULL);
351
0
  REQUIRE(rdata->length >= 3);
352
353
0
  DNS_RDATACOMMON_INIT(ipseckey, rdata->type, rdata->rdclass);
354
355
0
  dns_name_init(&name);
356
0
  dns_rdata_toregion(rdata, &region);
357
358
0
  ipseckey->precedence = uint8_fromregion(&region);
359
0
  isc_region_consume(&region, 1);
360
361
0
  ipseckey->gateway_type = uint8_fromregion(&region);
362
0
  isc_region_consume(&region, 1);
363
364
0
  ipseckey->algorithm = uint8_fromregion(&region);
365
0
  isc_region_consume(&region, 1);
366
367
0
  switch (ipseckey->gateway_type) {
368
0
  case 0:
369
0
    break;
370
371
0
  case 1:
372
0
    n = uint32_fromregion(&region);
373
0
    ipseckey->in_addr.s_addr = htonl(n);
374
0
    isc_region_consume(&region, 4);
375
0
    break;
376
377
0
  case 2:
378
0
    INSIST(region.length >= 16U);
379
0
    memmove(ipseckey->in6_addr.s6_addr, region.base, 16);
380
0
    isc_region_consume(&region, 16);
381
0
    break;
382
383
0
  case 3:
384
0
    dns_name_init(&ipseckey->gateway);
385
0
    dns_name_fromregion(&name, &region);
386
0
    name_duporclone(&name, mctx, &ipseckey->gateway);
387
0
    isc_region_consume(&region, name_length(&name));
388
0
    break;
389
0
  }
390
391
0
  ipseckey->keylength = region.length;
392
0
  if (ipseckey->keylength != 0U) {
393
0
    ipseckey->key = mem_maybedup(mctx, region.base,
394
0
               ipseckey->keylength);
395
0
  } else {
396
0
    ipseckey->key = NULL;
397
0
  }
398
399
0
  ipseckey->mctx = mctx;
400
0
  return ISC_R_SUCCESS;
401
0
}
402
403
static void
404
0
freestruct_ipseckey(ARGS_FREESTRUCT) {
405
0
  dns_rdata_ipseckey_t *ipseckey = source;
406
407
0
  REQUIRE(ipseckey != NULL);
408
0
  REQUIRE(ipseckey->common.rdtype == dns_rdatatype_ipseckey);
409
410
0
  if (ipseckey->mctx == NULL) {
411
0
    return;
412
0
  }
413
414
0
  if (ipseckey->gateway_type == 3) {
415
0
    dns_name_free(&ipseckey->gateway, ipseckey->mctx);
416
0
  }
417
418
0
  if (ipseckey->key != NULL) {
419
0
    isc_mem_free(ipseckey->mctx, ipseckey->key);
420
0
  }
421
422
0
  ipseckey->mctx = NULL;
423
0
}
424
425
static isc_result_t
426
0
additionaldata_ipseckey(ARGS_ADDLDATA) {
427
0
  REQUIRE(rdata->type == dns_rdatatype_ipseckey);
428
429
0
  UNUSED(rdata);
430
0
  UNUSED(owner);
431
0
  UNUSED(add);
432
0
  UNUSED(arg);
433
434
0
  return ISC_R_SUCCESS;
435
0
}
436
437
static isc_result_t
438
0
digest_ipseckey(ARGS_DIGEST) {
439
0
  isc_region_t region;
440
441
0
  REQUIRE(rdata->type == dns_rdatatype_ipseckey);
442
443
0
  dns_rdata_toregion(rdata, &region);
444
0
  return (digest)(arg, &region);
445
0
}
446
447
static bool
448
0
checkowner_ipseckey(ARGS_CHECKOWNER) {
449
0
  REQUIRE(type == dns_rdatatype_ipseckey);
450
451
0
  UNUSED(name);
452
0
  UNUSED(type);
453
0
  UNUSED(rdclass);
454
0
  UNUSED(wildcard);
455
456
0
  return true;
457
0
}
458
459
static bool
460
0
checknames_ipseckey(ARGS_CHECKNAMES) {
461
0
  REQUIRE(rdata->type == dns_rdatatype_ipseckey);
462
463
0
  UNUSED(rdata);
464
0
  UNUSED(owner);
465
0
  UNUSED(bad);
466
467
0
  return true;
468
0
}
469
470
static int
471
0
casecompare_ipseckey(ARGS_COMPARE) {
472
0
  isc_region_t region1;
473
0
  isc_region_t region2;
474
0
  dns_name_t name1;
475
0
  dns_name_t name2;
476
0
  int order;
477
478
0
  REQUIRE(rdata1->type == rdata2->type);
479
0
  REQUIRE(rdata1->rdclass == rdata2->rdclass);
480
0
  REQUIRE(rdata1->type == dns_rdatatype_ipseckey);
481
0
  REQUIRE(rdata1->length >= 3);
482
0
  REQUIRE(rdata2->length >= 3);
483
484
0
  dns_rdata_toregion(rdata1, &region1);
485
0
  dns_rdata_toregion(rdata2, &region2);
486
487
0
  if (memcmp(region1.base, region2.base, 3) != 0 || region1.base[1] != 3)
488
0
  {
489
0
    return isc_region_compare(&region1, &region2);
490
0
  }
491
492
0
  dns_name_init(&name1);
493
0
  dns_name_init(&name2);
494
495
0
  isc_region_consume(&region1, 3);
496
0
  isc_region_consume(&region2, 3);
497
498
0
  dns_name_fromregion(&name1, &region1);
499
0
  dns_name_fromregion(&name2, &region2);
500
501
0
  order = dns_name_rdatacompare(&name1, &name2);
502
0
  if (order != 0) {
503
0
    return order;
504
0
  }
505
506
0
  isc_region_consume(&region1, name_length(&name1));
507
0
  isc_region_consume(&region2, name_length(&name2));
508
509
0
  return isc_region_compare(&region1, &region2);
510
0
}
511
512
#endif /* RDATA_GENERIC_IPSECKEY_45_C */