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

ares_parse_a_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_a_reply(const unsigned char *abuf, int alen,
00027                        struct hostent **host)
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 }

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