int restore_check_mode(const char* uuid) { char* type = NULL; uint64_t version = 0; idevice_t device = NULL; restored_client_t restore = NULL; idevice_error_t device_error = IDEVICE_E_SUCCESS; restored_error_t restore_error = RESTORE_E_SUCCESS; device_error = idevice_new(&device, uuid); if (device_error != IDEVICE_E_SUCCESS) { return -1; } restore_error = restored_client_new(device, &restore, "idevicerestore"); if (restore_error != RESTORE_E_SUCCESS) { idevice_free(device); return -1; } restore_error = restored_query_type(restore, &type, &version); if (restore_error != RESTORE_E_SUCCESS) { restored_client_free(restore); idevice_free(device); return -1; } restored_client_free(restore); idevice_free(device); restore = NULL; device = NULL; return 0; }
int restore_check_device(const char* uuid) { int i = 0; char* type = NULL; char* model = NULL; plist_t node = NULL; uint64_t version = 0; idevice_t device = NULL; restored_client_t restore = NULL; idevice_error_t device_error = IDEVICE_E_SUCCESS; restored_error_t restore_error = RESTORE_E_SUCCESS; device_error = idevice_new(&device, uuid); if (device_error != IDEVICE_E_SUCCESS) { return -1; } restore_error = restored_client_new(device, &restore, "idevicerestore"); if (restore_error != RESTORE_E_SUCCESS) { idevice_free(device); return -1; } restore_error = restored_query_type(restore, &type, &version); if (restore_error != RESTORE_E_SUCCESS) { restored_client_free(restore); idevice_free(device); return -1; } restore_error = restored_get_value(restore, "HardwareModel", &node); if (restore_error != RESTORE_E_SUCCESS) { error("ERROR: Unable to get HardwareModel from restored\n"); restored_client_free(restore); idevice_free(device); return -1; } restored_client_free(restore); idevice_free(device); restore = NULL; device = NULL; if (!node || plist_get_node_type(node) != PLIST_STRING) { error("ERROR: Unable to get HardwareModel information\n"); if (node) plist_free(node); return -1; } plist_get_string_val(node, &model); for (i = 0; idevicerestore_devices[i].model != NULL; i++) { if (!strcasecmp(model, idevicerestore_devices[i].model)) { break; } } return idevicerestore_devices[i].device_id; }
int restore_open_with_timeout(const char* uuid, idevice_t* device, restored_client_t* restore) { int i = 0; int attempts = 10; idevice_t context = NULL; restored_client_t client = NULL; idevice_error_t device_error = IDEVICE_E_SUCCESS; restored_error_t restore_error = RESTORE_E_SUCCESS; *device = NULL; *restore = NULL; device_error = idevice_event_subscribe(&restore_device_callback, NULL); if (device_error != IDEVICE_E_SUCCESS) { error("ERROR: Unable to subscribe to device events\n"); return -1; } for (i = 1; i <= attempts; i++) { if (restore_device_connected == 1) { break; } if (i == attempts) { error("ERROR: Unable to connect to device in restore mode\n"); } sleep(2); } device_error = idevice_new(&context, uuid); if (device_error != IDEVICE_E_SUCCESS) { return -1; } restore_error = restored_client_new(context, &client, "idevicerestore"); if (restore_error != RESTORE_E_SUCCESS) { idevice_event_unsubscribe(); idevice_free(context); return -1; } restore_error = restored_query_type(client, NULL, NULL); if (restore_error != RESTORE_E_SUCCESS) { restored_client_free(client); idevice_event_unsubscribe(); idevice_free(context); return -1; } *device = context; *restore = client; return 0; }
LIBIMOBILEDEVICE_API restored_error_t restored_client_new(idevice_t device, restored_client_t *client, const char *label) { if (!client) return RESTORE_E_INVALID_ARG; restored_error_t ret = RESTORE_E_SUCCESS; idevice_error_t idev_ret; static struct lockdownd_service_descriptor service = { /*.port = 0xf27e, .ssl_enabled = 0*/ 0xf27e, 0 }; property_list_service_client_t plistclient = NULL; if (property_list_service_client_new(device, (lockdownd_service_descriptor_t)&service, &plistclient) != PROPERTY_LIST_SERVICE_E_SUCCESS) { debug_info("could not connect to restored (device %s)", device->udid); return RESTORE_E_MUX_ERROR; } restored_client_t client_loc = (restored_client_t) malloc(sizeof(struct restored_client_private)); client_loc->parent = plistclient; client_loc->udid = NULL; client_loc->label = NULL; client_loc->info = NULL; if (label != NULL) //client_loc->label = strdup(label); client_loc->label = _strdup(label); idev_ret = idevice_get_udid(device, &client_loc->udid); if (IDEVICE_E_SUCCESS != idev_ret) { debug_info("failed to get device udid."); ret = RESTORE_E_DEVICE_ERROR; } debug_info("device udid: %s", client_loc->udid); if (RESTORE_E_SUCCESS == ret) { *client = client_loc; } else { restored_client_free(client_loc); } return ret; }
/** * Creates a new restored client for the device. * * @param device The device to create a restored client for * @param client The pointer to the location of the new restored_client * @param label The label to use for communication. Usually the program name. * * @return RESTORE_E_SUCCESS on success, NP_E_INVALID_ARG when client is NULL */ restored_error_t restored_client_new(idevice_t device, restored_client_t *client, const char *label) { if (!client) return RESTORE_E_INVALID_ARG; restored_error_t ret = RESTORE_E_SUCCESS; static struct lockdownd_service_descriptor service = { .port = 0xf27e, .ssl_enabled = 0 }; property_list_service_client_t plistclient = NULL; if (property_list_service_client_new(device, (lockdownd_service_descriptor_t)&service, &plistclient) != PROPERTY_LIST_SERVICE_E_SUCCESS) { debug_info("could not connect to restored (device %s)", device->udid); return RESTORE_E_MUX_ERROR; } restored_client_t client_loc = (restored_client_t) malloc(sizeof(struct restored_client_private)); client_loc->parent = plistclient; client_loc->udid = NULL; client_loc->label = NULL; client_loc->info = NULL; if (label != NULL) client_loc->label = strdup(label); ret = idevice_get_udid(device, &client_loc->udid); if (RESTORE_E_SUCCESS != ret) { debug_info("failed to get device udid."); } debug_info("device udid: %s", client_loc->udid); if (RESTORE_E_SUCCESS == ret) { *client = client_loc; } else { restored_client_free(client_loc); } return ret; } /** * Sends the Goodbye request to restored signaling the end of communication. * * @param client The restore client * * @return RESTORE_E_SUCCESS on success, NP_E_INVALID_ARG when client is NULL, * RESTORE_E_PLIST_ERROR if the device did not acknowledge the request */ restored_error_t restored_goodbye(restored_client_t client) { if (!client) return RESTORE_E_INVALID_ARG; restored_error_t ret = RESTORE_E_UNKNOWN_ERROR; plist_t dict = plist_new_dict(); plist_dict_add_label(dict, client->label); plist_dict_insert_item(dict,"Request", plist_new_string("Goodbye")); debug_info("called"); ret = restored_send(client, dict); plist_free(dict); dict = NULL; ret = restored_receive(client, &dict); if (!dict) { debug_info("did not get goodbye response back"); return RESTORE_E_PLIST_ERROR; } if (restored_check_result(dict) == RESULT_SUCCESS) { debug_info("success"); ret = RESTORE_E_SUCCESS; } plist_free(dict); dict = NULL; return ret; } /** * Requests to start a restore and retrieve it's port on success. * * @param client The restored client * @param options PLIST_DICT with options for the restore process or NULL * @param version the restore protocol version, see restored_query_type() * * @return RESTORE_E_SUCCESS on success, NP_E_INVALID_ARG if a parameter * is NULL, RESTORE_E_START_RESTORE_FAILED if the request fails */ restored_error_t restored_start_restore(restored_client_t client, plist_t options, uint64_t version) { if (!client) return RESTORE_E_INVALID_ARG; plist_t dict = NULL; restored_error_t ret = RESTORE_E_UNKNOWN_ERROR; dict = plist_new_dict(); plist_dict_add_label(dict, client->label); plist_dict_insert_item(dict,"Request", plist_new_string("StartRestore")); if (options) { plist_dict_insert_item(dict, "RestoreOptions", plist_copy(options)); } plist_dict_insert_item(dict,"RestoreProtocolVersion", plist_new_uint(version)); /* send to device */ ret = restored_send(client, dict); plist_free(dict); dict = NULL; return ret; } /** * Requests device to reboot. * * @param client The restored client * * @return RESTORE_E_SUCCESS on success, NP_E_INVALID_ARG if a parameter * is NULL */ restored_error_t restored_reboot(restored_client_t client) { if (!client) return RESTORE_E_INVALID_ARG; plist_t dict = NULL; restored_error_t ret = RESTORE_E_UNKNOWN_ERROR; dict = plist_new_dict(); plist_dict_add_label(dict, client->label); plist_dict_insert_item(dict,"Request", plist_new_string("Reboot")); /* send to device */ ret = restored_send(client, dict); plist_free(dict); dict = NULL; if (RESTORE_E_SUCCESS != ret) return ret; ret = restored_receive(client, &dict); if (RESTORE_E_SUCCESS != ret) return ret; if (!dict) return RESTORE_E_PLIST_ERROR; plist_free(dict); dict = NULL; return ret; }
void restore_close(idevice_t device, restored_client_t restore) { if (restore) restored_client_free(restore); if (device) idevice_free(device); }
LIBIMOBILEDEVICE_API restored_error_t restored_client_new(idevice_t device, restored_client_t *client, const char *label) { if (!client) return RESTORE_E_INVALID_ARG; restored_error_t ret = RESTORE_E_SUCCESS; idevice_error_t idev_ret; static struct lockdownd_service_descriptor service = { .port = 0xf27e, .ssl_enabled = 0 }; property_list_service_client_t plistclient = NULL; if (property_list_service_client_new(device, (lockdownd_service_descriptor_t)&service, &plistclient) != PROPERTY_LIST_SERVICE_E_SUCCESS) { debug_info("could not connect to restored (device %s)", device->udid); return RESTORE_E_MUX_ERROR; } restored_client_t client_loc = (restored_client_t) malloc(sizeof(struct restored_client_private)); client_loc->parent = plistclient; client_loc->udid = NULL; client_loc->label = NULL; client_loc->info = NULL; if (label != NULL) client_loc->label = strdup(label); idev_ret = idevice_get_udid(device, &client_loc->udid); if (IDEVICE_E_SUCCESS != idev_ret) { debug_info("failed to get device udid."); ret = RESTORE_E_DEVICE_ERROR; } debug_info("device udid: %s", client_loc->udid); if (RESTORE_E_SUCCESS == ret) { *client = client_loc; } else { restored_client_free(client_loc); } return ret; } LIBIMOBILEDEVICE_API restored_error_t restored_goodbye(restored_client_t client) { if (!client) return RESTORE_E_INVALID_ARG; restored_error_t ret = RESTORE_E_UNKNOWN_ERROR; plist_t dict = plist_new_dict(); plist_dict_add_label(dict, client->label); plist_dict_set_item(dict,"Request", plist_new_string("Goodbye")); debug_info("called"); ret = restored_send(client, dict); plist_free(dict); dict = NULL; ret = restored_receive(client, &dict); if (!dict) { debug_info("did not get goodbye response back"); return RESTORE_E_PLIST_ERROR; } if (restored_check_result(dict) == RESULT_SUCCESS) { debug_info("success"); ret = RESTORE_E_SUCCESS; } plist_free(dict); dict = NULL; return ret; } LIBIMOBILEDEVICE_API restored_error_t restored_start_restore(restored_client_t client, plist_t options, uint64_t version) { if (!client) return RESTORE_E_INVALID_ARG; plist_t dict = NULL; restored_error_t ret = RESTORE_E_UNKNOWN_ERROR; dict = plist_new_dict(); plist_dict_add_label(dict, client->label); plist_dict_set_item(dict,"Request", plist_new_string("StartRestore")); if (options) { plist_dict_set_item(dict, "RestoreOptions", plist_copy(options)); } plist_dict_set_item(dict,"RestoreProtocolVersion", plist_new_uint(version)); /* send to device */ ret = restored_send(client, dict); plist_free(dict); dict = NULL; return ret; } LIBIMOBILEDEVICE_API restored_error_t restored_reboot(restored_client_t client) { if (!client) return RESTORE_E_INVALID_ARG; plist_t dict = NULL; restored_error_t ret = RESTORE_E_UNKNOWN_ERROR; dict = plist_new_dict(); plist_dict_add_label(dict, client->label); plist_dict_set_item(dict,"Request", plist_new_string("Reboot")); /* send to device */ ret = restored_send(client, dict); plist_free(dict); dict = NULL; if (RESTORE_E_SUCCESS != ret) return ret; ret = restored_receive(client, &dict); if (RESTORE_E_SUCCESS != ret) return ret; if (!dict) return RESTORE_E_PLIST_ERROR; plist_free(dict); dict = NULL; return ret; }