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