Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

ares.h File Reference

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ares_options

Defines

#define ARES_SUCCESS   0
#define ARES_ENODATA   1
#define ARES_EFORMERR   2
#define ARES_ESERVFAIL   3
#define ARES_ENOTFOUND   4
#define ARES_ENOTIMP   5
#define ARES_EREFUSED   6
#define ARES_EBADQUERY   7
#define ARES_EBADNAME   8
#define ARES_EBADFAMILY   9
#define ARES_EBADRESP   10
#define ARES_ECONNREFUSED   11
#define ARES_ETIMEOUT   12
#define ARES_EOF   13
#define ARES_EFILE   14
#define ARES_ENOMEM   15
#define ARES_EDESTRUCTION   16
#define ARES_FLAG_USEVC   (1 << 0)
#define ARES_FLAG_PRIMARY   (1 << 1)
#define ARES_FLAG_IGNTC   (1 << 2)
#define ARES_FLAG_NORECURSE   (1 << 3)
#define ARES_FLAG_STAYOPEN   (1 << 4)
#define ARES_FLAG_NOSEARCH   (1 << 5)
#define ARES_FLAG_NOALIASES   (1 << 6)
#define ARES_FLAG_NOCHECKRESP   (1 << 7)
#define ARES_OPT_FLAGS   (1 << 0)
#define ARES_OPT_TIMEOUT   (1 << 1)
#define ARES_OPT_TRIES   (1 << 2)
#define ARES_OPT_NDOTS   (1 << 3)
#define ARES_OPT_UDP_PORT   (1 << 4)
#define ARES_OPT_TCP_PORT   (1 << 5)
#define ARES_OPT_SERVERS   (1 << 6)
#define ARES_OPT_DOMAINS   (1 << 7)
#define ARES_OPT_LOOKUPS   (1 << 8)

Typedefs

typedef ares_channeldataares_channel
typedef void(* ares_callback )(void *arg, int status, unsigned char *abuf, int alen)
typedef void(* ares_host_callback )(void *arg, int status, struct hostent *hostent)

Functions

int ares_init (ares_channel *channelptr)
int ares_init_options (ares_channel *channelptr, struct ares_options *options, int optmask)
void ares_destroy (ares_channel channel)
void ares_send (ares_channel channel, const unsigned char *qbuf, int qlen, ares_callback callback, void *arg)
void ares_query (ares_channel channel, const char *name, int dnsclass, int type, ares_callback callback, void *arg)
void ares_search (ares_channel channel, const char *name, int dnsclass, int type, ares_callback callback, void *arg)
void ares_gethostbyname (ares_channel channel, const char *name, int family, ares_host_callback callback, void *arg)
void ares_gethostbyaddr (ares_channel channel, const void *addr, int addrlen, int family, ares_host_callback callback, void *arg)
int ares_fds (ares_channel channel, fd_set *read_fds, fd_set *write_fds)
timevalares_timeout (ares_channel channel, struct timeval *maxtv, struct timeval *tv)
void ares_process (ares_channel channel, fd_set *read_fds, fd_set *write_fds)
int ares_mkquery (const char *name, int dnsclass, int type, unsigned short id, int rd, unsigned char **buf, int *buflen)
int ares_expand_name (const unsigned char *encoded, const unsigned char *abuf, int alen, char **s, int *enclen)
int ares_parse_a_reply (const unsigned char *abuf, int alen, struct hostent **host)
int ares_parse_ptr_reply (const unsigned char *abuf, int alen, const void *addr, int addrlen, int family, struct hostent **host)
void ares_free_string (unsigned char *str)
void ares_free_hostent (struct hostent *host)
const char * ares_strerror (int code, char **memptr)
void ares_free_errmem (char *mem)


Define Documentation

#define ARES_EBADFAMILY   9
 

Definition at line 41 of file ares.h.

#define ARES_EBADNAME   8
 

Definition at line 40 of file ares.h.

Referenced by ares_expand_name(), ares_mkquery(), and fake_hostent().

#define ARES_EBADQUERY   7
 

Definition at line 39 of file ares.h.

Referenced by ares_send().

#define ARES_EBADRESP   10
 

Definition at line 42 of file ares.h.

Referenced by ares_parse_a_reply(), and ares_parse_ptr_reply().

#define ARES_ECONNREFUSED   11
 

Definition at line 43 of file ares.h.

Referenced by ares_send().

#define ARES_EDESTRUCTION   16
 

Definition at line 48 of file ares.h.

Referenced by addr_callback(), ares_destroy(), and host_callback().

#define ARES_EFILE   14
 

Definition at line 46 of file ares.h.

#define ARES_EFORMERR   2
 

Definition at line 32 of file ares.h.

Referenced by qcallback().

#define ARES_ENODATA   1
 

Definition at line 31 of file ares.h.

Referenced by ares_parse_a_reply(), ares_parse_ptr_reply(), qcallback(), and search_callback().

#define ARES_ENOMEM   15
 

Definition at line 47 of file ares.h.

Referenced by ares__send_query(), ares_expand_name(), ares_gethostbyaddr(), ares_gethostbyname(), ares_init_options(), ares_mkquery(), ares_parse_a_reply(), ares_parse_ptr_reply(), ares_query(), ares_search(), ares_send(), cat_domain(), fake_hostent(), init_by_defaults(), init_by_options(), and single_domain().

#define ARES_ENOTFOUND   4
 

Definition at line 34 of file ares.h.

Referenced by gethostbynameaddr(), next_lookup(), qcallback(), and search_callback().

#define ARES_ENOTIMP   5
 

Definition at line 35 of file ares.h.

Referenced by ares_gethostbyaddr(), ares_gethostbyname(), and qcallback().

#define ARES_EOF   13
 

Definition at line 45 of file ares.h.

#define ARES_EREFUSED   6
 

Definition at line 36 of file ares.h.

Referenced by qcallback().

#define ARES_ESERVFAIL   3
 

Definition at line 33 of file ares.h.

Referenced by qcallback(), and search_callback().

