summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am31
-rw-r--r--src/libusbmuxd.c248
-rw-r--r--src/main.c1447
-rw-r--r--src/sock_stuff.c301
-rw-r--r--src/sock_stuff.h28
-rw-r--r--src/usbmux.c1264
-rw-r--r--src/usbmux.h53
-rw-r--r--src/usbmuxd-proto.h52
-rw-r--r--src/usbmuxd.h91
9 files changed, 0 insertions, 3515 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
deleted file mode 100644
index 547870e..0000000
--- a/src/Makefile.am
+++ /dev/null
@@ -1,31 +0,0 @@
1AM_CFLAGS = $(GLOBAL_CFLAGS) $(libusb_CFLAGS)
2AM_LDFLAGS = $(libusb_LIBS) -lpthread -lrt
3
4# Libraries
5
6noinst_LTLIBRARIES = libusbmux.la libsock_stuff.la
7libsock_stuff_la_SOURCES = sock_stuff.c \
8 sock_stuff.h
9
10libusbmux_la_SOURCES = usbmux.c \
11 usbmux.h
12libusbmux_la_CFLAGS = $(AM_CFLAGS)
13libusbmux_la_LDFLAGS = $(AM_LDFLAGS)
14
15lib_LTLIBRARIES = libusbmuxd.la
16libusbmuxd_la_SOURCES = libusbmuxd.c \
17 usbmuxd.h \
18 usbmuxd-proto.h
19libusbmuxd_la_LIBADD = libsock_stuff.la
20
21include_HEADERS = usbmuxd.h \
22 usbmuxd-proto.h
23
24# Programs
25
26sbin_PROGRAMS = usbmuxd
27
28usbmuxd_SOURCES = main.c
29usbmuxd_LDADD = libusbmux.la \
30 libsock_stuff.la
31
diff --git a/src/libusbmuxd.c b/src/libusbmuxd.c
deleted file mode 100644
index 4cd0a6d..0000000
--- a/src/libusbmuxd.c
+++ /dev/null
@@ -1,248 +0,0 @@
1#include <stdint.h>
2#include <stdlib.h>
3#include <errno.h>
4#include <stdio.h>
5#include <string.h>
6#include <sys/socket.h>
7#include <arpa/inet.h>
8#include <unistd.h>
9
10// usbmuxd public interface
11#include <usbmuxd.h>
12// usbmuxd protocol
13#include <usbmuxd-proto.h>
14// socket utility functions
15#include "sock_stuff.h"
16
17static int usbmuxd_get_result(int sfd, uint32_t tag, uint32_t * result)
18{
19 struct usbmuxd_result res;
20 int recv_len;
21
22 if (!result) {
23 return -EINVAL;
24 }
25
26 if ((recv_len = recv_buf(sfd, &res, sizeof(res))) <= 0) {
27 perror("recv");
28 return -errno;
29 } else {
30 if ((recv_len == sizeof(res))
31 && (res.header.length == (uint32_t) recv_len)
32 && (res.header.reserved == 0)
33 && (res.header.type == USBMUXD_RESULT)
34 ) {
35 *result = res.result;
36 if (res.header.tag == tag) {
37 return 1;
38 } else {
39 return 0;
40 }
41 }
42 }
43
44 return -1;
45}
46
47int usbmuxd_scan(usbmuxd_scan_result ** available_devices)
48{
49 struct usbmuxd_scan_request s_req;
50 int sfd;
51 int scan_success = 0;
52 uint32_t res;
53 uint32_t pktlen;
54 int recv_len;
55 usbmuxd_scan_result *newlist = NULL;
56 struct usbmuxd_device_info_record dev_info_pkt;
57 int dev_cnt = 0;
58
59 sfd = connect_unix_socket(USBMUXD_SOCKET_FILE);
60 if (sfd < 0) {
61 fprintf(stderr, "%s: error opening socket!\n", __func__);
62 return sfd;
63 }
64
65 s_req.header.length = sizeof(struct usbmuxd_scan_request);
66 s_req.header.reserved = 0;
67 s_req.header.type = USBMUXD_SCAN;
68 s_req.header.tag = 2;
69
70 // send scan request packet
71 if (send_buf(sfd, &s_req, s_req.header.length) ==
72 (int) s_req.header.length) {
73 res = -1;
74 // get response
75 if (usbmuxd_get_result(sfd, s_req.header.tag, &res) && (res == 0)) {
76 scan_success = 1;
77 } else {
78 fprintf(stderr,
79 "%s: Did not get response to scan request (with result=0)...\n",
80 __func__);
81 close(sfd);
82 return res;
83 }
84 }
85
86 if (!scan_success) {
87 fprintf(stderr, "%s: Could not send scan request!\n", __func__);
88 return -1;
89 }
90
91 *available_devices = NULL;
92 // receive device list
93 while (1) {
94 if (recv_buf_timeout(sfd, &pktlen, 4, MSG_PEEK, 1000) == 4) {
95 if (pktlen != sizeof(dev_info_pkt)) {
96 // invalid packet size received!
97 fprintf(stderr,
98 "%s: Invalid packet size (%d) received when expecting a device info record.\n",
99 __func__, pktlen);
100 break;
101 }
102
103 recv_len = recv_buf(sfd, &dev_info_pkt, pktlen);
104 if (recv_len <= 0) {
105 fprintf(stderr,
106 "%s: Error when receiving device info record\n",
107 __func__);
108 break;
109 } else if ((uint32_t) recv_len < pktlen) {
110 fprintf(stderr,
111 "%s: received less data than specified in header!\n",
112 __func__);
113 } else {
114 //fprintf(stderr, "%s: got device record with id %d, UUID=%s\n", __func__, dev_info_pkt.device_info.device_id, dev_info_pkt.device_info.serial_number);
115 newlist =
116 (usbmuxd_scan_result *) realloc(*available_devices,
117 sizeof
118 (usbmuxd_scan_result) *
119 (dev_cnt + 1));
120 if (newlist) {
121 newlist[dev_cnt].handle =
122 (int) dev_info_pkt.device.device_id;
123 newlist[dev_cnt].product_id =
124 dev_info_pkt.device.product_id;
125 memset(newlist[dev_cnt].serial_number, '\0',
126 sizeof(newlist[dev_cnt].serial_number));
127 memcpy(newlist[dev_cnt].serial_number,
128 dev_info_pkt.device.serial_number,
129 sizeof(dev_info_pkt.device.serial_number));
130 *available_devices = newlist;
131 dev_cnt++;
132 } else {
133 fprintf(stderr,
134 "%s: ERROR: out of memory when trying to realloc!\n",
135 __func__);
136 break;
137 }
138 }
139 } else {
140 // we _should_ have all of them now.
141 // or perhaps an error occured.
142 break;
143 }
144 }
145
146 // terminating zero record
147 newlist =
148 (usbmuxd_scan_result *) realloc(*available_devices,
149 sizeof(usbmuxd_scan_result) *
150 (dev_cnt + 1));
151 memset(newlist + dev_cnt, 0, sizeof(usbmuxd_scan_result));
152 *available_devices = newlist;
153
154 return dev_cnt;
155}
156
157int usbmuxd_connect(const int handle, const unsigned short tcp_port)
158{
159 int sfd;
160 struct usbmuxd_connect_request c_req;
161 int connected = 0;
162 uint32_t res = -1;
163
164 sfd = connect_unix_socket(USBMUXD_SOCKET_FILE);
165 if (sfd < 0) {
166 fprintf(stderr, "%s: Error: Connection to usbmuxd failed: %s\n",
167 __func__, strerror(errno));
168 return sfd;
169 }
170
171 c_req.header.length = sizeof(c_req);
172 c_req.header.reserved = 0;
173 c_req.header.type = USBMUXD_CONNECT;
174 c_req.header.tag = 3;
175 c_req.device_id = (uint32_t) handle;
176 c_req.tcp_dport = htons(tcp_port);
177 c_req.reserved = 0;
178
179 if (send_buf(sfd, &c_req, sizeof(c_req)) < 0) {
180 perror("send");
181 } else {
182 // read ACK
183 //fprintf(stderr, "%s: Reading connect result...\n", __func__);
184 if (usbmuxd_get_result(sfd, c_req.header.tag, &res)) {
185 if (res == 0) {
186 //fprintf(stderr, "%s: Connect success!\n", __func__);
187 connected = 1;
188 } else {
189 fprintf(stderr, "%s: Connect failed, Error code=%d\n",
190 __func__, res);
191 }
192 }
193 }
194
195 if (connected) {
196 return sfd;
197 }
198
199 close(sfd);
200
201 return -1;
202}
203
204int usbmuxd_disconnect(int sfd)
205{
206 return close(sfd);
207}
208
209int usbmuxd_send(int sfd, const char *data, uint32_t len, uint32_t *sent_bytes)
210{
211 int num_sent;
212
213 if (sfd < 0) {
214 return -EINVAL;
215 }
216
217 num_sent = send(sfd, (void*)data, len, 0);
218 if (num_sent < 0) {
219 *sent_bytes = 0;
220 fprintf(stderr, "%s: Error %d when sending: %s\n", __func__, num_sent, strerror(errno));
221 return num_sent;
222 } else if ((uint32_t)num_sent < len) {
223 fprintf(stderr, "%s: Warning: Did not send enough (only %d of %d)\n", __func__, num_sent, len);
224 }
225
226 *sent_bytes = num_sent;
227
228 return 0;
229}
230
231int usbmuxd_recv_timeout(int sfd, char *data, uint32_t len, uint32_t *recv_bytes, unsigned int timeout)
232{
233 int num_recv = recv_buf_timeout(sfd, (void*)data, len, 0, timeout);
234 if (num_recv < 0) {
235 *recv_bytes = 0;
236 return num_recv;
237 }
238
239 *recv_bytes = num_recv;
240
241 return 0;
242}
243
244int usbmuxd_recv(int sfd, char *data, uint32_t len, uint32_t *recv_bytes)
245{
246 return usbmuxd_recv_timeout(sfd, data, len, recv_bytes, 5000);
247}
248
diff --git a/src/main.c b/src/main.c
deleted file mode 100644
index 19649b1..0000000
--- a/src/main.c
+++ /dev/null
@@ -1,1447 +0,0 @@
1/*
2 * usbmuxd -- daemon for communication with iPhone/iPod via USB
3 *
4 * Copyright (c) 2009 Nikias Bassen. All Rights Reserved.
5 * Based upon iTunnel source code, Copyright (c) 2008 Jing Su.
6 * http://www.cs.toronto.edu/~jingsu/itunnel/
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22#include <stddef.h>
23#include <stdio.h>
24#include <errno.h>
25#include <stdlib.h>
26#include <string.h>
27#include <getopt.h>
28#include <stdarg.h>
29#include <syslog.h>
30#include <fcntl.h>
31#include <sys/socket.h>
32#include <sys/un.h>
33#include <sys/stat.h>
34#include <arpa/inet.h>
35#include <unistd.h>
36#include <signal.h>
37#include <pthread.h>
38#include <stdint.h>
39#include <usb.h>
40#include <pwd.h>
41
42#include "usbmuxd-proto.h"
43#include "sock_stuff.h"
44
45#include "usbmux.h"
46
47#define DEFAULT_TIMEOUT 4000
48#define DEFAULT_CHILDREN_CAPACITY 10
49#define DEBUG_LEVEL 0
50
51#define LOCKFILE "/var/run/usbmuxd.lock"
52
53#define THREAD (unsigned int)pthread_self()
54
55static int quit_flag = 0;
56static int fsock = -1;
57static int verbose = DEBUG_LEVEL;
58static int foreground = 0;
59static int exit_on_no_devices = 0;
60static int drop_privileges = 0;
61static int opt_udev = 0;
62static int opt_exit = 0;
63static int exit_signal = 0;
64
65struct device_info {
66 uint32_t device_id;
67 usbmux_device_t phone;
68 int use_count;
69 pthread_t bulk_reader;
70 pthread_mutex_t mutex;
71 /* mutex for mutual exclusion of calling the usbmux_send function
72 * TODO: I don't know if we need really need this? */
73 pthread_mutex_t writer_mutex;
74};
75
76struct client_data {
77 volatile int dead;
78 int socket;
79 int tag;
80 pthread_t thread;
81 pthread_t handler;
82 pthread_t reader;
83 int reader_quit;
84 int reader_dead;
85 int handler_dead;
86 int connected;
87 usbmux_client_t muxclient;
88 struct device_info *dev;
89};
90
91static struct device_info **devices = NULL;
92static int device_count = 0;
93static pthread_mutex_t usbmux_mutex = PTHREAD_MUTEX_INITIALIZER;
94static pthread_mutex_t usb_mutex = PTHREAD_MUTEX_INITIALIZER;
95
96/**
97 * logs a message to syslog when running as daemon or to stdout/stderr when
98 * running in foreground.
99 * @param prio The logging priority.
100 * @param format The message to be printed.
101 */
102static void logmsg(int prio, const char *format, ...)
103{
104 va_list args;
105 va_start(args, format);
106
107 if (!foreground) {
108 // daemon. log using syslog.
109 vsyslog(prio, format, args);
110 } else {
111 // running in foreground. log to stdout/stderr.
112 char msgbuf[256];
113 FILE *lfp = stdout;
114 switch (prio) {
115 case LOG_EMERG:
116 case LOG_ALERT:
117 case LOG_CRIT:
118 case LOG_ERR:
119 case LOG_WARNING:
120 lfp = stderr;
121 break;
122 default:
123 lfp = stdout;
124 }
125 strcpy(msgbuf, "usbmuxd: ");
126 vsnprintf(msgbuf + 9, 244, format, args);
127 strcat(msgbuf, "\n");
128 fputs(msgbuf, lfp);
129 }
130
131 va_end(args);
132}
133
134#ifdef DEBUG
135/**
136 * for debugging purposes.
137 */
138static void print_buffer(FILE * fp, const char *data, const int length)
139{
140 int i;
141 int j;
142 unsigned char c;
143
144 for (i = 0; i < length; i += 16) {
145 if (verbose >= 4)
146 fprintf(fp, "%04x: ", i);
147 for (j = 0; j < 16; j++) {
148 if (i + j >= length) {
149 if (verbose >= 4)
150 fprintf(fp, " ");
151 continue;
152 }
153 if (verbose >= 4)
154 fprintf(fp, "%02hhx ", *(data + i + j));
155 }
156 if (verbose >= 4)
157 fprintf(fp, " | ");
158 for (j = 0; j < 16; j++) {
159 if (i + j >= length)
160 break;
161 c = *(data + i + j);
162 if ((c < 32) || (c > 127)) {
163 if (verbose >= 4)
164 fprintf(fp, ".");
165 continue;
166 }
167 if (verbose >= 4)
168 fprintf(fp, "%c", c);
169 }
170 if (verbose >= 4)
171 fprintf(fp, "\n");
172 }
173 if (verbose >= 4)
174 fprintf(fp, "\n");
175}
176#endif
177
178/**
179 * Read incoming usbmuxd packet. If the packet is larger than
180 * the size specified by len, the data will be truncated.
181 *
182 * @param fd the file descriptor to read from.
183 * @param data pointer to a buffer to store the read data to.
184 * @param len the length of the data to be read. The buffer
185 * pointed to by data should be at least len bytes in size.
186 *
187 * @return
188 */
189static int usbmuxd_get_request(int fd, void **data, size_t len)
190{
191 uint32_t pktlen;
192 int recv_len;
193
194 if (peek_buf(fd, &pktlen, sizeof(pktlen)) < (int) sizeof(pktlen)) {
195 return -errno;
196 }
197
198 if (len == 0) {
199 // allocate buffer space
200 *data = malloc(pktlen);
201 } else if (len < pktlen) {
202 // target buffer is to small to hold this packet! fix it!
203 if (verbose >= 2)
204 logmsg(LOG_WARNING,
205 "%s: WARNING -- packet (%d) is larger than target buffer (%d)! Truncating.",
206 __func__, pktlen, len);
207 pktlen = len;
208 }
209
210 recv_len = recv_buf(fd, *data, pktlen);
211 if ((recv_len > 0) && ((uint32_t) recv_len < pktlen)) {
212 if (verbose >= 2)
213 logmsg(LOG_WARNING,
214 "%s: Uh-oh, we got less than the packet's size, %d instead of %d...",
215 __func__, recv_len, pktlen);
216 }
217#ifdef DEBUG
218 if (*data && (recv_len > 0) && verbose >= 4) {
219 fprintf(stderr, "%s: received:\n", __func__);
220 print_buffer(stderr, *data, recv_len);
221 }
222#endif
223
224 return recv_len;
225}
226
227/**
228 * Send a usbmuxd result packet with given tag and result_code.
229 *
230 * @param fd the file descriptor to write to.
231 * @param tag the tag value that identifies where this message belongs to.
232 * @param result_code the error value (0 = Success, most likely errno values otherwise)
233 *
234 * @return the return value returned by send_buf (normally the number of bytes sent)
235 */
236static int usbmuxd_send_result(int fd, uint32_t tag, uint32_t result_code)
237{
238 struct usbmuxd_result res;
239 int ret;
240
241 res.header.length = sizeof(res);
242 res.header.reserved = 0;
243 res.header.type = USBMUXD_RESULT;
244 res.header.tag = tag;
245 res.result = result_code;
246
247 if (verbose >= 4)
248 logmsg(LOG_NOTICE, "%s: tag=%d result=%d", __func__,
249 res.header.tag, res.result);
250
251 ret = send_buf(fd, &res, sizeof(res));
252 fsync(fd); // let's get it sent
253 return ret;
254}
255
256/**
257 * this thread reads from the usb connection and writes the
258 * data to the connected client.
259 *
260 * @param arg pointer to a client_data structure.
261 *
262 * @return NULL in any case
263 */
264static void *usbmuxd_client_reader_thread(void *arg)
265{
266 struct client_data *cdata;
267
268 char rbuffer[512];
269 uint32_t rbuffersize = 512;
270 uint32_t rlen;
271 int err;
272 char *cursor;
273 ssize_t len;
274 int result;
275
276 if (!arg) {
277 if (verbose >= 2)
278 logmsg(LOG_ERR, "%s: invalid client_data supplied!", __func__);
279 cdata->reader_dead = 1;
280 return NULL;
281 }
282
283 cdata = (struct client_data *) arg;
284
285 cdata->reader_dead = 0;
286
287 if (verbose >= 3)
288 logmsg(LOG_NOTICE, "%s[%x]: started (device %d:%d, use_count=%d)", __func__, THREAD,
289 cdata->dev->device_id >> 16, cdata->dev->device_id & 0xFFFF, cdata->dev->use_count);
290
291 while (!quit_flag && !cdata->reader_quit) {
292 result = check_fd(cdata->socket, FD_WRITE, DEFAULT_TIMEOUT);
293 if (result <= 0) {
294 if (result < 0) {
295 if (verbose >= 2)
296 logmsg(LOG_ERR, "%s: select error: %s", __func__,
297 strerror(errno));
298 }
299 continue;
300 }
301
302 rlen = 0;
303 err =
304 usbmux_recv_timeout(cdata->muxclient, rbuffer, rbuffersize,
305 &rlen, DEFAULT_TIMEOUT);
306 if (err != 0) {
307 if (verbose >= 2)
308 logmsg(LOG_ERR,
309 "%s[%x]: encountered USB read error: %d",
310 __func__, THREAD, err);
311 break;
312 }
313
314 cursor = rbuffer;
315 while (rlen > 0) {
316 len = send_buf(cdata->socket, cursor, rlen);
317 if (len <= 0) {
318 logmsg(LOG_ERR, "%s: Error: send returned %d", __func__,
319 len);
320 err = 1;
321 break;
322 }
323 // calculate remainder
324 rlen -= len;
325 // advance cursor
326 cursor += len;
327 }
328 if (err != 0) {
329 logmsg(LOG_ERR, "%s: Error when writing to client...",
330 __func__);
331 break;
332 }
333 fsync(cdata->socket);
334 }
335
336 if (verbose >= 3)
337 logmsg(LOG_NOTICE, "%s[%x]: terminated", __func__, THREAD);
338
339 cdata->reader_dead = 1;
340
341 return NULL;
342}
343
344/**
345 * This function handles the connecting procedure to a previously
346 * set up usbmux client.
347 * Sends a usbmuxd result packet denoting success or failure.
348 * A successful result is mandatory for later communication.
349 *
350 * @param cdata pointer to a previously initialized client_data structure
351 *
352 * @return
353 */
354static int usbmuxd_handleConnectResult(struct client_data *cdata)
355{
356 int result;
357 char buffer[512];
358 char err_type[64];
359 int err_code;
360 ssize_t maxlen = 512;
361 uint32_t rlen;
362 int err;
363
364 if (!cdata) {
365 if (verbose >= 2)
366 logmsg(LOG_ERR, "%s: Invalid client_data provided!", __func__);
367 return -EINVAL;
368 }
369
370 result = check_fd(cdata->socket, FD_WRITE, DEFAULT_TIMEOUT);
371 if (result <= 0) {
372 if (result < 0) {
373 if (verbose >= 2)
374 logmsg(LOG_ERR, "%s: select error: %s", __func__,
375 strerror(errno));
376 return result;
377 }
378 } else {
379 result = 0;
380 err =
381 usbmux_recv_timeout(cdata->muxclient, buffer, maxlen, &rlen,
382 100);
383 if (err < 0) {
384 if (verbose >= 2)
385 logmsg(LOG_ERR, "%s: encountered USB read error: %d",
386 __func__, err);
387 usbmuxd_send_result(cdata->socket, cdata->tag, -err);
388 return err;
389 } else {
390 if (rlen > 0) {
391 if ((buffer[0] == 1) && (rlen > 20)
392 && !memcmp(buffer + 1, "handleConnectResult:", 20)) {
393 // hm... we got an error message!
394 buffer[rlen] = 0;
395 if (verbose >= 1)
396 logmsg(LOG_ERR, "%s: %s\n", __func__, buffer + 22);
397
398 if (sscanf
399 (buffer + 22, "%s - %d\n", err_type, &err_code)
400 == 2) {
401 usbmuxd_send_result(cdata->socket, cdata->tag,
402 err_code);
403 return -err_code;
404 } else {
405 usbmuxd_send_result(cdata->socket, cdata->tag,
406 ENODATA);
407 return -ENODATA;
408 }
409 } else {
410 // send success result
411 usbmuxd_send_result(cdata->socket, cdata->tag, 0);
412 // and the server greeting message
413 send_buf(cdata->socket, buffer, rlen);
414 }
415 } else {
416 // no server greeting? this seems to be ok. send success.
417 usbmuxd_send_result(cdata->socket, cdata->tag, 0);
418 }
419 }
420 //fsync(cdata->socket);
421 }
422 return result;
423}
424
425/**
426 * This thread handles the communication between the connected iPhone/iPod
427 * and the client that created the connection.
428 */
429static void *usbmuxd_client_handler_thread(void *arg)
430{
431 struct client_data *cdata;
432 int result;
433 char *cursor;
434 char buffer[32740];
435 ssize_t len;
436 ssize_t maxlen = sizeof(buffer);
437 uint32_t wlen;
438 int err;
439
440 if (!arg) {
441 if (verbose >= 2)
442 logmsg(LOG_ERR, "%s: invalid client_data provided!", __func__);
443 return NULL;
444 }
445
446 cdata = (struct client_data *) arg;
447
448 if (verbose >= 3)
449 logmsg(LOG_NOTICE, "%s[%x]: started (device %d:%d, use_count=%d)", __func__, THREAD,
450 cdata->dev->device_id >> 16, cdata->dev->device_id & 0xFFFF, cdata->dev->use_count);
451
452 if (usbmuxd_handleConnectResult(cdata)) {
453 if (verbose >= 3)
454 logmsg(LOG_ERR, "handleConnectResult: Error");
455 goto leave;
456 } else {
457 if (verbose >= 3)
458 logmsg(LOG_NOTICE, "handleConnectResult: Success");
459 }
460
461 // starting mux reader thread
462 cdata->reader_quit = 0;
463 cdata->reader_dead = 0;
464 if (pthread_create
465 (&cdata->reader, NULL, usbmuxd_client_reader_thread, cdata) != 0) {
466 if (verbose >= 2)
467 logmsg(LOG_ERR, "%s: could not start client_reader thread",
468 __func__);
469 cdata->reader = 0;
470 }
471
472 while (!quit_flag && !cdata->reader_dead) {
473 result = check_fd(cdata->socket, FD_READ, DEFAULT_TIMEOUT);
474 if (result <= 0) {
475 if (result < 0) {
476 if (verbose >= 3)
477 logmsg(LOG_ERR, "%s[%x]: Error: checkfd: %s", __func__, THREAD, strerror(errno));
478 }
479 continue;
480 }
481 // check_fd told us there's data available, so read from client
482 // and push to USB device.
483 len = recv(cdata->socket, buffer, maxlen, 0);
484 if (len == 0) {
485 break;
486 }
487 if (len < 0) {
488 if (verbose >= 2)
489 logmsg(LOG_ERR, "%s[%x]: Error: recv: %s", __func__, THREAD, strerror(errno));
490 break;
491 }
492
493 cursor = buffer;
494
495 pthread_mutex_lock(&cdata->dev->writer_mutex);
496 do {
497 wlen = 0;
498 err = usbmux_send(cdata->muxclient, cursor, len, &wlen);
499 if (err == -ETIMEDOUT) {
500 // some kind of timeout... just be patient and retry.
501 } else if (err < 0) {
502 if (verbose >= 2)
503 logmsg(LOG_ERR, "%s[%x]: USB write error: %d", __func__, THREAD, err);
504 len = -1;
505 break;
506 }
507 // calculate remainder.
508 len -= wlen;
509 // advance cursor appropiately.
510 cursor += wlen;
511 }
512 while ((len > 0) && !quit_flag);
513 pthread_mutex_unlock(&cdata->dev->writer_mutex);
514 if (len < 0) {
515 break;
516 }
517 }
518
519 leave:
520 // cleanup
521 if (verbose >= 3)
522 logmsg(LOG_NOTICE, "%s[%x]: terminating", __func__, THREAD);
523 if (cdata->reader != 0) {
524 cdata->reader_quit = 1;
525 pthread_join(cdata->reader, NULL);
526 }
527
528 cdata->handler_dead = 1;
529
530 if (verbose >= 3)
531 logmsg(LOG_NOTICE, "%s[%x]: terminated", __func__, THREAD);
532 return NULL;
533}
534
535/**
536 * Thread performing usb_bulk_read from the connected device.
537 * One thread per device. Lives as long as the device is in use.
538 */
539static void *usbmuxd_bulk_reader_thread(void *arg)
540{
541 struct device_info *cur_dev;
542 int err;
543
544 if (!arg) {
545 if (verbose >= 2)
546 logmsg(LOG_ERR, "%s: Invalid client_data provided", __func__);
547 return NULL;
548 }
549
550 cur_dev = (struct device_info *) arg;
551
552 if (verbose >= 3)
553 logmsg(LOG_NOTICE, "%s: started", __func__);
554
555 while (!quit_flag && cur_dev) {
556
557 pthread_mutex_lock(&cur_dev->mutex);
558 if (cur_dev->use_count <= 0) {
559 pthread_mutex_unlock(&cur_dev->mutex);
560 break;
561 }
562 pthread_mutex_unlock(&cur_dev->mutex);
563
564 if ((err = usbmux_pullbulk(cur_dev->phone)) < 0) {
565 if (verbose >= 1)
566 logmsg(LOG_ERR, "%s: error %d when reading from device",
567 __func__, err);
568 break;
569 }
570 }
571
572 if (verbose >= 3)
573 logmsg(LOG_NOTICE, "%s: terminated", __func__);
574
575 return NULL;
576}
577
578/**
579 * This thread is started when a new connection is accepted.
580 * It performs the handshake, then waits for the connect packet and
581 * on success it starts the usbmuxd_client_handler thread.
582 */
583static void *usbmuxd_client_init_thread(void *arg)
584{
585 struct client_data *cdata;
586 struct usbmuxd_scan_request *s_req;
587 struct usbmuxd_device_info_record dev_info_rec;
588 struct usbmuxd_connect_request *c_req = NULL;
589
590 struct usb_bus *bus;
591 struct usb_device *dev;
592
593 int recv_len;
594 int found = 0;
595 int res;
596 int i;
597
598 usbmux_device_t phone = NULL;
599 struct device_info *cur_dev = NULL;
600
601 if (!arg) {
602 if (verbose >= 1)
603 logmsg(LOG_ERR, "%s[%x]: invalid client_data provided!",
604 __func__, THREAD);
605 return NULL;
606 }
607
608 cdata = (struct client_data *) arg;
609 cdata->dead = 0;
610
611 if (verbose >= 3)
612 logmsg(LOG_NOTICE, "%s[%x]: started (fd=%d)", __func__, THREAD,
613 cdata->socket);
614
615 if ((recv_len =
616 usbmuxd_get_request(cdata->socket, (void **) &s_req, 0)) <= 0) {
617 if (verbose >= 2)
618 logmsg(LOG_ERR, "%s[%x]: No scan packet received, error %s",
619 __func__, THREAD, strerror(errno));
620 goto leave;
621 }
622
623 if ((recv_len == sizeof(struct usbmuxd_scan_request))
624 && (s_req->header.length == sizeof(struct usbmuxd_scan_request))
625 && (s_req->header.reserved == 0)
626 && (s_req->header.type == USBMUXD_SCAN)) {
627 // send success response
628 if (verbose >= 3)
629 logmsg(LOG_NOTICE, "%s[%x]: Got scan packet!", __func__,
630 THREAD);
631 usbmuxd_send_result(cdata->socket, s_req->header.tag, 0);
632 } else if ((recv_len == sizeof(struct usbmuxd_connect_request))
633 && (s_req->header.type == USBMUXD_CONNECT)) {
634 c_req = (struct usbmuxd_connect_request *) s_req;
635 s_req = NULL;
636 goto connect;
637 } else {
638 // send error response and exit
639 if (verbose >= 2)
640 logmsg(LOG_ERR, "%s[%x]: Invalid scan packet received.",
641 __func__, THREAD);
642 // TODO is this required?!
643 usbmuxd_send_result(cdata->socket, s_req->header.tag, EINVAL);
644 goto leave;
645 }
646
647 pthread_mutex_lock(&usb_mutex);
648 // gather data about all iPhones/iPods attached
649
650 if (verbose >= 5)
651 logmsg(LOG_DEBUG, "%s[%x]: usb init", __func__, THREAD);
652 usb_init();
653 if (verbose >= 5)
654 logmsg(LOG_DEBUG, "%s[%x]: usb find busses", __func__, THREAD);
655 usb_find_busses();
656 if (verbose >= 5)
657 logmsg(LOG_DEBUG, "%s[%x]: usb find devices", __func__, THREAD);
658 usb_find_devices();
659
660 if (verbose >= 2)
661 logmsg(LOG_NOTICE, "%s[%x]: Looking for attached devices...",
662 __func__, THREAD);
663
664 for (bus = usb_get_busses(); bus; bus = bus->next) {
665 for (dev = bus->devices; dev; dev = dev->next) {
666 if (dev->descriptor.idVendor == 0x05ac
667 && dev->descriptor.idProduct >= 0x1290
668 && dev->descriptor.idProduct <= 0x1294) {
669 if (verbose >= 1)
670 logmsg(LOG_NOTICE,
671 "%s[%x]: Found device on bus %s, id %s",
672 __func__, THREAD, bus->dirname, dev->filename);
673 found++;
674
675 // construct packet
676 memset(&dev_info_rec, 0, sizeof(dev_info_rec));
677 dev_info_rec.header.length = sizeof(dev_info_rec);
678 dev_info_rec.header.type = USBMUXD_DEVICE_INFO;
679 uint32_t dev_id =
680 strtol(dev->filename, NULL, 10)
681 + (strtoul(bus->dirname, NULL, 10) << 16);
682 dev_info_rec.device.device_id = dev_id;
683 dev_info_rec.device.product_id = dev->descriptor.idProduct;
684 if (dev->descriptor.iSerialNumber) {
685 usb_dev_handle *udev;
686 //pthread_mutex_lock(&usbmux_mutex);
687 udev = usb_open(dev);
688 if (udev) {
689 usb_get_string_simple(udev,
690 dev->descriptor.iSerialNumber,
691 dev_info_rec.device.serial_number,
692 sizeof(dev_info_rec.device.serial_number) + 1);
693 usb_close(udev);
694 } else {
695 logmsg(LOG_ERR, "%s[%x]: Error: usb_open(): %s\n", __func__, THREAD, usb_strerror());
696 }
697 //pthread_mutex_unlock(&usbmux_mutex);
698 }
699#ifdef DEBUG
700 if (verbose >= 4)
701 print_buffer(stderr, (char *) &dev_info_rec,
702 sizeof(dev_info_rec));
703#endif
704
705 // send it
706 if (send_buf
707 (cdata->socket, &dev_info_rec,
708 sizeof(dev_info_rec)) <= 0) {
709 if (verbose >= 3)
710 logmsg(LOG_ERR,
711 "%s[%x]: Error: Could not send device info: %s",
712 __func__, THREAD, strerror(errno));
713 found--;
714 }
715 }
716 }
717 }
718 pthread_mutex_unlock(&usb_mutex);
719
720 if (found <= 0) {
721 if (verbose >= 1)
722 logmsg(LOG_NOTICE,
723 "%s[%x]: No attached iPhone/iPod devices found.",
724 __func__, THREAD);
725 usbmuxd_send_result(cdata->socket, s_req->header.tag, -ENODEV);
726 goto leave;
727 }
728
729 goto leave;
730
731/* if (verbose >= 3)
732 logmsg(LOG_NOTICE, "%s[%x]: Waiting for connect request", __func__,
733 THREAD);
734
735 // now wait for connect request
736 //memset(&c_req, 0, sizeof(c_req));
737 if ((recv_len =
738 usbmuxd_get_request(cdata->socket, (void **) &c_req, 0)) <= 0) {
739 if (verbose >= 3)
740 logmsg(LOG_NOTICE,
741 "%s[%x]: Did not receive any connect request.",
742 __func__, THREAD);
743 goto leave;
744 }*/
745
746 connect:
747
748 if (c_req->header.type != USBMUXD_CONNECT) {
749 if (verbose >= 2)
750 logmsg(LOG_ERR,
751 "%s[%x]: Unexpected packet of type %d received.",
752 __func__, THREAD, c_req->header.type);
753 goto leave;
754 }
755
756 if (verbose >= 3)
757 logmsg(LOG_NOTICE,
758 "%s[%x]: Setting up connection to usb device %d:%d on port %d",
759 __func__, THREAD, c_req->device_id >> 16, c_req->device_id & 0xFFFF, ntohs(c_req->tcp_dport));
760
761 // find the device, and open usb connection
762 pthread_mutex_lock(&usbmux_mutex);
763 phone = NULL;
764 cur_dev = NULL;
765 // first check if we already have an open connection
766 if (devices) {
767 for (i = 0; i < device_count; i++) {
768 if (devices[i]) {
769 if (devices[i]->device_id == c_req->device_id) {
770 devices[i]->use_count++;
771 cur_dev = devices[i];
772 phone = cur_dev->phone;
773 break;
774 }
775 }
776 }
777 }
778 if (!phone) {
779 // if not found, make a new connection
780 if (verbose >= 2)
781 logmsg(LOG_NOTICE,
782 "%s[%x]: creating new usb connection, device %d:%d",
783 __func__, THREAD, c_req->device_id >> 16, c_req->device_id & 0xFFFF);
784
785 pthread_mutex_lock(&usb_mutex);
786 if (usbmux_get_specific_device(c_req->device_id >> 16, c_req->device_id & 0xFFFF, &phone) < 0) {
787 pthread_mutex_unlock(&usb_mutex);
788 pthread_mutex_unlock(&usbmux_mutex);
789 if (verbose >= 1)
790 logmsg(LOG_ERR, "%s[%x]: device %d:%d could not be opened",
791 __func__, THREAD, c_req->device_id >> 16, c_req->device_id & 0xFFFF);
792 usbmuxd_send_result(cdata->socket, c_req->header.tag, ENODEV);
793 goto leave;
794 }
795 pthread_mutex_unlock(&usb_mutex);
796
797 // create device object
798 if (verbose >= 3)
799 logmsg(LOG_DEBUG, "%s[%x]: add to device list", __func__,
800 THREAD);
801 cur_dev =
802 (struct device_info *) malloc(sizeof(struct device_info));
803 memset(cur_dev, 0, sizeof(struct device_info));
804 cur_dev->use_count = 1;
805 cur_dev->device_id = c_req->device_id;
806 cur_dev->phone = phone;
807 cur_dev->bulk_reader = 0;
808 pthread_mutex_init(&cur_dev->mutex, NULL);
809 pthread_mutex_init(&cur_dev->writer_mutex, NULL);
810
811 if (verbose >= 3)
812 logmsg(LOG_DEBUG, "%s[%x]: device_count = %d", __func__,
813 THREAD, device_count);
814
815 // add to list of devices
816 devices =
817 (struct device_info **) realloc(devices,
818 sizeof(struct device_info *) *
819 (device_count + 1));
820 if (devices) {
821 devices[device_count] = cur_dev;
822 device_count++;
823 }
824 } else {
825 if (verbose >= 2)
826 logmsg(LOG_NOTICE,
827 "%s[%x]: reusing usb connection, device %d:%d",
828 __func__, THREAD, c_req->device_id >> 16, c_req->device_id & 0xFFFF);
829 }
830 pthread_mutex_unlock(&usbmux_mutex);
831
832 // setup connection to iPhone/iPod
833 pthread_mutex_lock(&cur_dev->writer_mutex);
834 res =
835 usbmux_new_client(cur_dev->phone, 0, ntohs(c_req->tcp_dport),
836 &(cdata->muxclient));
837 pthread_mutex_unlock(&cur_dev->writer_mutex);
838
839 if (res != 0) {
840 usbmuxd_send_result(cdata->socket, c_req->header.tag, res);
841 if (verbose >= 1)
842 logmsg(LOG_ERR,
843 "%s[%x]: mux_new_client returned %d, aborting.",
844 __func__, THREAD, res);
845 goto leave;
846 }
847 // start bulk reader thread (once per device)
848 pthread_mutex_lock(&cur_dev->mutex);
849 if (cur_dev->bulk_reader == 0) {
850 pthread_create(&cur_dev->bulk_reader, NULL,
851 usbmuxd_bulk_reader_thread, cur_dev);
852 }
853 pthread_mutex_unlock(&cur_dev->mutex);
854
855 // wait for the initial handshake (SYN->SYN+ACK->ACK) to complete)
856 struct timespec ts;
857 ts.tv_sec = 0;
858 ts.tv_nsec = 100000000;
859
860 i = 0;
861 while (i < 10000) {
862 if (usbmux_is_connected(cdata->muxclient)) {
863 break;
864 }
865 nanosleep(&ts, NULL);
866 i+=100;
867 }
868 if (!usbmux_is_connected(cdata->muxclient)) {
869 usbmuxd_send_result(cdata->socket, c_req->header.tag, -ENOTCONN);
870 goto leave;
871 }
872
873 // start connection handler thread
874 cdata->handler_dead = 0;
875 cdata->tag = c_req->header.tag;
876 cdata->dev = cur_dev;
877 if (pthread_create
878 (&cdata->handler, NULL, usbmuxd_client_handler_thread, cdata) != 0)
879 {
880 if (verbose >= 1)
881 logmsg(LOG_ERR,
882 "%s[%x]: could not create usbmuxd_client_handler_thread!",
883 __func__, THREAD);
884 cdata->handler = 0;
885 goto leave;
886 }
887 // wait for handler thread to finish its work
888 if (cdata->handler != 0) {
889 pthread_join(cdata->handler, NULL);
890 }
891
892 if (verbose >= 2)
893 logmsg(LOG_NOTICE, "%s[%x]: closing connection", __func__, THREAD);
894
895 // time to clean up
896 if (cdata && cdata->muxclient) { // should be non-NULL
897 pthread_mutex_lock(&cdata->dev->writer_mutex);
898 usbmux_free_client(cdata->muxclient);
899 pthread_mutex_unlock(&cdata->dev->writer_mutex);
900 }
901
902 leave:
903 if (verbose >= 3)
904 logmsg(LOG_NOTICE, "%s[%x]: terminating", __func__, THREAD);
905
906 if (s_req) {
907 free(s_req);
908 }
909 if (c_req) {
910 free(c_req);
911 }
912 // this has to be freed only if it's not in use anymore as it closes
913 // the USB connection
914 pthread_mutex_lock(&usbmux_mutex);
915 if (cur_dev) {
916 pthread_mutex_lock(&cur_dev->mutex);
917 if (cur_dev->use_count > 1) {
918 if (verbose >= 2)
919 logmsg(LOG_NOTICE,
920 "%s[%x]: decreasing device use count (from %d to %d)",
921 __func__, THREAD, cur_dev->use_count,
922 cur_dev->use_count - 1);
923 cur_dev->use_count--;
924 pthread_mutex_unlock(&cur_dev->mutex);
925 } else {
926 if (verbose >= 2)
927 logmsg(LOG_NOTICE,
928 "%s[%x]: last client disconnected, cleaning up",
929 __func__, THREAD);
930 cur_dev->use_count = 0;
931 pthread_mutex_unlock(&cur_dev->mutex);
932 if (cur_dev->bulk_reader != 0) {
933 if (verbose >= 3)
934 logmsg(LOG_NOTICE, "%s[%x]: joining bulk_reader...",
935 __func__, THREAD);
936 pthread_join(cur_dev->bulk_reader, NULL);
937 }
938 pthread_mutex_lock(&usb_mutex);
939 usbmux_free_device(cur_dev->phone);
940 pthread_mutex_unlock(&usb_mutex);
941 pthread_mutex_destroy(&cur_dev->writer_mutex);
942 pthread_mutex_destroy(&cur_dev->mutex);
943 free(cur_dev);
944 cur_dev = NULL;
945 if (device_count > 1) {
946 struct device_info **newlist;
947 int j = 0;
948
949 newlist =
950 (struct device_info **)
951 malloc(sizeof(struct device_info *)
952 * device_count - 1);
953 for (i = 0; i < device_count; i++) {
954 if (devices[i] != NULL) {
955 newlist[j++] = devices[i];
956 }
957 }
958 free(devices);
959 devices = newlist;
960 device_count--;
961 } else {
962 free(devices);
963 devices = NULL;
964 device_count = 0;
965 }
966 }
967 }
968 pthread_mutex_unlock(&usbmux_mutex);
969
970 cdata->dead = 1;
971 close(cdata->socket);
972
973 if (verbose >= 3)
974 logmsg(LOG_NOTICE, "%s[%x]: terminated", __func__, THREAD);
975
976 return NULL;
977}
978
979/**
980 * make this program run detached from the current console
981 */
982static int daemonize()
983{
984 pid_t pid;
985 pid_t sid;
986
987 // already a daemon
988 if (getppid() == 1)
989 return 0;
990
991 pid = fork();
992 if (pid < 0) {
993 exit(EXIT_FAILURE);
994 }
995
996 if (pid > 0) {
997 // exit parent process
998 exit(EXIT_SUCCESS);
999 }
1000 // At this point we are executing as the child process
1001
1002 // Change the file mode mask
1003 umask(0);
1004
1005 // Create a new SID for the child process
1006 sid = setsid();
1007 if (sid < 0) {
1008 return -1;
1009 }
1010 // Change the current working directory.
1011 if ((chdir("/")) < 0) {
1012 return -2;
1013 }
1014 // Redirect standard files to /dev/null
1015 if (!freopen("/dev/null", "r", stdin)) {
1016 logmsg(LOG_ERR, "ERROR: redirection of stdin failed.\n");
1017 }
1018 if (!freopen("/dev/null", "w", stdout)) {
1019 logmsg(LOG_ERR, "ERROR: redirection of stdout failed.\n");
1020 }
1021 if (!freopen("/dev/null", "w", stderr)) {
1022 logmsg(LOG_ERR, "ERROR: redirection of stderr failed.\n");
1023 }
1024
1025 return 0;
1026}
1027
1028static void usage()
1029{
1030 printf("usage: usbmuxd [options]\n");
1031 printf("\t-h|--help print this message\n");
1032 printf("\t-v|--verbose be verbose (use twice or more to increase)\n");
1033 printf("\t-f|--foreground do not daemonize\n");
1034 printf("\t-e|--exit-on-no-devices exit if no device is attached\n");
1035 printf("\t-d|--drop-privileges drop privileges after startup\n");
1036 printf("\t-u|--udev udev operation mode\n");
1037 printf("\t-x|--exit tell a running instance to exit\n");
1038 printf("\t-X|--force-exit tell a running instance to exit, even if\n");
1039 printf("\t there are still devices connected\n");
1040 printf("\n");
1041}
1042
1043static void parse_opts(int argc, char **argv)
1044{
1045 static struct option longopts[] = {
1046 {"help", 0, NULL, 'h'},
1047 {"foreground", 0, NULL, 'f'},
1048 {"verbose", 0, NULL, 'v'},
1049 {"exit-on-no-devices", 0, NULL, 'e'},
1050 {"drop-privileges", 0, NULL, 'd'},
1051 {"udev", 0, NULL, 'u'},
1052 {"exit", 0, NULL, 'x'},
1053 {"force-exit", 0, NULL, 'X'},
1054 {NULL, 0, NULL, 0}
1055 };
1056 int c;
1057
1058 while (1) {
1059 c = getopt_long(argc, argv, "hfveduxX", longopts, (int *) 0);
1060 if (c == -1) {
1061 break;
1062 }
1063
1064 switch (c) {
1065 case 'h':
1066 usage();
1067 exit(0);
1068 case 'f':
1069 foreground = 1;
1070 break;
1071 case 'v':
1072 sock_stuff_set_verbose(++verbose);
1073 break;
1074 case 'e':
1075 exit_on_no_devices = 1;
1076 break;
1077 case 'd':
1078 drop_privileges = 1;
1079 break;
1080 case 'u':
1081 opt_udev = 1;
1082 break;
1083 case 'x':
1084 opt_exit = 1;
1085 exit_signal = SIGQUIT;
1086 break;
1087 case 'X':
1088 opt_exit = 1;
1089 exit_signal = SIGTERM;
1090 break;
1091 default:
1092 usage();
1093 exit(2);
1094 }
1095 }
1096 if (opt_udev)
1097 foreground = 0;
1098}
1099
1100/**
1101 * checks for attached devices
1102 *
1103 * @return number of devices found
1104 */
1105static int devices_attached()
1106{
1107 struct usb_bus *bus;
1108 struct usb_device *dev;
1109 int res = 0;
1110
1111 usb_init();
1112 usb_find_busses();
1113 usb_find_devices();
1114
1115 for (bus = usb_get_busses(); bus; bus = bus->next) {
1116 for (dev = bus->devices; dev; dev = dev->next) {
1117 if (dev->descriptor.idVendor == 0x05ac
1118 && dev->descriptor.idProduct >= 0x1290
1119 && dev->descriptor.idProduct <= 0x1294) {
1120 res++;
1121 }
1122 }
1123 }
1124
1125 return res;
1126}
1127
1128/**
1129 * signal handler function for cleaning up properly
1130 */
1131static void handle_signal(int sig)
1132{
1133 if (sig == SIGTERM) {
1134 quit_flag = 1;
1135 } else {
1136 if (sig == SIGINT) {
1137 if (verbose >= 1)
1138 fprintf(stderr, "CTRL+C pressed\n");
1139 }
1140
1141 if (verbose >= 1)
1142 fprintf(stderr, "Checking if we can terminate (no more devices attached)...\n");
1143
1144 if (devices_attached() > 0) {
1145 // we can't quit, there are still devices attached.
1146 if (verbose >= 1)
1147 fprintf(stderr, "Refusing to terminate, there are still devices attached. Kill me with signal 15 (TERM) to force quit.\n");
1148 } else {
1149 // it's safe to quit
1150 quit_flag = 1;
1151 }
1152 }
1153}
1154
1155/**
1156 * main function. Initializes all stuff and then loops waiting in accept.
1157 */
1158int main(int argc, char **argv)
1159{
1160 struct sockaddr_un c_addr;
1161 socklen_t len = sizeof(struct sockaddr_un);
1162 struct client_data *cdata = NULL;
1163 struct client_data **children = NULL;
1164 int children_capacity = DEFAULT_CHILDREN_CAPACITY;
1165 int i;
1166 int result = 0;
1167 int exit_val = 0;
1168 int cnt = 0;
1169 FILE *lfd = NULL;
1170 struct flock lock;
1171
1172 parse_opts(argc, argv);
1173
1174 argc -= optind;
1175 argv += optind;
1176
1177 if (!foreground) {
1178 openlog("usbmuxd", LOG_PID, 0);
1179 }
1180
1181 if (verbose >= 1)
1182 logmsg(LOG_NOTICE, "starting");
1183
1184 // signal(SIGHUP, reload_conf); // none yet
1185 signal(SIGINT, handle_signal);
1186 signal(SIGQUIT, handle_signal);
1187 signal(SIGTERM, handle_signal);
1188 signal(SIGPIPE, SIG_IGN);
1189
1190 // check for other running instance
1191 lfd = fopen(LOCKFILE, "r");
1192 if (lfd) {
1193 lock.l_type = 0;
1194 lock.l_whence = SEEK_SET;
1195 lock.l_start = 0;
1196 lock.l_len = 0;
1197 fcntl(fileno(lfd), F_GETLK, &lock);
1198 fclose(lfd);
1199 if (lock.l_type != F_UNLCK) {
1200 if (opt_exit) {
1201 if (lock.l_pid && !kill(lock.l_pid, 0)) {
1202 logmsg(LOG_NOTICE, "sending signal %d to instance with pid %d", exit_signal, lock.l_pid);
1203 if (kill(lock.l_pid, exit_signal) < 0) {
1204 logmsg(LOG_ERR, "Error: could not deliver signal %d to pid %d", exit_signal, lock.l_pid);
1205 }
1206 exit_val = 0;
1207 goto terminate;
1208 } else {
1209 logmsg(LOG_ERR, "Error: could not determine pid of the other running instance!");
1210 exit_val = -1;
1211 goto terminate;
1212 }
1213 } else {
1214 logmsg(LOG_NOTICE,
1215 "another instance is already running (pid %d). exiting.", lock.l_pid);
1216 if (!opt_udev) {
1217 exit_val = -1;
1218 }
1219 goto terminate;
1220 }
1221 }
1222 }
1223
1224 if (opt_exit) {
1225 logmsg(LOG_NOTICE, "no running instance found, none killed. exiting.");
1226 goto terminate;
1227 }
1228
1229 if (exit_on_no_devices) {
1230 if (devices_attached() <= 0) {
1231 logmsg(LOG_NOTICE, "no devices attached. exiting.");
1232 return 0;
1233 }
1234 }
1235
1236 fsock = create_unix_socket(USBMUXD_SOCKET_FILE);
1237 if (fsock < 0) {
1238 logmsg(LOG_ERR, "Could not create socket, exiting");
1239 if (!foreground) {
1240 closelog();
1241 }
1242 return -1;
1243 }
1244
1245 chmod(USBMUXD_SOCKET_FILE, 0666);
1246
1247 if (verbose >= 2)
1248 usb_set_debug(verbose);
1249
1250 if (verbose >= 4)
1251 usbmux_set_debug(1);
1252
1253 if (!foreground) {
1254 if (daemonize() < 0) {
1255 fprintf(stderr, "usbmuxd: FATAL: Could not daemonize!\n");
1256 syslog(LOG_ERR, "FATAL: Could not daemonize!");
1257 closelog();
1258 exit(EXIT_FAILURE);
1259 }
1260 }
1261 // now open the lockfile and place the lock
1262 lfd = fopen(LOCKFILE, "w");
1263 if (lfd) {
1264 lock.l_type = F_WRLCK;
1265 lock.l_whence = SEEK_SET;
1266 lock.l_start = 0;
1267 lock.l_len = 0;
1268 if (fcntl(fileno(lfd), F_SETLK, &lock) == -1) {
1269 logmsg(LOG_ERR, "ERROR: lockfile locking failed!");
1270 exit(EXIT_FAILURE);
1271 }
1272 }
1273 // drop elevated privileges
1274 if (drop_privileges && (getuid() == 0 || geteuid() == 0)) {
1275 struct passwd *pw = getpwnam("nobody");
1276 if (pw) {
1277 setuid(pw->pw_uid);
1278 } else {
1279 logmsg(LOG_ERR,
1280 "ERROR: Dropping privileges failed, check if user 'nobody' exists! Will now terminate.");
1281 exit(EXIT_FAILURE);
1282 }
1283
1284 // security check
1285 if (setuid(0) != -1) {
1286 logmsg(LOG_ERR, "ERROR: Failed to drop privileges properly!");
1287 exit(EXIT_FAILURE);
1288 }
1289 if (verbose >= 2)
1290 logmsg(LOG_NOTICE, "Successfully dropped privileges");
1291 }
1292 // Reserve space for 10 clients which should be enough. If not, the
1293 // buffer gets enlarged later.
1294 children =
1295 (struct client_data **) malloc(sizeof(struct client_data *) *
1296 children_capacity);
1297 if (!children) {
1298 logmsg(LOG_ERR,
1299 "Out of memory when allocating memory for child threads. Terminating.");
1300 if (!foreground) {
1301 closelog();
1302 }
1303 exit(EXIT_FAILURE);
1304 }
1305 memset(children, 0, sizeof(struct client_data *) * children_capacity);
1306
1307 if (verbose >= 2)
1308 logmsg(LOG_NOTICE, "waiting for connection");
1309 while (!quit_flag) {
1310 // Check the file descriptor before accepting a connection.
1311 // If no connection attempt is made, just repeat...
1312 result = check_fd(fsock, FD_READ, 1000);
1313 if (result <= 0) {
1314 if (result == 0) {
1315 // cleanup
1316 for (i = 0; i < children_capacity; i++) {
1317 if (children[i]) {
1318 if (children[i]->dead != 0) {
1319 pthread_join(children[i]->thread, NULL);
1320 if (verbose >= 3)
1321 logmsg(LOG_NOTICE,
1322 "reclaimed client thread (fd=%d)",
1323 children[i]->socket);
1324 free(children[i]);
1325 children[i] = NULL;
1326 cnt++;
1327 } else {
1328 cnt = 0;
1329 }
1330 } else {
1331 cnt++;
1332 }
1333 }
1334
1335 if ((children_capacity > DEFAULT_CHILDREN_CAPACITY)
1336 && ((children_capacity - cnt) <=
1337 DEFAULT_CHILDREN_CAPACITY)) {
1338 children_capacity = DEFAULT_CHILDREN_CAPACITY;
1339 children =
1340 realloc(children,
1341 sizeof(struct client_data *) *
1342 children_capacity);
1343 }
1344 continue;
1345 } else {
1346 if (verbose >= 3)
1347 logmsg(LOG_ERR, "usbmuxd: select error: %s",
1348 strerror(errno));
1349 continue;
1350 }
1351 }
1352
1353 cdata = (struct client_data *) malloc(sizeof(struct client_data));
1354 memset(cdata, 0, sizeof(struct client_data));
1355 if (!cdata) {
1356 quit_flag = 1;
1357 logmsg(LOG_ERR, "Error: Out of memory! Terminating.");
1358 break;
1359 }
1360
1361 cdata->socket = accept(fsock, (struct sockaddr *) &c_addr, &len);
1362 if (cdata->socket < 0) {
1363 free(cdata);
1364 if (errno == EINTR) {
1365 continue;
1366 } else {
1367 if (verbose >= 3)
1368 logmsg(LOG_ERR, "Error in accept: %s",
1369 strerror(errno));
1370 continue;
1371 }
1372 }
1373
1374 if (verbose >= 1)
1375 logmsg(LOG_NOTICE, "new client connected (fd=%d)",
1376 cdata->socket);
1377
1378 // create client thread:
1379 if (pthread_create
1380 (&cdata->thread, NULL, usbmuxd_client_init_thread, cdata) == 0)
1381 {
1382 for (i = 0; i < children_capacity; i++) {
1383 if (children[i] == NULL)
1384 break;
1385 }
1386 if (i == children_capacity) {
1387 // enlarge buffer
1388 children_capacity++;
1389 children =
1390 realloc(children,
1391 sizeof(struct client_data *) *
1392 children_capacity);
1393 if (!children) {
1394 logmsg(LOG_ERR,
1395 "Out of memory when enlarging child thread buffer");
1396 }
1397 }
1398 children[i] = cdata;
1399 } else {
1400 logmsg(LOG_ERR, "Failed to create client_init_thread.");
1401 close(cdata->socket);
1402 free(cdata);
1403 cdata = NULL;
1404 }
1405 }
1406
1407 if (verbose >= 3)
1408 logmsg(LOG_NOTICE, "terminating");
1409
1410 // preparing for shutdown: wait for child threads to terminate (if any)
1411 if (verbose >= 2)
1412 logmsg(LOG_NOTICE, "waiting for child threads to terminate...");
1413 for (i = 0; i < children_capacity; i++) {
1414 if (children[i] != NULL) {
1415 pthread_join(children[i]->thread, NULL);
1416 free(children[i]);
1417 children[i] = NULL;
1418 }
1419 }
1420
1421 // delete the children set.
1422 free(children);
1423 children = NULL;
1424
1425
1426 if (fsock >= 0) {
1427 close(fsock);
1428 }
1429
1430 unlink(USBMUXD_SOCKET_FILE);
1431
1432 // unlock lock file and close it.
1433 if (lfd) {
1434 lock.l_type = F_UNLCK;
1435 fcntl(fileno(lfd), F_SETLK, &lock);
1436 fclose(lfd);
1437 }
1438
1439terminate:
1440 if (verbose >= 1)
1441 logmsg(LOG_NOTICE, "terminated");
1442 if (!foreground) {
1443 closelog();
1444 }
1445
1446 return 0;
1447}
diff --git a/src/sock_stuff.c b/src/sock_stuff.c
deleted file mode 100644
index 137375d..0000000
--- a/src/sock_stuff.c
+++ /dev/null
@@ -1,301 +0,0 @@
1#include <stdio.h>
2#include <stddef.h>
3#include <unistd.h>
4#include <errno.h>
5#include <sys/time.h>
6#include <sys/stat.h>
7#include <sys/socket.h>
8#include <sys/un.h>
9#include <netinet/in.h>
10#include <netdb.h>
11#include <arpa/inet.h>
12#include "sock_stuff.h"
13
14#define RECV_TIMEOUT 20000
15
16static int verbose = 0;
17
18void sock_stuff_set_verbose(int level)
19{
20 verbose = level;
21}
22
23int create_unix_socket(const char *filename)
24{
25 struct sockaddr_un name;
26 int sock;
27 size_t size;
28
29 // remove if still present
30 unlink(filename);
31
32 /* Create the socket. */
33 sock = socket(PF_LOCAL, SOCK_STREAM, 0);
34 if (sock < 0) {
35 perror("socket");
36 return -1;
37 }
38
39 /* Bind a name to the socket. */
40 name.sun_family = AF_LOCAL;
41 strncpy(name.sun_path, filename, sizeof(name.sun_path));
42 name.sun_path[sizeof(name.sun_path) - 1] = '\0';
43
44 /* The size of the address is
45 the offset of the start of the filename,
46 plus its length,
47 plus one for the terminating null byte.
48 Alternatively you can just do:
49 size = SUN_LEN (&name);
50 */
51 size = (offsetof(struct sockaddr_un, sun_path)
52 + strlen(name.sun_path) + 1);
53
54 if (bind(sock, (struct sockaddr *) &name, size) < 0) {
55 perror("bind");
56 close(sock);
57 return -1;
58 }
59
60 if (listen(sock, 10) < 0) {
61 perror("listen");
62 close(sock);
63 return -1;
64 }
65
66 return sock;
67}
68
69int connect_unix_socket(const char *filename)
70{
71 struct sockaddr_un name;
72 int sfd = -1;
73 size_t size;
74 struct stat fst;
75
76 // check if socket file exists...
77 if (stat(filename, &fst) != 0) {
78 if (verbose >= 2)
79 fprintf(stderr, "%s: stat '%s': %s\n", __func__, filename,
80 strerror(errno));
81 return -1;
82 }
83 // ... and if it is a unix domain socket
84 if (!S_ISSOCK(fst.st_mode)) {
85 if (verbose >= 2)
86 fprintf(stderr, "%s: File '%s' is not a socket!\n", __func__,
87 filename);
88 return -1;
89 }
90 // make a new socket
91 if ((sfd = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) {
92 if (verbose >= 2)
93 fprintf(stderr, "%s: socket: %s\n", __func__, strerror(errno));
94 return -1;
95 }
96 // and connect to 'filename'
97 name.sun_family = AF_LOCAL;
98 strncpy(name.sun_path, filename, sizeof(name.sun_path));
99 name.sun_path[sizeof(name.sun_path) - 1] = 0;
100
101 size = (offsetof(struct sockaddr_un, sun_path)
102 + strlen(name.sun_path) + 1);
103
104 if (connect(sfd, (struct sockaddr *) &name, size) < 0) {
105 close(sfd);
106 if (verbose >= 2)
107 fprintf(stderr, "%s: connect: %s\n", __func__,
108 strerror(errno));
109 return -1;
110 }
111
112 return sfd;
113}
114
115int create_socket(uint16_t port)
116{
117 int sfd = -1;
118 int yes = 1;
119 struct sockaddr_in saddr;
120
121 if (0 > (sfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP))) {
122 perror("socket()");
123 return -1;
124 }
125
126 if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
127 perror("setsockopt()");
128 close(sfd);
129 return -1;
130 }
131
132 memset((void *) &saddr, 0, sizeof(saddr));
133 saddr.sin_family = AF_INET;
134 saddr.sin_addr.s_addr = htonl(INADDR_ANY);
135 saddr.sin_port = htons(port);
136
137 if (0 > bind(sfd, (struct sockaddr *) &saddr, sizeof(saddr))) {
138 perror("bind()");
139 close(sfd);
140 return -1;
141 }
142
143 if (listen(sfd, 1) == -1) {
144 perror("listen()");
145 close(sfd);
146 return -1;
147 }
148
149 return sfd;
150}
151
152int connect_socket(const char *addr, uint16_t port)
153{
154 int sfd = -1;
155 int yes = 1;
156 struct hostent *hp;
157 struct sockaddr_in saddr;
158
159 if (!addr) {
160 errno = EINVAL;
161 return -1;
162 }
163
164 if ((hp = gethostbyname(addr)) == NULL) {
165 if (verbose >= 2)
166 fprintf(stderr, "%s: unknown host '%s'\n", __func__, addr);
167 return -1;
168 }
169
170 if (!hp->h_addr) {
171 if (verbose >= 2)
172 fprintf(stderr, "%s: gethostbyname returned NULL address!\n",
173 __func__);
174 return -1;
175 }
176
177 if (0 > (sfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP))) {
178 perror("socket()");
179 return -1;
180 }
181
182 if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
183 perror("setsockopt()");
184 close(sfd);
185 return -1;
186 }
187
188 memset((void *) &saddr, 0, sizeof(saddr));
189 saddr.sin_family = AF_INET;
190 saddr.sin_addr.s_addr = *(uint32_t *) hp->h_addr;
191 saddr.sin_port = htons(port);
192
193 if (connect(sfd, (struct sockaddr *) &saddr, sizeof(saddr)) < 0) {
194 perror("connect");
195 close(sfd);
196 return -2;
197 }
198
199 return sfd;
200}
201
202int check_fd(int fd, fd_mode fdm, unsigned int timeout)
203{
204 fd_set fds;
205 int sret;
206 int eagain;
207 struct timeval to;
208
209 if (fd <= 0) {
210 if (verbose >= 2)
211 fprintf(stderr, "ERROR: invalid fd in check_fd %d\n", fd);
212 return -1;
213 }
214
215 FD_ZERO(&fds);
216 FD_SET(fd, &fds);
217
218 to.tv_sec = (time_t) (timeout / 1000);
219 to.tv_usec = (time_t) ((timeout - (to.tv_sec * 1000)) * 1000);
220
221 sret = -1;
222
223 do {
224 eagain = 0;
225 switch (fdm) {
226 case FD_READ:
227 sret = select(fd + 1, &fds, NULL, NULL, &to);
228 break;
229 case FD_WRITE:
230 sret = select(fd + 1, NULL, &fds, NULL, &to);
231 break;
232 case FD_EXCEPT:
233 sret = select(fd + 1, NULL, NULL, &fds, &to);
234 break;
235 default:
236 return -1;
237 }
238
239 if (sret < 0) {
240 switch (errno) {
241 case EINTR:
242 // interrupt signal in select
243 if (verbose >= 2)
244 fprintf(stderr, "%s: EINTR\n", __func__);
245 eagain = 1;
246 break;
247 case EAGAIN:
248 if (verbose >= 2)
249 fprintf(stderr, "%s: EAGAIN\n", __func__);
250 break;
251 default:
252 if (verbose >= 2)
253 fprintf(stderr, "%s: select failed: %s\n", __func__,
254 strerror(errno));
255 return -1;
256 }
257 }
258 } while (eagain);
259
260 return sret;
261}
262
263int recv_buf(int fd, void *data, size_t length)
264{
265 return recv_buf_timeout(fd, data, length, 0, RECV_TIMEOUT);
266}
267
268int peek_buf(int fd, void *data, size_t length)
269{
270 return recv_buf_timeout(fd, data, length, MSG_PEEK, RECV_TIMEOUT);
271}
272
273int recv_buf_timeout(int fd, void *data, size_t length, int flags,
274 unsigned int timeout)
275{
276 int res;
277 int result;
278
279 // check if data is available
280 res = check_fd(fd, FD_READ, timeout);
281 if (res <= 0) {
282 return res;
283 }
284 // if we get here, there _is_ data available
285 result = recv(fd, data, length, flags);
286 if (res > 0 && result == 0) {
287 // but this is an error condition
288 if (verbose >= 3)
289 fprintf(stderr, "%s: fd=%d recv returned 0\n", __func__, fd);
290 return -EAGAIN;
291 }
292 if (result < 0) {
293 return -errno;
294 }
295 return result;
296}
297
298int send_buf(int fd, void *data, size_t length)
299{
300 return send(fd, data, length, 0);
301}
diff --git a/src/sock_stuff.h b/src/sock_stuff.h
deleted file mode 100644
index 190f7e1..0000000
--- a/src/sock_stuff.h
+++ /dev/null
@@ -1,28 +0,0 @@
1#ifndef __SOCK_STUFF_H
2#define __SOCK_STUFF_H
3
4#include <stdint.h>
5
6enum fd_mode {
7 FD_READ,
8 FD_WRITE,
9 FD_EXCEPT
10};
11typedef enum fd_mode fd_mode;
12
13int create_unix_socket(const char *filename);
14int connect_unix_socket(const char *filename);
15int create_socket(uint16_t port);
16int connect_socket(const char *addr, uint16_t port);
17int check_fd(int fd, fd_mode fdm, unsigned int timeout);
18
19int recv_buf(int fd, void *data, size_t size);
20int peek_buf(int fd, void *data, size_t size);
21int recv_buf_timeout(int fd, void *data, size_t size, int flags,
22 unsigned int timeout);
23
24int send_buf(int fd, void *data, size_t size);
25
26void sock_stuff_set_verbose(int level);
27
28#endif /* __SOCK_STUFF_H */
diff --git a/src/usbmux.c b/src/usbmux.c
deleted file mode 100644
index c5e38dd..0000000
--- a/src/usbmux.c
+++ /dev/null
@@ -1,1264 +0,0 @@
1/*
2 * Copyright (c) 2008 Jing Su. All Rights Reserved.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18#include <stdint.h>
19#include <stdarg.h>
20#include <stdlib.h>
21#include <string.h>
22#include <usb.h>
23#include <stdio.h>
24#include <arpa/inet.h>
25#include <errno.h>
26#include <pthread.h>
27#include "usbmux.h"
28
29#define BULKIN 0x85
30#define BULKOUT 0x04
31
32static const uint8_t TCP_FIN = 1;
33static const uint8_t TCP_SYN = 1 << 1;
34static const uint8_t TCP_RST = 1 << 2;
35static const uint8_t TCP_PSH = 1 << 3;
36static const uint8_t TCP_ACK = 1 << 4;
37static const uint8_t TCP_URG = 1 << 5;
38
39// I have trouble figuring out how to properly manage the windowing to
40// the device. It keeps sending back 512 and seems to drop off a cliff
41// when the device gets overwhelmed. In addition, the device likes to
42// panic and send out RESETS before the window hits zero. Also, waiting
43// for responses seems to not be a winning strategy.
44//
45// Since I'm not sure how in the hell to interpret the window sizes that
46// the device is sending back to us, I've figured out some magic number
47// constants which seem to work okay.
48static const uint32_t WINDOW_MAX = 5 * 1024;
49static const uint32_t WINDOW_INCREMENT = 512;
50
51typedef struct {
52 char *buffer;
53 int leftover;
54 int capacity;
55} receivebuf_t;
56
57struct usbmux_device_int {
58 struct usb_dev_handle *usbdev;
59 struct usb_device *__device;
60 receivebuf_t usbReceive;
61 int wMaxPacketSize;
62};
63
64typedef struct {
65 uint32_t type, length, major, minor, allnull;
66} usbmux_version_header;
67
68typedef struct {
69 uint32_t type, length;
70 uint16_t sport, dport;
71 uint32_t scnt, ocnt;
72 uint8_t offset, tcp_flags;
73 uint16_t window, nullnull, length16;
74} usbmux_tcp_header;
75
76struct usbmux_client_int {
77 usbmux_tcp_header *header;
78 usbmux_device_t device;
79
80 char *recv_buffer;
81 int r_len;
82 pthread_cond_t wait;
83
84 // this contains a conditional variable which usb-writers can wait
85 // on while waiting for window updates from the device.
86 pthread_cond_t wr_wait;
87 // I'm going to do something really cheesy here. We are going to
88 // just record the most recent scnt that we are expecting to hear
89 // back on. We will actually halt progress by limiting the number
90 // of outstanding un-acked bulk sends that we have beamed out.
91 uint32_t wr_pending_scnt;
92 long wr_window;
93
94 pthread_mutex_t mutex;
95
96 // this variable is not protected by the mutex. This will always
97 // be E_SUCCESS, unless an error of some kind breaks this stream.
98 // this will then be set to the error that caused the broken stream.
99 // no further operations other than free_client will be allowed.
100 int error;
101
102 int cleanup;
103
104 int connected;
105};
106
107
108static pthread_mutex_t usbmuxmutex = PTHREAD_MUTEX_INITIALIZER;
109static pthread_mutex_t printmutex = PTHREAD_MUTEX_INITIALIZER;
110static usbmux_client_t *connlist = NULL;
111static int clients = 0;
112
113
114/**
115 */
116int toto_debug = 0;
117
118void usbmux_set_debug(int e)
119{
120 toto_debug = e;
121}
122
123static void log_debug_msg(const char *format, ...)
124{
125#ifndef STRIP_DEBUG_CODE
126 va_list args;
127 /* run the real fprintf */
128 va_start(args, format);
129
130 if (toto_debug) {
131 pthread_mutex_lock(&printmutex);
132 vfprintf(stderr, format, args);
133 pthread_mutex_unlock(&printmutex);
134 }
135
136 va_end(args);
137#endif
138}
139
140/**
141 * for debugging purposes.
142 */
143static void print_buffer(const char *data, const int length)
144{
145 if (toto_debug <= 0) {
146 return;
147 }
148 int i;
149 int j;
150 unsigned char c;
151
152 for (i = 0; i < length; i += 16) {
153 printf("%04x: ", i);
154 for (j = 0; j < 16; j++) {
155 if (i + j >= length) {
156 printf(" ");
157 continue;
158 }
159 printf("%02hhx ", *(data + i + j));
160 }
161 printf(" | ");
162 for (j = 0; j < 16; j++) {
163 if (i + j >= length)
164 break;
165 c = *(data + i + j);
166 if ((c < 32) || (c > 127)) {
167 printf(".");
168 continue;
169 }
170 printf("%c", c);
171 }
172 printf("\n");
173 }
174 printf("\n");
175}
176
177static void hton_header(usbmux_tcp_header * hdr)
178{
179 if (hdr) {
180 hdr->length = htonl(hdr->length);
181 hdr->scnt = htonl(hdr->scnt);
182 hdr->ocnt = htonl(hdr->ocnt);
183 hdr->length16 = htons(hdr->length16);
184 }
185}
186
187static void ntoh_header(usbmux_tcp_header * hdr)
188{
189 if (hdr) {
190 hdr->length = ntohl(hdr->length);
191 hdr->scnt = ntohl(hdr->scnt);
192 hdr->ocnt = ntohl(hdr->ocnt);
193 hdr->length16 = ntohs(hdr->length16);
194 }
195}
196
197/** Creates a USBMux header containing version information
198 *
199 * @return A USBMux header
200 */
201static usbmux_version_header *version_header()
202{
203 usbmux_version_header *version =
204 (usbmux_version_header *) malloc(sizeof(usbmux_version_header));
205 version->type = 0;
206 version->length = htonl(20);
207 version->major = htonl(1);
208 version->minor = 0;
209 version->allnull = 0;
210 return version;
211}
212
213/**
214 * This function sets the configuration of the given device to 3
215 * and claims the interface 1. If usb_set_configuration fails, it detaches
216 * the kernel driver that blocks the device, and retries configuration.
217 *
218 * @param device which device to configure
219 */
220static int usbmux_config_usb_device(usbmux_device_t device)
221{
222 int ret;
223 int bytes;
224 char buf[512];
225
226 log_debug_msg("claiming interface... ");
227 ret = usb_claim_interface(device->usbdev, 1);
228 if (ret != 0) {
229 log_debug_msg("Error: usb_claim_interface returned %d: %s\n", ret,
230 strerror(-ret));
231 return -ENODEV;
232 } else {
233 log_debug_msg("done.\n");
234 }
235
236 // get the last configuration
237 struct usb_config_descriptor *cfg = &device->__device->config[device->__device->descriptor.bNumConfigurations-1];
238 if (cfg && cfg->bNumInterfaces >= 2) {
239 struct usb_interface *ifp = &cfg->interface[1];
240 if (ifp && ifp->num_altsetting >= 1) {
241 struct usb_interface_descriptor *as = &ifp->altsetting[0];
242 int i;
243 for (i = 0; i < as->bNumEndpoints; i++) {
244 struct usb_endpoint_descriptor *ep=&as->endpoint[i];
245 if (ep->bEndpointAddress == BULKOUT) {
246 device->wMaxPacketSize = ep->wMaxPacketSize;
247 }
248 }
249 }
250 }
251
252 log_debug_msg("Setting wMaxPacketSize to %d\n", device->wMaxPacketSize);
253
254 do {
255 bytes = usb_bulk_read(device->usbdev, BULKIN, buf, 512, 800);
256 } while (bytes > 0);
257
258 return 0;
259}
260
261/**
262 * Given a USB bus and device number, returns a device handle to the device on
263 * that bus. To aid compatibility with future devices, this function does not
264 * check the vendor and device IDs! To do that, you should use
265 * usbmux_get_device() or a system-specific API (e.g. HAL).
266 *
267 * @param bus_n The USB bus number.
268 * @param dev_n The USB device number.
269 * @param device A pointer to a usbmux_device_t, which must be set to NULL upon
270 * calling usbmux_get_specific_device, which will be filled with a device
271 * descriptor on return.
272 * @return 0 if ok, otherwise a negative errno value.
273 */
274int usbmux_get_specific_device(int bus_n, int dev_n,
275 usbmux_device_t * device)
276{
277 struct usb_bus *bus;
278 struct usb_device *dev;
279 usbmux_version_header *version;
280 int bytes = 0;
281
282 //check we can actually write in device
283 if (!device || (device && *device))
284 return -EINVAL;
285
286 usbmux_device_t newdevice =
287 (usbmux_device_t) malloc(sizeof(struct usbmux_device_int));
288
289 // Initialize the struct
290 newdevice->usbdev = NULL;
291 newdevice->__device = NULL;
292
293 // don't forget these:
294 newdevice->usbReceive.buffer = NULL;
295 newdevice->usbReceive.leftover = 0;
296 newdevice->usbReceive.capacity = 0;
297
298 // wMaxPacketSize
299 newdevice->wMaxPacketSize = 64;
300
301 // Initialize libusb
302 usb_init();
303 usb_find_busses();
304 usb_find_devices();
305
306 // Set the device configuration
307 for (bus = usb_get_busses(); bus; bus = bus->next)
308 if (strtoul(bus->dirname, NULL, 10) == bus_n)
309 for (dev = bus->devices; dev != NULL; dev = dev->next)
310 if (strtol(dev->filename, NULL, 10) == dev_n) {
311 newdevice->__device = dev;
312 newdevice->usbdev = usb_open(newdevice->__device);
313 if (!newdevice->usbdev) {
314 fprintf(stderr, "%s: Error: usb_open(): %s\n", __func__, usb_strerror());
315 }
316 if (usbmux_config_usb_device(newdevice) == 0) {
317 goto found;
318 }
319 }
320
321 usbmux_free_device(newdevice);
322
323 log_debug_msg("usbmux_get_specific_device: device not found\n");
324 return -ENODEV;
325
326 found:
327 // Send the version command to the device
328 version = version_header();
329 bytes =
330 usb_bulk_write(newdevice->usbdev, BULKOUT, (char *) version,
331 sizeof(*version), 800);
332 if (bytes < 20) {
333 log_debug_msg("%s: libusb did NOT send enough!\n", __func__);
334 if (bytes < 0) {
335 log_debug_msg("%s: libusb gave me the error %d: %s (%s)\n",
336 __func__, bytes, usb_strerror(),
337 strerror(-bytes));
338 }
339 }
340 // Read the device's response
341 bytes =
342 usb_bulk_read(newdevice->usbdev, BULKIN, (char *) version,
343 sizeof(*version), 800);
344
345 // Check for bad response
346 if (bytes < 20) {
347 free(version);
348 usbmux_free_device(newdevice);
349 log_debug_msg("%s: Invalid version message -- header too short.\n",
350 __func__);
351 if (bytes < 0) {
352 log_debug_msg("%s: libusb error message %d: %s (%s)\n",
353 __func__, bytes, usb_strerror(),
354 strerror(-bytes));
355 return bytes;
356 }
357 return -EBADMSG;
358 }
359 // Check for correct version
360 if (ntohl(version->major) == 1 && ntohl(version->minor) == 0) {
361 // We're all ready to roll.
362 log_debug_msg("%s: success\n", __func__);
363 free(version);
364 *device = newdevice;
365 return 0;
366 } else {
367 // Bad header
368 usbmux_free_device(newdevice);
369 free(version);
370 log_debug_msg("%s: Received a bad header/invalid version number.",
371 __func__);
372 return -EBADMSG;
373 }
374
375 // If it got to this point it's gotta be bad
376 log_debug_msg("%s: Unknown error.\n", __func__);
377 usbmux_free_device(newdevice);
378 free(version);
379 return -EBADMSG; // if it got to this point it's gotta be bad
380}
381
382/** Cleans up an usbmux_device_t structure, then frees the structure itself.
383 * This is a library-level function; deals directly with the device to tear
384 * down relations, but otherwise is mostly internal.
385 *
386 * @param device A pointer to an usbmux_device_t structure.
387 */
388int usbmux_free_device(usbmux_device_t device)
389{
390 char buf[512];
391 int bytes = -1;
392
393 if (!device)
394 return -EINVAL;
395 int ret = 0;
396
397 if (device->usbdev) {
398 do {
399 bytes = usb_bulk_read(device->usbdev, BULKIN, buf, 512, 800);
400 } while (bytes > 0);
401 }
402
403 if (bytes < 0) {
404 ret = bytes;
405 }
406
407 if (device->usbReceive.buffer) {
408 free(device->usbReceive.buffer);
409 }
410 if (device->usbdev) {
411 usb_release_interface(device->usbdev, 1);
412 usb_close(device->usbdev);
413 ret = 0;
414 }
415 free(device);
416
417 return ret;
418}
419
420
421
422/** Sends data to the device
423 * This is a low-level (i.e. directly to device) function.
424 *
425 * @param device The device to send data to
426 * @param data The data to send
427 * @param datalen The length of the data
428 * @return The number of bytes sent, or -ERRNO on error
429 */
430static int send_to_device(usbmux_device_t device, char *data, int datalen)
431{
432 if (!device)
433 return -EINVAL;
434
435 int timeout = 1000;
436 int retrycount = 0;
437 int bytes = 0;
438
439if (toto_debug > 0) {
440 pthread_mutex_lock(&printmutex);
441 printf("===============================\n%s: trying to send\n",
442 __func__);
443 print_buffer(data, datalen);
444 printf("===============================\n");
445 pthread_mutex_unlock(&printmutex);
446}
447
448 do {
449 if (retrycount > 3) {
450 log_debug_msg
451 ("EPIC FAIL! aborting on retry count overload.\n");
452 return -ECOMM;
453 }
454
455 bytes =
456 usb_bulk_write(device->usbdev, BULKOUT, data, datalen,
457 timeout);
458 if (bytes == -ETIMEDOUT) {
459 // timed out waiting for write.
460 log_debug_msg("usb_bulk_write timeout error.\n");
461 return bytes;
462 } else if (bytes < 0) {
463 log_debug_msg
464 ("usb_bulk_write failed with error. err:%d (%s)(%s)\n",
465 bytes, usb_strerror(), strerror(-bytes));
466 return bytes;
467 } else if (bytes == 0) {
468 log_debug_msg("usb_bulk_write sent nothing. retrying.\n");
469 timeout = timeout * 4;
470 retrycount++;
471 continue;
472 } else if (bytes < datalen) {
473 log_debug_msg
474 ("usb_bulk_write failed to send full dataload. %d of %d\n",
475 bytes, datalen);
476 timeout = timeout * 4;
477 retrycount++;
478 data += bytes;
479 datalen -= bytes;
480 continue;
481 }
482 if ((bytes % device->wMaxPacketSize) == 0) {
483 log_debug_msg("NOTE: sending NULL packet\n");
484 char nullp = 0;
485 int res = usb_bulk_write(device->usbdev, BULKOUT,
486 &nullp, 0, timeout);
487 if (res < 0) {
488 log_debug_msg("ERROR: NULL packet write returned %d\n", res);
489 }
490 }
491 } while (0); // fall out
492
493 if (bytes > 0) {
494 if (toto_debug > 0) {
495 pthread_mutex_lock(&printmutex);
496 printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
497 printf("%s: sent to device\n", __func__);
498 print_buffer(data, bytes);
499 printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
500 pthread_mutex_unlock(&printmutex);
501 }
502 }
503 return bytes;
504}
505
506/** Receives data from the device
507 * This function is a low-level (i.e. direct from device) function.
508 *
509 * @param device The device to receive data from
510 * @param data Where to put data read
511 * @param datalen How much data to read in
512 * @param timeout How many milliseconds to wait for data
513 *
514 * @return How many bytes were read in, or -1 on error.
515 */
516static int recv_from_device_timeout(usbmux_device_t device, char *data,
517 int datalen, int timeoutmillis)
518{
519 if (!device)
520 return -EINVAL;
521 //log_debug_msg("%s: attempting to receive %i bytes\n", __func__, datalen);
522
523 int bytes =
524 usb_bulk_read(device->usbdev, BULKIN, data, datalen,
525 timeoutmillis);
526 // There are some things which are errors, others which are no problem.
527 // It's not documented in libUSB, but it seems that the error values
528 // returned are just negated ERRNO values.
529 if (bytes < 0) {
530 if (bytes == -ETIMEDOUT) {
531 // ignore this. it just means timeout reached before we
532 // picked up any data. no problem.
533 return 0;
534 } else {
535 fprintf(stderr, "%s: libusb gave me the error %d: %s (%s)\n",
536 __func__, bytes, usb_strerror(), strerror(-bytes));
537 log_debug_msg("%s: libusb gave me the error %d: %s (%s)\n",
538 __func__, bytes, usb_strerror(),
539 strerror(-bytes));
540 }
541 return bytes;
542 }
543 if (bytes > 0) {
544 if (toto_debug > 0) {
545 pthread_mutex_lock(&printmutex);
546 printf("<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
547 printf("%s: received from device:\n", __func__);
548 print_buffer(data, bytes);
549 printf("<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
550 pthread_mutex_unlock(&printmutex);
551 }
552 }
553
554 return bytes;
555}
556
557/** Creates a USBMux packet for the given set of ports.
558 *
559 * @param s_port The source port for the connection.
560 * @param d_port The destination port for the connection.
561 *
562 * @return A USBMux packet
563 */
564static usbmux_tcp_header *new_mux_packet(uint16_t s_port, uint16_t d_port)
565{
566 usbmux_tcp_header *conn =
567 (usbmux_tcp_header *) malloc(sizeof(usbmux_tcp_header));
568 conn->type = htonl(6);
569 conn->length = sizeof(usbmux_tcp_header);
570 conn->sport = htons(s_port);
571 conn->dport = htons(d_port);
572 conn->scnt = 0;
573 conn->ocnt = 0;
574 conn->offset = 0x50;
575 conn->window = htons(0x0200);
576 conn->nullnull = 0x0000;
577 conn->length16 = sizeof(usbmux_tcp_header);
578 return conn;
579}
580
581
582/** Removes a connection from the list of connections made.
583 * The list of connections is necessary for buffering.
584 *
585 * @param connection The connection to delete from the tracking list.
586 */
587static void delete_connection(usbmux_client_t connection)
588{
589 usbmux_client_t *newlist = NULL;
590
591 pthread_mutex_lock(&usbmuxmutex);
592
593 // update the global list of connections
594 if (clients > 1) {
595 newlist =
596 (usbmux_client_t *) malloc(sizeof(usbmux_client_t) *
597 (clients - 1));
598 int i = 0, j = 0;
599 for (i = 0; i < clients; i++) {
600 if (connlist[i] == connection)
601 continue;
602 else {
603 newlist[j] = connlist[i];
604 j++;
605 }
606 }
607 }
608 if (connlist) {
609 free(connlist);
610 }
611 connlist = newlist;
612 clients--;
613
614 // free up this connection
615 pthread_mutex_lock(&connection->mutex);
616 if (connection->recv_buffer) {
617 free(connection->recv_buffer);
618 connection->recv_buffer = NULL;
619 }
620 if (connection->header) {
621 free(connection->header);
622 connection->header = NULL;
623 }
624 connection->r_len = 0;
625 pthread_mutex_unlock(&connection->mutex);
626 pthread_mutex_destroy(&connection->mutex);
627 free(connection);
628
629 pthread_mutex_unlock(&usbmuxmutex);
630}
631
632/** Adds a connection to the list of connections made.
633 * The connection list is necessary for buffering.
634 *
635 * @param connection The connection to add to the global list of connections.
636 */
637
638static void add_connection(usbmux_client_t connection)
639{
640 pthread_mutex_lock(&usbmuxmutex);
641 usbmux_client_t *newlist =
642 (usbmux_client_t *) realloc(connlist,
643 sizeof(usbmux_client_t) * (clients +
644 1));
645 newlist[clients] = connection;
646 connlist = newlist;
647 clients++;
648 pthread_mutex_unlock(&usbmuxmutex);
649}
650
651/**
652 * Get a source port number that is not used by one of our connections
653 * This is needed for us to make sure we are not sending on another
654 * connection.
655 */
656static uint16_t get_free_port()
657{
658 int i;
659 uint16_t newport = 30000;
660 int cnt = 0;
661
662 pthread_mutex_lock(&usbmuxmutex);
663 while (1) {
664 cnt = 0;
665 for (i = 0; i < clients; i++) {
666 if (ntohs(connlist[i]->header->sport) == newport) {
667 cnt++;
668 }
669 }
670 if (cnt == 0) {
671 // newport is not used in our list of connections!
672 break;
673 } else {
674 newport++;
675 if (newport < 30000) {
676 // if all ports from 30000 to 65535 are in use,
677 // the value wraps (16-bit overflow)
678 // return 0, no port is available.
679 // This should not happen, but just in case ;)
680 newport = 0;
681 break;
682 }
683 }
684 }
685 pthread_mutex_unlock(&usbmuxmutex);
686
687 return newport;
688}
689
690/** Initializes a connection to 'device' with source port s_port and destination port d_port
691 *
692 * @param device The device to initialize a connection on.
693 * @param src_port The source port
694 * @param dst_port The destination port -- 0xf27e for lockdownd.
695 * @param client A mux TCP header for the connection which is used for tracking and data transfer.
696 * @return 0 on success, a negative errno value otherwise.
697 */
698int usbmux_new_client(usbmux_device_t device, uint16_t src_port,
699 uint16_t dst_port, usbmux_client_t * client)
700{
701 if (!device || !dst_port)
702 return -EINVAL;
703
704 src_port = get_free_port();
705
706 if (!src_port) {
707 // this is a special case, if we get 0, this is not good, so
708 return -EISCONN; // TODO: error code suitable?
709 }
710 // Initialize connection stuff
711 usbmux_client_t new_connection =
712 (usbmux_client_t) malloc(sizeof(struct usbmux_client_int));
713 new_connection->header = new_mux_packet(src_port, dst_port);
714
715 // send TCP syn
716 if (new_connection && new_connection->header) {
717 int err = 0;
718 new_connection->header->tcp_flags = TCP_SYN;
719 new_connection->header->length = new_connection->header->length;
720 new_connection->header->length16 =
721 new_connection->header->length16;
722 new_connection->header->scnt = 0;
723 new_connection->header->ocnt = 0;
724 new_connection->device = device;
725 new_connection->recv_buffer = NULL;
726 new_connection->r_len = 0;
727 pthread_cond_init(&new_connection->wait, NULL);
728 pthread_mutex_init(&new_connection->mutex, NULL);
729 pthread_cond_init(&new_connection->wr_wait, NULL);
730 new_connection->wr_pending_scnt = 0;
731 new_connection->wr_window = 0;
732 add_connection(new_connection);
733 new_connection->error = 0;
734 new_connection->cleanup = 0;
735 new_connection->connected = 0;
736 hton_header(new_connection->header);
737 log_debug_msg("%s: send_to_device (%d --> %d)\n", __func__,
738 ntohs(new_connection->header->sport),
739 ntohs(new_connection->header->dport));
740 err =
741 send_to_device(device, (char *) new_connection->header,
742 sizeof(usbmux_tcp_header));
743 if (err >= 0) {
744 *client = new_connection;
745 return 0;
746 } else {
747 delete_connection(new_connection);
748 return err;
749 }
750 }
751 // if we get to this point it's probably bad
752 return -ENOMEM;
753}
754
755/** Cleans up the given USBMux connection.
756 * @note Once a connection is closed it may not be used again.
757 *
758 * @param connection The connection to close.
759 *
760 * @return 0 on success or a negative errno value on error.
761 */
762int usbmux_free_client(usbmux_client_t client)
763{
764 if (!client || !client->device)
765 return -EINVAL;
766
767 int err = 0;
768 int result = 0;
769 pthread_mutex_lock(&client->mutex);
770 client->header->tcp_flags = TCP_RST;
771 client->header->length = 0x1C;
772 client->header->window = 0;
773 client->header->length16 = 0x1C;
774 hton_header(client->header);
775
776 err =
777 send_to_device(client->device, (char *) client->header,
778 sizeof(usbmux_tcp_header));
779 if (err < 0) {
780 log_debug_msg("%s: error sending TCP_FIN\n", __func__);
781 result = err;
782 }
783
784 client->cleanup = 1;
785
786 // make sure we don't have any last-minute laggards waiting on this.
787 // I put it after the mutex unlock because we have cases where the
788 // conditional wait is dependent on re-grabbing that mutex.
789 pthread_cond_broadcast(&client->wait);
790 pthread_cond_destroy(&client->wait);
791 pthread_cond_broadcast(&client->wr_wait);
792 pthread_cond_destroy(&client->wr_wait);
793
794 pthread_mutex_unlock(&client->mutex);
795
796 return result;
797}
798
799/** Sends the given data over the selected connection.
800 *
801 * @param client The client we're sending data on.
802 * @param data A pointer to the data to send.
803 * @param datalen How much data we're sending.
804 * @param sent_bytes The number of bytes sent, minus the header (28)
805 *
806 * @return 0 on success or a negative errno value on error.
807 */
808int usbmux_send(usbmux_client_t client, const char *data, uint32_t datalen,
809 uint32_t * sent_bytes)
810{
811 if (!client->device || !client || !sent_bytes)
812 return -EINVAL;
813
814 if (client->error < 0) {
815 return client->error;
816 }
817
818 *sent_bytes = 0;
819 pthread_mutex_lock(&client->mutex);
820
821 int sendresult = 0;
822 uint32_t blocksize = 0;
823 if (client->wr_window <= 0) {
824 struct timespec ts;
825 clock_gettime(CLOCK_REALTIME, &ts);
826 //ts.tv_sec += 1;
827 ts.tv_nsec += 750 * 1000;
828 if (pthread_cond_timedwait(&client->wait, &client->mutex, &ts) ==
829 ETIMEDOUT) {
830 // timed out. optimistically grow the window and try to make progress
831 client->wr_window += WINDOW_INCREMENT;
832 }
833 }
834
835 blocksize = sizeof(usbmux_tcp_header) + datalen;
836
837 // client->scnt and client->ocnt should already be in host notation...
838 // we don't need to change them juuuust yet.
839 char *buffer = (char *) malloc(blocksize + 2); // allow 2 bytes of safety padding
840 // Set the length
841 client->header->length = blocksize;
842 client->header->length16 = blocksize;
843
844 // Put header into big-endian notation
845 hton_header(client->header);
846 // Concatenation of stuff in the buffer.
847 memcpy(buffer, client->header, sizeof(usbmux_tcp_header));
848 memcpy(buffer + sizeof(usbmux_tcp_header), data, datalen);
849
850 log_debug_msg("%s: send_to_device(%d --> %d)\n", __func__,
851 ntohs(client->header->sport),
852 ntohs(client->header->dport));
853 sendresult = send_to_device(client->device, buffer, blocksize);
854 // Now that we've sent it off, we can clean up after our sloppy selves.
855 if (buffer)
856 free(buffer);
857
858 // revert header fields that have been swapped before trying to send
859 ntoh_header(client->header);
860
861 // update counts ONLY if the send succeeded.
862 if ((uint32_t) sendresult == blocksize) {
863 // Re-calculate scnt
864 client->header->scnt += datalen;
865 client->wr_window -= blocksize;
866 }
867
868 pthread_mutex_unlock(&client->mutex);
869
870 if (sendresult == -ETIMEDOUT || sendresult == 0) {
871 // no problem for now...
872 *sent_bytes = 0;
873 return -ETIMEDOUT;
874 } else if (sendresult < 0) {
875 return sendresult;
876 } else if ((uint32_t) sendresult == blocksize) {
877 // actual number of data bytes sent.
878 *sent_bytes = sendresult - sizeof(usbmux_tcp_header);
879 return 0;
880 } else {
881 fprintf(stderr,
882 "usbsend managed to dump a packet that is not full size. %d of %d\n",
883 sendresult, blocksize);
884 return -EBADMSG;
885 }
886}
887
888/** append the packet's DATA to the receive buffer for the client.
889 *
890 * this has a few other corner-case functions:
891 * 1. this will properly handle the handshake syn+ack.
892 * 2. for all receives, this will appropriately update the ocnt.
893 *
894 * @return number of bytes consumed (header + data)
895 */
896static uint32_t append_receive_buffer(usbmux_client_t client, char *packet)
897{
898 if (client == NULL || packet == NULL)
899 return 0;
900
901 usbmux_tcp_header *header = (usbmux_tcp_header *) packet;
902 char *data = &packet[sizeof(usbmux_tcp_header)];
903 uint32_t packetlen = ntohl(header->length);
904 uint32_t datalen = packetlen - sizeof(usbmux_tcp_header);
905
906 int dobroadcast = 0;
907
908 pthread_mutex_lock(&client->mutex);
909
910 // we need to handle a few corner case tasks and book-keeping which
911 // falls on our responsibility because we are the ones reading in
912 // feedback.
913 if (client->header->scnt == 0 && client->header->ocnt == 0) {
914 log_debug_msg("client is still waiting for handshake.\n");
915 if (header->tcp_flags == (TCP_SYN | TCP_ACK)) {
916 log_debug_msg("yes, got syn+ack ; replying with ack.\n");
917 client->header->tcp_flags = TCP_ACK;
918 client->header->length = sizeof(usbmux_tcp_header);
919 client->header->length16 = sizeof(usbmux_tcp_header);
920 client->header->scnt += 1;
921 client->header->ocnt = header->ocnt;
922 hton_header(client->header);
923 // push it to USB
924 // TODO: need to check for error in the send here.... :(
925 log_debug_msg("%s: send_to_device (%d --> %d)\n", __func__,
926 ntohs(client->header->sport),
927 ntohs(client->header->dport));
928 if (send_to_device
929 (client->device, (char *) client->header,
930 sizeof(usbmux_tcp_header)) <= 0) {
931 log_debug_msg("%s: error when pushing to usb...\n",
932 __func__);
933 } else {
934 client->connected = 1;
935 }
936 // need to revert some of the fields back to host notation.
937 ntoh_header(client->header);
938 } else {
939 client->error = -ECONNABORTED;
940 // woah... this connection failed us.
941 // TODO: somehow signal that this stream is a no-go.
942 log_debug_msg("WOAH! client failed to get proper syn+ack.\n");
943 }
944 }
945 // update TCP counters and windows.
946 //
947 // save the window that we're getting from the USB device.
948 // apparently the window is bigger than just the 512 that's typically
949 // advertised. iTunes apparently shifts this value by 8 to get a much
950 // larger number.
951 if (header->tcp_flags & TCP_RST) {
952 client->error = -ECONNRESET;
953
954 if (datalen > 0) {
955 char e_msg[128];
956 e_msg[0] = 0;
957 if (datalen > 1) {
958 memcpy(e_msg, data + 1, datalen - 1);
959 e_msg[datalen - 1] = 0;
960 }
961 // fetch the message
962 switch (data[0]) {
963 case 0:
964 // this is not an error, it's just a status message.
965 log_debug_msg("received status message: %s\n", e_msg);
966 datalen = 0;
967 break;
968 case 1:
969 log_debug_msg("received error message: %s\n", e_msg);
970 datalen = 0;
971 break;
972 default:
973 log_debug_msg
974 ("received unknown message (type 0x%02x): %s\n",
975 data[0], e_msg);
976 //datalen = 0; // <-- we let this commented out for testing
977 break;
978 }
979 } else {
980 log_debug_msg
981 ("peer sent connection reset. setting error: %d\n",
982 client->error);
983 }
984 }
985 // the packet's ocnt tells us how much of our data the device has received.
986 if (header->tcp_flags & TCP_ACK) {
987 // this is a hacky magic number condition. it seems that once
988 // the window reported by the device starts to drop below this
989 // number, we quickly fall into connection reset problems.
990 // Once we see the reported window size start falling off,
991 // ut off and wait for solid acks to come back.
992 if (ntohs(header->window) < 256)
993 client->wr_window = 0;
994
995 // check what just got acked.
996 if (ntohl(header->ocnt) < client->header->scnt) {
997 // we got some kind of ack, but it hasn't caught up
998 // with the pending that have been sent.
999 pthread_cond_broadcast(&client->wr_wait);
1000 } else if (ntohl(header->ocnt) >
1001 /*client->wr_pending_scnt */ client->header->scnt) {
1002 fprintf(stderr,
1003 "WTF?! acks overtook pending outstanding. %u,%u\n",
1004 ntohl(header->ocnt), client->wr_pending_scnt);
1005 } else {
1006 // reset the window
1007 client->wr_window = WINDOW_MAX;
1008 pthread_cond_broadcast(&client->wr_wait);
1009 }
1010 }
1011 // the packet's scnt will be our new ocnt.
1012 client->header->ocnt = ntohl(header->scnt);
1013
1014 // ensure there is enough space, either by first malloc or realloc
1015 if (datalen > 0) {
1016 log_debug_msg("%s: putting %d bytes into client's recv_buffer\n",
1017 __func__, datalen);
1018 if (client->r_len == 0)
1019 dobroadcast = 1;
1020
1021 if (client->recv_buffer == NULL) {
1022 client->recv_buffer = malloc(datalen);
1023 client->r_len = 0;
1024 } else {
1025 client->recv_buffer =
1026 realloc(client->recv_buffer, client->r_len + datalen);
1027 }
1028
1029 memcpy(&client->recv_buffer[client->r_len], data, datalen);
1030 client->r_len += datalen;
1031 }
1032
1033 pthread_mutex_unlock(&client->mutex);
1034
1035 // I put this outside the mutex unlock just so that when the threads
1036 // wake, we don't have to do another round of unlock+try to grab.
1037 if (dobroadcast)
1038 pthread_cond_broadcast(&client->wait);
1039
1040 return packetlen;
1041}
1042
1043/**
1044 * @note THERE IS NO MUTEX LOCK IN THIS FUNCTION!
1045 * because we're only called from one location, pullbulk, where the lock
1046 * is already held.
1047 */
1048static usbmux_client_t find_client(usbmux_tcp_header * recv_header)
1049{
1050 // remember, as we're looking for the client, the receive header is
1051 // coming from the USB into our client. This means that when we check
1052 // the src/dst ports, we need to reverse them.
1053 usbmux_client_t retval = NULL;
1054
1055 // just for debugging check, I'm going to convert the numbers to host-endian.
1056 uint16_t hsport = ntohs(recv_header->sport);
1057 uint16_t hdport = ntohs(recv_header->dport);
1058
1059 pthread_mutex_lock(&usbmuxmutex);
1060 int i;
1061 for (i = 0; i < clients; i++) {
1062 uint16_t csport = ntohs(connlist[i]->header->sport);
1063 uint16_t cdport = ntohs(connlist[i]->header->dport);
1064
1065 if (hsport == cdport && hdport == csport) {
1066 retval = connlist[i];
1067 break;
1068 }
1069 }
1070 pthread_mutex_unlock(&usbmuxmutex);
1071
1072 return retval;
1073}
1074
1075/** pull in a big USB bulk packet and distribute it to queues appropriately.
1076 */
1077int usbmux_pullbulk(usbmux_device_t device)
1078{
1079 if (!device)
1080 return -EINVAL;
1081
1082 int res = 0;
1083 static const int DEFAULT_CAPACITY = 128 * 1024;
1084 if (device->usbReceive.buffer == NULL) {
1085 device->usbReceive.capacity = DEFAULT_CAPACITY;
1086 device->usbReceive.buffer = malloc(device->usbReceive.capacity);
1087 device->usbReceive.leftover = 0;
1088 }
1089 // start the cursor off just ahead of the leftover.
1090 char *cursor = &device->usbReceive.buffer[device->usbReceive.leftover];
1091 // pull in content, note that the amount we can pull is capacity minus leftover
1092 int readlen =
1093 recv_from_device_timeout(device, cursor,
1094 device->usbReceive.capacity -
1095 device->usbReceive.leftover, 3000);
1096 if (readlen < 0) {
1097 res = readlen;
1098 //fprintf(stderr, "recv_from_device_timeout gave us an error.\n");
1099 readlen = 0;
1100 }
1101 if (readlen > 0) {
1102 //fprintf(stdout, "recv_from_device_timeout pulled an extra %d bytes\n", readlen);
1103 }
1104 // the amount of content we have to work with is the remainder plus
1105 // what we managed to read
1106 device->usbReceive.leftover += readlen;
1107
1108 // reset the cursor to the front of that buffer and work through
1109 // trying to decode packets out of them.
1110 cursor = device->usbReceive.buffer;
1111 while (1) {
1112 // check if there's even sufficient data to decode a header
1113 if (device->usbReceive.leftover < sizeof(usbmux_tcp_header))
1114 break;
1115 usbmux_tcp_header *header = (usbmux_tcp_header *) cursor;
1116
1117 log_debug_msg("%s: recv_from_device_timeout (%d --> %d)\n",
1118 __func__, ntohs(header->sport),
1119 ntohs(header->dport));
1120
1121 // now that we have a header, check if there is sufficient data
1122 // to construct a full packet, including its data
1123 uint32_t packetlen = ntohl(header->length);
1124 if ((uint32_t) device->usbReceive.leftover < packetlen) {
1125 fprintf(stderr,
1126 "%s: not enough data to construct a full packet\n",
1127 __func__);
1128 break;
1129 }
1130 // ok... find the client this packet will get stuffed to.
1131 usbmux_client_t client = find_client(header);
1132 if (client == NULL) {
1133 log_debug_msg
1134 ("WARNING: client for packet cannot be found. dropping packet.\n");
1135 } else {
1136 // stuff the data
1137 log_debug_msg
1138 ("%s: found client, calling append_receive_buffer\n",
1139 __func__);
1140 append_receive_buffer(client, cursor);
1141
1142 // perhaps this is too general, == -ECONNRESET
1143 // might be a better check here
1144 if (client->error < 0) {
1145 pthread_mutex_lock(&client->mutex);
1146 if (client->cleanup) {
1147 pthread_mutex_unlock(&client->mutex);
1148 log_debug_msg("freeing up connection (%d->%d)\n",
1149 ntohs(client->header->sport),
1150 ntohs(client->header->dport));
1151 delete_connection(client);
1152 } else {
1153 pthread_mutex_unlock(&client->mutex);
1154 }
1155 }
1156 }
1157
1158 // move the cursor and account for the consumption
1159 cursor += packetlen;
1160 device->usbReceive.leftover -= packetlen;
1161 }
1162
1163 // now, we need to manage any leftovers.
1164 // I'm going to manage the leftovers by alloc'ing a new block and
1165 // copyingthe leftovers to it. This is just to prevent problems with
1166 // memory moves where there may be overlap. Besides, the leftovers
1167 // should be small enough that this copy is minimal in overhead.
1168 //
1169 // if there are no leftovers, we just leave the datastructure as is,
1170 // and re-use the block next time.
1171 if (device->usbReceive.leftover > 0
1172 && cursor != device->usbReceive.buffer) {
1173 log_debug_msg("%s: we got a leftover, so handle it\n", __func__);
1174 char *newbuff = malloc(DEFAULT_CAPACITY);
1175 memcpy(newbuff, cursor, device->usbReceive.leftover);
1176 free(device->usbReceive.buffer);
1177 device->usbReceive.buffer = newbuff;
1178 device->usbReceive.capacity = DEFAULT_CAPACITY;
1179 }
1180
1181 return res;
1182}
1183
1184/**
1185 * return the error code stored in usbmux_client_t structure,
1186 * e.g. non-zero when an usb read error occurs.
1187 *
1188 * @param client the usbmux client
1189 *
1190 * @return 0 or a negative errno value.
1191 */
1192int usbmux_get_error(usbmux_client_t client)
1193{
1194 if (!client) {
1195 return 0;
1196 }
1197 return client->error;
1198}
1199
1200/** This function reads from the client's recv_buffer.
1201 *
1202 * @param client The client to receive data from.
1203 * @param data Where to put the data we receive.
1204 * @param datalen How much data to read.
1205 * @param timeout How many milliseconds to wait for data
1206 *
1207 * @return 0 on success or a negative errno value on failure.
1208 */
1209int usbmux_recv_timeout(usbmux_client_t client, char *data,
1210 uint32_t datalen, uint32_t * recv_bytes,
1211 int timeout)
1212{
1213
1214 if (!client || !data || datalen == 0 || !recv_bytes)
1215 return -EINVAL;
1216
1217 if (client->error < 0)
1218 return client->error;
1219
1220 pthread_mutex_lock(&client->mutex);
1221
1222 if (timeout > 0 && (client->recv_buffer == NULL || client->r_len == 0)) {
1223 struct timespec ts;
1224 clock_gettime(CLOCK_REALTIME, &ts);
1225 ts.tv_sec += timeout / 1000;
1226 ts.tv_nsec += (timeout - ((int) (timeout / 1000)) * 1000) * 1000;
1227 pthread_cond_timedwait(&client->wait, &client->mutex, &ts);
1228 }
1229
1230 *recv_bytes = 0;
1231 if (client->recv_buffer != NULL && client->r_len > 0) {
1232 uint32_t foolen = datalen;
1233 if ((int) foolen > client->r_len)
1234 foolen = client->r_len;
1235 memcpy(data, client->recv_buffer, foolen);
1236 *recv_bytes = foolen;
1237
1238 // preserve any left-over unread amounts.
1239 int remainder = client->r_len - foolen;
1240 if (remainder > 0) {
1241 char *newbuf = malloc(remainder);
1242 memcpy(newbuf, client->recv_buffer + foolen, remainder);
1243 client->r_len = remainder;
1244 free(client->recv_buffer);
1245 client->recv_buffer = newbuf;
1246 } else {
1247 free(client->recv_buffer);
1248 client->recv_buffer = NULL;
1249 client->r_len = 0;
1250 }
1251 }
1252
1253 pthread_mutex_unlock(&client->mutex);
1254
1255 return 0;
1256}
1257
1258int usbmux_is_connected(usbmux_client_t client)
1259{
1260 if (!client) {
1261 return 0;
1262 }
1263 return client->connected;
1264}
diff --git a/src/usbmux.h b/src/usbmux.h
deleted file mode 100644
index 155316a..0000000
--- a/src/usbmux.h
+++ /dev/null
@@ -1,53 +0,0 @@
1/*
2 * Copyright (c) 2008 Jing Su. All Rights Reserved.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19#ifndef __USBMUX_H__
20#define __USBMUX_H__
21
22#include <stdint.h>
23#include <sys/types.h>
24//#include <sys/stat.h>
25
26
27void usbmux_set_debug(int e);
28
29struct usbmux_device_int;
30typedef struct usbmux_device_int *usbmux_device_t;
31
32struct usbmux_client_int;
33typedef struct usbmux_client_int *usbmux_client_t;
34
35int usbmux_get_device ( usbmux_device_t *device );
36int usbmux_get_specific_device(int bus_n, int dev_n, usbmux_device_t * device);
37int usbmux_free_device ( usbmux_device_t device );
38
39
40int usbmux_new_client ( usbmux_device_t device, uint16_t src_port, uint16_t dst_port, usbmux_client_t *client );
41int usbmux_free_client ( usbmux_client_t client );
42
43int usbmux_send(usbmux_client_t client, const char *data, uint32_t datalen, uint32_t * sent_bytes);
44
45int usbmux_recv_timeout(usbmux_client_t client, char *data, uint32_t datalen, uint32_t * recv_bytes, int timeout);
46
47int usbmux_pullbulk(usbmux_device_t device);
48
49int usbmux_get_error(usbmux_client_t client);
50
51int usbmux_is_connected(usbmux_client_t client);
52
53#endif
diff --git a/src/usbmuxd-proto.h b/src/usbmuxd-proto.h
deleted file mode 100644
index 7f8c2d6..0000000
--- a/src/usbmuxd-proto.h
+++ /dev/null
@@ -1,52 +0,0 @@
1/* Protocol defintion for usbmuxd proxy protocol */
2
3#ifndef __USBMUXD_PROTO_H
4#define __USBMUXD_PROTO_H
5
6#include <stdint.h>
7
8#define USBMUXD_SOCKET_FILE "/var/run/usbmuxd"
9
10struct usbmuxd_header {
11 uint32_t length; // length of message, including header
12 uint32_t reserved; // always zero
13 uint32_t type; // message type
14 uint32_t tag; // responses to this query will echo back this tag
15} __attribute__((__packed__));
16
17struct usbmuxd_result {
18 struct usbmuxd_header header;
19 uint32_t result;
20} __attribute__((__packed__));
21
22struct usbmuxd_connect_request {
23 struct usbmuxd_header header;
24 uint32_t device_id;
25 uint16_t tcp_dport; // TCP port number
26 uint16_t reserved; // set to zero
27} __attribute__((__packed__));
28
29struct usbmuxd_device {
30 uint32_t device_id;
31 uint16_t product_id;
32 char serial_number[40];
33} __attribute__((__packed__));
34
35struct usbmuxd_device_info_record {
36 struct usbmuxd_header header;
37 struct usbmuxd_device device;
38 char padding[222];
39} __attribute__((__packed__));
40
41struct usbmuxd_scan_request {
42 struct usbmuxd_header header;
43} __attribute__((__packed__));
44
45enum {
46 USBMUXD_RESULT = 1,
47 USBMUXD_CONNECT = 2,
48 USBMUXD_SCAN = 3,
49 USBMUXD_DEVICE_INFO = 4,
50};
51
52#endif /* __USBMUXD_PROTO_H */
diff --git a/src/usbmuxd.h b/src/usbmuxd.h
deleted file mode 100644
index ba45ec3..0000000
--- a/src/usbmuxd.h
+++ /dev/null
@@ -1,91 +0,0 @@
1#ifndef __USBMUXD_H
2#define __USBMUXD_H
3
4/**
5 * Array entry returned by 'usbmuxd_scan()' scanning.
6 *
7 * If more than one device is available, 'product_id' and
8 * 'serial_number' and be analysed to help make a selection.
9 * The relevant 'handle' should be passed to 'usbmuxd_connect()', to
10 * start a proxy connection. The value 'handle' should be considered
11 * opaque and no presumption made about the meaning of its value.
12 */
13typedef struct {
14 int handle;
15 int product_id;
16 char serial_number[41];
17} usbmuxd_scan_result;
18
19/**
20 * Contacts usbmuxd and performs a scan for connected devices.
21 *
22 * @param available_devices pointer to array of usbmuxd_scan_result.
23 * Array of available devices. The required 'handle'
24 * should be passed to 'usbmuxd_connect()'. The returned array
25 * is zero-terminated for convenience; the final (unused)
26 * entry containing handle == 0. The returned array pointer
27 * should be freed by passing to 'free()' after use.
28 *
29 * @return number of available devices, zero on no devices, or negative on error
30 */
31int usbmuxd_scan(usbmuxd_scan_result **available_devices);
32
33/**
34 * Request proxy connect to
35 *
36 * @param handle returned by 'usbmuxd_scan()'
37 *
38 * @param tcp_port TCP port number on device, in range 0-65535.
39 * common values are 62078 for lockdown, and 22 for SSH.
40 *
41 * @return file descriptor socket of the connection, or -1 on error
42 */
43int usbmuxd_connect(const int handle, const unsigned short tcp_port);
44
45/**
46 * Disconnect. For now, this just closes the socket file descriptor.
47 *
48 * @param sfd socker file descriptor returned by usbmuxd_connect()
49 *
50 * @return 0 on success, -1 on error.
51 */
52int usbmuxd_disconnect(int sfd);
53
54/**
55 * Send data to the specified socket.
56 *
57 * @param sfd socket file descriptor returned by usbmuxd_connect()
58 * @param data buffer to send
59 * @param len size of buffer to send
60 * @param sent_bytes how many bytes sent
61 *
62 * @return 0 on success, a negative errno value otherwise.
63 */
64int usbmuxd_send(int sfd, const char *data, uint32_t len, uint32_t *sent_bytes);
65
66/**
67 * Receive data from the specified socket.
68 *
69 * @param sfd socket file descriptor returned by usbmuxd_connect()
70 * @param data buffer to put the data to
71 * @param len number of bytes to receive
72 * @param recv_bytes number of bytes received
73 * @param timeout how many milliseconds to wait for data
74 *
75 * @return 0 on success, a negative errno value otherwise.
76 */
77int usbmuxd_recv_timeout(int sfd, char *data, uint32_t len, uint32_t *recv_bytes, unsigned int timeout);
78
79/**
80 * Receive data from the specified socket with a default timeout.
81 *
82 * @param sfd socket file descriptor returned by usbmuxd_connect()
83 * @param data buffer to put the data to
84 * @param len number of bytes to receive
85 * @param recv_bytes number of bytes received
86 *
87 * @return 0 on success, a negative errno value otherwise.
88 */
89int usbmuxd_recv(int sfd, char *data, uint32_t len, uint32_t *recv_bytes);
90
91#endif /* __USBMUXD_H */