39
39
* fashion that it might be confused with the original M.I.T. software.
44
If a system version is available but buggy, save handles to it,
45
redefine the names to refer to static functions defined here, and
46
in those functions, call the system versions and fix up the
47
returned data. Use the native data structures and flag values.
49
If no system version exists, use gethostby* and fake it. Define
50
the data structures and flag values locally.
53
On Mac OS X, getaddrinfo results aren't cached (though
54
gethostbyname results are), so we need to build a cache here. Now
55
things are getting really messy. Because the cache is in use, we
56
use getservbyname, and throw away thread safety. (Not that the
57
cache is thread safe, but when we get locking support, that'll be
58
dealt with.) This code needs tearing down and rebuilding, soon.
61
Note that recent Windows developers' code has an interesting hack:
62
When you include the right header files, with the right set of
63
macros indicating system versions, you'll get an inline function
64
that looks for getaddrinfo (or whatever) in the system library, and
65
calls it if it's there. If it's not there, it fakes it with
68
We're taking a simpler approach: A system provides these routines or
71
Someday, we may want to take into account different versions (say,
72
different revs of GNU libc) where some are broken in one way, and
73
some work or are broken in another way. Cross that bridge when we
78
+ For AIX 4.3.3, using the RFC 2133 definition: Implement
79
AI_NUMERICHOST. It's not defined in the header file.
81
For certain (old?) versions of GNU libc, AI_NUMERICHOST is
82
defined but not implemented.
84
+ Use gethostbyname2, inet_aton and other IPv6 or thread-safe
85
functions if available. But, see
86
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=135182 for one
87
gethostbyname2 problem on Linux. And besides, if a platform is
88
supporting IPv6 at all, they really should be doing getaddrinfo
91
+ inet_ntop, inet_pton
93
+ Conditionally export/import the function definitions, so a
94
library can have a single copy instead of multiple.
96
+ Upgrade host requirements to include working implementations of
97
these functions, and throw all this away. Pleeease? :-) */
99
#include "port-sockets.h"
100
#include "socket-utils.h"
101
#include "k5-platform.h"
102
#include "k5-thread.h"
103
#include "supp-int.h"
105
#include <stdio.h> /* for sprintf */
108
#define IMPLEMENT_FAKE_GETADDRINFO
42
109
#include "fake-addrinfo.h"
44
/* Allocate the storage here. */
45
struct fac krb5int_fac = { K5_MUTEX_PARTIAL_INITIALIZER, 0 };
47
int krb5int_init_fac (void)
49
return k5_mutex_finish_init(&krb5int_fac.lock);
52
void krb5int_fini_fac (void)
54
k5_mutex_destroy(&krb5int_fac.lock);
57
extern int krb5int_call_thread_support_init(void);
58
int krb5int_lock_fac (void)
114
getaddrinfo (/*@in@*/ /*@null@*/ const char *,
115
/*@in@*/ /*@null@*/ const char *,
116
/*@in@*/ /*@null@*/ const struct addrinfo *,
117
/*@out@*/ struct addrinfo **)
120
freeaddrinfo (/*@only@*/ /*@out@*/ struct addrinfo *)
123
getnameinfo (const struct sockaddr *addr, socklen_t addrsz,
124
/*@out@*/ /*@null@*/ char *h, socklen_t hsz,
125
/*@out@*/ /*@null@*/ char *s, socklen_t ssz,
127
/*@requires (maxSet(h)+1) >= hsz /\ (maxSet(s)+1) >= ssz @*/
128
/* too hard: maxRead(addr) >= (addrsz-1) */
129
/*@modifies *h, *s@*/;
130
extern /*@dependent@*/ char *gai_strerror (int code) /*@*/;
135
#include "cache-addrinfo.h"
137
#if (defined (__linux__) && defined(HAVE_GETADDRINFO)) || defined (_AIX)
138
/* See comments below. */
139
# define WRAP_GETADDRINFO
142
#if defined (__linux__) && defined(HAVE_GETADDRINFO)
143
# define COPY_FIRST_CANONNAME
147
# define NUMERIC_SERVICE_BROKEN
148
# define COPY_FIRST_CANONNAME
152
#ifdef COPY_FIRST_CANONNAME
156
#ifdef NUMERIC_SERVICE_BROKEN
157
# include <ctype.h> /* isdigit */
158
# include <stdlib.h> /* strtoul */
162
/* Do we actually have *any* systems we care about that don't provide
163
either getaddrinfo or one of these two flavors of
165
#if !defined(HAVE_GETHOSTBYNAME_R) || defined(THREADSAFE_GETHOSTBYNAME)
166
typedef struct hostent *GET_HOST_TMP;
167
#define GET_HOST_BY_NAME(NAME, HP, ERR, TMP) \
168
{ TMP = gethostbyname (NAME); (ERR) = h_errno; (HP) = TMP; }
169
#define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR, TMP) \
170
{ TMP = gethostbyaddr ((ADDR), (ADDRLEN), (FAMILY)); (ERR) = h_errno; (HP) = TMP; }
172
#ifdef _AIX /* XXX should have a feature test! */
175
struct hostent_data data;
177
#define GET_HOST_BY_NAME(NAME, HP, ERR, TMP) \
179
(HP) = (gethostbyname_r((NAME), &TMP.ent, &TMP.data) \
185
#define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR) \
187
struct hostent my_h_ent; \
188
struct hostent_data my_h_ent_data; \
189
(HP) = (gethostbyaddr_r((ADDR), (ADDRLEN), (FAMILY), &my_h_ent, \
197
#ifdef GETHOSTBYNAME_R_RETURNS_INT
202
#define GET_HOST_BY_NAME(NAME, HP, ERR, TMP) \
204
struct hostent *my_hp = NULL; \
205
int my_h_err, my_ret; \
206
my_ret = gethostbyname_r((NAME), &TMP.ent, \
207
TMP.buf, sizeof (TMP.buf), &my_hp, \
209
(HP) = (((my_ret != 0) || (my_hp != &TMP.ent)) \
214
#define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR, TMP) \
216
struct hostent *my_hp; \
217
int my_h_err, my_ret; \
218
my_ret = gethostbyaddr_r((ADDR), (ADDRLEN), (FAMILY), &TMP.ent, \
219
TMP.buf, sizeof (TMP.buf), &my_hp, \
221
(HP) = (((my_ret != 0) || (my_hp != &TMP.ent)) \
231
#define GET_HOST_BY_NAME(NAME, HP, ERR, TMP) \
234
(HP) = gethostbyname_r((NAME), &TMP.ent, \
235
TMP.buf, sizeof (TMP.buf), &my_h_err); \
238
#define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR, TMP) \
241
(HP) = gethostbyaddr_r((ADDR), (ADDRLEN), (FAMILY), &TMP.ent, \
242
TMP.buf, sizeof (TMP.buf), &my_h_err); \
245
#endif /* returns int? */
249
/* Now do the same for getservby* functions. */
250
#ifndef HAVE_GETSERVBYNAME_R
251
typedef struct servent *GET_SERV_TMP;
252
#define GET_SERV_BY_NAME(NAME, PROTO, SP, ERR, TMP) \
253
(TMP = getservbyname (NAME, PROTO), (SP) = TMP, (ERR) = (SP) ? 0 : -1)
254
#define GET_SERV_BY_PORT(PORT, PROTO, SP, ERR, TMP) \
255
(TMP = getservbyport (PORT, PROTO), (SP) = TMP, (ERR) = (SP) ? 0 : -1)
257
#ifdef GETSERVBYNAME_R_RETURNS_INT
262
#define GET_SERV_BY_NAME(NAME, PROTO, SP, ERR, TMP) \
264
struct servent *my_sp; \
266
(SP) = (getservbyname_r((NAME), (PROTO), &TMP.ent, \
267
TMP.buf, sizeof (TMP.buf), &my_sp, \
273
#define GET_SERV_BY_PORT(PORT, PROTO, SP, ERR, TMP) \
275
struct servent *my_sp; \
277
(SP) = (getservbyport_r((PORT), (PROTO), &TMP.ent, \
278
TMP.buf, sizeof (TMP.buf), &my_sp, \
285
/* returns ptr -- IRIX? */
290
#define GET_SERV_BY_NAME(NAME, PROTO, SP, ERR, TMP) \
292
(SP) = getservbyname_r((NAME), (PROTO), &TMP.ent, \
293
TMP.buf, sizeof (TMP.buf)); \
294
(ERR) = (SP) == NULL; \
297
#define GET_SERV_BY_PORT(PORT, PROTO, SP, ERR, TMP) \
299
struct servent *my_sp; \
300
my_sp = getservbyport_r((PORT), (PROTO), &TMP.ent, \
301
TMP.buf, sizeof (TMP.buf)); \
303
(ERR) = my_sp == 0; \
304
(ERR) = (ERR); /* avoid "unused" warning */ \
309
#if defined(WRAP_GETADDRINFO) || defined(FAI_CACHE)
311
system_getaddrinfo (const char *name, const char *serv,
312
const struct addrinfo *hint,
313
struct addrinfo **res)
315
return getaddrinfo(name, serv, hint, res);
319
system_freeaddrinfo (struct addrinfo *ai)
324
/* Note: Implementations written to RFC 2133 use size_t, while RFC
325
2553 implementations use socklen_t, for the second parameter.
327
Mac OS X (10.2) and AIX 4.3.3 appear to be in the RFC 2133 camp,
328
but we don't have an autoconf test for that right now. */
330
system_getnameinfo (const struct sockaddr *sa, socklen_t salen,
331
char *host, size_t hostlen, char *serv, size_t servlen,
334
return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
338
#if !defined (HAVE_GETADDRINFO) || defined(WRAP_GETADDRINFO) || defined(FAI_CACHE)
341
#define getaddrinfo my_fake_getaddrinfo
343
#define freeaddrinfo my_fake_freeaddrinfo
347
#if !defined (HAVE_GETADDRINFO)
350
#define gai_strerror my_fake_gai_strerror
352
#endif /* ! HAVE_GETADDRINFO */
354
#if (!defined (HAVE_GETADDRINFO) || defined (WRAP_GETADDRINFO)) && defined(DEBUG_ADDRINFO)
355
/* Some debug routines. */
357
static const char *protoname (int p, char *buf) {
358
#define X(N) if (p == IPPROTO_ ## N) return #N
376
sprintf(buf, " %-2d", p);
380
static const char *socktypename (int t, char *buf) {
382
case SOCK_DGRAM: return "DGRAM";
383
case SOCK_STREAM: return "STREAM";
384
case SOCK_RAW: return "RAW";
385
case SOCK_RDM: return "RDM";
386
case SOCK_SEQPACKET: return "SEQPACKET";
388
sprintf(buf, " %-2d", t);
392
static const char *familyname (int f, char *buf) {
395
sprintf(buf, "AF %d", f);
397
case AF_INET: return "AF_INET";
398
case AF_INET6: return "AF_INET6";
400
case AF_UNIX: return "AF_UNIX";
405
static void debug_dump_getaddrinfo_args (const char *name, const char *serv,
406
const struct addrinfo *hint)
410
"getaddrinfo(hostname %s, service %s,\n"
412
name ? name : "(null)", serv ? serv : "(null)");
416
#define Z(FLAG) if (hint->ai_flags & AI_##FLAG) fprintf(stderr, "%s%s", sep, #FLAG), sep = "|"
419
#ifdef AI_NUMERICHOST
423
fprintf(stderr, "no-flags");
425
fprintf(stderr, " %s", familyname(hint->ai_family, buf));
426
if (hint->ai_socktype)
427
fprintf(stderr, " SOCK_%s", socktypename(hint->ai_socktype, buf));
428
if (hint->ai_protocol)
429
fprintf(stderr, " IPPROTO_%s", protoname(hint->ai_protocol, buf));
431
fprintf(stderr, "(null)");
432
fprintf(stderr, " }):\n");
435
static void debug_dump_error (int err)
437
fprintf(stderr, "error %d: %s\n", err, gai_strerror(err));
440
static void debug_dump_addrinfos (const struct addrinfo *ai)
444
fprintf(stderr, "addrinfos returned:\n");
446
fprintf(stderr, "%p...", ai);
447
fprintf(stderr, " socktype=%s", socktypename(ai->ai_socktype, buf));
448
fprintf(stderr, " ai_family=%s", familyname(ai->ai_family, buf));
449
if (ai->ai_family != ai->ai_addr->sa_family)
450
fprintf(stderr, " sa_family=%s",
451
familyname(ai->ai_addr->sa_family, buf));
452
fprintf(stderr, "\n");
456
fprintf(stderr, "end addrinfos returned (%d)\n");
461
#if !defined (HAVE_GETADDRINFO) || defined (WRAP_GETADDRINFO)
464
int getaddrinfo (const char *name, const char *serv,
465
const struct addrinfo *hint, struct addrinfo **result);
468
void freeaddrinfo (struct addrinfo *ai);
472
#if !defined (HAVE_GETADDRINFO)
474
#define HAVE_FAKE_GETADDRINFO /* was not originally HAVE_GETADDRINFO */
475
#define HAVE_GETADDRINFO
476
#define NEED_FAKE_GETNAMEINFO
477
#undef HAVE_GETNAMEINFO
478
#define HAVE_GETNAMEINFO 1
481
#define getnameinfo my_fake_getnameinfo
484
char *gai_strerror (int code);
488
#if !defined (HAVE_GETADDRINFO)
490
int getnameinfo (const struct sockaddr *addr, socklen_t len,
491
char *host, socklen_t hostlen,
492
char *service, socklen_t servicelen,
496
/* Fudge things on older gai implementations. */
497
/* AIX 4.3.3 is based on RFC 2133; no AI_NUMERICHOST. */
498
#ifndef AI_NUMERICHOST
499
# define AI_NUMERICHOST 0
501
/* Partial RFC 2553 implementations may not have AI_ADDRCONFIG and
502
friends, which RFC 3493 says are now part of the getaddrinfo
503
interface, and we'll want to use. */
504
#ifndef AI_ADDRCONFIG
505
# define AI_ADDRCONFIG 0
508
# define AI_V4MAPPED 0
514
# define AI_DEFAULT (AI_ADDRCONFIG|AI_V4MAPPED)
517
#if defined(HAVE_FAKE_GETADDRINFO) || defined(FAI_CACHE)
518
#define NEED_FAKE_GETADDRINFO
521
#if defined(NEED_FAKE_GETADDRINFO) || defined(WRAP_GETADDRINFO)
525
#ifdef NEED_FAKE_GETADDRINFO
526
#include <string.h> /* for strspn */
528
static inline int translate_h_errno (int h);
530
static inline int fai_add_entry (struct addrinfo **result, void *addr,
531
int port, const struct addrinfo *template)
533
struct addrinfo *n = malloc (sizeof (struct addrinfo));
536
if (template->ai_family != AF_INET
537
#ifdef KRB5_USE_INET6
538
&& template->ai_family != AF_INET6
543
if (template->ai_family == AF_INET) {
544
struct sockaddr_in *sin4;
545
sin4 = malloc (sizeof (struct sockaddr_in));
548
memset (sin4, 0, sizeof (struct sockaddr_in)); /* for sin_zero */
549
n->ai_addr = (struct sockaddr *) sin4;
550
sin4->sin_family = AF_INET;
551
sin4->sin_addr = *(struct in_addr *)addr;
552
sin4->sin_port = port;
554
sin4->sin_len = sizeof (struct sockaddr_in);
557
#ifdef KRB5_USE_INET6
558
if (template->ai_family == AF_INET6) {
559
struct sockaddr_in6 *sin6;
560
sin6 = malloc (sizeof (struct sockaddr_in6));
563
memset (sin6, 0, sizeof (struct sockaddr_in6)); /* for sin_zero */
564
n->ai_addr = (struct sockaddr *) sin6;
565
sin6->sin6_family = AF_INET6;
566
sin6->sin6_addr = *(struct in6_addr *)addr;
567
sin6->sin6_port = port;
569
sin6->sin6_len = sizeof (struct sockaddr_in6);
573
n->ai_next = *result;
579
/* fake addrinfo cache entries */
580
#define CACHE_ENTRY_LIFETIME 15 /* seconds */
582
static void plant_face (const char *name, struct face *entry)
584
entry->name = strdup(name);
585
if (entry->name == NULL)
586
/* @@ Wastes memory. */
588
k5_mutex_assert_locked(&krb5int_fac.lock);
589
entry->next = krb5int_fac.data;
590
entry->expiration = time(0) + CACHE_ENTRY_LIFETIME;
591
krb5int_fac.data = entry;
592
#ifdef DEBUG_ADDRINFO
593
printf("added cache entry '%s' at %p: %d ipv4, %d ipv6; expire %d\n",
594
name, entry, entry->naddrs4, entry->naddrs6, entry->expiration);
598
static int find_face (const char *name, struct face **entry)
600
struct face *fp, **fpp;
601
time_t now = time(0);
603
/* First, scan for expired entries and free them.
604
(Future improvement: Integrate these two loops.) */
605
#ifdef DEBUG_ADDRINFO
606
printf("scanning cache at %d for '%s'...\n", now, name);
608
k5_mutex_assert_locked(&krb5int_fac.lock);
609
for (fpp = &krb5int_fac.data; *fpp; ) {
611
#ifdef DEBUG_ADDRINFO
612
printf(" checking expiration time of @%p: %d\n",
615
if (fp->expiration < now) {
616
#ifdef DEBUG_ADDRINFO
617
printf("\texpiring cache entry\n");
625
/* Stay at this point in the list, and check again. */
631
for (fp = krb5int_fac.data; fp; fp = fp->next) {
632
#ifdef DEBUG_ADDRINFO
633
printf(" comparing entry @%p\n", fp);
635
if (!strcasecmp(fp->name, name)) {
636
#ifdef DEBUG_ADDRINFO
637
printf("\tMATCH!\n");
648
static int krb5int_lock_fac(void), krb5int_unlock_fac(void);
650
static inline int fai_add_hosts_by_name (const char *name,
651
struct addrinfo *template,
652
int portnum, int flags,
653
struct addrinfo **result)
660
err = krb5int_lock_fac();
665
if (!find_face(name, &ce)) {
666
struct addrinfo myhints = { 0 }, *ai, *ai2;
669
#ifdef DEBUG_ADDRINFO
670
printf("looking up new data for '%s'...\n", name);
672
myhints.ai_socktype = SOCK_STREAM;
673
myhints.ai_flags = AI_CANONNAME;
674
/* Don't set ai_family -- we want to cache all address types,
675
because the next lookup may not use the same constraints as
676
the current one. We *could* cache them separately, so that
677
we never have to look up an IPv6 address if we are always
678
asked for IPv4 only, but let's deal with that later, if we
680
/* Try NULL for the service for now.
682
It would be nice to use the requested service name, and not
683
have to patch things up, but then we'd be doing multiple
684
queries for the same host when we get different services.
685
We were using "telnet" for a little more confidence that
686
getaddrinfo would heed the hints to only give us stream
687
socket types (with no socket type and null service name, we
688
might get stream *and* dgram *and* raw, for each address,
689
or only raw). The RFC 3493 description of ai_socktype
690
sometimes associates it with the specified service,
693
But on Mac OS X (10.3, 10.4) they've "extended" getaddrinfo
694
to make SRV RR queries. (Please, somebody, show me
695
something in the specs that actually supports this? RFC
696
3493 says nothing about it, but it does say getaddrinfo is
697
the new way to look up hostnames. RFC 2782 says SRV
698
records should *not* be used unless the application
699
protocol spec says to do so. The Telnet spec does not say
700
to do it.) And then they complain when our code
701
"unexpectedly" seems to use this "extension" in cases where
702
they don't want it to be used.
704
Fortunately, it appears that if we specify ai_socktype as
705
SOCK_STREAM and use a null service name, we only get one
706
copy of each address on all the platforms I've tried,
707
although it may not have ai_socktype filled in properly.
708
So, we'll fudge it with that for now. */
709
aierr = system_getaddrinfo(name, NULL, &myhints, &ai);
711
krb5int_unlock_fac();
714
ce = malloc(sizeof(struct face));
715
memset(ce, 0, sizeof(*ce));
716
ce->expiration = time(0) + 30;
717
for (ai2 = ai; ai2; ai2 = ai2->ai_next) {
718
#ifdef DEBUG_ADDRINFO
719
printf(" found an address in family %d...\n", ai2->ai_family);
721
switch (ai2->ai_family) {
732
ce->addrs4 = calloc(ce->naddrs4, sizeof(*ce->addrs4));
733
if (ce->addrs4 == NULL && ce->naddrs4 != 0) {
734
krb5int_unlock_fac();
735
system_freeaddrinfo(ai);
738
ce->addrs6 = calloc(ce->naddrs6, sizeof(*ce->addrs6));
739
if (ce->addrs6 == NULL && ce->naddrs6 != 0) {
740
krb5int_unlock_fac();
742
system_freeaddrinfo(ai);
745
for (ai2 = ai, i4 = i6 = 0; ai2; ai2 = ai2->ai_next) {
746
switch (ai2->ai_family) {
748
ce->addrs4[i4++] = ((struct sockaddr_in *)ai2->ai_addr)->sin_addr;
751
ce->addrs6[i6++] = ((struct sockaddr_in6 *)ai2->ai_addr)->sin6_addr;
757
ce->canonname = ai->ai_canonname ? strdup(ai->ai_canonname) : 0;
758
system_freeaddrinfo(ai);
759
plant_face(name, ce);
761
template->ai_family = AF_INET6;
762
template->ai_addrlen = sizeof(struct sockaddr_in6);
763
for (i = 0; i < ce->naddrs6; i++) {
764
r = fai_add_entry (result, &ce->addrs6[i], portnum, template);
766
krb5int_unlock_fac();
770
template->ai_family = AF_INET;
771
template->ai_addrlen = sizeof(struct sockaddr_in);
772
for (i = 0; i < ce->naddrs4; i++) {
773
r = fai_add_entry (result, &ce->addrs4[i], portnum, template);
775
krb5int_unlock_fac();
779
if (*result && (flags & AI_CANONNAME))
780
(*result)->ai_canonname = (ce->canonname
781
? strdup(ce->canonname)
783
krb5int_unlock_fac();
793
GET_HOST_BY_NAME (name, hp, herr, htmp);
795
return translate_h_errno (herr);
796
for (i = 0; hp->h_addr_list[i]; i++) {
797
r = fai_add_entry (result, hp->h_addr_list[i], portnum, template);
801
if (*result && (flags & AI_CANONNAME))
802
(*result)->ai_canonname = strdup (hp->h_name);
809
fake_freeaddrinfo (struct addrinfo *ai)
811
struct addrinfo *next;
814
if (ai->ai_canonname)
815
free (ai->ai_canonname);
824
fake_getaddrinfo (const char *name, const char *serv,
825
const struct addrinfo *hint, struct addrinfo **result)
827
struct addrinfo *res = 0;
829
int port = 0, socktype;
831
struct addrinfo template;
833
#ifdef DEBUG_ADDRINFO
834
debug_dump_getaddrinfo_args(name, serv, hint);
838
if (hint->ai_family != 0 && hint->ai_family != AF_INET)
840
socktype = hint->ai_socktype;
841
flags = hint->ai_flags;
848
size_t numlen = strspn (serv, "0123456789");
849
if (serv[numlen] == '\0') {
851
unsigned long p = strtoul (serv, 0, 10);
852
if (p == 0 || p > 65535)
857
int try_dgram_too = 0, s_err;
862
socktype = SOCK_STREAM;
865
GET_SERV_BY_NAME(serv, socktype == SOCK_STREAM ? "tcp" : "udp",
869
socktype = SOCK_DGRAM;
870
goto try_service_lookup;
879
name = (flags & AI_PASSIVE) ? "0.0.0.0" : "127.0.0.1";
880
flags |= AI_NUMERICHOST;
883
template.ai_family = AF_INET;
884
template.ai_addrlen = sizeof (struct sockaddr_in);
885
template.ai_socktype = socktype;
886
template.ai_protocol = 0;
887
template.ai_flags = 0;
888
template.ai_canonname = 0;
889
template.ai_next = 0;
890
template.ai_addr = 0;
892
/* If NUMERICHOST is set, parse a numeric address.
893
If it's not set, don't accept such names. */
894
if (flags & AI_NUMERICHOST) {
895
struct in_addr addr4;
897
ret = inet_aton (name, &addr4);
901
addr4.s_addr = inet_addr (name);
902
if (addr4.s_addr == 0xffffffff || addr4.s_addr == -1)
903
/* 255.255.255.255 or parse error, both bad */
906
ret = fai_add_entry (&res, &addr4, port, &template);
908
ret = fai_add_hosts_by_name (name, &template, port, flags,
912
if (ret && ret != NO_ADDRESS) {
913
fake_freeaddrinfo (res);
922
#ifdef NEED_FAKE_GETNAMEINFO
924
fake_getnameinfo (const struct sockaddr *sa, socklen_t len,
925
char *host, socklen_t hostlen,
926
char *service, socklen_t servicelen,
930
const struct sockaddr_in *sinp;
934
if (sa->sa_family != AF_INET) {
937
sinp = (const struct sockaddr_in *) sa;
940
if (hostlen < 0 || hlen != hostlen) {
945
if (servicelen < 0 || slen != servicelen) {
951
if (flags & NI_NUMERICHOST) {
952
#if (defined(__GNUC__) && defined(__mips__)) || 1 /* thread safety always */
953
/* The inet_ntoa call, passing a struct, fails on IRIX 6.5
954
using gcc 2.95; we get back "0.0.0.0". Since this in a
955
configuration still important at Athena, here's the
956
workaround, which also happens to be thread-safe.... */
957
const unsigned char *uc;
960
uc = (const unsigned char *) &sinp->sin_addr;
961
sprintf(tmpbuf, "%d.%d.%d.%d", uc[0], uc[1], uc[2], uc[3]);
962
strncpy(host, tmpbuf, hlen);
966
p = inet_ntoa (sinp->sin_addr);
967
strncpy (host, p, hlen);
973
GET_HOST_BY_ADDR((const char *) &sinp->sin_addr,
974
sizeof (struct in_addr),
975
sa->sa_family, hp, herr, htmp);
977
if (herr == NO_ADDRESS && !(flags & NI_NAMEREQD)) /* ??? */
979
return translate_h_errno (herr);
981
/* According to the Open Group spec, getnameinfo can
982
silently truncate, but must still return a
983
null-terminated string. */
984
strncpy (host, hp->h_name, hlen);
990
if (flags & NI_NUMERICSERV) {
994
port = ntohs (sinp->sin_port);
995
if (port < 0 || port > 65535)
997
sprintf (numbuf, "%d", port);
998
strncpy (service, numbuf, slen);
1003
GET_SERV_BY_PORT(sinp->sin_port,
1004
(flags & NI_DGRAM) ? "udp" : "tcp",
1007
goto numeric_service;
1008
strncpy (service, sp->s_name, slen);
1010
service[servicelen-1] = 0;
1017
#if defined(HAVE_FAKE_GETADDRINFO) || defined(NEED_FAKE_GETNAMEINFO)
1020
char *gai_strerror (int code)
1023
case EAI_ADDRFAMILY: return "address family for nodename not supported";
1024
case EAI_AGAIN: return "temporary failure in name resolution";
1025
case EAI_BADFLAGS: return "bad flags to getaddrinfo/getnameinfo";
1026
case EAI_FAIL: return "non-recoverable failure in name resolution";
1027
case EAI_FAMILY: return "ai_family not supported";
1028
case EAI_MEMORY: return "out of memory";
1029
case EAI_NODATA: return "no address associated with hostname";
1030
case EAI_NONAME: return "name does not exist";
1031
case EAI_SERVICE: return "service name not supported for specified socket type";
1032
case EAI_SOCKTYPE: return "ai_socktype not supported";
1033
case EAI_SYSTEM: return strerror (errno);
1034
default: return "bogus getaddrinfo error?";
1039
static inline int translate_h_errno (int h)
1044
#ifdef NETDB_INTERNAL
1045
case NETDB_INTERNAL:
1046
if (errno == ENOMEM)
1050
case HOST_NOT_FOUND:
1057
#if NO_DATA != NO_ADDRESS
1066
#if defined(HAVE_FAKE_GETADDRINFO) || defined(FAI_CACHE)
1068
int getaddrinfo (const char *name, const char *serv,
1069
const struct addrinfo *hint, struct addrinfo **result)
1071
return fake_getaddrinfo(name, serv, hint, result);
1075
void freeaddrinfo (struct addrinfo *ai)
1077
fake_freeaddrinfo(ai);
1080
#ifdef NEED_FAKE_GETNAMEINFO
1082
int getnameinfo (const struct sockaddr *sa, socklen_t len,
1083
char *host, socklen_t hostlen,
1084
char *service, socklen_t servicelen,
1087
return fake_getnameinfo(sa, len, host, hostlen, service, servicelen,
1090
#endif /* NEED_FAKE_GETNAMEINFO */
1091
#endif /* HAVE_FAKE_GETADDRINFO */
1092
#endif /* NEED_FAKE_GETADDRINFO */
1095
#ifdef WRAP_GETADDRINFO
1099
getaddrinfo (const char *name, const char *serv, const struct addrinfo *hint,
1100
struct addrinfo **result)
1103
#if defined(_AIX) || defined(COPY_FIRST_CANONNAME)
1104
struct addrinfo *ai;
1106
#ifdef NUMERIC_SERVICE_BROKEN
1107
int service_is_numeric = 0;
1108
int service_port = 0;
1109
int socket_type = 0;
1112
#ifdef DEBUG_ADDRINFO
1113
debug_dump_getaddrinfo_args(name, serv, hint);
1116
#ifdef NUMERIC_SERVICE_BROKEN
1117
/* AIX 4.3.3 is broken. (Or perhaps out of date?)
1119
If a numeric service is provided, and it doesn't correspond to
1120
a known service name for tcp or udp (as appropriate), an error
1121
code (for "host not found") is returned. If the port maps to a
1122
known service for both udp and tcp, all is well. */
1123
if (serv && serv[0] && isdigit(serv[0])) {
1124
unsigned long lport;
1126
lport = strtoul(serv, &end, 10);
1129
return EAI_SOCKTYPE;
1130
service_is_numeric = 1;
1131
service_port = htons(lport);
1132
#ifdef AI_NUMERICSERV
1133
if (hint && hint->ai_flags & AI_NUMERICSERV)
1137
serv = "discard"; /* defined for both udp and tcp */
1139
socket_type = hint->ai_socktype;
1144
aierr = system_getaddrinfo (name, serv, hint, result);
1145
if (aierr || *result == 0) {
1146
#ifdef DEBUG_ADDRINFO
1147
debug_dump_error(aierr);
1152
/* Linux libc version 6 (libc-2.2.4.so on Debian) is broken.
1154
RFC 2553 says that when AI_CANONNAME is set, the ai_canonname
1155
flag of the first returned structure has the canonical name of
1156
the host. Instead, GNU libc sets ai_canonname in each returned
1157
structure to the name that the corresponding address maps to,
1158
if any, or a printable numeric form.
1160
RFC 2553 bis and the new Open Group spec say that field will be
1161
the canonical name if it can be determined, otherwise, the
1162
provided hostname or a copy of it.
1164
IMNSHO, "canonical name" means CNAME processing and not PTR
1165
processing, but I can see arguing it. Using the numeric form
1166
when that's not the form provided is just wrong. So, let's fix
1169
The glibc 2.2.5 sources indicate that the canonical name is
1170
*not* allocated separately, it's just some extra storage tacked
1171
on the end of the addrinfo structure. So, let's try this
1172
approach: If getaddrinfo sets ai_canonname, we'll replace the
1173
*first* one with allocated storage, and free up that pointer in
1174
freeaddrinfo if it's set; the other ai_canonname fields will be
1175
left untouched. And we'll just pray that the application code
1176
won't mess around with the list structure; if we start doing
1177
that, we'll have to start replacing and freeing all of the
1178
ai_canonname fields.
1180
Ref: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=133668 .
1182
Since it's dependent on the target hostname, it's hard to check
1183
for at configure time. Always do it on Linux for now. When
1184
they get around to fixing it, add a compile-time or run-time
1185
check for the glibc version in use.
1187
Some Windows documentation says that even when AI_CANONNAME is
1188
set, the returned ai_canonname field can be null. The NetBSD
1189
1.5 implementation also does this, if the input hostname is a
1190
numeric host address string. That case isn't handled well at
1193
Libc version 5 didn't have getaddrinfo at all. */
1195
#ifdef COPY_FIRST_CANONNAME
1197
* This code must *always* return an error, return a null
1198
* ai_canonname, or return an ai_canonname allocated here using
1199
* malloc, so that freeaddrinfo can always free a non-null
1200
* ai_canonname. Note that it really doesn't matter if the
1201
* AI_CANONNAME flag was set.
1204
if (ai->ai_canonname) {
1206
const char *name2 = 0;
1211
* Current versions of GET_HOST_BY_NAME will fail if the
1212
* target hostname has IPv6 addresses only. Make sure it
1213
* fails fairly cleanly.
1215
GET_HOST_BY_NAME (name, hp, herr, htmp);
1218
* This case probably means it's an IPv6-only name. If
1219
* ai_canonname is a numeric address, get rid of it.
1221
if (ai->ai_canonname && strchr(ai->ai_canonname, ':'))
1222
ai->ai_canonname = 0;
1223
name2 = ai->ai_canonname ? ai->ai_canonname : name;
1225
/* Sometimes gethostbyname will be directed to /etc/hosts
1226
first, and sometimes that file will have entries with
1227
the unqualified name first. So take the first entry
1228
that looks like it could be a FQDN. */
1229
for (i = 0; hp->h_aliases[i]; i++) {
1230
if (strchr(hp->h_aliases[i], '.') != 0) {
1231
name2 = hp->h_aliases[i];
1235
/* Give up, just use the first name (h_name ==
1236
h_aliases[0] on all systems I've seen). */
1237
if (hp->h_aliases[i] == 0)
1241
ai->ai_canonname = strdup(name2);
1242
if (name2 != 0 && ai->ai_canonname == 0) {
1243
system_freeaddrinfo(ai);
1245
#ifdef DEBUG_ADDRINFO
1246
debug_dump_error(EAI_MEMORY);
1250
/* Zap the remaining ai_canonname fields glibc fills in, in
1251
case the application messes around with the list
1253
while ((ai = ai->ai_next) != NULL)
1254
ai->ai_canonname = 0;
1258
#ifdef NUMERIC_SERVICE_BROKEN
1259
if (service_port != 0) {
1260
for (ai = *result; ai; ai = ai->ai_next) {
1261
if (socket_type != 0 && ai->ai_socktype == 0)
1262
/* Is this check actually needed? */
1263
ai->ai_socktype = socket_type;
1264
switch (ai->ai_family) {
1266
((struct sockaddr_in *)ai->ai_addr)->sin_port = service_port;
1269
((struct sockaddr_in6 *)ai->ai_addr)->sin6_port = service_port;
1277
for (ai = *result; ai; ai = ai->ai_next) {
1278
/* AIX 4.3.3 libc is broken. It doesn't set the family or len
1279
fields of the sockaddr structures. Usually, sa_family is
1280
zero, but I've seen it set to 1 in some cases also (maybe
1281
just leftover from previous contents of the memory
1282
block?). So, always override what libc returned. */
1283
ai->ai_addr->sa_family = ai->ai_family;
1284
#ifdef HAVE_SA_LEN /* always true on AIX, actually */
1285
ai->ai_addr->sa_len = ai->ai_addrlen;
1290
/* Not dealt with currently:
1292
- Some versions of GNU libc can lose some IPv4 addresses in
1293
certain cases when multiple IPv4 and IPv6 addresses are
1296
#ifdef DEBUG_ADDRINFO
1297
debug_dump_addrinfos(*result);
1304
void freeaddrinfo (struct addrinfo *ai)
1306
#ifdef COPY_FIRST_CANONNAME
1308
free(ai->ai_canonname);
1309
ai->ai_canonname = 0;
1310
system_freeaddrinfo(ai);
1313
system_freeaddrinfo(ai);
1316
#endif /* WRAP_GETADDRINFO */
1318
static int krb5int_lock_fac (void)
61
1321
err = krb5int_call_thread_support_init();