#define ARES_ETIMEOUT   12
 

Definition at line 44 of file ares.h.

Referenced by process_timeouts().

#define ARES_FLAG_IGNTC   (1 << 2)
 

Definition at line 53 of file ares.h.

Referenced by process_answer().

#define ARES_FLAG_NOALIASES   (1 << 6)
 

Definition at line 57 of file ares.h.

#define ARES_FLAG_NOCHECKRESP   (1 << 7)
 

Definition at line 58 of file ares.h.

Referenced by process_answer().

#define ARES_FLAG_NORECURSE   (1 << 3)
 

Definition at line 54 of file ares.h.

Referenced by ares_query().

#define ARES_FLAG_NOSEARCH   (1 << 5)
 

Definition at line 56 of file ares.h.

Referenced by single_domain().

#define ARES_FLAG_PRIMARY   (1 << 1)
 

Definition at line 52 of file ares.h.

Referenced by ares_init_options().

#define ARES_FLAG_STAYOPEN   (1 << 4)
 

Definition at line 55 of file ares.h.

Referenced by end_query().

#define ARES_FLAG_USEVC   (1 << 0)
 

Definition at line 51 of file ares.h.

Referenced by ares_send(), and dns_client().

#define ARES_OPT_DOMAINS   (1 << 7)
 

Definition at line 68 of file ares.h.

Referenced by init_by_options().

#define ARES_OPT_FLAGS   (1 << 0)
 

Definition at line 61 of file ares.h.

Referenced by dns_client(), and init_by_options().

#define ARES_OPT_LOOKUPS   (1 << 8)
 

Definition at line 69 of file ares.h.

Referenced by init_by_options().

#define ARES_OPT_NDOTS   (1 << 3)
 

Definition at line 64 of file ares.h.

Referenced by init_by_options().

#define ARES_OPT_SERVERS   (1 << 6)
 

Definition at line 67 of file ares.h.

Referenced by dns_client(), gethostbynameaddr(), and init_by_options().

#define ARES_OPT_TCP_PORT   (1 << 5)
 

Definition at line 66 of file ares.h.

Referenced by init_by_options().

#define ARES_OPT_TIMEOUT   (1 << 1)
 

Definition at line 62 of file ares.h.

Referenced by init_by_options().

#define ARES_OPT_TRIES   (1 << 2)
 

Definition at line 63 of file ares.h.

Referenced by init_by_options().

#define ARES_OPT_UDP_PORT   (1 << 4)
 

Definition at line 65 of file ares.h.

Referenced by init_by_options().

#define ARES_SUCCESS   0
 

Definition at line 28 of file ares.h.

Referenced by addr_callback(), ares_expand_name(), ares_init_options(), ares_mkquery(), ares_parse_a_reply(), ares_parse_ptr_reply(), ares_query(), ares_search(), callback(), cat_domain(), dns_client(), dns_client_callback(), fake_hostent(), gethostbynameaddr(), host_callback(), init_by_defaults(), init_by_options(), process_answer(), qcallback(), same_questions(), search_callback(), and single_domain().


Typedef Documentation

typedef void(* ares_callback)(void *arg, int status, unsigned char *abuf, int alen)
 

Definition at line 87 of file ares.h.

Referenced by ares_query(), ares_search(), and ares_send().

typedef struct ares_channeldata* ares_channel
 

Definition at line 86 of file ares.h.

Referenced by ares__send_query(), ares_destroy(), ares_fds(), ares_gethostbyaddr(), ares_gethostbyname(), ares_init(), ares_init_options(), ares_process(), ares_query(), ares_search(), ares_send(), ares_timeout(), dns_client(), end_query(), gethostbynameaddr(), handle_error(), host_callback(), init_by_defaults(), init_by_options(), next_server(), open_tcp_socket(), open_udp_socket(), process_answer(), process_timeouts(), read_tcp_data(), read_udp_packets(), search_callback(), single_domain(), and write_tcp_data().

typedef void(* ares_host_callback)(void *arg, int status, struct hostent *hostent)
 

Definition at line 89 of file ares.h.

Referenced by ares_gethostbyaddr(), ares_gethostbyname(), and fake_hostent().


Function Documentation

void ares_destroy ares_channel  channel  ) 
 

Definition at line 25 of file ares_destroy.c.

References ares__close_sockets(), ares_channel, ARES_EDESTRUCTION, query::callback, ares_channeldata::domains, free, ares_channeldata::lookups, ares_channeldata::ndomains, query::next, ares_channeldata::nservers, NULL, ares_channeldata::queries, ares_channeldata::servers, and ares_channeldata::sortlist.

Referenced by dns_client(), and gethostbynameaddr().

00026 {
00027   int i;
00028   struct query *query;
00029 
00030   for (i = 0; i < channel->nservers; i++)
00031     ares__close_sockets(&channel->servers[i]);
00032   free(channel->servers);
00033   for (i = 0; i < channel->ndomains; i++)
00034     free(channel->domains[i]);
00035   free(channel->domains);
00036   free(channel->sortlist);
00037   free(channel->lookups);
00038   while (channel->queries)
00039     {
00040       query = channel->queries;
00041       channel->queries = query->next;
00042       query->callback(query->arg, ARES_EDESTRUCTION, NULL, 0);
00043       free(query->tcpbuf);
00044       free(query->skip_server);
00045       free(query);
00046     }
00047   free(channel);
00048 }

Here is the call graph for this function:

int ares_expand_name const unsigned char *  encoded,
const unsigned char *  abuf,
int  alen,
char **  s,
int *  enclen
 

Definition at line 52 of file ares_expand_name.c.

References ARES_EBADNAME, ARES_ENOMEM, ARES_SUCCESS, INDIR_MASK, len, malloc, and name_length().

Referenced by ares_parse_a_reply(), ares_parse_ptr_reply(), and same_questions().

