1 /* $NetBSD: ntp_rfc2553.c,v 1.4 2007/01/06 19:45:22 kardel Exp $ */
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 #include <sys/socket.h>
76 #ifdef HAVE_NETINET_IN_H
77 #include <netinet/in.h>
79 #include "ntp_rfc2553.h"
82 #include "ntp_malloc.h"
83 #include "ntp_stdlib.h"
84 #include "ntp_string.h"
86 #ifndef ISC_PLATFORM_HAVEIPV6
88 static char *ai_errlist
[] = {
90 "Address family for hostname not supported", /* EAI_ADDRFAMILY */
91 "Temporary failure in name resolution", /* EAI_AGAIN */
92 "Invalid value for ai_flags", /* EAI_BADFLAGS */
93 "Non-recoverable failure in name resolution", /* EAI_FAIL */
94 "ai_family not supported", /* EAI_FAMILY */
95 "Memory allocation failure", /* EAI_MEMORY */
96 "No address associated with hostname", /* EAI_NODATA */
97 "hostname nor servname provided, or not known", /* EAI_NONAME */
98 "servname not supported for ai_socktype", /* EAI_SERVICE */
99 "ai_socktype not supported", /* EAI_SOCKTYPE */
100 "System error returned in errno", /* EAI_SYSTEM */
101 "Invalid value for hints", /* EAI_BADHINTS */
102 "Resolved protocol is unknown", /* EAI_PROTOCOL */
103 "Unknown error", /* EAI_MAX */
113 struct hostent
**Addresses
118 * Encapsulate gethostbyname to control the error code
124 struct hostent
**Addresses
127 *Addresses
= gethostbyname(name
);
132 static int do_nodename
P((const char *nodename
, struct addrinfo
*ai
,
133 const struct addrinfo
*hints
));
136 getaddrinfo (const char *nodename
, const char *servname
,
137 const struct addrinfo
*hints
, struct addrinfo
**res
)
141 struct addrinfo
*ai
= NULL
;
143 const char *proto
= NULL
;
144 int family
, socktype
, flags
, protocol
;
148 * If no name is provide just return an error
150 if (nodename
== NULL
&& servname
== NULL
)
153 ai
= calloc(sizeof(struct addrinfo
), 1);
158 * Copy default values from hints, if available
161 ai
->ai_flags
= hints
->ai_flags
;
162 ai
->ai_family
= hints
->ai_family
;
163 ai
->ai_socktype
= hints
->ai_socktype
;
164 ai
->ai_protocol
= hints
->ai_protocol
;
166 family
= hints
->ai_family
;
167 socktype
= hints
->ai_socktype
;
168 protocol
= hints
->ai_protocol
;
169 flags
= hints
->ai_flags
;
173 switch (hints
->ai_socktype
) {
184 switch (hints
->ai_socktype
) {
196 return (EAI_SOCKTYPE
);
201 switch (hints
->ai_socktype
) {
209 return (EAI_SOCKTYPE
);
223 rval
= do_nodename(nodename
, ai
, hints
);
230 * First, look up the service name (port) if it was
231 * requested. If the socket type wasn't specified, then
232 * try and figure it out.
234 if (servname
!= NULL
) {
237 port
= strtol(servname
, &e
, 10);
240 return (EAI_SOCKTYPE
);
241 if (port
< 0 || port
> 65535)
242 return (EAI_SERVICE
);
243 port
= htons((unsigned short) port
);
245 sp
= getservbyname(servname
, proto
);
247 return (EAI_SERVICE
);
250 if (strcmp(sp
->s_proto
, "tcp") == 0)
251 socktype
= SOCK_STREAM
;
252 else if (strcmp(sp
->s_proto
, "udp") == 0)
253 socktype
= SOCK_DGRAM
;
261 * Set up the port number
263 if (ai
->ai_family
== AF_INET
)
264 ((struct sockaddr_in
*)ai
->ai_addr
)->sin_port
= (unsigned short) port
;
265 else if (ai
->ai_family
== AF_INET6
)
266 ((struct sockaddr_in6
*)ai
->ai_addr
)->sin6_port
= (unsigned short) port
;
272 freeaddrinfo(struct addrinfo
*ai
)
274 if (ai
->ai_canonname
!= NULL
)
276 free(ai
->ai_canonname
);
277 ai
->ai_canonname
= NULL
;
279 if (ai
->ai_addr
!= NULL
)
289 getnameinfo (const struct sockaddr
*sa
, u_int salen
, char *host
,
290 size_t hostlen
, char *serv
, size_t servlen
, int flags
)
295 if (sa
->sa_family
!= AF_INET
)
298 (const char *)&((const struct sockaddr_in
*)sa
)->sin_addr
,
301 if (h_errno
== TRY_AGAIN
)
306 if (host
!= NULL
&& hostlen
> 0) {
308 * Don't exceed buffer
310 namelen
= min(strlen(hp
->h_name
), hostlen
- 1);
312 strncpy(host
, hp
->h_name
, namelen
);
313 host
[namelen
] = '\0';
320 gai_strerror(int ecode
)
322 if (ecode
< 0 || ecode
> EAI_MAX
)
324 return ai_errlist
[ecode
];
329 const char *nodename
,
331 const struct addrinfo
*hints
)
333 struct hostent
*hp
= NULL
;
334 struct sockaddr_in
*sockin
;
335 struct sockaddr_in6
*sockin6
;
338 ai
->ai_addr
= calloc(sizeof(struct sockaddr_storage
), 1);
339 if (ai
->ai_addr
== NULL
)
343 * For an empty node name just use the wildcard.
344 * NOTE: We need to assume that the address family is
345 * set elsewhere so that we can set the appropriate wildcard
347 if (nodename
== NULL
) {
348 ai
->ai_addrlen
= sizeof(struct sockaddr_storage
);
349 if (ai
->ai_family
== AF_INET
)
351 sockin
= (struct sockaddr_in
*)ai
->ai_addr
;
352 sockin
->sin_family
= (short) ai
->ai_family
;
353 sockin
->sin_addr
.s_addr
= htonl(INADDR_ANY
);
357 sockin6
= (struct sockaddr_in6
*)ai
->ai_addr
;
358 sockin6
->sin6_family
= (short) ai
->ai_family
;
360 * we have already zeroed out the address
361 * so we don't actually need to do this
362 * This assignment is causing problems so
363 * we don't do what this would do.
364 sockin6->sin6_addr = in6addr_any;
367 #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
368 ai
->ai_addr
->sa_len
= SOCKLEN(ai
->ai_addr
);
375 * See if we have an IPv6 address
377 if(strchr(nodename
, ':') != NULL
) {
378 if (inet_pton(AF_INET6
, nodename
,
379 &((struct sockaddr_in6
*)ai
->ai_addr
)->sin6_addr
) == 1) {
380 ((struct sockaddr_in6
*)ai
->ai_addr
)->sin6_family
= AF_INET6
;
381 ai
->ai_family
= AF_INET6
;
382 ai
->ai_addrlen
= sizeof(struct sockaddr_in6
);
388 * See if we have an IPv4 address
390 if (inet_pton(AF_INET
, nodename
,
391 &((struct sockaddr_in
*)ai
->ai_addr
)->sin_addr
) == 1) {
392 ((struct sockaddr
*)ai
->ai_addr
)->sa_family
= AF_INET
;
393 ai
->ai_family
= AF_INET
;
394 ai
->ai_addrlen
= sizeof(struct sockaddr_in
);
399 * If the numeric host flag is set, don't attempt resolution
401 if (hints
!= NULL
&& (hints
->ai_flags
& AI_NUMERICHOST
))
408 errval
= DNSlookup_name(nodename
, AF_INET
, &hp
);
411 if (errval
== TRY_AGAIN
|| errval
== EAI_AGAIN
)
413 else if (errval
== EAI_NONAME
) {
414 if (inet_pton(AF_INET
, nodename
,
415 &((struct sockaddr_in
*)ai
->ai_addr
)->sin_addr
) == 1) {
416 ((struct sockaddr
*)ai
->ai_addr
)->sa_family
= AF_INET
;
417 ai
->ai_family
= AF_INET
;
418 ai
->ai_addrlen
= sizeof(struct sockaddr_in
);
428 ai
->ai_family
= hp
->h_addrtype
;
429 ai
->ai_addrlen
= sizeof(struct sockaddr
);
430 sockin
= (struct sockaddr_in
*)ai
->ai_addr
;
431 memcpy(&sockin
->sin_addr
, hp
->h_addr
, hp
->h_length
);
432 ai
->ai_addr
->sa_family
= hp
->h_addrtype
;
433 #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
434 ai
->ai_addr
->sa_len
= sizeof(struct sockaddr
);
436 if (hints
!= NULL
&& hints
->ai_flags
& AI_CANONNAME
) {
437 ai
->ai_canonname
= malloc(strlen(hp
->h_name
) + 1);
438 if (ai
->ai_canonname
== NULL
)
440 strcpy(ai
->ai_canonname
, hp
->h_name
);
445 #endif /* !ISC_PLATFORM_HAVEIPV6 */