Commit ad65cefa authored by Jonathan Beck's avatar Jonathan Beck

migrate usbmux.c.

parent 21d5d4ac
......@@ -32,18 +32,19 @@ extern "C" {
//general errors
#define IPHONE_E_SUCCESS 0
#define IPHONE_E_INVALID_ARG -1
#define IPHONE_E_NO_DEVICE -2
#define IPHONE_E_TIMEOUT -3
#define IPHONE_E_NOT_ENOUGH_DATA -4
#define IPHONE_E_BAD_HEADER -5
#define IPHONE_E_UNKNOWN_ERROR -2
#define IPHONE_E_NO_DEVICE -3
#define IPHONE_E_TIMEOUT -4
#define IPHONE_E_NOT_ENOUGH_DATA -5
#define IPHONE_E_BAD_HEADER -6
//lockdownd specific error
#define IPHONE_E_INVALID_CONF -6
#define IPHONE_E_PAIRING_FAILED -7
#define IPHONE_E_SSL_ERROR -8
#define IPHONE_E_INVALID_CONF -7
#define IPHONE_E_PAIRING_FAILED -8
#define IPHONE_E_SSL_ERROR -9
//afc specific error
#define IPHONE_E_NO_SUCH_FILE -9
#define IPHONE_E_NO_SUCH_FILE -10
struct iphone_device_int;
typedef struct iphone_device_int *iphone_device_t;
......
......@@ -42,7 +42,6 @@ int iphone_get_device ( iphone_device_t *device ){
struct usb_bus *bus, *busses;
struct usb_device *dev;
iphone_device_t phone = (iphone_device_t)malloc(sizeof(struct iphone_device_int));
usbmux_version_header *version = version_header();
// Initialize the struct
phone->device = NULL;
......@@ -126,7 +125,7 @@ int iphone_get_device ( iphone_device_t *device ){
if (debug) fprintf(stderr, "get_iPhone(): Unknown error.\n");
free_iPhone(phone);
free(version);
return IPHONE_E_NO_DEVICE; // if it got to this point it's gotta be bad
return IPHONE_E_UNKNOWN_ERROR; // if it got to this point it's gotta be bad
}
/** Cleans up an iPhone structure, then frees the structure itself.
......
......@@ -77,8 +77,8 @@ char *lockdownd_generate_hostid() {
iphone_lckd_client_t new_lockdownd_client(iphone_device_t phone) {
if (!phone) return NULL;
iphone_lckd_client_t control = (iphone_lckd_client_t)malloc(sizeof(struct iphone_lckd_client_int));
control->connection = mux_connect(phone, 0x0a00, 0xf27e);
if (!control->connection) {
if (IPHONE_E_SUCCESS != iphone_mux_new_client ( phone, 0x0a00, 0xf27e, &control->connection)) {
free(control);
return NULL;
}
......@@ -100,7 +100,7 @@ void iphone_lckd_free_client( iphone_lckd_client_t client ) {
mux_close_connection(client->connection);
}
if (client->ssl_session) gnutls_deinit(*control->ssl_session);
if (client->ssl_session) gnutls_deinit(*client->ssl_session);
free(client->ssl_session);
free(client);
}
......
......@@ -33,7 +33,7 @@
struct iphone_lckd_client_int {
usbmux_connection *connection;
iphone_umux_client_t connection;
gnutls_session_t *ssl_session;
int in_SSL;
char *gtls_buffer_hack;
......
......@@ -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.
* @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.
*/
usbmux_connection *mux_connect(iphone_device_t phone, uint16 s_port, uint16 d_port) {
if (!phone || !s_port || !d_port) return NULL;
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);
}
......
......@@ -43,12 +43,12 @@ typedef struct {
uint16 window, nullnull, length16;
} usbmux_tcp_header;
typedef struct {
struct iphone_umux_client_int {
usbmux_tcp_header *header;
iphone_device_t phone;
char *recv_buffer;
int r_len;
} usbmux_connection;
};
usbmux_tcp_header *new_mux_packet(uint16 s_port, uint16 d_port);
......@@ -58,10 +58,5 @@ typedef struct {
usbmux_version_header *version_header();
usbmux_connection *mux_connect(iphone_device_t phone, uint16 s_port, uint16 d_port);
void mux_close_connection(usbmux_connection *connection);
int mux_send(usbmux_connection *connection, const char *data, uint32 datalen);
int mux_recv(usbmux_connection *connection, char *data, uint32 datalen);
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment