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