]>
Commit | Line | Data |
---|---|---|
67c8f8a1 A |
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 $ | |
32bb7e43 A |
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 | ||
030b743d A |
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 | ||
67c8f8a1 A |
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> | |
32bb7e43 | 86 | #include <IOKit/IOReturn.h> |
67c8f8a1 A |
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 | ||
32bb7e43 | 100 | static mach_port_t getHelperPort(int retry) |
67c8f8a1 A |
101 | { |
102 | static mach_port_t port = MACH_PORT_NULL; | |
32bb7e43 A |
103 | if (retry) port = MACH_PORT_NULL; |
104 | if (port == MACH_PORT_NULL && BOOTSTRAP_SUCCESS != bootstrap_look_up(bootstrap_port, kmDNSHelperServiceName, &port)) | |
67c8f8a1 A |
105 | LogMsg("%s: cannot contact helper", __func__); |
106 | return port; | |
107 | } | |
108 | ||
32bb7e43 | 109 | const char *mDNSHelperError(int err) |
67c8f8a1 | 110 | { |
32bb7e43 | 111 | static const char *p = "<unknown error>"; |
67c8f8a1 A |
112 | if (mDNSHelperErrorBase < err && mDNSHelperErrorEnd > err) |
113 | p = errorstring[err - mDNSHelperErrorBase - 1]; | |
114 | return p; | |
115 | } | |
116 | ||
67c8f8a1 | 117 | /* Ugly but handy. */ |
32bb7e43 A |
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) | |
67c8f8a1 A |
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); | |
32bb7e43 | 148 | kr = proxy_mDNSPreferencesSetName(getHelperPort(retry), key, oldname, newname); |
67c8f8a1 A |
149 | MACHRETRYLOOP_END(kr, retry, err, fin); |
150 | ||
151 | fin: | |
32bb7e43 | 152 | (void)err; |
67c8f8a1 A |
153 | } |
154 | ||
32bb7e43 | 155 | void mDNSDynamicStoreSetConfig(int key, const char *subkey, CFPropertyListRef value) |
67c8f8a1 A |
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 | ||
32bb7e43 | 163 | if (NULL == (stream = CFWriteStreamCreateWithAllocatedBuffers(NULL, NULL))) |
67c8f8a1 A |
164 | { |
165 | err = kmDNSHelperCreationFailed; | |
32bb7e43 | 166 | LogMsg("%s: CFWriteStreamCreateWithAllocatedBuffers failed", __func__); |
67c8f8a1 A |
167 | goto fin; |
168 | } | |
169 | CFWriteStreamOpen(stream); | |
32bb7e43 | 170 | if (0 == CFPropertyListWriteToStream(value, stream, kCFPropertyListBinaryFormat_v1_0, NULL)) |
67c8f8a1 A |
171 | { |
172 | err = kmDNSHelperPListWriteFailed; | |
173 | LogMsg("%s: CFPropertyListWriteToStream failed", __func__); | |
174 | goto fin; | |
175 | } | |
32bb7e43 | 176 | if (NULL == (bytes = CFWriteStreamCopyProperty(stream, kCFStreamPropertyDataWritten))) |
67c8f8a1 A |
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); | |
32bb7e43 | 186 | kr = proxy_mDNSDynamicStoreSetConfig(getHelperPort(retry), key, subkey ? subkey : "", (vm_offset_t)CFDataGetBytePtr(bytes), CFDataGetLength(bytes)); |
67c8f8a1 A |
187 | MACHRETRYLOOP_END(kr, retry, err, fin); |
188 | ||
189 | fin: | |
32bb7e43 A |
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: | |
67c8f8a1 A |
225 | return err; |
226 | } | |
227 | ||
32bb7e43 A |
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) | |
67c8f8a1 A |
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; | |
32bb7e43 | 247 | int retry = 0, err = 0; |
67c8f8a1 | 248 | |
67c8f8a1 | 249 | MACHRETRYLOOP_BEGIN(kr, retry, err, fin); |
32bb7e43 | 250 | kr = proxy_mDNSKeychainGetSecrets(getHelperPort(retry), &numsecrets, (vm_offset_t *)&secrets, &secretsCnt, &err); |
67c8f8a1 | 251 | MACHRETRYLOOP_END(kr, retry, err, fin); |
030b743d | 252 | |
32bb7e43 | 253 | if (NULL == (bytes = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, secrets, secretsCnt, kCFAllocatorNull))) |
67c8f8a1 A |
254 | { |
255 | err = kmDNSHelperCreationFailed; | |
256 | LogMsg("%s: CFDataCreateWithBytesNoCopy failed", __func__); | |
257 | goto fin; | |
258 | } | |
32bb7e43 | 259 | if (NULL == (plist = CFPropertyListCreateFromXMLData(kCFAllocatorDefault, bytes, kCFPropertyListImmutable, NULL))) |
67c8f8a1 A |
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: | |
32bb7e43 A |
276 | if (NULL != bytes) CFRelease(bytes); |
277 | if (NULL != secrets) vm_deallocate(mach_task_self(), (vm_offset_t)secrets, secretsCnt); | |
67c8f8a1 A |
278 | return err; |
279 | } | |
280 | ||
32bb7e43 | 281 | void mDNSAutoTunnelInterfaceUpDown(int updown, v6addr_t address) |
67c8f8a1 A |
282 | { |
283 | kern_return_t kr = KERN_SUCCESS; | |
32bb7e43 | 284 | int retry = 0, err = 0; |
67c8f8a1 | 285 | MACHRETRYLOOP_BEGIN(kr, retry, err, fin); |
32bb7e43 | 286 | kr = proxy_mDNSAutoTunnelInterfaceUpDown(getHelperPort(retry), updown, address); |
67c8f8a1 | 287 | MACHRETRYLOOP_END(kr, retry, err, fin); |
67c8f8a1 | 288 | fin: |
32bb7e43 | 289 | (void)err; |
67c8f8a1 A |
290 | } |
291 | ||
32bb7e43 | 292 | void mDNSConfigureServer(int updown, const domainname *const fqdn) |
67c8f8a1 A |
293 | { |
294 | kern_return_t kr = KERN_SUCCESS; | |
32bb7e43 A |
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 | } | |
67c8f8a1 | 303 | MACHRETRYLOOP_BEGIN(kr, retry, err, fin); |
32bb7e43 | 304 | kr = proxy_mDNSConfigureServer(getHelperPort(retry), updown, fqdnStr); |
67c8f8a1 | 305 | MACHRETRYLOOP_END(kr, retry, err, fin); |
67c8f8a1 | 306 | fin: |
32bb7e43 | 307 | (void)err; |
67c8f8a1 A |
308 | } |
309 | ||
32bb7e43 | 310 | int mDNSAutoTunnelSetKeys(int replacedelete, v6addr_t local_inner, |
67c8f8a1 | 311 | v4addr_t local_outer, short local_port, v6addr_t remote_inner, |
32bb7e43 | 312 | v4addr_t remote_outer, short remote_port, const domainname *const fqdn) |
67c8f8a1 A |
313 | { |
314 | kern_return_t kr = KERN_SUCCESS; | |
32bb7e43 A |
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 | } | |
67c8f8a1 | 323 | MACHRETRYLOOP_BEGIN(kr, retry, err, fin); |
32bb7e43 | 324 | kr = proxy_mDNSAutoTunnelSetKeys(getHelperPort(retry), replacedelete, local_inner, local_outer, local_port, remote_inner, remote_outer, remote_port, fqdnStr, &err); |
67c8f8a1 | 325 | MACHRETRYLOOP_END(kr, retry, err, fin); |
67c8f8a1 A |
326 | fin: |
327 | return err; | |
328 | } |