ntp_rfc2553.c revision 1.1.1.8 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.6 christos DEBUG_INSIST(ai_cpy->ai_canonname == ai_src->ai_canonname);
207 1.1.1.6 christos INSIST(ai_src->ai_addrlen <= sizeof(sockaddr_u));
208 1.1.1.2 christos memcpy(psau, ai_src->ai_addr, ai_src->ai_addrlen);
209 1.1.1.2 christos ai_cpy->ai_addr = &psau->sa;
210 1.1.1.2 christos ++psau;
211 1.1.1.6 christos if (NULL != ai_src->ai_canonname) {
212 1.1.1.2 christos ai_cpy->ai_canonname = pcanon;
213 1.1.1.2 christos str_octets = 1 + strlen(ai_src->ai_canonname);
214 1.1.1.2 christos memcpy(pcanon, ai_src->ai_canonname, str_octets);
215 1.1.1.2 christos pcanon += str_octets;
216 1.1.1.2 christos }
217 1.1.1.2 christos if (NULL != ai_cpy->ai_next) {
218 1.1.1.2 christos if (just_one)
219 1.1.1.2 christos ai_cpy->ai_next = NULL;
220 1.1.1.2 christos else
221 1.1.1.2 christos ai_cpy->ai_next = ai_cpy + 1;
222 1.1.1.2 christos }
223 1.1.1.2 christos ++ai_cpy;
224 1.1.1.2 christos }
225 1.1.1.5 christos ENSURE(pcanon == ((char *)dst + octets));
226 1.1.1.2 christos
227 1.1.1.2 christos return dst;
228 1.1.1.2 christos }
229 1.1.1.2 christos
230 1.1 kardel
231 1.1 kardel #ifndef ISC_PLATFORM_HAVEIPV6
232 1.1 kardel
233 1.1 kardel static char *ai_errlist[] = {
234 1.1 kardel "Success",
235 1.1 kardel "Address family for hostname not supported", /* EAI_ADDRFAMILY */
236 1.1 kardel "Temporary failure in name resolution", /* EAI_AGAIN */
237 1.1 kardel "Invalid value for ai_flags", /* EAI_BADFLAGS */
238 1.1 kardel "Non-recoverable failure in name resolution", /* EAI_FAIL */
239 1.1 kardel "ai_family not supported", /* EAI_FAMILY */
240 1.1 kardel "Memory allocation failure", /* EAI_MEMORY */
241 1.1 kardel "No address associated with hostname", /* EAI_NODATA */
242 1.1 kardel "hostname nor servname provided, or not known", /* EAI_NONAME */
243 1.1 kardel "servname not supported for ai_socktype", /* EAI_SERVICE */
244 1.1 kardel "ai_socktype not supported", /* EAI_SOCKTYPE */
245 1.1 kardel "System error returned in errno", /* EAI_SYSTEM */
246 1.1 kardel "Invalid value for hints", /* EAI_BADHINTS */
247 1.1 kardel "Resolved protocol is unknown", /* EAI_PROTOCOL */
248 1.1 kardel "Unknown error", /* EAI_MAX */
249 1.1 kardel };
250 1.1 kardel
251 1.1 kardel /*
252 1.1 kardel * Local declaration
253 1.1 kardel */
254 1.1 kardel int
255 1.1 kardel DNSlookup_name(
256 1.1 kardel const char *name,
257 1.1 kardel int ai_family,
258 1.1 kardel struct hostent **Addresses
259 1.1 kardel );
260 1.1 kardel
261 1.1 kardel #ifndef SYS_WINNT
262 1.1 kardel /*
263 1.1 kardel * Encapsulate gethostbyname to control the error code
264 1.1 kardel */
265 1.1 kardel int
266 1.1 kardel DNSlookup_name(
267 1.1 kardel const char *name,
268 1.1 kardel int ai_family,
269 1.1 kardel struct hostent **Addresses
270 1.1 kardel )
271 1.1 kardel {
272 1.1 kardel *Addresses = gethostbyname(name);
273 1.1 kardel return (h_errno);
274 1.1 kardel }
275 1.1 kardel #endif
276 1.1 kardel
277 1.1 kardel static int do_nodename (const char *nodename, struct addrinfo *ai,
278 1.1 kardel const struct addrinfo *hints);
279 1.1 kardel
280 1.1 kardel int
281 1.1 kardel getaddrinfo (const char *nodename, const char *servname,
282 1.1 kardel const struct addrinfo *hints, struct addrinfo **res)
283 1.1 kardel {
284 1.1 kardel int rval;
285 1.1 kardel struct servent *sp;
286 1.1 kardel struct addrinfo *ai = NULL;
287 1.1 kardel int port;
288 1.1 kardel const char *proto = NULL;
289 1.1 kardel int family, socktype, flags, protocol;
290 1.1 kardel
291 1.1 kardel
292 1.1 kardel /*
293 1.1 kardel * If no name is provide just return an error
294 1.1 kardel */
295 1.1 kardel if (nodename == NULL && servname == NULL)
296 1.1 kardel return (EAI_NONAME);
297 1.1 kardel
298 1.1 kardel ai = calloc(sizeof(struct addrinfo), 1);
299 1.1 kardel if (ai == NULL)
300 1.1 kardel return (EAI_MEMORY);
301 1.1 kardel
302 1.1 kardel /*
303 1.1 kardel * Copy default values from hints, if available
304 1.1 kardel */
305 1.1 kardel if (hints != NULL) {
306 1.1 kardel ai->ai_flags = hints->ai_flags;
307 1.1 kardel ai->ai_family = hints->ai_family;
308 1.1 kardel ai->ai_socktype = hints->ai_socktype;
309 1.1 kardel ai->ai_protocol = hints->ai_protocol;
310 1.1 kardel
311 1.1 kardel family = hints->ai_family;
312 1.1 kardel socktype = hints->ai_socktype;
313 1.1 kardel protocol = hints->ai_protocol;
314 1.1 kardel flags = hints->ai_flags;
315 1.1 kardel
316 1.1 kardel switch (family) {
317 1.1 kardel case AF_UNSPEC:
318 1.1 kardel switch (hints->ai_socktype) {
319 1.1 kardel case SOCK_STREAM:
320 1.1 kardel proto = "tcp";
321 1.1 kardel break;
322 1.1 kardel case SOCK_DGRAM:
323 1.1 kardel proto = "udp";
324 1.1 kardel break;
325 1.1 kardel }
326 1.1 kardel break;
327 1.1 kardel case AF_INET:
328 1.1 kardel case AF_INET6:
329 1.1 kardel switch (hints->ai_socktype) {
330 1.1 kardel case 0:
331 1.1 kardel break;
332 1.1 kardel case SOCK_STREAM:
333 1.1 kardel proto = "tcp";
334 1.1 kardel break;
335 1.1 kardel case SOCK_DGRAM:
336 1.1 kardel proto = "udp";
337 1.1 kardel break;
338 1.1 kardel case SOCK_RAW:
339 1.1 kardel break;
340 1.1 kardel default:
341 1.1 kardel return (EAI_SOCKTYPE);
342 1.1 kardel }
343 1.1 kardel break;
344 1.1 kardel #ifdef AF_LOCAL
345 1.1 kardel case AF_LOCAL:
346 1.1 kardel switch (hints->ai_socktype) {
347 1.1 kardel case 0:
348 1.1 kardel break;
349 1.1 kardel case SOCK_STREAM:
350 1.1 kardel break;
351 1.1 kardel case SOCK_DGRAM:
352 1.1 kardel break;
353 1.1 kardel default:
354 1.1 kardel return (EAI_SOCKTYPE);
355 1.1 kardel }
356 1.1 kardel break;
357 1.1 kardel #endif
358 1.1 kardel default:
359 1.1 kardel return (EAI_FAMILY);
360 1.1 kardel }
361 1.1 kardel } else {
362 1.1 kardel protocol = 0;
363 1.1 kardel family = 0;
364 1.1 kardel socktype = 0;
365 1.1 kardel flags = 0;
366 1.1 kardel }
367 1.1 kardel
368 1.1 kardel rval = do_nodename(nodename, ai, hints);
369 1.1 kardel if (rval != 0) {
370 1.1 kardel freeaddrinfo(ai);
371 1.1 kardel return (rval);
372 1.1 kardel }
373 1.1 kardel
374 1.1 kardel /*
375 1.1 kardel * First, look up the service name (port) if it was
376 1.1 kardel * requested. If the socket type wasn't specified, then
377 1.1 kardel * try and figure it out.
378 1.1 kardel */
379 1.1 kardel if (servname != NULL) {
380 1.1 kardel char *e;
381 1.1 kardel
382 1.1 kardel port = strtol(servname, &e, 10);
383 1.1 kardel if (*e == '\0') {
384 1.1 kardel if (socktype == 0)
385 1.1 kardel return (EAI_SOCKTYPE);
386 1.1 kardel if (port < 0 || port > 65535)
387 1.1 kardel return (EAI_SERVICE);
388 1.1 kardel port = htons((unsigned short) port);
389 1.1 kardel } else {
390 1.1 kardel sp = getservbyname(servname, proto);
391 1.1 kardel if (sp == NULL)
392 1.1 kardel return (EAI_SERVICE);
393 1.1 kardel port = sp->s_port;
394 1.1 kardel if (socktype == 0) {
395 1.1 kardel if (strcmp(sp->s_proto, "tcp") == 0)
396 1.1 kardel socktype = SOCK_STREAM;
397 1.1 kardel else if (strcmp(sp->s_proto, "udp") == 0)
398 1.1 kardel socktype = SOCK_DGRAM;
399 1.1 kardel }
400 1.1 kardel }
401 1.1 kardel } else
402 1.1 kardel port = 0;
403 1.1 kardel
404 1.1 kardel /*
405 1.1 kardel *
406 1.1 kardel * Set up the port number
407 1.1 kardel */
408 1.1 kardel if (ai->ai_family == AF_INET)
409 1.1 kardel ((struct sockaddr_in *)ai->ai_addr)->sin_port = (unsigned short) port;
410 1.1 kardel else if (ai->ai_family == AF_INET6)
411 1.1 kardel ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port = (unsigned short) port;
412 1.1 kardel *res = ai;
413 1.1 kardel return (0);
414 1.1 kardel }
415 1.1 kardel
416 1.1 kardel void
417 1.1 kardel freeaddrinfo(struct addrinfo *ai)
418 1.1 kardel {
419 1.1 kardel if (ai->ai_canonname != NULL)
420 1.1 kardel {
421 1.1 kardel free(ai->ai_canonname);
422 1.1 kardel ai->ai_canonname = NULL;
423 1.1 kardel }
424 1.1 kardel if (ai->ai_addr != NULL)
425 1.1 kardel {
426 1.1 kardel free(ai->ai_addr);
427 1.1 kardel ai->ai_addr = NULL;
428 1.1 kardel }
429 1.1 kardel free(ai);
430 1.1 kardel ai = NULL;
431 1.1 kardel }
432 1.1 kardel
433 1.1 kardel int
434 1.1 kardel getnameinfo (const struct sockaddr *sa, u_int salen, char *host,
435 1.1 kardel size_t hostlen, char *serv, size_t servlen, int flags)
436 1.1 kardel {
437 1.1 kardel struct hostent *hp;
438 1.1 kardel
439 1.1 kardel if (sa->sa_family != AF_INET)
440 1.1 kardel return (EAI_FAMILY);
441 1.1 kardel hp = gethostbyaddr(
442 1.1 kardel (const char *)&((const struct sockaddr_in *)sa)->sin_addr,
443 1.1 kardel 4, AF_INET);
444 1.1 kardel if (hp == NULL) {
445 1.1 kardel if (h_errno == TRY_AGAIN)
446 1.1 kardel return (EAI_AGAIN);
447 1.1 kardel else
448 1.1 kardel return (EAI_FAIL);
449 1.1 kardel }
450 1.1.1.2 christos if (host != NULL && hostlen > 0)
451 1.1.1.2 christos strlcpy(host, hp->h_name, hostlen);
452 1.1 kardel return (0);
453 1.1 kardel }
454 1.1 kardel
455 1.1 kardel char *
456 1.1 kardel gai_strerror(int ecode)
457 1.1 kardel {
458 1.1 kardel if (ecode < 0 || ecode > EAI_MAX)
459 1.1 kardel ecode = EAI_MAX;
460 1.1 kardel return ai_errlist[ecode];
461 1.1 kardel }
462 1.1 kardel
463 1.1 kardel static int
464 1.1 kardel do_nodename(
465 1.1 kardel const char *nodename,
466 1.1 kardel struct addrinfo *ai,
467 1.1 kardel const struct addrinfo *hints)
468 1.1 kardel {
469 1.1 kardel struct hostent *hp = NULL;
470 1.1 kardel struct sockaddr_in *sockin;
471 1.1 kardel struct sockaddr_in6 *sockin6;
472 1.1 kardel int errval;
473 1.1 kardel
474 1.1 kardel ai->ai_addr = calloc(sizeof(struct sockaddr_storage), 1);
475 1.1 kardel if (ai->ai_addr == NULL)
476 1.1 kardel return (EAI_MEMORY);
477 1.1 kardel
478 1.1 kardel /*
479 1.1 kardel * For an empty node name just use the wildcard.
480 1.1 kardel * NOTE: We need to assume that the address family is
481 1.1 kardel * set elsewhere so that we can set the appropriate wildcard
482 1.1 kardel */
483 1.1 kardel if (nodename == NULL) {
484 1.1 kardel if (ai->ai_family == AF_INET)
485 1.1 kardel {
486 1.1.1.6 christos ai->ai_addrlen = sizeof(struct sockaddr_in);
487 1.1 kardel sockin = (struct sockaddr_in *)ai->ai_addr;
488 1.1 kardel sockin->sin_family = (short) ai->ai_family;
489 1.1 kardel sockin->sin_addr.s_addr = htonl(INADDR_ANY);
490 1.1 kardel }
491 1.1 kardel else
492 1.1 kardel {
493 1.1.1.6 christos ai->ai_addrlen = sizeof(struct sockaddr_in6);
494 1.1 kardel sockin6 = (struct sockaddr_in6 *)ai->ai_addr;
495 1.1 kardel sockin6->sin6_family = (short) ai->ai_family;
496 1.1 kardel /*
497 1.1 kardel * we have already zeroed out the address
498 1.1 kardel * so we don't actually need to do this
499 1.1 kardel * This assignment is causing problems so
500 1.1 kardel * we don't do what this would do.
501 1.1 kardel sockin6->sin6_addr = in6addr_any;
502 1.1 kardel */
503 1.1 kardel }
504 1.1 kardel #ifdef ISC_PLATFORM_HAVESALEN
505 1.1 kardel ai->ai_addr->sa_len = SOCKLEN(ai->ai_addr);
506 1.1 kardel #endif
507 1.1 kardel
508 1.1 kardel return (0);
509 1.1 kardel }
510 1.1 kardel
511 1.1 kardel /*
512 1.1 kardel * See if we have an IPv6 address
513 1.1 kardel */
514 1.1 kardel if(strchr(nodename, ':') != NULL) {
515 1.1 kardel if (inet_pton(AF_INET6, nodename,
516 1.1 kardel &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr) == 1) {
517 1.1 kardel ((struct sockaddr_in6 *)ai->ai_addr)->sin6_family = AF_INET6;
518 1.1 kardel ai->ai_family = AF_INET6;
519 1.1 kardel ai->ai_addrlen = sizeof(struct sockaddr_in6);
520 1.1 kardel return (0);
521 1.1 kardel }
522 1.1 kardel }
523 1.1 kardel
524 1.1 kardel /*
525 1.1 kardel * See if we have an IPv4 address
526 1.1 kardel */
527 1.1 kardel if (inet_pton(AF_INET, nodename,
528 1.1 kardel &((struct sockaddr_in *)ai->ai_addr)->sin_addr) == 1) {
529 1.1 kardel ((struct sockaddr *)ai->ai_addr)->sa_family = AF_INET;
530 1.1 kardel ai->ai_family = AF_INET;
531 1.1 kardel ai->ai_addrlen = sizeof(struct sockaddr_in);
532 1.1 kardel return (0);
533 1.1 kardel }
534 1.1 kardel
535 1.1 kardel /*
536 1.1 kardel * If the numeric host flag is set, don't attempt resolution
537 1.1 kardel */
538 1.1 kardel if (hints != NULL && (hints->ai_flags & AI_NUMERICHOST))
539 1.1 kardel return (EAI_NONAME);
540 1.1 kardel
541 1.1 kardel /*
542 1.1 kardel * Look for a name
543 1.1 kardel */
544 1.1 kardel
545 1.1 kardel errval = DNSlookup_name(nodename, AF_INET, &hp);
546 1.1 kardel
547 1.1 kardel if (hp == NULL) {
548 1.1 kardel if (errval == TRY_AGAIN || errval == EAI_AGAIN)
549 1.1 kardel return (EAI_AGAIN);
550 1.1 kardel else if (errval == EAI_NONAME) {
551 1.1 kardel if (inet_pton(AF_INET, nodename,
552 1.1 kardel &((struct sockaddr_in *)ai->ai_addr)->sin_addr) == 1) {
553 1.1 kardel ((struct sockaddr *)ai->ai_addr)->sa_family = AF_INET;
554 1.1 kardel ai->ai_family = AF_INET;
555 1.1 kardel ai->ai_addrlen = sizeof(struct sockaddr_in);
556 1.1 kardel return (0);
557 1.1 kardel }
558 1.1 kardel return (errval);
559 1.1 kardel }
560 1.1 kardel else
561 1.1 kardel {
562 1.1 kardel return (errval);
563 1.1 kardel }
564 1.1 kardel }
565 1.1 kardel ai->ai_family = hp->h_addrtype;
566 1.1 kardel ai->ai_addrlen = sizeof(struct sockaddr);
567 1.1 kardel sockin = (struct sockaddr_in *)ai->ai_addr;
568 1.1 kardel memcpy(&sockin->sin_addr, hp->h_addr, hp->h_length);
569 1.1 kardel ai->ai_addr->sa_family = hp->h_addrtype;
570 1.1 kardel #ifdef ISC_PLATFORM_HAVESALEN
571 1.1 kardel ai->ai_addr->sa_len = sizeof(struct sockaddr);
572 1.1 kardel #endif
573 1.1.1.2 christos if (hints != NULL && (hints->ai_flags & AI_CANONNAME))
574 1.1 kardel ai->ai_canonname = estrdup(hp->h_name);
575 1.1 kardel return (0);
576 1.1 kardel }
577 1.1 kardel
578 1.1 kardel #endif /* !ISC_PLATFORM_HAVEIPV6 */
579