#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) |
|
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: