summaryrefslogtreecommitdiffstats
path: root/tools/icat.c
diff options
context:
space:
mode:
authorGravatar Adrien Guinet2017-08-02 01:56:29 -0700
committerGravatar Nikias Bassen2019-08-03 01:44:55 +0800
commit219e6bcae2ab93cd98bd352b62fb0f9d21051344 (patch)
tree5aabae021beb797aa8de1794953459a1afca3c68 /tools/icat.c
parent6539b0261889bff41972338fa64cd230183fad42 (diff)
downloadlibusbmuxd-219e6bcae2ab93cd98bd352b62fb0f9d21051344.tar.gz
libusbmuxd-219e6bcae2ab93cd98bd352b62fb0f9d21051344.tar.bz2
tools: Add new tool 'icat'
Diffstat (limited to 'tools/icat.c')
-rw-r--r--tools/icat.c148
1 files changed, 148 insertions, 0 deletions
diff --git a/tools/icat.c b/tools/icat.c
new file mode 100644
index 0000000..9296a23
--- /dev/null
+++ b/tools/icat.c
@@ -0,0 +1,148 @@
+/*
+ * icat.c -- simple netcat-like tool that enables service access to iOS devices
+ *
+ * Copyright (C) 2017 Adrien Guinet <adrien@guinet.me>
+ *
+ * Based on iproxy which is based upon iTunnel source code, Copyright (c)
+ * 2008 Jing Su. http://www.cs.toronto.edu/~jingsu/itunnel/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/ioctl.h>
+
+#include "usbmuxd.h"
+
+static size_t read_data_socket(int fd, uint8_t* buf, size_t bufsize)
+{
+ size_t bytesavailable;
+ if (ioctl(fd, FIONREAD, &bytesavailable) != 0) {
+ perror("ioctl FIONREAD failed");
+ exit(1);
+ }
+ size_t bufread = (bytesavailable >= bufsize) ? bufsize:bytesavailable;
+ ssize_t ret = read(fd, buf, bufread);
+ if (ret < 0) {
+ perror("read failed");
+ exit(1);
+ }
+ return (size_t)ret;
+}
+
+int main(int argc, char **argv)
+{
+ if (argc < 2) {
+ printf("usage: %s DEVICE_TCP_PORT [UDID]\n", argv[0]);
+ return 1;
+ }
+
+ int device_port = atoi(argv[1]);
+ char* device_udid = NULL;
+
+ if (argc > 2) {
+ device_udid = argv[2];
+ }
+
+ if (!device_port) {
+ fprintf(stderr, "Invalid device_port specified!\n");
+ return -EINVAL;
+ }
+
+ usbmuxd_device_info_t *dev_list = NULL;
+ int count;
+ if ((count = usbmuxd_get_device_list(&dev_list)) < 0) {
+ printf("Connecting to usbmuxd failed, terminating.\n");
+ free(dev_list);
+ return 1;
+ }
+
+ if (dev_list == NULL || dev_list[0].handle == 0) {
+ fprintf(stderr, "No connected device found, terminating.\n");
+ free(dev_list);
+ return 1;
+ }
+
+ usbmuxd_device_info_t *dev = NULL;
+ if (device_udid) {
+ int i;
+ for (i = 0; i < count; i++) {
+ if (strncmp(dev_list[i].udid, device_udid, sizeof(dev_list[0].udid)) == 0) {
+ dev = &(dev_list[i]);
+ break;
+ }
+ }
+ } else {
+ dev = &(dev_list[0]);
+ }
+
+ if (dev == NULL || dev->handle == 0) {
+ fprintf(stderr, "No connected/matching device found, disconnecting client.\n");
+ free(dev_list);
+ return 1;
+ }
+
+ int devfd = usbmuxd_connect(dev->handle, device_port);
+ free(dev_list);
+ if (devfd < 0) {
+ fprintf(stderr, "Error connecting to device!\n");
+ return 1;
+ }
+
+ fd_set fds;
+ FD_ZERO(&fds);
+ FD_SET(STDIN_FILENO, &fds);
+ FD_SET(devfd, &fds);
+
+ int ret = 0;
+ uint8_t buf[4096];
+ while (1) {
+ fd_set read_fds = fds;
+ int ret_sel = select(devfd+1, &read_fds, NULL, NULL, NULL);
+ if (ret_sel < 0) {
+ perror("select");
+ ret = 1;
+ break;
+ }
+
+ if (FD_ISSET(STDIN_FILENO, &read_fds)) {
+ size_t n = read_data_socket(STDIN_FILENO, buf, sizeof(buf));
+ if (n == 0) {
+ break;
+ }
+ write(devfd, buf, n);
+ }
+
+ if (FD_ISSET(devfd, &read_fds)) {
+ size_t n = read_data_socket(devfd, buf, sizeof(buf));
+ if (n == 0) {
+ break;
+ }
+ write(STDOUT_FILENO, buf, n);
+ }
+ }
+
+ close(devfd);
+ return ret;
+}