/[resiprocate]/main/contrib/ares/ares_parse_a_reply.c
ViewVC logotype

Contents of /main/contrib/ares/ares_parse_a_reply.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 5295 - (show annotations) (download)
Mon Aug 22 00:30:05 2005 UTC (14 years, 2 months ago) by jason
File MIME type: text/plain
File size: 4591 byte(s)
merged 5270:HEAD from b-directory-reorg
1 /* Copyright 1998 by the Massachusetts Institute of Technology.
2 *
3 * Permission to use, copy, modify, and distribute this
4 * software and its documentation for any purpose and without
5 * fee is hereby granted, provided that the above copyright
6 * notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting
8 * documentation, and that the name of M.I.T. not be used in
9 * advertising or publicity pertaining to distribution of the
10 * software without specific, written prior permission.
11 * M.I.T. makes no representations about the suitability of
12 * this software for any purpose. It is provided "as is"
13 * without express or implied warranty.
14 */
15
16
17 #include <sys/types.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include "ares.h"
21 #include "ares_dns.h"
22 #include "ares_private.h"
23
24 #ifndef WIN32
25 #include <sys/socket.h>
26 #include <netinet/in.h>
27 #include <arpa/inet.h>
28 #ifndef __CYGWIN__
29 # include <arpa/nameser.h>
30 #endif
31 #include <netdb.h>
32 #endif
33
34 int ares_parse_a_reply(const unsigned char *abuf, int alen,
35 struct hostent **host)
36 {
37 unsigned int qdcount, ancount;
38 int status, i, len, rr_type, rr_class, rr_len, naddrs;
39 int naliases;
40 const unsigned char *aptr;
41 char *hostname, *rr_name, *rr_data, **aliases;
42 struct in_addr *addrs;
43 struct hostent *hostent;
44
45 /* Set *host to NULL for all failure cases. */
46 *host = NULL;
47
48 /* Give up if abuf doesn't have room for a header. */
49 if (alen < HFIXEDSZ)
50 return ARES_EBADRESP;
51
52 /* Fetch the question and answer count from the header. */
53 qdcount = DNS_HEADER_QDCOUNT(abuf);
54 ancount = DNS_HEADER_ANCOUNT(abuf);
55 if (qdcount != 1)
56 return ARES_EBADRESP;
57
58 /* Expand the name from the question, and skip past the question. */
59 aptr = abuf + HFIXEDSZ;
60 status = ares_expand_name(aptr, abuf, alen, &hostname, &len);
61 if (status != ARES_SUCCESS)
62 return status;
63 if (aptr + len + QFIXEDSZ > abuf + alen)
64 {
65 free(hostname);
66 return ARES_EBADRESP;
67 }
68 aptr += len + QFIXEDSZ;
69
70 /* Allocate addresses and aliases; ancount gives an upper bound for both. */
71 addrs = malloc(ancount * sizeof(struct in_addr));
72 if (!addrs)
73 {
74 free(hostname);
75 return ARES_ENOMEM;
76 }
77 aliases = malloc((ancount + 1) * sizeof(char *));
78 if (!aliases)
79 {
80 free(hostname);
81 free(addrs);
82 return ARES_ENOMEM;
83 }
84 naddrs = 0;
85 naliases = 0;
86
87 /* Examine each answer resource record (RR) in turn. */
88 for (i = 0; i < (int)ancount; i++)
89 {
90 /* Decode the RR up to the data field. */
91 status = ares_expand_name(aptr, abuf, alen, &rr_name, &len);
92 if (status != ARES_SUCCESS)
93 break;
94 aptr += len;
95 if (aptr + RRFIXEDSZ > abuf + alen)
96 {
97 status = ARES_EBADRESP;
98 break;
99 }
100 rr_type = DNS_RR_TYPE(aptr);
101 rr_class = DNS_RR_CLASS(aptr);
102 rr_len = DNS_RR_LEN(aptr);
103 aptr += RRFIXEDSZ;
104
105 if (rr_class == C_IN && rr_type == T_A
106 && rr_len == sizeof(struct in_addr)
107 && strcasecmp(rr_name, hostname) == 0)
108 {
109 memcpy(&addrs[naddrs], aptr, sizeof(struct in_addr));
110 naddrs++;
111 status = ARES_SUCCESS;
112 }
113
114 if (rr_class == C_IN && rr_type == T_CNAME)
115 {
116 /* Record the RR name as an alias. */
117 aliases[naliases] = rr_name;
118 naliases++;
119
120 /* Decode the RR data and replace the hostname with it. */
121 status = ares_expand_name(aptr, abuf, alen, &rr_data, &len);
122 if (status != ARES_SUCCESS)
123 break;
124 free(hostname);
125 hostname = rr_data;
126 }
127 else
128 free(rr_name);
129
130 aptr += rr_len;
131 if (aptr > abuf + alen)
132 {
133 status = ARES_EBADRESP;
134 break;
135 }
136 }
137
138 if (status == ARES_SUCCESS && naddrs == 0)
139 status = ARES_ENODATA;
140 if (status == ARES_SUCCESS)
141 {
142 /* We got our answer. Allocate memory to build the host entry. */
143 aliases[naliases] = NULL;
144 hostent = malloc(sizeof(struct hostent));
145 if (hostent)
146 {
147 hostent->h_addr_list = malloc((naddrs + 1) * sizeof(char *));
148 if (hostent->h_addr_list)
149 {
150 /* Fill in the hostent and return successfully. */
151 hostent->h_name = hostname;
152 hostent->h_aliases = aliases;
153 hostent->h_addrtype = AF_INET;
154 hostent->h_length = sizeof(struct in_addr);
155 for (i = 0; i < naddrs; i++)
156 hostent->h_addr_list[i] = (char *) &addrs[i];
157 hostent->h_addr_list[naddrs] = NULL;
158 *host = hostent;
159 return ARES_SUCCESS;
160 }
161 free(hostent);
162 }
163 status = ARES_ENOMEM;
164 }
165 for (i = 0; i < naliases; i++)
166 free(aliases[i]);
167 free(aliases);
168 free(addrs);
169 free(hostname);
170 return status;
171 }

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27