ntp_rfc2553.c revision 1.1.1.3 1 1.1 kardel /*
2 1.1 kardel * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
3 1.1 kardel * All rights reserved.
4 1.1 kardel *
5 1.1 kardel * Redistribution and use in source and binary forms, with or without
6 1.1 kardel * modification, are permitted provided that the following conditions
7 1.1 kardel * are met:
8 1.1 kardel * 1. Redistributions of source code must retain the above copyright
9 1.1 kardel * notice, this list of conditions and the following disclaimer.
10 1.1 kardel * 2. Redistributions in binary form must reproduce the above copyright
11 1.1 kardel * notice, this list of conditions and the following disclaimer in the
12 1.1 kardel * documentation and/or other materials provided with the distribution.
13 1.1 kardel * 3. Neither the name of the project nor the names of its contributors
14 1.1 kardel * may be used to endorse or promote products derived from this software
15 1.1 kardel * without specific prior written permission.
16 1.1 kardel *
17 1.1 kardel * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18 1.1 kardel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 1.1 kardel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 1.1 kardel * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21 1.1 kardel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 1.1 kardel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 1.1 kardel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 1.1 kardel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 1.1 kardel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 1.1 kardel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 1.1 kardel * SUCH DAMAGE.
28 1.1 kardel */
29 1.1 kardel
30 1.1 kardel /*
31 1.1 kardel * Copyright (c) 1982, 1986, 1990, 1993
32 1.1 kardel * The Regents of the University of California. All rights reserved.
33 1.1 kardel *
34 1.1 kardel * Redistribution and use in source and binary forms, with or without
35 1.1 kardel * modification, are permitted provided that the following conditions
36 1.1 kardel * are met:
37 1.1 kardel * 1. Redistributions of source code must retain the above copyright
38 1.1 kardel * notice, this list of conditions and the following disclaimer.
39 1.1 kardel * 2. Redistributions in binary form must reproduce the above copyright
40 1.1 kardel * notice, this list of conditions and the following disclaimer in the
41 1.1 kardel * documentation and/or other materials provided with the distribution.
42 1.1 kardel * 3. All advertising materials mentioning features or use of this software
43 1.1 kardel * must display the following acknowledgement:
44 1.1 kardel * This product includes software developed by the University of
45 1.1 kardel * California, Berkeley and its contributors.
46 1.1 kardel * 4. Neither the name of the University nor the names of its contributors
47 1.1 kardel * may be used to endorse or promote products derived from this software
48 1.1 kardel * without specific prior written permission.
49 1.1 kardel *
50 1.1 kardel * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
51 1.1 kardel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52 1.1 kardel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53 1.1 kardel * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
54 1.1 kardel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55 1.1 kardel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56 1.1 kardel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57 1.1 kardel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
58 1.1 kardel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
59 1.1 kardel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60 1.1 kardel * SUCH DAMAGE.
61 1.1 kardel *
62 1.1 kardel */
63 1.1 kardel
64 1.1 kardel /*
65 1.1 kardel * Compatability shims with the rfc2553 API to simplify ntp.
66 1.1 kardel */
67 1.1 kardel
68 1.1 kardel #include <config.h>
69 1.1 kardel
70 1.1 kardel #include <sys/types.h>
71 1.1 kardel #include <ctype.h>
72 1.1 kardel #ifdef HAVE_SYS_SOCKET_H
73 1.1 kardel #include <sys/socket.h>
74 1.1 kardel #endif
75 1.1 kardel #include <isc/net.h>
76 1.1 kardel #ifdef HAVE_NETINET_IN_H
77 1.1 kardel #include <netinet/in.h>
78 1.1 kardel #endif
79 1.1 kardel #include "ntp_rfc2553.h"
80 1.1 kardel
81 1.1 kardel #include "ntpd.h"
82 1.1 kardel #include "ntp_malloc.h"
83 1.1 kardel #include "ntp_string.h"
84 1.1.1.2 christos #include "ntp_debug.h"
85 1.1.1.2 christos
86 1.1.1.2 christos
87 1.1.1.2 christos /*
88 1.1.1.2 christos * copy_addrinfo() - copy a single addrinfo to malloc()'d block.
89 1.1.1.2 christos * copy_addrinfo_list() - copy an addrinfo list to malloc()'d block.
90 1.1.1.2 christos *
91 1.1.1.2 christos * Copies an addrinfo list and its associated data to a contiguous block
92 1.1.1.2 christos * of storage from emalloc(). Callback routines invoked via
93 1.1.1.2 christos * getaddrinfo_sometime() have access to the resulting addrinfo list
94 1.1.1.2 christos * only until they return. This routine provides an easy way to make a
95 1.1.1.2 christos * persistent copy. Although the list provided to gai_sometime_callback
96 1.1.1.2 christos * routines is similarly contiguous, to keep this code usable in any
97 1.1.1.2 christos * context where we might want to duplicate an addrinfo list, it does
98 1.1.1.2 christos * not require the input list be contiguous.
99 1.1.1.2 christos *
100 1.1.1.2 christos * The returned list head pointer is passed to free() to release the
101 1.1.1.2 christos * entire list.
102 1.1.1.2 christos *
103 1.1.1.2 christos * In keeping with the rest of the NTP distribution, sockaddr_u is used
104 1.1.1.2 christos * in preference to struct sockaddr_storage, which is a member of the
105 1.1.1.2 christos * former union and so compatible.
106 1.1.1.2 christos *
107 1.1.1.2 christos * The rest of ntp_rfc2553.c is conditioned on ISC_PLATFORM_HAVEIPV6
108 1.1.1.2 christos * not being defined, copy_addrinfo_*() are exceptions.
109 1.1.1.2 christos */
110 1.1.1.2 christos struct addrinfo * copy_addrinfo_common(const struct addrinfo *, int
111 1.1.1.2 christos #ifdef EREALLOC_CALLSITE
112 1.1.1.2 christos ,
113 1.1.1.2 christos const char *, int
114 1.1.1.2 christos #endif
115 1.1.1.2 christos );
116 1.1.1.2 christos
117 1.1.1.2 christos
118 1.1.1.2 christos struct addrinfo *
119 1.1.1.2 christos copy_addrinfo_impl(
120 1.1.1.2 christos const struct addrinfo * src
121 1.1.1.2 christos #ifdef EREALLOC_CALLSITE
122 1.1.1.2 christos ,
123 1.1.1.2 christos const char * caller_file,
124 1.1.1.2 christos int caller_line
125 1.1.1.2 christos #endif
126 1.1.1.2 christos )
127 1.1.1.2 christos {
128 1.1.1.2 christos return copy_addrinfo_common(src, TRUE
129 1.1.1.2 christos #ifdef EREALLOC_CALLSITE
130 1.1.1.2 christos ,
131 1.1.1.2 christos caller_file, caller_line
132 1.1.1.2 christos #endif
133 1.1.1.2 christos );
134 1.1.1.2 christos }
135 1.1.1.2 christos
136 1.1.1.2 christos
137 1.1.1.2 christos struct addrinfo *
138 1.1.1.2 christos copy_addrinfo_list_impl(
139 1.1.1.2 christos const struct addrinfo * src
140 1.1.1.2 christos #ifdef EREALLOC_CALLSITE
141 1.1.1.2 christos ,
142 1.1.1.2 christos const char * caller_file,
143 1.1.1.2 christos int caller_line
144 1.1.1.2 christos #endif
145 1.1.1.2 christos )
146 1.1.1.2 christos {
147 1.1.1.2 christos return copy_addrinfo_common(src, FALSE
148 1.1.1.2 christos #ifdef EREALLOC_CALLSITE
149 1.1.1.2 christos ,
150 1.1.1.2 christos caller_file, caller_line
151 1.1.1.2 christos #endif
152 1.1.1.2 christos );
153 1.1.1.2 christos }
154 1.1.1.2 christos
155 1.1.1.2 christos
156 1.1.1.2 christos struct addrinfo *
157 1.1.1.2 christos copy_addrinfo_common(
158 1.1.1.2 christos const struct addrinfo * src,
159 1.1.1.2 christos int just_one
160 1.1.1.2 christos #ifdef EREALLOC_CALLSITE
161 1.1.1.2 christos ,
162 1.1.1.2 christos const char * caller_file,
163 1.1.1.2 christos int caller_line
164 1.1.1.2 christos #endif
165 1.1.1.2 christos )
166 1.1.1.2 christos {
167 1.1.1.2 christos const struct addrinfo * ai_src;
168 1.1.1.2 christos const struct addrinfo * ai_nxt;
169 1.1.1.2 christos struct addrinfo * ai_cpy;
170 1.1.1.2 christos struct addrinfo * dst;
171 1.1.1.2 christos sockaddr_u * psau;
172 1.1.1.2 christos char * pcanon;
173 1.1.1.2 christos u_int elements;
174 1.1.1.2 christos size_t octets;
175 1.1.1.2 christos size_t canons_octets;
176 1.1.1.2 christos size_t str_octets;
177 1.1.1.2 christos
178 1.1.1.2 christos elements = 0;
179 1.1.1.2 christos canons_octets = 0;
180 1.1.1.2 christos
181 1.1.1.2 christos for (ai_src = src; NULL != ai_src; ai_src = ai_nxt) {
182 1.1.1.2 christos if (just_one)
183 1.1.1.2 christos ai_nxt = NULL;
184 1.1.1.2 christos else
185 1.1.1.2 christos ai_nxt = ai_src->ai_next;
186 1.1.1.2 christos ++elements;
187 1.1.1.2 christos if (NULL != ai_src->ai_canonname)
188 1.1.1.2 christos canons_octets += 1 + strlen(ai_src->ai_canonname);
189 1.1.1.2 christos }
190 1.1.1.2 christos
191 1.1.1.2 christos octets = elements * (sizeof(*ai_cpy) + sizeof(*psau));
192 1.1.1.2 christos octets += canons_octets;
193 1.1.1.2 christos
194 1.1.1.2 christos dst = erealloczsite(NULL, octets, 0, TRUE, caller_file,
195 1.1.1.2 christos caller_line);
196 1.1.1.2 christos ai_cpy = dst;
197 1.1.1.2 christos psau = (void *)(ai_cpy + elements);
198 1.1.1.2 christos pcanon = (void *)(psau + elements);
199 1.1.1.2 christos
200 1.1.1.2 christos for (ai_src = src; NULL != ai_src; ai_src = ai_nxt) {
201 1.1.1.2 christos if (just_one)
202 1.1.1.2 christos ai_nxt = NULL;
203 1.1.1.2 christos else
204 1.1.1.2 christos ai_nxt = ai_src->ai_next;
205 1.1.1.2 christos *ai_cpy = *ai_src;
206 1.1.1.2 christos REQUIRE(ai_src->ai_addrlen <= sizeof(sockaddr_u));
207 1.1.1.2 christos memcpy(psau, ai_src->ai_addr, ai_src->ai_addrlen);
208 1.1.1.2 christos ai_cpy->ai_addr = &psau->sa;
209 1.1.1.2 christos ++psau;
210 1.1.1.2 christos if (NULL != ai_cpy->ai_canonname) {
211 1.1.1.2 christos ai_cpy->ai_canonname = pcanon;
212 1.1.1.2 christos str_octets = 1 + strlen(ai_src->ai_canonname);
213 1.1.1.2 christos memcpy(pcanon, ai_src->ai_canonname, str_octets);
214 1.1.1.2 christos pcanon += str_octets;
215 1.1.1.2 christos }
216 1.1.1.2 christos if (NULL != ai_cpy->ai_next) {
217 1.1.1.2 christos if (just_one)
218 1.1.1.2 christos ai_cpy->ai_next = NULL;
219 1.1.1.2 christos else
220 1.1.1.2 christos ai_cpy->ai_next = ai_cpy + 1;
221 1.1.1.2 christos }
222 1.1.1.2 christos ++ai_cpy;
223 1.1.1.2 christos }
224 1.1.1.2 christos NTP_ENSURE(pcanon == ((char *)dst + octets));
225 1.1.1.2 christos
226 1.1.1.2 christos return dst;
227 1.1.1.2 christos }
228 1.1.1.2 christos
229 1.1 kardel
230 1.1 kardel #ifndef ISC_PLATFORM_HAVEIPV6
231 1.1 kardel
232 1.1 kardel static char *ai_errlist[] = {
233 1.1 kardel "Success",
234 1.1 kardel "Address family for hostname not supported", /* EAI_ADDRFAMILY */
235 1.1 kardel "Temporary failure in name resolution", /* EAI_AGAIN */
236 1.1 kardel "Invalid value for ai_flags", /* EAI_BADFLAGS */
237 1.1 kardel "Non-recoverable failure in name resolution", /* EAI_FAIL */
238 1.1 kardel "ai_family not supported", /* EAI_FAMILY */
239 1.1 kardel "Memory allocation failure", /* EAI_MEMORY */
240 1.1 kardel "No address associated with hostname", /* EAI_NODATA */
241 1.1 kardel "hostname nor servname provided, or not known", /* EAI_NONAME */
242 1.1 kardel "servname not supported for ai_socktype", /* EAI_SERVICE */
243 1.1 kardel "ai_socktype not supported", /* EAI_SOCKTYPE */
244 1.1 kardel "System error returned in errno", /* EAI_SYSTEM */
245 1.1 kardel "Invalid value for hints", /* EAI_BADHINTS */
246 1.1 kardel "Resolved protocol is unknown", /* EAI_PROTOCOL */
247 1.1 kardel "Unknown error", /* EAI_MAX */
248 1.1 kardel };
249 1.1 kardel
250 1.1 kardel /*
251 1.1 kardel * Local declaration
252 1.1 kardel */
253 1.1 kardel int
254 1.1 kardel DNSlookup_name(
255 1.1 kardel const char *name,
256 1.1 kardel int ai_family,
257 1.1 kardel struct hostent **Addresses
258 1.1 kardel );
259 1.1 kardel
260 1.1 kardel #ifndef SYS_WINNT
261 1.1 kardel /*
262 1.1 kardel * Encapsulate gethostbyname to control the error code
263 1.1 kardel */
264 1.1 kardel int
265 1.1 kardel DNSlookup_name(
266 1.1 kardel const char *name,
267 1.1 kardel int ai_family,
268 1.1 kardel struct hostent **Addresses
269 1.1 kardel )
270 1.1 kardel {
271 1.1 kardel *Addresses = gethostbyname(name);
272 1.1 kardel return (h_errno);
273 1.1 kardel }
274 1.1 kardel #endif
275 1.1 kardel
276 1.1 kardel static int do_nodename (const char *nodename, struct addrinfo *ai,
277 1.1 kardel const struct addrinfo *hints);
278 1.1 kardel
279 1.1 kardel int
280 1.1 kardel getaddrinfo (const char *nodename, const char *servname,
281 1.1 kardel const struct addrinfo *hints, struct addrinfo **res)
282 1.1 kardel {
283 1.1 kardel int rval;
284 1.1 kardel struct servent *sp;
285 1.1 kardel struct addrinfo *ai = NULL;
286 1.1 kardel int port;
287 1.1 kardel const char *proto = NULL;
288 1.1 kardel int family, socktype, flags, protocol;
289 1.1 kardel
290 1.1 kardel
291 1.1 kardel /*
292 1.1 kardel * If no name is provide just return an error
293 1.1 kardel */
294 1.1 kardel if (nodename == NULL && servname == NULL)
295 1.1 kardel return (EAI_NONAME);
296 1.1 kardel
297 1.1 kardel ai = calloc(sizeof(struct addrinfo), 1);
298 1.1 kardel if (ai == NULL)
299 1.1 kardel return (EAI_MEMORY);
300 1.1 kardel
301 1.1 kardel /*
302 1.1 kardel * Copy default values from hints, if available
303 1.1 kardel */
304 1.1 kardel if (hints != NULL) {
305 1.1 kardel ai->ai_flags = hints->ai_flags;
306 1.1 kardel ai->ai_family = hints->ai_family;
307 1.1 kardel ai->ai_socktype = hints->ai_socktype;
308 1.1 kardel ai->ai_protocol = hints->ai_protocol;
309 1.1 kardel
310 1.1 kardel family = hints->ai_family;
311 1.1 kardel socktype = hints->ai_socktype;
312 1.1 kardel protocol = hints->ai_protocol;
313 1.1 kardel flags = hints->ai_flags;
314 1.1 kardel
315 1.1 kardel switch (family) {
316 1.1 kardel case AF_UNSPEC:
317 1.1 kardel switch (hints->ai_socktype) {
318 1.1 kardel case SOCK_STREAM:
319 1.1 kardel proto = "tcp";
320 1.1 kardel break;
321 1.1 kardel case SOCK_DGRAM:
322 1.1 kardel proto = "udp";
323 1.1 kardel break;
324 1.1 kardel }
325 1.1 kardel break;
326 1.1 kardel case AF_INET:
327 1.1 kardel case AF_INET6:
328 1.1 kardel switch (hints->ai_socktype) {
329 1.1 kardel case 0:
330 1.1 kardel break;
331 1.1 kardel case SOCK_STREAM:
332 1.1 kardel proto = "tcp";
333 1.1 kardel break;
334 1.1 kardel case SOCK_DGRAM:
335 1.1 kardel proto = "udp";
336 1.1 kardel break;
337 1.1 kardel case SOCK_RAW:
338 1.1 kardel break;
339 1.1 kardel default:
340 1.1 kardel return (EAI_SOCKTYPE);
341 1.1 kardel }
342 1.1 kardel break;
343 1.1 kardel #ifdef AF_LOCAL
344 1.1 kardel case AF_LOCAL:
345 1.1 kardel switch (hints->ai_socktype) {
346 1.1 kardel case 0:
347 1.1 kardel break;
348 1.1 kardel case SOCK_STREAM:
349 1.1 kardel break;
350 1.1 kardel case SOCK_DGRAM:
351 1.1 kardel break;
352 1.1 kardel default:
353 1.1 kardel return (EAI_SOCKTYPE);
354 1.1 kardel }
355 1.1 kardel break;
356 1.1 kardel #endif
357 1.1 kardel default:
358 1.1 kardel return (EAI_FAMILY);
359 1.1 kardel }
360 1.1 kardel } else {
361 1.1 kardel protocol = 0;
362 1.1 kardel family = 0;
363 1.1 kardel socktype = 0;
364 1.1 kardel flags = 0;
365 1.1 kardel }
366 1.1 kardel
367 1.1 kardel rval = do_nodename(nodename, ai, hints);
368 1.1 kardel if (rval != 0) {
369 1.1 kardel freeaddrinfo(ai);
370 1.1 kardel return (rval);
371 1.1 kardel }
372 1.1 kardel
373 1.1 kardel /*
374 1.1 kardel * First, look up the service name (port) if it was
375 1.1 kardel * requested. If the socket type wasn't specified, then
376 1.1 kardel * try and figure it out.
377 1.1 kardel */
378 1.1 kardel if (servname != NULL) {
379 1.1 kardel char *e;
380 1.1 kardel
381 1.1 kardel port = strtol(servname, &e, 10);
382 1.1 kardel if (*e == '\0') {
383 1.1 kardel if (socktype == 0)
384 1.1 kardel return (EAI_SOCKTYPE);
385 1.1 kardel if (port < 0 || port > 65535)
386 1.1 kardel return (EAI_SERVICE);
387 1.1 kardel port = htons((unsigned short) port);
388 1.1 kardel } else {
389 1.1 kardel sp = getservbyname(servname, proto);
390 1.1 kardel if (sp == NULL)
391 1.1 kardel return (EAI_SERVICE);
392 1.1 kardel port = sp->s_port;
393 1.1 kardel if (socktype == 0) {
394 1.1 kardel if (strcmp(sp->s_proto, "tcp") == 0)
395 1.1 kardel socktype = SOCK_STREAM;
396 1.1 kardel else if (strcmp(sp->s_proto, "udp") == 0)
397 1.1 kardel socktype = SOCK_DGRAM;
398 1.1 kardel }
399 1.1 kardel }
400 1.1 kardel } else
401 1.1 kardel port = 0;
402 1.1 kardel
403 1.1 kardel /*
404 1.1 kardel *
405 1.1 kardel * Set up the port number
406 1.1 kardel */
407 1.1 kardel if (ai->ai_family == AF_INET)
408 1.1 kardel ((struct sockaddr_in *)ai->ai_addr)->sin_port = (unsigned short) port;
409 1.1 kardel else if (ai->ai_family == AF_INET6)
410 1.1 kardel ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port = (unsigned short) port;
411 1.1 kardel *res = ai;
412 1.1 kardel return (0);
413 1.1 kardel }
414 1.1 kardel
415 1.1 kardel void
416 1.1 kardel freeaddrinfo(struct addrinfo *ai)
417 1.1 kardel {
418 1.1 kardel if (ai->ai_canonname != NULL)
419 1.1 kardel {
420 1.1 kardel free(ai->ai_canonname);
421 1.1 kardel ai->ai_canonname = NULL;
422 1.1 kardel }
423 1.1 kardel if (ai->ai_addr != NULL)
424 1.1 kardel {
425 1.1 kardel free(ai->ai_addr);
426 1.1 kardel ai->ai_addr = NULL;
427 1.1 kardel }
428 1.1 kardel free(ai);
429 1.1 kardel ai = NULL;
430 1.1 kardel }
431 1.1 kardel
432 1.1 kardel int
433 1.1 kardel getnameinfo (const struct sockaddr *sa, u_int salen, char *host,
434 1.1 kardel size_t hostlen, char *serv, size_t servlen, int flags)
435 1.1 kardel {
436 1.1 kardel struct hostent *hp;
437 1.1 kardel
438 1.1 kardel if (sa->sa_family != AF_INET)
439 1.1 kardel return (EAI_FAMILY);
440 1.1 kardel hp = gethostbyaddr(
441 1.1 kardel (const char *)&((const struct sockaddr_in *)sa)->sin_addr,
442 1.1 kardel 4, AF_INET);
443 1.1 kardel if (hp == NULL) {
444 1.1 kardel if (h_errno == TRY_AGAIN)
445 1.1 kardel return (EAI_AGAIN);
446 1.1 kardel else
447 1.1 kardel return (EAI_FAIL);
448 1.1 kardel }
449 1.1.1.2 christos if (host != NULL && hostlen > 0)
450 1.1.1.2 christos strlcpy(host, hp->h_name, hostlen);
451 1.1 kardel return (0);
452 1.1 kardel }
453 1.1 kardel
454 1.1 kardel char *
455 1.1 kardel gai_strerror(int ecode)
456 1.1 kardel {
457 1.1 kardel if (ecode < 0 || ecode > EAI_MAX)
458 1.1 kardel ecode = EAI_MAX;
459 1.1 kardel return ai_errlist[ecode];
460 1.1 kardel }
461 1.1 kardel
462 1.1 kardel static int
463 1.1 kardel do_nodename(
464 1.1 kardel const char *nodename,
465 1.1 kardel struct addrinfo *ai,
466 1.1 kardel const struct addrinfo *hints)
467 1.1 kardel {
468 1.1 kardel struct hostent *hp = NULL;
469 1.1 kardel struct sockaddr_in *sockin;
470 1.1 kardel struct sockaddr_in6 *sockin6;
471 1.1 kardel int errval;
472 1.1 kardel
473 1.1 kardel ai->ai_addr = calloc(sizeof(struct sockaddr_storage), 1);
474 1.1 kardel if (ai->ai_addr == NULL)
475 1.1 kardel return (EAI_MEMORY);
476 1.1 kardel
477 1.1 kardel /*
478 1.1 kardel * For an empty node name just use the wildcard.
479 1.1 kardel * NOTE: We need to assume that the address family is
480 1.1 kardel * set elsewhere so that we can set the appropriate wildcard
481 1.1 kardel */
482 1.1 kardel if (nodename == NULL) {
483 1.1 kardel ai->ai_addrlen = sizeof(struct sockaddr_storage);
484 1.1 kardel if (ai->ai_family == AF_INET)
485 1.1 kardel {
486 1.1 kardel sockin = (struct sockaddr_in *)ai->ai_addr;
487 1.1 kardel sockin->sin_family = (short) ai->ai_family;
488 1.1 kardel sockin->sin_addr.s_addr = htonl(INADDR_ANY);
489 1.1 kardel }
490 1.1 kardel else
491 1.1 kardel {
492 1.1 kardel sockin6 = (struct sockaddr_in6 *)ai->ai_addr;
493 1.1 kardel sockin6->sin6_family = (short) ai->ai_family;
494 1.1 kardel /*
495 1.1 kardel * we have already zeroed out the address
496 1.1 kardel * so we don't actually need to do this
497 1.1 kardel * This assignment is causing problems so
498 1.1 kardel * we don't do what this would do.
499 1.1 kardel sockin6->sin6_addr = in6addr_any;
500 1.1 kardel */
501 1.1 kardel }
502 1.1 kardel #ifdef ISC_PLATFORM_HAVESALEN
503 1.1 kardel ai->ai_addr->sa_len = SOCKLEN(ai->ai_addr);
504 1.1 kardel #endif
505 1.1 kardel
506 1.1 kardel return (0);
507 1.1 kardel }
508 1.1 kardel
509 1.1 kardel /*
510 1.1 kardel * See if we have an IPv6 address
511 1.1 kardel */
512 1.1 kardel if(strchr(nodename, ':') != NULL) {
513 1.1 kardel if (inet_pton(AF_INET6, nodename,
514 1.1 kardel &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr) == 1) {
515 1.1 kardel ((struct sockaddr_in6 *)ai->ai_addr)->sin6_family = AF_INET6;
516 1.1 kardel ai->ai_family = AF_INET6;
517 1.1 kardel ai->ai_addrlen = sizeof(struct sockaddr_in6);
518 1.1 kardel return (0);
519 1.1 kardel }
520 1.1 kardel }
521 1.1 kardel
522 1.1 kardel /*
523 1.1 kardel * See if we have an IPv4 address
524 1.1 kardel */
525 1.1 kardel if (inet_pton(AF_INET, nodename,
526 1.1 kardel &((struct sockaddr_in *)ai->ai_addr)->sin_addr) == 1) {
527 1.1 kardel ((struct sockaddr *)ai->ai_addr)->sa_family = AF_INET;
528 1.1 kardel ai->ai_family = AF_INET;
529 1.1 kardel ai->ai_addrlen = sizeof(struct sockaddr_in);
530 1.1 kardel return (0);
531 1.1 kardel }
532 1.1 kardel
533 1.1 kardel /*
534 1.1 kardel * If the numeric host flag is set, don't attempt resolution
535 1.1 kardel */
536 1.1 kardel if (hints != NULL && (hints->ai_flags & AI_NUMERICHOST))
537 1.1 kardel return (EAI_NONAME);
538 1.1 kardel
539 1.1 kardel /*
540 1.1 kardel * Look for a name
541 1.1 kardel */
542 1.1 kardel
543 1.1 kardel errval = DNSlookup_name(nodename, AF_INET, &hp);
544 1.1 kardel
545 1.1 kardel if (hp == NULL) {
546 1.1 kardel if (errval == TRY_AGAIN || errval == EAI_AGAIN)
547 1.1 kardel return (EAI_AGAIN);
548 1.1 kardel else if (errval == EAI_NONAME) {
549 1.1 kardel if (inet_pton(AF_INET, nodename,
550 1.1 kardel &((struct sockaddr_in *)ai->ai_addr)->sin_addr) == 1) {
551 1.1 kardel ((struct sockaddr *)ai->ai_addr)->sa_family = AF_INET;
552 1.1 kardel ai->ai_family = AF_INET;
553 1.1 kardel ai->ai_addrlen = sizeof(struct sockaddr_in);
554 1.1 kardel return (0);
555 1.1 kardel }
556 1.1 kardel return (errval);
557 1.1 kardel }
558 1.1 kardel else
559 1.1 kardel {
560 1.1 kardel return (errval);
561 1.1 kardel }
562 1.1 kardel }
563 1.1 kardel ai->ai_family = hp->h_addrtype;
564 1.1 kardel ai->ai_addrlen = sizeof(struct sockaddr);
565 1.1 kardel sockin = (struct sockaddr_in *)ai->ai_addr;
566 1.1 kardel memcpy(&sockin->sin_addr, hp->h_addr, hp->h_length);
567 1.1 kardel ai->ai_addr->sa_family = hp->h_addrtype;
568 1.1 kardel #ifdef ISC_PLATFORM_HAVESALEN
569 1.1 kardel ai->ai_addr->sa_len = sizeof(struct sockaddr);
570 1.1 kardel #endif
571 1.1.1.2 christos if (hints != NULL && (hints->ai_flags & AI_CANONNAME))
572 1.1 kardel ai->ai_canonname = estrdup(hp->h_name);
573 1.1 kardel return (0);
574 1.1 kardel }
575 1.1 kardel
576 1.1 kardel #endif /* !ISC_PLATFORM_HAVEIPV6 */
577