2 * Copyright (c) 2007 Apple Inc. All rights reserved.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 Change History (most recent first):
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
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
28 Revision 1.17 2009/03/20 20:52:22 cheshire
29 <rdar://problem/6703952> Support CFUserNotificationDisplayNotice in mDNSResponderHelper
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
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
37 Revision 1.14 2009/01/14 01:38:42 mcguire
38 <rdar://problem/6492710> Write out DynamicStore per-interface SleepProxyServer info
40 Revision 1.13 2009/01/14 01:28:17 mcguire
41 removed unused variable
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
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.
51 Revision 1.10 2008/10/29 21:25:35 cheshire
52 Don't report kIOReturnNotReady errors
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
57 Revision 1.8 2008/10/20 22:01:28 cheshire
58 Made new Mach simpleroutine "mDNSRequestBPF"
60 Revision 1.7 2008/09/27 00:58:32 cheshire
61 Added mDNSRequestBPF definition
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)
66 Revision 1.5 2007/09/07 22:44:03 mcguire
67 <rdar://problem/5448420> Move CFUserNotification code to mDNSResponderHelper
69 Revision 1.4 2007/09/04 22:32:58 mcguire
70 <rdar://problem/5453633> BTMM: BTMM overwrites /etc/racoon/remote/anonymous.conf
72 Revision 1.3 2007/08/23 21:44:55 cheshire
73 Made code layout style consistent with existing project style; added $Log header
75 Revision 1.2 2007/08/18 01:02:03 mcguire
76 <rdar://problem/5415593> No Bonjour services are getting registered at boot
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
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"
90 #include "helpermsg.h"
92 #define ERROR(x, y) y,
93 static const char *errorstring
[] =
95 #include "helper-error.h"
100 static mach_port_t
getHelperPort(int retry
)
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__
);
109 const char *mDNSHelperError(int err
)
111 static const char *p
= "<unknown error>";
112 if (mDNSHelperErrorBase
< err
&& mDNSHelperErrorEnd
> err
)
113 p
= errorstring
[err
- mDNSHelperErrorBase
- 1];
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
121 #define MACHRETRYLOOP_BEGIN(kr, retry, err, fin) \
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; \
129 (err) = kmDNSHelperCommunicationFailed; \
130 LogMsg("%s: Mach communication failed: %s", __func__, mach_error_string(kr)); \
134 if (0 != (err) && kIOReturnNotReady != (err)) \
135 { LogMsg("%s: %d 0x%X (%s)", __func__, (err), (err), mDNSHelperError(err)); goto fin; }
137 void mDNSPreferencesSetName(int key
, domainlabel
*old
, domainlabel
*new)
139 kern_return_t kr
= KERN_FAILURE
;
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
);
147 MACHRETRYLOOP_BEGIN(kr
, retry
, err
, fin
);
148 kr
= proxy_mDNSPreferencesSetName(getHelperPort(retry
), key
, oldname
, newname
);
149 MACHRETRYLOOP_END(kr
, retry
, err
, fin
);
155 void mDNSDynamicStoreSetConfig(int key
, const char *subkey
, CFPropertyListRef value
)
157 CFWriteStreamRef stream
= NULL
;
158 CFDataRef bytes
= NULL
;
159 kern_return_t kr
= KERN_FAILURE
;
163 if (NULL
== (stream
= CFWriteStreamCreateWithAllocatedBuffers(NULL
, NULL
)))
165 err
= kmDNSHelperCreationFailed
;
166 LogMsg("%s: CFWriteStreamCreateWithAllocatedBuffers failed", __func__
);
169 CFWriteStreamOpen(stream
);
170 if (0 == CFPropertyListWriteToStream(value
, stream
, kCFPropertyListBinaryFormat_v1_0
, NULL
))
172 err
= kmDNSHelperPListWriteFailed
;
173 LogMsg("%s: CFPropertyListWriteToStream failed", __func__
);
176 if (NULL
== (bytes
= CFWriteStreamCopyProperty(stream
, kCFStreamPropertyDataWritten
)))
178 err
= kmDNSHelperCreationFailed
;
179 LogMsg("%s: CFWriteStreamCopyProperty failed", __func__
);
182 CFWriteStreamClose(stream
);
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
);
190 if (NULL
!= stream
) { CFWriteStreamClose(stream
); CFRelease(stream
); }
191 if (NULL
!= bytes
) CFRelease(bytes
);
195 void mDNSRequestBPF(void)
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
);
206 int mDNSPowerRequest(int key
, int interval
)
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
);
217 int mDNSSetARP(int ifindex
, const v4addr_t ip
, const ethaddr_t eth
)
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
);
228 void mDNSNotify(const char *title
, const char *msg
) // Both strings are UTF-8 text
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
);
239 int mDNSKeychainGetSecrets(CFArrayRef
*result
)
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;
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
);
253 if (NULL
== (bytes
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, secrets
, secretsCnt
, kCFAllocatorNull
)))
255 err
= kmDNSHelperCreationFailed
;
256 LogMsg("%s: CFDataCreateWithBytesNoCopy failed", __func__
);
259 if (NULL
== (plist
= CFPropertyListCreateFromXMLData(kCFAllocatorDefault
, bytes
, kCFPropertyListImmutable
, NULL
)))
261 err
= kmDNSHelperInvalidPList
;
262 LogMsg("%s: CFPropertyListCreateFromXMLData failed", __func__
);
265 if (CFArrayGetTypeID() != CFGetTypeID(plist
))
267 err
= kmDNSHelperTypeError
;
268 LogMsg("%s: Unexpected result type", __func__
);
273 *result
= (CFArrayRef
)plist
;
276 if (NULL
!= bytes
) CFRelease(bytes
);
277 if (NULL
!= secrets
) vm_deallocate(mach_task_self(), (vm_offset_t
)secrets
, secretsCnt
);
281 void mDNSAutoTunnelInterfaceUpDown(int updown
, v6addr_t address
)
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
);
292 void mDNSConfigureServer(int updown
, const domainname
*const fqdn
)
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
))
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;
303 MACHRETRYLOOP_BEGIN(kr
, retry
, err
, fin
);
304 kr
= proxy_mDNSConfigureServer(getHelperPort(retry
), updown
, fqdnStr
);
305 MACHRETRYLOOP_END(kr
, retry
, err
, fin
);
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
)
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
))
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;
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
);