00054 {
00055   int len, indir = 0;
00056   char *q;
00057   const unsigned char *p;
00058 
00059   len = name_length(encoded, abuf, alen);
00060   if (len == -1)
00061     return ARES_EBADNAME;
00062 
00063   *s = malloc(len + 1);
00064   if (!*s)
00065     return ARES_ENOMEM;
00066   q = *s;
00067 
00068   /* No error-checking necessary; it was all done by name_length(). */
00069   p = encoded;
00070   while (*p)
00071     {
00072       if ((*p & INDIR_MASK) == INDIR_MASK)
00073         {
00074           if (!indir)
00075             {
00076               *enclen = p + 2 - encoded;
00077               indir = 1;
00078             }
00079           p = abuf + ((*p & ~INDIR_MASK) << 8 | *(p + 1));
00080         }
00081       else
00082         {
00083           len = *p;
00084           p++;
00085           while (len--)
00086             {
00087               if (*p == '.' || *p == '\\')
00088                 *q++ = '\\';
00089               *q++ = *p;
00090               p++;
00091             }
00092           *q++ = '.';
00093         }
00094     }
00095   if (!indir)
00096     *enclen = p + 1 - encoded;
00097 
00098   /* Nuke the trailing period if we wrote one. */
00099   if (q > *s)
00100     *(q - 1) = 0;
00101 
00102   return ARES_SUCCESS;
00103 }

Here is the call graph for this function:

int ares_fds ares_channel  channel,
fd_set read_fds,
fd_set write_fds
 

Definition at line 25 of file ares_fds.c.

References ares_channel, FD_SET, ares_channeldata::nservers, ares_channeldata::queries, and ares_channeldata::servers.

Referenced by dns_client(), and gethostbynameaddr().

00026 {
00027   struct server_state *server;
00028   int i, nfds;
00029 
00030   /* No queries, no file descriptors. */
00031   if (!channel->queries)
00032     return 0;
00033 
00034   nfds = 0;
00035   for (i = 0; i < channel->nservers; i++)
00036     {
00037       server = &channel->servers[i];
00038       if (server->udp_socket != -1)
00039         {
00040           FD_SET(server->udp_socket, read_fds);
00041           if (server->udp_socket >= nfds)
00042             nfds = server->udp_socket + 1;
00043         }
00044       if (server->tcp_socket != -1)
00045         {
00046           FD_SET(server->tcp_socket, read_fds);
00047           if (server->qhead)
00048             FD_SET(server->tcp_socket, write_fds);
00049           if (server->tcp_socket >= nfds)
00050             nfds = server->tcp_socket + 1;
00051         }
00052     }
00053   return nfds;
00054 }

void ares_free_errmem char *  mem  ) 
 

Definition at line 29 of file ares_free_errmem.c.

Referenced by dns_client(), and dns_client_callback().

00030 {
00031         (void) mem;
00032 }

void ares_free_hostent struct hostent host  ) 
 

Definition at line 25 of file ares_free_hostent.c.

References free, hostent::h_addr_list, hostent::h_aliases, and hostent::h_name.

Referenced by end_aquery(), and end_hquery().

00026 {
00027   char **p;
00028 
00029   free(host->h_name);
00030   for (p = host->h_aliases; *p; p++)
00031     free(*p);
00032   free(host->h_aliases);
00033   free(host->h_addr_list[0]);
00034   free(host->h_addr_list);
00035   free(host);
00036 }

void ares_free_string unsigned char *  str  ) 
 

Definition at line 25 of file ares_free_string.c.

References free.

Referenced by ares_query().

00026 {
00027   free(str);
00028 }

void ares_gethostbyaddr ares_channel  channel,
const void *  addr,
int  addrlen,
int  family,
ares_host_callback  callback,
void *  arg
 

Definition at line 46 of file ares_gethostbyaddr.c.

References AF_INET, ares_channel, ARES_ENOMEM, ARES_ENOTIMP, ares_host_callback, callback(), ares_channeldata::lookups, malloc, next_lookup(), and NULL.

Referenced by dns_client(), and gethostbynameaddr().

00048 {
00049   struct addr_query *aquery;
00050 
00051   if (family != AF_INET || addrlen != sizeof(struct in_addr))
00052     {
00053       callback(arg, ARES_ENOTIMP, NULL);
00054       return;
00055     }
00056 
00057   aquery = malloc(sizeof(struct addr_query));
00058   if (!aquery)
00059     {
00060       callback(arg, ARES_ENOMEM, NULL);
00061       return;
00062     }
00063   aquery->channel = channel;
00064   memcpy(&aquery->addr, addr, sizeof(aquery->addr));
00065   aquery->callback = callback;
00066   aquery->arg = arg;
00067   aquery->remaining_lookups = channel->lookups;
00068 
00069   next_lookup(aquery);
00070 }

Here is the call graph for this function:

void ares_gethostbyname ares_channel  channel,
const char *  name,
int  family,
ares_host_callback  callback,
void *  arg
 

Definition at line 47 of file ares_gethostbyname.c.

References AF_INET, ares_channel, ARES_ENOMEM, ARES_ENOTIMP, ares_host_callback, callback(), fake_hostent(), free, ares_channeldata::lookups, malloc, name, next_lookup(), NULL, and strdup.

Referenced by dns_client(), and gethostbynameaddr().

00049 {
00050   struct host_query *hquery;
00051 
00052   /* Right now we only know how to look up Internet addresses. */
00053   if (family != AF_INET)
00054     {
00055       callback(arg, ARES_ENOTIMP, NULL);
00056       return;
00057     }
00058 
00059   if (fake_hostent(name, callback, arg))
00060     return;
00061 
00062   /* Allocate and fill in the host query structure. */
00063   hquery = malloc(sizeof(struct host_query));
00064   if (!hquery)
00065     {
00066       callback(arg, ARES_ENOMEM, NULL);
00067       return;
00068     }
00069 
00070   hquery->channel = channel;
00071   hquery->name = strdup(name);
00072   if (!hquery->name)
00073     {
00074       free(hquery);
00075       callback(arg, ARES_ENOMEM, NULL);
00076       return;
00077     }
00078 
00079   hquery->callback = callback;
00080   hquery->arg = arg;
00081   hquery->remaining_lookups = channel->lookups;
00082 
00083   /* Start performing lookups according to channel->lookups. */
00084   next_lookup(hquery);
00085 }

