reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
ares_gethostbyname.c
Go to the documentation of this file.
1/* Copyright 1998 by the Massachusetts Institute of Technology.
2 *
3 * Permission to use, copy, modify, and distribute this
4 * software and its documentation for any purpose and without
5 * fee is hereby granted, provided that the above copyright
6 * notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting
8 * documentation, and that the name of M.I.T. not be used in
9 * advertising or publicity pertaining to distribution of the
10 * software without specific, written prior permission.
11 * M.I.T. makes no representations about the suitability of
12 * this software for any purpose. It is provided "as is"
13 * without express or implied warranty.
14 */
15
16
17#include <sys/types.h>
18#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
21#include <ctype.h>
22
23#ifndef WIN32
24#include <sys/socket.h>
25#include <netinet/in.h>
26#include <arpa/inet.h>
27#ifndef __CYGWIN__
28# include "ares_nameser.h"
29#endif
30#include <netdb.h>
31#endif
32
33#include "ares.h"
34#include "ares_private.h"
35#include "ares_local.h"
36
37struct host_query {
38 /* Arguments passed to ares_gethostbyname() */
40 char *name;
42 void *arg;
43
44 const char *remaining_lookups;
45};
46
47static void next_lookup(struct host_query *hquery);
48static void host_callback(void *arg, int status, unsigned char *abuf,
49 int alen);
50static void end_hquery(struct host_query *hquery, int status,
51 struct hostent *host);
52static int fake_hostent(const char *name, ares_host_callback callback,
53 void *arg);
54static int file_lookup(const char *name, struct hostent **host);
55static void sort_addresses(struct hostent *host, struct apattern *sortlist,
56 int nsort);
57static int get_address_index(struct in_addr *addr, struct apattern *sortlist,
58 int nsort);
59
60#ifdef WIN32
61extern char w32hostspath[];
62#endif
63
64void ares_gethostbyname(ares_channel channel, const char* name, int family,
66{
67 struct host_query* hquery;
68
69 /* See if request can be handled by local pseudo-domain DNS */
71 {
72 return;
73 }
74
75 /* Right now we only know how to look up Internet addresses. */
76 if (family != AF_INET)
77 {
79 return;
80 }
81
83 return;
84
85 /* Allocate and fill in the host query structure. */
86 hquery = malloc(sizeof(struct host_query));
87 if (!hquery)
88 {
90 return;
91 }
92 hquery->channel = channel;
93 hquery->name = strdup(name);
94 if (!hquery->name)
95 {
96 free(hquery);
98 return;
99 }
100 hquery->callback = callback;
101 hquery->arg = arg;
102 hquery->remaining_lookups = channel->lookups;
103
104 /* Start performing lookups according to channel->lookups. */
106}
107
108static void next_lookup(struct host_query* hquery)
109{
110 int status;
111 const char* p;
112 struct hostent* host;
113
114 for (p = hquery->remaining_lookups; *p; p++)
115 {
116 switch (*p)
117 {
118 case 'b':
119 /* DNS lookup */
120 hquery->remaining_lookups = p + 1;
121 ares_search(hquery->channel, hquery->name, C_IN, T_A, host_callback,
122 hquery);
123 return;
124
125 case 'f':
126 /* Host file lookup */
127 status = file_lookup(hquery->name, &host);
128 if (status != ARES_ENOTFOUND)
129 {
130 end_hquery(hquery, status, host);
131 return;
132 }
133 break;
134 }
135 }
137}
138
139static void host_callback(void* arg, int status, unsigned char* abuf, int alen)
140{
141 struct host_query* hquery = (struct host_query*)arg;
142 ares_channel channel = hquery->channel;
143 struct hostent* host;
144
145 if (status == ARES_SUCCESS)
146 {
147 status = ares_parse_a_reply(abuf, alen, &host);
148 if (host && channel->nsort)
149 sort_addresses(host, channel->sortlist, channel->nsort);
150 end_hquery(hquery, status, host);
151 }
152 else if (status == ARES_EDESTRUCTION)
153 end_hquery(hquery, status, NULL);
154 else
156}
157
158static void end_hquery(struct host_query* hquery, int status,
159 struct hostent* host)
160{
161 hquery->callback(hquery->arg, status, host);
162 if (host)
163 ares_free_hostent(host);
164 free(hquery->name);
165 free(hquery);
166}
167
168/* If the name looks like an IP address, fake up a host entry, end the
169 * query immediately, and return true. Otherwise return false.
170 */
171static int fake_hostent(const char* name, ares_host_callback callback,
172 void* arg)
173{
174 struct in_addr addr;
175 struct hostent hostent;
176 const char* p;
177 char* aliases[1] = { NULL };
178 char* addrs[2];
179
180 /* It only looks like an IP address if it's all numbers and dots. */
181 for (p = name; *p; p++)
182 {
183 if (!isdigit((unsigned char)*p) && *p != '.')
184 return 0;
185 }
186
187 /* It also only looks like an IP address if it's non-zero-length and
188 * doesn't end with a dot.
189 */
190 if (p == name || *(p - 1) == '.')
191 return 0;
192
193 /* It looks like an IP address. Figure out what IP address it is. */
194#if defined(_MSC_VER) && _MSC_VER >= 1800 /* removing compilation warning in VS2013+ */
195 inet_pton(AF_INET, name, &addr.s_addr);
196#else
197 addr.s_addr = inet_addr(name);
198#endif
199
200 if (addr.s_addr == INADDR_NONE)
201 {
203 return 1;
204 }
205
206 /* Duplicate the name, to avoid a constness violation. */
207 hostent.h_name = strdup(name);
208 if (!hostent.h_name)
209 {
211 return 1;
212 }
213
214 /* Fill in the rest of the host structure and terminate the query. */
215 addrs[0] = (char*)&addr;
216 addrs[1] = NULL;
217 hostent.h_aliases = aliases;
218 hostent.h_addrtype = AF_INET;
219 hostent.h_length = sizeof(struct in_addr);
220 hostent.h_addr_list = addrs;
222
223 free(hostent.h_name);
224 return 1;
225}
226
227int hostfile_lookup(const char* name, struct hostent** host)
228{
229 return file_lookup(name, host);
230}
231
232static int file_lookup(const char* name, struct hostent** host)
233{
234 FILE* fp;
235 char** alias;
236 int status;
237
238#ifdef WIN32
239 fopen_s(&fp, w32hostspath, "r");
240#else
241 fp = fopen(PATH_HOSTS, "r");
242#endif
243 if (!fp)
244 return ARES_ENOTFOUND;
245
246 while ((status = ares__get_hostent(fp, host)) == ARES_SUCCESS)
247 {
248 if (strcasecmp((*host)->h_name, name) == 0)
249 break;
250 for (alias = (*host)->h_aliases; *alias; alias++)
251 {
252 if (strcasecmp(*alias, name) == 0)
253 break;
254 }
255 if (*alias)
256 break;
257 ares_free_hostent(*host);
258 }
259 fclose(fp);
260 if (status == ARES_EOF)
261 status = ARES_ENOTFOUND;
262 if (status != ARES_SUCCESS)
263 *host = NULL;
264 return status;
265}
266
267static void sort_addresses(struct hostent* host, struct apattern* sortlist,
268 int nsort)
269{
270 struct in_addr a1, a2;
271 int i1, i2, ind1, ind2;
272
273 /* This is a simple insertion sort, not optimized at all. i1 walks
274 * through the address list, with the loop invariant that everything
275 * to the left of i1 is sorted. In the loop body, the value at i1 is moved
276 * back through the list (via i2) until it is in sorted order.
277 */
278 for (i1 = 0; host->h_addr_list[i1]; i1++)
279 {
280 memcpy(&a1, host->h_addr_list[i1], sizeof(struct in_addr));
281 ind1 = get_address_index(&a1, sortlist, nsort);
282 for (i2 = i1 - 1; i2 >= 0; i2--)
283 {
284 memcpy(&a2, host->h_addr_list[i2], sizeof(struct in_addr));
285 ind2 = get_address_index(&a2, sortlist, nsort);
286 if (ind2 <= ind1)
287 break;
288 memcpy(host->h_addr_list[i2 + 1], &a2, sizeof(struct in_addr));
289 }
290 memcpy(host->h_addr_list[i2 + 1], &a1, sizeof(struct in_addr));
291 }
292}
293
294/* Find the first entry in sortlist which matches addr. Return nsort
295 * if none of them match.
296 */
297static int get_address_index(struct in_addr* addr, struct apattern* sortlist,
298 int nsort)
299{
300 int i;
301
302 for (i = 0; i < nsort; i++)
303 {
304 if ((addr->s_addr & sortlist[i].mask.s_addr) == sortlist[i].addr.s_addr)
305 break;
306 }
307 return i;
308}
#define INADDR_NONE
Definition adig.c:51
static void callback(void *arg, int status, unsigned char *abuf, int alen)
Definition adig.c:388
#define ARES_SUCCESS
Definition ares.h:79
#define ARES_ENOMEM
Definition ares.h:98
#define ARES_EOF
Definition ares.h:96
#define ARES_ENOTFOUND
Definition ares.h:85
void ares_search(ares_channel channel, const char *name, int dnsclass, int type, ares_callback callback, void *arg)
Definition ares_search.c:45
int ares_parse_a_reply(const unsigned char *abuf, int alen, struct hostent **host)
#define ARES_EDESTRUCTION
Definition ares.h:99
#define ARES_ENOTIMP
Definition ares.h:86
#define ARES_EBADNAME
Definition ares.h:91
void ares_free_hostent(struct hostent *host)
void(* ares_host_callback)(void *arg, int status, struct hostent *hostent)
Definition ares.h:174
int ares__get_hostent(FILE *fp, struct hostent **host)
static void end_hquery(struct host_query *hquery, int status, struct hostent *host)
void ares_gethostbyname(ares_channel channel, const char *name, int family, ares_host_callback callback, void *arg)
static void next_lookup(struct host_query *hquery)
static int get_address_index(struct in_addr *addr, struct apattern *sortlist, int nsort)
static void host_callback(void *arg, int status, unsigned char *abuf, int alen)
static void sort_addresses(struct hostent *host, struct apattern *sortlist, int nsort)
static int fake_hostent(const char *name, ares_host_callback callback, void *arg)
int hostfile_lookup(const char *name, struct hostent **host)
static int file_lookup(const char *name, struct hostent **host)
int ares_local_gethostbyname(ares_channel channel, const char *name, int family, ares_host_callback callback, void *arg)
Definition ares_local.c:6
#define C_IN
#define PATH_HOSTS
#define T_A
Definition compat.hxx:152
struct in_addr mask
struct in_addr addr
struct apattern * sortlist
const char * remaining_lookups
ares_channel channel
ares_host_callback callback
void list()
Definition userAdmin.cxx:66