1/* 2 * Copyright (c) 2003 - 2008 Apple, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24#include <stdlib.h> 25#include <string.h> 26#include <stdio.h> 27#include <mach/mach.h> 28#include <pthread.h> 29#include <netdb.h> 30#include <netdb_async.h> 31#include <netinet/in.h> 32#include <arpa/inet.h> 33#include <dns.h> 34#include <dns_util.h> 35#include <stdarg.h> 36#include <si_module.h> 37 38extern void *LI_ils_create(char *fmt, ...); 39 40/* 41 typedef void (*dns_async_callback)(int32_t status, char *buf, uint32_t len, struct sockaddr *from, int fromlen, void *context); 42*/ 43 44typedef struct 45{ 46 void *orig_callback; 47 void *orig_context; 48 si_mod_t *dns; 49} _dns_context_t; 50 51static void 52_dns_callback(si_item_t *item, uint32_t status, void *ctx) 53{ 54 _dns_context_t *my_ctx; 55 si_dnspacket_t *res; 56 char *packet; 57 struct sockaddr *from; 58 uint32_t pl; 59 int fl; 60 61 if (ctx == NULL) return; 62 63 my_ctx = (_dns_context_t *)ctx; 64 if (my_ctx->orig_callback == NULL) 65 { 66 si_item_release(item); 67 si_module_release(my_ctx->dns); 68 free(my_ctx); 69 return; 70 } 71 72 if (status >= SI_STATUS_INTERNAL) status = NO_RECOVERY; 73 74 packet = NULL; 75 pl = 0; 76 from = NULL; 77 fl = 0; 78 79 res = NULL; 80 if (item != NULL) res = (si_dnspacket_t *)((char *)item + sizeof(si_item_t)); 81 82 if ((res != NULL) && (res->dns_packet_len > 0)) 83 { 84 packet = malloc(res->dns_packet_len); 85 if (packet == NULL) status = NO_RECOVERY; 86 else 87 { 88 pl = res->dns_packet_len; 89 memcpy(packet, res->dns_packet, res->dns_packet_len); 90 91 if (res->dns_server_len > 0) 92 { 93 from = malloc(res->dns_server_len); 94 if (from == NULL) 95 { 96 status = NO_RECOVERY; 97 free(packet); 98 packet = NULL; 99 pl = 0; 100 } 101 else 102 { 103 fl = res->dns_server_len; 104 memcpy(from, res->dns_server, res->dns_server_len); 105 } 106 } 107 } 108 } 109 110 si_item_release(item); 111 112 ((dns_async_callback)(my_ctx->orig_callback))(status, packet, pl, from, fl, my_ctx->orig_context); 113 114 si_module_release(my_ctx->dns); 115 free(my_ctx); 116} 117 118int32_t 119dns_async_start(mach_port_t *p, const char *name, uint16_t dnsclass, uint16_t dnstype, uint32_t do_search, dns_async_callback callback, void *context) 120{ 121 si_mod_t *dns; 122 int call; 123 uint32_t c, t; 124 _dns_context_t *my_ctx; 125 126 *p = MACH_PORT_NULL; 127 128 if (name == NULL) return NO_RECOVERY; 129 130 dns = si_module_with_name("mdns"); 131 if (dns == NULL) return NO_RECOVERY; 132 133 my_ctx = (_dns_context_t *)calloc(1, sizeof(_dns_context_t)); 134 if (my_ctx == NULL) 135 { 136 si_module_release(dns); 137 return NO_RECOVERY; 138 } 139 140 my_ctx->orig_callback = callback; 141 my_ctx->orig_context = context; 142 my_ctx->dns = dns; 143 144 call = SI_CALL_DNS_QUERY; 145 if (do_search != 0) call = SI_CALL_DNS_SEARCH; 146 147 c = dnsclass; 148 t = dnstype; 149 150 *p = si_async_call(dns, call, name, NULL, NULL, c, t, 0, 0, (void *)_dns_callback, (void *)my_ctx); 151 if (*p == MACH_PORT_NULL) 152 { 153 free(my_ctx); 154 si_module_release(dns); 155 return NO_RECOVERY; 156 } 157 158 return 0; 159} 160 161void 162dns_async_cancel(mach_port_t p) 163{ 164 si_async_cancel(p); 165} 166 167int32_t 168dns_async_send(mach_port_t *p, const char *name, uint16_t dnsclass, uint16_t dnstype, uint32_t do_search) 169{ 170 return dns_async_start(p, name, dnsclass, dnstype, do_search, NULL, NULL); 171} 172 173/* unsupported */ 174int32_t 175dns_async_receive(mach_port_t p, char **buf, uint32_t *len, struct sockaddr **from, uint32_t *fromlen) 176{ 177 return 0; 178} 179 180int32_t 181dns_async_handle_reply(void *msg) 182{ 183 si_async_handle_reply(msg); 184 return 0; 185} 186