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

ares_parse_ptr_reply.c File Reference

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

Include dependency graph for ares_parse_ptr_reply.c:

Go to the source code of this file.

Functions

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


Function Documentation

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:


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