summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/libiphone/libiphone.h44
-rw-r--r--src/AFC.c40
-rw-r--r--src/AFC.h2
-rw-r--r--src/MobileSync.c14
-rw-r--r--src/MobileSync.h2
-rw-r--r--src/NotificationProxy.c28
-rw-r--r--src/NotificationProxy.h2
-rw-r--r--src/iphone.c371
-rw-r--r--src/iphone.h22
-rw-r--r--src/lockdown.c26
-rw-r--r--src/lockdown.h2
-rw-r--r--src/userpref.c6
-rw-r--r--src/userpref.h4
-rw-r--r--tools/iphone_id.c9
-rw-r--r--tools/iphoneinfo.c4
-rw-r--r--tools/iphonesyslog.c16
16 files changed, 437 insertions, 155 deletions
diff --git a/include/libiphone/libiphone.h b/include/libiphone/libiphone.h
index 1451f15..77860f8 100644
--- a/include/libiphone/libiphone.h
+++ b/include/libiphone/libiphone.h
@@ -31,7 +31,6 @@ extern "C" {
#include <sys/types.h>
#include <sys/stat.h>
#include <plist/plist.h>
-#include <usbmuxd.h>
/* Error Codes */
#define IPHONE_E_SUCCESS 0
@@ -46,19 +45,56 @@ typedef int16_t iphone_error_t;
struct iphone_device_int;
typedef struct iphone_device_int *iphone_device_t;
+struct iphone_connection_int;
+typedef struct iphone_connection_int *iphone_connection_t;
+
/* Debugging */
#define DBGMASK_ALL 0xFFFF
#define DBGMASK_NONE 0x0000
#define DBGMASK_LOCKDOWND (1 << 1)
#define DBGMASK_MOBILESYNC (1 << 2)
+/* generic */
void iphone_set_debug_mask(uint16_t mask);
void iphone_set_debug_level(int level);
-/* Interface */
-iphone_error_t iphone_get_device(iphone_device_t *device);
-iphone_error_t iphone_get_device_by_uuid(iphone_device_t *device, const char *uuid);
+/* discovery (events/asynchronous) */
+// event type
+enum iphone_event_type {
+ IPHONE_DEVICE_ADD = 1,
+ IPHONE_DEVICE_REMOVE
+};
+
+// event data structure
+typedef struct {
+ enum iphone_event_type event;
+ const char *uuid;
+ int conn_type;
+} iphone_event_t;
+
+// event callback function prototype
+typedef void (*iphone_event_cb_t) (const iphone_event_t *event, void *user_data);
+
+// functions
+iphone_error_t iphone_event_subscribe(iphone_event_cb_t callback, void *user_data);
+iphone_error_t iphone_event_unsubscribe();
+
+/* discovery (synchronous) */
+iphone_error_t iphone_get_device_list(char ***devices, int *count);
+iphone_error_t iphone_free_device_list(char **devices);
+
+/* device structure creation and destruction */
+iphone_error_t iphone_device_new(iphone_device_t *device, const char *uuid);
iphone_error_t iphone_device_free(iphone_device_t device);
+
+/* connection/disconnection and communication */
+iphone_error_t iphone_device_connect(iphone_device_t device, uint16_t dst_port, iphone_connection_t *connection);
+iphone_error_t iphone_device_disconnect(iphone_connection_t connection);
+iphone_error_t iphone_device_send(iphone_connection_t connection, const char *data, uint32_t len, uint32_t *sent_bytes);
+iphone_error_t iphone_device_recv_timeout(iphone_connection_t connection, char *data, uint32_t len, uint32_t *recv_bytes, unsigned int timeout);
+iphone_error_t iphone_device_recv(iphone_connection_t connection, char *data, uint32_t len, uint32_t *recv_bytes);
+
+/* misc */
iphone_error_t iphone_device_get_handle(iphone_device_t device, uint32_t *handle);
iphone_error_t iphone_device_get_uuid(iphone_device_t device, char **uuid);
diff --git a/src/AFC.c b/src/AFC.c
index b27080a..ba436e7 100644
--- a/src/AFC.c
+++ b/src/AFC.c
@@ -68,18 +68,18 @@ afc_error_t afc_client_new(iphone_device_t device, int dst_port, afc_client_t *
return AFC_E_INVALID_ARGUMENT;
/* attempt connection */
- int sfd = usbmuxd_connect(device->handle, dst_port);
- if (sfd < 0) {
+ iphone_connection_t connection = NULL;
+ if (iphone_device_connect(device, dst_port, &connection) != IPHONE_E_SUCCESS) {
return AFC_E_MUX_ERROR;
}
afc_client_t client_loc = (afc_client_t) malloc(sizeof(struct afc_client_int));
- client_loc->sfd = sfd;
+ client_loc->connection = connection;
/* allocate a packet */
client_loc->afc_packet = (AFCPacket *) malloc(sizeof(AFCPacket));
if (!client_loc->afc_packet) {
- usbmuxd_disconnect(client_loc->sfd);
+ iphone_device_disconnect(client_loc->connection);
free(client_loc);
return AFC_E_NO_MEM;
}
@@ -102,10 +102,10 @@ afc_error_t afc_client_new(iphone_device_t device, int dst_port, afc_client_t *
*/
afc_error_t afc_client_free(afc_client_t client)
{
- if (!client || client->sfd < 0 || !client->afc_packet)
+ if (!client || !client->connection || !client->afc_packet)
return AFC_E_INVALID_ARGUMENT;
- usbmuxd_disconnect(client->sfd);
+ iphone_device_disconnect(client->connection);
free(client->afc_packet);
if (client->mutex) {
g_mutex_free(client->mutex);
@@ -132,7 +132,7 @@ static int afc_dispatch_packet(afc_client_t client, const char *data, uint64_t l
int bytes = 0, offset = 0;
char *buffer;
- if (!client || client->sfd < 0 || !client->afc_packet)
+ if (!client || !client->connection || !client->afc_packet)
return 0;
if (!data || !length)
@@ -164,7 +164,7 @@ static int afc_dispatch_packet(afc_client_t client, const char *data, uint64_t l
return -1;
}
memcpy(buffer + sizeof(AFCPacket), data, offset);
- usbmuxd_send(client->sfd, buffer, client->afc_packet->this_length, (uint32_t*)&bytes);
+ iphone_device_send(client->connection, buffer, client->afc_packet->this_length, (uint32_t*)&bytes);
free(buffer);
if (bytes <= 0) {
return bytes;
@@ -175,7 +175,7 @@ static int afc_dispatch_packet(afc_client_t client, const char *data, uint64_t l
log_debug_msg("%s: Buffer: \n", __func__);
log_debug_buffer(data + offset, length - offset);
- usbmuxd_send(client->sfd, data + offset, length - offset, (uint32_t*)&bytes);
+ iphone_device_send(client->connection, data + offset, length - offset, (uint32_t*)&bytes);
return bytes;
} else {
log_debug_msg("%s: doin things the old way\n", __func__);
@@ -188,7 +188,7 @@ static int afc_dispatch_packet(afc_client_t client, const char *data, uint64_t l
}
log_debug_buffer(buffer, client->afc_packet->this_length);
log_debug_msg("\n");
- usbmuxd_send(client->sfd, buffer, client->afc_packet->this_length, (uint32_t*)&bytes);
+ iphone_device_send(client->connection, buffer, client->afc_packet->this_length, (uint32_t*)&bytes);
if (buffer) {
free(buffer);
@@ -220,7 +220,7 @@ static afc_error_t afc_receive_data(afc_client_t client, char **dump_here, int *
*bytes = 0;
/* first, read the AFC header */
- usbmuxd_recv(client->sfd, (char*)&header, sizeof(AFCPacket), (uint32_t*)bytes);
+ iphone_device_recv(client->connection, (char*)&header, sizeof(AFCPacket), (uint32_t*)bytes);
if (*bytes <= 0) {
log_debug_msg("%s: Just didn't get enough.\n", __func__);
*dump_here = NULL;
@@ -273,7 +273,7 @@ static afc_error_t afc_receive_data(afc_client_t client, char **dump_here, int *
*dump_here = (char*)malloc(entire_len);
if (this_len > 0) {
- usbmuxd_recv(client->sfd, *dump_here, this_len, (uint32_t*)bytes);
+ iphone_device_recv(client->connection, *dump_here, this_len, (uint32_t*)bytes);
if (*bytes <= 0) {
free(*dump_here);
*dump_here = NULL;
@@ -291,7 +291,7 @@ static afc_error_t afc_receive_data(afc_client_t client, char **dump_here, int *
if (entire_len > this_len) {
while (current_count < entire_len) {
- usbmuxd_recv(client->sfd, (*dump_here)+current_count, entire_len - current_count, (uint32_t*)bytes);
+ iphone_device_recv(client->connection, (*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;
@@ -517,7 +517,7 @@ afc_error_t afc_remove_path(afc_client_t client, const char *path)
int bytes;
afc_error_t ret = AFC_E_UNKNOWN_ERROR;
- if (!client || !path || !client->afc_packet || client->sfd < 0)
+ if (!client || !path || !client->afc_packet || !client->connection)
return AFC_E_INVALID_ARGUMENT;
afc_lock(client);
@@ -560,7 +560,7 @@ afc_error_t afc_rename_path(afc_client_t client, const char *from, const char *t
int bytes = 0;
afc_error_t ret = AFC_E_UNKNOWN_ERROR;
- if (!client || !from || !to || !client->afc_packet || client->sfd < 0)
+ if (!client || !from || !to || !client->afc_packet || !client->connection)
return AFC_E_INVALID_ARGUMENT;
afc_lock(client);
@@ -687,7 +687,7 @@ afc_file_open(afc_client_t client, const char *filename,
// set handle to 0 so in case an error occurs, the handle is invalid
*handle = 0;
- if (!client || client->sfd < 0|| !client->afc_packet)
+ if (!client || !client->connection || !client->afc_packet)
return AFC_E_INVALID_ARGUMENT;
afc_lock(client);
@@ -742,7 +742,7 @@ afc_file_read(afc_client_t client, uint64_t handle, char *data, int length, uint
const int MAXIMUM_READ_SIZE = 1 << 16;
afc_error_t ret = AFC_E_SUCCESS;
- if (!client || !client->afc_packet || client->sfd < 0 || handle == 0)
+ if (!client || !client->afc_packet || !client->connection || handle == 0)
return AFC_E_INVALID_ARGUMENT;
log_debug_msg("%s: called for length %i\n", __func__, length);
@@ -819,7 +819,7 @@ afc_file_write(afc_client_t client, uint64_t handle,
char *out_buffer = NULL;
afc_error_t ret = AFC_E_SUCCESS;
- if (!client || !client->afc_packet || client->sfd < 0 || !bytes || (handle == 0))
+ if (!client || !client->afc_packet || !client->connection || !bytes || (handle == 0))
return AFC_E_INVALID_ARGUMENT;
afc_lock(client);
@@ -1139,7 +1139,7 @@ afc_error_t afc_truncate(afc_client_t client, const char *path, off_t newsize)
uint64_t size_requested = newsize;
afc_error_t ret = AFC_E_UNKNOWN_ERROR;
- if (!client || !path || !client->afc_packet || client->sfd < 0)
+ if (!client || !path || !client->afc_packet || !client->connection)
return AFC_E_INVALID_ARGUMENT;
afc_lock(client);
@@ -1183,7 +1183,7 @@ afc_error_t afc_make_link(afc_client_t client, afc_link_type_t linktype, const c
uint64_t type = linktype;
afc_error_t ret = AFC_E_UNKNOWN_ERROR;
- if (!client || !target || !linkname || !client->afc_packet || client->sfd < 0)
+ if (!client || !target || !linkname || !client->afc_packet || !client->connection)
return AFC_E_INVALID_ARGUMENT;
afc_lock(client);
diff --git a/src/AFC.h b/src/AFC.h
index 7ed6bd8..685d7b5 100644
--- a/src/AFC.h
+++ b/src/AFC.h
@@ -46,7 +46,7 @@ typedef struct __AFCToken {
} AFCToken;
struct afc_client_int {
- int sfd;
+ iphone_connection_t connection;
AFCPacket *afc_packet;
int file_handle;
int lock;
diff --git a/src/MobileSync.c b/src/MobileSync.c
index 4463251..8a7d724 100644
--- a/src/MobileSync.c
+++ b/src/MobileSync.c
@@ -40,13 +40,13 @@ mobilesync_error_t mobilesync_client_new(iphone_device_t device, int dst_port,
mobilesync_error_t ret = MOBILESYNC_E_UNKNOWN_ERROR;
/* Attempt connection */
- int sfd = usbmuxd_connect(device->handle, dst_port);
- if (sfd < 0) {
+ iphone_connection_t connection = NULL;
+ if (iphone_device_connect(device, dst_port, &connection) != IPHONE_E_SUCCESS) {
return ret;
}
mobilesync_client_t client_loc = (mobilesync_client_t) malloc(sizeof(struct mobilesync_client_int));
- client_loc->sfd = sfd;
+ client_loc->connection = connection;
/* perform handshake */
plist_t array = NULL;
@@ -126,7 +126,7 @@ mobilesync_error_t mobilesync_client_free(mobilesync_client_t client)
return IPHONE_E_INVALID_ARG;
mobilesync_disconnect(client);
- return (usbmuxd_disconnect(client->sfd) == 0 ? MOBILESYNC_E_SUCCESS: MOBILESYNC_E_MUX_ERROR);
+ return (iphone_device_disconnect(client->connection) == 0 ? MOBILESYNC_E_SUCCESS: MOBILESYNC_E_MUX_ERROR);
}
/** Polls the iPhone for MobileSync data.
@@ -144,14 +144,14 @@ mobilesync_error_t mobilesync_recv(mobilesync_client_t client, plist_t * plist)
char *receive = NULL;
uint32_t datalen = 0, bytes = 0, received_bytes = 0;
- ret = usbmuxd_recv(client->sfd, (char *) &datalen, sizeof(datalen), &bytes);
+ ret = iphone_device_recv(client->connection, (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 == MOBILESYNC_E_SUCCESS)) {
- ret = usbmuxd_recv(client->sfd, receive + received_bytes, datalen - received_bytes, &bytes);
+ ret = iphone_device_recv(client->connection, receive + received_bytes, datalen - received_bytes, &bytes);
received_bytes += bytes;
}
@@ -207,7 +207,7 @@ mobilesync_error_t mobilesync_send(mobilesync_client_t client, plist_t plist)
memcpy(real_query, &length, sizeof(length));
memcpy(real_query + 4, content, ntohl(length));
- ret = usbmuxd_send(client->sfd, real_query, ntohl(length) + sizeof(length), (uint32_t*)&bytes);
+ ret = iphone_device_send(client->connection, real_query, ntohl(length) + sizeof(length), (uint32_t*)&bytes);
free(real_query);
return (ret == 0 ? MOBILESYNC_E_SUCCESS: MOBILESYNC_E_MUX_ERROR);
}
diff --git a/src/MobileSync.h b/src/MobileSync.h
index 6347399..605145f 100644
--- a/src/MobileSync.h
+++ b/src/MobileSync.h
@@ -24,7 +24,7 @@
#include "libiphone/mobilesync.h"
struct mobilesync_client_int {
- int sfd;
+ iphone_connection_t connection;
};
#endif
diff --git a/src/NotificationProxy.c b/src/NotificationProxy.c
index e4735cc..da636ab 100644
--- a/src/NotificationProxy.c
+++ b/src/NotificationProxy.c
@@ -83,9 +83,9 @@ static np_error_t np_plist_send(np_client_t client, plist_t dict)
}
nlen = htonl(length);
- usbmuxd_send(client->sfd, (const char*)&nlen, sizeof(nlen), (uint32_t*)&bytes);
+ iphone_device_send(client->connection, (const char*)&nlen, sizeof(nlen), (uint32_t*)&bytes);
if (bytes == sizeof(nlen)) {
- usbmuxd_send(client->sfd, XML_content, length, (uint32_t*)&bytes);
+ iphone_device_send(client->connection, XML_content, length, (uint32_t*)&bytes);
if (bytes > 0) {
if ((uint32_t)bytes == length) {
res = NP_E_SUCCESS;
@@ -121,13 +121,13 @@ np_error_t np_client_new(iphone_device_t device, int dst_port, np_client_t *clie
return NP_E_INVALID_ARG;
/* Attempt connection */
- int sfd = usbmuxd_connect(device->handle, dst_port);
- if (sfd < 0) {
+ iphone_connection_t connection = NULL;
+ if (iphone_device_connect(device, dst_port, &connection) != IPHONE_E_SUCCESS) {
return NP_E_UNKNOWN_ERROR;
}
np_client_t client_loc = (np_client_t) malloc(sizeof(struct np_client_int));
- client_loc->sfd = sfd;
+ client_loc->connection = connection;
client_loc->mutex = g_mutex_new();
@@ -146,8 +146,8 @@ np_error_t np_client_free(np_client_t client)
if (!client)
return NP_E_INVALID_ARG;
- usbmuxd_disconnect(client->sfd);
- client->sfd = -1;
+ iphone_device_disconnect(client->connection);
+ client->connection = NULL;
if (client->notifier) {
log_debug_msg("joining np callback\n");
g_thread_join(client->notifier);
@@ -293,12 +293,12 @@ static int np_get_notification(np_client_t client, char **notification)
char *XML_content = NULL;
plist_t dict = NULL;
- if (!client || client->sfd < 0 || *notification)
+ if (!client || !client->connection || *notification)
return -1;
np_lock(client);
- usbmuxd_recv_timeout(client->sfd, (char*)&pktlen, sizeof(pktlen), &bytes, 500);
+ iphone_device_recv_timeout(client->connection, (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");
@@ -310,7 +310,7 @@ static int np_get_notification(np_client_t client, char **notification)
XML_content = (char*)malloc(pktlen);
log_debug_msg("pointer %p\n", XML_content);
- usbmuxd_recv_timeout(client->sfd, XML_content, pktlen, &bytes, 1000);
+ iphone_device_recv_timeout(client->connection, XML_content, pktlen, &bytes, 1000);
if (bytes <= 0) {
res = -1;
} else {
@@ -390,7 +390,7 @@ gpointer np_notifier( gpointer arg )
if (!npt) return NULL;
log_debug_msg("%s: starting callback.\n", __func__);
- while (npt->client->sfd >= 0) {
+ while (npt->client->connection) {
np_get_notification(npt->client, &notification);
if (notification) {
npt->cbfunc(notification);
@@ -429,11 +429,11 @@ np_error_t np_set_notify_callback( np_client_t client, np_notify_cb_t notify_cb
np_lock(client);
if (client->notifier) {
log_debug_msg("%s: callback already set, removing\n");
- int conn = client->sfd;
- client->sfd = -1;
+ iphone_connection_t conn = client->connection;
+ client->connection = NULL;
g_thread_join(client->notifier);
client->notifier = NULL;
- client->sfd = conn;
+ client->connection = conn;
}
if (notify_cb) {
diff --git a/src/NotificationProxy.h b/src/NotificationProxy.h
index bc5be43..84f1f89 100644
--- a/src/NotificationProxy.h
+++ b/src/NotificationProxy.h
@@ -26,7 +26,7 @@
#include "libiphone/notification_proxy.h"
struct np_client_int {
- int sfd;
+ iphone_connection_t connection;
GMutex *mutex;
GThread *notifier;
};
diff --git a/src/iphone.c b/src/iphone.c
index e694373..80e796b 100644
--- a/src/iphone.c
+++ b/src/iphone.c
@@ -1,8 +1,9 @@
/*
* iphone.c
- * Functions for creating and initializing iPhone structures.
+ * Device discovery and communication interface.
*
* Copyright (c) 2008 Zach C. All Rights Reserved.
+ * Copyright (c) 2009 Nikias Bassen. 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
@@ -19,104 +20,161 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <errno.h>
+#include <usbmuxd.h>
#include "iphone.h"
#include "utils.h"
+static iphone_event_cb_t event_cb = NULL;
+
+static void usbmux_event_cb(const usbmuxd_event_t *event, void *user_data)
+{
+ iphone_event_t ev;
+
+ ev.event = event->event;
+ ev.uuid = event->device.uuid;
+ ev.conn_type = CONNECTION_USBMUXD;
+
+ if (event_cb) {
+ event_cb(&ev, user_data);
+ }
+}
+
/**
- * 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.
+ * Register a callback function that will be called when device add/remove
+ * events occur.
*
- * @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 callback Callback function to call.
+ * @param user_data Application-specific data passed as parameter
+ * to the registered callback function.
*
- * @return IPHONE_E_SUCCESS if ok, otherwise an error code.
+ * @return IPHONE_E_SUCCESS on success or an error value when an error occured.
*/
-iphone_error_t iphone_get_device_by_uuid(iphone_device_t * device, const char *uuid)
+iphone_error_t iphone_event_subscribe(iphone_event_cb_t callback, void *user_data)
{
- iphone_device_t phone;
- uint32_t handle = 0;
- char *serial_number = malloc(41);
- usbmuxd_scan_result *dev_list = NULL;
- int i;
-
- 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;
- strcpy(serial_number, dev_list[0].serial_number);
- } 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;
- strcpy(serial_number, dev_list[i].serial_number);
- break;
- }
- }
- }
- free(dev_list);
-
- if (handle > 0) {
- phone = (iphone_device_t) malloc(sizeof(struct iphone_device_int));
- phone->handle = handle;
- phone->serial_number = serial_number;
- *device = phone;
- return IPHONE_E_SUCCESS;
- }
+ event_cb = callback;
+ int res = usbmuxd_subscribe(usbmux_event_cb, user_data);
+ if (res != 0) {
+ event_cb = NULL;
+ log_debug_msg("%s: Error %d when subscribing usbmux event callback!\n", __func__, res);
+ return IPHONE_E_UNKNOWN_ERROR;
}
+ return IPHONE_E_SUCCESS;
+}
- return IPHONE_E_NO_DEVICE;
+/**
+ * Release the event callback function that has been registered with
+ * iphone_event_subscribe().
+ *
+ * @return IPHONE_E_SUCCESS on success or an error value when an error occured.
+ */
+iphone_error_t iphone_event_unsubscribe()
+{
+ event_cb = NULL;
+ int res = usbmuxd_unsubscribe();
+ if (res != 0) {
+ log_debug_msg("%s: Error %d when unsubscribing usbmux event callback!\n", __func__, res);
+ return IPHONE_E_UNKNOWN_ERROR;
+ }
+ return IPHONE_E_SUCCESS;
}
/**
- * This function has the purpose to retrieve a handle to the first
- * attached iPhone/iPod reported by usbmuxd.
+ * Get a list of currently available devices.
*
- * @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.
+ * @param devices List of uuids of devices that are currently available.
+ * This list is terminated by a NULL pointer.
+ * @param count Number of devices found.
*
- * @return IPHONE_E_SUCCESS if ok, otherwise an error code.
+ * @return IPHONE_E_SUCCESS on success or an error value when an error occured.
*/
-iphone_error_t iphone_get_device(iphone_device_t * device)
+iphone_error_t iphone_get_device_list(char ***devices, int *count)
{
- return iphone_get_device_by_uuid(device, NULL);
+ usbmuxd_device_info_t *dev_list;
+
+ *devices = NULL;
+ *count = 0;
+
+ if (usbmuxd_get_device_list(&dev_list) < 0) {
+ log_debug_msg("%s: ERROR: usbmuxd is not running!\n", __func__);
+ return IPHONE_E_NO_DEVICE;
+ }
+
+ char **newlist = NULL;
+ int i, newcount = 0;
+
+ for (i = 0; dev_list[i].handle > 0; i++) {
+ newlist = realloc(*devices, sizeof(char*) * (newcount+1));
+ newlist[newcount++] = strdup(dev_list[i].uuid);
+ *devices = newlist;
+ }
+ usbmuxd_free_device_list(dev_list);
+
+ *count = newcount;
+ newlist = realloc(*devices, sizeof(char*) * (newcount+1));
+ newlist[newcount] = NULL;
+ *devices = newlist;
+
+ return IPHONE_E_SUCCESS;
}
-iphone_error_t iphone_device_get_handle(iphone_device_t device, uint32_t *handle)
+/**
+ * Free a list of device uuids.
+ *
+ * @param devices List of uuids to free.
+ *
+ * @return Always returnes IPHONE_E_SUCCESS.
+ */
+iphone_error_t iphone_free_device_list(char **devices)
{
- if (!device)
- return IPHONE_E_INVALID_ARG;
-
- *handle = device->handle;
+ if (devices) {
+ int i = 0;
+ while (devices[i++]) {
+ free(devices[i]);
+ }
+ free(devices);
+ }
return IPHONE_E_SUCCESS;
}
-iphone_error_t iphone_device_get_uuid(iphone_device_t device, char **uuid)
+/**
+ * Creates an iphone_device_t structure for the device specified by uuid,
+ * if the device is available.
+ *
+ * @note The resulting iphone_device_t structure has to be freed with
+ * iphone_device_free() if it is no longer used.
+ *
+ * @param device Upon calling this function, a pointer to a location of type
+ * iphone_device_t. On successful return, this location will be populated.
+ * @param uuid The UUID to match.
+ *
+ * @return IPHONE_E_SUCCESS if ok, otherwise an error code.
+ */
+iphone_error_t iphone_device_new(iphone_device_t * device, const char *uuid)
{
- if (!device)
- return IPHONE_E_INVALID_ARG;
+ usbmuxd_device_info_t muxdev;
+ int res = usbmuxd_get_device_by_uuid(uuid, &muxdev);
+ if (res > 0) {
+ iphone_device_t phone = (iphone_device_t) malloc(sizeof(struct iphone_device_int));
+ phone->uuid = strdup(muxdev.uuid);
+ phone->conn_type = CONNECTION_USBMUXD;
+ phone->conn_data = (void*)muxdev.handle;
+ *device = phone;
+ return IPHONE_E_SUCCESS;
+ }
+ /* other connection types could follow here */
- *uuid = strdup(device->serial_number);
- return IPHONE_E_SUCCESS;
+ return IPHONE_E_NO_DEVICE;
}
/** Cleans up an iPhone structure, then frees the structure itself.
* This is a library-level function; deals directly with the iPhone to tear
* down relations, but otherwise is mostly internal.
*
- * @param phone A pointer to an iPhone structure.
+ * @param device A pointer to an iPhone structure.
*/
iphone_error_t iphone_device_free(iphone_device_t device)
{
@@ -126,8 +184,189 @@ iphone_error_t iphone_device_free(iphone_device_t device)
ret = IPHONE_E_SUCCESS;
- free(device->serial_number);
+ free(device->uuid);
+
+ if (device->conn_type == CONNECTION_USBMUXD) {
+ device->conn_data = 0;
+ }
+ if (device->conn_data) {
+ free(device->conn_data);
+ }
free(device);
return ret;
}
+/**
+ * Set up a connection to the given device.
+ *
+ * @param device The device to connect to.
+ * @param dst_port The destination port to connect to.
+ * @param connection Pointer to an iphone_connection_t that will be filled
+ * with the necessary data of the connection.
+ *
+ * @return IPHONE_E_SUCCESS if ok, otherwise an error code.
+ */
+iphone_error_t iphone_device_connect(iphone_device_t device, uint16_t dst_port, iphone_connection_t *connection)
+{
+ if (!device) {
+ return IPHONE_E_INVALID_ARG;
+ }
+
+ if (device->conn_type == CONNECTION_USBMUXD) {
+ int sfd = usbmuxd_connect((uint32_t)(device->conn_data), dst_port);
+ if (sfd < 0) {
+ log_debug_msg("%s: ERROR: Connecting to usbmuxd failed: %d (%s)\n", __func__, sfd, strerror(-sfd));
+ return IPHONE_E_UNKNOWN_ERROR;
+ }
+ iphone_connection_t new_connection = (iphone_connection_t)malloc(sizeof(struct iphone_connection_int));
+ new_connection->type = CONNECTION_USBMUXD;
+ new_connection->data = (void*)sfd;
+ *connection = new_connection;
+ return IPHONE_E_SUCCESS;
+ } else {
+ log_debug_msg("%s: Unknown connection type %d\n", __func__, device->conn_type);
+ }
+
+ return IPHONE_E_UNKNOWN_ERROR;
+}
+
+/**
+ * Disconnect from the device and clean up the connection structure.
+ *
+ * @param connection The connection to close.
+ *
+ * @return IPHONE_E_SUCCESS if ok, otherwise an error code.
+ */
+iphone_error_t iphone_device_disconnect(iphone_connection_t connection)
+{
+ if (!connection) {
+ return IPHONE_E_INVALID_ARG;
+ }
+ iphone_error_t result = IPHONE_E_UNKNOWN_ERROR;
+ if (connection->type == CONNECTION_USBMUXD) {
+ usbmuxd_disconnect((int)(connection->data));
+ result = IPHONE_E_SUCCESS;
+ } else {
+ log_debug_msg("%s: Unknown connection type %d\n", __func__, connection->type);
+ }
+ free(connection);
+ return result;
+}
+
+/**
+ * Send data to a device via the given connection.
+ *
+ * @param connection The connection to send data over.
+ * @param data Buffer with data to send.
+ * @param len Size of the buffer to send.
+ * @param sent_bytes Pointer to an uint32_t that will be filled
+ * with the number of bytes actually sent.
+ *
+ * @return IPHONE_E_SUCCESS if ok, otherwise an error code.
+ */
+iphone_error_t iphone_device_send(iphone_connection_t connection, const char *data, uint32_t len, uint32_t *sent_bytes)
+{
+ if (!connection || !data) {
+ return IPHONE_E_INVALID_ARG;
+ }
+
+ if (connection->type == CONNECTION_USBMUXD) {
+ int res = usbmuxd_send((int)(connection->data), data, len, sent_bytes);
+ if (res < 0) {
+ log_debug_msg("%s: ERROR: usbmuxd_send returned %d (%s)\n", __func__, res, strerror(-res));
+ return IPHONE_E_UNKNOWN_ERROR;
+ }
+ return IPHONE_E_SUCCESS;
+ } else {
+ log_debug_msg("%s: Unknown connection type %d\n", __func__, connection->type);
+ }
+ return IPHONE_E_UNKNOWN_ERROR;
+}
+
+/**
+ * Receive data from a device via the given connection.
+ * This function will return after the given timeout even if no data has been
+ * received.
+ *
+ * @param connection The connection to receive data from.
+ * @param data Buffer that will be filled with the received data.
+ * This buffer has to be large enough to hold len bytes.
+ * @param len Buffer size or number of bytes to receive.
+ * @param recv_bytes Number of bytes actually received.
+ * @param timeout Timeout in milliseconds after which this function should
+ * return even if no data has been received.
+ *
+ * @return IPHONE_E_SUCCESS if ok, otherwise an error code.
+ */
+iphone_error_t iphone_device_recv_timeout(iphone_connection_t connection, char *data, uint32_t len, uint32_t *recv_bytes, unsigned int timeout)
+{
+ if (!connection) {
+ return IPHONE_E_INVALID_ARG;
+ }
+
+ if (connection->type == CONNECTION_USBMUXD) {
+ int res = usbmuxd_recv_timeout((int)(connection->data), data, len, recv_bytes, timeout);
+ if (res < 0) {
+ log_debug_msg("%s: ERROR: usbmuxd_recv_timeout returned %d (%s)\n", __func__, res, strerror(-res));
+ return IPHONE_E_UNKNOWN_ERROR;
+ }
+ } else {
+ log_debug_msg("%s: Unknown connection type %d\n", __func__, connection->type);
+ }
+ return IPHONE_E_UNKNOWN_ERROR;
+}
+
+/**
+ * Receive data from a device via the given connection.
+ * This function is like iphone_device_recv_timeout, but with a predefined
+ * reasonable timeout.
+ *
+ * @param connection The connection to receive data from.
+ * @param data Buffer that will be filled with the received data.
+ * This buffer has to be large enough to hold len bytes.
+ * @param len Buffer size or number of bytes to receive.
+ * @param recv_bytes Number of bytes actually received.
+ *
+ * @return IPHONE_E_SUCCESS if ok, otherwise an error code.
+ */
+iphone_error_t iphone_device_recv(iphone_connection_t connection, char *data, uint32_t len, uint32_t *recv_bytes)
+{
+ if (!connection) {
+ return -EINVAL;
+ }
+
+ if (connection->type == CONNECTION_USBMUXD) {
+ int res = usbmuxd_recv((int)(connection->data), data, len, recv_bytes);
+ if (res < 0) {
+ log_debug_msg("%s: ERROR: usbmuxd_recv returned %d (%s)\n", __func__, res, strerror(-res));
+ return IPHONE_E_UNKNOWN_ERROR;
+ }
+ } else {
+ log_debug_msg("%s: Unknown connection type %d\n", __func__, connection->type);
+ }
+ return IPHONE_E_UNKNOWN_ERROR;
+}
+
+iphone_error_t iphone_device_get_handle(iphone_device_t device, uint32_t *handle)
+{
+ if (!device)
+ return IPHONE_E_INVALID_ARG;
+
+ if (device->conn_type == CONNECTION_USBMUXD) {
+ *handle = (uint32_t)device->conn_data;
+ return IPHONE_E_SUCCESS;
+ } else {
+ log_debug_msg("%s: Unknown connection type %d\n", __func__, device->conn_type);
+ }
+ return IPHONE_E_UNKNOWN_ERROR;
+}
+
+iphone_error_t iphone_device_get_uuid(iphone_device_t device, char **uuid)
+{
+ if (!device)
+ return IPHONE_E_INVALID_ARG;
+
+ *uuid = strdup(device->uuid);
+ return IPHONE_E_SUCCESS;
+}
+
diff --git a/src/iphone.h b/src/iphone.h
index 6e14280..98b0ed8 100644
--- a/src/iphone.h
+++ b/src/iphone.h
@@ -1,7 +1,7 @@
/*
* iphone.h
- * iPhone struct
- *
+ * Device discovery and communication interface -- header file.
+ *
* Copyright (c) 2008 Zach C. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
@@ -18,18 +18,24 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-
#ifndef IPHONE_H
#define IPHONE_H
-#include <stdint.h>
-
#include "libiphone/libiphone.h"
+enum connection_type {
+ CONNECTION_USBMUXD = 1
+};
+
+struct iphone_connection_int {
+ enum connection_type type;
+ void *data;
+};
+
struct iphone_device_int {
- char *buffer;
- uint32_t handle;
- char *serial_number;
+ char *uuid;
+ enum connection_type conn_type;
+ void *conn_data;
};
#endif
diff --git a/src/lockdown.c b/src/lockdown.c
index 7a2aa7d..a05b5db 100644
--- a/src/lockdown.c
+++ b/src/lockdown.c
@@ -213,12 +213,14 @@ lockdownd_error_t lockdownd_client_free(lockdownd_client_t client)
lockdownd_stop_ssl_session(client);
- if (client->sfd > 0) {
+ if (client->connection) {
lockdownd_goodbye(client);
// IMO, read of final "sessionUpcall connection closed" packet
// should come here instead of in iphone_free_device
- ret = usbmuxd_disconnect(client->sfd);
+ if ((ret = iphone_device_disconnect(client->connection)) != IPHONE_E_SUCCESS) {
+ ret = LOCKDOWN_E_UNKNOWN_ERROR;
+ }
}
free(client);
@@ -241,7 +243,7 @@ lockdownd_error_t lockdownd_recv(lockdownd_client_t client, plist_t *plist)
uint32_t datalen = 0, bytes = 0, received_bytes = 0;
if (!client->in_SSL)
- ret = usbmuxd_recv(client->sfd, (char *) &datalen, sizeof(datalen), &bytes);
+ ret = iphone_device_recv(client->connection, (char *) &datalen, sizeof(datalen), &bytes);
else {
ssize_t res = gnutls_record_recv(*client->ssl_session, &datalen, sizeof(datalen));
if (res < 0) {
@@ -260,7 +262,7 @@ lockdownd_error_t lockdownd_recv(lockdownd_client_t client, plist_t *plist)
/* fill buffer and request more packets if needed */
if (!client->in_SSL) {
while ((received_bytes < datalen) && (ret == LOCKDOWN_E_SUCCESS)) {
- ret = usbmuxd_recv(client->sfd, receive + received_bytes, datalen - received_bytes, &bytes);
+ ret = iphone_device_recv(client->connection, receive + received_bytes, datalen - received_bytes, &bytes);
received_bytes += bytes;
}
} else {
@@ -328,7 +330,7 @@ lockdownd_error_t lockdownd_send(lockdownd_client_t client, plist_t plist)
log_dbg_msg(DBGMASK_LOCKDOWND, "%s: made the query, sending it along\n", __func__);
if (!client->in_SSL)
- ret = usbmuxd_send(client->sfd, real_query, ntohl(length) + sizeof(length), (uint32_t*)&bytes);
+ ret = iphone_device_send(client->connection, real_query, ntohl(length) + sizeof(length), (uint32_t*)&bytes);
else {
ssize_t res = gnutls_record_send(*client->ssl_session, real_query, ntohl(length) + sizeof(length));
if (res < 0) {
@@ -659,19 +661,19 @@ lockdownd_error_t lockdownd_get_device_name(lockdownd_client_t client, char **de
*/
lockdownd_error_t lockdownd_client_new(iphone_device_t device, lockdownd_client_t *client)
{
- if (!device || !client)
+ if (!client)
return LOCKDOWN_E_INVALID_ARG;
lockdownd_error_t ret = LOCKDOWN_E_SUCCESS;
char *host_id = NULL;
- int sfd = usbmuxd_connect(device->handle, 0xf27e);
- if (sfd < 0) {
- log_debug_msg("%s: could not connect to lockdownd (device handle %d)\n", __func__, device->handle);
+ iphone_connection_t connection;
+ if (iphone_device_connect(device, 0xf27e, &connection) != IPHONE_E_SUCCESS) {
+ log_debug_msg("%s: could not connect to lockdownd (device %s)\n", __func__, device->uuid);
return LOCKDOWN_E_MUX_ERROR;
}
lockdownd_client_t client_loc = (lockdownd_client_t) malloc(sizeof(struct lockdownd_client_int));
- client_loc->sfd = sfd;
+ client_loc->connection = connection;
client_loc->ssl_session = (gnutls_session_t *) malloc(sizeof(gnutls_session_t));
client_loc->in_SSL = 0;
@@ -1176,7 +1178,7 @@ ssize_t lockdownd_secuwrite(gnutls_transport_ptr_t transport, char *buffer, size
client = (lockdownd_client_t) transport;
log_dbg_msg(DBGMASK_LOCKDOWND, "%s: called\n", __func__);
log_dbg_msg(DBGMASK_LOCKDOWND, "%s: pre-send length = %zi\n", __func__, length);
- usbmuxd_send(client->sfd, buffer, length, &bytes);
+ iphone_device_send(client->connection, buffer, length, &bytes);
log_dbg_msg(DBGMASK_LOCKDOWND, "%s: post-send sent %i bytes\n", __func__, bytes);
return bytes;
}
@@ -1205,7 +1207,7 @@ 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 = usbmuxd_recv(client->sfd, recv_buffer, this_len, (uint32_t*)&bytes)) != LOCKDOWN_E_SUCCESS) {
+ if ((res = iphone_device_recv(client->connection, recv_buffer, this_len, (uint32_t*)&bytes)) != LOCKDOWN_E_SUCCESS) {
log_debug_msg("%s: ERROR: usbmux_recv returned %d\n", __func__, res);
return res;
}
diff --git a/src/lockdown.h b/src/lockdown.h
index 1e193f6..19cf9f2 100644
--- a/src/lockdown.h
+++ b/src/lockdown.h
@@ -28,7 +28,7 @@
#include "libiphone/lockdown.h"
struct lockdownd_client_int {
- int sfd;
+ iphone_connection_t connection;
gnutls_session_t *ssl_session;
int in_SSL;
char session_id[40];
diff --git a/src/userpref.c b/src/userpref.c
index 9dd1a01..10c14a0 100644
--- a/src/userpref.c
+++ b/src/userpref.c
@@ -88,7 +88,7 @@ static char *userpref_generate_host_id()
*
* @param host_id A null terminated string containing a valid HostID.
*/
-static int userpref_set_host_id(char *host_id)
+static int userpref_set_host_id(const char *host_id)
{
GKeyFile *key_file;
gsize length;
@@ -164,7 +164,7 @@ void userpref_get_host_id(char **host_id)
* @return 1 if the iPhone has been connected previously to this configuration
* or 0 otherwise.
*/
-int userpref_has_device_public_key(char *uuid)
+int userpref_has_device_public_key(const char *uuid)
{
int ret = 0;
gchar *config_file;
@@ -187,7 +187,7 @@ int userpref_has_device_public_key(char *uuid)
* @return 1 on success and 0 if no public key is given or if it has already
* been marked as connected previously.
*/
-userpref_error_t userpref_set_device_public_key(char *uuid, gnutls_datum_t public_key)
+userpref_error_t userpref_set_device_public_key(const char *uuid, gnutls_datum_t public_key)
{
if (NULL == public_key.data)
return USERPREF_E_INVALID_ARG;
diff --git a/src/userpref.h b/src/userpref.h
index 414c093..fcb8b62 100644
--- a/src/userpref.h
+++ b/src/userpref.h
@@ -36,8 +36,8 @@ typedef int16_t userpref_error_t;
userpref_error_t userpref_get_keys_and_certs(gnutls_x509_privkey_t root_privkey, gnutls_x509_crt_t root_crt, gnutls_x509_privkey_t host_privkey, gnutls_x509_crt_t host_crt);
userpref_error_t userpref_set_keys_and_certs(gnutls_datum_t * root_key, gnutls_datum_t * root_cert, gnutls_datum_t * host_key, gnutls_datum_t * host_cert);
userpref_error_t userpref_get_certs_as_pem(gnutls_datum_t *pem_root_cert, gnutls_datum_t *pem_host_cert);
-userpref_error_t userpref_set_device_public_key(char *uuid, gnutls_datum_t public_key);
-int userpref_has_device_public_key(char *uuid);
+userpref_error_t userpref_set_device_public_key(const char *uuid, gnutls_datum_t public_key);
+int userpref_has_device_public_key(const char *uuid);
void userpref_get_host_id(char **host_id);
#endif
diff --git a/tools/iphone_id.c b/tools/iphone_id.c
index 835e214..ab36e7c 100644
--- a/tools/iphone_id.c
+++ b/tools/iphone_id.c
@@ -28,7 +28,7 @@ int main(int argc, char **argv)
{
iphone_device_t phone = NULL;
lockdownd_client_t client = NULL;
- usbmuxd_scan_result *dev_list;
+ usbmuxd_device_info_t *dev_list;
char *devname = NULL;
int ret = 0;
int i;
@@ -65,7 +65,7 @@ int main(int argc, char **argv)
switch (mode) {
case MODE_SHOW_ID:
- iphone_get_device_by_uuid(&phone, uuid);
+ iphone_device_new(&phone, uuid);
if (!phone) {
fprintf(stderr, "ERROR: No device with UUID=%s attached.\n", uuid);
return -2;
@@ -96,13 +96,14 @@ int main(int argc, char **argv)
return ret;
case MODE_LIST_DEVICES:
default:
- if (usbmuxd_scan(&dev_list) < 0) {
+ if (usbmuxd_get_device_list(&dev_list) < 0) {
fprintf(stderr, "ERROR: usbmuxd is not running!\n");
return -1;
}
for (i = 0; dev_list[i].handle > 0; i++) {
- printf("handle=%d product_id=%04x uuid=%s\n", dev_list[i].handle, dev_list[i].product_id, dev_list[i].serial_number);
+ printf("handle=%d product_id=%04x uuid=%s\n", dev_list[i].handle, dev_list[i].product_id, dev_list[i].uuid);
}
+ usbmuxd_free_device_list(dev_list);
return 0;
}
}
diff --git a/tools/iphoneinfo.c b/tools/iphoneinfo.c
index 7e275b2..16a1069 100644
--- a/tools/iphoneinfo.c
+++ b/tools/iphoneinfo.c
@@ -121,7 +121,7 @@ int main(int argc, char *argv[])
}
if (uuid[0] != 0) {
- ret = iphone_get_device_by_uuid(&phone, uuid);
+ ret = iphone_device_new(&phone, uuid);
if (ret != IPHONE_E_SUCCESS) {
printf("No device found with uuid %s, is it plugged in?\n", uuid);
return -1;
@@ -129,7 +129,7 @@ int main(int argc, char *argv[])
}
else
{
- ret = iphone_get_device(&phone);
+ ret = iphone_device_new(&phone, NULL);
if (ret != IPHONE_E_SUCCESS) {
printf("No device found, is it plugged in?\n");
return -1;
diff --git a/tools/iphonesyslog.c b/tools/iphonesyslog.c
index a096101..10b3fb6 100644
--- a/tools/iphonesyslog.c
+++ b/tools/iphonesyslog.c
@@ -28,7 +28,6 @@
#include <libiphone/libiphone.h>
#include <libiphone/lockdown.h>
-#include <usbmuxd.h>
static int quit_flag = 0;
@@ -86,7 +85,7 @@ int main(int argc, char *argv[])
}
if (uuid[0] != 0) {
- ret = iphone_get_device_by_uuid(&phone, uuid);
+ ret = iphone_device_new(&phone, uuid);
if (ret != IPHONE_E_SUCCESS) {
printf("No device found with uuid %s, is it plugged in?\n", uuid);
return -1;
@@ -94,7 +93,7 @@ int main(int argc, char *argv[])
}
else
{
- ret = iphone_get_device(&phone);
+ ret = iphone_device_new(&phone, NULL);
if (ret != IPHONE_E_SUCCESS) {
printf("No device found, is it plugged in?\n");
return -1;
@@ -112,16 +111,15 @@ int main(int argc, char *argv[])
lockdownd_client_free(client);
/* connect to socket relay messages */
- iphone_device_get_handle(phone, &handle);
- int sfd = usbmuxd_connect(handle, port);
- if (sfd < 0) {
+ iphone_connection_t conn = NULL;
+ if ((iphone_device_connect(phone, port, &conn) != IPHONE_E_SUCCESS) || !conn) {
printf("ERROR: Could not open usbmux connection.\n");
} else {
while (!quit_flag) {
char *receive = NULL;
uint32_t datalen = 0, bytes = 0, recv_bytes = 0;
- ret = usbmuxd_recv(sfd, (char *) &datalen, sizeof(datalen), &bytes);
+ ret = iphone_device_recv(conn, (char *) &datalen, sizeof(datalen), &bytes);
datalen = ntohl(datalen);
if (datalen == 0)
@@ -131,7 +129,7 @@ int main(int argc, char *argv[])
receive = (char *) malloc(sizeof(char) * datalen);
while (!quit_flag && (recv_bytes <= datalen)) {
- ret = usbmuxd_recv(sfd, receive, datalen, &bytes);
+ ret = iphone_device_recv(conn, receive, datalen, &bytes);
if (bytes == 0)
break;
@@ -144,7 +142,7 @@ int main(int argc, char *argv[])
free(receive);
}
}
- usbmuxd_disconnect(sfd);
+ iphone_device_disconnect(conn);
} else {
printf("ERROR: Could not start service com.apple.syslog_relay.\n");
}