1 /* MIT License
2 *
3 * Copyright (c) 1998 Massachusetts Institute of Technology
4 * Copyright (c) 2005 Dominick Meglio
5 * Copyright (c) 2019 Andrew Selivanov
6 * Copyright (c) 2021 Brad House
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
17 * Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * SOFTWARE.
26 *
27 * SPDX-License-Identifier: MIT
28 */
29
30 #include "ares_setup.h"
31
32 #ifdef HAVE_NETINET_IN_H
33 # include <netinet/in.h>
34 #endif
35 #ifdef HAVE_NETDB_H
36 # include <netdb.h>
37 #endif
38 #ifdef HAVE_ARPA_INET_H
39 # include <arpa/inet.h>
40 #endif
41
42 #include "ares_nameser.h"
43
44 #ifdef HAVE_STRINGS_H
45 # include <strings.h>
46 #endif
47
48 #ifdef HAVE_LIMITS_H
49 # include <limits.h>
50 #endif
51
52 #include "ares.h"
53 #include "ares_dns.h"
54 #include "ares_inet_net_pton.h"
55 #include "ares_private.h"
56
ares__addrinfo2hostent(const struct ares_addrinfo * ai,int family,struct hostent ** host)57 ares_status_t ares__addrinfo2hostent(const struct ares_addrinfo *ai, int family,
58 struct hostent **host)
59 {
60 struct ares_addrinfo_node *next;
61 struct ares_addrinfo_cname *next_cname;
62 char **aliases = NULL;
63 char *addrs = NULL;
64 size_t naliases = 0;
65 size_t naddrs = 0;
66 size_t alias = 0;
67 size_t i;
68
69 if (ai == NULL || host == NULL) {
70 return ARES_EBADQUERY;
71 }
72
73 /* Use the first node of the response as the family, since hostent can only
74 * represent one family. We assume getaddrinfo() returned a sorted list if
75 * the user requested AF_UNSPEC. */
76 if (family == AF_UNSPEC && ai->nodes) {
77 family = ai->nodes->ai_family;
78 }
79
80 if (family != AF_INET && family != AF_INET6) {
81 return ARES_EBADQUERY;
82 }
83
84 *host = ares_malloc(sizeof(**host));
85 if (!(*host)) {
86 goto enomem;
87 }
88 memset(*host, 0, sizeof(**host));
89
90 next = ai->nodes;
91 while (next) {
92 if (next->ai_family == family) {
93 ++naddrs;
94 }
95 next = next->ai_next;
96 }
97
98 next_cname = ai->cnames;
99 while (next_cname) {
100 if (next_cname->alias) {
101 ++naliases;
102 }
103 next_cname = next_cname->next;
104 }
105
106 aliases = ares_malloc((naliases + 1) * sizeof(char *));
107 if (!aliases) {
108 goto enomem;
109 }
110 (*host)->h_aliases = aliases;
111 memset(aliases, 0, (naliases + 1) * sizeof(char *));
112
113 if (naliases) {
114 for (next_cname = ai->cnames; next_cname != NULL;
115 next_cname = next_cname->next) {
116 if (next_cname->alias == NULL) {
117 continue;
118 }
119 aliases[alias] = ares_strdup(next_cname->alias);
120 if (!aliases[alias]) {
121 goto enomem;
122 }
123 alias++;
124 }
125 }
126
127
128 (*host)->h_addr_list = ares_malloc((naddrs + 1) * sizeof(char *));
129 if (!(*host)->h_addr_list) {
130 goto enomem;
131 }
132
133 memset((*host)->h_addr_list, 0, (naddrs + 1) * sizeof(char *));
134
135 if (ai->cnames) {
136 (*host)->h_name = ares_strdup(ai->cnames->name);
137 if ((*host)->h_name == NULL && ai->cnames->name) {
138 goto enomem;
139 }
140 } else {
141 (*host)->h_name = ares_strdup(ai->name);
142 if ((*host)->h_name == NULL && ai->name) {
143 goto enomem;
144 }
145 }
146
147 (*host)->h_addrtype = (HOSTENT_ADDRTYPE_TYPE)family;
148
149 if (family == AF_INET) {
150 (*host)->h_length = sizeof(struct in_addr);
151 }
152
153 if (family == AF_INET6) {
154 (*host)->h_length = sizeof(struct ares_in6_addr);
155 }
156
157 if (naddrs) {
158 addrs = ares_malloc(naddrs * (size_t)(*host)->h_length);
159 if (!addrs) {
160 goto enomem;
161 }
162
163 i = 0;
164 for (next = ai->nodes; next != NULL; next = next->ai_next) {
165 if (next->ai_family != family) {
166 continue;
167 }
168 (*host)->h_addr_list[i] = addrs + (i * (size_t)(*host)->h_length);
169 if (family == AF_INET6) {
170 memcpy(
171 (*host)->h_addr_list[i],
172 &(CARES_INADDR_CAST(struct sockaddr_in6 *, next->ai_addr)->sin6_addr),
173 (size_t)(*host)->h_length);
174 }
175 if (family == AF_INET) {
176 memcpy(
177 (*host)->h_addr_list[i],
178 &(CARES_INADDR_CAST(struct sockaddr_in *, next->ai_addr)->sin_addr),
179 (size_t)(*host)->h_length);
180 }
181 ++i;
182 }
183
184 if (i == 0) {
185 ares_free(addrs);
186 }
187 }
188
189 if (naddrs == 0 && naliases == 0) {
190 ares_free_hostent(*host);
191 *host = NULL;
192 return ARES_ENODATA;
193 }
194
195 return ARES_SUCCESS;
196
197 enomem:
198 ares_free_hostent(*host);
199 *host = NULL;
200 return ARES_ENOMEM;
201 }
202
ares__addrinfo2addrttl(const struct ares_addrinfo * ai,int family,size_t req_naddrttls,struct ares_addrttl * addrttls,struct ares_addr6ttl * addr6ttls,size_t * naddrttls)203 ares_status_t ares__addrinfo2addrttl(const struct ares_addrinfo *ai, int family,
204 size_t req_naddrttls,
205 struct ares_addrttl *addrttls,
206 struct ares_addr6ttl *addr6ttls,
207 size_t *naddrttls)
208 {
209 struct ares_addrinfo_node *next;
210 struct ares_addrinfo_cname *next_cname;
211 int cname_ttl = INT_MAX;
212
213 if (family != AF_INET && family != AF_INET6) {
214 return ARES_EBADQUERY;
215 }
216
217 if (ai == NULL || naddrttls == NULL) {
218 return ARES_EBADQUERY;
219 }
220
221 if (family == AF_INET && addrttls == NULL) {
222 return ARES_EBADQUERY;
223 }
224
225 if (family == AF_INET6 && addr6ttls == NULL) {
226 return ARES_EBADQUERY;
227 }
228
229 if (req_naddrttls == 0) {
230 return ARES_EBADQUERY;
231 }
232
233 *naddrttls = 0;
234
235 next_cname = ai->cnames;
236 while (next_cname) {
237 if (next_cname->ttl < cname_ttl) {
238 cname_ttl = next_cname->ttl;
239 }
240 next_cname = next_cname->next;
241 }
242
243 for (next = ai->nodes; next != NULL; next = next->ai_next) {
244 if (next->ai_family != family) {
245 continue;
246 }
247
248 if (*naddrttls >= req_naddrttls) {
249 break;
250 }
251
252 if (family == AF_INET6) {
253 if (next->ai_ttl > cname_ttl) {
254 addr6ttls[*naddrttls].ttl = cname_ttl;
255 } else {
256 addr6ttls[*naddrttls].ttl = next->ai_ttl;
257 }
258
259 memcpy(
260 &addr6ttls[*naddrttls].ip6addr,
261 &(CARES_INADDR_CAST(struct sockaddr_in6 *, next->ai_addr)->sin6_addr),
262 sizeof(struct ares_in6_addr));
263 } else {
264 if (next->ai_ttl > cname_ttl) {
265 addrttls[*naddrttls].ttl = cname_ttl;
266 } else {
267 addrttls[*naddrttls].ttl = next->ai_ttl;
268 }
269 memcpy(
270 &addrttls[*naddrttls].ipaddr,
271 &(CARES_INADDR_CAST(struct sockaddr_in *, next->ai_addr)->sin_addr),
272 sizeof(struct in_addr));
273 }
274 (*naddrttls)++;
275 }
276
277 return ARES_SUCCESS;
278 }
279