ahost should use ares_getaddrinfo() these days (#669)

ahost wasn't printing both ipv4 and ipv6 addresses. This day and age, it really should.

This PR also adds the ability to specify the servers to use.

Fix By: Brad House (@bradh352)
pull/673/head
Brad House 1 year ago committed by GitHub
parent eebfe0c15e
commit 44c59a91c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 9
      docs/ahost.1
  2. 112
      src/tools/ahost.c

@ -39,11 +39,14 @@ Print some extra debugging output.
Display this help and exit. Display this help and exit.
.TP .TP
\fB\-t\fR type \fB\-t\fR type
If type is "a", print the A record (default). If type is "a", print the A record.
If type is "aaaa", print the AAAA record. If type is "aaaa", print the AAAA record.
If type is "u", look for either AAAA or A record (in that order). If type is "u", look for both AAAA and A records (default).
.TP .TP
\fB\-s\fR \fIdomain\fP \fB\-s\fR server
Set the server list to use for DNS lookups.
.TP
\fB\-D\fR \fIdomain\fP
Specify the \fIdomain\fP to search instead of using the default values from Specify the \fIdomain\fP to search instead of using the default values from
.br .br
/etc/resolv.conf. This option only has an effect on platforms that use /etc/resolv.conf. This option only has an effect on platforms that use

@ -58,6 +58,8 @@
#endif #endif
static void callback(void *arg, int status, int timeouts, struct hostent *host); static void callback(void *arg, int status, int timeouts, struct hostent *host);
static void ai_callback(void *arg, int status, int timeouts,
struct ares_addrinfo *result);
static void usage(void); static void usage(void);
static void print_help_info_ahost(void); static void print_help_info_ahost(void);
@ -69,7 +71,7 @@ int main(int argc, char **argv)
int status; int status;
int nfds; int nfds;
int c; int c;
int addr_family = AF_INET; int addr_family = AF_UNSPEC;
fd_set read_fds; fd_set read_fds;
fd_set write_fds; fd_set write_fds;
struct timeval *tvp; struct timeval *tvp;
@ -77,6 +79,7 @@ int main(int argc, char **argv)
struct in_addr addr4; struct in_addr addr4;
struct ares_in6_addr addr6; struct ares_in6_addr addr6;
ares_getopt_state_t state; ares_getopt_state_t state;
char *servers = NULL;
#ifdef USE_WINSOCK #ifdef USE_WINSOCK
WORD wVersionRequested = MAKEWORD(USE_WINSOCK, USE_WINSOCK); WORD wVersionRequested = MAKEWORD(USE_WINSOCK, USE_WINSOCK);
@ -93,14 +96,14 @@ int main(int argc, char **argv)
} }
ares_getopt_init(&state, argc, (const char **)argv); ares_getopt_init(&state, argc, (const char **)argv);
while ((c = ares_getopt(&state, "dt:h?s:")) != -1) { while ((c = ares_getopt(&state, "dt:h?D:s:")) != -1) {
switch (c) { switch (c) {
case 'd': case 'd':
#ifdef WATT32 #ifdef WATT32
dbug_init(); dbug_init();
#endif #endif
break; break;
case 's': case 'D':
optmask |= ARES_OPT_DOMAINS; optmask |= ARES_OPT_DOMAINS;
options.ndomains++; options.ndomains++;
options.domains = (char **)realloc( options.domains = (char **)realloc(
@ -118,9 +121,18 @@ int main(int argc, char **argv)
usage(); usage();
} }
break; break;
case 'h': case 's':
print_help_info_ahost(); if (state.optarg == NULL) {
fprintf(stderr, "%s", "missing servers");
usage();
break;
}
if (servers) {
free(servers);
}
servers = strdup(state.optarg);
break; break;
case 'h':
case '?': case '?':
print_help_info_ahost(); print_help_info_ahost();
break; break;
@ -138,10 +150,22 @@ int main(int argc, char **argv)
status = ares_init_options(&channel, &options, optmask); status = ares_init_options(&channel, &options, optmask);
if (status != ARES_SUCCESS) { if (status != ARES_SUCCESS) {
free(servers);
fprintf(stderr, "ares_init: %s\n", ares_strerror(status)); fprintf(stderr, "ares_init: %s\n", ares_strerror(status));
return 1; return 1;
} }
if (servers) {
status = ares_set_servers_csv(channel, servers);
if (status != ARES_SUCCESS) {
fprintf(stderr, "ares_set_serveres_csv: %s\n", ares_strerror(status));
free(servers);
usage();
return 1;
}
free(servers);
}
/* Initiate the queries, one per command-line argument. */ /* Initiate the queries, one per command-line argument. */
for (; *argv; argv++) { for (; *argv; argv++) {
if (ares_inet_pton(AF_INET, *argv, &addr4) == 1) { if (ares_inet_pton(AF_INET, *argv, &addr4) == 1) {
@ -151,7 +175,10 @@ int main(int argc, char **argv)
ares_gethostbyaddr(channel, &addr6, sizeof(addr6), AF_INET6, callback, ares_gethostbyaddr(channel, &addr6, sizeof(addr6), AF_INET6, callback,
*argv); *argv);
} else { } else {
ares_gethostbyname(channel, *argv, addr_family, callback, *argv); struct ares_addrinfo_hints hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = addr_family;
ares_getaddrinfo(channel, *argv, NULL, &hints, ai_callback, *argv);
} }
} }
@ -202,25 +229,47 @@ static void callback(void *arg, int status, int timeouts, struct hostent *host)
ares_inet_ntop(host->h_addrtype, *p, addr_buf, sizeof(addr_buf)); ares_inet_ntop(host->h_addrtype, *p, addr_buf, sizeof(addr_buf));
printf("%-32s\t%s", host->h_name, addr_buf); printf("%-32s\t%s", host->h_name, addr_buf);
#if 0
if (host->h_aliases[0])
{
int i;
printf (", Aliases: ");
for (i = 0; host->h_aliases[i]; i++)
printf("%s ", host->h_aliases[i]);
}
#endif
puts(""); puts("");
} }
} }
static void ai_callback(void *arg, int status, int timeouts,
struct ares_addrinfo *result)
{
struct ares_addrinfo_node *node = NULL;
(void)timeouts;
if (status != ARES_SUCCESS) {
fprintf(stderr, "%s: %s\n", (char *)arg, ares_strerror(status));
return;
}
for (node = result->nodes; node != NULL; node = node->ai_next) {
char addr_buf[64] = "";
const void *ptr = NULL;
if (node->ai_family == AF_INET) {
struct sockaddr_in *in_addr =
(struct sockaddr_in *)((void *)node->ai_addr);
ptr = &in_addr->sin_addr;
} else if (node->ai_family == AF_INET6) {
struct sockaddr_in6 *in_addr =
(struct sockaddr_in6 *)((void *)node->ai_addr);
ptr = &in_addr->sin6_addr;
} else {
continue;
}
ares_inet_ntop(node->ai_family, ptr, addr_buf, sizeof(addr_buf));
printf("%-32s\t%s\n", result->name, addr_buf);
}
ares_freeaddrinfo(result);
}
static void usage(void) static void usage(void)
{ {
fprintf( fprintf(stderr, "usage: ahost [-h] [-d] [[-D {domain}] ...] [-s {server}] "
stderr, "[-t {a|aaaa|u}] {host|addr} ...\n");
"usage: ahost [-h] [-d] [-s {domain}] [-t {a|aaaa|u}] {host|addr} ...\n");
exit(1); exit(1);
} }
@ -229,19 +278,18 @@ static void print_help_info_ahost(void)
{ {
printf("ahost, version %s\n\n", ARES_VERSION_STR); printf("ahost, version %s\n\n", ARES_VERSION_STR);
printf( printf(
"usage: ahost [-h] [-d] [[-s domain] ...] [-t a|aaaa|u] host|addr ...\n\n" "usage: ahost [-h] [-d] [-D domain] [-s server] [-t a|aaaa|u] host|addr "
" h : Display this help and exit.\n" "...\n\n"
" d : Print some extra debugging output.\n\n" " -h : Display this help and exit.\n"
" s domain : Specify the domain to search instead of using the default " " -d : Print some extra debugging output.\n\n"
" -D domain : Specify the domain to search instead of using the default "
"values\n" "values\n"
" from /etc/resolv.conf. This option only has an effect on\n" " -s server : Connect to the specified DNS server, instead of the\n"
" platforms that use /etc/resolv.conf for DNS " " system's default one(s). Servers are tried in round-robin,\n"
"configuration;\n" " if the previous one failed.\n"
" it has no effect on other platforms (such as Win32 or " " -t type : If type is \"a\", print the A record.\n"
"Android).\n\n" " If type is \"aaaa\", print the AAAA record.\n"
" t type : If type is \"a\", print the A record (default).\n" " If type is \"u\" (default), print both A and AAAA records.\n"
" If type is \"aaaa\", print the AAAA record.\n" "\n");
" If type is \"u\", look for either AAAA or A record (in "
"that order).\n\n");
exit(0); exit(0);
} }

Loading…
Cancel
Save