ares_parse_a_reply.c
Go to the documentation of this file.
1 
2 /* Copyright 1998 by the Massachusetts Institute of Technology.
3  * Copyright (C) 2019 by Andrew Selivanov
4  *
5  * Permission to use, copy, modify, and distribute this
6  * software and its documentation for any purpose and without
7  * fee is hereby granted, provided that the above copyright
8  * notice appear in all copies and that both that copyright
9  * notice and this permission notice appear in supporting
10  * documentation, and that the name of M.I.T. not be used in
11  * advertising or publicity pertaining to distribution of the
12  * software without specific, written prior permission.
13  * M.I.T. makes no representations about the suitability of
14  * this software for any purpose. It is provided "as is"
15  * without express or implied warranty.
16  */
17 
18 #include "ares_setup.h"
19 
20 #ifdef HAVE_NETINET_IN_H
21 # include <netinet/in.h>
22 #endif
23 #ifdef HAVE_NETDB_H
24 # include <netdb.h>
25 #endif
26 #ifdef HAVE_ARPA_INET_H
27 # include <arpa/inet.h>
28 #endif
29 
30 #include "ares_nameser.h"
31 
32 #ifdef HAVE_STRINGS_H
33 # include <strings.h>
34 #endif
35 
36 #ifdef HAVE_LIMITS_H
37 # include <limits.h>
38 #endif
39 
40 #include "ares.h"
41 #include "ares_dns.h"
42 #include "ares_private.h"
43 
44 int ares_parse_a_reply(const unsigned char *abuf, int alen,
45  struct hostent **host,
46  struct ares_addrttl *addrttls, int *naddrttls)
47 {
48  struct ares_addrinfo ai;
49  struct ares_addrinfo_node *next;
50  struct ares_addrinfo_cname *next_cname;
51  char **aliases = NULL;
52  char *question_hostname = NULL;
53  struct hostent *hostent = NULL;
54  struct in_addr *addrs = NULL;
55  int naliases = 0, naddrs = 0, alias = 0, i;
56  int cname_ttl = INT_MAX;
57  int status;
58 
59  memset(&ai, 0, sizeof(ai));
60 
61  status = ares__parse_into_addrinfo2(abuf, alen, &question_hostname, &ai);
62  if (status != ARES_SUCCESS)
63  {
64  ares_free(question_hostname);
65 
66  if (naddrttls)
67  {
68  *naddrttls = 0;
69  }
70 
71  return status;
72  }
73 
74  hostent = ares_malloc(sizeof(struct hostent));
75  if (!hostent)
76  {
77  goto enomem;
78  }
79 
80  next = ai.nodes;
81  while (next)
82  {
83  if (next->ai_family == AF_INET)
84  {
85  ++naddrs;
86  }
87  next = next->ai_next;
88  }
89 
90  next_cname = ai.cnames;
91  while (next_cname)
92  {
93  if(next_cname->alias)
94  ++naliases;
95  next_cname = next_cname->next;
96  }
97 
98  aliases = ares_malloc((naliases + 1) * sizeof(char *));
99  if (!aliases)
100  {
101  goto enomem;
102  }
103 
104  if (naliases)
105  {
106  next_cname = ai.cnames;
107  while (next_cname)
108  {
109  if(next_cname->alias)
110  aliases[alias++] = ares_strdup(next_cname->alias);
111  if(next_cname->ttl < cname_ttl)
112  cname_ttl = next_cname->ttl;
113  next_cname = next_cname->next;
114  }
115  }
116 
117  aliases[alias] = NULL;
118 
119  hostent->h_addr_list = ares_malloc((naddrs + 1) * sizeof(char *));
120  if (!hostent->h_addr_list)
121  {
122  goto enomem;
123  }
124 
125  for (i = 0; i < naddrs + 1; ++i)
126  {
127  hostent->h_addr_list[i] = NULL;
128  }
129 
130  if (ai.cnames)
131  {
132  hostent->h_name = ares_strdup(ai.cnames->name);
133  ares_free(question_hostname);
134  }
135  else
136  {
137  hostent->h_name = question_hostname;
138  }
139 
140  hostent->h_aliases = aliases;
141  hostent->h_addrtype = AF_INET;
142  hostent->h_length = sizeof(struct in_addr);
143 
144  if (naddrs)
145  {
146  addrs = ares_malloc(naddrs * sizeof(struct in_addr));
147  if (!addrs)
148  {
149  goto enomem;
150  }
151 
152  i = 0;
153  next = ai.nodes;
154  while (next)
155  {
156  if (next->ai_family == AF_INET)
157  {
158  hostent->h_addr_list[i] = (char *)&addrs[i];
159  memcpy(hostent->h_addr_list[i],
160  &(CARES_INADDR_CAST(struct sockaddr_in *, next->ai_addr)->sin_addr),
161  sizeof(struct in_addr));
162  if (naddrttls && i < *naddrttls)
163  {
164  if (next->ai_ttl > cname_ttl)
165  addrttls[i].ttl = cname_ttl;
166  else
167  addrttls[i].ttl = next->ai_ttl;
168 
169  memcpy(&addrttls[i].ipaddr,
170  &(CARES_INADDR_CAST(struct sockaddr_in *, next->ai_addr)->sin_addr),
171  sizeof(struct in_addr));
172  }
173  ++i;
174  }
175  next = next->ai_next;
176  }
177  if (i == 0)
178  {
179  ares_free(addrs);
180  }
181  }
182 
183  if (host)
184  {
185  *host = hostent;
186  }
187  else
188  {
189  ares_free_hostent(hostent);
190  }
191 
192  if (naddrttls)
193  {
194  /* Truncated to at most *naddrttls entries */
195  *naddrttls = (naddrs > *naddrttls)?*naddrttls:naddrs;
196  }
197 
200  return ARES_SUCCESS;
201 
202 enomem:
203  ares_free(aliases);
204  ares_free(hostent);
207  ares_free(question_hostname);
208  return ARES_ENOMEM;
209 }
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
ares__freeaddrinfo_cnames
void ares__freeaddrinfo_cnames(struct ares_addrinfo_cname *head)
Definition: ares_freeaddrinfo.c:27
ares_addrinfo
Definition: ares.h:616
memset
return memset(p, 0, total)
ares.h
ares_strdup
char * ares_strdup(const char *s1)
Definition: ares_strdup.c:23
ares_addrinfo_cname::alias
char * alias
Definition: ares.h:611
ares_dns.h
status
absl::Status status
Definition: rls.cc:251
ares_addrttl::ttl
int ttl
Definition: ares.h:522
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
CARES_INADDR_CAST
#define CARES_INADDR_CAST(type, var)
Definition: ares_private.h:56
ARES_SUCCESS
#define ARES_SUCCESS
Definition: ares.h:98
ares_setup.h
ares_addrinfo_cname::next
struct ares_addrinfo_cname * next
Definition: ares.h:613
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
next
AllocList * next[kMaxLevel]
Definition: abseil-cpp/absl/base/internal/low_level_alloc.cc:100
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
ares_parse_a_reply
int ares_parse_a_reply(const unsigned char *abuf, int alen, struct hostent **host, struct ares_addrttl *addrttls, int *naddrttls)
Definition: ares_parse_a_reply.c:44
ares_addrttl
Definition: ares.h:520
ares_private.h
ares_nameser.h
ares_addrinfo_cname::name
char * name
Definition: ares.h:612
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