1: /*
2: * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. Neither the name of the project nor the names of its contributors
14: * may be used to endorse or promote products derived from this software
15: * without specific prior written permission.
16: *
17: * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20: * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27: * SUCH DAMAGE.
28: */
29:
30: /*
31: * Copyright (c) 1982, 1986, 1990, 1993
32: * The Regents of the University of California. All rights reserved.
33: *
34: * Redistribution and use in source and binary forms, with or without
35: * modification, are permitted provided that the following conditions
36: * are met:
37: * 1. Redistributions of source code must retain the above copyright
38: * notice, this list of conditions and the following disclaimer.
39: * 2. Redistributions in binary form must reproduce the above copyright
40: * notice, this list of conditions and the following disclaimer in the
41: * documentation and/or other materials provided with the distribution.
42: * 3. All advertising materials mentioning features or use of this software
43: * must display the following acknowledgement:
44: * This product includes software developed by the University of
45: * California, Berkeley and its contributors.
46: * 4. Neither the name of the University nor the names of its contributors
47: * may be used to endorse or promote products derived from this software
48: * without specific prior written permission.
49: *
50: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
51: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
54: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
58: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
59: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60: * SUCH DAMAGE.
61: *
62: */
63:
64: /*
65: * Compatability shims with the rfc2553 API to simplify ntp.
66: */
67:
68: #include <config.h>
69:
70: #include <sys/types.h>
71: #include <ctype.h>
72: #ifdef HAVE_SYS_SOCKET_H
73: #include <sys/socket.h>
74: #endif
75: #include <isc/net.h>
76: #ifdef HAVE_NETINET_IN_H
77: #include <netinet/in.h>
78: #endif
79: #include "ntp_rfc2553.h"
80:
81: #include "ntpd.h"
82: #include "ntp_malloc.h"
83: #include "ntp_stdlib.h"
84: #include "ntp_string.h"
85:
86: #ifndef ISC_PLATFORM_HAVEIPV6
87:
88: static char *ai_errlist[] = {
89: "Success",
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 */
104: };
105:
106: /*
107: * Local declaration
108: */
109: int
110: DNSlookup_name(
111: const char *name,
112: int ai_family,
113: struct hostent **Addresses
114: );
115:
116: #ifndef SYS_WINNT
117: /*
118: * Encapsulate gethostbyname to control the error code
119: */
120: int
121: DNSlookup_name(
122: const char *name,
123: int ai_family,
124: struct hostent **Addresses
125: )
126: {
127: *Addresses = gethostbyname(name);
128: return (h_errno);
129: }
130: #endif
131:
132: static int do_nodename (const char *nodename, struct addrinfo *ai,
133: const struct addrinfo *hints);
134:
135: int
136: getaddrinfo (const char *nodename, const char *servname,
137: const struct addrinfo *hints, struct addrinfo **res)
138: {
139: int rval;
140: struct servent *sp;
141: struct addrinfo *ai = NULL;
142: int port;
143: const char *proto = NULL;
144: int family, socktype, flags, protocol;
145:
146:
147: /*
148: * If no name is provide just return an error
149: */
150: if (nodename == NULL && servname == NULL)
151: return (EAI_NONAME);
152:
153: ai = calloc(sizeof(struct addrinfo), 1);
154: if (ai == NULL)
155: return (EAI_MEMORY);
156:
157: /*
158: * Copy default values from hints, if available
159: */
160: if (hints != NULL) {
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;
165:
166: family = hints->ai_family;
167: socktype = hints->ai_socktype;
168: protocol = hints->ai_protocol;
169: flags = hints->ai_flags;
170:
171: switch (family) {
172: case AF_UNSPEC:
173: switch (hints->ai_socktype) {
174: case SOCK_STREAM:
175: proto = "tcp";
176: break;
177: case SOCK_DGRAM:
178: proto = "udp";
179: break;
180: }
181: break;
182: case AF_INET:
183: case AF_INET6:
184: switch (hints->ai_socktype) {
185: case 0:
186: break;
187: case SOCK_STREAM:
188: proto = "tcp";
189: break;
190: case SOCK_DGRAM:
191: proto = "udp";
192: break;
193: case SOCK_RAW:
194: break;
195: default:
196: return (EAI_SOCKTYPE);
197: }
198: break;
199: #ifdef AF_LOCAL
200: case AF_LOCAL:
201: switch (hints->ai_socktype) {
202: case 0:
203: break;
204: case SOCK_STREAM:
205: break;
206: case SOCK_DGRAM:
207: break;
208: default:
209: return (EAI_SOCKTYPE);
210: }
211: break;
212: #endif
213: default:
214: return (EAI_FAMILY);
215: }
216: } else {
217: protocol = 0;
218: family = 0;
219: socktype = 0;
220: flags = 0;
221: }
222:
223: rval = do_nodename(nodename, ai, hints);
224: if (rval != 0) {
225: freeaddrinfo(ai);
226: return (rval);
227: }
228:
229: /*
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.
233: */
234: if (servname != NULL) {
235: char *e;
236:
237: port = strtol(servname, &e, 10);
238: if (*e == '\0') {
239: if (socktype == 0)
240: return (EAI_SOCKTYPE);
241: if (port < 0 || port > 65535)
242: return (EAI_SERVICE);
243: port = htons((unsigned short) port);
244: } else {
245: sp = getservbyname(servname, proto);
246: if (sp == NULL)
247: return (EAI_SERVICE);
248: port = sp->s_port;
249: if (socktype == 0) {
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;
254: }
255: }
256: } else
257: port = 0;
258:
259: /*
260: *
261: * Set up the port number
262: */
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;
267: *res = ai;
268: return (0);
269: }
270:
271: void
272: freeaddrinfo(struct addrinfo *ai)
273: {
274: if (ai->ai_canonname != NULL)
275: {
276: free(ai->ai_canonname);
277: ai->ai_canonname = NULL;
278: }
279: if (ai->ai_addr != NULL)
280: {
281: free(ai->ai_addr);
282: ai->ai_addr = NULL;
283: }
284: free(ai);
285: ai = NULL;
286: }
287:
288: int
289: getnameinfo (const struct sockaddr *sa, u_int salen, char *host,
290: size_t hostlen, char *serv, size_t servlen, int flags)
291: {
292: struct hostent *hp;
293: int namelen;
294:
295: if (sa->sa_family != AF_INET)
296: return (EAI_FAMILY);
297: hp = gethostbyaddr(
298: (const char *)&((const struct sockaddr_in *)sa)->sin_addr,
299: 4, AF_INET);
300: if (hp == NULL) {
301: if (h_errno == TRY_AGAIN)
302: return (EAI_AGAIN);
303: else
304: return (EAI_FAIL);
305: }
306: if (host != NULL && hostlen > 0) {
307: /*
308: * Don't exceed buffer
309: */
310: namelen = min(strlen(hp->h_name), hostlen - 1);
311: if (namelen > 0) {
312: strncpy(host, hp->h_name, namelen);
313: host[namelen] = '\0';
314: }
315: }
316: return (0);
317: }
318:
319: char *
320: gai_strerror(int ecode)
321: {
322: if (ecode < 0 || ecode > EAI_MAX)
323: ecode = EAI_MAX;
324: return ai_errlist[ecode];
325: }
326:
327: static int
328: do_nodename(
329: const char *nodename,
330: struct addrinfo *ai,
331: const struct addrinfo *hints)
332: {
333: struct hostent *hp = NULL;
334: struct sockaddr_in *sockin;
335: struct sockaddr_in6 *sockin6;
336: int errval;
337:
338: ai->ai_addr = calloc(sizeof(struct sockaddr_storage), 1);
339: if (ai->ai_addr == NULL)
340: return (EAI_MEMORY);
341:
342: /*
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
346: */
347: if (nodename == NULL) {
348: ai->ai_addrlen = sizeof(struct sockaddr_storage);
349: if (ai->ai_family == AF_INET)
350: {
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);
354: }
355: else
356: {
357: sockin6 = (struct sockaddr_in6 *)ai->ai_addr;
358: sockin6->sin6_family = (short) ai->ai_family;
359: /*
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;
365: */
366: }
367: #ifdef ISC_PLATFORM_HAVESALEN
368: ai->ai_addr->sa_len = SOCKLEN(ai->ai_addr);
369: #endif
370:
371: return (0);
372: }
373:
374: /*
375: * See if we have an IPv6 address
376: */
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);
383: return (0);
384: }
385: }
386:
387: /*
388: * See if we have an IPv4 address
389: */
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);
395: return (0);
396: }
397:
398: /*
399: * If the numeric host flag is set, don't attempt resolution
400: */
401: if (hints != NULL && (hints->ai_flags & AI_NUMERICHOST))
402: return (EAI_NONAME);
403:
404: /*
405: * Look for a name
406: */
407:
408: errval = DNSlookup_name(nodename, AF_INET, &hp);
409:
410: if (hp == NULL) {
411: if (errval == TRY_AGAIN || errval == EAI_AGAIN)
412: return (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);
419: return (0);
420: }
421: return (errval);
422: }
423: else
424: {
425: return (errval);
426: }
427: }
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 ISC_PLATFORM_HAVESALEN
434: ai->ai_addr->sa_len = sizeof(struct sockaddr);
435: #endif
436: if (hints != NULL && hints->ai_flags & AI_CANONNAME)
437: ai->ai_canonname = estrdup(hp->h_name);
438: return (0);
439: }
440:
441: #endif /* !ISC_PLATFORM_HAVEIPV6 */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>