1 Star 0 Fork 47

zhangcui/third_party_cares

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
adig.c 22.22 KB
一键复制 编辑 原始数据 按行查看 历史
mamingshuai 提交于 2021-06-02 00:28 +08:00 . update OpenHarmony 2.0 Canary
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827
/* Copyright 1998 by the Massachusetts Institute of Technology.
*
*
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
* fee is hereby granted, provided that the above copyright
* notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting
* documentation, and that the name of M.I.T. not be used in
* advertising or publicity pertaining to distribution of the
* software without specific, written prior permission.
* M.I.T. makes no representations about the suitability of
* this software for any purpose. It is provided "as is"
* without express or implied warranty.
*/
#include "ares_setup.h"
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
#endif
#ifdef HAVE_NETDB_H
# include <netdb.h>
#endif
#ifdef HAVE_ARPA_NAMESER_H
# include <arpa/nameser.h>
#else
# include "nameser.h"
#endif
#ifdef HAVE_ARPA_NAMESER_COMPAT_H
# include <arpa/nameser_compat.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include "ares.h"
#include "ares_dns.h"
#include "ares_getopt.h"
#include "ares_nowarn.h"
#ifndef HAVE_STRDUP
# include "ares_strdup.h"
# define strdup(ptr) ares_strdup(ptr)
#endif
#ifndef HAVE_STRCASECMP
# include "ares_strcasecmp.h"
# define strcasecmp(p1,p2) ares_strcasecmp(p1,p2)
#endif
#ifndef HAVE_STRNCASECMP
# include "ares_strcasecmp.h"
# define strncasecmp(p1,p2,n) ares_strncasecmp(p1,p2,n)
#endif
#ifdef WATT32
#undef WIN32 /* Redefined in MingW headers */
#endif
#ifndef T_SRV
# define T_SRV 33 /* Server selection */
#endif
#ifndef T_NAPTR
# define T_NAPTR 35 /* Naming authority pointer */
#endif
#ifndef T_DS
# define T_DS 43 /* Delegation Signer (RFC4034) */
#endif
#ifndef T_SSHFP
# define T_SSHFP 44 /* SSH Key Fingerprint (RFC4255) */
#endif
#ifndef T_RRSIG
# define T_RRSIG 46 /* Resource Record Signature (RFC4034) */
#endif
#ifndef T_NSEC
# define T_NSEC 47 /* Next Secure (RFC4034) */
#endif
#ifndef T_DNSKEY
# define T_DNSKEY 48 /* DNS Public Key (RFC4034) */
#endif
struct nv {
const char *name;
int value;
};
static const struct nv flags[] = {
{ "usevc", ARES_FLAG_USEVC },
{ "primary", ARES_FLAG_PRIMARY },
{ "igntc", ARES_FLAG_IGNTC },
{ "norecurse", ARES_FLAG_NORECURSE },
{ "stayopen", ARES_FLAG_STAYOPEN },
{ "noaliases", ARES_FLAG_NOALIASES }
};
static const int nflags = sizeof(flags) / sizeof(flags[0]);
static const struct nv classes[] = {
{ "IN", C_IN },
{ "CHAOS", C_CHAOS },
{ "HS", C_HS },
{ "ANY", C_ANY }
};
static const int nclasses = sizeof(classes) / sizeof(classes[0]);
static const struct nv types[] = {
{ "A", T_A },
{ "NS", T_NS },
{ "MD", T_MD },
{ "MF", T_MF },
{ "CNAME", T_CNAME },
{ "SOA", T_SOA },
{ "MB", T_MB },
{ "MG", T_MG },
{ "MR", T_MR },
{ "NULL", T_NULL },
{ "WKS", T_WKS },
{ "PTR", T_PTR },
{ "HINFO", T_HINFO },
{ "MINFO", T_MINFO },
{ "MX", T_MX },
{ "TXT", T_TXT },
{ "RP", T_RP },
{ "AFSDB", T_AFSDB },
{ "X25", T_X25 },
{ "ISDN", T_ISDN },
{ "RT", T_RT },
{ "NSAP", T_NSAP },
{ "NSAP_PTR", T_NSAP_PTR },
{ "SIG", T_SIG },
{ "KEY", T_KEY },
{ "PX", T_PX },
{ "GPOS", T_GPOS },
{ "AAAA", T_AAAA },
{ "LOC", T_LOC },
{ "SRV", T_SRV },
{ "AXFR", T_AXFR },
{ "MAILB", T_MAILB },
{ "MAILA", T_MAILA },
{ "NAPTR", T_NAPTR },
{ "DS", T_DS },
{ "SSHFP", T_SSHFP },
{ "RRSIG", T_RRSIG },
{ "NSEC", T_NSEC },
{ "DNSKEY", T_DNSKEY },
{ "ANY", T_ANY }
};
static const int ntypes = sizeof(types) / sizeof(types[0]);
static const char *opcodes[] = {
"QUERY", "IQUERY", "STATUS", "(reserved)", "NOTIFY",
"(unknown)", "(unknown)", "(unknown)", "(unknown)",
"UPDATEA", "UPDATED", "UPDATEDA", "UPDATEM", "UPDATEMA",
"ZONEINIT", "ZONEREF"
};
static const char *rcodes[] = {
"NOERROR", "FORMERR", "SERVFAIL", "NXDOMAIN", "NOTIMP", "REFUSED",
"(unknown)", "(unknown)", "(unknown)", "(unknown)", "(unknown)",
"(unknown)", "(unknown)", "(unknown)", "(unknown)", "NOCHANGE"
};
static void callback(void *arg, int status, int timeouts,
unsigned char *abuf, int alen);
static const unsigned char *display_question(const unsigned char *aptr,
const unsigned char *abuf,
int alen);
static const unsigned char *display_rr(const unsigned char *aptr,
const unsigned char *abuf, int alen);
static const char *type_name(int type);
static const char *class_name(int dnsclass);
static void usage(void);
static void destroy_addr_list(struct ares_addr_node *head);
static void append_addr_list(struct ares_addr_node **head,
struct ares_addr_node *node);
int main(int argc, char **argv)
{
ares_channel channel;
int c, i, optmask = ARES_OPT_FLAGS, dnsclass = C_IN, type = T_A;
int status, nfds, count;
struct ares_options options;
struct hostent *hostent;
fd_set read_fds, write_fds;
struct timeval *tvp, tv;
struct ares_addr_node *srvr, *servers = NULL;
#ifdef USE_WINSOCK
WORD wVersionRequested = MAKEWORD(USE_WINSOCK,USE_WINSOCK);
WSADATA wsaData;
WSAStartup(wVersionRequested, &wsaData);
#endif
status = ares_library_init(ARES_LIB_INIT_ALL);
if (status != ARES_SUCCESS)
{
fprintf(stderr, "ares_library_init: %s\n", ares_strerror(status));
return 1;
}
options.flags = ARES_FLAG_NOCHECKRESP;
options.servers = NULL;
options.nservers = 0;
while ((c = ares_getopt(argc, argv, "df:s:c:t:T:U:")) != -1)
{
switch (c)
{
case 'd':
#ifdef WATT32
dbug_init();
#endif
break;
case 'f':
/* Add a flag. */
for (i = 0; i < nflags; i++)
{
if (strcmp(flags[i].name, optarg) == 0)
break;
}
if (i < nflags)
options.flags |= flags[i].value;
else
usage();
break;
case 's':
/* User-specified name servers override default ones. */
srvr = malloc(sizeof(struct ares_addr_node));
if (!srvr)
{
fprintf(stderr, "Out of memory!\n");
destroy_addr_list(servers);
return 1;
}
append_addr_list(&servers, srvr);
if (ares_inet_pton(AF_INET, optarg, &srvr->addr.addr4) > 0)
srvr->family = AF_INET;
else if (ares_inet_pton(AF_INET6, optarg, &srvr->addr.addr6) > 0)
srvr->family = AF_INET6;
else
{
hostent = gethostbyname(optarg);
if (!hostent)
{
fprintf(stderr, "adig: server %s not found.\n", optarg);
destroy_addr_list(servers);
return 1;
}
switch (hostent->h_addrtype)
{
case AF_INET:
srvr->family = AF_INET;
memcpy(&srvr->addr.addr4, hostent->h_addr,
sizeof(srvr->addr.addr4));
break;
case AF_INET6:
srvr->family = AF_INET6;
memcpy(&srvr->addr.addr6, hostent->h_addr,
sizeof(srvr->addr.addr6));
break;
default:
fprintf(stderr,
"adig: server %s unsupported address family.\n", optarg);
destroy_addr_list(servers);
return 1;
}
}
/* Notice that calling ares_init_options() without servers in the
* options struct and with ARES_OPT_SERVERS set simultaneously in
* the options mask, results in an initialization with no servers.
* When alternative name servers have been specified these are set
* later calling ares_set_servers() overriding any existing server
* configuration. To prevent initial configuration with default
* servers that will be discarded later, ARES_OPT_SERVERS is set.
* If this flag is not set here the result shall be the same but
* ares_init_options() will do needless work. */
optmask |= ARES_OPT_SERVERS;
break;
case 'c':
/* Set the query class. */
for (i = 0; i < nclasses; i++)
{
if (strcasecmp(classes[i].name, optarg) == 0)
break;
}
if (i < nclasses)
dnsclass = classes[i].value;
else
usage();
break;
case 't':
/* Set the query type. */
for (i = 0; i < ntypes; i++)
{
if (strcasecmp(types[i].name, optarg) == 0)
break;
}
if (i < ntypes)
type = types[i].value;
else
usage();
break;
case 'T':
/* Set the TCP port number. */
if (!ISDIGIT(*optarg))
usage();
options.tcp_port = (unsigned short)strtol(optarg, NULL, 0);
optmask |= ARES_OPT_TCP_PORT;
break;
case 'U':
/* Set the UDP port number. */
if (!ISDIGIT(*optarg))
usage();
options.udp_port = (unsigned short)strtol(optarg, NULL, 0);
optmask |= ARES_OPT_UDP_PORT;
break;
}
}
argc -= optind;
argv += optind;
if (argc == 0)
usage();
status = ares_init_options(&channel, &options, optmask);
if (status != ARES_SUCCESS)
{
fprintf(stderr, "ares_init_options: %s\n",
ares_strerror(status));
return 1;
}
if(servers)
{
status = ares_set_servers(channel, servers);
destroy_addr_list(servers);
if (status != ARES_SUCCESS)
{
fprintf(stderr, "ares_init_options: %s\n",
ares_strerror(status));
return 1;
}
}
/* Initiate the queries, one per command-line argument. If there is
* only one query to do, supply NULL as the callback argument;
* otherwise, supply the query name as an argument so we can
* distinguish responses for the user when printing them out.
*/
if (argc == 1)
ares_query(channel, *argv, dnsclass, type, callback, (char *) NULL);
else
{
for (; *argv; argv++)
ares_query(channel, *argv, dnsclass, type, callback, *argv);
}
/* Wait for all queries to complete. */
for (;;)
{
FD_ZERO(&read_fds);
FD_ZERO(&write_fds);
nfds = ares_fds(channel, &read_fds, &write_fds);
if (nfds == 0)
break;
tvp = ares_timeout(channel, NULL, &tv);
count = select(nfds, &read_fds, &write_fds, NULL, tvp);
if (count < 0 && (status = SOCKERRNO) != EINVAL)
{
printf("select fail: %d", status);
return 1;
}
ares_process(channel, &read_fds, &write_fds);
}
ares_destroy(channel);
ares_library_cleanup();
#ifdef USE_WINSOCK
WSACleanup();
#endif
return 0;
}
static void callback(void *arg, int status, int timeouts,
unsigned char *abuf, int alen)
{
char *name = (char *) arg;
int id, qr, opcode, aa, tc, rd, ra, rcode;
unsigned int qdcount, ancount, nscount, arcount, i;
const unsigned char *aptr;
(void) timeouts;
/* Display the query name if given. */
if (name)
printf("Answer for query %s:\n", name);
/* Display an error message if there was an error, but only stop if
* we actually didn't get an answer buffer.
*/
if (status != ARES_SUCCESS)
{
printf("%s\n", ares_strerror(status));
if (!abuf)
return;
}
/* Won't happen, but check anyway, for safety. */
if (alen < HFIXEDSZ)
return;
/* Parse the answer header. */
id = DNS_HEADER_QID(abuf);
qr = DNS_HEADER_QR(abuf);
opcode = DNS_HEADER_OPCODE(abuf);
aa = DNS_HEADER_AA(abuf);
tc = DNS_HEADER_TC(abuf);
rd = DNS_HEADER_RD(abuf);
ra = DNS_HEADER_RA(abuf);
rcode = DNS_HEADER_RCODE(abuf);
qdcount = DNS_HEADER_QDCOUNT(abuf);
ancount = DNS_HEADER_ANCOUNT(abuf);
nscount = DNS_HEADER_NSCOUNT(abuf);
arcount = DNS_HEADER_ARCOUNT(abuf);
/* Display the answer header. */
printf("id: %d\n", id);
printf("flags: %s%s%s%s%s\n",
qr ? "qr " : "",
aa ? "aa " : "",
tc ? "tc " : "",
rd ? "rd " : "",
ra ? "ra " : "");
printf("opcode: %s\n", opcodes[opcode]);
printf("rcode: %s\n", rcodes[rcode]);
/* Display the questions. */
printf("Questions:\n");
aptr = abuf + HFIXEDSZ;
for (i = 0; i < qdcount; i++)
{
aptr = display_question(aptr, abuf, alen);
if (aptr == NULL)
return;
}
/* Display the answers. */
printf("Answers:\n");
for (i = 0; i < ancount; i++)
{
aptr = display_rr(aptr, abuf, alen);
if (aptr == NULL)
return;
}
/* Display the NS records. */
printf("NS records:\n");
for (i = 0; i < nscount; i++)
{
aptr = display_rr(aptr, abuf, alen);
if (aptr == NULL)
return;
}
/* Display the additional records. */
printf("Additional records:\n");
for (i = 0; i < arcount; i++)
{
aptr = display_rr(aptr, abuf, alen);
if (aptr == NULL)
return;
}
}
static const unsigned char *display_question(const unsigned char *aptr,
const unsigned char *abuf,
int alen)
{
char *name;
int type, dnsclass, status;
long len;
/* Parse the question name. */
status = ares_expand_name(aptr, abuf, alen, &name, &len);
if (status != ARES_SUCCESS)
return NULL;
aptr += len;
/* Make sure there's enough data after the name for the fixed part
* of the question.
*/
if (aptr + QFIXEDSZ > abuf + alen)
{
ares_free_string(name);
return NULL;
}
/* Parse the question type and class. */
type = DNS_QUESTION_TYPE(aptr);
dnsclass = DNS_QUESTION_CLASS(aptr);
aptr += QFIXEDSZ;
/* Display the question, in a format sort of similar to how we will
* display RRs.
*/
printf("\t%-15s.\t", name);
if (dnsclass != C_IN)
printf("\t%s", class_name(dnsclass));
printf("\t%s\n", type_name(type));
ares_free_string(name);
return aptr;
}
static const unsigned char *display_rr(const unsigned char *aptr,
const unsigned char *abuf, int alen)
{
const unsigned char *p;
int type, dnsclass, ttl, dlen, status;
long len;
char addr[46];
union {
unsigned char * as_uchar;
char * as_char;
} name;
/* Parse the RR name. */
status = ares_expand_name(aptr, abuf, alen, &name.as_char, &len);
if (status != ARES_SUCCESS)
return NULL;
aptr += len;
/* Make sure there is enough data after the RR name for the fixed
* part of the RR.
*/
if (aptr + RRFIXEDSZ > abuf + alen)
{
ares_free_string(name.as_char);
return NULL;
}
/* Parse the fixed part of the RR, and advance to the RR data
* field. */
type = DNS_RR_TYPE(aptr);
dnsclass = DNS_RR_CLASS(aptr);
ttl = DNS_RR_TTL(aptr);
dlen = DNS_RR_LEN(aptr);
aptr += RRFIXEDSZ;
if (aptr + dlen > abuf + alen)
{
ares_free_string(name.as_char);
return NULL;
}
/* Display the RR name, class, and type. */
printf("\t%-15s.\t%d", name.as_char, ttl);
if (dnsclass != C_IN)
printf("\t%s", class_name(dnsclass));
printf("\t%s", type_name(type));
ares_free_string(name.as_char);
/* Display the RR data. Don't touch aptr. */
switch (type)
{
case T_CNAME:
case T_MB:
case T_MD:
case T_MF:
case T_MG:
case T_MR:
case T_NS:
case T_PTR:
/* For these types, the RR data is just a domain name. */
status = ares_expand_name(aptr, abuf, alen, &name.as_char, &len);
if (status != ARES_SUCCESS)
return NULL;
printf("\t%s.", name.as_char);
ares_free_string(name.as_char);
break;
case T_HINFO:
/* The RR data is two length-counted character strings. */
p = aptr;
len = *p;
if (p + len + 1 > aptr + dlen)
return NULL;
status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
if (status != ARES_SUCCESS)
return NULL;
printf("\t%s", name.as_char);
ares_free_string(name.as_char);
p += len;
len = *p;
if (p + len + 1 > aptr + dlen)
return NULL;
status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
if (status != ARES_SUCCESS)
return NULL;
printf("\t%s", name.as_char);
ares_free_string(name.as_char);
break;
case T_MINFO:
/* The RR data is two domain names. */
p = aptr;
status = ares_expand_name(p, abuf, alen, &name.as_char, &len);
if (status != ARES_SUCCESS)
return NULL;
printf("\t%s.", name.as_char);
ares_free_string(name.as_char);
p += len;
status = ares_expand_name(p, abuf, alen, &name.as_char, &len);
if (status != ARES_SUCCESS)
return NULL;
printf("\t%s.", name.as_char);
ares_free_string(name.as_char);
break;
case T_MX:
/* The RR data is two bytes giving a preference ordering, and
* then a domain name.
*/
if (dlen < 2)
return NULL;
printf("\t%d", (int)DNS__16BIT(aptr));
status = ares_expand_name(aptr + 2, abuf, alen, &name.as_char, &len);
if (status != ARES_SUCCESS)
return NULL;
printf("\t%s.", name.as_char);
ares_free_string(name.as_char);
break;
case T_SOA:
/* The RR data is two domain names and then five four-byte
* numbers giving the serial number and some timeouts.
*/
p = aptr;
status = ares_expand_name(p, abuf, alen, &name.as_char, &len);
if (status != ARES_SUCCESS)
return NULL;
printf("\t%s.\n", name.as_char);
ares_free_string(name.as_char);
p += len;
status = ares_expand_name(p, abuf, alen, &name.as_char, &len);
if (status != ARES_SUCCESS)
return NULL;
printf("\t\t\t\t\t\t%s.\n", name.as_char);
ares_free_string(name.as_char);
p += len;
if (p + 20 > aptr + dlen)
return NULL;
printf("\t\t\t\t\t\t( %u %u %u %u %u )",
DNS__32BIT(p), DNS__32BIT(p+4),
DNS__32BIT(p+8), DNS__32BIT(p+12),
DNS__32BIT(p+16));
break;
case T_TXT:
/* The RR data is one or more length-counted character
* strings. */
p = aptr;
while (p < aptr + dlen)
{
len = *p;
if (p + len + 1 > aptr + dlen)
return NULL;
status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
if (status != ARES_SUCCESS)
return NULL;
printf("\t%s", name.as_char);
ares_free_string(name.as_char);
p += len;
}
break;
case T_A:
/* The RR data is a four-byte Internet address. */
if (dlen != 4)
return NULL;
printf("\t%s", ares_inet_ntop(AF_INET,aptr,addr,sizeof(addr)));
break;
case T_AAAA:
/* The RR data is a 16-byte IPv6 address. */
if (dlen != 16)
return NULL;
printf("\t%s", ares_inet_ntop(AF_INET6,aptr,addr,sizeof(addr)));
break;
case T_WKS:
/* Not implemented yet */
break;
case T_SRV:
/* The RR data is three two-byte numbers representing the
* priority, weight, and port, followed by a domain name.
*/
printf("\t%d", (int)DNS__16BIT(aptr));
printf(" %d", (int)DNS__16BIT(aptr + 2));
printf(" %d", (int)DNS__16BIT(aptr + 4));
status = ares_expand_name(aptr + 6, abuf, alen, &name.as_char, &len);
if (status != ARES_SUCCESS)
return NULL;
printf("\t%s.", name.as_char);
ares_free_string(name.as_char);
break;
case T_NAPTR:
printf("\t%d", (int)DNS__16BIT(aptr)); /* order */
printf(" %d\n", (int)DNS__16BIT(aptr + 2)); /* preference */
p = aptr + 4;
status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
if (status != ARES_SUCCESS)
return NULL;
printf("\t\t\t\t\t\t%s\n", name.as_char);
ares_free_string(name.as_char);
p += len;
status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
if (status != ARES_SUCCESS)
return NULL;
printf("\t\t\t\t\t\t%s\n", name.as_char);
ares_free_string(name.as_char);
p += len;
status = ares_expand_string(p, abuf, alen, &name.as_uchar, &len);
if (status != ARES_SUCCESS)
return NULL;
printf("\t\t\t\t\t\t%s\n", name.as_char);
ares_free_string(name.as_char);
p += len;
status = ares_expand_name(p, abuf, alen, &name.as_char, &len);
if (status != ARES_SUCCESS)
return NULL;
printf("\t\t\t\t\t\t%s", name.as_char);
ares_free_string(name.as_char);
break;
case T_DS:
case T_SSHFP:
case T_RRSIG:
case T_NSEC:
case T_DNSKEY:
printf("\t[RR type parsing unavailable]");
break;
default:
printf("\t[Unknown RR; cannot parse]");
break;
}
printf("\n");
return aptr + dlen;
}
static const char *type_name(int type)
{
int i;
for (i = 0; i < ntypes; i++)
{
if (types[i].value == type)
return types[i].name;
}
return "(unknown)";
}
static const char *class_name(int dnsclass)
{
int i;
for (i = 0; i < nclasses; i++)
{
if (classes[i].value == dnsclass)
return classes[i].name;
}
return "(unknown)";
}
static void usage(void)
{
fprintf(stderr, "usage: adig [-h] [-d] [-f flag] [-s server] [-c class] "
"[-t type] [-T|U port] name ...\n");
exit(1);
}
static void destroy_addr_list(struct ares_addr_node *head)
{
while(head)
{
struct ares_addr_node *detached = head;
head = head->next;
free(detached);
}
}
static void append_addr_list(struct ares_addr_node **head,
struct ares_addr_node *node)
{
struct ares_addr_node *last;
node->next = NULL;
if(*head)
{
last = *head;
while(last->next)
last = last->next;
last->next = node;
}
else
*head = node;
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/zhang-cui11/third_party_cares.git
git@gitee.com:zhang-cui11/third_party_cares.git
zhang-cui11
third_party_cares
third_party_cares
master

搜索帮助