1 /* -*- Mode: C; tab-width: 4 -*-
3 * Copyright (c) 2007-2018 Apple Inc. All rights reserved.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 #include <mach/mach.h>
19 #include <mach/mach_error.h>
20 #include <mach/vm_map.h>
21 #include <servers/bootstrap.h>
22 #include <IOKit/IOReturn.h>
23 #include <CoreFoundation/CoreFoundation.h>
24 #include "mDNSDebug.h"
26 #include <dispatch/dispatch.h>
27 #include <arpa/inet.h>
28 #include <xpc/private.h>
32 // Implementation Notes about the HelperQueue:
34 // To prevent blocking the main queue, all communications with mDNSResponderHelper should happen on
35 // HelperQueue. There are a few calls which are still synchronous and needs to be handled separately
38 // When spawning off the work to the HelperQueue, any arguments that are pointers need to be copied
39 // explicitly as they may cease to exist after the call returns. From within the block that is scheduled,
40 // arrays defined on the stack can't be referenced and hence it is enclosed them in a struct. If the array is
41 // an argument to the function, the blocks can reference them as they are passed in as pointers. But care should
42 // be taken to copy them locally as they may cease to exist when the function returns.
46 //*************************************************************************************************************
48 static dispatch_queue_t HelperQueue
;
49 static xpc_connection_t helper_xpc_conn
= NULL
;
51 static int64_t maxwait_secs
= 5LL;
53 #define mDNSHELPER_DEBUG LogOperation
55 //*************************************************************************************************************
58 static void HelperLog(const char *prefix
, xpc_object_t o
)
60 char *desc
= xpc_copy_description(o
);
61 mDNSHELPER_DEBUG("HelperLog %s: %s", prefix
, desc
);
65 //*************************************************************************************************************
67 //*************************************************************************************************************
70 mDNSlocal
void Init_Connection(const char *servname
)
72 helper_xpc_conn
= xpc_connection_create_mach_service(servname
, HelperQueue
, XPC_CONNECTION_MACH_SERVICE_PRIVILEGED
);
74 xpc_connection_set_event_handler(helper_xpc_conn
, ^(xpc_object_t event
)
76 mDNSHELPER_DEBUG("Init_Connection xpc: [%s] \n", xpc_dictionary_get_string(event
, XPC_ERROR_KEY_DESCRIPTION
));
79 xpc_connection_resume(helper_xpc_conn
);
82 mDNSlocal
int SendDict_ToServer(xpc_object_t msg
)
84 __block
int errorcode
= kHelperErr_NoResponse
;
86 HelperLog("SendDict_ToServer Sending msg to Daemon", msg
);
88 dispatch_semaphore_t sem
= dispatch_semaphore_create(0);
89 dispatch_retain(sem
); // for the block below
91 xpc_connection_send_message_with_reply(helper_xpc_conn
, msg
, HelperQueue
, ^(xpc_object_t recv_msg
)
93 xpc_type_t type
= xpc_get_type(recv_msg
);
95 if (type
== XPC_TYPE_DICTIONARY
)
97 HelperLog("SendDict_ToServer Received reply msg from Daemon", recv_msg
);
98 uint64_t reply_status
= xpc_dictionary_get_uint64(recv_msg
, kHelperReplyStatus
);
99 errorcode
= xpc_dictionary_get_int64(recv_msg
, kHelperErrCode
);
101 switch (reply_status
)
103 case kHelperReply_ACK
:
104 mDNSHELPER_DEBUG("NoError: successful reply");
107 LogMsg("default: Unexpected reply from Helper");
113 LogMsg("SendDict_ToServer Received unexpected reply from daemon [%s]",
114 xpc_dictionary_get_string(recv_msg
, XPC_ERROR_KEY_DESCRIPTION
));
115 HelperLog("SendDict_ToServer Unexpected Reply contents", recv_msg
);
118 dispatch_semaphore_signal(sem
);
119 dispatch_release(sem
);
123 if (dispatch_semaphore_wait(sem
, dispatch_time(DISPATCH_TIME_NOW
, (maxwait_secs
* NSEC_PER_SEC
))) != 0)
124 LogMsg("SendDict_ToServer: UNEXPECTED WAIT_TIME in dispatch_semaphore_wait");
126 dispatch_release(sem
);
128 mDNSHELPER_DEBUG("SendDict_ToServer returning with errorcode[%d]", errorcode
);
133 mDNSlocal xpc_object_t
SendDict_GetReply(xpc_object_t msg
)
135 // Create empty dictionary
136 __block xpc_object_t dict
= xpc_dictionary_create(NULL
, NULL
, 0);
137 if (!dict
) return NULL
;
140 HelperLog("SendDict_GetReply Sending msg to Daemon", msg
);
142 dispatch_semaphore_t sem
= dispatch_semaphore_create(0);
143 dispatch_retain(sem
); // for the block below
145 xpc_connection_send_message_with_reply(helper_xpc_conn
, msg
, HelperQueue
, ^(xpc_object_t recv_msg
)
147 xpc_type_t type
= xpc_get_type(recv_msg
);
149 if (type
== XPC_TYPE_DICTIONARY
)
151 HelperLog("SendDict_GetReply Received reply msg from Daemon", recv_msg
);
152 uint64_t reply_status
= xpc_dictionary_get_uint64(recv_msg
, kHelperReplyStatus
);
154 switch (reply_status
)
156 case kHelperReply_ACK
:
157 mDNSHELPER_DEBUG("NoError: successful reply");
160 LogMsg("default: Unexpected reply from Helper");
163 // Copy result into dict reply
164 xpc_dictionary_apply(recv_msg
, ^bool(const char *key
, xpc_object_t value
)
166 xpc_dictionary_set_value(dict
, key
, value
);
172 LogMsg("SendDict_GetReply Received unexpected reply from daemon [%s]",
173 xpc_dictionary_get_string(recv_msg
, XPC_ERROR_KEY_DESCRIPTION
));
174 HelperLog("SendDict_GetReply Unexpected Reply contents", recv_msg
);
177 dispatch_semaphore_signal(sem
);
178 dispatch_release(sem
);
183 if (dispatch_semaphore_wait(sem
, dispatch_time(DISPATCH_TIME_NOW
, (maxwait_secs
* NSEC_PER_SEC
))) != 0)
185 LogMsg("SendDict_GetReply: UNEXPECTED WAIT_TIME in dispatch_semaphore_wait");
187 dispatch_release(sem
);
192 dispatch_release(sem
);
197 //**************************************************************************************************************
199 mDNSexport mStatus
mDNSHelperInit()
201 HelperQueue
= dispatch_queue_create("com.apple.mDNSResponder.HelperQueue", NULL
);
202 if (HelperQueue
== NULL
)
204 LogMsg("dispatch_queue_create: Helper queue NULL");
205 return mStatus_NoMemoryErr
;
207 return mStatus_NoError
;
210 void mDNSPreferencesSetName(int key
, domainlabel
*old
, domainlabel
*new)
214 char oldname
[MAX_DOMAIN_LABEL
+1];
215 char newname
[MAX_DOMAIN_LABEL
+1];
218 mDNSPlatformMemZero(names
.oldname
, MAX_DOMAIN_LABEL
+ 1);
219 mDNSPlatformMemZero(names
.newname
, MAX_DOMAIN_LABEL
+ 1);
221 ConvertDomainLabelToCString_unescaped(old
, names
.oldname
);
224 ConvertDomainLabelToCString_unescaped(new, names
.newname
);
227 mDNSHELPER_DEBUG("mDNSPreferencesSetName: XPC IPC Test oldname %s newname %s", names
.oldname
, names
.newname
);
228 Init_Connection(kHelperService
);
230 // Create Dictionary To Send
231 xpc_object_t dict
= xpc_dictionary_create(NULL
, NULL
, 0);
232 xpc_dictionary_set_uint64(dict
, kHelperMode
, set_name
);
234 xpc_dictionary_set_uint64(dict
, kPrefsNameKey
, key
);
235 xpc_dictionary_set_string(dict
, kPrefsOldName
, names
.oldname
);
236 xpc_dictionary_set_string(dict
, kPrefsNewName
, names
.newname
);
238 SendDict_ToServer(dict
);
244 void mDNSRequestBPF()
246 mDNSHELPER_DEBUG("mDNSRequestBPF: Using XPC IPC");
247 Init_Connection(kHelperService
);
249 // Create Dictionary To Send
250 xpc_object_t dict
= xpc_dictionary_create(NULL
, NULL
, 0);
251 xpc_dictionary_set_uint64(dict
, kHelperMode
, bpf_request
);
252 SendDict_ToServer(dict
);
258 int mDNSPowerRequest(int key
, int interval
)
260 int err_code
= kHelperErr_NotConnected
;
262 mDNSHELPER_DEBUG("mDNSPowerRequest: Using XPC IPC calling out to Helper key is [%d] interval is [%d]", key
, interval
);
263 Init_Connection(kHelperService
);
265 // Create Dictionary To Send
266 xpc_object_t dict
= xpc_dictionary_create(NULL
, NULL
, 0);
267 xpc_dictionary_set_uint64(dict
, kHelperMode
, power_req
);
268 xpc_dictionary_set_uint64(dict
, "powerreq_key", key
);
269 xpc_dictionary_set_uint64(dict
, "powerreq_interval", interval
);
271 err_code
= SendDict_ToServer(dict
);
275 mDNSHELPER_DEBUG("mDNSPowerRequest: Using XPC IPC returning error_code %d", err_code
);
279 int mDNSSetLocalAddressCacheEntry(int ifindex
, int family
, const v6addr_t ip
, const ethaddr_t eth
)
281 int err_code
= kHelperErr_NotConnected
;
283 mDNSHELPER_DEBUG("mDNSSetLocalAddressCacheEntry: Using XPC IPC calling out to Helper: ifindex is [%d] family is [%d]", ifindex
, family
);
285 Init_Connection(kHelperService
);
287 // Create Dictionary To Send
288 xpc_object_t dict
= xpc_dictionary_create(NULL
, NULL
, 0);
289 xpc_dictionary_set_uint64(dict
, kHelperMode
, set_localaddr_cacheentry
);
291 xpc_dictionary_set_uint64(dict
, "slace_ifindex", ifindex
);
292 xpc_dictionary_set_uint64(dict
, "slace_family", family
);
294 xpc_dictionary_set_data(dict
, "slace_ip", (uint8_t*)ip
, sizeof(v6addr_t
));
295 xpc_dictionary_set_data(dict
, "slace_eth", (uint8_t*)eth
, sizeof(ethaddr_t
));
297 err_code
= SendDict_ToServer(dict
);
301 mDNSHELPER_DEBUG("mDNSSetLocalAddressCacheEntry: Using XPC IPC returning error_code %d", err_code
);
306 void mDNSNotify(const char *title
, const char *msg
) // Both strings are UTF-8 text
308 mDNSHELPER_DEBUG("mDNSNotify() calling out to Helper XPC IPC title[%s] msg[%s]", title
, msg
);
310 Init_Connection(kHelperService
);
312 // Create Dictionary To Send
313 xpc_object_t dict
= xpc_dictionary_create(NULL
, NULL
, 0);
314 xpc_dictionary_set_uint64(dict
, kHelperMode
, user_notify
);
316 xpc_dictionary_set_string(dict
, "notify_title", title
);
317 xpc_dictionary_set_string(dict
, "notify_msg", msg
);
319 SendDict_ToServer(dict
);
326 int mDNSKeychainGetSecrets(CFArrayRef
*result
)
329 CFPropertyListRef plist
= NULL
;
330 CFDataRef bytes
= NULL
;
331 unsigned int numsecrets
= 0;
332 unsigned int secretsCnt
= 0;
333 int error_code
= kHelperErr_NotConnected
;
334 xpc_object_t reply_dict
= NULL
;
335 const void *sec
= NULL
;
336 size_t secrets_size
= 0;
338 mDNSHELPER_DEBUG("mDNSKeychainGetSecrets: Using XPC IPC calling out to Helper");
340 Init_Connection(kHelperService
);
342 // Create Dictionary To Send
343 xpc_object_t dict
= xpc_dictionary_create(NULL
, NULL
, 0);
344 xpc_dictionary_set_uint64(dict
, kHelperMode
, keychain_getsecrets
);
346 reply_dict
= SendDict_GetReply(dict
);
348 if (reply_dict
!= NULL
)
350 numsecrets
= xpc_dictionary_get_uint64(reply_dict
, "keychain_num_secrets");
351 sec
= xpc_dictionary_get_data(reply_dict
, "keychain_secrets", &secrets_size
);
352 secretsCnt
= xpc_dictionary_get_uint64(reply_dict
, "keychain_secrets_count");
353 error_code
= xpc_dictionary_get_int64(reply_dict
, kHelperErrCode
);
356 mDNSHELPER_DEBUG("mDNSKeychainGetSecrets: Using XPC IPC calling out to Helper: numsecrets is %d, secretsCnt is %d error_code is %d secret_size is %d",
357 numsecrets
, secretsCnt
, error_code
, secrets_size
);
359 if (NULL
== (bytes
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, (void*)sec
, secretsCnt
, kCFAllocatorNull
)))
361 error_code
= kHelperErr_ApiErr
;
362 LogMsg("mDNSKeychainGetSecrets: CFDataCreateWithBytesNoCopy failed");
366 if (NULL
== (plist
= CFPropertyListCreateWithData(kCFAllocatorDefault
, bytes
, kCFPropertyListImmutable
, NULL
, NULL
)))
368 error_code
= kHelperErr_ApiErr
;
369 LogMsg("mDNSKeychainGetSecrets: CFPropertyListCreateFromXMLData failed");
373 if (CFArrayGetTypeID() != CFGetTypeID(plist
))
375 error_code
= kHelperErr_ApiErr
;
376 LogMsg("mDNSKeychainGetSecrets: Unexpected result type");
382 *result
= (CFArrayRef
)plist
;
391 xpc_release(reply_dict
);
400 int mDNSAutoTunnelSetKeys(int replacedelete
, v6addr_t local_inner
,
401 v6addr_t local_outer
, short local_port
, v6addr_t remote_inner
,
402 v6addr_t remote_outer
, short remote_port
, const char* const prefix
, const domainname
*const fqdn
)
405 int err_code
= kHelperErr_NotConnected
;
407 mDNSHELPER_DEBUG("mDNSAutoTunnelSetKeys: Using XPC IPC calling out to Helper. Parameters are repdel[%d], lport[%d], rport[%d], prefix[%s], fqdn[%##s]",
408 replacedelete
, local_port
, remote_port
, prefix
, fqdn
->c
);
411 char buf1
[INET6_ADDRSTRLEN
];
412 char buf2
[INET6_ADDRSTRLEN
];
413 char buf3
[INET6_ADDRSTRLEN
];
414 char buf4
[INET6_ADDRSTRLEN
];
421 inet_ntop(AF_INET6
, local_inner
, buf1
, sizeof(buf1
));
422 inet_ntop(AF_INET6
, local_outer
, buf2
, sizeof(buf2
));
423 inet_ntop(AF_INET6
, remote_inner
, buf3
, sizeof(buf3
));
424 inet_ntop(AF_INET6
, remote_outer
, buf4
, sizeof(buf4
));
426 char fqdnStr
[MAX_ESCAPED_DOMAIN_NAME
+ 10] = { 0 }; // Assume the prefix is no larger than 10 chars
429 mDNSPlatformStrCopy(fqdnStr
, prefix
);
430 ConvertDomainNameToCString(fqdn
, fqdnStr
+ mDNSPlatformStrLen(prefix
));
433 mDNSHELPER_DEBUG("mDNSAutoTunnelSetKeys: Using XPC IPC calling out to Helper: Parameters are local_inner is %s, local_outeris %s, remote_inner is %s, remote_outer is %s",
434 buf1
, buf2
, buf3
, buf4
);
436 Init_Connection(kHelperService
);
438 // Create Dictionary To Send
439 xpc_object_t dict
= xpc_dictionary_create(NULL
, NULL
, 0);
440 xpc_dictionary_set_uint64(dict
, kHelperMode
, autotunnel_setkeys
);
442 xpc_dictionary_set_data(dict
, "autotunnelsetkeys_localinner", (uint8_t*)local_inner
, sizeof(v6addr_t
));
443 xpc_dictionary_set_data(dict
, "autotunnelsetkeys_localouter", (uint8_t*)local_outer
, sizeof(v6addr_t
));
444 xpc_dictionary_set_data(dict
, "autotunnelsetkeys_remoteinner", (uint8_t*)remote_inner
, sizeof(v6addr_t
));
445 xpc_dictionary_set_data(dict
, "autotunnelsetkeys_remoteouter", (uint8_t*)remote_outer
, sizeof(v6addr_t
));
447 xpc_dictionary_set_uint64(dict
, "autotunnelsetkeys_lport", local_port
);
448 xpc_dictionary_set_uint64(dict
, "autotunnelsetkeys_rport", remote_port
);
449 xpc_dictionary_set_uint64(dict
, "autotunnelsetkeys_repdel", replacedelete
);
451 // xpc_dictionary_set_string(dict, "autotunnelsetkeys_prefix", prefix);
452 xpc_dictionary_set_string(dict
, "autotunnelsetkeys_fqdnStr", fqdnStr
);
454 err_code
= SendDict_ToServer(dict
);
459 mDNSHELPER_DEBUG("mDNSAutoTunnelSetKeys: Using XPC IPC returning error_code %d", err_code
);
461 mDNSHELPER_DEBUG("mDNSAutoTunnelSetKeys: this should NOT be done in mDNSResponder/Helper. For future we shall be using <rdar://problem/13792729>");
465 void mDNSSendWakeupPacket(unsigned int ifid
, char *eth_addr
, char *ip_addr
, int iteration
)
467 // (void) ip_addr; // unused
468 // (void) iteration; // unused
470 mDNSHELPER_DEBUG("mDNSSendWakeupPacket: Entered ethernet address[%s],ip_address[%s], interface_id[%d], iteration[%d]",
471 eth_addr
, ip_addr
, ifid
, iteration
);
473 Init_Connection(kHelperService
);
475 // Create Dictionary To Send
476 xpc_object_t dict
= xpc_dictionary_create(NULL
, NULL
, 0);
477 xpc_dictionary_set_uint64(dict
, kHelperMode
, send_wakepkt
);
479 xpc_dictionary_set_uint64(dict
, "interface_index", ifid
);
480 xpc_dictionary_set_string(dict
, "ethernet_address", eth_addr
);
481 xpc_dictionary_set_string(dict
, "ip_address", ip_addr
);
482 xpc_dictionary_set_uint64(dict
, "swp_iteration", iteration
);
484 SendDict_ToServer(dict
);
490 void mDNSPacketFilterControl(uint32_t command
, char * ifname
, uint32_t count
, pfArray_t portArray
, pfArray_t protocolArray
)
495 pfArray_t protocolArray
;
498 mDNSPlatformMemCopy(pfa
.portArray
, portArray
, sizeof(pfArray_t
));
499 mDNSPlatformMemCopy(pfa
.protocolArray
, protocolArray
, sizeof(pfArray_t
));
501 mDNSHELPER_DEBUG("mDNSPacketFilterControl: XPC IPC, ifname %s", ifname
);
502 Init_Connection(kHelperService
);
504 // Create Dictionary To Send
505 xpc_object_t dict
= xpc_dictionary_create(NULL
, NULL
, 0);
506 xpc_dictionary_set_uint64(dict
, kHelperMode
, p2p_packetfilter
);
508 xpc_dictionary_set_uint64(dict
, "pf_opcode", command
);
510 xpc_dictionary_set_string(dict
, "pf_ifname", ifname
);
511 xpc_dictionary_set_uint64(dict
, "pf_count", count
);
513 xpc_dictionary_set_uint64(dict
, "pf_port0", pfa
.portArray
[0]);
514 xpc_dictionary_set_uint64(dict
, "pf_port1", pfa
.portArray
[1]);
515 xpc_dictionary_set_uint64(dict
, "pf_port2", pfa
.portArray
[2]);
516 xpc_dictionary_set_uint64(dict
, "pf_port3", pfa
.portArray
[3]);
518 xpc_dictionary_set_uint64(dict
, "pf_protocol0", pfa
.protocolArray
[0]);
519 xpc_dictionary_set_uint64(dict
, "pf_protocol1", pfa
.protocolArray
[1]);
520 xpc_dictionary_set_uint64(dict
, "pf_protocol2", pfa
.protocolArray
[2]);
521 xpc_dictionary_set_uint64(dict
, "pf_protocol3", pfa
.protocolArray
[3]);
522 SendDict_ToServer(dict
);
526 mDNSHELPER_DEBUG("mDNSPacketFilterControl: portArray0[%d] portArray1[%d] portArray2[%d] portArray3[%d] protocolArray0[%d] protocolArray1[%d] protocolArray2[%d] protocolArray3[%d]",
527 pfa
.portArray
[0], pfa
.portArray
[1], pfa
.portArray
[2], pfa
.portArray
[3], pfa
.protocolArray
[0], pfa
.protocolArray
[1], pfa
.protocolArray
[2], pfa
.protocolArray
[3]);
531 void mDNSSendKeepalive(const v6addr_t sadd
, const v6addr_t dadd
, uint16_t lport
, uint16_t rport
, uint32_t seq
, uint32_t ack
, uint16_t win
)
534 mDNSHELPER_DEBUG("mDNSSendKeepalive: Using XPC IPC calling out to Helper: lport is[%d] rport is[%d] seq is[%d] ack is[%d] win is[%d]",
535 lport
, rport
, seq
, ack
, win
);
537 char buf1
[INET6_ADDRSTRLEN
];
538 char buf2
[INET6_ADDRSTRLEN
];
543 inet_ntop(AF_INET6
, sadd
, buf1
, sizeof(buf1
));
544 inet_ntop(AF_INET6
, dadd
, buf2
, sizeof(buf2
));
545 mDNSHELPER_DEBUG("mDNSSendKeepalive: Using XPC IPC calling out to Helper: sadd is %s, dadd is %s", buf1
, buf2
);
547 Init_Connection(kHelperService
);
549 // Create Dictionary To Send
550 xpc_object_t dict
= xpc_dictionary_create(NULL
, NULL
, 0);
551 xpc_dictionary_set_uint64(dict
, kHelperMode
, send_keepalive
);
553 xpc_dictionary_set_data(dict
, "send_keepalive_sadd", (uint8_t*)sadd
, sizeof(v6addr_t
));
554 xpc_dictionary_set_data(dict
, "send_keepalive_dadd", (uint8_t*)dadd
, sizeof(v6addr_t
));
556 xpc_dictionary_set_uint64(dict
, "send_keepalive_lport", lport
);
557 xpc_dictionary_set_uint64(dict
, "send_keepalive_rport", rport
);
558 xpc_dictionary_set_uint64(dict
, "send_keepalive_seq", seq
);
559 xpc_dictionary_set_uint64(dict
, "send_keepalive_ack", ack
);
560 xpc_dictionary_set_uint64(dict
, "send_keepalive_win", win
);
562 SendDict_ToServer(dict
);
568 int mDNSRetrieveTCPInfo(int family
, v6addr_t laddr
, uint16_t lport
, v6addr_t raddr
, uint16_t rport
, uint32_t *seq
, uint32_t *ack
, uint16_t *win
, int32_t *intfid
)
570 int error_code
= kHelperErr_NotConnected
;
571 xpc_object_t reply_dict
= NULL
;
573 mDNSHELPER_DEBUG("mDNSRetrieveTCPInfo: Using XPC IPC calling out to Helper: lport is[%d] rport is[%d] family is[%d]",
574 lport
, rport
, family
);
576 char buf1
[INET6_ADDRSTRLEN
];
577 char buf2
[INET6_ADDRSTRLEN
];
581 inet_ntop(AF_INET6
, laddr
, buf1
, sizeof(buf1
));
582 inet_ntop(AF_INET6
, raddr
, buf2
, sizeof(buf2
));
583 mDNSHELPER_DEBUG("mDNSRetrieveTCPInfo:: Using XPC IPC calling out to Helper: laddr is %s, raddr is %s", buf1
, buf2
);
585 Init_Connection(kHelperService
);
587 // Create Dictionary To Send
588 xpc_object_t dict
= xpc_dictionary_create(NULL
, NULL
, 0);
589 xpc_dictionary_set_uint64(dict
, kHelperMode
, retreive_tcpinfo
);
591 xpc_dictionary_set_data(dict
, "retreive_tcpinfo_laddr", (uint8_t*)laddr
, sizeof(v6addr_t
));
592 xpc_dictionary_set_data(dict
, "retreive_tcpinfo_raddr", (uint8_t*)raddr
, sizeof(v6addr_t
));
594 xpc_dictionary_set_uint64(dict
, "retreive_tcpinfo_family", family
);
595 xpc_dictionary_set_uint64(dict
, "retreive_tcpinfo_lport", lport
);
596 xpc_dictionary_set_uint64(dict
, "retreive_tcpinfo_rport", rport
);
598 reply_dict
= SendDict_GetReply(dict
);
600 if (reply_dict
!= NULL
)
602 *seq
= xpc_dictionary_get_uint64(reply_dict
, "retreive_tcpinfo_seq");
603 *ack
= xpc_dictionary_get_uint64(reply_dict
, "retreive_tcpinfo_ack");
604 *win
= xpc_dictionary_get_uint64(reply_dict
, "retreive_tcpinfo_win");
605 *intfid
= (int32_t)xpc_dictionary_get_uint64(reply_dict
, "retreive_tcpinfo_ifid");
606 error_code
= xpc_dictionary_get_int64(reply_dict
, kHelperErrCode
);
609 mDNSHELPER_DEBUG("mDNSRetrieveTCPInfo: Using XPC IPC calling out to Helper: seq is %d, ack is %d, win is %d, intfid is %d, error is %d",
610 *seq
, *ack
, *win
, *intfid
, error_code
);
615 xpc_release(reply_dict
);