reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
ares_parse_a_reply.c
Go to the documentation of this file.
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 "ares_nameser.h"
30#endif
31#include <netdb.h>
32#endif
33
34int ares_parse_a_reply(const unsigned char* abuf, int alen,
35 struct hostent** host)
36{
37 unsigned int qdcount, ancount;
38 int status, i, rr_type, rr_class, rr_len, naddrs;
39 long int len;
40 int naliases;
41 const unsigned char* aptr;
42 char* hostname, * rr_name, * rr_data, ** aliases;
43 struct in_addr* addrs;
44 struct hostent* hostent;
45
46 /* Set *host to NULL for all failure cases. */
47 *host = NULL;
48
49 /* Give up if abuf doesn't have room for a header. */
50 if (alen < HFIXEDSZ)
51 return ARES_EBADRESP;
52
53 /* Fetch the question and answer count from the header. */
56 if (qdcount != 1)
57 return ARES_EBADRESP;
58
59 /* Expand the name from the question, and skip past the question. */
60 aptr = abuf + HFIXEDSZ;
61 status = ares_expand_name(aptr, abuf, alen, &hostname, &len);
62 if (status != ARES_SUCCESS)
63 return status;
64 if (aptr + len + QFIXEDSZ > abuf + alen)
65 {
66 free(hostname);
67 return ARES_EBADRESP;
68 }
69 aptr += len + QFIXEDSZ;
70
71 /* Allocate addresses and aliases; ancount gives an upper bound for both. */
72 addrs = malloc(ancount * sizeof(struct in_addr));
73 if (!addrs)
74 {
75 free(hostname);
76 return ARES_ENOMEM;
77 }
78 aliases = malloc((ancount + 1) * sizeof(char*));
79 if (!aliases)
80 {
81 free(hostname);
82 free(addrs);
83 return ARES_ENOMEM;
84 }
85 naddrs = 0;
86 naliases = 0;
87
88 /* Examine each answer resource record (RR) in turn. */
89 for (i = 0; i < (int)ancount; i++)
90 {
91 /* Decode the RR up to the data field. */
92 status = ares_expand_name(aptr, abuf, alen, &rr_name, &len);
93 if (status != ARES_SUCCESS)
94 break;
95 aptr += len;
96 if (aptr + RRFIXEDSZ > abuf + alen)
97 {
99 status = ARES_EBADRESP;
100 break;
101 }
105 aptr += RRFIXEDSZ;
106 if (aptr + rr_len > abuf + alen)
107 {
108 free(rr_name);
109 status = ARES_EBADRESP;
110 break;
111 }
112
113 if (rr_class == C_IN && rr_type == T_A
114 && rr_len == sizeof(struct in_addr)
115 && strcasecmp(rr_name, hostname) == 0)
116 {
117 memcpy(&addrs[naddrs], aptr, sizeof(struct in_addr));
118 naddrs++;
119 status = ARES_SUCCESS;
120 }
121
122 if (rr_class == C_IN && rr_type == T_CNAME)
123 {
124 /* Record the RR name as an alias. */
126 naliases++;
127
128 /* Decode the RR data and replace the hostname with it. */
129 status = ares_expand_name(aptr, abuf, alen, &rr_data, &len);
130 if (status != ARES_SUCCESS)
131 break;
132 free(hostname);
133 hostname = rr_data;
134 }
135 else
136 free(rr_name);
137
138 aptr += rr_len;
139 if (aptr > abuf + alen)
140 {
141 status = ARES_EBADRESP;
142 break;
143 }
144 }
145
146 if (status == ARES_SUCCESS && naddrs == 0)
147 status = ARES_ENODATA;
148 if (status == ARES_SUCCESS)
149 {
150 /* We got our answer. Allocate memory to build the host entry. */
152 hostent = malloc(sizeof(struct hostent));
153 if (hostent)
154 {
155 hostent->h_addr_list = malloc((naddrs + 1) * sizeof(char*));
156 if (hostent->h_addr_list)
157 {
158 /* Fill in the hostent and return successfully. */
159 hostent->h_name = hostname;
160 hostent->h_aliases = aliases;
161 hostent->h_addrtype = AF_INET;
162 hostent->h_length = sizeof(struct in_addr);
163 for (i = 0; i < naddrs; i++)
164 hostent->h_addr_list[i] = (char*)&addrs[i];
165 hostent->h_addr_list[naddrs] = NULL;
166 if (!naddrs && addrs)
167 free(addrs);
168 *host = hostent;
169 return ARES_SUCCESS;
170 }
171 free(hostent);
172 }
173 status = ARES_ENOMEM;
174 }
175 for (i = 0; i < naliases; i++)
176 free(aliases[i]);
177 free(aliases);
178 free(addrs);
179 free(hostname);
180 return status;
181}
#define ARES_SUCCESS
Definition ares.h:79
#define ARES_ENOMEM
Definition ares.h:98
#define ARES_ENODATA
Definition ares.h:82
#define DNS_RR_LEN(r)
Definition ares.h:53
#define DNS_HEADER_QDCOUNT(h)
Definition ares.h:48
#define DNS_HEADER_ANCOUNT(h)
Definition ares.h:49
int ares_expand_name(const unsigned char *encoded, const unsigned char *abuf, int alen, char **s, long *enclen)
#define ARES_EBADRESP
Definition ares.h:93
#define DNS_RR_TYPE(r)
Definition ares.h:52
#define DNS_RR_CLASS(r)
Definition ares_dns.h:69
#define QFIXEDSZ
#define C_IN
#define T_CNAME
#define HFIXEDSZ
#define RRFIXEDSZ
int ares_parse_a_reply(const unsigned char *abuf, int alen, struct hostent **host)
#define T_A
Definition compat.hxx:152
void list()
Definition userAdmin.cxx:66