Coverage Report

Created: 2023-09-25 07:14

/src/c-ares/src/lib/ares__addrinfo2hostent.c
Line
Count
Source (jump to first uncovered line)
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
 * SPDX-License-Identifier: MIT
19
 */
20
21
#include "ares_setup.h"
22
23
#ifdef HAVE_NETINET_IN_H
24
#  include <netinet/in.h>
25
#endif
26
#ifdef HAVE_NETDB_H
27
#  include <netdb.h>
28
#endif
29
#ifdef HAVE_ARPA_INET_H
30
#  include <arpa/inet.h>
31
#endif
32
33
#include "ares_nameser.h"
34
35
#ifdef HAVE_STRINGS_H
36
#  include <strings.h>
37
#endif
38
39
#ifdef HAVE_LIMITS_H
40
#  include <limits.h>
41
#endif
42
43
#include "ares.h"
44
#include "ares_dns.h"
45
#include "ares_inet_net_pton.h"
46
#include "ares_private.h"
47
48
int ares__addrinfo2hostent(const struct ares_addrinfo *ai, int family,
49
                           struct hostent **host)
50
730
{
51
730
  struct ares_addrinfo_node *next;
52
730
  struct ares_addrinfo_cname *next_cname;
53
730
  char **aliases = NULL;
54
730
  char *addrs = NULL;
55
730
  int naliases = 0, naddrs = 0, alias = 0, i;
56
57
730
  if (ai == NULL || host == NULL)
58
0
    return ARES_EBADQUERY;
59
60
730
  *host = ares_malloc(sizeof(**host));
61
730
  if (!(*host))
62
0
    {
63
0
      goto enomem;
64
0
    }
65
730
  memset(*host, 0, sizeof(**host));
66
67
  /* Use the first node of the response as the family, since hostent can only
68
   * represent one family.  We assume getaddrinfo() returned a sorted list if
69
   * the user requested AF_UNSPEC. */
70
730
  if (family == AF_UNSPEC && ai->nodes)
71
0
    family = ai->nodes->ai_family;
72
73
730
  next = ai->nodes;
74
69.1k
  while (next)
75
68.4k
    {
76
68.4k
      if(next->ai_family == family)
77
34.2k
        {
78
34.2k
          ++naddrs;
79
34.2k
        }
80
68.4k
      next = next->ai_next;
81
68.4k
    }
82
83
730
  next_cname = ai->cnames;
84
3.01k
  while (next_cname)
85
2.28k
    {
86
2.28k
      if(next_cname->alias)
87
2.28k
        ++naliases;
88
2.28k
      next_cname = next_cname->next;
89
2.28k
    }
90
91
730
  aliases = ares_malloc((naliases + 1) * sizeof(char *));
92
730
  if (!aliases)
93
0
    {
94
0
      goto enomem;
95
0
    }
96
730
  (*host)->h_aliases = aliases;
97
730
  memset(aliases, 0, (naliases + 1) * sizeof(char *));
98
99
730
  if (naliases)
100
226
    {
101
226
      next_cname = ai->cnames;
102
2.51k
      while (next_cname)
103
2.28k
        {
104
2.28k
          if(next_cname->alias) {
105
2.28k
            aliases[alias] = ares_strdup(next_cname->alias);
106
2.28k
            if (!aliases[alias]) {
107
0
              goto enomem;
108
0
            }
109
2.28k
            alias++;
110
2.28k
          }
111
2.28k
          next_cname = next_cname->next;
112
2.28k
        }
113
226
    }
114
115
116
730
  (*host)->h_addr_list = ares_malloc((naddrs + 1) * sizeof(char *));
117
730
  if (!(*host)->h_addr_list)
118
0
    {
119
0
      goto enomem;
120
0
    }
121
122
730
  memset((*host)->h_addr_list, 0, (naddrs + 1) * sizeof(char *));
123
124
730
  if (ai->cnames)
125
226
    {
126
226
      (*host)->h_name = ares_strdup(ai->cnames->name);
127
226
      if ((*host)->h_name == NULL && ai->cnames->name)
128
0
        {
129
0
          goto enomem;
130
0
        }
131
226
    }
132
504
  else
133
504
    {
134
504
      (*host)->h_name = ares_strdup(ai->name);
135
504
      if ((*host)->h_name == NULL && ai->name)
136
0
        {
137
0
          goto enomem;
138
0
        }
139
504
    }
140
141
730
  (*host)->h_addrtype = family;
142
730
  (*host)->h_length = (family == AF_INET)?
143
365
     sizeof(struct in_addr):sizeof(struct ares_in6_addr);
144
145
730
  if (naddrs)
146
191
    {
147
191
      addrs = ares_malloc(naddrs * (*host)->h_length);
148
191
      if (!addrs)
149
0
        {
150
0
          goto enomem;
151
0
        }
152
153
191
      i = 0;
154
191
      next = ai->nodes;
155
52.3k
      while (next)
156
52.1k
        {
157
52.1k
          if(next->ai_family == family)
158
34.2k
            {
159
34.2k
              (*host)->h_addr_list[i] = addrs + (i * (*host)->h_length);
160
34.2k
              if (family == AF_INET6)
161
272
                {
162
272
                  memcpy((*host)->h_addr_list[i],
163
272
                     &(CARES_INADDR_CAST(struct sockaddr_in6 *, next->ai_addr)->sin6_addr),
164
272
                     (*host)->h_length);
165
272
                }
166
33.9k
              else
167
33.9k
                {
168
33.9k
                  memcpy((*host)->h_addr_list[i],
169
33.9k
                     &(CARES_INADDR_CAST(struct sockaddr_in *, next->ai_addr)->sin_addr),
170
33.9k
                     (*host)->h_length);
171
33.9k
                }
172
34.2k
              ++i;
173
34.2k
            }
174
52.1k
          next = next->ai_next;
175
52.1k
        }
176
177
191
      if (i == 0)
178
0
        {
179
0
          ares_free(addrs);
180
0
        }
181
191
    }
182
183
730
  if (naddrs == 0 && naliases == 0)
184
329
    {
185
329
      ares_free_hostent(*host);
186
329
      *host = NULL;
187
329
      return ARES_ENODATA;
188
329
    }
189
190
401
  return ARES_SUCCESS;
191
192
0
enomem:
193
0
  ares_free_hostent(*host);
194
0
  *host = NULL;
195
0
  return ARES_ENOMEM;
196
730
}
197
198
199
int ares__addrinfo2addrttl(const struct ares_addrinfo *ai, int family,
200
                           int req_naddrttls, struct ares_addrttl *addrttls,
201
                           struct ares_addr6ttl *addr6ttls, int *naddrttls)
