ares__parse_into_addrinfo.c
Go to the documentation of this file.
1 /* Copyright (C) 2019 by Andrew Selivanov
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 #include "ares_setup.h"
17 
18 #ifdef HAVE_NETINET_IN_H
19 # include <netinet/in.h>
20 #endif
21 #ifdef HAVE_NETDB_H
22 # include <netdb.h>
23 #endif
24 #ifdef HAVE_ARPA_INET_H
25 # include <arpa/inet.h>
26 #endif
27 
28 #include "ares_nameser.h"
29 
30 #ifdef HAVE_STRINGS_H
31 # include <strings.h>
32 #endif
33 
34 #ifdef HAVE_LIMITS_H
35 # include <limits.h>
36 #endif
37 
38 #include "ares.h"
39 #include "ares_dns.h"
40 #include "ares_private.h"
41 
42 int ares__parse_into_addrinfo2(const unsigned char *abuf,
43  int alen,
44  char **question_hostname,
45  struct ares_addrinfo *ai)
46 {
47  unsigned int qdcount, ancount;
48  int status, i, rr_type, rr_class, rr_len, rr_ttl;
49  int got_a = 0, got_aaaa = 0, got_cname = 0;
50  long len;
51  const unsigned char *aptr;
52  char *hostname, *rr_name = NULL, *rr_data;
53  struct ares_addrinfo_cname *cname, *cnames = NULL;
54  struct ares_addrinfo_node *node, *nodes = NULL;
55  struct sockaddr_in *sin;
56  struct sockaddr_in6 *sin6;
57 
58  *question_hostname = NULL;
59 
60  /* Give up if abuf doesn't have room for a header. */
61  if (alen < HFIXEDSZ)
62  return ARES_EBADRESP;
63 
64  /* Fetch the question and answer count from the header. */
65  qdcount = DNS_HEADER_QDCOUNT(abuf);
66  ancount = DNS_HEADER_ANCOUNT(abuf);
67  if (qdcount != 1)
68  return ARES_EBADRESP;
69 
70 
71  /* Expand the name from the question, and skip past the question. */
72  aptr = abuf + HFIXEDSZ;
73  status = ares__expand_name_for_response(aptr, abuf, alen, question_hostname, &len, 0);
74  if (status != ARES_SUCCESS)
75  return status;
76  if (aptr + len + QFIXEDSZ > abuf + alen)
77  {
78  return ARES_EBADRESP;
79  }
80 
81  hostname = *question_hostname;
82 
83  aptr += len + QFIXEDSZ;
84 
85  /* Examine each answer resource record (RR) in turn. */
86  for (i = 0; i < (int)ancount; i++)
87  {
88  /* Decode the RR up to the data field. */
89  status = ares__expand_name_for_response(aptr, abuf, alen, &rr_name, &len, 0);
90  if (status != ARES_SUCCESS)
91  {
92  rr_name = NULL;
93  goto failed_stat;
94  }
95 
96  aptr += len;
97  if (aptr + RRFIXEDSZ > abuf + alen)
98  {
100  goto failed_stat;
101  }
102  rr_type = DNS_RR_TYPE(aptr);
103  rr_class = DNS_RR_CLASS(aptr);
104  rr_len = DNS_RR_LEN(aptr);
105  rr_ttl = DNS_RR_TTL(aptr);
106  aptr += RRFIXEDSZ;
107  if (aptr + rr_len > abuf + alen)
108  {
110  goto failed_stat;
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  got_a = 1;
118  if (aptr + sizeof(struct in_addr) > abuf + alen)
119  { /* LCOV_EXCL_START: already checked above */
121  goto failed_stat;
122  } /* LCOV_EXCL_STOP */
123 
124  node = ares__append_addrinfo_node(&nodes);
125  if (!node)
126  {
128  goto failed_stat;
129  }
130 
131  sin = ares_malloc(sizeof(struct sockaddr_in));
132  if (!sin)
133  {
135  goto failed_stat;
136  }
137  memset(sin, 0, sizeof(struct sockaddr_in));
138  memcpy(&sin->sin_addr.s_addr, aptr, sizeof(struct in_addr));
139  sin->sin_family = AF_INET;
140 
141  node->ai_addr = (struct sockaddr *)sin;
142  node->ai_family = AF_INET;
143  node->ai_addrlen = sizeof(struct sockaddr_in);
144 
145  node->ai_ttl = rr_ttl;
146 
148  }
149  else if (rr_class == C_IN && rr_type == T_AAAA
150  && rr_len == sizeof(struct ares_in6_addr)
151  && strcasecmp(rr_name, hostname) == 0)
152  {
153  got_aaaa = 1;
154  if (aptr + sizeof(struct ares_in6_addr) > abuf + alen)
155  { /* LCOV_EXCL_START: already checked above */
157  goto failed_stat;
158  } /* LCOV_EXCL_STOP */
159 
160  node = ares__append_addrinfo_node(&nodes);
161  if (!node)
162  {
164  goto failed_stat;
165  }
166 
167  sin6 = ares_malloc(sizeof(struct sockaddr_in6));
168  if (!sin6)
169  {
171  goto failed_stat;
172  }
173 
174  memset(sin6, 0, sizeof(struct sockaddr_in6));
175  memcpy(&sin6->sin6_addr.s6_addr, aptr, sizeof(struct ares_in6_addr));
176  sin6->sin6_family = AF_INET6;
177 
178  node->ai_addr = (struct sockaddr *)sin6;
179  node->ai_family = AF_INET6;
180  node->ai_addrlen = sizeof(struct sockaddr_in6);
181 
182  node->ai_ttl = rr_ttl;
183 
185  }
186 
187  if (rr_class == C_IN && rr_type == T_CNAME)
188  {
189  got_cname = 1;
190  status = ares__expand_name_for_response(aptr, abuf, alen, &rr_data,
191  &len, 1);
192  if (status != ARES_SUCCESS)
193  {
194  goto failed_stat;
195  }
196 
197  /* Decode the RR data and replace the hostname with it. */
198  /* SA: Seems wrong as it introduses order dependency. */
199  hostname = rr_data;
200 
201  cname = ares__append_addrinfo_cname(&cnames);
202  if (!cname)
203  {
205  ares_free(rr_data);
206  goto failed_stat;
207  }
208  cname->ttl = rr_ttl;
209  cname->alias = rr_name;
210  cname->name = rr_data;
211  }
212  else
213  {
214  ares_free(rr_name);
215  }
216 
217 
218  aptr += rr_len;
219  if (aptr > abuf + alen)
220  { /* LCOV_EXCL_START: already checked above */
222  goto failed_stat;
223  } /* LCOV_EXCL_STOP */
224  }
225 
226  if (status == ARES_SUCCESS)
227  {
228  ares__addrinfo_cat_nodes(&ai->nodes, nodes);
229  if (got_cname)
230  {
231  ares__addrinfo_cat_cnames(&ai->cnames, cnames);
232  return status;
233  }
234  else if (got_a == 0 && got_aaaa == 0)
235  {
236  /* the check for naliases to be zero is to make sure CNAME responses
237  don't get caught here */
239  }
240  }
241 
242  return status;
243 
244 failed_stat:
245  ares_free(rr_name);
248  return status;
249 }
250 
251 int ares__parse_into_addrinfo(const unsigned char *abuf,
252  int alen,
253  struct ares_addrinfo *ai)
254 {
255  int status;
256  char *question_hostname;
257  status = ares__parse_into_addrinfo2(abuf, alen, &question_hostname, ai);
258  ares_free(question_hostname);
259  return status;
260 }
ares__freeaddrinfo_nodes
void ares__freeaddrinfo_nodes(struct ares_addrinfo_node *head)
Definition: ares_freeaddrinfo.c:40
ARES_ENOMEM
#define ARES_ENOMEM
Definition: ares.h:117
ares_addrinfo_node
Definition: ares.h:593
T_A
#define T_A
Definition: ares_nameser.h:310
ares_addrinfo_node::ai_addrlen
ares_socklen_t ai_addrlen
Definition: ares.h:599
DNS_RR_LEN
#define DNS_RR_LEN(r)
Definition: ares_dns.h:104
ares__freeaddrinfo_cnames
void ares__freeaddrinfo_cnames(struct ares_addrinfo_cname *head)
Definition: ares_freeaddrinfo.c:27
AF_INET6
#define AF_INET6
Definition: ares_setup.h:208
ares_addrinfo
Definition: ares.h:616
memset
return memset(p, 0, total)
ares__addrinfo_cat_cnames
void ares__addrinfo_cat_cnames(struct ares_addrinfo_cname **head, struct ares_addrinfo_cname *tail)
Definition: ares_getaddrinfo.c:142
ares.h
ares_addrinfo_node::ai_addr
struct sockaddr * ai_addr
Definition: ares.h:600
ares__append_addrinfo_node
struct ares_addrinfo_node * ares__append_addrinfo_node(struct ares_addrinfo_node **head)
Definition: ares_getaddrinfo.c:182
ares_addrinfo_cname::alias
char * alias
Definition: ares.h:611
ares_addrinfo_node::ai_family
int ai_family
Definition: ares.h:596
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
ares_addrinfo_node::ai_ttl
int ai_ttl
Definition: ares.h:594
DNS_RR_TYPE
#define DNS_RR_TYPE(r)
Definition: ares_dns.h:101
ares__append_addrinfo_cname
struct ares_addrinfo_cname * ares__append_addrinfo_cname(struct ares_addrinfo_cname **head)
Definition: ares_getaddrinfo.c:123
ARES_EBADRESP
#define ARES_EBADRESP
Definition: ares.h:112
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
sockaddr_in6
Definition: ares_ipv6.h:25
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
T_AAAA
#define T_AAAA
Definition: ares_nameser.h:391
sockaddr_in6::sin6_family
unsigned short sin6_family
Definition: ares_ipv6.h:27
ares__parse_into_addrinfo
int ares__parse_into_addrinfo(const unsigned char *abuf, int alen, struct ares_addrinfo *ai)
Definition: ares__parse_into_addrinfo.c:251
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__addrinfo_cat_nodes
void ares__addrinfo_cat_nodes(struct ares_addrinfo_node **head, struct ares_addrinfo_node *tail)
Definition: ares_getaddrinfo.c:201
ares_setup.h
ares_addrinfo::nodes
struct ares_addrinfo_node * nodes
Definition: ares.h:618
ares_addrinfo_cname
Definition: ares.h:609
ares_addrinfo::cnames
struct ares_addrinfo_cname * cnames
Definition: ares.h:617
ares__parse_into_addrinfo2
int ares__parse_into_addrinfo2(const unsigned char *abuf, int alen, char **question_hostname, struct ares_addrinfo *ai)
Definition: ares__parse_into_addrinfo.c:42
C_IN
#define C_IN
Definition: ares_nameser.h:292
ares_in6_addr
Definition: ares.h:514
ares_addrinfo_cname::ttl
int ttl
Definition: ares.h:610
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
sockaddr_in6::sin6_addr
struct ares_in6_addr sin6_addr
Definition: ares_ipv6.h:30
DNS_RR_TTL
#define DNS_RR_TTL(r)
Definition: ares_dns.h:103
len
int len
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:46
ares_nameser.h
ares_addrinfo_cname::name
char * name
Definition: ares.h:612
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