"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.17.5/lib/samples/sample-update.c" (4 Sep 2020, 19494 Bytes) of package /linux/misc/dns/bind9/9.17.5/bind-9.17.5.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "sample-update.c" see the Fossies "Dox" file reference documentation.

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