quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

ahost.c (8314B)


      1 /* MIT License
      2  *
      3  * Copyright (c) 1998 Massachusetts Institute of Technology
      4  * Copyright (c) The c-ares project and its contributors
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a copy
      7  * of this software and associated documentation files (the "Software"), to deal
      8  * in the Software without restriction, including without limitation the rights
      9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     10  * copies of the Software, and to permit persons to whom the Software is
     11  * furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice (including the next
     14  * paragraph) shall be included in all copies or substantial portions of the
     15  * Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     23  * SOFTWARE.
     24  *
     25  * SPDX-License-Identifier: MIT
     26  */
     27 
     28 #include "ares_setup.h"
     29 
     30 #if !defined(_WIN32) || defined(WATT32)
     31 #  include <netinet/in.h>
     32 #  include <arpa/inet.h>
     33 #  include <netdb.h>
     34 #endif
     35 
     36 #ifdef HAVE_STRINGS_H
     37 #  include <strings.h>
     38 #endif
     39 
     40 #include "ares.h"
     41 #include "ares_dns.h"
     42 #include "ares_getopt.h"
     43 #include "ares_ipv6.h"
     44 
     45 #include "ares_str.h"
     46 
     47 static void callback(void *arg, int status, int timeouts, struct hostent *host);
     48 static void ai_callback(void *arg, int status, int timeouts,
     49                         struct ares_addrinfo *result);
     50 static void usage(void);
     51 static void print_help_info_ahost(void);
     52 
     53 int         main(int argc, char **argv)
     54 {
     55   struct ares_options  options;
     56   int                  optmask = 0;
     57   ares_channel_t      *channel;
     58   int                  status;
     59   int                  nfds;
     60   int                  c;
     61   int                  addr_family = AF_UNSPEC;
     62   fd_set               read_fds;
     63   fd_set               write_fds;
     64   struct timeval      *tvp;
     65   struct timeval       tv;
     66   struct in_addr       addr4;
     67   struct ares_in6_addr addr6;
     68   ares_getopt_state_t  state;
     69   char                *servers = NULL;
     70 
     71 #ifdef USE_WINSOCK
     72   WORD    wVersionRequested = MAKEWORD(USE_WINSOCK, USE_WINSOCK);
     73   WSADATA wsaData;
     74   WSAStartup(wVersionRequested, &wsaData);
     75 #endif
     76 
     77   memset(&options, 0, sizeof(options));
     78 
     79   status = ares_library_init(ARES_LIB_INIT_ALL);
     80   if (status != ARES_SUCCESS) {
     81     fprintf(stderr, "ares_library_init: %s\n", ares_strerror(status));
     82     return 1;
     83   }
     84 
     85   ares_getopt_init(&state, argc, (const char * const *)argv);
     86   while ((c = ares_getopt(&state, "dt:h?D:s:")) != -1) {
     87     switch (c) {
     88       case 'd':
     89 #ifdef WATT32
     90         dbug_init();
     91 #endif
     92         break;
     93       case 'D':
     94         optmask |= ARES_OPT_DOMAINS;
     95         options.ndomains++;
     96         options.domains = (char **)realloc(
     97           options.domains, (size_t)options.ndomains * sizeof(char *));
     98         options.domains[options.ndomains - 1] = strdup(state.optarg);
     99         break;
    100       case 't':
    101         if (ares_strcaseeq(state.optarg, "a")) {
    102           addr_family = AF_INET;
    103         } else if (ares_strcaseeq(state.optarg, "aaaa")) {
    104           addr_family = AF_INET6;
    105         } else if (ares_strcaseeq(state.optarg, "u")) {
    106           addr_family = AF_UNSPEC;
    107         } else {
    108           usage();
    109         }
    110         break;
    111       case 's':
    112         if (state.optarg == NULL) {
    113           fprintf(stderr, "%s", "missing servers");
    114           usage();
    115           break;
    116         }
    117         if (servers) {
    118           free(servers);
    119         }
    120         servers = strdup(state.optarg);
    121         break;
    122       case 'h':
    123       case '?':
    124         print_help_info_ahost();
    125         break;
    126       default:
    127         usage();
    128         break;
    129     }
    130   }
    131 
    132   argc -= state.optind;
    133   argv += state.optind;
    134   if (argc < 1) {
    135     usage();
    136   }
    137 
    138   status = ares_init_options(&channel, &options, optmask);
    139   if (status != ARES_SUCCESS) {
    140     free(servers);
    141     fprintf(stderr, "ares_init: %s\n", ares_strerror(status));
    142     return 1;
    143   }
    144 
    145   if (servers) {
    146     status = ares_set_servers_csv(channel, servers);
    147     if (status != ARES_SUCCESS) {
    148       fprintf(stderr, "ares_set_serveres_csv: %s\n", ares_strerror(status));
    149       free(servers);
    150       usage();
    151       return 1;
    152     }
    153     free(servers);
    154   }
    155 
    156   /* Initiate the queries, one per command-line argument. */
    157   for (; *argv; argv++) {
    158     if (ares_inet_pton(AF_INET, *argv, &addr4) == 1) {
    159       ares_gethostbyaddr(channel, &addr4, sizeof(addr4), AF_INET, callback,
    160                          *argv);
    161     } else if (ares_inet_pton(AF_INET6, *argv, &addr6) == 1) {
    162       ares_gethostbyaddr(channel, &addr6, sizeof(addr6), AF_INET6, callback,
    163                          *argv);
    164     } else {
    165       struct ares_addrinfo_hints hints;
    166       memset(&hints, 0, sizeof(hints));
    167       hints.ai_family = addr_family;
    168       ares_getaddrinfo(channel, *argv, NULL, &hints, ai_callback, *argv);
    169     }
    170   }
    171 
    172   /* Wait for all queries to complete. */
    173   for (;;) {
    174     int res;
    175     FD_ZERO(&read_fds);
    176     FD_ZERO(&write_fds);
    177     nfds = ares_fds(channel, &read_fds, &write_fds);
    178     if (nfds == 0) {
    179       break;
    180     }
    181     tvp = ares_timeout(channel, NULL, &tv);
    182     if (tvp == NULL) {
    183       break;
    184     }
    185     res = select(nfds, &read_fds, &write_fds, NULL, tvp);
    186     if (-1 == res) {
    187       break;
    188     }
    189     ares_process(channel, &read_fds, &write_fds);
    190   }
    191 
    192   ares_destroy(channel);
    193 
    194   ares_library_cleanup();
    195 
    196 #ifdef USE_WINSOCK
    197   WSACleanup();
    198 #endif
    199 
    200   return 0;
    201 }
    202 
    203 static void callback(void *arg, int status, int timeouts, struct hostent *host)
    204 {
    205   char **p;
    206 
    207   (void)timeouts;
    208 
    209   if (status != ARES_SUCCESS) {
    210     fprintf(stderr, "%s: %s\n", (char *)arg, ares_strerror(status));
    211     return;
    212   }
    213 
    214   for (p = host->h_addr_list; *p; p++) {
    215     char addr_buf[46] = "??";
    216 
    217     ares_inet_ntop(host->h_addrtype, *p, addr_buf, sizeof(addr_buf));
    218     printf("%-32s\t%s", host->h_name, addr_buf);
    219     puts("");
    220   }
    221 }
    222 
    223 static void ai_callback(void *arg, int status, int timeouts,
    224                         struct ares_addrinfo *result)
    225 {
    226   struct ares_addrinfo_node *node = NULL;
    227   (void)timeouts;
    228 
    229 
    230   if (status != ARES_SUCCESS) {
    231     fprintf(stderr, "%s: %s\n", (char *)arg, ares_strerror(status));
    232     return;
    233   }
    234 
    235   for (node = result->nodes; node != NULL; node = node->ai_next) {
    236     char        addr_buf[64] = "";
    237     const void *ptr          = NULL;
    238     if (node->ai_family == AF_INET) {
    239       const struct sockaddr_in *in_addr =
    240         (const struct sockaddr_in *)((void *)node->ai_addr);
    241       ptr = &in_addr->sin_addr;
    242     } else if (node->ai_family == AF_INET6) {
    243       const struct sockaddr_in6 *in_addr =
    244         (const struct sockaddr_in6 *)((void *)node->ai_addr);
    245       ptr = &in_addr->sin6_addr;
    246     } else {
    247       continue;
    248     }
    249     ares_inet_ntop(node->ai_family, ptr, addr_buf, sizeof(addr_buf));
    250     printf("%-32s\t%s\n", result->name, addr_buf);
    251   }
    252 
    253   ares_freeaddrinfo(result);
    254 }
    255 
    256 static void usage(void)
    257 {
    258   fprintf(stderr, "usage: ahost [-h] [-d] [[-D {domain}] ...] [-s {server}] "
    259                   "[-t {a|aaaa|u}] {host|addr} ...\n");
    260   exit(1);
    261 }
    262 
    263 /* Information from the man page. Formatting taken from man -h */
    264 static void print_help_info_ahost(void)
    265 {
    266   /* Split due to maximum c89 string literal of 509 bytes */
    267   printf("ahost, version %s\n\n", ARES_VERSION_STR);
    268   printf(
    269     "usage: ahost [-h] [-d] [-D domain] [-s server] [-t a|aaaa|u] host|addr "
    270     "...\n\n");
    271   printf(
    272     "  -h : Display this help and exit.\n"
    273     "  -d : Print some extra debugging output.\n\n"
    274     "  -D domain : Specify the domain to search instead of using the default "
    275     "values\n");
    276   printf(
    277     "  -s server : Connect to the specified DNS server, instead of the\n"
    278     "              system's default one(s). Servers are tried in round-robin,\n"
    279     "              if the previous one failed.\n"
    280     "  -t type   : If type is \"a\", print the A record.\n");
    281   printf(
    282     "              If type is \"aaaa\", print the AAAA record.\n"
    283     "              If type is \"u\" (default), print both A and AAAA records.\n"
    284     "\n");
    285   exit(0);
    286 }