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 "k5-platform.h"
105 #include "k5-thread.h"
106 #include "port-sockets.h"
107 #include "socket-utils.h"
108 #include "supp-int.h"
110 #define IMPLEMENT_FAKE_GETADDRINFO
111 #include "fake-addrinfo.h"
116 getaddrinfo (/*@in@*/ /*@null@*/ const char *,
117 /*@in@*/ /*@null@*/ const char *,
118 /*@in@*/ /*@null@*/ const struct addrinfo *,
119 /*@out@*/ struct addrinfo **)
122 freeaddrinfo (/*@only@*/ /*@out@*/ struct addrinfo *)
125 getnameinfo (const struct sockaddr *addr, socklen_t addrsz,
126 /*@out@*/ /*@null@*/ char *h, socklen_t hsz,
127 /*@out@*/ /*@null@*/ char *s, socklen_t ssz,
129 /*@requires (maxSet(h)+1) >= hsz /\ (maxSet(s)+1) >= ssz @*/
130 /* too hard: maxRead(addr) >= (addrsz-1) */
131 /*@modifies *h, *s@*/;
132 extern /*@dependent@*/ char *gai_strerror (int code) /*@*/;
137 #include "cache-addrinfo.h"
139 #if (defined (__linux__) && defined(HAVE_GETADDRINFO)) || defined (_AIX)
140 /* See comments below. */
141 # define WRAP_GETADDRINFO
144 #if defined (__linux__) && defined(HAVE_GETADDRINFO)
145 /* Define COPY_FIRST_CANONNAME for glibc 2.3 and prior. */
146 #include <features.h>
147 # ifdef __GLIBC_PREREQ
148 # if ! __GLIBC_PREREQ(2, 4)
149 # define COPY_FIRST_CANONNAME
152 # define COPY_FIRST_CANONNAME
157 # define NUMERIC_SERVICE_BROKEN
158 # define COPY_FIRST_CANONNAME
162 #ifdef COPY_FIRST_CANONNAME
166 #ifdef NUMERIC_SERVICE_BROKEN
167 # include <ctype.h> /* isdigit */
168 # include <stdlib.h> /* strtoul */
172 /* Do we actually have *any* systems we care about that don't provide
173 either getaddrinfo or one of these two flavors of
175 #if !defined(HAVE_GETHOSTBYNAME_R) || defined(THREADSAFE_GETHOSTBYNAME)
176 typedef struct hostent *GET_HOST_TMP;
177 #define GET_HOST_BY_NAME(NAME, HP, ERR, TMP) \
178 { TMP = gethostbyname (NAME); (ERR) = h_errno; (HP) = TMP; }
179 #define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR, TMP) \
180 { TMP = gethostbyaddr ((ADDR), (ADDRLEN), (FAMILY)); (ERR) = h_errno; (HP) = TMP; }
182 #ifdef _AIX /* XXX should have a feature test! */
185 struct hostent_data data;
187 #define GET_HOST_BY_NAME(NAME, HP, ERR, TMP) \
189 (HP) = (gethostbyname_r((NAME), &TMP.ent, &TMP.data) \
195 #define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR) \
197 struct hostent my_h_ent; \
198 struct hostent_data my_h_ent_data; \
199 (HP) = (gethostbyaddr_r((ADDR), (ADDRLEN), (FAMILY), &my_h_ent, \
207 #ifdef GETHOSTBYNAME_R_RETURNS_INT
212 #define GET_HOST_BY_NAME(NAME, HP, ERR, TMP) \
214 struct hostent *my_hp = NULL; \
215 int my_h_err, my_ret; \
216 my_ret = gethostbyname_r((NAME), &TMP.ent, \
217 TMP.buf, sizeof (TMP.buf), &my_hp, \
219 (HP) = (((my_ret != 0) || (my_hp != &TMP.ent)) \
224 #define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR, TMP) \
226 struct hostent *my_hp; \
227 int my_h_err, my_ret; \
228 my_ret = gethostbyaddr_r((ADDR), (ADDRLEN), (FAMILY), &TMP.ent, \
229 TMP.buf, sizeof (TMP.buf), &my_hp, \
231 (HP) = (((my_ret != 0) || (my_hp != &TMP.ent)) \
241 #define GET_HOST_BY_NAME(NAME, HP, ERR, TMP) \
244 (HP) = gethostbyname_r((NAME), &TMP.ent, \
245 TMP.buf, sizeof (TMP.buf), &my_h_err); \
248 #define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR, TMP) \
251 (HP) = gethostbyaddr_r((ADDR), (ADDRLEN), (FAMILY), &TMP.ent, \
252 TMP.buf, sizeof (TMP.buf), &my_h_err); \
255 #endif /* returns int? */
259 /* Now do the same for getservby* functions. */
260 #ifndef HAVE_GETSERVBYNAME_R
261 typedef struct servent *GET_SERV_TMP;
262 #define GET_SERV_BY_NAME(NAME, PROTO, SP, ERR, TMP) \
263 (TMP = getservbyname (NAME, PROTO), (SP) = TMP, (ERR) = (SP) ? 0 : -1)
264 #define GET_SERV_BY_PORT(PORT, PROTO, SP, ERR, TMP) \
265 (TMP = getservbyport (PORT, PROTO), (SP) = TMP, (ERR) = (SP) ? 0 : -1)
267 #ifdef GETSERVBYNAME_R_RETURNS_INT
272 #define GET_SERV_BY_NAME(NAME, PROTO, SP, ERR, TMP) \
274 struct servent *my_sp; \
276 (SP) = (getservbyname_r((NAME), (PROTO), &TMP.ent, \
277 TMP.buf, sizeof (TMP.buf), &my_sp, \
283 #define GET_SERV_BY_PORT(PORT, PROTO, SP, ERR, TMP) \
285 struct servent *my_sp; \
287 (SP) = (getservbyport_r((PORT), (PROTO), &TMP.ent, \
288 TMP.buf, sizeof (TMP.buf), &my_sp, \
295 /* returns ptr -- IRIX? */
300 #define GET_SERV_BY_NAME(NAME, PROTO, SP, ERR, TMP) \
302 (SP) = getservbyname_r((NAME), (PROTO), &TMP.ent, \
303 TMP.buf, sizeof (TMP.buf)); \
304 (ERR) = (SP) == NULL; \
307 #define GET_SERV_BY_PORT(PORT, PROTO, SP, ERR, TMP) \
309 struct servent *my_sp; \
310 my_sp = getservbyport_r((PORT), (PROTO), &TMP.ent, \
311 TMP.buf, sizeof (TMP.buf)); \
313 (ERR) = my_sp == 0; \
314 (ERR) = (ERR); /* avoid "unused" warning */ \
319 #if defined(WRAP_GETADDRINFO) || defined(FAI_CACHE)
321 system_getaddrinfo (const char *name, const char *serv,
322 const struct addrinfo *hint,
323 struct addrinfo **res)
325 return getaddrinfo(name, serv, hint, res);
329 system_freeaddrinfo (struct addrinfo *ai)
334 /* Note: Implementations written to RFC 2133 use size_t, while RFC
335 2553 implementations use socklen_t, for the second parameter.
337 Mac OS X (10.2) and AIX 4.3.3 appear to be in the RFC 2133 camp,
338 but we don't have an autoconf test for that right now. */
340 system_getnameinfo (const struct sockaddr *sa, socklen_t salen,
341 char *host, size_t hostlen, char *serv, size_t servlen,
344 return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
348 #if !defined (HAVE_GETADDRINFO) || defined(WRAP_GETADDRINFO) || defined(FAI_CACHE)
351 #define getaddrinfo my_fake_getaddrinfo
353 #define freeaddrinfo my_fake_freeaddrinfo
357 #if !defined (HAVE_GETADDRINFO)
360 #define gai_strerror my_fake_gai_strerror
362 #endif /* ! HAVE_GETADDRINFO */
364 #if (!defined (HAVE_GETADDRINFO) || defined (WRAP_GETADDRINFO)) && defined(DEBUG_ADDRINFO)
365 /* Some debug routines. */
367 static const char *protoname (int p, char *buf, size_t bufsize) {
368 #define X(N) if (p == IPPROTO_ ## N) return #N
386 snprintf(buf, bufsize, " %-2d", p);
390 static const char *socktypename (int t, char *buf, size_t bufsize) {
392 case SOCK_DGRAM: return "DGRAM";
393 case SOCK_STREAM: return "STREAM";
394 case SOCK_RAW: return "RAW";
395 case SOCK_RDM: return "RDM";
396 case SOCK_SEQPACKET: return "SEQPACKET";
398 snprintf(buf, bufsize, " %-2d", t);
402 static const char *familyname (int f, char *buf, size_t bufsize) {
405 snprintf(buf, bufsize, "AF %d", f);
407 case AF_INET: return "AF_INET";
408 case AF_INET6: return "AF_INET6";
410 case AF_UNIX: return "AF_UNIX";
415 static void debug_dump_getaddrinfo_args (const char *name, const char *serv,
416 const struct addrinfo *hint)
420 "getaddrinfo(hostname %s, service %s,\n"
422 name ? name : "(null)", serv ? serv : "(null)");
426 #define Z(FLAG) if (hint->ai_flags & AI_##FLAG) fprintf(stderr, "%s%s", sep, #FLAG), sep = "|"
429 #ifdef AI_NUMERICHOST
433 fprintf(stderr, "no-flags");
435 fprintf(stderr, " %s", familyname(hint->ai_family, buf,
437 if (hint->ai_socktype)
438 fprintf(stderr, " SOCK_%s", socktypename(hint->ai_socktype, buf,
440 if (hint->ai_protocol)
441 fprintf(stderr, " IPPROTO_%s", protoname(hint->ai_protocol, buf,
444 fprintf(stderr, "(null)");
445 fprintf(stderr, " }):\n");
448 static void debug_dump_error (int err)
450 fprintf(stderr, "error %d: %s\n", err, gai_strerror(err));
453 static void debug_dump_addrinfos (const struct addrinfo *ai)
457 fprintf(stderr, "addrinfos returned:\n");
459 fprintf(stderr, "%p...", ai);
460 fprintf(stderr, " socktype=%s", socktypename(ai->ai_socktype, buf,
462 fprintf(stderr, " ai_family=%s", familyname(ai->ai_family, buf,
464 if (ai->ai_family != ai->ai_addr->sa_family)
465 fprintf(stderr, " sa_family=%s",
466 familyname(ai->ai_addr->sa_family, buf, sizeof(buf)));
467 fprintf(stderr, "\n");
471 fprintf(stderr, "end addrinfos returned (%d)\n");
476 #if !defined (HAVE_GETADDRINFO) || defined (WRAP_GETADDRINFO)
479 int getaddrinfo (const char *name, const char *serv,
480 const struct addrinfo *hint, struct addrinfo **result);
483 void freeaddrinfo (struct addrinfo *ai);
487 #if !defined (HAVE_GETADDRINFO)
489 #define HAVE_FAKE_GETADDRINFO /* was not originally HAVE_GETADDRINFO */
490 #define HAVE_GETADDRINFO
491 #define NEED_FAKE_GETNAMEINFO
492 #undef HAVE_GETNAMEINFO
493 #define HAVE_GETNAMEINFO 1
496 #define getnameinfo my_fake_getnameinfo
499 char *gai_strerror (int code);
503 #if !defined (HAVE_GETADDRINFO)
505 int getnameinfo (const struct sockaddr *addr, socklen_t len,
506 char *host, socklen_t hostlen,
507 char *service, socklen_t servicelen,
511 /* Fudge things on older gai implementations. */
512 /* AIX 4.3.3 is based on RFC 2133; no AI_NUMERICHOST. */
513 #ifndef AI_NUMERICHOST
514 # define AI_NUMERICHOST 0
516 /* Partial RFC 2553 implementations may not have AI_ADDRCONFIG and
517 friends, which RFC 3493 says are now part of the getaddrinfo
518 interface, and we'll want to use. */
519 #ifndef AI_ADDRCONFIG
520 # define AI_ADDRCONFIG 0
523 # define AI_V4MAPPED 0
529 # define AI_DEFAULT (AI_ADDRCONFIG|AI_V4MAPPED)
532 #if defined(HAVE_FAKE_GETADDRINFO) || defined(FAI_CACHE)
533 #define NEED_FAKE_GETADDRINFO
536 #if defined(NEED_FAKE_GETADDRINFO) || defined(WRAP_GETADDRINFO)
540 #ifdef NEED_FAKE_GETADDRINFO
541 #include <string.h> /* for strspn */
543 static inline int translate_h_errno (int h);
545 static inline int fai_add_entry (struct addrinfo **result, void *addr,
546 int port, const struct addrinfo *template)
548 struct addrinfo *n = malloc (sizeof (struct addrinfo));
551 if (template->ai_family != AF_INET
552 && template->ai_family != AF_INET6
556 if (template->ai_family == AF_INET) {
557 struct sockaddr_in *sin4;
558 sin4 = malloc (sizeof (struct sockaddr_in));
561 memset (sin4, 0, sizeof (struct sockaddr_in)); /* for sin_zero */
562 n->ai_addr = (struct sockaddr *) sin4;
563 sin4->sin_family = AF_INET;
564 sin4->sin_addr = *(struct in_addr *)addr;
565 sin4->sin_port = port;
567 if (template->ai_family == AF_INET6) {
568 struct sockaddr_in6 *sin6;
569 sin6 = malloc (sizeof (struct sockaddr_in6));
572 memset (sin6, 0, sizeof (struct sockaddr_in6)); /* for sin_zero */
573 n->ai_addr = (struct sockaddr *) sin6;
574 sin6->sin6_family = AF_INET6;
575 sin6->sin6_addr = *(struct in6_addr *)addr;
576 sin6->sin6_port = port;
578 n->ai_next = *result;
584 /* fake addrinfo cache entries */
585 #define CACHE_ENTRY_LIFETIME 15 /* seconds */
587 static void plant_face (const char *name, struct face *entry)
589 entry->name = strdup(name);
590 if (entry->name == NULL)
591 /* @@ Wastes memory. */
593 k5_mutex_assert_locked(&krb5int_fac.lock);
594 entry->next = krb5int_fac.data;
595 entry->expiration = time(0) + CACHE_ENTRY_LIFETIME;
596 krb5int_fac.data = entry;
597 #ifdef DEBUG_ADDRINFO
598 printf("added cache entry '%s' at %p: %d ipv4, %d ipv6; expire %d\n",
599 name, entry, entry->naddrs4, entry->naddrs6, entry->expiration);
603 static int find_face (const char *name, struct face **entry)
605 struct face *fp, **fpp;
606 time_t now = time(0);
608 /* First, scan for expired entries and free them.
609 (Future improvement: Integrate these two loops.) */
610 #ifdef DEBUG_ADDRINFO
611 printf("scanning cache at %d for '%s'...\n", now, name);
613 k5_mutex_assert_locked(&krb5int_fac.lock);
614 for (fpp = &krb5int_fac.data; *fpp; ) {
616 #ifdef DEBUG_ADDRINFO
617 printf(" checking expiration time of @%p: %d\n",
620 if (fp->expiration < now) {
621 #ifdef DEBUG_ADDRINFO
622 printf("\texpiring cache entry\n");
630 /* Stay at this point in the list, and check again. */
636 for (fp = krb5int_fac.data; fp; fp = fp->next) {
637 #ifdef DEBUG_ADDRINFO
638 printf(" comparing entry @%p\n", fp);
640 if (!strcasecmp(fp->name, name)) {
641 #ifdef DEBUG_ADDRINFO
642 printf("\tMATCH!\n");
654 static int krb5int_lock_fac(void), krb5int_unlock_fac(void);
657 static inline int fai_add_hosts_by_name (const char *name,
658 struct addrinfo *template,
659 int portnum, int flags,
660 struct addrinfo **result)
667 err = krb5int_lock_fac();
672 if (!find_face(name, &ce)) {
673 struct addrinfo myhints = { 0 }, *ai, *ai2;
676 #ifdef DEBUG_ADDRINFO
677 printf("looking up new data for '%s'...\n", name);
679 myhints.ai_socktype = SOCK_STREAM;
680 myhints.ai_flags = AI_CANONNAME;
681 /* Don't set ai_family -- we want to cache all address types,
682 because the next lookup may not use the same constraints as
683 the current one. We *could* cache them separately, so that
684 we never have to look up an IPv6 address if we are always
685 asked for IPv4 only, but let's deal with that later, if we
687 /* Try NULL for the service for now.
689 It would be nice to use the requested service name, and not
690 have to patch things up, but then we'd be doing multiple
691 queries for the same host when we get different services.
692 We were using "telnet" for a little more confidence that
693 getaddrinfo would heed the hints to only give us stream
694 socket types (with no socket type and null service name, we
695 might get stream *and* dgram *and* raw, for each address,
696 or only raw). The RFC 3493 description of ai_socktype
697 sometimes associates it with the specified service,
700 But on Mac OS X (10.3, 10.4) they've "extended" getaddrinfo
701 to make SRV RR queries. (Please, somebody, show me
702 something in the specs that actually supports this? RFC
703 3493 says nothing about it, but it does say getaddrinfo is
704 the new way to look up hostnames. RFC 2782 says SRV
705 records should *not* be used unless the application
706 protocol spec says to do so. The Telnet spec does not say
707 to do it.) And then they complain when our code
708 "unexpectedly" seems to use this "extension" in cases where
709 they don't want it to be used.
711 Fortunately, it appears that if we specify ai_socktype as
712 SOCK_STREAM and use a null service name, we only get one
713 copy of each address on all the platforms I've tried,
714 although it may not have ai_socktype filled in properly.
715 So, we'll fudge it with that for now. */
716 aierr = system_getaddrinfo(name, NULL, &myhints, &ai);
718 krb5int_unlock_fac();
721 ce = malloc(sizeof(struct face));
722 memset(ce, 0, sizeof(*ce));
723 ce->expiration = time(0) + 30;
724 for (ai2 = ai; ai2; ai2 = ai2->ai_next) {
725 #ifdef DEBUG_ADDRINFO
726 printf(" found an address in family %d...\n", ai2->ai_family);
728 switch (ai2->ai_family) {
739 ce->addrs4 = calloc(ce->naddrs4, sizeof(*ce->addrs4));
740 if (ce->addrs4 == NULL && ce->naddrs4 != 0) {
741 krb5int_unlock_fac();
742 system_freeaddrinfo(ai);
745 ce->addrs6 = calloc(ce->naddrs6, sizeof(*ce->addrs6));
746 if (ce->addrs6 == NULL && ce->naddrs6 != 0) {
747 krb5int_unlock_fac();
749 system_freeaddrinfo(ai);
752 for (ai2 = ai, i4 = i6 = 0; ai2; ai2 = ai2->ai_next) {
753 switch (ai2->ai_family) {
755 ce->addrs4[i4++] = ((struct sockaddr_in *)ai2->ai_addr)->sin_addr;
758 ce->addrs6[i6++] = ((struct sockaddr_in6 *)ai2->ai_addr)->sin6_addr;
764 ce->canonname = ai->ai_canonname ? strdup(ai->ai_canonname) : 0;
765 system_freeaddrinfo(ai);
766 plant_face(name, ce);
768 template->ai_family = AF_INET6;
769 template->ai_addrlen = sizeof(struct sockaddr_in6);
770 for (i = 0; i < ce->naddrs6; i++) {
771 r = fai_add_entry (result, &ce->addrs6[i], portnum, template);
773 krb5int_unlock_fac();
777 template->ai_family = AF_INET;
778 template->ai_addrlen = sizeof(struct sockaddr_in);
779 for (i = 0; i < ce->naddrs4; i++) {
780 r = fai_add_entry (result, &ce->addrs4[i], portnum, template);
782 krb5int_unlock_fac();
786 if (*result && (flags & AI_CANONNAME))
787 (*result)->ai_canonname = (ce->canonname
788 ? strdup(ce->canonname)
790 krb5int_unlock_fac();
800 GET_HOST_BY_NAME (name, hp, herr, htmp);
802 return translate_h_errno (herr);
803 for (i = 0; hp->h_addr_list[i]; i++) {
804 r = fai_add_entry (result, hp->h_addr_list[i], portnum, template);
808 if (*result && (flags & AI_CANONNAME))
809 (*result)->ai_canonname = strdup (hp->h_name);
816 fake_freeaddrinfo (struct addrinfo *ai)
818 struct addrinfo *next;
821 if (ai->ai_canonname)
822 free (ai->ai_canonname);
831 fake_getaddrinfo (const char *name, const char *serv,
832 const struct addrinfo *hint, struct addrinfo **result)
834 struct addrinfo *res = 0;
836 int port = 0, socktype;
838 struct addrinfo template;
840 #ifdef DEBUG_ADDRINFO
841 debug_dump_getaddrinfo_args(name, serv, hint);
845 if (hint->ai_family != 0 && hint->ai_family != AF_INET)
847 socktype = hint->ai_socktype;
848 flags = hint->ai_flags;
855 size_t numlen = strspn (serv, "0123456789");
856 if (serv[numlen] == '\0') {
858 unsigned long p = strtoul (serv, 0, 10);
859 if (p == 0 || p > 65535)
864 int try_dgram_too = 0, s_err;
869 socktype = SOCK_STREAM;
872 GET_SERV_BY_NAME(serv, socktype == SOCK_STREAM ? "tcp" : "udp",
876 socktype = SOCK_DGRAM;
877 goto try_service_lookup;
886 name = (flags & AI_PASSIVE) ? "0.0.0.0" : "127.0.0.1";
887 flags |= AI_NUMERICHOST;
890 template.ai_family = AF_INET;
891 template.ai_addrlen = sizeof (struct sockaddr_in);
892 template.ai_socktype = socktype;
893 template.ai_protocol = 0;
894 template.ai_flags = 0;
895 template.ai_canonname = 0;
896 template.ai_next = 0;
897 template.ai_addr = 0;
899 /* If NUMERICHOST is set, parse a numeric address.
900 If it's not set, don't accept such names. */
901 if (flags & AI_NUMERICHOST) {
902 struct in_addr addr4;
904 ret = inet_aton (name, &addr4);
908 addr4.s_addr = inet_addr (name);
909 if (addr4.s_addr == 0xffffffff || addr4.s_addr == -1)
910 /* 255.255.255.255 or parse error, both bad */
913 ret = fai_add_entry (&res, &addr4, port, &template);
915 ret = fai_add_hosts_by_name (name, &template, port, flags,
919 if (ret && ret != NO_ADDRESS) {
920 fake_freeaddrinfo (res);
929 #ifdef NEED_FAKE_GETNAMEINFO
931 fake_getnameinfo (const struct sockaddr *sa, socklen_t len,
932 char *host, socklen_t hostlen,
933 char *service, socklen_t servicelen,
937 const struct sockaddr_in *sinp;
941 if (sa->sa_family != AF_INET) {
944 sinp = (const struct sockaddr_in *) sa;
947 if (hostlen < 0 || hlen != hostlen) {
952 if (servicelen < 0 || slen != servicelen) {
958 if (flags & NI_NUMERICHOST) {
959 #if (defined(__GNUC__) && defined(__mips__)) || 1 /* thread safety always */
960 /* The inet_ntoa call, passing a struct, fails on IRIX 6.5
961 using gcc 2.95; we get back "0.0.0.0". Since this in a
962 configuration still important at Athena, here's the
963 workaround, which also happens to be thread-safe.... */
964 const unsigned char *uc;
967 uc = (const unsigned char *) &sinp->sin_addr;
968 snprintf(tmpbuf, sizeof(tmpbuf), "%d.%d.%d.%d",
969 uc[0], uc[1], uc[2], uc[3]);
970 strncpy(host, tmpbuf, hlen);
974 p = inet_ntoa (sinp->sin_addr);
975 strncpy (host, p, hlen);
981 GET_HOST_BY_ADDR((const char *) &sinp->sin_addr,
982 sizeof (struct in_addr),
983 sa->sa_family, hp, herr, htmp);
985 if (herr == NO_ADDRESS && !(flags & NI_NAMEREQD)) /* ??? */
987 return translate_h_errno (herr);
989 /* According to the Open Group spec, getnameinfo can
990 silently truncate, but must still return a
991 null-terminated string. */
992 strncpy (host, hp->h_name, hlen);
998 if (flags & NI_NUMERICSERV) {
1002 port = ntohs (sinp->sin_port);
1003 if (port < 0 || port > 65535)
1005 snprintf (numbuf, sizeof(numbuf), "%d", port);
1006 strncpy (service, numbuf, slen);
1011 GET_SERV_BY_PORT(sinp->sin_port,
1012 (flags & NI_DGRAM) ? "udp" : "tcp",
1015 goto numeric_service;
1016 strncpy (service, sp->s_name, slen);
1018 service[servicelen-1] = 0;
1025 #if defined(HAVE_FAKE_GETADDRINFO) || defined(NEED_FAKE_GETNAMEINFO)
1028 char *gai_strerror (int code)
1031 case EAI_ADDRFAMILY: return "address family for nodename not supported";
1032 case EAI_AGAIN: return "temporary failure in name resolution";
1033 case EAI_BADFLAGS: return "bad flags to getaddrinfo/getnameinfo";
1034 case EAI_FAIL: return "non-recoverable failure in name resolution";
1035 case EAI_FAMILY: return "ai_family not supported";
1036 case EAI_MEMORY: return "out of memory";
1037 case EAI_NODATA: return "no address associated with hostname";
1038 case EAI_NONAME: return "name does not exist";
1039 case EAI_SERVICE: return "service name not supported for specified socket type";
1040 case EAI_SOCKTYPE: return "ai_socktype not supported";
1041 case EAI_SYSTEM: return strerror (errno);
1042 default: return "bogus getaddrinfo error?";
1047 static inline int translate_h_errno (int h)
1052 #ifdef NETDB_INTERNAL
1053 case NETDB_INTERNAL:
1054 if (errno == ENOMEM)
1058 case HOST_NOT_FOUND:
1065 #if NO_DATA != NO_ADDRESS
1074 #if defined(HAVE_FAKE_GETADDRINFO) || defined(FAI_CACHE)
1076 int getaddrinfo (const char *name, const char *serv,
1077 const struct addrinfo *hint, struct addrinfo **result)
1079 return fake_getaddrinfo(name, serv, hint, result);
1083 void freeaddrinfo (struct addrinfo *ai)
1085 fake_freeaddrinfo(ai);
1088 #ifdef NEED_FAKE_GETNAMEINFO
1090 int getnameinfo (const struct sockaddr *sa, socklen_t len,
1091 char *host, socklen_t hostlen,
1092 char *service, socklen_t servicelen,
1095 return fake_getnameinfo(sa, len, host, hostlen, service, servicelen,
1098 #endif /* NEED_FAKE_GETNAMEINFO */
1099 #endif /* HAVE_FAKE_GETADDRINFO */
1100 #endif /* NEED_FAKE_GETADDRINFO */
1103 #ifdef WRAP_GETADDRINFO
1107 getaddrinfo (const char *name, const char *serv, const struct addrinfo *hint,
1108 struct addrinfo **result)
1111 #if defined(_AIX) || defined(COPY_FIRST_CANONNAME)
1112 struct addrinfo *ai;
1114 #ifdef NUMERIC_SERVICE_BROKEN
1115 int service_is_numeric = 0;
1116 int service_port = 0;
1117 int socket_type = 0;
1120 #ifdef DEBUG_ADDRINFO
1121 debug_dump_getaddrinfo_args(name, serv, hint);
1124 #ifdef NUMERIC_SERVICE_BROKEN
1125 /* AIX 4.3.3 is broken. (Or perhaps out of date?)
1127 If a numeric service is provided, and it doesn't correspond to
1128 a known service name for tcp or udp (as appropriate), an error
1129 code (for "host not found") is returned. If the port maps to a
1130 known service for both udp and tcp, all is well. */
1131 if (serv && serv[0] && isdigit(serv[0])) {
1132 unsigned long lport;
1134 lport = strtoul(serv, &end, 10);
1137 return EAI_SOCKTYPE;
1138 service_is_numeric = 1;
1139 service_port = lport;
1140 #ifdef AI_NUMERICSERV
1141 if (hint && hint->ai_flags & AI_NUMERICSERV)
1145 serv = "discard"; /* defined for both udp and tcp */
1147 socket_type = hint->ai_socktype;
1152 aierr = system_getaddrinfo (name, serv, hint, result);
1153 if (aierr || *result == 0) {
1154 #ifdef DEBUG_ADDRINFO
1155 debug_dump_error(aierr);
1160 /* Linux libc version 6 prior to 2.3.4 is broken.
1162 RFC 2553 says that when AI_CANONNAME is set, the ai_canonname
1163 flag of the first returned structure has the canonical name of
1164 the host. Instead, GNU libc sets ai_canonname in each returned
1165 structure to the name that the corresponding address maps to,
1166 if any, or a printable numeric form.
1168 RFC 2553 bis and the new Open Group spec say that field will be
1169 the canonical name if it can be determined, otherwise, the
1170 provided hostname or a copy of it.
1172 IMNSHO, "canonical name" means CNAME processing and not PTR
1173 processing, but I can see arguing it. Using the numeric form
1174 when that's not the form provided is just wrong. So, let's fix
1177 The glibc 2.2.5 sources indicate that the canonical name is
1178 *not* allocated separately, it's just some extra storage tacked
1179 on the end of the addrinfo structure. So, let's try this
1180 approach: If getaddrinfo sets ai_canonname, we'll replace the
1181 *first* one with allocated storage, and free up that pointer in
1182 freeaddrinfo if it's set; the other ai_canonname fields will be
1183 left untouched. And we'll just pray that the application code
1184 won't mess around with the list structure; if we start doing
1185 that, we'll have to start replacing and freeing all of the
1186 ai_canonname fields.
1188 Ref: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=133668 .
1190 Since it's dependent on the target hostname, it's hard to check
1191 for at configure time. The bug was fixed in glibc 2.3.4.
1192 After the fix, the ai_canonname field is allocated, so our
1193 workaround leaks memory. We disable the workaround for glibc
1194 >= 2.4, but there is no easy way to test for glibc patch
1195 versions, so we still leak memory under glibc 2.3.4 through
1198 Some Windows documentation says that even when AI_CANONNAME is
1199 set, the returned ai_canonname field can be null. The NetBSD
1200 1.5 implementation also does this, if the input hostname is a
1201 numeric host address string. That case isn't handled well at
1204 Libc version 5 didn't have getaddrinfo at all. */
1206 #ifdef COPY_FIRST_CANONNAME
1208 * This code must *always* return an error, return a null
1209 * ai_canonname, or return an ai_canonname allocated here using
1210 * malloc, so that freeaddrinfo can always free a non-null
1211 * ai_canonname. Note that it really doesn't matter if the
1212 * AI_CANONNAME flag was set.
1215 if (ai->ai_canonname) {
1217 const char *name2 = 0;
1222 * Current versions of GET_HOST_BY_NAME will fail if the
1223 * target hostname has IPv6 addresses only. Make sure it
1224 * fails fairly cleanly.
1226 GET_HOST_BY_NAME (name, hp, herr, htmp);
1229 * This case probably means it's an IPv6-only name. If
1230 * ai_canonname is a numeric address, get rid of it.
1232 if (ai->ai_canonname && strchr(ai->ai_canonname, ':'))
1233 ai->ai_canonname = 0;
1234 name2 = ai->ai_canonname ? ai->ai_canonname : name;
1237 * Sometimes gethostbyname will be directed to /etc/hosts
1238 * first, and sometimes that file will have entries with
1239 * the unqualified name first. So take the first entry
1240 * that looks like it could be a FQDN. Starting with h_name
1241 * and then all the aliases.
1243 for (i = 0, name2 = hp->h_name; name2; i++) {
1244 if (strchr(name2, '.') != 0)
1246 name2 = hp->h_aliases[i];
1252 ai->ai_canonname = strdup(name2);
1253 if (name2 != 0 && ai->ai_canonname == 0) {
1254 system_freeaddrinfo(ai);
1256 #ifdef DEBUG_ADDRINFO
1257 debug_dump_error(EAI_MEMORY);
1261 /* Zap the remaining ai_canonname fields glibc fills in, in
1262 case the application messes around with the list
1264 while ((ai = ai->ai_next) != NULL)
1265 ai->ai_canonname = 0;
1269 #ifdef NUMERIC_SERVICE_BROKEN
1270 if (service_port != 0) {
1271 for (ai = *result; ai; ai = ai->ai_next) {
1272 if (socket_type != 0 && ai->ai_socktype == 0)
1273 /* Is this check actually needed? */
1274 ai->ai_socktype = socket_type;
1275 sa_setport(ai->ai_addr, service_port);
1281 for (ai = *result; ai; ai = ai->ai_next) {
1282 /* AIX 4.3.3 libc is broken. It doesn't set the family or len
1283 fields of the sockaddr structures. Usually, sa_family is
1284 zero, but I've seen it set to 1 in some cases also (maybe
1285 just leftover from previous contents of the memory
1286 block?). So, always override what libc returned. */
1287 ai->ai_addr->sa_family = ai->ai_family;
1291 /* Not dealt with currently:
1293 - Some versions of GNU libc can lose some IPv4 addresses in
1294 certain cases when multiple IPv4 and IPv6 addresses are
1297 #ifdef DEBUG_ADDRINFO
1298 debug_dump_addrinfos(*result);
1305 void freeaddrinfo (struct addrinfo *ai)
1307 #ifdef COPY_FIRST_CANONNAME
1309 free(ai->ai_canonname);
1310 ai->ai_canonname = 0;
1311 system_freeaddrinfo(ai);
1314 system_freeaddrinfo(ai);
1317 #endif /* WRAP_GETADDRINFO */
1320 static int krb5int_lock_fac (void)
1323 err = krb5int_call_thread_support_init();
1326 return k5_mutex_lock(&krb5int_fac.lock);
1329 static int krb5int_unlock_fac (void)
1331 return k5_mutex_unlock(&krb5int_fac.lock);
1335 /* Some systems don't define in6addr_any. */
1336 const struct in6_addr krb5int_in6addr_any = IN6ADDR_ANY_INIT;
1338 int krb5int_getaddrinfo (const char *node, const char *service,
1339 const struct addrinfo *hints,
1340 struct addrinfo **aip)
1342 return getaddrinfo(node, service, hints, aip);
1345 void krb5int_freeaddrinfo (struct addrinfo *ai)
1350 const char *krb5int_gai_strerror(int err)
1352 return gai_strerror(err);
1355 int krb5int_getnameinfo (const struct sockaddr *sa, socklen_t salen,
1356 char *hbuf, size_t hbuflen,
1357 char *sbuf, size_t sbuflen,
1360 return getnameinfo(sa, salen, hbuf, hbuflen, sbuf, sbuflen, flags);