summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Martin Szulecki2012-04-01 01:42:28 +0200
committerGravatar Martin Szulecki2012-10-21 14:19:50 +0200
commit8b61d177dbfa5c12d582bd58df8243b6d21571b8 (patch)
treee1df30e08431d0f8f3c480bdd394d9a740711015
parentd09e25b69d2744ba7a6a88cc58d9cc8fc4810d2a (diff)
downloadlibimobiledevice-8b61d177dbfa5c12d582bd58df8243b6d21571b8.tar.gz
libimobiledevice-8b61d177dbfa5c12d582bd58df8243b6d21571b8.tar.bz2
diagnostics_relay: Add basic new service implementation
-rw-r--r--include/Makefile.am3
-rw-r--r--include/libimobiledevice/diagnostics_relay.h58
-rw-r--r--src/Makefile.am3
-rw-r--r--src/diagnostics_relay.c340
-rw-r--r--src/diagnostics_relay.h31
5 files changed, 433 insertions, 2 deletions
diff --git a/include/Makefile.am b/include/Makefile.am
index 849295f..957d533 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -14,4 +14,5 @@ nobase_include_HEADERS = libimobiledevice/libimobiledevice.h \
14 libimobiledevice/house_arrest.h \ 14 libimobiledevice/house_arrest.h \
15 libimobiledevice/mobilebackup2.h \ 15 libimobiledevice/mobilebackup2.h \
16 libimobiledevice/misagent.h \ 16 libimobiledevice/misagent.h \
17 libimobiledevice/restore.h 17 libimobiledevice/restore.h\
18 libimobiledevice/diagnostics_relay.h
diff --git a/include/libimobiledevice/diagnostics_relay.h b/include/libimobiledevice/diagnostics_relay.h
new file mode 100644
index 0000000..58c26df
--- /dev/null
+++ b/include/libimobiledevice/diagnostics_relay.h
@@ -0,0 +1,58 @@
1/**
2 * @file libimobiledevice/diagnostics_relay.h
3 * @brief Request iOS diagnostic information from device.
4 * \internal
5 *
6 * Copyright (c) 2012 Martin Szulecki, All Rights Reserved.
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23#ifndef IDIAGNOSTICS_RELAY_H
24#define IDIAGNOSTICS_RELAY_H
25
26#ifdef __cplusplus
27extern "C" {
28#endif
29
30#include <libimobiledevice/libimobiledevice.h>
31
32/** @name Error Codes */
33/*@{*/
34#define DIAGNOSTICS_RELAY_E_SUCCESS 0
35#define DIAGNOSTICS_RELAY_E_INVALID_ARG -1
36#define DIAGNOSTICS_RELAY_E_PLIST_ERROR -2
37#define DIAGNOSTICS_RELAY_E_MUX_ERROR -3
38
39#define DIAGNOSTICS_RELAY_E_UNKNOWN_ERROR -256
40/*@}*/
41
42/** Represents an error code. */
43typedef int16_t diagnostics_relay_error_t;
44
45typedef struct diagnostics_relay_client_private diagnostics_relay_client_private;
46typedef diagnostics_relay_client_private *diagnostics_relay_client_t; /**< The client handle. */
47
48diagnostics_relay_error_t diagnostics_relay_client_new(idevice_t device, uint16_t port, diagnostics_relay_client_t *client);
49diagnostics_relay_error_t diagnostics_relay_client_free(diagnostics_relay_client_t client);
50
51diagnostics_relay_error_t diagnostics_relay_goodbye(diagnostics_relay_client_t client);
52diagnostics_relay_error_t diagnostics_relay_request_diagnostics(diagnostics_relay_client_t client, plist_t* diagnostics);
53
54#ifdef __cplusplus
55}
56#endif
57
58#endif
diff --git a/src/Makefile.am b/src/Makefile.am
index d26baf1..f1f5f39 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -23,4 +23,5 @@ libimobiledevice_la_SOURCES = idevice.c idevice.h \
23 house_arrest.c house_arrest.h\ 23 house_arrest.c house_arrest.h\
24 mobilebackup2.c mobilebackup2.h\ 24 mobilebackup2.c mobilebackup2.h\
25 misagent.c misagent.h\ 25 misagent.c misagent.h\
26 restore.c restore.h 26 restore.c restore.h\
27 diagnostics_relay.c diagnostics_relay.h
diff --git a/src/diagnostics_relay.c b/src/diagnostics_relay.c
new file mode 100644
index 0000000..4cde230
--- /dev/null
+++ b/src/diagnostics_relay.c
@@ -0,0 +1,340 @@
1 /*
2 * diagnostics_relay.c
3 * com.apple.mobile.diagnostics_relay service implementation.
4 *
5 * Copyright (c) 2012 Martin Szulecki, All Rights Reserved.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21#include <string.h>
22#include <stdlib.h>
23#include "diagnostics_relay.h"
24#include "property_list_service.h"
25#include "debug.h"
26
27#define RESULT_SUCCESS 0
28#define RESULT_FAILURE 1
29
30/**
31 * Internally used function for checking the result from a service response
32 * plist to a previously sent request.
33 *
34 * @param dict The plist to evaluate.
35 * @param query_match Name of the request to match or NULL if no match is
36 * required.
37 *
38 * @return RESULT_SUCCESS when the result is 'Success',
39 * RESULT_FAILURE when the result is 'Failure',
40 * or a negative value if an error occured during evaluation.
41 */
42static int diagnostics_relay_check_result(plist_t dict, const char *query_match)
43{
44 int ret = -1;
45
46 plist_t query_node = plist_dict_get_item(dict, "Request");
47 if (!query_node) {
48 return ret;
49 }
50 if (plist_get_node_type(query_node) != PLIST_STRING) {
51 return ret;
52 } else {
53 char *query_value = NULL;
54 plist_get_string_val(query_node, &query_value);
55 if (!query_value) {
56 return ret;
57 }
58 if (query_match && (strcmp(query_value, query_match) != 0)) {
59 free(query_value);
60 return ret;
61 }
62 free(query_value);
63 }
64
65 plist_t result_node = plist_dict_get_item(dict, "Status");
66 if (!result_node)
67 return ret;
68
69 plist_type result_type = plist_get_node_type(result_node);
70 if (result_type == PLIST_STRING) {
71 char *result_value = NULL;
72
73 plist_get_string_val(result_node, &result_value);
74
75 if (result_value) {
76 if (!strcmp(result_value, "Success")) {
77 ret = RESULT_SUCCESS;
78 } else if (!strcmp(result_value, "Failure")) {
79 ret = RESULT_FAILURE;
80 } else {
81 debug_info("ERROR: unknown result value '%s'", result_value);
82 }
83 }
84 if (result_value)
85 free(result_value);
86 }
87 return ret;
88}
89
90/**
91 * Connects to the diagnostics_relay service on the specified device.
92 *
93 * @param device The device to connect to.
94 * @param port Destination port (usually given by lockdownd_start_service).
95 * @param client Reference that will point to a newly allocated
96 * diagnostics_relay_client_t upon successful return.
97 *
98 * @return DIAGNOSTICS_RELAY_E_SUCCESS on success,
99 * DIAGNOSTICS_RELAY_E_INVALID_ARG when one of the parameters is invalid,
100 * or DIAGNOSTICS_RELAY_E_MUX_ERROR when the connection failed.
101 */
102diagnostics_relay_error_t diagnostics_relay_client_new(idevice_t device, uint16_t port, diagnostics_relay_client_t *client)
103{
104 if (!device || port == 0 || !client || *client) {
105 return DIAGNOSTICS_RELAY_E_INVALID_ARG;
106 }
107
108 property_list_service_client_t plistclient = NULL;
109 if (property_list_service_client_new(device, port, &plistclient) != PROPERTY_LIST_SERVICE_E_SUCCESS) {
110 return DIAGNOSTICS_RELAY_E_MUX_ERROR;
111 }
112
113 /* create client object */
114 diagnostics_relay_client_t client_loc = (diagnostics_relay_client_t) malloc(sizeof(struct diagnostics_relay_client_private));
115 client_loc->parent = plistclient;
116
117 /* all done, return success */
118 *client = client_loc;
119 return DIAGNOSTICS_RELAY_E_SUCCESS;
120}
121
122/**
123 * Disconnects a diagnostics_relay client from the device and frees up the
124 * diagnostics_relay client data.
125 *
126 * @param client The diagnostics_relay client to disconnect and free.
127 *
128 * @return DIAGNOSTICS_RELAY_E_SUCCESS on success,
129 * DIAGNOSTICS_RELAY_E_INVALID_ARG when one of client or client->parent
130 * is invalid, or DIAGNOSTICS_RELAY_E_UNKNOWN_ERROR when the was an
131 * error freeing the parent property_list_service client.
132 */
133diagnostics_relay_error_t diagnostics_relay_client_free(diagnostics_relay_client_t client)
134{
135 if (!client)
136 return DIAGNOSTICS_RELAY_E_INVALID_ARG;
137
138 if (property_list_service_client_free(client->parent) != PROPERTY_LIST_SERVICE_E_SUCCESS) {
139 return DIAGNOSTICS_RELAY_E_UNKNOWN_ERROR;
140 }
141 return DIAGNOSTICS_RELAY_E_SUCCESS;
142}
143
144/**
145 * Receives a plist from the service.
146 *
147 * @param client The diagnostics_relay client
148 * @param plist The plist to store the received data
149 *
150 * @return DIAGNOSTICS_RELAY_E_SUCCESS on success,
151 * DIAGNOSTICS_RELAY_E_INVALID_ARG when client or plist is NULL
152 */
153static diagnostics_relay_error_t diagnostics_relay_receive(diagnostics_relay_client_t client, plist_t *plist)
154{
155 if (!client || !plist || (plist && *plist))
156 return DIAGNOSTICS_RELAY_E_INVALID_ARG;
157
158 diagnostics_relay_error_t ret = DIAGNOSTICS_RELAY_E_SUCCESS;
159 property_list_service_error_t err;
160
161 err = property_list_service_receive_plist(client->parent, plist);
162 if (err != PROPERTY_LIST_SERVICE_E_SUCCESS) {
163 ret = DIAGNOSTICS_RELAY_E_UNKNOWN_ERROR;
164 }
165
166 if (!*plist)
167 ret = DIAGNOSTICS_RELAY_E_PLIST_ERROR;
168
169 return ret;
170}
171
172/**
173 * Sends a plist to the service.
174 *
175 * @note This function is low-level and should only be used if you need to send
176 * a new type of message.
177 *
178 * @param client The diagnostics_relay client
179 * @param plist The plist to send
180 *
181 * @return DIAGNOSTICS_RELAY_E_SUCCESS on success,
182 * DIAGNOSTICS_RELAY_E_INVALID_ARG when client or plist is NULL
183 */
184static diagnostics_relay_error_t diagnostics_relay_send(diagnostics_relay_client_t client, plist_t plist)
185{
186 if (!client || !plist)
187 return DIAGNOSTICS_RELAY_E_INVALID_ARG;
188
189 diagnostics_relay_error_t ret = DIAGNOSTICS_RELAY_E_SUCCESS;
190 idevice_error_t err;
191
192 err = property_list_service_send_xml_plist(client->parent, plist);
193 if (err != PROPERTY_LIST_SERVICE_E_SUCCESS) {
194 ret = DIAGNOSTICS_RELAY_E_UNKNOWN_ERROR;
195 }
196 return ret;
197}
198
199/**
200 * Sends the Goodbye request signaling the end of communication.
201 *
202 * @param client The diagnostics_relay client
203 *
204 * @return DIAGNOSTICS_RELAY_E_SUCCESS on success,
205 * DIAGNOSTICS_RELAY_E_INVALID_ARG when client is NULL,
206 * DIAGNOSTICS_RELAY_E_PLIST_ERROR if the device did not acknowledge the
207 * request
208 */
209diagnostics_relay_error_t diagnostics_relay_goodbye(diagnostics_relay_client_t client)
210{
211 if (!client)
212 return DIAGNOSTICS_RELAY_E_INVALID_ARG;
213
214 diagnostics_relay_error_t ret = DIAGNOSTICS_RELAY_E_UNKNOWN_ERROR;
215
216 plist_t dict = plist_new_dict();
217 plist_dict_insert_item(dict, "Request", plist_new_string("Goodbye"));
218
219 ret = diagnostics_relay_send(client, dict);
220 plist_free(dict);
221 dict = NULL;
222
223 ret = diagnostics_relay_receive(client, &dict);
224 if (!dict) {
225 debug_info("did not get goodbye response back");
226 return DIAGNOSTICS_RELAY_E_PLIST_ERROR;
227 }
228
229 if (diagnostics_relay_check_result(dict, "Goodbye") == RESULT_SUCCESS) {
230 debug_info("success");
231 ret = DIAGNOSTICS_RELAY_E_SUCCESS;
232 }
233 plist_free(dict);
234 dict = NULL;
235 return ret;
236}
237
238diagnostics_relay_error_t diagnostics_relay_request_diagnostics(diagnostics_relay_client_t client, plist_t* diagnostics)
239{
240 if (!client || diagnostics == NULL)
241 return DIAGNOSTICS_RELAY_E_INVALID_ARG;
242
243 diagnostics_relay_error_t ret = DIAGNOSTICS_RELAY_E_UNKNOWN_ERROR;
244
245 plist_t dict = plist_new_dict();
246/*
247 Provides a diagnostics interface. Some stuff is only available on iOS 5+
248
249 Protocol:
250
251 Request:
252 <key>Request</key><string>IORegistry</string>
253 [<key>CurrentPlane</key><string>IODeviceTree</string>]
254 Response:
255 [Diagnostics]
256 IORegistry
257 ...
258 Status
259 "Success" | "UnknownRequest"
260 [ErrorCode]
261 %d
262
263 Unknown Strings:
264
265 ? IO80211Interface
266 ? InternalBuild
267 ? DisplayFail
268 ? DisplayPass
269 ? WaitForDisconnect
270
271 Known/Tested Requests:
272
273 // wifi: Show wifi status
274 plist_dict_insert_item(dict,"Request", plist_new_string("WiFi"));
275
276 // gas_gauge: Show battery load cycles and more
277 plist_dict_insert_item(dict,"Request", plist_new_string("GasGauge"));
278 plist_dict_insert_item(dict,"Request", plist_new_string("NAND"));
279 plist_dict_insert_item(dict,"Request", plist_new_string("Sleep"));
280 plist_dict_insert_item(dict,"Request", plist_new_string("Shutdown"));
281 plist_dict_insert_item(dict,"Request", plist_new_string("Restart"));
282
283 // obliberate: Wipe data on device
284 // @note: Currently yields: "iPhone mobile_diagnostics_relay[253] <Error>: do_obliterate: obliteration denied: not running internal build."
285 plist_dict_insert_item(dict,"Request", plist_new_string("Obliterate"));
286 ? DataPartitionOnly
287 ? ObliterationType
288 ? ObliterateDataPartition
289 ? ObliterationTypeWipeAndBrick
290 ? DisplayProgressBar
291 ? SkipDataObliteration
292 ? ObliterationMessage
293
294 // mobile_gestalt: read out managed keys
295 plist_t keys = plist_new_array();
296 plist_array_append_item(keys, plist_new_string("UserAssignedDeviceName"));
297 plist_array_append_item(keys, plist_new_string("BasebandSecurityInfo"));
298 plist_array_append_item(keys, plist_new_string("BasebandSerialNumber"));
299 plist_array_append_item(keys, plist_new_string("MyPhoneNumber"));
300 plist_array_append_item(keys, plist_new_string("SNUM"));
301 plist_dict_insert_item(dict,"MobileGestaltKeys", keys);
302 plist_dict_insert_item(dict,"Request", plist_new_string("MobileGestalt"));
303
304 // io registry: dump by plane or name and class
305 plist_dict_insert_item(dict,"CurrentPlane", plist_new_string("IODeviceTree"));
306 or
307 plist_dict_insert_item(dict,"EntryName", plist_new_string("baseband"));
308 plist_dict_insert_item(dict,"EntryClass", plist_new_string("IOPlatformDevice"));
309 plist_dict_insert_item(dict,"Request", plist_new_string("IORegistry"));
310*/
311 plist_dict_insert_item(dict,"Request", plist_new_string("IORegistry"));
312 plist_dict_insert_item(dict,"CurrentPlane", plist_new_string(""));
313 ret = diagnostics_relay_send(client, dict);
314 plist_free(dict);
315 dict = NULL;
316
317 ret = diagnostics_relay_receive(client, &dict);
318 if (!dict) {
319 debug_info("did not get response back");
320 return DIAGNOSTICS_RELAY_E_PLIST_ERROR;
321 }
322
323 if (diagnostics_relay_check_result(dict, "Diagnostics") == RESULT_SUCCESS) {
324 debug_info("success");
325 ret = DIAGNOSTICS_RELAY_E_SUCCESS;
326 }
327 if (ret != DIAGNOSTICS_RELAY_E_SUCCESS) {
328 plist_free(dict);
329 return ret;
330 }
331
332 plist_t value_node = plist_dict_get_item(dict, "Diagnostics");
333 if (value_node) {
334 debug_info("has a value");
335 *diagnostics = plist_copy(value_node);
336 }
337
338 plist_free(dict);
339 return ret;
340}
diff --git a/src/diagnostics_relay.h b/src/diagnostics_relay.h
new file mode 100644
index 0000000..2a9eb1a
--- /dev/null
+++ b/src/diagnostics_relay.h
@@ -0,0 +1,31 @@
1 /*
2 * diagnostics_relay.h
3 * com.apple.mobile.diagnostics_relay service header file.
4 *
5 * Copyright (c) 2012 Martin Szulecki, All Rights Reserved.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21#ifndef DIAGNOSTICS_RELAY_H
22#define DIAGNOSTICS_RELAY_H
23
24#include "libimobiledevice/diagnostics_relay.h"
25#include "property_list_service.h"
26
27struct diagnostics_relay_client_private {
28 property_list_service_client_t parent;
29};
30
31#endif