reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
ares_search.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 <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <ctype.h>
21#include "ares.h"
22#include "ares_private.h"
23
25 /* Arguments passed to ares_search */
27 char *name; /* copied into an allocated buffer */
29 int type;
31 void *arg;
32
33 int status_as_is; /* error status from trying as-is */
34 int next_domain; /* next search domain to try */
35 int trying_as_is; /* current query is for name as-is */
36};
37
38static void search_callback(void *arg, int status, unsigned char *abuf,
39 int alen);
40static void end_squery(struct search_query *squery, int status,
41 unsigned char *abuf, int alen);
42static int cat_domain(const char *name, const char *domain, char **s);
43static int single_domain(ares_channel channel, const char *name, char **s);
44
45void ares_search(ares_channel channel, const char *name, int dnsclass,
46 int type, ares_callback callback, void *arg)
47{
48 struct search_query *squery;
49 char *s;
50 const char *p;
51 int status, ndots;
52
53 /* If name only yields one domain to search, then we don't have
54 * to keep extra state, so just do an ares_query().
55 */
56 status = single_domain(channel, name, &s);
57 if (status != ARES_SUCCESS)
58 {
59 callback(arg, status, NULL, 0);
60 return;
61 }
62 if (s)
63 {
65 free(s);
66 return;
67 }
68
69 /* Allocate a search_query structure to hold the state necessary for
70 * doing multiple lookups.
71 */
72 squery = malloc(sizeof(struct search_query));
73 if (!squery)
74 {
76 return;
77 }
78 squery->channel = channel;
79 squery->name = strdup(name);
80 if (!squery->name)
81 {
82 free(squery);
84 return;
85 }
86 squery->dnsclass = dnsclass;
87 squery->type = type;
88 squery->status_as_is = -1;
89 squery->callback = callback;
90 squery->arg = arg;
91
92 /* Count the number of dots in name. */
93 ndots = 0;
94 for (p = name; *p; p++)
95 {
96 if (*p == '.')
97 ndots++;
98 }
99
100 /* If ndots is at least the channel ndots threshold (usually 1),
101 * then we try the name as-is first. Otherwise, we try the name
102 * as-is last.
103 */
104 if (ndots >= channel->ndots)
105 {
106 /* Try the name as-is first. */
107 squery->next_domain = 0;
108 squery->trying_as_is = 1;
110 }
111 else
112 {
113 /* Try the name as-is last; start with the first search domain. */
114 squery->next_domain = 1;
115 squery->trying_as_is = 0;
116 status = cat_domain(name, channel->domains[0], &s);
117 if (status == ARES_SUCCESS)
118 {
120 free(s);
121 }
122 else
123 {
124 free(squery->name);
125 free(squery);
126 callback(arg, status, NULL, 0);
127 }
128 }
129}
130
131static void search_callback(void *arg, int status, unsigned char *abuf,
132 int alen)
133{
134 struct search_query *squery = (struct search_query *) arg;
135 ares_channel channel = squery->channel;
136 char *s;
137
138 /* Stop searching unless we got a non-fatal error. */
139 if (status != ARES_ENODATA && status != ARES_ESERVFAIL
140 && status != ARES_ENOTFOUND)
141 end_squery(squery, status, abuf, alen);
142 else
143 {
144 /* Save the status if we were trying as-is. */
145 if (squery->trying_as_is)
146 squery->status_as_is = status;
147 if (squery->next_domain < channel->ndomains)
148 {
149 /* Try the next domain. */
150 status = cat_domain(squery->name,
151 channel->domains[squery->next_domain], &s);
152 if (status != ARES_SUCCESS)
153 end_squery(squery, status, NULL, 0);
154 else
155 {
156 squery->trying_as_is = 0;
157 squery->next_domain++;
158 ares_query(channel, s, squery->dnsclass, squery->type,
160 free(s);
161 }
162 }
163 else if (squery->status_as_is == -1)
164 {
165 /* Try the name as-is at the end. */
166 squery->trying_as_is = 1;
167 ares_query(channel, squery->name, squery->dnsclass, squery->type,
169 }
170 else
171 end_squery(squery, squery->status_as_is, NULL, 0);
172 }
173}
174
175static void end_squery(struct search_query *squery, int status,
176 unsigned char *abuf, int alen)
177{
178 squery->callback(squery->arg, status, abuf, alen);
179 free(squery->name);
180 free(squery);
181}
182
183/* Concatenate two domains. */
184static int cat_domain(const char *name, const char *domain, char **s)
185{
186 size_t nlen = strlen(name), dlen = strlen(domain);
187
188 *s = malloc(nlen + 1 + dlen + 1);
189 if (!*s)
190 return ARES_ENOMEM;
191 memcpy(*s, name, nlen);
192 (*s)[nlen] = '.';
193 memcpy(*s + nlen + 1, domain, dlen);
194 (*s)[nlen + 1 + dlen] = 0;
195 return ARES_SUCCESS;
196}
197
198/* Determine if this name only yields one query. If it does, set *s to
199 * the string we should query, in an allocated buffer. If not, set *s
200 * to NULL.
201 */
202static int single_domain(ares_channel channel, const char* name, char** s)
203{
204 size_t len = strlen(name);
205 const char* hostaliases;
206 FILE* fp;
207 char* line = NULL;
208 int linesize, status;
209 const char* p, * q;
210
211 /* If the name contains a trailing dot, then the single query is the name
212 * sans the trailing dot.
213 */
214 if (name[len - 1] == '.')
215 {
216 *s = strdup(name);
217 return (*s) ? ARES_SUCCESS : ARES_ENOMEM;
218 }
219
220 if (!(channel->flags & ARES_FLAG_NOALIASES) && !strchr(name, '.'))
221 {
222 /* The name might be a host alias. */
223#ifdef UNDER_CE
225#elif defined(_MSC_VER)
226 char hostaliasBuf[256] = { 0 };
227 size_t requiredSize = 0;
228 getenv_s(&requiredSize, hostaliasBuf, sizeof(hostaliasBuf), "HOSTALIASES");
230#else
231 hostaliases = getenv("HOSTALIASES");
232#endif
233 if (hostaliases)
234 {
235#ifdef WIN32
236 fopen_s(&fp, hostaliases, "r");
237#else
238 fp = fopen(hostaliases, "r");
239#endif
240 if (fp)
241 {
242 while ((status = ares__read_line(fp, &line, &linesize))
243 == ARES_SUCCESS)
244 {
245 if (strncasecmp(line, name, len) != 0 ||
246 !isspace((unsigned char)line[len]))
247 continue;
248 p = line + len;
249 while (isspace((unsigned char)*p))
250 p++;
251 if (*p)
252 {
253 q = p + 1;
254 while (*q && !isspace((unsigned char)*q))
255 q++;
256 *s = malloc(q - p + 1);
257 if (*s)
258 {
259 memcpy(*s, p, q - p);
260 (*s)[q - p] = 0;
261 }
262 free(line);
263 fclose(fp);
264 return (*s) ? ARES_SUCCESS : ARES_ENOMEM;
265 }
266 }
267 free(line);
268 fclose(fp);
269 if (status != ARES_SUCCESS)
270 return status;
271 }
272 }
273 }
274
276 {
277 /* No domain search to do; just try the name as-is. */
278 *s = strdup(name);
279 return (*s) ? ARES_SUCCESS : ARES_ENOMEM;
280 }
281
282 *s = NULL;
283 return ARES_SUCCESS;
284}
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_FLAG_NOALIASES
Definition ares.h:108
#define ARES_ENODATA
Definition ares.h:82
#define ARES_ENOTFOUND
Definition ares.h:85
#define ARES_FLAG_NOSEARCH
Definition ares.h:107
void ares_query(ares_channel channel, const char *name, int dnsclass, int type, ares_callback callback, void *arg)
Definition ares_query.c:38
void(* ares_callback)(void *arg, int status, unsigned char *abuf, int alen)
Definition ares.h:172
#define ARES_ESERVFAIL
Definition ares.h:84
int ares__read_line(FILE *fp, char **buf, int *bufsize)
static void end_squery(struct search_query *squery, int status, unsigned char *abuf, int alen)
static int single_domain(ares_channel channel, const char *name, char **s)
static int cat_domain(const char *name, const char *domain, char **s)
void ares_search(ares_channel channel, const char *name, int dnsclass, int type, ares_callback callback, void *arg)
Definition ares_search.c:45
static void search_callback(void *arg, int status, unsigned char *abuf, int alen)
ares_channel channel
Definition ares_search.c:26
ares_callback callback
Definition ares_search.c:30
void list()
Definition userAdmin.cxx:66