1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
3 * Copyright (C) 2001,2002,2003,2004,2005,2006 by the Massachusetts Institute of Technology,
4 * Cambridge, MA, USA. All Rights Reserved.
6 * This software is being provided to you, the LICENSEE, by the
7 * Massachusetts Institute of Technology (M.I.T.) under the following
8 * license. By obtaining, using and/or copying this software, you agree
9 * that you have read, understood, and will comply with these terms and
12 * Export of this software from the United States of America may
13 * require a specific license from the United States Government.
14 * It is the responsibility of any person or organization contemplating
15 * export to obtain such a license before exporting.
17 * WITHIN THAT CONSTRAINT, permission to use, copy, modify and distribute
18 * this software and its documentation for any purpose and without fee or
19 * royalty is hereby granted, provided that you agree to comply with the
20 * following copyright notice and statements, including the disclaimer, and
21 * that the same appear on ALL copies of the software and documentation,
22 * including modifications that you make for internal use or for
25 * THIS SOFTWARE IS PROVIDED "AS IS", AND M.I.T. MAKES NO REPRESENTATIONS
26 * OR WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not
27 * limitation, M.I.T. MAKES NO REPRESENTATIONS OR WARRANTIES OF
28 * MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF
29 * THE LICENSED SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY
30 * PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
32 * The name of the Massachusetts Institute of Technology or M.I.T. may NOT
33 * be used in advertising or publicity pertaining to distribution of the
34 * software. Title to copyright in this software and any associated
35 * documentation shall at all times remain with M.I.T., and USER agrees to
38 * Furthermore if you modify this software you must label
39 * your software as modified software and not distribute it in such a
40 * fashion that it might be confused with the original M.I.T. software.
46 * If a system version is available but buggy, save handles to it,
47 * redefine the names to refer to static functions defined here, and
48 * in those functions, call the system versions and fix up the
49 * returned data. Use the native data structures and flag values.
51 * If no system version exists, use gethostby* and fake it. Define
52 * the data structures and flag values locally.
55 * On Mac OS X, getaddrinfo results aren't cached (though
56 * gethostbyname results are), so we need to build a cache here. Now
57 * things are getting really messy. Because the cache is in use, we
58 * use getservbyname, and throw away thread safety. (Not that the
59 * cache is thread safe, but when we get locking support, that'll be
60 * dealt with.) This code needs tearing down and rebuilding, soon.
63 * Note that recent Windows developers' code has an interesting hack:
64 * When you include the right header files, with the right set of
65 * macros indicating system versions, you'll get an inline function
66 * that looks for getaddrinfo (or whatever) in the system library, and
67 * calls it if it's there. If it's not there, it fakes it with
70 * We're taking a simpler approach: A system provides these routines or
73 * Someday, we may want to take into account different versions (say,
74 * different revs of GNU libc) where some are broken in one way, and
75 * some work or are broken in another way. Cross that bridge when we
82 * + For AIX 4.3.3, using the RFC 2133 definition: Implement
83 * AI_NUMERICHOST. It's not defined in the header file.
85 * For certain (old?) versions of GNU libc, AI_NUMERICHOST is
86 * defined but not implemented.
88 * + Use gethostbyname2, inet_aton and other IPv6 or thread-safe
89 * functions if available. But, see
90 * http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=135182 for one
91 * gethostbyname2 problem on Linux. And besides, if a platform is
92 * supporting IPv6 at all, they really should be doing getaddrinfo
95 * + inet_ntop, inet_pton
97 * + Conditionally export/import the function definitions, so a
98 * library can have a single copy instead of multiple.
100 * + Upgrade host requirements to include working implementations of
101 * these functions, and throw all this away. Pleeease? :-)
104 #include "port-sockets.h"
105 #include "socket-utils.h"
106 #include "k5-platform.h"
107 #include "k5-thread.h"
108 #include "supp-int.h"
113 #define IMPLEMENT_FAKE_GETADDRINFO
114 #include "fake-addrinfo.h"
119 getaddrinfo (/*@in@*/ /*@null@*/ const char *,
120 /*@in@*/ /*@null@*/ const char *,
121 /*@in@*/ /*@null@*/ const struct addrinfo *,
122 /*@out@*/ struct addrinfo **)
125 freeaddrinfo (/*@only@*/ /*@out@*/ struct addrinfo *)
128 getnameinfo (const struct sockaddr *addr, socklen_t addrsz,
129 /*@out@*/ /*@null@*/ char *h, socklen_t hsz,
130 /*@out@*/ /*@null@*/ char *s, socklen_t ssz,
132 /*@requires (maxSet(h)+1) >= hsz /\ (maxSet(s)+1) >= ssz @*/
133 /* too hard: maxRead(addr) >= (addrsz-1) */
134 /*@modifies *h, *s@*/;
135 extern /*@dependent@*/ char *gai_strerror (int code) /*@*/;
140 #include "cache-addrinfo.h"
142 #if (defined (__linux__) && defined(HAVE_GETADDRINFO)) || defined (_AIX)
143 /* See comments below. */
144 # define WRAP_GETADDRINFO
147 #if defined (__linux__) && defined(HAVE_GETADDRINFO)
148 /* Define COPY_FIRST_CANONNAME for glibc 2.3 and prior. */
149 #include <features.h>
150 # ifdef __GLIBC_PREREQ
151 # if ! __GLIBC_PREREQ(2, 4)
152 # define COPY_FIRST_CANONNAME
155 # define COPY_FIRST_CANONNAME
160 # define NUMERIC_SERVICE_BROKEN
161 # define COPY_FIRST_CANONNAME
165 #ifdef COPY_FIRST_CANONNAME
169 #ifdef NUMERIC_SERVICE_BROKEN
170 # include <ctype.h> /* isdigit */
171 # include <stdlib.h> /* strtoul */
175 /* Do we actually have *any* systems we care about that don't provide
176 either getaddrinfo or one of these two flavors of
178 #if !defined(HAVE_GETHOSTBYNAME_R) || defined(THREADSAFE_GETHOSTBYNAME)
179 typedef struct hostent *GET_HOST_TMP;
180 #define GET_HOST_BY_NAME(NAME, HP, ERR, TMP) \
181 { TMP = gethostbyname (NAME); (ERR) = h_errno; (HP) = TMP; }
182 #define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR, TMP) \
183 { TMP = gethostbyaddr ((ADDR), (ADDRLEN), (FAMILY)); (ERR) = h_errno; (HP) = TMP; }
185 #ifdef _AIX /* XXX should have a feature test! */
188 struct hostent_data data;
190 #define GET_HOST_BY_NAME(NAME, HP, ERR, TMP) \
192 (HP) = (gethostbyname_r((NAME), &TMP.ent, &TMP.data) \
198 #define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR) \
200 struct hostent my_h_ent; \
201 struct hostent_data my_h_ent_data; \
202 (HP) = (gethostbyaddr_r((ADDR), (ADDRLEN), (FAMILY), &my_h_ent, \
210 #ifdef GETHOSTBYNAME_R_RETURNS_INT
215 #define GET_HOST_BY_NAME(NAME, HP, ERR, TMP) \
217 struct hostent *my_hp = NULL; \
218 int my_h_err, my_ret; \
219 my_ret = gethostbyname_r((NAME), &TMP.ent, \
220 TMP.buf, sizeof (TMP.buf), &my_hp, \
222 (HP) = (((my_ret != 0) || (my_hp != &TMP.ent)) \
227 #define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR, TMP) \
229 struct hostent *my_hp; \
230 int my_h_err, my_ret; \
231 my_ret = gethostbyaddr_r((ADDR), (ADDRLEN), (FAMILY), &TMP.ent, \
232 TMP.buf, sizeof (TMP.buf), &my_hp, \
234 (HP) = (((my_ret != 0) || (my_hp != &TMP.ent)) \
244 #define GET_HOST_BY_NAME(NAME, HP, ERR, TMP) \
247 (HP) = gethostbyname_r((NAME), &TMP.ent, \
248 TMP.buf, sizeof (TMP.buf), &my_h_err); \
251 #define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR, TMP) \
254 (HP) = gethostbyaddr_r((ADDR), (ADDRLEN), (FAMILY), &TMP.ent, \
255 TMP.buf, sizeof (TMP.buf), &my_h_err); \
258 #endif /* returns int? */
262 /* Now do the same for getservby* functions. */
263 #ifndef HAVE_GETSERVBYNAME_R
264 typedef struct servent *GET_SERV_TMP;
265 #define GET_SERV_BY_NAME(NAME, PROTO, SP, ERR, TMP) \
266 (TMP = getservbyname (NAME, PROTO), (SP) = TMP, (ERR) = (SP) ? 0 : -1)
267 #define GET_SERV_BY_PORT(PORT, PROTO, SP, ERR, TMP) \
268 (TMP = getservbyport (PORT, PROTO), (SP) = TMP, (ERR) = (SP) ? 0 : -1)
270 #ifdef GETSERVBYNAME_R_RETURNS_INT
275 #define GET_SERV_BY_NAME(NAME, PROTO, SP, ERR, TMP) \
277 struct servent *my_sp; \
279 (SP) = (getservbyname_r((NAME), (PROTO), &TMP.ent, \
280 TMP.buf, sizeof (TMP.buf), &my_sp, \
286 #define GET_SERV_BY_PORT(PORT, PROTO, SP, ERR, TMP) \
288 struct servent *my_sp; \
290 (SP) = (getservbyport_r((PORT), (PROTO), &TMP.ent, \
291 TMP.buf, sizeof (TMP.buf), &my_sp, \
298 /* returns ptr -- IRIX? */
303 #define GET_SERV_BY_NAME(NAME, PROTO, SP, ERR, TMP) \
305 (SP) = getservbyname_r((NAME), (PROTO), &TMP.ent, \
306 TMP.buf, sizeof (TMP.buf)); \
307 (ERR) = (SP) == NULL; \
310 #define GET_SERV_BY_PORT(PORT, PROTO, SP, ERR, TMP) \
312 struct servent *my_sp; \
313 my_sp = getservbyport_r((PORT), (PROTO), &TMP.ent, \
314 TMP.buf, sizeof (TMP.buf)); \
316 (ERR) = my_sp == 0; \
317 (ERR) = (ERR); /* avoid "unused" warning */ \
322 #if defined(WRAP_GETADDRINFO) || defined(FAI_CACHE)
324 system_getaddrinfo (const char *name, const char *serv,
325 const struct addrinfo *hint,
326 struct addrinfo **res)
328 return getaddrinfo(name, serv, hint, res);
332 system_freeaddrinfo (struct addrinfo *ai)
337 /* Note: Implementations written to RFC 2133 use size_t, while RFC
338 2553 implementations use socklen_t, for the second parameter.
340 Mac OS X (10.2) and AIX 4.3.3 appear to be in the RFC 2133 camp,
341 but we don't have an autoconf test for that right now. */
343 system_getnameinfo (const struct sockaddr *sa, socklen_t salen,
344 char *host, size_t hostlen, char *serv, size_t servlen,
347 return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
351 #if !defined (HAVE_GETADDRINFO) || defined(WRAP_GETADDRINFO) || defined(FAI_CACHE)
354 #define getaddrinfo my_fake_getaddrinfo
356 #define freeaddrinfo my_fake_freeaddrinfo
360 #if !defined (HAVE_GETADDRINFO)
363 #define gai_strerror my_fake_gai_strerror
365 #endif /* ! HAVE_GETADDRINFO */
367 #if (!defined (HAVE_GETADDRINFO) || defined (WRAP_GETADDRINFO)) && defined(DEBUG_ADDRINFO)
368 /* Some debug routines. */
370 static const char *protoname (int p, char *buf, size_t bufsize) {
371 #define X(N) if (p == IPPROTO_ ## N) return #N
389 snprintf(buf, bufsize, " %-2d", p);
393 static const char *socktypename (int t, char *buf, size_t bufsize) {
395 case SOCK_DGRAM: return "DGRAM";
396 case SOCK_STREAM: return "STREAM";
397 case SOCK_RAW: return "RAW";
398 case SOCK_RDM: return "RDM";
399 case SOCK_SEQPACKET: return "SEQPACKET";
401 snprintf(buf, bufsize, " %-2d", t);
405 static const char *familyname (int f, char *buf, size_t bufsize) {
408 snprintf(buf, bufsize, "AF %d", f);
410 case AF_INET: return "AF_INET";
411 case AF_INET6: return "AF_INET6";
413 case AF_UNIX: return "AF_UNIX";
418 static void debug_dump_getaddrinfo_args (const char *name, const char *serv,
419 const struct addrinfo *hint)
423 "getaddrinfo(hostname %s, service %s,\n"
425 name ? name : "(null)", serv ? serv : "(null)");
429 #define Z(FLAG) if (hint->ai_flags & AI_##FLAG) fprintf(stderr, "%s%s", sep, #FLAG), sep = "|"
432 #ifdef AI_NUMERICHOST
436 fprintf(stderr, "no-flags");
438 fprintf(stderr, " %s", familyname(hint->ai_family, buf,
440 if (hint->ai_socktype)
441 fprintf(stderr, " SOCK_%s", socktypename(hint->ai_socktype, buf,
443 if (hint->ai_protocol)
444 fprintf(stderr, " IPPROTO_%s", protoname(hint->ai_protocol, buf,
447 fprintf(stderr, "(null)");
448 fprintf(stderr, " }):\n");
451 static void debug_dump_error (int err)
453 fprintf(stderr, "error %d: %s\n", err, gai_strerror(err));
456 static void debug_dump_addrinfos (const struct addrinfo *ai)
460 fprintf(stderr, "addrinfos returned:\n");
462 fprintf(stderr, "%p...", ai);
463 fprintf(stderr, " socktype=%s", socktypename(ai->ai_socktype, buf,
465 fprintf(stderr, " ai_family=%s", familyname(ai->ai_family, buf,
467 if (ai->ai_family != ai->ai_addr->sa_family)
468 fprintf(stderr, " sa_family=%s",
469 familyname(ai->ai_addr->sa_family, buf, sizeof(buf)));
470 fprintf(stderr, "\n");
474 fprintf(stderr, "end addrinfos returned (%d)\n");
479 #if !defined (HAVE_GETADDRINFO) || defined (WRAP_GETADDRINFO)
482 int getaddrinfo (const char *name, const char *serv,
483 const struct addrinfo *hint, struct addrinfo **result);
486 void freeaddrinfo (struct addrinfo *ai);
490 #if !defined (HAVE_GETADDRINFO)
492 #define HAVE_FAKE_GETADDRINFO /* was not originally HAVE_GETADDRINFO */
493 #define HAVE_GETADDRINFO
494 #define NEED_FAKE_GETNAMEINFO
495 #undef HAVE_GETNAMEINFO
496 #define HAVE_GETNAMEINFO 1
499 #define getnameinfo my_fake_getnameinfo
502 char *gai_strerror (int code);
506 #if !defined (HAVE_GETADDRINFO)
508 int getnameinfo (const struct sockaddr *addr, socklen_t len,
509 char *host, socklen_t hostlen,
510 char *service, socklen_t servicelen,
514 /* Fudge things on older gai implementations. */
515 /* AIX 4.3.3 is based on RFC 2133; no AI_NUMERICHOST. */
516 #ifndef AI_NUMERICHOST
517 # define AI_NUMERICHOST 0
519 /* Partial RFC 2553 implementations may not have AI_ADDRCONFIG and
520 friends, which RFC 3493 says are now part of the getaddrinfo
521 interface, and we'll want to use. */
522 #ifndef AI_ADDRCONFIG
523 # define AI_ADDRCONFIG 0
526 # define AI_V4MAPPED 0
532 # define AI_DEFAULT (AI_ADDRCONFIG|AI_V4MAPPED)
535 #if defined(HAVE_FAKE_GETADDRINFO) || defined(FAI_CACHE)
536 #define NEED_FAKE_GETADDRINFO
539 #if defined(NEED_FAKE_GETADDRINFO) || defined(WRAP_GETADDRINFO)
543 #ifdef NEED_FAKE_GETADDRINFO
544 #include <string.h> /* for strspn */
546 static inline int translate_h_errno (int h);
548 static inline int fai_add_entry (struct addrinfo **result, void *addr,
549 int port, const struct addrinfo *template)
551 struct addrinfo *n = malloc (sizeof (struct addrinfo));
554 if (template->ai_family != AF_INET
555 #ifdef KRB5_USE_INET6
556 && template->ai_family != AF_INET6
561 if (template->ai_family == AF_INET) {
562 struct sockaddr_in *sin4;
563 sin4 = malloc (sizeof (struct sockaddr_in));
566 memset (sin4, 0, sizeof (struct sockaddr_in)); /* for sin_zero */
567 n->ai_addr = (struct sockaddr *) sin4;
568 sin4->sin_family = AF_INET;
569 sin4->sin_addr = *(struct in_addr *)addr;
570 sin4->sin_port = port;
572 sin4->sin_len = sizeof (struct sockaddr_in);
575 #ifdef KRB5_USE_INET6
576 if (template->ai_family == AF_INET6) {
577 struct sockaddr_in6 *sin6;
578 sin6 = malloc (sizeof (struct sockaddr_in6));
581 memset (sin6, 0, sizeof (struct sockaddr_in6)); /* for sin_zero */
582 n->ai_addr = (struct sockaddr *) sin6;
583 sin6->sin6_family = AF_INET6;
584 sin6->sin6_addr = *(struct in6_addr *)addr;
585 sin6->sin6_port = port;
587 sin6->sin6_len = sizeof (struct sockaddr_in6);
591 n->ai_next = *result;
597 /* fake addrinfo cache entries */
598 #define CACHE_ENTRY_LIFETIME 15 /* seconds */
600 static void plant_face (const char *name, struct face *entry)
602 entry->name = strdup(name);
603 if (entry->name == NULL)
604 /* @@ Wastes memory. */
606 k5_mutex_assert_locked(&krb5int_fac.lock);
607 entry->next = krb5int_fac.data;
608 entry->expiration = time(0) + CACHE_ENTRY_LIFETIME;
609 krb5int_fac.data = entry;
610 #ifdef DEBUG_ADDRINFO
611 printf("added cache entry '%s' at %p: %d ipv4, %d ipv6; expire %d\n",
612 name, entry, entry->naddrs4, entry->naddrs6, entry->expiration);
616 static int find_face (const char *name, struct face **entry)
618 struct face *fp, **fpp;
619 time_t now = time(0);
621 /* First, scan for expired entries and free them.
622 (Future improvement: Integrate these two loops.) */
623 #ifdef DEBUG_ADDRINFO
624 printf("scanning cache at %d for '%s'...\n", now, name);
626 k5_mutex_assert_locked(&krb5int_fac.lock);
627 for (fpp = &krb5int_fac.data; *fpp; ) {
629 #ifdef DEBUG_ADDRINFO
630 printf(" checking expiration time of @%p: %d\n",
633 if (fp->expiration < now) {
634 #ifdef DEBUG_ADDRINFO
635 printf("\texpiring cache entry\n");
643 /* Stay at this point in the list, and check again. */
649 for (fp = krb5int_fac.data; fp; fp = fp->next) {
650 #ifdef DEBUG_ADDRINFO
651 printf(" comparing entry @%p\n", fp);
653 if (!strcasecmp(fp->name, name)) {
654 #ifdef DEBUG_ADDRINFO
655 printf("\tMATCH!\n");
667 static int krb5int_lock_fac(void), krb5int_unlock_fac(void);
670 static inline int fai_add_hosts_by_name (const char *name,
671 struct addrinfo *template,
672 int portnum, int flags,
673 struct addrinfo **result)
680 err = krb5int_lock_fac();
685 if (!find_face(name, &ce)) {
686 struct addrinfo myhints = { 0 }, *ai, *ai2;
689 #ifdef DEBUG_ADDRINFO
690 printf("looking up new data for '%s'...\n", name);
692 myhints.ai_socktype = SOCK_STREAM;
693 myhints.ai_flags = AI_CANONNAME;
694 /* Don't set ai_family -- we want to cache all address types,
695 because the next lookup may not use the same constraints as
696 the current one. We *could* cache them separately, so that
697 we never have to look up an IPv6 address if we are always
698 asked for IPv4 only, but let's deal with that later, if we
700 /* Try NULL for the service for now.
702 It would be nice to use the requested service name, and not
703 have to patch things up, but then we'd be doing multiple
704 queries for the same host when we get different services.
705 We were using "telnet" for a little more confidence that
706 getaddrinfo would heed the hints to only give us stream
707 socket types (with no socket type and null service name, we
708 might get stream *and* dgram *and* raw, for each address,
709 or only raw). The RFC 3493 description of ai_socktype
710 sometimes associates it with the specified service,
713 But on Mac OS X (10.3, 10.4) they've "extended" getaddrinfo
714 to make SRV RR queries. (Please, somebody, show me
715 something in the specs that actually supports this? RFC
716 3493 says nothing about it, but it does say getaddrinfo is
717 the new way to look up hostnames. RFC 2782 says SRV
718 records should *not* be used unless the application
719 protocol spec says to do so. The Telnet spec does not say
720 to do it.) And then they complain when our code
721 "unexpectedly" seems to use this "extension" in cases where
722 they don't want it to be used.
724 Fortunately, it appears that if we specify ai_socktype as
725 SOCK_STREAM and use a null service name, we only get one
726 copy of each address on all the platforms I've tried,
727 although it may not have ai_socktype filled in properly.
728 So, we'll fudge it with that for now. */
729 aierr = system_getaddrinfo(name, NULL, &myhints, &ai);
731 krb5int_unlock_fac();
734 ce = malloc(sizeof(struct face));
735 memset(ce, 0, sizeof(*ce));
736 ce->expiration = time(0) + 30;
737 for (ai2 = ai; ai2; ai2 = ai2->ai_next) {
738 #ifdef DEBUG_ADDRINFO
739 printf(" found an address in family %d...\n", ai2->ai_family);
741 switch (ai2->ai_family) {
752 ce->addrs4 = calloc(ce->naddrs4, sizeof(*ce->addrs4));
753 if (ce->addrs4 == NULL && ce->naddrs4 != 0) {
754 krb5int_unlock_fac();
755 system_freeaddrinfo(ai);
758 ce->addrs6 = calloc(ce->naddrs6, sizeof(*ce->addrs6));
759 if (ce->addrs6 == NULL && ce->naddrs6 != 0) {
760 krb5int_unlock_fac();
762 system_freeaddrinfo(ai);
765 for (ai2 = ai, i4 = i6 = 0; ai2; ai2 = ai2->ai_next) {
766 switch (ai2->ai_family) {
768 ce->addrs4[i4++] = ((struct sockaddr_in *)ai2->ai_addr)->sin_addr;
771 ce->addrs6[i6++] = ((struct sockaddr_in6 *)ai2->ai_addr)->sin6_addr;
777 ce->canonname = ai->ai_canonname ? strdup(ai->ai_canonname) : 0;
778 system_freeaddrinfo(ai);
779 plant_face(name, ce);
781 template->ai_family = AF_INET6;
782 template->ai_addrlen = sizeof(struct sockaddr_in6);
783 for (i = 0; i < ce->naddrs6; i++) {
784 r = fai_add_entry (result, &ce->addrs6[i], portnum, template);
786 krb5int_unlock_fac();
790 template->ai_family = AF_INET;
791 template->ai_addrlen = sizeof(struct sockaddr_in);
792 for (i = 0; i < ce->naddrs4; i++) {
793 r = fai_add_entry (result, &ce->addrs4[i], portnum, template);
795 krb5int_unlock_fac();
799 if (*result && (flags & AI_CANONNAME))
800 (*result)->ai_canonname = (ce->canonname
801 ? strdup(ce->canonname)
803 krb5int_unlock_fac();
813 GET_HOST_BY_NAME (name, hp, herr, htmp);
815 return translate_h_errno (herr);
816 for (i = 0; hp->h_addr_list[i]; i++) {
817 r = fai_add_entry (result, hp->h_addr_list[i], portnum, template);
821 if (*result && (flags & AI_CANONNAME))
822 (*result)->ai_canonname = strdup (hp->h_name);
829 fake_freeaddrinfo (struct addrinfo *ai)
831 struct addrinfo *next;
834 if (ai->ai_canonname)
835 free (ai->ai_canonname);
844 fake_getaddrinfo (const char *name, const char *serv,
845 const struct addrinfo *hint, struct addrinfo **result)
847 struct addrinfo *res = 0;
849 int port = 0, socktype;
851 struct addrinfo template;
853 #ifdef DEBUG_ADDRINFO
854 debug_dump_getaddrinfo_args(name, serv, hint);
858 if (hint->ai_family != 0 && hint->ai_family != AF_INET)
860 socktype = hint->ai_socktype;
861 flags = hint->ai_flags;
868 size_t numlen = strspn (serv, "0123456789");
869 if (serv[numlen] == '\0') {
871 unsigned long p = strtoul (serv, 0, 10);
872 if (p == 0 || p > 65535)
877 int try_dgram_too = 0, s_err;
882 socktype = SOCK_STREAM;
885 GET_SERV_BY_NAME(serv, socktype == SOCK_STREAM ? "tcp" : "udp",
889 socktype = SOCK_DGRAM;
890 goto try_service_lookup;
899 name = (flags & AI_PASSIVE) ? "0.0.0.0" : "127.0.0.1";
900 flags |= AI_NUMERICHOST;
903 template.ai_family = AF_INET;
904 template.ai_addrlen = sizeof (struct sockaddr_in);
905 template.ai_socktype = socktype;
906 template.ai_protocol = 0;
907 template.ai_flags = 0;
908 template.ai_canonname = 0;
909 template.ai_next = 0;
910 template.ai_addr = 0;
912 /* If NUMERICHOST is set, parse a numeric address.
913 If it's not set, don't accept such names. */
914 if (flags & AI_NUMERICHOST) {
915 struct in_addr addr4;
917 ret = inet_aton (name, &addr4);
921 addr4.s_addr = inet_addr (name);
922 if (addr4.s_addr == 0xffffffff || addr4.s_addr == -1)
923 /* 255.255.255.255 or parse error, both bad */
926 ret = fai_add_entry (&res, &addr4, port, &template);
928 ret = fai_add_hosts_by_name (name, &template, port, flags,
932 if (ret && ret != NO_ADDRESS) {
933 fake_freeaddrinfo (res);
942 #ifdef NEED_FAKE_GETNAMEINFO
944 fake_getnameinfo (const struct sockaddr *sa, socklen_t len,
945 char *host, socklen_t hostlen,
946 char *service, socklen_t servicelen,
950 const struct sockaddr_in *sinp;
954 if (sa->sa_family != AF_INET) {
957 sinp = (const struct sockaddr_in *) sa;
960 if (hostlen < 0 || hlen != hostlen) {
965 if (servicelen < 0 || slen != servicelen) {
971 if (flags & NI_NUMERICHOST) {
972 #if (defined(__GNUC__) && defined(__mips__)) || 1 /* thread safety always */
973 /* The inet_ntoa call, passing a struct, fails on IRIX 6.5
974 using gcc 2.95; we get back "0.0.0.0". Since this in a
975 configuration still important at Athena, here's the
976 workaround, which also happens to be thread-safe.... */
977 const unsigned char *uc;
980 uc = (const unsigned char *) &sinp->sin_addr;
981 snprintf(tmpbuf, sizeof(tmpbuf), "%d.%d.%d.%d",
982 uc[0], uc[1], uc[2], uc[3]);
983 strncpy(host, tmpbuf, hlen);
987 p = inet_ntoa (sinp->sin_addr);
988 strncpy (host, p, hlen);
994 GET_HOST_BY_ADDR((const char *) &sinp->sin_addr,
995 sizeof (struct in_addr),
996 sa->sa_family, hp, herr, htmp);
998 if (herr == NO_ADDRESS && !(flags & NI_NAMEREQD)) /* ??? */
1000 return translate_h_errno (herr);
1002 /* According to the Open Group spec, getnameinfo can
1003 silently truncate, but must still return a
1004 null-terminated string. */
1005 strncpy (host, hp->h_name, hlen);
1007 host[hostlen-1] = 0;
1011 if (flags & NI_NUMERICSERV) {
1015 port = ntohs (sinp->sin_port);
1016 if (port < 0 || port > 65535)
1018 snprintf (numbuf, sizeof(numbuf), "%d", port);
1019 strncpy (service, numbuf, slen);
1024 GET_SERV_BY_PORT(sinp->sin_port,
1025 (flags & NI_DGRAM) ? "udp" : "tcp",
1028 goto numeric_service;
1029 strncpy (service, sp->s_name, slen);
1031 service[servicelen-1] = 0;
1038 #if defined(HAVE_FAKE_GETADDRINFO) || defined(NEED_FAKE_GETNAMEINFO)
1041 char *gai_strerror (int code)
1044 case EAI_ADDRFAMILY: return "address family for nodename not supported";
1045 case EAI_AGAIN: return "temporary failure in name resolution";
1046 case EAI_BADFLAGS: return "bad flags to getaddrinfo/getnameinfo";
1047 case EAI_FAIL: return "non-recoverable failure in name resolution";
1048 case EAI_FAMILY: return "ai_family not supported";
1049 case EAI_MEMORY: return "out of memory";
1050 case EAI_NODATA: return "no address associated with hostname";
1051 case EAI_NONAME: return "name does not exist";
1052 case EAI_SERVICE: return "service name not supported for specified socket type";
1053 case EAI_SOCKTYPE: return "ai_socktype not supported";
1054 case EAI_SYSTEM: return strerror (errno);
1055 default: return "bogus getaddrinfo error?";
1060 static inline int translate_h_errno (int h)
1065 #ifdef NETDB_INTERNAL
1066 case NETDB_INTERNAL:
1067 if (errno == ENOMEM)
1071 case HOST_NOT_FOUND:
1078 #if NO_DATA != NO_ADDRESS
1087 #if defined(HAVE_FAKE_GETADDRINFO) || defined(FAI_CACHE)
1089 int getaddrinfo (const char *name, const char *serv,
1090 const struct addrinfo *hint, struct addrinfo **result)
1092 return fake_getaddrinfo(name, serv, hint, result);
1096 void freeaddrinfo (struct addrinfo *ai)
1098 fake_freeaddrinfo(ai);
1101 #ifdef NEED_FAKE_GETNAMEINFO
1103 int getnameinfo (const struct sockaddr *sa, socklen_t len,
1104 char *host, socklen_t hostlen,
1105 char *service, socklen_t servicelen,
1108 return fake_getnameinfo(sa, len, host, hostlen, service, servicelen,
1111 #endif /* NEED_FAKE_GETNAMEINFO */
1112 #endif /* HAVE_FAKE_GETADDRINFO */
1113 #endif /* NEED_FAKE_GETADDRINFO */
1116 #ifdef WRAP_GETADDRINFO
1120 getaddrinfo (const char *name, const char *serv, const struct addrinfo *hint,
1121 struct addrinfo **result)
1124 #if defined(_AIX) || defined(COPY_FIRST_CANONNAME)
1125 struct addrinfo *ai;
1127 #ifdef NUMERIC_SERVICE_BROKEN
1128 int service_is_numeric = 0;
1129 int service_port = 0;
1130 int socket_type = 0;
1133 #ifdef DEBUG_ADDRINFO
1134 debug_dump_getaddrinfo_args(name, serv, hint);
1137 #ifdef NUMERIC_SERVICE_BROKEN
1138 /* AIX 4.3.3 is broken. (Or perhaps out of date?)
1140 If a numeric service is provided, and it doesn't correspond to
1141 a known service name for tcp or udp (as appropriate), an error
1142 code (for "host not found") is returned. If the port maps to a
1143 known service for both udp and tcp, all is well. */
1144 if (serv && serv[0] && isdigit(serv[0])) {
1145 unsigned long lport;
1147 lport = strtoul(serv, &end, 10);
1150 return EAI_SOCKTYPE;
1151 service_is_numeric = 1;
1152 service_port = htons(lport);
1153 #ifdef AI_NUMERICSERV
1154 if (hint && hint->ai_flags & AI_NUMERICSERV)
1158 serv = "discard"; /* defined for both udp and tcp */
1160 socket_type = hint->ai_socktype;
1165 aierr = system_getaddrinfo (name, serv, hint, result);
1166 if (aierr || *result == 0) {
1167 #ifdef DEBUG_ADDRINFO
1168 debug_dump_error(aierr);
1173 /* Linux libc version 6 prior to 2.3.4 is broken.
1175 RFC 2553 says that when AI_CANONNAME is set, the ai_canonname
1176 flag of the first returned structure has the canonical name of
1177 the host. Instead, GNU libc sets ai_canonname in each returned
1178 structure to the name that the corresponding address maps to,
1179 if any, or a printable numeric form.
1181 RFC 2553 bis and the new Open Group spec say that field will be
1182 the canonical name if it can be determined, otherwise, the
1183 provided hostname or a copy of it.
1185 IMNSHO, "canonical name" means CNAME processing and not PTR
1186 processing, but I can see arguing it. Using the numeric form
1187 when that's not the form provided is just wrong. So, let's fix
1190 The glibc 2.2.5 sources indicate that the canonical name is
1191 *not* allocated separately, it's just some extra storage tacked
1192 on the end of the addrinfo structure. So, let's try this
1193 approach: If getaddrinfo sets ai_canonname, we'll replace the
1194 *first* one with allocated storage, and free up that pointer in
1195 freeaddrinfo if it's set; the other ai_canonname fields will be
1196 left untouched. And we'll just pray that the application code
1197 won't mess around with the list structure; if we start doing
1198 that, we'll have to start replacing and freeing all of the
1199 ai_canonname fields.
1201 Ref: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=133668 .
1203 Since it's dependent on the target hostname, it's hard to check
1204 for at configure time. The bug was fixed in glibc 2.3.4.
1205 After the fix, the ai_canonname field is allocated, so our
1206 workaround leaks memory. We disable the workaround for glibc
1207 >= 2.4, but there is no easy way to test for glibc patch
1208 versions, so we still leak memory under glibc 2.3.4 through
1211 Some Windows documentation says that even when AI_CANONNAME is
1212 set, the returned ai_canonname field can be null. The NetBSD
1213 1.5 implementation also does this, if the input hostname is a
1214 numeric host address string. That case isn't handled well at
1217 Libc version 5 didn't have getaddrinfo at all. */
1219 #ifdef COPY_FIRST_CANONNAME
1221 * This code must *always* return an error, return a null
1222 * ai_canonname, or return an ai_canonname allocated here using
1223 * malloc, so that freeaddrinfo can always free a non-null
1224 * ai_canonname. Note that it really doesn't matter if the
1225 * AI_CANONNAME flag was set.
1228 if (ai->ai_canonname) {
1230 const char *name2 = 0;
1235 * Current versions of GET_HOST_BY_NAME will fail if the
1236 * target hostname has IPv6 addresses only. Make sure it
1237 * fails fairly cleanly.
1239 GET_HOST_BY_NAME (name, hp, herr, htmp);
1242 * This case probably means it's an IPv6-only name. If
1243 * ai_canonname is a numeric address, get rid of it.
1245 if (ai->ai_canonname && strchr(ai->ai_canonname, ':'))
1246 ai->ai_canonname = 0;
1247 name2 = ai->ai_canonname ? ai->ai_canonname : name;
1249 /* Sometimes gethostbyname will be directed to /etc/hosts
1250 first, and sometimes that file will have entries with
1251 the unqualified name first. So take the first entry
1252 that looks like it could be a FQDN. */
1253 for (i = 0; hp->h_aliases[i]; i++) {
1254 if (strchr(hp->h_aliases[i], '.') != 0) {
1255 name2 = hp->h_aliases[i];
1259 /* Give up, just use the first name (h_name ==
1260 h_aliases[0] on all systems I've seen). */
1261 if (hp->h_aliases[i] == 0)
1265 ai->ai_canonname = strdup(name2);
1266 if (name2 != 0 && ai->ai_canonname == 0) {
1267 system_freeaddrinfo(ai);
1269 #ifdef DEBUG_ADDRINFO
1270 debug_dump_error(EAI_MEMORY);
1274 /* Zap the remaining ai_canonname fields glibc fills in, in
1275 case the application messes around with the list
1277 while ((ai = ai->ai_next) != NULL)
1278 ai->ai_canonname = 0;
1282 #ifdef NUMERIC_SERVICE_BROKEN
1283 if (service_port != 0) {
1284 for (ai = *result; ai; ai = ai->ai_next) {
1285 if (socket_type != 0 && ai->ai_socktype == 0)
1286 /* Is this check actually needed? */
1287 ai->ai_socktype = socket_type;
1288 switch (ai->ai_family) {
1290 ((struct sockaddr_in *)ai->ai_addr)->sin_port = service_port;
1293 ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port = service_port;
1301 for (ai = *result; ai; ai = ai->ai_next) {
1302 /* AIX 4.3.3 libc is broken. It doesn't set the family or len
1303 fields of the sockaddr structures. Usually, sa_family is
1304 zero, but I've seen it set to 1 in some cases also (maybe
1305 just leftover from previous contents of the memory
1306 block?). So, always override what libc returned. */
1307 ai->ai_addr->sa_family = ai->ai_family;
1308 #ifdef HAVE_SA_LEN /* always true on AIX, actually */
1309 ai->ai_addr->sa_len = ai->ai_addrlen;
1314 /* Not dealt with currently:
1316 - Some versions of GNU libc can lose some IPv4 addresses in
1317 certain cases when multiple IPv4 and IPv6 addresses are
1320 #ifdef DEBUG_ADDRINFO
1321 debug_dump_addrinfos(*result);
1328 void freeaddrinfo (struct addrinfo *ai)
1330 #ifdef COPY_FIRST_CANONNAME
1332 free(ai->ai_canonname);
1333 ai->ai_canonname = 0;
1334 system_freeaddrinfo(ai);
1337 system_freeaddrinfo(ai);
1340 #endif /* WRAP_GETADDRINFO */
1343 static int krb5int_lock_fac (void)
1346 err = krb5int_call_thread_support_init();
1349 return k5_mutex_lock(&krb5int_fac.lock);
1352 static int krb5int_unlock_fac (void)
1354 return k5_mutex_unlock(&krb5int_fac.lock);
1358 #if defined(KRB5_USE_INET6)
1359 /* Some systems don't define in6addr_any. */
1360 const struct in6_addr krb5int_in6addr_any = IN6ADDR_ANY_INIT;
1362 /* Are any of the systems without IPv6 support among those where
1363 we cross-check the actual exported symbols against the export
1364 list? Not sure, play it safe. */
1365 const char krb5int_in6addr_any = 0;
1368 int krb5int_getaddrinfo (const char *node, const char *service,
1369 const struct addrinfo *hints,
1370 struct addrinfo **aip)
1372 return getaddrinfo(node, service, hints, aip);
1375 void krb5int_freeaddrinfo (struct addrinfo *ai)
1380 const char *krb5int_gai_strerror(int err)
1382 return gai_strerror(err);
1385 int krb5int_getnameinfo (const struct sockaddr *sa, socklen_t salen,
1386 char *hbuf, size_t hbuflen,
1387 char *sbuf, size_t sbuflen,
1390 return getnameinfo(sa, salen, hbuf, hbuflen, sbuf, sbuflen, flags);