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