2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.1 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
26 #include <mach/mach.h>
29 #include <rpc/types.h>
32 #include <sys/socket.h>
33 #include <netinet/in.h>
35 #include <arpa/inet.h>
39 #include "_lu_types.h"
44 #define HOST_CACHE_SIZE 10
45 #define DEFAULT_HOST_CACHE_TTL 10
47 #define CACHE_BYNAME 0
48 #define CACHE_BYADDR 1
50 static pthread_mutex_t _host_cache_lock
= PTHREAD_MUTEX_INITIALIZER
;
51 static unsigned int _host_cache_ttl
= DEFAULT_HOST_CACHE_TTL
;
53 static void *_host_byname_cache
[HOST_CACHE_SIZE
] = { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
};
54 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
};
55 static unsigned int _host_byname_cache_best_before
[HOST_CACHE_SIZE
] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
56 static unsigned int _host_byname_cache_index
= 0;
58 static void *_host_byaddr_cache
[HOST_CACHE_SIZE
] = { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
};
59 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
};
60 static unsigned int _host_byaddr_cache_best_before
[HOST_CACHE_SIZE
] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
61 static unsigned int _host_byaddr_cache_index
= 0;
63 static pthread_mutex_t _host_lock
= PTHREAD_MUTEX_INITIALIZER
;
65 extern struct hostent
*_res_gethostbyaddr();
66 extern struct hostent
*_res_gethostbyname();
67 extern struct hostent
*_old_gethostbyaddr();
68 extern struct hostent
*_old_gethostbyname();
69 extern struct hostent
*_old_gethostent();
70 extern void _old_sethostent();
71 extern void _old_endhostent();
72 extern void _old_sethostfile();
74 extern mach_port_t _lu_port
;
75 extern int _lu_running(void);
79 #define IPV6_ADDR_LEN 16
80 #define IPV4_ADDR_LEN 4
82 __private_extern__
void
83 free_host_data(struct hostent
*h
)
88 if (h
== NULL
) return;
90 if (h
->h_name
!= NULL
) free(h
->h_name
);
92 aliases
= h
->h_aliases
;
95 while (*aliases
!= NULL
) free(*aliases
++);
99 if (h
->h_addr_list
!= NULL
)
101 for (i
= 0; h
->h_addr_list
[i
] != NULL
; i
++) free(h
->h_addr_list
[i
]);
102 free(h
->h_addr_list
);
107 freehostent(struct hostent
*h
)
109 if (h
== NULL
) return;
115 free_lu_thread_info_host(void *x
)
117 struct lu_thread_info
*tdata
;
119 if (x
== NULL
) return;
121 tdata
= (struct lu_thread_info
*)x
;
123 if (tdata
->lu_entry
!= NULL
)
125 freehostent((struct hostent
*)tdata
->lu_entry
);
126 tdata
->lu_entry
= NULL
;
129 _lu_data_free_vm_xdr(tdata
);
134 __private_extern__
struct hostent
*
135 extract_host(XDR
*xdr
, int want
, int *err
)
138 int i
, j
, nvals
, nkeys
, status
, addr_len
;
139 int family
, addr_count
, map_count
;
141 struct in6_addr addr6
;
142 char *key
, **vals
, **mapvals
;
147 addr_len
= sizeof(u_long
*);
155 if (!xdr_int(xdr
, &nkeys
))
161 h
= (struct hostent
*)calloc(1, sizeof(struct hostent
));
164 h
->h_length
= IPV4_ADDR_LEN
;
166 if (want
> WANT_A4_ONLY
)
169 h
->h_length
= IPV6_ADDR_LEN
;
172 h
->h_addrtype
= family
;
174 for (i
= 0; i
< nkeys
; i
++)
180 status
= _lu_xdr_attribute(xdr
, &key
, &vals
, &nvals
);
196 if ((h
->h_name
== NULL
) && (!strcmp("name", key
)))
201 h
->h_aliases
= (char **)calloc(nvals
, sizeof(char *));
202 for (j
= 1; j
< nvals
; j
++) h
->h_aliases
[j
-1] = vals
[j
];
206 else if ((family
== AF_INET
) && (h
->h_addr_list
== NULL
) && (!strcmp("ip_address", key
)))
209 h
->h_addr_list
= (char **)calloc(nvals
+ 1, addr_len
);
211 for (j
= 0; j
< nvals
; j
++)
214 inet_aton(vals
[j
], &addr
);
215 h
->h_addr_list
[j
] = (char *)calloc(1, IPV4_ADDR_LEN
);
216 memmove(h
->h_addr_list
[j
], &(addr
.s_addr
), IPV4_ADDR_LEN
);
219 h
->h_addr_list
[nvals
] = NULL
;
222 else if ((family
== AF_INET6
) && (h
->h_addr_list
== NULL
) && (!strcmp("ipv6_address", key
)))
225 h
->h_addr_list
= (char **)calloc(nvals
+ 1, addr_len
);
227 for (j
= 0; j
< nvals
; j
++)
229 memset(&addr6
, 0, sizeof(struct in6_addr
));
230 inet_pton(family
, vals
[j
], &addr6
);
231 h
->h_addr_list
[j
] = (char *)calloc(1, IPV6_ADDR_LEN
);
232 memmove(h
->h_addr_list
[j
], &(addr6
.__u6_addr
.__u6_addr32
[0]), IPV6_ADDR_LEN
);
235 h
->h_addr_list
[nvals
] = NULL
;
238 else if ((family
== AF_INET6
) && (mapvals
== NULL
) && (!strcmp("ip_address", key
)))
248 for (; j
< nvals
; j
++) free(vals
[j
]);
253 if ((mapvals
!= NULL
) && (want
> WANT_A6_ONLY
))
255 addr6
.__u6_addr
.__u6_addr32
[0] = 0x00000000;
256 addr6
.__u6_addr
.__u6_addr32
[1] = 0x00000000;
257 addr6
.__u6_addr
.__u6_addr32
[2] = htonl(0x0000ffff);
261 h
->h_addr_list
= (char **)calloc(map_count
+ 1, addr_len
);
265 h
->h_addr_list
= (char **)realloc(h
->h_addr_list
, (addr_count
+ map_count
+ 1) * addr_len
);
268 for (i
= 0; i
< map_count
; i
++)
271 inet_aton(mapvals
[i
], &addr
);
272 h
->h_addr_list
[addr_count
] = (char *)calloc(1, IPV6_ADDR_LEN
);
273 memmove(&(addr6
.__u6_addr
.__u6_addr32
[3]), &(addr
.s_addr
), IPV4_ADDR_LEN
);
274 memcpy(h
->h_addr_list
[addr_count
++], &(addr6
.__u6_addr
.__u6_addr32
[0]), IPV6_ADDR_LEN
);
277 h
->h_addr_list
[addr_count
] = NULL
;
282 for (i
= 0; i
< map_count
; i
++) free(mapvals
[i
]);
286 if (h
->h_addr_list
== NULL
)
293 if (h
->h_name
== NULL
) h
->h_name
= strdup("");
294 if (h
->h_aliases
== NULL
) h
->h_aliases
= (char **)calloc(1, sizeof(char *));
299 static struct hostent
*
300 copy_host(struct hostent
*in
)
302 int i
, len
, addr_len
;
305 if (in
== NULL
) return NULL
;
307 h
= (struct hostent
*)calloc(1, sizeof(struct hostent
));
309 h
->h_name
= LU_COPY_STRING(in
->h_name
);
312 if (in
->h_aliases
!= NULL
)
314 for (len
= 0; in
->h_aliases
[len
] != NULL
; len
++);
317 h
->h_aliases
= (char **)calloc(len
+ 1, sizeof(char *));
318 for (i
= 0; i
< len
; i
++)
320 h
->h_aliases
[i
] = strdup(in
->h_aliases
[i
]);
323 h
->h_addrtype
= in
->h_addrtype
;
324 h
->h_length
= in
->h_length
;
327 if (in
->h_addr_list
!= NULL
)
329 for (len
= 0; in
->h_addr_list
[len
] != NULL
; len
++);
332 addr_len
= sizeof(u_long
*);
333 h
->h_addr_list
= (char **)calloc(len
+ 1, addr_len
);
334 for (i
= 0; i
< len
; i
++)
336 h
->h_addr_list
[i
] = (char *)malloc(h
->h_length
);
337 memmove(h
->h_addr_list
[i
], in
->h_addr_list
[i
], h
->h_length
);
344 recycle_host(struct lu_thread_info
*tdata
, struct hostent
*in
)
348 if (tdata
== NULL
) return;
349 h
= (struct hostent
*)tdata
->lu_entry
;
354 tdata
->lu_entry
= NULL
;
357 if (tdata
->lu_entry
== NULL
)
359 tdata
->lu_entry
= in
;
365 h
->h_name
= in
->h_name
;
366 h
->h_aliases
= in
->h_aliases
;
367 h
->h_addrtype
= in
->h_addrtype
;
368 h
->h_length
= in
->h_length
;
369 h
->h_addr_list
= in
->h_addr_list
;
374 __private_extern__
struct hostent
*
375 fake_hostent(const char *name
, struct in_addr addr
)
380 if (name
== NULL
) return NULL
;
382 h
= (struct hostent
*)calloc(1, sizeof(struct hostent
));
384 h
->h_name
= strdup(name
);
386 h
->h_aliases
= (char **)calloc(1, sizeof(char *));
388 h
->h_addrtype
= AF_INET
;
389 h
->h_length
= sizeof(long);
391 addr_len
= sizeof(u_long
*);
392 h
->h_addr_list
= (char **)calloc(2, addr_len
);
394 h
->h_addr_list
[0] = (char *)malloc(h
->h_length
);
395 memmove(h
->h_addr_list
[0], &(addr
.s_addr
), h
->h_length
);
400 __private_extern__
struct hostent
*
401 fake_hostent6(const char *name
, struct in6_addr addr
)
406 if (name
== NULL
) return NULL
;
408 h
= (struct hostent
*)calloc(1, sizeof(struct hostent
));
410 h
->h_name
= strdup(name
);
412 h
->h_aliases
= (char **)calloc(1, sizeof(char *));
414 h
->h_addrtype
= AF_INET6
;
417 addr_len
= sizeof(u_long
*);
418 h
->h_addr_list
= (char **)calloc(2, addr_len
);
420 h
->h_addr_list
[0] = (char *)malloc(h
->h_length
);
421 memmove(h
->h_addr_list
[0], &(addr
.__u6_addr
.__u6_addr32
[0]), h
->h_length
);
426 __private_extern__
unsigned int
429 return _host_cache_ttl
;
432 __private_extern__
void
433 set_host_cache_ttl(unsigned int ttl
)
437 pthread_mutex_lock(&_host_cache_lock
);
439 _host_cache_ttl
= ttl
;
443 for (i
= 0; i
< HOST_CACHE_SIZE
; i
++)
445 if (_host_byname_cache
[i
] == NULL
) continue;
447 freehostent((struct hostent
*)_host_byname_cache
[i
]);
448 _host_byname_cache
[i
] = NULL
;
449 _host_byname_cache_flavor
[i
] = WANT_NOTHING
;
450 _host_byname_cache_best_before
[i
] = 0;
453 for (i
= 0; i
< HOST_CACHE_SIZE
; i
++)
455 if (_host_byaddr_cache
[i
] == NULL
) continue;
457 freehostent((struct hostent
*)_host_byaddr_cache
[i
]);
458 _host_byaddr_cache
[i
] = NULL
;
459 _host_byaddr_cache_flavor
[i
] = WANT_NOTHING
;
460 _host_byaddr_cache_best_before
[i
] = 0;
464 pthread_mutex_unlock(&_host_cache_lock
);
468 cache_host(struct hostent
*h
, int want
, int how
)
471 struct hostent
*hcache
;
473 if (_host_cache_ttl
== 0) return;
474 if (h
== NULL
) return;
476 pthread_mutex_lock(&_host_cache_lock
);
478 hcache
= copy_host(h
);
480 gettimeofday(&now
, NULL
);
482 if (how
== CACHE_BYNAME
)
484 if (_host_byname_cache
[_host_byname_cache_index
] != NULL
)
485 freehostent((struct hostent
*)_host_byname_cache
[_host_byname_cache_index
]);
487 _host_byname_cache
[_host_byname_cache_index
] = hcache
;
488 _host_byname_cache_flavor
[_host_byname_cache_index
] = want
;
489 _host_byname_cache_best_before
[_host_byname_cache_index
] = now
.tv_sec
+ _host_cache_ttl
;
490 _host_byname_cache_index
= (_host_byname_cache_index
+ 1) % HOST_CACHE_SIZE
;
494 if (_host_byaddr_cache
[_host_byaddr_cache_index
] != NULL
)
495 freehostent((struct hostent
*)_host_byaddr_cache
[_host_byaddr_cache_index
]);
497 _host_byaddr_cache
[_host_byaddr_cache_index
] = hcache
;
498 _host_byaddr_cache_flavor
[_host_byaddr_cache_index
] = want
;
499 _host_byaddr_cache_best_before
[_host_byaddr_cache_index
] = now
.tv_sec
+ _host_cache_ttl
;
500 _host_byaddr_cache_index
= (_host_byaddr_cache_index
+ 1) % HOST_CACHE_SIZE
;
503 pthread_mutex_unlock(&_host_cache_lock
);
506 static struct hostent
*
507 cache_gethostbyname(const char *name
, int want
)
510 struct hostent
*h
, *res
;
514 if (_host_cache_ttl
== 0) return NULL
;
515 if (name
== NULL
) return NULL
;
517 pthread_mutex_lock(&_host_cache_lock
);
519 gettimeofday(&now
, NULL
);
521 for (i
= 0; i
< HOST_CACHE_SIZE
; i
++)
523 if (_host_byname_cache_best_before
[i
] == 0) continue;
524 if ((unsigned int)now
.tv_sec
> _host_byname_cache_best_before
[i
]) continue;
526 if (_host_byname_cache_flavor
[i
] != want
) continue;
528 h
= (struct hostent
*)_host_byname_cache
[i
];
530 if (h
->h_name
!= NULL
)
532 if (!strcmp(name
, h
->h_name
))
535 pthread_mutex_unlock(&_host_cache_lock
);
540 aliases
= h
->h_aliases
;
543 pthread_mutex_unlock(&_host_cache_lock
);
547 for (; *aliases
!= NULL
; *aliases
++)
549 if (!strcmp(name
, *aliases
))
552 pthread_mutex_unlock(&_host_cache_lock
);
558 pthread_mutex_unlock(&_host_cache_lock
);
562 static struct hostent
*
563 cache_gethostbyaddr(const char *addr
, int want
)
566 struct hostent
*h
, *res
;
569 if (addr
== NULL
) return NULL
;
570 if (_host_cache_ttl
== 0) return NULL
;
572 pthread_mutex_lock(&_host_cache_lock
);
574 gettimeofday(&now
, NULL
);
577 if (want
> WANT_A4_ONLY
) len
= IPV6_ADDR_LEN
;
579 for (i
= 0; i
< HOST_CACHE_SIZE
; i
++)
581 if (_host_byaddr_cache_best_before
[i
] == 0) continue;
582 if ((unsigned int)now
.tv_sec
> _host_byaddr_cache_best_before
[i
]) continue;
584 if (_host_byaddr_cache_flavor
[i
] != want
) continue;
586 h
= (struct hostent
*)_host_byaddr_cache
[i
];
588 if (h
->h_addr_list
== NULL
) continue;
590 for (j
= 0; h
->h_addr_list
[j
] != NULL
; j
++)
592 if (memcmp(addr
, h
->h_addr_list
[j
], len
) == 0)
595 pthread_mutex_unlock(&_host_cache_lock
);
601 pthread_mutex_unlock(&_host_cache_lock
);
605 static struct hostent
*
606 lu_gethostbyaddr(const char *addr
, int want
, int *err
)
609 unsigned int datalen
;
611 static int proc4
= -1;
612 static int proc6
= -1;
613 char *lookup_buf
, *address
;
614 int proc
, count
, len
, family
;
615 struct in_addr addr4
;
616 struct in6_addr addr6
;
620 if ((want
== WANT_A6_ONLY
) || (want
== WANT_A6_PLUS_MAPPED_A4
))
626 if ((family
== AF_INET
) && (proc4
< 0))
628 if (_lookup_link(_lu_port
, "gethostbyaddr", &proc4
) != KERN_SUCCESS
)
634 else if ((family
== AF_INET6
) && (proc6
< 0))
636 if (_lookup_link(_lu_port
, "getipv6nodebyaddr", &proc6
) != KERN_SUCCESS
)
645 if (family
== AF_INET
)
647 memmove(&(addr4
.s_addr
), addr
, IPV4_ADDR_LEN
);
648 addr4
.s_addr
= htonl(addr4
.s_addr
);
649 address
= (char *)&(addr4
.s_addr
);
654 memmove(&(addr6
.__u6_addr
.__u6_addr32
[0]), addr
, IPV6_ADDR_LEN
);
655 addr6
.__u6_addr
.__u6_addr32
[0] = htonl(addr6
.__u6_addr
.__u6_addr32
[0]);
656 addr6
.__u6_addr
.__u6_addr32
[1] = htonl(addr6
.__u6_addr
.__u6_addr32
[1]);
657 addr6
.__u6_addr
.__u6_addr32
[2] = htonl(addr6
.__u6_addr
.__u6_addr32
[2]);
658 addr6
.__u6_addr
.__u6_addr32
[3] = htonl(addr6
.__u6_addr
.__u6_addr32
[3]);
659 address
= (char *)&(addr6
.__u6_addr
.__u6_addr32
[0]);
666 if (_lookup_all(_lu_port
, proc
, (unit
*)address
, len
/ BYTES_PER_XDR_UNIT
, &lookup_buf
, &datalen
) != KERN_SUCCESS
)
672 datalen
*= BYTES_PER_XDR_UNIT
;
673 if ((lookup_buf
== NULL
) || (datalen
== 0)) return NULL
;
675 xdrmem_create(&inxdr
, lookup_buf
, datalen
, XDR_DECODE
);
678 if (!xdr_int(&inxdr
, &count
))
681 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
689 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
690 *err
= HOST_NOT_FOUND
;
696 h
= extract_host(&inxdr
, want
, err
);
698 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
703 static struct hostent
*
704 lu_gethostbyname(const char *name
, int want
, int *err
)
707 unsigned int datalen
;
708 char namebuf
[_LU_MAXLUSTRLEN
+ BYTES_PER_XDR_UNIT
];
711 static int proc4
= -1;
712 static int proc6
= -1;
714 int proc
, count
, family
;
717 if (want
> WANT_A4_ONLY
) family
= AF_INET6
;
719 if (((want
== WANT_MAPPED_A4_ONLY
) || (family
== AF_INET
)) && (proc4
< 0))
721 if (_lookup_link(_lu_port
, "gethostbyname", &proc4
) != KERN_SUCCESS
)
727 else if ((family
== AF_INET6
) && (proc6
< 0))
729 if (_lookup_link(_lu_port
, "getipv6nodebyname", &proc6
) != KERN_SUCCESS
)
737 if ((family
== AF_INET6
) && (want
!= WANT_MAPPED_A4_ONLY
)) proc
= proc6
;
739 xdrmem_create(&outxdr
, namebuf
, sizeof(namebuf
), XDR_ENCODE
);
740 if (!xdr__lu_string(&outxdr
, (_lu_string
*)&name
))
742 xdr_destroy(&outxdr
);
750 if (_lookup_all(_lu_port
, proc
, (unit
*)namebuf
, xdr_getpos(&outxdr
) / BYTES_PER_XDR_UNIT
, &lookup_buf
, &datalen
) != KERN_SUCCESS
)
752 xdr_destroy(&outxdr
);
757 xdr_destroy(&outxdr
);
759 datalen
*= BYTES_PER_XDR_UNIT
;
760 if ((lookup_buf
== NULL
) || (datalen
== 0)) return NULL
;
762 xdrmem_create(&inxdr
, lookup_buf
, datalen
, XDR_DECODE
);
765 if (!xdr_int(&inxdr
, &count
))
768 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
776 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
777 *err
= HOST_NOT_FOUND
;
783 h
= extract_host(&inxdr
, want
, err
);
785 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
793 struct lu_thread_info
*tdata
;
795 tdata
= _lu_data_create_key(_lu_data_key_host
, free_lu_thread_info_host
);
796 _lu_data_free_vm_xdr(tdata
);
805 static struct hostent
*
806 lu_gethostent(int want
, int *err
)
808 static int proc
= -1;
809 struct lu_thread_info
*tdata
;
812 tdata
= _lu_data_create_key(_lu_data_key_host
, free_lu_thread_info_host
);
815 tdata
= (struct lu_thread_info
*)calloc(1, sizeof(struct lu_thread_info
));
816 _lu_data_set_key(_lu_data_key_host
, tdata
);
819 if (tdata
->lu_vm
== NULL
)
823 if (_lookup_link(_lu_port
, "gethostent", &proc
) != KERN_SUCCESS
)
831 if (_lookup_all(_lu_port
, proc
, NULL
, 0, &(tdata
->lu_vm
), &(tdata
->lu_vm_length
)) != KERN_SUCCESS
)
838 /* mig stubs measure size in words (4 bytes) */
839 tdata
->lu_vm_length
*= 4;
841 if (tdata
->lu_xdr
!= NULL
)
843 xdr_destroy(tdata
->lu_xdr
);
846 tdata
->lu_xdr
= (XDR
*)calloc(1, sizeof(XDR
));
848 xdrmem_create(tdata
->lu_xdr
, tdata
->lu_vm
, tdata
->lu_vm_length
, XDR_DECODE
);
849 if (!xdr_int(tdata
->lu_xdr
, &tdata
->lu_vm_cursor
))
857 if (tdata
->lu_vm_cursor
== 0)
860 *err
= HOST_NOT_FOUND
;
864 h
= extract_host(tdata
->lu_xdr
, want
, err
);
868 *err
= HOST_NOT_FOUND
;
873 tdata
->lu_vm_cursor
--;
878 static struct hostent
*
879 gethostbyaddrerrno(const char *addr
, int len
, int type
, int *err
)
881 struct hostent
*res
= NULL
;
882 int want
, from_cache
;
887 if (type
== AF_INET6
) want
= WANT_A6_ONLY
;
889 if ((type
== AF_INET6
) && (len
== 16) && (is_a4_mapped((const char *)addr
) || is_a4_compat((const char *)addr
)))
894 want
= WANT_MAPPED_A4_ONLY
;
898 res
= cache_gethostbyaddr(addr
, want
);
904 else if (_lu_running())
906 res
= lu_gethostbyaddr(addr
, want
, err
);
910 pthread_mutex_lock(&_host_lock
);
911 res
= copy_host(_res_gethostbyaddr(addr
, len
, type
));
912 if (res
== NULL
) res
= copy_host(_old_gethostbyaddr(addr
, len
, type
));
914 pthread_mutex_unlock(&_host_lock
);
917 if (from_cache
== 0) cache_host(res
, want
, CACHE_BYADDR
);
923 gethostbyaddr(const char *addr
, int len
, int type
)
926 struct lu_thread_info
*tdata
;
928 res
= gethostbyaddrerrno(addr
, len
, type
, &h_errno
);
934 tdata
= _lu_data_create_key(_lu_data_key_host
, free_lu_thread_info_host
);
937 tdata
= (struct lu_thread_info
*)calloc(1, sizeof(struct lu_thread_info
));
938 _lu_data_set_key(_lu_data_key_host
, tdata
);
941 recycle_host(tdata
, res
);
942 return (struct hostent
*)tdata
->lu_entry
;
946 gethostbynameerrno(const char *name
, int *err
)
948 struct hostent
*res
= NULL
;
950 int i
, is_addr
, from_cache
;
955 * If name is all dots and digits without a trailing dot,
956 * call inet_aton. If it's OK, return a fake entry.
957 * Otherwise, return an error.
959 * If name has alpha or ends with a dot, proceed as usual...
963 *err
= HOST_NOT_FOUND
;
969 *err
= HOST_NOT_FOUND
;
974 for (i
= 0; name
[i
] != '\0'; i
++)
976 if (name
[i
] == '.') continue;
977 if ((name
[i
] >= '0') && (name
[i
] <= '9')) continue;
982 if ((is_addr
== 1) && (name
[i
-1] == '.')) is_addr
= 0;
989 if (inet_aton(name
, &addr
) == 0)
991 *err
= HOST_NOT_FOUND
;
994 res
= fake_hostent(name
, addr
);
999 res
= cache_gethostbyname(name
, WANT_A4_ONLY
);
1006 else if (_lu_running())
1008 res
= lu_gethostbyname(name
, WANT_A4_ONLY
, err
);
1012 pthread_mutex_lock(&_host_lock
);
1013 res
= copy_host(_res_gethostbyname(name
));
1014 if (res
== NULL
) res
= copy_host(_old_gethostbyname(name
));
1016 pthread_mutex_unlock(&_host_lock
);
1021 if (inet_aton(name
, &addr
) == 0)
1023 *err
= HOST_NOT_FOUND
;
1027 res
= gethostbyaddrerrno((char *)&addr
, sizeof(addr
), AF_INET
, err
);
1030 res
= fake_hostent(name
, addr
);
1034 if (from_cache
== 0) cache_host(res
, WANT_A4_ONLY
, CACHE_BYNAME
);
1040 gethostbyname(const char *name
)
1042 struct hostent
*res
;
1043 struct lu_thread_info
*tdata
;
1045 res
= gethostbynameerrno(name
, &h_errno
);
1051 tdata
= _lu_data_create_key(_lu_data_key_host
, free_lu_thread_info_host
);
1054 tdata
= (struct lu_thread_info
*)calloc(1, sizeof(struct lu_thread_info
));
1055 _lu_data_set_key(_lu_data_key_host
, tdata
);
1058 recycle_host(tdata
, res
);
1059 return (struct hostent
*)tdata
->lu_entry
;
1063 gethostbyname2(const char *name
, int af
)
1065 struct hostent
*res
;
1066 struct lu_thread_info
*tdata
;
1068 res
= getipnodebyname(name
, af
, 0, &h_errno
);
1071 errno
= EAFNOSUPPORT
;
1072 h_errno
= NETDB_INTERNAL
;
1076 tdata
= _lu_data_create_key(_lu_data_key_host
, free_lu_thread_info_host
);
1079 tdata
= (struct lu_thread_info
*)calloc(1, sizeof(struct lu_thread_info
));
1080 _lu_data_set_key(_lu_data_key_host
, tdata
);
1083 recycle_host(tdata
, res
);
1084 return (struct hostent
*)tdata
->lu_entry
;
1090 struct hostent
*res
= NULL
;
1091 struct lu_thread_info
*tdata
;
1093 tdata
= _lu_data_create_key(_lu_data_key_host
, free_lu_thread_info_host
);
1096 tdata
= (struct lu_thread_info
*)calloc(1, sizeof(struct lu_thread_info
));
1097 _lu_data_set_key(_lu_data_key_host
, tdata
);
1102 res
= lu_gethostent(WANT_A4_ONLY
, &h_errno
);
1106 pthread_mutex_lock(&_host_lock
);
1107 res
= copy_host(_old_gethostent());
1108 pthread_mutex_unlock(&_host_lock
);
1111 recycle_host(tdata
, res
);
1112 return (struct hostent
*)tdata
->lu_entry
;
1116 sethostent(int stayopen
)
1118 if (_lu_running()) lu_sethostent();
1119 else _old_sethostent(stayopen
);
1125 if (_lu_running()) lu_endhostent();
1126 else _old_endhostent();
1129 __private_extern__
int
1130 is_a4_mapped(const char *s
)
1135 if (s
== NULL
) return 0;
1137 for (i
= 0; i
< 10; i
++)
1140 if (c
!= 0x0) return 0;
1143 for (i
= 10; i
< 12; i
++)
1146 if (c
!= 0xff) return 0;
1152 __private_extern__
int
1153 is_a4_compat(const char *s
)
1158 if (s
== NULL
) return 0;
1160 for (i
= 0; i
< 12; i
++)
1163 if (c
!= 0x0) return 0;
1166 /* Check for :: and ::1 */
1167 for (i
= 13; i
< 15; i
++)
1169 /* anything non-zero in these 3 bytes means it's a V4 address */
1171 if (c
!= 0x0) return 1;
1174 /* Leading 15 bytes are all zero */
1176 if (c
== 0x0) return 0;
1177 if (c
== 0x1) return 0;
1183 getipnodebyaddr(const void *src
, size_t len
, int af
, int *err
)
1185 struct hostent
*res
;
1189 res
= gethostbyaddrerrno((const char *)src
, len
, af
, err
);
1195 if (res
->h_name
== NULL
)
1205 getipnodebyname(const char *name
, int af
, int flags
, int *err
)
1207 int status
, want
, really_want
, if4
, if6
, from_cache
;
1208 struct hostent
*res
;
1209 struct ifaddrs
*ifa
, *ifap
;
1210 struct in_addr addr4
;
1211 struct in6_addr addr6
;
1213 memset(&addr4
, 0, sizeof(struct in_addr
));
1214 memset(&addr6
, 0, sizeof(struct in6_addr
));
1220 status
= inet_aton(name
, &addr4
);
1223 /* return a fake hostent */
1224 res
= fake_hostent(name
, addr4
);
1228 else if (af
== AF_INET6
)
1230 status
= inet_pton(af
, name
, &addr6
);
1233 /* return a fake hostent */
1234 res
= fake_hostent6(name
, addr6
);
1237 status
= inet_aton(name
, &addr4
);
1240 if (!(flags
& (AI_V4MAPPED
|AI_V4MAPPED_CFG
)))
1242 *err
= HOST_NOT_FOUND
;
1246 addr6
.__u6_addr
.__u6_addr32
[0] = 0x00000000;
1247 addr6
.__u6_addr
.__u6_addr32
[1] = 0x00000000;
1248 addr6
.__u6_addr
.__u6_addr32
[2] = htonl(0x0000ffff);
1249 memmove(&(addr6
.__u6_addr
.__u6_addr32
[3]), &(addr4
.s_addr
), IPV4_ADDR_LEN
);
1251 /* return a fake hostent */
1252 res
= fake_hostent6(name
, addr6
);
1263 * IF AI_ADDRCONFIG is set, we need to know what interface flavors we really have.
1269 if (flags
& AI_ADDRCONFIG
)
1271 if (getifaddrs(&ifa
) < 0)
1277 for (ifap
= ifa
; ifap
!= NULL
; ifap
= ifap
->ifa_next
)
1279 if (ifap
->ifa_addr
== NULL
) continue;
1280 if ((ifap
->ifa_flags
& IFF_UP
) == 0) continue;
1281 if (ifap
->ifa_addr
->sa_family
== AF_INET
) if4
++;
1282 else if (ifap
->ifa_addr
->sa_family
== AF_INET6
) if6
++;
1287 /* Bail out if there are no interfaces */
1288 if ((if4
== 0) && (if6
== 0))
1296 * Figure out what we want.
1297 * If user asked for AF_INET, we only want V4 addresses.
1299 want
= WANT_A4_ONLY
;
1304 want
= WANT_A4_ONLY
;
1305 if ((flags
& AI_ADDRCONFIG
) && (if4
== 0))
1313 /* af == AF_INET6 */
1314 want
= WANT_A6_ONLY
;
1316 if (flags
& (AI_V4MAPPED
|AI_V4MAPPED_CFG
))
1320 want
= WANT_A6_PLUS_MAPPED_A4
;
1325 want
= WANT_A6_ONLY
;
1326 really_want
= WANT_A6_OR_MAPPED_A4_IF_NO_A6
;
1331 if ((flags
& AI_ADDRCONFIG
) && (if6
== 0))
1340 res
= cache_gethostbyname(name
, want
);
1346 else if (_lu_running())
1348 res
= lu_gethostbyname(name
, want
, err
);
1349 if ((res
== NULL
) &&
1350 ((really_want
== WANT_A6_OR_MAPPED_A4_IF_NO_A6
) ||
1351 (really_want
== WANT_A6_PLUS_MAPPED_A4
)))
1353 res
= lu_gethostbyname(name
, WANT_MAPPED_A4_ONLY
, err
);
1358 pthread_mutex_lock(&_host_lock
);
1359 res
= copy_host(_res_gethostbyname(name
));
1360 if (res
== NULL
) res
= copy_host(_old_gethostbyname(name
));
1362 pthread_mutex_unlock(&_host_lock
);
1367 *err
= HOST_NOT_FOUND
;
1371 if (from_cache
== 0) cache_host(res
, want
, CACHE_BYNAME
);