"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.11.23/lib/samples/sample-update.c" (7 Sep 2020, 20096 Bytes) of package /linux/misc/dns/bind9/9.11.23/bind-9.11.23.tar.gz:


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