2 * Copyright (c) 2002 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 /* async gethostbyXXX function prototypes */
28 #include <netdb_async.h>
31 #include <mach/mach.h>
32 #include <netinfo/_lu_types.h>
33 #include <netinfo/lookup.h>
34 #include <rpc/types.h>
36 #include <sys/socket.h>
37 #include <netinet/in.h>
38 #include <arpa/inet.h>
41 #include <libkern/OSByteOrder.h>
46 extern mach_port_t _lu_port
;
47 extern int _lu_running(void);
51 #define msgh_request_port msgh_remote_port
52 #define msgh_reply_port msgh_local_port
57 gethostbyaddr_async_callback hostAddr
;
58 gethostbyname_async_callback hostName
;
59 getipnodebyaddr_async_callback nodeAddr
;
60 getipnodebyname_async_callback nodeName
;
61 } a_request_callout_t
;
63 typedef struct a_requests
65 struct a_requests
*next
;
74 mach_port_t replyPort
;
75 a_request_callout_t callout
;
77 struct hostent
*hent
; /* if reply known in XXX_start() */
80 static a_requests_t
*a_requests
= NULL
;
81 static pthread_mutex_t a_requests_lock
= PTHREAD_MUTEX_INITIALIZER
;
83 #define MAX_LOOKUP_ATTEMPTS 10
86 _lookup_all_tx(mach_port_t server
, int proc
, ooline_data indata
, mach_msg_type_number_t indataCnt
, mach_port_t
*replyPort
)
90 mach_msg_header_t Head
;
93 mach_msg_type_number_t indataCnt
;
98 register Request
*InP
= &In
;
100 unsigned int msgh_size
;
102 if (indataCnt
> 4096) return MIG_ARRAY_TOO_LARGE
;
104 if (*replyPort
== MACH_PORT_NULL
)
106 mr
= mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE
, replyPort
);
107 if (mr
!= KERN_SUCCESS
) return mr
;
110 msgh_size
= (sizeof(Request
) - 16384) + ((4 * indataCnt
));
111 InP
->Head
.msgh_bits
= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
, MACH_MSG_TYPE_MAKE_SEND_ONCE
);
112 // InP->Head.msgh_size = msgh_size; /* msgh_size passed as argument */
113 InP
->Head
.msgh_request_port
= server
;
114 InP
->Head
.msgh_reply_port
= *replyPort
;
115 InP
->Head
.msgh_id
= 4241776;
116 InP
->NDR
= NDR_record
;
118 InP
->indataCnt
= indataCnt
;
119 memcpy((char *)InP
->indata
, (const char *)indata
, 4 * indataCnt
);
121 mr
= mach_msg(&InP
->Head
, /* msg */
122 MACH_SEND_MSG
, /* options */
123 msgh_size
, /* send_size */
125 MACH_PORT_NULL
, /* rcv_name */
126 MACH_MSG_TIMEOUT_NONE
, /* timeout */
127 MACH_PORT_NULL
); /* notify */
131 case MACH_MSG_SUCCESS
:
134 case MACH_SEND_INVALID_REPLY
:
135 (void)mach_port_mod_refs(mach_task_self(), *replyPort
, MACH_PORT_RIGHT_RECEIVE
, -1);
136 *replyPort
= MACH_PORT_NULL
;
146 _lookup_all_rx(void *msg
, ooline_data
*outdata
, mach_msg_type_number_t
*outdataCnt
, security_token_t
*token
)
150 mach_msg_header_t Head
;
151 mach_msg_body_t msgh_body
;
152 mach_msg_ool_descriptor_t outdata
;
154 mach_msg_type_number_t outdataCnt
;
155 mach_msg_format_0_trailer_t trailer
;
160 * mach_msg_header_t Head;
162 * kern_return_t RetCode;
163 * } mig_reply_error_t;
166 register Reply
*OutP
= msg
;
167 mach_msg_format_0_trailer_t
*TrailerP
;
168 boolean_t msgh_simple
;
170 if (OutP
->Head
.msgh_id
!= (4241776 + 100))
172 if (OutP
->Head
.msgh_id
== MACH_NOTIFY_SEND_ONCE
) return MIG_SERVER_DIED
;
173 else return MIG_REPLY_MISMATCH
;
176 msgh_simple
= !(OutP
->Head
.msgh_bits
& MACH_MSGH_BITS_COMPLEX
);
178 TrailerP
= (mach_msg_format_0_trailer_t
*)((vm_offset_t
)OutP
+ round_msg(OutP
->Head
.msgh_size
));
179 if (TrailerP
->msgh_trailer_type
!= MACH_MSG_TRAILER_FORMAT_0
) return MIG_TRAILER_ERROR
;
181 if (OutP
->NDR
.int_rep
!= NDR_record
.int_rep
)
185 ((mig_reply_error_t
*)OutP
)->RetCode
= OSReadSwapInt32(&(((mig_reply_error_t
*)OutP
)->RetCode
), 0);
189 OutP
->outdataCnt
= OSReadSwapInt32(&(OutP
->outdataCnt
), 0);
193 if (msgh_simple
&& ((mig_reply_error_t
*)OutP
)->RetCode
!= KERN_SUCCESS
) return ((mig_reply_error_t
*)OutP
)->RetCode
;
195 *outdata
= (ooline_data
)(OutP
->outdata
.address
);
196 *outdataCnt
= OutP
->outdataCnt
;
198 *token
= TrailerP
->msgh_sender
;
203 static a_requests_t
*
204 request_extract(mach_port_t port
)
206 a_requests_t
*request0
, *request
;
208 pthread_mutex_lock(&a_requests_lock
);
211 request
= a_requests
;
213 while (request
!= NULL
)
215 if (port
== request
->replyPort
)
217 /* request found, remove from list */
218 if (request0
!= NULL
)
220 request0
->next
= request
->next
;
224 a_requests
= request
->next
;
231 /* not this request, skip to next */
233 request
= request
->next
;
237 pthread_mutex_unlock(&a_requests_lock
);
243 request_queue(a_requests_t
*request
)
245 pthread_mutex_lock(&a_requests_lock
);
247 request
->next
= a_requests
;
248 a_requests
= request
;
250 pthread_mutex_unlock(&a_requests_lock
);
256 sendCannedReply(a_requests_t
*request
, int *error
)
260 * mach_msg_header_t Head;
262 * kern_return_t RetCode;
263 * } mig_reply_error_t;
266 mig_reply_error_t Out
;
267 register mig_reply_error_t
*OutP
= &Out
;
269 mach_msg_return_t mr
;
270 unsigned int msgh_size
;
272 mach_port_t sendPort
;
273 mach_msg_type_name_t sendType
;
276 * allocate reply port
278 kr
= mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE
, &request
->replyPort
);
279 if (kr
!= KERN_SUCCESS
)
281 *error
= NO_RECOVERY
;
285 kr
= mach_port_extract_right(mach_task_self(), request
->replyPort
, MACH_MSG_TYPE_MAKE_SEND_ONCE
, &sendPort
, &sendType
);
286 if (kr
!= KERN_SUCCESS
)
288 (void)mach_port_destroy(mach_task_self(), request
->replyPort
);
289 request
->replyPort
= MACH_PORT_NULL
;
290 *error
= NO_RECOVERY
;
295 * queue reply message
297 msgh_size
= sizeof(Out
);
298 OutP
->Head
.msgh_bits
= MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE
, 0);
299 // OutP->Head.msgh_size = msgh_size; /* msgh_size passed as argument */
300 OutP
->Head
.msgh_request_port
= sendPort
;
301 OutP
->Head
.msgh_reply_port
= MACH_PORT_NULL
;
302 OutP
->Head
.msgh_id
= 4241776 + 100;
303 OutP
->RetCode
= MIG_REMOTE_ERROR
;
304 OutP
->NDR
= NDR_record
;
306 mr
= mach_msg(&OutP
->Head
, MACH_SEND_MSG
, msgh_size
, 0, MACH_PORT_NULL
, MACH_MSG_TIMEOUT_NONE
, MACH_PORT_NULL
);
307 if (mr
!= MACH_MSG_SUCCESS
)
309 if (mr
== MACH_SEND_INVALID_REPLY
)
311 (void)mach_port_destroy(mach_task_self(), request
->replyPort
);
312 request
->replyPort
= MACH_PORT_NULL
;
315 *error
= NO_RECOVERY
;
323 _async_cancel(mach_port_t port
)
325 a_requests_t
*request
;
327 request
= request_extract(port
);
330 (void)mach_port_mod_refs(mach_task_self(), request
->replyPort
, MACH_PORT_RIGHT_RECEIVE
, -1);
331 if (request
->request
.data
) free(request
->request
.data
);
332 if (request
->hent
) freehostent(request
->hent
);
340 _gethostbyaddr_async_start(const char *addr
, int len
, int type
, a_request_callout_t callout
, void *context
, int *error
)
344 a_requests_t
*request
;
346 static int proc4
= -1;
347 struct in_addr
*v4addr
;
348 static int proc6
= -1;
349 struct in6_addr
*v6addr
;
352 if (type
== AF_INET6
) want
= WANT_A6_ONLY
;
354 if ((type
== AF_INET6
) && (len
== 16) && (is_a4_mapped((const char *)addr
) || is_a4_compat((const char *)addr
)))
359 want
= WANT_MAPPED_A4_ONLY
;
368 if (_lookup_link(_lu_port
, "gethostbyaddr", &proc4
) != KERN_SUCCESS
)
370 *error
= NO_RECOVERY
;
371 return MACH_PORT_NULL
;
375 if (len
!= sizeof(struct in_addr
))
377 *error
= NO_RECOVERY
;
381 v4addr
= malloc(len
);
382 memmove(v4addr
, addr
, len
);
383 v4addr
->s_addr
= htonl(v4addr
->s_addr
);
385 address
= (void *)v4addr
;
394 if (_lookup_link(_lu_port
, "getipv6nodebyaddr", &proc6
) != KERN_SUCCESS
)
396 *error
= NO_RECOVERY
;
397 return MACH_PORT_NULL
;
401 if (len
!= sizeof(struct in6_addr
))
403 *error
= NO_RECOVERY
;
407 v6addr
= malloc(len
);
408 memmove(v6addr
, addr
, len
);
409 v6addr
->__u6_addr
.__u6_addr32
[0] = htonl(v6addr
->__u6_addr
.__u6_addr32
[0]);
410 v6addr
->__u6_addr
.__u6_addr32
[1] = htonl(v6addr
->__u6_addr
.__u6_addr32
[1]);
411 v6addr
->__u6_addr
.__u6_addr32
[2] = htonl(v6addr
->__u6_addr
.__u6_addr32
[2]);
412 v6addr
->__u6_addr
.__u6_addr32
[3] = htonl(v6addr
->__u6_addr
.__u6_addr32
[3]);
414 address
= (void *)v6addr
;
420 *error
= NO_RECOVERY
;
421 return MACH_PORT_NULL
;
424 request
= malloc(sizeof(a_requests_t
));
425 request
->next
= NULL
;
426 request
->retry
= MAX_LOOKUP_ATTEMPTS
;
427 request
->request
.proc
= proc
;
428 request
->request
.data
= (ooline_data
)address
;
429 request
->request
.dataLen
= len
/ BYTES_PER_XDR_UNIT
;
430 request
->request
.want
= want
;
431 request
->replyPort
= MACH_PORT_NULL
;
432 request
->callout
= callout
;
433 request
->context
= context
;
434 request
->hent
= NULL
;
437 * allocate reply port, send query to lookupd
439 if (_lookup_all_tx(_lu_port
, request
->request
.proc
, request
->request
.data
, request
->request
.dataLen
, &request
->replyPort
) == KERN_SUCCESS
)
441 request_queue(request
);
445 if (request
->request
.data
) free(request
->request
.data
);
447 *error
= NO_RECOVERY
;
448 return MACH_PORT_NULL
;
451 return request
->replyPort
;
455 _gethostbyaddr_async_handleReply(void *replyMsg
, a_requests_t
**requestP
, struct hostent
**he
, int *error
)
459 unsigned int datalen
;
461 mach_msg_header_t
*msg
= (mach_msg_header_t
*)replyMsg
;
462 a_requests_t
*request
;
463 kern_return_t status
;
464 security_token_t token
;
466 request
= request_extract(msg
->msgh_local_port
);
469 /* excuse me, what happenned to the request info? */
477 /* unpack the reply */
478 status
= _lookup_all_rx(replyMsg
, &data
, &datalen
, &token
);
484 case MIG_SERVER_DIED
:
485 if (--request
->retry
> 0)
487 /* retry the request */
488 if (_lookup_all_tx(_lu_port
, request
->request
.proc
, request
->request
.data
, request
->request
.dataLen
, &request
->replyPort
) == KERN_SUCCESS
)
490 request_queue(request
);
497 *error
= HOST_NOT_FOUND
;
501 datalen
*= BYTES_PER_XDR_UNIT
;
503 if (token
.val
[0] != 0)
505 vm_deallocate(mach_task_self(), (vm_address_t
)data
, datalen
);
506 *error
= NO_RECOVERY
;
510 xdrmem_create(&inxdr
, data
, datalen
, XDR_DECODE
);
513 if (!xdr_int(&inxdr
, &count
))
516 vm_deallocate(mach_task_self(), (vm_address_t
)data
, datalen
);
517 *error
= NO_RECOVERY
;
524 vm_deallocate(mach_task_self(), (vm_address_t
)data
, datalen
);
525 *error
= HOST_NOT_FOUND
;
530 *he
= extract_host(&inxdr
, request
->request
.want
, error
);
532 vm_deallocate(mach_task_self(), (vm_address_t
)data
, datalen
);
537 gethostbyaddr_async_start(const char *addr
, int len
, int type
, gethostbyaddr_async_callback callout
, void *context
)
539 a_request_callout_t cb
;
544 h_errno
= NO_RECOVERY
;
545 return MACH_PORT_NULL
;
548 cb
.hostAddr
= callout
;
549 mp
= _gethostbyaddr_async_start(addr
, len
, type
, cb
, context
, &h_errno
);
554 gethostbyaddr_async_cancel(mach_port_t port
)
561 gethostbyaddr_async_handleReply(void *replyMsg
)
564 struct hostent
*he
= NULL
;
565 a_requests_t
*request
= NULL
;
567 if (_gethostbyaddr_async_handleReply(replyMsg
, &request
, &he
, &error
))
569 /* if we have an answer to provide */
571 (request
->callout
.hostAddr
)(he
, request
->context
);
573 (void)mach_port_mod_refs(mach_task_self(), request
->replyPort
, MACH_PORT_RIGHT_RECEIVE
, -1);
574 if (request
->request
.data
) free(request
->request
.data
);
576 if (he
!= NULL
) freehostent(he
);
583 getipnodebyaddr_async_start(const void *addr
, size_t len
, int af
, int *error
, getipnodebyaddr_async_callback callout
, void *context
)
585 a_request_callout_t cb
;
590 *error
= NO_RECOVERY
;
591 return MACH_PORT_NULL
;
594 cb
.nodeAddr
= callout
;
595 mp
= _gethostbyaddr_async_start(addr
, len
, af
, cb
, context
, error
);
600 getipnodebyaddr_async_cancel(mach_port_t port
)
607 getipnodebyaddr_async_handleReply(void *replyMsg
)
610 struct hostent
*he
= NULL
;
611 a_requests_t
*request
= NULL
;
613 if (_gethostbyaddr_async_handleReply(replyMsg
, &request
, &he
, &error
))
615 /* if we have an answer to provide */
616 (request
->callout
.nodeAddr
)(he
, error
, request
->context
);
618 (void)mach_port_mod_refs(mach_task_self(), request
->replyPort
, MACH_PORT_RIGHT_RECEIVE
, -1);
619 if (request
->request
.data
) free(request
->request
.data
);
622 * Note: it is up to the callback function to call
631 _gethostbyname_async_start(const char *name
, int want
, int *error
, a_request_callout_t callout
, void *context
)
634 boolean_t is_addr
= FALSE
;
635 mach_port_t mp
= MACH_PORT_NULL
;
638 a_requests_t
*request
;
639 static int proc4
= -1;
640 static int proc6
= -1;
641 struct in_addr v4addr
;
642 struct in6_addr v6addr
;
644 if ((name
== NULL
) || (name
[0] == '\0'))
647 return MACH_PORT_NULL
;
650 af
= (want
== WANT_A4_ONLY
) ? AF_INET
: AF_INET6
;
652 if ((af
== AF_INET
) || (want
== WANT_MAPPED_A4_ONLY
))
656 if (_lookup_link(_lu_port
, "gethostbyname", &proc4
) != KERN_SUCCESS
)
658 *error
= NO_RECOVERY
;
659 return MACH_PORT_NULL
;
664 else /* if (af == AF_INET6) */
668 if (_lookup_link(_lu_port
, "getipv6nodebyname", &proc6
) != KERN_SUCCESS
)
670 *error
= NO_RECOVERY
;
671 return MACH_PORT_NULL
;
677 request
= malloc(sizeof(a_requests_t
));
678 request
->next
= NULL
;
679 request
->retry
= MAX_LOOKUP_ATTEMPTS
;
680 request
->request
.proc
= proc
;
681 request
->request
.data
= NULL
;
682 request
->request
.dataLen
= 0;
683 request
->request
.want
= want
;
684 request
->replyPort
= MACH_PORT_NULL
;
685 request
->callout
= callout
;
686 request
->context
= context
;
687 request
->hent
= NULL
;
693 memset(&v4addr
, 0, sizeof(struct in_addr
));
694 if (inet_aton(name
, &v4addr
) == 1)
696 /* return a fake hostent */
697 request
->hent
= fake_hostent(name
, v4addr
);
705 memset(&v6addr
, 0, sizeof(struct in6_addr
));
706 if (inet_pton(af
, name
, &v6addr
) == 1)
708 /* return a fake hostent */
709 request
->hent
= fake_hostent6(name
, v6addr
);
714 memset(&v4addr
, 0, sizeof(struct in_addr
));
715 if (inet_aton(name
, &v4addr
) == 1)
717 if (want
== WANT_A4_ONLY
)
720 *error
= HOST_NOT_FOUND
;
721 return MACH_PORT_NULL
;
724 v6addr
.__u6_addr
.__u6_addr32
[0] = 0x00000000;
725 v6addr
.__u6_addr
.__u6_addr32
[1] = 0x00000000;
726 v6addr
.__u6_addr
.__u6_addr32
[2] = htonl(0x0000ffff);
727 memmove(&(v6addr
.__u6_addr
.__u6_addr32
[3]), &(v4addr
.s_addr
), sizeof(struct in_addr
));
729 /* return a fake hostent */
730 request
->hent
= fake_hostent6(name
, v6addr
);
738 *error
= NO_RECOVERY
;
739 return MACH_PORT_NULL
;
745 * queue reply message
747 if (sendCannedReply(request
, error
))
749 request_queue(request
);
750 return request
->replyPort
;
754 freehostent(request
->hent
);
756 return MACH_PORT_NULL
;
760 request
->request
.dataLen
= _LU_MAXLUSTRLEN
+ BYTES_PER_XDR_UNIT
;
761 request
->request
.data
= malloc(request
->request
.dataLen
);
763 xdrmem_create(&outxdr
, request
->request
.data
, request
->request
.dataLen
, XDR_ENCODE
);
764 if (!xdr__lu_string(&outxdr
, (_lu_string
*)&name
))
766 xdr_destroy(&outxdr
);
767 free(request
->request
.data
);
769 *error
= NO_RECOVERY
;
770 return MACH_PORT_NULL
;
773 request
->request
.dataLen
= xdr_getpos(&outxdr
) / BYTES_PER_XDR_UNIT
;
776 * allocate reply port, send query to lookupd
778 if (_lookup_all_tx(_lu_port
, request
->request
.proc
, request
->request
.data
, request
->request
.dataLen
, &request
->replyPort
) == KERN_SUCCESS
)
780 request_queue(request
);
781 mp
= request
->replyPort
;
785 free(request
->request
.data
);
787 *error
= NO_RECOVERY
;
791 xdr_destroy(&outxdr
);
796 _gethostbyname_async_handleReply(void *replyMsg
, a_requests_t
**requestP
, struct hostent
**he
, int *error
)
799 unsigned int datalen
;
802 mach_msg_header_t
*msg
= (mach_msg_header_t
*)replyMsg
;
803 a_requests_t
*request
;
804 kern_return_t status
;
805 security_token_t token
;
808 request
= request_extract(msg
->msgh_local_port
);
811 /* excuse me, what happenned to the request info? */
822 * if the reply was already available when the
829 /* unpack the reply */
830 status
= _lookup_all_rx(replyMsg
, &data
, &datalen
, &token
);
836 case MIG_SERVER_DIED
:
837 if (--request
->retry
> 0)
842 if (_lookup_all_tx(_lu_port
, request
->request
.proc
, request
->request
.data
, request
->request
.dataLen
, &request
->replyPort
) == KERN_SUCCESS
)
844 request_queue(request
);
851 *error
= HOST_NOT_FOUND
;
855 datalen
*= BYTES_PER_XDR_UNIT
;
857 if (token
.val
[0] != 0)
859 vm_deallocate(mach_task_self(), (vm_address_t
)data
, datalen
);
860 *error
= NO_RECOVERY
;
864 xdrmem_create(&inxdr
, data
, datalen
, XDR_DECODE
);
867 if (!xdr_int(&inxdr
, &count
))
870 vm_deallocate(mach_task_self(), (vm_address_t
)data
, datalen
);
871 *error
= NO_RECOVERY
;
878 vm_deallocate(mach_task_self(), (vm_address_t
)data
, datalen
);
879 *error
= HOST_NOT_FOUND
;
883 want
= request
->request
.want
;
884 if (want
== WANT_A6_OR_MAPPED_A4_IF_NO_A6
) want
= WANT_A6_ONLY
;
886 *he
= extract_host(&inxdr
, want
, error
);
888 vm_deallocate(mach_task_self(), (vm_address_t
)data
, datalen
);
893 gethostbyname_async_start(const char *name
, gethostbyname_async_callback callout
, void *context
)
895 a_request_callout_t cb
;
897 mach_port_t mp
= MACH_PORT_NULL
;
901 h_errno
= NO_RECOVERY
;
902 return MACH_PORT_NULL
;
905 cb
.hostName
= callout
;
906 mp
= _gethostbyname_async_start(name
, WANT_A4_ONLY
, &error
, cb
, context
);
907 if (mp
== MACH_PORT_NULL
)
916 gethostbyname_async_cancel(mach_port_t port
)
923 gethostbyname_async_handleReply(void *replyMsg
)
927 a_requests_t
*request
;
929 if (_gethostbyname_async_handleReply(replyMsg
, &request
, &he
, &error
))
931 /* if we have an answer to provide */
933 (request
->callout
.hostAddr
)(he
, request
->context
);
935 (void)mach_port_mod_refs(mach_task_self(), request
->replyPort
, MACH_PORT_RIGHT_RECEIVE
, -1);
936 if (request
->request
.data
) free(request
->request
.data
);
938 if (he
!= NULL
) freehostent(he
);
945 getipnodebyname_async_start(const char *name
, int af
, int flags
, int *error
, getipnodebyname_async_callback callout
, void *context
)
947 a_request_callout_t cb
;
950 mach_port_t mp
= MACH_PORT_NULL
;
951 int want
= WANT_A4_ONLY
;
952 struct ifaddrs
*ifa
, *ifap
;
956 h_errno
= NO_RECOVERY
;
957 return MACH_PORT_NULL
;
961 * IF AI_ADDRCONFIG is set, we need to know what interface flavors we really have.
963 if (flags
& AI_ADDRCONFIG
)
965 if (getifaddrs(&ifa
) < 0)
967 *error
= NO_RECOVERY
;
968 return MACH_PORT_NULL
;
971 for (ifap
= ifa
; ifap
!= NULL
; ifap
= ifap
->ifa_next
)
973 if (ifap
->ifa_addr
== NULL
) continue;
974 if ((ifap
->ifa_flags
& IFF_UP
) == 0) continue;
975 if (ifap
->ifa_addr
->sa_family
== AF_INET
)
979 else if (ifap
->ifa_addr
->sa_family
== AF_INET6
)
987 /* Bail out if there are no interfaces */
988 if ((if4
== 0) && (if6
== 0))
991 return MACH_PORT_NULL
;
996 * Figure out what we want.
997 * If user asked for AF_INET, we only want V4 addresses.
1003 want
= WANT_A4_ONLY
;
1004 if ((flags
& AI_ADDRCONFIG
) && (if4
== 0))
1006 *error
= NO_ADDRESS
;
1007 return MACH_PORT_NULL
;
1014 want
= WANT_A6_ONLY
;
1015 if (flags
& (AI_V4MAPPED
|AI_V4MAPPED_CFG
))
1019 want
= WANT_A6_PLUS_MAPPED_A4
;
1023 want
= WANT_A6_OR_MAPPED_A4_IF_NO_A6
;
1028 if ((flags
& AI_ADDRCONFIG
) && (if6
== 0))
1030 *error
= NO_ADDRESS
;
1031 return MACH_PORT_NULL
;
1038 cb
.nodeName
= callout
;
1039 mp
= _gethostbyname_async_start(name
, want
, &h_errno
, cb
, context
);
1044 getipnodebyname_async_cancel(mach_port_t port
)
1046 _async_cancel(port
);
1051 getipnodebyname_async_handleReply(void *replyMsg
)
1054 struct hostent
*he
= NULL
;
1055 a_requests_t
*request
= NULL
;
1056 static int proc4
= -1;
1058 if (_gethostbyname_async_handleReply(replyMsg
, &request
, &he
, &error
))
1061 * we have an answer to provide
1063 if ((he
== NULL
) && (error
== HOST_NOT_FOUND
) && ((request
->request
.want
== WANT_A6_PLUS_MAPPED_A4
) || (request
->request
.want
== WANT_A6_OR_MAPPED_A4_IF_NO_A6
)))
1066 * no host found (yet), if requested we send a
1067 * followup query to lookupd.
1071 if (_lookup_link(_lu_port
, "gethostbyname", &proc4
) != KERN_SUCCESS
)
1073 error
= NO_RECOVERY
;
1078 request
->request
.proc
= proc4
;
1079 request
->request
.want
= WANT_MAPPED_A4_ONLY
;
1080 if (_lookup_all_tx(_lu_port
, request
->request
.proc
, request
->request
.data
, request
->request
.dataLen
, &request
->replyPort
) == KERN_SUCCESS
)
1082 request_queue(request
);
1087 error
= NO_RECOVERY
;
1092 (request
->callout
.nodeName
)(he
, error
, request
->context
);
1093 (void)mach_port_mod_refs(mach_task_self(), request
->replyPort
, MACH_PORT_RIGHT_RECEIVE
, -1);
1094 if (request
->request
.data
!= NULL
) free(request
->request
.data
);
1097 * Note: it is up to the callback function to call