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
);
383 address
= (void *)v4addr
;
392 if (_lookup_link(_lu_port
, "getipv6nodebyaddr", &proc6
) != KERN_SUCCESS
)
394 *error
= NO_RECOVERY
;
395 return MACH_PORT_NULL
;
399 if (len
!= sizeof(struct in6_addr
))
401 *error
= NO_RECOVERY
;
402 return MACH_PORT_NULL
;
405 v6addr
= malloc(len
);
406 memmove(v6addr
, addr
, len
);
407 v6addr
->__u6_addr
.__u6_addr32
[0] = htonl(v6addr
->__u6_addr
.__u6_addr32
[0]);
408 v6addr
->__u6_addr
.__u6_addr32
[1] = htonl(v6addr
->__u6_addr
.__u6_addr32
[1]);
409 v6addr
->__u6_addr
.__u6_addr32
[2] = htonl(v6addr
->__u6_addr
.__u6_addr32
[2]);
410 v6addr
->__u6_addr
.__u6_addr32
[3] = htonl(v6addr
->__u6_addr
.__u6_addr32
[3]);
412 address
= (void *)v6addr
;
418 *error
= NO_RECOVERY
;
419 return MACH_PORT_NULL
;
422 request
= malloc(sizeof(a_requests_t
));
423 request
->next
= NULL
;
424 request
->retry
= MAX_LOOKUP_ATTEMPTS
;
425 request
->request
.proc
= proc
;
426 request
->request
.data
= (ooline_data
)address
;
427 request
->request
.dataLen
= len
/ BYTES_PER_XDR_UNIT
;
428 request
->request
.want
= want
;
429 request
->replyPort
= MACH_PORT_NULL
;
430 request
->callout
= callout
;
431 request
->context
= context
;
432 request
->hent
= NULL
;
435 * allocate reply port, send query to lookupd
437 if (_lookup_all_tx(_lu_port
, request
->request
.proc
, request
->request
.data
, request
->request
.dataLen
, &request
->replyPort
) == KERN_SUCCESS
)
439 request_queue(request
);
443 if (request
->request
.data
) free(request
->request
.data
);
445 *error
= NO_RECOVERY
;
446 return MACH_PORT_NULL
;
449 return request
->replyPort
;
453 _gethostbyaddr_async_handleReply(void *replyMsg
, a_requests_t
**requestP
, struct hostent
**he
, int *error
)
457 unsigned int datalen
;
459 mach_msg_header_t
*msg
= (mach_msg_header_t
*)replyMsg
;
460 a_requests_t
*request
;
461 kern_return_t status
;
462 security_token_t token
;
464 request
= request_extract(msg
->msgh_local_port
);
467 /* excuse me, what happenned to the request info? */
475 /* unpack the reply */
476 status
= _lookup_all_rx(replyMsg
, &data
, &datalen
, &token
);
482 case MIG_SERVER_DIED
:
483 if (--request
->retry
> 0)
485 /* retry the request */
486 if (_lookup_all_tx(_lu_port
, request
->request
.proc
, request
->request
.data
, request
->request
.dataLen
, &request
->replyPort
) == KERN_SUCCESS
)
488 request_queue(request
);
495 *error
= HOST_NOT_FOUND
;
499 datalen
*= BYTES_PER_XDR_UNIT
;
501 if (token
.val
[0] != 0)
503 vm_deallocate(mach_task_self(), (vm_address_t
)data
, datalen
);
504 *error
= NO_RECOVERY
;
508 xdrmem_create(&inxdr
, data
, datalen
, XDR_DECODE
);
511 if (!xdr_int(&inxdr
, &count
))
514 vm_deallocate(mach_task_self(), (vm_address_t
)data
, datalen
);
515 *error
= NO_RECOVERY
;
522 vm_deallocate(mach_task_self(), (vm_address_t
)data
, datalen
);
523 *error
= HOST_NOT_FOUND
;
528 *he
= extract_host(&inxdr
, request
->request
.want
, error
);
530 vm_deallocate(mach_task_self(), (vm_address_t
)data
, datalen
);
535 gethostbyaddr_async_start(const char *addr
, int len
, int type
, gethostbyaddr_async_callback callout
, void *context
)
537 a_request_callout_t cb
;
542 h_errno
= NO_RECOVERY
;
543 return MACH_PORT_NULL
;
546 cb
.hostAddr
= callout
;
547 mp
= _gethostbyaddr_async_start(addr
, len
, type
, cb
, context
, &h_errno
);
552 gethostbyaddr_async_cancel(mach_port_t port
)
559 gethostbyaddr_async_handleReply(void *replyMsg
)
562 struct hostent
*he
= NULL
;
563 a_requests_t
*request
= NULL
;
565 if (_gethostbyaddr_async_handleReply(replyMsg
, &request
, &he
, &error
))
567 /* if we have an answer to provide */
569 (request
->callout
.hostAddr
)(he
, request
->context
);
571 (void)mach_port_mod_refs(mach_task_self(), request
->replyPort
, MACH_PORT_RIGHT_RECEIVE
, -1);
572 if (request
->request
.data
) free(request
->request
.data
);
574 if (he
!= NULL
) freehostent(he
);
581 getipnodebyaddr_async_start(const void *addr
, size_t len
, int af
, int *error
, getipnodebyaddr_async_callback callout
, void *context
)
583 a_request_callout_t cb
;
588 *error
= NO_RECOVERY
;
589 return MACH_PORT_NULL
;
592 cb
.nodeAddr
= callout
;
593 mp
= _gethostbyaddr_async_start(addr
, len
, af
, cb
, context
, error
);
598 getipnodebyaddr_async_cancel(mach_port_t port
)
605 getipnodebyaddr_async_handleReply(void *replyMsg
)
608 struct hostent
*he
= NULL
;
609 a_requests_t
*request
= NULL
;
611 if (_gethostbyaddr_async_handleReply(replyMsg
, &request
, &he
, &error
))
613 /* if we have an answer to provide */
614 (request
->callout
.nodeAddr
)(he
, error
, request
->context
);
616 (void)mach_port_mod_refs(mach_task_self(), request
->replyPort
, MACH_PORT_RIGHT_RECEIVE
, -1);
617 if (request
->request
.data
) free(request
->request
.data
);
620 * Note: it is up to the callback function to call
629 _gethostbyname_async_start(const char *name
, int want
, int *error
, a_request_callout_t callout
, void *context
)
632 boolean_t is_addr
= FALSE
;
633 mach_port_t mp
= MACH_PORT_NULL
;
636 a_requests_t
*request
;
637 static int proc4
= -1;
638 static int proc6
= -1;
639 struct in_addr v4addr
;
640 struct in6_addr v6addr
;
642 if ((name
== NULL
) || (name
[0] == '\0'))
645 return MACH_PORT_NULL
;
648 af
= (want
== WANT_A4_ONLY
) ? AF_INET
: AF_INET6
;
650 if ((af
== AF_INET
) || (want
== WANT_MAPPED_A4_ONLY
))
654 if (_lookup_link(_lu_port
, "gethostbyname", &proc4
) != KERN_SUCCESS
)
656 *error
= NO_RECOVERY
;
657 return MACH_PORT_NULL
;
662 else /* if (af == AF_INET6) */
666 if (_lookup_link(_lu_port
, "getipv6nodebyname", &proc6
) != KERN_SUCCESS
)
668 *error
= NO_RECOVERY
;
669 return MACH_PORT_NULL
;
675 request
= malloc(sizeof(a_requests_t
));
676 request
->next
= NULL
;
677 request
->retry
= MAX_LOOKUP_ATTEMPTS
;
678 request
->request
.proc
= proc
;
679 request
->request
.data
= NULL
;
680 request
->request
.dataLen
= 0;
681 request
->request
.want
= want
;
682 request
->replyPort
= MACH_PORT_NULL
;
683 request
->callout
= callout
;
684 request
->context
= context
;
685 request
->hent
= NULL
;
691 memset(&v4addr
, 0, sizeof(struct in_addr
));
692 if (inet_aton(name
, &v4addr
) == 1)
694 /* return a fake hostent */
695 request
->hent
= fake_hostent(name
, v4addr
);
703 memset(&v6addr
, 0, sizeof(struct in6_addr
));
704 if (inet_pton(af
, name
, &v6addr
) == 1)
706 /* return a fake hostent */
707 request
->hent
= fake_hostent6(name
, v6addr
);
712 memset(&v4addr
, 0, sizeof(struct in_addr
));
713 if (inet_aton(name
, &v4addr
) == 1)
715 if (want
== WANT_A4_ONLY
)
718 *error
= HOST_NOT_FOUND
;
719 return MACH_PORT_NULL
;
722 v6addr
.__u6_addr
.__u6_addr32
[0] = 0x00000000;
723 v6addr
.__u6_addr
.__u6_addr32
[1] = 0x00000000;
724 v6addr
.__u6_addr
.__u6_addr32
[2] = htonl(0x0000ffff);
725 memmove(&(v6addr
.__u6_addr
.__u6_addr32
[3]), &(v4addr
.s_addr
), sizeof(struct in_addr
));
727 /* return a fake hostent */
728 request
->hent
= fake_hostent6(name
, v6addr
);
736 *error
= NO_RECOVERY
;
737 return MACH_PORT_NULL
;
743 * queue reply message
745 if (sendCannedReply(request
, error
))
747 request_queue(request
);
748 return request
->replyPort
;
752 freehostent(request
->hent
);
754 return MACH_PORT_NULL
;
758 request
->request
.dataLen
= _LU_MAXLUSTRLEN
+ BYTES_PER_XDR_UNIT
;
759 request
->request
.data
= malloc(request
->request
.dataLen
);
761 xdrmem_create(&outxdr
, request
->request
.data
, request
->request
.dataLen
, XDR_ENCODE
);
762 if (!xdr__lu_string(&outxdr
, (_lu_string
*)&name
))
764 xdr_destroy(&outxdr
);
765 free(request
->request
.data
);
767 *error
= NO_RECOVERY
;
768 return MACH_PORT_NULL
;
771 request
->request
.dataLen
= xdr_getpos(&outxdr
) / BYTES_PER_XDR_UNIT
;
774 * allocate reply port, send query to lookupd
776 if (_lookup_all_tx(_lu_port
, request
->request
.proc
, request
->request
.data
, request
->request
.dataLen
, &request
->replyPort
) == KERN_SUCCESS
)
778 request_queue(request
);
779 mp
= request
->replyPort
;
783 free(request
->request
.data
);
785 *error
= NO_RECOVERY
;
789 xdr_destroy(&outxdr
);
794 _gethostbyname_async_handleReply(void *replyMsg
, a_requests_t
**requestP
, struct hostent
**he
, int *error
)
797 unsigned int datalen
;
800 mach_msg_header_t
*msg
= (mach_msg_header_t
*)replyMsg
;
801 a_requests_t
*request
;
802 kern_return_t status
;
803 security_token_t token
;
806 request
= request_extract(msg
->msgh_local_port
);
809 /* excuse me, what happenned to the request info? */
820 * if the reply was already available when the
827 /* unpack the reply */
828 status
= _lookup_all_rx(replyMsg
, &data
, &datalen
, &token
);
834 case MIG_SERVER_DIED
:
835 if (--request
->retry
> 0)
840 if (_lookup_all_tx(_lu_port
, request
->request
.proc
, request
->request
.data
, request
->request
.dataLen
, &request
->replyPort
) == KERN_SUCCESS
)
842 request_queue(request
);
849 *error
= HOST_NOT_FOUND
;
853 datalen
*= BYTES_PER_XDR_UNIT
;
855 if (token
.val
[0] != 0)
857 vm_deallocate(mach_task_self(), (vm_address_t
)data
, datalen
);
858 *error
= NO_RECOVERY
;
862 xdrmem_create(&inxdr
, data
, datalen
, XDR_DECODE
);
865 if (!xdr_int(&inxdr
, &count
))
868 vm_deallocate(mach_task_self(), (vm_address_t
)data
, datalen
);
869 *error
= NO_RECOVERY
;
876 vm_deallocate(mach_task_self(), (vm_address_t
)data
, datalen
);
877 *error
= HOST_NOT_FOUND
;
881 want
= request
->request
.want
;
882 if (want
== WANT_A6_OR_MAPPED_A4_IF_NO_A6
) want
= WANT_A6_ONLY
;
884 *he
= extract_host(&inxdr
, want
, error
);
886 vm_deallocate(mach_task_self(), (vm_address_t
)data
, datalen
);
891 gethostbyname_async_start(const char *name
, gethostbyname_async_callback callout
, void *context
)
893 a_request_callout_t cb
;
895 mach_port_t mp
= MACH_PORT_NULL
;
899 h_errno
= NO_RECOVERY
;
900 return MACH_PORT_NULL
;
903 cb
.hostName
= callout
;
904 mp
= _gethostbyname_async_start(name
, WANT_A4_ONLY
, &error
, cb
, context
);
905 if (mp
== MACH_PORT_NULL
)
914 gethostbyname_async_cancel(mach_port_t port
)
921 gethostbyname_async_handleReply(void *replyMsg
)
925 a_requests_t
*request
;
927 if (_gethostbyname_async_handleReply(replyMsg
, &request
, &he
, &error
))
929 /* if we have an answer to provide */
931 (request
->callout
.hostAddr
)(he
, request
->context
);
933 (void)mach_port_mod_refs(mach_task_self(), request
->replyPort
, MACH_PORT_RIGHT_RECEIVE
, -1);
934 if (request
->request
.data
) free(request
->request
.data
);
936 if (he
!= NULL
) freehostent(he
);
943 getipnodebyname_async_start(const char *name
, int af
, int flags
, int *error
, getipnodebyname_async_callback callout
, void *context
)
945 a_request_callout_t cb
;
948 mach_port_t mp
= MACH_PORT_NULL
;
949 int want
= WANT_A4_ONLY
;
950 struct ifaddrs
*ifa
, *ifap
;
954 h_errno
= NO_RECOVERY
;
955 return MACH_PORT_NULL
;
959 * IF AI_ADDRCONFIG is set, we need to know what interface flavors we really have.
961 if (flags
& AI_ADDRCONFIG
)
963 if (getifaddrs(&ifa
) < 0)
965 *error
= NO_RECOVERY
;
966 return MACH_PORT_NULL
;
969 for (ifap
= ifa
; ifap
!= NULL
; ifap
= ifap
->ifa_next
)
971 if (ifap
->ifa_addr
== NULL
) continue;
972 if ((ifap
->ifa_flags
& IFF_UP
) == 0) continue;
973 if (ifap
->ifa_addr
->sa_family
== AF_INET
)
977 else if (ifap
->ifa_addr
->sa_family
== AF_INET6
)
985 /* Bail out if there are no interfaces */
986 if ((if4
== 0) && (if6
== 0))
989 return MACH_PORT_NULL
;
994 * Figure out what we want.
995 * If user asked for AF_INET, we only want V4 addresses.
1001 want
= WANT_A4_ONLY
;
1002 if ((flags
& AI_ADDRCONFIG
) && (if4
== 0))
1004 *error
= NO_ADDRESS
;
1005 return MACH_PORT_NULL
;
1012 want
= WANT_A6_ONLY
;
1013 if (flags
& (AI_V4MAPPED
|AI_V4MAPPED_CFG
))
1017 want
= WANT_A6_PLUS_MAPPED_A4
;
1021 want
= WANT_A6_OR_MAPPED_A4_IF_NO_A6
;
1026 if ((flags
& AI_ADDRCONFIG
) && (if6
== 0))
1028 *error
= NO_ADDRESS
;
1029 return MACH_PORT_NULL
;
1036 cb
.nodeName
= callout
;
1037 mp
= _gethostbyname_async_start(name
, want
, &h_errno
, cb
, context
);
1042 getipnodebyname_async_cancel(mach_port_t port
)
1044 _async_cancel(port
);
1049 getipnodebyname_async_handleReply(void *replyMsg
)
1052 struct hostent
*he
= NULL
;
1053 a_requests_t
*request
= NULL
;
1054 static int proc4
= -1;
1056 if (_gethostbyname_async_handleReply(replyMsg
, &request
, &he
, &error
))
1059 * we have an answer to provide
1061 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
)))
1064 * no host found (yet), if requested we send a
1065 * followup query to lookupd.
1069 if (_lookup_link(_lu_port
, "gethostbyname", &proc4
) != KERN_SUCCESS
)
1071 error
= NO_RECOVERY
;
1076 request
->request
.proc
= proc4
;
1077 request
->request
.want
= WANT_MAPPED_A4_ONLY
;
1078 if (_lookup_all_tx(_lu_port
, request
->request
.proc
, request
->request
.data
, request
->request
.dataLen
, &request
->replyPort
) == KERN_SUCCESS
)
1080 request_queue(request
);
1085 error
= NO_RECOVERY
;
1090 (request
->callout
.nodeName
)(he
, error
, request
->context
);
1091 (void)mach_port_mod_refs(mach_task_self(), request
->replyPort
, MACH_PORT_RIGHT_RECEIVE
, -1);
1092 if (request
->request
.data
!= NULL
) free(request
->request
.data
);
1095 * Note: it is up to the callback function to call