diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/AFC.c | 66 | ||||
| -rw-r--r-- | src/AFC.h | 11 | ||||
| -rw-r--r-- | src/ifuse.c | 5 | ||||
| -rw-r--r-- | src/iphone.c | 3 | ||||
| -rw-r--r-- | src/lockdown.c | 36 | ||||
| -rw-r--r-- | src/lockdown.h | 3 | ||||
| -rw-r--r-- | src/plist.h | 1 | ||||
| -rw-r--r-- | src/usbmux.c | 251 | ||||
| -rw-r--r-- | src/usbmux.h | 17 | ||||
| -rw-r--r-- | src/userpref.c | 2 |
10 files changed, 277 insertions, 118 deletions
| @@ -34,7 +34,6 @@ AFClient *afc_connect(iPhone *phone, int s_port, int d_port) { | |||
| 34 | else { | 34 | else { |
| 35 | client->afc_packet = (AFCPacket*)malloc(sizeof(AFCPacket)); | 35 | client->afc_packet = (AFCPacket*)malloc(sizeof(AFCPacket)); |
| 36 | if (client->afc_packet) { | 36 | if (client->afc_packet) { |
| 37 | client->phone = phone; | ||
| 38 | client->afc_packet->packet_num = 0; | 37 | client->afc_packet->packet_num = 0; |
| 39 | client->afc_packet->unknown1 = client->afc_packet->unknown2 = client->afc_packet->unknown3 = client->afc_packet->unknown4 = client->afc_packet->entire_length = client->afc_packet->this_length = 0; | 38 | client->afc_packet->unknown1 = client->afc_packet->unknown2 = client->afc_packet->unknown3 = client->afc_packet->unknown4 = client->afc_packet->entire_length = client->afc_packet->this_length = 0; |
| 40 | client->afc_packet->header1 = 0x36414643; | 39 | client->afc_packet->header1 = 0x36414643; |
| @@ -42,7 +41,7 @@ AFClient *afc_connect(iPhone *phone, int s_port, int d_port) { | |||
| 42 | client->file_handle = 0; | 41 | client->file_handle = 0; |
| 43 | return client; | 42 | return client; |
| 44 | } else { | 43 | } else { |
| 45 | mux_close_connection(client->phone, client->connection); | 44 | mux_close_connection(client->connection); |
| 46 | free(client); | 45 | free(client); |
| 47 | return NULL; | 46 | return NULL; |
| 48 | } | 47 | } |
| @@ -53,8 +52,8 @@ AFClient *afc_connect(iPhone *phone, int s_port, int d_port) { | |||
| 53 | 52 | ||
| 54 | void afc_disconnect(AFClient *client) { | 53 | void afc_disconnect(AFClient *client) { |
| 55 | // client and its members should never be NULL is assumed here. | 54 | // client and its members should never be NULL is assumed here. |
| 56 | if (!client || !client->connection || !client->phone || !client->afc_packet) return; | 55 | if (!client || !client->connection || !client->afc_packet) return; |
| 57 | mux_close_connection(client->phone, client->connection); | 56 | mux_close_connection(client->connection); |
| 58 | free(client->afc_packet); | 57 | free(client->afc_packet); |
| 59 | free(client); | 58 | free(client); |
| 60 | } | 59 | } |
| @@ -67,10 +66,10 @@ int count_nullspaces(char *string, int number) { | |||
| 67 | return nulls; | 66 | return nulls; |
| 68 | } | 67 | } |
| 69 | 68 | ||
| 70 | int dispatch_AFC_packet(AFClient *client, char *data, int length) { | 69 | int dispatch_AFC_packet(AFClient *client, const char *data, int length) { |
| 71 | char *buffer; | 70 | char *buffer; |
| 72 | int bytes = 0, offset = 0; | 71 | int bytes = 0, offset = 0; |
| 73 | if (!client || !client->connection || !client->phone || !client->afc_packet) return 0; | 72 | if (!client || !client->connection || !client->afc_packet) return 0; |
| 74 | if (!data || !length) length = 0; | 73 | if (!data || !length) length = 0; |
| 75 | 74 | ||
| 76 | client->afc_packet->packet_num++; | 75 | client->afc_packet->packet_num++; |
| @@ -91,7 +90,7 @@ int dispatch_AFC_packet(AFClient *client, char *data, int length) { | |||
| 91 | } | 90 | } |
| 92 | if (debug) printf("dispatch_AFC_packet: fucked-up packet method (probably a write)\n"); | 91 | if (debug) printf("dispatch_AFC_packet: fucked-up packet method (probably a write)\n"); |
| 93 | memcpy(buffer+sizeof(AFCPacket), data, offset); | 92 | memcpy(buffer+sizeof(AFCPacket), data, offset); |
| 94 | bytes = mux_send(client->phone, client->connection, buffer, client->afc_packet->this_length); | 93 | bytes = mux_send(client->connection, buffer, client->afc_packet->this_length); |
| 95 | free(buffer); | 94 | free(buffer); |
| 96 | if (bytes <= 0) { return 0; } | 95 | if (bytes <= 0) { return 0; } |
| 97 | if (debug) { | 96 | if (debug) { |
| @@ -102,7 +101,7 @@ int dispatch_AFC_packet(AFClient *client, char *data, int length) { | |||
| 102 | } | 101 | } |
| 103 | 102 | ||
| 104 | 103 | ||
| 105 | bytes = mux_send(client->phone, client->connection, data+offset, length-offset); | 104 | bytes = mux_send(client->connection, data+offset, length-offset); |
| 106 | if (bytes <= 0) { return 0; } | 105 | if (bytes <= 0) { return 0; } |
| 107 | else { return bytes; } | 106 | else { return bytes; } |
| 108 | } else { | 107 | } else { |
| @@ -114,7 +113,7 @@ int dispatch_AFC_packet(AFClient *client, char *data, int length) { | |||
| 114 | if (length > 0) { memcpy(buffer+sizeof(AFCPacket), data, length); buffer[sizeof(AFCPacket)+length] = '\0'; } | 113 | if (length > 0) { memcpy(buffer+sizeof(AFCPacket), data, length); buffer[sizeof(AFCPacket)+length] = '\0'; } |
| 115 | if (debug) fwrite(buffer, 1, client->afc_packet->this_length, stdout); | 114 | if (debug) fwrite(buffer, 1, client->afc_packet->this_length, stdout); |
| 116 | if (debug) printf("\n"); | 115 | if (debug) printf("\n"); |
| 117 | bytes = mux_send(client->phone, client->connection, buffer, client->afc_packet->this_length); | 116 | bytes = mux_send(client->connection, buffer, client->afc_packet->this_length); |
| 118 | if (bytes <= 0) return 0; | 117 | if (bytes <= 0) return 0; |
| 119 | else return bytes; | 118 | else return bytes; |
| 120 | } | 119 | } |
| @@ -126,9 +125,9 @@ int receive_AFC_data(AFClient *client, char **dump_here) { | |||
| 126 | char *buffer = (char*)malloc(sizeof(AFCPacket) * 4); | 125 | char *buffer = (char*)malloc(sizeof(AFCPacket) * 4); |
| 127 | char *final_buffer = NULL; | 126 | char *final_buffer = NULL; |
| 128 | int bytes = 0, recv_len = 0, current_count=0; | 127 | int bytes = 0, recv_len = 0, current_count=0; |
| 129 | int retval = 0; | 128 | int retval = 0; |
| 130 | 129 | ||
| 131 | bytes = mux_recv(client->phone, client->connection, buffer, sizeof(AFCPacket) * 4); | 130 | bytes = mux_recv(client->connection, buffer, sizeof(AFCPacket) * 4); |
| 132 | if (bytes <= 0) { | 131 | if (bytes <= 0) { |
| 133 | free(buffer); | 132 | free(buffer); |
| 134 | printf("Just didn't get enough.\n"); | 133 | printf("Just didn't get enough.\n"); |
| @@ -151,10 +150,17 @@ int receive_AFC_data(AFClient *client, char **dump_here) { | |||
| 151 | uint32 param1 = buffer[sizeof(AFCPacket)]; | 150 | uint32 param1 = buffer[sizeof(AFCPacket)]; |
| 152 | free(buffer); | 151 | free(buffer); |
| 153 | 152 | ||
| 154 | if (r_packet->operation == 0x01 && !((client->afc_packet->operation == AFC_DELETE && param1 == 7))) { | 153 | if (r_packet->operation == AFC_ERROR |
| 155 | if (debug) printf("Oops? Bad operation code received: 0x%0X\n", r_packet->operation); | 154 | && !(client->afc_packet->operation == AFC_DELETE && param1 == 7) |
| 156 | if (param1 == 0) { | 155 | ) |
| 156 | { | ||
| 157 | if (debug) printf("Oops? Bad operation code received: 0x%X, operation=0x%X, param1=%d\n", | ||
| 158 | r_packet->operation, client->afc_packet->operation, param1); | ||
| 159 | recv_len = r_packet->entire_length - r_packet->this_length; | ||
| 160 | if (debug) printf("recv_len=%d\n", recv_len); | ||
| 161 | if(param1 == 0) { | ||
| 157 | if (debug) printf("... false alarm, but still\n"); | 162 | if (debug) printf("... false alarm, but still\n"); |
| 163 | *dump_here = NULL; | ||
| 158 | return 1; | 164 | return 1; |
| 159 | } | 165 | } |
| 160 | else { if (debug) printf("Errno %i\n", param1); } | 166 | else { if (debug) printf("Errno %i\n", param1); } |
| @@ -167,13 +173,17 @@ int receive_AFC_data(AFClient *client, char **dump_here) { | |||
| 167 | 173 | ||
| 168 | recv_len = r_packet->entire_length - r_packet->this_length; | 174 | recv_len = r_packet->entire_length - r_packet->this_length; |
| 169 | free(r_packet); | 175 | free(r_packet); |
| 170 | if (!recv_len) return bytes; | 176 | if (!recv_len) |
| 177 | { | ||
| 178 | *dump_here = NULL; | ||
| 179 | return 0; | ||
| 180 | } | ||
| 171 | 181 | ||
| 172 | // Keep collecting packets until we have received the entire file. | 182 | // Keep collecting packets until we have received the entire file. |
| 173 | buffer = (char*)malloc(sizeof(char) * (recv_len < MAXIMUM_PACKET_SIZE) ? recv_len : MAXIMUM_PACKET_SIZE); | 183 | buffer = (char*)malloc(sizeof(char) * (recv_len < MAXIMUM_PACKET_SIZE) ? recv_len : MAXIMUM_PACKET_SIZE); |
| 174 | final_buffer = (char*)malloc(sizeof(char) * recv_len); | 184 | final_buffer = (char*)malloc(sizeof(char) * recv_len); |
| 175 | while(current_count < recv_len){ | 185 | while(current_count < recv_len){ |
| 176 | bytes = mux_recv(client->phone, client->connection, buffer, recv_len-current_count); | 186 | bytes = mux_recv(client->connection, buffer, recv_len-current_count); |
| 177 | if (bytes < 0) | 187 | if (bytes < 0) |
| 178 | { | 188 | { |
| 179 | if(debug) printf("receive_AFC_data: mux_recv failed: %d\n", bytes); | 189 | if(debug) printf("receive_AFC_data: mux_recv failed: %d\n", bytes); |
| @@ -200,7 +210,7 @@ int receive_AFC_data(AFClient *client, char **dump_here) { | |||
| 200 | return current_count; | 210 | return current_count; |
| 201 | } | 211 | } |
| 202 | 212 | ||
| 203 | char **afc_get_dir_list(AFClient *client, char *dir) { | 213 | char **afc_get_dir_list(AFClient *client, const char *dir) { |
| 204 | client->afc_packet->operation = AFC_LIST_DIR; | 214 | client->afc_packet->operation = AFC_LIST_DIR; |
| 205 | int bytes = 0; | 215 | int bytes = 0; |
| 206 | char *blah = NULL, **list = NULL; | 216 | char *blah = NULL, **list = NULL; |
| @@ -232,7 +242,7 @@ char **make_strings_list(char *tokens, int true_length) { | |||
| 232 | } | 242 | } |
| 233 | 243 | ||
| 234 | int afc_delete_file(AFClient *client, const char *path) { | 244 | int afc_delete_file(AFClient *client, const char *path) { |
| 235 | if (!client || !path || !client->afc_packet || !client->phone ||!client->connection) return 0; | 245 | if (!client || !path || !client->afc_packet || !client->connection) return 0; |
| 236 | 246 | ||
| 237 | char *receive = NULL; | 247 | char *receive = NULL; |
| 238 | client->afc_packet->this_length = client->afc_packet->entire_length = 0; | 248 | client->afc_packet->this_length = client->afc_packet->entire_length = 0; |
| @@ -248,7 +258,7 @@ int afc_delete_file(AFClient *client, const char *path) { | |||
| 248 | } | 258 | } |
| 249 | 259 | ||
| 250 | int afc_rename_file(AFClient *client, const char *from, const char *to) { | 260 | int afc_rename_file(AFClient *client, const char *from, const char *to) { |
| 251 | if (!client || !from || !to || !client->afc_packet || !client->phone || !client->connection) return 0; | 261 | if (!client || !from || !to || !client->afc_packet || !client->connection) return 0; |
| 252 | 262 | ||
| 253 | char *receive = NULL; | 263 | char *receive = NULL; |
| 254 | char *send = (char*)malloc(sizeof(char) * (strlen(from) + strlen(to) + 1 + sizeof(uint32))); | 264 | char *send = (char*)malloc(sizeof(char) * (strlen(from) + strlen(to) + 1 + sizeof(uint32))); |
| @@ -271,7 +281,7 @@ int afc_rename_file(AFClient *client, const char *from, const char *to) { | |||
| 271 | 281 | ||
| 272 | 282 | ||
| 273 | 283 | ||
| 274 | AFCFile *afc_get_file_info(AFClient *client, char *path) { | 284 | AFCFile *afc_get_file_info(AFClient *client, const char *path) { |
| 275 | client->afc_packet->operation = AFC_GET_INFO; | 285 | client->afc_packet->operation = AFC_GET_INFO; |
| 276 | client->afc_packet->entire_length = client->afc_packet->this_length = 0; | 286 | client->afc_packet->entire_length = client->afc_packet->this_length = 0; |
| 277 | dispatch_AFC_packet(client, path, strlen(path)); | 287 | dispatch_AFC_packet(client, path, strlen(path)); |
| @@ -312,7 +322,7 @@ AFCFile *afc_get_file_info(AFClient *client, char *path) { | |||
| 312 | 322 | ||
| 313 | AFCFile *afc_open_file(AFClient *client, const char *filename, uint32 file_mode) { | 323 | AFCFile *afc_open_file(AFClient *client, const char *filename, uint32 file_mode) { |
| 314 | if (file_mode != AFC_FILE_READ && file_mode != AFC_FILE_WRITE) return NULL; | 324 | if (file_mode != AFC_FILE_READ && file_mode != AFC_FILE_WRITE) return NULL; |
| 315 | if (!client ||!client->connection || !client->phone ||!client->afc_packet) return NULL; | 325 | if (!client ||!client->connection || !client->afc_packet) return NULL; |
| 316 | char *further_data = (char*)malloc(sizeof(char) * (8 + strlen(filename) + 1)); | 326 | char *further_data = (char*)malloc(sizeof(char) * (8 + strlen(filename) + 1)); |
| 317 | AFCFile *file_infos = NULL; | 327 | AFCFile *file_infos = NULL; |
| 318 | memcpy(further_data, &file_mode, 4); | 328 | memcpy(further_data, &file_mode, 4); |
| @@ -345,7 +355,7 @@ AFCFile *afc_open_file(AFClient *client, const char *filename, uint32 file_mode) | |||
| 345 | } | 355 | } |
| 346 | 356 | ||
| 347 | int afc_read_file(AFClient *client, AFCFile *file, char *data, int length) { | 357 | int afc_read_file(AFClient *client, AFCFile *file, char *data, int length) { |
| 348 | if (!client || !client->afc_packet || !client->phone || !client->connection || !file) return -1; | 358 | if (!client || !client->afc_packet || !client->connection || !file) return -1; |
| 349 | AFCFilePacket *packet = (AFCFilePacket*)malloc(sizeof(AFCFilePacket)); | 359 | AFCFilePacket *packet = (AFCFilePacket*)malloc(sizeof(AFCFilePacket)); |
| 350 | char *input = NULL; | 360 | char *input = NULL; |
| 351 | packet->unknown1 = packet->unknown2 = 0; | 361 | packet->unknown1 = packet->unknown2 = 0; |
| @@ -359,11 +369,15 @@ int afc_read_file(AFClient *client, AFCFile *file, char *data, int length) { | |||
| 359 | 369 | ||
| 360 | if (bytes > 0) { | 370 | if (bytes > 0) { |
| 361 | bytes = receive_AFC_data(client, &input); | 371 | bytes = receive_AFC_data(client, &input); |
| 362 | if (bytes <= 0) { | 372 | if (bytes < 0) { |
| 363 | if (input) free(input); | 373 | if (input) free(input); |
| 364 | return -1; | 374 | return -1; |
| 375 | } else if (bytes == 0) { | ||
| 376 | if (input) free(input); | ||
| 377 | return 0; | ||
| 365 | } else { | 378 | } else { |
| 366 | memcpy(data, input, (bytes > length) ? length : bytes); | 379 | if (input) |
| 380 | memcpy(data, input, (bytes > length) ? length : bytes); | ||
| 367 | free(input); | 381 | free(input); |
| 368 | return (bytes > length) ? length : bytes; | 382 | return (bytes > length) ? length : bytes; |
| 369 | } | 383 | } |
| @@ -373,9 +387,9 @@ int afc_read_file(AFClient *client, AFCFile *file, char *data, int length) { | |||
| 373 | return 0; | 387 | return 0; |
| 374 | } | 388 | } |
| 375 | 389 | ||
| 376 | int afc_write_file(AFClient *client, AFCFile *file, char *data, int length) { | 390 | int afc_write_file(AFClient *client, AFCFile *file, const char *data, int length) { |
| 377 | char *acknowledgement = NULL; | 391 | char *acknowledgement = NULL; |
| 378 | if (!client ||!client->afc_packet ||!client->phone || !client->connection || !file) return -1; | 392 | if (!client ||!client->afc_packet || !client->connection || !file) return -1; |
| 379 | client->afc_packet->this_length = sizeof(AFCPacket) + 8; | 393 | client->afc_packet->this_length = sizeof(AFCPacket) + 8; |
| 380 | client->afc_packet->entire_length = client->afc_packet->this_length + length; | 394 | client->afc_packet->entire_length = client->afc_packet->this_length + length; |
| 381 | client->afc_packet->operation = AFC_WRITE; | 395 | client->afc_packet->operation = AFC_WRITE; |
| @@ -35,8 +35,7 @@ typedef struct { | |||
| 35 | } AFCPacket; | 35 | } AFCPacket; |
| 36 | 36 | ||
| 37 | typedef struct { | 37 | typedef struct { |
| 38 | usbmux_tcp_header *connection; | 38 | usbmux_connection *connection; |
| 39 | iPhone *phone; | ||
| 40 | AFCPacket *afc_packet; | 39 | AFCPacket *afc_packet; |
| 41 | int file_handle; | 40 | int file_handle; |
| 42 | } AFClient; | 41 | } AFClient; |
| @@ -79,14 +78,14 @@ AFClient *afc_connect(iPhone *phone, int s_port, int d_port); | |||
| 79 | void afc_disconnect(AFClient *client); | 78 | void afc_disconnect(AFClient *client); |
| 80 | int count_nullspaces(char *string, int number); | 79 | int count_nullspaces(char *string, int number); |
| 81 | char **make_strings_list(char *tokens, int true_length); | 80 | char **make_strings_list(char *tokens, int true_length); |
| 82 | int dispatch_AFC_packet(AFClient *client, char *data, int length); | 81 | int dispatch_AFC_packet(AFClient *client, const char *data, int length); |
| 83 | int receive_AFC_data(AFClient *client, char **dump_here); | 82 | int receive_AFC_data(AFClient *client, char **dump_here); |
| 84 | 83 | ||
| 85 | char **afc_get_dir_list(AFClient *client, char *dir); | 84 | char **afc_get_dir_list(AFClient *client, const char *dir); |
| 86 | AFCFile *afc_get_file_info(AFClient *client, char *path); | 85 | AFCFile *afc_get_file_info(AFClient *client, const char *path); |
| 87 | AFCFile *afc_open_file(AFClient *client, const char *filename, uint32 file_mode); | 86 | AFCFile *afc_open_file(AFClient *client, const char *filename, uint32 file_mode); |
| 88 | void afc_close_file(AFClient *client, AFCFile *file); | 87 | void afc_close_file(AFClient *client, AFCFile *file); |
| 89 | int afc_read_file(AFClient *client, AFCFile *file, char *data, int length); | 88 | int afc_read_file(AFClient *client, AFCFile *file, char *data, int length); |
| 90 | int afc_write_file(AFClient *client, AFCFile *file, char *data, int length); | 89 | int afc_write_file(AFClient *client, AFCFile *file, const char *data, int length); |
| 91 | int afc_delete_file(AFClient *client, const char *path); | 90 | int afc_delete_file(AFClient *client, const char *path); |
| 92 | int afc_rename_file(AFClient *client, const char *from, const char *to); | 91 | int afc_rename_file(AFClient *client, const char *from, const char *to); |
diff --git a/src/ifuse.c b/src/ifuse.c index e4d14e5..900bb17 100644 --- a/src/ifuse.c +++ b/src/ifuse.c | |||
| @@ -155,9 +155,10 @@ void *ifuse_init(struct fuse_conn_info *conn) { | |||
| 155 | return afc; | 155 | return afc; |
| 156 | } | 156 | } |
| 157 | 157 | ||
| 158 | void ifuse_cleanup(AFClient *afc) { | 158 | void ifuse_cleanup(void *data) { |
| 159 | AFClient *afc = (AFClient *)data; | ||
| 159 | if (afc) { | 160 | if (afc) { |
| 160 | iPhone *phone = afc->phone; | 161 | iPhone *phone = afc->connection->phone; |
| 161 | afc_disconnect(afc); | 162 | afc_disconnect(afc); |
| 162 | free_iPhone(phone); | 163 | free_iPhone(phone); |
| 163 | } | 164 | } |
diff --git a/src/iphone.c b/src/iphone.c index e4acea9..aa9687c 100644 --- a/src/iphone.c +++ b/src/iphone.c | |||
| @@ -171,10 +171,11 @@ int send_to_phone(iPhone *phone, char *data, int datalen) { | |||
| 171 | int recv_from_phone(iPhone *phone, char *data, int datalen) { | 171 | int recv_from_phone(iPhone *phone, char *data, int datalen) { |
| 172 | if (!phone) return -1; | 172 | if (!phone) return -1; |
| 173 | int bytes = 0; | 173 | int bytes = 0; |
| 174 | if (debug) printf("recv_from_phone(): attempting to receive %i bytes\n", datalen); | ||
| 174 | bytes = usb_bulk_read(phone->device, BULKIN, data, datalen, 3500); | 175 | bytes = usb_bulk_read(phone->device, BULKIN, data, datalen, 3500); |
| 175 | if(bytes < 0) | 176 | if(bytes < 0) |
| 176 | { | 177 | { |
| 177 | if(debug) printf("recv_from_iphone(): libusb gave me the error %d: %s (%s)\n", bytes, usb_strerror(), strerror(-bytes)); | 178 | if(debug) printf("recv_from_phone(): libusb gave me the error %d: %s (%s)\n", bytes, usb_strerror(), strerror(-bytes)); |
| 178 | return -1; | 179 | return -1; |
| 179 | } | 180 | } |
| 180 | return bytes; | 181 | return bytes; |
diff --git a/src/lockdown.c b/src/lockdown.c index 7fd3aa6..4fd8a66 100644 --- a/src/lockdown.c +++ b/src/lockdown.c | |||
| @@ -39,7 +39,6 @@ lockdownd_client *new_lockdownd_client(iPhone *phone) { | |||
| 39 | 39 | ||
| 40 | control->ssl_session = (gnutls_session_t*)malloc(sizeof(gnutls_session_t)); | 40 | control->ssl_session = (gnutls_session_t*)malloc(sizeof(gnutls_session_t)); |
| 41 | control->in_SSL = 0; | 41 | control->in_SSL = 0; |
| 42 | control->iphone = phone; | ||
| 43 | control->gtls_buffer_hack_len = 0; | 42 | control->gtls_buffer_hack_len = 0; |
| 44 | return control; | 43 | return control; |
| 45 | } | 44 | } |
| @@ -47,7 +46,7 @@ lockdownd_client *new_lockdownd_client(iPhone *phone) { | |||
| 47 | void lockdown_close(lockdownd_client *control) { | 46 | void lockdown_close(lockdownd_client *control) { |
| 48 | if (!control) return; | 47 | if (!control) return; |
| 49 | if (control->connection) { | 48 | if (control->connection) { |
| 50 | mux_close_connection(control->iphone, control->connection); | 49 | mux_close_connection(control->connection); |
| 51 | } | 50 | } |
| 52 | 51 | ||
| 53 | if (control->ssl_session) free(control->ssl_session); | 52 | if (control->ssl_session) free(control->ssl_session); |
| @@ -56,21 +55,23 @@ void lockdown_close(lockdownd_client *control) { | |||
| 56 | 55 | ||
| 57 | 56 | ||
| 58 | int lockdownd_recv(lockdownd_client *control, char **dump_data) { | 57 | int lockdownd_recv(lockdownd_client *control, char **dump_data) { |
| 58 | if (!control) return 0; | ||
| 59 | char *receive; | 59 | char *receive; |
| 60 | uint32 datalen = 0, bytes = 0; | 60 | uint32 datalen = 0, bytes = 0; |
| 61 | 61 | ||
| 62 | if (!control->in_SSL) bytes = mux_recv(control->iphone, control->connection, &datalen, sizeof(datalen)); | 62 | if (!control->in_SSL) bytes = mux_recv(control->connection, (char *)&datalen, sizeof(datalen)); |
| 63 | else bytes = gnutls_record_recv(*control->ssl_session, &datalen, sizeof(datalen)); | 63 | else bytes = gnutls_record_recv(*control->ssl_session, &datalen, sizeof(datalen)); |
| 64 | datalen = ntohl(datalen); | 64 | datalen = ntohl(datalen); |
| 65 | 65 | ||
| 66 | receive = (char*)malloc(sizeof(char) * datalen); | 66 | receive = (char*)malloc(sizeof(char) * datalen); |
| 67 | if (!control->in_SSL) bytes = mux_recv(control->iphone, control->connection, receive, datalen); | 67 | if (!control->in_SSL) bytes = mux_recv(control->connection, receive, datalen); |
| 68 | else bytes = gnutls_record_recv(*control->ssl_session, receive, datalen); | 68 | else bytes = gnutls_record_recv(*control->ssl_session, receive, datalen); |
| 69 | *dump_data = receive; | 69 | *dump_data = receive; |
| 70 | return bytes; | 70 | return bytes; |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | int lockdownd_send(lockdownd_client *control, char *raw_data, uint32 length) { | 73 | int lockdownd_send(lockdownd_client *control, char *raw_data, uint32 length) { |
| 74 | if (!control) return 0; | ||
| 74 | char *real_query; | 75 | char *real_query; |
| 75 | int bytes; | 76 | int bytes; |
| 76 | 77 | ||
| @@ -78,29 +79,39 @@ int lockdownd_send(lockdownd_client *control, char *raw_data, uint32 length) { | |||
| 78 | length = htonl(length); | 79 | length = htonl(length); |
| 79 | memcpy(real_query, &length, sizeof(length)); | 80 | memcpy(real_query, &length, sizeof(length)); |
| 80 | memcpy(real_query+4, raw_data, ntohl(length)); | 81 | memcpy(real_query+4, raw_data, ntohl(length)); |
| 81 | if (!control->in_SSL) bytes = mux_send(control->iphone, control->connection, real_query, ntohl(length)+sizeof(length)); | 82 | if (debug) { |
| 83 | printf("lockdownd_send(): made the query, sending it along\n"); | ||
| 84 | FILE *packet = fopen("grpkt", "w"); | ||
| 85 | fwrite(real_query, 1, ntohl(length)+4, packet); | ||
| 86 | fclose(packet); | ||
| 87 | packet = NULL; | ||
| 88 | } | ||
| 89 | |||
| 90 | if (!control->in_SSL) bytes = mux_send(control->connection, real_query, ntohl(length)+sizeof(length)); | ||
| 82 | else gnutls_record_send(*control->ssl_session, real_query, ntohl(length)+sizeof(length)); | 91 | else gnutls_record_send(*control->ssl_session, real_query, ntohl(length)+sizeof(length)); |
| 92 | if (debug) printf("lockdownd_send(): sent it!\n"); | ||
| 93 | free(real_query); | ||
| 83 | return bytes; | 94 | return bytes; |
| 84 | } | 95 | } |
| 85 | 96 | ||
| 86 | int lockdownd_hello(lockdownd_client *control) { | 97 | int lockdownd_hello(lockdownd_client *control) { |
| 98 | if (!control) return 0; | ||
| 87 | xmlDocPtr plist = new_plist(); | 99 | xmlDocPtr plist = new_plist(); |
| 88 | xmlNode *dict, *key; | 100 | xmlNode *dict, *key; |
| 89 | char **dictionary; | 101 | char **dictionary; |
| 90 | int bytes = 0, i = 0; | 102 | int bytes = 0, i = 0; |
| 91 | 103 | ||
| 104 | if (debug) printf("lockdownd_hello() called\n"); | ||
| 92 | dict = add_child_to_plist(plist, "dict", "\n", NULL, 0); | 105 | dict = add_child_to_plist(plist, "dict", "\n", NULL, 0); |
| 93 | key = add_key_str_dict_element(plist, dict, "Request", "QueryType", 1); | 106 | key = add_key_str_dict_element(plist, dict, "Request", "QueryType", 1); |
| 94 | char *XML_content; | 107 | char *XML_content; |
| 95 | uint32 length; | 108 | uint32 length; |
| 96 | 109 | ||
| 97 | xmlDocDumpMemory(plist, &XML_content, &length); | 110 | xmlDocDumpMemory(plist, (xmlChar **)&XML_content, &length); |
| 98 | |||
| 99 | bytes = lockdownd_send(control, XML_content, length); | 111 | bytes = lockdownd_send(control, XML_content, length); |
| 100 | 112 | ||
| 101 | xmlFree(XML_content); | 113 | xmlFree(XML_content); |
| 102 | xmlFreeDoc(plist); plist = NULL; | 114 | xmlFreeDoc(plist); plist = NULL; |
| 103 | |||
| 104 | bytes = lockdownd_recv(control, &XML_content); | 115 | bytes = lockdownd_recv(control, &XML_content); |
| 105 | 116 | ||
| 106 | plist = xmlReadMemory(XML_content, bytes, NULL, NULL, 0); | 117 | plist = xmlReadMemory(XML_content, bytes, NULL, NULL, 0); |
| @@ -118,6 +129,7 @@ int lockdownd_hello(lockdownd_client *control) { | |||
| 118 | for (i = 0; strcmp(dictionary[i], ""); i+=2) { | 129 | for (i = 0; strcmp(dictionary[i], ""); i+=2) { |
| 119 | if (!strcmp(dictionary[i], "Result") && !strcmp(dictionary[i+1], "Success")) { | 130 | if (!strcmp(dictionary[i], "Result") && !strcmp(dictionary[i+1], "Success")) { |
| 120 | free_dictionary(dictionary); | 131 | free_dictionary(dictionary); |
| 132 | if (debug) printf("lockdownd_hello(): success\n"); | ||
| 121 | return 1; | 133 | return 1; |
| 122 | } | 134 | } |
| 123 | } | 135 | } |
| @@ -147,7 +159,7 @@ int lockdownd_start_SSL_session(lockdownd_client *control, const char *HostID) { | |||
| 147 | return 0; | 159 | return 0; |
| 148 | } | 160 | } |
| 149 | 161 | ||
| 150 | xmlDocDumpMemory(plist, &what2send, &len); | 162 | xmlDocDumpMemory(plist, (xmlChar **)&what2send, &len); |
| 151 | bytes = lockdownd_send(control, what2send, len); | 163 | bytes = lockdownd_send(control, what2send, len); |
| 152 | 164 | ||
| 153 | xmlFree(what2send); | 165 | xmlFree(what2send); |
| @@ -239,7 +251,7 @@ ssize_t lockdownd_secuwrite(gnutls_transport_ptr_t transport, char *buffer, size | |||
| 239 | control = (lockdownd_client*)transport; | 251 | control = (lockdownd_client*)transport; |
| 240 | if (debug) printf("lockdownd_secuwrite() called\n"); | 252 | if (debug) printf("lockdownd_secuwrite() called\n"); |
| 241 | if (debug) printf("pre-send\nlength = %i\n", length); | 253 | if (debug) printf("pre-send\nlength = %i\n", length); |
| 242 | bytes = mux_send(control->iphone, control->connection, buffer, length); | 254 | bytes = mux_send(control->connection, buffer, length); |
| 243 | if (debug) printf("post-send\nsent %i bytes\n", bytes); | 255 | if (debug) printf("post-send\nsent %i bytes\n", bytes); |
| 244 | if (debug) { | 256 | if (debug) { |
| 245 | FILE *my_ssl_packet = fopen("sslpacketwrite.out", "w+"); | 257 | FILE *my_ssl_packet = fopen("sslpacketwrite.out", "w+"); |
| @@ -289,7 +301,7 @@ ssize_t lockdownd_securead(gnutls_transport_ptr_t transport, char *buffer, size_ | |||
| 289 | char *recv_buffer = (char*)malloc(sizeof(char) * (length * 1000)); // ensuring nothing stupid happens | 301 | char *recv_buffer = (char*)malloc(sizeof(char) * (length * 1000)); // ensuring nothing stupid happens |
| 290 | 302 | ||
| 291 | if (debug) printf("pre-read\nclient wants %i bytes\n", length); | 303 | if (debug) printf("pre-read\nclient wants %i bytes\n", length); |
| 292 | bytes = mux_recv(control->iphone, control->connection, recv_buffer, (length * 1000)); | 304 | bytes = mux_recv(control->connection, recv_buffer, (length * 1000)); |
| 293 | if (debug) printf("post-read\nwe got %i bytes\n", bytes); | 305 | if (debug) printf("post-read\nwe got %i bytes\n", bytes); |
| 294 | if (debug && bytes < 0) { | 306 | if (debug && bytes < 0) { |
| 295 | printf("lockdownd_securead(): uh oh\n"); | 307 | printf("lockdownd_securead(): uh oh\n"); |
| @@ -339,7 +351,7 @@ int lockdownd_start_service(lockdownd_client *control, const char *service) { | |||
| 339 | key = add_key_str_dict_element(plist, dict, "Service", service, 1); | 351 | key = add_key_str_dict_element(plist, dict, "Service", service, 1); |
| 340 | if (!key) { xmlFreeDoc(plist); return 0; } | 352 | if (!key) { xmlFreeDoc(plist); return 0; } |
| 341 | 353 | ||
| 342 | xmlDocDumpMemory(plist, &XML_query, &length); | 354 | xmlDocDumpMemory(plist, (xmlChar **)&XML_query, &length); |
| 343 | 355 | ||
| 344 | lockdownd_send(control, XML_query, length); | 356 | lockdownd_send(control, XML_query, length); |
| 345 | free(XML_query); | 357 | free(XML_query); |
diff --git a/src/lockdown.h b/src/lockdown.h index 874afb9..4abfe18 100644 --- a/src/lockdown.h +++ b/src/lockdown.h | |||
| @@ -28,9 +28,8 @@ | |||
| 28 | #include <string.h> | 28 | #include <string.h> |
| 29 | 29 | ||
| 30 | typedef struct { | 30 | typedef struct { |
| 31 | usbmux_tcp_header *connection; | 31 | usbmux_connection *connection; |
| 32 | gnutls_session_t *ssl_session; | 32 | gnutls_session_t *ssl_session; |
| 33 | iPhone *iphone; | ||
| 34 | int in_SSL; | 33 | int in_SSL; |
| 35 | char *gtls_buffer_hack; | 34 | char *gtls_buffer_hack; |
| 36 | int gtls_buffer_hack_len; | 35 | int gtls_buffer_hack_len; |
diff --git a/src/plist.h b/src/plist.h index 7b72456..3d1edda 100644 --- a/src/plist.h +++ b/src/plist.h | |||
| @@ -29,5 +29,6 @@ xmlNode *add_key_str_dict_element(xmlDocPtr plist, xmlNode *dict, const char *ke | |||
| 29 | xmlNode *add_child_to_plist(xmlDocPtr plist, const char *name, const char *content, xmlNode *to_node, int depth); | 29 | xmlNode *add_child_to_plist(xmlDocPtr plist, const char *name, const char *content, xmlNode *to_node, int depth); |
| 30 | void free_plist(xmlDocPtr plist); | 30 | void free_plist(xmlDocPtr plist); |
| 31 | xmlDocPtr new_plist(); | 31 | xmlDocPtr new_plist(); |
| 32 | char **read_dict_element_strings(xmlNode *dict); | ||
| 32 | void free_dictionary(char **dictionary); | 33 | void free_dictionary(char **dictionary); |
| 33 | #endif | 34 | #endif |
diff --git a/src/usbmux.c b/src/usbmux.c index bdeea09..043f8af 100644 --- a/src/usbmux.c +++ b/src/usbmux.c | |||
| @@ -29,6 +29,9 @@ | |||
| 29 | 29 | ||
| 30 | extern int debug; | 30 | extern int debug; |
| 31 | 31 | ||
| 32 | static usbmux_connection **connlist = NULL; | ||
| 33 | static int connections = 0; | ||
| 34 | |||
| 32 | usbmux_tcp_header *new_mux_packet(uint16 s_port, uint16 d_port) { | 35 | usbmux_tcp_header *new_mux_packet(uint16 s_port, uint16 d_port) { |
| 33 | usbmux_tcp_header *conn = (usbmux_tcp_header*)malloc(sizeof(usbmux_tcp_header)); | 36 | usbmux_tcp_header *conn = (usbmux_tcp_header*)malloc(sizeof(usbmux_tcp_header)); |
| 34 | conn->type = htonl(6); | 37 | conn->type = htonl(6); |
| @@ -54,6 +57,47 @@ usbmux_version_header *version_header() { | |||
| 54 | return version; | 57 | return version; |
| 55 | } | 58 | } |
| 56 | 59 | ||
| 60 | |||
| 61 | // Maintenance functions. | ||
| 62 | |||
| 63 | /* delete_connection(connection) | ||
| 64 | * connection: the connection to delete from the tracking list. | ||
| 65 | * Removes a connection from the list of connections made. | ||
| 66 | * The list of connections is necessary for buffering. | ||
| 67 | */ | ||
| 68 | |||
| 69 | void delete_connection(usbmux_connection *connection) { | ||
| 70 | usbmux_connection **newlist = (usbmux_connection**)malloc(sizeof(usbmux_connection*) * (connections - 1)); | ||
| 71 | int i = 0, j = 0; | ||
| 72 | for (i = 0; i < connections; i++) { | ||
| 73 | if (connlist[i] == connection) continue; | ||
| 74 | else { | ||
| 75 | newlist[j] = connlist[i]; | ||
| 76 | j++; | ||
| 77 | } | ||
| 78 | } | ||
| 79 | free(connlist); | ||
| 80 | connlist = newlist; | ||
| 81 | connections--; | ||
| 82 | if (connection->recv_buffer) free(connection->recv_buffer); | ||
| 83 | if (connection->header) free(connection->header); | ||
| 84 | connection->r_len = 0; | ||
| 85 | free(connection); | ||
| 86 | } | ||
| 87 | |||
| 88 | /* add_connection(connection) | ||
| 89 | * connection: the connection to add to the global list of connections. | ||
| 90 | * Adds a connection to the list of connections made. | ||
| 91 | * The connection list is necessary for buffering. | ||
| 92 | */ | ||
| 93 | |||
| 94 | void add_connection(usbmux_connection *connection) { | ||
| 95 | usbmux_connection **newlist = (usbmux_connection**)realloc(connlist, sizeof(usbmux_connection*) * (connections+1)); | ||
| 96 | newlist[connections] = connection; | ||
| 97 | connlist = newlist; | ||
| 98 | connections++; | ||
| 99 | } | ||
| 100 | |||
| 57 | /* mux_connect(phone, s_port, d_port) | 101 | /* mux_connect(phone, s_port, d_port) |
| 58 | * This is a higher-level USBMuxTCP-type function. | 102 | * This is a higher-level USBMuxTCP-type function. |
| 59 | * phone: the iPhone to initialize a connection on. | 103 | * phone: the iPhone to initialize a connection on. |
| @@ -64,27 +108,33 @@ usbmux_version_header *version_header() { | |||
| 64 | * Returns a mux TCP header for the connection which is used for tracking and data transfer. | 108 | * Returns a mux TCP header for the connection which is used for tracking and data transfer. |
| 65 | */ | 109 | */ |
| 66 | 110 | ||
| 67 | usbmux_tcp_header *mux_connect(iPhone *phone, uint16 s_port, uint16 d_port) { | 111 | usbmux_connection *mux_connect(iPhone *phone, uint16 s_port, uint16 d_port) { |
| 68 | if (!phone || !s_port || !d_port) return NULL; | 112 | if (!phone || !s_port || !d_port) return NULL; |
| 69 | int bytes = 0; | 113 | int bytes = 0; |
| 70 | // Initialize connection stuff | 114 | // Initialize connection stuff |
| 71 | usbmux_tcp_header *new_connection; | 115 | usbmux_connection *new_connection = (usbmux_connection*)malloc(sizeof(usbmux_connection)); |
| 72 | new_connection = new_mux_packet(s_port, d_port); | 116 | new_connection->header = new_mux_packet(s_port, d_port); |
| 73 | usbmux_tcp_header *response; | 117 | usbmux_tcp_header *response; |
| 74 | response = (usbmux_tcp_header*)malloc(sizeof(usbmux_tcp_header)); | 118 | response = (usbmux_tcp_header*)malloc(sizeof(usbmux_tcp_header)); |
| 75 | // blargg | 119 | // blargg |
| 76 | if (new_connection) { | 120 | if (new_connection && new_connection->header) { |
| 77 | new_connection->tcp_flags = 0x02; | 121 | new_connection->header->tcp_flags = 0x02; |
| 78 | new_connection->length = htonl(new_connection->length); | 122 | new_connection->header->length = htonl(new_connection->header->length); |
| 79 | new_connection->length16 = htons(new_connection->length16); | 123 | new_connection->header->length16 = htons(new_connection->header->length16); |
| 80 | 124 | ||
| 81 | if (send_to_phone(phone, (char*)new_connection, sizeof(*new_connection)) >= 0) { | 125 | if (send_to_phone(phone, (char*)new_connection->header, sizeof(usbmux_tcp_header)) >= 0) { |
| 82 | bytes = recv_from_phone(phone, (char*)response, sizeof(*response)); | 126 | bytes = recv_from_phone(phone, (char*)response, sizeof(*response)); |
| 83 | if (response->tcp_flags != 0x12) return NULL; | 127 | if (response->tcp_flags != 0x12) return NULL; |
| 84 | else { | 128 | else { |
| 85 | new_connection->tcp_flags = 0x10; | 129 | if (debug) printf("mux_connect: connection success\n"); |
| 86 | new_connection->scnt = 1; | 130 | new_connection->header->tcp_flags = 0x10; |
| 87 | new_connection->ocnt = 1; | 131 | new_connection->header->scnt = 1; |
| 132 | new_connection->header->ocnt = 1; | ||
| 133 | add_connection(new_connection); | ||
| 134 | new_connection->phone = phone; | ||
| 135 | new_connection->recv_buffer = NULL; | ||
| 136 | new_connection->r_len = 0; | ||
| 137 | add_connection(new_connection); | ||
| 88 | return new_connection; | 138 | return new_connection; |
| 89 | } | 139 | } |
| 90 | } else { | 140 | } else { |
| @@ -103,23 +153,24 @@ usbmux_tcp_header *mux_connect(iPhone *phone, uint16 s_port, uint16 d_port) { | |||
| 103 | * | 153 | * |
| 104 | * Doesn't return anything; WILL FREE THE CONNECTION'S MEMORY!!! | 154 | * Doesn't return anything; WILL FREE THE CONNECTION'S MEMORY!!! |
| 105 | */ | 155 | */ |
| 106 | void mux_close_connection(iPhone *phone, usbmux_tcp_header *connection) { | 156 | |
| 107 | if (!phone || !connection) return; | 157 | void mux_close_connection(usbmux_connection *connection) { |
| 158 | if (!connection || !connection->phone) return; | ||
| 108 | 159 | ||
| 109 | connection->tcp_flags = 0x04; | 160 | connection->header->tcp_flags = 0x04; |
| 110 | connection->scnt = htonl(connection->scnt); | 161 | connection->header->scnt = htonl(connection->header->scnt); |
| 111 | connection->ocnt = htonl(connection->ocnt); | 162 | connection->header->ocnt = htonl(connection->header->ocnt); |
| 112 | int bytes = 0; | 163 | int bytes = 0; |
| 113 | 164 | ||
| 114 | bytes = usb_bulk_write(phone->device, BULKOUT, (char*)connection, sizeof(*connection), 800); | 165 | bytes = usb_bulk_write(connection->phone->device, BULKOUT, (char*)connection->header, sizeof(usbmux_tcp_header), 800); |
| 115 | if(debug && bytes < 0) | 166 | if(debug && bytes < 0) |
| 116 | printf("mux_close_connection(): when writing, libusb gave me the error: %s\n", usb_strerror()); | 167 | printf("mux_close_connection(): when writing, libusb gave me the error: %s\n", usb_strerror()); |
| 117 | 168 | ||
| 118 | bytes = usb_bulk_read(phone->device, BULKIN, (char*)connection, sizeof(*connection), 800); | 169 | bytes = usb_bulk_read(connection->phone->device, BULKIN, (char*)connection->header, sizeof(usbmux_tcp_header), 800); |
| 119 | if(debug && bytes < 0) | 170 | if(debug && bytes < 0) |
| 120 | printf("get_iPhone(): when reading, libusb gave me the error: %s\n", usb_strerror()); | 171 | printf("get_iPhone(): when reading, libusb gave me the error: %s\n", usb_strerror()); |
| 121 | 172 | ||
| 122 | free(connection); | 173 | delete_connection(connection); |
| 123 | } | 174 | } |
| 124 | 175 | ||
| 125 | /* mux_send(phone, connection, data, datalen) | 176 | /* mux_send(phone, connection, data, datalen) |
| @@ -131,40 +182,46 @@ void mux_close_connection(iPhone *phone, usbmux_tcp_header *connection) { | |||
| 131 | * | 182 | * |
| 132 | * Returns number of bytes sent, minus the header (28), or -1 on error. | 183 | * Returns number of bytes sent, minus the header (28), or -1 on error. |
| 133 | */ | 184 | */ |
| 134 | int mux_send(iPhone *phone, usbmux_tcp_header *connection, char *data, uint32 datalen) { | 185 | int mux_send(usbmux_connection *connection, const char *data, uint32 datalen) { |
| 135 | if (!phone || !connection || !data || datalen == 0) return -1; | 186 | if (!connection->phone || !connection || !data || datalen == 0) return -1; |
| 136 | // connection->scnt and connection->ocnt should already be in host notation... | 187 | // connection->scnt and connection->ocnt should already be in host notation... |
| 137 | // we don't need to change them juuuust yet. | 188 | // we don't need to change them juuuust yet. |
| 138 | int bytes = 0; | 189 | int bytes = 0; |
| 139 | if (debug) printf("mux_send(): client wants to send %i bytes\n", datalen); | 190 | if (debug) printf("mux_send(): client wants to send %i bytes\n", datalen); |
| 140 | char *buffer = (char*)malloc(sizeof(*connection) + datalen + 2); // allow 2 bytes of safety padding | 191 | char *buffer = (char*)malloc(sizeof(usbmux_tcp_header) + datalen + 2); // allow 2 bytes of safety padding |
| 141 | // Set the length and pre-emptively htonl/htons it | 192 | // Set the length and pre-emptively htonl/htons it |
| 142 | connection->length = htonl(sizeof(*connection) + datalen); | 193 | connection->header->length = htonl(sizeof(usbmux_tcp_header) + datalen); |
| 143 | connection->length16 = htons(sizeof(*connection) + datalen); | 194 | connection->header->length16 = htons(sizeof(usbmux_tcp_header) + datalen); |
| 144 | 195 | ||
| 145 | // Put scnt and ocnt into big-endian notation | 196 | // Put scnt and ocnt into big-endian notation |
| 146 | connection->scnt = htonl(connection->scnt); | 197 | connection->header->scnt = htonl(connection->header->scnt); |
| 147 | connection->ocnt = htonl(connection->ocnt); | 198 | connection->header->ocnt = htonl(connection->header->ocnt); |
| 148 | // Concatenation of stuff in the buffer. | 199 | // Concatenation of stuff in the buffer. |
| 149 | memcpy(buffer, connection, sizeof(*connection)); | 200 | memcpy(buffer, connection->header, sizeof(usbmux_tcp_header)); |
| 150 | memcpy(buffer+sizeof(*connection)/*+sizeof(datalen)*/, data, datalen); | 201 | memcpy(buffer+sizeof(usbmux_tcp_header), data, datalen); |
| 151 | 202 | ||
| 152 | // We have a buffer full of data, we should now send it to the phone. | 203 | // We have a buffer full of data, we should now send it to the phone. |
| 153 | if (debug) printf("actually sending %i bytes of data at %x\n", sizeof(*connection)+datalen, buffer); | 204 | if (debug) printf("actually sending %i bytes of data at %x\n", sizeof(usbmux_tcp_header)+datalen, buffer); |
| 154 | 205 | ||
| 155 | 206 | ||
| 156 | bytes = send_to_phone(phone, buffer, sizeof(*connection)+datalen); | 207 | bytes = send_to_phone(connection->phone, buffer, sizeof(usbmux_tcp_header)+datalen); |
| 157 | 208 | if (debug) printf("mux_send: sent %i bytes!\n", bytes); | |
| 158 | // Now that we've sent it off, we can clean up after our sloppy selves. | 209 | // Now that we've sent it off, we can clean up after our sloppy selves. |
| 159 | free(buffer); | 210 | if (debug) { |
| 211 | FILE *packet = fopen("packet", "a+"); | ||
| 212 | fwrite(buffer, 1, bytes, packet); | ||
| 213 | fclose(packet); | ||
| 214 | printf("\n"); | ||
| 215 | } | ||
| 160 | 216 | ||
| 217 | if (buffer) free(buffer); | ||
| 161 | // Re-calculate scnt and ocnt | 218 | // Re-calculate scnt and ocnt |
| 162 | connection->scnt = ntohl(connection->scnt) + datalen; | 219 | connection->header->scnt = ntohl(connection->header->scnt) + datalen; |
| 163 | connection->ocnt = ntohl(connection->ocnt); | 220 | connection->header->ocnt = ntohl(connection->header->ocnt); |
| 164 | 221 | ||
| 165 | // Revert lengths | 222 | // Revert lengths |
| 166 | connection->length = ntohl(connection->length); | 223 | connection->header->length = ntohl(connection->header->length); |
| 167 | connection->length16 = ntohs(connection->length16); | 224 | connection->header->length16 = ntohs(connection->header->length16); |
| 168 | 225 | ||
| 169 | // Now return the bytes. | 226 | // Now return the bytes. |
| 170 | if (bytes < sizeof(*connection)+datalen) { | 227 | if (bytes < sizeof(*connection)+datalen) { |
| @@ -186,39 +243,103 @@ int mux_send(iPhone *phone, usbmux_tcp_header *connection, char *data, uint32 da | |||
| 186 | * Returns: how many bytes were read, or -1 if something bad happens. | 243 | * Returns: how many bytes were read, or -1 if something bad happens. |
| 187 | */ | 244 | */ |
| 188 | 245 | ||
| 189 | int mux_recv(iPhone *phone, usbmux_tcp_header *connection, char *data, uint32 datalen) { | 246 | int mux_recv(usbmux_connection *connection, char *data, uint32 datalen) { |
| 190 | char *buffer = (char*)malloc(sizeof(*connection) + sizeof(datalen) + datalen); | 247 | /* |
| 191 | int bytes = 0, my_datalen = 0; | 248 | * Order of operation: |
| 249 | * 1.) Check if the connection has a pre-received buffer. | ||
| 250 | * 2.) If so, fill data with the buffer, as much as needed. | ||
| 251 | * a.) Return quickly if the buffer has enough | ||
| 252 | * b.) If the buffer is only part of the datalen, get the rest of datalen (and if we can't, just return) | ||
| 253 | * 3.) If not, receive directly from the phone. | ||
| 254 | * a.) Check incoming packet's ports. If proper, follow proper buffering and receiving operation. | ||
| 255 | * b.) If not, find the connection the ports belong to and fill that connection's buffer, then return mux_recv with the same args to try again. | ||
| 256 | */ | ||
| 192 | if (debug) printf("mux_recv: datalen == %i\n", datalen); | 257 | if (debug) printf("mux_recv: datalen == %i\n", datalen); |
| 193 | bytes = recv_from_phone(phone, buffer, sizeof(*connection) + datalen); | 258 | int bytes = 0, i = 0, complex = 0, offset = 0; |
| 194 | if (debug) printf("mux_recv: bytes == %i\n", bytes); | 259 | char *buffer = NULL; |
| 195 | if (bytes < datalen) { | 260 | usbmux_tcp_header *header = NULL; |
| 196 | if (bytes < 28) { | 261 | |
| 197 | // if they didn't do that annoying thing, something else mighta happened. | 262 | if (connection->recv_buffer) { |
| 198 | if (debug) printf("mux_recv: bytes too low anyway!\n"); | 263 | if (connection->r_len >= datalen) { |
| 199 | free(buffer); | 264 | memcpy(data, connection->recv_buffer, datalen); |
| 200 | return -1; | 265 | if (connection->r_len == datalen) { |
| 201 | } else if (bytes == 28) { // no data... | 266 | // reset everything |
| 202 | free(buffer); | 267 | free(connection->recv_buffer); |
| 203 | return 0; | 268 | connection->r_len = 0; |
| 204 | } else { // bytes > 28 | 269 | connection->recv_buffer = NULL; |
| 205 | my_datalen = ntohl(buffer[4]) - 28; | 270 | } else { |
| 206 | connection->ocnt += my_datalen; | 271 | buffer = (char*)malloc(sizeof(char) * (connection->r_len - datalen)); |
| 207 | memcpy(data, buffer+28, bytes - 28); | 272 | memcpy(buffer, connection->recv_buffer+datalen, (connection->r_len - datalen)); |
| 208 | free(buffer); | 273 | connection->r_len -= datalen; |
| 209 | if (debug) printf("mux_recv: bytes received: %i\n", bytes - 28); | 274 | free(connection->recv_buffer); |
| 210 | return bytes - 28; | 275 | connection->recv_buffer = buffer; |
| 276 | } | ||
| 277 | |||
| 278 | // Since we were able to fill the data straight from our buffer, we can just return datalen. See 2a above. | ||
| 279 | return datalen; | ||
| 280 | } else { | ||
| 281 | memcpy(data, connection->recv_buffer, connection->r_len); | ||
| 282 | free(connection->recv_buffer); // don't need to deal with anymore, but... | ||
| 283 | offset = connection->r_len; // see #2b, above | ||
| 284 | connection->r_len = 0; | ||
| 211 | } | 285 | } |
| 212 | } else {// all's good, they didn't do anything bonky. | 286 | } // End of what to do if we have a pre-buffer. See #1 and #2 above. |
| 213 | my_datalen = ntohl(buffer[4]) - 28; | 287 | |
| 214 | connection->ocnt += my_datalen; | 288 | buffer = (char*)malloc(sizeof(char) * 131072); // make sure we get enough ;) |
| 215 | if (bytes == (datalen+28)) memcpy(data, buffer+28, datalen); | 289 | |
| 216 | else if (bytes == datalen) memcpy(data, buffer+28, datalen-28); | 290 | // See #3. |
| 291 | bytes = recv_from_phone(connection->phone, buffer, 131072); | ||
| 292 | if (bytes < 28) { | ||
| 293 | free(buffer); | ||
| 294 | if (debug) printf("mux_recv: Did not even get the header.\n"); | ||
| 295 | return -1; | ||
| 296 | } | ||
| 297 | |||
| 298 | header = (usbmux_tcp_header*)buffer; | ||
| 299 | if (header->sport != connection->header->dport || header->dport != connection->header->sport) { | ||
| 300 | // Ooooops -- we got someone else's packet. | ||
| 301 | // We gotta stick it in their buffer. (Take that any old way you want ;) ) | ||
| 302 | for (i = 0; i < connections; i++) { | ||
| 303 | if (connlist[i]->header->sport == header->dport && connlist[i]->header->dport == header->sport) { | ||
| 304 | // we have a winner. | ||
| 305 | connlist[i]->r_len += bytes - 28; | ||
| 306 | connlist[i]->recv_buffer = (char*)realloc(connlist[i]->recv_buffer, sizeof(char) * connection->r_len); // grow their buffer | ||
| 307 | complex = connlist[i]->r_len - (bytes - 28); | ||
| 308 | memcpy(connlist[i]->recv_buffer+complex, buffer+28, bytes-28); // paste into their buffer | ||
| 309 | connlist[i]->header->ocnt += bytes-28; | ||
| 310 | } | ||
| 311 | } | ||
| 312 | // If it wasn't ours, it's been handled by this point... or forgotten. | ||
| 313 | // Free our buffer and continue. | ||
| 314 | free(buffer); | ||
| 315 | buffer = NULL; | ||
| 316 | return mux_recv(connection, data, datalen); // recurse back in to try again | ||
| 317 | } | ||
| 318 | |||
| 319 | // The packet was absolutely meant for us if it hits this point. | ||
| 320 | // The pre-buffer has been taken care of, so, again, if we're at this point we have to read from the phone. | ||
| 321 | |||
| 322 | if ((bytes-28) > datalen) { | ||
| 323 | // Copy what we need into the data, buffer the rest because we can. | ||
| 324 | memcpy(data+offset, buffer+28, datalen); // data+offset: see #2b, above | ||
| 325 | complex = connection->r_len + (bytes-28) - datalen; | ||
| 326 | connection->recv_buffer = (char*)realloc(connection->recv_buffer, (sizeof(char) * complex)); | ||
| 327 | connection->r_len = complex; | ||
| 328 | complex = connection->r_len - (bytes-28) - datalen; | ||
| 329 | memcpy(connection->recv_buffer+complex, buffer+28+datalen, (bytes-28) - datalen); | ||
| 330 | free(buffer); | ||
| 331 | connection->header->ocnt += bytes-28; | ||
| 332 | return datalen; | ||
| 333 | } else { | ||
| 334 | // Fill the data with what we have, and just return. | ||
| 335 | memcpy(data+offset, buffer+28, bytes-28); // data+offset: see #2b, above | ||
| 336 | connection->header->ocnt += bytes-28; | ||
| 217 | free(buffer); | 337 | free(buffer); |
| 218 | if (debug) printf("mux_recv: bytes received: %i\n", bytes - 28); | 338 | return (bytes-28); |
| 219 | return bytes - 28; | ||
| 220 | } | 339 | } |
| 221 | 340 | ||
| 222 | return bytes; | 341 | // If we get to this point, 'tis probably bad. |
| 342 | if (debug) printf("mux_recv: Heisenbug: bytes and datalen not matching up\n"); | ||
| 343 | return -1; | ||
| 223 | } | 344 | } |
| 224 | 345 | ||
diff --git a/src/usbmux.h b/src/usbmux.h index 7c17dd1..332dc8a 100644 --- a/src/usbmux.h +++ b/src/usbmux.h | |||
| @@ -43,6 +43,13 @@ typedef struct { | |||
| 43 | uint16 window, nullnull, length16; | 43 | uint16 window, nullnull, length16; |
| 44 | } usbmux_tcp_header; | 44 | } usbmux_tcp_header; |
| 45 | 45 | ||
| 46 | typedef struct { | ||
| 47 | usbmux_tcp_header *header; | ||
| 48 | iPhone *phone; | ||
| 49 | char *recv_buffer; | ||
| 50 | int r_len; | ||
| 51 | } usbmux_connection; | ||
| 52 | |||
| 46 | usbmux_tcp_header *new_mux_packet(uint16 s_port, uint16 d_port); | 53 | usbmux_tcp_header *new_mux_packet(uint16 s_port, uint16 d_port); |
| 47 | 54 | ||
| 48 | typedef struct { | 55 | typedef struct { |
| @@ -51,8 +58,10 @@ typedef struct { | |||
| 51 | 58 | ||
| 52 | usbmux_version_header *version_header(); | 59 | usbmux_version_header *version_header(); |
| 53 | 60 | ||
| 54 | usbmux_tcp_header *mux_connect(iPhone *phone, uint16 s_port, uint16 d_port); | 61 | usbmux_connection *mux_connect(iPhone *phone, uint16 s_port, uint16 d_port); |
| 55 | void mux_close_connection(iPhone *phone, usbmux_tcp_header *connection); | 62 | void mux_close_connection(usbmux_connection *connection); |
| 56 | int mux_send(iPhone *phone, usbmux_tcp_header *connection, char *data, uint32 datalen); | 63 | int mux_send(usbmux_connection *connection, const char *data, uint32 datalen); |
| 57 | int mux_recv(iPhone *phone, usbmux_tcp_header *connection, char *data, uint32 datalen); | 64 | int mux_recv(usbmux_connection *connection, char *data, uint32 datalen); |
| 65 | |||
| 66 | |||
| 58 | #endif | 67 | #endif |
diff --git a/src/userpref.c b/src/userpref.c index 366016c..27aded5 100644 --- a/src/userpref.c +++ b/src/userpref.c | |||
| @@ -20,6 +20,8 @@ | |||
| 20 | */ | 20 | */ |
| 21 | 21 | ||
| 22 | #include <glib.h> | 22 | #include <glib.h> |
| 23 | #include <stdio.h> | ||
| 24 | #include <string.h> | ||
| 23 | #include "userpref.h" | 25 | #include "userpref.h" |
| 24 | 26 | ||
| 25 | #define LIBIPHONE_CONF_DIR "libiphone" | 27 | #define LIBIPHONE_CONF_DIR "libiphone" |
