]>
Commit | Line | Data |
---|---|---|
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 | ||
22 | struct _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 | ||
33 | static bool LogDebugEnabled() | |
34 | { | |
04ca8c30 | 35 | return true; |
51601d48 A |
36 | } |
37 | ||
38 | static 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 | ||
50 | void 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 | |
75 | static 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 | |
133 | static 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 | ||
159 | DNSXErrorType 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 |