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 addr4
.s_addr
= htonl(addr4
.s_addr
);
653 address
= (char *)&(addr4
.s_addr
);
658 memmove(&(addr6
.__u6_addr
.__u6_addr32
[0]), addr
, IPV6_ADDR_LEN
);
659 addr6
.__u6_addr
.__u6_addr32
[0] = htonl(addr6
.__u6_addr
.__u6_addr32
[0]);
660 addr6
.__u6_addr
.__u6_addr32
[1] = htonl(addr6
.__u6_addr
.__u6_addr32
[1]);
661 addr6
.__u6_addr
.__u6_addr32
[2] = htonl(addr6
.__u6_addr
.__u6_addr32
[2]);
662 addr6
.__u6_addr
.__u6_addr32
[3] = htonl(addr6
.__u6_addr
.__u6_addr32
[3]);
663 address
= (char *)&(addr6
.__u6_addr
.__u6_addr32
[0]);
670 if (_lookup_all(_lu_port
, proc
, (unit
*)address
, len
/ BYTES_PER_XDR_UNIT
, &lookup_buf
, &datalen
) != KERN_SUCCESS
)
672 *err
= HOST_NOT_FOUND
;
676 datalen
*= BYTES_PER_XDR_UNIT
;
677 if ((lookup_buf
== NULL
) || (datalen
== 0)) return NULL
;
679 xdrmem_create(&inxdr
, lookup_buf
, datalen
, XDR_DECODE
);
682 if (!xdr_int(&inxdr
, &count
))
685 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
693 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
694 *err
= HOST_NOT_FOUND
;
700 h
= extract_host(&inxdr
, want
, err
);
702 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
707 static struct hostent
*
708 lu_gethostbyname(const char *name
, int want
, int *err
)
711 unsigned int datalen
;
712 char namebuf
[_LU_MAXLUSTRLEN
+ BYTES_PER_XDR_UNIT
];
715 static int proc4
= -1;
716 static int proc6
= -1;
718 int proc
, count
, family
;
721 if (want
> WANT_A4_ONLY
) family
= AF_INET6
;
723 if (((want
== WANT_MAPPED_A4_ONLY
) || (family
== AF_INET
)) && (proc4
< 0))
725 if (_lookup_link(_lu_port
, "gethostbyname", &proc4
) != KERN_SUCCESS
)
731 else if ((family
== AF_INET6
) && (proc6
< 0))
733 if (_lookup_link(_lu_port
, "getipv6nodebyname", &proc6
) != KERN_SUCCESS
)
741 if ((family
== AF_INET6
) && (want
!= WANT_MAPPED_A4_ONLY
)) proc
= proc6
;
743 xdrmem_create(&outxdr
, namebuf
, sizeof(namebuf
), XDR_ENCODE
);
744 if (!xdr__lu_string(&outxdr
, (_lu_string
*)&name
))
746 xdr_destroy(&outxdr
);
754 if (_lookup_all(_lu_port
, proc
, (unit
*)namebuf
, xdr_getpos(&outxdr
) / BYTES_PER_XDR_UNIT
, &lookup_buf
, &datalen
) != KERN_SUCCESS
)
756 xdr_destroy(&outxdr
);
757 *err
= HOST_NOT_FOUND
;
761 xdr_destroy(&outxdr
);
763 datalen
*= BYTES_PER_XDR_UNIT
;
764 if ((lookup_buf
== NULL
) || (datalen
== 0)) return NULL
;
766 xdrmem_create(&inxdr
, lookup_buf
, datalen
, XDR_DECODE
);
769 if (!xdr_int(&inxdr
, &count
))
772 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
780 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
781 *err
= HOST_NOT_FOUND
;
787 h
= extract_host(&inxdr
, want
, err
);
789 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
797 struct lu_thread_info
*tdata
;
799 tdata
= _lu_data_create_key(_lu_data_key_host
, free_lu_thread_info_host
);
800 _lu_data_free_vm_xdr(tdata
);
809 static struct hostent
*
810 lu_gethostent(int want
, int *err
)
812 static int proc
= -1;
813 struct lu_thread_info
*tdata
;
816 tdata
= _lu_data_create_key(_lu_data_key_host
, free_lu_thread_info_host
);
819 tdata
= (struct lu_thread_info
*)calloc(1, sizeof(struct lu_thread_info
));
820 _lu_data_set_key(_lu_data_key_host
, tdata
);
823 if (tdata
->lu_vm
== NULL
)
827 if (_lookup_link(_lu_port
, "gethostent", &proc
) != KERN_SUCCESS
)
835 if (_lookup_all(_lu_port
, proc
, NULL
, 0, &(tdata
->lu_vm
), &(tdata
->lu_vm_length
)) != KERN_SUCCESS
)
838 *err
= HOST_NOT_FOUND
;
842 /* mig stubs measure size in words (4 bytes) */
843 tdata
->lu_vm_length
*= 4;
845 if (tdata
->lu_xdr
!= NULL
)
847 xdr_destroy(tdata
->lu_xdr
);
850 tdata
->lu_xdr
= (XDR
*)calloc(1, sizeof(XDR
));
852 xdrmem_create(tdata
->lu_xdr
, tdata
->lu_vm
, tdata
->lu_vm_length
, XDR_DECODE
);
853 if (!xdr_int(tdata
->lu_xdr
, &tdata
->lu_vm_cursor
))
861 if (tdata
->lu_vm_cursor
== 0)
864 *err
= HOST_NOT_FOUND
;
868 h
= extract_host(tdata
->lu_xdr
, want
, err
);
872 *err
= HOST_NOT_FOUND
;
877 tdata
->lu_vm_cursor
--;
882 static struct hostent
*
883 gethostbyaddrerrno(const char *addr
, int len
, int type
, int *err
)
885 struct hostent
*res
= NULL
;
886 int want
, from_cache
;
891 if (type
== AF_INET6
) want
= WANT_A6_ONLY
;
893 if ((type
== AF_INET6
) && (len
== 16) && (is_a4_mapped((const char *)addr
) || is_a4_compat((const char *)addr
)))
898 want
= WANT_MAPPED_A4_ONLY
;
902 res
= cache_gethostbyaddr(addr
, want
);
908 else if (_lu_running())
910 res
= lu_gethostbyaddr(addr
, want
, err
);
914 pthread_mutex_lock(&_host_lock
);
915 res
= copy_host(_old_gethostbyaddr(addr
, len
, type
));
917 pthread_mutex_unlock(&_host_lock
);
920 if (from_cache
== 0) cache_host(res
, want
, CACHE_BYADDR
);
926 gethostbyaddr(const void *addr
, socklen_t len
, int type
)
929 struct lu_thread_info
*tdata
;
931 res
= gethostbyaddrerrno(addr
, len
, type
, &h_errno
);
937 tdata
= _lu_data_create_key(_lu_data_key_host
, free_lu_thread_info_host
);
940 tdata
= (struct lu_thread_info
*)calloc(1, sizeof(struct lu_thread_info
));
941 _lu_data_set_key(_lu_data_key_host
, tdata
);
944 recycle_host(tdata
, res
);
945 return (struct hostent
*)tdata
->lu_entry
;
949 gethostbynameerrno(const char *name
, int *err
)
951 struct hostent
*res
= NULL
;
953 int i
, is_addr
, from_cache
;
958 * If name is all dots and digits without a trailing dot,
959 * call inet_aton. If it's OK, return a fake entry.
960 * Otherwise, return an error.
962 * If name has alpha or ends with a dot, proceed as usual...
966 *err
= HOST_NOT_FOUND
;
972 *err
= HOST_NOT_FOUND
;
977 for (i
= 0; name
[i
] != '\0'; i
++)
979 if (name
[i
] == '.') continue;
980 if ((name
[i
] >= '0') && (name
[i
] <= '9')) continue;
985 if ((is_addr
== 1) && (name
[i
-1] == '.')) is_addr
= 0;
992 if (inet_aton(name
, &addr
) == 0)
994 *err
= HOST_NOT_FOUND
;
997 res
= fake_hostent(name
, addr
);
1002 res
= cache_gethostbyname(name
, WANT_A4_ONLY
);
1009 else if (_lu_running())
1011 res
= lu_gethostbyname(name
, WANT_A4_ONLY
, err
);
1015 pthread_mutex_lock(&_host_lock
);
1016 res
= copy_host(_old_gethostbyname(name
));
1018 pthread_mutex_unlock(&_host_lock
);
1023 if (inet_aton(name
, &addr
) == 0)
1025 *err
= HOST_NOT_FOUND
;
1029 res
= gethostbyaddrerrno((char *)&addr
, sizeof(addr
), AF_INET
, err
);
1032 res
= fake_hostent(name
, addr
);
1036 if (from_cache
== 0) cache_host(res
, WANT_A4_ONLY
, CACHE_BYNAME
);
1042 gethostbyname(const char *name
)
1044 struct hostent
*res
;
1045 struct lu_thread_info
*tdata
;
1047 res
= gethostbynameerrno(name
, &h_errno
);
1053 tdata
= _lu_data_create_key(_lu_data_key_host
, free_lu_thread_info_host
);
1056 tdata
= (struct lu_thread_info
*)calloc(1, sizeof(struct lu_thread_info
));
1057 _lu_data_set_key(_lu_data_key_host
, tdata
);
1060 recycle_host(tdata
, res
);
1061 return (struct hostent
*)tdata
->lu_entry
;
1065 gethostbyname2(const char *name
, int af
)
1067 struct hostent
*res
;
1068 struct lu_thread_info
*tdata
;
1070 res
= getipnodebyname(name
, af
, 0, &h_errno
);
1073 errno
= EAFNOSUPPORT
;
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(_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
);
1377 * Given a host's name, this routine returns its 48 bit ethernet address.
1378 * Returns zero if successful, non-zero otherwise.
1381 lu_ether_hostton(const char *host
, struct ether_addr
*e
)
1383 unsigned int i
, n
, j
, x
[6];
1384 ni_proplist
*q
, **r
;
1387 if (host
== NULL
) return -1;
1388 if (e
== NULL
) return -1;
1390 q
= lookupd_make_query("2", "kvk", "name", host
, "en_address");
1391 if (q
== NULL
) return -1;
1393 n
= lookupd_query(q
, &r
);
1394 ni_proplist_free(q
);
1397 if (n
== 0) return -1;
1398 if (r
[0] == NULL
) return -1;
1400 i
= ni_proplist_match(*r
[0], "en_address", NULL
);
1401 if (i
== (unsigned int)NI_INDEX_NULL
) return -1;
1403 if (r
[0]->ni_proplist_val
[i
].nip_val
.ni_namelist_len
== 0) return -1;
1405 s
= r
[0]->ni_proplist_val
[i
].nip_val
.ni_namelist_val
[0];
1406 j
= sscanf(s
, " %x:%x:%x:%x:%x:%x", &x
[0], &x
[1], &x
[2], &x
[3], &x
[4], &x
[5]);
1409 for (i
= 0; i
< n
; i
++)
1411 ni_proplist_free(r
[i
]);
1418 for (i
= 0; i
< 6; i
++) e
->ether_addr_octet
[i
] = x
[i
];
1420 for (i
= 0; i
< n
; i
++)
1422 ni_proplist_free(r
[i
]);
1431 * Given a 48 bit ethernet address, this routine return its host name.
1432 * Returns zero if successful, non-zero otherwise.
1435 lu_ether_ntohost(char *host
, const struct ether_addr
*e
)
1437 unsigned int i
, n
, len
, x
[6];
1438 ni_proplist
*q
, **r
;
1441 if (host
== NULL
) return -1;
1442 if (e
== NULL
) return -1;
1444 for (i
= 0; i
< 6; i
++) x
[i
] = e
->ether_addr_octet
[i
];
1445 sprintf(str
, "%x:%x:%x:%x:%x:%x", x
[0], x
[1], x
[2], x
[3], x
[4], x
[5]);
1447 q
= lookupd_make_query("2", "kv", "en_address", str
);
1448 if (q
== NULL
) return -1;
1450 n
= lookupd_query(q
, &r
);
1451 ni_proplist_free(q
);
1453 if (n
== 0) return -1;
1454 if (r
[0] == NULL
) return -1;
1456 i
= ni_proplist_match(*r
[0], "name", NULL
);
1457 if (i
== (unsigned int)NI_INDEX_NULL
) return -1;
1459 if (r
[0]->ni_proplist_val
[i
].nip_val
.ni_namelist_len
== 0) return -1;
1461 len
= strlen(r
[0]->ni_proplist_val
[i
].nip_val
.ni_namelist_val
[0]) + 1;
1462 memcpy(host
, r
[0]->ni_proplist_val
[i
].nip_val
.ni_namelist_val
[0], len
);
1464 for (i
= 0; i
< n
; i
++) ni_proplist_free(r
[i
]);
1470 ether_hostton(const char *host
, struct ether_addr
*e
)
1472 if (_lu_running()) return lu_ether_hostton(host
, e
);
1473 return _old_ether_hostton(host
, e
);
1477 ether_ntohost(char *host
, const struct ether_addr
*e
)
1479 if (_lu_running()) return lu_ether_ntohost(host
, e
);
1480 return _old_ether_ntohost(host
, e
);