Here is the call graph for this function:

int ares_init ares_channel channelptr  ) 
 

Definition at line 34 of file ares_init.c.

References ares_channel, ares_init_options(), and NULL.

00035 {
00036   return ares_init_options(channelptr, NULL, 0);
00037 }

Here is the call graph for this function:

int ares_init_options ares_channel channelptr,
struct ares_options options,
int  optmask
 

Definition at line 40 of file ares_init.c.

References ares_channel, ARES_ENOMEM, ARES_FLAG_PRIMARY, ARES_SUCCESS, ares_channeldata::domains, ares_channeldata::flags, free, gettimeofday(), init_by_defaults(), init_by_options(), ares_channeldata::lookups, malloc, ares_channeldata::ndomains, ares_channeldata::ndots, ares_channeldata::next_id, ares_channeldata::nservers, ares_channeldata::nsort, NULL, ares_channeldata::queries, ares_channeldata::servers, ares_channeldata::sortlist, status, ares_channeldata::tcp_port, time, ares_channeldata::timeout, ares_channeldata::tries, ares_channeldata::udp_port, and server_state::udp_socket.

Referenced by ares_init(), dns_client(), and gethostbynameaddr().

00042 {
00043   ares_channel channel;
00044   int i, status;
00045   struct server_state *server;
00046 
00047   channel = malloc(sizeof(struct ares_channeldata));
00048   if (!channel)
00049     return ARES_ENOMEM;
00050 
00051   /* Set everything to distinguished values so we know they haven't
00052    * been set yet.
00053    */
00054   channel->flags = -1;
00055   channel->timeout = -1;
00056   channel->tries = -1;
00057   channel->ndots = -1;
00058   channel->udp_port = -1;
00059   channel->tcp_port = -1;
00060   channel->nservers = -1;
00061   channel->ndomains = -1;
00062   channel->nsort = -1;
00063   channel->lookups = NULL;
00064 
00065   /* Initialize configuration by each of the four sources, from highest
00066    * precedence to lowest.
00067    */
00068   status = init_by_options(channel, options, optmask);
00069   if (status == ARES_SUCCESS)
00070     status = init_by_defaults(channel);
00071   if (status != ARES_SUCCESS)
00072     {
00073       /* Something failed; clean up memory we may have allocated. */
00074       if (channel->nservers != -1)
00075         free(channel->servers);
00076       if (channel->ndomains != -1)
00077         {
00078           for (i = 0; i < channel->ndomains; i++)
00079             free(channel->domains[i]);
00080           free(channel->domains);
00081         }
00082       if (channel->nsort != -1)
00083         free(channel->sortlist);
00084       free(channel->lookups);
00085       free(channel);
00086       return status;
00087     }
00088 
00089   /* Trim to one server if ARES_FLAG_PRIMARY is set. */
00090   if ((channel->flags & ARES_FLAG_PRIMARY) && channel->nservers > 1)
00091     channel->nservers = 1;
00092 
00093   /* Initialize server states. */
00094   for (i = 0; i < channel->nservers; i++)
00095     {
00096       server = &channel->servers[i];
00097       server->udp_socket = -1;
00098       server->tcp_socket = -1;
00099       server->tcp_lenbuf_pos = 0;
00100       server->tcp_buffer = NULL;
00101       server->qhead = NULL;
00102       server->qtail = NULL;
00103     }
00104 
00105   /* Choose a somewhat random query ID.  The main point is to avoid
00106    * collisions with stale queries.  An attacker trying to spoof a DNS
00107    * answer also has to guess the query ID, but it's only a 16-bit
00108    * field, so there's not much to be done about that.
00109    */
00110 
00111 //  channel->next_id = (RetrieveClock() ^ os_current_process()) & 0xffff;
00112   {
00113     struct timeval time;
00114     gettimeofday(&time,NULL);
00115     channel->next_id = (time.tv_usec ^ time.tv_sec) & 0xffff;
00116   }
00117 
00118   channel->queries = NULL;
00119 
00120   *channelptr = channel;
00121   return ARES_SUCCESS;
00122 }

Here is the call graph for this function:

int ares_mkquery const char *  name,
int  dnsclass,
int  type,
unsigned short  id,
int  rd,
unsigned char **  buf,
int *  buflen
 

Definition at line 74 of file ares_mkquery.c.

References ARES_EBADNAME, ARES_ENOMEM, ARES_SUCCESS, DNS_HEADER_SET_OPCODE, DNS_HEADER_SET_QDCOUNT, DNS_HEADER_SET_QID, DNS_HEADER_SET_RD, DNS_QUESTION_SET_CLASS, DNS_QUESTION_SET_TYPE, HFIXEDSZ, len, malloc, MAXLABEL, name, QFIXEDSZ, and QUERY.

Referenced by ares_query().

