1 /* 2 * Copyright (C) 2001,2002,2003,2004,2005,2006 by the Massachusetts Institute of Technology, 3 * Cambridge, MA, USA. All Rights Reserved. 4 * 5 * This software is being provided to you, the LICENSEE, by the 6 * Massachusetts Institute of Technology (M.I.T.) under the following 7 * license. By obtaining, using and/or copying this software, you agree 8 * that you have read, understood, and will comply with these terms and 9 * conditions: 10 * 11 * Export of this software from the United States of America may 12 * require a specific license from the United States Government. 13 * It is the responsibility of any person or organization contemplating 14 * export to obtain such a license before exporting. 15 * 16 * WITHIN THAT CONSTRAINT, permission to use, copy, modify and distribute 17 * this software and its documentation for any purpose and without fee or 18 * royalty is hereby granted, provided that you agree to comply with the 19 * following copyright notice and statements, including the disclaimer, and 20 * that the same appear on ALL copies of the software and documentation, 21 * including modifications that you make for internal use or for 22 * distribution: 23 * 24 * THIS SOFTWARE IS PROVIDED "AS IS", AND M.I.T. MAKES NO REPRESENTATIONS 25 * OR WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not 26 * limitation, M.I.T. MAKES NO REPRESENTATIONS OR WARRANTIES OF 27 * MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF 28 * THE LICENSED SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY 29 * PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. 30 * 31 * The name of the Massachusetts Institute of Technology or M.I.T. may NOT 32 * be used in advertising or publicity pertaining to distribution of the 33 * software. Title to copyright in this software and any associated 34 * documentation shall at all times remain with M.I.T., and USER agrees to 35 * preserve same. 36 * 37 * Furthermore if you modify this software you must label 38 * your software as modified software and not distribute it in such a 39 * fashion that it might be confused with the original M.I.T. software. 40 */ 41 42 /* Approach overview: 43 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. 48 49 If no system version exists, use gethostby* and fake it. Define 50 the data structures and flag values locally. 51 52 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. 59 60 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 66 gethostby* calls. 67 68 We're taking a simpler approach: A system provides these routines or 69 it does not. 70 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 74 come to it. */ 75 76 /* To do, maybe: 77 78 + For AIX 4.3.3, using the RFC 2133 definition: Implement 79 AI_NUMERICHOST. It's not defined in the header file. 80 81 For certain (old?) versions of GNU libc, AI_NUMERICHOST is 82 defined but not implemented. 83 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 89 by now. 90 91 + inet_ntop, inet_pton 92 93 + Conditionally export/import the function definitions, so a 94 library can have a single copy instead of multiple. 95 96 + Upgrade host requirements to include working implementations of 97 these functions, and throw all this away. Pleeease? :-) */ 98 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" 104 105 #include <stdio.h> /* for sprintf */ 106 #include <errno.h> 107 108 #define IMPLEMENT_FAKE_GETADDRINFO 109 #include "fake-addrinfo.h" 110 111 #ifdef S_SPLINT_S 112 /*@-incondefs@*/ 113 extern int 114 getaddrinfo (/*@in@*/ /*@null@*/ const char *, 115 /*@in@*/ /*@null@*/ const char *, 116 /*@in@*/ /*@null@*/ const struct addrinfo *, 117 /*@out@*/ struct addrinfo **) 118 ; 119 extern void 120 freeaddrinfo (/*@only@*/ /*@out@*/ struct addrinfo *) 121 ; 122 extern int 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, 126 int flags) 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) /*@*/; 131 /*@=incondefs@*/ 132 #endif 133 134 135 #include "cache-addrinfo.h" 136 137 #if (defined (__linux__) && defined(HAVE_GETADDRINFO)) || defined (_AIX) 138 /* See comments below. */ 139 # define WRAP_GETADDRINFO 140 #endif 141 142 #if defined (__linux__) && defined(HAVE_GETADDRINFO) 143 # define COPY_FIRST_CANONNAME 144 #endif 145 146 #ifdef _AIX 147 # define NUMERIC_SERVICE_BROKEN 148 # define COPY_FIRST_CANONNAME 149 #endif 150 151 152 #ifdef COPY_FIRST_CANONNAME 153 # include <string.h> 154 #endif 155 156 #ifdef NUMERIC_SERVICE_BROKEN 157 # include <ctype.h> /* isdigit */ 158 # include <stdlib.h> /* strtoul */ 159 #endif 160 161 162 /* Do we actually have *any* systems we care about that don't provide 163 either getaddrinfo or one of these two flavors of 164 gethostbyname_r? */ 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; } 171 #else 172 #ifdef _AIX /* XXX should have a feature test! */ 173 typedef struct { 174 struct hostent ent; 175 struct hostent_data data; 176 } GET_HOST_TMP; 177 #define GET_HOST_BY_NAME(NAME, HP, ERR, TMP) \ 178 { \ 179 (HP) = (gethostbyname_r((NAME), &TMP.ent, &TMP.data) \ 180 ? 0 \ 181 : &TMP.ent); \ 182 (ERR) = h_errno; \ 183 } 184 /* 185 #define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR) \ 186 { \ 187 struct hostent my_h_ent; \ 188 struct hostent_data my_h_ent_data; \ 189 (HP) = (gethostbyaddr_r((ADDR), (ADDRLEN), (FAMILY), &my_h_ent, \ 190 &my_h_ent_data) \ 191 ? 0 \ 192 : &my_h_ent); \ 193 (ERR) = my_h_err; \ 194 } 195 */ 196 #else 197 #ifdef GETHOSTBYNAME_R_RETURNS_INT 198 typedef struct { 199 struct hostent ent; 200 char buf[8192]; 201 } GET_HOST_TMP; 202 #define GET_HOST_BY_NAME(NAME, HP, ERR, TMP) \ 203 { \ 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, \ 208 &my_h_err); \ 209 (HP) = (((my_ret != 0) || (my_hp != &TMP.ent)) \ 210 ? 0 \ 211 : &TMP.ent); \ 212 (ERR) = my_h_err; \ 213 } 214 #define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR, TMP) \ 215 { \ 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, \ 220 &my_h_err); \ 221 (HP) = (((my_ret != 0) || (my_hp != &TMP.ent)) \ 222 ? 0 \ 223 : &TMP.ent); \ 224 (ERR) = my_h_err; \ 225 } 226 #else 227 typedef struct { 228 struct hostent ent; 229 char buf[8192]; 230 } GET_HOST_TMP; 231 #define GET_HOST_BY_NAME(NAME, HP, ERR, TMP) \ 232 { \ 233 int my_h_err; \ 234 (HP) = gethostbyname_r((NAME), &TMP.ent, \ 235 TMP.buf, sizeof (TMP.buf), &my_h_err); \ 236 (ERR) = my_h_err; \ 237 } 238 #define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR, TMP) \ 239 { \ 240 int my_h_err; \ 241 (HP) = gethostbyaddr_r((ADDR), (ADDRLEN), (FAMILY), &TMP.ent, \ 242 TMP.buf, sizeof (TMP.buf), &my_h_err); \ 243 (ERR) = my_h_err; \ 244 } 245 #endif /* returns int? */ 246 #endif /* _AIX */ 247 #endif 248 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) 256 #else 257 #ifdef GETSERVBYNAME_R_RETURNS_INT 258 typedef struct { 259 struct servent ent; 260 char buf[8192]; 261 } GET_SERV_TMP; 262 #define GET_SERV_BY_NAME(NAME, PROTO, SP, ERR, TMP) \ 263 { \ 264 struct servent *my_sp; \ 265 int my_s_err; \ 266 (SP) = (getservbyname_r((NAME), (PROTO), &TMP.ent, \ 267 TMP.buf, sizeof (TMP.buf), &my_sp, \ 268 &my_s_err) \ 269 ? 0 \ 270 : &TMP.ent); \ 271 (ERR) = my_s_err; \ 272 } 273 #define GET_SERV_BY_PORT(PORT, PROTO, SP, ERR, TMP) \ 274 { \ 275 struct servent *my_sp; \ 276 int my_s_err; \ 277 (SP) = (getservbyport_r((PORT), (PROTO), &TMP.ent, \ 278 TMP.buf, sizeof (TMP.buf), &my_sp, \ 279 &my_s_err) \ 280 ? 0 \ 281 : &TMP.ent); \ 282 (ERR) = my_s_err; \ 283 } 284 #else 285 /* returns ptr -- IRIX? */ 286 typedef struct { 287 struct servent ent; 288 char buf[8192]; 289 } GET_SERV_TMP; 290 #define GET_SERV_BY_NAME(NAME, PROTO, SP, ERR, TMP) \ 291 { \ 292 (SP) = getservbyname_r((NAME), (PROTO), &TMP.ent, \ 293 TMP.buf, sizeof (TMP.buf)); \ 294 (ERR) = (SP) == NULL; \ 295 } 296 297 #define GET_SERV_BY_PORT(PORT, PROTO, SP, ERR, TMP) \ 298 { \ 299 struct servent *my_sp; \ 300 my_sp = getservbyport_r((PORT), (PROTO), &TMP.ent, \ 301 TMP.buf, sizeof (TMP.buf)); \ 302 (SP) = my_sp; \ 303 (ERR) = my_sp == 0; \ 304 (ERR) = (ERR); /* avoid "unused" warning */ \ 305 } 306 #endif 307 #endif 308 309 #if defined(WRAP_GETADDRINFO) || defined(FAI_CACHE) 310 static inline int 311 system_getaddrinfo (const char *name, const char *serv, 312 const struct addrinfo *hint, 313 struct addrinfo **res) 314 { 315 return getaddrinfo(name, serv, hint, res); 316 } 317 318 static inline void 319 system_freeaddrinfo (struct addrinfo *ai) 320 { 321 freeaddrinfo(ai); 322 } 323 324 /* Note: Implementations written to RFC 2133 use size_t, while RFC 325 2553 implementations use socklen_t, for the second parameter. 326 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. */ 329 static inline int 330 system_getnameinfo (const struct sockaddr *sa, socklen_t salen, 331 char *host, size_t hostlen, char *serv, size_t servlen, 332 int flags) 333 { 334 return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags); 335 } 336 #endif 337 338 #if !defined (HAVE_GETADDRINFO) || defined(WRAP_GETADDRINFO) || defined(FAI_CACHE) 339 340 #undef getaddrinfo 341 #define getaddrinfo my_fake_getaddrinfo 342 #undef freeaddrinfo 343 #define freeaddrinfo my_fake_freeaddrinfo 344 345 #endif 346 347 #if !defined (HAVE_GETADDRINFO) 348 349 #undef gai_strerror 350 #define gai_strerror my_fake_gai_strerror 351 352 #endif /* ! HAVE_GETADDRINFO */ 353 354 #if (!defined (HAVE_GETADDRINFO) || defined (WRAP_GETADDRINFO)) && defined(DEBUG_ADDRINFO) 355 /* Some debug routines. */ 356 357 static const char *protoname (int p, char *buf) { 358 #define X(N) if (p == IPPROTO_ ## N) return #N 359 360 X(TCP); 361 X(UDP); 362 X(ICMP); 363 X(IPV6); 364 #ifdef IPPROTO_GRE 365 X(GRE); 366 #endif 367 X(NONE); 368 X(RAW); 369 #ifdef IPPROTO_COMP 370 X(COMP); 371 #endif 372 #ifdef IPPROTO_IGMP 373 X(IGMP); 374 #endif 375 376 sprintf(buf, " %-2d", p); 377 return buf; 378 } 379 380 static const char *socktypename (int t, char *buf) { 381 switch (t) { 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"; 387 } 388 sprintf(buf, " %-2d", t); 389 return buf; 390 } 391 392 static const char *familyname (int f, char *buf) { 393 switch (f) { 394 default: 395 sprintf(buf, "AF %d", f); 396 return buf; 397 case AF_INET: return "AF_INET"; 398 case AF_INET6: return "AF_INET6"; 399 #ifdef AF_UNIX 400 case AF_UNIX: return "AF_UNIX"; 401 #endif 402 } 403 } 404 405 static void debug_dump_getaddrinfo_args (const char *name, const char *serv, 406 const struct addrinfo *hint) 407 { 408 const char *sep; 409 fprintf(stderr, 410 "getaddrinfo(hostname %s, service %s,\n" 411 " hints { ", 412 name ? name : "(null)", serv ? serv : "(null)"); 413 if (hint) { 414 char buf[30]; 415 sep = ""; 416 #define Z(FLAG) if (hint->ai_flags & AI_##FLAG) fprintf(stderr, "%s%s", sep, #FLAG), sep = "|" 417 Z(CANONNAME); 418 Z(PASSIVE); 419 #ifdef AI_NUMERICHOST 420 Z(NUMERICHOST); 421 #endif 422 if (sep[0] == 0) 423 fprintf(stderr, "no-flags"); 424 if (hint->ai_family) 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)); 430 } else 431 fprintf(stderr, "(null)"); 432 fprintf(stderr, " }):\n"); 433 } 434 435 static void debug_dump_error (int err) 436 { 437 fprintf(stderr, "error %d: %s\n", err, gai_strerror(err)); 438 } 439 440 static void debug_dump_addrinfos (const struct addrinfo *ai) 441 { 442 int count = 0; 443 char buf[10]; 444 fprintf(stderr, "addrinfos returned:\n"); 445 while (ai) { 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"); 453 ai = ai->ai_next; 454 count++; 455 } 456 fprintf(stderr, "end addrinfos returned (%d)\n"); 457 } 458 459 #endif 460 461 #if !defined (HAVE_GETADDRINFO) || defined (WRAP_GETADDRINFO) 462 463 static 464 int getaddrinfo (const char *name, const char *serv, 465 const struct addrinfo *hint, struct addrinfo **result); 466 467 static 468 void freeaddrinfo (struct addrinfo *ai); 469 470 #endif 471 472 #if !defined (HAVE_GETADDRINFO) 473 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 479 480 #undef getnameinfo 481 #define getnameinfo my_fake_getnameinfo 482 483 static 484 char *gai_strerror (int code); 485 486 #endif 487 488 #if !defined (HAVE_GETADDRINFO) 489 static 490 int getnameinfo (const struct sockaddr *addr, socklen_t len, 491 char *host, socklen_t hostlen, 492 char *service, socklen_t servicelen, 493 int flags); 494 #endif 495 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 500 #endif 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 506 #endif 507 #ifndef AI_V4MAPPED 508 # define AI_V4MAPPED 0 509 #endif 510 #ifndef AI_ALL 511 # define AI_ALL 0 512 #endif 513 #ifndef AI_DEFAULT 514 # define AI_DEFAULT (AI_ADDRCONFIG|AI_V4MAPPED) 515 #endif 516 517 #if defined(HAVE_FAKE_GETADDRINFO) || defined(FAI_CACHE) 518 #define NEED_FAKE_GETADDRINFO 519 #endif 520 521 #if defined(NEED_FAKE_GETADDRINFO) || defined(WRAP_GETADDRINFO) 522 #include <stdlib.h> 523 #endif 524 525 #ifdef NEED_FAKE_GETADDRINFO 526 #include <string.h> /* for strspn */ 527 528 static inline int translate_h_errno (int h); 529 530 static inline int fai_add_entry (struct addrinfo **result, void *addr, 531 int port, const struct addrinfo *template) 532 { 533 struct addrinfo *n = malloc (sizeof (struct addrinfo)); 534 if (n == 0) 535 return EAI_MEMORY; 536 if (template->ai_family != AF_INET 537 #ifdef KRB5_USE_INET6 538 && template->ai_family != AF_INET6 539 #endif 540 ) 541 return EAI_FAMILY; 542 *n = *template; 543 if (template->ai_family == AF_INET) { 544 struct sockaddr_in *sin4; 545 sin4 = malloc (sizeof (struct sockaddr_in)); 546 if (sin4 == 0) 547 return EAI_MEMORY; 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; 553 #ifdef HAVE_SA_LEN 554 sin4->sin_len = sizeof (struct sockaddr_in); 555 #endif 556 } 557 #ifdef KRB5_USE_INET6 558 if (template->ai_family == AF_INET6) { 559 struct sockaddr_in6 *sin6; 560 sin6 = malloc (sizeof (struct sockaddr_in6)); 561 if (sin6 == 0) 562 return EAI_MEMORY; 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; 568 #ifdef HAVE_SA_LEN 569 sin6->sin6_len = sizeof (struct sockaddr_in6); 570 #endif 571 } 572 #endif 573 n->ai_next = *result; 574 *result = n; 575 return 0; 576 } 577 578 #ifdef FAI_CACHE 579 /* fake addrinfo cache entries */ 580 #define CACHE_ENTRY_LIFETIME 15 /* seconds */ 581 582 static void plant_face (const char *name, struct face *entry) 583 { 584 entry->name = strdup(name); 585 if (entry->name == NULL) 586 /* @@ Wastes memory. */ 587 return; 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); 595 #endif 596 } 597 598 static int find_face (const char *name, struct face **entry) 599 { 600 struct face *fp, **fpp; 601 time_t now = time(0); 602 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); 607 #endif 608 k5_mutex_assert_locked(&krb5int_fac.lock); 609 for (fpp = &krb5int_fac.data; *fpp; ) { 610 fp = *fpp; 611 #ifdef DEBUG_ADDRINFO 612 printf(" checking expiration time of @%p: %d\n", 613 fp, fp->expiration); 614 #endif 615 if (fp->expiration < now) { 616 #ifdef DEBUG_ADDRINFO 617 printf("\texpiring cache entry\n"); 618 #endif 619 free(fp->name); 620 free(fp->canonname); 621 free(fp->addrs4); 622 free(fp->addrs6); 623 *fpp = fp->next; 624 free(fp); 625 /* Stay at this point in the list, and check again. */ 626 } else 627 /* Move forward. */ 628 fpp = &(*fpp)->next; 629 } 630 631 for (fp = krb5int_fac.data; fp; fp = fp->next) { 632 #ifdef DEBUG_ADDRINFO 633 printf(" comparing entry @%p\n", fp); 634 #endif 635 if (!strcasecmp(fp->name, name)) { 636 #ifdef DEBUG_ADDRINFO 637 printf("\tMATCH!\n"); 638 #endif 639 *entry = fp; 640 return 1; 641 } 642 } 643 return 0; 644 } 645 646 #endif 647 648 static int krb5int_lock_fac(void), krb5int_unlock_fac(void); 649 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) 654 { 655 #ifdef FAI_CACHE 656 657 struct face *ce; 658 int i, r, err; 659 660 err = krb5int_lock_fac(); 661 if (err) { 662 errno = err; 663 return EAI_SYSTEM; 664 } 665 if (!find_face(name, &ce)) { 666 struct addrinfo myhints = { 0 }, *ai, *ai2; 667 int i4, i6, aierr; 668 669 #ifdef DEBUG_ADDRINFO 670 printf("looking up new data for '%s'...\n", name); 671 #endif 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 679 have to. */ 680 /* Try NULL for the service for now. 681 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, 691 sometimes not. 692 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. 703 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); 710 if (aierr) { 711 krb5int_unlock_fac(); 712 return aierr; 713 } 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); 720 #endif 721 switch (ai2->ai_family) { 722 case AF_INET: 723 ce->naddrs4++; 724 break; 725 case AF_INET6: 726 ce->naddrs6++; 727 break; 728 default: 729 break; 730 } 731 } 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); 736 return EAI_MEMORY; 737 } 738 ce->addrs6 = calloc(ce->naddrs6, sizeof(*ce->addrs6)); 739 if (ce->addrs6 == NULL && ce->naddrs6 != 0) { 740 krb5int_unlock_fac(); 741 free(ce->addrs4); 742 system_freeaddrinfo(ai); 743 return EAI_MEMORY; 744 } 745 for (ai2 = ai, i4 = i6 = 0; ai2; ai2 = ai2->ai_next) { 746 switch (ai2->ai_family) { 747 case AF_INET: 748 ce->addrs4[i4++] = ((struct sockaddr_in *)ai2->ai_addr)->sin_addr; 749 break; 750 case AF_INET6: 751 ce->addrs6[i6++] = ((struct sockaddr_in6 *)ai2->ai_addr)->sin6_addr; 752 break; 753 default: 754 break; 755 } 756 } 757 ce->canonname = ai->ai_canonname ? strdup(ai->ai_canonname) : 0; 758 system_freeaddrinfo(ai); 759 plant_face(name, ce); 760 } 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); 765 if (r) { 766 krb5int_unlock_fac(); 767 return r; 768 } 769 } 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); 774 if (r) { 775 krb5int_unlock_fac(); 776 return r; 777 } 778 } 779 if (*result && (flags & AI_CANONNAME)) 780 (*result)->ai_canonname = (ce->canonname 781 ? strdup(ce->canonname) 782 : NULL); 783 krb5int_unlock_fac(); 784 return 0; 785 786 #else 787 788 struct hostent *hp; 789 int i, r; 790 int herr; 791 GET_HOST_TMP htmp; 792 793 GET_HOST_BY_NAME (name, hp, herr, htmp); 794 if (hp == 0) 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); 798 if (r) 799 return r; 800 } 801 if (*result && (flags & AI_CANONNAME)) 802 (*result)->ai_canonname = strdup (hp->h_name); 803 return 0; 804 805 #endif 806 } 807 808 static inline void 809 fake_freeaddrinfo (struct addrinfo *ai) 810 { 811 struct addrinfo *next; 812 while (ai) { 813 next = ai->ai_next; 814 if (ai->ai_canonname) 815 free (ai->ai_canonname); 816 if (ai->ai_addr) 817 free (ai->ai_addr); 818 free (ai); 819 ai = next; 820 } 821 } 822 823 static inline int 824 fake_getaddrinfo (const char *name, const char *serv, 825 const struct addrinfo *hint, struct addrinfo **result) 826 { 827 struct addrinfo *res = 0; 828 int ret; 829 int port = 0, socktype; 830 int flags; 831 struct addrinfo template; 832 833 #ifdef DEBUG_ADDRINFO 834 debug_dump_getaddrinfo_args(name, serv, hint); 835 #endif 836 837 if (hint != 0) { 838 if (hint->ai_family != 0 && hint->ai_family != AF_INET) 839 return EAI_NODATA; 840 socktype = hint->ai_socktype; 841 flags = hint->ai_flags; 842 } else { 843 socktype = 0; 844 flags = 0; 845 } 846 847 if (serv) { 848 size_t numlen = strspn (serv, "0123456789"); 849 if (serv[numlen] == '\0') { 850 /* pure numeric */ 851 unsigned long p = strtoul (serv, 0, 10); 852 if (p == 0 || p > 65535) 853 return EAI_NONAME; 854 port = htons (p); 855 } else { 856 struct servent *sp; 857 int try_dgram_too = 0, s_err; 858 GET_SERV_TMP stmp; 859 860 if (socktype == 0) { 861 try_dgram_too = 1; 862 socktype = SOCK_STREAM; 863 } 864 try_service_lookup: 865 GET_SERV_BY_NAME(serv, socktype == SOCK_STREAM ? "tcp" : "udp", 866 sp, s_err, stmp); 867 if (sp == 0) { 868 if (try_dgram_too) { 869 socktype = SOCK_DGRAM; 870 goto try_service_lookup; 871 } 872 return EAI_SERVICE; 873 } 874 port = sp->s_port; 875 } 876 } 877 878 if (name == 0) { 879 name = (flags & AI_PASSIVE) ? "0.0.0.0" : "127.0.0.1"; 880 flags |= AI_NUMERICHOST; 881 } 882 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; 891 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; 896 #if 0 897 ret = inet_aton (name, &addr4); 898 if (ret) 899 return EAI_NONAME; 900 #else 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 */ 904 return EAI_NONAME; 905 #endif 906 ret = fai_add_entry (&res, &addr4, port, &template); 907 } else { 908 ret = fai_add_hosts_by_name (name, &template, port, flags, 909 &res); 910 } 911 912 if (ret && ret != NO_ADDRESS) { 913 fake_freeaddrinfo (res); 914 return ret; 915 } 916 if (res == 0) 917 return NO_ADDRESS; 918 *result = res; 919 return 0; 920 } 921 922 #ifdef NEED_FAKE_GETNAMEINFO 923 static inline int 924 fake_getnameinfo (const struct sockaddr *sa, socklen_t len, 925 char *host, socklen_t hostlen, 926 char *service, socklen_t servicelen, 927 int flags) 928 { 929 struct hostent *hp; 930 const struct sockaddr_in *sinp; 931 struct servent *sp; 932 size_t hlen, slen; 933 934 if (sa->sa_family != AF_INET) { 935 return EAI_FAMILY; 936 } 937 sinp = (const struct sockaddr_in *) sa; 938 939 hlen = hostlen; 940 if (hostlen < 0 || hlen != hostlen) { 941 errno = EINVAL; 942 return EAI_SYSTEM; 943 } 944 slen = servicelen; 945 if (servicelen < 0 || slen != servicelen) { 946 errno = EINVAL; 947 return EAI_SYSTEM; 948 } 949 950 if (host) { 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; 958 char tmpbuf[20]; 959 numeric_host: 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); 963 #else 964 char *p; 965 numeric_host: 966 p = inet_ntoa (sinp->sin_addr); 967 strncpy (host, p, hlen); 968 #endif 969 } else { 970 int herr; 971 GET_HOST_TMP htmp; 972 973 GET_HOST_BY_ADDR((const char *) &sinp->sin_addr, 974 sizeof (struct in_addr), 975 sa->sa_family, hp, herr, htmp); 976 if (hp == 0) { 977 if (herr == NO_ADDRESS && !(flags & NI_NAMEREQD)) /* ??? */ 978 goto numeric_host; 979 return translate_h_errno (herr); 980 } 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); 985 } 986 host[hostlen-1] = 0; 987 } 988 989 if (service) { 990 if (flags & NI_NUMERICSERV) { 991 char numbuf[10]; 992 int port; 993 numeric_service: 994 port = ntohs (sinp->sin_port); 995 if (port < 0 || port > 65535) 996 return EAI_FAIL; 997 sprintf (numbuf, "%d", port); 998 strncpy (service, numbuf, slen); 999 } else { 1000 int serr; 1001 GET_SERV_TMP stmp; 1002 1003 GET_SERV_BY_PORT(sinp->sin_port, 1004 (flags & NI_DGRAM) ? "udp" : "tcp", 1005 sp, serr, stmp); 1006 if (sp == 0) 1007 goto numeric_service; 1008 strncpy (service, sp->s_name, slen); 1009 } 1010 service[servicelen-1] = 0; 1011 } 1012 1013 return 0; 1014 } 1015 #endif 1016 1017 #if defined(HAVE_FAKE_GETADDRINFO) || defined(NEED_FAKE_GETNAMEINFO) 1018 1019 static inline 1020 char *gai_strerror (int code) 1021 { 1022 switch (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?"; 1035 } 1036 } 1037 #endif 1038 1039 static inline int translate_h_errno (int h) 1040 { 1041 switch (h) { 1042 case 0: 1043 return 0; 1044 #ifdef NETDB_INTERNAL 1045 case NETDB_INTERNAL: 1046 if (errno == ENOMEM) 1047 return EAI_MEMORY; 1048 return EAI_SYSTEM; 1049 #endif 1050 case HOST_NOT_FOUND: 1051 return EAI_NONAME; 1052 case TRY_AGAIN: 1053 return EAI_AGAIN; 1054 case NO_RECOVERY: 1055 return EAI_FAIL; 1056 case NO_DATA: 1057 #if NO_DATA != NO_ADDRESS 1058 case NO_ADDRESS: 1059 #endif 1060 return EAI_NODATA; 1061 default: 1062 return EAI_SYSTEM; 1063 } 1064 } 1065 1066 #if defined(HAVE_FAKE_GETADDRINFO) || defined(FAI_CACHE) 1067 static inline 1068 int getaddrinfo (const char *name, const char *serv, 1069 const struct addrinfo *hint, struct addrinfo **result) 1070 { 1071 return fake_getaddrinfo(name, serv, hint, result); 1072 } 1073 1074 static inline 1075 void freeaddrinfo (struct addrinfo *ai) 1076 { 1077 fake_freeaddrinfo(ai); 1078 } 1079 1080 #ifdef NEED_FAKE_GETNAMEINFO 1081 static inline 1082 int getnameinfo (const struct sockaddr *sa, socklen_t len, 1083 char *host, socklen_t hostlen, 1084 char *service, socklen_t servicelen, 1085 int flags) 1086 { 1087 return fake_getnameinfo(sa, len, host, hostlen, service, servicelen, 1088 flags); 1089 } 1090 #endif /* NEED_FAKE_GETNAMEINFO */ 1091 #endif /* HAVE_FAKE_GETADDRINFO */ 1092 #endif /* NEED_FAKE_GETADDRINFO */ 1093 1094 1095 #ifdef WRAP_GETADDRINFO 1096 1097 static inline 1098 int 1099 getaddrinfo (const char *name, const char *serv, const struct addrinfo *hint, 1100 struct addrinfo **result) 1101 { 1102 int aierr; 1103 #if defined(_AIX) || defined(COPY_FIRST_CANONNAME) 1104 struct addrinfo *ai; 1105 #endif 1106 #ifdef NUMERIC_SERVICE_BROKEN 1107 int service_is_numeric = 0; 1108 int service_port = 0; 1109 int socket_type = 0; 1110 #endif 1111 1112 #ifdef DEBUG_ADDRINFO 1113 debug_dump_getaddrinfo_args(name, serv, hint); 1114 #endif 1115 1116 #ifdef NUMERIC_SERVICE_BROKEN 1117 /* AIX 4.3.3 is broken. (Or perhaps out of date?) 1118 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; 1125 char *end; 1126 lport = strtoul(serv, &end, 10); 1127 if (!*end) { 1128 if (lport > 65535) 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) 1134 serv = "9"; 1135 else 1136 #endif 1137 serv = "discard"; /* defined for both udp and tcp */ 1138 if (hint) 1139 socket_type = hint->ai_socktype; 1140 } 1141 } 1142 #endif 1143 1144 aierr = system_getaddrinfo (name, serv, hint, result); 1145 if (aierr || *result == 0) { 1146 #ifdef DEBUG_ADDRINFO 1147 debug_dump_error(aierr); 1148 #endif 1149 return aierr; 1150 } 1151 1152 /* Linux libc version 6 (libc-2.2.4.so on Debian) is broken. 1153 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. 1159 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. 1163 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 1167 it. 1168 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. 1179 1180 Ref: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=133668 . 1181 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. 1186 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 1191 the moment. 1192 1193 Libc version 5 didn't have getaddrinfo at all. */ 1194 1195 #ifdef COPY_FIRST_CANONNAME 1196 /* 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. 1202 */ 1203 ai = *result; 1204 if (ai->ai_canonname) { 1205 struct hostent *hp; 1206 const char *name2 = 0; 1207 int i, herr; 1208 GET_HOST_TMP htmp; 1209 1210 /* 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. 1214 */ 1215 GET_HOST_BY_NAME (name, hp, herr, htmp); 1216 if (hp == 0) { 1217 /* 1218 * This case probably means it's an IPv6-only name. If 1219 * ai_canonname is a numeric address, get rid of it. 1220 */ 1221 if (ai->ai_canonname && strchr(ai->ai_canonname, ':')) 1222 ai->ai_canonname = 0; 1223 name2 = ai->ai_canonname ? ai->ai_canonname : name; 1224 } else { 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]; 1232 break; 1233 } 1234 } 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) 1238 name2 = hp->h_name; 1239 } 1240 1241 ai->ai_canonname = strdup(name2); 1242 if (name2 != 0 && ai->ai_canonname == 0) { 1243 system_freeaddrinfo(ai); 1244 *result = 0; 1245 #ifdef DEBUG_ADDRINFO 1246 debug_dump_error(EAI_MEMORY); 1247 #endif 1248 return EAI_MEMORY; 1249 } 1250 /* Zap the remaining ai_canonname fields glibc fills in, in 1251 case the application messes around with the list 1252 structure. */ 1253 while ((ai = ai->ai_next) != NULL) 1254 ai->ai_canonname = 0; 1255 } 1256 #endif 1257 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) { 1265 case AF_INET: 1266 ((struct sockaddr_in *)ai->ai_addr)->sin_port = service_port; 1267 break; 1268 case AF_INET6: 1269 ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port = service_port; 1270 break; 1271 } 1272 } 1273 } 1274 #endif 1275 1276 #ifdef _AIX 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; 1286 #endif 1287 } 1288 #endif 1289 1290 /* Not dealt with currently: 1291 1292 - Some versions of GNU libc can lose some IPv4 addresses in 1293 certain cases when multiple IPv4 and IPv6 addresses are 1294 available. */ 1295 1296 #ifdef DEBUG_ADDRINFO 1297 debug_dump_addrinfos(*result); 1298 #endif 1299 1300 return 0; 1301 } 1302 1303 static inline 1304 void freeaddrinfo (struct addrinfo *ai) 1305 { 1306 #ifdef COPY_FIRST_CANONNAME 1307 if (ai) { 1308 free(ai->ai_canonname); 1309 ai->ai_canonname = 0; 1310 system_freeaddrinfo(ai); 1311 } 1312 #else 1313 system_freeaddrinfo(ai); 1314 #endif 1315 } 1316 #endif /* WRAP_GETADDRINFO */ 1317 1318 static int krb5int_lock_fac (void) 1319 { 1320 int err; 1321 err = krb5int_call_thread_support_init(); 1322 if (err) 1323 return err; 1324 return k5_mutex_lock(&krb5int_fac.lock); 1325 } 1326 1327 static int krb5int_unlock_fac (void) 1328 { 1329 return k5_mutex_unlock(&krb5int_fac.lock); 1330 } 1331 1332 /* Some systems don't define in6addr_any. */ 1333 const struct in6_addr krb5int_in6addr_any = IN6ADDR_ANY_INIT; 1334 1335 int krb5int_getaddrinfo (const char *node, const char *service, 1336 const struct addrinfo *hints, 1337 struct addrinfo **aip) 1338 { 1339 return getaddrinfo(node, service, hints, aip); 1340 } 1341 1342 void krb5int_freeaddrinfo (struct addrinfo *ai) 1343 { 1344 freeaddrinfo(ai); 1345 } 1346 1347 const char *krb5int_gai_strerror(int err) 1348 { 1349 return gai_strerror(err); 1350 } 1351 1352 int krb5int_getnameinfo (const struct sockaddr *sa, socklen_t salen, 1353 char *hbuf, size_t hbuflen, 1354 char *sbuf, size_t sbuflen, 1355 int flags) 1356 { 1357 return getnameinfo(sa, salen, hbuf, hbuflen, sbuf, sbuflen, flags); 1358 } 1359