19c2daa00SOllivier Robert /*
29c2daa00SOllivier Robert * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
39c2daa00SOllivier Robert * All rights reserved.
49c2daa00SOllivier Robert *
59c2daa00SOllivier Robert * Redistribution and use in source and binary forms, with or without
69c2daa00SOllivier Robert * modification, are permitted provided that the following conditions
79c2daa00SOllivier Robert * are met:
89c2daa00SOllivier Robert * 1. Redistributions of source code must retain the above copyright
99c2daa00SOllivier Robert * notice, this list of conditions and the following disclaimer.
109c2daa00SOllivier Robert * 2. Redistributions in binary form must reproduce the above copyright
119c2daa00SOllivier Robert * notice, this list of conditions and the following disclaimer in the
129c2daa00SOllivier Robert * documentation and/or other materials provided with the distribution.
139c2daa00SOllivier Robert * 3. Neither the name of the project nor the names of its contributors
149c2daa00SOllivier Robert * may be used to endorse or promote products derived from this software
159c2daa00SOllivier Robert * without specific prior written permission.
169c2daa00SOllivier Robert *
179c2daa00SOllivier Robert * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
189c2daa00SOllivier Robert * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
199c2daa00SOllivier Robert * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
209c2daa00SOllivier Robert * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
219c2daa00SOllivier Robert * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
229c2daa00SOllivier Robert * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
239c2daa00SOllivier Robert * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
249c2daa00SOllivier Robert * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
259c2daa00SOllivier Robert * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
269c2daa00SOllivier Robert * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
279c2daa00SOllivier Robert * SUCH DAMAGE.
289c2daa00SOllivier Robert */
299c2daa00SOllivier Robert
309c2daa00SOllivier Robert /*
319c2daa00SOllivier Robert * Copyright (c) 1982, 1986, 1990, 1993
329c2daa00SOllivier Robert * The Regents of the University of California. All rights reserved.
339c2daa00SOllivier Robert *
349c2daa00SOllivier Robert * Redistribution and use in source and binary forms, with or without
359c2daa00SOllivier Robert * modification, are permitted provided that the following conditions
369c2daa00SOllivier Robert * are met:
379c2daa00SOllivier Robert * 1. Redistributions of source code must retain the above copyright
389c2daa00SOllivier Robert * notice, this list of conditions and the following disclaimer.
399c2daa00SOllivier Robert * 2. Redistributions in binary form must reproduce the above copyright
409c2daa00SOllivier Robert * notice, this list of conditions and the following disclaimer in the
419c2daa00SOllivier Robert * documentation and/or other materials provided with the distribution.
429c2daa00SOllivier Robert * 3. All advertising materials mentioning features or use of this software
439c2daa00SOllivier Robert * must display the following acknowledgement:
449c2daa00SOllivier Robert * This product includes software developed by the University of
459c2daa00SOllivier Robert * California, Berkeley and its contributors.
469c2daa00SOllivier Robert * 4. Neither the name of the University nor the names of its contributors
479c2daa00SOllivier Robert * may be used to endorse or promote products derived from this software
489c2daa00SOllivier Robert * without specific prior written permission.
499c2daa00SOllivier Robert *
509c2daa00SOllivier Robert * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
519c2daa00SOllivier Robert * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
529c2daa00SOllivier Robert * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
539c2daa00SOllivier Robert * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
549c2daa00SOllivier Robert * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
559c2daa00SOllivier Robert * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
569c2daa00SOllivier Robert * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
579c2daa00SOllivier Robert * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
589c2daa00SOllivier Robert * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
599c2daa00SOllivier Robert * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
609c2daa00SOllivier Robert * SUCH DAMAGE.
619c2daa00SOllivier Robert *
629c2daa00SOllivier Robert */
639c2daa00SOllivier Robert
649c2daa00SOllivier Robert /*
659c2daa00SOllivier Robert * Compatability shims with the rfc2553 API to simplify ntp.
669c2daa00SOllivier Robert */
679c2daa00SOllivier Robert
689c2daa00SOllivier Robert #include <config.h>
699c2daa00SOllivier Robert
709c2daa00SOllivier Robert #include <sys/types.h>
719c2daa00SOllivier Robert #include <ctype.h>
722b15cb3dSCy Schubert #ifdef HAVE_SYS_SOCKET_H
739c2daa00SOllivier Robert #include <sys/socket.h>
742b15cb3dSCy Schubert #endif
75ea906c41SOllivier Robert #include <isc/net.h>
769c2daa00SOllivier Robert #ifdef HAVE_NETINET_IN_H
779c2daa00SOllivier Robert #include <netinet/in.h>
789c2daa00SOllivier Robert #endif
79ea906c41SOllivier Robert #include "ntp_rfc2553.h"
809c2daa00SOllivier Robert
819c2daa00SOllivier Robert #include "ntpd.h"
829c2daa00SOllivier Robert #include "ntp_malloc.h"
839c2daa00SOllivier Robert #include "ntp_string.h"
842b15cb3dSCy Schubert #include "ntp_debug.h"
852b15cb3dSCy Schubert
862b15cb3dSCy Schubert
872b15cb3dSCy Schubert /*
882b15cb3dSCy Schubert * copy_addrinfo() - copy a single addrinfo to malloc()'d block.
892b15cb3dSCy Schubert * copy_addrinfo_list() - copy an addrinfo list to malloc()'d block.
902b15cb3dSCy Schubert *
912b15cb3dSCy Schubert * Copies an addrinfo list and its associated data to a contiguous block
922b15cb3dSCy Schubert * of storage from emalloc(). Callback routines invoked via
932b15cb3dSCy Schubert * getaddrinfo_sometime() have access to the resulting addrinfo list
942b15cb3dSCy Schubert * only until they return. This routine provides an easy way to make a
952b15cb3dSCy Schubert * persistent copy. Although the list provided to gai_sometime_callback
962b15cb3dSCy Schubert * routines is similarly contiguous, to keep this code usable in any
972b15cb3dSCy Schubert * context where we might want to duplicate an addrinfo list, it does
982b15cb3dSCy Schubert * not require the input list be contiguous.
992b15cb3dSCy Schubert *
1002b15cb3dSCy Schubert * The returned list head pointer is passed to free() to release the
1012b15cb3dSCy Schubert * entire list.
1022b15cb3dSCy Schubert *
1032b15cb3dSCy Schubert * In keeping with the rest of the NTP distribution, sockaddr_u is used
1042b15cb3dSCy Schubert * in preference to struct sockaddr_storage, which is a member of the
1052b15cb3dSCy Schubert * former union and so compatible.
1062b15cb3dSCy Schubert *
1072b15cb3dSCy Schubert * The rest of ntp_rfc2553.c is conditioned on ISC_PLATFORM_HAVEIPV6
1082b15cb3dSCy Schubert * not being defined, copy_addrinfo_*() are exceptions.
1092b15cb3dSCy Schubert */
1102b15cb3dSCy Schubert struct addrinfo * copy_addrinfo_common(const struct addrinfo *, int
1112b15cb3dSCy Schubert #ifdef EREALLOC_CALLSITE
1122b15cb3dSCy Schubert ,
1132b15cb3dSCy Schubert const char *, int
1142b15cb3dSCy Schubert #endif
1152b15cb3dSCy Schubert );
1162b15cb3dSCy Schubert
1172b15cb3dSCy Schubert
1182b15cb3dSCy Schubert struct addrinfo *
copy_addrinfo_impl(const struct addrinfo * src,const char * caller_file,int caller_line)1192b15cb3dSCy Schubert copy_addrinfo_impl(
1202b15cb3dSCy Schubert const struct addrinfo * src
1212b15cb3dSCy Schubert #ifdef EREALLOC_CALLSITE
1222b15cb3dSCy Schubert ,
1232b15cb3dSCy Schubert const char * caller_file,
1242b15cb3dSCy Schubert int caller_line
1252b15cb3dSCy Schubert #endif
1262b15cb3dSCy Schubert )
1272b15cb3dSCy Schubert {
1282b15cb3dSCy Schubert return copy_addrinfo_common(src, TRUE
1292b15cb3dSCy Schubert #ifdef EREALLOC_CALLSITE
1302b15cb3dSCy Schubert ,
1312b15cb3dSCy Schubert caller_file, caller_line
1322b15cb3dSCy Schubert #endif
1332b15cb3dSCy Schubert );
1342b15cb3dSCy Schubert }
1352b15cb3dSCy Schubert
1362b15cb3dSCy Schubert
1372b15cb3dSCy Schubert struct addrinfo *
copy_addrinfo_list_impl(const struct addrinfo * src,const char * caller_file,int caller_line)1382b15cb3dSCy Schubert copy_addrinfo_list_impl(
1392b15cb3dSCy Schubert const struct addrinfo * src
1402b15cb3dSCy Schubert #ifdef EREALLOC_CALLSITE
1412b15cb3dSCy Schubert ,
1422b15cb3dSCy Schubert const char * caller_file,
1432b15cb3dSCy Schubert int caller_line
1442b15cb3dSCy Schubert #endif
1452b15cb3dSCy Schubert )
1462b15cb3dSCy Schubert {
1472b15cb3dSCy Schubert return copy_addrinfo_common(src, FALSE
1482b15cb3dSCy Schubert #ifdef EREALLOC_CALLSITE
1492b15cb3dSCy Schubert ,
1502b15cb3dSCy Schubert caller_file, caller_line
1512b15cb3dSCy Schubert #endif
1522b15cb3dSCy Schubert );
1532b15cb3dSCy Schubert }
1542b15cb3dSCy Schubert
1552b15cb3dSCy Schubert
1562b15cb3dSCy Schubert struct addrinfo *
copy_addrinfo_common(const struct addrinfo * src,int just_one,const char * caller_file,int caller_line)1572b15cb3dSCy Schubert copy_addrinfo_common(
1582b15cb3dSCy Schubert const struct addrinfo * src,
1592b15cb3dSCy Schubert int just_one
1602b15cb3dSCy Schubert #ifdef EREALLOC_CALLSITE
1612b15cb3dSCy Schubert ,
1622b15cb3dSCy Schubert const char * caller_file,
1632b15cb3dSCy Schubert int caller_line
1642b15cb3dSCy Schubert #endif
1652b15cb3dSCy Schubert )
1662b15cb3dSCy Schubert {
1672b15cb3dSCy Schubert const struct addrinfo * ai_src;
1682b15cb3dSCy Schubert const struct addrinfo * ai_nxt;
1692b15cb3dSCy Schubert struct addrinfo * ai_cpy;
1702b15cb3dSCy Schubert struct addrinfo * dst;
1712b15cb3dSCy Schubert sockaddr_u * psau;
1722b15cb3dSCy Schubert char * pcanon;
1732b15cb3dSCy Schubert u_int elements;
1742b15cb3dSCy Schubert size_t octets;
1752b15cb3dSCy Schubert size_t canons_octets;
1762b15cb3dSCy Schubert size_t str_octets;
1772b15cb3dSCy Schubert
1782b15cb3dSCy Schubert elements = 0;
1792b15cb3dSCy Schubert canons_octets = 0;
1802b15cb3dSCy Schubert
1812b15cb3dSCy Schubert for (ai_src = src; NULL != ai_src; ai_src = ai_nxt) {
1822b15cb3dSCy Schubert if (just_one)
1832b15cb3dSCy Schubert ai_nxt = NULL;
1842b15cb3dSCy Schubert else
1852b15cb3dSCy Schubert ai_nxt = ai_src->ai_next;
1862b15cb3dSCy Schubert ++elements;
1872b15cb3dSCy Schubert if (NULL != ai_src->ai_canonname)
1882b15cb3dSCy Schubert canons_octets += 1 + strlen(ai_src->ai_canonname);
1892b15cb3dSCy Schubert }
1902b15cb3dSCy Schubert
1912b15cb3dSCy Schubert octets = elements * (sizeof(*ai_cpy) + sizeof(*psau));
1922b15cb3dSCy Schubert octets += canons_octets;
1932b15cb3dSCy Schubert
1942b15cb3dSCy Schubert dst = erealloczsite(NULL, octets, 0, TRUE, caller_file,
1952b15cb3dSCy Schubert caller_line);
1962b15cb3dSCy Schubert ai_cpy = dst;
1972b15cb3dSCy Schubert psau = (void *)(ai_cpy + elements);
1982b15cb3dSCy Schubert pcanon = (void *)(psau + elements);
1992b15cb3dSCy Schubert
2002b15cb3dSCy Schubert for (ai_src = src; NULL != ai_src; ai_src = ai_nxt) {
2012b15cb3dSCy Schubert if (just_one)
2022b15cb3dSCy Schubert ai_nxt = NULL;
2032b15cb3dSCy Schubert else
2042b15cb3dSCy Schubert ai_nxt = ai_src->ai_next;
2052b15cb3dSCy Schubert *ai_cpy = *ai_src;
206*3311ff84SXin LI DEBUG_INSIST(ai_cpy->ai_canonname == ai_src->ai_canonname);
207*3311ff84SXin LI INSIST(ai_src->ai_addrlen <= sizeof(sockaddr_u));
2082b15cb3dSCy Schubert memcpy(psau, ai_src->ai_addr, ai_src->ai_addrlen);
2092b15cb3dSCy Schubert ai_cpy->ai_addr = &psau->sa;
2102b15cb3dSCy Schubert ++psau;
211*3311ff84SXin LI if (NULL != ai_src->ai_canonname) {
2122b15cb3dSCy Schubert ai_cpy->ai_canonname = pcanon;
2132b15cb3dSCy Schubert str_octets = 1 + strlen(ai_src->ai_canonname);
2142b15cb3dSCy Schubert memcpy(pcanon, ai_src->ai_canonname, str_octets);
2152b15cb3dSCy Schubert pcanon += str_octets;
2162b15cb3dSCy Schubert }
2172b15cb3dSCy Schubert if (NULL != ai_cpy->ai_next) {
2182b15cb3dSCy Schubert if (just_one)
2192b15cb3dSCy Schubert ai_cpy->ai_next = NULL;
2202b15cb3dSCy Schubert else
2212b15cb3dSCy Schubert ai_cpy->ai_next = ai_cpy + 1;
2222b15cb3dSCy Schubert }
2232b15cb3dSCy Schubert ++ai_cpy;
2242b15cb3dSCy Schubert }
2259034852cSGleb Smirnoff ENSURE(pcanon == ((char *)dst + octets));
2262b15cb3dSCy Schubert
2272b15cb3dSCy Schubert return dst;
2282b15cb3dSCy Schubert }
2292b15cb3dSCy Schubert
2309c2daa00SOllivier Robert
231ea906c41SOllivier Robert #ifndef ISC_PLATFORM_HAVEIPV6
2329c2daa00SOllivier Robert
2339c2daa00SOllivier Robert static char *ai_errlist[] = {
2349c2daa00SOllivier Robert "Success",
2359c2daa00SOllivier Robert "Address family for hostname not supported", /* EAI_ADDRFAMILY */
2369c2daa00SOllivier Robert "Temporary failure in name resolution", /* EAI_AGAIN */
2379c2daa00SOllivier Robert "Invalid value for ai_flags", /* EAI_BADFLAGS */
2389c2daa00SOllivier Robert "Non-recoverable failure in name resolution", /* EAI_FAIL */
2399c2daa00SOllivier Robert "ai_family not supported", /* EAI_FAMILY */
2409c2daa00SOllivier Robert "Memory allocation failure", /* EAI_MEMORY */
2419c2daa00SOllivier Robert "No address associated with hostname", /* EAI_NODATA */
2429c2daa00SOllivier Robert "hostname nor servname provided, or not known", /* EAI_NONAME */
2439c2daa00SOllivier Robert "servname not supported for ai_socktype", /* EAI_SERVICE */
2449c2daa00SOllivier Robert "ai_socktype not supported", /* EAI_SOCKTYPE */
2459c2daa00SOllivier Robert "System error returned in errno", /* EAI_SYSTEM */
2469c2daa00SOllivier Robert "Invalid value for hints", /* EAI_BADHINTS */
2479c2daa00SOllivier Robert "Resolved protocol is unknown", /* EAI_PROTOCOL */
2489c2daa00SOllivier Robert "Unknown error", /* EAI_MAX */
2499c2daa00SOllivier Robert };
2509c2daa00SOllivier Robert
251ea906c41SOllivier Robert /*
252ea906c41SOllivier Robert * Local declaration
253ea906c41SOllivier Robert */
254ea906c41SOllivier Robert int
255ea906c41SOllivier Robert DNSlookup_name(
256ea906c41SOllivier Robert const char *name,
257ea906c41SOllivier Robert int ai_family,
258ea906c41SOllivier Robert struct hostent **Addresses
259ea906c41SOllivier Robert );
260ea906c41SOllivier Robert
261ea906c41SOllivier Robert #ifndef SYS_WINNT
262ea906c41SOllivier Robert /*
263ea906c41SOllivier Robert * Encapsulate gethostbyname to control the error code
264ea906c41SOllivier Robert */
265ea906c41SOllivier Robert int
DNSlookup_name(const char * name,int ai_family,struct hostent ** Addresses)266ea906c41SOllivier Robert DNSlookup_name(
267ea906c41SOllivier Robert const char *name,
268ea906c41SOllivier Robert int ai_family,
269ea906c41SOllivier Robert struct hostent **Addresses
270ea906c41SOllivier Robert )
271ea906c41SOllivier Robert {
272ea906c41SOllivier Robert *Addresses = gethostbyname(name);
273ea906c41SOllivier Robert return (h_errno);
274ea906c41SOllivier Robert }
275ea906c41SOllivier Robert #endif
276ea906c41SOllivier Robert
2772b15cb3dSCy Schubert static int do_nodename (const char *nodename, struct addrinfo *ai,
2782b15cb3dSCy Schubert const struct addrinfo *hints);
2799c2daa00SOllivier Robert
2809c2daa00SOllivier Robert int
getaddrinfo(const char * nodename,const char * servname,const struct addrinfo * hints,struct addrinfo ** res)2819c2daa00SOllivier Robert getaddrinfo (const char *nodename, const char *servname,
2829c2daa00SOllivier Robert const struct addrinfo *hints, struct addrinfo **res)
2839c2daa00SOllivier Robert {
2849c2daa00SOllivier Robert int rval;
285ea906c41SOllivier Robert struct servent *sp;
286ea906c41SOllivier Robert struct addrinfo *ai = NULL;
287ea906c41SOllivier Robert int port;
288ea906c41SOllivier Robert const char *proto = NULL;
289ea906c41SOllivier Robert int family, socktype, flags, protocol;
290ea906c41SOllivier Robert
291ea906c41SOllivier Robert
292ea906c41SOllivier Robert /*
293ea906c41SOllivier Robert * If no name is provide just return an error
294ea906c41SOllivier Robert */
295ea906c41SOllivier Robert if (nodename == NULL && servname == NULL)
296ea906c41SOllivier Robert return (EAI_NONAME);
2979c2daa00SOllivier Robert
2989c2daa00SOllivier Robert ai = calloc(sizeof(struct addrinfo), 1);
2999c2daa00SOllivier Robert if (ai == NULL)
3009c2daa00SOllivier Robert return (EAI_MEMORY);
3019c2daa00SOllivier Robert
302ea906c41SOllivier Robert /*
303ea906c41SOllivier Robert * Copy default values from hints, if available
304ea906c41SOllivier Robert */
305ea906c41SOllivier Robert if (hints != NULL) {
306ea906c41SOllivier Robert ai->ai_flags = hints->ai_flags;
307ea906c41SOllivier Robert ai->ai_family = hints->ai_family;
308ea906c41SOllivier Robert ai->ai_socktype = hints->ai_socktype;
309ea906c41SOllivier Robert ai->ai_protocol = hints->ai_protocol;
310ea906c41SOllivier Robert
311ea906c41SOllivier Robert family = hints->ai_family;
312ea906c41SOllivier Robert socktype = hints->ai_socktype;
313ea906c41SOllivier Robert protocol = hints->ai_protocol;
314ea906c41SOllivier Robert flags = hints->ai_flags;
315ea906c41SOllivier Robert
316ea906c41SOllivier Robert switch (family) {
317ea906c41SOllivier Robert case AF_UNSPEC:
318ea906c41SOllivier Robert switch (hints->ai_socktype) {
319ea906c41SOllivier Robert case SOCK_STREAM:
320ea906c41SOllivier Robert proto = "tcp";
321ea906c41SOllivier Robert break;
322ea906c41SOllivier Robert case SOCK_DGRAM:
323ea906c41SOllivier Robert proto = "udp";
324ea906c41SOllivier Robert break;
325ea906c41SOllivier Robert }
326ea906c41SOllivier Robert break;
327ea906c41SOllivier Robert case AF_INET:
328ea906c41SOllivier Robert case AF_INET6:
329ea906c41SOllivier Robert switch (hints->ai_socktype) {
330ea906c41SOllivier Robert case 0:
331ea906c41SOllivier Robert break;
332ea906c41SOllivier Robert case SOCK_STREAM:
333ea906c41SOllivier Robert proto = "tcp";
334ea906c41SOllivier Robert break;
335ea906c41SOllivier Robert case SOCK_DGRAM:
336ea906c41SOllivier Robert proto = "udp";
337ea906c41SOllivier Robert break;
338ea906c41SOllivier Robert case SOCK_RAW:
339ea906c41SOllivier Robert break;
340ea906c41SOllivier Robert default:
341ea906c41SOllivier Robert return (EAI_SOCKTYPE);
342ea906c41SOllivier Robert }
343ea906c41SOllivier Robert break;
344ea906c41SOllivier Robert #ifdef AF_LOCAL
345ea906c41SOllivier Robert case AF_LOCAL:
346ea906c41SOllivier Robert switch (hints->ai_socktype) {
347ea906c41SOllivier Robert case 0:
348ea906c41SOllivier Robert break;
349ea906c41SOllivier Robert case SOCK_STREAM:
350ea906c41SOllivier Robert break;
351ea906c41SOllivier Robert case SOCK_DGRAM:
352ea906c41SOllivier Robert break;
353ea906c41SOllivier Robert default:
354ea906c41SOllivier Robert return (EAI_SOCKTYPE);
355ea906c41SOllivier Robert }
356ea906c41SOllivier Robert break;
357ea906c41SOllivier Robert #endif
358ea906c41SOllivier Robert default:
359ea906c41SOllivier Robert return (EAI_FAMILY);
360ea906c41SOllivier Robert }
361ea906c41SOllivier Robert } else {
362ea906c41SOllivier Robert protocol = 0;
363ea906c41SOllivier Robert family = 0;
364ea906c41SOllivier Robert socktype = 0;
365ea906c41SOllivier Robert flags = 0;
366ea906c41SOllivier Robert }
367ea906c41SOllivier Robert
3689c2daa00SOllivier Robert rval = do_nodename(nodename, ai, hints);
3699c2daa00SOllivier Robert if (rval != 0) {
3709c2daa00SOllivier Robert freeaddrinfo(ai);
3719c2daa00SOllivier Robert return (rval);
3729c2daa00SOllivier Robert }
373ea906c41SOllivier Robert
374ea906c41SOllivier Robert /*
375ea906c41SOllivier Robert * First, look up the service name (port) if it was
376ea906c41SOllivier Robert * requested. If the socket type wasn't specified, then
377ea906c41SOllivier Robert * try and figure it out.
378ea906c41SOllivier Robert */
3799c2daa00SOllivier Robert if (servname != NULL) {
380ea906c41SOllivier Robert char *e;
381ea906c41SOllivier Robert
382ea906c41SOllivier Robert port = strtol(servname, &e, 10);
383ea906c41SOllivier Robert if (*e == '\0') {
384ea906c41SOllivier Robert if (socktype == 0)
385ea906c41SOllivier Robert return (EAI_SOCKTYPE);
386ea906c41SOllivier Robert if (port < 0 || port > 65535)
3879c2daa00SOllivier Robert return (EAI_SERVICE);
388ea906c41SOllivier Robert port = htons((unsigned short) port);
389ea906c41SOllivier Robert } else {
390ea906c41SOllivier Robert sp = getservbyname(servname, proto);
391ea906c41SOllivier Robert if (sp == NULL)
392ea906c41SOllivier Robert return (EAI_SERVICE);
393ea906c41SOllivier Robert port = sp->s_port;
394ea906c41SOllivier Robert if (socktype == 0) {
395ea906c41SOllivier Robert if (strcmp(sp->s_proto, "tcp") == 0)
396ea906c41SOllivier Robert socktype = SOCK_STREAM;
397ea906c41SOllivier Robert else if (strcmp(sp->s_proto, "udp") == 0)
398ea906c41SOllivier Robert socktype = SOCK_DGRAM;
3999c2daa00SOllivier Robert }
4009c2daa00SOllivier Robert }
401ea906c41SOllivier Robert } else
402ea906c41SOllivier Robert port = 0;
403ea906c41SOllivier Robert
404ea906c41SOllivier Robert /*
405ea906c41SOllivier Robert *
406ea906c41SOllivier Robert * Set up the port number
407ea906c41SOllivier Robert */
408ea906c41SOllivier Robert if (ai->ai_family == AF_INET)
409ea906c41SOllivier Robert ((struct sockaddr_in *)ai->ai_addr)->sin_port = (unsigned short) port;
410ea906c41SOllivier Robert else if (ai->ai_family == AF_INET6)
411ea906c41SOllivier Robert ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port = (unsigned short) port;
4129c2daa00SOllivier Robert *res = ai;
4139c2daa00SOllivier Robert return (0);
4149c2daa00SOllivier Robert }
4159c2daa00SOllivier Robert
4169c2daa00SOllivier Robert void
freeaddrinfo(struct addrinfo * ai)4179c2daa00SOllivier Robert freeaddrinfo(struct addrinfo *ai)
4189c2daa00SOllivier Robert {
4199c2daa00SOllivier Robert if (ai->ai_canonname != NULL)
420ea906c41SOllivier Robert {
4219c2daa00SOllivier Robert free(ai->ai_canonname);
422ea906c41SOllivier Robert ai->ai_canonname = NULL;
423ea906c41SOllivier Robert }
4249c2daa00SOllivier Robert if (ai->ai_addr != NULL)
425ea906c41SOllivier Robert {
4269c2daa00SOllivier Robert free(ai->ai_addr);
427ea906c41SOllivier Robert ai->ai_addr = NULL;
428ea906c41SOllivier Robert }
4299c2daa00SOllivier Robert free(ai);
430ea906c41SOllivier Robert ai = NULL;
4319c2daa00SOllivier Robert }
4329c2daa00SOllivier Robert
4339c2daa00SOllivier Robert int
getnameinfo(const struct sockaddr * sa,u_int salen,char * host,size_t hostlen,char * serv,size_t servlen,int flags)4349c2daa00SOllivier Robert getnameinfo (const struct sockaddr *sa, u_int salen, char *host,
4359c2daa00SOllivier Robert size_t hostlen, char *serv, size_t servlen, int flags)
4369c2daa00SOllivier Robert {
4379c2daa00SOllivier Robert struct hostent *hp;
4389c2daa00SOllivier Robert
4399c2daa00SOllivier Robert if (sa->sa_family != AF_INET)
4409c2daa00SOllivier Robert return (EAI_FAMILY);
4419c2daa00SOllivier Robert hp = gethostbyaddr(
4429c2daa00SOllivier Robert (const char *)&((const struct sockaddr_in *)sa)->sin_addr,
4439c2daa00SOllivier Robert 4, AF_INET);
4449c2daa00SOllivier Robert if (hp == NULL) {
4459c2daa00SOllivier Robert if (h_errno == TRY_AGAIN)
4469c2daa00SOllivier Robert return (EAI_AGAIN);
4479c2daa00SOllivier Robert else
4489c2daa00SOllivier Robert return (EAI_FAIL);
4499c2daa00SOllivier Robert }
4502b15cb3dSCy Schubert if (host != NULL && hostlen > 0)
4512b15cb3dSCy Schubert strlcpy(host, hp->h_name, hostlen);
4529c2daa00SOllivier Robert return (0);
4539c2daa00SOllivier Robert }
4549c2daa00SOllivier Robert
4559c2daa00SOllivier Robert char *
gai_strerror(int ecode)4569c2daa00SOllivier Robert gai_strerror(int ecode)
4579c2daa00SOllivier Robert {
4589c2daa00SOllivier Robert if (ecode < 0 || ecode > EAI_MAX)
4599c2daa00SOllivier Robert ecode = EAI_MAX;
4609c2daa00SOllivier Robert return ai_errlist[ecode];
4619c2daa00SOllivier Robert }
4629c2daa00SOllivier Robert
4639c2daa00SOllivier Robert static int
do_nodename(const char * nodename,struct addrinfo * ai,const struct addrinfo * hints)4649c2daa00SOllivier Robert do_nodename(
4659c2daa00SOllivier Robert const char *nodename,
4669c2daa00SOllivier Robert struct addrinfo *ai,
4679c2daa00SOllivier Robert const struct addrinfo *hints)
4689c2daa00SOllivier Robert {
469ea906c41SOllivier Robert struct hostent *hp = NULL;
4709c2daa00SOllivier Robert struct sockaddr_in *sockin;
471ea906c41SOllivier Robert struct sockaddr_in6 *sockin6;
472ea906c41SOllivier Robert int errval;
4739c2daa00SOllivier Robert
4749c2daa00SOllivier Robert ai->ai_addr = calloc(sizeof(struct sockaddr_storage), 1);
4759c2daa00SOllivier Robert if (ai->ai_addr == NULL)
4769c2daa00SOllivier Robert return (EAI_MEMORY);
4779c2daa00SOllivier Robert
478ea906c41SOllivier Robert /*
479ea906c41SOllivier Robert * For an empty node name just use the wildcard.
480ea906c41SOllivier Robert * NOTE: We need to assume that the address family is
481ea906c41SOllivier Robert * set elsewhere so that we can set the appropriate wildcard
482ea906c41SOllivier Robert */
483ea906c41SOllivier Robert if (nodename == NULL) {
484ea906c41SOllivier Robert if (ai->ai_family == AF_INET)
485ea906c41SOllivier Robert {
486*3311ff84SXin LI ai->ai_addrlen = sizeof(struct sockaddr_in);
487ea906c41SOllivier Robert sockin = (struct sockaddr_in *)ai->ai_addr;
488ea906c41SOllivier Robert sockin->sin_family = (short) ai->ai_family;
489ea906c41SOllivier Robert sockin->sin_addr.s_addr = htonl(INADDR_ANY);
490ea906c41SOllivier Robert }
491ea906c41SOllivier Robert else
492ea906c41SOllivier Robert {
493*3311ff84SXin LI ai->ai_addrlen = sizeof(struct sockaddr_in6);
494ea906c41SOllivier Robert sockin6 = (struct sockaddr_in6 *)ai->ai_addr;
495ea906c41SOllivier Robert sockin6->sin6_family = (short) ai->ai_family;
496ea906c41SOllivier Robert /*
497ea906c41SOllivier Robert * we have already zeroed out the address
498ea906c41SOllivier Robert * so we don't actually need to do this
499ea906c41SOllivier Robert * This assignment is causing problems so
500ea906c41SOllivier Robert * we don't do what this would do.
501ea906c41SOllivier Robert sockin6->sin6_addr = in6addr_any;
502ea906c41SOllivier Robert */
503ea906c41SOllivier Robert }
5042b15cb3dSCy Schubert #ifdef ISC_PLATFORM_HAVESALEN
505ea906c41SOllivier Robert ai->ai_addr->sa_len = SOCKLEN(ai->ai_addr);
506ea906c41SOllivier Robert #endif
507ea906c41SOllivier Robert
508ea906c41SOllivier Robert return (0);
509ea906c41SOllivier Robert }
510ea906c41SOllivier Robert
511ea906c41SOllivier Robert /*
512ea906c41SOllivier Robert * See if we have an IPv6 address
513ea906c41SOllivier Robert */
514ea906c41SOllivier Robert if(strchr(nodename, ':') != NULL) {
515ea906c41SOllivier Robert if (inet_pton(AF_INET6, nodename,
516ea906c41SOllivier Robert &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr) == 1) {
517ea906c41SOllivier Robert ((struct sockaddr_in6 *)ai->ai_addr)->sin6_family = AF_INET6;
518ea906c41SOllivier Robert ai->ai_family = AF_INET6;
519ea906c41SOllivier Robert ai->ai_addrlen = sizeof(struct sockaddr_in6);
520ea906c41SOllivier Robert return (0);
521ea906c41SOllivier Robert }
522ea906c41SOllivier Robert }
523ea906c41SOllivier Robert
524ea906c41SOllivier Robert /*
525ea906c41SOllivier Robert * See if we have an IPv4 address
526ea906c41SOllivier Robert */
527ea906c41SOllivier Robert if (inet_pton(AF_INET, nodename,
528ea906c41SOllivier Robert &((struct sockaddr_in *)ai->ai_addr)->sin_addr) == 1) {
529ea906c41SOllivier Robert ((struct sockaddr *)ai->ai_addr)->sa_family = AF_INET;
5309c2daa00SOllivier Robert ai->ai_family = AF_INET;
5319c2daa00SOllivier Robert ai->ai_addrlen = sizeof(struct sockaddr_in);
5329c2daa00SOllivier Robert return (0);
5339c2daa00SOllivier Robert }
534ea906c41SOllivier Robert
535ea906c41SOllivier Robert /*
536ea906c41SOllivier Robert * If the numeric host flag is set, don't attempt resolution
537ea906c41SOllivier Robert */
538ea906c41SOllivier Robert if (hints != NULL && (hints->ai_flags & AI_NUMERICHOST))
5399c2daa00SOllivier Robert return (EAI_NONAME);
540ea906c41SOllivier Robert
541ea906c41SOllivier Robert /*
542ea906c41SOllivier Robert * Look for a name
543ea906c41SOllivier Robert */
544ea906c41SOllivier Robert
545ea906c41SOllivier Robert errval = DNSlookup_name(nodename, AF_INET, &hp);
546ea906c41SOllivier Robert
5479c2daa00SOllivier Robert if (hp == NULL) {
548ea906c41SOllivier Robert if (errval == TRY_AGAIN || errval == EAI_AGAIN)
5499c2daa00SOllivier Robert return (EAI_AGAIN);
550ea906c41SOllivier Robert else if (errval == EAI_NONAME) {
551ea906c41SOllivier Robert if (inet_pton(AF_INET, nodename,
552ea906c41SOllivier Robert &((struct sockaddr_in *)ai->ai_addr)->sin_addr) == 1) {
553ea906c41SOllivier Robert ((struct sockaddr *)ai->ai_addr)->sa_family = AF_INET;
5549c2daa00SOllivier Robert ai->ai_family = AF_INET;
5559c2daa00SOllivier Robert ai->ai_addrlen = sizeof(struct sockaddr_in);
5569c2daa00SOllivier Robert return (0);
5579c2daa00SOllivier Robert }
558ea906c41SOllivier Robert return (errval);
559ea906c41SOllivier Robert }
560ea906c41SOllivier Robert else
561ea906c41SOllivier Robert {
562ea906c41SOllivier Robert return (errval);
5639c2daa00SOllivier Robert }
5649c2daa00SOllivier Robert }
5659c2daa00SOllivier Robert ai->ai_family = hp->h_addrtype;
5669c2daa00SOllivier Robert ai->ai_addrlen = sizeof(struct sockaddr);
5679c2daa00SOllivier Robert sockin = (struct sockaddr_in *)ai->ai_addr;
5689c2daa00SOllivier Robert memcpy(&sockin->sin_addr, hp->h_addr, hp->h_length);
5699c2daa00SOllivier Robert ai->ai_addr->sa_family = hp->h_addrtype;
5702b15cb3dSCy Schubert #ifdef ISC_PLATFORM_HAVESALEN
5719c2daa00SOllivier Robert ai->ai_addr->sa_len = sizeof(struct sockaddr);
5729c2daa00SOllivier Robert #endif
5732b15cb3dSCy Schubert if (hints != NULL && (hints->ai_flags & AI_CANONNAME))
5742b15cb3dSCy Schubert ai->ai_canonname = estrdup(hp->h_name);
5759c2daa00SOllivier Robert return (0);
5769c2daa00SOllivier Robert }
5779c2daa00SOllivier Robert
578ea906c41SOllivier Robert #endif /* !ISC_PLATFORM_HAVEIPV6 */
579