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 #include <netdb_async.h>
29 #include <mach/mach.h>
30 #include <sys/socket.h>
31 #include <netinet/in.h>
32 #include <arpa/inet.h>
40 #define IPV6_ADDR_LEN 16
41 #define IPV4_ADDR_LEN 4
50 gethostbyaddr_async_start(const char *addr
, int len
, int family
, gethostbyaddr_async_callback callback
, void *context
)
56 my_context_t
*my_context
;
60 if (addr
== NULL
) return MACH_PORT_NULL
;
61 if (len
== 0) return MACH_PORT_NULL
;
62 if ((family
!= AF_INET
) && (family
!= AF_INET6
)) return MACH_PORT_NULL
;
65 if (family
== AF_INET6
) want
= WANT_A6_ONLY
;
67 if ((family
== AF_INET6
) && (len
== IPV6_ADDR_LEN
) && (is_a4_mapped((const char *)addr
) || is_a4_compat((const char *)addr
)))
72 want
= WANT_MAPPED_A4_ONLY
;
77 status
= LI_DSLookupGetProcedureNumber("gethostbyaddr", &proc
);
78 if (status
!= KERN_SUCCESS
) return MACH_PORT_NULL
;
81 request
= kvbuf_query("ksku", "address", addr
, "family", want
);
82 if (request
== NULL
) return MACH_PORT_NULL
;
84 my_context
= (my_context_t
*)calloc(1, sizeof(my_context_t
));
85 if (my_context
== NULL
) return MACH_PORT_NULL
;
87 my_context
->user_context
= context
;
88 my_context
->want
= want
;
90 status
= LI_async_start(&mp
, proc
, request
, (void *)callback
, my_context
);
97 gethostbyaddr_async_cancel(mach_port_t port
)
99 my_context_t
*my_context
;
103 LI_async_call_cancel(port
, (void **)&my_context
);
105 if (my_context
!= NULL
) free(my_context
);
109 gethostbyaddr_async_handleReply(void *msg
)
111 gethostbyaddr_async_callback callback
;
116 my_context_t
*my_context
;
119 callback
= (gethostbyaddr_async_callback
)NULL
;
125 status
= LI_async_handle_reply(msg
, &reply
, (void **)&callback
, (void **)&my_context
);
126 if ((status
!= KERN_SUCCESS
) || (reply
== NULL
))
128 if (status
== MIG_REPLY_MISMATCH
) return;
129 if (callback
!= NULL
)
131 if (my_context
!= NULL
) context
= my_context
->user_context
;
132 callback(NULL
, context
);
139 if (my_context
!= NULL
)
141 context
= my_context
->user_context
;
142 want
= my_context
->want
;
146 out
= extract_host(reply
, want
);
149 callback(out
, context
);
153 getipnodebyaddr_async_start(const void *addr
, size_t len
, int family
, int *error
, getipnodebyaddr_async_callback callback
, void *context
)
156 int32_t want
, status
;
159 my_context_t
*my_context
;
163 if (addr
== NULL
) return MACH_PORT_NULL
;
164 if (len
== 0) return MACH_PORT_NULL
;
165 if ((family
!= AF_INET
) && (family
!= AF_INET6
)) return MACH_PORT_NULL
;
168 if (family
== AF_INET6
) want
= WANT_A6_ONLY
;
170 if ((family
== AF_INET6
) && (len
== IPV6_ADDR_LEN
) && (is_a4_mapped((const char *)addr
) || is_a4_compat((const char *)addr
)))
175 want
= WANT_MAPPED_A4_ONLY
;
180 status
= LI_DSLookupGetProcedureNumber("gethostbyaddr", &proc
);
181 if (status
!= KERN_SUCCESS
) return MACH_PORT_NULL
;
184 request
= kvbuf_query("ksku", "address", addr
, "family", want
);
185 if (request
== NULL
) return MACH_PORT_NULL
;
187 my_context
= (my_context_t
*)calloc(1, sizeof(my_context_t
));
188 if (my_context
== NULL
) return MACH_PORT_NULL
;
190 my_context
->user_context
= context
;
191 my_context
->want
= want
;
193 status
= LI_async_start(&mp
, proc
, request
, (void *)callback
, my_context
);
200 getipnodebyaddr_async_cancel(mach_port_t port
)
202 my_context_t
*my_context
;
206 LI_async_call_cancel(port
, (void **)&my_context
);
208 if (my_context
!= NULL
) free(my_context
);
212 getipnodebyaddr_async_handleReply(void *msg
)
214 getipnodebyaddr_async_callback callback
;
219 my_context_t
*my_context
;
222 callback
= (getipnodebyaddr_async_callback
)NULL
;
228 status
= LI_async_handle_reply(msg
, &reply
, (void **)&callback
, (void **)&my_context
);
229 if ((status
!= KERN_SUCCESS
) || (reply
== NULL
))
231 if (status
== MIG_REPLY_MISMATCH
) return;
232 if (callback
!= NULL
)
234 if (my_context
!= NULL
) context
= my_context
->user_context
;
235 callback(NULL
, NO_RECOVERY
, context
);
242 if (my_context
!= NULL
)
244 context
= my_context
->user_context
;
245 want
= my_context
->want
;
249 out
= extract_host(reply
, want
);
254 callback(NULL
, HOST_NOT_FOUND
, context
);
258 callback(out
, 0, context
);
262 gethostbyname_async_start(const char *name
, gethostbyname_async_callback callback
, void *context
)
271 if (name
== NULL
) return MACH_PORT_NULL
;
275 status
= LI_DSLookupGetProcedureNumber("gethostbyname", &proc
);
276 if (status
!= KERN_SUCCESS
) return MACH_PORT_NULL
;
279 request
= kvbuf_query("ksksks", "name", name
, "ipv4", "1", "ipv6", "0");
280 if (request
== NULL
) return MACH_PORT_NULL
;
282 status
= LI_async_start(&mp
, proc
, request
, (void *)callback
, context
);
289 gethostbyname_async_cancel(mach_port_t port
)
291 LI_async_call_cancel(port
, NULL
);
295 gethostbyname_async_handleReply(void *msg
)
297 gethostbyname_async_callback callback
;
304 callback
= (gethostbyname_async_callback
)NULL
;
309 status
= LI_async_handle_reply(msg
, &reply
, (void **)&callback
, (void **)&context
);
310 if ((status
!= KERN_SUCCESS
) || (reply
== NULL
))
312 if (status
== MIG_REPLY_MISMATCH
) return;
313 if (callback
!= NULL
)
315 callback(NULL
, context
);
320 out
= extract_host(reply
, AF_INET
);
323 callback(out
, context
);
327 getipnodebyname_async_start(const char *name
, int family
, int flags
, int *err
, getipnodebyname_async_callback callback
, void *context
)
330 int32_t status
, want
, want4
, want6
, if4
, if6
;
333 struct ifaddrs
*ifa
, *ifap
;
334 struct in_addr addr4
;
335 struct in6_addr addr6
;
336 my_context_t
*my_context
;
338 if (name
== NULL
) return MACH_PORT_NULL
;
340 if (err
!= NULL
) *err
= 0;
345 memset(&addr4
, 0, sizeof(struct in_addr
));
346 memset(&addr6
, 0, sizeof(struct in6_addr
));
348 if (flags
& AI_ADDRCONFIG
)
350 if (getifaddrs(&ifa
) < 0)
352 if (err
!= NULL
) *err
= NO_RECOVERY
;
353 return MACH_PORT_NULL
;
356 for (ifap
= ifa
; ifap
!= NULL
; ifap
= ifap
->ifa_next
)
358 if (ifap
->ifa_addr
== NULL
) continue;
359 if ((ifap
->ifa_flags
& IFF_UP
) == 0) continue;
360 if (ifap
->ifa_addr
->sa_family
== AF_INET
) if4
++;
361 else if (ifap
->ifa_addr
->sa_family
== AF_INET6
) if6
++;
366 /* Bail out if there are no interfaces */
367 if ((if4
== 0) && (if6
== 0))
369 if (err
!= NULL
) *err
= NO_RECOVERY
;
370 return MACH_PORT_NULL
;
375 * Figure out what we want.
376 * If user asked for AF_INET, we only want V4 addresses.
380 if (family
== AF_INET
)
382 if ((flags
& AI_ADDRCONFIG
) && (if4
== 0))
384 if (err
!= NULL
) *err
= NO_RECOVERY
;
385 return MACH_PORT_NULL
;
390 /* family == AF_INET6 */
393 if (flags
& (AI_V4MAPPED
| AI_V4MAPPED_CFG
))
397 want
= WANT_A6_PLUS_MAPPED_A4
;
401 want
= WANT_A6_OR_MAPPED_A4_IF_NO_A6
;
406 if ((flags
& AI_ADDRCONFIG
) && (if6
== 0))
408 if (err
!= NULL
) *err
= NO_RECOVERY
;
409 return MACH_PORT_NULL
;
416 status
= LI_DSLookupGetProcedureNumber("gethostbyname", &proc
);
417 if (status
!= KERN_SUCCESS
) return MACH_PORT_NULL
;
420 my_context
= (my_context_t
*)calloc(1, sizeof(my_context_t
));
421 if (my_context
== NULL
)
424 return MACH_PORT_NULL
;
427 my_context
->user_context
= context
;
428 my_context
->want
= want
;
433 if (want
== WANT_A4_ONLY
) want6
= 0;
434 else if (want
== WANT_A6_ONLY
) want4
= 0;
435 else if (WANT_MAPPED_A4_ONLY
) want6
= 0;
437 request
= kvbuf_query("kskuku", "name", name
, "ipv4", want4
, "ipv6", want6
);
438 if (request
== NULL
) return MACH_PORT_NULL
;
440 status
= LI_async_start(&mp
, proc
, request
, (void *)callback
, my_context
);
447 getipnodebyname_async_cancel(mach_port_t port
)
449 my_context_t
*my_context
;
453 LI_async_call_cancel(port
, (void **)&my_context
);
455 if (my_context
!= NULL
) free(my_context
);
459 getipnodebyname_async_handleReply(void *msg
)
461 getipnodebyname_async_callback callback
;
466 my_context_t
*my_context
;
469 callback
= (getipnodebyname_async_callback
)NULL
;
475 status
= LI_async_handle_reply(msg
, &reply
, (void **)&callback
, (void **)&my_context
);
476 if ((status
!= KERN_SUCCESS
) || (reply
== NULL
))
478 if (status
== MIG_REPLY_MISMATCH
) return;
479 if (callback
!= NULL
)
481 if (my_context
!= NULL
) context
= my_context
->user_context
;
482 callback(NULL
, NO_RECOVERY
, context
);
489 if (my_context
!= NULL
)
491 context
= my_context
->user_context
;
492 want
= my_context
->want
;
496 out
= extract_host(reply
, want
);
501 err
= HOST_NOT_FOUND
;
502 callback(NULL
, err
, context
);
506 callback(out
, 0, context
);