Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/krb5/src/util/support/fake-addrinfo.c
34889 views
1
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
/*
3
* Copyright (C) 2001,2002,2003,2004,2005,2006 by the Massachusetts Institute of Technology,
4
* Cambridge, MA, USA. All Rights Reserved.
5
*
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
10
* conditions:
11
*
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.
16
*
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
23
* distribution:
24
*
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.
31
*
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
36
* preserve same.
37
*
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.
41
*/
42
43
/*
44
* Approach overview:
45
*
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.
50
*
51
* If no system version exists, use gethostby* and fake it. Define
52
* the data structures and flag values locally.
53
*
54
*
55
* On macOS, 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.
61
*
62
*
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
68
* gethostby* calls.
69
*
70
* We're taking a simpler approach: A system provides these routines or
71
* it does not.
72
*
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
76
* come to it.
77
*/
78
79
/*
80
* To do, maybe:
81
*
82
* + For AIX 4.3.3, using the RFC 2133 definition: Implement
83
* AI_NUMERICHOST. It's not defined in the header file.
84
*
85
* For certain (old?) versions of GNU libc, AI_NUMERICHOST is
86
* defined but not implemented.
87
*
88
* + Use gethostbyname2, inet_aton and other IPv6 or thread-safe
89
* functions if available. But, see
90
* https://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
93
* by now.
94
*
95
* + inet_ntop, inet_pton
96
*
97
* + Conditionally export/import the function definitions, so a
98
* library can have a single copy instead of multiple.
99
*
100
* + Upgrade host requirements to include working implementations of
101
* these functions, and throw all this away. Pleeease? :-)
102
*/
103
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"
109
110
#define IMPLEMENT_FAKE_GETADDRINFO
111
#include "fake-addrinfo.h"
112
113
#ifdef S_SPLINT_S
114
/*@-incondefs@*/
115
extern int
116
getaddrinfo (/*@in@*/ /*@null@*/ const char *,
117
/*@in@*/ /*@null@*/ const char *,
118
/*@in@*/ /*@null@*/ const struct addrinfo *,
119
/*@out@*/ struct addrinfo **)
120
;
121
extern void
122
freeaddrinfo (/*@only@*/ /*@out@*/ struct addrinfo *)
123
;
124
extern int
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,
128
int flags)
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) /*@*/;
133
/*@=incondefs@*/
134
#endif
135
136
137
#include "cache-addrinfo.h"
138
139
#if (defined (__linux__) && defined(HAVE_GETADDRINFO)) || defined (_AIX)
140
/* See comments below. */
141
# define WRAP_GETADDRINFO
142
#endif
143
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
150
# endif
151
# else
152
# define COPY_FIRST_CANONNAME
153
# endif
154
#endif
155
156
#ifdef _AIX
157
# define NUMERIC_SERVICE_BROKEN
158
# define COPY_FIRST_CANONNAME
159
#endif
160
161
162
#ifdef COPY_FIRST_CANONNAME
163
# include <string.h>
164
#endif
165
166
#ifdef NUMERIC_SERVICE_BROKEN
167
# include <ctype.h> /* isdigit */
168
# include <stdlib.h> /* strtoul */
169
#endif
170
171
172
/* Do we actually have *any* systems we care about that don't provide
173
either getaddrinfo or one of these two flavors of
174
gethostbyname_r? */
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; }
181
#else
182
#ifdef _AIX /* XXX should have a feature test! */
183
typedef struct {
184
struct hostent ent;
185
struct hostent_data data;
186
} GET_HOST_TMP;
187
#define GET_HOST_BY_NAME(NAME, HP, ERR, TMP) \
188
{ \
189
(HP) = (gethostbyname_r((NAME), &TMP.ent, &TMP.data) \
190
? 0 \
191
: &TMP.ent); \
192
(ERR) = h_errno; \
193
}
194
/*
195
#define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR) \
196
{ \
197
struct hostent my_h_ent; \
198
struct hostent_data my_h_ent_data; \
199
(HP) = (gethostbyaddr_r((ADDR), (ADDRLEN), (FAMILY), &my_h_ent, \
200
&my_h_ent_data) \
201
? 0 \
202
: &my_h_ent); \
203
(ERR) = my_h_err; \
204
}
205
*/
206
#else
207
#ifdef GETHOSTBYNAME_R_RETURNS_INT
208
typedef struct {
209
struct hostent ent;
210
char buf[8192];
211
} GET_HOST_TMP;
212
#define GET_HOST_BY_NAME(NAME, HP, ERR, TMP) \
213
{ \
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, \
218
&my_h_err); \
219
(HP) = (((my_ret != 0) || (my_hp != &TMP.ent)) \
220
? 0 \
221
: &TMP.ent); \
222
(ERR) = my_h_err; \
223
}
224
#define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR, TMP) \
225
{ \
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, \
230
&my_h_err); \
231
(HP) = (((my_ret != 0) || (my_hp != &TMP.ent)) \
232
? 0 \
233
: &TMP.ent); \
234
(ERR) = my_h_err; \
235
}
236
#else
237
typedef struct {
238
struct hostent ent;
239
char buf[8192];
240
} GET_HOST_TMP;
241
#define GET_HOST_BY_NAME(NAME, HP, ERR, TMP) \
242
{ \
243
int my_h_err; \
244
(HP) = gethostbyname_r((NAME), &TMP.ent, \
245
TMP.buf, sizeof (TMP.buf), &my_h_err); \
246
(ERR) = my_h_err; \
247
}
248
#define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR, TMP) \
249
{ \
250
int my_h_err; \
251
(HP) = gethostbyaddr_r((ADDR), (ADDRLEN), (FAMILY), &TMP.ent, \
252
TMP.buf, sizeof (TMP.buf), &my_h_err); \
253
(ERR) = my_h_err; \
254
}
255
#endif /* returns int? */
256
#endif /* _AIX */
257
#endif
258
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)
266
#else
267
#ifdef GETSERVBYNAME_R_RETURNS_INT
268
typedef struct {
269
struct servent ent;
270
char buf[8192];
271
} GET_SERV_TMP;
272
#define GET_SERV_BY_NAME(NAME, PROTO, SP, ERR, TMP) \
273
{ \
274
struct servent *my_sp; \
275
int my_s_err; \
276
(SP) = (getservbyname_r((NAME), (PROTO), &TMP.ent, \
277
TMP.buf, sizeof (TMP.buf), &my_sp, \
278
&my_s_err) \
279
? 0 \
280
: &TMP.ent); \
281
(ERR) = my_s_err; \
282
}
283
#define GET_SERV_BY_PORT(PORT, PROTO, SP, ERR, TMP) \
284
{ \
285
struct servent *my_sp; \
286
int my_s_err; \
287
(SP) = (getservbyport_r((PORT), (PROTO), &TMP.ent, \
288
TMP.buf, sizeof (TMP.buf), &my_sp, \
289
&my_s_err) \
290
? 0 \
291
: &TMP.ent); \
292
(ERR) = my_s_err; \
293
}
294
#else
295
/* returns ptr -- IRIX? */
296
typedef struct {
297
struct servent ent;
298
char buf[8192];
299
} GET_SERV_TMP;
300
#define GET_SERV_BY_NAME(NAME, PROTO, SP, ERR, TMP) \
301
{ \
302
(SP) = getservbyname_r((NAME), (PROTO), &TMP.ent, \
303
TMP.buf, sizeof (TMP.buf)); \
304
(ERR) = (SP) == NULL; \
305
}
306
307
#define GET_SERV_BY_PORT(PORT, PROTO, SP, ERR, TMP) \
308
{ \
309
struct servent *my_sp; \
310
my_sp = getservbyport_r((PORT), (PROTO), &TMP.ent, \
311
TMP.buf, sizeof (TMP.buf)); \
312
(SP) = my_sp; \
313
(ERR) = my_sp == 0; \
314
(ERR) = (ERR); /* avoid "unused" warning */ \
315
}
316
#endif
317
#endif
318
319
#if defined(WRAP_GETADDRINFO) || defined(FAI_CACHE)
320
static inline int
321
system_getaddrinfo (const char *name, const char *serv,
322
const struct addrinfo *hint,
323
struct addrinfo **res)
324
{
325
return getaddrinfo(name, serv, hint, res);
326
}
327
328
static inline void
329
system_freeaddrinfo (struct addrinfo *ai)
330
{
331
freeaddrinfo(ai);
332
}
333
334
#endif
335
336
#if !defined (HAVE_GETADDRINFO) || defined(WRAP_GETADDRINFO) || defined(FAI_CACHE)
337
338
#undef getaddrinfo
339
#define getaddrinfo my_fake_getaddrinfo
340
#undef freeaddrinfo
341
#define freeaddrinfo my_fake_freeaddrinfo
342
343
#endif
344
345
#if !defined (HAVE_GETADDRINFO)
346
347
#undef gai_strerror
348
#define gai_strerror my_fake_gai_strerror
349
350
#endif /* ! HAVE_GETADDRINFO */
351
352
#if (!defined (HAVE_GETADDRINFO) || defined (WRAP_GETADDRINFO)) && defined(DEBUG_ADDRINFO)
353
/* Some debug routines. */
354
355
static const char *protoname (int p, char *buf, size_t bufsize) {
356
#define X(N) if (p == IPPROTO_ ## N) return #N
357
358
X(TCP);
359
X(UDP);
360
X(ICMP);
361
X(IPV6);
362
#ifdef IPPROTO_GRE
363
X(GRE);
364
#endif
365
X(NONE);
366
X(RAW);
367
#ifdef IPPROTO_COMP
368
X(COMP);
369
#endif
370
#ifdef IPPROTO_IGMP
371
X(IGMP);
372
#endif
373
374
snprintf(buf, bufsize, " %-2d", p);
375
return buf;
376
}
377
378
static const char *socktypename (int t, char *buf, size_t bufsize) {
379
switch (t) {
380
case SOCK_DGRAM: return "DGRAM";
381
case SOCK_STREAM: return "STREAM";
382
case SOCK_RAW: return "RAW";
383
case SOCK_RDM: return "RDM";
384
case SOCK_SEQPACKET: return "SEQPACKET";
385
}
386
snprintf(buf, bufsize, " %-2d", t);
387
return buf;
388
}
389
390
static const char *familyname (int f, char *buf, size_t bufsize) {
391
switch (f) {
392
default:
393
snprintf(buf, bufsize, "AF %d", f);
394
return buf;
395
case AF_INET: return "AF_INET";
396
case AF_INET6: return "AF_INET6";
397
#ifdef AF_UNIX
398
case AF_UNIX: return "AF_UNIX";
399
#endif
400
}
401
}
402
403
static void debug_dump_getaddrinfo_args (const char *name, const char *serv,
404
const struct addrinfo *hint)
405
{
406
const char *sep;
407
fprintf(stderr,
408
"getaddrinfo(hostname %s, service %s,\n"
409
" hints { ",
410
name ? name : "(null)", serv ? serv : "(null)");
411
if (hint) {
412
char buf[30];
413
sep = "";
414
#define Z(FLAG) if (hint->ai_flags & AI_##FLAG) fprintf(stderr, "%s%s", sep, #FLAG), sep = "|"
415
Z(CANONNAME);
416
Z(PASSIVE);
417
#ifdef AI_NUMERICHOST
418
Z(NUMERICHOST);
419
#endif
420
if (sep[0] == 0)
421
fprintf(stderr, "no-flags");
422
if (hint->ai_family)
423
fprintf(stderr, " %s", familyname(hint->ai_family, buf,
424
sizeof(buf)));
425
if (hint->ai_socktype)
426
fprintf(stderr, " SOCK_%s", socktypename(hint->ai_socktype, buf,
427
sizeof(buf)));
428
if (hint->ai_protocol)
429
fprintf(stderr, " IPPROTO_%s", protoname(hint->ai_protocol, buf,
430
sizeof(buf)));
431
} else
432
fprintf(stderr, "(null)");
433
fprintf(stderr, " }):\n");
434
}
435
436
static void debug_dump_error (int err)
437
{
438
fprintf(stderr, "error %d: %s\n", err, gai_strerror(err));
439
}
440
441
static void debug_dump_addrinfos (const struct addrinfo *ai)
442
{
443
int count = 0;
444
char buf[10];
445
fprintf(stderr, "addrinfos returned:\n");
446
while (ai) {
447
fprintf(stderr, "%p...", ai);
448
fprintf(stderr, " socktype=%s", socktypename(ai->ai_socktype, buf,
449
sizeof(buf)));
450
fprintf(stderr, " ai_family=%s", familyname(ai->ai_family, buf,
451
sizeof(buf)));
452
if (ai->ai_family != ai->ai_addr->sa_family)
453
fprintf(stderr, " sa_family=%s",
454
familyname(ai->ai_addr->sa_family, buf, sizeof(buf)));
455
fprintf(stderr, "\n");
456
ai = ai->ai_next;
457
count++;
458
}
459
fprintf(stderr, "end addrinfos returned (%d)\n");
460
}
461
462
#endif
463
464
#if !defined (HAVE_GETADDRINFO) || defined (WRAP_GETADDRINFO)
465
466
static
467
int getaddrinfo (const char *name, const char *serv,
468
const struct addrinfo *hint, struct addrinfo **result);
469
470
static
471
void freeaddrinfo (struct addrinfo *ai);
472
473
#endif
474
475
#if !defined (HAVE_GETADDRINFO)
476
477
#define HAVE_FAKE_GETADDRINFO /* was not originally HAVE_GETADDRINFO */
478
#define HAVE_GETADDRINFO
479
#define NEED_FAKE_GETNAMEINFO
480
#undef HAVE_GETNAMEINFO
481
#define HAVE_GETNAMEINFO 1
482
483
#undef getnameinfo
484
#define getnameinfo my_fake_getnameinfo
485
486
static
487
char *gai_strerror (int code);
488
489
#endif
490
491
#if !defined (HAVE_GETADDRINFO)
492
static
493
int getnameinfo (const struct sockaddr *addr, socklen_t len,
494
char *host, socklen_t hostlen,
495
char *service, socklen_t servicelen,
496
int flags);
497
#endif
498
499
/* Fudge things on older gai implementations. */
500
/* AIX 4.3.3 is based on RFC 2133; no AI_NUMERICHOST. */
501
#ifndef AI_NUMERICHOST
502
# define AI_NUMERICHOST 0
503
#endif
504
/* Partial RFC 2553 implementations may not have AI_ADDRCONFIG and
505
friends, which RFC 3493 says are now part of the getaddrinfo
506
interface, and we'll want to use. */
507
#ifndef AI_ADDRCONFIG
508
# define AI_ADDRCONFIG 0
509
#endif
510
#ifndef AI_V4MAPPED
511
# define AI_V4MAPPED 0
512
#endif
513
#ifndef AI_ALL
514
# define AI_ALL 0
515
#endif
516
#ifndef AI_DEFAULT
517
# define AI_DEFAULT (AI_ADDRCONFIG|AI_V4MAPPED)
518
#endif
519
520
#if defined(HAVE_FAKE_GETADDRINFO) || defined(FAI_CACHE)
521
#define NEED_FAKE_GETADDRINFO
522
#endif
523
524
#if defined(NEED_FAKE_GETADDRINFO) || defined(WRAP_GETADDRINFO)
525
#include <stdlib.h>
526
#endif
527
528
#ifdef NEED_FAKE_GETADDRINFO
529
#include <string.h> /* for strspn */
530
531
static inline int translate_h_errno (int h);
532
533
static inline int fai_add_entry (struct addrinfo **result, void *addr,
534
int port, const struct addrinfo *template)
535
{
536
struct addrinfo *n = malloc (sizeof (struct addrinfo));
537
if (n == 0)
538
return EAI_MEMORY;
539
if (template->ai_family != AF_INET
540
&& template->ai_family != AF_INET6
541
)
542
return EAI_FAMILY;
543
*n = *template;
544
if (template->ai_family == AF_INET) {
545
struct sockaddr_in *sin4;
546
sin4 = malloc (sizeof (struct sockaddr_in));
547
if (sin4 == 0)
548
return EAI_MEMORY;
549
memset (sin4, 0, sizeof (struct sockaddr_in)); /* for sin_zero */
550
n->ai_addr = (struct sockaddr *) sin4;
551
sin4->sin_family = AF_INET;
552
sin4->sin_addr = *(struct in_addr *)addr;
553
sin4->sin_port = port;
554
}
555
if (template->ai_family == AF_INET6) {
556
struct sockaddr_in6 *sin6;
557
sin6 = malloc (sizeof (struct sockaddr_in6));
558
if (sin6 == 0)
559
return EAI_MEMORY;
560
memset (sin6, 0, sizeof (struct sockaddr_in6)); /* for sin_zero */
561
n->ai_addr = (struct sockaddr *) sin6;
562
sin6->sin6_family = AF_INET6;
563
sin6->sin6_addr = *(struct in6_addr *)addr;
564
sin6->sin6_port = port;
565
}
566
n->ai_next = *result;
567
*result = n;
568
return 0;
569
}
570
571
#ifdef FAI_CACHE
572
/* fake addrinfo cache entries */
573
#define CACHE_ENTRY_LIFETIME 15 /* seconds */
574
575
static void plant_face (const char *name, struct face *entry)
576
{
577
entry->name = strdup(name);
578
if (entry->name == NULL)
579
/* @@ Wastes memory. */
580
return;
581
k5_mutex_assert_locked(&krb5int_fac.lock);
582
entry->next = krb5int_fac.data;
583
entry->expiration = time(0) + CACHE_ENTRY_LIFETIME;
584
krb5int_fac.data = entry;
585
#ifdef DEBUG_ADDRINFO
586
printf("added cache entry '%s' at %p: %d ipv4, %d ipv6; expire %d\n",
587
name, entry, entry->naddrs4, entry->naddrs6, entry->expiration);
588
#endif
589
}
590
591
static int find_face (const char *name, struct face **entry)
592
{
593
struct face *fp, **fpp;
594
time_t now = time(0);
595
596
/* First, scan for expired entries and free them.
597
(Future improvement: Integrate these two loops.) */
598
#ifdef DEBUG_ADDRINFO
599
printf("scanning cache at %d for '%s'...\n", now, name);
600
#endif
601
k5_mutex_assert_locked(&krb5int_fac.lock);
602
for (fpp = &krb5int_fac.data; *fpp; ) {
603
fp = *fpp;
604
#ifdef DEBUG_ADDRINFO
605
printf(" checking expiration time of @%p: %d\n",
606
fp, fp->expiration);
607
#endif
608
if (fp->expiration < now) {
609
#ifdef DEBUG_ADDRINFO
610
printf("\texpiring cache entry\n");
611
#endif
612
free(fp->name);
613
free(fp->canonname);
614
free(fp->addrs4);
615
free(fp->addrs6);
616
*fpp = fp->next;
617
free(fp);
618
/* Stay at this point in the list, and check again. */
619
} else
620
/* Move forward. */
621
fpp = &(*fpp)->next;
622
}
623
624
for (fp = krb5int_fac.data; fp; fp = fp->next) {
625
#ifdef DEBUG_ADDRINFO
626
printf(" comparing entry @%p\n", fp);
627
#endif
628
if (!strcasecmp(fp->name, name)) {
629
#ifdef DEBUG_ADDRINFO
630
printf("\tMATCH!\n");
631
#endif
632
*entry = fp;
633
return 1;
634
}
635
}
636
return 0;
637
}
638
639
#endif
640
641
#ifdef FAI_CACHE
642
static int krb5int_lock_fac(void), krb5int_unlock_fac(void);
643
#endif
644
645
static inline int fai_add_hosts_by_name (const char *name,
646
struct addrinfo *template,
647
int portnum, int flags,
648
struct addrinfo **result)
649
{
650
#ifdef FAI_CACHE
651
652
struct face *ce;
653
int i, r, err;
654
655
err = krb5int_lock_fac();
656
if (err) {
657
errno = err;
658
return EAI_SYSTEM;
659
}
660
if (!find_face(name, &ce)) {
661
struct addrinfo myhints = { 0 }, *ai, *ai2;
662
int i4, i6, aierr;
663
664
#ifdef DEBUG_ADDRINFO
665
printf("looking up new data for '%s'...\n", name);
666
#endif
667
myhints.ai_socktype = SOCK_STREAM;
668
myhints.ai_flags = AI_CANONNAME;
669
/* Don't set ai_family -- we want to cache all address types,
670
because the next lookup may not use the same constraints as
671
the current one. We *could* cache them separately, so that
672
we never have to look up an IPv6 address if we are always
673
asked for IPv4 only, but let's deal with that later, if we
674
have to. */
675
/* Try NULL for the service for now.
676
677
It would be nice to use the requested service name, and not
678
have to patch things up, but then we'd be doing multiple
679
queries for the same host when we get different services.
680
We were using "telnet" for a little more confidence that
681
getaddrinfo would heed the hints to only give us stream
682
socket types (with no socket type and null service name, we
683
might get stream *and* dgram *and* raw, for each address,
684
or only raw). The RFC 3493 description of ai_socktype
685
sometimes associates it with the specified service,
686
sometimes not.
687
688
But on macOS (10.3, 10.4) they've "extended" getaddrinfo
689
to make SRV RR queries. (Please, somebody, show me
690
something in the specs that actually supports this? RFC
691
3493 says nothing about it, but it does say getaddrinfo is
692
the new way to look up hostnames. RFC 2782 says SRV
693
records should *not* be used unless the application
694
protocol spec says to do so. The Telnet spec does not say
695
to do it.) And then they complain when our code
696
"unexpectedly" seems to use this "extension" in cases where
697
they don't want it to be used.
698
699
Fortunately, it appears that if we specify ai_socktype as
700
SOCK_STREAM and use a null service name, we only get one
701
copy of each address on all the platforms I've tried,
702
although it may not have ai_socktype filled in properly.
703
So, we'll fudge it with that for now. */
704
aierr = system_getaddrinfo(name, NULL, &myhints, &ai);
705
if (aierr) {
706
krb5int_unlock_fac();
707
return aierr;
708
}
709
ce = malloc(sizeof(struct face));
710
memset(ce, 0, sizeof(*ce));
711
ce->expiration = time(0) + 30;
712
for (ai2 = ai; ai2; ai2 = ai2->ai_next) {
713
#ifdef DEBUG_ADDRINFO
714
printf(" found an address in family %d...\n", ai2->ai_family);
715
#endif
716
switch (ai2->ai_family) {
717
case AF_INET:
718
ce->naddrs4++;
719
break;
720
case AF_INET6:
721
ce->naddrs6++;
722
break;
723
default:
724
break;
725
}
726
}
727
ce->addrs4 = calloc(ce->naddrs4, sizeof(*ce->addrs4));
728
if (ce->addrs4 == NULL && ce->naddrs4 != 0) {
729
krb5int_unlock_fac();
730
system_freeaddrinfo(ai);
731
return EAI_MEMORY;
732
}
733
ce->addrs6 = calloc(ce->naddrs6, sizeof(*ce->addrs6));
734
if (ce->addrs6 == NULL && ce->naddrs6 != 0) {
735
krb5int_unlock_fac();
736
free(ce->addrs4);
737
system_freeaddrinfo(ai);
738
return EAI_MEMORY;
739
}
740
for (ai2 = ai, i4 = i6 = 0; ai2; ai2 = ai2->ai_next) {
741
switch (ai2->ai_family) {
742
case AF_INET:
743
ce->addrs4[i4++] = ((struct sockaddr_in *)ai2->ai_addr)->sin_addr;
744
break;
745
case AF_INET6:
746
ce->addrs6[i6++] = ((struct sockaddr_in6 *)ai2->ai_addr)->sin6_addr;
747
break;
748
default:
749
break;
750
}
751
}
752
ce->canonname = ai->ai_canonname ? strdup(ai->ai_canonname) : 0;
753
system_freeaddrinfo(ai);
754
plant_face(name, ce);
755
}
756
template->ai_family = AF_INET6;
757
template->ai_addrlen = sizeof(struct sockaddr_in6);
758
for (i = 0; i < ce->naddrs6; i++) {
759
r = fai_add_entry (result, &ce->addrs6[i], portnum, template);
760
if (r) {
761
krb5int_unlock_fac();
762
return r;
763
}
764
}
765
template->ai_family = AF_INET;
766
template->ai_addrlen = sizeof(struct sockaddr_in);
767
for (i = 0; i < ce->naddrs4; i++) {
768
r = fai_add_entry (result, &ce->addrs4[i], portnum, template);
769
if (r) {
770
krb5int_unlock_fac();
771
return r;
772
}
773
}
774
if (*result && (flags & AI_CANONNAME))
775
(*result)->ai_canonname = (ce->canonname
776
? strdup(ce->canonname)
777
: NULL);
778
krb5int_unlock_fac();
779
return 0;
780
781
#else
782
783
struct hostent *hp;
784
int i, r;
785
int herr;
786
GET_HOST_TMP htmp;
787
788
GET_HOST_BY_NAME (name, hp, herr, htmp);
789
if (hp == 0)
790
return translate_h_errno (herr);
791
for (i = 0; hp->h_addr_list[i]; i++) {
792
r = fai_add_entry (result, hp->h_addr_list[i], portnum, template);
793
if (r)
794
return r;
795
}
796
if (*result && (flags & AI_CANONNAME))
797
(*result)->ai_canonname = strdup (hp->h_name);
798
return 0;
799
800
#endif
801
}
802
803
static inline void
804
fake_freeaddrinfo (struct addrinfo *ai)
805
{
806
struct addrinfo *next;
807
while (ai) {
808
next = ai->ai_next;
809
if (ai->ai_canonname)
810
free (ai->ai_canonname);
811
if (ai->ai_addr)
812
free (ai->ai_addr);
813
free (ai);
814
ai = next;
815
}
816
}
817
818
static inline int
819
fake_getaddrinfo (const char *name, const char *serv,
820
const struct addrinfo *hint, struct addrinfo **result)
821
{
822
struct addrinfo *res = 0;
823
int ret;
824
int port = 0, socktype;
825
int flags;
826
struct addrinfo template;
827
828
#ifdef DEBUG_ADDRINFO
829
debug_dump_getaddrinfo_args(name, serv, hint);
830
#endif
831
832
if (hint != 0) {
833
if (hint->ai_family != 0 && hint->ai_family != AF_INET)
834
return EAI_NODATA;
835
socktype = hint->ai_socktype;
836
flags = hint->ai_flags;
837
} else {
838
socktype = 0;
839
flags = 0;
840
}
841
842
if (serv) {
843
size_t numlen = strspn (serv, "0123456789");
844
if (serv[numlen] == '\0') {
845
/* pure numeric */
846
unsigned long p = strtoul (serv, 0, 10);
847
if (p == 0 || p > 65535)
848
return EAI_NONAME;
849
port = htons (p);
850
} else {
851
struct servent *sp;
852
int try_dgram_too = 0, s_err;
853
GET_SERV_TMP stmp;
854
855
if (socktype == 0) {
856
try_dgram_too = 1;
857
socktype = SOCK_STREAM;
858
}
859
try_service_lookup:
860
GET_SERV_BY_NAME(serv, socktype == SOCK_STREAM ? "tcp" : "udp",
861
sp, s_err, stmp);
862
if (sp == 0) {
863
if (try_dgram_too) {
864
socktype = SOCK_DGRAM;
865
goto try_service_lookup;
866
}
867
return EAI_SERVICE;
868
}
869
port = sp->s_port;
870
}
871
}
872
873
if (name == 0) {
874
name = (flags & AI_PASSIVE) ? "0.0.0.0" : "127.0.0.1";
875
flags |= AI_NUMERICHOST;
876
}
877
878
template.ai_family = AF_INET;
879
template.ai_addrlen = sizeof (struct sockaddr_in);
880
template.ai_socktype = socktype;
881
template.ai_protocol = 0;
882
template.ai_flags = 0;
883
template.ai_canonname = 0;
884
template.ai_next = 0;
885
template.ai_addr = 0;
886
887
/* If NUMERICHOST is set, parse a numeric address.
888
If it's not set, don't accept such names. */
889
if (flags & AI_NUMERICHOST) {
890
struct in_addr addr4;
891
addr4.s_addr = inet_addr (name);
892
if (addr4.s_addr == 0xffffffff || addr4.s_addr == -1)
893
/* 255.255.255.255 or parse error, both bad */
894
return EAI_NONAME;
895
ret = fai_add_entry (&res, &addr4, port, &template);
896
} else {
897
ret = fai_add_hosts_by_name (name, &template, port, flags,
898
&res);
899
}
900
901
if (ret && ret != NO_ADDRESS) {
902
fake_freeaddrinfo (res);
903
return ret;
904
}
905
if (res == 0)
906
return NO_ADDRESS;
907
*result = res;
908
return 0;
909
}
910
911
#ifdef NEED_FAKE_GETNAMEINFO
912
static inline int
913
fake_getnameinfo (const struct sockaddr *sa, socklen_t len,
914
char *host, socklen_t hostlen,
915
char *service, socklen_t servicelen,
916
int flags)
917
{
918
struct hostent *hp;
919
const struct sockaddr_in *sinp;
920
struct servent *sp;
921
size_t hlen, slen;
922
923
if (sa->sa_family != AF_INET) {
924
return EAI_FAMILY;
925
}
926
sinp = (const struct sockaddr_in *) sa;
927
928
hlen = hostlen;
929
if (hostlen < 0 || hlen != hostlen) {
930
errno = EINVAL;
931
return EAI_SYSTEM;
932
}
933
slen = servicelen;
934
if (servicelen < 0 || slen != servicelen) {
935
errno = EINVAL;
936
return EAI_SYSTEM;
937
}
938
939
if (host) {
940
if (flags & NI_NUMERICHOST) {
941
#if (defined(__GNUC__) && defined(__mips__)) || 1 /* thread safety always */
942
/* The inet_ntoa call, passing a struct, fails on IRIX 6.5
943
using gcc 2.95; we get back "0.0.0.0". Since this in a
944
configuration still important at Athena, here's the
945
workaround, which also happens to be thread-safe.... */
946
const unsigned char *uc;
947
char tmpbuf[20];
948
numeric_host:
949
uc = (const unsigned char *) &sinp->sin_addr;
950
snprintf(tmpbuf, sizeof(tmpbuf), "%d.%d.%d.%d",
951
uc[0], uc[1], uc[2], uc[3]);
952
strncpy(host, tmpbuf, hlen);
953
#else
954
char *p;
955
numeric_host:
956
p = inet_ntoa (sinp->sin_addr);
957
strncpy (host, p, hlen);
958
#endif
959
} else {
960
int herr;
961
GET_HOST_TMP htmp;
962
963
GET_HOST_BY_ADDR((const char *) &sinp->sin_addr,
964
sizeof (struct in_addr),
965
sa->sa_family, hp, herr, htmp);
966
if (hp == 0) {
967
if (herr == NO_ADDRESS && !(flags & NI_NAMEREQD)) /* ??? */
968
goto numeric_host;
969
return translate_h_errno (herr);
970
}
971
/* According to the Open Group spec, getnameinfo can
972
silently truncate, but must still return a
973
null-terminated string. */
974
strncpy (host, hp->h_name, hlen);
975
}
976
host[hostlen-1] = 0;
977
}
978
979
if (service) {
980
if (flags & NI_NUMERICSERV) {
981
char numbuf[10];
982
int port;
983
numeric_service:
984
port = ntohs (sinp->sin_port);
985
if (port < 0 || port > 65535)
986
return EAI_FAIL;
987
snprintf (numbuf, sizeof(numbuf), "%d", port);
988
strncpy (service, numbuf, slen);
989
} else {
990
int serr;
991
GET_SERV_TMP stmp;
992
993
GET_SERV_BY_PORT(sinp->sin_port,
994
(flags & NI_DGRAM) ? "udp" : "tcp",
995
sp, serr, stmp);
996
if (sp == 0)
997
goto numeric_service;
998
strncpy (service, sp->s_name, slen);
999
}
1000
service[servicelen-1] = 0;
1001
}
1002
1003
return 0;
1004
}
1005
#endif
1006
1007
#if defined(HAVE_FAKE_GETADDRINFO) || defined(NEED_FAKE_GETNAMEINFO)
1008
1009
static inline
1010
char *gai_strerror (int code)
1011
{
1012
switch (code) {
1013
case EAI_ADDRFAMILY: return "address family for nodename not supported";
1014
case EAI_AGAIN: return "temporary failure in name resolution";
1015
case EAI_BADFLAGS: return "bad flags to getaddrinfo/getnameinfo";
1016
case EAI_FAIL: return "non-recoverable failure in name resolution";
1017
case EAI_FAMILY: return "ai_family not supported";
1018
case EAI_MEMORY: return "out of memory";
1019
case EAI_NODATA: return "no address associated with hostname";
1020
case EAI_NONAME: return "name does not exist";
1021
case EAI_SERVICE: return "service name not supported for specified socket type";
1022
case EAI_SOCKTYPE: return "ai_socktype not supported";
1023
case EAI_SYSTEM: return strerror (errno);
1024
default: return "bogus getaddrinfo error?";
1025
}
1026
}
1027
#endif
1028
1029
static inline int translate_h_errno (int h)
1030
{
1031
switch (h) {
1032
case 0:
1033
return 0;
1034
#ifdef NETDB_INTERNAL
1035
case NETDB_INTERNAL:
1036
if (errno == ENOMEM)
1037
return EAI_MEMORY;
1038
return EAI_SYSTEM;
1039
#endif
1040
case HOST_NOT_FOUND:
1041
return EAI_NONAME;
1042
case TRY_AGAIN:
1043
return EAI_AGAIN;
1044
case NO_RECOVERY:
1045
return EAI_FAIL;
1046
case NO_DATA:
1047
#if NO_DATA != NO_ADDRESS
1048
case NO_ADDRESS:
1049
#endif
1050
return EAI_NODATA;
1051
default:
1052
return EAI_SYSTEM;
1053
}
1054
}
1055
1056
#if defined(HAVE_FAKE_GETADDRINFO) || defined(FAI_CACHE)
1057
static inline
1058
int getaddrinfo (const char *name, const char *serv,
1059
const struct addrinfo *hint, struct addrinfo **result)
1060
{
1061
return fake_getaddrinfo(name, serv, hint, result);
1062
}
1063
1064
static inline
1065
void freeaddrinfo (struct addrinfo *ai)
1066
{
1067
fake_freeaddrinfo(ai);
1068
}
1069
1070
#ifdef NEED_FAKE_GETNAMEINFO
1071
static inline
1072
int getnameinfo (const struct sockaddr *sa, socklen_t len,
1073
char *host, socklen_t hostlen,
1074
char *service, socklen_t servicelen,
1075
int flags)
1076
{
1077
return fake_getnameinfo(sa, len, host, hostlen, service, servicelen,
1078
flags);
1079
}
1080
#endif /* NEED_FAKE_GETNAMEINFO */
1081
#endif /* HAVE_FAKE_GETADDRINFO */
1082
#endif /* NEED_FAKE_GETADDRINFO */
1083
1084
1085
#ifdef WRAP_GETADDRINFO
1086
1087
static inline
1088
int
1089
getaddrinfo (const char *name, const char *serv, const struct addrinfo *hint,
1090
struct addrinfo **result)
1091
{
1092
int aierr;
1093
#if defined(_AIX) || defined(COPY_FIRST_CANONNAME)
1094
struct addrinfo *ai;
1095
#endif
1096
#ifdef NUMERIC_SERVICE_BROKEN
1097
int service_is_numeric = 0;
1098
int service_port = 0;
1099
int socket_type = 0;
1100
#endif
1101
1102
#ifdef DEBUG_ADDRINFO
1103
debug_dump_getaddrinfo_args(name, serv, hint);
1104
#endif
1105
1106
#ifdef NUMERIC_SERVICE_BROKEN
1107
/* AIX 4.3.3 is broken. (Or perhaps out of date?)
1108
1109
If a numeric service is provided, and it doesn't correspond to
1110
a known service name for tcp or udp (as appropriate), an error
1111
code (for "host not found") is returned. If the port maps to a
1112
known service for both udp and tcp, all is well. */
1113
if (serv && serv[0] && isdigit(serv[0])) {
1114
unsigned long lport;
1115
char *end;
1116
lport = strtoul(serv, &end, 10);
1117
if (!*end) {
1118
if (lport > 65535)
1119
return EAI_SOCKTYPE;
1120
service_is_numeric = 1;
1121
service_port = lport;
1122
#ifdef AI_NUMERICSERV
1123
if (hint && hint->ai_flags & AI_NUMERICSERV)
1124
serv = "9";
1125
else
1126
#endif
1127
serv = "discard"; /* defined for both udp and tcp */
1128
if (hint)
1129
socket_type = hint->ai_socktype;
1130
}
1131
}
1132
#endif
1133
1134
aierr = system_getaddrinfo (name, serv, hint, result);
1135
if (aierr || *result == 0) {
1136
#ifdef DEBUG_ADDRINFO
1137
debug_dump_error(aierr);
1138
#endif
1139
return aierr;
1140
}
1141
1142
/* Linux libc version 6 prior to 2.3.4 is broken.
1143
1144
RFC 2553 says that when AI_CANONNAME is set, the ai_canonname
1145
flag of the first returned structure has the canonical name of
1146
the host. Instead, GNU libc sets ai_canonname in each returned
1147
structure to the name that the corresponding address maps to,
1148
if any, or a printable numeric form.
1149
1150
RFC 2553 bis and the new Open Group spec say that field will be
1151
the canonical name if it can be determined, otherwise, the
1152
provided hostname or a copy of it.
1153
1154
IMNSHO, "canonical name" means CNAME processing and not PTR
1155
processing, but I can see arguing it. Using the numeric form
1156
when that's not the form provided is just wrong. So, let's fix
1157
it.
1158
1159
The glibc 2.2.5 sources indicate that the canonical name is
1160
*not* allocated separately, it's just some extra storage tacked
1161
on the end of the addrinfo structure. So, let's try this
1162
approach: If getaddrinfo sets ai_canonname, we'll replace the
1163
*first* one with allocated storage, and free up that pointer in
1164
freeaddrinfo if it's set; the other ai_canonname fields will be
1165
left untouched. And we'll just pray that the application code
1166
won't mess around with the list structure; if we start doing
1167
that, we'll have to start replacing and freeing all of the
1168
ai_canonname fields.
1169
1170
Ref: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=133668 .
1171
1172
Since it's dependent on the target hostname, it's hard to check
1173
for at configure time. The bug was fixed in glibc 2.3.4.
1174
After the fix, the ai_canonname field is allocated, so our
1175
workaround leaks memory. We disable the workaround for glibc
1176
>= 2.4, but there is no easy way to test for glibc patch
1177
versions, so we still leak memory under glibc 2.3.4 through
1178
2.3.6.
1179
1180
Some Windows documentation says that even when AI_CANONNAME is
1181
set, the returned ai_canonname field can be null. The NetBSD
1182
1.5 implementation also does this, if the input hostname is a
1183
numeric host address string. That case isn't handled well at
1184
the moment.
1185
1186
Libc version 5 didn't have getaddrinfo at all. */
1187
1188
#ifdef COPY_FIRST_CANONNAME
1189
/*
1190
* This code must *always* return an error, return a null
1191
* ai_canonname, or return an ai_canonname allocated here using
1192
* malloc, so that freeaddrinfo can always free a non-null
1193
* ai_canonname. Note that it really doesn't matter if the
1194
* AI_CANONNAME flag was set.
1195
*/
1196
ai = *result;
1197
if (ai->ai_canonname) {
1198
struct hostent *hp;
1199
const char *name2 = 0;
1200
int i, herr;
1201
GET_HOST_TMP htmp;
1202
1203
/*
1204
* Current versions of GET_HOST_BY_NAME will fail if the
1205
* target hostname has IPv6 addresses only. Make sure it
1206
* fails fairly cleanly.
1207
*/
1208
GET_HOST_BY_NAME (name, hp, herr, htmp);
1209
if (hp == 0) {
1210
/*
1211
* This case probably means it's an IPv6-only name. If
1212
* ai_canonname is a numeric address, get rid of it.
1213
*/
1214
if (ai->ai_canonname && strchr(ai->ai_canonname, ':'))
1215
ai->ai_canonname = 0;
1216
name2 = ai->ai_canonname ? ai->ai_canonname : name;
1217
} else {
1218
/*
1219
* Sometimes gethostbyname will be directed to /etc/hosts
1220
* first, and sometimes that file will have entries with
1221
* the unqualified name first. So take the first entry
1222
* that looks like it could be a FQDN. Starting with h_name
1223
* and then all the aliases.
1224
*/
1225
for (i = 0, name2 = hp->h_name; name2; i++) {
1226
if (strchr(name2, '.') != 0)
1227
break;
1228
name2 = hp->h_aliases[i];
1229
}
1230
if (name2 == 0)
1231
name2 = hp->h_name;
1232
}
1233
1234
ai->ai_canonname = strdup(name2);
1235
if (name2 != 0 && ai->ai_canonname == 0) {
1236
system_freeaddrinfo(ai);
1237
*result = 0;
1238
#ifdef DEBUG_ADDRINFO
1239
debug_dump_error(EAI_MEMORY);
1240
#endif
1241
return EAI_MEMORY;
1242
}
1243
/* Zap the remaining ai_canonname fields glibc fills in, in
1244
case the application messes around with the list
1245
structure. */
1246
while ((ai = ai->ai_next) != NULL)
1247
ai->ai_canonname = 0;
1248
}
1249
#endif
1250
1251
#ifdef NUMERIC_SERVICE_BROKEN
1252
if (service_port != 0) {
1253
for (ai = *result; ai; ai = ai->ai_next) {
1254
if (socket_type != 0 && ai->ai_socktype == 0)
1255
/* Is this check actually needed? */
1256
ai->ai_socktype = socket_type;
1257
sa_setport(ai->ai_addr, service_port);
1258
}
1259
}
1260
#endif
1261
1262
#ifdef _AIX
1263
for (ai = *result; ai; ai = ai->ai_next) {
1264
/* AIX 4.3.3 libc is broken. It doesn't set the family or len
1265
fields of the sockaddr structures. Usually, sa_family is
1266
zero, but I've seen it set to 1 in some cases also (maybe
1267
just leftover from previous contents of the memory
1268
block?). So, always override what libc returned. */
1269
ai->ai_addr->sa_family = ai->ai_family;
1270
}
1271
#endif
1272
1273
/* Not dealt with currently:
1274
1275
- Some versions of GNU libc can lose some IPv4 addresses in
1276
certain cases when multiple IPv4 and IPv6 addresses are
1277
available. */
1278
1279
#ifdef DEBUG_ADDRINFO
1280
debug_dump_addrinfos(*result);
1281
#endif
1282
1283
return 0;
1284
}
1285
1286
static inline
1287
void freeaddrinfo (struct addrinfo *ai)
1288
{
1289
#ifdef COPY_FIRST_CANONNAME
1290
if (ai) {
1291
free(ai->ai_canonname);
1292
ai->ai_canonname = 0;
1293
system_freeaddrinfo(ai);
1294
}
1295
#else
1296
system_freeaddrinfo(ai);
1297
#endif
1298
}
1299
#endif /* WRAP_GETADDRINFO */
1300
1301
#ifdef FAI_CACHE
1302
static int krb5int_lock_fac (void)
1303
{
1304
int err;
1305
err = krb5int_call_thread_support_init();
1306
if (err)
1307
return err;
1308
return k5_mutex_lock(&krb5int_fac.lock);
1309
}
1310
1311
static int krb5int_unlock_fac (void)
1312
{
1313
return k5_mutex_unlock(&krb5int_fac.lock);
1314
}
1315
#endif
1316
1317
/* Some systems don't define in6addr_any. */
1318
const struct in6_addr krb5int_in6addr_any = IN6ADDR_ANY_INIT;
1319
1320
int krb5int_getaddrinfo (const char *node, const char *service,
1321
const struct addrinfo *hints,
1322
struct addrinfo **aip)
1323
{
1324
return getaddrinfo(node, service, hints, aip);
1325
}
1326
1327
void krb5int_freeaddrinfo (struct addrinfo *ai)
1328
{
1329
freeaddrinfo(ai);
1330
}
1331
1332
const char *krb5int_gai_strerror(int err)
1333
{
1334
return gai_strerror(err);
1335
}
1336
1337
int krb5int_getnameinfo (const struct sockaddr *sa, socklen_t salen,
1338
char *hbuf, size_t hbuflen,
1339
char *sbuf, size_t sbuflen,
1340
int flags)
1341
{
1342
return getnameinfo(sa, salen, hbuf, hbuflen, sbuf, sbuflen, flags);
1343
}
1344
1345