00076 {
00077   int len;
00078   unsigned char *q;
00079   const char *p;
00080 
00081   /* Compute the length of the encoded name so we can check buflen.
00082    * Start counting at 1 for the zero-length label at the end. */
00083   len = 1;
00084   for (p = name; *p; p++)
00085     {
00086       if (*p == '\\' && *(p + 1) != 0)
00087         p++;
00088       len++;
00089     }
00090   /* If there are n periods in the name, there are n + 1 labels, and
00091    * thus n + 1 length fields, unless the name is empty or ends with a
00092    * period.  So add 1 unless name is empty or ends with a period.
00093    */
00094   if (*name && *(p - 1) != '.')
00095     len++;
00096 
00097   *buflen = len + HFIXEDSZ + QFIXEDSZ;
00098   *buf = malloc(*buflen);
00099   if (!*buf)
00100       return ARES_ENOMEM;
00101 
00102   /* Set up the header. */
00103   q = *buf;
00104   memset(q, 0, HFIXEDSZ);
00105   DNS_HEADER_SET_QID(q, id);
00106   DNS_HEADER_SET_OPCODE(q, QUERY);
00107   DNS_HEADER_SET_RD(q, (rd) ? 1 : 0);
00108   DNS_HEADER_SET_QDCOUNT(q, 1);
00109 
00110   /* A name of "." is a screw case for the loop below, so adjust it. */
00111   if (strcmp(name, ".") == 0)
00112     name++;
00113 
00114   /* Start writing out the name after the header. */
00115   q += HFIXEDSZ;
00116   while (*name)
00117     {
00118       if (*name == '.')
00119         return ARES_EBADNAME;
00120 
00121       /* Count the number of bytes in this label. */
00122       len = 0;
00123       for (p = name; *p && *p != '.'; p++)
00124         {
00125           if (*p == '\\' && *(p + 1) != 0)
00126             p++;
00127           len++;
00128         }
00129       if (len > MAXLABEL)
00130         return ARES_EBADNAME;
00131 
00132       /* Encode the length and copy the data. */
00133       *q++ = len;
00134       for (p = name; *p && *p != '.'; p++)
00135         {
00136           if (*p == '\\' && *(p + 1) != 0)
00137             p++;
00138           *q++ = *p;
00139         }
00140 
00141       /* Go to the next label and repeat, unless we hit the end. */
00142       if (!*p)
00143         break;
00144       name = p + 1;
00145     }
00146 
00147   /* Add the zero-length label at the end. */
00148   *q++ = 0;
00149 
00150   /* Finish off the question with the type and class. */
00151   DNS_QUESTION_SET_TYPE(q, type);
00152   DNS_QUESTION_SET_CLASS(q, dnsclass);
00153 
00154   return ARES_SUCCESS;
00155 }

int ares_parse_a_reply const unsigned char *  abuf,
int  alen,
struct hostent **  host
 

Definition at line 26 of file ares_parse_a_reply.c.

References AF_INET, ARES_EBADRESP, ARES_ENODATA, ARES_ENOMEM, ares_expand_name(), ARES_SUCCESS, C_IN, DNS_HEADER_ANCOUNT, DNS_HEADER_QDCOUNT, DNS_RR_CLASS, DNS_RR_LEN, DNS_RR_TYPE, free, HFIXEDSZ, len, malloc, NULL, QFIXEDSZ, RRFIXEDSZ, status, strcasecmp, T_A, and T_CNAME.

Referenced by host_callback().

00028 {
00029   unsigned int qdcount, ancount;
00030   int status, i, len, rr_type, rr_class, rr_len, naddrs;
00031   int naliases;
00032   const unsigned char *aptr;
00033   char *hostname, *rr_name, *rr_data, **aliases;
00034   struct in_addr *addrs;
00035   struct hostent *hostent;
00036 
00037   /* Set *host to NULL for all failure cases. */
00038   *host = NULL;
00039 
00040   /* Give up if abuf doesn't have room for a header. */
00041   if (alen < HFIXEDSZ)
00042     return ARES_EBADRESP;
00043 
00044   /* Fetch the question and answer count from the header. */
00045   qdcount = DNS_HEADER_QDCOUNT(abuf);
00046   ancount = DNS_HEADER_ANCOUNT(abuf);
00047   if (qdcount != 1)
00048     return ARES_EBADRESP;
00049 
00050   /* Expand the name from the question, and skip past the question. */
00051   aptr = abuf + HFIXEDSZ;
00052   status = ares_expand_name(aptr, abuf, alen, &hostname, &len);
00053   if (status != ARES_SUCCESS)
00054     return status;
00055   if (aptr + len + QFIXEDSZ > abuf + alen)
00056     {
00057       free(hostname);
00058       return ARES_EBADRESP;
00059     }
00060   aptr += len + QFIXEDSZ;
00061 
00062   /* Allocate addresses and aliases; ancount gives an upper bound for both. */
00063   addrs = malloc(ancount * sizeof(struct in_addr));
00064   if (!addrs)
00065     {
00066       free(hostname);
00067       return ARES_ENOMEM;
00068     }
00069   aliases = malloc((ancount + 1) * sizeof(char *));
00070   if (!aliases)
00071     {
00072       free(hostname);
00073       free(addrs);
00074       return ARES_ENOMEM;
00075     }
00076   naddrs = 0;
00077   naliases = 0;
00078 
00079   /* Examine each answer resource record (RR) in turn. */
00080   for (i = 0; i < ancount; i++)
00081     {
00082       /* Decode the RR up to the data field. */
00083       status = ares_expand_name(aptr, abuf, alen, &rr_name, &len);
00084       if (status != ARES_SUCCESS)
00085         break;
00086       aptr += len;
00087       if (aptr + RRFIXEDSZ > abuf + alen)
00088         {
00089           status = ARES_EBADRESP;
00090           break;
00091         }
00092       rr_type = DNS_RR_TYPE(aptr);
00093       rr_class = DNS_RR_CLASS(aptr);
00094       rr_len = DNS_RR_LEN(aptr);
00095       aptr += RRFIXEDSZ;
00096 
00097       if (rr_class == C_IN && rr_type == T_A
00098           && rr_len == sizeof(struct in_addr)
00099           && strcasecmp(rr_name, hostname) == 0)
00100         {
00101           memcpy(&addrs[naddrs], aptr, sizeof(struct in_addr));
00102           naddrs++;
00103           status = ARES_SUCCESS;
00104         }
00105 
00106       if (rr_class == C_IN && rr_type == T_CNAME)
00107         {
00108           /* Record the RR name as an alias. */
00109           aliases[naliases] = rr_name;
00110           naliases++;
00111 
00112           /* Decode the RR data and replace the hostname with it. */
00113           status = ares_expand_name(aptr, abuf, alen, &rr_data, &len);
00114           if (status != ARES_SUCCESS)
00115             break;
00116           free(hostname);
00117           hostname = rr_data;
00118         }
00119       else
00120         free(rr_name);
00121 
00122       aptr += rr_len;
00123       if (aptr > abuf + alen)
00124         {
00125           status = ARES_EBADRESP;
00126           break;
00127         }
00128     }
00129 
00130   if (status == ARES_SUCCESS && naddrs == 0)
00131     status = ARES_ENODATA;
00132   if (status == ARES_SUCCESS)
00133     {
00134       /* We got our answer.  Allocate memory to build the host entry. */
00135       aliases[naliases] = NULL;
00136       hostent = malloc(sizeof(struct hostent));
00137       if (hostent)
00138         {
00139           hostent->h_addr_list = malloc((naddrs + 1) * sizeof(char *));
00140           if (hostent->h_addr_list)
00141             {
00142               /* Fill in the hostent and return successfully. */
00143               hostent->h_name = hostname;
00144               hostent->h_aliases = aliases;
00145               hostent->h_addrtype = AF_INET;
00146               hostent->h_length = sizeof(struct in_addr);
00147               for (i = 0; i < naddrs; i++)
00148                 hostent->h_addr_list[i] = (char *) &addrs[i];
00149               hostent->h_addr_list[naddrs] = NULL;
00150               *host = hostent;
00151               return ARES_SUCCESS;
00152             }
00153           free(hostent);
00154         }
00155       status = ARES_ENOMEM;
00156     }
00157   for (i = 0; i < naliases; i++)
00158     free(aliases[i]);
00159   free(aliases);
00160   free(addrs);
00161   free(hostname);
00162   return status;
00163 }

