]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSMacOSX/helper-stubs.c
mDNSResponder-212.1.tar.gz
[apple/mdnsresponder.git] / mDNSMacOSX / helper-stubs.c
1 /*
2 * Copyright (c) 2007 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 Change History (most recent first):
17
18 $Log: helper-stubs.c,v $
19 Revision 1.19 2009/04/20 20:40:14 cheshire
20 <rdar://problem/6786150> uDNS: Running location cycling caused configd and mDNSResponder to deadlock
21 Changed mDNSPreferencesSetName (and similar) routines from MIG "routine" to MIG "simpleroutine"
22 so we don't deadlock waiting for a result that we're just going to ignore anyway
23
24 Revision 1.18 2009/03/20 22:12:27 mcguire
25 <rdar://problem/6703952> Support CFUserNotificationDisplayNotice in mDNSResponderHelper
26 Make the call to the helper a simpleroutine: don't wait for an unused return value
27
28 Revision 1.17 2009/03/20 20:52:22 cheshire
29 <rdar://problem/6703952> Support CFUserNotificationDisplayNotice in mDNSResponderHelper
30
31 Revision 1.16 2009/03/14 01:42:56 mcguire
32 <rdar://problem/5457116> BTMM: Fix issues with multiple .Mac accounts on the same machine
33
34 Revision 1.15 2009/01/22 02:14:27 cheshire
35 <rdar://problem/6515626> Sleep Proxy: Set correct target MAC address, instead of all zeroes
36
37 Revision 1.14 2009/01/14 01:38:42 mcguire
38 <rdar://problem/6492710> Write out DynamicStore per-interface SleepProxyServer info
39
40 Revision 1.13 2009/01/14 01:28:17 mcguire
41 removed unused variable
42
43 Revision 1.12 2008/11/11 00:46:37 cheshire
44 Don't just show "<unknown error>"; show the actual numeric error code too, so we can see what the unknown error was
45
46 Revision 1.11 2008/11/04 23:54:09 cheshire
47 Added routine mDNSSetARP(), used to replace an SPS client's entry in our ARP cache with
48 a dummy one, so that IP traffic to the SPS client initiated by the SPS machine can be
49 captured by our BPF filters, and used as a trigger to wake the sleeping machine.
50
51 Revision 1.10 2008/10/29 21:25:35 cheshire
52 Don't report kIOReturnNotReady errors
53
54 Revision 1.9 2008/10/24 01:42:36 cheshire
55 Added mDNSPowerRequest helper routine to request a scheduled wakeup some time in the future
56
57 Revision 1.8 2008/10/20 22:01:28 cheshire
58 Made new Mach simpleroutine "mDNSRequestBPF"
59
60 Revision 1.7 2008/09/27 00:58:32 cheshire
61 Added mDNSRequestBPF definition
62
63 Revision 1.6 2007/12/10 23:23:48 cheshire
64 Removed unnecessary log message ("mDNSKeychainGetSecrets failed 0 00000000" because mDNSKeychainGetSecrets was failing to return a valid array)
65
66 Revision 1.5 2007/09/07 22:44:03 mcguire
67 <rdar://problem/5448420> Move CFUserNotification code to mDNSResponderHelper
68
69 Revision 1.4 2007/09/04 22:32:58 mcguire
70 <rdar://problem/5453633> BTMM: BTMM overwrites /etc/racoon/remote/anonymous.conf
71
72 Revision 1.3 2007/08/23 21:44:55 cheshire
73 Made code layout style consistent with existing project style; added $Log header
74
75 Revision 1.2 2007/08/18 01:02:03 mcguire
76 <rdar://problem/5415593> No Bonjour services are getting registered at boot
77
78 Revision 1.1 2007/08/08 22:34:58 mcguire
79 <rdar://problem/5197869> Security: Run mDNSResponder as user id mdnsresponder instead of root
80 */
81
82 #include <mach/mach.h>
83 #include <mach/mach_error.h>
84 #include <mach/vm_map.h>
85 #include <servers/bootstrap.h>
86 #include <IOKit/IOReturn.h>
87 #include <CoreFoundation/CoreFoundation.h>
88 #include "mDNSDebug.h"
89 #include "helper.h"
90 #include "helpermsg.h"
91
92 #define ERROR(x, y) y,
93 static const char *errorstring[] =
94 {
95 #include "helper-error.h"
96 NULL
97 };
98 #undef ERROR
99
100 static mach_port_t getHelperPort(int retry)
101 {
102 static mach_port_t port = MACH_PORT_NULL;
103 if (retry) port = MACH_PORT_NULL;
104 if (port == MACH_PORT_NULL && BOOTSTRAP_SUCCESS != bootstrap_look_up(bootstrap_port, kmDNSHelperServiceName, &port))
105 LogMsg("%s: cannot contact helper", __func__);
106 return port;
107 }
108
109 const char *mDNSHelperError(int err)
110 {
111 static const char *p = "<unknown error>";
112 if (mDNSHelperErrorBase < err && mDNSHelperErrorEnd > err)
113 p = errorstring[err - mDNSHelperErrorBase - 1];
114 return p;
115 }
116
117 /* Ugly but handy. */
118 // We don't bother reporting kIOReturnNotReady because that error code occurs in "normal" operation
119 // and doesn't indicate anything unexpected that needs to be investigated
120
121 #define MACHRETRYLOOP_BEGIN(kr, retry, err, fin) \
122 for (;;) \
123 {
124 #define MACHRETRYLOOP_END(kr, retry, err, fin) \
125 if (KERN_SUCCESS == (kr)) break; \
126 else if (MACH_SEND_INVALID_DEST == (kr) && 0 == (retry)++) continue; \
127 else \
128 { \
129 (err) = kmDNSHelperCommunicationFailed; \
130 LogMsg("%s: Mach communication failed: %s", __func__, mach_error_string(kr)); \
131 goto fin; \
132 } \
133 } \
134 if (0 != (err) && kIOReturnNotReady != (err)) \
135 { LogMsg("%s: %d 0x%X (%s)", __func__, (err), (err), mDNSHelperError(err)); goto fin; }
136
137 void mDNSPreferencesSetName(int key, domainlabel *old, domainlabel *new)
138 {
139 kern_return_t kr = KERN_FAILURE;
140 int retry = 0;
141 int err = 0;
142 char oldname[MAX_DOMAIN_LABEL+1] = {0};
143 char newname[MAX_DOMAIN_LABEL+1] = {0};
144 ConvertDomainLabelToCString_unescaped(old, oldname);
145 if (new) ConvertDomainLabelToCString_unescaped(new, newname);
146
147 MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
148 kr = proxy_mDNSPreferencesSetName(getHelperPort(retry), key, oldname, newname);
149 MACHRETRYLOOP_END(kr, retry, err, fin);
150
151 fin:
152 (void)err;
153 }
154
155 void mDNSDynamicStoreSetConfig(int key, const char *subkey, CFPropertyListRef value)
156 {
157 CFWriteStreamRef stream = NULL;
158 CFDataRef bytes = NULL;
159 kern_return_t kr = KERN_FAILURE;
160 int retry = 0;
161 int err = 0;
162
163 if (NULL == (stream = CFWriteStreamCreateWithAllocatedBuffers(NULL, NULL)))
164 {
165 err = kmDNSHelperCreationFailed;
166 LogMsg("%s: CFWriteStreamCreateWithAllocatedBuffers failed", __func__);
167 goto fin;
168 }
169 CFWriteStreamOpen(stream);
170 if (0 == CFPropertyListWriteToStream(value, stream, kCFPropertyListBinaryFormat_v1_0, NULL))
171 {
172 err = kmDNSHelperPListWriteFailed;
173 LogMsg("%s: CFPropertyListWriteToStream failed", __func__);
174 goto fin;
175 }
176 if (NULL == (bytes = CFWriteStreamCopyProperty(stream, kCFStreamPropertyDataWritten)))
177 {
178 err = kmDNSHelperCreationFailed;
179 LogMsg("%s: CFWriteStreamCopyProperty failed", __func__);
180 goto fin;
181 }
182 CFWriteStreamClose(stream);
183 CFRelease(stream);
184 stream = NULL;
185 MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
186 kr = proxy_mDNSDynamicStoreSetConfig(getHelperPort(retry), key, subkey ? subkey : "", (vm_offset_t)CFDataGetBytePtr(bytes), CFDataGetLength(bytes));
187 MACHRETRYLOOP_END(kr, retry, err, fin);
188
189 fin:
190 if (NULL != stream) { CFWriteStreamClose(stream); CFRelease(stream); }
191 if (NULL != bytes) CFRelease(bytes);
192 (void)err;
193 }
194
195 void mDNSRequestBPF(void)
196 {
197 kern_return_t kr = KERN_FAILURE;
198 int retry = 0, err = 0;
199 MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
200 kr = proxy_mDNSRequestBPF(getHelperPort(retry));
201 MACHRETRYLOOP_END(kr, retry, err, fin);
202 fin:
203 (void)err;
204 }
205
206 int mDNSPowerRequest(int key, int interval)
207 {
208 kern_return_t kr = KERN_FAILURE;
209 int retry = 0, err = 0;
210 MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
211 kr = proxy_mDNSPowerRequest(getHelperPort(retry), key, interval, &err);
212 MACHRETRYLOOP_END(kr, retry, err, fin);
213 fin:
214 return err;
215 }
216
217 int mDNSSetARP(int ifindex, const v4addr_t ip, const ethaddr_t eth)
218 {
219 kern_return_t kr = KERN_FAILURE;
220 int retry = 0, err = 0;
221 MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
222 kr = proxy_mDNSSetARP(getHelperPort(retry), ifindex, (uint8_t*)ip, (uint8_t*)eth, &err);
223 MACHRETRYLOOP_END(kr, retry, err, fin);
224 fin:
225 return err;
226 }
227
228 void mDNSNotify(const char *title, const char *msg) // Both strings are UTF-8 text
229 {
230 kern_return_t kr = KERN_FAILURE;
231 int retry = 0, err = 0;
232 MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
233 kr = proxy_mDNSNotify(getHelperPort(retry), title, msg);
234 MACHRETRYLOOP_END(kr, retry, err, fin);
235 fin:
236 (void)err;
237 }
238
239 int mDNSKeychainGetSecrets(CFArrayRef *result)
240 {
241 CFPropertyListRef plist = NULL;
242 CFDataRef bytes = NULL;
243 kern_return_t kr = KERN_FAILURE;
244 unsigned int numsecrets = 0;
245 void *secrets = NULL;
246 mach_msg_type_number_t secretsCnt = 0;
247 int retry = 0, err = 0;
248
249 MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
250 kr = proxy_mDNSKeychainGetSecrets(getHelperPort(retry), &numsecrets, (vm_offset_t *)&secrets, &secretsCnt, &err);
251 MACHRETRYLOOP_END(kr, retry, err, fin);
252
253 if (NULL == (bytes = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, secrets, secretsCnt, kCFAllocatorNull)))
254 {
255 err = kmDNSHelperCreationFailed;
256 LogMsg("%s: CFDataCreateWithBytesNoCopy failed", __func__);
257 goto fin;
258 }
259 if (NULL == (plist = CFPropertyListCreateFromXMLData(kCFAllocatorDefault, bytes, kCFPropertyListImmutable, NULL)))
260 {
261 err = kmDNSHelperInvalidPList;
262 LogMsg("%s: CFPropertyListCreateFromXMLData failed", __func__);
263 goto fin;
264 }
265 if (CFArrayGetTypeID() != CFGetTypeID(plist))
266 {
267 err = kmDNSHelperTypeError;
268 LogMsg("%s: Unexpected result type", __func__);
269 CFRelease(plist);
270 plist = NULL;
271 goto fin;
272 }
273 *result = (CFArrayRef)plist;
274
275 fin:
276 if (NULL != bytes) CFRelease(bytes);
277 if (NULL != secrets) vm_deallocate(mach_task_self(), (vm_offset_t)secrets, secretsCnt);
278 return err;
279 }
280
281 void mDNSAutoTunnelInterfaceUpDown(int updown, v6addr_t address)
282 {
283 kern_return_t kr = KERN_SUCCESS;
284 int retry = 0, err = 0;
285 MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
286 kr = proxy_mDNSAutoTunnelInterfaceUpDown(getHelperPort(retry), updown, address);
287 MACHRETRYLOOP_END(kr, retry, err, fin);
288 fin:
289 (void)err;
290 }
291
292 void mDNSConfigureServer(int updown, const domainname *const fqdn)
293 {
294 kern_return_t kr = KERN_SUCCESS;
295 int retry = 0, err = 0;
296 char fqdnStr[MAX_ESCAPED_DOMAIN_NAME] = { 0 };
297 if (fqdn && ConvertDomainNameToCString(fqdn, fqdnStr))
298 {
299 // remove the trailing dot, as that is not used in the keychain entry racoon will lookup
300 mDNSu32 fqdnEnd = mDNSPlatformStrLen(fqdnStr);
301 if (fqdnEnd) fqdnStr[fqdnEnd - 1] = 0;
302 }
303 MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
304 kr = proxy_mDNSConfigureServer(getHelperPort(retry), updown, fqdnStr);
305 MACHRETRYLOOP_END(kr, retry, err, fin);
306 fin:
307 (void)err;
308 }
309
310 int mDNSAutoTunnelSetKeys(int replacedelete, v6addr_t local_inner,
311 v4addr_t local_outer, short local_port, v6addr_t remote_inner,
312 v4addr_t remote_outer, short remote_port, const domainname *const fqdn)
313 {
314 kern_return_t kr = KERN_SUCCESS;
315 int retry = 0, err = 0;
316 char fqdnStr[MAX_ESCAPED_DOMAIN_NAME] = { 0 };
317 if (fqdn && ConvertDomainNameToCString(fqdn, fqdnStr))
318 {
319 // remove the trailing dot, as that is not used in the keychain entry racoon will lookup
320 mDNSu32 fqdnEnd = mDNSPlatformStrLen(fqdnStr);
321 if (fqdnEnd) fqdnStr[fqdnEnd - 1] = 0;
322 }
323 MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
324 kr = proxy_mDNSAutoTunnelSetKeys(getHelperPort(retry), replacedelete, local_inner, local_outer, local_port, remote_inner, remote_outer, remote_port, fqdnStr, &err);
325 MACHRETRYLOOP_END(kr, retry, err, fin);
326 fin:
327 return err;
328 }