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

ares_parse_ptr_reply.c

Go to the documentation of this file.
00001 /* Copyright 1998 by the Massachusetts Institute of Technology.
00002  *
00003  * Permission to use, copy, modify, and distribute this
00004  * software and its documentation for any purpose and without
00005  * fee is hereby granted, provided that the above copyright
00006  * notice appear in all copies and that both that copyright
00007  * notice and this permission notice appear in supporting
00008  * documentation, and that the name of M.I.T. not be used in
00009  * advertising or publicity pertaining to distribution of the
00010  * software without specific, written prior permission.
00011  * M.I.T. makes no representations about the suitability of
00012  * this software for any purpose.  It is provided "as is"
00013  * without express or implied warranty.
00014  *
00015  * CHANGELOG: this file has been modified by Sergio Perez Alcañiz <serpeal@disca.upv.es> 
00016  *            Departamento de Informática de Sistemas y Computadores          
00017  *            Universidad Politécnica de Valencia                             
00018  *            Valencia (Spain)    
00019  *            Date: April 2003                                          
00020  *
00021  */
00022 
00023 #include "ares_private.h"
00024 #include "ares_dns.h"
00025 
00026 int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr,
00027                          int addrlen, int family, struct hostent **host)
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 }

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