Here is the call graph for this function:

int ares_parse_ptr_reply const unsigned char *  abuf,
int  alen,
const void *  addr,
int  addrlen,
int  family,
struct hostent **  host
 

Definition at line 26 of file ares_parse_ptr_reply.c.

References ARES_EBADRESP, ARES_ENODATA, ARES_ENOMEM, ares_expand_name(), ARES_SUCCESS, C_IN, DNS_HEADER_ANCOUNT, DNS_HEADER_QDCOUNT, DNS_RR_CLASS, DNS_RR_LEN, DNS_RR_TYPE, free, HFIXEDSZ, len, malloc, NULL, QFIXEDSZ, RRFIXEDSZ, status, strcasecmp, T_CNAME, and T_PTR.

Referenced by addr_callback().

00028 {
00029   unsigned int qdcount, ancount;
00030   int status, i, len, rr_type, rr_class, rr_len;
00031   const unsigned char *aptr;
00032   char *ptrname, *hostname, *rr_name, *rr_data;
00033   struct hostent *hostent;
00034 
00035   /* Set *host to NULL for all failure cases. */
00036   *host = NULL;
00037 
00038   /* Give up if abuf doesn't have room for a header. */
00039   if (alen < HFIXEDSZ)
00040     return ARES_EBADRESP;
00041 
00042   /* Fetch the question and answer count from the header. */
00043   qdcount = DNS_HEADER_QDCOUNT(abuf);
00044   ancount = DNS_HEADER_ANCOUNT(abuf);
00045   if (qdcount != 1)
00046     return ARES_EBADRESP;
00047 
00048   /* Expand the name from the question, and skip past the question. */
00049   aptr = abuf + HFIXEDSZ;
00050   status = ares_expand_name(aptr, abuf, alen, &ptrname, &len);
00051   if (status != ARES_SUCCESS)
00052     return status;
00053   if (aptr + len + QFIXEDSZ > abuf + alen)
00054     {
00055       free(ptrname);
00056       return ARES_EBADRESP;
00057     }
00058   aptr += len + QFIXEDSZ;
00059 
00060   /* Examine each answer resource record (RR) in turn. */
00061   hostname = NULL;
00062   for (i = 0; i < ancount; i++)
00063     {
00064       /* Decode the RR up to the data field. */
00065       status = ares_expand_name(aptr, abuf, alen, &rr_name, &len);
00066       if (status != ARES_SUCCESS)
00067         break;
00068       aptr += len;
00069       if (aptr + RRFIXEDSZ > abuf + alen)
00070         {
00071           status = ARES_EBADRESP;
00072           break;
00073         }
00074       rr_type = DNS_RR_TYPE(aptr);
00075       rr_class = DNS_RR_CLASS(aptr);
00076       rr_len = DNS_RR_LEN(aptr);
00077       aptr += RRFIXEDSZ;
00078 
00079       if (rr_class == C_IN && rr_type == T_PTR
00080           && strcasecmp(rr_name, ptrname) == 0)
00081         {
00082           /* Decode the RR data and set hostname to it. */
00083           status = ares_expand_name(aptr, abuf, alen, &rr_data, &len);
00084           if (status != ARES_SUCCESS)
00085             break;
00086           if (hostname)
00087             free(hostname);
00088           hostname = rr_data;
00089         }
00090 
00091       if (rr_class == C_IN && rr_type == T_CNAME)
00092         {
00093           /* Decode the RR data and replace ptrname with it. */
00094           status = ares_expand_name(aptr, abuf, alen, &rr_data, &len);
00095           if (status != ARES_SUCCESS)
00096             break;
00097           free(ptrname);
00098           ptrname = rr_data;
00099         }
00100 
00101       free(rr_name);
00102       aptr += rr_len;
00103       if (aptr > abuf + alen)
00104         {
00105           status = ARES_EBADRESP;
00106           break;
00107         }
00108     }
00109 
00110   if (status == ARES_SUCCESS && !hostname)
00111     status = ARES_ENODATA;
00112   if (status == ARES_SUCCESS)
00113     {
00114       /* We got our answer.  Allocate memory to build the host entry. */
00115       hostent = malloc(sizeof(struct hostent));
00116       if (hostent)
00117         {
00118           hostent->h_addr_list = malloc(2 * sizeof(char *));
00119           if (hostent->h_addr_list)
00120             {
00121               hostent->h_addr_list[0] = malloc(addrlen);
00122               if (hostent->h_addr_list[0])
00123                 {
00124                   hostent->h_aliases = malloc(sizeof (char *));
00125                   if (hostent->h_aliases)
00126                     {
00127                       /* Fill in the hostent and return successfully. */
00128                       hostent->h_name = hostname;
00129                       hostent->h_aliases[0] = NULL;
00130                       hostent->h_addrtype = family;
00131                       hostent->h_length = addrlen;
00132                       memcpy(hostent->h_addr_list[0], addr, addrlen);
00133                       hostent->h_addr_list[1] = NULL;
00134                       *host = hostent;
00135                       free(ptrname);
00136                       return ARES_SUCCESS;
00137                     }
00138                   free(hostent->h_addr_list[0]);
00139                 }
00140               free(hostent->h_addr_list);
00141             }
00142           free(hostent);
00143         }
00144       status = ARES_ENOMEM;
00145     }
00146   if (hostname)
00147     free(hostname);
00148   free(ptrname);
00149   return status;
00150 }

