• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 1998 by the Massachusetts Institute of Technology.
2  * Copyright 2005 Dominick Meglio
3  * Copyright (C) 2019 by Andrew Selivanov
4  * Copyright (C) 2021 by Brad House
5  *
6  * Permission to use, copy, modify, and distribute this
7  * software and its documentation for any purpose and without
8  * fee is hereby granted, provided that the above copyright
9  * notice appear in all copies and that both that copyright
10  * notice and this permission notice appear in supporting
11  * documentation, and that the name of M.I.T. not be used in
12  * advertising or publicity pertaining to distribution of the
13  * software without specific, written prior permission.
14  * M.I.T. makes no representations about the suitability of
15  * this software for any purpose.  It is provided "as is"
16  * without express or implied warranty.
17  */
18 
19 #include "ares_setup.h"
20 
21 #ifdef HAVE_NETINET_IN_H
22 #  include <netinet/in.h>
23 #endif
24 #ifdef HAVE_NETDB_H
25 #  include <netdb.h>
26 #endif
27 #ifdef HAVE_ARPA_INET_H
28 #  include <arpa/inet.h>
29 #endif
30 
31 #include "ares_nameser.h"
32 
33 #ifdef HAVE_STRINGS_H
34 #  include <strings.h>
35 #endif
36 
37 #ifdef HAVE_LIMITS_H
38 #  include <limits.h>
39 #endif
40 
41 #include "ares.h"
42 #include "ares_dns.h"
43 #include "ares_inet_net_pton.h"
44 #include "ares_private.h"
45 
ares__addrinfo2hostent(const struct ares_addrinfo * ai,int family,struct hostent ** host)46 int ares__addrinfo2hostent(const struct ares_addrinfo *ai, int family,
47                            struct hostent **host)
48 {
49   struct ares_addrinfo_node *next;
50   struct ares_addrinfo_cname *next_cname;
51   char **aliases = NULL;
52   char *addrs = NULL;
53   int naliases = 0, naddrs = 0, alias = 0, i;
54 
55   if (ai == NULL || host == NULL)
56     return ARES_EBADQUERY;
57 
58   *host = ares_malloc(sizeof(**host));
59   if (!(*host))
60     {
61       goto enomem;
62     }
63   memset(*host, 0, sizeof(**host));
64 
65   /* Use the first node of the response as the family, since hostent can only
66    * represent one family.  We assume getaddrinfo() returned a sorted list if
67    * the user requested AF_UNSPEC. */
68   if (family == AF_UNSPEC && ai->nodes)
69     family = ai->nodes->ai_family;
70 
71   next = ai->nodes;
72   while (next)
73     {
74       if(next->ai_family == family)
75         {
76           ++naddrs;
77         }
78       next = next->ai_next;
79     }
80 
81   next_cname = ai->cnames;
82   while (next_cname)
83     {
84       if(next_cname->alias)
85         ++naliases;
86       next_cname = next_cname->next;
87     }
88 
89   aliases = ares_malloc((naliases + 1) * sizeof(char *));
90   if (!aliases)
91     {
92       goto enomem;
93     }
94   (*host)->h_aliases = aliases;
95   memset(aliases, 0, (naliases + 1) * sizeof(char *));
96 
97   if (naliases)
98     {
99       next_cname = ai->cnames;
100       while (next_cname)
101         {
102           if(next_cname->alias) {
103             aliases[alias] = ares_strdup(next_cname->alias);
104             if (!aliases[alias]) {
105               goto enomem;
106             }
107             alias++;
108           }
109           next_cname = next_cname->next;
110         }
111     }
112 
113 
114   (*host)->h_addr_list = ares_malloc((naddrs + 1) * sizeof(char *));
115   if (!(*host)->h_addr_list)
116     {
117       goto enomem;
118     }
119 
120   memset((*host)->h_addr_list, 0, (naddrs + 1) * sizeof(char *));
121 
122   if (ai->cnames)
123     {
124       (*host)->h_name = ares_strdup(ai->cnames->name);
125       if ((*host)->h_name == NULL && ai->cnames->name)
126         {
127           goto enomem;
128         }
129     }
130   else
131     {
132       (*host)->h_name = ares_strdup(ai->name);
133       if ((*host)->h_name == NULL && ai->name)
134         {
135           goto enomem;
136         }
137     }
138 
139   (*host)->h_addrtype = family;
140   (*host)->h_length = (family == AF_INET)?
141      sizeof(struct in_addr):sizeof(struct ares_in6_addr);
142 
143   if (naddrs)
144     {
145       addrs = ares_malloc(naddrs * (*host)->h_length);
146       if (!addrs)
147         {
148           goto enomem;
149         }
150 
151       i = 0;
152       next = ai->nodes;
153       while (next)
154         {
155           if(next->ai_family == family)
156             {
157               (*host)->h_addr_list[i] = addrs + (i * (*host)->h_length);
158               if (family == AF_INET6)
159                 {
160                   memcpy((*host)->h_addr_list[i],
161                      &(CARES_INADDR_CAST(struct sockaddr_in6 *, next->ai_addr)->sin6_addr),
162                      (*host)->h_length);
163                 }
164               else
165                 {
166                   memcpy((*host)->h_addr_list[i],
167                      &(CARES_INADDR_CAST(struct sockaddr_in *, next->ai_addr)->sin_addr),
168                      (*host)->h_length);
169                 }
170               ++i;
171             }
172           next = next->ai_next;
173         }
174 
175       if (i == 0)
176         {
177           ares_free(addrs);
178         }
179     }
180 
181   if (naddrs == 0 && naliases == 0)
182     {
183       ares_free_hostent(*host);
184       *host = NULL;
185       return ARES_ENODATA;
186     }
187 
188   return ARES_SUCCESS;
189 
190 enomem:
191   ares_free_hostent(*host);
192   *host = NULL;
193   return ARES_ENOMEM;
194 }
195 
196 
ares__addrinfo2addrttl(const struct ares_addrinfo * ai,int family,int req_naddrttls,struct ares_addrttl * addrttls,struct ares_addr6ttl * addr6ttls,int * naddrttls)197 int ares__addrinfo2addrttl(const struct ares_addrinfo *ai, int family,
198                            int req_naddrttls, struct ares_addrttl *addrttls,
199                            struct ares_addr6ttl *addr6ttls, int *naddrttls)
200 {
201   struct ares_addrinfo_node *next;
202   struct ares_addrinfo_cname *next_cname;
203   int cname_ttl = INT_MAX;
204 
205   if (family != AF_INET && family != AF_INET6)
206     return ARES_EBADQUERY;
207 
208   if (ai == NULL || naddrttls == NULL)
209     return ARES_EBADQUERY;
210 
211   if (family == AF_INET && addrttls == NULL)
212     return ARES_EBADQUERY;
213 
214   if (family == AF_INET6 && addr6ttls == NULL)
215     return ARES_EBADQUERY;
216 
217   if (req_naddrttls == 0)
218     return ARES_EBADQUERY;
219 
220   *naddrttls = 0;
221 
222   next_cname = ai->cnames;
223   while (next_cname)
224     {
225       if(next_cname->ttl < cname_ttl)
226         cname_ttl = next_cname->ttl;
227       next_cname = next_cname->next;
228     }
229 
230   next = ai->nodes;
231   while (next)
232     {
233       if(next->ai_family == family)
234         {
235           if (*naddrttls < req_naddrttls)
236             {
237                 if (family == AF_INET6)
238                   {
239                     if(next->ai_ttl > cname_ttl)
240                       addr6ttls[*naddrttls].ttl = cname_ttl;
241                     else
242                       addr6ttls[*naddrttls].ttl = next->ai_ttl;
243 
244                     memcpy(&addr6ttls[*naddrttls].ip6addr,
245                            &(CARES_INADDR_CAST(struct sockaddr_in6 *, next->ai_addr)->sin6_addr),
246                            sizeof(struct ares_in6_addr));
247                   }
248                 else
249                   {
250                     if(next->ai_ttl > cname_ttl)
251                       addrttls[*naddrttls].ttl = cname_ttl;
252                     else
253                       addrttls[*naddrttls].ttl = next->ai_ttl;
254                     memcpy(&addrttls[*naddrttls].ipaddr,
255                            &(CARES_INADDR_CAST(struct sockaddr_in *, next->ai_addr)->sin_addr),
256                            sizeof(struct in_addr));
257                   }
258                 (*naddrttls)++;
259              }
260         }
261       next = next->ai_next;
262     }
263 
264   return ARES_SUCCESS;
265 }
266 
267