2 /* Copyright 1998 by the Massachusetts Institute of Technology.
3 * Copyright (C) 2019 by Andrew Selivanov
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.
18 #include "ares_setup.h"
20 #ifdef HAVE_NETINET_IN_H
21 # include <netinet/in.h>
26 #ifdef HAVE_ARPA_INET_H
27 # include <arpa/inet.h>
29 #ifdef HAVE_ARPA_NAMESER_H
30 # include <arpa/nameser.h>
34 #ifdef HAVE_ARPA_NAMESER_COMPAT_H
35 # include <arpa/nameser_compat.h>
48 #include "ares_private.h"
50 int ares_parse_a_reply(const unsigned char *abuf, int alen,
51 struct hostent **host,
52 struct ares_addrttl *addrttls, int *naddrttls)
54 struct ares_addrinfo ai;
55 struct ares_addrinfo_node *next;
56 struct ares_addrinfo_cname *next_cname;
57 char **aliases = NULL;
58 char *question_hostname = NULL;
59 struct hostent *hostent = NULL;
60 struct in_addr *addrs = NULL;
61 int naliases = 0, naddrs = 0, alias = 0, i;
62 int cname_ttl = INT_MAX;
65 memset(&ai, 0, sizeof(ai));
67 status = ares__parse_into_addrinfo2(abuf, alen, &question_hostname, &ai);
68 if (status != ARES_SUCCESS)
70 ares_free(question_hostname);
80 hostent = ares_malloc(sizeof(struct hostent));
89 if (next->ai_family == AF_INET)
96 next_cname = ai.cnames;
101 next_cname = next_cname->next;
104 aliases = ares_malloc((naliases + 1) * sizeof(char *));
112 next_cname = ai.cnames;
115 if(next_cname->alias)
116 aliases[alias++] = strdup(next_cname->alias);
117 if(next_cname->ttl < cname_ttl)
118 cname_ttl = next_cname->ttl;
119 next_cname = next_cname->next;
123 aliases[alias] = NULL;
125 hostent->h_addr_list = ares_malloc((naddrs + 1) * sizeof(char *));
126 if (!hostent->h_addr_list)
131 for (i = 0; i < naddrs + 1; ++i)
133 hostent->h_addr_list[i] = NULL;
138 hostent->h_name = strdup(ai.cnames->name);
139 ares_free(question_hostname);
143 hostent->h_name = question_hostname;
146 hostent->h_aliases = aliases;
147 hostent->h_addrtype = AF_INET;
148 hostent->h_length = sizeof(struct in_addr);
152 addrs = ares_malloc(naddrs * sizeof(struct in_addr));
162 if (next->ai_family == AF_INET)
164 hostent->h_addr_list[i] = (char *)&addrs[i];
165 memcpy(hostent->h_addr_list[i],
166 &(CARES_INADDR_CAST(struct sockaddr_in *, next->ai_addr)->sin_addr),
167 sizeof(struct in_addr));
168 if (naddrttls && i < *naddrttls)
170 if (next->ai_ttl > cname_ttl)
171 addrttls[i].ttl = cname_ttl;
173 addrttls[i].ttl = next->ai_ttl;
175 memcpy(&addrttls[i].ipaddr,
176 &(CARES_INADDR_CAST(struct sockaddr_in *, next->ai_addr)->sin_addr),
177 sizeof(struct in_addr));
181 next = next->ai_next;
195 ares_free_hostent(hostent);
200 /* Truncated to at most *naddrttls entries */
201 *naddrttls = (naddrs > *naddrttls)?*naddrttls:naddrs;
204 ares__freeaddrinfo_cnames(ai.cnames);
205 ares__freeaddrinfo_nodes(ai.nodes);
211 ares__freeaddrinfo_cnames(ai.cnames);
212 ares__freeaddrinfo_nodes(ai.nodes);
213 ares_free(question_hostname);