diff --git a/.gitignore b/.gitignore index fb6a17e..fc8d37c 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,3 @@ usbmuxd-1.0.5.tar.bz2 /usbmuxd-1.0.9-c24463e.tar.bz2 /usbmuxd-1.0.9.tar.bz2 /usbmuxd-1.1.0.tar.bz2 -/usbmuxd-1.1.1.tar.bz2 -/usbmuxd-61b99ab5c25609c11369733a0df97c03a0581a56.tar.gz -/usbmuxd-0b1b233b57d581515978a09e5a4394bfa4ee4962.tar.gz -/usbmuxd-3ded00c9985a5108cfc7591a309f9a23d57a8cba.tar.gz diff --git a/68bdf4be88b128c56eea5117361c4e7b51eb27b1...9af2b12552693a47601347e1eafc1e94132d727e.patch b/68bdf4be88b128c56eea5117361c4e7b51eb27b1...9af2b12552693a47601347e1eafc1e94132d727e.patch new file mode 100644 index 0000000..75923cf --- /dev/null +++ b/68bdf4be88b128c56eea5117361c4e7b51eb27b1...9af2b12552693a47601347e1eafc1e94132d727e.patch @@ -0,0 +1,4157 @@ +From 50cb34766753f9ad6a046bdc3e1fa1f1a1aacc73 Mon Sep 17 00:00:00 2001 +From: Martin Szulecki +Date: Fri, 17 Oct 2014 22:30:14 +0200 +Subject: [PATCH 01/66] Post-release version bump to 1.1.1 + +--- + configure.ac | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/configure.ac b/configure.ac +index 21ff1b8..4cd3b5d 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -2,7 +2,7 @@ + # Process this file with autoconf to produce a configure script. + + AC_PREREQ(2.64) +-AC_INIT([usbmuxd], [1.1.0], [https://github.com/libimobiledevice/usbmuxd/issues],, [http://libimobiledevice.org]) ++AC_INIT([usbmuxd], [1.1.1], [https://github.com/libimobiledevice/usbmuxd/issues],, [http://libimobiledevice.org]) + AM_INIT_AUTOMAKE([dist-bzip2 no-dist-gzip check-news]) + m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES]) + AC_CONFIG_SRCDIR([src/]) +-- +2.23.0 + + +From 04e07442bbc8a5d8515fa1eea52cb15ebd2cc992 Mon Sep 17 00:00:00 2001 +From: Martin Szulecki +Date: Fri, 31 Oct 2014 12:52:23 +0100 +Subject: [PATCH 02/66] Use new get_tick_count() to avoid timing issues on + packets + +--- + src/log.c | 3 ++- + src/usb-linux.c | 11 ++++++----- + src/utils.c | 18 +++++++++++++++--- + src/utils.h | 1 + + 4 files changed, 24 insertions(+), 9 deletions(-) + +diff --git a/src/log.c b/src/log.c +index 9ad09da..46839ee 100644 +--- a/src/log.c ++++ b/src/log.c +@@ -31,6 +31,7 @@ + #include + + #include "log.h" ++#include "utils.h" + + unsigned int log_level = LL_WARNING; + +@@ -70,7 +71,7 @@ void usbmuxd_log(enum loglevel level, const char *fmt, ...) + if(level > log_level) + return; + +- gettimeofday(&ts, NULL); ++ get_tick_count(&ts); + tp = localtime(&ts.tv_sec); + + fs = malloc(20 + strlen(fmt)); +diff --git a/src/usb-linux.c b/src/usb-linux.c +index 751b6ed..8acbace 100644 +--- a/src/usb-linux.c ++++ b/src/usb-linux.c +@@ -34,6 +34,7 @@ + #include "usb.h" + #include "log.h" + #include "device.h" ++#include "utils.h" + + // interval for device connection/disconnection polling, in milliseconds + // we need this because there is currently no asynchronous device discovery mechanism in libusb +@@ -266,7 +267,7 @@ int usb_discover(void) + usbmuxd_log(LL_FATAL, "Too many errors getting device list"); + return cnt; + } else { +- gettimeofday(&next_dev_poll_time, NULL); ++ get_tick_count(&next_dev_poll_time); + next_dev_poll_time.tv_usec += DEVICE_POLL_TIME * 1000; + next_dev_poll_time.tv_sec += next_dev_poll_time.tv_usec / 1000000; + next_dev_poll_time.tv_usec = next_dev_poll_time.tv_usec % 1000000; +@@ -477,7 +478,7 @@ int usb_discover(void) + + libusb_free_device_list(devs, 1); + +- gettimeofday(&next_dev_poll_time, NULL); ++ get_tick_count(&next_dev_poll_time); + next_dev_poll_time.tv_usec += DEVICE_POLL_TIME * 1000; + next_dev_poll_time.tv_sec += next_dev_poll_time.tv_usec / 1000000; + next_dev_poll_time.tv_usec = next_dev_poll_time.tv_usec % 1000000; +@@ -538,7 +539,7 @@ static int dev_poll_remain_ms(void) + struct timeval tv; + if(!device_polling) + return 100000; // devices will never be polled if this is > 0 +- gettimeofday(&tv, NULL); ++ get_tick_count(&tv); + msecs = (next_dev_poll_time.tv_sec - tv.tv_sec) * 1000; + msecs += (next_dev_poll_time.tv_usec - tv.tv_usec) / 1000; + if(msecs < 0) +@@ -595,7 +596,7 @@ int usb_process_timeout(int msec) + { + int res; + struct timeval tleft, tcur, tfin; +- gettimeofday(&tcur, NULL); ++ get_tick_count(&tcur); + tfin.tv_sec = tcur.tv_sec + (msec / 1000); + tfin.tv_usec = tcur.tv_usec + (msec % 1000) * 1000; + tfin.tv_sec += tfin.tv_usec / 1000000; +@@ -614,7 +615,7 @@ int usb_process_timeout(int msec) + } + // reap devices marked dead due to an RX error + reap_dead_devices(); +- gettimeofday(&tcur, NULL); ++ get_tick_count(&tcur); + } + return 0; + } +diff --git a/src/utils.c b/src/utils.c +index 5dd871d..ceb65e1 100644 +--- a/src/utils.c ++++ b/src/utils.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + #include + + #include "utils.h" +@@ -298,15 +299,26 @@ int plist_write_to_filename(plist_t plist, const char *filename, enum plist_form + return 1; + } + ++void get_tick_count(struct timeval * tv) ++{ ++ struct timespec ts; ++ if(0 == clock_gettime(CLOCK_MONOTONIC, &ts)) { ++ tv->tv_sec = ts.tv_sec; ++ tv->tv_usec = ts.tv_nsec / 1000; ++ } else { ++ gettimeofday(tv, NULL); ++ } ++} ++ + /** + * Get number of milliseconds since the epoch. + */ + uint64_t mstime64(void) + { + struct timeval tv; +- gettimeofday(&tv, NULL); ++ get_tick_count(&tv); + +- // Careful, avoid overflow on 32 bit systems +- // time_t could be 4 bytes ++ // Careful, avoid overflow on 32 bit systems ++ // time_t could be 4 bytes + return ((long long)tv.tv_sec) * 1000LL + ((long long)tv.tv_usec) / 1000LL; + } +diff --git a/src/utils.h b/src/utils.h +index 00041a0..1137a93 100644 +--- a/src/utils.h ++++ b/src/utils.h +@@ -87,5 +87,6 @@ int plist_read_from_filename(plist_t *plist, const char *filename); + int plist_write_to_filename(plist_t plist, const char *filename, enum plist_format_t format); + + uint64_t mstime64(void); ++void get_tick_count(struct timeval * tv); + + #endif +-- +2.23.0 + + +From 5e017fbb36d4ccafb9be6859d90f2c04b20b3d06 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Tue, 11 Nov 2014 13:49:03 +0100 +Subject: [PATCH 03/66] client: Log pid of connecting clients (if supported) + +--- + src/client.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/src/client.c b/src/client.c +index 67a29e8..d5f31e4 100644 +--- a/src/client.c ++++ b/src/client.c +@@ -22,6 +22,8 @@ + #include + #endif + ++#define _GNU_SOURCE 1 ++ + #include + #include + #include +@@ -166,7 +168,21 @@ int client_accept(int listenfd) + collection_add(&client_list, client); + pthread_mutex_unlock(&client_list_mutex); + ++#ifdef SO_PEERCRED ++ if (log_level >= LL_INFO) { ++ struct ucred cr; ++ len = sizeof(struct ucred); ++ getsockopt(cfd, SOL_SOCKET, SO_PEERCRED, &cr, &len); ++ ++ if (getpid() == cr.pid) { ++ usbmuxd_log(LL_INFO, "New client on fd %d (self)", client->fd); ++ } else { ++ usbmuxd_log(LL_INFO, "New client on fd %d (pid %d)", client->fd, cr.pid); ++ } ++ } ++#else + usbmuxd_log(LL_INFO, "New client on fd %d", client->fd); ++#endif + return client->fd; + } + +-- +2.23.0 + + +From 086d443338ec4fa70f27f0880e63eb08f112c390 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Tue, 11 Nov 2014 13:51:16 +0100 +Subject: [PATCH 04/66] client: Remove invalid line feed from log message + +--- + src/client.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/client.c b/src/client.c +index d5f31e4..403340a 100644 +--- a/src/client.c ++++ b/src/client.c +@@ -231,7 +231,7 @@ static int send_pkt(struct mux_client *client, uint32_t tag, enum usbmuxd_msgtyp + usbmuxd_log(LL_DEBUG, "%s: Enlarging client %d output buffer %d -> %d", __func__, client->fd, client->ob_capacity, new_size); + new_buf = realloc(client->ob_buf, new_size); + if (!new_buf) { +- usbmuxd_log(LL_FATAL, "%s: Failed to realloc.\n", __func__); ++ usbmuxd_log(LL_FATAL, "%s: Failed to realloc.", __func__); + return -1; + } + client->ob_buf = new_buf; +-- +2.23.0 + + +From 07c5634cef09a913d6307de5b0edd6e73aaebfb3 Mon Sep 17 00:00:00 2001 +From: Martin Szulecki +Date: Mon, 10 Nov 2014 16:56:48 +0100 +Subject: [PATCH 05/66] Bump libusb dependency to 1.0.9 for + libusb_get_device_speed() + +--- + configure.ac | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/configure.ac b/configure.ac +index 4cd3b5d..6c2481a 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -16,7 +16,7 @@ AM_PROG_CC_C_O + AC_PROG_LIBTOOL + + # Checks for libraries. +-PKG_CHECK_MODULES(libusb, libusb-1.0 >= 1.0.3) ++PKG_CHECK_MODULES(libusb, libusb-1.0 >= 1.0.9) + PKG_CHECK_MODULES(libplist, libplist >= 1.11) + PKG_CHECK_MODULES(libimobiledevice, libimobiledevice-1.0 >= 1.1.6, have_limd=yes, have_limd=no) + AC_CHECK_LIB(pthread, [pthread_create, pthread_mutex_lock], [AC_SUBST(libpthread_LIBS,[-lpthread])], [AC_MSG_ERROR([libpthread is required to build usbmuxd])]) +-- +2.23.0 + + +From 4da37c1e130e32c4bbad13de7461e0612ca15597 Mon Sep 17 00:00:00 2001 +From: Martin Szulecki +Date: Mon, 10 Nov 2014 16:58:10 +0100 +Subject: [PATCH 06/66] Get USB speed for device and use it for device attached + client message + +--- + src/client.c | 3 +-- + src/device.c | 2 ++ + src/device.h | 1 + + src/usb-linux.c | 29 +++++++++++++++++++++++++++++ + src/usb.h | 1 + + 5 files changed, 34 insertions(+), 2 deletions(-) + +diff --git a/src/client.c b/src/client.c +index 403340a..268c8b9 100644 +--- a/src/client.c ++++ b/src/client.c +@@ -306,8 +306,7 @@ static plist_t create_device_attached_plist(struct device_info *dev) + plist_dict_set_item(dict, "MessageType", plist_new_string("Attached")); + plist_dict_set_item(dict, "DeviceID", plist_new_uint(dev->id)); + plist_t props = plist_new_dict(); +- // TODO: get current usb speed +- plist_dict_set_item(props, "ConnectionSpeed", plist_new_uint(480000000)); ++ plist_dict_set_item(props, "ConnectionSpeed", plist_new_uint(dev->speed)); + plist_dict_set_item(props, "ConnectionType", plist_new_string("USB")); + plist_dict_set_item(props, "DeviceID", plist_new_uint(dev->id)); + plist_dict_set_item(props, "LocationID", plist_new_uint(dev->location)); +diff --git a/src/device.c b/src/device.c +index e5377cc..ddd1d4a 100644 +--- a/src/device.c ++++ b/src/device.c +@@ -572,6 +572,7 @@ static void device_version_input(struct mux_device *dev, struct version_header * + info.location = usb_get_location(dev->usbdev); + info.serial = usb_get_serial(dev->usbdev); + info.pid = usb_get_pid(dev->usbdev); ++ info.speed = usb_get_speed(dev->usbdev); + preflight_worker_device_add(&info); + } + +@@ -924,6 +925,7 @@ int device_get_list(int include_hidden, struct device_info **devices) + p->serial = usb_get_serial(dev->usbdev); + p->location = usb_get_location(dev->usbdev); + p->pid = usb_get_pid(dev->usbdev); ++ p->speed = usb_get_speed(dev->usbdev); + count++; + p++; + } +diff --git a/src/device.h b/src/device.h +index e731b36..85703e4 100644 +--- a/src/device.h ++++ b/src/device.h +@@ -28,6 +28,7 @@ struct device_info { + const char *serial; + uint32_t location; + uint16_t pid; ++ uint64_t speed; + }; + + void device_data_input(struct usb_device *dev, unsigned char *buf, uint32_t length); +diff --git a/src/usb-linux.c b/src/usb-linux.c +index 8acbace..9878f41 100644 +--- a/src/usb-linux.c ++++ b/src/usb-linux.c +@@ -56,6 +56,7 @@ struct usb_device { + struct collection rx_xfers; + struct collection tx_xfers; + int wMaxPacketSize; ++ uint64_t speed; + }; + + static struct collection device_list; +@@ -425,6 +426,7 @@ int usb_discover(void) + usbdev->address = address; + usbdev->vid = devdesc.idVendor; + usbdev->pid = devdesc.idProduct; ++ usbdev->speed = 480000000; + usbdev->dev = handle; + usbdev->alive = 1; + usbdev->wMaxPacketSize = libusb_get_max_packet_size(dev, usbdev->ep_out); +@@ -435,6 +437,25 @@ int usb_discover(void) + usbmuxd_log(LL_INFO, "Using wMaxPacketSize=%d for device %d-%d", usbdev->wMaxPacketSize, usbdev->bus, usbdev->address); + } + ++ switch (libusb_get_device_speed(dev)) { ++ case LIBUSB_SPEED_LOW: ++ usbdev->speed = 1500000; ++ break; ++ case LIBUSB_SPEED_FULL: ++ usbdev->speed = 12000000; ++ break; ++ case LIBUSB_SPEED_SUPER: ++ usbdev->speed = 5000000000; ++ break; ++ case LIBUSB_SPEED_HIGH: ++ case LIBUSB_SPEED_UNKNOWN: ++ default: ++ usbdev->speed = 480000000; ++ break; ++ } ++ ++ usbmuxd_log(LL_INFO, "USB Speed is %g MBit/s for device %d-%d", (double)(usbdev->speed / 1000000.0), usbdev->bus, usbdev->address); ++ + collection_init(&usbdev->tx_xfers); + collection_init(&usbdev->rx_xfers); + +@@ -510,6 +531,14 @@ uint16_t usb_get_pid(struct usb_device *dev) + return dev->pid; + } + ++uint64_t usb_get_speed(struct usb_device *dev) ++{ ++ if (!dev->dev) { ++ return 0; ++ } ++ return dev->speed; ++} ++ + void usb_get_fds(struct fdlist *list) + { + const struct libusb_pollfd **usbfds; +diff --git a/src/usb.h b/src/usb.h +index 8eff456..da784b3 100644 +--- a/src/usb.h ++++ b/src/usb.h +@@ -54,6 +54,7 @@ void usb_shutdown(void); + const char *usb_get_serial(struct usb_device *dev); + uint32_t usb_get_location(struct usb_device *dev); + uint16_t usb_get_pid(struct usb_device *dev); ++uint64_t usb_get_speed(struct usb_device *dev); + void usb_get_fds(struct fdlist *list); + int usb_get_timeout(void); + int usb_send(struct usb_device *dev, const unsigned char *buf, int length); +-- +2.23.0 + + +From 23ecea077d8f22d9da5cae50df3e2ff3406fee90 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Tue, 11 Nov 2014 09:21:39 +0100 +Subject: [PATCH 07/66] client: Make sure fd is writable before calling send() + to avoid blocking + +--- + src/client.c | 19 ++++++++++++++++++- + 1 file changed, 18 insertions(+), 1 deletion(-) + +diff --git a/src/client.c b/src/client.c +index 268c8b9..417ba35 100644 +--- a/src/client.c ++++ b/src/client.c +@@ -30,6 +30,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -100,12 +101,28 @@ int client_read(struct mux_client *client, void *buffer, uint32_t len) + */ + int client_write(struct mux_client *client, void *buffer, uint32_t len) + { ++ int sret = -1; ++ fd_set fds; ++ struct timeval to = {0, 0}; ++ + usbmuxd_log(LL_SPEW, "client_write fd %d buf %p len %d", client->fd, buffer, len); + if(client->state != CLIENT_CONNECTED) { + usbmuxd_log(LL_ERROR, "Attempted to write to client %d not in CONNECTED state", client->fd); + return -1; + } +- return send(client->fd, buffer, len, 0); ++ ++ /* make sure fd is ready for writing */ ++ FD_ZERO(&fds); ++ FD_SET(client->fd, &fds); ++ sret = select(client->fd + 1, NULL, &fds, NULL, &to); ++ ++ /* only send data if the fd is ready */ ++ if (sret > 0) { ++ sret = send(client->fd, buffer, len, 0); ++ } else { ++ usbmuxd_log(LL_ERROR, "ERROR: client_write: fd %d not ready for writing", client->fd); ++ } ++ return sret; + } + + /** +-- +2.23.0 + + +From a5e57e872bb5be8b13d3497f2c07fff8a8e37f3f Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Wed, 12 Nov 2014 13:31:34 +0100 +Subject: [PATCH 08/66] Revert "client: Make sure fd is writable before calling + send() to avoid blocking" + +This reverts commit 23ecea077d8f22d9da5cae50df3e2ff3406fee90. +--- + src/client.c | 19 +------------------ + 1 file changed, 1 insertion(+), 18 deletions(-) + +diff --git a/src/client.c b/src/client.c +index 417ba35..268c8b9 100644 +--- a/src/client.c ++++ b/src/client.c +@@ -30,7 +30,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -101,28 +100,12 @@ int client_read(struct mux_client *client, void *buffer, uint32_t len) + */ + int client_write(struct mux_client *client, void *buffer, uint32_t len) + { +- int sret = -1; +- fd_set fds; +- struct timeval to = {0, 0}; +- + usbmuxd_log(LL_SPEW, "client_write fd %d buf %p len %d", client->fd, buffer, len); + if(client->state != CLIENT_CONNECTED) { + usbmuxd_log(LL_ERROR, "Attempted to write to client %d not in CONNECTED state", client->fd); + return -1; + } +- +- /* make sure fd is ready for writing */ +- FD_ZERO(&fds); +- FD_SET(client->fd, &fds); +- sret = select(client->fd + 1, NULL, &fds, NULL, &to); +- +- /* only send data if the fd is ready */ +- if (sret > 0) { +- sret = send(client->fd, buffer, len, 0); +- } else { +- usbmuxd_log(LL_ERROR, "ERROR: client_write: fd %d not ready for writing", client->fd); +- } +- return sret; ++ return send(client->fd, buffer, len, 0); + } + + /** +-- +2.23.0 + + +From a3cae2b7a3dfe8120f2a65a1fae8640bb4f095a5 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Wed, 12 Nov 2014 19:53:06 +0100 +Subject: [PATCH 09/66] Use non-blocking sockets for client communication + +This approach is better than using blocking sockets and select() since +there's no guarantee that send() doesn't block. Plus we're using poll() +anyway so send() and recv() will only be called if the socket is actually +ready for writing/reading. +--- + src/client.c | 23 ++++++++++++++++++++++- + src/main.c | 9 +++++++++ + 2 files changed, 31 insertions(+), 1 deletion(-) + +diff --git a/src/client.c b/src/client.c +index 268c8b9..4ec4025 100644 +--- a/src/client.c ++++ b/src/client.c +@@ -33,6 +33,7 @@ + #include + #include + #include ++#include + + #include + +@@ -100,12 +101,23 @@ int client_read(struct mux_client *client, void *buffer, uint32_t len) + */ + int client_write(struct mux_client *client, void *buffer, uint32_t len) + { ++ int sret = -1; ++ + usbmuxd_log(LL_SPEW, "client_write fd %d buf %p len %d", client->fd, buffer, len); + if(client->state != CLIENT_CONNECTED) { + usbmuxd_log(LL_ERROR, "Attempted to write to client %d not in CONNECTED state", client->fd); + return -1; + } +- return send(client->fd, buffer, len, 0); ++ ++ sret = send(client->fd, buffer, len, 0); ++ if (sret < 0) { ++ if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { ++ usbmuxd_log(LL_ERROR, "ERROR: client_write: fd %d not ready for writing", client->fd); ++ } else { ++ usbmuxd_log(LL_ERROR, "ERROR: client_write: sending to fd %d failed: %s", client->fd, strerror(errno)); ++ } ++ } ++ return sret; + } + + /** +@@ -150,6 +162,15 @@ int client_accept(int listenfd) + return cfd; + } + ++ int flags = fcntl(cfd, F_GETFL, 0); ++ if (flags < 0) { ++ usbmuxd_log(LL_ERROR, "ERROR: Could not get socket flags!"); ++ } else { ++ if (fcntl(cfd, F_SETFL, flags | O_NONBLOCK) < 0) { ++ usbmuxd_log(LL_ERROR, "ERROR: Could not set socket to non-blocking mode"); ++ } ++ } ++ + struct mux_client *client; + client = malloc(sizeof(struct mux_client)); + memset(client, 0, sizeof(struct mux_client)); +diff --git a/src/main.c b/src/main.c +index b1f4eeb..2e4439c 100644 +--- a/src/main.c ++++ b/src/main.c +@@ -82,6 +82,15 @@ static int create_socket(void) { + return -1; + } + ++ int flags = fcntl(listenfd, F_GETFL, 0); ++ if (flags < 0) { ++ usbmuxd_log(LL_FATAL, "ERROR: Could not get flags for socket"); ++ } else { ++ if (fcntl(listenfd, F_SETFL, flags | O_NONBLOCK) < 0) { ++ usbmuxd_log(LL_FATAL, "ERROR: Could not set socket to non-blocking"); ++ } ++ } ++ + bzero(&bind_addr, sizeof(bind_addr)); + bind_addr.sun_family = AF_UNIX; + strcpy(bind_addr.sun_path, socket_path); +-- +2.23.0 + + +From f961e3589910a8c3d90752edeee1604fe1a1fb02 Mon Sep 17 00:00:00 2001 +From: Martin Szulecki +Date: Fri, 21 Nov 2014 15:15:17 +0100 +Subject: [PATCH 10/66] docs: Use correct manual section (8) for manpage + +--- + docs/Makefile.am | 2 +- + docs/{usbmuxd.1 => usbmuxd.8} | 10 +++++----- + 2 files changed, 6 insertions(+), 6 deletions(-) + rename docs/{usbmuxd.1 => usbmuxd.8} (98%) + +diff --git a/docs/Makefile.am b/docs/Makefile.am +index 12e0e57..70a61ca 100644 +--- a/docs/Makefile.am ++++ b/docs/Makefile.am +@@ -1,3 +1,3 @@ +-man_MANS = usbmuxd.1 ++man_MANS = usbmuxd.8 + + EXTRA_DIST = $(man_MANS) +diff --git a/docs/usbmuxd.1 b/docs/usbmuxd.8 +similarity index 98% +rename from docs/usbmuxd.1 +rename to docs/usbmuxd.8 +index 00f0a5c..0a05f12 100644 +--- a/docs/usbmuxd.1 ++++ b/docs/usbmuxd.8 +@@ -1,4 +1,4 @@ +-.TH "usbmuxd" 1 ++.TH "usbmuxd" 8 + .SH NAME + usbmuxd \- Expose a socket to multiplex connections from and to iOS devices. + .SH SYNOPSIS +@@ -52,17 +52,17 @@ Run in systemd operation mode (implies -z and -f). + .B \-x, \-\-exit + Notify a running instance to exit if there are no devices connected (sends + SIGUSR1 to running instance) and exit. +-.TP ++.TP + .B \-X, \-\-force-exit + Notify a running instance to exit even if there are still devices connected + (always works) and exit. +-.TP ++.TP + .B \-v, \-\-verbose + be verbose (use twice or more to increase verbose level). +-.TP ++.TP + .B \-V, \-\-version + print version information and exit. +-.TP ++.TP + .B \-h, \-\-help + prints usage information. + +-- +2.23.0 + + +From 7f7a360848bac728d8a51f4a22515fbebd3ef6b1 Mon Sep 17 00:00:00 2001 +From: Martin Szulecki +Date: Fri, 21 Nov 2014 16:37:12 +0100 +Subject: [PATCH 11/66] systemd: Add documentation reference to unit file + +--- + systemd/usbmuxd.service.in | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/systemd/usbmuxd.service.in b/systemd/usbmuxd.service.in +index c2bd617..e978738 100644 +--- a/systemd/usbmuxd.service.in ++++ b/systemd/usbmuxd.service.in +@@ -1,5 +1,6 @@ + [Unit] + Description=Socket daemon for the usbmux protocol used by Apple devices ++Documentation=man:usbmuxd(8) + + [Service] + Type=simple +-- +2.23.0 + + +From 4bd7cd0d28e7f5920de51470b863f3aeee00409d Mon Sep 17 00:00:00 2001 +From: Martin Szulecki +Date: Fri, 21 Nov 2014 16:43:31 +0100 +Subject: [PATCH 12/66] systemd: Remove Type option from service file as it + already defaults to simple + +--- + systemd/usbmuxd.service.in | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/systemd/usbmuxd.service.in b/systemd/usbmuxd.service.in +index e978738..bee2476 100644 +--- a/systemd/usbmuxd.service.in ++++ b/systemd/usbmuxd.service.in +@@ -3,6 +3,5 @@ Description=Socket daemon for the usbmux protocol used by Apple devices + Documentation=man:usbmuxd(8) + + [Service] +-Type=simple + ExecStart=@sbindir@/usbmuxd --user usbmux --systemd + PIDFile=@localstatedir@/run/usbmuxd.pid +-- +2.23.0 + + +From 3444d5a3a68998ac62b8f8c96414aad608024575 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Tue, 2 Dec 2014 17:55:57 +0100 +Subject: [PATCH 13/66] Updated NEWS with latest changes + +--- + NEWS | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/NEWS b/NEWS +index 1720654..6052936 100644 +--- a/NEWS ++++ b/NEWS +@@ -1,3 +1,13 @@ ++Version 1.1.1 ++~~~~~~~~~~~~~ ++ ++* Changes: ++ - Use clock_gettime() instead of gettimeofday() to avoid timing issues ++ when calculating packet timeouts ++ - Get correct USB device speed instead of hardcoded value ++ - Use non-blocking sockets for client communication to avoid hanging ++ - Use correct manual section (8) for manpage ++ + Version 1.1.0 + ~~~~~~~~~~~~~ + +-- +2.23.0 + + +From ab51bbbe6d78678db1bdd04be1eeec6bb1d59c34 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Tue, 11 Nov 2014 14:34:26 +0100 +Subject: [PATCH 14/66] Rename usb-linux.c to more suitable usb.c + +--- + src/Makefile.am | 2 +- + src/{usb-linux.c => usb.c} | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + rename src/{usb-linux.c => usb.c} (99%) + +diff --git a/src/Makefile.am b/src/Makefile.am +index b92eb64..5ef0d3b 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -11,7 +11,7 @@ usbmuxd_SOURCES = client.c client.h \ + device.c device.h \ + preflight.c preflight.h \ + log.c log.h \ +- usbmuxd-proto.h usb-linux.c usb.h \ ++ usbmuxd-proto.h usb.c usb.h \ + utils.c utils.h \ + conf.c conf.h \ + main.c +diff --git a/src/usb-linux.c b/src/usb.c +similarity index 99% +rename from src/usb-linux.c +rename to src/usb.c +index 9878f41..f5e8092 100644 +--- a/src/usb-linux.c ++++ b/src/usb.c +@@ -1,5 +1,5 @@ + /* +- * usb-linux.c ++ * usb.c + * + * Copyright (C) 2009 Hector Martin + * Copyright (C) 2009 Nikias Bassen +-- +2.23.0 + + +From b752fbc1dd92238a34c888fbaef921aa802c4a82 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Tue, 11 Nov 2014 14:47:22 +0100 +Subject: [PATCH 15/66] usb: Implement device discovery using libusb hotplug + events + +--- + src/usb.c | 470 +++++++++++++++++++++++++++++++----------------------- + 1 file changed, 268 insertions(+), 202 deletions(-) + +diff --git a/src/usb.c b/src/usb.c +index f5e8092..3ce2abb 100644 +--- a/src/usb.c ++++ b/src/usb.c +@@ -36,6 +36,10 @@ + #include "device.h" + #include "utils.h" + ++#if (defined(LIBUSB_API_VERSION) && (LIBUSB_API_VERSION >= 0x01000102)) || (defined(LIBUSBX_API_VERSION) && (LIBUSBX_API_VERSION >= 0x01000102)) ++#define HAVE_LIBUSB_HOTPLUG_API 1 ++#endif ++ + // interval for device connection/disconnection polling, in milliseconds + // we need this because there is currently no asynchronous device discovery mechanism in libusb + #define DEVICE_POLL_TIME 1000 +@@ -65,6 +69,7 @@ static struct timeval next_dev_poll_time; + + static int devlist_failures; + static int device_polling; ++static int device_hotplug = 1; + + static void usb_disconnect(struct usb_device *dev) + { +@@ -253,9 +258,217 @@ static int start_rx_loop(struct usb_device *dev) + return 0; + } + ++static int usb_device_add(libusb_device* dev) ++{ ++ int j, res; ++ // the following are non-blocking operations on the device list ++ uint8_t bus = libusb_get_bus_number(dev); ++ uint8_t address = libusb_get_device_address(dev); ++ struct libusb_device_descriptor devdesc; ++ int found = 0; ++ FOREACH(struct usb_device *usbdev, &device_list) { ++ if(usbdev->bus == bus && usbdev->address == address) { ++ usbdev->alive = 1; ++ found = 1; ++ break; ++ } ++ } ENDFOREACH ++ if(found) ++ return 0; //device already found ++ ++ if((res = libusb_get_device_descriptor(dev, &devdesc)) != 0) { ++ usbmuxd_log(LL_WARNING, "Could not get device descriptor for device %d-%d: %d", bus, address, res); ++ return -1; ++ } ++ if(devdesc.idVendor != VID_APPLE) ++ return -1; ++ if((devdesc.idProduct < PID_RANGE_LOW) || ++ (devdesc.idProduct > PID_RANGE_MAX)) ++ return -1; ++ libusb_device_handle *handle; ++ usbmuxd_log(LL_INFO, "Found new device with v/p %04x:%04x at %d-%d", devdesc.idVendor, devdesc.idProduct, bus, address); ++ // potentially blocking operations follow; they will only run when new devices are detected, which is acceptable ++ if((res = libusb_open(dev, &handle)) != 0) { ++ usbmuxd_log(LL_WARNING, "Could not open device %d-%d: %d", bus, address, res); ++ return -1; ++ } ++ ++ int current_config = 0; ++ if((res = libusb_get_configuration(handle, ¤t_config)) != 0) { ++ usbmuxd_log(LL_WARNING, "Could not get configuration for device %d-%d: %d", bus, address, res); ++ libusb_close(handle); ++ return -1; ++ } ++ if (current_config != devdesc.bNumConfigurations) { ++ struct libusb_config_descriptor *config; ++ if((res = libusb_get_active_config_descriptor(dev, &config)) != 0) { ++ usbmuxd_log(LL_NOTICE, "Could not get old configuration descriptor for device %d-%d: %d", bus, address, res); ++ } else { ++ for(j=0; jbNumInterfaces; j++) { ++ const struct libusb_interface_descriptor *intf = &config->interface[j].altsetting[0]; ++ if((res = libusb_kernel_driver_active(handle, intf->bInterfaceNumber)) < 0) { ++ usbmuxd_log(LL_NOTICE, "Could not check kernel ownership of interface %d for device %d-%d: %d", intf->bInterfaceNumber, bus, address, res); ++ continue; ++ } ++ if(res == 1) { ++ usbmuxd_log(LL_INFO, "Detaching kernel driver for device %d-%d, interface %d", bus, address, intf->bInterfaceNumber); ++ if((res = libusb_detach_kernel_driver(handle, intf->bInterfaceNumber)) < 0) { ++ usbmuxd_log(LL_WARNING, "Could not detach kernel driver (%d), configuration change will probably fail!", res); ++ continue; ++ } ++ } ++ } ++ libusb_free_config_descriptor(config); ++ } ++ ++ usbmuxd_log(LL_INFO, "Setting configuration for device %d-%d, from %d to %d", bus, address, current_config, devdesc.bNumConfigurations); ++ if((res = libusb_set_configuration(handle, devdesc.bNumConfigurations)) != 0) { ++ usbmuxd_log(LL_WARNING, "Could not set configuration %d for device %d-%d: %d", devdesc.bNumConfigurations, bus, address, res); ++ libusb_close(handle); ++ return -1; ++ } ++ } ++ ++ struct libusb_config_descriptor *config; ++ if((res = libusb_get_active_config_descriptor(dev, &config)) != 0) { ++ usbmuxd_log(LL_WARNING, "Could not get configuration descriptor for device %d-%d: %d", bus, address, res); ++ libusb_close(handle); ++ return -1; ++ } ++ ++ struct usb_device *usbdev; ++ usbdev = malloc(sizeof(struct usb_device)); ++ memset(usbdev, 0, sizeof(*usbdev)); ++ ++ for(j=0; jbNumInterfaces; j++) { ++ const struct libusb_interface_descriptor *intf = &config->interface[j].altsetting[0]; ++ if(intf->bInterfaceClass != INTERFACE_CLASS || ++ intf->bInterfaceSubClass != INTERFACE_SUBCLASS || ++ intf->bInterfaceProtocol != INTERFACE_PROTOCOL) ++ continue; ++ if(intf->bNumEndpoints != 2) { ++ usbmuxd_log(LL_WARNING, "Endpoint count mismatch for interface %d of device %d-%d", intf->bInterfaceNumber, bus, address); ++ continue; ++ } ++ if((intf->endpoint[0].bEndpointAddress & 0x80) == LIBUSB_ENDPOINT_OUT && ++ (intf->endpoint[1].bEndpointAddress & 0x80) == LIBUSB_ENDPOINT_IN) { ++ usbdev->interface = intf->bInterfaceNumber; ++ usbdev->ep_out = intf->endpoint[0].bEndpointAddress; ++ usbdev->ep_in = intf->endpoint[1].bEndpointAddress; ++ usbmuxd_log(LL_INFO, "Found interface %d with endpoints %02x/%02x for device %d-%d", usbdev->interface, usbdev->ep_out, usbdev->ep_in, bus, address); ++ break; ++ } else if((intf->endpoint[1].bEndpointAddress & 0x80) == LIBUSB_ENDPOINT_OUT && ++ (intf->endpoint[0].bEndpointAddress & 0x80) == LIBUSB_ENDPOINT_IN) { ++ usbdev->interface = intf->bInterfaceNumber; ++ usbdev->ep_out = intf->endpoint[1].bEndpointAddress; ++ usbdev->ep_in = intf->endpoint[0].bEndpointAddress; ++ usbmuxd_log(LL_INFO, "Found interface %d with swapped endpoints %02x/%02x for device %d-%d", usbdev->interface, usbdev->ep_out, usbdev->ep_in, bus, address); ++ break; ++ } else { ++ usbmuxd_log(LL_WARNING, "Endpoint type mismatch for interface %d of device %d-%d", intf->bInterfaceNumber, bus, address); ++ } ++ } ++ ++ if(j == config->bNumInterfaces) { ++ usbmuxd_log(LL_WARNING, "Could not find a suitable USB interface for device %d-%d", bus, address); ++ libusb_free_config_descriptor(config); ++ libusb_close(handle); ++ free(usbdev); ++ return -1; ++ } ++ ++ libusb_free_config_descriptor(config); ++ ++ if((res = libusb_claim_interface(handle, usbdev->interface)) != 0) { ++ usbmuxd_log(LL_WARNING, "Could not claim interface %d for device %d-%d: %d", usbdev->interface, bus, address, res); ++ libusb_close(handle); ++ free(usbdev); ++ return -1; ++ } ++ ++ if((res = libusb_get_string_descriptor_ascii(handle, devdesc.iSerialNumber, (uint8_t *)usbdev->serial, 256)) <= 0) { ++ usbmuxd_log(LL_WARNING, "Could not get serial number for device %d-%d: %d", bus, address, res); ++ libusb_release_interface(handle, usbdev->interface); ++ libusb_close(handle); ++ free(usbdev); ++ return -1; ++ } ++ usbdev->serial[res] = 0; ++ usbdev->bus = bus; ++ usbdev->address = address; ++ usbdev->vid = devdesc.idVendor; ++ usbdev->pid = devdesc.idProduct; ++ usbdev->speed = 480000000; ++ usbdev->dev = handle; ++ usbdev->alive = 1; ++ usbdev->wMaxPacketSize = libusb_get_max_packet_size(dev, usbdev->ep_out); ++ if (usbdev->wMaxPacketSize <= 0) { ++ usbmuxd_log(LL_ERROR, "Could not determine wMaxPacketSize for device %d-%d, setting to 64", usbdev->bus, usbdev->address); ++ usbdev->wMaxPacketSize = 64; ++ } else { ++ usbmuxd_log(LL_INFO, "Using wMaxPacketSize=%d for device %d-%d", usbdev->wMaxPacketSize, usbdev->bus, usbdev->address); ++ } ++ ++ switch (libusb_get_device_speed(dev)) { ++ case LIBUSB_SPEED_LOW: ++ usbdev->speed = 1500000; ++ break; ++ case LIBUSB_SPEED_FULL: ++ usbdev->speed = 12000000; ++ break; ++ case LIBUSB_SPEED_SUPER: ++ usbdev->speed = 5000000000; ++ break; ++ case LIBUSB_SPEED_HIGH: ++ case LIBUSB_SPEED_UNKNOWN: ++ default: ++ usbdev->speed = 480000000; ++ break; ++ } ++ ++ usbmuxd_log(LL_INFO, "USB Speed is %g MBit/s for device %d-%d", (double)(usbdev->speed / 1000000.0), usbdev->bus, usbdev->address); ++ ++ collection_init(&usbdev->tx_xfers); ++ collection_init(&usbdev->rx_xfers); ++ ++ collection_add(&device_list, usbdev); ++ ++ if(device_add(usbdev) < 0) { ++ usb_disconnect(usbdev); ++ return -1; ++ } ++ ++ // Spin up NUM_RX_LOOPS parallel usb data retrieval loops ++ // Old usbmuxds used only 1 rx loop, but that leaves the ++ // USB port sleeping most of the time ++ int rx_loops = NUM_RX_LOOPS; ++ for (rx_loops = NUM_RX_LOOPS; rx_loops > 0; rx_loops--) { ++ if(start_rx_loop(usbdev) < 0) { ++ usbmuxd_log(LL_WARNING, "Failed to start RX loop number %d", NUM_RX_LOOPS - rx_loops); ++ } ++ } ++ ++ // Ensure we have at least 1 RX loop going ++ if (rx_loops == NUM_RX_LOOPS) { ++ usbmuxd_log(LL_FATAL, "Failed to start any RX loop for device %d-%d", ++ usbdev->bus, usbdev->address); ++ device_remove(usbdev); ++ usb_disconnect(usbdev); ++ return -1; ++ } else if (rx_loops > 0) { ++ usbmuxd_log(LL_WARNING, "Failed to start all %d RX loops. Going on with %d loops. " ++ "This may have negative impact on device read speed.", ++ NUM_RX_LOOPS, NUM_RX_LOOPS - rx_loops); ++ } else { ++ usbmuxd_log(LL_DEBUG, "All %d RX loops started successfully", NUM_RX_LOOPS); ++ } ++ ++ return 0; ++} ++ + int usb_discover(void) + { +- int cnt, i, j, res; ++ int cnt, i; + int valid_count = 0; + libusb_device **devs; + +@@ -288,209 +501,10 @@ int usb_discover(void) + // Enumerate all USB devices and mark the ones we already know + // about as live, again + for(i=0; ibus == bus && usbdev->address == address) { +- valid_count++; +- usbdev->alive = 1; +- found = 1; +- break; +- } +- } ENDFOREACH +- if(found) +- continue; //device already found +- if((res = libusb_get_device_descriptor(dev, &devdesc)) != 0) { +- usbmuxd_log(LL_WARNING, "Could not get device descriptor for device %d-%d: %d", bus, address, res); +- continue; +- } +- if(devdesc.idVendor != VID_APPLE) +- continue; +- if((devdesc.idProduct < PID_RANGE_LOW) || +- (devdesc.idProduct > PID_RANGE_MAX)) +- continue; +- libusb_device_handle *handle; +- usbmuxd_log(LL_INFO, "Found new device with v/p %04x:%04x at %d-%d", devdesc.idVendor, devdesc.idProduct, bus, address); +- // potentially blocking operations follow; they will only run when new devices are detected, which is acceptable +- if((res = libusb_open(dev, &handle)) != 0) { +- usbmuxd_log(LL_WARNING, "Could not open device %d-%d: %d", bus, address, res); ++ if (usb_device_add(dev) < 0) { + continue; + } +- +- int current_config = 0; +- if((res = libusb_get_configuration(handle, ¤t_config)) != 0) { +- usbmuxd_log(LL_WARNING, "Could not get configuration for device %d-%d: %d", bus, address, res); +- libusb_close(handle); +- continue; +- } +- if (current_config != devdesc.bNumConfigurations) { +- struct libusb_config_descriptor *config; +- if((res = libusb_get_active_config_descriptor(dev, &config)) != 0) { +- usbmuxd_log(LL_NOTICE, "Could not get old configuration descriptor for device %d-%d: %d", bus, address, res); +- } else { +- for(j=0; jbNumInterfaces; j++) { +- const struct libusb_interface_descriptor *intf = &config->interface[j].altsetting[0]; +- if((res = libusb_kernel_driver_active(handle, intf->bInterfaceNumber)) < 0) { +- usbmuxd_log(LL_NOTICE, "Could not check kernel ownership of interface %d for device %d-%d: %d", intf->bInterfaceNumber, bus, address, res); +- continue; +- } +- if(res == 1) { +- usbmuxd_log(LL_INFO, "Detaching kernel driver for device %d-%d, interface %d", bus, address, intf->bInterfaceNumber); +- if((res = libusb_detach_kernel_driver(handle, intf->bInterfaceNumber)) < 0) { +- usbmuxd_log(LL_WARNING, "Could not detach kernel driver (%d), configuration change will probably fail!", res); +- continue; +- } +- } +- } +- libusb_free_config_descriptor(config); +- } +- +- usbmuxd_log(LL_INFO, "Setting configuration for device %d-%d, from %d to %d", bus, address, current_config, devdesc.bNumConfigurations); +- if((res = libusb_set_configuration(handle, devdesc.bNumConfigurations)) != 0) { +- usbmuxd_log(LL_WARNING, "Could not set configuration %d for device %d-%d: %d", devdesc.bNumConfigurations, bus, address, res); +- libusb_close(handle); +- continue; +- } +- } +- +- struct libusb_config_descriptor *config; +- if((res = libusb_get_active_config_descriptor(dev, &config)) != 0) { +- usbmuxd_log(LL_WARNING, "Could not get configuration descriptor for device %d-%d: %d", bus, address, res); +- libusb_close(handle); +- continue; +- } +- +- struct usb_device *usbdev; +- usbdev = malloc(sizeof(struct usb_device)); +- memset(usbdev, 0, sizeof(*usbdev)); +- +- for(j=0; jbNumInterfaces; j++) { +- const struct libusb_interface_descriptor *intf = &config->interface[j].altsetting[0]; +- if(intf->bInterfaceClass != INTERFACE_CLASS || +- intf->bInterfaceSubClass != INTERFACE_SUBCLASS || +- intf->bInterfaceProtocol != INTERFACE_PROTOCOL) +- continue; +- if(intf->bNumEndpoints != 2) { +- usbmuxd_log(LL_WARNING, "Endpoint count mismatch for interface %d of device %d-%d", intf->bInterfaceNumber, bus, address); +- continue; +- } +- if((intf->endpoint[0].bEndpointAddress & 0x80) == LIBUSB_ENDPOINT_OUT && +- (intf->endpoint[1].bEndpointAddress & 0x80) == LIBUSB_ENDPOINT_IN) { +- usbdev->interface = intf->bInterfaceNumber; +- usbdev->ep_out = intf->endpoint[0].bEndpointAddress; +- usbdev->ep_in = intf->endpoint[1].bEndpointAddress; +- usbmuxd_log(LL_INFO, "Found interface %d with endpoints %02x/%02x for device %d-%d", usbdev->interface, usbdev->ep_out, usbdev->ep_in, bus, address); +- break; +- } else if((intf->endpoint[1].bEndpointAddress & 0x80) == LIBUSB_ENDPOINT_OUT && +- (intf->endpoint[0].bEndpointAddress & 0x80) == LIBUSB_ENDPOINT_IN) { +- usbdev->interface = intf->bInterfaceNumber; +- usbdev->ep_out = intf->endpoint[1].bEndpointAddress; +- usbdev->ep_in = intf->endpoint[0].bEndpointAddress; +- usbmuxd_log(LL_INFO, "Found interface %d with swapped endpoints %02x/%02x for device %d-%d", usbdev->interface, usbdev->ep_out, usbdev->ep_in, bus, address); +- break; +- } else { +- usbmuxd_log(LL_WARNING, "Endpoint type mismatch for interface %d of device %d-%d", intf->bInterfaceNumber, bus, address); +- } +- } +- +- if(j == config->bNumInterfaces) { +- usbmuxd_log(LL_WARNING, "Could not find a suitable USB interface for device %d-%d", bus, address); +- libusb_free_config_descriptor(config); +- libusb_close(handle); +- free(usbdev); +- continue; +- } +- +- libusb_free_config_descriptor(config); +- +- if((res = libusb_claim_interface(handle, usbdev->interface)) != 0) { +- usbmuxd_log(LL_WARNING, "Could not claim interface %d for device %d-%d: %d", usbdev->interface, bus, address, res); +- libusb_close(handle); +- free(usbdev); +- continue; +- } +- +- if((res = libusb_get_string_descriptor_ascii(handle, devdesc.iSerialNumber, (uint8_t *)usbdev->serial, 256)) <= 0) { +- usbmuxd_log(LL_WARNING, "Could not get serial number for device %d-%d: %d", bus, address, res); +- libusb_release_interface(handle, usbdev->interface); +- libusb_close(handle); +- free(usbdev); +- continue; +- } +- usbdev->serial[res] = 0; +- usbdev->bus = bus; +- usbdev->address = address; +- usbdev->vid = devdesc.idVendor; +- usbdev->pid = devdesc.idProduct; +- usbdev->speed = 480000000; +- usbdev->dev = handle; +- usbdev->alive = 1; +- usbdev->wMaxPacketSize = libusb_get_max_packet_size(dev, usbdev->ep_out); +- if (usbdev->wMaxPacketSize <= 0) { +- usbmuxd_log(LL_ERROR, "Could not determine wMaxPacketSize for device %d-%d, setting to 64", usbdev->bus, usbdev->address); +- usbdev->wMaxPacketSize = 64; +- } else { +- usbmuxd_log(LL_INFO, "Using wMaxPacketSize=%d for device %d-%d", usbdev->wMaxPacketSize, usbdev->bus, usbdev->address); +- } +- +- switch (libusb_get_device_speed(dev)) { +- case LIBUSB_SPEED_LOW: +- usbdev->speed = 1500000; +- break; +- case LIBUSB_SPEED_FULL: +- usbdev->speed = 12000000; +- break; +- case LIBUSB_SPEED_SUPER: +- usbdev->speed = 5000000000; +- break; +- case LIBUSB_SPEED_HIGH: +- case LIBUSB_SPEED_UNKNOWN: +- default: +- usbdev->speed = 480000000; +- break; +- } +- +- usbmuxd_log(LL_INFO, "USB Speed is %g MBit/s for device %d-%d", (double)(usbdev->speed / 1000000.0), usbdev->bus, usbdev->address); +- +- collection_init(&usbdev->tx_xfers); +- collection_init(&usbdev->rx_xfers); +- +- collection_add(&device_list, usbdev); +- +- if(device_add(usbdev) < 0) { +- usb_disconnect(usbdev); +- continue; +- } +- +- // Spin up NUM_RX_LOOPS parallel usb data retrieval loops +- // Old usbmuxds used only 1 rx loop, but that leaves the +- // USB port sleeping most of the time +- int rx_loops = NUM_RX_LOOPS; +- for (rx_loops = NUM_RX_LOOPS; rx_loops > 0; rx_loops--) { +- if(start_rx_loop(usbdev) < 0) { +- usbmuxd_log(LL_WARNING, "Failed to start RX loop number %d", NUM_RX_LOOPS - rx_loops); +- } +- } +- +- // Ensure we have at least 1 RX loop going +- if (rx_loops == NUM_RX_LOOPS) { +- usbmuxd_log(LL_FATAL, "Failed to start any RX loop for device %d-%d", +- usbdev->bus, usbdev->address); +- device_remove(usbdev); +- usb_disconnect(usbdev); +- continue; +- } else if (rx_loops > 0) { +- usbmuxd_log(LL_WARNING, "Failed to start all %d RX loops. Going on with %d loops. " +- "This may have negative impact on device read speed.", +- NUM_RX_LOOPS, NUM_RX_LOOPS - rx_loops); +- } else { +- usbmuxd_log(LL_DEBUG, "All %d RX loops started successfully", NUM_RX_LOOPS); +- } +- + valid_count++; + } + +@@ -560,6 +574,7 @@ void usb_autodiscover(int enable) + { + usbmuxd_log(LL_DEBUG, "usb polling enable: %d", enable); + device_polling = enable; ++ device_hotplug = enable; + } + + static int dev_poll_remain_ms(void) +@@ -649,6 +664,32 @@ int usb_process_timeout(int msec) + return 0; + } + ++#ifdef HAVE_LIBUSB_HOTPLUG_API ++static libusb_hotplug_callback_handle usb_hotplug_cb_handle; ++ ++static int usb_hotplug_cb(libusb_context *ctx, libusb_device *device, libusb_hotplug_event event, void *user_data) ++{ ++ if (LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED == event) { ++ if (device_hotplug) { ++ usb_device_add(device); ++ } ++ } else if (LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT == event) { ++ uint8_t bus = libusb_get_bus_number(device); ++ uint8_t address = libusb_get_device_address(device); ++ FOREACH(struct usb_device *usbdev, &device_list) { ++ if(usbdev->bus == bus && usbdev->address == address) { ++ usbdev->alive = 0; ++ device_remove(usbdev); ++ break; ++ } ++ } ENDFOREACH ++ } else { ++ usbmuxd_log(LL_ERROR, "Unhandled event %d", event); ++ } ++ return 0; ++} ++#endif ++ + int usb_init(void) + { + int res; +@@ -665,12 +706,37 @@ int usb_init(void) + + collection_init(&device_list); + +- return usb_discover(); ++#ifdef HAVE_LIBUSB_HOTPLUG_API ++ if (libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) { ++ usbmuxd_log(LL_INFO, "Registering for libusb hotplug events"); ++ res = libusb_hotplug_register_callback(NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, LIBUSB_HOTPLUG_ENUMERATE, VID_APPLE, LIBUSB_HOTPLUG_MATCH_ANY, 0, usb_hotplug_cb, NULL, &usb_hotplug_cb_handle); ++ if (res == LIBUSB_SUCCESS) { ++ device_polling = 0; ++ } else { ++ usbmuxd_log(LL_ERROR, "ERROR: Could not register for libusb hotplug events (%d)", res); ++ } ++ } else { ++ usbmuxd_log(LL_ERROR, "libusb does not support hotplug events"); ++ } ++#endif ++ if (device_polling) { ++ res = usb_discover(); ++ if (res >= 0) { ++ } ++ } else { ++ res = collection_count(&device_list); ++ } ++ return res; + } + + void usb_shutdown(void) + { + usbmuxd_log(LL_DEBUG, "usb_shutdown"); ++ ++#ifdef HAVE_LIBUSB_HOTPLUG_API ++ libusb_hotplug_deregister_callback(NULL, usb_hotplug_cb_handle); ++#endif ++ + FOREACH(struct usb_device *usbdev, &device_list) { + device_remove(usbdev); + usb_disconnect(usbdev); +-- +2.23.0 + + +From 4b102f04bc67f1128ba55ac90b2bf2cb1ce09850 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Tue, 11 Nov 2014 14:47:54 +0100 +Subject: [PATCH 16/66] preflight: Remove obsoleted extern function + declarations + +--- + src/preflight.h | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/src/preflight.h b/src/preflight.h +index 7c45bb9..dd8647e 100644 +--- a/src/preflight.h ++++ b/src/preflight.h +@@ -22,9 +22,6 @@ + + #include "device.h" + +-extern void userpref_get_system_buid(char **systembuid); +-extern void userpref_device_record_get_host_id(const char *udid, char **host_id); +- + void preflight_device_remove_cb(void *data); + void preflight_worker_device_add(struct device_info* info); + +-- +2.23.0 + + +From 816b587e32d894083bf884ca647e6c734b242e3f Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Tue, 2 Dec 2014 19:22:05 +0100 +Subject: [PATCH 17/66] Update NEWS with latest changes + +--- + NEWS | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/NEWS b/NEWS +index 6052936..7430c27 100644 +--- a/NEWS ++++ b/NEWS +@@ -2,6 +2,7 @@ Version 1.1.1 + ~~~~~~~~~~~~~ + + * Changes: ++ - Make use of libusb hotplug events for device discovery + - Use clock_gettime() instead of gettimeofday() to avoid timing issues + when calculating packet timeouts + - Get correct USB device speed instead of hardcoded value +-- +2.23.0 + + +From 423fb8c0e9750190d2b7f9c306df9efaa7080dbd Mon Sep 17 00:00:00 2001 +From: Martin Szulecki +Date: Wed, 28 Jan 2015 19:35:10 +0100 +Subject: [PATCH 18/66] Update README with new git URL, IRC and twitter profile + +--- + README | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/README b/README +index be2d70a..7d96013 100644 +--- a/README ++++ b/README +@@ -69,7 +69,7 @@ Home: + http://www.libimobiledevice.org/ + + Code: +- git clone http://git.sukimashita.com/usbmuxd.git ++ git clone http://git.libimobiledevice.org/usbmuxd.git + + Code (Mirror): + git clone https://github.com/libimobiledevice/usbmuxd.git +@@ -83,6 +83,9 @@ Mailing List: + IRC: + irc://irc.freenode.net#libimobiledevice + ++Twitter: ++ https://twitter.com/libimobiledev ++ + Credits + ======= + +@@ -93,4 +96,4 @@ libimobiledevice is an independent software library and has not been + authorized, sponsored, or otherwise approved by Apple Inc. + + README Updated on: +- 2014-10-02 ++ 2015-01-28 +-- +2.23.0 + + +From 90a38cc24794d2807c7e0a3d11f2eaaea76b8ebd Mon Sep 17 00:00:00 2001 +From: Aaron Burghardt +Date: Fri, 31 Jul 2015 12:28:20 -0400 +Subject: [PATCH 19/66] send_system_buid: fix leak of buid string returned by + config_get_system_buid. + +--- + src/client.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/client.c b/src/client.c +index 4ec4025..e4154d2 100644 +--- a/src/client.c ++++ b/src/client.c +@@ -373,6 +373,7 @@ static int send_system_buid(struct mux_client *client, uint32_t tag) + + plist_t dict = plist_new_dict(); + plist_dict_set_item(dict, "BUID", plist_new_string(buid)); ++ free(buid); + res = send_plist_pkt(client, tag, dict); + plist_free(dict); + return res; +-- +2.23.0 + + +From 726db697a22b4eb3de4ce8e2c8697cc16465c73a Mon Sep 17 00:00:00 2001 +From: Aaron Burghardt +Date: Fri, 31 Jul 2015 12:34:22 -0400 +Subject: [PATCH 20/66] internal_get_value: fix over-free of node returned by + plist_dict_get_item. + +--- + src/conf.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/src/conf.c b/src/conf.c +index 0dcb062..9c9233a 100644 +--- a/src/conf.c ++++ b/src/conf.c +@@ -290,7 +290,6 @@ static int internal_get_value(const char* config_file, const char *key, plist_t + plist_t n = plist_dict_get_item(config, key); + if (n) { + *value = plist_copy(n); +- plist_free(n); + n = NULL; + } + } +-- +2.23.0 + + +From fc3982fa1e3e8972f8f49e2e35eef82e02f1deaf Mon Sep 17 00:00:00 2001 +From: Aaron Burghardt +Date: Thu, 30 Jul 2015 15:31:50 -0400 +Subject: [PATCH 21/66] Add a static clock_gettime() substitute for OS X. + +--- + src/utils.c | 33 +++++++++++++++++++++++++++++++++ + 1 file changed, 33 insertions(+) + +diff --git a/src/utils.c b/src/utils.c +index ceb65e1..67860b3 100644 +--- a/src/utils.c ++++ b/src/utils.c +@@ -30,6 +30,9 @@ + #include + #include + #include ++#ifdef __APPLE__ ++#include ++#endif + + #include "utils.h" + +@@ -299,6 +302,36 @@ int plist_write_to_filename(plist_t plist, const char *filename, enum plist_form + return 1; + } + ++#ifdef __APPLE__ ++typedef int clockid_t; ++#define CLOCK_MONOTONIC 1 ++ ++static int clock_gettime(clockid_t clk_id, struct timespec *ts) ++{ ++ // See http://developer.apple.com/library/mac/qa/qa1398 ++ ++ uint64_t mach_time, nano_sec; ++ ++ static mach_timebase_info_data_t base_info; ++ ++ mach_time = mach_absolute_time(); ++ ++ if (base_info.denom == 0) { ++ (void) mach_timebase_info(&base_info); ++ } ++ ++ if (base_info.numer == 1 && base_info.denom == 1) ++ nano_sec = mach_time; ++ else ++ nano_sec = mach_time * base_info.numer / base_info.denom; ++ ++ ts->tv_sec = nano_sec / 1000000000; ++ ts->tv_nsec = nano_sec % 1000000000; ++ ++ return 0; ++} ++#endif ++ + void get_tick_count(struct timeval * tv) + { + struct timespec ts; +-- +2.23.0 + + +From 9120f132edffe4e05a31179c18453979656ffd3a Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Thu, 28 Jan 2016 16:24:07 +0100 +Subject: [PATCH 22/66] Fix debug message printing the wrong timeout value + +--- + src/main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/main.c b/src/main.c +index 2e4439c..4f792c4 100644 +--- a/src/main.c ++++ b/src/main.c +@@ -189,7 +189,7 @@ static int main_loop(int listenfd) + to = usb_get_timeout(); + usbmuxd_log(LL_FLOOD, "USB timeout is %d ms", to); + dto = device_get_timeout(); +- usbmuxd_log(LL_FLOOD, "Device timeout is %d ms", to); ++ usbmuxd_log(LL_FLOOD, "Device timeout is %d ms", dto); + if(dto < to) + to = dto; + +-- +2.23.0 + + +From 86dbc6cc25ddac32369ae5d47cec35cf16283ace Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Thu, 28 Jan 2016 16:29:08 +0100 +Subject: [PATCH 23/66] device: Plug small memory leak + +--- + src/device.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/device.c b/src/device.c +index ddd1d4a..5374d7c 100644 +--- a/src/device.c ++++ b/src/device.c +@@ -829,6 +829,7 @@ int device_add(struct usb_device *usbdev) + vh.padding = 0; + if((res = send_packet(dev, MUX_PROTO_VERSION, &vh, NULL, 0)) < 0) { + usbmuxd_log(LL_ERROR, "Error sending version request packet to device %d", id); ++ free(dev->pktbuf); + free(dev); + return res; + } +-- +2.23.0 + + +From e2f4d0fd3ca51b3809b4982b4e5241ac5c477c5d Mon Sep 17 00:00:00 2001 +From: Jan Beich +Date: Thu, 28 Jan 2016 16:43:28 +0100 +Subject: [PATCH 24/66] Try to autodetect ppoll(2) instead of hardcoding the + list of platforms lacking it thus using fallback. + +--- + configure.ac | 1 + + src/main.c | 2 +- + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/configure.ac b/configure.ac +index 6c2481a..d204ba0 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -96,6 +96,7 @@ AC_TYPE_UINT8_T + AC_FUNC_MALLOC + AC_FUNC_REALLOC + AC_CHECK_FUNCS([strcasecmp strdup strerror strndup stpcpy]) ++AC_CHECK_FUNCS([ppoll]) + + # Check for operating system + AC_MSG_CHECKING([whether to enable WIN32 build settings]) +diff --git a/src/main.c b/src/main.c +index 4f792c4..a276e90 100644 +--- a/src/main.c ++++ b/src/main.c +@@ -159,7 +159,7 @@ static void set_signal_handlers(void) + sigaction(SIGUSR2, &sa, NULL); + } + +-#if defined(__FreeBSD__) || defined(__APPLE__) ++#ifndef HAVE_PPOLL + static int ppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout, const sigset_t *sigmask) + { + int ready; +-- +2.23.0 + + +From 35e5d48f29ae03b2b9686109e4ed9ab8b9677ce8 Mon Sep 17 00:00:00 2001 +From: Moritz Schlarb +Date: Sun, 15 Nov 2015 15:29:14 +0100 +Subject: [PATCH 25/66] Fix --with-systemd argument to configure + +Otherwise, specifying ''--with-systemd'' will actually lead to systemd support being disabled. +Got that from https://www.gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf-2.69/html_node/External-Software.html (last example). +--- + configure.ac | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/configure.ac b/configure.ac +index d204ba0..5e8fad7 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -59,7 +59,7 @@ fi + AC_ARG_WITH([systemd], + [AS_HELP_STRING([--without-systemd], + [do not build with systemd support @<:@default=yes@:>@])], +- [with_systemd=no], ++ [], + [with_systemd=yes]) + + AC_ARG_WITH([systemdsystemunitdir], +-- +2.23.0 + + +From 8a5545de25d243955c68fb8d6c1bd9ef856b8e8a Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Mon, 17 Jul 2017 21:08:15 +0200 +Subject: [PATCH 26/66] utils: Use autoconf to check for availability of + clock_gettime() + +--- + configure.ac | 2 +- + src/utils.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 5e8fad7..b836f45 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -96,7 +96,7 @@ AC_TYPE_UINT8_T + AC_FUNC_MALLOC + AC_FUNC_REALLOC + AC_CHECK_FUNCS([strcasecmp strdup strerror strndup stpcpy]) +-AC_CHECK_FUNCS([ppoll]) ++AC_CHECK_FUNCS([ppoll clock_gettime]) + + # Check for operating system + AC_MSG_CHECKING([whether to enable WIN32 build settings]) +diff --git a/src/utils.c b/src/utils.c +index 67860b3..28664d4 100644 +--- a/src/utils.c ++++ b/src/utils.c +@@ -302,7 +302,7 @@ int plist_write_to_filename(plist_t plist, const char *filename, enum plist_form + return 1; + } + +-#ifdef __APPLE__ ++#ifndef HAVE_CLOCK_GETTIME + typedef int clockid_t; + #define CLOCK_MONOTONIC 1 + +-- +2.23.0 + + +From b6ec966d105e9f72d3a5a671afe526f54f3d327f Mon Sep 17 00:00:00 2001 +From: Frederik Carlier +Date: Sun, 29 Oct 2017 22:04:17 +0100 +Subject: [PATCH 27/66] Better error handling when saving pair records + +plist_write_to_filename and buffer_write_to_filename now return 0 if the actual write operation failed (e.g. because access is denied to the file), and set errno if required. +--- + src/utils.c | 42 ++++++++++++++++++++++++++++++++---------- + src/utils.h | 4 ++-- + 2 files changed, 34 insertions(+), 12 deletions(-) + +diff --git a/src/utils.c b/src/utils.c +index 28664d4..e30a0b3 100644 +--- a/src/utils.c ++++ b/src/utils.c +@@ -30,6 +30,7 @@ + #include + #include + #include ++#include + #ifdef __APPLE__ + #include + #endif +@@ -214,7 +215,7 @@ char *string_concat(const char *str, ...) + return result; + } + +-void buffer_read_from_filename(const char *filename, char **buffer, uint64_t *length) ++int buffer_read_from_filename(const char *filename, char **buffer, uint64_t *length) + { + FILE *f; + uint64_t size; +@@ -223,7 +224,7 @@ void buffer_read_from_filename(const char *filename, char **buffer, uint64_t *le + + f = fopen(filename, "rb"); + if (!f) { +- return; ++ return 0; + } + + fseek(f, 0, SEEK_END); +@@ -232,26 +233,49 @@ void buffer_read_from_filename(const char *filename, char **buffer, uint64_t *le + + if (size == 0) { + fclose(f); +- return; ++ return 0; + } + + *buffer = (char*)malloc(sizeof(char)*(size+1)); ++ ++ if (!buffer) { ++ return 0; ++ } ++ ++ int ret = 1; + if (fread(*buffer, sizeof(char), size, f) != size) { + usbmuxd_log(LL_ERROR, "%s: ERROR: couldn't read %d bytes from %s", __func__, (int)size, filename); ++ free(buffer); ++ ret = 0; ++ errno = EIO; + } + fclose(f); + + *length = size; ++ return ret; + } + +-void buffer_write_to_filename(const char *filename, const char *buffer, uint64_t length) ++int buffer_write_to_filename(const char *filename, const char *buffer, uint64_t length) + { + FILE *f; + + f = fopen(filename, "wb"); + if (f) { +- fwrite(buffer, sizeof(char), length, f); ++ size_t written = fwrite(buffer, sizeof(char), length, f); + fclose(f); ++ ++ if (written == length) { ++ return 1; ++ } ++ else { ++ // Not all data could be written. ++ errno = EIO; ++ return 0; ++ } ++ } ++ else { ++ // Failed to open the file, let the caller know. ++ return 0; + } + } + +@@ -263,9 +287,7 @@ int plist_read_from_filename(plist_t *plist, const char *filename) + if (!filename) + return 0; + +- buffer_read_from_filename(filename, &buffer, &length); +- +- if (!buffer) { ++ if (!buffer_read_from_filename(filename, &buffer, &length)) { + return 0; + } + +@@ -295,11 +317,11 @@ int plist_write_to_filename(plist_t plist, const char *filename, enum plist_form + else + return 0; + +- buffer_write_to_filename(filename, buffer, length); ++ int res = buffer_write_to_filename(filename, buffer, length); + + free(buffer); + +- return 1; ++ return res; + } + + #ifndef HAVE_CLOCK_GETTIME +diff --git a/src/utils.h b/src/utils.h +index 1137a93..b5cab3f 100644 +--- a/src/utils.h ++++ b/src/utils.h +@@ -75,8 +75,8 @@ char *stpcpy(char * s1, const char * s2); + #endif + char *string_concat(const char *str, ...); + +-void buffer_read_from_filename(const char *filename, char **buffer, uint64_t *length); +-void buffer_write_to_filename(const char *filename, const char *buffer, uint64_t length); ++int buffer_read_from_filename(const char *filename, char **buffer, uint64_t *length); ++int buffer_write_to_filename(const char *filename, const char *buffer, uint64_t length); + + enum plist_format_t { + PLIST_FORMAT_XML, +-- +2.23.0 + + +From 46bdf3ec90acf3916ee8aba622a7da9da5eb8e06 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Sun, 29 Oct 2017 22:06:21 +0100 +Subject: [PATCH 28/66] conf: Report an error if writing to config file fails + +--- + src/conf.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/src/conf.c b/src/conf.c +index 9c9233a..f211d99 100644 +--- a/src/conf.c ++++ b/src/conf.c +@@ -254,11 +254,11 @@ static int internal_set_value(const char *config_file, const char *key, plist_t + usbmuxd_log(LL_DEBUG, "setting key %s in config_file %s", key, config_file); + } + +- plist_write_to_filename(config, config_file, PLIST_FORMAT_XML); ++ int res = plist_write_to_filename(config, config_file, PLIST_FORMAT_XML); + + plist_free(config); + +- return 1; ++ return res; + } + + static int config_set_value(const char *key, plist_t value) +@@ -273,6 +273,9 @@ static int config_set_value(const char *key, plist_t value) + config_file = string_concat(config_path, DIR_SEP_S, CONFIG_FILE, NULL); + + int result = internal_set_value(config_file, key, value); ++ if (!result) { ++ usbmuxd_log(LL_ERROR, "ERROR: Failed to write to '%s': %s", config_file, strerror(errno)); ++ } + + free(config_file); + +@@ -378,7 +381,9 @@ void config_get_system_buid(char **system_buid) + /* no config, generate system_buid */ + usbmuxd_log(LL_DEBUG, "no previous %s found", CONFIG_SYSTEM_BUID_KEY); + *system_buid = config_generate_system_buid(); +- config_set_system_buid(*system_buid); ++ if (!config_set_system_buid(*system_buid)) { ++ usbmuxd_log(LL_WARNING, "WARNING: Failed to store SystemBUID, this might be a problem"); ++ } + } + + usbmuxd_log(LL_DEBUG, "using %s as %s", *system_buid, CONFIG_SYSTEM_BUID_KEY); +-- +2.23.0 + + +From 7f601f8e5241756c09d08a1319d90f24b9f8b1bc Mon Sep 17 00:00:00 2001 +From: Rudolf Tammekivi +Date: Thu, 28 Dec 2017 16:20:19 +0200 +Subject: [PATCH 29/66] client: Plug memory leak + +--- + src/client.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/client.c b/src/client.c +index e4154d2..a9d09d3 100644 +--- a/src/client.c ++++ b/src/client.c +@@ -617,6 +617,7 @@ static int client_command(struct mux_client *client, struct usbmuxd_header *hdr) + } else { + rval = EINVAL; + } ++ free(record_data); + if (send_result(client, hdr->tag, rval) < 0) + return -1; + return 0; +-- +2.23.0 + + +From 789b16a4a42ab56899092392f1c2d5dde6e9dd34 Mon Sep 17 00:00:00 2001 +From: Alexis Ballier +Date: Sun, 7 Jan 2018 02:41:48 +0100 +Subject: [PATCH 30/66] usb: Store the whole device descriptor in struct + usb_device + +--- + src/usb.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/src/usb.c b/src/usb.c +index 3ce2abb..e0fadfd 100644 +--- a/src/usb.c ++++ b/src/usb.c +@@ -53,7 +53,6 @@ + struct usb_device { + libusb_device_handle *dev; + uint8_t bus, address; +- uint16_t vid, pid; + char serial[256]; + int alive; + uint8_t interface, ep_in, ep_out; +@@ -61,6 +60,7 @@ struct usb_device { + struct collection tx_xfers; + int wMaxPacketSize; + uint64_t speed; ++ struct libusb_device_descriptor devdesc; + }; + + static struct collection device_list; +@@ -396,8 +396,7 @@ static int usb_device_add(libusb_device* dev) + usbdev->serial[res] = 0; + usbdev->bus = bus; + usbdev->address = address; +- usbdev->vid = devdesc.idVendor; +- usbdev->pid = devdesc.idProduct; ++ usbdev->devdesc = devdesc; + usbdev->speed = 480000000; + usbdev->dev = handle; + usbdev->alive = 1; +@@ -542,7 +541,7 @@ uint16_t usb_get_pid(struct usb_device *dev) + if(!dev->dev) { + return 0; + } +- return dev->pid; ++ return dev->devdesc.idProduct; + } + + uint64_t usb_get_speed(struct usb_device *dev) +-- +2.23.0 + + +From d29b74db77433a80fa2eb293216e8f572ffe4c57 Mon Sep 17 00:00:00 2001 +From: Alexis Ballier +Date: Mon, 8 Jan 2018 02:00:12 +0100 +Subject: [PATCH 31/66] usb: Use libusb asynchronous I/O for getting initial + device information. + +usb_device_add may now be called from libusb main loop via the hotplug +callbacks. +No blocking call must occur there and libusb 1.0.21 now returns an error +when trying to perform blocking I/O in this callback. + +Should fix the error when hotpluging a device reported in #81 +--- + src/usb.c | 146 +++++++++++++++++++++++++++++++++++++++++------------- + 1 file changed, 111 insertions(+), 35 deletions(-) + +diff --git a/src/usb.c b/src/usb.c +index e0fadfd..88d781d 100644 +--- a/src/usb.c ++++ b/src/usb.c +@@ -61,6 +61,7 @@ struct usb_device { + int wMaxPacketSize; + uint64_t speed; + struct libusb_device_descriptor devdesc; ++ unsigned char transfer_buffer[1024 + LIBUSB_CONTROL_SETUP_SIZE]; + }; + + static struct collection device_list; +@@ -258,6 +259,91 @@ static int start_rx_loop(struct usb_device *dev) + return 0; + } + ++static void get_serial_callback(struct libusb_transfer *transfer) ++{ ++ unsigned int di, si; ++ struct usb_device *usbdev = transfer->user_data; ++ ++ if(transfer->status != LIBUSB_TRANSFER_COMPLETED) { ++ usbmuxd_log(LL_ERROR, "Failed to request serial for device %d-%d (%i)", usbdev->bus, usbdev->address, transfer->status); ++ libusb_free_transfer(transfer); ++ return; ++ } ++ ++ /* De-unicode, taken from libusb */ ++ unsigned char *data = libusb_control_transfer_get_data(transfer); ++ for (di = 0, si = 2; si < data[0] && di < sizeof(usbdev->serial)-1; si += 2) { ++ if ((data[si] & 0x80) || (data[si + 1])) /* non-ASCII */ ++ usbdev->serial[di++] = '?'; ++ else ++ usbdev->serial[di++] = data[si]; ++ } ++ usbdev->serial[di] = 0; ++ ++ usbmuxd_log(LL_INFO, "Got serial '%s' for device %d-%d", usbdev->serial, usbdev->bus, usbdev->address); ++ ++ libusb_free_transfer(transfer); ++ ++ /* Finish setup now */ ++ if(device_add(usbdev) < 0) { ++ usb_disconnect(usbdev); ++ return; ++ } ++ ++ // Spin up NUM_RX_LOOPS parallel usb data retrieval loops ++ // Old usbmuxds used only 1 rx loop, but that leaves the ++ // USB port sleeping most of the time ++ int rx_loops = NUM_RX_LOOPS; ++ for (rx_loops = NUM_RX_LOOPS; rx_loops > 0; rx_loops--) { ++ if(start_rx_loop(usbdev) < 0) { ++ usbmuxd_log(LL_WARNING, "Failed to start RX loop number %d", NUM_RX_LOOPS - rx_loops); ++ } ++ } ++ ++ // Ensure we have at least 1 RX loop going ++ if (rx_loops == NUM_RX_LOOPS) { ++ usbmuxd_log(LL_FATAL, "Failed to start any RX loop for device %d-%d", ++ usbdev->bus, usbdev->address); ++ device_remove(usbdev); ++ usb_disconnect(usbdev); ++ return; ++ } else if (rx_loops > 0) { ++ usbmuxd_log(LL_WARNING, "Failed to start all %d RX loops. Going on with %d loops. " ++ "This may have negative impact on device read speed.", ++ NUM_RX_LOOPS, NUM_RX_LOOPS - rx_loops); ++ } else { ++ usbmuxd_log(LL_DEBUG, "All %d RX loops started successfully", NUM_RX_LOOPS); ++ } ++} ++ ++static void get_langid_callback(struct libusb_transfer *transfer) ++{ ++ int res; ++ struct usb_device *usbdev = transfer->user_data; ++ ++ if(transfer->status != LIBUSB_TRANSFER_COMPLETED) { ++ usbmuxd_log(LL_ERROR, "Failed to request lang ID for device %d-%d (%i)", usbdev->bus, ++ usbdev->address, transfer->status); ++ libusb_free_transfer(transfer); ++ return; ++ } ++ ++ unsigned char *data = libusb_control_transfer_get_data(transfer); ++ uint16_t langid = (uint16_t)(data[2] | (data[3] << 8)); ++ usbmuxd_log(LL_INFO, "Got lang ID %u for device %d-%d", langid, usbdev->bus, usbdev->address); ++ ++ /* re-use the same transfer */ ++ libusb_fill_control_setup(usbdev->transfer_buffer, LIBUSB_ENDPOINT_IN, LIBUSB_REQUEST_GET_DESCRIPTOR, ++ (uint16_t)((LIBUSB_DT_STRING << 8) | usbdev->devdesc.iSerialNumber), ++ langid, sizeof(usbdev->transfer_buffer)); ++ libusb_fill_control_transfer(transfer, usbdev->dev, usbdev->transfer_buffer, get_serial_callback, usbdev, 1000); ++ ++ if((res = libusb_submit_transfer(transfer)) < 0) { ++ usbmuxd_log(LL_ERROR, "Could not request transfer for device %d-%d (%d)", usbdev->bus, usbdev->address, res); ++ libusb_free_transfer(transfer); ++ } ++} ++ + static int usb_device_add(libusb_device* dev) + { + int j, res; +@@ -265,6 +351,7 @@ static int usb_device_add(libusb_device* dev) + uint8_t bus = libusb_get_bus_number(dev); + uint8_t address = libusb_get_device_address(dev); + struct libusb_device_descriptor devdesc; ++ struct libusb_transfer *transfer; + int found = 0; + FOREACH(struct usb_device *usbdev, &device_list) { + if(usbdev->bus == bus && usbdev->address == address) { +@@ -287,7 +374,8 @@ static int usb_device_add(libusb_device* dev) + return -1; + libusb_device_handle *handle; + usbmuxd_log(LL_INFO, "Found new device with v/p %04x:%04x at %d-%d", devdesc.idVendor, devdesc.idProduct, bus, address); +- // potentially blocking operations follow; they will only run when new devices are detected, which is acceptable ++ // No blocking operation can follow: it may be run in the libusb hotplug callback and libusb will refuse any ++ // blocking call + if((res = libusb_open(dev, &handle)) != 0) { + usbmuxd_log(LL_WARNING, "Could not open device %d-%d: %d", bus, address, res); + return -1; +@@ -386,14 +474,15 @@ static int usb_device_add(libusb_device* dev) + return -1; + } + +- if((res = libusb_get_string_descriptor_ascii(handle, devdesc.iSerialNumber, (uint8_t *)usbdev->serial, 256)) <= 0) { +- usbmuxd_log(LL_WARNING, "Could not get serial number for device %d-%d: %d", bus, address, res); +- libusb_release_interface(handle, usbdev->interface); ++ transfer = libusb_alloc_transfer(0); ++ if(!transfer) { ++ usbmuxd_log(LL_WARNING, "Failed to allocate transfer for device %d-%d: %d", bus, address, res); + libusb_close(handle); + free(usbdev); + return -1; + } +- usbdev->serial[res] = 0; ++ ++ usbdev->serial[0] = 0; + usbdev->bus = bus; + usbdev->address = address; + usbdev->devdesc = devdesc; +@@ -427,40 +516,27 @@ static int usb_device_add(libusb_device* dev) + + usbmuxd_log(LL_INFO, "USB Speed is %g MBit/s for device %d-%d", (double)(usbdev->speed / 1000000.0), usbdev->bus, usbdev->address); + +- collection_init(&usbdev->tx_xfers); +- collection_init(&usbdev->rx_xfers); +- +- collection_add(&device_list, usbdev); +- +- if(device_add(usbdev) < 0) { +- usb_disconnect(usbdev); ++ /** ++ * From libusb: ++ * Asking for the zero'th index is special - it returns a string ++ * descriptor that contains all the language IDs supported by the ++ * device. ++ **/ ++ libusb_fill_control_setup(usbdev->transfer_buffer, LIBUSB_ENDPOINT_IN, LIBUSB_REQUEST_GET_DESCRIPTOR, LIBUSB_DT_STRING << 8, 0, sizeof(usbdev->transfer_buffer)); ++ libusb_fill_control_transfer(transfer, handle, usbdev->transfer_buffer, get_langid_callback, usbdev, 1000); ++ ++ if((res = libusb_submit_transfer(transfer)) < 0) { ++ usbmuxd_log(LL_ERROR, "Could not request transfer for device %d-%d (%d)", usbdev->bus, usbdev->address, res); ++ libusb_free_transfer(transfer); ++ libusb_close(handle); ++ free(usbdev); + return -1; + } + +- // Spin up NUM_RX_LOOPS parallel usb data retrieval loops +- // Old usbmuxds used only 1 rx loop, but that leaves the +- // USB port sleeping most of the time +- int rx_loops = NUM_RX_LOOPS; +- for (rx_loops = NUM_RX_LOOPS; rx_loops > 0; rx_loops--) { +- if(start_rx_loop(usbdev) < 0) { +- usbmuxd_log(LL_WARNING, "Failed to start RX loop number %d", NUM_RX_LOOPS - rx_loops); +- } +- } ++ collection_init(&usbdev->tx_xfers); ++ collection_init(&usbdev->rx_xfers); + +- // Ensure we have at least 1 RX loop going +- if (rx_loops == NUM_RX_LOOPS) { +- usbmuxd_log(LL_FATAL, "Failed to start any RX loop for device %d-%d", +- usbdev->bus, usbdev->address); +- device_remove(usbdev); +- usb_disconnect(usbdev); +- return -1; +- } else if (rx_loops > 0) { +- usbmuxd_log(LL_WARNING, "Failed to start all %d RX loops. Going on with %d loops. " +- "This may have negative impact on device read speed.", +- NUM_RX_LOOPS, NUM_RX_LOOPS - rx_loops); +- } else { +- usbmuxd_log(LL_DEBUG, "All %d RX loops started successfully", NUM_RX_LOOPS); +- } ++ collection_add(&device_list, usbdev); + + return 0; + } +-- +2.23.0 + + +From 63cd3057a38c8daf49e839712f1f0bebd0046acb Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Mon, 8 Jan 2018 02:35:36 +0100 +Subject: [PATCH 32/66] usb: Use heap buffer instead of making the usb_device + struct larger + +Since this buffer is only used during device initialization we don't want +the usb_device struct to be unecessary big. +--- + src/usb.c | 24 ++++++++++++++++++------ + 1 file changed, 18 insertions(+), 6 deletions(-) + +diff --git a/src/usb.c b/src/usb.c +index 88d781d..df05b9d 100644 +--- a/src/usb.c ++++ b/src/usb.c +@@ -61,7 +61,6 @@ struct usb_device { + int wMaxPacketSize; + uint64_t speed; + struct libusb_device_descriptor devdesc; +- unsigned char transfer_buffer[1024 + LIBUSB_CONTROL_SETUP_SIZE]; + }; + + static struct collection device_list; +@@ -321,6 +320,8 @@ static void get_langid_callback(struct libusb_transfer *transfer) + int res; + struct usb_device *usbdev = transfer->user_data; + ++ transfer->flags |= LIBUSB_TRANSFER_FREE_BUFFER; ++ + if(transfer->status != LIBUSB_TRANSFER_COMPLETED) { + usbmuxd_log(LL_ERROR, "Failed to request lang ID for device %d-%d (%i)", usbdev->bus, + usbdev->address, transfer->status); +@@ -333,10 +334,10 @@ static void get_langid_callback(struct libusb_transfer *transfer) + usbmuxd_log(LL_INFO, "Got lang ID %u for device %d-%d", langid, usbdev->bus, usbdev->address); + + /* re-use the same transfer */ +- libusb_fill_control_setup(usbdev->transfer_buffer, LIBUSB_ENDPOINT_IN, LIBUSB_REQUEST_GET_DESCRIPTOR, ++ libusb_fill_control_setup(transfer->buffer, LIBUSB_ENDPOINT_IN, LIBUSB_REQUEST_GET_DESCRIPTOR, + (uint16_t)((LIBUSB_DT_STRING << 8) | usbdev->devdesc.iSerialNumber), +- langid, sizeof(usbdev->transfer_buffer)); +- libusb_fill_control_transfer(transfer, usbdev->dev, usbdev->transfer_buffer, get_serial_callback, usbdev, 1000); ++ langid, 1024 + LIBUSB_CONTROL_SETUP_SIZE); ++ libusb_fill_control_transfer(transfer, usbdev->dev, transfer->buffer, get_serial_callback, usbdev, 1000); + + if((res = libusb_submit_transfer(transfer)) < 0) { + usbmuxd_log(LL_ERROR, "Could not request transfer for device %d-%d (%d)", usbdev->bus, usbdev->address, res); +@@ -482,6 +483,16 @@ static int usb_device_add(libusb_device* dev) + return -1; + } + ++ unsigned char *transfer_buffer = malloc(1024 + LIBUSB_CONTROL_SETUP_SIZE + 8); ++usbmuxd_log(LL_INFO, "%p", transfer_buffer); ++ if (!transfer_buffer) { ++ usbmuxd_log(LL_WARNING, "Failed to allocate transfer buffer for device %d-%d: %d", bus, address, res); ++ libusb_close(handle); ++ free(usbdev); ++ return -1; ++ } ++ memset(transfer_buffer, '\0', 1024 + LIBUSB_CONTROL_SETUP_SIZE + 8); ++ + usbdev->serial[0] = 0; + usbdev->bus = bus; + usbdev->address = address; +@@ -522,13 +533,14 @@ static int usb_device_add(libusb_device* dev) + * descriptor that contains all the language IDs supported by the + * device. + **/ +- libusb_fill_control_setup(usbdev->transfer_buffer, LIBUSB_ENDPOINT_IN, LIBUSB_REQUEST_GET_DESCRIPTOR, LIBUSB_DT_STRING << 8, 0, sizeof(usbdev->transfer_buffer)); +- libusb_fill_control_transfer(transfer, handle, usbdev->transfer_buffer, get_langid_callback, usbdev, 1000); ++ libusb_fill_control_setup(transfer_buffer, LIBUSB_ENDPOINT_IN, LIBUSB_REQUEST_GET_DESCRIPTOR, LIBUSB_DT_STRING << 8, 0, 1024 + LIBUSB_CONTROL_SETUP_SIZE); ++ libusb_fill_control_transfer(transfer, handle, transfer_buffer, get_langid_callback, usbdev, 1000); + + if((res = libusb_submit_transfer(transfer)) < 0) { + usbmuxd_log(LL_ERROR, "Could not request transfer for device %d-%d (%d)", usbdev->bus, usbdev->address, res); + libusb_free_transfer(transfer); + libusb_close(handle); ++ free(transfer_buffer); + free(usbdev); + return -1; + } +-- +2.23.0 + + +From 17179ab58fac82a0dca48a5c88ef19c6c70ff8a5 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Mon, 8 Jan 2018 02:46:15 +0100 +Subject: [PATCH 33/66] usb: Fix calculation of RX loop count + +--- + src/usb.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/usb.c b/src/usb.c +index df05b9d..6225bd5 100644 +--- a/src/usb.c ++++ b/src/usb.c +@@ -296,6 +296,7 @@ static void get_serial_callback(struct libusb_transfer *transfer) + for (rx_loops = NUM_RX_LOOPS; rx_loops > 0; rx_loops--) { + if(start_rx_loop(usbdev) < 0) { + usbmuxd_log(LL_WARNING, "Failed to start RX loop number %d", NUM_RX_LOOPS - rx_loops); ++ break; + } + } + +-- +2.23.0 + + +From 9dfc1eb993a886532c38553a4eeefcfa79180417 Mon Sep 17 00:00:00 2001 +From: Carlos Maddela +Date: Mon, 18 Sep 2017 14:32:46 +1000 +Subject: [PATCH 34/66] Fix typo in error message. + +--- + src/device.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/device.c b/src/device.c +index 5374d7c..6d807f2 100644 +--- a/src/device.c ++++ b/src/device.c +@@ -588,7 +588,7 @@ static void device_control_input(struct mux_device *dev, unsigned char *payload, + usbmuxd_log(LL_ERROR, "%s: ERROR: %s", __func__, buf); + free(buf); + } else { +- usbmuxd_log(LL_ERROR, "%s: Error occured, but empty error message", __func__); ++ usbmuxd_log(LL_ERROR, "%s: Error occurred, but empty error message", __func__); + } + break; + case 7: +-- +2.23.0 + + +From 27cbec8e00b2da5ac0514c76473d6d0b0164ab6f Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Wed, 31 Jan 2018 00:48:54 +0100 +Subject: [PATCH 35/66] usb: Remove leftover debug log output + +--- + src/usb.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/src/usb.c b/src/usb.c +index 6225bd5..0977c24 100644 +--- a/src/usb.c ++++ b/src/usb.c +@@ -485,7 +485,6 @@ static int usb_device_add(libusb_device* dev) + } + + unsigned char *transfer_buffer = malloc(1024 + LIBUSB_CONTROL_SETUP_SIZE + 8); +-usbmuxd_log(LL_INFO, "%p", transfer_buffer); + if (!transfer_buffer) { + usbmuxd_log(LL_WARNING, "Failed to allocate transfer buffer for device %d-%d: %d", bus, address, res); + libusb_close(handle); +-- +2.23.0 + + +From 7f54d304149f405dc70ac924471df0d5e3e5ea09 Mon Sep 17 00:00:00 2001 +From: Gavin Li +Date: Sun, 14 Jan 2018 02:10:18 -0800 +Subject: [PATCH 36/66] udev: ensure that all events relating to device are + tagged systemd + +systemd will not restart the usbmuxd service the after the first time it +is plugged in if it does not receive the "remove" events, which also +happen to lack the idVendor and idProduct attributes, so use +ENV{PRODUCT} instead. +--- + configure.ac | 2 +- + udev/39-usbmuxd.rules.in | 7 +++++-- + 2 files changed, 6 insertions(+), 3 deletions(-) + +diff --git a/configure.ac b/configure.ac +index b836f45..1ce46d8 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -74,7 +74,7 @@ fi + AM_CONDITIONAL(WANT_SYSTEMD, [test -n "$with_systemdsystemunitdir" -a "x$with_systemdsystemunitdir" != xno -a "x$with_systemd" = "xyes" ]) + + if test "x$with_systemd" = xyes; then +- udev_activation_rule="TAG+=\"systemd\", ENV{SYSTEMD_WANTS}=\"usbmuxd.service\"" ++ udev_activation_rule="ENV{SYSTEMD_WANTS}=\"usbmuxd.service\"" + else + udev_activation_rule="RUN+=\"@sbindir@/usbmuxd --user usbmux --udev\"" + fi +diff --git a/udev/39-usbmuxd.rules.in b/udev/39-usbmuxd.rules.in +index 91b14db..7d14d22 100644 +--- a/udev/39-usbmuxd.rules.in ++++ b/udev/39-usbmuxd.rules.in +@@ -1,7 +1,10 @@ + # usbmuxd (Apple Mobile Device Muxer listening on /var/run/usbmuxd) + ++# systemd should receive all events relating to device ++SUBSYSTEM=="usb", ENV{PRODUCT}=="5ac/12[9a][0-9a-f]/*", TAG+="systemd" ++ + # Initialize iOS devices into "deactivated" USB configuration state and activate usbmuxd +-ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="05ac", ATTR{idProduct}=="12[9a][0-9a-f]", ENV{USBMUX_SUPPORTED}="1", ATTR{bConfigurationValue}="0", OWNER="usbmux", @udev_activation_rule@ ++SUBSYSTEM=="usb", ENV{PRODUCT}=="5ac/12[9a][0-9a-f]/*", ACTION=="add", ENV{USBMUX_SUPPORTED}="1", ATTR{bConfigurationValue}="0", OWNER="usbmux", @udev_activation_rule@ + + # Exit usbmuxd when the last device is removed +-ACTION=="remove", SUBSYSTEM=="usb", ENV{PRODUCT}=="5ac/12[9a][0-9a-f]/*", ENV{INTERFACE}=="255/*", RUN+="@sbindir@/usbmuxd -x" ++SUBSYSTEM=="usb", ENV{PRODUCT}=="5ac/12[9a][0-9a-f]/*", ACTION=="remove", RUN+="@sbindir@/usbmuxd -x" +-- +2.23.0 + + +From b888970f68fb16961a7cc3a526065fab7a5d96ca Mon Sep 17 00:00:00 2001 +From: Rudolf Tammekivi +Date: Wed, 31 Jan 2018 01:10:54 +0100 +Subject: [PATCH 37/66] udev: Handle all events only once + +This fixes spontaneous USB reconfiguration causing "remove" event to be sent to +the daemon, which causes it to close itself if it did not have enough time to +connect to phone. +--- + udev/39-usbmuxd.rules.in | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/udev/39-usbmuxd.rules.in b/udev/39-usbmuxd.rules.in +index 7d14d22..140869e 100644 +--- a/udev/39-usbmuxd.rules.in ++++ b/udev/39-usbmuxd.rules.in +@@ -1,10 +1,10 @@ + # usbmuxd (Apple Mobile Device Muxer listening on /var/run/usbmuxd) + + # systemd should receive all events relating to device +-SUBSYSTEM=="usb", ENV{PRODUCT}=="5ac/12[9a][0-9a-f]/*", TAG+="systemd" ++SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ENV{PRODUCT}=="5ac/12[9a][0-9a-f]/*", TAG+="systemd" + + # Initialize iOS devices into "deactivated" USB configuration state and activate usbmuxd +-SUBSYSTEM=="usb", ENV{PRODUCT}=="5ac/12[9a][0-9a-f]/*", ACTION=="add", ENV{USBMUX_SUPPORTED}="1", ATTR{bConfigurationValue}="0", OWNER="usbmux", @udev_activation_rule@ ++SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ENV{PRODUCT}=="5ac/12[9a][0-9a-f]/*", ACTION=="add", ENV{USBMUX_SUPPORTED}="1", ATTR{bConfigurationValue}="0", OWNER="usbmux", @udev_activation_rule@ + + # Exit usbmuxd when the last device is removed +-SUBSYSTEM=="usb", ENV{PRODUCT}=="5ac/12[9a][0-9a-f]/*", ACTION=="remove", RUN+="@sbindir@/usbmuxd -x" ++SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ENV{PRODUCT}=="5ac/12[9a][0-9a-f]/*", ACTION=="remove", RUN+="@sbindir@/usbmuxd -x" +-- +2.23.0 + + +From e567b881bdce3e3e7b46d2a9d0d344b876257606 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Mon, 9 Apr 2018 16:57:38 +0200 +Subject: [PATCH 38/66] log: Fix timestamps being printed incorrectly when + running in foreground + +Due to usage of wrong function (get_tick_count) the timestamps have +been printed incorrectly based on clock_gettime. This commit fixes it by +using gettimeofday correctly and also makes sure that this is thread-safe +by using localtime_r if available. +Furthermore, this commit will also have the effect that when logging +through syslog we don't determine the current time anymore because the +timestamp is not even used. +--- + src/log.c | 16 +++++++++++----- + 1 file changed, 11 insertions(+), 5 deletions(-) + +diff --git a/src/log.c b/src/log.c +index 46839ee..cd7c2d5 100644 +--- a/src/log.c ++++ b/src/log.c +@@ -65,20 +65,26 @@ void usbmuxd_log(enum loglevel level, const char *fmt, ...) + { + va_list ap; + char *fs; +- struct timeval ts; +- struct tm *tp; + + if(level > log_level) + return; + +- get_tick_count(&ts); +- tp = localtime(&ts.tv_sec); +- + fs = malloc(20 + strlen(fmt)); + + if(log_syslog) { + sprintf(fs, "[%d] %s\n", level, fmt); + } else { ++ struct timeval ts; ++ struct tm tp_; ++ struct tm *tp; ++ ++ gettimeofday(&ts, NULL); ++#ifdef HAVE_LOCALTIME_R ++ tp = localtime_r(&ts.tv_sec, &tp_); ++#else ++ tp = localtime(&ts.tv_sec); ++#endif ++ + strftime(fs, 10, "[%H:%M:%S", tp); + sprintf(fs+9, ".%03d][%d] %s\n", (int)(ts.tv_usec / 1000), level, fmt); + } +-- +2.23.0 + + +From 13dd964026558f85f38caae848635b6931b42bc1 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Mon, 9 Apr 2018 18:01:46 +0200 +Subject: [PATCH 39/66] configure: Add missing check for localtime_r introduced + in previous commit + +--- + configure.ac | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/configure.ac b/configure.ac +index 1ce46d8..2690f78 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -96,7 +96,7 @@ AC_TYPE_UINT8_T + AC_FUNC_MALLOC + AC_FUNC_REALLOC + AC_CHECK_FUNCS([strcasecmp strdup strerror strndup stpcpy]) +-AC_CHECK_FUNCS([ppoll clock_gettime]) ++AC_CHECK_FUNCS([ppoll clock_gettime localtime_r]) + + # Check for operating system + AC_MSG_CHECKING([whether to enable WIN32 build settings]) +-- +2.23.0 + + +From b95a0a014d48e3d4169d2f9885fcd0863abd57c1 Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Wed, 18 Apr 2018 18:44:23 +0200 +Subject: [PATCH 40/66] udev: Work around systemd bug related to bind events on + Linux 4.12+ + +Make sure that udev doesn't lose our properties when bind events come +in, as implemented in kernels 4.12+. + +See https://github.com/systemd/systemd/issues/8221 +and https://github.com/systemd/systemd/issues/7109 +--- + udev/39-usbmuxd.rules.in | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/udev/39-usbmuxd.rules.in b/udev/39-usbmuxd.rules.in +index 140869e..4e84755 100644 +--- a/udev/39-usbmuxd.rules.in ++++ b/udev/39-usbmuxd.rules.in +@@ -6,5 +6,8 @@ SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ENV{PRODUCT}=="5ac/12[9a][0-9a-f]/ + # Initialize iOS devices into "deactivated" USB configuration state and activate usbmuxd + SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ENV{PRODUCT}=="5ac/12[9a][0-9a-f]/*", ACTION=="add", ENV{USBMUX_SUPPORTED}="1", ATTR{bConfigurationValue}="0", OWNER="usbmux", @udev_activation_rule@ + ++# Make sure properties don't get lost when bind action is called ++SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ENV{PRODUCT}=="5ac/12[9a][0-9a-f]/*", ACTION=="bind", ENV{USBMUX_SUPPORTED}="1", OWNER="usbmux", @udev_activation_rule@ ++ + # Exit usbmuxd when the last device is removed + SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ENV{PRODUCT}=="5ac/12[9a][0-9a-f]/*", ACTION=="remove", RUN+="@sbindir@/usbmuxd -x" +-- +2.23.0 + + +From 065a2cd678f5335c14d157dc0bc35286e562a4d6 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Wed, 9 May 2018 14:59:36 +0200 +Subject: [PATCH 41/66] Remove whitespace errors + +--- + src/device.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/src/device.c b/src/device.c +index 6d807f2..d5cf9f0 100644 +--- a/src/device.c ++++ b/src/device.c +@@ -129,7 +129,7 @@ pthread_mutex_t device_list_mutex; + + static struct mux_device* get_mux_device_for_id(int device_id) + { +- struct mux_device *dev = NULL; ++ struct mux_device *dev = NULL; + pthread_mutex_lock(&device_list_mutex); + FOREACH(struct mux_device *cdev, &device_list) { + if(cdev->id == device_id) { +@@ -433,12 +433,12 @@ static int send_tcp_ack(struct mux_connection *conn) + if(send_tcp(conn, TH_ACK, NULL, 0) < 0) { + usbmuxd_log(LL_ERROR, "Error sending TCP ACK (%d->%d)", conn->sport, conn->dport); + connection_teardown(conn); +- return -1; ++ return -1; + } + +- update_connection(conn); ++ update_connection(conn); + +- return 0; ++ return 0; + } + + /** +@@ -534,7 +534,7 @@ static void connection_device_input(struct mux_connection *conn, unsigned char * + + void device_abort_connect(int device_id, struct mux_client *client) + { +- struct mux_connection *conn = get_mux_connection(device_id, client); ++ struct mux_connection *conn = get_mux_connection(device_id, client); + if (conn) { + connection_teardown(conn); + } else { +@@ -740,7 +740,7 @@ void device_data_input(struct usb_device *usbdev, unsigned char *buffer, uint32_ + dev->pktlen = 0; + return; + } +- memcpy(dev->pktbuf + dev->pktlen, buffer, length); ++ memcpy(dev->pktbuf + dev->pktlen, buffer, length); + struct mux_header *mhdr = (struct mux_header *)dev->pktbuf; + if((length < USB_MRU) || (ntohl(mhdr->length) == (length + dev->pktlen))) { + buffer = dev->pktbuf; +-- +2.23.0 + + +From ca6f4718deb56367bbae33312e0f341e0595f3eb Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Tue, 15 May 2018 00:24:58 +0200 +Subject: [PATCH 42/66] client: Set socket options for client connections to + improve performance + +--- + src/client.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/src/client.c b/src/client.c +index a9d09d3..a9c986a 100644 +--- a/src/client.c ++++ b/src/client.c +@@ -30,6 +30,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -171,6 +172,17 @@ int client_accept(int listenfd) + } + } + ++ int bufsize = 0x20000; ++ if (setsockopt(cfd, SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(int)) == -1) { ++ usbmuxd_log(LL_WARNING, "Could not set send buffer for client socket"); ++ } ++ if (setsockopt(cfd, SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(int)) == -1) { ++ usbmuxd_log(LL_WARNING, "Could not set receive buffer for client socket"); ++ } ++ ++ int yes = 1; ++ setsockopt(cfd, IPPROTO_TCP, TCP_NODELAY, (void*)&yes, sizeof(int)); ++ + struct mux_client *client; + client = malloc(sizeof(struct mux_client)); + memset(client, 0, sizeof(struct mux_client)); +-- +2.23.0 + + +From 08d9ec01cf59c7bb3febe3c4600e9efeb81901e3 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Tue, 15 May 2018 00:27:52 +0200 +Subject: [PATCH 43/66] device: Flush buffer to client when remote side + unexpectedly terminates connection + +--- + src/client.c | 3 ++- + src/device.c | 15 ++++++++++++++- + 2 files changed, 16 insertions(+), 2 deletions(-) + +diff --git a/src/client.c b/src/client.c +index a9c986a..bbdac84 100644 +--- a/src/client.c ++++ b/src/client.c +@@ -113,7 +113,8 @@ int client_write(struct mux_client *client, void *buffer, uint32_t len) + sret = send(client->fd, buffer, len, 0); + if (sret < 0) { + if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { +- usbmuxd_log(LL_ERROR, "ERROR: client_write: fd %d not ready for writing", client->fd); ++ usbmuxd_log(LL_DEBUG, "client_write: fd %d not ready for writing", client->fd); ++ sret = 0; + } else { + usbmuxd_log(LL_ERROR, "ERROR: client_write: sending to fd %d failed: %s", client->fd, strerror(errno)); + } +diff --git a/src/device.c b/src/device.c +index d5cf9f0..3edaea0 100644 +--- a/src/device.c ++++ b/src/device.c +@@ -32,6 +32,7 @@ + #include + #include + #include ++#include + #include "device.h" + #include "client.h" + #include "preflight.h" +@@ -314,10 +315,21 @@ static void connection_teardown(struct mux_connection *conn) + } else { + conn->state = CONN_DEAD; + if((conn->events & POLLOUT) && conn->ib_size > 0){ ++ usbmuxd_log(LL_DEBUG, "%s: flushing buffer to client (%u bytes)", __func__, conn->ib_size); ++ uint64_t tm_last = mstime64(); + while(1){ + size = client_write(conn->client, conn->ib_buf, conn->ib_size); +- if(size <= 0) { ++ if(size < 0) { ++ usbmuxd_log(LL_ERROR, "%s: aborting buffer flush to client after error.", __func__); + break; ++ } else if (size == 0) { ++ uint64_t tm_now = mstime64(); ++ if (tm_now - tm_last > 1000) { ++ usbmuxd_log(LL_ERROR, "%s: aborting buffer flush to client after unsuccessfully attempting for %dms.", __func__, (int)(tm_now - tm_last)); ++ break; ++ } ++ usleep(10000); ++ continue; + } + if(size == (int)conn->ib_size) { + conn->ib_size = 0; +@@ -326,6 +338,7 @@ static void connection_teardown(struct mux_connection *conn) + conn->ib_size -= size; + memmove(conn->ib_buf, conn->ib_buf + size, conn->ib_size); + } ++ tm_last = mstime64(); + } + } + client_close(conn->client); +-- +2.23.0 + + +From ee85938c21043ef5f7cd4dfbc7677f385814d4d8 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Mon, 23 Jul 2018 03:52:58 +0100 +Subject: [PATCH 44/66] client: Implement ListListeners command + +--- + src/client.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 117 insertions(+), 4 deletions(-) + +diff --git a/src/client.c b/src/client.c +index bbdac84..a24233c 100644 +--- a/src/client.c ++++ b/src/client.c +@@ -26,6 +26,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -69,10 +70,13 @@ struct mux_client { + int connect_device; + enum client_state state; + uint32_t proto_version; ++ uint32_t number; ++ plist_t info; + }; + + static struct collection client_list; + pthread_mutex_t client_list_mutex; ++static uint32_t client_number = 0; + + /** + * Receive raw data from the client socket. +@@ -197,8 +201,10 @@ int client_accept(int listenfd) + client->ib_capacity = CMD_BUF_SIZE; + client->state = CLIENT_COMMAND; + client->events = POLLIN; ++ client->info = NULL; + + pthread_mutex_lock(&client_list_mutex); ++ client->number = client_number++; + collection_add(&client_list, client); + pthread_mutex_unlock(&client_list_mutex); + +@@ -229,10 +235,10 @@ void client_close(struct mux_client *client) + device_abort_connect(client->connect_device, client); + } + close(client->fd); +- if(client->ob_buf) +- free(client->ob_buf); +- if(client->ib_buf) +- free(client->ib_buf); ++ free(client->ob_buf); ++ free(client->ib_buf); ++ plist_free(client->info); ++ + pthread_mutex_lock(&client_list_mutex); + collection_remove(&client_list, client); + pthread_mutex_unlock(&client_list_mutex); +@@ -377,6 +383,69 @@ static int send_device_list(struct mux_client *client, uint32_t tag) + return res; + } + ++static int send_listener_list(struct mux_client *client, uint32_t tag) ++{ ++ int res = -1; ++ ++ plist_t dict = plist_new_dict(); ++ plist_t listeners = plist_new_array(); ++ ++ pthread_mutex_lock(&client_list_mutex); ++ FOREACH(struct mux_client *lc, &client_list) { ++ if (lc->state == CLIENT_LISTEN) { ++ plist_t n = NULL; ++ plist_t l = plist_new_dict(); ++ plist_dict_set_item(l, "Blacklisted", plist_new_bool(0)); ++ n = NULL; ++ if (lc->info) { ++ n = plist_dict_get_item(lc->info, "BundleID"); ++ } ++ if (n) { ++ plist_dict_set_item(l, "BundleID", plist_copy(n)); ++ } ++ plist_dict_set_item(l, "ConnType", plist_new_uint(0)); ++ ++ n = NULL; ++ char *progname = NULL; ++ if (lc->info) { ++ n = plist_dict_get_item(lc->info, "ProgName"); ++ } ++ if (n) { ++ plist_get_string_val(n, &progname); ++ } ++ if (!progname) { ++ progname = strdup("unknown"); ++ } ++ char *idstring = malloc(strlen(progname) + 12); ++ sprintf(idstring, "%u-%s", client->number, progname); ++ ++ plist_dict_set_item(l, "ID String", plist_new_string(idstring)); ++ free(idstring); ++ plist_dict_set_item(l, "ProgName", plist_new_string(progname)); ++ free(progname); ++ ++ n = NULL; ++ uint64_t version = 0; ++ if (lc->info) { ++ n = plist_dict_get_item(lc->info, "kLibUSBMuxVersion"); ++ } ++ if (n) { ++ plist_get_uint_val(n, &version); ++ } ++ plist_dict_set_item(l, "kLibUSBMuxVersion", plist_new_uint(version)); ++ ++ plist_array_append_item(listeners, l); ++ } ++ } ENDFOREACH ++ pthread_mutex_unlock(&client_list_mutex); ++ ++ plist_dict_set_item(dict, "ListenerList", listeners); ++ res = send_plist_pkt(client, tag, dict); ++ plist_free(dict); ++ ++ return res; ++} ++ + static int send_system_buid(struct mux_client *client, uint32_t tag) + { + int res = -1; +@@ -489,6 +558,43 @@ static char* plist_dict_get_string_val(plist_t dict, const char* key) + return str; + } + ++static void update_client_info(struct mux_client *client, plist_t dict) ++{ ++ plist_t node = NULL; ++ char *strval = NULL; ++ uint64_t u64val = 0; ++ plist_t info = plist_new_dict(); ++ ++ node = plist_dict_get_item(dict, "BundleID"); ++ if (node && (plist_get_node_type(node) == PLIST_STRING)) { ++ plist_get_string_val(node, &strval); ++ plist_dict_set_item(info, "BundleID", plist_new_string(strval)); ++ } ++ ++ strval = NULL; ++ node = plist_dict_get_item(dict, "ClientVersionString"); ++ if (node && (plist_get_node_type(node) == PLIST_STRING)) { ++ plist_get_string_val(node, &strval); ++ plist_dict_set_item(info, "ClientVersionString", plist_new_string(strval)); ++ } ++ ++ strval = NULL; ++ node = plist_dict_get_item(dict, "ProgName"); ++ if (node && (plist_get_node_type(node) == PLIST_STRING)) { ++ plist_get_string_val(node, &strval); ++ plist_dict_set_item(info, "ProgName", plist_new_string(strval)); ++ } ++ ++ u64val = 0; ++ node = plist_dict_get_item(dict, "kLibUSBMuxVersion"); ++ if (node && (plist_get_node_type(node) == PLIST_UINT)) { ++ plist_get_uint_val(node, &u64val); ++ plist_dict_set_item(info, "kLibUSBMuxVersion", plist_new_uint(u64val)); ++ } ++ plist_free(client->info); ++ client->info = info; ++} ++ + static int client_command(struct mux_client *client, struct usbmuxd_header *hdr) + { + int res; +@@ -536,6 +642,7 @@ static int client_command(struct mux_client *client, struct usbmuxd_header *hdr) + plist_free(dict); + return -1; + } ++ update_client_info(client, dict); + if (!strcmp(message, "Listen")) { + free(message); + plist_free(dict); +@@ -592,6 +699,12 @@ static int client_command(struct mux_client *client, struct usbmuxd_header *hdr) + if (send_device_list(client, hdr->tag) < 0) + return -1; + return 0; ++ } else if (!strcmp(message, "ListListeners")) { ++ free(message); ++ plist_free(dict); ++ if (send_listener_list(client, hdr->tag) < 0) ++ return -1; ++ return 0; + } else if (!strcmp(message, "ReadBUID")) { + free(message); + plist_free(dict); +-- +2.23.0 + + +From d33402036d563667a76910dbfec50a37b622d3a5 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Sat, 15 Sep 2018 03:46:34 +0200 +Subject: [PATCH 45/66] client: Send 'Paired' message when a device's pairing + record has been stored successfully + +This requires the SavePairRecord message sent from the client to contain a +usbmux device id so the device can be matched accordingly. +For the record: This is the original behavior. +--- + src/client.c | 58 +++++++++++++++++++++++++++++++++++++++++++++ + src/client.h | 1 + + src/usbmuxd-proto.h | 2 +- + 3 files changed, 60 insertions(+), 1 deletion(-) + +diff --git a/src/client.c b/src/client.c +index a24233c..c566d8c 100644 +--- a/src/client.c ++++ b/src/client.c +@@ -524,6 +524,24 @@ static int notify_device_remove(struct mux_client *client, uint32_t device_id) + return res; + } + ++static int notify_device_paired(struct mux_client *client, uint32_t device_id) ++{ ++ int res = -1; ++ if (client->proto_version == 1) { ++ /* XML plist packet */ ++ plist_t dict = plist_new_dict(); ++ plist_dict_set_item(dict, "MessageType", plist_new_string("Paired")); ++ plist_dict_set_item(dict, "DeviceID", plist_new_uint(device_id)); ++ res = send_plist_pkt(client, 0, dict); ++ plist_free(dict); ++ } ++ else { ++ /* binary packet */ ++ res = send_pkt(client, 0, MESSAGE_DEVICE_PAIRED, &device_id, sizeof(uint32_t)); ++ } ++ return res; ++} ++ + static int start_listen(struct mux_client *client) + { + struct device_info *devs = NULL; +@@ -738,6 +756,34 @@ static int client_command(struct mux_client *client, struct usbmuxd_header *hdr) + res = config_set_device_record(record_id, record_data, record_size); + if (res < 0) { + rval = -res; ++ } else { ++ plist_t p_dev_id = plist_dict_get_item(dict, "DeviceID"); ++ uint32_t dev_id = 0; ++ if (p_dev_id && plist_get_node_type(p_dev_id) == PLIST_UINT) { ++ uint64_t u_dev_id = 0; ++ plist_get_uint_val(p_dev_id, &u_dev_id); ++ dev_id = (uint32_t)u_dev_id; ++ } ++ if (dev_id > 0) { ++ struct device_info *devs = NULL; ++ struct device_info *dev; ++ int i; ++ int count = device_get_list(1, &devs); ++ int found = 0; ++ dev = devs; ++ for (i = 0; devs && i < count; i++, dev++) { ++ if ((uint32_t)dev->id == dev_id && (strcmp(dev->serial, record_id) == 0)) { ++ found++; ++ break; ++ } ++ } ++ if (!found) { ++ usbmuxd_log(LL_ERROR, "ERROR: SavePairRecord: DeviceID %d (%s) is not connected\n", dev_id, record_id); ++ } else { ++ client_device_paired(dev_id); ++ } ++ free(devs); ++ } + } + free(record_id); + } else { +@@ -937,6 +983,18 @@ void client_device_remove(int device_id) + pthread_mutex_unlock(&client_list_mutex); + } + ++void client_device_paired(int device_id) ++{ ++ pthread_mutex_lock(&client_list_mutex); ++ uint32_t id = device_id; ++ usbmuxd_log(LL_DEBUG, "client_device_paired: id %d", device_id); ++ FOREACH(struct mux_client *client, &client_list) { ++ if (client->state == CLIENT_LISTEN) ++ notify_device_paired(client, id); ++ } ENDFOREACH ++ pthread_mutex_unlock(&client_list_mutex); ++} ++ + void client_init(void) + { + usbmuxd_log(LL_DEBUG, "client_init"); +diff --git a/src/client.h b/src/client.h +index bac563d..6cac4db 100644 +--- a/src/client.h ++++ b/src/client.h +@@ -35,6 +35,7 @@ int client_notify_connect(struct mux_client *client, enum usbmuxd_result result) + + void client_device_add(struct device_info *dev); + void client_device_remove(int device_id); ++void client_device_paired(int device_id); + + int client_accept(int fd); + void client_get_fds(struct fdlist *list); +diff --git a/src/usbmuxd-proto.h b/src/usbmuxd-proto.h +index a344e60..9416416 100644 +--- a/src/usbmuxd-proto.h ++++ b/src/usbmuxd-proto.h +@@ -52,7 +52,7 @@ enum usbmuxd_msgtype { + MESSAGE_LISTEN = 3, + MESSAGE_DEVICE_ADD = 4, + MESSAGE_DEVICE_REMOVE = 5, +- //??? ++ MESSAGE_DEVICE_PAIRED = 6, + //??? + MESSAGE_PLIST = 8, + }; +-- +2.23.0 + + +From 49576fdf06e3a7e3ef7824f29136556005f2239d Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Tue, 2 Oct 2018 14:54:18 +0200 +Subject: [PATCH 46/66] preflight: Fix compatibility with latest internal + changes to libimobiledevice + +--- + configure.ac | 2 +- + src/preflight.c | 6 +++++- + 2 files changed, 6 insertions(+), 2 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 2690f78..46a725e 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -18,7 +18,7 @@ AC_PROG_LIBTOOL + # Checks for libraries. + PKG_CHECK_MODULES(libusb, libusb-1.0 >= 1.0.9) + PKG_CHECK_MODULES(libplist, libplist >= 1.11) +-PKG_CHECK_MODULES(libimobiledevice, libimobiledevice-1.0 >= 1.1.6, have_limd=yes, have_limd=no) ++PKG_CHECK_MODULES(libimobiledevice, libimobiledevice-1.0 >= 1.2.1, have_limd=yes, have_limd=no) + AC_CHECK_LIB(pthread, [pthread_create, pthread_mutex_lock], [AC_SUBST(libpthread_LIBS,[-lpthread])], [AC_MSG_ERROR([libpthread is required to build usbmuxd])]) + + AC_ARG_WITH([preflight], +diff --git a/src/preflight.c b/src/preflight.c +index c74e49d..0eea179 100644 +--- a/src/preflight.c ++++ b/src/preflight.c +@@ -49,8 +49,10 @@ enum connection_type { + + struct idevice_private { + char *udid; ++ uint32_t mux_id; + enum connection_type conn_type; + void *conn_data; ++ int version; + }; + + struct cb_data { +@@ -123,8 +125,10 @@ static void* preflight_worker_handle_device_add(void* userdata) + struct device_info *info = (struct device_info*)userdata; + struct idevice_private *_dev = (struct idevice_private*)malloc(sizeof(struct idevice_private)); + _dev->udid = strdup(info->serial); ++ _dev->mux_id = info->id; + _dev->conn_type = CONNECTION_USBMUXD; +- _dev->conn_data = (void*)(long)info->id; ++ _dev->conn_data = NULL; ++ _dev->version = 0; + + idevice_t dev = (idevice_t)_dev; + +-- +2.23.0 + + +From f838cf6dc212c779562984e8a16a4cedfc1d6daf Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Fri, 5 Oct 2018 05:22:29 +0200 +Subject: [PATCH 47/66] usb: Add hyphen to new style UDIDs introduced with + iPhone XS/XR + +--- + src/usb.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/src/usb.c b/src/usb.c +index 0977c24..44c33ce 100644 +--- a/src/usb.c ++++ b/src/usb.c +@@ -277,12 +277,19 @@ static void get_serial_callback(struct libusb_transfer *transfer) + else + usbdev->serial[di++] = data[si]; + } +- usbdev->serial[di] = 0; ++ usbdev->serial[di] = '\0'; + + usbmuxd_log(LL_INFO, "Got serial '%s' for device %d-%d", usbdev->serial, usbdev->bus, usbdev->address); + + libusb_free_transfer(transfer); + ++ /* new style UDID: add hyphen between first 8 and following 16 digits */ ++ if (di == 24) { ++ memmove(&usbdev->serial[9], &usbdev->serial[8], 16); ++ usbdev->serial[8] = '-'; ++ usbdev->serial[di+1] = '\0'; ++ } ++ + /* Finish setup now */ + if(device_add(usbdev) < 0) { + usb_disconnect(usbdev); +-- +2.23.0 + + +From 1cc8b343a4bc9320758c78e187b13bb3c9029f12 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Fri, 12 Oct 2018 14:26:01 +0200 +Subject: [PATCH 48/66] usb: Fix adding hyphen to new style UDIDs by not + counting '\0' towards string length + +--- + src/usb.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/usb.c b/src/usb.c +index 44c33ce..b659d90 100644 +--- a/src/usb.c ++++ b/src/usb.c +@@ -274,6 +274,8 @@ static void get_serial_callback(struct libusb_transfer *transfer) + for (di = 0, si = 2; si < data[0] && di < sizeof(usbdev->serial)-1; si += 2) { + if ((data[si] & 0x80) || (data[si + 1])) /* non-ASCII */ + usbdev->serial[di++] = '?'; ++ else if (data[si] == '\0') ++ break; + else + usbdev->serial[di++] = data[si]; + } +-- +2.23.0 + + +From 9a93f8727414c33f9efa5448b468533a347cf519 Mon Sep 17 00:00:00 2001 +From: Eric Chen +Date: Wed, 28 Nov 2018 18:17:24 +0800 +Subject: [PATCH 49/66] client: Fix Use-after-Free in handling of + SavePairRecord message when reading device id + +--- + src/client.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/client.c b/src/client.c +index c566d8c..3472e6e 100644 +--- a/src/client.c ++++ b/src/client.c +@@ -750,7 +750,6 @@ static int client_command(struct mux_client *client, struct usbmuxd_header *hdr) + if (rdata && plist_get_node_type(rdata) == PLIST_DATA) { + plist_get_data_val(rdata, &record_data, &record_size); + } +- plist_free(dict); + + if (record_id && record_data) { + res = config_set_device_record(record_id, record_data, record_size); +@@ -790,6 +789,7 @@ static int client_command(struct mux_client *client, struct usbmuxd_header *hdr) + rval = EINVAL; + } + free(record_data); ++ plist_free(dict); + if (send_result(client, hdr->tag, rval) < 0) + return -1; + return 0; +-- +2.23.0 + + +From a1963ec3717e1e652de9d10311077a454d9bb8e9 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Thu, 29 Nov 2018 00:32:05 +0100 +Subject: [PATCH 50/66] utils: Fix free on invalid pointer + +Credit to tjps see: #100 https://github.com/libimobiledevice/usbmuxd/pull/100 +--- + src/utils.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/utils.c b/src/utils.c +index e30a0b3..206c684 100644 +--- a/src/utils.c ++++ b/src/utils.c +@@ -245,7 +245,7 @@ int buffer_read_from_filename(const char *filename, char **buffer, uint64_t *len + int ret = 1; + if (fread(*buffer, sizeof(char), size, f) != size) { + usbmuxd_log(LL_ERROR, "%s: ERROR: couldn't read %d bytes from %s", __func__, (int)size, filename); +- free(buffer); ++ free(*buffer); + ret = 0; + errno = EIO; + } +-- +2.23.0 + + +From 96e4aabe0b9a46ea9da4955a10c774a8e58fe677 Mon Sep 17 00:00:00 2001 +From: Mikkel Kamstrup Erlandsen +Date: Wed, 10 Oct 2018 12:43:06 +0200 +Subject: [PATCH 51/66] build: check if clock_gettime() requires -lrt on old + GNU systems + +--- + configure.ac | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/configure.ac b/configure.ac +index 46a725e..d0c8201 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -92,6 +92,9 @@ AC_TYPE_UINT16_T + AC_TYPE_UINT32_T + AC_TYPE_UINT8_T + ++# Check if clock_gettime requires -lrt (old GNU systems) ++AC_SEARCH_LIBS([clock_gettime],[rt posix4]) ++ + # Checks for library functions. + AC_FUNC_MALLOC + AC_FUNC_REALLOC +-- +2.23.0 + + +From 8a6d05cf73a7d11166e2029d9bbce377ab78f4b7 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Thu, 7 Feb 2019 03:44:28 +0100 +Subject: [PATCH 52/66] Allow logging to a dedicated logfile + +--- + src/main.c | 51 +++++++++++++++++++++++++++++++++++---------------- + 1 file changed, 35 insertions(+), 16 deletions(-) + +diff --git a/src/main.c b/src/main.c +index a276e90..f3c58b7 100644 +--- a/src/main.c ++++ b/src/main.c +@@ -1,9 +1,9 @@ + /* + * main.c + * ++ * Copyright (C) 2009-2019 Nikias Bassen + * Copyright (C) 2013-2014 Martin Szulecki + * Copyright (C) 2009 Hector Martin +- * Copyright (C) 2009 Nikias Bassen + * Copyright (C) 2009 Paul Sladen + * + * This program is free software; you can redistribute it and/or modify +@@ -54,6 +54,7 @@ static const char *lockfile = "/var/run/usbmuxd.pid"; + + int should_exit; + int should_discover; ++int use_logfile = 0; + + static int verbose = 0; + static int foreground = 0; +@@ -376,6 +377,7 @@ static void usage() + printf(" \t\tconnected (sends SIGUSR1 to running instance) and exit.\n"); + printf(" -X, --force-exit\tNotify a running instance to exit even if there are still\n"); + printf(" \tdevices connected (always works) and exit.\n"); ++ printf(" -l, --logfile=LOGFILE\tLog (append) to LOGFILE instead of stderr or syslog.\n"); + printf(" -V, --version\t\tPrint version information and exit.\n"); + printf("\n"); + } +@@ -383,31 +385,32 @@ static void usage() + static void parse_opts(int argc, char **argv) + { + static struct option longopts[] = { +- {"help", 0, NULL, 'h'}, +- {"foreground", 0, NULL, 'f'}, +- {"verbose", 0, NULL, 'v'}, +- {"user", 1, NULL, 'U'}, +- {"disable-hotplug", 0, NULL, 'n'}, +- {"enable-exit", 0, NULL, 'z'}, ++ {"help", no_argument, NULL, 'h'}, ++ {"foreground", no_argument, NULL, 'f'}, ++ {"verbose", no_argument, NULL, 'v'}, ++ {"user", required_argument, NULL, 'U'}, ++ {"disable-hotplug", no_argument, NULL, 'n'}, ++ {"enable-exit", no_argument, NULL, 'z'}, + #ifdef HAVE_UDEV +- {"udev", 0, NULL, 'u'}, ++ {"udev", no_argument, NULL, 'u'}, + #endif + #ifdef HAVE_SYSTEMD +- {"systemd", 0, NULL, 's'}, ++ {"systemd", no_argument, NULL, 's'}, + #endif +- {"exit", 0, NULL, 'x'}, +- {"force-exit", 0, NULL, 'X'}, +- {"version", 0, NULL, 'V'}, ++ {"exit", no_argument, NULL, 'x'}, ++ {"force-exit", no_argument, NULL, 'X'}, ++ {"logfile", required_argument, NULL, 'l'}, ++ {"version", no_argument, NULL, 'V'}, + {NULL, 0, NULL, 0} + }; + int c; + + #ifdef HAVE_SYSTEMD +- const char* opts_spec = "hfvVuU:xXsnz"; ++ const char* opts_spec = "hfvVuU:xXsnzl:"; + #elif HAVE_UDEV +- const char* opts_spec = "hfvVuU:xXnz"; ++ const char* opts_spec = "hfvVuU:xXnzl:"; + #else +- const char* opts_spec = "hfvVU:xXnz"; ++ const char* opts_spec = "hfvVU:xXnzl:"; + #endif + + while (1) { +@@ -459,6 +462,22 @@ static void parse_opts(int argc, char **argv) + opt_exit = 1; + exit_signal = SIGTERM; + break; ++ case 'l': ++ if (!*optarg) { ++ usbmuxd_log(LL_FATAL, "ERROR: --logfile requires a non-empty filename"); ++ usage(); ++ exit(2); ++ } ++ if (use_logfile) { ++ usbmuxd_log(LL_FATAL, "ERROR: --logfile cannot be used multiple times"); ++ exit(2); ++ } ++ if (!freopen(optarg, "a", stderr)) { ++ usbmuxd_log(LL_FATAL, "ERROR: fdreopen: %s", strerror(errno)); ++ } else { ++ use_logfile = 1; ++ } ++ break; + default: + usage(); + exit(2); +@@ -479,7 +498,7 @@ int main(int argc, char *argv[]) + argc -= optind; + argv += optind; + +- if (!foreground) { ++ if (!foreground && !use_logfile) { + verbose += LL_WARNING; + log_enable_syslog(); + } else { +-- +2.23.0 + + +From a236e559cd2bfcd920dc684d06b188abfd6e2c32 Mon Sep 17 00:00:00 2001 +From: Adam Laurie +Date: Sat, 31 Dec 2016 12:17:06 +0000 +Subject: [PATCH 53/66] allow preflight error to pass so simple mode will still + work + +--- + src/preflight.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/preflight.c b/src/preflight.c +index 0eea179..15429c0 100644 +--- a/src/preflight.c ++++ b/src/preflight.c +@@ -236,7 +236,9 @@ retry: + lockdownd_service_descriptor_t service = NULL; + lerr = lockdownd_start_service(lockdown, "com.apple.mobile.insecure_notification_proxy", &service); + if (lerr != LOCKDOWN_E_SUCCESS) { +- usbmuxd_log(LL_ERROR, "%s: ERROR: Could not start insecure_notification_proxy on %s, lockdown error %d", __func__, _dev->udid, lerr); ++ /* even though we failed, simple mode should still work, so only warn of an error */ ++ usbmuxd_log(LL_INFO, "%s: ERROR: Could not start insecure_notification_proxy on %s, lockdown error %d", __func__, _dev->udid, lerr); ++ client_device_add(info); + goto leave; + } + +-- +2.23.0 + + +From b1b0bf390363fa36aff1bc09443ff751943b9c34 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Tue, 5 Mar 2019 02:53:56 +0100 +Subject: [PATCH 54/66] client: Plug memory leaks in update_client_info() + +plist_get_string_val() was used to get the string values of the +respective nodes, however those strings were never freed. +Improved by simply copying the nodes instead. +--- + src/client.c | 17 ++++------------- + 1 file changed, 4 insertions(+), 13 deletions(-) + +diff --git a/src/client.c b/src/client.c +index 3472e6e..85d0c8b 100644 +--- a/src/client.c ++++ b/src/client.c +@@ -579,35 +579,26 @@ static char* plist_dict_get_string_val(plist_t dict, const char* key) + static void update_client_info(struct mux_client *client, plist_t dict) + { + plist_t node = NULL; +- char *strval = NULL; +- uint64_t u64val = 0; + plist_t info = plist_new_dict(); + + node = plist_dict_get_item(dict, "BundleID"); + if (node && (plist_get_node_type(node) == PLIST_STRING)) { +- plist_get_string_val(node, &strval); +- plist_dict_set_item(info, "BundleID", plist_new_string(strval)); ++ plist_dict_set_item(info, "BundleID", plist_copy(node)); + } + +- strval = NULL; + node = plist_dict_get_item(dict, "ClientVersionString"); + if (node && (plist_get_node_type(node) == PLIST_STRING)) { +- plist_get_string_val(node, &strval); +- plist_dict_set_item(info, "ClientVersionString", plist_new_string(strval)); ++ plist_dict_set_item(info, "ClientVersionString", plist_copy(node)); + } + +- strval = NULL; + node = plist_dict_get_item(dict, "ProgName"); + if (node && (plist_get_node_type(node) == PLIST_STRING)) { +- plist_get_string_val(node, &strval); +- plist_dict_set_item(info, "ProgName", plist_new_string(strval)); ++ plist_dict_set_item(info, "ProgName", plist_copy(node)); + } + +- u64val = 0; + node = plist_dict_get_item(dict, "kLibUSBMuxVersion"); + if (node && (plist_get_node_type(node) == PLIST_UINT)) { +- plist_get_uint_val(node, &u64val); +- plist_dict_set_item(info, "kLibUSBMuxVersion", plist_new_uint(u64val)); ++ plist_dict_set_item(info, "kLibUSBMuxVersion", plist_copy(node)); + } + plist_free(client->info); + client->info = info; +-- +2.23.0 + + +From bc9abb07b1a2a731b4b6ca89ef99ad86e2442e93 Mon Sep 17 00:00:00 2001 +From: Ian Macalinao +Date: Sun, 13 Dec 2015 09:43:45 -0600 +Subject: [PATCH 55/66] Convert README to Markdown + +--- + README => README.md | 83 +++++++++++++++++++-------------------------- + 1 file changed, 34 insertions(+), 49 deletions(-) + rename README => README.md (71%) + +diff --git a/README b/README.md +similarity index 71% +rename from README +rename to README.md +index 7d96013..748594b 100644 +--- a/README ++++ b/README.md +@@ -1,10 +1,10 @@ +-About +-===== ++# usbmud ++ ++## About + + A socket daemon to multiplex connections from and to iOS devices. + +-Background +-========== ++## Background + + usbmuxd stands for "USB multiplexing daemon". This daemon is in charge of + multiplexing connections over USB to an iOS device. To users, it means +@@ -26,34 +26,35 @@ Due to iOS 7 the daemon now also manages pairing records with iOS devices and + the host in "/var/lib/lockdown" (Linux) or "/var/db/lockdown" (Mac OS X). + Ensure proper permissions are setup for the daemon to access the directory. + +-Requirements +-============ ++## Requirements + + Development Packages of: +- libimobiledevice +- libplist +- libusb ++* libimobiledevice ++* libplist ++* libusb + + Software: +- make +- autoheader +- automake +- autoconf +- libtool +- pkg-config +- gcc +- udev (Linux only) ++ make ++ autoheader ++ automake ++ autoconf ++ libtool ++ pkg-config ++ gcc ++ udev (Linux only) + + Optional: +- systemd (Linux only) ++ systemd (Linux only) + +-Installation +-============ ++## Installation + + To compile run: +- ./autogen.sh +- make +- sudo make install ++ ++```bash ++./autogen.sh ++make ++sudo make install ++``` + + The daemon is automatically started by udev or systemd depending on what you + have configured it on hotplug of an iOS device and exits if the last device +@@ -62,32 +63,17 @@ was unplugged. + For debugging purposes it is helpful to start usbmuxd using the foreground '-f' + argument and enable verbose mode '-v' to get suitable logs. + +-Who/What/Where? +-=============== +- +-Home: +- http://www.libimobiledevice.org/ +- +-Code: +- git clone http://git.libimobiledevice.org/usbmuxd.git +- +-Code (Mirror): +- git clone https://github.com/libimobiledevice/usbmuxd.git +- +-Tickets: +- http://github.com/libimobiledevice/usbmuxd/issues +- +-Mailing List: +- http://lists.libimobiledevice.org/mailman/listinfo/libimobiledevice-devel +- +-IRC: +- irc://irc.freenode.net#libimobiledevice ++## Who/What/Where? + +-Twitter: +- https://twitter.com/libimobiledev ++* Home: http://www.libimobiledevice.org/ ++* Code: `git clone http://git.libimobiledevice.org/usbmuxd.git` ++* Code (Mirror): `git clone https://github.com/libimobiledevice/usbmuxd.git` ++* Tickets: http://github.com/libimobiledevice/usbmuxd/issues ++* Mailing List: http://lists.libimobiledevice.org/mailman/listinfo/libimobiledevice-devel ++* IRC: irc://irc.freenode.net#libimobiledevice ++* Twitter: https://twitter.com/libimobiledev + +-Credits +-======= ++## Credits + + The first usbmuxd daemon implementation was authored by Hector Martin. + +@@ -95,5 +81,4 @@ Apple, iPhone, iPod, and iPod Touch are trademarks of Apple Inc. + libimobiledevice is an independent software library and has not been + authorized, sponsored, or otherwise approved by Apple Inc. + +-README Updated on: +- 2015-01-28 ++README Updated on: 2015-12-13 +-- +2.23.0 + + +From d81cb1a62cfc30ce3d17d2fb312d7dc1e04e1e65 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Thu, 16 May 2019 15:38:00 +0200 +Subject: [PATCH 56/66] Updated README.md + +--- + README.md | 38 +++++++++++++++++++------------------- + 1 file changed, 19 insertions(+), 19 deletions(-) + +diff --git a/README.md b/README.md +index 748594b..6192f67 100644 +--- a/README.md ++++ b/README.md +@@ -11,19 +11,19 @@ multiplexing connections over USB to an iOS device. To users, it means + you can sync your music, contacts, photos, etc. over USB. To developers, it + means you can connect to any listening localhost socket on the device. usbmuxd + is not used for tethering data transfer which uses a dedicated USB interface as +-a virtual network device. Multiple connections to different TCP ports can happen ++a virtual network device. Multiple connections to different TCP ports can happen + in parallel. The higher-level layers are handled by libimobiledevice. + + When usbmuxd is running (normally started, or stopped as a result of "udev" + auto-insertion messages or by systemd) it provides a socket interface in +-"/var/run/usbmuxd" that is designed to be compatible with the socket interface ++`/var/run/usbmuxd` that is designed to be compatible with the socket interface + that is provided on Mac OS X. + + You should also create a "usbmux" user that has access to USB devices on your + system. Alternatively, you can pass a different username using the -U argument. + + Due to iOS 7 the daemon now also manages pairing records with iOS devices and +-the host in "/var/lib/lockdown" (Linux) or "/var/db/lockdown" (Mac OS X). ++the host in `/var/lib/lockdown` (Linux) or `/var/db/lockdown` (macOS). + Ensure proper permissions are setup for the daemon to access the directory. + + ## Requirements +@@ -34,17 +34,17 @@ Development Packages of: + * libusb + + Software: +- make +- autoheader +- automake +- autoconf +- libtool +- pkg-config +- gcc +- udev (Linux only) ++* make ++* autoheader ++* automake ++* autoconf ++* libtool ++* pkg-config ++* gcc or clang ++* udev (Linux only) + + Optional: +- systemd (Linux only) ++* systemd (Linux only) + + ## Installation + +@@ -60,16 +60,16 @@ The daemon is automatically started by udev or systemd depending on what you + have configured it on hotplug of an iOS device and exits if the last device + was unplugged. + +-For debugging purposes it is helpful to start usbmuxd using the foreground '-f' +-argument and enable verbose mode '-v' to get suitable logs. ++For debugging purposes it is helpful to start usbmuxd using the foreground `-f` ++argument and enable verbose mode `-v` to get suitable logs. + + ## Who/What/Where? + +-* Home: http://www.libimobiledevice.org/ +-* Code: `git clone http://git.libimobiledevice.org/usbmuxd.git` ++* Home: https://www.libimobiledevice.org/ ++* Code: `git clone https://git.libimobiledevice.org/usbmuxd.git` + * Code (Mirror): `git clone https://github.com/libimobiledevice/usbmuxd.git` +-* Tickets: http://github.com/libimobiledevice/usbmuxd/issues +-* Mailing List: http://lists.libimobiledevice.org/mailman/listinfo/libimobiledevice-devel ++* Tickets: https://github.com/libimobiledevice/usbmuxd/issues ++* Mailing List: https://lists.libimobiledevice.org/mailman/listinfo/libimobiledevice-devel + * IRC: irc://irc.freenode.net#libimobiledevice + * Twitter: https://twitter.com/libimobiledev + +@@ -81,4 +81,4 @@ Apple, iPhone, iPod, and iPod Touch are trademarks of Apple Inc. + libimobiledevice is an independent software library and has not been + authorized, sponsored, or otherwise approved by Apple Inc. + +-README Updated on: 2015-12-13 ++README Updated on: 2019-05-16 +-- +2.23.0 + + +From 5a9601b831ad459e587f5812c3314b3598bdcdc0 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Thu, 16 May 2019 15:45:13 +0200 +Subject: [PATCH 57/66] Updated README.md + +--- + README.md | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/README.md b/README.md +index 6192f67..42dab69 100644 +--- a/README.md ++++ b/README.md +@@ -14,16 +14,16 @@ is not used for tethering data transfer which uses a dedicated USB interface as + a virtual network device. Multiple connections to different TCP ports can happen + in parallel. The higher-level layers are handled by libimobiledevice. + +-When usbmuxd is running (normally started, or stopped as a result of "udev" +-auto-insertion messages or by systemd) it provides a socket interface in ++When usbmuxd is running (normally started or stopped as a result of _udev_ ++auto-insertion messages, or by _systemd_) it provides a socket interface in + `/var/run/usbmuxd` that is designed to be compatible with the socket interface +-that is provided on Mac OS X. ++that is provided on macOS. + +-You should also create a "usbmux" user that has access to USB devices on your +-system. Alternatively, you can pass a different username using the -U argument. ++You should also create a `usbmux` user that has access to USB devices on your ++system. Alternatively, you can pass a different username using the `-U` argument. + +-Due to iOS 7 the daemon now also manages pairing records with iOS devices and +-the host in `/var/lib/lockdown` (Linux) or `/var/db/lockdown` (macOS). ++The daemon also manages pairing records with iOS devices and the host in ++`/var/lib/lockdown` (Linux) or `/var/db/lockdown` (macOS). + Ensure proper permissions are setup for the daemon to access the directory. + + ## Requirements +-- +2.23.0 + + +From 8bcbac4d0bf857ef2ccbaf5be4f7af3613f4f5df Mon Sep 17 00:00:00 2001 +From: Frederik Carlier +Date: Tue, 21 May 2019 16:44:47 +0200 +Subject: [PATCH 58/66] Fix typo (usbmuxd) in README + +--- + README.md | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/README.md b/README.md +index 42dab69..9a2d869 100644 +--- a/README.md ++++ b/README.md +@@ -1,4 +1,4 @@ +-# usbmud ++# usbmuxd + + ## About + +-- +2.23.0 + + +From 1f8ddeff95884da404a7fbd74d27e04ca8c99a50 Mon Sep 17 00:00:00 2001 +From: mrmacete +Date: Fri, 30 Mar 2018 15:38:43 +0200 +Subject: [PATCH 59/66] Avoid using configuration 5 + +- this fixes setting configuration for iOS 11 devices inside virtual machines which caused timeout and subsequent reboot of the device when unplugged from USB +--- + src/usb.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/src/usb.c b/src/usb.c +index b659d90..364930c 100644 +--- a/src/usb.c ++++ b/src/usb.c +@@ -392,13 +392,17 @@ static int usb_device_add(libusb_device* dev) + return -1; + } + ++ int desired_config = devdesc.bNumConfigurations; ++ if (desired_config > 4) { ++ desired_config = 4; ++ } + int current_config = 0; + if((res = libusb_get_configuration(handle, ¤t_config)) != 0) { + usbmuxd_log(LL_WARNING, "Could not get configuration for device %d-%d: %d", bus, address, res); + libusb_close(handle); + return -1; + } +- if (current_config != devdesc.bNumConfigurations) { ++ if (current_config != desired_config) { + struct libusb_config_descriptor *config; + if((res = libusb_get_active_config_descriptor(dev, &config)) != 0) { + usbmuxd_log(LL_NOTICE, "Could not get old configuration descriptor for device %d-%d: %d", bus, address, res); +@@ -420,9 +424,9 @@ static int usb_device_add(libusb_device* dev) + libusb_free_config_descriptor(config); + } + +- usbmuxd_log(LL_INFO, "Setting configuration for device %d-%d, from %d to %d", bus, address, current_config, devdesc.bNumConfigurations); +- if((res = libusb_set_configuration(handle, devdesc.bNumConfigurations)) != 0) { +- usbmuxd_log(LL_WARNING, "Could not set configuration %d for device %d-%d: %d", devdesc.bNumConfigurations, bus, address, res); ++ usbmuxd_log(LL_INFO, "Setting configuration for device %d-%d, from %d to %d", bus, address, current_config, desired_config); ++ if((res = libusb_set_configuration(handle, desired_config)) != 0) { ++ usbmuxd_log(LL_WARNING, "Could not set configuration %d for device %d-%d: %d", desired_config, bus, address, res); + libusb_close(handle); + return -1; + } +-- +2.23.0 + + +From 1afa7350f9da03365f3b8f98dcb763b396e52723 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Fri, 13 Sep 2019 11:54:22 +0200 +Subject: [PATCH 60/66] device: Plug memory leak in error condition when TH_SYN + sending fails + +--- + src/device.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/src/device.c b/src/device.c +index 3edaea0..0cd9af4 100644 +--- a/src/device.c ++++ b/src/device.c +@@ -344,10 +344,8 @@ static void connection_teardown(struct mux_connection *conn) + client_close(conn->client); + } + } +- if(conn->ib_buf) +- free(conn->ib_buf); +- if(conn->ob_buf) +- free(conn->ob_buf); ++ free(conn->ib_buf); ++ free(conn->ob_buf); + collection_remove(&conn->dev->connections, conn); + free(conn); + } +@@ -394,6 +392,8 @@ int device_start_connect(int device_id, uint16_t dport, struct mux_client *clien + res = send_tcp(conn, TH_SYN, NULL, 0); + if(res < 0) { + usbmuxd_log(LL_ERROR, "Error sending TCP SYN to device %d (%d->%d)", dev->id, sport, dport); ++ free(conn->ib_buf); ++ free(conn->ob_buf); + free(conn); + return -RESULT_CONNREFUSED; //bleh + } +-- +2.23.0 + + +From c41226df521de464a89f3d027f3e67d13d10d96f Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Fri, 4 Oct 2019 03:14:04 +0200 +Subject: [PATCH 61/66] preflight: Let insecure notification proxy terminate + when pairing is done + +--- + src/preflight.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/src/preflight.c b/src/preflight.c +index 15429c0..f46786e 100644 +--- a/src/preflight.c ++++ b/src/preflight.c +@@ -59,6 +59,7 @@ struct cb_data { + idevice_t dev; + np_client_t np; + int is_device_connected; ++ int is_finished; + }; + + static void lockdownd_set_untrusted_host_buid(lockdownd_client_t lockdown) +@@ -97,6 +98,7 @@ static void np_callback(const char* notification, void* userdata) + lerr = lockdownd_client_new(dev, &lockdown, "usbmuxd"); + if (lerr != LOCKDOWN_E_SUCCESS) { + usbmuxd_log(LL_ERROR, "%s: ERROR: Could not connect to lockdownd on device %s, lockdown error %d", __func__, _dev->udid, lerr); ++ cbdata->is_finished = 1; + return; + } + +@@ -104,10 +106,11 @@ static void np_callback(const char* notification, void* userdata) + if (lerr != LOCKDOWN_E_SUCCESS) { + usbmuxd_log(LL_ERROR, "%s: ERROR: Pair failed for device %s, lockdown error %d", __func__, _dev->udid, lerr); + lockdownd_client_free(lockdown); ++ cbdata->is_finished = 1; + return; + } + lockdownd_client_free(lockdown); +- // device will reconnect by itself at this point. ++ cbdata->is_finished = 1; + + } else if (strcmp(notification, "com.apple.mobile.lockdown.request_host_buid") == 0) { + lerr = lockdownd_client_new(cbdata->dev, &lockdown, "usbmuxd"); +@@ -255,6 +258,7 @@ retry: + cbdata.dev = dev; + cbdata.np = np; + cbdata.is_device_connected = 1; ++ cbdata.is_finished = 0; + + np_set_notify_callback(np, np_callback, (void*)&cbdata); + device_set_preflight_cb_data(info->id, (void*)&cbdata); +@@ -273,7 +277,7 @@ retry: + /* make device visible anyways */ + client_device_add(info); + +- while (cbdata.np && cbdata.is_device_connected == 1) { ++ while (cbdata.np && cbdata.is_device_connected && !cbdata.is_finished) { + sleep(1); + } + device_set_preflight_cb_data(info->id, NULL); +-- +2.23.0 + + +From c3fc55697b8fdf59055e4842a9e6bf7db15a35c9 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Mon, 7 Oct 2019 20:24:21 +0200 +Subject: [PATCH 62/66] Replace obsolete _BSD_SOURCE define with + _DEFAULT_SOURCE + +--- + src/device.c | 2 +- + src/main.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/device.c b/src/device.c +index 0cd9af4..ba5ed73 100644 +--- a/src/device.c ++++ b/src/device.c +@@ -18,7 +18,7 @@ + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +-#define _BSD_SOURCE ++#define _DEFAULT_SOURCE + + #ifdef HAVE_CONFIG_H + #include +diff --git a/src/main.c b/src/main.c +index f3c58b7..34aa1f4 100644 +--- a/src/main.c ++++ b/src/main.c +@@ -20,7 +20,7 @@ + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +-#define _BSD_SOURCE ++#define _DEFAULT_SOURCE + #define _GNU_SOURCE + + #ifdef HAVE_CONFIG_H +-- +2.23.0 + + +From 135ab5253879c197edae416b523e01aad4e13d98 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Mon, 7 Oct 2019 20:25:00 +0200 +Subject: [PATCH 63/66] device: Make sure to operate on the copy of the device + list in device_get_list() + +--- + src/device.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/device.c b/src/device.c +index ba5ed73..afb2d92 100644 +--- a/src/device.c ++++ b/src/device.c +@@ -933,7 +933,7 @@ int device_get_list(int include_hidden, struct device_info **devices) + *devices = malloc(sizeof(struct device_info) * dev_list.capacity); + struct device_info *p = *devices; + +- FOREACH(struct mux_device *dev, &device_list) { ++ FOREACH(struct mux_device *dev, &dev_list) { + if((dev->state == MUXDEV_ACTIVE) && (include_hidden || dev->visible)) { + p->id = dev->id; + p->serial = usb_get_serial(dev->usbdev); +-- +2.23.0 + + +From 7a1110f5c13e7249062da952e1ac4de1b56d4a4e Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Mon, 7 Oct 2019 21:19:48 +0200 +Subject: [PATCH 64/66] preflight: Prevent possible UaF if usb device is + removed while preflight is in progress + +The device serial number is only used by reference, however since the preflight helper +runs in a separate thread the usb device might be invalidated before the preflight operation +is complete, leading to a use-after-free when passing on the device info, followed by accessing +the device serial number. By copying the serial number this can be avoided. +--- + src/preflight.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/src/preflight.c b/src/preflight.c +index f46786e..86a51cf 100644 +--- a/src/preflight.c ++++ b/src/preflight.c +@@ -337,6 +337,7 @@ leave: + if (dev) + idevice_free(dev); + ++ free((char*)info->serial); + free(info); + + return NULL; +@@ -353,6 +354,9 @@ void preflight_worker_device_add(struct device_info* info) + struct device_info *infocopy = (struct device_info*)malloc(sizeof(struct device_info)); + + memcpy(infocopy, info, sizeof(struct device_info)); ++ if (info->serial) { ++ infocopy->serial = strdup(info->serial); ++ } + + pthread_t th; + pthread_attr_t attr; +@@ -362,6 +366,7 @@ void preflight_worker_device_add(struct device_info* info) + + int perr = pthread_create(&th, &attr, preflight_worker_handle_device_add, infocopy); + if (perr != 0) { ++ free((char*)infocopy->serial); + free(infocopy); + usbmuxd_log(LL_ERROR, "ERROR: failed to start preflight worker thread for device %s: %s (%d). Invoking client_device_add() directly but things might not work as expected.", info->serial, strerror(perr), perr); + client_device_add(info); +-- +2.23.0 + + +From 24e06d5247c37a7712d85f032ed3ba74d7a039f8 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Sat, 2 Nov 2019 01:04:48 +0100 +Subject: [PATCH 65/66] Define _BSD_SOURCE again for older platforms. + +While defining _BSD_SOURCE prints deprecation warnings, defining both +_DEFAULT_SOURCE and _BSD_SOURCE will not. +--- + src/device.c | 1 + + src/main.c | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/src/device.c b/src/device.c +index afb2d92..87a36cc 100644 +--- a/src/device.c ++++ b/src/device.c +@@ -19,6 +19,7 @@ + */ + + #define _DEFAULT_SOURCE ++#define _BSD_SOURCE + + #ifdef HAVE_CONFIG_H + #include +diff --git a/src/main.c b/src/main.c +index 34aa1f4..aede710 100644 +--- a/src/main.c ++++ b/src/main.c +@@ -21,6 +21,7 @@ + */ + + #define _DEFAULT_SOURCE ++#define _BSD_SOURCE + #define _GNU_SOURCE + + #ifdef HAVE_CONFIG_H +-- +2.23.0 + + +From 9af2b12552693a47601347e1eafc1e94132d727e Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Mon, 11 Nov 2019 18:08:22 +0100 +Subject: [PATCH 66/66] Fix compatibility with latest changes in + libimobiledevice + +--- + configure.ac | 9 +++++++++ + src/preflight.c | 9 ++++++--- + 2 files changed, 15 insertions(+), 3 deletions(-) + +diff --git a/configure.ac b/configure.ac +index d0c8201..fb59203 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -35,6 +35,15 @@ if test "x$have_limd" = "xyes"; then + AC_DEFINE(HAVE_LIBIMOBILEDEVICE, 1, [Define if you have libimobiledevice support]) + AC_SUBST(libimobiledevice_CFLAGS) + AC_SUBST(libimobiledevice_LIBS) ++ AC_CACHE_CHECK(for enum idevice_connection_type, ac_cv_enum_idevice_connection_type, ++ AC_TRY_COMPILE([ ++ #include ++ ], [ ++ enum idevice_connection_type conn_type = CONNECTION_USBMUXD; ++ ], ac_cv_enum_idevice_connection_type=yes, ac_cv_enum_idevice_connection_type=no)) ++ if (test "$ac_cv_enum_idevice_connection_type" = "yes"); then ++ AC_DEFINE(HAVE_ENUM_IDEVICE_CONNECTION_TYPE, 1, [Define if enum idevice_connection_type is available]) ++ fi + fi + else + if test "x$with_preflight" == "xyes"; then +diff --git a/src/preflight.c b/src/preflight.c +index 86a51cf..c7cfa50 100644 +--- a/src/preflight.c ++++ b/src/preflight.c +@@ -43,14 +43,17 @@ + #include "log.h" + + #ifdef HAVE_LIBIMOBILEDEVICE +-enum connection_type { +- CONNECTION_USBMUXD = 1 ++#ifndef HAVE_ENUM_IDEVICE_CONNECTION_TYPE ++enum idevice_connection_type { ++ CONNECTION_USBMUXD = 1, ++ CONNECTION_NETWORK + }; ++#endif + + struct idevice_private { + char *udid; + uint32_t mux_id; +- enum connection_type conn_type; ++ enum idevice_connection_type conn_type; + void *conn_data; + int version; + }; +-- +2.23.0 + diff --git a/changelog b/changelog deleted file mode 100644 index 9600c27..0000000 --- a/changelog +++ /dev/null @@ -1,215 +0,0 @@ -* Sat Jul 22 2023 Fedora Release Engineering - 1.1.1-10 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild - -* Sat Jan 21 2023 Fedora Release Engineering - 1.1.1-9 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild - -* Sat Jul 23 2022 Fedora Release Engineering - 1.1.1-8 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild - -* Sat Jan 22 2022 Fedora Release Engineering - 1.1.1-7 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild - -* Fri Jul 23 2021 Fedora Release Engineering - 1.1.1-6 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild - -* Tue Mar 02 2021 Zbigniew Jędrzejewski-Szmek - 1.1.1-5 -- Rebuilt for updated systemd-rpm-macros - See https://pagure.io/fesco/issue/2583. - -* Wed Jan 27 2021 Fedora Release Engineering - 1.1.1-4 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild - -* Wed Jul 29 2020 Fedora Release Engineering - 1.1.1-3 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild - -* Wed Jul 22 2020 Tom Stellard - 1.1.1-2 -- Use make macros -- https://fedoraproject.org/wiki/Changes/UseMakeBuildInstallMacro - -* Tue Jun 16 2020 Bastien Nocera - 1.1.1-1 -+ usbmuxd-1.1.1-1 -- Update to 1.1.1 - -* Fri Jan 31 2020 Fedora Release Engineering - 1.1.0-18 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild - -* Mon Nov 25 2019 Bastien Nocera - 1.1.0-17 -+ usbmuxd-1.1.0-17 -- Update to latest git snapshot - -* Sat Jul 27 2019 Fedora Release Engineering - 1.1.0-16 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild - -* Sun Feb 03 2019 Fedora Release Engineering - 1.1.0-15 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild - -* Sat Jul 14 2018 Fedora Release Engineering - 1.1.0-14 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild - -* Wed Apr 18 2018 Bastien Nocera - 1.1.0-13 -+ usbmuxd-1.1.0-13 -- Fix usbmuxd not starting up a second time, and properties being lost - with kernel >= 4.12 - -* Fri Mar 9 2018 Peter Robinson 1.1.0-12 -- Add gcc BR - -* Fri Feb 09 2018 Fedora Release Engineering - 1.1.0-11 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild - -* Thu Aug 03 2017 Fedora Release Engineering - 1.1.0-10 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild - -* Thu Jul 27 2017 Fedora Release Engineering - 1.1.0-9 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild - -* Tue May 16 2017 Peter Robinson 1.1.0-8 -- Use _udevrulesdir macro - -* Sat Feb 11 2017 Fedora Release Engineering - 1.1.0-7 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild - -* Fri Feb 05 2016 Fedora Release Engineering - 1.1.0-6 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild - -* Fri Jun 19 2015 Fedora Release Engineering - 1.1.0-5 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild - -* Wed Feb 11 2015 Peter Robinson 1.0.10-4 -- Rebuild (libimobiledevice) - -* Tue Feb 3 2015 Peter Robinson 1.0.10-3 -- Use %%license - -* Tue Oct 21 2014 Peter Robinson 1.0.10-2 -- (rebuild) - -* Fri Oct 17 2014 Peter Robinson 1.0.10-1 -- New stable 1.1.0 release - -* Fri Oct 17 2014 Peter Robinson 1.0.9-3 -- Bump for correct overrides - -* Fri Oct 17 2014 Peter Robinson 1.0.9-2 -- Refresh usbmuxd owner bits - -* Wed Oct 15 2014 Peter Robinson 1.0.9-1 -- New stable 1.0.9 release - -* Tue Sep 09 2014 Rex Dieter - 1.0.9-0.6.c24463e -- Obsoletes: usbmuxd < 1.0.9 (multilib upgrade path) -- move Obsoletes: usbmuxd-devel to libusbmuxd-devel - -* Mon Aug 18 2014 Fedora Release Engineering - 1.0.9-0.5.c24463e -- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild - -* Wed Jul 30 2014 Peter Robinson 1.0.9-0.4.c24463e -- Add upstream patch for systemd support - -* Sun Jun 08 2014 Fedora Release Engineering - 1.0.9-0.3.c24463e -- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild - -* Mon Apr 21 2014 Peter Robinson 1.0.9-0.2 -- Minor update - -* Mon Apr 21 2014 Peter Robinson 1.0.9-0.1 -- Initial 1.0.9 snapshot - -* Thu Oct 10 2013 Ralf Corsépius - 1.0.8-10 -- Add BR: systemd for systemd.macros (RHBZ #1017493). - -* Tue Oct 8 2013 Peter Robinson 1.0.8-9 -- Fix rpm scripts - -* Sun Aug 04 2013 Fedora Release Engineering - 1.0.8-8 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild - -* Fri Feb 15 2013 Fedora Release Engineering - 1.0.8-7 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild - -* Mon Nov 19 2012 Bastien Nocera 1.0.8-6 -- Fix source URL - -* Thu Oct 4 2012 Peter Robinson - 1.0.8-5 -- Make use of the new systemd macros -- Minor updates to spec - -* Sun Jul 22 2012 Fedora Release Engineering - 1.0.8-4 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild - -* Mon Jul 09 2012 Bastien Nocera 1.0.8-3 -- Use systemd to start usbmuxd instead of udev (#786853) - -* Sat Apr 28 2012 Bastien Nocera 1.0.8-2 -- Fix usbmuxd not starting under udev - -* Mon Apr 9 2012 Peter Robinson 1.0.8-1 -- New stable 1.0.8 release - -* Thu Feb 2 2012 Peter Robinson - 1.0.7-3 -- Add debian patch for CVE-2012-0065. Fixes RHBZ 783523 - -* Sat Jan 14 2012 Fedora Release Engineering - 1.0.7-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild - -* Tue Mar 22 2011 Peter Robinson 1.0.7-1 -- New stable 1.0.7 release - -* Mon Feb 07 2011 Fedora Release Engineering - 1.0.6-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild - -* Sun Oct 24 2010 Peter Robinson 1.0.6-1 -- New stable 1.0.6 release - -* Fri Jul 23 2010 Peter Robinson 1.0.5-1 -- New stable 1.0.5 release - -* Fri May 28 2010 Bastien Nocera 1.0.4-3 -- Fix udev rule to use the usbmuxd user - -* Wed May 12 2010 Peter Robinson 1.0.4-2 -- Actually upload a source file - -* Tue May 11 2010 Peter Robinson 1.0.4-1 -- New stable 1.0.4 release - -* Mon Mar 22 2010 Peter Robinson 1.0.3-1 -- New stable 1.0.3 release - -* Thu Feb 11 2010 Peter Robinson 1.0.2-1 -- New stable 1.0.2 release - -* Tue Feb 09 2010 Bastien Nocera 1.0.0-3 -- Use the gid/uid reserved for usbmuxd in setup 2.8.15 and above - -* Fri Jan 29 2010 Peter Robinson 1.0.0-2 -- Run deamon under the usbmuxd user - -* Mon Dec 7 2009 Peter Robinson 1.0.0-1 -- New stable 1.0.0 release - -* Sat Oct 31 2009 Peter Robinson 1.0.0-0.1.rc2 -- New 1.0.0-rc2 test release - -* Thu Oct 29 2009 Peter Robinson 1.0.0-0.2.rc1 -- Add patch to fix install of 64 bit libs - -* Tue Oct 27 2009 Peter Robinson 1.0.0-0.1.rc1 -- New 1.0.0-rc1 test release - -* Fri Aug 14 2009 Bastien Nocera 0.1.4-2 -- Make usbmuxd autostart on newer kernels -- (Still doesn't exit properly though) - -* Mon Aug 10 2009 Peter Robinson 0.1.4-1 -- Update to 0.1.4 - -* Tue Aug 4 2009 Peter Robinson 0.1.3-1 -- Update to 0.1.3, review input - -* Mon Aug 3 2009 Peter Robinson 0.1.2-1 -- Update to 0.1.2 - -* Mon Aug 3 2009 Peter Robinson 0.1.1-1 -- Initial packaging diff --git a/sources b/sources index 83a15ef..f160070 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (usbmuxd-3ded00c9985a5108cfc7591a309f9a23d57a8cba.tar.gz) = 2c5bd94ee1cf484507c3582a101d04a32a94b33296632992f99cf4a08bc87c56e71570cd5855fb20d285344cb6e382afa8c2b1aa0be50b693b229fd25069814b +34361c59320cb0b1f9ebcd2798ee1b39 usbmuxd-1.1.0.tar.bz2 diff --git a/usbmuxd.spec b/usbmuxd.spec index a9a4530..638d1f1 100644 --- a/usbmuxd.spec +++ b/usbmuxd.spec @@ -1,33 +1,25 @@ -%global forgeurl https://github.com/libimobiledevice/usbmuxd -%global commit 3ded00c9985a5108cfc7591a309f9a23d57a8cba -%global date 20251205 -%{?commit:%global shortcommit %(c=%{commit}; echo ${c:0:7})} +Name: usbmuxd +Version: 1.1.0 +Release: 18%{?dist} +Summary: Daemon for communicating with Apple's iOS devices +# All code is dual licenses as GPLv3+ or GPLv2+, except libusbmuxd which is LGPLv2+. +License: GPLv3+ or GPLv2+ +URL: http://www.libimobiledevice.org/ +Source0: http://www.libimobiledevice.org/downloads/%{name}-%{version}.tar.bz2 -Name: usbmuxd -Version: 1.1.1^%{date}git%{shortcommit} -Release: %autorelease -Summary: Daemon for communicating with Apple's iOS devices -License: GPL-3.0-only OR GPL-2.0-only -URL: https://libimobiledevice.org -Source0: %{forgeurl}/archive/%{commit}/%{name}-%{commit}.tar.gz -Source1: %{name}.sysusers -Source2: %{name}.tmpfiles +BuildRequires: gcc +BuildRequires: libimobiledevice-devel +BuildRequires: libplist-devel +BuildRequires: libusbx-devel +BuildRequires: systemd -BuildRequires: autoconf -BuildRequires: automake -BuildRequires: gcc -BuildRequires: libtool -BuildRequires: make -BuildRequires: sed -BuildRequires: systemd -%{?sysusers_requires_compat} +Requires(pre): shadow-utils +Requires(post): systemd +Requires(preun): systemd +Requires(postun): systemd -BuildRequires: libimobiledevice-devel -BuildRequires: libplist-devel -BuildRequires: libusbx-devel - -Requires: systemd-udev -Recommends: systemd +BuildRequires: autoconf libtool automake git +Patch0: 68bdf4be88b128c56eea5117361c4e7b51eb27b1...9af2b12552693a47601347e1eafc1e94132d727e.patch %description usbmuxd is a daemon used for communicating with Apple's iPod Touch, iPhone, @@ -35,30 +27,27 @@ iPad and Apple TV devices. It allows multiple services on the device to be accessed simultaneously. %prep -%autosetup -p1 -n %{name}-%{commit} - -%if %{defined commit} -echo %{version} > .tarball-version -%endif +%autosetup -p1 -S git_am +autoreconf -f -i # Set the owner of the device node to be usbmuxd sed -i.owner 's/OWNER="usbmux"/OWNER="usbmuxd"/' udev/39-usbmuxd.rules.in sed -i.user 's/--user usbmux/--user usbmuxd/' systemd/usbmuxd.service.in %build -NOCONFIGURE=1 ./autogen.sh %configure -%make_build + +make %{?_smp_mflags} V=1 %install -%make_install - -mkdir -p %{buildroot}%{_localstatedir}/lib/lockdown/ -install -Dpm0644 %{SOURCE1} %{buildroot}%{_sysusersdir}/usbmuxd.conf -install -Dpm0644 %{SOURCE2} %{buildroot}%{_tmpfilesdir}/usbmuxd.conf +make install DESTDIR=$RPM_BUILD_ROOT %pre -%sysusers_create_compat %{SOURCE1} +getent group usbmuxd >/dev/null || groupadd -r usbmuxd -g 113 +getent passwd usbmuxd >/dev/null || \ +useradd -r -g usbmuxd -d / -s /sbin/nologin \ + -c "usbmuxd user" -u 113 usbmuxd +exit 0 %post %systemd_post usbmuxd.service @@ -76,9 +65,187 @@ install -Dpm0644 %{SOURCE2} %{buildroot}%{_tmpfilesdir}/usbmuxd.conf %{_udevrulesdir}/39-usbmuxd.rules %{_sbindir}/usbmuxd %{_datadir}/man/man8/usbmuxd.8.gz -%attr(2775, usbmuxd, usbmuxd) %dir %{_localstatedir}/lib/lockdown/ -%{_sysusersdir}/usbmuxd.conf -%{_tmpfilesdir}/usbmuxd.conf %changelog -%autochangelog +* Fri Jan 31 2020 Fedora Release Engineering - 1.1.0-18 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild + +* Mon Nov 25 2019 Bastien Nocera - 1.1.0-17 ++ usbmuxd-1.1.0-17 +- Update to latest git snapshot + +* Sat Jul 27 2019 Fedora Release Engineering - 1.1.0-16 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild + +* Sun Feb 03 2019 Fedora Release Engineering - 1.1.0-15 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild + +* Sat Jul 14 2018 Fedora Release Engineering - 1.1.0-14 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Wed Apr 18 2018 Bastien Nocera - 1.1.0-13 ++ usbmuxd-1.1.0-13 +- Fix usbmuxd not starting up a second time, and properties being lost + with kernel >= 4.12 + +* Fri Mar 9 2018 Peter Robinson 1.1.0-12 +- Add gcc BR + +* Fri Feb 09 2018 Fedora Release Engineering - 1.1.0-11 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild + +* Thu Aug 03 2017 Fedora Release Engineering - 1.1.0-10 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild + +* Thu Jul 27 2017 Fedora Release Engineering - 1.1.0-9 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Tue May 16 2017 Peter Robinson 1.1.0-8 +- Use _udevrulesdir macro + +* Sat Feb 11 2017 Fedora Release Engineering - 1.1.0-7 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild + +* Fri Feb 05 2016 Fedora Release Engineering - 1.1.0-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild + +* Fri Jun 19 2015 Fedora Release Engineering - 1.1.0-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Wed Feb 11 2015 Peter Robinson 1.0.10-4 +- Rebuild (libimobiledevice) + +* Tue Feb 3 2015 Peter Robinson 1.0.10-3 +- Use %%license + +* Tue Oct 21 2014 Peter Robinson 1.0.10-2 +- (rebuild) + +* Fri Oct 17 2014 Peter Robinson 1.0.10-1 +- New stable 1.1.0 release + +* Fri Oct 17 2014 Peter Robinson 1.0.9-3 +- Bump for correct overrides + +* Fri Oct 17 2014 Peter Robinson 1.0.9-2 +- Refresh usbmuxd owner bits + +* Wed Oct 15 2014 Peter Robinson 1.0.9-1 +- New stable 1.0.9 release + +* Tue Sep 09 2014 Rex Dieter - 1.0.9-0.6.c24463e +- Obsoletes: usbmuxd < 1.0.9 (multilib upgrade path) +- move Obsoletes: usbmuxd-devel to libusbmuxd-devel + +* Mon Aug 18 2014 Fedora Release Engineering - 1.0.9-0.5.c24463e +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild + +* Wed Jul 30 2014 Peter Robinson 1.0.9-0.4.c24463e +- Add upstream patch for systemd support + +* Sun Jun 08 2014 Fedora Release Engineering - 1.0.9-0.3.c24463e +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild + +* Mon Apr 21 2014 Peter Robinson 1.0.9-0.2 +- Minor update + +* Mon Apr 21 2014 Peter Robinson 1.0.9-0.1 +- Initial 1.0.9 snapshot + +* Thu Oct 10 2013 Ralf Corsépius - 1.0.8-10 +- Add BR: systemd for systemd.macros (RHBZ #1017493). + +* Tue Oct 8 2013 Peter Robinson 1.0.8-9 +- Fix rpm scripts + +* Sun Aug 04 2013 Fedora Release Engineering - 1.0.8-8 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild + +* Fri Feb 15 2013 Fedora Release Engineering - 1.0.8-7 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild + +* Mon Nov 19 2012 Bastien Nocera 1.0.8-6 +- Fix source URL + +* Thu Oct 4 2012 Peter Robinson - 1.0.8-5 +- Make use of the new systemd macros +- Minor updates to spec + +* Sun Jul 22 2012 Fedora Release Engineering - 1.0.8-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Mon Jul 09 2012 Bastien Nocera 1.0.8-3 +- Use systemd to start usbmuxd instead of udev (#786853) + +* Sat Apr 28 2012 Bastien Nocera 1.0.8-2 +- Fix usbmuxd not starting under udev + +* Mon Apr 9 2012 Peter Robinson 1.0.8-1 +- New stable 1.0.8 release + +* Thu Feb 2 2012 Peter Robinson - 1.0.7-3 +- Add debian patch for CVE-2012-0065. Fixes RHBZ 783523 + +* Sat Jan 14 2012 Fedora Release Engineering - 1.0.7-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Tue Mar 22 2011 Peter Robinson 1.0.7-1 +- New stable 1.0.7 release + +* Mon Feb 07 2011 Fedora Release Engineering - 1.0.6-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Sun Oct 24 2010 Peter Robinson 1.0.6-1 +- New stable 1.0.6 release + +* Fri Jul 23 2010 Peter Robinson 1.0.5-1 +- New stable 1.0.5 release + +* Fri May 28 2010 Bastien Nocera 1.0.4-3 +- Fix udev rule to use the usbmuxd user + +* Wed May 12 2010 Peter Robinson 1.0.4-2 +- Actually upload a source file + +* Tue May 11 2010 Peter Robinson 1.0.4-1 +- New stable 1.0.4 release + +* Mon Mar 22 2010 Peter Robinson 1.0.3-1 +- New stable 1.0.3 release + +* Thu Feb 11 2010 Peter Robinson 1.0.2-1 +- New stable 1.0.2 release + +* Tue Feb 09 2010 Bastien Nocera 1.0.0-3 +- Use the gid/uid reserved for usbmuxd in setup 2.8.15 and above + +* Fri Jan 29 2010 Peter Robinson 1.0.0-2 +- Run deamon under the usbmuxd user + +* Mon Dec 7 2009 Peter Robinson 1.0.0-1 +- New stable 1.0.0 release + +* Sat Oct 31 2009 Peter Robinson 1.0.0-0.1.rc2 +- New 1.0.0-rc2 test release + +* Thu Oct 29 2009 Peter Robinson 1.0.0-0.2.rc1 +- Add patch to fix install of 64 bit libs + +* Tue Oct 27 2009 Peter Robinson 1.0.0-0.1.rc1 +- New 1.0.0-rc1 test release + +* Fri Aug 14 2009 Bastien Nocera 0.1.4-2 +- Make usbmuxd autostart on newer kernels +- (Still doesn't exit properly though) + +* Mon Aug 10 2009 Peter Robinson 0.1.4-1 +- Update to 0.1.4 + +* Tue Aug 4 2009 Peter Robinson 0.1.3-1 +- Update to 0.1.3, review input + +* Mon Aug 3 2009 Peter Robinson 0.1.2-1 +- Update to 0.1.2 + +* Mon Aug 3 2009 Peter Robinson 0.1.1-1 +- Initial packaging diff --git a/usbmuxd.sysusers b/usbmuxd.sysusers deleted file mode 100644 index 011882a..0000000 --- a/usbmuxd.sysusers +++ /dev/null @@ -1,7 +0,0 @@ -# UID and GID 113 are reserved for this package: -# https://src.fedoraproject.org/rpms/usbmuxd/c/c204e89b56d7f889f13c707581ebe3f838a7c2a9 -# https://pagure.io/setup/c/70e005798f1fb4c73b07f824ba8df518f32e5fc3 -# -#Type Name ID GECOS Home directory Shell -g usbmuxd 113 -u usbmuxd 113:113 "usbmuxd user" - - diff --git a/usbmuxd.tmpfiles b/usbmuxd.tmpfiles deleted file mode 100644 index cd8eda2..0000000 --- a/usbmuxd.tmpfiles +++ /dev/null @@ -1,2 +0,0 @@ -#Type Path Mode User Group Age Argument -d /var/lib/lockdown 2775 usbmuxd usbmuxd - -