summaryrefslogtreecommitdiffstats
path: root/src/usbmux.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/usbmux.c')
-rw-r--r--src/usbmux.c170
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 @@
29 29
30extern int debug; 30extern int debug;
31 31
32static usbmux_connection **connlist = NULL; 32static iphone_umux_client_t *connlist = NULL;
33static int connections = 0; 33static int clients = 0;
34 34
35/** Creates a USBMux packet for the given set of ports. 35/** Creates a USBMux packet for the given set of ports.
36 * 36 *
@@ -76,10 +76,10 @@ usbmux_version_header *version_header() {
76 * 76 *
77 * @param connection The connection to delete from the tracking list. 77 * @param connection The connection to delete from the tracking list.
78 */ 78 */
79void delete_connection(usbmux_connection *connection) { 79void delete_connection(iphone_umux_client_t connection) {
80 usbmux_connection **newlist = (usbmux_connection**)malloc(sizeof(usbmux_connection*) * (connections - 1)); 80 iphone_umux_client_t *newlist = (iphone_umux_client_t*)malloc(sizeof(iphone_umux_client_t) * (clients - 1));
81 int i = 0, j = 0; 81 int i = 0, j = 0;
82 for (i = 0; i < connections; i++) { 82 for (i = 0; i < clients; i++) {
83 if (connlist[i] == connection) continue; 83 if (connlist[i] == connection) continue;
84 else { 84 else {
85 newlist[j] = connlist[i]; 85 newlist[j] = connlist[i];
@@ -88,7 +88,7 @@ void delete_connection(usbmux_connection *connection) {
88 } 88 }
89 free(connlist); 89 free(connlist);
90 connlist = newlist; 90 connlist = newlist;
91 connections--; 91 clients--;
92 if (connection->recv_buffer) free(connection->recv_buffer); 92 if (connection->recv_buffer) free(connection->recv_buffer);
93 if (connection->header) free(connection->header); 93 if (connection->header) free(connection->header);
94 connection->r_len = 0; 94 connection->r_len = 0;
@@ -101,59 +101,64 @@ void delete_connection(usbmux_connection *connection) {
101 * @param connection The connection to add to the global list of connections. 101 * @param connection The connection to add to the global list of connections.
102 */ 102 */
103 103
104void add_connection(usbmux_connection *connection) { 104void add_connection(iphone_umux_client_t connection) {
105 usbmux_connection **newlist = (usbmux_connection**)realloc(connlist, sizeof(usbmux_connection*) * (connections+1)); 105 iphone_umux_client_t* newlist = (iphone_umux_client_t*)realloc(connlist, sizeof(iphone_umux_client_t) * (clients+1));
106 newlist[connections] = connection; 106 newlist[clients] = connection;
107 connlist = newlist; 107 connlist = newlist;
108 connections++; 108 clients++;
109} 109}
110 110
111/** Initializes a connection on phone, with source port s_port and destination port d_port 111/** Initializes a connection on phone, with source port s_port and destination port d_port
112 * 112 *
113 * @param phone The iPhone to initialize a connection on. 113 * @param device The iPhone to initialize a connection on.
114 * @param s_port The source port 114 * @param src_port The source port
115 * @param d_port The destination port -- 0xf27e for lockdownd. 115 * @param dst_port The destination port -- 0xf27e for lockdownd.
116 * 116 * @param client A mux TCP header for the connection which is used for tracking and data transfer.
117 * @return A mux TCP header for the connection which is used for tracking and data transfer. 117 * @return IPHONE_E_SUCCESS on success, an error code otherwise.
118 */ 118 */
119usbmux_connection *mux_connect(iphone_device_t phone, uint16 s_port, uint16 d_port) { 119int iphone_mux_new_client ( iphone_device_t device, uint16_t src_port, uint16_t dst_port, iphone_umux_client_t *client ){
120 if (!phone || !s_port || !d_port) return NULL; 120 if (!device || !src_port || !dst_port)
121 return IPHONE_E_INVALID_ARG;
122
121 int bytes = 0; 123 int bytes = 0;
122 // Initialize connection stuff 124 // Initialize connection stuff
123 usbmux_connection *new_connection = (usbmux_connection*)malloc(sizeof(usbmux_connection)); 125 iphone_umux_client_t new_connection = (iphone_umux_client_t)malloc(sizeof(struct iphone_umux_client_int));
124 new_connection->header = new_mux_packet(s_port, d_port); 126 new_connection->header = new_mux_packet(src_port, dst_port);
127
125 // blargg 128 // blargg
126 if (new_connection && new_connection->header) { 129 if (new_connection && new_connection->header) {
127 new_connection->header->tcp_flags = 0x02; 130 new_connection->header->tcp_flags = 0x02;
128 new_connection->header->length = htonl(new_connection->header->length); 131 new_connection->header->length = htonl(new_connection->header->length);
129 new_connection->header->length16 = htons(new_connection->header->length16); 132 new_connection->header->length16 = htons(new_connection->header->length16);
130 133
131 if (send_to_phone(phone, (char*)new_connection->header, sizeof(usbmux_tcp_header)) >= 0) { 134 if (send_to_phone(device, (char*)new_connection->header, sizeof(usbmux_tcp_header)) >= 0) {
132 usbmux_tcp_header *response; 135 usbmux_tcp_header *response;
133 response = (usbmux_tcp_header*)malloc(sizeof(usbmux_tcp_header)); 136 response = (usbmux_tcp_header*)malloc(sizeof(usbmux_tcp_header));
134 bytes = recv_from_phone(phone, (char*)response, sizeof(*response)); 137 bytes = recv_from_phone(device, (char*)response, sizeof(*response));
135 if (response->tcp_flags != 0x12) { 138 if (response->tcp_flags != 0x12) {
136 free(response); 139 free(response);
137 return NULL; 140 return IPHONE_E_UNKNOWN_ERROR;
138 } else { 141 } else {
139 free(response); 142 free(response);
143
140 if (debug) printf("mux_connect: connection success\n"); 144 if (debug) printf("mux_connect: connection success\n");
141 new_connection->header->tcp_flags = 0x10; 145 new_connection->header->tcp_flags = 0x10;
142 new_connection->header->scnt = 1; 146 new_connection->header->scnt = 1;
143 new_connection->header->ocnt = 1; 147 new_connection->header->ocnt = 1;
144 new_connection->phone = phone; 148 new_connection->phone = device;
145 new_connection->recv_buffer = NULL; 149 new_connection->recv_buffer = NULL;
146 new_connection->r_len = 0; 150 new_connection->r_len = 0;
147 add_connection(new_connection); 151 add_connection(new_connection);
148 return new_connection; 152 *client = new_connection;
153 return IPHONE_E_SUCCESS;
149 } 154 }
150 } else { 155 } else {
151 return NULL; 156 return IPHONE_E_NOT_ENOUGH_DATA;
152 } 157 }
153 } 158 }
154 159
155 // if we get to this point it's probably bad 160 // if we get to this point it's probably bad
156 return NULL; 161 return IPHONE_E_UNKNOWN_ERROR;
157} 162}
158 163
159/** Cleans up the given USBMux connection. 164/** Cleans up the given USBMux connection.
@@ -161,56 +166,59 @@ usbmux_connection *mux_connect(iphone_device_t phone, uint16 s_port, uint16 d_po
161 * 166 *
162 * @param connection The connection to close. 167 * @param connection The connection to close.
163 */ 168 */
164void mux_close_connection(usbmux_connection *connection) { 169void iphone_mux_free_client ( iphone_umux_client_t client ) {
165 if (!connection || !connection->phone) return; 170 if (!client || !client->phone) return;
166 171
167 connection->header->tcp_flags = 0x04; 172 client->header->tcp_flags = 0x04;
168 connection->header->scnt = htonl(connection->header->scnt); 173 client->header->scnt = htonl(client->header->scnt);
169 connection->header->ocnt = htonl(connection->header->ocnt); 174 client->header->ocnt = htonl(client->header->ocnt);
170 int bytes = 0; 175 int bytes = 0;
171 176
172 bytes = usb_bulk_write(connection->phone->device, BULKOUT, (char*)connection->header, sizeof(usbmux_tcp_header), 800); 177 bytes = usb_bulk_write(client->phone->device, BULKOUT, (char*)client->header, sizeof(usbmux_tcp_header), 800);
173 if(debug && bytes < 0) 178 if(debug && bytes < 0)
174 printf("mux_close_connection(): when writing, libusb gave me the error: %s\n", usb_strerror()); 179 printf("mux_close_connection(): when writing, libusb gave me the error: %s\n", usb_strerror());
175 180
176 bytes = usb_bulk_read(connection->phone->device, BULKIN, (char*)connection->header, sizeof(usbmux_tcp_header), 800); 181 bytes = usb_bulk_read(client->phone->device, BULKIN, (char*)client->header, sizeof(usbmux_tcp_header), 800);
177 if(debug && bytes < 0) 182 if(debug && bytes < 0)
178 printf("get_iPhone(): when reading, libusb gave me the error: %s\n", usb_strerror()); 183 printf("get_iPhone(): when reading, libusb gave me the error: %s\n", usb_strerror());
179 184
180 delete_connection(connection); 185 delete_connection(client);
181} 186}
182 187
188
183/** Sends the given data over the selected connection. 189/** Sends the given data over the selected connection.
184 * 190 *
185 * @param connection The connection we're sending data on. 191 * @param phone The iPhone to send to.
192 * @param client The client we're sending data on.
186 * @param data A pointer to the data to send. 193 * @param data A pointer to the data to send.
187 * @param datalen How much data we're sending. 194 * @param datalen How much data we're sending.
188 * 195 *
189 * @return The number of bytes sent, minus the header (28), or -1 on error. 196 * @return The number of bytes sent, minus the header (28), or -1 on error.
190 */ 197 */
191int mux_send(usbmux_connection *connection, const char *data, uint32 datalen) { 198
192 if (!connection->phone || !connection || !data || datalen == 0) return -1; 199int iphone_mux_send ( iphone_umux_client_t client, const char *data, uint32_t datalen ) {
193 // connection->scnt and connection->ocnt should already be in host notation... 200 if (!client->phone || !client || !data || datalen == 0) return -1;
201 // client->scnt and client->ocnt should already be in host notation...
194 // we don't need to change them juuuust yet. 202 // we don't need to change them juuuust yet.
195 int bytes = 0; 203 int bytes = 0;
196 if (debug) printf("mux_send(): client wants to send %i bytes\n", datalen); 204 if (debug) printf("mux_send(): client wants to send %i bytes\n", datalen);
197 char *buffer = (char*)malloc(sizeof(usbmux_tcp_header) + datalen + 2); // allow 2 bytes of safety padding 205 char *buffer = (char*)malloc(sizeof(usbmux_tcp_header) + datalen + 2); // allow 2 bytes of safety padding
198 // Set the length and pre-emptively htonl/htons it 206 // Set the length and pre-emptively htonl/htons it
199 connection->header->length = htonl(sizeof(usbmux_tcp_header) + datalen); 207 client->header->length = htonl(sizeof(usbmux_tcp_header) + datalen);
200 connection->header->length16 = htons(sizeof(usbmux_tcp_header) + datalen); 208 client->header->length16 = htons(sizeof(usbmux_tcp_header) + datalen);
201 209
202 // Put scnt and ocnt into big-endian notation 210 // Put scnt and ocnt into big-endian notation
203 connection->header->scnt = htonl(connection->header->scnt); 211 client->header->scnt = htonl(client->header->scnt);
204 connection->header->ocnt = htonl(connection->header->ocnt); 212 client->header->ocnt = htonl(client->header->ocnt);
205 // Concatenation of stuff in the buffer. 213 // Concatenation of stuff in the buffer.
206 memcpy(buffer, connection->header, sizeof(usbmux_tcp_header)); 214 memcpy(buffer, client->header, sizeof(usbmux_tcp_header));
207 memcpy(buffer+sizeof(usbmux_tcp_header), data, datalen); 215 memcpy(buffer+sizeof(usbmux_tcp_header), data, datalen);
208 216
209 // We have a buffer full of data, we should now send it to the phone. 217 // We have a buffer full of data, we should now send it to the phone.
210 if (debug) printf("actually sending %zi bytes of data at %p\n", sizeof(usbmux_tcp_header)+datalen, buffer); 218 if (debug) printf("actually sending %zi bytes of data at %p\n", sizeof(usbmux_tcp_header)+datalen, buffer);
211 219
212 220
213 bytes = send_to_phone(connection->phone, buffer, sizeof(usbmux_tcp_header)+datalen); 221 bytes = send_to_phone(client->phone, buffer, sizeof(usbmux_tcp_header)+datalen);
214 if (debug) printf("mux_send: sent %i bytes!\n", bytes); 222 if (debug) printf("mux_send: sent %i bytes!\n", bytes);
215 // Now that we've sent it off, we can clean up after our sloppy selves. 223 // Now that we've sent it off, we can clean up after our sloppy selves.
216 if (debug) { 224 if (debug) {
@@ -222,12 +230,12 @@ int mux_send(usbmux_connection *connection, const char *data, uint32 datalen) {
222 230
223 if (buffer) free(buffer); 231 if (buffer) free(buffer);
224 // Re-calculate scnt and ocnt 232 // Re-calculate scnt and ocnt
225 connection->header->scnt = ntohl(connection->header->scnt) + datalen; 233 client->header->scnt = ntohl(client->header->scnt) + datalen;
226 connection->header->ocnt = ntohl(connection->header->ocnt); 234 client->header->ocnt = ntohl(client->header->ocnt);
227 235
228 // Revert lengths 236 // Revert lengths
229 connection->header->length = ntohl(connection->header->length); 237 client->header->length = ntohl(client->header->length);
230 connection->header->length16 = ntohs(connection->header->length16); 238 client->header->length16 = ntohs(client->header->length16);
231 239
232 // Now return the bytes. 240 // Now return the bytes.
233 if (bytes < sizeof(usbmux_tcp_header)+datalen) { 241 if (bytes < sizeof(usbmux_tcp_header)+datalen) {
@@ -247,52 +255,52 @@ int mux_send(usbmux_connection *connection, const char *data, uint32 datalen) {
247 * 255 *
248 * @return How many bytes were read, or -1 if something bad happens. 256 * @return How many bytes were read, or -1 if something bad happens.
249 */ 257 */
250int mux_recv(usbmux_connection *connection, char *data, uint32 datalen) { 258int iphone_mux_recv ( iphone_umux_client_t client, char *data, uint32_t datalen ) {
251 /* 259 /*
252 * Order of operation: 260 * Order of operation:
253 * 1.) Check if the connection has a pre-received buffer. 261 * 1.) Check if the client has a pre-received buffer.
254 * 2.) If so, fill data with the buffer, as much as needed. 262 * 2.) If so, fill data with the buffer, as much as needed.
255 * a.) Return quickly if the buffer has enough 263 * a.) Return quickly if the buffer has enough
256 * b.) If the buffer is only part of the datalen, get the rest of datalen (and if we can't, just return) 264 * b.) If the buffer is only part of the datalen, get the rest of datalen (and if we can't, just return)
257 * 3.) If not, receive directly from the phone. 265 * 3.) If not, receive directly from the phone.
258 * a.) Check incoming packet's ports. If proper, follow proper buffering and receiving operation. 266 * a.) Check incoming packet's ports. If proper, follow proper buffering and receiving operation.
259 * 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. 267 * 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.
260 */ 268 */
261 if (debug) printf("mux_recv: datalen == %i\n", datalen); 269 if (debug) printf("mux_recv: datalen == %i\n", datalen);
262 int bytes = 0, i = 0, complex = 0, offset = 0; 270 int bytes = 0, i = 0, complex = 0, offset = 0;
263 char *buffer = NULL; 271 char *buffer = NULL;
264 usbmux_tcp_header *header = NULL; 272 usbmux_tcp_header *header = NULL;
265 273
266 if (connection->recv_buffer) { 274 if (client->recv_buffer) {
267 if (connection->r_len >= datalen) { 275 if (client->r_len >= datalen) {
268 memcpy(data, connection->recv_buffer, datalen); 276 memcpy(data, client->recv_buffer, datalen);
269 if (connection->r_len == datalen) { 277 if (client->r_len == datalen) {
270 // reset everything 278 // reset everything
271 free(connection->recv_buffer); 279 free(client->recv_buffer);
272 connection->r_len = 0; 280 client->r_len = 0;
273 connection->recv_buffer = NULL; 281 client->recv_buffer = NULL;
274 } else { 282 } else {
275 buffer = (char*)malloc(sizeof(char) * (connection->r_len - datalen)); 283 buffer = (char*)malloc(sizeof(char) * (client->r_len - datalen));
276 memcpy(buffer, connection->recv_buffer+datalen, (connection->r_len - datalen)); 284 memcpy(buffer, client->recv_buffer+datalen, (client->r_len - datalen));
277 connection->r_len -= datalen; 285 client->r_len -= datalen;
278 free(connection->recv_buffer); 286 free(client->recv_buffer);
279 connection->recv_buffer = buffer; 287 client->recv_buffer = buffer;
280 } 288 }
281 289
282 // Since we were able to fill the data straight from our buffer, we can just return datalen. See 2a above. 290 // Since we were able to fill the data straight from our buffer, we can just return datalen. See 2a above.
283 return datalen; 291 return datalen;
284 } else { 292 } else {
285 memcpy(data, connection->recv_buffer, connection->r_len); 293 memcpy(data, client->recv_buffer, client->r_len);
286 free(connection->recv_buffer); // don't need to deal with anymore, but... 294 free(client->recv_buffer); // don't need to deal with anymore, but...
287 offset = connection->r_len; // see #2b, above 295 offset = client->r_len; // see #2b, above
288 connection->r_len = 0; 296 client->r_len = 0;
289 } 297 }
290 } // End of what to do if we have a pre-buffer. See #1 and #2 above. 298 } // End of what to do if we have a pre-buffer. See #1 and #2 above.
291 299
292 buffer = (char*)malloc(sizeof(char) * 131072); // make sure we get enough ;) 300 buffer = (char*)malloc(sizeof(char) * 131072); // make sure we get enough ;)
293 301
294 // See #3. 302 // See #3.
295 bytes = recv_from_phone(connection->phone, buffer, 131072); 303 bytes = recv_from_phone(client->phone, buffer, 131072);
296 if (bytes < 28) { 304 if (bytes < 28) {
297 free(buffer); 305 free(buffer);
298 if (debug) printf("mux_recv: Did not even get the header.\n"); 306 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) {
300 } 308 }
301 309
302 header = (usbmux_tcp_header*)buffer; 310 header = (usbmux_tcp_header*)buffer;
303 if (header->sport != connection->header->dport || header->dport != connection->header->sport) { 311 if (header->sport != client->header->dport || header->dport != client->header->sport) {
304 // Ooooops -- we got someone else's packet. 312 // Ooooops -- we got someone else's packet.
305 // We gotta stick it in their buffer. (Take that any old way you want ;) ) 313 // We gotta stick it in their buffer. (Take that any old way you want ;) )
306 for (i = 0; i < connections; i++) { 314 for (i = 0; i < clients; i++) {
307 if (connlist[i]->header->sport == header->dport && connlist[i]->header->dport == header->sport) { 315 if (connlist[i]->header->sport == header->dport && connlist[i]->header->dport == header->sport) {
308 // we have a winner. 316 // we have a winner.
309 char *nfb = (char*)malloc(sizeof(char) * (connlist[i]->r_len + (bytes - 28))); 317 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) {
312 free(connlist[i]->recv_buffer); 320 free(connlist[i]->recv_buffer);
313 } 321 }
314 connlist[i]->r_len += bytes - 28; 322 connlist[i]->r_len += bytes - 28;
315 //connlist[i]->recv_buffer = (char*)realloc(connlist[i]->recv_buffer, sizeof(char) * connection->r_len); // grow their buffer 323 //connlist[i]->recv_buffer = (char*)realloc(connlist[i]->recv_buffer, sizeof(char) * client->r_len); // grow their buffer
316 connlist[i]->recv_buffer = nfb; 324 connlist[i]->recv_buffer = nfb;
317 nfb = NULL; // A cookie for you if you can guess what "nfb" means. 325 nfb = NULL; // A cookie for you if you can guess what "nfb" means.
318 complex = connlist[i]->r_len - (bytes - 28); 326 complex = connlist[i]->r_len - (bytes - 28);
@@ -324,7 +332,7 @@ int mux_recv(usbmux_connection *connection, char *data, uint32 datalen) {
324 // Free our buffer and continue. 332 // Free our buffer and continue.
325 free(buffer); 333 free(buffer);
326 buffer = NULL; 334 buffer = NULL;
327 return mux_recv(connection, data, datalen); // recurse back in to try again 335 return mux_recv(client, data, datalen); // recurse back in to try again
328 } 336 }
329 337
330 // The packet was absolutely meant for us if it hits this point. 338 // 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) {
333 if ((bytes-28) > datalen) { 341 if ((bytes-28) > datalen) {
334 // Copy what we need into the data, buffer the rest because we can. 342 // Copy what we need into the data, buffer the rest because we can.
335 memcpy(data+offset, buffer+28, datalen); // data+offset: see #2b, above 343 memcpy(data+offset, buffer+28, datalen); // data+offset: see #2b, above
336 complex = connection->r_len + (bytes-28) - datalen; 344 complex = client->r_len + (bytes-28) - datalen;
337 connection->recv_buffer = (char*)realloc(connection->recv_buffer, (sizeof(char) * complex)); 345 client->recv_buffer = (char*)realloc(client->recv_buffer, (sizeof(char) * complex));
338 connection->r_len = complex; 346 client->r_len = complex;
339 complex = connection->r_len - (bytes-28) - datalen; 347 complex = client->r_len - (bytes-28) - datalen;
340 memcpy(connection->recv_buffer+complex, buffer+28+datalen, (bytes-28) - datalen); 348 memcpy(client->recv_buffer+complex, buffer+28+datalen, (bytes-28) - datalen);
341 free(buffer); 349 free(buffer);
342 connection->header->ocnt += bytes-28; 350 client->header->ocnt += bytes-28;
343 return datalen; 351 return datalen;
344 } else { 352 } else {
345 // Fill the data with what we have, and just return. 353 // Fill the data with what we have, and just return.
346 memcpy(data+offset, buffer+28, bytes-28); // data+offset: see #2b, above 354 memcpy(data+offset, buffer+28, bytes-28); // data+offset: see #2b, above
347 connection->header->ocnt += bytes-28; 355 client->header->ocnt += bytes-28;
348 free(buffer); 356 free(buffer);
349 return (bytes-28); 357 return (bytes-28);
350 } 358 }