summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGravatar Martin Szulecki2009-05-24 00:25:03 +0200
committerGravatar Martin Szulecki2009-05-24 00:25:03 +0200
commit36ea32e0064f33d6a285684c3069f4d75bbac7a8 (patch)
tree039291b47e954fe8529f52e1fc71f7e924761a6a /src
parent46f8d46845355e6a33a6dcb97ba11d4c4cab62eb (diff)
parent435f5feb4b5c501db52743a170908687d3ba6f60 (diff)
downloadlibimobiledevice-36ea32e0064f33d6a285684c3069f4d75bbac7a8.tar.gz
libimobiledevice-36ea32e0064f33d6a285684c3069f4d75bbac7a8.tar.bz2
Merge branch 'master' of git://github.com/MattColyer/libiphone into martin
Conflicts: src/Makefile.am
Diffstat (limited to 'src')
-rw-r--r--src/AFC.c75
-rw-r--r--src/AFC.h4
-rw-r--r--src/Makefile.am7
-rw-r--r--src/MobileSync.c25
-rw-r--r--src/MobileSync.h3
-rw-r--r--src/NotificationProxy.c47
-rw-r--r--src/NotificationProxy.h3
-rw-r--r--src/iphone.c295
-rw-r--r--src/iphone.h17
-rw-r--r--src/lockdown.c89
-rw-r--r--src/lockdown.h4
-rw-r--r--src/usbmux.c410
-rw-r--r--src/usbmux.h58
13 files changed, 187 insertions, 850 deletions
diff --git a/src/AFC.c b/src/AFC.c
index e5fe526..71093df 100644
--- a/src/AFC.c
+++ b/src/AFC.c
@@ -20,7 +20,9 @@
*/
#include <stdio.h>
+#include <stdlib.h>
#include <errno.h>
+#include <unistd.h>
#include "AFC.h"
#include "utils.h"
@@ -61,29 +63,28 @@ static void afc_unlock(iphone_afc_client_t client)
*
* @return A handle to the newly-connected client or NULL upon error.
*/
-iphone_error_t iphone_afc_new_client(iphone_device_t device, int src_port, int dst_port, iphone_afc_client_t * client)
+iphone_error_t iphone_afc_new_client(iphone_device_t device, int dst_port, iphone_afc_client_t * client)
{
- int ret = IPHONE_E_SUCCESS;
-
//makes sure thread environment is available
if (!g_thread_supported())
g_thread_init(NULL);
- iphone_afc_client_t client_loc = (iphone_afc_client_t) malloc(sizeof(struct iphone_afc_client_int));
if (!device)
return IPHONE_E_INVALID_ARG;
// Attempt connection
- client_loc->connection = NULL;
- ret = iphone_mux_new_client(device, src_port, dst_port, &client_loc->connection);
- if (IPHONE_E_SUCCESS != ret || !client_loc->connection) {
- free(client_loc);
- return ret;
+ int sfd = usbmuxd_connect(device->handle, dst_port);
+ if (sfd < 0) {
+ return IPHONE_E_UNKNOWN_ERROR; // ret;
}
+
+ iphone_afc_client_t client_loc = (iphone_afc_client_t) malloc(sizeof(struct iphone_afc_client_int));
+ client_loc->sfd = sfd;
+
// Allocate a packet
client_loc->afc_packet = (AFCPacket *) malloc(sizeof(AFCPacket));
if (!client_loc->afc_packet) {
- iphone_mux_free_client(client_loc->connection);
+ usbmuxd_disconnect(client_loc->sfd);
free(client_loc);
return IPHONE_E_UNKNOWN_ERROR;
}
@@ -106,10 +107,10 @@ iphone_error_t iphone_afc_new_client(iphone_device_t device, int src_port, int d
*/
iphone_error_t iphone_afc_free_client(iphone_afc_client_t client)
{
- if (!client || !client->connection || !client->afc_packet)
+ if (!client || client->sfd < 0 || !client->afc_packet)
return IPHONE_E_INVALID_ARG;
- iphone_mux_free_client(client->connection);
+ usbmuxd_disconnect(client->sfd);
free(client->afc_packet);
if (client->mutex) {
g_mutex_free(client->mutex);
@@ -217,7 +218,7 @@ static int dispatch_AFC_packet(iphone_afc_client_t client, const char *data, int
int bytes = 0, offset = 0;
char *buffer;
- if (!client || !client->connection || !client->afc_packet)
+ if (!client || client->sfd < 0 || !client->afc_packet)
return 0;
if (!data || !length)
length = 0;
@@ -248,7 +249,7 @@ static int dispatch_AFC_packet(iphone_afc_client_t client, const char *data, int
return -1;
}
memcpy(buffer + sizeof(AFCPacket), data, offset);
- iphone_mux_send(client->connection, buffer, client->afc_packet->this_length, (uint32_t*)&bytes);
+ usbmuxd_send(client->sfd, buffer, client->afc_packet->this_length, (uint32_t*)&bytes);
free(buffer);
if (bytes <= 0) {
return bytes;
@@ -259,7 +260,7 @@ static int dispatch_AFC_packet(iphone_afc_client_t client, const char *data, int
log_debug_msg("Buffer: \n");
log_debug_buffer(data + offset, length - offset);
- iphone_mux_send(client->connection, data + offset, length - offset, (uint32_t*)&bytes);
+ usbmuxd_send(client->sfd, data + offset, length - offset, (uint32_t*)&bytes);
return bytes;
} else {
log_debug_msg("dispatch_AFC_packet doin things the old way\n");
@@ -273,7 +274,7 @@ static int dispatch_AFC_packet(iphone_afc_client_t client, const char *data, int
}
log_debug_buffer(buffer, client->afc_packet->this_length);
log_debug_msg("\n");
- iphone_mux_send(client->connection, buffer, client->afc_packet->this_length, (uint32_t*)&bytes);
+ usbmuxd_send(client->sfd, buffer, client->afc_packet->this_length, (uint32_t*)&bytes);
if (buffer) {
free(buffer);
@@ -307,7 +308,7 @@ static int receive_AFC_data(iphone_afc_client_t client, char **dump_here)
client->afcerror = 0;
// first, read the AFC header
- iphone_mux_recv(client->connection, (char*)&header, sizeof(AFCPacket), (uint32_t*)&bytes);
+ usbmuxd_recv(client->sfd, (char*)&header, sizeof(AFCPacket), (uint32_t*)&bytes);
if (bytes <= 0) {
log_debug_msg("%s: Just didn't get enough.\n", __func__);
*dump_here = NULL;
@@ -359,24 +360,26 @@ static int receive_AFC_data(iphone_afc_client_t client, char **dump_here)
}
*dump_here = (char*)malloc(entire_len);
- iphone_mux_recv(client->connection, *dump_here, this_len, (uint32_t*)&bytes);
- if (bytes <= 0) {
- free(*dump_here);
- *dump_here = NULL;
- log_debug_msg("%s: Did not get packet contents!\n", __func__);
- return -1;
- } else if ((uint32_t)bytes < this_len) {
- free(*dump_here);
- *dump_here = NULL;
- log_debug_msg("%s: Could not receive this_len=%d bytes\n", __func__, this_len);
- return -1;
+ if (this_len > 0) {
+ usbmuxd_recv(client->sfd, *dump_here, this_len, (uint32_t*)&bytes);
+ if (bytes <= 0) {
+ free(*dump_here);
+ *dump_here = NULL;
+ log_debug_msg("%s: Did not get packet contents!\n", __func__);
+ return -1;
+ } else if ((uint32_t)bytes < this_len) {
+ free(*dump_here);
+ *dump_here = NULL;
+ log_debug_msg("%s: Could not receive this_len=%d bytes\n", __func__, this_len);
+ return -1;
+ }
}
current_count = this_len;
if (entire_len > this_len) {
while (current_count < entire_len) {
- iphone_mux_recv(client->connection, (*dump_here)+current_count, entire_len - current_count, (uint32_t*)&bytes);
+ usbmuxd_recv(client->sfd, (*dump_here)+current_count, entire_len - current_count, (uint32_t*)&bytes);
if (bytes <= 0) {
log_debug_msg("%s: Error receiving data (recv returned %d)\n", __func__, bytes);
break;
@@ -559,7 +562,7 @@ iphone_error_t iphone_afc_delete_file(iphone_afc_client_t client, const char *pa
char *response = NULL;
int bytes;
- if (!client || !path || !client->afc_packet || !client->connection)
+ if (!client || !path || !client->afc_packet || client->sfd < 0)
return IPHONE_E_INVALID_ARG;
afc_lock(client);
@@ -600,7 +603,7 @@ iphone_error_t iphone_afc_rename_file(iphone_afc_client_t client, const char *fr
char *send = (char *) malloc(sizeof(char) * (strlen(from) + strlen(to) + 1 + sizeof(uint32_t)));
int bytes = 0;
- if (!client || !from || !to || !client->afc_packet || !client->connection)
+ if (!client || !from || !to || !client->afc_packet || client->sfd < 0)
return IPHONE_E_INVALID_ARG;
afc_lock(client);
@@ -748,7 +751,7 @@ iphone_error_t iphone_afc_get_file_attr(iphone_afc_client_t client, const char *
{
iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
- if (!client || !client->connection || !client->afc_packet || !stbuf)
+ if (!client || client->sfd < 0 || !client->afc_packet || !stbuf)
return IPHONE_E_INVALID_ARG;
memset(stbuf, 0, sizeof(struct stat));
@@ -793,7 +796,7 @@ iphone_afc_open_file(iphone_afc_client_t client, const char *filename,
int bytes = 0, length = 0;
char *data = (char *) malloc(sizeof(char) * (8 + strlen(filename) + 1));
- if (!client || !client->connection || !client->afc_packet)
+ if (!client || client->sfd < 0|| !client->afc_packet)
return IPHONE_E_INVALID_ARG;
afc_lock(client);
@@ -851,7 +854,7 @@ iphone_afc_read_file(iphone_afc_client_t client, iphone_afc_file_t file, char *d
int current_count = 0, bytes_loc = 0;
const int MAXIMUM_READ_SIZE = 1 << 16;
- if (!client || !client->afc_packet || !client->connection || !file)
+ if (!client || !client->afc_packet || client->sfd < 0 || !file)
return IPHONE_E_INVALID_ARG;
log_debug_msg("afc_read_file called for length %i\n", length);
@@ -926,7 +929,7 @@ iphone_afc_write_file(iphone_afc_client_t client, iphone_afc_file_t file,
int bytes_loc = 0;
char *out_buffer = NULL;
- if (!client || !client->afc_packet || !client->connection || !file || !bytes)
+ if (!client || !client->afc_packet || client->sfd < 0 || !file || !bytes)
return IPHONE_E_INVALID_ARG;
afc_lock(client);
@@ -1219,7 +1222,7 @@ iphone_error_t iphone_afc_truncate(iphone_afc_client_t client, const char *path,
int bytes = 0;
uint64_t size_requested = newsize;
- if (!client || !path || !client->afc_packet || !client->connection)
+ if (!client || !path || !client->afc_packet || client->sfd < 0)
return IPHONE_E_INVALID_ARG;
afc_lock(client);
diff --git a/src/AFC.h b/src/AFC.h
index 41b4d67..5827518 100644
--- a/src/AFC.h
+++ b/src/AFC.h
@@ -19,7 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "usbmux.h"
+#include "libiphone/libiphone.h"
#include "iphone.h"
#include <string.h>
@@ -47,7 +47,7 @@ typedef struct __AFCToken {
} AFCToken;
struct iphone_afc_client_int {
- iphone_umux_client_t connection;
+ int sfd;
AFCPacket *afc_packet;
int file_handle;
int lock;
diff --git a/src/Makefile.am b/src/Makefile.am
index 0cae16b..5489684 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,11 +1,10 @@
INCLUDES = -I$(top_srcdir)/include
-AM_CFLAGS = $(GLOBAL_CFLAGS) $(libusb_CFLAGS) $(libglib2_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(libgthread2_CFLAGS) $(libplist_CFLAGS) $(LFS_CFLAGS)
-AM_LDFLAGS = $(libusb_LIBS) $(libglib2_LIBS) $(libgnutls_LIBS) $(libgcrypt_LIBS) $(libtasn1_LIBS) $(libgthread2_LIBS) $(libplist_LIBS)
+AM_CFLAGS = $(GLOBAL_CFLAGS) $(libusbmuxd_CFLAGS) $(libglib2_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(libgthread2_CFLAGS) $(libplist_CFLAGS) $(LFS_CFLAGS)
+AM_LDFLAGS = $(libglib2_LIBS) $(libgnutls_LIBS) $(libtasn1_LIBS) $(libgthread2_LIBS) $(libplist_LIBS) $(libusbmuxd_LIBS)
lib_LTLIBRARIES = libiphone.la
-libiphone_la_SOURCES = usbmux.c usbmux.h \
- iphone.c iphone.h \
+libiphone_la_SOURCES = iphone.c iphone.h \
lockdown.c lockdown.h\
AFC.c AFC.h\
NotificationProxy.c NotificationProxy.h\
diff --git a/src/MobileSync.c b/src/MobileSync.c
index 58d0beb..7d6e947 100644
--- a/src/MobileSync.c
+++ b/src/MobileSync.c
@@ -22,29 +22,30 @@
#include "MobileSync.h"
#include <plist/plist.h>
#include <string.h>
+#include <stdlib.h>
#include <arpa/inet.h>
#define MSYNC_VERSION_INT1 100
#define MSYNC_VERSION_INT2 100
-iphone_error_t iphone_msync_new_client(iphone_device_t device, int src_port, int dst_port,
+iphone_error_t iphone_msync_new_client(iphone_device_t device, int dst_port,
iphone_msync_client_t * client)
{
- if (!device || src_port == 0 || dst_port == 0 || !client || *client)
+ if (!device || dst_port == 0 || !client || *client)
return IPHONE_E_INVALID_ARG;
iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
- iphone_msync_client_t client_loc = (iphone_msync_client_t) malloc(sizeof(struct iphone_msync_client_int));
-
// Attempt connection
- client_loc->connection = NULL;
- ret = iphone_mux_new_client(device, src_port, dst_port, &client_loc->connection);
- if (IPHONE_E_SUCCESS != ret || !client_loc->connection) {
- free(client_loc);
+ int sfd = usbmuxd_connect(device->handle, dst_port);
+ if (sfd < 0) {
return ret;
}
+
+ iphone_msync_client_t client_loc = (iphone_msync_client_t) malloc(sizeof(struct iphone_msync_client_int));
+ client_loc->sfd = sfd;
+
//perform handshake
plist_t array = NULL;
@@ -120,7 +121,7 @@ iphone_error_t iphone_msync_free_client(iphone_msync_client_t client)
return IPHONE_E_INVALID_ARG;
iphone_msync_stop_session(client);
- return iphone_mux_free_client(client->connection);
+ return usbmuxd_disconnect(client->sfd);
}
/** Polls the iPhone for MobileSync data.
@@ -138,14 +139,14 @@ iphone_error_t iphone_msync_recv(iphone_msync_client_t client, plist_t * plist)
char *receive = NULL;
uint32_t datalen = 0, bytes = 0, received_bytes = 0;
- ret = iphone_mux_recv(client->connection, (char *) &datalen, sizeof(datalen), &bytes);
+ ret = usbmuxd_recv(client->sfd, (char *) &datalen, sizeof(datalen), &bytes);
datalen = ntohl(datalen);
receive = (char *) malloc(sizeof(char) * datalen);
/* fill buffer and request more packets if needed */
while ((received_bytes < datalen) && (ret == IPHONE_E_SUCCESS)) {
- ret = iphone_mux_recv(client->connection, receive + received_bytes, datalen - received_bytes, &bytes);
+ ret = usbmuxd_recv(client->sfd, receive + received_bytes, datalen - received_bytes, &bytes);
received_bytes += bytes;
}
@@ -201,7 +202,7 @@ iphone_error_t iphone_msync_send(iphone_msync_client_t client, plist_t plist)
memcpy(real_query, &length, sizeof(length));
memcpy(real_query + 4, content, ntohl(length));
- ret = iphone_mux_send(client->connection, real_query, ntohl(length) + sizeof(length), &bytes);
+ ret = usbmuxd_send(client->sfd, real_query, ntohl(length) + sizeof(length), (uint32_t*)&bytes);
free(real_query);
return ret;
}
diff --git a/src/MobileSync.h b/src/MobileSync.h
index 7655b59..495e702 100644
--- a/src/MobileSync.h
+++ b/src/MobileSync.h
@@ -21,7 +21,6 @@
#ifndef MOBILESYNC_H
#define MOBILESYNC_H
-#include "usbmux.h"
#include "iphone.h"
#include "utils.h"
@@ -30,7 +29,7 @@
struct iphone_msync_client_int {
- iphone_umux_client_t connection;
+ int sfd;
};
diff --git a/src/NotificationProxy.c b/src/NotificationProxy.c
index d8bcc34..6fc048c 100644
--- a/src/NotificationProxy.c
+++ b/src/NotificationProxy.c
@@ -21,6 +21,7 @@
#include <string.h>
#include <stdio.h>
+#include <stdlib.h>
#include <arpa/inet.h>
#include <plist/plist.h>
#include "NotificationProxy.h"
@@ -79,9 +80,9 @@ static iphone_error_t np_plist_send(iphone_np_client_t client, plist_t dict)
}
nlen = htonl(length);
- iphone_mux_send(client->connection, (const char*)&nlen, sizeof(nlen), (uint32_t*)&bytes);
+ usbmuxd_send(client->sfd, (const char*)&nlen, sizeof(nlen), (uint32_t*)&bytes);
if (bytes == sizeof(nlen)) {
- iphone_mux_send(client->connection, XML_content, length, (uint32_t*)&bytes);
+ usbmuxd_send(client->sfd, XML_content, length, (uint32_t*)&bytes);
if (bytes > 0) {
if ((uint32_t)bytes == length) {
res = IPHONE_E_SUCCESS;
@@ -107,26 +108,24 @@ static iphone_error_t np_plist_send(iphone_np_client_t client, plist_t dict)
*
* @return A handle to the newly-connected client or NULL upon error.
*/
-iphone_error_t iphone_np_new_client ( iphone_device_t device, int src_port, int dst_port, iphone_np_client_t *client )
+iphone_error_t iphone_np_new_client ( iphone_device_t device, int dst_port, iphone_np_client_t *client )
{
- int ret = IPHONE_E_SUCCESS;
-
//makes sure thread environment is available
if (!g_thread_supported())
g_thread_init(NULL);
- iphone_np_client_t client_loc = (iphone_np_client_t) malloc(sizeof(struct iphone_np_client_int));
if (!device)
return IPHONE_E_INVALID_ARG;
// Attempt connection
- client_loc->connection = NULL;
- ret = iphone_mux_new_client(device, src_port, dst_port, &client_loc->connection);
- if (IPHONE_E_SUCCESS != ret || !client_loc->connection) {
- free(client_loc);
- return ret;
+ int sfd = usbmuxd_connect(device->handle, dst_port);
+ if (sfd < 0) {
+ return IPHONE_E_UNKNOWN_ERROR; //ret;
}
+ iphone_np_client_t client_loc = (iphone_np_client_t) malloc(sizeof(struct iphone_np_client_int));
+ client_loc->sfd = sfd;
+
client_loc->mutex = g_mutex_new();
client_loc->notifier = NULL;
@@ -144,13 +143,11 @@ iphone_error_t iphone_np_free_client ( iphone_np_client_t client )
if (!client)
return IPHONE_E_INVALID_ARG;
- if (client->connection) {
- iphone_mux_free_client(client->connection);
- client->connection = NULL;
- if (client->notifier) {
- log_debug_msg("joining np callback\n");
- g_thread_join(client->notifier);
- }
+ usbmuxd_disconnect(client->sfd);
+ client->sfd = -1;
+ if (client->notifier) {
+ log_debug_msg("joining np callback\n");
+ g_thread_join(client->notifier);
}
if (client->mutex) {
g_mutex_free(client->mutex);
@@ -295,13 +292,13 @@ iphone_error_t iphone_np_get_notification( iphone_np_client_t client, char **not
char *XML_content = NULL;
plist_t dict = NULL;
- if (!client || !client->connection || *notification) {
+ if (!client || client->sfd < 0 || *notification) {
return IPHONE_E_INVALID_ARG;
}
np_lock(client);
- iphone_mux_recv_timeout(client->connection, (char*)&pktlen, sizeof(pktlen), &bytes, 500);
+ usbmuxd_recv_timeout(client->sfd, (char*)&pktlen, sizeof(pktlen), &bytes, 500);
log_debug_msg("NotificationProxy: initial read=%i\n", bytes);
if (bytes < 4) {
log_debug_msg("NotificationProxy: no notification received!\n");
@@ -313,7 +310,7 @@ iphone_error_t iphone_np_get_notification( iphone_np_client_t client, char **not
XML_content = (char*)malloc(pktlen);
log_debug_msg("pointer %p\n", XML_content);
- iphone_mux_recv_timeout(client->connection, XML_content, pktlen, &bytes, 1000);
+ usbmuxd_recv_timeout(client->sfd, XML_content, pktlen, &bytes, 1000);
if (bytes <= 0) {
res = IPHONE_E_UNKNOWN_ERROR;
} else {
@@ -393,7 +390,7 @@ gpointer iphone_np_notifier( gpointer arg )
if (!npt) return NULL;
log_debug_msg("%s: starting callback.\n", __func__);
- while (npt->client->connection) {
+ while (npt->client->sfd >= 0) {
iphone_np_get_notification(npt->client, &notification);
if (notification) {
npt->cbfunc(notification);
@@ -432,11 +429,11 @@ iphone_error_t iphone_np_set_notify_callback( iphone_np_client_t client, iphone_
np_lock(client);
if (client->notifier) {
log_debug_msg("%s: callback already set, removing\n");
- iphone_umux_client_t conn = client->connection;
- client->connection = NULL;
+ int conn = client->sfd;
+ client->sfd = -1;
g_thread_join(client->notifier);
client->notifier = NULL;
- client->connection = conn;
+ client->sfd = conn;
}
if (notify_cb) {
diff --git a/src/NotificationProxy.h b/src/NotificationProxy.h
index 3552b79..afae98a 100644
--- a/src/NotificationProxy.h
+++ b/src/NotificationProxy.h
@@ -19,13 +19,12 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libiphone/libiphone.h"
-#include "usbmux.h"
#include "iphone.h"
#include <glib.h>
struct iphone_np_client_int {
- iphone_umux_client_t connection;
+ int sfd;
GMutex *mutex;
GThread *notifier;
};
diff --git a/src/iphone.c b/src/iphone.c
index 9dd3c07..9551173 100644
--- a/src/iphone.c
+++ b/src/iphone.c
@@ -19,200 +19,85 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "usbmux.h"
#include "iphone.h"
#include "utils.h"
-#include <arpa/inet.h>
-#include <usb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <errno.h>
+#include <libiphone/libiphone.h>
/**
- * This function sets the configuration of the given device to 3
- * and claims the interface 1. If usb_set_configuration fails, it detaches
- * the kernel driver that blocks the device, and retries configuration.
+ * Retrieves a list of connected devices from usbmuxd and matches their
+ * UUID with the given UUID. If the given UUID is NULL then the first
+ * device reported by usbmuxd is used.
*
- * @param phone which device to configure
- */
-static void iphone_config_usb_device(iphone_device_t phone)
-{
- int ret;
- int bytes;
- unsigned char buf[512];
-
- log_debug_msg("setting configuration... ");
- ret = usb_set_configuration(phone->device, 3);
- if (ret != 0) {
- log_debug_msg("Hm, usb_set_configuration returned %d: %s, trying to fix:\n", ret, strerror(-ret));
- log_debug_msg("-> detaching kernel driver... ");
- ret =
- usb_detach_kernel_driver_np(phone->device,
- phone->__device->config->interface->altsetting->bInterfaceNumber);
- if (ret != 0) {
- log_debug_msg("usb_detach_kernel_driver_np returned %d: %s\n", ret, strerror(-ret));
- } else {
- log_debug_msg("done.\n");
- log_debug_msg("setting configuration again... ");
- ret = usb_set_configuration(phone->device, 3);
- if (ret != 0) {
- log_debug_msg("Error: usb_set_configuration returned %d: %s\n", ret, strerror(-ret));
- } else {
- log_debug_msg("done.\n");
- }
- }
- } else {
- log_debug_msg("done.\n");
- }
-
- log_debug_msg("claiming interface... ");
- ret = usb_claim_interface(phone->device, 1);
- if (ret != 0) {
- log_debug_msg("Error: usb_claim_interface returned %d: %s\n", ret, strerror(-ret));
- } else {
- log_debug_msg("done.\n");
- }
-
- do {
- bytes = usb_bulk_read(phone->device, BULKIN, (void *) &buf, 512, 800);
- if (bytes > 0) {
- log_debug_msg("iphone_config_usb_device: initial read returned %d bytes of data.\n", bytes);
- log_debug_buffer(buf, bytes);
- }
- } while (bytes > 0);
-}
-
-/**
- * Given a USB bus and device number, returns a device handle to the iPhone on
- * that bus. To aid compatibility with future devices, this function does not
- * check the vendor and device IDs! To do that, you should use
- * iphone_get_device() or a system-specific API (e.g. HAL).
+ * @param device Upon calling this function, a pointer to a location of type
+ * iphone_device_t, which must have the value NULL. On return, this location
+ * will be filled with a handle to the device.
+ * @param uuid The UUID to match.
*
- * @param bus_n The USB bus number.
- * @param dev_n The USB device number.
- * @param device A pointer to a iphone_device_t, which must be set to NULL upon
- * calling iphone_get_specific_device, which will be filled with a device
- * descriptor on return.
* @return IPHONE_E_SUCCESS if ok, otherwise an error code.
*/
-iphone_error_t iphone_get_specific_device(unsigned int bus_n, int dev_n, iphone_device_t * device)
+iphone_error_t iphone_get_device_by_uuid(iphone_device_t * device, const char *uuid)
{
- struct usb_bus *bus, *busses;
- struct usb_device *dev;
- usbmux_version_header *version;
- int bytes = 0;
-
- //check we can actually write in device
- if (!device || (device && *device))
- return IPHONE_E_INVALID_ARG;
-
- iphone_device_t phone = (iphone_device_t) malloc(sizeof(struct iphone_device_int));
+ iphone_device_t phone;
+ uint32_t handle = 0;
+ usbmuxd_scan_result *dev_list = NULL;
+ int i;
- // Initialize the struct
- phone->device = NULL;
- phone->__device = NULL;
- phone->buffer = NULL;
-
- // Initialize libusb
- usb_init();
- usb_find_busses();
- usb_find_devices();
- busses = usb_get_busses();
-
- // Set the device configuration
- for (bus = busses; bus; bus = bus->next)
- if (strtoul(bus->dirname, NULL, 10) == bus_n)
- for (dev = bus->devices; dev != NULL; dev = dev->next)
- if (strtol(dev->filename, NULL, 10) == dev_n) {
- phone->__device = dev;
- phone->device = usb_open(phone->__device);
- iphone_config_usb_device(phone);
- goto found;
+ if (usbmuxd_scan(&dev_list) < 0) {
+ log_debug_msg("%s: usbmuxd_scan returned an error, is usbmuxd running?\n", __func__);
+ }
+ if (dev_list && dev_list[0].handle > 0) {
+ if (!uuid) {
+ // select first device found if no UUID specified
+ handle = dev_list[0].handle;
+ } else {
+ // otherwise walk through the list
+ for (i = 0; dev_list[i].handle > 0; i++) {
+ log_debug_msg("%s: device handle=%d, uuid=%s\n", __func__, dev_list[i].handle, dev_list[i].serial_number);
+ if (strcasecmp(uuid, dev_list[i].serial_number) == 0) {
+ handle = dev_list[i].handle;
+ break;
}
-
- iphone_free_device(phone);
-
- log_debug_msg("iphone_get_specific_device: iPhone not found\n");
- return IPHONE_E_NO_DEVICE;
-
- found:
- // Send the version command to the phone
- version = version_header();
- bytes = usb_bulk_write(phone->device, BULKOUT, (char *) version, sizeof(*version), 800);
- if (bytes < 20) {
- log_debug_msg("get_iPhone(): libusb did NOT send enough!\n");
- if (bytes < 0) {
- log_debug_msg("get_iPhone(): libusb gave me the error %d: %s (%s)\n",
- bytes, usb_strerror(), strerror(-bytes));
+ }
}
- }
- // Read the phone's response
- bytes = usb_bulk_read(phone->device, BULKIN, (char *) version, sizeof(*version), 800);
+ free(dev_list);
- // Check for bad response
- if (bytes < 20) {
- free(version);
- iphone_free_device(phone);
- log_debug_msg("get_iPhone(): Invalid version message -- header too short.\n");
- if (bytes < 0)
- log_debug_msg("get_iPhone(): libusb error message %d: %s (%s)\n", bytes, usb_strerror(), strerror(-bytes));
- return IPHONE_E_NOT_ENOUGH_DATA;
- }
- // Check for correct version
- if (ntohl(version->major) == 1 && ntohl(version->minor) == 0) {
- // We're all ready to roll.
- log_debug_msg("get_iPhone() success\n");
- free(version);
- *device = phone;
- return IPHONE_E_SUCCESS;
- } else {
- // Bad header
- log_debug_msg("get_iPhone(): Received a bad header/invalid version number.\n");
- log_debug_buffer((char *) version, sizeof(*version));
- iphone_free_device(phone);
- free(version);
- return IPHONE_E_BAD_HEADER;
+ if (handle > 0) {
+ phone = (iphone_device_t) malloc(sizeof(struct iphone_device_int));
+ phone->handle = handle;
+ *device = phone;
+ return IPHONE_E_SUCCESS;
+ }
}
- // If it got to this point it's gotta be bad
- log_debug_msg("get_iPhone(): Unknown error.\n");
- iphone_free_device(phone);
- free(version);
- return IPHONE_E_UNKNOWN_ERROR; // if it got to this point it's gotta be bad
+ return IPHONE_E_NO_DEVICE;
}
/**
- * Scans all USB busses and devices for a known AFC-compatible device and
- * returns a handle to the first such device it finds. Known devices include
- * those with vendor ID 0x05ac and product ID between 0x1290 and 0x1293
- * inclusive.
+ * This function has the purpose to retrieve a handle to the first
+ * attached iPhone/iPod reported by usbmuxd.
*
- * This function is convenient, but on systems where higher-level abstractions
- * (such as HAL) are available it may be preferable to use
- * iphone_get_specific_device instead, because it can deal with multiple
- * connected devices as well as devices not known to libiphone.
- *
- * @param device Upon calling this function, a pointer to a location of type
+ * @param Upon calling this function, a pointer to a location of type
* iphone_device_t, which must have the value NULL. On return, this location
* will be filled with a handle to the device.
+ *
* @return IPHONE_E_SUCCESS if ok, otherwise an error code.
*/
iphone_error_t iphone_get_device(iphone_device_t * device)
{
- struct usb_bus *bus;
- struct usb_device *dev;
-
- usb_init();
- usb_find_busses();
- usb_find_devices();
-
- for (bus = usb_get_busses(); bus != NULL; bus = bus->next)
- for (dev = bus->devices; dev != NULL; dev = dev->next)
- if (dev->descriptor.idVendor == 0x05ac
- && dev->descriptor.idProduct >= 0x1290 && dev->descriptor.idProduct <= 0x1293)
- return iphone_get_specific_device(strtoul(bus->dirname, NULL, 10), strtol(dev->filename, NULL, 10), device);
+ return iphone_get_device_by_uuid(device, NULL);
+}
- return IPHONE_E_NO_DEVICE;
+uint32_t iphone_get_device_handle(iphone_device_t device)
+{
+ if (device) {
+ return device->handle;
+ } else {
+ return 0;
+ }
}
/** Cleans up an iPhone structure, then frees the structure itself.
@@ -226,88 +111,10 @@ iphone_error_t iphone_free_device(iphone_device_t device)
if (!device)
return IPHONE_E_INVALID_ARG;
iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
- int bytes;
- unsigned char buf[512];
- // read final package(s)
- if (device->device != NULL) {
- do {
- bytes = usb_bulk_read(device->device, BULKIN, (void *) &buf, 512, 800);
- if (bytes > 0) {
- log_debug_msg("iphone_free_device: final read returned\n");
- log_debug_buffer(buf, bytes);
- }
- } while (bytes > 0);
- }
+ ret = IPHONE_E_SUCCESS;
- if (device->buffer) {
- free(device->buffer);
- }
- if (device->device) {
- usb_release_interface(device->device, 1);
- usb_close(device->device);
- ret = IPHONE_E_SUCCESS;
- }
free(device);
return ret;
}
-/** Sends data to the phone
- * This is a low-level (i.e. directly to phone) function.
- *
- * @param phone The iPhone to send data to
- * @param data The data to send to the iPhone
- * @param datalen The length of the data
- * @return The number of bytes sent, or -1 on error or something.
- */
-int send_to_phone(iphone_device_t phone, char *data, int datalen)
-{
- if (!phone)
- return -1;
- int bytes = 0;
-
- if (!phone)
- return -1;
- log_debug_msg("send_to_phone: Attempting to send datalen = %i data = %p\n", datalen, data);
-
- bytes = usb_bulk_write(phone->device, BULKOUT, data, datalen, 800);
- if (bytes < datalen) {
- if (bytes < 0)
- log_debug_msg("send_to_iphone(): libusb gave me the error %d: %s - %s\n", bytes, usb_strerror(),
- strerror(-bytes));
- return -1;
- } else {
- return bytes;
- }
- /* Should not be reached */
- return -1;
-}
-
-/** This function is a low-level (i.e. direct to iPhone) function.
- *
- * @param phone The iPhone to receive data from
- * @param data Where to put data read
- * @param datalen How much data to read in
- * @param timeout How many milliseconds to wait for data
- *
- * @return How many bytes were read in, or -1 on error.
- */
-int recv_from_phone(iphone_device_t phone, char *data, int datalen, int timeout)
-{
- if (!phone)
- return -1;
- int bytes = 0;
-
- if (!phone)
- return -1;
- log_debug_msg("recv_from_phone(): attempting to receive %i bytes\n", datalen);
-
- bytes = usb_bulk_read(phone->device, BULKIN, data, datalen, timeout);
- if (bytes < 0) {
- log_debug_msg("recv_from_phone(): libusb gave me the error %d: %s (%s)\n", bytes, usb_strerror(),
- strerror(-bytes));
- return -1;
- }
-
- return bytes;
-}
diff --git a/src/iphone.h b/src/iphone.h
index 15515e3..94d2f9f 100644
--- a/src/iphone.h
+++ b/src/iphone.h
@@ -22,24 +22,11 @@
#ifndef IPHONE_H
#define IPHONE_H
-#ifndef USBMUX_H
-#include "usbmux.h"
-#warning usbmux not included?
-#endif
-
-#include <usb.h>
-#include <libiphone/libiphone.h>
-
-#define BULKIN 0x85
-#define BULKOUT 0x04
+#include <stdint.h>
struct iphone_device_int {
char *buffer;
- struct usb_dev_handle *device;
- struct usb_device *__device;
+ uint32_t handle;
};
-// Function definitions
-int send_to_phone(iphone_device_t phone, char *data, int datalen);
-int recv_from_phone(iphone_device_t phone, char *data, int datalen, int timeout);
#endif
diff --git a/src/lockdown.c b/src/lockdown.c
index 5ade79a..ae408be 100644
--- a/src/lockdown.c
+++ b/src/lockdown.c
@@ -19,7 +19,6 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "usbmux.h"
#include "utils.h"
#include "iphone.h"
#include "lockdown.h"
@@ -27,6 +26,7 @@
#include <arpa/inet.h>
#include <errno.h>
#include <string.h>
+#include <stdlib.h>
#include <glib.h>
#include <libtasn1.h>
#include <gnutls/x509.h>
@@ -53,13 +53,15 @@ iphone_lckd_client_t new_lockdownd_client(iphone_device_t phone)
{
if (!phone)
return NULL;
- iphone_lckd_client_t control = (iphone_lckd_client_t) malloc(sizeof(struct iphone_lckd_client_int));
- if (IPHONE_E_SUCCESS != iphone_mux_new_client(phone, 0x0a00, 0xf27e, &control->connection)) {
- free(control);
+ int sfd = usbmuxd_connect(phone->handle, 0xf27e);
+ if (sfd < 0) {
+ log_debug_msg("%s: could not connect to lockdownd (device handle %d)\n", __func__, phone->handle);
return NULL;
}
+ iphone_lckd_client_t control = (iphone_lckd_client_t) malloc(sizeof(struct iphone_lckd_client_int));
+ control->sfd = sfd;
control->ssl_session = (gnutls_session_t *) malloc(sizeof(gnutls_session_t));
control->in_SSL = 0;
return control;
@@ -167,13 +169,13 @@ iphone_error_t iphone_lckd_free_client(iphone_lckd_client_t client)
iphone_lckd_stop_SSL_session(client);
- if (client->connection) {
+ if (client->sfd > 0) {
lockdownd_close(client);
// IMO, read of final "sessionUpcall connection closed" packet
// should come here instead of in iphone_free_device
- ret = iphone_mux_free_client(client->connection);
+ ret = usbmuxd_disconnect(client->sfd);
}
free(client);
@@ -197,11 +199,16 @@ iphone_error_t iphone_lckd_recv(iphone_lckd_client_t client, plist_t * plist)
uint32_t datalen = 0, bytes = 0, received_bytes = 0;
if (!client->in_SSL)
- ret = iphone_mux_recv(client->connection, (char *) &datalen, sizeof(datalen), &bytes);
+ ret = usbmuxd_recv(client->sfd, (char *) &datalen, sizeof(datalen), &bytes);
else {
- bytes = gnutls_record_recv(*client->ssl_session, &datalen, sizeof(datalen));
- if (bytes > 0)
+ ssize_t res = gnutls_record_recv(*client->ssl_session, &datalen, sizeof(datalen));
+ if (res < 0) {
+ log_dbg_msg(DBGMASK_LOCKDOWND, "gnutls_record_recv: Error occured: %s\n", gnutls_strerror(res));
+ return IPHONE_E_SSL_ERROR;
+ } else {
+ bytes = res;
ret = IPHONE_E_SUCCESS;
+ }
}
datalen = ntohl(datalen);
@@ -210,13 +217,18 @@ iphone_error_t iphone_lckd_recv(iphone_lckd_client_t client, plist_t * plist)
if (!client->in_SSL) {
/* fill buffer and request more packets if needed */
while ((received_bytes < datalen) && (ret == IPHONE_E_SUCCESS)) {
- ret = iphone_mux_recv(client->connection, receive + received_bytes, datalen - received_bytes, &bytes);
+ ret = usbmuxd_recv(client->sfd, receive + received_bytes, datalen - received_bytes, &bytes);
received_bytes += bytes;
}
} else {
- received_bytes = gnutls_record_recv(*client->ssl_session, receive, datalen);
- if (received_bytes > 0)
+ ssize_t res = gnutls_record_recv(*client->ssl_session, receive, datalen);
+ if (res < 0) {
+ log_dbg_msg(DBGMASK_LOCKDOWND, "gnutls_record_recv: Error occured: %s\n", gnutls_strerror(res));
+ ret = IPHONE_E_SSL_ERROR;
+ } else {
+ received_bytes = res;
ret = IPHONE_E_SUCCESS;
+ }
}
if (ret != IPHONE_E_SUCCESS) {
@@ -224,7 +236,7 @@ iphone_error_t iphone_lckd_recv(iphone_lckd_client_t client, plist_t * plist)
return ret;
}
- if (received_bytes <= 0) {
+ if ((ssize_t)received_bytes <= 0) {
free(receive);
return IPHONE_E_NOT_ENOUGH_DATA;
}
@@ -271,12 +283,22 @@ iphone_error_t iphone_lckd_send(iphone_lckd_client_t client, plist_t plist)
log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_send(): made the query, sending it along\n");
if (!client->in_SSL)
- ret = iphone_mux_send(client->connection, real_query, ntohl(length) + sizeof(length), &bytes);
+ ret = usbmuxd_send(client->sfd, real_query, ntohl(length) + sizeof(length), (uint32_t*)&bytes);
else {
- gnutls_record_send(*client->ssl_session, real_query, ntohl(length) + sizeof(length));
- ret = IPHONE_E_SUCCESS;
+ ssize_t res = gnutls_record_send(*client->ssl_session, real_query, ntohl(length) + sizeof(length));
+ if (res < 0) {
+ log_dbg_msg(DBGMASK_LOCKDOWND, "gnutls_record_send: Error occured: %s\n", gnutls_strerror(res));
+ ret = IPHONE_E_SSL_ERROR;
+ } else {
+ bytes = res;
+ ret = IPHONE_E_SUCCESS;
+ }
+ }
+ if (ret == IPHONE_E_SUCCESS) {
+ log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_send(): sent it!\n");
+ } else {
+ log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_send(): sending failed!\n");
}
- log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_send(): sent it!\n");
free(real_query);
return ret;
@@ -425,7 +447,7 @@ iphone_error_t lockdownd_generic_get_value(iphone_lckd_client_t control, const c
char *value_value = NULL;
plist_get_string_val(value_value_node, &value_value);
- value->data = value_value;
+ value->data = (unsigned char*)value_value;
value->size = strlen(value_value);
ret = IPHONE_E_SUCCESS;
}
@@ -435,7 +457,7 @@ iphone_error_t lockdownd_generic_get_value(iphone_lckd_client_t control, const c
uint64_t size = 0;
plist_get_data_val(value_value_node, &value_value, &size);
- value->data = value_value;
+ value->data = (unsigned char*)value_value;
value->size = size;
ret = IPHONE_E_SUCCESS;
}
@@ -457,7 +479,7 @@ iphone_error_t lockdownd_get_device_uid(iphone_lckd_client_t control, char **uid
{
gnutls_datum_t temp = { NULL, 0 };
iphone_error_t ret = lockdownd_generic_get_value(control, "Key", "UniqueDeviceID", &temp);
- *uid = temp.data;
+ *uid = (char*)temp.data;
return ret;
}
@@ -465,7 +487,7 @@ iphone_error_t lockdownd_get_device_uid(iphone_lckd_client_t control, char **uid
*
* @note You most likely want lockdownd_init unless you are doing something special.
*
- * @return 1 on success and 0 on failure.
+ * @return IPHONE_E_SUCCESS on succes or an error value < 0 on failure.
*/
iphone_error_t lockdownd_get_device_public_key(iphone_lckd_client_t control, gnutls_datum_t * public_key)
{
@@ -733,14 +755,14 @@ iphone_error_t lockdownd_gen_pair_cert(gnutls_datum_t public_key, gnutls_datum_t
if (ASN1_SUCCESS == asn1_der_decoding(&asn1_pub_key, der_pub_key.data, der_pub_key.size, NULL)) {
/* get size to read */
- int ret1 = asn1_read_value(asn1_pub_key, "modulus", NULL, &modulus.size);
- int ret2 = asn1_read_value(asn1_pub_key, "publicExponent", NULL, &exponent.size);
+ int ret1 = asn1_read_value(asn1_pub_key, "modulus", NULL, (int*)&modulus.size);
+ int ret2 = asn1_read_value(asn1_pub_key, "publicExponent", NULL, (int*)&exponent.size);
modulus.data = gnutls_malloc(modulus.size);
exponent.data = gnutls_malloc(exponent.size);
- ret1 = asn1_read_value(asn1_pub_key, "modulus", modulus.data, &modulus.size);
- ret2 = asn1_read_value(asn1_pub_key, "publicExponent", exponent.data, &exponent.size);
+ ret1 = asn1_read_value(asn1_pub_key, "modulus", modulus.data, (int*)&modulus.size);
+ ret2 = asn1_read_value(asn1_pub_key, "publicExponent", exponent.data, (int*)&exponent.size);
if (ASN1_SUCCESS == ret1 && ASN1_SUCCESS == ret2)
ret = IPHONE_E_SUCCESS;
}
@@ -755,7 +777,7 @@ iphone_error_t lockdownd_gen_pair_cert(gnutls_datum_t public_key, gnutls_datum_t
if (IPHONE_E_SUCCESS == ret && 0 != modulus.size && 0 != exponent.size) {
gnutls_global_init();
- gnutls_datum_t essentially_null = { strdup("abababababababab"), strlen("abababababababab") };
+ gnutls_datum_t essentially_null = { (unsigned char*)strdup("abababababababab"), strlen("abababababababab") };
gnutls_x509_privkey_t fake_privkey, root_privkey, host_privkey;
gnutls_x509_crt_t dev_cert, root_cert, host_cert;
@@ -1021,12 +1043,12 @@ iphone_error_t lockdownd_start_SSL_session(iphone_lckd_client_t control, const c
*/
ssize_t lockdownd_secuwrite(gnutls_transport_ptr_t transport, char *buffer, size_t length)
{
- int bytes = 0;
+ uint32_t bytes = 0;
iphone_lckd_client_t control;
control = (iphone_lckd_client_t) transport;
log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_secuwrite() called\n");
log_dbg_msg(DBGMASK_LOCKDOWND, "pre-send\nlength = %zi\n", length);
- iphone_mux_send(control->connection, buffer, length, &bytes);
+ usbmuxd_send(control->sfd, buffer, length, &bytes);
log_dbg_msg(DBGMASK_LOCKDOWND, "post-send\nsent %i bytes\n", bytes);
dump_debug_buffer("sslpacketwrite.out", buffer, length);
@@ -1044,7 +1066,7 @@ ssize_t lockdownd_secuwrite(gnutls_transport_ptr_t transport, char *buffer, size
ssize_t lockdownd_securead(gnutls_transport_ptr_t transport, char *buffer, size_t length)
{
int bytes = 0, pos_start_fill = 0;
- int tbytes = 0;
+ size_t tbytes = 0;
int this_len = length;
iphone_error_t res;
iphone_lckd_client_t control;
@@ -1059,19 +1081,12 @@ ssize_t lockdownd_securead(gnutls_transport_ptr_t transport, char *buffer, size_
// repeat until we have the full data or an error occurs.
do {
- if ((res = iphone_mux_recv(control->connection, recv_buffer, this_len, &bytes)) != IPHONE_E_SUCCESS) {
+ if ((res = usbmuxd_recv(control->sfd, recv_buffer, this_len, (uint32_t*)&bytes)) != IPHONE_E_SUCCESS) {
log_debug_msg("%s: ERROR: iphone_mux_recv returned %d\n", __func__, res);
return res;
}
log_debug_msg("post-read\nwe got %i bytes\n", bytes);
- if (bytes < 0) {
- log_debug_msg("lockdownd_securead(): uh oh\n");
- log_debug_msg
- ("I believe what we have here is a failure to communicate... libusb says %s but strerror says %s\n",
- usb_strerror(), strerror(errno));
- return bytes; // + 28; // an errno
- }
// increase read count
tbytes += bytes;
diff --git a/src/lockdown.h b/src/lockdown.h
index 7485006..1f9d84c 100644
--- a/src/lockdown.h
+++ b/src/lockdown.h
@@ -22,8 +22,6 @@
#ifndef LOCKDOWND_H
#define LOCKDOWND_H
-#include "usbmux.h"
-
#include <gnutls/gnutls.h>
#include <string.h>
#include <libiphone/libiphone.h>
@@ -32,7 +30,7 @@
struct iphone_lckd_client_int {
- iphone_umux_client_t connection;
+ int sfd;
gnutls_session_t *ssl_session;
int in_SSL;
char session_id[40];
diff --git a/src/usbmux.c b/src/usbmux.c
deleted file mode 100644
index 7d74b4b..0000000
--- a/src/usbmux.c
+++ /dev/null
@@ -1,410 +0,0 @@
-/*
- * usbmux.c
- * Interprets the usb multiplexing protocol used by the iPhone.
- *
- * Copyright (c) 2008 Zach C. All Rights Reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <sys/types.h>
-#include <arpa/inet.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "usbmux.h"
-#include "utils.h"
-
-static iphone_umux_client_t *connlist = NULL;
-static int clients = 0;
-
-/** Creates a USBMux packet for the given set of ports.
- *
- * @param s_port The source port for the connection.
- * @param d_port The destination port for the connection.
- *
- * @return A USBMux packet
- */
-usbmux_tcp_header *new_mux_packet(uint16_t s_port, uint16_t d_port)
-{
- usbmux_tcp_header *conn = (usbmux_tcp_header *) malloc(sizeof(usbmux_tcp_header));
- conn->type = htonl(6);
- conn->length = 28;
- conn->sport = htons(s_port);
- conn->dport = htons(d_port);
- conn->scnt = 0;
- conn->ocnt = 0;
- conn->offset = 0x50;
- conn->window = htons(0x0200);
- conn->nullnull = 0x0000;
- conn->length16 = 28;
- return conn;
-}
-
-/** Creates a USBMux header containing version information
- *
- * @return A USBMux header
- */
-usbmux_version_header *version_header(void)
-{
- usbmux_version_header *version = (usbmux_version_header *) malloc(sizeof(usbmux_version_header));
- version->type = 0;
- version->length = htonl(20);
- version->major = htonl(1);
- version->minor = 0;
- version->allnull = 0;
- return version;
-}
-
-
-// Maintenance functions.
-
-/** Removes a connection from the list of connections made.
- * The list of connections is necessary for buffering.
- *
- * @param connection The connection to delete from the tracking list.
- */
-static void delete_connection(iphone_umux_client_t connection)
-{
- iphone_umux_client_t *newlist = (iphone_umux_client_t *) malloc(sizeof(iphone_umux_client_t) * (clients - 1));
- int i = 0, j = 0;
- for (i = 0; i < clients; i++) {
- if (connlist[i] == connection)
- continue;
- else {
- newlist[j] = connlist[i];
- j++;
- }
- }
- free(connlist);
- connlist = newlist;
- clients--;
- if (connection->recv_buffer)
- free(connection->recv_buffer);
- if (connection->header)
- free(connection->header);
- connection->r_len = 0;
- free(connection);
-}
-
-/** Adds a connection to the list of connections made.
- * The connection list is necessary for buffering.
- *
- * @param connection The connection to add to the global list of connections.
- */
-
-static void add_connection(iphone_umux_client_t connection)
-{
- iphone_umux_client_t *newlist =
- (iphone_umux_client_t *) realloc(connlist, sizeof(iphone_umux_client_t) * (clients + 1));
- newlist[clients] = connection;
- connlist = newlist;
- clients++;
-}
-
-/** Initializes a connection on phone, with source port s_port and destination port d_port
- *
- * @param device The iPhone to initialize a connection on.
- * @param src_port The source port
- * @param dst_port The destination port -- 0xf27e for lockdownd.
- * @param client A mux TCP header for the connection which is used for tracking and data transfer.
- * @return IPHONE_E_SUCCESS on success, an error code otherwise.
- */
-iphone_error_t iphone_mux_new_client(iphone_device_t device, uint16_t src_port, uint16_t dst_port,
- iphone_umux_client_t * client)
-{
- if (!device || !src_port || !dst_port)
- return IPHONE_E_INVALID_ARG;
-
- int bytes = 0;
- // Initialize connection stuff
- iphone_umux_client_t new_connection = (iphone_umux_client_t) malloc(sizeof(struct iphone_umux_client_int));
- new_connection->header = new_mux_packet(src_port, dst_port);
-
- // blargg
- if (new_connection && new_connection->header) {
- new_connection->header->tcp_flags = 0x02;
- new_connection->header->length = htonl(new_connection->header->length);
- new_connection->header->length16 = htons(new_connection->header->length16);
-
- if (send_to_phone(device, (char *) new_connection->header, sizeof(usbmux_tcp_header)) >= 0) {
- usbmux_tcp_header *response;
- response = (usbmux_tcp_header *) malloc(sizeof(usbmux_tcp_header));
- bytes = recv_from_phone(device, (char *) response, sizeof(*response), 3500);
- if (response->tcp_flags != 0x12) {
- free(response);
- return IPHONE_E_UNKNOWN_ERROR;
- } else {
- free(response);
-
- log_debug_msg("mux_connect: connection success\n");
- new_connection->header->tcp_flags = 0x10;
- new_connection->header->scnt = 1;
- new_connection->header->ocnt = 1;
- new_connection->phone = device;
- new_connection->recv_buffer = NULL;
- new_connection->r_len = 0;
- add_connection(new_connection);
- *client = new_connection;
- return IPHONE_E_SUCCESS;
- }
- } else {
- return IPHONE_E_NOT_ENOUGH_DATA;
- }
- }
- // if we get to this point it's probably bad
- return IPHONE_E_UNKNOWN_ERROR;
-}
-
-/** Cleans up the given USBMux connection.
- * @note Once a connection is closed it may not be used again.
- *
- * @param connection The connection to close.
- *
- * @return IPHONE_E_SUCCESS on success.
- */
-iphone_error_t iphone_mux_free_client(iphone_umux_client_t client)
-{
- if (!client || !client->phone)
- return IPHONE_E_INVALID_ARG;
-
- client->header->tcp_flags = 0x04;
- client->header->length = htonl(0x1C);
- client->header->scnt = htonl(client->header->scnt);
- client->header->ocnt = htonl(client->header->ocnt);
- client->header->window = 0;
- client->header->length16 = htons(0x1C);
- int bytes = 0;
-
- bytes = usb_bulk_write(client->phone->device, BULKOUT, (char *) client->header, sizeof(usbmux_tcp_header), 800);
- if (bytes < 0)
- log_debug_msg("iphone_muxèfree_client(): when writing, libusb gave me the error: %s\n", usb_strerror());
-
- bytes = usb_bulk_read(client->phone->device, BULKIN, (char *) client->header, sizeof(usbmux_tcp_header), 800);
- if (bytes < 0)
- log_debug_msg("get_iPhone(): when reading, libusb gave me the error: %s\n", usb_strerror());
-
- delete_connection(client);
-
- return IPHONE_E_SUCCESS;
-}
-
-
-/** Sends the given data over the selected connection.
- *
- * @param phone The iPhone to send to.
- * @param client The client we're sending data on.
- * @param data A pointer to the data to send.
- * @param datalen How much data we're sending.
- * @param sent_bytes The number of bytes sent, minus the header (28)
- *
- * @return IPHONE_E_SUCCESS on success.
- */
-
-iphone_error_t iphone_mux_send(iphone_umux_client_t client, const char *data, uint32_t datalen, uint32_t * sent_bytes)
-{
- if (!client->phone || !client || !data || datalen == 0 || !sent_bytes)
- return IPHONE_E_INVALID_ARG;
- // client->scnt and client->ocnt should already be in host notation...
- // we don't need to change them juuuust yet.
- *sent_bytes = 0;
- log_debug_msg("mux_send(): client wants to send %i bytes\n", datalen);
- char *buffer = (char *) malloc(sizeof(usbmux_tcp_header) + datalen + 2); // allow 2 bytes of safety padding
- // Set the length and pre-emptively htonl/htons it
- client->header->length = htonl(sizeof(usbmux_tcp_header) + datalen);
- client->header->length16 = htons(sizeof(usbmux_tcp_header) + datalen);
-
- // Put scnt and ocnt into big-endian notation
- client->header->scnt = htonl(client->header->scnt);
- client->header->ocnt = htonl(client->header->ocnt);
- // Concatenation of stuff in the buffer.
- memcpy(buffer, client->header, sizeof(usbmux_tcp_header));
- memcpy(buffer + sizeof(usbmux_tcp_header), data, datalen);
-
- // We have a buffer full of data, we should now send it to the phone.
- log_debug_msg("actually sending %zi bytes of data at %p\n", sizeof(usbmux_tcp_header) + datalen, buffer);
-
-
- *sent_bytes = send_to_phone(client->phone, buffer, sizeof(usbmux_tcp_header) + datalen);
- log_debug_msg("mux_send: sent %i bytes!\n", *sent_bytes);
- // Now that we've sent it off, we can clean up after our sloppy selves.
- dump_debug_buffer("packet", buffer, *sent_bytes);
- if (buffer)
- free(buffer);
- // Re-calculate scnt and ocnt
- client->header->scnt = ntohl(client->header->scnt) + datalen;
- client->header->ocnt = ntohl(client->header->ocnt);
-
- // Revert lengths
- client->header->length = ntohl(client->header->length);
- client->header->length16 = ntohs(client->header->length16);
-
- // Now return the bytes.
- if (*sent_bytes < sizeof(usbmux_tcp_header) + datalen) {
- *sent_bytes = 0;
- return IPHONE_E_NOT_ENOUGH_DATA;
- } else {
- *sent_bytes = *sent_bytes - 28; // actual length sent. :/
- }
-
- return IPHONE_E_SUCCESS;
-}
-
-/** This is a higher-level USBMuxTCP-like function
- *
- * @param connection The connection to receive data on.
- * @param data Where to put the data we receive.
- * @param datalen How much data to read.
- * @param recv_bytes Pointer to a uint32_t that will be set
- * to the number of bytes received.
- * @param timeout How many milliseconds to wait for data.
- *
- * @return IPHONE_E_SUCCESS on success, or and error value.
- */
-iphone_error_t iphone_mux_recv_timeout(iphone_umux_client_t client, char *data, uint32_t datalen, uint32_t * recv_bytes, int timeout)
-{
-
- if (!client || !data || datalen == 0 || !recv_bytes)
- return IPHONE_E_INVALID_ARG;
- /*
- * Order of operation:
- * 1.) Check if the client has a pre-received buffer.
- * 2.) If so, fill data with the buffer, as much as needed.
- * a.) Return quickly if the buffer has enough
- * b.) If the buffer is only part of the datalen, get the rest of datalen (and if we can't, just return)
- * 3.) If not, receive directly from the phone.
- * a.) Check incoming packet's ports. If proper, follow proper buffering and receiving operation.
- * b.) If not, find the client the ports belong to and fill that client's buffer, then return mux_recv with the same args to try again.
- */
- log_debug_msg("mux_recv: datalen == %i\n", datalen);
- int bytes = 0, i = 0, complex = 0, offset = 0;
- *recv_bytes = 0;
- char *buffer = NULL;
- usbmux_tcp_header *header = NULL;
-
- if (client->recv_buffer) {
- if (client->r_len >= datalen) {
- memcpy(data, client->recv_buffer, datalen);
- if (client->r_len == datalen) {
- // reset everything
- free(client->recv_buffer);
- client->r_len = 0;
- client->recv_buffer = NULL;
- } else {
- buffer = (char *) malloc(sizeof(char) * (client->r_len - datalen));
- memcpy(buffer, client->recv_buffer + datalen, (client->r_len - datalen));
- client->r_len -= datalen;
- free(client->recv_buffer);
- client->recv_buffer = buffer;
- }
-
- // Since we were able to fill the data straight from our buffer, we can just return datalen. See 2a above.
- *recv_bytes = datalen;
- return IPHONE_E_SUCCESS;
- } else {
- memcpy(data, client->recv_buffer, client->r_len);
- free(client->recv_buffer); // don't need to deal with anymore, but...
- client->recv_buffer = NULL;
- offset = client->r_len; // see #2b, above
- client->r_len = 0;
- }
- } // End of what to do if we have a pre-buffer. See #1 and #2 above.
-
- buffer = (char *) malloc(sizeof(char) * 131072); // make sure we get enough ;)
-
- // See #3.
- bytes = recv_from_phone(client->phone, buffer, 131072, timeout);
- if (bytes < 28) {
- free(buffer);
- log_debug_msg("mux_recv: Did not even get the header.\n");
- return IPHONE_E_NOT_ENOUGH_DATA;
- }
-
- header = (usbmux_tcp_header *) buffer;
- if (header->sport != client->header->dport || header->dport != client->header->sport) {
- // Ooooops -- we got someone else's packet.
- // We gotta stick it in their buffer. (Take that any old way you want ;) )
- for (i = 0; i < clients; i++) {
- if (connlist[i]->header->sport == header->dport && connlist[i]->header->dport == header->sport) {
- // we have a winner.
- char *nfb = (char *) malloc(sizeof(char) * (connlist[i]->r_len + (bytes - 28)));
- if (connlist[i]->recv_buffer && connlist[i]->r_len) {
- memcpy(nfb, connlist[i]->recv_buffer, connlist[i]->r_len);
- free(connlist[i]->recv_buffer);
- }
- connlist[i]->r_len += bytes - 28;
- //connlist[i]->recv_buffer = (char*)realloc(connlist[i]->recv_buffer, sizeof(char) * client->r_len); // grow their buffer
- connlist[i]->recv_buffer = nfb;
- nfb = NULL; // A cookie for you if you can guess what "nfb" means.
- complex = connlist[i]->r_len - (bytes - 28);
- memcpy(connlist[i]->recv_buffer + complex, buffer + 28, bytes - 28); // paste into their buffer
- connlist[i]->header->ocnt += bytes - 28;
- }
- }
- // If it wasn't ours, it's been handled by this point... or forgotten.
- // Free our buffer and continue.
- free(buffer);
- buffer = NULL;
- return iphone_mux_recv(client, data, datalen, recv_bytes); // recurse back in to try again
- }
- // The packet was absolutely meant for us if it hits this point.
- // The pre-buffer has been taken care of, so, again, if we're at this point we have to read from the phone.
-
- if ((bytes - 28) > datalen) {
- // Copy what we need into the data, buffer the rest because we can.
- memcpy(data + offset, buffer + 28, datalen); // data+offset: see #2b, above
- complex = client->r_len + ((bytes - 28) - datalen);
- client->recv_buffer = (char *) realloc(client->recv_buffer, (sizeof(char) * complex));
- client->r_len = complex;
- complex = client->r_len - ((bytes - 28) - datalen);
- memcpy(client->recv_buffer + complex, buffer + 28 + datalen, (bytes - 28) - datalen);
- free(buffer);
- client->header->ocnt += bytes - 28;
- *recv_bytes = datalen;
- return IPHONE_E_SUCCESS;
- } else {
- // Fill the data with what we have, and just return.
- memcpy(data + offset, buffer + 28, bytes - 28); // data+offset: see #2b, above
- client->header->ocnt += bytes - 28;
- free(buffer);
- *recv_bytes = bytes - 28;
- return IPHONE_E_SUCCESS;
- }
-
- // If we get to this point, 'tis probably bad.
- log_debug_msg("mux_recv: Heisenbug: bytes and datalen not matching up\n");
- return IPHONE_E_UNKNOWN_ERROR;
-}
-
-/**
- * This function is just like 'iphone_mux_recv_timeout' but you do not need
- * to specify a timeout. It simply calls iphone_mux_recv_timeout with a
- * timeout value of 3500 milliseconds.
- *
- * @param connection The connection to receive data on.
- * @param data Where to put the data we receive.
- * @param datalen How much data to read.
- * @param recv_bytes Pointer to a uint32_t that will be set
- * to the number of bytes received.
- *
- * @return The return value of iphone_mux_recv_timeout.
- *
- * @see iphone_mux_recv_timeout
- */
-iphone_error_t iphone_mux_recv(iphone_umux_client_t client, char *data, uint32_t datalen, uint32_t * recv_bytes)
-{
- return iphone_mux_recv_timeout(client, data, datalen, recv_bytes, 3500);
-}
diff --git a/src/usbmux.h b/src/usbmux.h
deleted file mode 100644
index bea83f7..0000000
--- a/src/usbmux.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * usbmux.h
- * Defines structures and variables pertaining to the usb multiplexing.
- *
- * Copyright (c) 2008 Zach C. All Rights Reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <sys/types.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include "libiphone/libiphone.h"
-
-#ifndef USBMUX_H
-#define USBMUX_H
-
-#ifndef IPHONE_H
-#include "iphone.h"
-#endif
-
-typedef struct {
- uint32_t type, length;
- uint16_t sport, dport;
- uint32_t scnt, ocnt;
- uint8_t offset, tcp_flags;
- uint16_t window, nullnull, length16;
-} usbmux_tcp_header;
-
-struct iphone_umux_client_int {
- usbmux_tcp_header *header;
- iphone_device_t phone;
- char *recv_buffer;
- int r_len;
-};
-
-usbmux_tcp_header *new_mux_packet(uint16_t s_port, uint16_t d_port);
-
-typedef struct {
- uint32_t type, length, major, minor, allnull;
-} usbmux_version_header;
-
-usbmux_version_header *version_header(void);
-
-
-#endif