diff options
author | Jonathan Beck | 2008-08-31 11:47:18 +0200 |
---|---|---|
committer | Jonathan Beck | 2008-08-31 19:33:19 +0200 |
commit | 86f61988990daa30c8564e2b26666dd442bd6e65 (patch) | |
tree | 985400ee8848585dabf8efbe2acbfc37d9b3f2f8 | |
parent | dc89741f00bd6919c0eedbd882c05f66d72fdbee (diff) | |
download | libimobiledevice-86f61988990daa30c8564e2b26666dd442bd6e65.tar.gz libimobiledevice-86f61988990daa30c8564e2b26666dd442bd6e65.tar.bz2 |
make all functions return an error code.
-rw-r--r-- | include/libiphone/libiphone.h | 56 | ||||
-rw-r--r-- | src/AFC.c | 130 | ||||
-rw-r--r-- | src/iphone.c | 25 | ||||
-rw-r--r-- | src/lockdown.c | 84 | ||||
-rw-r--r-- | src/usbmux.c | 48 |
5 files changed, 197 insertions, 146 deletions
diff --git a/include/libiphone/libiphone.h b/include/libiphone/libiphone.h index 768ff21..26d35ab 100644 --- a/include/libiphone/libiphone.h +++ b/include/libiphone/libiphone.h @@ -46,6 +46,8 @@ extern "C" { //afc specific error #define IPHONE_E_NO_SUCH_FILE -10 +typedef short iphone_error_t; + enum { AFC_FILE_READ = 0x00000002, // seems to be able to read and write files AFC_FILE_WRITE = 0x00000003, // writes and creates a file, blanks it out, etc. @@ -73,44 +75,44 @@ struct iphone_afc_file_int; typedef struct iphone_afc_file_int *iphone_afc_file_t; //device related functions -int iphone_get_device ( iphone_device_t *device ); -void iphone_free_device ( iphone_device_t device ); +iphone_error_t iphone_get_device ( iphone_device_t *device ); +iphone_error_t iphone_free_device ( iphone_device_t device ); //lockdownd related functions -int iphone_lckd_new_client ( iphone_device_t device, iphone_lckd_client_t *client ); -void iphone_lckd_free_client( iphone_lckd_client_t client ); +iphone_error_t iphone_lckd_new_client ( iphone_device_t device, iphone_lckd_client_t *client ); +iphone_error_t iphone_lckd_free_client( iphone_lckd_client_t client ); -int iphone_lckd_start_service ( iphone_lckd_client_t client, const char *service ); -int iphone_lckd_recv ( iphone_lckd_client_t client, char **dump_data ); -int iphone_lckd_send ( iphone_lckd_client_t client, char *raw_data, uint32_t length ); +iphone_error_t iphone_lckd_start_service ( iphone_lckd_client_t client, const char *service, int *port ); +iphone_error_t iphone_lckd_recv ( iphone_lckd_client_t client, char **dump_data, uint32_t *recv_bytes ); +iphone_error_t iphone_lckd_send ( iphone_lckd_client_t client, char *raw_data, uint32_t length, uint32_t *recv_bytes ); //usbmux related functions -int iphone_mux_new_client ( iphone_device_t device, uint16_t src_port, uint16_t dst_port, iphone_umux_client_t *client ); -void iphone_mux_free_client ( iphone_umux_client_t client ); +iphone_error_t iphone_mux_new_client ( iphone_device_t device, uint16_t src_port, uint16_t dst_port, iphone_umux_client_t *client ); +iphone_error_t iphone_mux_free_client ( iphone_umux_client_t client ); -int iphone_mux_send ( iphone_umux_client_t client, const char *data, uint32_t datalen ); -int iphone_mux_recv ( iphone_umux_client_t client, char *data, uint32_t datalen ); +iphone_error_t iphone_mux_send ( iphone_umux_client_t client, const char *data, uint32_t datalen, uint32_t *sent_bytes ); +iphone_error_t iphone_mux_recv ( iphone_umux_client_t client, char *data, uint32_t datalen, uint32_t *recv_bytes ); //afc related functions -int iphone_afc_new_client ( iphone_device_t device, int src_port, int dst_port, iphone_afc_client_t *client ); -void iphone_afc_free_client ( iphone_afc_client_t client ); - -char **iphone_afc_get_devinfo ( iphone_afc_client_t client ); -char **iphone_afc_get_dir_list ( iphone_afc_client_t client, const char *dir); - -int iphone_afc_get_file_attr ( iphone_afc_client_t client, const char *filename, struct stat *stbuf ); -int iphone_afc_open_file ( iphone_afc_client_t client, const char *filename, uint32_t file_mode, iphone_afc_file_t *file ); -void iphone_afc_close_file ( iphone_afc_client_t client, iphone_afc_file_t file); -int iphone_afc_read_file ( iphone_afc_client_t client, iphone_afc_file_t file, char *data, int length); -int iphone_afc_write_file ( iphone_afc_client_t client, iphone_afc_file_t file, const char *data, int length); -int iphone_afc_seek_file ( iphone_afc_client_t client, iphone_afc_file_t file, int seekpos); -int iphone_afc_truncate_file ( iphone_afc_client_t client, iphone_afc_file_t file, uint32_t newsize); -int iphone_afc_delete_file ( iphone_afc_client_t client, const char *path); -int iphone_afc_rename_file ( iphone_afc_client_t client, const char *from, const char *to); -int iphone_afc_mkdir ( iphone_afc_client_t client, const char *dir); +iphone_error_t iphone_afc_new_client ( iphone_device_t device, int src_port, int dst_port, iphone_afc_client_t *client ); +iphone_error_t iphone_afc_free_client ( iphone_afc_client_t client ); + +iphone_error_t iphone_afc_get_devinfo ( iphone_afc_client_t client, char ***infos ); +iphone_error_t iphone_afc_get_dir_list ( iphone_afc_client_t client, const char *dir, char ***list); + +iphone_error_t iphone_afc_get_file_attr ( iphone_afc_client_t client, const char *filename, struct stat *stbuf ); +iphone_error_t iphone_afc_open_file ( iphone_afc_client_t client, const char *filename, uint32_t file_mode, iphone_afc_file_t *file ); +iphone_error_t iphone_afc_close_file ( iphone_afc_client_t client, iphone_afc_file_t file); +iphone_error_t iphone_afc_read_file ( iphone_afc_client_t client, iphone_afc_file_t file, char *data, int length, uint32_t *bytes); +iphone_error_t iphone_afc_write_file ( iphone_afc_client_t client, iphone_afc_file_t file, const char *data, int length, uint32_t *bytes); +iphone_error_t iphone_afc_seek_file ( iphone_afc_client_t client, iphone_afc_file_t file, int seekpos); +iphone_error_t iphone_afc_truncate_file ( iphone_afc_client_t client, iphone_afc_file_t file, uint32_t newsize); +iphone_error_t iphone_afc_delete_file ( iphone_afc_client_t client, const char *path); +iphone_error_t iphone_afc_rename_file ( iphone_afc_client_t client, const char *from, const char *to); +iphone_error_t iphone_afc_mkdir ( iphone_afc_client_t client, const char *dir); #ifdef __cplusplus @@ -58,7 +58,7 @@ static void afc_unlock(iphone_afc_client_t client) { // just to be pretty * * @return A handle to the newly-connected client or NULL upon error. */ -int iphone_afc_new_client ( iphone_device_t device, int src_port, int dst_port, iphone_afc_client_t *client ) { +iphone_error_t iphone_afc_new_client ( iphone_device_t device, int src_port, int dst_port, iphone_afc_client_t *client ) { int ret = IPHONE_E_SUCCESS; iphone_afc_client_t client_loc = (iphone_afc_client_t)malloc(sizeof(struct iphone_afc_client_int)); @@ -100,12 +100,14 @@ int iphone_afc_new_client ( iphone_device_t device, int src_port, int dst_port, * * @param client The client to disconnect. */ -void iphone_afc_free_client ( iphone_afc_client_t client ) { - if (!client || !client->connection || !client->afc_packet) return; +iphone_error_t iphone_afc_free_client ( iphone_afc_client_t client ) { + if (!client || !client->connection || !client->afc_packet) + return IPHONE_E_INVALID_ARG; iphone_mux_free_client(client->connection); free(client->afc_packet); free(client); + return IPHONE_E_SUCCESS; } @@ -324,11 +326,12 @@ static char **make_strings_list(char *tokens, int true_length) { * @return A char ** list of files in that directory, terminated by an empty * string for now or NULL if there was an error. */ -char **iphone_afc_get_dir_list ( iphone_afc_client_t client, const char *dir) { +iphone_error_t iphone_afc_get_dir_list ( iphone_afc_client_t client, const char *dir, char ***list) { int bytes = 0; - char *data = NULL, **list = NULL; + char *data = NULL, **list_loc = NULL; + iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; - if (!client || !dir) return NULL; + if (!client || !dir || !list) return IPHONE_E_INVALID_ARG; afc_lock(client); @@ -339,23 +342,25 @@ char **iphone_afc_get_dir_list ( iphone_afc_client_t client, const char *dir) { bytes = dispatch_AFC_packet(client, dir, strlen(dir)); if (bytes <= 0) { afc_unlock(client); - return NULL; + return IPHONE_E_NOT_ENOUGH_DATA; } // Receive the data bytes = receive_AFC_data(client, &data); if (bytes < 0 && !data) { afc_unlock(client); - return NULL; + return IPHONE_E_NOT_ENOUGH_DATA; } // Parse the data - list = make_strings_list(data, bytes); + list_loc = make_strings_list(data, bytes); + if (list_loc) ret = IPHONE_E_SUCCESS; if (data) free(data); afc_unlock(client); + *list = list_loc; - return list; + return ret; } /** Get device info for a client connection to phone. (free space on disk, etc.) @@ -365,11 +370,11 @@ char **iphone_afc_get_dir_list ( iphone_afc_client_t client, const char *dir) { * @return A char ** list of parameters as given by AFC or NULL if there was an * error. */ -char **iphone_afc_get_devinfo ( iphone_afc_client_t client ) { +iphone_error_t iphone_afc_get_devinfo ( iphone_afc_client_t client, char ***infos) { int bytes = 0; char *data = NULL, **list = NULL; - if (!client) return NULL; + if (!client || !infos) return IPHONE_E_INVALID_ARG; afc_lock(client); @@ -379,14 +384,14 @@ char **iphone_afc_get_devinfo ( iphone_afc_client_t client ) { bytes = dispatch_AFC_packet(client, NULL, 0); if (bytes < 0) { afc_unlock(client); - return NULL; + return IPHONE_E_NOT_ENOUGH_DATA; } // Receive the data bytes = receive_AFC_data(client, &data); if (bytes < 0 && !data) { afc_unlock(client); - return NULL; + return IPHONE_E_NOT_ENOUGH_DATA; } // Parse the data @@ -394,8 +399,8 @@ char **iphone_afc_get_devinfo ( iphone_afc_client_t client ) { if (data) free(data); afc_unlock(client); - - return list; + *infos = list; + return IPHONE_E_SUCCESS; } /** Deletes a file. @@ -406,7 +411,7 @@ char **iphone_afc_get_devinfo ( iphone_afc_client_t client ) { * @return IPHONE_E_SUCCESS if everythong went well, IPHONE_E_INVALID_ARG * if arguments are NULL or invalid, IPHONE_E_NOT_ENOUGH_DATA otherwise. */ -int iphone_afc_delete_file ( iphone_afc_client_t client, const char *path) { +iphone_error_t iphone_afc_delete_file ( iphone_afc_client_t client, const char *path) { char *response = NULL; int bytes; @@ -445,7 +450,7 @@ int iphone_afc_delete_file ( iphone_afc_client_t client, const char *path) { * @return IPHONE_E_SUCCESS if everythong went well, IPHONE_E_INVALID_ARG * if arguments are NULL or invalid, IPHONE_E_NOT_ENOUGH_DATA otherwise. */ -int iphone_afc_rename_file ( iphone_afc_client_t client, const char *from, const char *to) { +iphone_error_t iphone_afc_rename_file ( iphone_afc_client_t client, const char *from, const char *to) { char *response = NULL; char *send = (char*)malloc(sizeof(char) * (strlen(from) + strlen(to) + 1 + sizeof(uint32))); int bytes = 0; @@ -488,7 +493,7 @@ int iphone_afc_rename_file ( iphone_afc_client_t client, const char *from, const * @return IPHONE_E_SUCCESS if everythong went well, IPHONE_E_INVALID_ARG * if arguments are NULL or invalid, IPHONE_E_NOT_ENOUGH_DATA otherwise. */ -int iphone_afc_mkdir ( iphone_afc_client_t client, const char *dir) { +iphone_error_t iphone_afc_mkdir ( iphone_afc_client_t client, const char *dir) { int bytes = 0; char *response = NULL; @@ -586,7 +591,7 @@ iphone_afc_file_t afc_get_file_info(iphone_afc_client_t client, const char *path * @return A pointer to an AFCFile struct containing the information received, * or NULL on failure. */ -int iphone_afc_get_file_attr ( iphone_afc_client_t client, const char *filename, struct stat *stbuf ) { +iphone_error_t iphone_afc_get_file_attr ( iphone_afc_client_t client, const char *filename, struct stat *stbuf ) { int ret = IPHONE_E_SUCCESS; if (!client ||!client->connection || !client->afc_packet || !stbuf) return IPHONE_E_INVALID_ARG; @@ -620,7 +625,7 @@ int iphone_afc_get_file_attr ( iphone_afc_client_t client, const char *filename, * received by afc_get_file_info) as well as the handle to the file or * NULL in the case of failure. */ -int iphone_afc_open_file ( iphone_afc_client_t client, const char *filename, uint32_t file_mode, iphone_afc_file_t *file ) { +iphone_error_t iphone_afc_open_file ( iphone_afc_client_t client, const char *filename, uint32_t file_mode, iphone_afc_file_t *file ) { iphone_afc_file_t file_loc = NULL; uint32 ag = 0; int bytes = 0, length = 0; @@ -677,12 +682,12 @@ int iphone_afc_open_file ( iphone_afc_client_t client, const char *filename, uin * * @return The number of bytes read if successful. If there was an error -1. */ -int iphone_afc_read_file ( iphone_afc_client_t client, iphone_afc_file_t file, char *data, int length) { +iphone_error_t iphone_afc_read_file ( iphone_afc_client_t client, iphone_afc_file_t file, char *data, int length, uint32_t *bytes) { char *input = NULL; - int current_count = 0, bytes = 0; + int current_count = 0, bytes_loc = 0; const int MAXIMUM_READ_SIZE = 1 << 16; - if (!client || !client->afc_packet || !client->connection || !file) return -1; + if (!client || !client->afc_packet || !client->connection || !file) return IPHONE_E_INVALID_ARG; if (debug) fprintf(stderr, "afc_read_file called for length %i\n", length); afc_lock(client); @@ -698,40 +703,41 @@ int iphone_afc_read_file ( iphone_afc_client_t client, iphone_afc_file_t file, c packet->size = ((length - current_count) < MAXIMUM_READ_SIZE) ? (length - current_count) : MAXIMUM_READ_SIZE; client->afc_packet->operation = AFC_READ; client->afc_packet->entire_length = client->afc_packet->this_length = 0; - bytes = dispatch_AFC_packet(client, (char*)packet, sizeof(AFCFilePacket)); + bytes_loc = dispatch_AFC_packet(client, (char*)packet, sizeof(AFCFilePacket)); free(packet); - if (bytes <= 0) { + if (bytes_loc <= 0) { afc_unlock(client); - return -1; + return IPHONE_E_NOT_ENOUGH_DATA; } // Receive the data - bytes = receive_AFC_data(client, &input); - if (debug) fprintf(stderr, "afc_read_file: bytes returned: %i\n", bytes); + bytes_loc = receive_AFC_data(client, &input); + if (debug) fprintf(stderr, "afc_read_file: bytes returned: %i\n", bytes_loc); if (bytes < 0) { if (input) free(input); afc_unlock(client); - return -1; + return IPHONE_E_NOT_ENOUGH_DATA; } else if (bytes == 0) { if (input) free(input); afc_unlock(client); - return current_count; + *bytes = current_count; + return IPHONE_E_SUCCESS; //FIXME check that's actually a success } else { if (input) { - if (debug) fprintf(stderr, "afc_read_file: %d\n", bytes); - memcpy(data+current_count, input, (bytes > length) ? length : bytes); + if (debug) fprintf(stderr, "afc_read_file: %d\n", bytes_loc); + memcpy(data+current_count, input, (bytes_loc > length) ? length : bytes_loc); free(input); input = NULL; - current_count += (bytes > length) ? length : bytes; + current_count += (bytes_loc > length) ? length : bytes_loc; } } } if (debug) fprintf(stderr, "afc_read_file: returning current_count as %i\n", current_count); afc_unlock(client); - - return current_count; + *bytes = current_count; + return IPHONE_E_SUCCESS; } /** Writes a given number of bytes to a file. @@ -744,13 +750,13 @@ int iphone_afc_read_file ( iphone_afc_client_t client, iphone_afc_file_t file, c * @return The number of bytes written to the file, or a value less than 0 if * none were written... */ -int iphone_afc_write_file ( iphone_afc_client_t client, iphone_afc_file_t file, const char *data, int length) { +iphone_error_t iphone_afc_write_file ( iphone_afc_client_t client, iphone_afc_file_t file, const char *data, int length, uint32_t *bytes) { char *acknowledgement = NULL; const int MAXIMUM_WRITE_SIZE = 1 << 16; - uint32 zero = 0, bytes = 0, segments = (length / MAXIMUM_WRITE_SIZE), current_count = 0, i = 0; + uint32 zero = 0, bytes_loc = 0, segments = (length / MAXIMUM_WRITE_SIZE), current_count = 0, i = 0; char *out_buffer = NULL; - if (!client ||!client->afc_packet || !client->connection || !file) return -1; + if (!client ||!client->afc_packet || !client->connection || !file || !bytes_loc) return IPHONE_E_INVALID_ARG; afc_lock(client); @@ -766,19 +772,19 @@ int iphone_afc_write_file ( iphone_afc_client_t client, iphone_afc_file_t file, memcpy(out_buffer, (char*)&file->filehandle, sizeof(uint32)); memcpy(out_buffer+4, (char*)&zero, sizeof(uint32)); memcpy(out_buffer+8, data+current_count, MAXIMUM_WRITE_SIZE); - bytes = dispatch_AFC_packet(client, out_buffer, MAXIMUM_WRITE_SIZE + 8); - if (bytes < 0) { + bytes_loc = dispatch_AFC_packet(client, out_buffer, MAXIMUM_WRITE_SIZE + 8); + if (bytes_loc < 0) { afc_unlock(client); - return bytes; + return IPHONE_E_NOT_ENOUGH_DATA; } free(out_buffer); out_buffer = NULL; - current_count += bytes; - bytes = receive_AFC_data(client, &acknowledgement); - if (bytes < 0) { + current_count += bytes_loc; + bytes_loc = receive_AFC_data(client, &acknowledgement); + if (bytes_loc < 0) { afc_unlock(client); - return current_count; + return IPHONE_E_NOT_ENOUGH_DATA; } } @@ -786,7 +792,8 @@ int iphone_afc_write_file ( iphone_afc_client_t client, iphone_afc_file_t file, // this length is fine because it's always sizeof(AFCPacket) + 8, but to be sure we do it again if (current_count == length) { afc_unlock(client); - return current_count; + *bytes = current_count; + return IPHONE_E_SUCCESS; } client->afc_packet->this_length = sizeof(AFCPacket) + 8; @@ -796,25 +803,26 @@ int iphone_afc_write_file ( iphone_afc_client_t client, iphone_afc_file_t file, memcpy(out_buffer, (char*)&file->filehandle, sizeof(uint32)); memcpy(out_buffer+4, (char*)&zero, sizeof(uint32)); memcpy(out_buffer+8, data+current_count, (length - current_count)); - bytes = dispatch_AFC_packet(client, out_buffer, (length - current_count) + 8); + bytes_loc = dispatch_AFC_packet(client, out_buffer, (length - current_count) + 8); free(out_buffer); out_buffer = NULL; - current_count += bytes; + current_count += bytes_loc; - if (bytes <= 0) { + if (bytes_loc <= 0) { afc_unlock(client); - return current_count; + *bytes = current_count; + return IPHONE_E_SUCCESS; } - zero = bytes; - bytes = receive_AFC_data(client, &acknowledgement); + zero = bytes_loc; + bytes_loc = receive_AFC_data(client, &acknowledgement); afc_unlock(client); - if (bytes < 0) { + if (bytes_loc < 0) { if (debug) fprintf(stderr, "afc_write_file: uh oh?\n"); } - - return current_count; + + return IPHONE_E_UNKNOWN_ERROR; } /** Closes a file on the phone. @@ -823,7 +831,8 @@ int iphone_afc_write_file ( iphone_afc_client_t client, iphone_afc_file_t file, * @param file A pointer to an AFCFile struct containing the file handle of the * file to close. */ -void iphone_afc_close_file ( iphone_afc_client_t client, iphone_afc_file_t file) { +iphone_error_t iphone_afc_close_file ( iphone_afc_client_t client, iphone_afc_file_t file) { + if (!client || !file) return IPHONE_E_INVALID_ARG; char *buffer = malloc(sizeof(char) * 8); uint32 zero = 0; int bytes = 0; @@ -846,7 +855,7 @@ void iphone_afc_close_file ( iphone_afc_client_t client, iphone_afc_file_t file) if (bytes <= 0) { afc_unlock(client); - return; + return IPHONE_E_UNKNOWN_ERROR; } // Receive the response @@ -854,6 +863,7 @@ void iphone_afc_close_file ( iphone_afc_client_t client, iphone_afc_file_t file) if (buffer) free(buffer); free(file); afc_unlock(client); + return IPHONE_E_SUCCESS; } /** Seeks to a given position of a pre-opened file on the phone. @@ -865,7 +875,7 @@ void iphone_afc_close_file ( iphone_afc_client_t client, iphone_afc_file_t file) * * @return IPHONE_E_SUCCESS on success, IPHONE_E_NOT_ENOUGH_DATA on failure. */ -int iphone_afc_seek_file ( iphone_afc_client_t client, iphone_afc_file_t file, int seekpos) { +iphone_error_t iphone_afc_seek_file ( iphone_afc_client_t client, iphone_afc_file_t file, int seekpos) { char *buffer = (char*)malloc(sizeof(char) * 24); uint32 seekto = 0, bytes = 0, zero = 0; @@ -916,7 +926,7 @@ int iphone_afc_seek_file ( iphone_afc_client_t client, iphone_afc_file_t file, i * @note This function is more akin to ftruncate than truncate, and truncate * calls would have to open the file before calling this, sadly. */ -int iphone_afc_truncate_file ( iphone_afc_client_t client, iphone_afc_file_t file, uint32_t newsize) { +iphone_error_t iphone_afc_truncate_file ( iphone_afc_client_t client, iphone_afc_file_t file, uint32_t newsize) { char *buffer = (char*)malloc(sizeof(char) * 16); uint32 bytes = 0, zero = 0; diff --git a/src/iphone.c b/src/iphone.c index 3d179de..f5bc206 100644 --- a/src/iphone.c +++ b/src/iphone.c @@ -34,7 +34,7 @@ extern int debug; * @return A structure with data on the first iPhone it finds. (Or NULL, on * error) */ -int iphone_get_device ( iphone_device_t *device ){ +iphone_error_t iphone_get_device ( iphone_device_t *device ){ //check we can actually write in device if (!device || (device && *device)) return IPHONE_E_INVALID_ARG; @@ -102,7 +102,7 @@ int iphone_get_device ( iphone_device_t *device ){ iphone_free_device(phone); if (debug) fprintf(stderr, "get_iPhone(): Invalid version message -- header too short.\n"); if (debug && bytes < 0) fprintf(stderr, "get_iPhone(): libusb error message %d: %s (%s)\n", - bytes, usb_strerror(), strerror(-bytes)); + bytes, usb_strerror(), strerror(-bytes)); return IPHONE_E_NOT_ENOUGH_DATA; } @@ -134,14 +134,21 @@ int iphone_get_device ( iphone_device_t *device ){ * * @param phone A pointer to an iPhone structure. */ -void iphone_free_device ( iphone_device_t device ) { - if (device->buffer) free(device->buffer); - if (device->device) { - usb_release_interface(device->device, 1); - usb_reset(device->device); - usb_close(device->device); +iphone_error_t iphone_free_device ( iphone_device_t device ) { + if (!device) return IPHONE_E_INVALID_ARG; + iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; + + if (device->buffer) { + free(device->buffer); + if (device->device) { + usb_release_interface(device->device, 1); + usb_reset(device->device); + usb_close(device->device); + ret = IPHONE_E_SUCCESS; + } + free(device); } - free(device); + return ret; } /** Sends data to the phone diff --git a/src/lockdown.c b/src/lockdown.c index 179b0a9..a22b896 100644 --- a/src/lockdown.c +++ b/src/lockdown.c @@ -94,15 +94,18 @@ iphone_lckd_client_t new_lockdownd_client(iphone_device_t phone) { * * @param control The lockdown client */ -void iphone_lckd_free_client( iphone_lckd_client_t client ) { - if (!client) return; +iphone_error_t iphone_lckd_free_client( iphone_lckd_client_t client ) { + if (!client) return IPHONE_E_INVALID_ARG; + iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; + if (client->connection) { - iphone_mux_free_client(client->connection); + ret = iphone_mux_free_client(client->connection); } if (client->ssl_session) gnutls_deinit(*client->ssl_session); free(client->ssl_session); free(client); + return ret; } /** Polls the iPhone for lockdownd data. @@ -113,20 +116,28 @@ void iphone_lckd_free_client( iphone_lckd_client_t client ) { * * @return The number of bytes received */ -int iphone_lckd_recv ( iphone_lckd_client_t client, char **dump_data ) { - if (!client) return 0; +iphone_error_t iphone_lckd_recv ( iphone_lckd_client_t client, char **dump_data, uint32_t *recv_bytes ) { + if (!client || dump_data || !recv_bytes) return IPHONE_E_INVALID_ARG; + iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; char *receive; uint32 datalen = 0, bytes = 0; - if (!client->in_SSL) bytes = iphone_mux_recv(client->connection, (char *)&datalen, sizeof(datalen)); - else bytes = gnutls_record_recv(*client->ssl_session, &datalen, sizeof(datalen)); + if (!client->in_SSL) ret = iphone_mux_recv(client->connection, (char *)&datalen, sizeof(datalen), &bytes); + else { + bytes = gnutls_record_recv(*client->ssl_session, &datalen, sizeof(datalen)); + if (bytes > 0) ret = IPHONE_E_SUCCESS; + } datalen = ntohl(datalen); receive = (char*)malloc(sizeof(char) * datalen); - if (!client->in_SSL) bytes = iphone_mux_recv(client->connection, receive, datalen); - else bytes = gnutls_record_recv(*client->ssl_session, receive, datalen); + if (!client->in_SSL) ret = iphone_mux_recv(client->connection, receive, datalen, &bytes); + else { + bytes = gnutls_record_recv(*client->ssl_session, receive, datalen); + if (bytes > 0) ret = IPHONE_E_SUCCESS; + } *dump_data = receive; - return bytes; + *recv_bytes = bytes; + return ret; } /** Sends lockdownd data to the iPhone @@ -140,11 +151,12 @@ int iphone_lckd_recv ( iphone_lckd_client_t client, char **dump_data ) { * * @return The number of bytes sent */ -int iphone_lckd_send ( iphone_lckd_client_t client, char *raw_data, uint32_t length ) { - if (!client) return 0; +iphone_error_t iphone_lckd_send ( iphone_lckd_client_t client, char *raw_data, uint32_t length, uint32_t *sent_bytes ) { + if (!client || !raw_data || length == 0 || !sent_bytes) return IPHONE_E_INVALID_ARG; char *real_query; int bytes; - + iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; + real_query = (char*)malloc(sizeof(char) * (length+4)); length = htonl(length); memcpy(real_query, &length, sizeof(length)); @@ -157,11 +169,15 @@ int iphone_lckd_send ( iphone_lckd_client_t client, char *raw_data, uint32_t len packet = NULL; } - if (!client->in_SSL) bytes = iphone_mux_send(client->connection, real_query, ntohl(length)+sizeof(length)); - else gnutls_record_send(*client->ssl_session, real_query, ntohl(length)+sizeof(length)); + if (!client->in_SSL) ret = iphone_mux_send(client->connection, real_query, ntohl(length)+sizeof(length), &bytes); + else { + gnutls_record_send(*client->ssl_session, real_query, ntohl(length)+sizeof(length)); + ret = IPHONE_E_SUCCESS; + } if (debug) printf("lockdownd_send(): sent it!\n"); free(real_query); - return bytes; + *sent_bytes = bytes; + return ret; } /** Initiates the handshake for the lockdown session. Part of the lockdownd handshake. @@ -307,11 +323,11 @@ int lockdownd_get_device_public_key(iphone_lckd_client_t control, char **public_ * * @return 1 on success and 0 on failure */ -int iphone_lckd_new_client ( iphone_device_t device, iphone_lckd_client_t *client ) +iphone_error_t iphone_lckd_new_client ( iphone_device_t device, iphone_lckd_client_t *client ) { if (!device || !client || (client && *client) ) return IPHONE_E_INVALID_ARG; - int ret = IPHONE_E_SUCCESS; + iphone_error_t ret = IPHONE_E_SUCCESS; char *host_id = NULL; iphone_lckd_client_t client_loc = new_lockdownd_client( device ); @@ -815,14 +831,15 @@ ssize_t lockdownd_securead(gnutls_transport_ptr_t transport, char *buffer, size_ * * @return The port number the service was started on or 0 on failure. */ -int iphone_lckd_start_service ( iphone_lckd_client_t client, const char *service ) { - if (!client) return 0; +iphone_error_t iphone_lckd_start_service ( iphone_lckd_client_t client, const char *service, int *port ) { + if (!client || !service || !port) return IPHONE_E_INVALID_ARG; char* host_id = get_host_id(); - if (host_id && !client->in_SSL && !lockdownd_start_SSL_session(client, host_id)) return 0; + if (!host_id) return IPHONE_E_INVALID_CONF; + if (!client->in_SSL && !lockdownd_start_SSL_session(client, host_id)) return IPHONE_E_SSL_ERROR; char *XML_query, **dictionary; - uint32 length, i = 0, port = 0; + uint32 length, i = 0, port_loc = 0; uint8 result = 0; free(host_id); @@ -832,9 +849,9 @@ int iphone_lckd_start_service ( iphone_lckd_client_t client, const char *service xmlNode *dict = add_child_to_plist(plist, "dict", "\n", NULL, 0); xmlNode *key; key = add_key_str_dict_element(plist, dict, "Request", "StartService", 1); - if (!key) { xmlFreeDoc(plist); return 0; } + if (!key) { xmlFreeDoc(plist); return IPHONE_E_UNKNOWN_ERROR; } key = add_key_str_dict_element(plist, dict, "Service", service, 1); - if (!key) { xmlFreeDoc(plist); return 0; } + if (!key) { xmlFreeDoc(plist); return IPHONE_E_UNKNOWN_ERROR; } xmlDocDumpMemory(plist, (xmlChar **)&XML_query, &length); @@ -845,24 +862,24 @@ int iphone_lckd_start_service ( iphone_lckd_client_t client, const char *service xmlFreeDoc(plist); - if (length <= 0) return 0; + if (length <= 0) return IPHONE_E_NOT_ENOUGH_DATA; else { plist = xmlReadMemory(XML_query, length, NULL, NULL, 0); - if (!plist) return 0; + if (!plist) return IPHONE_E_UNKNOWN_ERROR; dict = xmlDocGetRootElement(plist); - if (!dict) return 0; + if (!dict) return IPHONE_E_UNKNOWN_ERROR; for (dict = dict->children; dict; dict = dict->next) { if (!xmlStrcmp(dict->name, "dict")) break; } - if (!dict) return 0; + if (!dict) return IPHONE_E_UNKNOWN_ERROR; dictionary = read_dict_element_strings(dict); for (i = 0; dictionary[i]; i+=2) { if (debug) printf("lockdownd_start_service() dictionary %s: %s\n", dictionary[i], dictionary[i+1]); if (!xmlStrcmp(dictionary[i], "Port")) { - port = atoi(dictionary[i+1]); + port_loc = atoi(dictionary[i+1]); if (debug) printf("lockdownd_start_service() atoi'd port: %i\n", port); } @@ -882,9 +899,12 @@ int iphone_lckd_start_service ( iphone_lckd_client_t client, const char *service free(XML_query); xmlFreeDoc(plist); free_dictionary(dictionary); - if (port && result) return port; - else return 0; + if (port && result) { + *port = port_loc; + return IPHONE_E_SUCCESS; + } + else return IPHONE_E_UNKNOWN_ERROR; } - return 0; + return IPHONE_E_UNKNOWN_ERROR; } diff --git a/src/usbmux.c b/src/usbmux.c index 5e3f441..8d85245 100644 --- a/src/usbmux.c +++ b/src/usbmux.c @@ -116,7 +116,7 @@ void add_connection(iphone_umux_client_t connection) { * @param client A mux TCP header for the connection which is used for tracking and data transfer. * @return IPHONE_E_SUCCESS on success, an error code otherwise. */ -int iphone_mux_new_client ( iphone_device_t device, uint16_t src_port, uint16_t dst_port, iphone_umux_client_t *client ){ +iphone_error_t iphone_mux_new_client ( iphone_device_t device, uint16_t src_port, uint16_t dst_port, iphone_umux_client_t *client ){ if (!device || !src_port || !dst_port) return IPHONE_E_INVALID_ARG; @@ -165,8 +165,10 @@ int iphone_mux_new_client ( iphone_device_t device, uint16_t src_port, uint16_t * @note Once a connection is closed it may not be used again. * * @param connection The connection to close. + * + * @return IPHONE_E_SUCCESS on success. */ -void iphone_mux_free_client ( iphone_umux_client_t client ) { +iphone_error_t iphone_mux_free_client ( iphone_umux_client_t client ) { if (!client || !client->phone) return; client->header->tcp_flags = 0x04; @@ -183,6 +185,8 @@ void iphone_mux_free_client ( iphone_umux_client_t client ) { printf("get_iPhone(): when reading, libusb gave me the error: %s\n", usb_strerror()); delete_connection(client); + + return IPHONE_E_SUCCESS; } @@ -192,15 +196,16 @@ void iphone_mux_free_client ( iphone_umux_client_t client ) { * @param client The client we're sending data on. * @param data A pointer to the data to send. * @param datalen How much data we're sending. + * @param sent_bytes The number of bytes sent, minus the header (28) * - * @return The number of bytes sent, minus the header (28), or -1 on error. + * @return IPHONE_E_SUCCESS on success. */ -int iphone_mux_send ( iphone_umux_client_t client, const char *data, uint32_t datalen ) { - if (!client->phone || !client || !data || datalen == 0) return -1; +iphone_error_t iphone_mux_send ( iphone_umux_client_t client, const char *data, uint32_t datalen, uint32_t *sent_bytes ) { + if (!client->phone || !client || !data || datalen == 0 || !sent_bytes) return IPHONE_E_INVALID_ARG; // client->scnt and client->ocnt should already be in host notation... // we don't need to change them juuuust yet. - int bytes = 0; + *sent_bytes = 0; if (debug) printf("mux_send(): client wants to send %i bytes\n", datalen); char *buffer = (char*)malloc(sizeof(usbmux_tcp_header) + datalen + 2); // allow 2 bytes of safety padding // Set the length and pre-emptively htonl/htons it @@ -218,12 +223,12 @@ int iphone_mux_send ( iphone_umux_client_t client, const char *data, uint32_t da if (debug) printf("actually sending %zi bytes of data at %p\n", sizeof(usbmux_tcp_header)+datalen, buffer); - bytes = send_to_phone(client->phone, buffer, sizeof(usbmux_tcp_header)+datalen); - if (debug) printf("mux_send: sent %i bytes!\n", bytes); + *sent_bytes = send_to_phone(client->phone, buffer, sizeof(usbmux_tcp_header)+datalen); + if (debug) printf("mux_send: sent %i bytes!\n", *sent_bytes); // Now that we've sent it off, we can clean up after our sloppy selves. if (debug) { FILE *packet = fopen("packet", "a+"); - fwrite(buffer, 1, bytes, packet); + fwrite(buffer, 1, *sent_bytes, packet); fclose(packet); printf("\n"); } @@ -238,13 +243,14 @@ int iphone_mux_send ( iphone_umux_client_t client, const char *data, uint32_t da client->header->length16 = ntohs(client->header->length16); // Now return the bytes. - if (bytes < sizeof(usbmux_tcp_header)+datalen) { - return -1; // blah + if (*sent_bytes < sizeof(usbmux_tcp_header)+datalen) { + *sent_bytes = 0; + return IPHONE_E_NOT_ENOUGH_DATA; } else { - return bytes - 28; // actual length sent. :/ + *sent_bytes = *sent_bytes - 28; // actual length sent. :/ } - return bytes; // or something + return IPHONE_E_UNKNOWN_ERROR; } /** This is a higher-level USBMuxTCP-like function @@ -255,7 +261,10 @@ int iphone_mux_send ( iphone_umux_client_t client, const char *data, uint32_t da * * @return How many bytes were read, or -1 if something bad happens. */ -int iphone_mux_recv ( iphone_umux_client_t client, char *data, uint32_t datalen ) { +iphone_error_t iphone_mux_recv ( iphone_umux_client_t client, char *data, uint32_t datalen, uint32_t *recv_bytes ) { + + if (!client || !data || datalen == 0 || !recv_bytes) + return IPHONE_E_INVALID_ARG; /* * Order of operation: * 1.) Check if the client has a pre-received buffer. @@ -268,6 +277,7 @@ int iphone_mux_recv ( iphone_umux_client_t client, char *data, uint32_t datalen */ if (debug) printf("mux_recv: datalen == %i\n", datalen); int bytes = 0, i = 0, complex = 0, offset = 0; + *recv_bytes = 0; char *buffer = NULL; usbmux_tcp_header *header = NULL; @@ -304,7 +314,7 @@ int iphone_mux_recv ( iphone_umux_client_t client, char *data, uint32_t datalen if (bytes < 28) { free(buffer); if (debug) printf("mux_recv: Did not even get the header.\n"); - return -1; + return IPHONE_E_NOT_ENOUGH_DATA; } header = (usbmux_tcp_header*)buffer; @@ -332,7 +342,7 @@ int iphone_mux_recv ( iphone_umux_client_t client, char *data, uint32_t datalen // Free our buffer and continue. free(buffer); buffer = NULL; - return iphone_mux_recv(client, data, datalen); // recurse back in to try again + return iphone_mux_recv(client, data, datalen, recv_bytes); // recurse back in to try again } // The packet was absolutely meant for us if it hits this point. @@ -348,13 +358,15 @@ int iphone_mux_recv ( iphone_umux_client_t client, char *data, uint32_t datalen memcpy(client->recv_buffer+complex, buffer+28+datalen, (bytes-28) - datalen); free(buffer); client->header->ocnt += bytes-28; - return datalen; + *recv_bytes = datalen; + return IPHONE_E_SUCCESS; } else { // Fill the data with what we have, and just return. memcpy(data+offset, buffer+28, bytes-28); // data+offset: see #2b, above client->header->ocnt += bytes-28; free(buffer); - return (bytes-28); + *recv_bytes = bytes - 28; + return IPHONE_E_SUCCESS; } // If we get to this point, 'tis probably bad. |