Here is the call graph for this function:

void ares_process ares_channel  channel,
fd_set read_fds,
fd_set write_fds
 

Definition at line 46 of file ares_process.c.

References ares_channel, process_timeouts(), read_tcp_data(), read_udp_packets(), time, and write_tcp_data().

Referenced by dns_client(), and gethostbynameaddr().

00047 {
00048   time_t now;
00049 
00050   time(&now);
00051   write_tcp_data(channel, write_fds, now);
00052   read_tcp_data(channel, read_fds, now);
00053   read_udp_packets(channel, read_fds, now);
00054   process_timeouts(channel, now);
00055 }

Here is the call graph for this function:

void ares_query ares_channel  channel,
const char *  name,
int  dnsclass,
int  type,
ares_callback  callback,
void *  arg
 

Definition at line 33 of file ares_query.c.

References ares_callback, ares_channel, ARES_ENOMEM, ARES_FLAG_NORECURSE, ares_free_string(), ares_mkquery(), ares_send(), ARES_SUCCESS, callback(), ares_channeldata::flags, malloc, name, ares_channeldata::next_id, NULL, qcallback(), and status.

Referenced by ares_search(), next_lookup(), and search_callback().

00035 {
00036   struct qquery *qquery;
00037   unsigned char *qbuf;
00038   int qlen, rd, status;
00039 
00040   /* Compose the query. */
00041   rd = !(channel->flags & ARES_FLAG_NORECURSE);
00042   status = ares_mkquery(name, dnsclass, type, channel->next_id, rd, &qbuf,
00043                         &qlen);
00044   channel->next_id++;
00045   if (status != ARES_SUCCESS)
00046     {
00047       callback(arg, status, NULL, 0);
00048       return;
00049     }
00050 
00051   /* Allocate and fill in the query structure. */
00052   qquery = malloc(sizeof(struct qquery));
00053   if (!qquery)
00054     {
00055       ares_free_string(qbuf);
00056       callback(arg, ARES_ENOMEM, NULL, 0);
00057       return;
00058     }
00059   qquery->callback = callback;
00060   qquery->arg = arg;
00061 
00062   /* Send it off.  qcallback will be called when we get an answer. */
00063   ares_send(channel, qbuf, qlen, qcallback, qquery);
00064   ares_free_string(qbuf);
00065 }

Here is the call graph for this function:

void ares_search ares_channel  channel,
const char *  name,
int  dnsclass,
int  type,
ares_callback  callback,
void *  arg
 

Definition at line 46 of file ares_search.c.

References ares_callback, ares_channel, ARES_ENOMEM, ares_query(), ARES_SUCCESS, callback(), cat_domain(), ares_channeldata::domains, free, malloc, name, ares_channeldata::ndots, NULL, search_callback(), single_domain(), status, and strdup.

Referenced by next_lookup().

00048 {
00049   struct search_query *squery;
00050   char *s;
00051   const char *p;
00052   int status, ndots;
00053   
00054   /* If name only yields one domain to search, then we don't have
00055    * to keep extra state, so just do an ares_query().
00056    */
00057   status = single_domain(channel, name, &s);
00058   if (status != ARES_SUCCESS)
00059     {
00060       callback(arg, status, NULL, 0);
00061       return;
00062     }
00063   if (s)
00064     {
00065       ares_query(channel, s, dnsclass, type, callback, arg);
00066       free(s);
00067       return;
00068     }
00069   
00070   /* Allocate a search_query structure to hold the state necessary for
00071    * doing multiple lookups.
00072    */
00073   squery = malloc(sizeof(struct search_query));
00074   if (!squery)
00075     {
00076       callback(arg, ARES_ENOMEM, NULL, 0);
00077       return;
00078     }
00079   squery->channel = channel;
00080   squery->name = strdup(name);
00081   if(!squery->name)
00082     {
00083       free(squery);
00084       callback(arg, ARES_ENOMEM, NULL, 0);
00085       return;
00086     }
00087   squery->dnsclass = dnsclass;
00088   squery->type = type;
00089   squery->status_as_is = -1;
00090   squery->callback = callback;
00091   squery->arg = arg;
00092   
00093   /* Count the number of dots in name. */
00094   ndots = 0;
00095   for (p = name; *p; p++)
00096     {
00097       if (*p == '.')
00098         ndots++;
00099     }
00100   
00101   /* If ndots is at least the channel ndots threshold (usually 1),
00102    * then we try the name as-is first.  Otherwise, we try the name
00103    * as-is last.
00104    */
00105   if (ndots >= channel->ndots)
00106     {
00107       /* Try the name as-is first. */
00108       squery->next_domain = 0;
00109       squery->trying_as_is = 1;
00110       ares_query(channel, name, dnsclass, type, search_callback, squery);
00111     }
00112   else
00113     {
00114       /* Try the name as-is last; start with the first search domain. */
00115       squery->next_domain = 1;
00116       squery->trying_as_is = 0;
00117       status = cat_domain(name, channel->domains[0], &s);
00118       if (status == ARES_SUCCESS)
00119         {
00120           ares_query(channel, s, dnsclass, type, search_callback, squery);
00121           free(s);
00122         }
00123       else
00124         callback(arg, status, NULL, 0);
00125     }
00126 }

Here is the call graph for this function:

