summaryrefslogtreecommitdiffstats
path: root/src/usbmux.c
diff options
context:
space:
mode:
authorGravatar Matt Colyer2008-07-29 10:13:37 -0700
committerGravatar Matt Colyer2008-07-29 10:13:37 -0700
commit3dc130f3049e250b2d5c0b48af1995fda2fad3d4 (patch)
tree9d801459ef68e83a0d4ca038c0589d8e4c8aa2b2 /src/usbmux.c
parent6039e5bbfc36aa5210295c38f251ed178ce5adbb (diff)
downloadlibimobiledevice-3dc130f3049e250b2d5c0b48af1995fda2fad3d4.tar.gz
libimobiledevice-3dc130f3049e250b2d5c0b48af1995fda2fad3d4.tar.bz2
Autotooled the project with very basic versioning support.
Diffstat (limited to 'src/usbmux.c')
-rw-r--r--src/usbmux.c198
1 files changed, 198 insertions, 0 deletions
diff --git a/src/usbmux.c b/src/usbmux.c
new file mode 100644
index 0000000..8c5fc34
--- /dev/null
+++ b/src/usbmux.c
@@ -0,0 +1,198 @@
1
2#include <sys/types.h>
3#include <arpa/inet.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7
8#include "usbmux.h"
9
10extern int debug;
11
12usbmux_tcp_header *new_mux_packet(uint16 s_port, uint16 d_port) {
13 usbmux_tcp_header *conn = (usbmux_tcp_header*)malloc(sizeof(usbmux_tcp_header));
14 conn->type = htonl(6);
15 conn->length = 28;
16 conn->sport = htons(s_port);
17 conn->dport = htons(d_port);
18 conn->scnt = 0;
19 conn->ocnt = 0;
20 conn->offset = 0x50;
21 conn->window = htons(0x0200);
22 conn->nullnull = 0x0000;
23 conn->length16 = 28;
24 return conn;
25}
26
27usbmux_version_header *version_header() {
28 usbmux_version_header *version = (usbmux_version_header*)malloc(sizeof(usbmux_version_header));
29 version->type = 0;
30 version->length = htonl(20);
31 version->major = htonl(1);
32 version->minor = 0;
33 version->allnull = 0;
34 return version;
35}
36
37/* mux_connect(phone, s_port, d_port)
38 * This is a higher-level USBMuxTCP-type function.
39 * phone: the iPhone to initialize a connection on.
40 * s_port: the source port
41 * d_port: the destination port -- 0xf27e for lockdownd.
42 * Initializes a connection on phone, with source port s_port and destination port d_port
43 *
44 * Returns a mux TCP header for the connection which is used for tracking and data transfer.
45 */
46
47usbmux_tcp_header *mux_connect(iPhone *phone, uint16 s_port, uint16 d_port) {
48 if (!phone || !s_port || !d_port) return NULL;
49 int bytes = 0;
50 // Initialize connection stuff
51 usbmux_tcp_header *new_connection;
52 new_connection = new_mux_packet(s_port, d_port);
53 usbmux_tcp_header *response;
54 response = (usbmux_tcp_header*)malloc(sizeof(usbmux_tcp_header));
55 // blargg
56 if (new_connection) {
57 new_connection->tcp_flags = 0x02;
58 new_connection->length = htonl(new_connection->length);
59 new_connection->length16 = htons(new_connection->length16);
60
61 if (send_to_phone(phone, (char*)new_connection, sizeof(*new_connection)) >= 0) {
62 bytes = recv_from_phone(phone, (char*)response, sizeof(*response));
63 if (response->tcp_flags != 0x12) return NULL;
64 else {
65 new_connection->tcp_flags = 0x10;
66 new_connection->scnt = 1;
67 new_connection->ocnt = 1;
68 return new_connection;
69 }
70 } else {
71 return NULL;
72 }
73 }
74
75 // if we get to this point it's probably bad
76 return NULL;
77}
78
79/* mux_close_connection(phone, connection)
80 * This is a higher-level USBmuxTCP-type function.
81 * phone: the iPhone to close a connection with.
82 * connection: the connection to close.
83 *
84 * Doesn't return anything; WILL FREE THE CONNECTION'S MEMORY!!!
85 */
86void mux_close_connection(iPhone *phone, usbmux_tcp_header *connection) {
87 if (!phone || !connection) return;
88
89 connection->tcp_flags = 0x04;
90 connection->scnt = htonl(connection->scnt);
91 connection->ocnt = htonl(connection->ocnt);
92 int bytes = 0;
93
94 bytes = usb_bulk_write(phone->device, BULKOUT, (char*)connection, sizeof(*connection), 800);
95 bytes = usb_bulk_read(phone->device, BULKIN, (char*)connection, sizeof(*connection), 800);
96
97 free(connection);
98}
99
100/* mux_send(phone, connection, data, datalen)
101 * This is a higher-level USBMuxTCP-like function.
102 * phone: the iPhone to send to.
103 * connection: the connection we're sending data on.
104 * data: a pointer to the data to send.
105 * datalen: how much data we're sending.
106 *
107 * Returns number of bytes sent, minus the header (28), or -1 on error.
108 */
109int mux_send(iPhone *phone, usbmux_tcp_header *connection, char *data, uint32 datalen) {
110 if (!phone || !connection || !data || datalen == 0) return -1;
111 // connection->scnt and connection->ocnt should already be in host notation...
112 // we don't need to change them juuuust yet.
113 int bytes = 0;
114 if (debug) printf("mux_send(): client wants to send %i bytes\n", datalen);
115 char *buffer = (char*)malloc(sizeof(*connection) + datalen + 2); // allow 2 bytes of safety padding
116 // Set the length and pre-emptively htonl/htons it
117 connection->length = htonl(sizeof(*connection) + datalen);
118 connection->length16 = htons(sizeof(*connection) + datalen);
119
120 // Put scnt and ocnt into big-endian notation
121 connection->scnt = htonl(connection->scnt);
122 connection->ocnt = htonl(connection->ocnt);
123 // Concatenation of stuff in the buffer.
124 memcpy(buffer, connection, sizeof(*connection));
125 memcpy(buffer+sizeof(*connection)/*+sizeof(datalen)*/, data, datalen);
126
127 // We have a buffer full of data, we should now send it to the phone.
128 if (debug) printf("actually sending %i bytes of data at %x\n", sizeof(*connection)+datalen, buffer);
129
130
131 bytes = send_to_phone(phone, buffer, sizeof(*connection)+datalen);
132
133 // Now that we've sent it off, we can clean up after our sloppy selves.
134 free(buffer);
135
136 // Re-calculate scnt and ocnt
137 connection->scnt = ntohl(connection->scnt) + datalen;
138 connection->ocnt = ntohl(connection->ocnt);
139
140 // Revert lengths
141 connection->length = ntohl(connection->length);
142 connection->length16 = ntohs(connection->length16);
143
144 // Now return the bytes.
145 if (bytes < sizeof(*connection)+datalen) {
146 return -1; // blah
147 } else {
148 return bytes - 28; // actual length sent. :/
149 }
150
151 return bytes; // or something
152}
153
154/* mux_recv(phone, connection, data, datalen)
155 * This is a higher-level USBMuxTCP-like function
156 * phone: the phone to receive data from.
157 * connection: the connection to receive data on.
158 * data: where to put the data we receive.
159 * datalen: how much data to read.
160 *
161 * Returns: how many bytes were read, or -1 if something bad happens.
162 */
163
164int mux_recv(iPhone *phone, usbmux_tcp_header *connection, char *data, uint32 datalen) {
165 char *buffer = (char*)malloc(sizeof(*connection) + sizeof(datalen) + datalen);
166 int bytes = 0, my_datalen = 0;
167 if (debug) printf("mux_recv: datalen == %i\n", datalen);
168 bytes = recv_from_phone(phone, buffer, sizeof(*connection) + datalen);
169 if (debug) printf("mux_recv: bytes == %i\n", bytes);
170 if (bytes < datalen) {
171 if (bytes < 28) {
172 // if they didn't do that annoying thing, something else mighta happened.
173 if (debug) printf("mux_recv: bytes too low anyway!\n");
174 free(buffer);
175 return -1;
176 } else if (bytes == 28) { // no data...
177 free(buffer);
178 return 0;
179 } else { // bytes > 28
180 my_datalen = ntohl(buffer[4]) - 28;
181 connection->ocnt += my_datalen;
182 memcpy(data, buffer+28, bytes - 28);
183 free(buffer);
184 if (debug) printf("mux_recv: bytes received: %i\n", bytes - 28);
185 return bytes - 28;
186 }
187 } else {// all's good, they didn't do anything bonky.
188 my_datalen = ntohl(buffer[4]) - 28;
189 connection->ocnt += my_datalen;
190 memcpy(data, buffer+28, datalen);
191 free(buffer);
192 if (debug) printf("mux_recv: bytes received: %i\n", bytes - 28);
193 return bytes - 28;
194 }
195
196 return bytes;
197}
198