• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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