2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
27 #include <mach/mach.h>
30 #include <rpc/types.h>
33 #include <sys/socket.h>
34 #include <netinet/in.h>
36 #include <arpa/inet.h>
40 #include "_lu_types.h"
45 #define HOST_CACHE_SIZE 10
46 #define DEFAULT_HOST_CACHE_TTL 10
48 #define CACHE_BYNAME 0
49 #define CACHE_BYADDR 1
51 static pthread_mutex_t _host_cache_lock
= PTHREAD_MUTEX_INITIALIZER
;
52 static unsigned int _host_cache_ttl
= DEFAULT_HOST_CACHE_TTL
;
54 static void *_host_byname_cache
[HOST_CACHE_SIZE
] = { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
};
55 static int _host_byname_cache_flavor
[HOST_CACHE_SIZE
] = { WANT_NOTHING
, WANT_NOTHING
, WANT_NOTHING
, WANT_NOTHING
, WANT_NOTHING
, WANT_NOTHING
, WANT_NOTHING
, WANT_NOTHING
, WANT_NOTHING
, WANT_NOTHING
};
56 static unsigned int _host_byname_cache_best_before
[HOST_CACHE_SIZE
] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
57 static unsigned int _host_byname_cache_index
= 0;
59 static void *_host_byaddr_cache
[HOST_CACHE_SIZE
] = { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
};
60 static int _host_byaddr_cache_flavor
[HOST_CACHE_SIZE
] = { WANT_NOTHING
, WANT_NOTHING
, WANT_NOTHING
, WANT_NOTHING
, WANT_NOTHING
, WANT_NOTHING
, WANT_NOTHING
, WANT_NOTHING
, WANT_NOTHING
, WANT_NOTHING
};
61 static unsigned int _host_byaddr_cache_best_before
[HOST_CACHE_SIZE
] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
62 static unsigned int _host_byaddr_cache_index
= 0;
64 static pthread_mutex_t _host_lock
= PTHREAD_MUTEX_INITIALIZER
;
66 extern struct hostent
*_res_gethostbyaddr();
67 extern struct hostent
*_res_gethostbyname();
68 extern struct hostent
*_old_gethostbyaddr();
69 extern struct hostent
*_old_gethostbyname();
70 extern struct hostent
*_old_gethostent();
71 extern void _old_sethostent();
72 extern void _old_endhostent();
73 extern void _old_sethostfile();
75 extern mach_port_t _lu_port
;
76 extern int _lu_running(void);
80 #define IPV6_ADDR_LEN 16
81 #define IPV4_ADDR_LEN 4
83 __private_extern__
void
84 free_host_data(struct hostent
*h
)
89 if (h
== NULL
) return;
91 if (h
->h_name
!= NULL
) free(h
->h_name
);
93 aliases
= h
->h_aliases
;
96 while (*aliases
!= NULL
) free(*aliases
++);
100 if (h
->h_addr_list
!= NULL
)
102 for (i
= 0; h
->h_addr_list
[i
] != NULL
; i
++) free(h
->h_addr_list
[i
]);
103 free(h
->h_addr_list
);
108 freehostent(struct hostent
*h
)
110 if (h
== NULL
) return;
116 free_lu_thread_info_host(void *x
)
118 struct lu_thread_info
*tdata
;
120 if (x
== NULL
) return;
122 tdata
= (struct lu_thread_info
*)x
;
124 if (tdata
->lu_entry
!= NULL
)
126 freehostent((struct hostent
*)tdata
->lu_entry
);
127 tdata
->lu_entry
= NULL
;
130 _lu_data_free_vm_xdr(tdata
);
135 __private_extern__
struct hostent
*
136 extract_host(XDR
*xdr
, int want
, int *err
)
139 int i
, j
, nvals
, nkeys
, status
, addr_len
;
140 int family
, addr_count
, map_count
;
142 struct in6_addr addr6
;
143 char *key
, **vals
, **mapvals
;
148 addr_len
= sizeof(u_long
*);
156 if (!xdr_int(xdr
, &nkeys
))
162 h
= (struct hostent
*)calloc(1, sizeof(struct hostent
));
165 h
->h_length
= IPV4_ADDR_LEN
;
167 if (want
> WANT_A4_ONLY
)
170 h
->h_length
= IPV6_ADDR_LEN
;
173 h
->h_addrtype
= family
;
175 for (i
= 0; i
< nkeys
; i
++)
181 status
= _lu_xdr_attribute(xdr
, &key
, &vals
, &nvals
);
197 if ((h
->h_name
== NULL
) && (!strcmp("name", key
)))
202 h
->h_aliases
= (char **)calloc(nvals
, sizeof(char *));
203 for (j
= 1; j
< nvals
; j
++) h
->h_aliases
[j
-1] = vals
[j
];
207 else if ((family
== AF_INET
) && (h
->h_addr_list
== NULL
) && (!strcmp("ip_address", key
)))
210 h
->h_addr_list
= (char **)calloc(nvals
+ 1, addr_len
);
212 for (j
= 0; j
< nvals
; j
++)
215 inet_aton(vals
[j
], &addr
);
216 h
->h_addr_list
[j
] = (char *)calloc(1, IPV4_ADDR_LEN
);
217 memmove(h
->h_addr_list
[j
], &(addr
.s_addr
), IPV4_ADDR_LEN
);
220 h
->h_addr_list
[nvals
] = NULL
;
223 else if ((family
== AF_INET6
) && (h
->h_addr_list
== NULL
) && (!strcmp("ipv6_address", key
)))
226 h
->h_addr_list
= (char **)calloc(nvals
+ 1, addr_len
);
228 for (j
= 0; j
< nvals
; j
++)
230 memset(&addr6
, 0, sizeof(struct in6_addr
));
231 inet_pton(family
, vals
[j
], &addr6
);
232 h
->h_addr_list
[j
] = (char *)calloc(1, IPV6_ADDR_LEN
);
233 memmove(h
->h_addr_list
[j
], &(addr6
.__u6_addr
.__u6_addr32
[0]), IPV6_ADDR_LEN
);
236 h
->h_addr_list
[nvals
] = NULL
;
239 else if ((family
== AF_INET6
) && (mapvals
== NULL
) && (!strcmp("ip_address", key
)))
249 for (; j
< nvals
; j
++) free(vals
[j
]);
254 if ((mapvals
!= NULL
) && (want
> WANT_A6_ONLY
))
256 addr6
.__u6_addr
.__u6_addr32
[0] = 0x00000000;
257 addr6
.__u6_addr
.__u6_addr32
[1] = 0x00000000;
258 addr6
.__u6_addr
.__u6_addr32
[2] = htonl(0x0000ffff);
262 h
->h_addr_list
= (char **)calloc(map_count
+ 1, addr_len
);
266 h
->h_addr_list
= (char **)realloc(h
->h_addr_list
, (addr_count
+ map_count
+ 1) * addr_len
);
269 for (i
= 0; i
< map_count
; i
++)
272 inet_aton(mapvals
[i
], &addr
);
273 h
->h_addr_list
[addr_count
] = (char *)calloc(1, IPV6_ADDR_LEN
);
274 memmove(&(addr6
.__u6_addr
.__u6_addr32
[3]), &(addr
.s_addr
), IPV4_ADDR_LEN
);
275 memcpy(h
->h_addr_list
[addr_count
++], &(addr6
.__u6_addr
.__u6_addr32
[0]), IPV6_ADDR_LEN
);
278 h
->h_addr_list
[addr_count
] = NULL
;
283 for (i
= 0; i
< map_count
; i
++) free(mapvals
[i
]);
287 if (h
->h_addr_list
== NULL
)
294 if (h
->h_name
== NULL
) h
->h_name
= strdup("");
295 if (h
->h_aliases
== NULL
) h
->h_aliases
= (char **)calloc(1, sizeof(char *));
300 static struct hostent
*
301 copy_host(struct hostent
*in
)
303 int i
, len
, addr_len
;
306 if (in
== NULL
) return NULL
;
308 h
= (struct hostent
*)calloc(1, sizeof(struct hostent
));
310 h
->h_name
= LU_COPY_STRING(in
->h_name
);
313 if (in
->h_aliases
!= NULL
)
315 for (len
= 0; in
->h_aliases
[len
] != NULL
; len
++);
318 h
->h_aliases
= (char **)calloc(len
+ 1, sizeof(char *));
319 for (i
= 0; i
< len
; i
++)
321 h
->h_aliases
[i
] = strdup(in
->h_aliases
[i
]);
324 h
->h_addrtype
= in
->h_addrtype
;
325 h
->h_length
= in
->h_length
;
328 if (in
->h_addr_list
!= NULL
)
330 for (len
= 0; in
->h_addr_list
[len
] != NULL
; len
++);
333 addr_len
= sizeof(u_long
*);
334 h
->h_addr_list
= (char **)calloc(len
+ 1, addr_len
);
335 for (i
= 0; i
< len
; i
++)
337 h
->h_addr_list
[i
] = (char *)malloc(h
->h_length
);
338 memmove(h
->h_addr_list
[i
], in
->h_addr_list
[i
], h
->h_length
);
345 recycle_host(struct lu_thread_info
*tdata
, struct hostent
*in
)
349 if (tdata
== NULL
) return;
350 h
= (struct hostent
*)tdata
->lu_entry
;
355 tdata
->lu_entry
= NULL
;
358 if (tdata
->lu_entry
== NULL
)
360 tdata
->lu_entry
= in
;
366 h
->h_name
= in
->h_name
;
367 h
->h_aliases
= in
->h_aliases
;
368 h
->h_addrtype
= in
->h_addrtype
;
369 h
->h_length
= in
->h_length
;
370 h
->h_addr_list
= in
->h_addr_list
;
375 __private_extern__
struct hostent
*
376 fake_hostent(const char *name
, struct in_addr addr
)
381 if (name
== NULL
) return NULL
;
383 h
= (struct hostent
*)calloc(1, sizeof(struct hostent
));
385 h
->h_name
= strdup(name
);
387 h
->h_aliases
= (char **)calloc(1, sizeof(char *));
389 h
->h_addrtype
= AF_INET
;
390 h
->h_length
= sizeof(long);
392 addr_len
= sizeof(u_long
*);
393 h
->h_addr_list
= (char **)calloc(2, addr_len
);
395 h
->h_addr_list
[0] = (char *)malloc(h
->h_length
);
396 memmove(h
->h_addr_list
[0], &(addr
.s_addr
), h
->h_length
);
401 __private_extern__
struct hostent
*
402 fake_hostent6(const char *name
, struct in6_addr addr
)
407 if (name
== NULL
) return NULL
;
409 h
= (struct hostent
*)calloc(1, sizeof(struct hostent
));
411 h
->h_name
= strdup(name
);
413 h
->h_aliases
= (char **)calloc(1, sizeof(char *));
415 h
->h_addrtype
= AF_INET6
;
418 addr_len
= sizeof(u_long
*);
419 h
->h_addr_list
= (char **)calloc(2, addr_len
);
421 h
->h_addr_list
[0] = (char *)malloc(h
->h_length
);
422 memmove(h
->h_addr_list
[0], &(addr
.__u6_addr
.__u6_addr32
[0]), h
->h_length
);
427 __private_extern__
unsigned int
430 return _host_cache_ttl
;
433 __private_extern__
void
434 set_host_cache_ttl(unsigned int ttl
)
438 pthread_mutex_lock(&_host_cache_lock
);
440 _host_cache_ttl
= ttl
;
444 for (i
= 0; i
< HOST_CACHE_SIZE
; i
++)
446 if (_host_byname_cache
[i
] == NULL
) continue;
448 freehostent((struct hostent
*)_host_byname_cache
[i
]);
449 _host_byname_cache
[i
] = NULL
;
450 _host_byname_cache_flavor
[i
] = WANT_NOTHING
;
451 _host_byname_cache_best_before
[i
] = 0;
454 for (i
= 0; i
< HOST_CACHE_SIZE
; i
++)
456 if (_host_byaddr_cache
[i
] == NULL
) continue;
458 freehostent((struct hostent
*)_host_byaddr_cache
[i
]);
459 _host_byaddr_cache
[i
] = NULL
;
460 _host_byaddr_cache_flavor
[i
] = WANT_NOTHING
;
461 _host_byaddr_cache_best_before
[i
] = 0;
465 pthread_mutex_unlock(&_host_cache_lock
);
469 cache_host(struct hostent
*h
, int want
, int how
)
472 struct hostent
*hcache
;
474 if (_host_cache_ttl
== 0) return;
475 if (h
== NULL
) return;
477 pthread_mutex_lock(&_host_cache_lock
);
479 hcache
= copy_host(h
);
481 gettimeofday(&now
, NULL
);
483 if (how
== CACHE_BYNAME
)
485 if (_host_byname_cache
[_host_byname_cache_index
] != NULL
)
486 freehostent((struct hostent
*)_host_byname_cache
[_host_byname_cache_index
]);
488 _host_byname_cache
[_host_byname_cache_index
] = hcache
;
489 _host_byname_cache_flavor
[_host_byname_cache_index
] = want
;
490 _host_byname_cache_best_before
[_host_byname_cache_index
] = now
.tv_sec
+ _host_cache_ttl
;
491 _host_byname_cache_index
= (_host_byname_cache_index
+ 1) % HOST_CACHE_SIZE
;
495 if (_host_byaddr_cache
[_host_byaddr_cache_index
] != NULL
)
496 freehostent((struct hostent
*)_host_byaddr_cache
[_host_byaddr_cache_index
]);
498 _host_byaddr_cache
[_host_byaddr_cache_index
] = hcache
;
499 _host_byaddr_cache_flavor
[_host_byaddr_cache_index
] = want
;
500 _host_byaddr_cache_best_before
[_host_byaddr_cache_index
] = now
.tv_sec
+ _host_cache_ttl
;
501 _host_byaddr_cache_index
= (_host_byaddr_cache_index
+ 1) % HOST_CACHE_SIZE
;
504 pthread_mutex_unlock(&_host_cache_lock
);
507 static struct hostent
*
508 cache_gethostbyname(const char *name
, int want
)
511 struct hostent
*h
, *res
;
515 if (_host_cache_ttl
== 0) return NULL
;
516 if (name
== NULL
) return NULL
;
518 pthread_mutex_lock(&_host_cache_lock
);
520 gettimeofday(&now
, NULL
);
522 for (i
= 0; i
< HOST_CACHE_SIZE
; i
++)
524 if (_host_byname_cache_best_before
[i
] == 0) continue;
525 if ((unsigned int)now
.tv_sec
> _host_byname_cache_best_before
[i
]) continue;
527 if (_host_byname_cache_flavor
[i
] != want
) continue;
529 h
= (struct hostent
*)_host_byname_cache
[i
];
531 if (h
->h_name
!= NULL
)
533 if (!strcmp(name
, h
->h_name
))
536 pthread_mutex_unlock(&_host_cache_lock
);
541 aliases
= h
->h_aliases
;
544 pthread_mutex_unlock(&_host_cache_lock
);
548 for (; *aliases
!= NULL
; *aliases
++)
550 if (!strcmp(name
, *aliases
))
553 pthread_mutex_unlock(&_host_cache_lock
);
559 pthread_mutex_unlock(&_host_cache_lock
);
563 static struct hostent
*
564 cache_gethostbyaddr(const char *addr
, int want
)
567 struct hostent
*h
, *res
;
570 if (addr
== NULL
) return NULL
;
571 if (_host_cache_ttl
== 0) return NULL
;
573 pthread_mutex_lock(&_host_cache_lock
);
575 gettimeofday(&now
, NULL
);
578 if (want
> WANT_A4_ONLY
) len
= IPV6_ADDR_LEN
;
580 for (i
= 0; i
< HOST_CACHE_SIZE
; i
++)
582 if (_host_byaddr_cache_best_before
[i
] == 0) continue;
583 if ((unsigned int)now
.tv_sec
> _host_byaddr_cache_best_before
[i
]) continue;
585 if (_host_byaddr_cache_flavor
[i
] != want
) continue;
587 h
= (struct hostent
*)_host_byaddr_cache
[i
];
589 if (h
->h_addr_list
== NULL
) continue;
591 for (j
= 0; h
->h_addr_list
[j
] != NULL
; j
++)
593 if (memcmp(addr
, h
->h_addr_list
[j
], len
) == 0)
596 pthread_mutex_unlock(&_host_cache_lock
);
602 pthread_mutex_unlock(&_host_cache_lock
);
606 static struct hostent
*
607 lu_gethostbyaddr(const char *addr
, int want
, int *err
)
610 unsigned int datalen
;
612 static int proc4
= -1;
613 static int proc6
= -1;
614 char *lookup_buf
, *address
;
615 int proc
, count
, len
, family
;
616 struct in_addr addr4
;
617 struct in6_addr addr6
;
621 if ((want
== WANT_A6_ONLY
) || (want
== WANT_A6_PLUS_MAPPED_A4
))
627 if ((family
== AF_INET
) && (proc4
< 0))
629 if (_lookup_link(_lu_port
, "gethostbyaddr", &proc4
) != KERN_SUCCESS
)
635 else if ((family
== AF_INET6
) && (proc6
< 0))
637 if (_lookup_link(_lu_port
, "getipv6nodebyaddr", &proc6
) != KERN_SUCCESS
)
646 if (family
== AF_INET
)
648 memmove(&(addr4
.s_addr
), addr
, IPV4_ADDR_LEN
);
649 addr4
.s_addr
= htonl(addr4
.s_addr
);
650 address
= (char *)&(addr4
.s_addr
);
655 memmove(&(addr6
.__u6_addr
.__u6_addr32
[0]), addr
, IPV6_ADDR_LEN
);
656 addr6
.__u6_addr
.__u6_addr32
[0] = htonl(addr6
.__u6_addr
.__u6_addr32
[0]);
657 addr6
.__u6_addr
.__u6_addr32
[1] = htonl(addr6
.__u6_addr
.__u6_addr32
[1]);
658 addr6
.__u6_addr
.__u6_addr32
[2] = htonl(addr6
.__u6_addr
.__u6_addr32
[2]);
659 addr6
.__u6_addr
.__u6_addr32
[3] = htonl(addr6
.__u6_addr
.__u6_addr32
[3]);
660 address
= (char *)&(addr6
.__u6_addr
.__u6_addr32
[0]);
667 if (_lookup_all(_lu_port
, proc
, (unit
*)address
, len
/ BYTES_PER_XDR_UNIT
, &lookup_buf
, &datalen
) != KERN_SUCCESS
)
673 datalen
*= BYTES_PER_XDR_UNIT
;
674 if ((lookup_buf
== NULL
) || (datalen
== 0)) return NULL
;
676 xdrmem_create(&inxdr
, lookup_buf
, datalen
, XDR_DECODE
);
679 if (!xdr_int(&inxdr
, &count
))
682 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
690 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
691 *err
= HOST_NOT_FOUND
;
697 h
= extract_host(&inxdr
, want
, err
);
699 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
704 static struct hostent
*
705 lu_gethostbyname(const char *name
, int want
, int *err
)
708 unsigned int datalen
;
709 char namebuf
[_LU_MAXLUSTRLEN
+ BYTES_PER_XDR_UNIT
];
712 static int proc4
= -1;
713 static int proc6
= -1;
715 int proc
, count
, family
;
718 if (want
> WANT_A4_ONLY
) family
= AF_INET6
;
720 if (((want
== WANT_MAPPED_A4_ONLY
) || (family
== AF_INET
)) && (proc4
< 0))
722 if (_lookup_link(_lu_port
, "gethostbyname", &proc4
) != KERN_SUCCESS
)
728 else if ((family
== AF_INET6
) && (proc6
< 0))
730 if (_lookup_link(_lu_port
, "getipv6nodebyname", &proc6
) != KERN_SUCCESS
)
738 if ((family
== AF_INET6
) && (want
!= WANT_MAPPED_A4_ONLY
)) proc
= proc6
;
740 xdrmem_create(&outxdr
, namebuf
, sizeof(namebuf
), XDR_ENCODE
);
741 if (!xdr__lu_string(&outxdr
, (_lu_string
*)&name
))
743 xdr_destroy(&outxdr
);
751 if (_lookup_all(_lu_port
, proc
, (unit
*)namebuf
, xdr_getpos(&outxdr
) / BYTES_PER_XDR_UNIT
, &lookup_buf
, &datalen
) != KERN_SUCCESS
)
753 xdr_destroy(&outxdr
);
758 xdr_destroy(&outxdr
);
760 datalen
*= BYTES_PER_XDR_UNIT
;
761 if ((lookup_buf
== NULL
) || (datalen
== 0)) return NULL
;
763 xdrmem_create(&inxdr
, lookup_buf
, datalen
, XDR_DECODE
);
766 if (!xdr_int(&inxdr
, &count
))
769 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
777 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
778 *err
= HOST_NOT_FOUND
;
784 h
= extract_host(&inxdr
, want
, err
);
786 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
794 struct lu_thread_info
*tdata
;
796 tdata
= _lu_data_create_key(_lu_data_key_host
, free_lu_thread_info_host
);
797 _lu_data_free_vm_xdr(tdata
);
806 static struct hostent
*
807 lu_gethostent(int want
, int *err
)
809 static int proc
= -1;
810 struct lu_thread_info
*tdata
;
813 tdata
= _lu_data_create_key(_lu_data_key_host
, free_lu_thread_info_host
);
816 tdata
= (struct lu_thread_info
*)calloc(1, sizeof(struct lu_thread_info
));
817 _lu_data_set_key(_lu_data_key_host
, tdata
);
820 if (tdata
->lu_vm
== NULL
)
824 if (_lookup_link(_lu_port
, "gethostent", &proc
) != KERN_SUCCESS
)
832 if (_lookup_all(_lu_port
, proc
, NULL
, 0, &(tdata
->lu_vm
), &(tdata
->lu_vm_length
)) != KERN_SUCCESS
)
839 /* mig stubs measure size in words (4 bytes) */
840 tdata
->lu_vm_length
*= 4;
842 if (tdata
->lu_xdr
!= NULL
)
844 xdr_destroy(tdata
->lu_xdr
);
847 tdata
->lu_xdr
= (XDR
*)calloc(1, sizeof(XDR
));
849 xdrmem_create(tdata
->lu_xdr
, tdata
->lu_vm
, tdata
->lu_vm_length
, XDR_DECODE
);
850 if (!xdr_int(tdata
->lu_xdr
, &tdata
->lu_vm_cursor
))
858 if (tdata
->lu_vm_cursor
== 0)
861 *err
= HOST_NOT_FOUND
;
865 h
= extract_host(tdata
->lu_xdr
, want
, err
);
869 *err
= HOST_NOT_FOUND
;
874 tdata
->lu_vm_cursor
--;
879 static struct hostent
*
880 gethostbyaddrerrno(const char *addr
, int len
, int type
, int *err
)
882 struct hostent
*res
= NULL
;
883 int want
, from_cache
;
888 if (type
== AF_INET6
) want
= WANT_A6_ONLY
;
890 if ((type
== AF_INET6
) && (len
== 16) && (is_a4_mapped((const char *)addr
) || is_a4_compat((const char *)addr
)))
895 want
= WANT_MAPPED_A4_ONLY
;
899 res
= cache_gethostbyaddr(addr
, want
);
905 else if (_lu_running())
907 res
= lu_gethostbyaddr(addr
, want
, err
);
911 pthread_mutex_lock(&_host_lock
);
912 res
= copy_host(_res_gethostbyaddr(addr
, len
, type
));
913 if (res
== NULL
) res
= copy_host(_old_gethostbyaddr(addr
, len
, type
));
915 pthread_mutex_unlock(&_host_lock
);
918 if (from_cache
== 0) cache_host(res
, want
, CACHE_BYADDR
);
924 gethostbyaddr(const char *addr
, int len
, int type
)
927 struct lu_thread_info
*tdata
;
929 res
= gethostbyaddrerrno(addr
, len
, type
, &h_errno
);
935 tdata
= _lu_data_create_key(_lu_data_key_host
, free_lu_thread_info_host
);
938 tdata
= (struct lu_thread_info
*)calloc(1, sizeof(struct lu_thread_info
));
939 _lu_data_set_key(_lu_data_key_host
, tdata
);
942 recycle_host(tdata
, res
);
943 return (struct hostent
*)tdata
->lu_entry
;
947 gethostbynameerrno(const char *name
, int *err
)
949 struct hostent
*res
= NULL
;
951 int i
, is_addr
, from_cache
;
956 * If name is all dots and digits without a trailing dot,
957 * call inet_aton. If it's OK, return a fake entry.
958 * Otherwise, return an error.
960 * If name has alpha or ends with a dot, proceed as usual...
964 *err
= HOST_NOT_FOUND
;
970 *err
= HOST_NOT_FOUND
;
975 for (i
= 0; name
[i
] != '\0'; i
++)
977 if (name
[i
] == '.') continue;
978 if ((name
[i
] >= '0') && (name
[i
] <= '9')) continue;
983 if ((is_addr
== 1) && (name
[i
-1] == '.')) is_addr
= 0;
990 if (inet_aton(name
, &addr
) == 0)
992 *err
= HOST_NOT_FOUND
;
995 res
= fake_hostent(name
, addr
);
1000 res
= cache_gethostbyname(name
, WANT_A4_ONLY
);
1007 else if (_lu_running())
1009 res
= lu_gethostbyname(name
, WANT_A4_ONLY
, err
);
1013 pthread_mutex_lock(&_host_lock
);
1014 res
= copy_host(_res_gethostbyname(name
));
1015 if (res
== NULL
) res
= copy_host(_old_gethostbyname(name
));
1017 pthread_mutex_unlock(&_host_lock
);
1022 if (inet_aton(name
, &addr
) == 0)
1024 *err
= HOST_NOT_FOUND
;
1028 res
= gethostbyaddrerrno((char *)&addr
, sizeof(addr
), AF_INET
, err
);
1031 res
= fake_hostent(name
, addr
);
1035 if (from_cache
== 0) cache_host(res
, WANT_A4_ONLY
, CACHE_BYNAME
);
1041 gethostbyname(const char *name
)
1043 struct hostent
*res
;
1044 struct lu_thread_info
*tdata
;
1046 res
= gethostbynameerrno(name
, &h_errno
);
1052 tdata
= _lu_data_create_key(_lu_data_key_host
, free_lu_thread_info_host
);
1055 tdata
= (struct lu_thread_info
*)calloc(1, sizeof(struct lu_thread_info
));
1056 _lu_data_set_key(_lu_data_key_host
, tdata
);
1059 recycle_host(tdata
, res
);
1060 return (struct hostent
*)tdata
->lu_entry
;
1064 gethostbyname2(const char *name
, int af
)
1066 struct hostent
*res
;
1067 struct lu_thread_info
*tdata
;
1069 res
= getipnodebyname(name
, af
, 0, &h_errno
);
1072 errno
= EAFNOSUPPORT
;
1073 h_errno
= NETDB_INTERNAL
;
1077 tdata
= _lu_data_create_key(_lu_data_key_host
, free_lu_thread_info_host
);
1080 tdata
= (struct lu_thread_info
*)calloc(1, sizeof(struct lu_thread_info
));
1081 _lu_data_set_key(_lu_data_key_host
, tdata
);
1084 recycle_host(tdata
, res
);
1085 return (struct hostent
*)tdata
->lu_entry
;
1091 struct hostent
*res
= NULL
;
1092 struct lu_thread_info
*tdata
;
1094 tdata
= _lu_data_create_key(_lu_data_key_host
, free_lu_thread_info_host
);
1097 tdata
= (struct lu_thread_info
*)calloc(1, sizeof(struct lu_thread_info
));
1098 _lu_data_set_key(_lu_data_key_host
, tdata
);
1103 res
= lu_gethostent(WANT_A4_ONLY
, &h_errno
);
1107 pthread_mutex_lock(&_host_lock
);
1108 res
= copy_host(_old_gethostent());
1109 pthread_mutex_unlock(&_host_lock
);
1112 recycle_host(tdata
, res
);
1113 return (struct hostent
*)tdata
->lu_entry
;
1117 sethostent(int stayopen
)
1119 if (_lu_running()) lu_sethostent();
1120 else _old_sethostent(stayopen
);
1126 if (_lu_running()) lu_endhostent();
1127 else _old_endhostent();
1130 __private_extern__
int
1131 is_a4_mapped(const char *s
)
1136 if (s
== NULL
) return 0;
1138 for (i
= 0; i
< 10; i
++)
1141 if (c
!= 0x0) return 0;
1144 for (i
= 10; i
< 12; i
++)
1147 if (c
!= 0xff) return 0;
1153 __private_extern__
int
1154 is_a4_compat(const char *s
)
1159 if (s
== NULL
) return 0;
1161 for (i
= 0; i
< 12; i
++)
1164 if (c
!= 0x0) return 0;
1167 /* Check for :: and ::1 */
1168 for (i
= 13; i
< 15; i
++)
1170 /* anything non-zero in these 3 bytes means it's a V4 address */
1172 if (c
!= 0x0) return 1;
1175 /* Leading 15 bytes are all zero */
1177 if (c
== 0x0) return 0;
1178 if (c
== 0x1) return 0;
1184 getipnodebyaddr(const void *src
, size_t len
, int af
, int *err
)
1186 struct hostent
*res
;
1190 res
= gethostbyaddrerrno((const char *)src
, len
, af
, err
);
1196 if (res
->h_name
== NULL
)
1206 getipnodebyname(const char *name
, int af
, int flags
, int *err
)
1208 int status
, want
, really_want
, if4
, if6
, from_cache
;
1209 struct hostent
*res
;
1210 struct ifaddrs
*ifa
, *ifap
;
1211 struct in_addr addr4
;
1212 struct in6_addr addr6
;
1214 memset(&addr4
, 0, sizeof(struct in_addr
));
1215 memset(&addr6
, 0, sizeof(struct in6_addr
));
1221 status
= inet_aton(name
, &addr4
);
1224 /* return a fake hostent */
1225 res
= fake_hostent(name
, addr4
);
1229 else if (af
== AF_INET6
)
1231 status
= inet_pton(af
, name
, &addr6
);
1234 /* return a fake hostent */
1235 res
= fake_hostent6(name
, addr6
);
1238 status
= inet_aton(name
, &addr4
);
1241 if (!(flags
& (AI_V4MAPPED
|AI_V4MAPPED_CFG
)))
1243 *err
= HOST_NOT_FOUND
;
1247 addr6
.__u6_addr
.__u6_addr32
[0] = 0x00000000;
1248 addr6
.__u6_addr
.__u6_addr32
[1] = 0x00000000;
1249 addr6
.__u6_addr
.__u6_addr32
[2] = htonl(0x0000ffff);
1250 memmove(&(addr6
.__u6_addr
.__u6_addr32
[3]), &(addr4
.s_addr
), IPV4_ADDR_LEN
);
1252 /* return a fake hostent */
1253 res
= fake_hostent6(name
, addr6
);
1264 * IF AI_ADDRCONFIG is set, we need to know what interface flavors we really have.
1270 if (flags
& AI_ADDRCONFIG
)
1272 if (getifaddrs(&ifa
) < 0)
1278 for (ifap
= ifa
; ifap
!= NULL
; ifap
= ifap
->ifa_next
)
1280 if (ifap
->ifa_addr
== NULL
) continue;
1281 if ((ifap
->ifa_flags
& IFF_UP
) == 0) continue;
1282 if (ifap
->ifa_addr
->sa_family
== AF_INET
) if4
++;
1283 else if (ifap
->ifa_addr
->sa_family
== AF_INET6
) if6
++;
1288 /* Bail out if there are no interfaces */
1289 if ((if4
== 0) && (if6
== 0))
1297 * Figure out what we want.
1298 * If user asked for AF_INET, we only want V4 addresses.
1300 want
= WANT_A4_ONLY
;
1305 want
= WANT_A4_ONLY
;
1306 if ((flags
& AI_ADDRCONFIG
) && (if4
== 0))
1314 /* af == AF_INET6 */
1315 want
= WANT_A6_ONLY
;
1317 if (flags
& (AI_V4MAPPED
|AI_V4MAPPED_CFG
))
1321 want
= WANT_A6_PLUS_MAPPED_A4
;
1326 want
= WANT_A6_ONLY
;
1327 really_want
= WANT_A6_OR_MAPPED_A4_IF_NO_A6
;
1332 if ((flags
& AI_ADDRCONFIG
) && (if6
== 0))
1341 res
= cache_gethostbyname(name
, want
);
1347 else if (_lu_running())
1349 res
= lu_gethostbyname(name
, want
, err
);
1350 if ((res
== NULL
) &&
1351 ((really_want
== WANT_A6_OR_MAPPED_A4_IF_NO_A6
) ||
1352 (really_want
== WANT_A6_PLUS_MAPPED_A4
)))
1354 res
= lu_gethostbyname(name
, WANT_MAPPED_A4_ONLY
, err
);
1359 pthread_mutex_lock(&_host_lock
);
1360 res
= copy_host(_res_gethostbyname(name
));
1361 if (res
== NULL
) res
= copy_host(_old_gethostbyname(name
));
1363 pthread_mutex_unlock(&_host_lock
);
1368 *err
= HOST_NOT_FOUND
;
1372 if (from_cache
== 0) cache_host(res
, want
, CACHE_BYNAME
);