4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * Copyright (c) 1982, 1986, 1990, 1993
34 * The Regents of the University of California. All rights reserved.
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution.
44 * 3. All advertising materials mentioning features or use of this software
45 * must display the following acknowledgement:
46 * This product includes software developed by the University of
47 * California, Berkeley and its contributors.
48 * 4. Neither the name of the University nor the names of its contributors
49 * may be used to endorse or promote products derived from this software
50 * without specific prior written permission.
52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
67 * Compatability shims with the rfc2553 API to simplify ntp.
72 #include <sys/types.h>
74 #ifdef HAVE_SYS_SOCKET_H
75 #include <sys/socket.h>
78 #ifdef HAVE_NETINET_IN_H
79 #include <netinet/in.h>
81 #include "ntp_rfc2553.h"
84 #include "ntp_malloc.h"
85 #include "ntp_stdlib.h"
86 #include "ntp_string.h"
88 #ifndef ISC_PLATFORM_HAVEIPV6
90 static char *ai_errlist
[] = {
92 "Address family for hostname not supported", /* EAI_ADDRFAMILY */
93 "Temporary failure in name resolution", /* EAI_AGAIN */
94 "Invalid value for ai_flags", /* EAI_BADFLAGS */
95 "Non-recoverable failure in name resolution", /* EAI_FAIL */
96 "ai_family not supported", /* EAI_FAMILY */
97 "Memory allocation failure", /* EAI_MEMORY */
98 "No address associated with hostname", /* EAI_NODATA */
99 "hostname nor servname provided, or not known", /* EAI_NONAME */
100 "servname not supported for ai_socktype", /* EAI_SERVICE */
101 "ai_socktype not supported", /* EAI_SOCKTYPE */
102 "System error returned in errno", /* EAI_SYSTEM */
103 "Invalid value for hints", /* EAI_BADHINTS */
104 "Resolved protocol is unknown", /* EAI_PROTOCOL */
105 "Unknown error", /* EAI_MAX */
115 struct hostent
**Addresses
120 * Encapsulate gethostbyname to control the error code
126 struct hostent
**Addresses
129 *Addresses
= gethostbyname(name
);
134 static int do_nodename (const char *nodename
, struct addrinfo
*ai
,
135 const struct addrinfo
*hints
);
138 getaddrinfo (const char *nodename
, const char *servname
,
139 const struct addrinfo
*hints
, struct addrinfo
**res
)
143 struct addrinfo
*ai
= NULL
;
145 const char *proto
= NULL
;
146 int family
, socktype
, flags
, protocol
;
150 * If no name is provide just return an error
152 if (nodename
== NULL
&& servname
== NULL
)
155 ai
= calloc(sizeof(struct addrinfo
), 1);
160 * Copy default values from hints, if available
163 ai
->ai_flags
= hints
->ai_flags
;
164 ai
->ai_family
= hints
->ai_family
;
165 ai
->ai_socktype
= hints
->ai_socktype
;
166 ai
->ai_protocol
= hints
->ai_protocol
;
168 family
= hints
->ai_family
;
169 socktype
= hints
->ai_socktype
;
170 protocol
= hints
->ai_protocol
;
171 flags
= hints
->ai_flags
;
175 switch (hints
->ai_socktype
) {
186 switch (hints
->ai_socktype
) {
198 return (EAI_SOCKTYPE
);
203 switch (hints
->ai_socktype
) {
211 return (EAI_SOCKTYPE
);
225 rval
= do_nodename(nodename
, ai
, hints
);
232 * First, look up the service name (port) if it was
233 * requested. If the socket type wasn't specified, then
234 * try and figure it out.
236 if (servname
!= NULL
) {
239 port
= strtol(servname
, &e
, 10);
242 return (EAI_SOCKTYPE
);
243 if (port
< 0 || port
> 65535)
244 return (EAI_SERVICE
);
245 port
= htons((unsigned short) port
);
247 sp
= getservbyname(servname
, proto
);
249 return (EAI_SERVICE
);
252 if (strcmp(sp
->s_proto
, "tcp") == 0)
253 socktype
= SOCK_STREAM
;
254 else if (strcmp(sp
->s_proto
, "udp") == 0)
255 socktype
= SOCK_DGRAM
;
263 * Set up the port number
265 if (ai
->ai_family
== AF_INET
)
266 ((struct sockaddr_in
*)ai
->ai_addr
)->sin_port
= (unsigned short) port
;
267 else if (ai
->ai_family
== AF_INET6
)
268 ((struct sockaddr_in6
*)ai
->ai_addr
)->sin6_port
= (unsigned short) port
;
274 freeaddrinfo(struct addrinfo
*ai
)
276 if (ai
->ai_canonname
!= NULL
)
278 free(ai
->ai_canonname
);
279 ai
->ai_canonname
= NULL
;
281 if (ai
->ai_addr
!= NULL
)
291 getnameinfo (const struct sockaddr
*sa
, u_int salen
, char *host
,
292 size_t hostlen
, char *serv
, size_t servlen
, int flags
)
297 if (sa
->sa_family
!= AF_INET
)
300 (const char *)&((const struct sockaddr_in
*)sa
)->sin_addr
,
303 if (h_errno
== TRY_AGAIN
)
308 if (host
!= NULL
&& hostlen
> 0) {
310 * Don't exceed buffer
312 namelen
= min(strlen(hp
->h_name
), hostlen
- 1);
314 strncpy(host
, hp
->h_name
, namelen
);
315 host
[namelen
] = '\0';
322 gai_strerror(int ecode
)
324 if (ecode
< 0 || ecode
> EAI_MAX
)
326 return ai_errlist
[ecode
];
331 const char *nodename
,
333 const struct addrinfo
*hints
)
335 struct hostent
*hp
= NULL
;
336 struct sockaddr_in
*sockin
;
337 struct sockaddr_in6
*sockin6
;
340 ai
->ai_addr
= calloc(sizeof(struct sockaddr_storage
), 1);
341 if (ai
->ai_addr
== NULL
)
345 * For an empty node name just use the wildcard.
346 * NOTE: We need to assume that the address family is
347 * set elsewhere so that we can set the appropriate wildcard
349 if (nodename
== NULL
) {
350 ai
->ai_addrlen
= sizeof(struct sockaddr_storage
);
351 if (ai
->ai_family
== AF_INET
)
353 sockin
= (struct sockaddr_in
*)ai
->ai_addr
;
354 sockin
->sin_family
= (short) ai
->ai_family
;
355 sockin
->sin_addr
.s_addr
= htonl(INADDR_ANY
);
359 sockin6
= (struct sockaddr_in6
*)ai
->ai_addr
;
360 sockin6
->sin6_family
= (short) ai
->ai_family
;
362 * we have already zeroed out the address
363 * so we don't actually need to do this
364 * This assignment is causing problems so
365 * we don't do what this would do.
366 sockin6->sin6_addr = in6addr_any;
369 #ifdef ISC_PLATFORM_HAVESALEN
370 ai
->ai_addr
->sa_len
= SOCKLEN(ai
->ai_addr
);
377 * See if we have an IPv6 address
379 if(strchr(nodename
, ':') != NULL
) {
380 if (inet_pton(AF_INET6
, nodename
,
381 &((struct sockaddr_in6
*)ai
->ai_addr
)->sin6_addr
) == 1) {
382 ((struct sockaddr_in6
*)ai
->ai_addr
)->sin6_family
= AF_INET6
;
383 ai
->ai_family
= AF_INET6
;
384 ai
->ai_addrlen
= sizeof(struct sockaddr_in6
);
390 * See if we have an IPv4 address
392 if (inet_pton(AF_INET
, nodename
,
393 &((struct sockaddr_in
*)ai
->ai_addr
)->sin_addr
) == 1) {
394 ((struct sockaddr
*)ai
->ai_addr
)->sa_family
= AF_INET
;
395 ai
->ai_family
= AF_INET
;
396 ai
->ai_addrlen
= sizeof(struct sockaddr_in
);
401 * If the numeric host flag is set, don't attempt resolution
403 if (hints
!= NULL
&& (hints
->ai_flags
& AI_NUMERICHOST
))
410 errval
= DNSlookup_name(nodename
, AF_INET
, &hp
);
413 if (errval
== TRY_AGAIN
|| errval
== EAI_AGAIN
)
415 else if (errval
== EAI_NONAME
) {
416 if (inet_pton(AF_INET
, nodename
,
417 &((struct sockaddr_in
*)ai
->ai_addr
)->sin_addr
) == 1) {
418 ((struct sockaddr
*)ai
->ai_addr
)->sa_family
= AF_INET
;
419 ai
->ai_family
= AF_INET
;
420 ai
->ai_addrlen
= sizeof(struct sockaddr_in
);
430 ai
->ai_family
= hp
->h_addrtype
;
431 ai
->ai_addrlen
= sizeof(struct sockaddr
);
432 sockin
= (struct sockaddr_in
*)ai
->ai_addr
;
433 memcpy(&sockin
->sin_addr
, hp
->h_addr
, hp
->h_length
);
434 ai
->ai_addr
->sa_family
= hp
->h_addrtype
;
435 #ifdef ISC_PLATFORM_HAVESALEN
436 ai
->ai_addr
->sa_len
= sizeof(struct sockaddr
);
438 if (hints
!= NULL
&& hints
->ai_flags
& AI_CANONNAME
)
439 ai
->ai_canonname
= estrdup(hp
->h_name
);
443 #endif /* !ISC_PLATFORM_HAVEIPV6 */