202
730
{
203
730
  struct ares_addrinfo_node *next;
204
730
  struct ares_addrinfo_cname *next_cname;
205
730
  int cname_ttl = INT_MAX;
206
207
730
  if (family != AF_INET && family != AF_INET6)
208
0
    return ARES_EBADQUERY;
209
210
730
  if (ai == NULL || naddrttls == NULL)
211
0
    return ARES_EBADQUERY;
212
213
730
  if (family == AF_INET && addrttls == NULL)
214
0
    return ARES_EBADQUERY;
215
216
730
  if (family == AF_INET6 && addr6ttls == NULL)
217
0
    return ARES_EBADQUERY;
218
219
730
  if (req_naddrttls == 0)
220
0
    return ARES_EBADQUERY;
221
222
730
  *naddrttls = 0;
223
224
730
  next_cname = ai->cnames;
225
3.01k
  while (next_cname)
226
2.28k
    {
227
2.28k
      if(next_cname->ttl < cname_ttl)
228
322
        cname_ttl = next_cname->ttl;
229
2.28k
      next_cname = next_cname->next;
230
2.28k
    }
231
232
730
  next = ai->nodes;
233
69.1k
  while (next)
234
68.4k
    {
235
68.4k
      if(next->ai_family == family)
236
34.2k
        {
237
34.2k
          if (*naddrttls < req_naddrttls)
238
378
            {
239
378
                if (family == AF_INET6)
240
107
                  {
241
107
                    if(next->ai_ttl > cname_ttl)
242
16
                      addr6ttls[*naddrttls].ttl = cname_ttl;
243
91
                    else
244
91
                      addr6ttls[*naddrttls].ttl = next->ai_ttl;
245
246
107
                    memcpy(&addr6ttls[*naddrttls].ip6addr,
247
107
                           &(CARES_INADDR_CAST(struct sockaddr_in6 *, next->ai_addr)->sin6_addr),
248
107
                           sizeof(struct ares_in6_addr));
249
107
                  }
250
271
                else
251
271
                  {
252
271
                    if(next->ai_ttl > cname_ttl)
253
21
                      addrttls[*naddrttls].ttl = cname_ttl;
254
250
                    else
255
250
                      addrttls[*naddrttls].ttl = next->ai_ttl;
256
271
                    memcpy(&addrttls[*naddrttls].ipaddr,
257
271
                           &(CARES_INADDR_CAST(struct sockaddr_in *, next->ai_addr)->sin_addr),
258
271
                           sizeof(struct in_addr));
259
271
                  }
260
378
                (*naddrttls)++;
261
378
             }
262
34.2k
        }
263
68.4k
      next = next->ai_next;
264
68.4k
    }
265
266
730
  return ARES_SUCCESS;
267
730
}
268