ares_parse_ptr_reply.c
Go to the documentation of this file.
1 
2 /* Copyright 1998 by the Massachusetts Institute of Technology.
3  *
4  * Permission to use, copy, modify, and distribute this
5  * software and its documentation for any purpose and without
6  * fee is hereby granted, provided that the above copyright
7  * notice appear in all copies and that both that copyright
8  * notice and this permission notice appear in supporting
9  * documentation, and that the name of M.I.T. not be used in
10  * advertising or publicity pertaining to distribution of the
11  * software without specific, written prior permission.
12  * M.I.T. makes no representations about the suitability of
13  * this software for any purpose. It is provided "as is"
14  * without express or implied warranty.
15  */
16 
17 #include "ares_setup.h"
18 
19 #ifdef HAVE_NETINET_IN_H
20 # include <netinet/in.h>
21 #endif
22 #ifdef HAVE_NETDB_H
23 # include <netdb.h>
24 #endif
25 
26 #include "ares_nameser.h"
27 
28 #ifdef HAVE_STRINGS_H
29 # include <strings.h>
30 #endif
31 
32 #include "ares.h"
33 #include "ares_dns.h"
34 #include "ares_nowarn.h"
35 #include "ares_private.h"
36 
37 int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr,
38  int addrlen, int family, struct hostent **host)
39 {
40  unsigned int qdcount, ancount;
41  int status, i, rr_type, rr_class, rr_len;
42  long len;
43  const unsigned char *aptr;
44  char *ptrname, *hostname, *rr_name, *rr_data;
45  struct hostent *hostent = NULL;
46  int aliascnt = 0;
47  int alias_alloc = 8;
48  char ** aliases;
49  size_t rr_data_len;
50 
51  /* Set *host to NULL for all failure cases. */
52  *host = NULL;
53 
54  /* Give up if abuf doesn't have room for a header. */
55  if (alen < HFIXEDSZ)
56  return ARES_EBADRESP;
57 
58  /* Fetch the question and answer count from the header. */
59  qdcount = DNS_HEADER_QDCOUNT(abuf);
60  ancount = DNS_HEADER_ANCOUNT(abuf);
61  if (qdcount != 1)
62  return ARES_EBADRESP;
63 
64  /* Expand the name from the question, and skip past the question. */
65  aptr = abuf + HFIXEDSZ;
66  status = ares__expand_name_for_response(aptr, abuf, alen, &ptrname, &len, 0);
67  if (status != ARES_SUCCESS)
68  return status;
69  if (aptr + len + QFIXEDSZ > abuf + alen)
70  {
71  ares_free(ptrname);
72  return ARES_EBADRESP;
73  }
74  aptr += len + QFIXEDSZ;
75 
76  /* Examine each answer resource record (RR) in turn. */
77  hostname = NULL;
78  aliases = ares_malloc(alias_alloc * sizeof(char *));
79  if (!aliases)
80  {
81  ares_free(ptrname);
82  return ARES_ENOMEM;
83  }
84  for (i = 0; i < (int)ancount; i++)
85  {
86  /* Decode the RR up to the data field. */
87  status = ares__expand_name_for_response(aptr, abuf, alen, &rr_name, &len, 0);
88  if (status != ARES_SUCCESS)
89  break;
90  aptr += len;
91  if (aptr + RRFIXEDSZ > abuf + alen)
92  {
93  ares_free(rr_name);
95  break;
96  }
97  rr_type = DNS_RR_TYPE(aptr);
98  rr_class = DNS_RR_CLASS(aptr);
99  rr_len = DNS_RR_LEN(aptr);
100  aptr += RRFIXEDSZ;
101  if (aptr + rr_len > abuf + alen)
102  {
103  ares_free(rr_name);
105  break;
106  }
107 
108  if (rr_class == C_IN && rr_type == T_PTR
109  && strcasecmp(rr_name, ptrname) == 0)
110  {
111  /* Decode the RR data and set hostname to it. */
112  status = ares__expand_name_for_response(aptr, abuf, alen, &rr_data,
113  &len, 1);
114  if (status != ARES_SUCCESS)
115  {
116  ares_free(rr_name);
117  break;
118  }
119  if (hostname)
120  ares_free(hostname);
121  hostname = rr_data;
122  rr_data_len = strlen(rr_data)+1;
123  aliases[aliascnt] = ares_malloc(rr_data_len * sizeof(char));
124  if (!aliases[aliascnt])
125  {
126  ares_free(rr_name);
128  break;
129  }
130  strncpy(aliases[aliascnt], rr_data, rr_data_len);
131  aliascnt++;
132  if (aliascnt >= alias_alloc) {
133  char **ptr;
134  alias_alloc *= 2;
135  ptr = ares_realloc(aliases, alias_alloc * sizeof(char *));
136  if(!ptr) {
137  ares_free(rr_name);
139  break;
140  }
141  aliases = ptr;
142  }
143  }
144 
145  if (rr_class == C_IN && rr_type == T_CNAME)
146  {
147  /* Decode the RR data and replace ptrname with it. */
148  status = ares__expand_name_for_response(aptr, abuf, alen, &rr_data,
149  &len, 1);
150  if (status != ARES_SUCCESS)
151  {
152  ares_free(rr_name);
153  break;
154  }
155  ares_free(ptrname);
156  ptrname = rr_data;
157  }
158 
159  ares_free(rr_name);
160  aptr += rr_len;
161  if (aptr > abuf + alen)
162  { /* LCOV_EXCL_START: already checked above */
164  break;
165  } /* LCOV_EXCL_STOP */
166  }
167 
168  if (status == ARES_SUCCESS && !hostname)
170  if (status == ARES_SUCCESS)
171  {
172  /* If we don't reach the end, we must have failed due to out of memory */
174 
175  /* We got our answer. Allocate memory to build the host entry. */
176  hostent = ares_malloc(sizeof(*hostent));
177  if (!hostent)
178  goto fail;
179 
180  /* If we don't memset here, cleanups may fail */
181  memset(hostent, 0, sizeof(*hostent));
182 
183  hostent->h_addr_list = ares_malloc(2 * sizeof(char *));
184  if (!hostent->h_addr_list)
185  goto fail;
186 
187 
188  if (addr && addrlen) {
189  hostent->h_addr_list[0] = ares_malloc(addrlen);
190  if (!hostent->h_addr_list[0])
191  goto fail;
192  } else {
193  hostent->h_addr_list[0] = NULL;
194  }
195 
196  hostent->h_aliases = ares_malloc((aliascnt+1) * sizeof (char *));
197  if (!hostent->h_aliases)
198  goto fail;
199 
200  /* Fill in the hostent and return successfully. */
201  hostent->h_name = hostname;
202  for (i=0 ; i<aliascnt ; i++)
203  hostent->h_aliases[i] = aliases[i];
204  hostent->h_aliases[aliascnt] = NULL;
205  hostent->h_addrtype = aresx_sitoss(family);
206  hostent->h_length = aresx_sitoss(addrlen);
207  if (addr && addrlen)
208  memcpy(hostent->h_addr_list[0], addr, addrlen);
209  hostent->h_addr_list[1] = NULL;
210  *host = hostent;
211  ares_free(aliases);
212  ares_free(ptrname);
213 
214  return ARES_SUCCESS;
215  }
216 
217 fail:
218  ares_free_hostent(hostent);
219 
220  for (i=0 ; i<aliascnt ; i++)
221  if (aliases[i])
222  ares_free(aliases[i]);
223  ares_free(aliases);
224  if (hostname)
225  ares_free(hostname);
226  ares_free(ptrname);
227  return status;
228 }
ptr
char * ptr
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:45
ARES_ENOMEM
#define ARES_ENOMEM
Definition: ares.h:117
DNS_RR_LEN
#define DNS_RR_LEN(r)
Definition: ares_dns.h:104
memset
return memset(p, 0, total)
ares.h
ares__expand_name_for_response
int ares__expand_name_for_response(const unsigned char *encoded, const unsigned char *abuf, int alen, char **s, long *enclen, int is_hostname)
Definition: ares_expand_name.c:291
ares_dns.h
status
absl::Status status
Definition: rls.cc:251
DNS_RR_TYPE
#define DNS_RR_TYPE(r)
Definition: ares_dns.h:101
ARES_EBADRESP
#define ARES_EBADRESP
Definition: ares.h:112
ares_free_hostent
CARES_EXTERN void ares_free_hostent(struct hostent *host)
Definition: ares_free_hostent.c:26
memcpy
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
ares_malloc
void *(* ares_malloc)(size_t size)=default_malloc
Definition: ares_library_init.c:58
xds_interop_client.int
int
Definition: xds_interop_client.py:113
ARES_ENODATA
#define ARES_ENODATA
Definition: ares.h:101
DNS_RR_CLASS
#define DNS_RR_CLASS(r)
Definition: ares_dns.h:102
T_CNAME
#define T_CNAME
Definition: ares_nameser.h:322
grpc_core::fail
Poll< absl::StatusOr< std::tuple< T... > > > fail()
Definition: try_join_test.cc:45
aresx_sitoss
short aresx_sitoss(int sinum)
Definition: ares_nowarn.c:119
RRFIXEDSZ
#define RRFIXEDSZ
Definition: ares_nameser.h:211
ARES_SUCCESS
#define ARES_SUCCESS
Definition: ares.h:98
DNS_HEADER_QDCOUNT
#define DNS_HEADER_QDCOUNT(h)
Definition: ares_dns.h:72
ares_setup.h
ares_realloc
void *(* ares_realloc)(void *ptr, size_t size)=default_realloc
Definition: ares_library_init.c:59
C_IN
#define C_IN
Definition: ares_nameser.h:292
ares_free
void(* ares_free)(void *ptr)=default_free
Definition: ares_library_init.c:60
DNS_HEADER_ANCOUNT
#define DNS_HEADER_ANCOUNT(h)
Definition: ares_dns.h:73
ares_private.h
QFIXEDSZ
#define QFIXEDSZ
Definition: ares_nameser.h:207
HFIXEDSZ
#define HFIXEDSZ
Definition: ares_nameser.h:203
ares_parse_ptr_reply
int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr, int addrlen, int family, struct hostent **host)
Definition: ares_parse_ptr_reply.c:37
len
int len
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:46
ares_nameser.h
T_PTR
#define T_PTR
Definition: ares_nameser.h:343
ares_nowarn.h
addr
struct sockaddr_in addr
Definition: libuv/docs/code/tcp-echo-server/main.c:10
strcasecmp
#define strcasecmp(p1, p2)
Definition: ares_private.h:114
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230


grpc
Author(s):
autogenerated on Fri May 16 2025 02:57:43