2 * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Portions Copyright (c) 2002 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 /* async gethostbyXXX function prototypes */
27 #include <netdb_async.h>
30 #include <mach/mach.h>
31 #include <netinfo/_lu_types.h>
32 #include <netinfo/lookup.h>
33 #include <rpc/types.h>
35 #include <sys/socket.h>
36 #include <netinet/in.h>
37 #include <arpa/inet.h>
40 #include <libkern/OSByteOrder.h>
45 extern mach_port_t _lu_port
;
46 extern int _lu_running(void);
50 #define msgh_request_port msgh_remote_port
51 #define msgh_reply_port msgh_local_port
56 gethostbyaddr_async_callback hostAddr
;
57 gethostbyname_async_callback hostName
;
58 getipnodebyaddr_async_callback nodeAddr
;
59 getipnodebyname_async_callback nodeName
;
60 } a_request_callout_t
;
62 typedef struct a_requests
64 struct a_requests
*next
;
73 mach_port_t replyPort
;
74 a_request_callout_t callout
;
76 struct hostent
*hent
; /* if reply known in XXX_start() */
79 static a_requests_t
*a_requests
= NULL
;
80 static pthread_mutex_t a_requests_lock
= PTHREAD_MUTEX_INITIALIZER
;
82 #define MAX_LOOKUP_ATTEMPTS 10
85 _lookup_all_tx(mach_port_t server
, int proc
, ooline_data indata
, mach_msg_type_number_t indataCnt
, mach_port_t
*replyPort
)
89 mach_msg_header_t Head
;
92 mach_msg_type_number_t indataCnt
;
97 register Request
*InP
= &In
;
99 unsigned int msgh_size
;
101 if (indataCnt
> 4096) return MIG_ARRAY_TOO_LARGE
;
103 if (*replyPort
== MACH_PORT_NULL
)
105 mr
= mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE
, replyPort
);
106 if (mr
!= KERN_SUCCESS
) return mr
;
109 msgh_size
= (sizeof(Request
) - 16384) + ((4 * indataCnt
));
110 InP
->Head
.msgh_bits
= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
, MACH_MSG_TYPE_MAKE_SEND_ONCE
);
111 // InP->Head.msgh_size = msgh_size; /* msgh_size passed as argument */
112 InP
->Head
.msgh_request_port
= server
;
113 InP
->Head
.msgh_reply_port
= *replyPort
;
114 InP
->Head
.msgh_id
= 4241776;
115 InP
->NDR
= NDR_record
;
117 InP
->indataCnt
= indataCnt
;
118 memcpy((char *)InP
->indata
, (const char *)indata
, 4 * indataCnt
);
120 mr
= mach_msg(&InP
->Head
, /* msg */
121 MACH_SEND_MSG
, /* options */
122 msgh_size
, /* send_size */
124 MACH_PORT_NULL
, /* rcv_name */
125 MACH_MSG_TIMEOUT_NONE
, /* timeout */
126 MACH_PORT_NULL
); /* notify */
130 case MACH_MSG_SUCCESS
:
133 case MACH_SEND_INVALID_REPLY
:
134 (void)mach_port_mod_refs(mach_task_self(), *replyPort
, MACH_PORT_RIGHT_RECEIVE
, -1);
135 *replyPort
= MACH_PORT_NULL
;
145 _lookup_all_rx(void *msg
, ooline_data
*outdata
, mach_msg_type_number_t
*outdataCnt
, security_token_t
*token
)
149 mach_msg_header_t Head
;
150 mach_msg_body_t msgh_body
;
151 mach_msg_ool_descriptor_t outdata
;
153 mach_msg_type_number_t outdataCnt
;
154 mach_msg_format_0_trailer_t trailer
;
159 * mach_msg_header_t Head;
161 * kern_return_t RetCode;
162 * } mig_reply_error_t;
165 register Reply
*OutP
= msg
;
166 mach_msg_format_0_trailer_t
*TrailerP
;
167 boolean_t msgh_simple
;
169 if (OutP
->Head
.msgh_id
!= (4241776 + 100))
171 if (OutP
->Head
.msgh_id
== MACH_NOTIFY_SEND_ONCE
) return MIG_SERVER_DIED
;
172 else return MIG_REPLY_MISMATCH
;
175 msgh_simple
= !(OutP
->Head
.msgh_bits
& MACH_MSGH_BITS_COMPLEX
);
177 TrailerP
= (mach_msg_format_0_trailer_t
*)((vm_offset_t
)OutP
+ round_msg(OutP
->Head
.msgh_size
));
178 if (TrailerP
->msgh_trailer_type
!= MACH_MSG_TRAILER_FORMAT_0
) return MIG_TRAILER_ERROR
;
180 if (OutP
->NDR
.int_rep
!= NDR_record
.int_rep
)
184 ((mig_reply_error_t
*)OutP
)->RetCode
= OSReadSwapInt32(&(((mig_reply_error_t
*)OutP
)->RetCode
), 0);
188 OutP
->outdataCnt
= OSReadSwapInt32(&(OutP
->outdataCnt
), 0);
192 if (msgh_simple
&& ((mig_reply_error_t
*)OutP
)->RetCode
!= KERN_SUCCESS
) return ((mig_reply_error_t
*)OutP
)->RetCode
;
194 *outdata
= (ooline_data
)(OutP
->outdata
.address
);
195 *outdataCnt
= OutP
->outdataCnt
;
197 *token
= TrailerP
->msgh_sender
;
202 static a_requests_t
*
203 request_extract(mach_port_t port
)
205 a_requests_t
*request0
, *request
;
207 pthread_mutex_lock(&a_requests_lock
);
210 request
= a_requests
;
212 while (request
!= NULL
)
214 if (port
== request
->replyPort
)
216 /* request found, remove from list */
217 if (request0
!= NULL
)
219 request0
->next
= request
->next
;
223 a_requests
= request
->next
;
230 /* not this request, skip to next */
232 request
= request
->next
;
236 pthread_mutex_unlock(&a_requests_lock
);
242 request_queue(a_requests_t
*request
)
244 pthread_mutex_lock(&a_requests_lock
);
246 request
->next
= a_requests
;
247 a_requests
= request
;
249 pthread_mutex_unlock(&a_requests_lock
);
255 sendCannedReply(a_requests_t
*request
, int *error
)
259 * mach_msg_header_t Head;
261 * kern_return_t RetCode;
262 * } mig_reply_error_t;
265 mig_reply_error_t Out
;
266 register mig_reply_error_t
*OutP
= &Out
;
268 mach_msg_return_t mr
;
269 unsigned int msgh_size
;
271 mach_port_t sendPort
;
272 mach_msg_type_name_t sendType
;
275 * allocate reply port
277 kr
= mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE
, &request
->replyPort
);
278 if (kr
!= KERN_SUCCESS
)
280 *error
= NO_RECOVERY
;
284 kr
= mach_port_extract_right(mach_task_self(), request
->replyPort
, MACH_MSG_TYPE_MAKE_SEND_ONCE
, &sendPort
, &sendType
);
285 if (kr
!= KERN_SUCCESS
)
287 (void)mach_port_destroy(mach_task_self(), request
->replyPort
);
288 request
->replyPort
= MACH_PORT_NULL
;
289 *error
= NO_RECOVERY
;
294 * queue reply message
296 msgh_size
= sizeof(Out
);
297 OutP
->Head
.msgh_bits
= MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE
, 0);
298 // OutP->Head.msgh_size = msgh_size; /* msgh_size passed as argument */
299 OutP
->Head
.msgh_request_port
= sendPort
;
300 OutP
->Head
.msgh_reply_port
= MACH_PORT_NULL
;
301 OutP
->Head
.msgh_id
= 4241776 + 100;
302 OutP
->RetCode
= MIG_REMOTE_ERROR
;
303 OutP
->NDR
= NDR_record
;
305 mr
= mach_msg(&OutP
->Head
, MACH_SEND_MSG
, msgh_size
, 0, MACH_PORT_NULL
, MACH_MSG_TIMEOUT_NONE
, MACH_PORT_NULL
);
306 if (mr
!= MACH_MSG_SUCCESS
)
308 if (mr
== MACH_SEND_INVALID_REPLY
)
310 (void)mach_port_destroy(mach_task_self(), request
->replyPort
);
311 request
->replyPort
= MACH_PORT_NULL
;
314 *error
= NO_RECOVERY
;
322 _async_cancel(mach_port_t port
)
324 a_requests_t
*request
;
326 request
= request_extract(port
);
329 (void)mach_port_mod_refs(mach_task_self(), request
->replyPort
, MACH_PORT_RIGHT_RECEIVE
, -1);
330 if (request
->request
.data
) free(request
->request
.data
);
331 if (request
->hent
) freehostent(request
->hent
);
339 _gethostbyaddr_async_start(const char *addr
, int len
, int type
, a_request_callout_t callout
, void *context
, int *error
)
343 a_requests_t
*request
;
345 static int proc4
= -1;
346 struct in_addr
*v4addr
;
347 static int proc6
= -1;
348 struct in6_addr
*v6addr
;
351 if (type
== AF_INET6
) want
= WANT_A6_ONLY
;
353 if ((type
== AF_INET6
) && (len
== 16) && (is_a4_mapped((const char *)addr
) || is_a4_compat((const char *)addr
)))
358 want
= WANT_MAPPED_A4_ONLY
;
367 if (_lookup_link(_lu_port
, "gethostbyaddr", &proc4
) != KERN_SUCCESS
)
369 *error
= NO_RECOVERY
;
370 return MACH_PORT_NULL
;
374 if (len
!= sizeof(struct in_addr
))
376 *error
= NO_RECOVERY
;
377 return MACH_PORT_NULL
;
380 v4addr
= malloc(len
);
381 memmove(v4addr
, addr
, len
);
382 v4addr
->s_addr
= htonl(v4addr
->s_addr
);
384 address
= (void *)v4addr
;
393 if (_lookup_link(_lu_port
, "getipv6nodebyaddr", &proc6
) != KERN_SUCCESS
)
395 *error
= NO_RECOVERY
;
396 return MACH_PORT_NULL
;
400 if (len
!= sizeof(struct in6_addr
))
402 *error
= NO_RECOVERY
;
403 return MACH_PORT_NULL
;
406 v6addr
= malloc(len
);
407 memmove(v6addr
, addr
, len
);
408 v6addr
->__u6_addr
.__u6_addr32
[0] = htonl(v6addr
->__u6_addr
.__u6_addr32
[0]);
409 v6addr
->__u6_addr
.__u6_addr32
[1] = htonl(v6addr
->__u6_addr
.__u6_addr32
[1]);
410 v6addr
->__u6_addr
.__u6_addr32
[2] = htonl(v6addr
->__u6_addr
.__u6_addr32
[2]);
411 v6addr
->__u6_addr
.__u6_addr32
[3] = htonl(v6addr
->__u6_addr
.__u6_addr32
[3]);
413 address
= (void *)v6addr
;
419 *error
= NO_RECOVERY
;
420 return MACH_PORT_NULL
;
423 request
= malloc(sizeof(a_requests_t
));
424 request
->next
= NULL
;
425 request
->retry
= MAX_LOOKUP_ATTEMPTS
;
426 request
->request
.proc
= proc
;
427 request
->request
.data
= (ooline_data
)address
;
428 request
->request
.dataLen
= len
/ BYTES_PER_XDR_UNIT
;
429 request
->request
.want
= want
;
430 request
->replyPort
= MACH_PORT_NULL
;
431 request
->callout
= callout
;
432 request
->context
= context
;
433 request
->hent
= NULL
;
436 * allocate reply port, send query to lookupd
438 if (_lookup_all_tx(_lu_port
, request
->request
.proc
, request
->request
.data
, request
->request
.dataLen
, &request
->replyPort
) == KERN_SUCCESS
)
440 request_queue(request
);
444 if (request
->request
.data
) free(request
->request
.data
);
446 *error
= NO_RECOVERY
;
447 return MACH_PORT_NULL
;
450 return request
->replyPort
;
454 _gethostbyaddr_async_handleReply(void *replyMsg
, a_requests_t
**requestP
, struct hostent
**he
, int *error
)
458 unsigned int datalen
;
460 mach_msg_header_t
*msg
= (mach_msg_header_t
*)replyMsg
;
461 a_requests_t
*request
;
462 kern_return_t status
;
463 security_token_t token
;
465 request
= request_extract(msg
->msgh_local_port
);
468 /* excuse me, what happenned to the request info? */
476 /* unpack the reply */
477 status
= _lookup_all_rx(replyMsg
, &data
, &datalen
, &token
);
483 case MIG_SERVER_DIED
:
484 if (--request
->retry
> 0)
486 /* retry the request */
487 if (_lookup_all_tx(_lu_port
, request
->request
.proc
, request
->request
.data
, request
->request
.dataLen
, &request
->replyPort
) == KERN_SUCCESS
)
489 request_queue(request
);
496 *error
= HOST_NOT_FOUND
;
500 datalen
*= BYTES_PER_XDR_UNIT
;
502 if (token
.val
[0] != 0)
504 vm_deallocate(mach_task_self(), (vm_address_t
)data
, datalen
);
505 *error
= NO_RECOVERY
;
509 xdrmem_create(&inxdr
, data
, datalen
, XDR_DECODE
);
512 if (!xdr_int(&inxdr
, &count
))
515 vm_deallocate(mach_task_self(), (vm_address_t
)data
, datalen
);
516 *error
= NO_RECOVERY
;
523 vm_deallocate(mach_task_self(), (vm_address_t
)data
, datalen
);
524 *error
= HOST_NOT_FOUND
;
529 *he
= extract_host(&inxdr
, request
->request
.want
, error
);
531 vm_deallocate(mach_task_self(), (vm_address_t
)data
, datalen
);
536 gethostbyaddr_async_start(const char *addr
, int len
, int type
, gethostbyaddr_async_callback callout
, void *context
)
538 a_request_callout_t cb
;
543 h_errno
= NO_RECOVERY
;
544 return MACH_PORT_NULL
;
547 cb
.hostAddr
= callout
;
548 mp
= _gethostbyaddr_async_start(addr
, len
, type
, cb
, context
, &h_errno
);
553 gethostbyaddr_async_cancel(mach_port_t port
)
560 gethostbyaddr_async_handleReply(void *replyMsg
)
563 struct hostent
*he
= NULL
;
564 a_requests_t
*request
= NULL
;
566 if (_gethostbyaddr_async_handleReply(replyMsg
, &request
, &he
, &error
))
568 /* if we have an answer to provide */
570 (request
->callout
.hostAddr
)(he
, request
->context
);
572 (void)mach_port_mod_refs(mach_task_self(), request
->replyPort
, MACH_PORT_RIGHT_RECEIVE
, -1);
573 if (request
->request
.data
) free(request
->request
.data
);
575 if (he
!= NULL
) freehostent(he
);
582 getipnodebyaddr_async_start(const void *addr
, size_t len
, int af
, int *error
, getipnodebyaddr_async_callback callout
, void *context
)
584 a_request_callout_t cb
;
589 *error
= NO_RECOVERY
;
590 return MACH_PORT_NULL
;
593 cb
.nodeAddr
= callout
;
594 mp
= _gethostbyaddr_async_start(addr
, len
, af
, cb
, context
, error
);
599 getipnodebyaddr_async_cancel(mach_port_t port
)
606 getipnodebyaddr_async_handleReply(void *replyMsg
)
609 struct hostent
*he
= NULL
;
610 a_requests_t
*request
= NULL
;
612 if (_gethostbyaddr_async_handleReply(replyMsg
, &request
, &he
, &error
))
614 /* if we have an answer to provide */
615 (request
->callout
.nodeAddr
)(he
, error
, request
->context
);
617 (void)mach_port_mod_refs(mach_task_self(), request
->replyPort
, MACH_PORT_RIGHT_RECEIVE
, -1);
618 if (request
->request
.data
) free(request
->request
.data
);
621 * Note: it is up to the callback function to call
630 _gethostbyname_async_start(const char *name
, int want
, int *error
, a_request_callout_t callout
, void *context
)
633 boolean_t is_addr
= FALSE
;
634 mach_port_t mp
= MACH_PORT_NULL
;
637 a_requests_t
*request
;
638 static int proc4
= -1;
639 static int proc6
= -1;
640 struct in_addr v4addr
;
641 struct in6_addr v6addr
;
643 if ((name
== NULL
) || (name
[0] == '\0'))
646 return MACH_PORT_NULL
;
649 af
= (want
== WANT_A4_ONLY
) ? AF_INET
: AF_INET6
;
651 if ((af
== AF_INET
) || (want
== WANT_MAPPED_A4_ONLY
))
655 if (_lookup_link(_lu_port
, "gethostbyname", &proc4
) != KERN_SUCCESS
)
657 *error
= NO_RECOVERY
;
658 return MACH_PORT_NULL
;
663 else /* if (af == AF_INET6) */
667 if (_lookup_link(_lu_port
, "getipv6nodebyname", &proc6
) != KERN_SUCCESS
)
669 *error
= NO_RECOVERY
;
670 return MACH_PORT_NULL
;
676 request
= malloc(sizeof(a_requests_t
));
677 request
->next
= NULL
;
678 request
->retry
= MAX_LOOKUP_ATTEMPTS
;
679 request
->request
.proc
= proc
;
680 request
->request
.data
= NULL
;
681 request
->request
.dataLen
= 0;
682 request
->request
.want
= want
;
683 request
->replyPort
= MACH_PORT_NULL
;
684 request
->callout
= callout
;
685 request
->context
= context
;
686 request
->hent
= NULL
;
692 memset(&v4addr
, 0, sizeof(struct in_addr
));
693 if (inet_aton(name
, &v4addr
) == 1)
695 /* return a fake hostent */
696 request
->hent
= fake_hostent(name
, v4addr
);
704 memset(&v6addr
, 0, sizeof(struct in6_addr
));
705 if (inet_pton(af
, name
, &v6addr
) == 1)
707 /* return a fake hostent */
708 request
->hent
= fake_hostent6(name
, v6addr
);
713 memset(&v4addr
, 0, sizeof(struct in_addr
));
714 if (inet_aton(name
, &v4addr
) == 1)
716 if (want
== WANT_A4_ONLY
)
719 *error
= HOST_NOT_FOUND
;
720 return MACH_PORT_NULL
;
723 v6addr
.__u6_addr
.__u6_addr32
[0] = 0x00000000;
724 v6addr
.__u6_addr
.__u6_addr32
[1] = 0x00000000;
725 v6addr
.__u6_addr
.__u6_addr32
[2] = htonl(0x0000ffff);
726 memmove(&(v6addr
.__u6_addr
.__u6_addr32
[3]), &(v4addr
.s_addr
), sizeof(struct in_addr
));
728 /* return a fake hostent */
729 request
->hent
= fake_hostent6(name
, v6addr
);
737 *error
= NO_RECOVERY
;
738 return MACH_PORT_NULL
;
744 * queue reply message
746 if (sendCannedReply(request
, error
))
748 request_queue(request
);
749 return request
->replyPort
;
753 freehostent(request
->hent
);
755 return MACH_PORT_NULL
;
759 request
->request
.dataLen
= _LU_MAXLUSTRLEN
+ BYTES_PER_XDR_UNIT
;
760 request
->request
.data
= malloc(request
->request
.dataLen
);
762 xdrmem_create(&outxdr
, request
->request
.data
, request
->request
.dataLen
, XDR_ENCODE
);
763 if (!xdr__lu_string(&outxdr
, (_lu_string
*)&name
))
765 xdr_destroy(&outxdr
);
766 free(request
->request
.data
);
768 *error
= NO_RECOVERY
;
769 return MACH_PORT_NULL
;
772 request
->request
.dataLen
= xdr_getpos(&outxdr
) / BYTES_PER_XDR_UNIT
;
775 * allocate reply port, send query to lookupd
777 if (_lookup_all_tx(_lu_port
, request
->request
.proc
, request
->request
.data
, request
->request
.dataLen
, &request
->replyPort
) == KERN_SUCCESS
)
779 request_queue(request
);
780 mp
= request
->replyPort
;
784 free(request
->request
.data
);
786 *error
= NO_RECOVERY
;
790 xdr_destroy(&outxdr
);
795 _gethostbyname_async_handleReply(void *replyMsg
, a_requests_t
**requestP
, struct hostent
**he
, int *error
)
798 unsigned int datalen
;
801 mach_msg_header_t
*msg
= (mach_msg_header_t
*)replyMsg
;
802 a_requests_t
*request
;
803 kern_return_t status
;
804 security_token_t token
;
807 request
= request_extract(msg
->msgh_local_port
);
810 /* excuse me, what happenned to the request info? */
821 * if the reply was already available when the
828 /* unpack the reply */
829 status
= _lookup_all_rx(replyMsg
, &data
, &datalen
, &token
);
835 case MIG_SERVER_DIED
:
836 if (--request
->retry
> 0)
841 if (_lookup_all_tx(_lu_port
, request
->request
.proc
, request
->request
.data
, request
->request
.dataLen
, &request
->replyPort
) == KERN_SUCCESS
)
843 request_queue(request
);
850 *error
= HOST_NOT_FOUND
;
854 datalen
*= BYTES_PER_XDR_UNIT
;
856 if (token
.val
[0] != 0)
858 vm_deallocate(mach_task_self(), (vm_address_t
)data
, datalen
);
859 *error
= NO_RECOVERY
;
863 xdrmem_create(&inxdr
, data
, datalen
, XDR_DECODE
);
866 if (!xdr_int(&inxdr
, &count
))
869 vm_deallocate(mach_task_self(), (vm_address_t
)data
, datalen
);
870 *error
= NO_RECOVERY
;
877 vm_deallocate(mach_task_self(), (vm_address_t
)data
, datalen
);
878 *error
= HOST_NOT_FOUND
;
882 want
= request
->request
.want
;
883 if (want
== WANT_A6_OR_MAPPED_A4_IF_NO_A6
) want
= WANT_A6_ONLY
;
885 *he
= extract_host(&inxdr
, want
, error
);
887 vm_deallocate(mach_task_self(), (vm_address_t
)data
, datalen
);
892 gethostbyname_async_start(const char *name
, gethostbyname_async_callback callout
, void *context
)
894 a_request_callout_t cb
;
896 mach_port_t mp
= MACH_PORT_NULL
;
900 h_errno
= NO_RECOVERY
;
901 return MACH_PORT_NULL
;
904 cb
.hostName
= callout
;
905 mp
= _gethostbyname_async_start(name
, WANT_A4_ONLY
, &error
, cb
, context
);
906 if (mp
== MACH_PORT_NULL
)
915 gethostbyname_async_cancel(mach_port_t port
)
922 gethostbyname_async_handleReply(void *replyMsg
)
926 a_requests_t
*request
;
928 if (_gethostbyname_async_handleReply(replyMsg
, &request
, &he
, &error
))
930 /* if we have an answer to provide */
932 (request
->callout
.hostAddr
)(he
, request
->context
);
934 (void)mach_port_mod_refs(mach_task_self(), request
->replyPort
, MACH_PORT_RIGHT_RECEIVE
, -1);
935 if (request
->request
.data
) free(request
->request
.data
);
937 if (he
!= NULL
) freehostent(he
);
944 getipnodebyname_async_start(const char *name
, int af
, int flags
, int *error
, getipnodebyname_async_callback callout
, void *context
)
946 a_request_callout_t cb
;
949 mach_port_t mp
= MACH_PORT_NULL
;
950 int want
= WANT_A4_ONLY
;
951 struct ifaddrs
*ifa
, *ifap
;
955 h_errno
= NO_RECOVERY
;
956 return MACH_PORT_NULL
;
960 * IF AI_ADDRCONFIG is set, we need to know what interface flavors we really have.
962 if (flags
& AI_ADDRCONFIG
)
964 if (getifaddrs(&ifa
) < 0)
966 *error
= NO_RECOVERY
;
967 return MACH_PORT_NULL
;
970 for (ifap
= ifa
; ifap
!= NULL
; ifap
= ifap
->ifa_next
)
972 if (ifap
->ifa_addr
== NULL
) continue;
973 if ((ifap
->ifa_flags
& IFF_UP
) == 0) continue;
974 if (ifap
->ifa_addr
->sa_family
== AF_INET
)
978 else if (ifap
->ifa_addr
->sa_family
== AF_INET6
)
986 /* Bail out if there are no interfaces */
987 if ((if4
== 0) && (if6
== 0))
990 return MACH_PORT_NULL
;
995 * Figure out what we want.
996 * If user asked for AF_INET, we only want V4 addresses.
1002 want
= WANT_A4_ONLY
;
1003 if ((flags
& AI_ADDRCONFIG
) && (if4
== 0))
1005 *error
= NO_ADDRESS
;
1006 return MACH_PORT_NULL
;
1013 want
= WANT_A6_ONLY
;
1014 if (flags
& (AI_V4MAPPED
|AI_V4MAPPED_CFG
))
1018 want
= WANT_A6_PLUS_MAPPED_A4
;
1022 want
= WANT_A6_OR_MAPPED_A4_IF_NO_A6
;
1027 if ((flags
& AI_ADDRCONFIG
) && (if6
== 0))
1029 *error
= NO_ADDRESS
;
1030 return MACH_PORT_NULL
;
1037 cb
.nodeName
= callout
;
1038 mp
= _gethostbyname_async_start(name
, want
, &h_errno
, cb
, context
);
1043 getipnodebyname_async_cancel(mach_port_t port
)
1045 _async_cancel(port
);
1050 getipnodebyname_async_handleReply(void *replyMsg
)
1053 struct hostent
*he
= NULL
;
1054 a_requests_t
*request
= NULL
;
1055 static int proc4
= -1;
1057 if (_gethostbyname_async_handleReply(replyMsg
, &request
, &he
, &error
))
1060 * we have an answer to provide
1062 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
)))
1065 * no host found (yet), if requested we send a
1066 * followup query to lookupd.
1070 if (_lookup_link(_lu_port
, "gethostbyname", &proc4
) != KERN_SUCCESS
)
1072 error
= NO_RECOVERY
;
1077 request
->request
.proc
= proc4
;
1078 request
->request
.want
= WANT_MAPPED_A4_ONLY
;
1079 if (_lookup_all_tx(_lu_port
, request
->request
.proc
, request
->request
.data
, request
->request
.dataLen
, &request
->replyPort
) == KERN_SUCCESS
)
1081 request_queue(request
);
1086 error
= NO_RECOVERY
;
1091 (request
->callout
.nodeName
)(he
, error
, request
->context
);
1092 (void)mach_port_mod_refs(mach_task_self(), request
->replyPort
, MACH_PORT_RIGHT_RECEIVE
, -1);
1093 if (request
->request
.data
!= NULL
) free(request
->request
.data
);
1096 * Note: it is up to the callback function to call