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