1 /* $NetBSD: sample-update.c,v 1.1.1.5 2015/07/08 15:38:07 christos Exp $ */ 2 3 /* 4 * Copyright (C) 2009, 2010, 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: sample-update.c,v 1.10 2010/12/09 00:54:34 marka Exp */ 20 21 #include <config.h> 22 23 #ifndef WIN32 24 #include <sys/types.h> 25 #include <sys/socket.h> 26 27 #include <netinet/in.h> 28 29 #include <arpa/inet.h> 30 31 #include <netdb.h> 32 #include <unistd.h> 33 #endif 34 35 #include <ctype.h> 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <string.h> 39 40 #include <isc/buffer.h> 41 #include <isc/commandline.h> 42 #include <isc/lex.h> 43 #include <isc/lib.h> 44 #include <isc/mem.h> 45 #include <isc/parseint.h> 46 #include <isc/sockaddr.h> 47 #include <isc/string.h> 48 #include <isc/util.h> 49 50 #include <dns/callbacks.h> 51 #include <dns/client.h> 52 #include <dns/fixedname.h> 53 #include <dns/lib.h> 54 #include <dns/name.h> 55 #include <dns/rdata.h> 56 #include <dns/rdataclass.h> 57 #include <dns/rdatalist.h> 58 #include <dns/rdataset.h> 59 #include <dns/rdatastruct.h> 60 #include <dns/rdatatype.h> 61 #include <dns/result.h> 62 #include <dns/secalg.h> 63 #include <dns/tsec.h> 64 65 #include <dst/dst.h> 66 67 static dns_tsec_t *tsec = NULL; 68 static const dns_rdataclass_t default_rdataclass = dns_rdataclass_in; 69 static isc_bufferlist_t usedbuffers; 70 static ISC_LIST(dns_rdatalist_t) usedrdatalists; 71 72 static void setup_tsec(char *keyfile, isc_mem_t *mctx); 73 static void update_addordelete(isc_mem_t *mctx, char *cmdline, 74 isc_boolean_t isdelete, dns_name_t *name); 75 static void evaluate_prereq(isc_mem_t *mctx, char *cmdline, dns_name_t *name); 76 77 ISC_PLATFORM_NORETURN_PRE static void 78 usage(void) ISC_PLATFORM_NORETURN_POST; 79 80 static void 81 usage(void) { 82 fprintf(stderr, "sample-update " 83 "[-a auth_server] " 84 "[-k keyfile] " 85 "[-p prerequisite] " 86 "[-r recursive_server] " 87 "[-z zonename] " 88 "(add|delete) \"name TTL RRtype RDATA\"\n"); 89 exit(1); 90 } 91 92 int 93 main(int argc, char *argv[]) { 94 int ch; 95 struct addrinfo hints, *res; 96 int gai_error; 97 dns_client_t *client = NULL; 98 char *zonenamestr = NULL; 99 char *keyfilename = NULL; 100 char *prereqstr = NULL; 101 isc_sockaddrlist_t auth_servers; 102 char *auth_server = NULL; 103 char *recursive_server = NULL; 104 isc_sockaddr_t sa_auth, sa_recursive; 105 isc_sockaddrlist_t rec_servers; 106 isc_result_t result; 107 isc_boolean_t isdelete; 108 isc_buffer_t b, *buf; 109 dns_fixedname_t zname0, pname0, uname0; 110 unsigned int namelen; 111 dns_name_t *zname = NULL, *uname, *pname; 112 dns_rdataset_t *rdataset; 113 dns_rdatalist_t *rdatalist; 114 dns_rdata_t *rdata; 115 dns_namelist_t updatelist, prereqlist, *prereqlistp = NULL; 116 isc_mem_t *umctx = NULL; 117 118 while ((ch = isc_commandline_parse(argc, argv, "a:k:p:r:z:")) != EOF) { 119 switch (ch) { 120 case 'k': 121 keyfilename = isc_commandline_argument; 122 break; 123 case 'a': 124 auth_server = isc_commandline_argument; 125 break; 126 case 'p': 127 prereqstr = isc_commandline_argument; 128 break; 129 case 'r': 130 recursive_server = isc_commandline_argument; 131 break; 132 case 'z': 133 zonenamestr = isc_commandline_argument; 134 break; 135 default: 136 usage(); 137 } 138 } 139 140 argc -= isc_commandline_index; 141 argv += isc_commandline_index; 142 if (argc < 2) 143 usage(); 144 145 /* command line argument validation */ 146 if (strcmp(argv[0], "delete") == 0) 147 isdelete = ISC_TRUE; 148 else if (strcmp(argv[0], "add") == 0) 149 isdelete = ISC_FALSE; 150 else { 151 fprintf(stderr, "invalid update command: %s\n", argv[0]); 152 exit(1); 153 } 154 155 if (auth_server == NULL && recursive_server == NULL) { 156 fprintf(stderr, "authoritative or recursive server " 157 "must be specified\n"); 158 usage(); 159 } 160 161 /* Initialization */ 162 ISC_LIST_INIT(usedbuffers); 163 ISC_LIST_INIT(usedrdatalists); 164 ISC_LIST_INIT(prereqlist); 165 ISC_LIST_INIT(auth_servers); 166 isc_lib_register(); 167 result = dns_lib_init(); 168 if (result != ISC_R_SUCCESS) { 169 fprintf(stderr, "dns_lib_init failed: %d\n", result); 170 exit(1); 171 } 172 result = isc_mem_create(0, 0, &umctx); 173 if (result != ISC_R_SUCCESS) { 174 fprintf(stderr, "failed to crate mctx\n"); 175 exit(1); 176 } 177 178 result = dns_client_create(&client, 0); 179 if (result != ISC_R_SUCCESS) { 180 fprintf(stderr, "dns_client_create failed: %d\n", result); 181 exit(1); 182 } 183 184 /* Set the authoritative server */ 185 if (auth_server != NULL) { 186 memset(&hints, 0, sizeof(hints)); 187 hints.ai_family = AF_UNSPEC; 188 hints.ai_socktype = SOCK_DGRAM; 189 hints.ai_protocol = IPPROTO_UDP; 190 #ifdef AI_NUMERICHOST 191 hints.ai_flags = AI_NUMERICHOST; 192 #endif 193 gai_error = getaddrinfo(auth_server, "53", &hints, &res); 194 if (gai_error != 0) { 195 fprintf(stderr, "getaddrinfo failed: %s\n", 196 gai_strerror(gai_error)); 197 exit(1); 198 } 199 INSIST(res->ai_addrlen <= sizeof(sa_auth.type)); 200 memmove(&sa_auth.type, res->ai_addr, res->ai_addrlen); 201 freeaddrinfo(res); 202 sa_auth.length = (unsigned int)res->ai_addrlen; 203 ISC_LINK_INIT(&sa_auth, link); 204 205 ISC_LIST_APPEND(auth_servers, &sa_auth, link); 206 } 207 208 /* Set the recursive server */ 209 if (recursive_server != NULL) { 210 memset(&hints, 0, sizeof(hints)); 211 hints.ai_family = AF_UNSPEC; 212 hints.ai_socktype = SOCK_DGRAM; 213 hints.ai_protocol = IPPROTO_UDP; 214 #ifdef AI_NUMERICHOST 215 hints.ai_flags = AI_NUMERICHOST; 216 #endif 217 gai_error = getaddrinfo(recursive_server, "53", &hints, &res); 218 if (gai_error != 0) { 219 fprintf(stderr, "getaddrinfo failed: %s\n", 220 gai_strerror(gai_error)); 221 exit(1); 222 } 223 INSIST(res->ai_addrlen <= sizeof(sa_recursive.type)); 224 memmove(&sa_recursive.type, res->ai_addr, res->ai_addrlen); 225 freeaddrinfo(res); 226 sa_recursive.length = (unsigned int)res->ai_addrlen; 227 ISC_LINK_INIT(&sa_recursive, link); 228 ISC_LIST_INIT(rec_servers); 229 ISC_LIST_APPEND(rec_servers, &sa_recursive, link); 230 result = dns_client_setservers(client, dns_rdataclass_in, 231 NULL, &rec_servers); 232 if (result != ISC_R_SUCCESS) { 233 fprintf(stderr, "set server failed: %d\n", result); 234 exit(1); 235 } 236 } 237 238 /* Construct zone name */ 239 zname = NULL; 240 if (zonenamestr != NULL) { 241 namelen = strlen(zonenamestr); 242 isc_buffer_init(&b, zonenamestr, namelen); 243 isc_buffer_add(&b, namelen); 244 dns_fixedname_init(&zname0); 245 zname = dns_fixedname_name(&zname0); 246 result = dns_name_fromtext(zname, &b, dns_rootname, 0, NULL); 247 if (result != ISC_R_SUCCESS) 248 fprintf(stderr, "failed to convert zone name: %d\n", 249 result); 250 } 251 252 /* Construct prerequisite name (if given) */ 253 if (prereqstr != NULL) { 254 dns_fixedname_init(&pname0); 255 pname = dns_fixedname_name(&pname0); 256 evaluate_prereq(umctx, prereqstr, pname); 257 ISC_LIST_APPEND(prereqlist, pname, link); 258 prereqlistp = &prereqlist; 259 } 260 261 /* Construct update name */ 262 ISC_LIST_INIT(updatelist); 263 dns_fixedname_init(&uname0); 264 uname = dns_fixedname_name(&uname0); 265 update_addordelete(umctx, argv[1], isdelete, uname); 266 ISC_LIST_APPEND(updatelist, uname, link); 267 268 /* Set up TSIG/SIG(0) key (if given) */ 269 if (keyfilename != NULL) 270 setup_tsec(keyfilename, umctx); 271 272 /* Perform update */ 273 result = dns_client_update(client, 274 default_rdataclass, /* XXX: fixed */ 275 zname, prereqlistp, &updatelist, 276 (auth_server == NULL) ? NULL : 277 &auth_servers, tsec, 0); 278 if (result != ISC_R_SUCCESS) { 279 fprintf(stderr, 280 "update failed: %s\n", dns_result_totext(result)); 281 } else 282 fprintf(stderr, "update succeeded\n"); 283 284 /* Cleanup */ 285 while ((pname = ISC_LIST_HEAD(prereqlist)) != NULL) { 286 while ((rdataset = ISC_LIST_HEAD(pname->list)) != NULL) { 287 ISC_LIST_UNLINK(pname->list, rdataset, link); 288 dns_rdataset_disassociate(rdataset); 289 isc_mem_put(umctx, rdataset, sizeof(*rdataset)); 290 } 291 ISC_LIST_UNLINK(prereqlist, pname, link); 292 } 293 while ((uname = ISC_LIST_HEAD(updatelist)) != NULL) { 294 while ((rdataset = ISC_LIST_HEAD(uname->list)) != NULL) { 295 ISC_LIST_UNLINK(uname->list, rdataset, link); 296 dns_rdataset_disassociate(rdataset); 297 isc_mem_put(umctx, rdataset, sizeof(*rdataset)); 298 } 299 ISC_LIST_UNLINK(updatelist, uname, link); 300 } 301 while ((rdatalist = ISC_LIST_HEAD(usedrdatalists)) != NULL) { 302 while ((rdata = ISC_LIST_HEAD(rdatalist->rdata)) != NULL) { 303 ISC_LIST_UNLINK(rdatalist->rdata, rdata, link); 304 isc_mem_put(umctx, rdata, sizeof(*rdata)); 305 } 306 ISC_LIST_UNLINK(usedrdatalists, rdatalist, link); 307 isc_mem_put(umctx, rdatalist, sizeof(*rdatalist)); 308 } 309 while ((buf = ISC_LIST_HEAD(usedbuffers)) != NULL) { 310 ISC_LIST_UNLINK(usedbuffers, buf, link); 311 isc_buffer_free(&buf); 312 } 313 if (tsec != NULL) 314 dns_tsec_destroy(&tsec); 315 isc_mem_destroy(&umctx); 316 dns_client_destroy(&client); 317 dns_lib_shutdown(); 318 319 return (0); 320 } 321 322 /* 323 * Subroutines borrowed from nsupdate.c 324 */ 325 #define MAXWIRE (64 * 1024) 326 #define TTL_MAX 2147483647U /* Maximum signed 32 bit integer. */ 327 328 static char * 329 nsu_strsep(char **stringp, const char *delim) { 330 char *string = *stringp; 331 char *s; 332 const char *d; 333 char sc, dc; 334 335 if (string == NULL) 336 return (NULL); 337 338 for (; *string != '\0'; string++) { 339 sc = *string; 340 for (d = delim; (dc = *d) != '\0'; d++) { 341 if (sc == dc) 342 break; 343 } 344 if (dc == 0) 345 break; 346 } 347 348 for (s = string; *s != '\0'; s++) { 349 sc = *s; 350 for (d = delim; (dc = *d) != '\0'; d++) { 351 if (sc == dc) { 352 *s++ = '\0'; 353 *stringp = s; 354 return (string); 355 } 356 } 357 } 358 *stringp = NULL; 359 return (string); 360 } 361 362 static void 363 fatal(const char *format, ...) { 364 va_list args; 365 366 va_start(args, format); 367 vfprintf(stderr, format, args); 368 va_end(args); 369 fprintf(stderr, "\n"); 370 exit(1); 371 } 372 373 static inline void 374 check_result(isc_result_t result, const char *msg) { 375 if (result != ISC_R_SUCCESS) 376 fatal("%s: %s", msg, isc_result_totext(result)); 377 } 378 379 static void 380 parse_name(char **cmdlinep, dns_name_t *name) { 381 isc_result_t result; 382 char *word; 383 isc_buffer_t source; 384 385 word = nsu_strsep(cmdlinep, " \t\r\n"); 386 if (word == NULL || *word == 0) { 387 fprintf(stderr, "could not read owner name\n"); 388 exit(1); 389 } 390 391 isc_buffer_init(&source, word, strlen(word)); 392 isc_buffer_add(&source, strlen(word)); 393 result = dns_name_fromtext(name, &source, dns_rootname, 0, NULL); 394 check_result(result, "dns_name_fromtext"); 395 isc_buffer_invalidate(&source); 396 } 397 398 static void 399 parse_rdata(isc_mem_t *mctx, char **cmdlinep, dns_rdataclass_t rdataclass, 400 dns_rdatatype_t rdatatype, dns_rdata_t *rdata) 401 { 402 char *cmdline = *cmdlinep; 403 isc_buffer_t source, *buf = NULL, *newbuf = NULL; 404 isc_region_t r; 405 isc_lex_t *lex = NULL; 406 dns_rdatacallbacks_t callbacks; 407 isc_result_t result; 408 409 while (cmdline != NULL && *cmdline != 0 && 410 isspace((unsigned char)*cmdline)) 411 cmdline++; 412 413 if (cmdline != NULL && *cmdline != 0) { 414 dns_rdatacallbacks_init(&callbacks); 415 result = isc_lex_create(mctx, strlen(cmdline), &lex); 416 check_result(result, "isc_lex_create"); 417 isc_buffer_init(&source, cmdline, strlen(cmdline)); 418 isc_buffer_add(&source, strlen(cmdline)); 419 result = isc_lex_openbuffer(lex, &source); 420 check_result(result, "isc_lex_openbuffer"); 421 result = isc_buffer_allocate(mctx, &buf, MAXWIRE); 422 check_result(result, "isc_buffer_allocate"); 423 result = dns_rdata_fromtext(rdata, rdataclass, rdatatype, lex, 424 dns_rootname, 0, mctx, buf, 425 &callbacks); 426 isc_lex_destroy(&lex); 427 if (result == ISC_R_SUCCESS) { 428 isc_buffer_usedregion(buf, &r); 429 result = isc_buffer_allocate(mctx, &newbuf, r.length); 430 check_result(result, "isc_buffer_allocate"); 431 isc_buffer_putmem(newbuf, r.base, r.length); 432 isc_buffer_usedregion(newbuf, &r); 433 dns_rdata_reset(rdata); 434 dns_rdata_fromregion(rdata, rdataclass, rdatatype, &r); 435 isc_buffer_free(&buf); 436 ISC_LIST_APPEND(usedbuffers, newbuf, link); 437 } else { 438 fprintf(stderr, "invalid rdata format: %s\n", 439 isc_result_totext(result)); 440 isc_buffer_free(&buf); 441 exit(1); 442 } 443 } else { 444 rdata->flags = DNS_RDATA_UPDATE; 445 } 446 *cmdlinep = cmdline; 447 } 448 449 static void 450 update_addordelete(isc_mem_t *mctx, char *cmdline, isc_boolean_t isdelete, 451 dns_name_t *name) 452 { 453 isc_result_t result; 454 isc_uint32_t ttl; 455 char *word; 456 dns_rdataclass_t rdataclass; 457 dns_rdatatype_t rdatatype; 458 dns_rdata_t *rdata = NULL; 459 dns_rdatalist_t *rdatalist = NULL; 460 dns_rdataset_t *rdataset = NULL; 461 isc_textregion_t region; 462 463 /* 464 * Read the owner name. 465 */ 466 parse_name(&cmdline, name); 467 468 rdata = isc_mem_get(mctx, sizeof(*rdata)); 469 if (rdata == NULL) { 470 fprintf(stderr, "memory allocation for rdata failed\n"); 471 exit(1); 472 } 473 dns_rdata_init(rdata); 474 475 /* 476 * If this is an add, read the TTL and verify that it's in range. 477 * If it's a delete, ignore a TTL if present (for compatibility). 478 */ 479 word = nsu_strsep(&cmdline, " \t\r\n"); 480 if (word == NULL || *word == 0) { 481 if (!isdelete) { 482 fprintf(stderr, "could not read owner ttl\n"); 483 exit(1); 484 } 485 else { 486 ttl = 0; 487 rdataclass = dns_rdataclass_any; 488 rdatatype = dns_rdatatype_any; 489 rdata->flags = DNS_RDATA_UPDATE; 490 goto doneparsing; 491 } 492 } 493 result = isc_parse_uint32(&ttl, word, 10); 494 if (result != ISC_R_SUCCESS) { 495 if (isdelete) { 496 ttl = 0; 497 goto parseclass; 498 } else { 499 fprintf(stderr, "ttl '%s': %s\n", word, 500 isc_result_totext(result)); 501 exit(1); 502 } 503 } 504 505 if (isdelete) 506 ttl = 0; 507 else if (ttl > TTL_MAX) { 508 fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n", 509 word, TTL_MAX); 510 exit(1); 511 } 512 513 /* 514 * Read the class or type. 515 */ 516 word = nsu_strsep(&cmdline, " \t\r\n"); 517 parseclass: 518 if (word == NULL || *word == 0) { 519 if (isdelete) { 520 rdataclass = dns_rdataclass_any; 521 rdatatype = dns_rdatatype_any; 522 rdata->flags = DNS_RDATA_UPDATE; 523 goto doneparsing; 524 } else { 525 fprintf(stderr, "could not read class or type\n"); 526 exit(1); 527 } 528 } 529 region.base = word; 530 region.length = strlen(word); 531 result = dns_rdataclass_fromtext(&rdataclass, ®ion); 532 if (result == ISC_R_SUCCESS) { 533 /* 534 * Now read the type. 535 */ 536 word = nsu_strsep(&cmdline, " \t\r\n"); 537 if (word == NULL || *word == 0) { 538 if (isdelete) { 539 rdataclass = dns_rdataclass_any; 540 rdatatype = dns_rdatatype_any; 541 rdata->flags = DNS_RDATA_UPDATE; 542 goto doneparsing; 543 } else { 544 fprintf(stderr, "could not read type\n"); 545 exit(1); 546 } 547 } 548 region.base = word; 549 region.length = strlen(word); 550 result = dns_rdatatype_fromtext(&rdatatype, ®ion); 551 if (result != ISC_R_SUCCESS) { 552 fprintf(stderr, "'%s' is not a valid type: %s\n", 553 word, isc_result_totext(result)); 554 exit(1); 555 } 556 } else { 557 rdataclass = default_rdataclass; 558 result = dns_rdatatype_fromtext(&rdatatype, ®ion); 559 if (result != ISC_R_SUCCESS) { 560 fprintf(stderr, "'%s' is not a valid class or type: " 561 "%s\n", word, isc_result_totext(result)); 562 exit(1); 563 } 564 } 565 566 parse_rdata(mctx, &cmdline, rdataclass, rdatatype, rdata); 567 568 if (isdelete) { 569 if ((rdata->flags & DNS_RDATA_UPDATE) != 0) 570 rdataclass = dns_rdataclass_any; 571 else 572 rdataclass = dns_rdataclass_none; 573 } else { 574 if ((rdata->flags & DNS_RDATA_UPDATE) != 0) { 575 fprintf(stderr, "could not read rdata\n"); 576 exit(1); 577 } 578 } 579 580 doneparsing: 581 582 rdatalist = isc_mem_get(mctx, sizeof(*rdatalist)); 583 if (rdatalist == NULL) { 584 fprintf(stderr, "memory allocation for rdatalist failed\n"); 585 exit(1); 586 } 587 dns_rdatalist_init(rdatalist); 588 rdatalist->type = rdatatype; 589 rdatalist->rdclass = rdataclass; 590 rdatalist->covers = rdatatype; 591 rdatalist->ttl = (dns_ttl_t)ttl; 592 ISC_LIST_INIT(rdatalist->rdata); 593 ISC_LIST_APPEND(rdatalist->rdata, rdata, link); 594 ISC_LIST_APPEND(usedrdatalists, rdatalist, link); 595 596 rdataset = isc_mem_get(mctx, sizeof(*rdataset)); 597 if (rdataset == NULL) { 598 fprintf(stderr, "memory allocation for rdataset failed\n"); 599 exit(1); 600 } 601 dns_rdataset_init(rdataset); 602 dns_rdatalist_tordataset(rdatalist, rdataset); 603 ISC_LIST_INIT(name->list); 604 ISC_LIST_APPEND(name->list, rdataset, link); 605 } 606 607 static void 608 make_prereq(isc_mem_t *mctx, char *cmdline, isc_boolean_t ispositive, 609 isc_boolean_t isrrset, dns_name_t *name) 610 { 611 isc_result_t result; 612 char *word; 613 isc_textregion_t region; 614 dns_rdataset_t *rdataset = NULL; 615 dns_rdatalist_t *rdatalist = NULL; 616 dns_rdataclass_t rdataclass; 617 dns_rdatatype_t rdatatype; 618 dns_rdata_t *rdata = NULL; 619 620 /* 621 * Read the owner name 622 */ 623 parse_name(&cmdline, name); 624 625 /* 626 * If this is an rrset prereq, read the class or type. 627 */ 628 if (isrrset) { 629 word = nsu_strsep(&cmdline, " \t\r\n"); 630 if (word == NULL || *word == 0) { 631 fprintf(stderr, "could not read class or type\n"); 632 exit(1); 633 } 634 region.base = word; 635 region.length = strlen(word); 636 result = dns_rdataclass_fromtext(&rdataclass, ®ion); 637 if (result == ISC_R_SUCCESS) { 638 /* 639 * Now read the type. 640 */ 641 word = nsu_strsep(&cmdline, " \t\r\n"); 642 if (word == NULL || *word == 0) { 643 fprintf(stderr, "could not read type\n"); 644 exit(1); 645 } 646 region.base = word; 647 region.length = strlen(word); 648 result = dns_rdatatype_fromtext(&rdatatype, ®ion); 649 if (result != ISC_R_SUCCESS) { 650 fprintf(stderr, "invalid type: %s\n", word); 651 exit(1); 652 } 653 } else { 654 rdataclass = default_rdataclass; 655 result = dns_rdatatype_fromtext(&rdatatype, ®ion); 656 if (result != ISC_R_SUCCESS) { 657 fprintf(stderr, "invalid type: %s\n", word); 658 exit(1); 659 } 660 } 661 } else 662 rdatatype = dns_rdatatype_any; 663 664 rdata = isc_mem_get(mctx, sizeof(*rdata)); 665 if (rdata == NULL) { 666 fprintf(stderr, "memory allocation for rdata failed\n"); 667 exit(1); 668 } 669 dns_rdata_init(rdata); 670 671 if (isrrset && ispositive) 672 parse_rdata(mctx, &cmdline, rdataclass, rdatatype, rdata); 673 else 674 rdata->flags = DNS_RDATA_UPDATE; 675 676 rdatalist = isc_mem_get(mctx, sizeof(*rdatalist)); 677 if (rdatalist == NULL) { 678 fprintf(stderr, "memory allocation for rdatalist failed\n"); 679 exit(1); 680 } 681 dns_rdatalist_init(rdatalist); 682 rdatalist->type = rdatatype; 683 if (ispositive) { 684 if (isrrset && rdata->data != NULL) 685 rdatalist->rdclass = rdataclass; 686 else 687 rdatalist->rdclass = dns_rdataclass_any; 688 } else 689 rdatalist->rdclass = dns_rdataclass_none; 690 rdatalist->covers = 0; 691 rdatalist->ttl = 0; 692 rdata->rdclass = rdatalist->rdclass; 693 rdata->type = rdatatype; 694 ISC_LIST_INIT(rdatalist->rdata); 695 ISC_LIST_APPEND(rdatalist->rdata, rdata, link); 696 ISC_LIST_APPEND(usedrdatalists, rdatalist, link); 697 698 rdataset = isc_mem_get(mctx, sizeof(*rdataset)); 699 if (rdataset == NULL) { 700 fprintf(stderr, "memory allocation for rdataset failed\n"); 701 exit(1); 702 } 703 dns_rdataset_init(rdataset); 704 dns_rdatalist_tordataset(rdatalist, rdataset); 705 ISC_LIST_INIT(name->list); 706 ISC_LIST_APPEND(name->list, rdataset, link); 707 } 708 709 static void 710 evaluate_prereq(isc_mem_t *mctx, char *cmdline, dns_name_t *name) { 711 char *word; 712 isc_boolean_t ispositive, isrrset; 713 714 word = nsu_strsep(&cmdline, " \t\r\n"); 715 if (word == NULL || *word == 0) { 716 fprintf(stderr, "could not read operation code\n"); 717 exit(1); 718 } 719 if (strcasecmp(word, "nxdomain") == 0) { 720 ispositive = ISC_FALSE; 721 isrrset = ISC_FALSE; 722 } else if (strcasecmp(word, "yxdomain") == 0) { 723 ispositive = ISC_TRUE; 724 isrrset = ISC_FALSE; 725 } else if (strcasecmp(word, "nxrrset") == 0) { 726 ispositive = ISC_FALSE; 727 isrrset = ISC_TRUE; 728 } else if (strcasecmp(word, "yxrrset") == 0) { 729 ispositive = ISC_TRUE; 730 isrrset = ISC_TRUE; 731 } else { 732 fprintf(stderr, "incorrect operation code: %s\n", word); 733 exit(1); 734 } 735 736 make_prereq(mctx, cmdline, ispositive, isrrset, name); 737 } 738 739 static void 740 setup_tsec(char *keyfile, isc_mem_t *mctx) { 741 dst_key_t *dstkey = NULL; 742 isc_result_t result; 743 dns_tsectype_t tsectype; 744 745 result = dst_key_fromnamedfile(keyfile, NULL, 746 DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx, 747 &dstkey); 748 if (result != ISC_R_SUCCESS) { 749 fprintf(stderr, "could not read key from %s: %s\n", 750 keyfile, isc_result_totext(result)); 751 exit(1); 752 } 753 754 if (dst_key_alg(dstkey) == DST_ALG_HMACMD5) 755 tsectype = dns_tsectype_tsig; 756 else 757 tsectype = dns_tsectype_sig0; 758 759 result = dns_tsec_create(mctx, tsectype, dstkey, &tsec); 760 dst_key_free(&dstkey); 761 if (result != ISC_R_SUCCESS) { 762 fprintf(stderr, "could not create tsec: %s\n", 763 isc_result_totext(result)); 764 exit(1); 765 } 766 } 767