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 <sys/types.h>
40 #include <netinet/if_ether.h>
42 #include "_lu_types.h"
47 #define HOST_CACHE_SIZE 10
48 #define DEFAULT_HOST_CACHE_TTL 10
50 #define CACHE_BYNAME 0
51 #define CACHE_BYADDR 1
53 static pthread_mutex_t _host_cache_lock
= PTHREAD_MUTEX_INITIALIZER
;
54 static unsigned int _host_cache_ttl
= DEFAULT_HOST_CACHE_TTL
;
56 static void *_host_byname_cache
[HOST_CACHE_SIZE
] = { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
};
57 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
};
58 static unsigned int _host_byname_cache_best_before
[HOST_CACHE_SIZE
] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
59 static unsigned int _host_byname_cache_index
= 0;
61 static void *_host_byaddr_cache
[HOST_CACHE_SIZE
] = { NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
};
62 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
};
63 static unsigned int _host_byaddr_cache_best_before
[HOST_CACHE_SIZE
] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
64 static unsigned int _host_byaddr_cache_index
= 0;
66 static pthread_mutex_t _host_lock
= PTHREAD_MUTEX_INITIALIZER
;
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 int _old_ether_hostton(const char *, struct ether_addr
*);
76 extern int _old_ether_ntohost(char *, const struct ether_addr
*);
78 extern mach_port_t _lu_port
;
79 extern int _lu_running(void);
83 #define IPV6_ADDR_LEN 16
84 #define IPV4_ADDR_LEN 4
86 __private_extern__
void
87 free_host_data(struct hostent
*h
)
92 if (h
== NULL
) return;
94 if (h
->h_name
!= NULL
) free(h
->h_name
);
96 aliases
= h
->h_aliases
;
99 while (*aliases
!= NULL
) free(*aliases
++);
103 if (h
->h_addr_list
!= NULL
)
105 for (i
= 0; h
->h_addr_list
[i
] != NULL
; i
++) free(h
->h_addr_list
[i
]);
106 free(h
->h_addr_list
);
111 freehostent(struct hostent
*h
)
113 if (h
== NULL
) return;
119 free_lu_thread_info_host(void *x
)
121 struct lu_thread_info
*tdata
;
123 if (x
== NULL
) return;
125 tdata
= (struct lu_thread_info
*)x
;
127 if (tdata
->lu_entry
!= NULL
)
129 freehostent((struct hostent
*)tdata
->lu_entry
);
130 tdata
->lu_entry
= NULL
;
133 _lu_data_free_vm_xdr(tdata
);
138 __private_extern__
struct hostent
*
139 extract_host(XDR
*xdr
, int want
, int *err
)
142 int i
, j
, nvals
, nkeys
, status
, addr_len
;
143 int family
, addr_count
, map_count
;
145 struct in6_addr addr6
;
146 char *key
, **vals
, **mapvals
;
151 addr_len
= sizeof(u_long
*);
159 if (!xdr_int(xdr
, &nkeys
))
165 h
= (struct hostent
*)calloc(1, sizeof(struct hostent
));
168 h
->h_length
= IPV4_ADDR_LEN
;
170 if (want
> WANT_A4_ONLY
)
173 h
->h_length
= IPV6_ADDR_LEN
;
176 h
->h_addrtype
= family
;
178 for (i
= 0; i
< nkeys
; i
++)
184 status
= _lu_xdr_attribute(xdr
, &key
, &vals
, &nvals
);
200 if ((h
->h_name
== NULL
) && (!strcmp("name", key
)))
205 h
->h_aliases
= (char **)calloc(nvals
, sizeof(char *));
206 for (j
= 1; j
< nvals
; j
++) h
->h_aliases
[j
-1] = vals
[j
];
210 else if ((family
== AF_INET
) && (h
->h_addr_list
== NULL
) && (!strcmp("ip_address", key
)))
213 h
->h_addr_list
= (char **)calloc(nvals
+ 1, addr_len
);
215 for (j
= 0; j
< nvals
; j
++)
218 inet_aton(vals
[j
], &addr
);
219 h
->h_addr_list
[j
] = (char *)calloc(1, IPV4_ADDR_LEN
);
220 memmove(h
->h_addr_list
[j
], &(addr
.s_addr
), IPV4_ADDR_LEN
);
223 h
->h_addr_list
[nvals
] = NULL
;
226 else if ((family
== AF_INET6
) && (h
->h_addr_list
== NULL
) && (!strcmp("ipv6_address", key
)))
229 h
->h_addr_list
= (char **)calloc(nvals
+ 1, addr_len
);
231 for (j
= 0; j
< nvals
; j
++)
233 memset(&addr6
, 0, sizeof(struct in6_addr
));
234 inet_pton(family
, vals
[j
], &addr6
);
235 h
->h_addr_list
[j
] = (char *)calloc(1, IPV6_ADDR_LEN
);
236 memmove(h
->h_addr_list
[j
], &(addr6
.__u6_addr
.__u6_addr32
[0]), IPV6_ADDR_LEN
);
239 h
->h_addr_list
[nvals
] = NULL
;
242 else if ((family
== AF_INET6
) && (mapvals
== NULL
) && (!strcmp("ip_address", key
)))
252 for (; j
< nvals
; j
++) free(vals
[j
]);
257 if ((mapvals
!= NULL
) && (want
> WANT_A6_ONLY
))
259 addr6
.__u6_addr
.__u6_addr32
[0] = 0x00000000;
260 addr6
.__u6_addr
.__u6_addr32
[1] = 0x00000000;
261 addr6
.__u6_addr
.__u6_addr32
[2] = htonl(0x0000ffff);
265 h
->h_addr_list
= (char **)calloc(map_count
+ 1, addr_len
);
269 h
->h_addr_list
= (char **)realloc(h
->h_addr_list
, (addr_count
+ map_count
+ 1) * addr_len
);
272 for (i
= 0; i
< map_count
; i
++)
275 inet_aton(mapvals
[i
], &addr
);
276 h
->h_addr_list
[addr_count
] = (char *)calloc(1, IPV6_ADDR_LEN
);
277 memmove(&(addr6
.__u6_addr
.__u6_addr32
[3]), &(addr
.s_addr
), IPV4_ADDR_LEN
);
278 memcpy(h
->h_addr_list
[addr_count
++], &(addr6
.__u6_addr
.__u6_addr32
[0]), IPV6_ADDR_LEN
);
281 h
->h_addr_list
[addr_count
] = NULL
;
286 for (i
= 0; i
< map_count
; i
++) free(mapvals
[i
]);
290 if (h
->h_addr_list
== NULL
)
297 if (h
->h_name
== NULL
) h
->h_name
= strdup("");
298 if (h
->h_aliases
== NULL
) h
->h_aliases
= (char **)calloc(1, sizeof(char *));
303 static struct hostent
*
304 copy_host(struct hostent
*in
)
306 int i
, len
, addr_len
;
309 if (in
== NULL
) return NULL
;
311 h
= (struct hostent
*)calloc(1, sizeof(struct hostent
));
313 h
->h_name
= LU_COPY_STRING(in
->h_name
);
316 if (in
->h_aliases
!= NULL
)
318 for (len
= 0; in
->h_aliases
[len
] != NULL
; len
++);
321 h
->h_aliases
= (char **)calloc(len
+ 1, sizeof(char *));
322 for (i
= 0; i
< len
; i
++)
324 h
->h_aliases
[i
] = strdup(in
->h_aliases
[i
]);
327 h
->h_addrtype
= in
->h_addrtype
;
328 h
->h_length
= in
->h_length
;
331 if (in
->h_addr_list
!= NULL
)
333 for (len
= 0; in
->h_addr_list
[len
] != NULL
; len
++);
336 addr_len
= sizeof(u_long
*);
337 h
->h_addr_list
= (char **)calloc(len
+ 1, addr_len
);
338 for (i
= 0; i
< len
; i
++)
340 h
->h_addr_list
[i
] = (char *)malloc(h
->h_length
);
341 memmove(h
->h_addr_list
[i
], in
->h_addr_list
[i
], h
->h_length
);
348 recycle_host(struct lu_thread_info
*tdata
, struct hostent
*in
)
352 if (tdata
== NULL
) return;
353 h
= (struct hostent
*)tdata
->lu_entry
;
358 tdata
->lu_entry
= NULL
;
361 if (tdata
->lu_entry
== NULL
)
363 tdata
->lu_entry
= in
;
369 h
->h_name
= in
->h_name
;
370 h
->h_aliases
= in
->h_aliases
;
371 h
->h_addrtype
= in
->h_addrtype
;
372 h
->h_length
= in
->h_length
;
373 h
->h_addr_list
= in
->h_addr_list
;
378 __private_extern__
struct hostent
*
379 fake_hostent(const char *name
, struct in_addr addr
)
384 if (name
== NULL
) return NULL
;
386 h
= (struct hostent
*)calloc(1, sizeof(struct hostent
));
388 h
->h_name
= strdup(name
);
390 h
->h_aliases
= (char **)calloc(1, sizeof(char *));
392 h
->h_addrtype
= AF_INET
;
393 h
->h_length
= sizeof(long);
395 addr_len
= sizeof(u_long
*);
396 h
->h_addr_list
= (char **)calloc(2, addr_len
);
398 h
->h_addr_list
[0] = (char *)malloc(h
->h_length
);
399 memmove(h
->h_addr_list
[0], &(addr
.s_addr
), h
->h_length
);
404 __private_extern__
struct hostent
*
405 fake_hostent6(const char *name
, struct in6_addr addr
)
410 if (name
== NULL
) return NULL
;
412 h
= (struct hostent
*)calloc(1, sizeof(struct hostent
));
414 h
->h_name
= strdup(name
);
416 h
->h_aliases
= (char **)calloc(1, sizeof(char *));
418 h
->h_addrtype
= AF_INET6
;
421 addr_len
= sizeof(u_long
*);
422 h
->h_addr_list
= (char **)calloc(2, addr_len
);
424 h
->h_addr_list
[0] = (char *)malloc(h
->h_length
);
425 memmove(h
->h_addr_list
[0], &(addr
.__u6_addr
.__u6_addr32
[0]), h
->h_length
);
430 __private_extern__
unsigned int
433 return _host_cache_ttl
;
436 __private_extern__
void
437 set_host_cache_ttl(unsigned int ttl
)
441 pthread_mutex_lock(&_host_cache_lock
);
443 _host_cache_ttl
= ttl
;
447 for (i
= 0; i
< HOST_CACHE_SIZE
; i
++)
449 if (_host_byname_cache
[i
] == NULL
) continue;
451 freehostent((struct hostent
*)_host_byname_cache
[i
]);
452 _host_byname_cache
[i
] = NULL
;
453 _host_byname_cache_flavor
[i
] = WANT_NOTHING
;
454 _host_byname_cache_best_before
[i
] = 0;
457 for (i
= 0; i
< HOST_CACHE_SIZE
; i
++)
459 if (_host_byaddr_cache
[i
] == NULL
) continue;
461 freehostent((struct hostent
*)_host_byaddr_cache
[i
]);
462 _host_byaddr_cache
[i
] = NULL
;
463 _host_byaddr_cache_flavor
[i
] = WANT_NOTHING
;
464 _host_byaddr_cache_best_before
[i
] = 0;
468 pthread_mutex_unlock(&_host_cache_lock
);
472 cache_host(struct hostent
*h
, int want
, int how
)
475 struct hostent
*hcache
;
477 if (_host_cache_ttl
== 0) return;
478 if (h
== NULL
) return;
480 pthread_mutex_lock(&_host_cache_lock
);
482 hcache
= copy_host(h
);
484 gettimeofday(&now
, NULL
);
486 if (how
== CACHE_BYNAME
)
488 if (_host_byname_cache
[_host_byname_cache_index
] != NULL
)
489 freehostent((struct hostent
*)_host_byname_cache
[_host_byname_cache_index
]);
491 _host_byname_cache
[_host_byname_cache_index
] = hcache
;
492 _host_byname_cache_flavor
[_host_byname_cache_index
] = want
;
493 _host_byname_cache_best_before
[_host_byname_cache_index
] = now
.tv_sec
+ _host_cache_ttl
;
494 _host_byname_cache_index
= (_host_byname_cache_index
+ 1) % HOST_CACHE_SIZE
;
498 if (_host_byaddr_cache
[_host_byaddr_cache_index
] != NULL
)
499 freehostent((struct hostent
*)_host_byaddr_cache
[_host_byaddr_cache_index
]);
501 _host_byaddr_cache
[_host_byaddr_cache_index
] = hcache
;
502 _host_byaddr_cache_flavor
[_host_byaddr_cache_index
] = want
;
503 _host_byaddr_cache_best_before
[_host_byaddr_cache_index
] = now
.tv_sec
+ _host_cache_ttl
;
504 _host_byaddr_cache_index
= (_host_byaddr_cache_index
+ 1) % HOST_CACHE_SIZE
;
507 pthread_mutex_unlock(&_host_cache_lock
);
510 static struct hostent
*
511 cache_gethostbyname(const char *name
, int want
)
514 struct hostent
*h
, *res
;
518 if (_host_cache_ttl
== 0) return NULL
;
519 if (name
== NULL
) return NULL
;
521 pthread_mutex_lock(&_host_cache_lock
);
523 gettimeofday(&now
, NULL
);
525 for (i
= 0; i
< HOST_CACHE_SIZE
; i
++)
527 if (_host_byname_cache_best_before
[i
] == 0) continue;
528 if ((unsigned int)now
.tv_sec
> _host_byname_cache_best_before
[i
]) continue;
530 if (_host_byname_cache_flavor
[i
] != want
) continue;
532 h
= (struct hostent
*)_host_byname_cache
[i
];
534 if (h
->h_name
!= NULL
)
536 if (!strcmp(name
, h
->h_name
))
539 pthread_mutex_unlock(&_host_cache_lock
);
544 aliases
= h
->h_aliases
;
547 pthread_mutex_unlock(&_host_cache_lock
);
551 for (; *aliases
!= NULL
; *aliases
++)
553 if (!strcmp(name
, *aliases
))
556 pthread_mutex_unlock(&_host_cache_lock
);
562 pthread_mutex_unlock(&_host_cache_lock
);
566 static struct hostent
*
567 cache_gethostbyaddr(const char *addr
, int want
)
570 struct hostent
*h
, *res
;
573 if (addr
== NULL
) return NULL
;
574 if (_host_cache_ttl
== 0) return NULL
;
576 pthread_mutex_lock(&_host_cache_lock
);
578 gettimeofday(&now
, NULL
);
581 if (want
> WANT_A4_ONLY
) len
= IPV6_ADDR_LEN
;
583 for (i
= 0; i
< HOST_CACHE_SIZE
; i
++)
585 if (_host_byaddr_cache_best_before
[i
] == 0) continue;
586 if ((unsigned int)now
.tv_sec
> _host_byaddr_cache_best_before
[i
]) continue;
588 if (_host_byaddr_cache_flavor
[i
] != want
) continue;
590 h
= (struct hostent
*)_host_byaddr_cache
[i
];
592 if (h
->h_addr_list
== NULL
) continue;
594 for (j
= 0; h
->h_addr_list
[j
] != NULL
; j
++)
596 if (memcmp(addr
, h
->h_addr_list
[j
], len
) == 0)
599 pthread_mutex_unlock(&_host_cache_lock
);
605 pthread_mutex_unlock(&_host_cache_lock
);
609 static struct hostent
*
610 lu_gethostbyaddr(const char *addr
, int want
, int *err
)
613 unsigned int datalen
;
615 static int proc4
= -1;
616 static int proc6
= -1;
617 char *lookup_buf
, *address
;
618 int proc
, count
, len
, family
;
619 struct in_addr addr4
;
620 struct in6_addr addr6
;
624 if ((want
== WANT_A6_ONLY
) || (want
== WANT_A6_PLUS_MAPPED_A4
))
630 if ((family
== AF_INET
) && (proc4
< 0))
632 if (_lookup_link(_lu_port
, "gethostbyaddr", &proc4
) != KERN_SUCCESS
)
638 else if ((family
== AF_INET6
) && (proc6
< 0))
640 if (_lookup_link(_lu_port
, "getipv6nodebyaddr", &proc6
) != KERN_SUCCESS
)
649 if (family
== AF_INET
)
651 memmove(&(addr4
.s_addr
), addr
, IPV4_ADDR_LEN
);
652 address
= (char *)&(addr4
.s_addr
);
657 memmove(&(addr6
.__u6_addr
.__u6_addr32
[0]), addr
, IPV6_ADDR_LEN
);
658 addr6
.__u6_addr
.__u6_addr32
[0] = htonl(addr6
.__u6_addr
.__u6_addr32
[0]);
659 addr6
.__u6_addr
.__u6_addr32
[1] = htonl(addr6
.__u6_addr
.__u6_addr32
[1]);
660 addr6
.__u6_addr
.__u6_addr32
[2] = htonl(addr6
.__u6_addr
.__u6_addr32
[2]);
661 addr6
.__u6_addr
.__u6_addr32
[3] = htonl(addr6
.__u6_addr
.__u6_addr32
[3]);
662 address
= (char *)&(addr6
.__u6_addr
.__u6_addr32
[0]);
669 if (_lookup_all(_lu_port
, proc
, (unit
*)address
, len
/ BYTES_PER_XDR_UNIT
, &lookup_buf
, &datalen
) != KERN_SUCCESS
)
671 *err
= HOST_NOT_FOUND
;
675 datalen
*= BYTES_PER_XDR_UNIT
;
676 if ((lookup_buf
== NULL
) || (datalen
== 0)) return NULL
;
678 xdrmem_create(&inxdr
, lookup_buf
, datalen
, XDR_DECODE
);
681 if (!xdr_int(&inxdr
, &count
))
684 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
692 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
693 *err
= HOST_NOT_FOUND
;
699 h
= extract_host(&inxdr
, want
, err
);
701 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
706 static struct hostent
*
707 lu_gethostbyname(const char *name
, int want
, int *err
)
710 unsigned int datalen
;
711 char namebuf
[_LU_MAXLUSTRLEN
+ BYTES_PER_XDR_UNIT
];
714 static int proc4
= -1;
715 static int proc6
= -1;
717 int proc
, count
, family
;
720 if (want
> WANT_A4_ONLY
) family
= AF_INET6
;
722 if (((want
== WANT_MAPPED_A4_ONLY
) || (family
== AF_INET
)) && (proc4
< 0))
724 if (_lookup_link(_lu_port
, "gethostbyname", &proc4
) != KERN_SUCCESS
)
730 else if ((family
== AF_INET6
) && (proc6
< 0))
732 if (_lookup_link(_lu_port
, "getipv6nodebyname", &proc6
) != KERN_SUCCESS
)
740 if ((family
== AF_INET6
) && (want
!= WANT_MAPPED_A4_ONLY
)) proc
= proc6
;
742 xdrmem_create(&outxdr
, namebuf
, sizeof(namebuf
), XDR_ENCODE
);
743 if (!xdr__lu_string(&outxdr
, (_lu_string
*)&name
))
745 xdr_destroy(&outxdr
);
753 if (_lookup_all(_lu_port
, proc
, (unit
*)namebuf
, xdr_getpos(&outxdr
) / BYTES_PER_XDR_UNIT
, &lookup_buf
, &datalen
) != KERN_SUCCESS
)
755 xdr_destroy(&outxdr
);
756 *err
= HOST_NOT_FOUND
;
760 xdr_destroy(&outxdr
);
762 datalen
*= BYTES_PER_XDR_UNIT
;
763 if ((lookup_buf
== NULL
) || (datalen
== 0)) return NULL
;
765 xdrmem_create(&inxdr
, lookup_buf
, datalen
, XDR_DECODE
);
768 if (!xdr_int(&inxdr
, &count
))
771 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
779 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
780 *err
= HOST_NOT_FOUND
;
786 h
= extract_host(&inxdr
, want
, err
);
788 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
796 struct lu_thread_info
*tdata
;
798 tdata
= _lu_data_create_key(_lu_data_key_host
, free_lu_thread_info_host
);
799 _lu_data_free_vm_xdr(tdata
);
808 static struct hostent
*
809 lu_gethostent(int want
, int *err
)
811 static int proc
= -1;
812 struct lu_thread_info
*tdata
;
815 tdata
= _lu_data_create_key(_lu_data_key_host
, free_lu_thread_info_host
);
818 tdata
= (struct lu_thread_info
*)calloc(1, sizeof(struct lu_thread_info
));
819 _lu_data_set_key(_lu_data_key_host
, tdata
);
822 if (tdata
->lu_vm
== NULL
)
826 if (_lookup_link(_lu_port
, "gethostent", &proc
) != KERN_SUCCESS
)
834 if (_lookup_all(_lu_port
, proc
, NULL
, 0, &(tdata
->lu_vm
), &(tdata
->lu_vm_length
)) != KERN_SUCCESS
)
837 *err
= HOST_NOT_FOUND
;
841 /* mig stubs measure size in words (4 bytes) */
842 tdata
->lu_vm_length
*= 4;
844 if (tdata
->lu_xdr
!= NULL
)
846 xdr_destroy(tdata
->lu_xdr
);
849 tdata
->lu_xdr
= (XDR
*)calloc(1, sizeof(XDR
));
851 xdrmem_create(tdata
->lu_xdr
, tdata
->lu_vm
, tdata
->lu_vm_length
, XDR_DECODE
);
852 if (!xdr_int(tdata
->lu_xdr
, &tdata
->lu_vm_cursor
))
860 if (tdata
->lu_vm_cursor
== 0)
863 *err
= HOST_NOT_FOUND
;
867 h
= extract_host(tdata
->lu_xdr
, want
, err
);
871 *err
= HOST_NOT_FOUND
;
876 tdata
->lu_vm_cursor
--;
881 static struct hostent
*
882 gethostbyaddrerrno(const char *addr
, int len
, int type
, int *err
)
884 struct hostent
*res
= NULL
;
885 int want
, from_cache
;
890 if (type
== AF_INET6
) want
= WANT_A6_ONLY
;
892 if ((type
== AF_INET6
) && (len
== 16) && (is_a4_mapped((const char *)addr
) || is_a4_compat((const char *)addr
)))
897 want
= WANT_MAPPED_A4_ONLY
;
901 res
= cache_gethostbyaddr(addr
, want
);
907 else if (_lu_running())
909 res
= lu_gethostbyaddr(addr
, want
, err
);
913 pthread_mutex_lock(&_host_lock
);
914 res
= copy_host(_old_gethostbyaddr(addr
, len
, type
));
916 pthread_mutex_unlock(&_host_lock
);
919 if (from_cache
== 0) cache_host(res
, want
, CACHE_BYADDR
);
925 gethostbyaddr(const void *addr
, socklen_t len
, int type
)
928 struct lu_thread_info
*tdata
;
930 res
= gethostbyaddrerrno(addr
, len
, type
, &h_errno
);
936 tdata
= _lu_data_create_key(_lu_data_key_host
, free_lu_thread_info_host
);
939 tdata
= (struct lu_thread_info
*)calloc(1, sizeof(struct lu_thread_info
));
940 _lu_data_set_key(_lu_data_key_host
, tdata
);
943 recycle_host(tdata
, res
);
944 return (struct hostent
*)tdata
->lu_entry
;
948 gethostbynameerrno(const char *name
, int *err
)
950 struct hostent
*res
= NULL
;
952 int i
, is_addr
, from_cache
;
957 * If name is all dots and digits without a trailing dot,
958 * call inet_aton. If it's OK, return a fake entry.
959 * Otherwise, return an error.
961 * If name has alpha or ends with a dot, proceed as usual...
965 *err
= HOST_NOT_FOUND
;
971 *err
= HOST_NOT_FOUND
;
976 for (i
= 0; name
[i
] != '\0'; i
++)
978 if (name
[i
] == '.') continue;
979 if ((name
[i
] >= '0') && (name
[i
] <= '9')) continue;
984 if ((is_addr
== 1) && (name
[i
-1] == '.')) is_addr
= 0;
991 if (inet_aton(name
, &addr
) == 0)
993 *err
= HOST_NOT_FOUND
;
996 res
= fake_hostent(name
, addr
);
1001 res
= cache_gethostbyname(name
, WANT_A4_ONLY
);
1008 else if (_lu_running())
1010 res
= lu_gethostbyname(name
, WANT_A4_ONLY
, err
);
1014 pthread_mutex_lock(&_host_lock
);
1015 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
;
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(_old_gethostbyname(name
));
1361 pthread_mutex_unlock(&_host_lock
);
1366 *err
= HOST_NOT_FOUND
;
1370 if (from_cache
== 0) cache_host(res
, want
, CACHE_BYNAME
);
1376 * Given a host's name, this routine returns its 48 bit ethernet address.
1377 * Returns zero if successful, non-zero otherwise.
1380 lu_ether_hostton(const char *host
, struct ether_addr
*e
)
1382 unsigned int i
, n
, j
, x
[6];
1383 ni_proplist
*q
, **r
;
1386 if (host
== NULL
) return -1;
1387 if (e
== NULL
) return -1;
1389 q
= lookupd_make_query("2", "kvk", "name", host
, "en_address");
1390 if (q
== NULL
) return -1;
1392 n
= lookupd_query(q
, &r
);
1393 ni_proplist_free(q
);
1396 if (n
== 0) return -1;
1397 if (r
[0] == NULL
) return -1;
1399 i
= ni_proplist_match(*r
[0], "en_address", NULL
);
1400 if (i
== (unsigned int)NI_INDEX_NULL
) return -1;
1402 if (r
[0]->ni_proplist_val
[i
].nip_val
.ni_namelist_len
== 0) return -1;
1404 s
= r
[0]->ni_proplist_val
[i
].nip_val
.ni_namelist_val
[0];
1405 j
= sscanf(s
, " %x:%x:%x:%x:%x:%x", &x
[0], &x
[1], &x
[2], &x
[3], &x
[4], &x
[5]);
1408 for (i
= 0; i
< n
; i
++)
1410 ni_proplist_free(r
[i
]);
1417 for (i
= 0; i
< 6; i
++) e
->ether_addr_octet
[i
] = x
[i
];
1419 for (i
= 0; i
< n
; i
++)
1421 ni_proplist_free(r
[i
]);
1430 * Given a 48 bit ethernet address, this routine return its host name.
1431 * Returns zero if successful, non-zero otherwise.
1434 lu_ether_ntohost(char *host
, const struct ether_addr
*e
)
1436 unsigned int i
, n
, len
, x
[6];
1437 ni_proplist
*q
, **r
;
1440 if (host
== NULL
) return -1;
1441 if (e
== NULL
) return -1;
1443 for (i
= 0; i
< 6; i
++) x
[i
] = e
->ether_addr_octet
[i
];
1444 sprintf(str
, "%x:%x:%x:%x:%x:%x", x
[0], x
[1], x
[2], x
[3], x
[4], x
[5]);
1446 q
= lookupd_make_query("2", "kv", "en_address", str
);
1447 if (q
== NULL
) return -1;
1449 n
= lookupd_query(q
, &r
);
1450 ni_proplist_free(q
);
1452 if (n
== 0) return -1;
1453 if (r
[0] == NULL
) return -1;
1455 i
= ni_proplist_match(*r
[0], "name", NULL
);
1456 if (i
== (unsigned int)NI_INDEX_NULL
) return -1;
1458 if (r
[0]->ni_proplist_val
[i
].nip_val
.ni_namelist_len
== 0) return -1;
1460 len
= strlen(r
[0]->ni_proplist_val
[i
].nip_val
.ni_namelist_val
[0]) + 1;
1461 memcpy(host
, r
[0]->ni_proplist_val
[i
].nip_val
.ni_namelist_val
[0], len
);
1463 for (i
= 0; i
< n
; i
++) ni_proplist_free(r
[i
]);
1469 ether_hostton(const char *host
, struct ether_addr
*e
)
1471 if (_lu_running()) return lu_ether_hostton(host
, e
);
1472 return _old_ether_hostton(host
, e
);
1476 ether_ntohost(char *host
, const struct ether_addr
*e
)
1478 if (_lu_running()) return lu_ether_ntohost(host
, e
);
1479 return _old_ether_ntohost(host
, e
);