00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
00036 *host = NULL;
00037
00038
00039 if (alen < HFIXEDSZ)
00040 return ARES_EBADRESP;
00041
00042
00043 qdcount = DNS_HEADER_QDCOUNT(abuf);
00044 ancount = DNS_HEADER_ANCOUNT(abuf);
00045 if (qdcount != 1)
00046 return ARES_EBADRESP;
00047
00048
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
00061 hostname = NULL;
00062 for (i = 0; i < ancount; i++)
00063 {
00064
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
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
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
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
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 }