"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.17.5/lib/samples/sample-async.c" (4 Sep 2020, 9441 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-async.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 <netinet/in.h>
   15 #include <sys/socket.h>
   16 #include <sys/types.h>
   17 #include <unistd.h>
   18 #endif /* ifndef WIN32 */
   19 
   20 #include <stdbool.h>
   21 #include <stdio.h>
   22 #include <stdlib.h>
   23 #include <string.h>
   24 
   25 #include <isc/app.h>
   26 #include <isc/attributes.h>
   27 #include <isc/buffer.h>
   28 #include <isc/commandline.h>
   29 #include <isc/lib.h>
   30 #include <isc/mem.h>
   31 #include <isc/print.h>
   32 #include <isc/sockaddr.h>
   33 #include <isc/socket.h>
   34 #include <isc/task.h>
   35 #include <isc/timer.h>
   36 #include <isc/util.h>
   37 
   38 #include <dns/client.h>
   39 #include <dns/fixedname.h>
   40 #include <dns/lib.h>
   41 #include <dns/name.h>
   42 #include <dns/rdataset.h>
   43 #include <dns/rdatatype.h>
   44 #include <dns/result.h>
   45 
   46 #define MAX_SERVERS 10
   47 #define MAX_QUERIES 100
   48 
   49 static dns_client_t *client = NULL;
   50 static isc_task_t *query_task = NULL;
   51 static isc_appctx_t *query_actx = NULL;
   52 static unsigned int outstanding_queries = 0;
   53 static const char *def_server = "127.0.0.1";
   54 static FILE *fp;
   55 
   56 struct query_trans {
   57     int id;
   58     bool inuse;
   59     dns_rdatatype_t type;
   60     dns_fixedname_t fixedname;
   61     dns_name_t *qname;
   62     dns_namelist_t answerlist;
   63     dns_clientrestrans_t *xid;
   64 };
   65 
   66 static struct query_trans query_array[MAX_QUERIES];
   67 
   68 static isc_result_t
   69 dispatch_query(struct query_trans *trans);
   70 
   71 static void
   72 ctxs_destroy(isc_mem_t **mctxp, isc_appctx_t **actxp, isc_taskmgr_t **taskmgrp,
   73          isc_socketmgr_t **socketmgrp, isc_timermgr_t **timermgrp) {
   74     if (*taskmgrp != NULL) {
   75         isc_taskmgr_destroy(taskmgrp);
   76     }
   77 
   78     if (*timermgrp != NULL) {
   79         isc_timermgr_destroy(timermgrp);
   80     }
   81 
   82     if (*socketmgrp != NULL) {
   83         isc_socketmgr_destroy(socketmgrp);
   84     }
   85 
   86     if (*actxp != NULL) {
   87         isc_appctx_destroy(actxp);
   88     }
   89 
   90     if (*mctxp != NULL) {
   91         isc_mem_destroy(mctxp);
   92     }
   93 }
   94 
   95 static isc_result_t
   96 ctxs_init(isc_mem_t **mctxp, isc_appctx_t **actxp, isc_taskmgr_t **taskmgrp,
   97       isc_socketmgr_t **socketmgrp, isc_timermgr_t **timermgrp) {
   98     isc_result_t result;
   99 
  100     isc_mem_create(mctxp);
  101 
  102     result = isc_appctx_create(*mctxp, actxp);
  103     if (result != ISC_R_SUCCESS) {
  104         goto fail;
  105     }
  106 
  107     result = isc_taskmgr_createinctx(*mctxp, 1, 0, taskmgrp);
  108     if (result != ISC_R_SUCCESS) {
  109         goto fail;
  110     }
  111 
  112     result = isc_socketmgr_createinctx(*mctxp, socketmgrp);
  113     if (result != ISC_R_SUCCESS) {
  114         goto fail;
  115     }
  116 
  117     result = isc_timermgr_createinctx(*mctxp, timermgrp);
  118     if (result != ISC_R_SUCCESS) {
  119         goto fail;
  120     }
  121 
  122     return (ISC_R_SUCCESS);
  123 
  124 fail:
  125     ctxs_destroy(mctxp, actxp, taskmgrp, socketmgrp, timermgrp);
  126 
  127     return (result);
  128 }
  129 
  130 static isc_result_t
  131 printdata(dns_rdataset_t *rdataset, dns_name_t *owner) {
  132     isc_buffer_t target;
  133     isc_result_t result;
  134     isc_region_t r;
  135     char t[4096];
  136 
  137     isc_buffer_init(&target, t, sizeof(t));
  138 
  139     if (!dns_rdataset_isassociated(rdataset)) {
  140         return (ISC_R_SUCCESS);
  141     }
  142     result = dns_rdataset_totext(rdataset, owner, false, false, &target);
  143     if (result != ISC_R_SUCCESS) {
  144         return (result);
  145     }
  146     isc_buffer_usedregion(&target, &r);
  147     printf("  %.*s", (int)r.length, (char *)r.base);
  148 
  149     return (ISC_R_SUCCESS);
  150 }
  151 
  152 static void
  153 process_answer(isc_task_t *task, isc_event_t *event) {
  154     struct query_trans *trans = event->ev_arg;
  155     dns_clientresevent_t *rev = (dns_clientresevent_t *)event;
  156     dns_name_t *name;
  157     dns_rdataset_t *rdataset;
  158     isc_result_t result;
  159 
  160     REQUIRE(task == query_task);
  161     REQUIRE(trans->inuse);
  162     REQUIRE(outstanding_queries > 0);
  163 
  164     printf("answer[%2d]\n", trans->id);
  165 
  166     if (rev->result != ISC_R_SUCCESS) {
  167         printf("  failed: %u(%s)\n", rev->result,
  168                dns_result_totext(rev->result));
  169     }
  170 
  171     for (name = ISC_LIST_HEAD(rev->answerlist); name != NULL;
  172          name = ISC_LIST_NEXT(name, link))
  173     {
  174         for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL;
  175              rdataset = ISC_LIST_NEXT(rdataset, link))
  176         {
  177             (void)printdata(rdataset, name);
  178         }
  179     }
  180 
  181     dns_client_freeresanswer(client, &rev->answerlist);
  182     dns_client_destroyrestrans(&trans->xid);
  183 
  184     isc_event_free(&event);
  185 
  186     trans->inuse = false;
  187     dns_fixedname_invalidate(&trans->fixedname);
  188     trans->qname = NULL;
  189     outstanding_queries--;
  190 
  191     result = dispatch_query(trans);
  192 #if 0  /* for cancel test */
  193     if (result == ISC_R_SUCCESS) {
  194         static int count = 0;
  195 
  196         if ((++count) % 10 == 0) {
  197             dns_client_cancelresolve(trans->xid);
  198         }
  199     }
  200 #endif /* if 0 */
  201     if (result == ISC_R_NOMORE && outstanding_queries == 0) {
  202         isc_app_ctxshutdown(query_actx);
  203     }
  204 }
  205 
  206 static isc_result_t
  207 dispatch_query(struct query_trans *trans) {
  208     isc_result_t result;
  209     unsigned int namelen;
  210     isc_buffer_t b;
  211     char buf[4096]; /* XXX ad hoc constant, but should be enough */
  212     char *cp;
  213 
  214     REQUIRE(trans != NULL);
  215     REQUIRE(!trans->inuse);
  216     REQUIRE(ISC_LIST_EMPTY(trans->answerlist));
  217     REQUIRE(outstanding_queries < MAX_QUERIES);
  218 
  219     /* Construct qname */
  220     cp = fgets(buf, sizeof(buf), fp);
  221     if (cp == NULL) {
  222         return (ISC_R_NOMORE);
  223     }
  224     /* zap NL if any */
  225     if ((cp = strchr(buf, '\n')) != NULL) {
  226         *cp = '\0';
  227     }
  228     namelen = strlen(buf);
  229     isc_buffer_init(&b, buf, namelen);
  230     isc_buffer_add(&b, namelen);
  231     trans->qname = dns_fixedname_initname(&trans->fixedname);
  232     result = dns_name_fromtext(trans->qname, &b, dns_rootname, 0, NULL);
  233     if (result != ISC_R_SUCCESS) {
  234         goto cleanup;
  235     }
  236 
  237     /* Start resolution */
  238     result = dns_client_startresolve(
  239         client, trans->qname, dns_rdataclass_in, trans->type, 0,
  240         query_task, process_answer, trans, &trans->xid);
  241     if (result != ISC_R_SUCCESS) {
  242         goto cleanup;
  243     }
  244 
  245     trans->inuse = true;
  246     outstanding_queries++;
  247 
  248     return (ISC_R_SUCCESS);
  249 
  250 cleanup:
  251     dns_fixedname_invalidate(&trans->fixedname);
  252 
  253     return (result);
  254 }
  255 
  256 ISC_NORETURN static void
  257 usage(void);
  258 
  259 static void
  260 usage(void) {
  261     fprintf(stderr, "usage: sample-async [-s server_address] [-t RR type] "
  262             "input_file\n");
  263 
  264     exit(1);
  265 }
  266 
  267 int
  268 main(int argc, char *argv[]) {
  269     int ch;
  270     isc_textregion_t tr;
  271     isc_mem_t *mctx = NULL;
  272     isc_taskmgr_t *taskmgr = NULL;
  273     isc_socketmgr_t *socketmgr = NULL;
  274     isc_timermgr_t *timermgr = NULL;
  275     int nservers = 0;
  276     const char *serveraddr[MAX_SERVERS];
  277     isc_sockaddr_t sa[MAX_SERVERS];
  278     isc_sockaddrlist_t servers;
  279     dns_rdatatype_t type = dns_rdatatype_a;
  280     struct in_addr inaddr;
  281     isc_result_t result;
  282     int i;
  283 
  284     while ((ch = isc_commandline_parse(argc, argv, "s:t:")) != -1) {
  285         switch (ch) {
  286         case 't':
  287             tr.base = isc_commandline_argument;
  288             tr.length = strlen(isc_commandline_argument);
  289             result = dns_rdatatype_fromtext(&type, &tr);
  290             if (result != ISC_R_SUCCESS) {
  291                 fprintf(stderr, "invalid RRtype: %s\n",
  292                     isc_commandline_argument);
  293                 exit(1);
  294             }
  295             break;
  296         case 's':
  297             if (nservers == MAX_SERVERS) {
  298                 fprintf(stderr, "too many servers (up to %d)\n",
  299                     MAX_SERVERS);
  300                 exit(1);
  301             }
  302             serveraddr[nservers++] =
  303                 (const char *)isc_commandline_argument;
  304             break;
  305         default:
  306             usage();
  307         }
  308     }
  309 
  310     argc -= isc_commandline_index;
  311     argv += isc_commandline_index;
  312     if (argc < 1) {
  313         usage();
  314     }
  315 
  316     if (nservers == 0) {
  317         nservers = 1;
  318         serveraddr[0] = def_server;
  319     }
  320 
  321     for (i = 0; i < MAX_QUERIES; i++) {
  322         query_array[i].id = i;
  323         query_array[i].inuse = false;
  324         query_array[i].type = type;
  325         dns_fixedname_init(&query_array[i].fixedname);
  326         query_array[i].qname = NULL;
  327         ISC_LIST_INIT(query_array[i].answerlist);
  328         query_array[i].xid = NULL;
  329     }
  330 
  331     isc_lib_register();
  332     result = dns_lib_init();
  333     if (result != ISC_R_SUCCESS) {
  334         fprintf(stderr, "dns_lib_init failed: %u\n", result);
  335         exit(1);
  336     }
  337 
  338     result = ctxs_init(&mctx, &query_actx, &taskmgr, &socketmgr, &timermgr);
  339     if (result != ISC_R_SUCCESS) {
  340         fprintf(stderr, "ctx create failed: %u\n", result);
  341         exit(1);
  342     }
  343 
  344     isc_app_ctxstart(query_actx);
  345 
  346     result = dns_client_createx(mctx, query_actx, taskmgr, socketmgr,
  347                     timermgr, 0, &client, NULL, NULL);
  348     if (result != ISC_R_SUCCESS) {
  349         fprintf(stderr, "dns_client_createx failed: %u\n", result);
  350         exit(1);
  351     }
  352 
  353     /* Set nameservers */
  354     ISC_LIST_INIT(servers);
  355     for (i = 0; i < nservers; i++) {
  356         if (inet_pton(AF_INET, serveraddr[i], &inaddr) != 1) {
  357             fprintf(stderr, "failed to parse IPv4 address %s\n",
  358                 serveraddr[i]);
  359             exit(1);
  360         }
  361         isc_sockaddr_fromin(&sa[i], &inaddr, 53);
  362         ISC_LIST_APPEND(servers, &sa[i], link);
  363     }
  364     result = dns_client_setservers(client, dns_rdataclass_in, NULL,
  365                        &servers);
  366     if (result != ISC_R_SUCCESS) {
  367         fprintf(stderr, "set server failed: %u\n", result);
  368         exit(1);
  369     }
  370 
  371     /* Create the main task */
  372     query_task = NULL;
  373     result = isc_task_create(taskmgr, 0, &query_task);
  374     if (result != ISC_R_SUCCESS) {
  375         fprintf(stderr, "failed to create task: %u\n", result);
  376         exit(1);
  377     }
  378 
  379     /* Open input file */
  380     fp = fopen(argv[0], "r");
  381     if (fp == NULL) {
  382         fprintf(stderr, "failed to open input file: %s\n", argv[1]);
  383         exit(1);
  384     }
  385 
  386     /* Dispatch initial queries */
  387     for (i = 0; i < MAX_QUERIES; i++) {
  388         result = dispatch_query(&query_array[i]);
  389         if (result == ISC_R_NOMORE) {
  390             break;
  391         }
  392     }
  393 
  394     /* Start event loop */
  395     isc_app_ctxrun(query_actx);
  396 
  397     /* Sanity check */
  398     for (i = 0; i < MAX_QUERIES; i++) {
  399         INSIST(!query_array[i].inuse);
  400     }
  401 
  402     /* Cleanup */
  403     isc_task_detach(&query_task);
  404     dns_client_destroy(&client);
  405     dns_lib_shutdown();
  406     isc_app_ctxfinish(query_actx);
  407     ctxs_destroy(&mctx, &query_actx, &taskmgr, &socketmgr, &timermgr);
  408 
  409     return (0);
  410 }