]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSMacOSX/helper-stubs.c
mDNSResponder-379.27.tar.gz
[apple/mdnsresponder.git] / mDNSMacOSX / helper-stubs.c
1 /*
2 * Copyright (c) 2007-2012 Apple Inc. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <mach/mach.h>
18 #include <mach/mach_error.h>
19 #include <mach/vm_map.h>
20 #include <servers/bootstrap.h>
21 #include <IOKit/IOReturn.h>
22 #include <CoreFoundation/CoreFoundation.h>
23 #include "mDNSDebug.h"
24 #include "helper.h"
25 #include "helpermsg.h"
26
27 #define ERROR(x, y) y,
28 static const char *errorstring[] =
29 {
30 #include "helper-error.h"
31 NULL
32 };
33 #undef ERROR
34
35 static mach_port_t getHelperPort(int retry)
36 {
37 static mach_port_t port = MACH_PORT_NULL;
38 if (retry) port = MACH_PORT_NULL;
39 if (port == MACH_PORT_NULL && BOOTSTRAP_SUCCESS != bootstrap_look_up(bootstrap_port, kmDNSHelperServiceName, &port))
40 LogMsg("%s: cannot contact helper", __func__);
41 return port;
42 }
43
44 const char *mDNSHelperError(int err)
45 {
46 static const char *p = "<unknown error>";
47 if (mDNSHelperErrorBase < err && mDNSHelperErrorEnd > err)
48 p = errorstring[err - mDNSHelperErrorBase - 1];
49 return p;
50 }
51
52 /* Ugly but handy. */
53 // We don't bother reporting kIOReturnNotReady because that error code occurs in "normal" operation
54 // and doesn't indicate anything unexpected that needs to be investigated
55
56 #define MACHRETRYLOOP_BEGIN(kr, retry, err, fin) \
57 for (;;) \
58 {
59 #define MACHRETRYLOOP_END(kr, retry, err, fin) \
60 if (KERN_SUCCESS == (kr)) break; \
61 else if (MACH_SEND_INVALID_DEST == (kr) && 0 == (retry)++) continue; \
62 else \
63 { \
64 (err) = kmDNSHelperCommunicationFailed; \
65 LogMsg("%s: Mach communication failed: %d %X %s", __func__, kr, kr, mach_error_string(kr)); \
66 goto fin; \
67 } \
68 } \
69 if (0 != (err) && kIOReturnNotReady != (err)) \
70 { LogMsg("%s: %d 0x%X (%s)", __func__, (err), (err), mDNSHelperError(err)); goto fin; }
71
72 void mDNSPreferencesSetName(int key, domainlabel *old, domainlabel *new)
73 {
74 kern_return_t kr = KERN_FAILURE;
75 int retry = 0;
76 int err = 0;
77 char oldname[MAX_DOMAIN_LABEL+1] = {0};
78 char newname[MAX_DOMAIN_LABEL+1] = {0};
79 ConvertDomainLabelToCString_unescaped(old, oldname);
80 if (new) ConvertDomainLabelToCString_unescaped(new, newname);
81
82 MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
83 kr = proxy_mDNSPreferencesSetName(getHelperPort(retry), key, oldname, newname);
84 MACHRETRYLOOP_END(kr, retry, err, fin);
85
86 fin:
87 (void)err;
88 }
89
90 void mDNSDynamicStoreSetConfig(int key, const char *subkey, CFPropertyListRef value)
91 {
92 CFWriteStreamRef stream = NULL;
93 CFDataRef bytes = NULL;
94 kern_return_t kr = KERN_FAILURE;
95 int retry = 0;
96 int err = 0;
97
98 if (NULL == (stream = CFWriteStreamCreateWithAllocatedBuffers(NULL, NULL)))
99 {
100 err = kmDNSHelperCreationFailed;
101 LogMsg("%s: CFWriteStreamCreateWithAllocatedBuffers failed", __func__);
102 goto fin;
103 }
104 CFWriteStreamOpen(stream);
105 if (0 == CFPropertyListWriteToStream(value, stream, kCFPropertyListBinaryFormat_v1_0, NULL))
106 {
107 err = kmDNSHelperPListWriteFailed;
108 LogMsg("%s: CFPropertyListWriteToStream failed", __func__);
109 goto fin;
110 }
111 if (NULL == (bytes = CFWriteStreamCopyProperty(stream, kCFStreamPropertyDataWritten)))
112 {
113 err = kmDNSHelperCreationFailed;
114 LogMsg("%s: CFWriteStreamCopyProperty failed", __func__);
115 goto fin;
116 }
117 CFWriteStreamClose(stream);
118 CFRelease(stream);
119 stream = NULL;
120 MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
121 kr = proxy_mDNSDynamicStoreSetConfig(getHelperPort(retry), key, subkey ? subkey : "", (vm_offset_t)CFDataGetBytePtr(bytes), CFDataGetLength(bytes));
122 MACHRETRYLOOP_END(kr, retry, err, fin);
123
124 fin:
125 if (NULL != stream) { CFWriteStreamClose(stream); CFRelease(stream); }
126 if (NULL != bytes) CFRelease(bytes);
127 (void)err;
128 }
129
130 void mDNSRequestBPF(void)
131 {
132 kern_return_t kr = KERN_FAILURE;
133 int retry = 0, err = 0;
134 MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
135 kr = proxy_mDNSRequestBPF(getHelperPort(retry));
136 MACHRETRYLOOP_END(kr, retry, err, fin);
137 fin:
138 (void)err;
139 }
140
141 int mDNSPowerRequest(int key, int interval)
142 {
143 kern_return_t kr = KERN_FAILURE;
144 int retry = 0, err = 0;
145 MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
146 kr = proxy_mDNSPowerRequest(getHelperPort(retry), key, interval, &err);
147 MACHRETRYLOOP_END(kr, retry, err, fin);
148 fin:
149 return err;
150 }
151
152 int mDNSSetLocalAddressCacheEntry(int ifindex, int family, const v6addr_t ip, const ethaddr_t eth)
153 {
154 kern_return_t kr = KERN_FAILURE;
155 int retry = 0, err = 0;
156 MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
157 kr = proxy_mDNSSetLocalAddressCacheEntry(getHelperPort(retry), ifindex, family, (uint8_t*)ip, (uint8_t*)eth, &err);
158 MACHRETRYLOOP_END(kr, retry, err, fin);
159 fin:
160 return err;
161 }
162
163 void mDNSNotify(const char *title, const char *msg) // Both strings are UTF-8 text
164 {
165 kern_return_t kr = KERN_FAILURE;
166 int retry = 0, err = 0;
167 MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
168 kr = proxy_mDNSNotify(getHelperPort(retry), title, msg);
169 MACHRETRYLOOP_END(kr, retry, err, fin);
170 fin:
171 (void)err;
172 }
173
174 int mDNSKeychainGetSecrets(CFArrayRef *result)
175 {
176 CFPropertyListRef plist = NULL;
177 CFDataRef bytes = NULL;
178 kern_return_t kr = KERN_FAILURE;
179 unsigned int numsecrets = 0;
180 vm_offset_t secrets = 0;
181 mach_msg_type_number_t secretsCnt = 0;
182 int retry = 0, err = 0;
183
184 MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
185 kr = proxy_mDNSKeychainGetSecrets(getHelperPort(retry), &numsecrets, &secrets, &secretsCnt, &err);
186 MACHRETRYLOOP_END(kr, retry, err, fin);
187
188 if (NULL == (bytes = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (void*)secrets, secretsCnt, kCFAllocatorNull)))
189 {
190 err = kmDNSHelperCreationFailed;
191 LogMsg("%s: CFDataCreateWithBytesNoCopy failed", __func__);
192 goto fin;
193 }
194 if (NULL == (plist = CFPropertyListCreateFromXMLData(kCFAllocatorDefault, bytes, kCFPropertyListImmutable, NULL)))
195 {
196 err = kmDNSHelperInvalidPList;
197 LogMsg("%s: CFPropertyListCreateFromXMLData failed", __func__);
198 goto fin;
199 }
200 if (CFArrayGetTypeID() != CFGetTypeID(plist))
201 {
202 err = kmDNSHelperTypeError;
203 LogMsg("%s: Unexpected result type", __func__);
204 CFRelease(plist);
205 plist = NULL;
206 goto fin;
207 }
208 *result = (CFArrayRef)plist;
209
210 fin:
211 if (bytes) CFRelease(bytes);
212 if (secrets) vm_deallocate(mach_task_self(), secrets, secretsCnt);
213 return err;
214 }
215
216 void mDNSConfigureServer(int updown, const char *const prefix, const domainname *const fqdn)
217 {
218 kern_return_t kr = KERN_SUCCESS;
219 int retry = 0, err = 0;
220 char fqdnStr[MAX_ESCAPED_DOMAIN_NAME + 10] = { 0 }; // Assume the prefix is no larger than 10 chars
221 if (fqdn)
222 {
223 mDNSPlatformStrCopy(fqdnStr, prefix);
224 ConvertDomainNameToCString(fqdn, fqdnStr + mDNSPlatformStrLen(prefix));
225 }
226 MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
227 kr = proxy_mDNSConfigureServer(getHelperPort(retry), updown, fqdnStr);
228 MACHRETRYLOOP_END(kr, retry, err, fin);
229 fin:
230 (void)err;
231 }
232
233 int mDNSAutoTunnelSetKeys(int replacedelete, v6addr_t local_inner,
234 v6addr_t local_outer, short local_port, v6addr_t remote_inner,
235 v6addr_t remote_outer, short remote_port, const char* const prefix, const domainname *const fqdn)
236 {
237 kern_return_t kr = KERN_SUCCESS;
238 int retry = 0, err = 0;
239 char fqdnStr[MAX_ESCAPED_DOMAIN_NAME + 10] = { 0 }; // Assume the prefix is no larger than 10 chars
240 if (fqdn)
241 {
242 mDNSPlatformStrCopy(fqdnStr, prefix);
243 ConvertDomainNameToCString(fqdn, fqdnStr + mDNSPlatformStrLen(prefix));
244 }
245 MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
246 kr = proxy_mDNSAutoTunnelSetKeys(getHelperPort(retry), replacedelete, local_inner, local_outer, local_port, remote_inner, remote_outer, remote_port, fqdnStr, &err);
247 MACHRETRYLOOP_END(kr, retry, err, fin);
248 fin:
249 return err;
250 }
251
252 void mDNSSendWakeupPacket(unsigned ifid, char *eth_addr, char *ip_addr, int iteration)
253 {
254 kern_return_t kr = KERN_SUCCESS;
255 int retry = 0, err = 0;
256 MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
257 kr = proxy_mDNSSendWakeupPacket(getHelperPort(retry), ifid, eth_addr, ip_addr, iteration);
258 MACHRETRYLOOP_END(kr, retry, err, fin);
259 fin:
260 (void) err;
261 }
262
263 void mDNSPacketFilterControl(uint32_t command, char * ifname, uint32_t count, pfArray_t portArray, pfArray_t protocolArray)
264 {
265 kern_return_t kr = KERN_SUCCESS;
266 int retry = 0, err = 0;
267 MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
268 kr = proxy_mDNSPacketFilterControl(getHelperPort(retry), command, ifname, count, portArray, protocolArray);
269 MACHRETRYLOOP_END(kr, retry, err, fin);
270 fin:
271 (void) err;
272 }
273
274 int mDNSSendKeepalive(v6addr_t sadd, v6addr_t dadd, uint16_t lport, uint16_t rport, unsigned seq, unsigned ack, uint16_t win)
275 {
276 kern_return_t kr = KERN_FAILURE;
277 int retry = 0, err = 0;
278 MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
279 kr = proxy_mDNSSendKeepalive(getHelperPort(retry), sadd, dadd, lport, rport, seq, ack, win);
280 MACHRETRYLOOP_END(kr, retry, err, fin);
281 fin:
282 return err;
283 }
284
285
286 int mDNSInterfaceAdvtIoctl(const char *ifname, int op)
287 {
288 kern_return_t kr = KERN_FAILURE;
289 int retry = 0, err = 0;
290
291 MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
292 kr = proxy_mDNSInterfaceAdvtIoctl(getHelperPort(retry), ifname, op);
293 MACHRETRYLOOP_END(kr, retry, err, fin);
294
295 fin:
296 return err;
297 }