void ares_send ares_channel  channel,
const unsigned char *  qbuf,
int  qlen,
ares_callback  callback,
void *  arg
 

Definition at line 26 of file ares_send.c.

References ares__send_query(), ares_callback, ares_channel, ARES_EBADQUERY, ARES_ECONNREFUSED, ARES_ENOMEM, ARES_FLAG_USEVC, callback(), DNS_HEADER_QID, ares_channeldata::flags, free, HFIXEDSZ, malloc, ares_channeldata::nservers, NULL, PACKETSZ, ares_channeldata::queries, and time.

Referenced by ares_query().

00028 {
00029   struct query *query;
00030   int i;
00031   time_t now;
00032 
00033   /* Verify that the query is at least long enough to hold the header. */
00034   if (qlen < HFIXEDSZ
00035 #ifndef LWIP
00036                   || qlen >= (1 << 16)
00037 #endif
00038                   )
00039     {
00040       callback(arg, ARES_EBADQUERY, NULL, 0);
00041       return;
00042     }
00043 
00044   /* Allocate space for query and allocated fields. */
00045   query = malloc(sizeof(struct query));
00046   if (!query)
00047     {
00048       callback(arg, ARES_ENOMEM, NULL, 0);
00049       return;
00050     }
00051   query->tcpbuf = malloc(qlen + 2);
00052   if (!query->tcpbuf)
00053     {
00054       free(query);
00055       callback(arg, ARES_ENOMEM, NULL, 0);
00056       return;
00057     }
00058   query->skip_server = malloc(channel->nservers * sizeof(int));
00059   if (!query->skip_server)
00060     {
00061       free(query->tcpbuf);
00062       free(query);
00063       callback(arg, ARES_ENOMEM, NULL, 0);
00064       return;
00065     }
00066 
00067   /* Compute the query ID.  Start with no timeout. */
00068   query->qid = DNS_HEADER_QID(qbuf);
00069   query->timeout = 0;
00070 
00071   /* Form the TCP query buffer by prepending qlen (as two
00072    * network-order bytes) to qbuf.
00073    */
00074   query->tcpbuf[0] = (qlen >> 8) & 0xff;
00075   query->tcpbuf[1] = qlen & 0xff;
00076   memcpy(query->tcpbuf + 2, qbuf, qlen);
00077   query->tcplen = qlen + 2;
00078 
00079   /* Fill in query arguments. */
00080   query->qbuf = query->tcpbuf + 2;
00081   query->qlen = qlen;
00082   query->callback = callback;
00083   query->arg = arg;
00084 
00085   /* Initialize query status. */
00086   query->try = 0;
00087   query->server = 0;
00088   for (i = 0; i < channel->nservers; i++)
00089     query->skip_server[i] = 0;
00090   query->using_tcp = (channel->flags & ARES_FLAG_USEVC) || qlen > PACKETSZ;
00091   query->error_status = ARES_ECONNREFUSED;
00092 
00093   /* Chain the query into this channel's query list. */
00094   query->next = channel->queries;
00095   channel->queries = query;
00096 
00097   /* Perform the first query action. */
00098   time(&now);
00099   ares__send_query(channel, query, now);
00100 }

Here is the call graph for this function:

const char* ares_strerror int  code,
char **  memptr
 

Definition at line 25 of file ares_strerror.c.

Referenced by dns_client(), and dns_client_callback().

00026 {
00027   /* A future implementation may want to handle internationalization.
00028    * For now, just return a string literal from a table.
00029    */
00030   const char *errtext[] = {
00031     "Successful completion",
00032     "DNS server returned answer with no data",
00033     "DNS server claims query was misformatted",
00034     "DNS server returned general failure",
00035     "Domain name not found",
00036     "DNS server does not implement requested operation",
00037     "DNS server refused query",
00038     "Misformatted DNS query",
00039     "Misformatted domain name",
00040     "Unsupported address family",
00041     "Misformatted DNS reply",
00042     "Could not contact DNS servers",
00043     "Timeout while contacting DNS servers",
00044     "End of file",
00045     "Error reading file",
00046     "Out of memory"
00047   };
00048 
00049   (void)memptr;
00050 
00051 //#ifdef LWIP_ASSERT
00052 //  LWIP_ASSERT("ares_strerror: code", code >= 0 && code < (sizeof(errtext) / sizeof(*errtext)));
00053 //#else
00054 //  assert(code >= 0 && code < (sizeof(errtext) / sizeof(*errtext)));
00055 //#endif
00056   return errtext[code];
00057 }

struct timeval* ares_timeout ares_channel  channel,
struct timeval maxtv,
struct timeval tv
 

Definition at line 25 of file ares_timeout.c.

References ares_channel, query::next, ares_channeldata::queries, time, timeval::tv_sec, and timeval::tv_usec.

Referenced by dns_client(), and gethostbynameaddr().

00027 {
00028   struct query *query;
00029   time_t now;
00030   int offset, min_offset;
00031 
00032   /* No queries, no timeout (and no fetch of the current time). */
00033   if (!channel->queries)
00034     return maxtv;
00035 
00036   /* Find the minimum timeout for the current set of queries. */
00037   time(&now);
00038   min_offset = -1;
00039   for (query = channel->queries; query; query = query->next)
00040     {
00041       if (query->timeout == 0)
00042         continue;
00043       offset = query->timeout - now;
00044       if (offset < 0)
00045         offset = 0;
00046       if (min_offset == -1 || offset < min_offset)
00047         min_offset = offset;
00048     }
00049 
00050   /* If we found a minimum timeout and it's sooner than the one
00051    * specified in maxtv (if any), return it.  Otherwise go with
00052    * maxtv.
00053    */
00054   if (min_offset != -1 && (!maxtv || min_offset <= maxtv->tv_sec))
00055     {
00056       tvbuf->tv_sec = min_offset;
00057       tvbuf->tv_usec = 0;
00058       return tvbuf;
00059     }
00060   else
00061     return maxtv;
00062 }


Generated on Wed Jan 14 12:58:59 2004 for RTL-lwIP-0.4 by doxygen 1.3.4