]> git.saurik.com Git - apple/mdnsresponder.git/blame - mDNSMacOSX/Private/dns_services.c
mDNSResponder-576.30.4.tar.gz
[apple/mdnsresponder.git] / mDNSMacOSX / Private / dns_services.c
CommitLineData
51601d48
A
1/* -*- Mode: C; tab-width: 4 -*-
2 *
3 * Copyright (c) 2012 Apple Inc. All rights reserved.
4 *
5 * PRIVATE DNSX CLIENT LIBRARY --FOR Apple Platforms ONLY OSX/iOS--
6 * Resides in /usr/lib/libdns_services.dylib
7 */
8
b8d5688b 9#include "dns_services.h"
51601d48
A
10#include "dns_xpc.h"
11#include <xpc/xpc.h>
12#include <Block.h>
13#include <stdio.h>
14#include <stdlib.h>
15#include <syslog.h>
16
17//*************************************************************************************************************
18// Globals
19
20#define connection_t xpc_connection_t
21
22struct _DNSXConnRef_t
23{
24 connection_t conn_ref; // xpc_connection between client and daemon
25 dispatch_queue_t lib_q; // internal queue created in library itself
26 void *AppCallBack; // Callback function ptr for Client
27 dispatch_queue_t client_q; // Queue specified by client for scheduling its Callback
28};
29
30//*************************************************************************************************************
31// Utility Functions
32
33static bool LogDebugEnabled()
34{
04ca8c30 35 return true;
51601d48
A
36}
37
38static void LogDebug(const char *prefix, xpc_object_t o)
39{
40 if (!LogDebugEnabled())
41 return;
42
43 char *desc = xpc_copy_description(o);
44 syslog(LOG_INFO, "%s: %s", prefix, desc);
45 free(desc);
46}
47
48//**************************************************************************************************************
49
50void DNSXRefDeAlloc(DNSXConnRef connRef)
51{
52 if (!connRef)
53 {
54 syslog(LOG_WARNING, "dns_services: DNSXRefDeAlloc called with NULL DNSXConnRef");
55 return;
56 }
57
58 // Schedule this work on the internal library queue
59 dispatch_sync(connRef->lib_q, ^{
60
61 xpc_release(connRef->conn_ref);
62 connRef->AppCallBack = NULL;
63 dispatch_release(connRef->client_q);
64
65 });
66
67 dispatch_release(connRef->lib_q);
68 free(connRef);
69
70 syslog(LOG_INFO, "dns_services: DNSXRefDeAlloc successfully DeAllocated connRef");
71
72}
73
74// Sends the Msg(Dictionary) to the Server
75static DNSXErrorType SendMsgToServer(DNSXConnRef *connRef, xpc_object_t msg, bool old_conn)
76{
77 DNSXErrorType errx = kDNSX_NoError;
78
79 LogDebug("dns_services: SendMsgToServer", msg);
80
81 xpc_connection_set_event_handler((*connRef)->conn_ref, ^(xpc_object_t recv_msg)
82 {
83 xpc_type_t type = xpc_get_type(recv_msg);
84
85 if (type == XPC_TYPE_DICTIONARY)
86 {
87 LogDebug("dns_services: SendMsgToServer SUCCESS CALLBACK FROM SERVER", recv_msg);
88 syslog(LOG_INFO, "dns_services: Successfully Sent Msg to the Daemon");
89 uint64_t daemon_status = xpc_dictionary_get_uint64(recv_msg, kDNSDaemonReply);
90
91 // Schedule the AppCallBacks on the Client Specified Queue
92 switch (daemon_status)
93 {
94 case kDNSDaemonEngaged:
95 dispatch_async((*connRef)->client_q, ^{
96 ((DNSXEnableProxyReply)(*connRef)->AppCallBack)((*connRef), kDNSX_Engaged);
97 });
98 break;
99 case kDNSMsgReceived:
100 dispatch_async((*connRef)->client_q, ^{
101 ((DNSXEnableProxyReply)(*connRef)->AppCallBack)((*connRef), kDNSX_NoError);
102 });
103 break;
104 default:
105 dispatch_async((*connRef)->client_q, ^{
106 ((DNSXEnableProxyReply)(*connRef)->AppCallBack)((*connRef), kDNSX_UnknownErr);
107 });
108 break;
109 }
110
111 }
112 else
113 {
114 LogDebug("dns_services: SendMsgToServer UNEXPECTED CALLBACK FROM SERVER", recv_msg);
115 syslog(LOG_WARNING, "dns_services: Connection failed since NO privileges to access service OR Daemon NOT Running");
116 dispatch_async((*connRef)->client_q, ^{
117 ((DNSXEnableProxyReply)(*connRef)->AppCallBack)((*connRef), kDNSX_DaemonNotRunning);
118 });
119 }
120 });
121
122 // To prevent Over-Resume of a connection
123 if (!old_conn)
124 xpc_connection_resume((*connRef)->conn_ref);
125 xpc_connection_send_message((*connRef)->conn_ref, msg);
126 if (!errx)
127 syslog(LOG_INFO, "dns_services: SendMSgToServer sent Msg Dict successfully to Daemon");
128 return errx;
129}
130
131// Creates a new DNSX Connection Reference(DNSXConnRef).
132// If DNSXConnRef exists, you may want to use that depending on the use case
133static DNSXErrorType InitConnection(DNSXConnRef *connRef, const char *servname, dispatch_queue_t clientq, void *AppCallBack)
134{
135 if (!connRef)
136 {
137 syslog(LOG_WARNING, "dns_services: InitConnection() called with NULL DNSXConnRef");
138 return kDNSX_BadParam;
139 }
140
141 *connRef = malloc(sizeof(struct _DNSXConnRef_t));
142 if (!(*connRef))
143 {
144 syslog(LOG_WARNING, "dns_services: InitConnection() No memory to allocate");
145 return kDNSX_NoMem;
146 }
147
148 // Initialize the DNSXConnRef
149 dispatch_retain(clientq);
150 (*connRef)->client_q = clientq;
151 (*connRef)->AppCallBack = AppCallBack;
152 (*connRef)->lib_q = dispatch_queue_create("com.apple.mDNSResponder.libdns_services.q", NULL);
153 (*connRef)->conn_ref = xpc_connection_create_mach_service(servname, (*connRef)->lib_q, XPC_CONNECTION_MACH_SERVICE_PRIVILEGED);
154
155 syslog(LOG_INFO, "dns_services: InitConnection() successfully create a new DNSXConnRef");
156 return kDNSX_NoError;
157}
158
159DNSXErrorType DNSXEnableProxy(DNSXConnRef *connRef, DNSProxyParameters proxyparam, IfIndex inIfindexArr[MaxInputIf],
160 IfIndex outIfindex, dispatch_queue_t clientq, DNSXEnableProxyReply callBack)
161{
162
163 DNSXErrorType errx = kDNSX_NoError;
164 bool old_conn = false;
165
166 // Sanity Checks
167 if (!connRef || !callBack || !clientq)
168 {
169 syslog(LOG_WARNING, "dns_services: DNSXEnableProxy called with NULL DNSXConnRef OR Callback OR ClientQ parameter");
170 return kDNSX_BadParam;
171 }
172
173 // If no connRef, get it from InitConnection()
174 if (!*connRef)
175 {
176 errx = InitConnection(connRef, kDNSProxyService, clientq, callBack);
177 if (errx) // On error InitConnection() leaves *connRef set to NULL
178 {
179 syslog(LOG_WARNING, "dns_services: Since InitConnection() returned %d error returning w/o sending msg", errx);
180 return errx;
181 }
182 }
183 else // Client already has a valid connRef
184 {
185 old_conn = true;
186 }
187
188 // Create Dictionary To Send
189 xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0);
190 if (!dict)
191 {
192 syslog(LOG_WARNING, "dns_services: DNSXEnableProxy could not create the Msg Dict To Send!");
193 DNSXRefDeAlloc(*connRef);
194 return kDNSX_DictError;
195 }
196
197 xpc_dictionary_set_uint64(dict, kDNSProxyParameters, proxyparam);
198
199 xpc_dictionary_set_uint64(dict, kDNSInIfindex0, inIfindexArr[0]);
200 xpc_dictionary_set_uint64(dict, kDNSInIfindex1, inIfindexArr[1]);
201 xpc_dictionary_set_uint64(dict, kDNSInIfindex2, inIfindexArr[2]);
202 xpc_dictionary_set_uint64(dict, kDNSInIfindex3, inIfindexArr[3]);
203 xpc_dictionary_set_uint64(dict, kDNSInIfindex4, inIfindexArr[4]);
204
205 xpc_dictionary_set_uint64(dict, kDNSOutIfindex, outIfindex);
206
207 errx = SendMsgToServer(connRef, dict, old_conn);
208 xpc_release(dict);
209
210 return errx;
211}
212