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

ares_parse_a_reply.c File Reference

#include "ares_private.h"
#include "ares_dns.h"

Include dependency graph for ares_parse_a_reply.c:

Go to the source code of this file.

Functions

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


Function Documentation

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:


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