diff options
Diffstat (limited to 'src/usbmux.c')
-rw-r--r-- | src/usbmux.c | 170 |
1 files changed, 89 insertions, 81 deletions
diff --git a/src/usbmux.c b/src/usbmux.c index a4a859a..48cb963 100644 --- a/src/usbmux.c +++ b/src/usbmux.c @@ -29,8 +29,8 @@ extern int debug; -static usbmux_connection **connlist = NULL; -static int connections = 0; +static iphone_umux_client_t *connlist = NULL; +static int clients = 0; /** Creates a USBMux packet for the given set of ports. * @@ -76,10 +76,10 @@ usbmux_version_header *version_header() { * * @param connection The connection to delete from the tracking list. */ -void delete_connection(usbmux_connection *connection) { - usbmux_connection **newlist = (usbmux_connection**)malloc(sizeof(usbmux_connection*) * (connections - 1)); +void delete_connection(iphone_umux_client_t connection) { + iphone_umux_client_t *newlist = (iphone_umux_client_t*)malloc(sizeof(iphone_umux_client_t) * (clients - 1)); int i = 0, j = 0; - for (i = 0; i < connections; i++) { + for (i = 0; i < clients; i++) { if (connlist[i] == connection) continue; else { newlist[j] = connlist[i]; @@ -88,7 +88,7 @@ void delete_connection(usbmux_connection *connection) { } free(connlist); connlist = newlist; - connections--; + clients--; if (connection->recv_buffer) free(connection->recv_buffer); if (connection->header) free(connection->header); connection->r_len = 0; @@ -101,59 +101,64 @@ void delete_connection(usbmux_connection *connection) { * @param connection The connection to add to the global list of connections. */ -void add_connection(usbmux_connection *connection) { - usbmux_connection **newlist = (usbmux_connection**)realloc(connlist, sizeof(usbmux_connection*) * (connections+1)); - newlist[connections] = connection; +void add_connection(iphone_umux_client_t connection) { + iphone_umux_client_t* newlist = (iphone_umux_client_t*)realloc(connlist, sizeof(iphone_umux_client_t) * (clients+1)); + newlist[clients] = connection; connlist = newlist; - connections++; + clients++; } /** Initializes a connection on phone, with source port s_port and destination port d_port * - * @param phone The iPhone to initialize a connection on. - * @param s_port The source port - * @param d_port The destination port -- 0xf27e for lockdownd. - * - * @return A mux TCP header for the connection which is used for tracking and data transfer. - */ -usbmux_connection *mux_connect(iphone_device_t phone, uint16 s_port, uint16 d_port) { - if (!phone || !s_port || !d_port) return NULL; + * @param device The iPhone to initialize a connection on. + * @param src_port The source port + * @param dst_port The destination port -- 0xf27e for lockdownd. + * @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 ){ + if (!device || !src_port || !dst_port) + return IPHONE_E_INVALID_ARG; + int bytes = 0; // Initialize connection stuff - usbmux_connection *new_connection = (usbmux_connection*)malloc(sizeof(usbmux_connection)); - new_connection->header = new_mux_packet(s_port, d_port); + iphone_umux_client_t new_connection = (iphone_umux_client_t)malloc(sizeof(struct iphone_umux_client_int)); + new_connection->header = new_mux_packet(src_port, dst_port); + // blargg if (new_connection && new_connection->header) { new_connection->header->tcp_flags = 0x02; new_connection->header->length = htonl(new_connection->header->length); new_connection->header->length16 = htons(new_connection->header->length16); - if (send_to_phone(phone, (char*)new_connection->header, sizeof(usbmux_tcp_header)) >= 0) { + if (send_to_phone(device, (char*)new_connection->header, sizeof(usbmux_tcp_header)) >= 0) { usbmux_tcp_header *response; response = (usbmux_tcp_header*)malloc(sizeof(usbmux_tcp_header)); - bytes = recv_from_phone(phone, (char*)response, sizeof(*response)); + bytes = recv_from_phone(device, (char*)response, sizeof(*response)); if (response->tcp_flags != 0x12) { free(response); - return NULL; + return IPHONE_E_UNKNOWN_ERROR; } else { free(response); + if (debug) printf("mux_connect: connection success\n"); new_connection->header->tcp_flags = 0x10; new_connection->header->scnt = 1; new_connection->header->ocnt = 1; - new_connection->phone = phone; + new_connection->phone = device; new_connection->recv_buffer = NULL; new_connection->r_len = 0; add_connection(new_connection); - return new_connection; + *client = new_connection; + return IPHONE_E_SUCCESS; } } else { - return NULL; + return IPHONE_E_NOT_ENOUGH_DATA; } } // if we get to this point it's probably bad - return NULL; + return IPHONE_E_UNKNOWN_ERROR; } /** Cleans up the given USBMux connection. @@ -161,56 +166,59 @@ usbmux_connection *mux_connect(iphone_device_t phone, uint16 s_port, uint16 d_po * * @param connection The connection to close. */ -void mux_close_connection(usbmux_connection *connection) { - if (!connection || !connection->phone) return; +void iphone_mux_free_client ( iphone_umux_client_t client ) { + if (!client || !client->phone) return; - connection->header->tcp_flags = 0x04; - connection->header->scnt = htonl(connection->header->scnt); - connection->header->ocnt = htonl(connection->header->ocnt); + client->header->tcp_flags = 0x04; + client->header->scnt = htonl(client->header->scnt); + client->header->ocnt = htonl(client->header->ocnt); int bytes = 0; - bytes = usb_bulk_write(connection->phone->device, BULKOUT, (char*)connection->header, sizeof(usbmux_tcp_header), 800); + bytes = usb_bulk_write(client->phone->device, BULKOUT, (char*)client->header, sizeof(usbmux_tcp_header), 800); if(debug && bytes < 0) printf("mux_close_connection(): when writing, libusb gave me the error: %s\n", usb_strerror()); - bytes = usb_bulk_read(connection->phone->device, BULKIN, (char*)connection->header, sizeof(usbmux_tcp_header), 800); + bytes = usb_bulk_read(client->phone->device, BULKIN, (char*)client->header, sizeof(usbmux_tcp_header), 800); if(debug && bytes < 0) printf("get_iPhone(): when reading, libusb gave me the error: %s\n", usb_strerror()); - delete_connection(connection); + delete_connection(client); } + /** Sends the given data over the selected connection. - * - * @param connection The connection we're sending data on. + * + * @param phone The iPhone to send to. + * @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. * * @return The number of bytes sent, minus the header (28), or -1 on error. */ -int mux_send(usbmux_connection *connection, const char *data, uint32 datalen) { - if (!connection->phone || !connection || !data || datalen == 0) return -1; - // connection->scnt and connection->ocnt should already be in host notation... + +int iphone_mux_send ( iphone_umux_client_t client, const char *data, uint32_t datalen ) { + if (!client->phone || !client || !data || datalen == 0) return -1; + // client->scnt and client->ocnt should already be in host notation... // we don't need to change them juuuust yet. int 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 - connection->header->length = htonl(sizeof(usbmux_tcp_header) + datalen); - connection->header->length16 = htons(sizeof(usbmux_tcp_header) + datalen); + client->header->length = htonl(sizeof(usbmux_tcp_header) + datalen); + client->header->length16 = htons(sizeof(usbmux_tcp_header) + datalen); // Put scnt and ocnt into big-endian notation - connection->header->scnt = htonl(connection->header->scnt); - connection->header->ocnt = htonl(connection->header->ocnt); + client->header->scnt = htonl(client->header->scnt); + client->header->ocnt = htonl(client->header->ocnt); // Concatenation of stuff in the buffer. - memcpy(buffer, connection->header, sizeof(usbmux_tcp_header)); + memcpy(buffer, client->header, sizeof(usbmux_tcp_header)); memcpy(buffer+sizeof(usbmux_tcp_header), data, datalen); // We have a buffer full of data, we should now send it to the phone. if (debug) printf("actually sending %zi bytes of data at %p\n", sizeof(usbmux_tcp_header)+datalen, buffer); - bytes = send_to_phone(connection->phone, buffer, sizeof(usbmux_tcp_header)+datalen); + bytes = send_to_phone(client->phone, buffer, sizeof(usbmux_tcp_header)+datalen); if (debug) printf("mux_send: sent %i bytes!\n", bytes); // Now that we've sent it off, we can clean up after our sloppy selves. if (debug) { @@ -222,12 +230,12 @@ int mux_send(usbmux_connection *connection, const char *data, uint32 datalen) { if (buffer) free(buffer); // Re-calculate scnt and ocnt - connection->header->scnt = ntohl(connection->header->scnt) + datalen; - connection->header->ocnt = ntohl(connection->header->ocnt); + client->header->scnt = ntohl(client->header->scnt) + datalen; + client->header->ocnt = ntohl(client->header->ocnt); // Revert lengths - connection->header->length = ntohl(connection->header->length); - connection->header->length16 = ntohs(connection->header->length16); + client->header->length = ntohl(client->header->length); + client->header->length16 = ntohs(client->header->length16); // Now return the bytes. if (bytes < sizeof(usbmux_tcp_header)+datalen) { @@ -247,52 +255,52 @@ int mux_send(usbmux_connection *connection, const char *data, uint32 datalen) { * * @return How many bytes were read, or -1 if something bad happens. */ -int mux_recv(usbmux_connection *connection, char *data, uint32 datalen) { +int iphone_mux_recv ( iphone_umux_client_t client, char *data, uint32_t datalen ) { /* * Order of operation: - * 1.) Check if the connection has a pre-received buffer. + * 1.) Check if the client has a pre-received buffer. * 2.) If so, fill data with the buffer, as much as needed. * a.) Return quickly if the buffer has enough * b.) If the buffer is only part of the datalen, get the rest of datalen (and if we can't, just return) * 3.) If not, receive directly from the phone. * a.) Check incoming packet's ports. If proper, follow proper buffering and receiving operation. - * 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. + * b.) If not, find the client the ports belong to and fill that client's buffer, then return mux_recv with the same args to try again. */ if (debug) printf("mux_recv: datalen == %i\n", datalen); int bytes = 0, i = 0, complex = 0, offset = 0; char *buffer = NULL; usbmux_tcp_header *header = NULL; - if (connection->recv_buffer) { - if (connection->r_len >= datalen) { - memcpy(data, connection->recv_buffer, datalen); - if (connection->r_len == datalen) { + if (client->recv_buffer) { + if (client->r_len >= datalen) { + memcpy(data, client->recv_buffer, datalen); + if (client->r_len == datalen) { // reset everything - free(connection->recv_buffer); - connection->r_len = 0; - connection->recv_buffer = NULL; + free(client->recv_buffer); + client->r_len = 0; + client->recv_buffer = NULL; } else { - buffer = (char*)malloc(sizeof(char) * (connection->r_len - datalen)); - memcpy(buffer, connection->recv_buffer+datalen, (connection->r_len - datalen)); - connection->r_len -= datalen; - free(connection->recv_buffer); - connection->recv_buffer = buffer; + buffer = (char*)malloc(sizeof(char) * (client->r_len - datalen)); + memcpy(buffer, client->recv_buffer+datalen, (client->r_len - datalen)); + client->r_len -= datalen; + free(client->recv_buffer); + client->recv_buffer = buffer; } // Since we were able to fill the data straight from our buffer, we can just return datalen. See 2a above. return datalen; } else { - memcpy(data, connection->recv_buffer, connection->r_len); - free(connection->recv_buffer); // don't need to deal with anymore, but... - offset = connection->r_len; // see #2b, above - connection->r_len = 0; + memcpy(data, client->recv_buffer, client->r_len); + free(client->recv_buffer); // don't need to deal with anymore, but... + offset = client->r_len; // see #2b, above + client->r_len = 0; } } // End of what to do if we have a pre-buffer. See #1 and #2 above. buffer = (char*)malloc(sizeof(char) * 131072); // make sure we get enough ;) // See #3. - bytes = recv_from_phone(connection->phone, buffer, 131072); + bytes = recv_from_phone(client->phone, buffer, 131072); if (bytes < 28) { free(buffer); if (debug) printf("mux_recv: Did not even get the header.\n"); @@ -300,10 +308,10 @@ int mux_recv(usbmux_connection *connection, char *data, uint32 datalen) { } header = (usbmux_tcp_header*)buffer; - if (header->sport != connection->header->dport || header->dport != connection->header->sport) { + if (header->sport != client->header->dport || header->dport != client->header->sport) { // Ooooops -- we got someone else's packet. // We gotta stick it in their buffer. (Take that any old way you want ;) ) - for (i = 0; i < connections; i++) { + for (i = 0; i < clients; i++) { if (connlist[i]->header->sport == header->dport && connlist[i]->header->dport == header->sport) { // we have a winner. char *nfb = (char*)malloc(sizeof(char) * (connlist[i]->r_len + (bytes - 28))); @@ -312,7 +320,7 @@ int mux_recv(usbmux_connection *connection, char *data, uint32 datalen) { free(connlist[i]->recv_buffer); } connlist[i]->r_len += bytes - 28; - //connlist[i]->recv_buffer = (char*)realloc(connlist[i]->recv_buffer, sizeof(char) * connection->r_len); // grow their buffer + //connlist[i]->recv_buffer = (char*)realloc(connlist[i]->recv_buffer, sizeof(char) * client->r_len); // grow their buffer connlist[i]->recv_buffer = nfb; nfb = NULL; // A cookie for you if you can guess what "nfb" means. complex = connlist[i]->r_len - (bytes - 28); @@ -324,7 +332,7 @@ int mux_recv(usbmux_connection *connection, char *data, uint32 datalen) { // Free our buffer and continue. free(buffer); buffer = NULL; - return mux_recv(connection, data, datalen); // recurse back in to try again + return mux_recv(client, data, datalen); // recurse back in to try again } // The packet was absolutely meant for us if it hits this point. @@ -333,18 +341,18 @@ int mux_recv(usbmux_connection *connection, char *data, uint32 datalen) { if ((bytes-28) > datalen) { // Copy what we need into the data, buffer the rest because we can. memcpy(data+offset, buffer+28, datalen); // data+offset: see #2b, above - complex = connection->r_len + (bytes-28) - datalen; - connection->recv_buffer = (char*)realloc(connection->recv_buffer, (sizeof(char) * complex)); - connection->r_len = complex; - complex = connection->r_len - (bytes-28) - datalen; - memcpy(connection->recv_buffer+complex, buffer+28+datalen, (bytes-28) - datalen); + complex = client->r_len + (bytes-28) - datalen; + client->recv_buffer = (char*)realloc(client->recv_buffer, (sizeof(char) * complex)); + client->r_len = complex; + complex = client->r_len - (bytes-28) - datalen; + memcpy(client->recv_buffer+complex, buffer+28+datalen, (bytes-28) - datalen); free(buffer); - connection->header->ocnt += bytes-28; + client->header->ocnt += bytes-28; return datalen; } else { // Fill the data with what we have, and just return. memcpy(data+offset, buffer+28, bytes-28); // data+offset: see #2b, above - connection->header->ocnt += bytes-28; + client->header->ocnt += bytes-28; free(buffer); return (bytes-28); } |