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