2 * Copyright (c) 2007-2012 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.
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"
25 #include "helpermsg.h"
27 #define ERROR(x, y) y,
28 static const char *errorstring
[] =
30 #include "helper-error.h"
35 static mach_port_t
getHelperPort(int retry
)
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__
);
44 const char *mDNSHelperError(int err
)
46 static const char *p
= "<unknown error>";
47 if (mDNSHelperErrorBase
< err
&& mDNSHelperErrorEnd
> err
)
48 p
= errorstring
[err
- mDNSHelperErrorBase
- 1];
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
56 #define MACHRETRYLOOP_BEGIN(kr, retry, err, fin) \
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; \
64 (err) = kmDNSHelperCommunicationFailed; \
65 LogMsg("%s: Mach communication failed: %d %X %s", __func__, kr, kr, mach_error_string(kr)); \
69 if (0 != (err) && kIOReturnNotReady != (err)) \
70 { LogMsg("%s: %d 0x%X (%s)", __func__, (err), (err), mDNSHelperError(err)); goto fin; }
72 void mDNSPreferencesSetName(int key
, domainlabel
*old
, domainlabel
*new)
74 kern_return_t kr
= KERN_FAILURE
;
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
);
82 MACHRETRYLOOP_BEGIN(kr
, retry
, err
, fin
);
83 kr
= proxy_mDNSPreferencesSetName(getHelperPort(retry
), key
, oldname
, newname
);
84 MACHRETRYLOOP_END(kr
, retry
, err
, fin
);
90 void mDNSDynamicStoreSetConfig(int key
, const char *subkey
, CFPropertyListRef value
)
92 CFWriteStreamRef stream
= NULL
;
93 CFDataRef bytes
= NULL
;
94 kern_return_t kr
= KERN_FAILURE
;
98 if (NULL
== (stream
= CFWriteStreamCreateWithAllocatedBuffers(NULL
, NULL
)))
100 err
= kmDNSHelperCreationFailed
;
101 LogMsg("%s: CFWriteStreamCreateWithAllocatedBuffers failed", __func__
);
104 CFWriteStreamOpen(stream
);
105 if (0 == CFPropertyListWriteToStream(value
, stream
, kCFPropertyListBinaryFormat_v1_0
, NULL
))
107 err
= kmDNSHelperPListWriteFailed
;
108 LogMsg("%s: CFPropertyListWriteToStream failed", __func__
);
111 if (NULL
== (bytes
= CFWriteStreamCopyProperty(stream
, kCFStreamPropertyDataWritten
)))
113 err
= kmDNSHelperCreationFailed
;
114 LogMsg("%s: CFWriteStreamCopyProperty failed", __func__
);
117 CFWriteStreamClose(stream
);
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
);
125 if (NULL
!= stream
) { CFWriteStreamClose(stream
); CFRelease(stream
); }
126 if (NULL
!= bytes
) CFRelease(bytes
);
130 void mDNSRequestBPF(void)
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
);
141 int mDNSPowerRequest(int key
, int interval
)
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
);
152 int mDNSSetLocalAddressCacheEntry(int ifindex
, int family
, const v6addr_t ip
, const ethaddr_t eth
)
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
);
163 void mDNSNotify(const char *title
, const char *msg
) // Both strings are UTF-8 text
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
);
174 int mDNSKeychainGetSecrets(CFArrayRef
*result
)
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;
184 MACHRETRYLOOP_BEGIN(kr
, retry
, err
, fin
);
185 kr
= proxy_mDNSKeychainGetSecrets(getHelperPort(retry
), &numsecrets
, &secrets
, &secretsCnt
, &err
);
186 MACHRETRYLOOP_END(kr
, retry
, err
, fin
);
188 if (NULL
== (bytes
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, (void*)secrets
, secretsCnt
, kCFAllocatorNull
)))
190 err
= kmDNSHelperCreationFailed
;
191 LogMsg("%s: CFDataCreateWithBytesNoCopy failed", __func__
);
194 if (NULL
== (plist
= CFPropertyListCreateFromXMLData(kCFAllocatorDefault
, bytes
, kCFPropertyListImmutable
, NULL
)))
196 err
= kmDNSHelperInvalidPList
;
197 LogMsg("%s: CFPropertyListCreateFromXMLData failed", __func__
);
200 if (CFArrayGetTypeID() != CFGetTypeID(plist
))
202 err
= kmDNSHelperTypeError
;
203 LogMsg("%s: Unexpected result type", __func__
);
208 *result
= (CFArrayRef
)plist
;
211 if (bytes
) CFRelease(bytes
);
212 if (secrets
) vm_deallocate(mach_task_self(), secrets
, secretsCnt
);
216 void mDNSConfigureServer(int updown
, const char *const prefix
, const domainname
*const fqdn
)
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
223 mDNSPlatformStrCopy(fqdnStr
, prefix
);
224 ConvertDomainNameToCString(fqdn
, fqdnStr
+ mDNSPlatformStrLen(prefix
));
226 MACHRETRYLOOP_BEGIN(kr
, retry
, err
, fin
);
227 kr
= proxy_mDNSConfigureServer(getHelperPort(retry
), updown
, fqdnStr
);
228 MACHRETRYLOOP_END(kr
, retry
, err
, fin
);
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
)
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
242 mDNSPlatformStrCopy(fqdnStr
, prefix
);
243 ConvertDomainNameToCString(fqdn
, fqdnStr
+ mDNSPlatformStrLen(prefix
));
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
);
252 void mDNSSendWakeupPacket(unsigned ifid
, char *eth_addr
, char *ip_addr
, int iteration
)
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
);
263 void mDNSPacketFilterControl(uint32_t command
, char * ifname
, uint32_t count
, pfArray_t portArray
, pfArray_t protocolArray
)
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
);
274 int mDNSSendKeepalive(v6addr_t sadd
, v6addr_t dadd
, uint16_t lport
, uint16_t rport
, unsigned seq
, unsigned ack
, uint16_t win
)
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
);
286 int mDNSInterfaceAdvtIoctl(const char *ifname
, int op
)
288 kern_return_t kr
= KERN_FAILURE
;
289 int retry
= 0, err
= 0;
291 MACHRETRYLOOP_BEGIN(kr
, retry
, err
, fin
);
292 kr
= proxy_mDNSInterfaceAdvtIoctl(getHelperPort(retry
), ifname
, op
);
293 MACHRETRYLOOP_END(kr
, retry
, err
, fin
);