[Spice-devel] [PATCH 4/5] Add a connectkernel utility to support the usbredir kernel module.

Jeremy White jwhite at codeweavers.com
Tue Jun 30 13:57:41 PDT 2015


This utility will connect to a remote system running usbredirserver,
and then write the socket to the sysfs attach point of usbredir,
thereby injecting the remote device into the local kernel.

Signed-off-by: Jeremy White <jwhite at codeweavers.com>
---
 Makefile.am                   |   2 +-
 configure.ac                  |   1 +
 connectkernel/.gitignore      |   3 +
 connectkernel/Makefile.am     |   5 ++
 connectkernel/connectkernel.1 |  33 +++++++++++
 connectkernel/connectkernel.c | 126 ++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 169 insertions(+), 1 deletion(-)
 create mode 100644 connectkernel/.gitignore
 create mode 100644 connectkernel/Makefile.am
 create mode 100644 connectkernel/connectkernel.1
 create mode 100644 connectkernel/connectkernel.c

diff --git a/Makefile.am b/Makefile.am
index f69a859..03ef2d0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,6 +1,6 @@
 SUBDIRS = usbredirparser usbredirhost
 if ! OS_WIN32
-SUBDIRS += usbredirserver  usbredirtestclient
+SUBDIRS += usbredirserver connectkernel usbredirtestclient
 endif
 
 EXTRA_DIST = README.multi-thread usb-redirection-protocol.txt
diff --git a/configure.ac b/configure.ac
index 25c9a5b..b3d6598 100644
--- a/configure.ac
+++ b/configure.ac
@@ -64,6 +64,7 @@ usbredirhost/libusbredirhost.pc
 usbredirparser/Makefile
 usbredirparser/libusbredirparser-0.5.pc
 usbredirserver/Makefile
+connectkernel/Makefile
 usbredirtestclient/Makefile
 ])
 AC_OUTPUT
diff --git a/connectkernel/.gitignore b/connectkernel/.gitignore
new file mode 100644
index 0000000..f6c7921
--- /dev/null
+++ b/connectkernel/.gitignore
@@ -0,0 +1,3 @@
+Makefile
+Makefile.in
+connectkernel
diff --git a/connectkernel/Makefile.am b/connectkernel/Makefile.am
new file mode 100644
index 0000000..72b2a86
--- /dev/null
+++ b/connectkernel/Makefile.am
@@ -0,0 +1,5 @@
+sbin_PROGRAMS = connectkernel
+
+connectkernel_SOURCES = connectkernel.c
+
+dist_man_MANS = connectkernel.1
diff --git a/connectkernel/connectkernel.1 b/connectkernel/connectkernel.1
new file mode 100644
index 0000000..90883a8
--- /dev/null
+++ b/connectkernel/connectkernel.1
@@ -0,0 +1,33 @@
+.TH CONNECTKERNEL "1" "July 2015" "connectkernel" "User Commands"
+.SH NAME
+connectkernel\- registering an exported USB device with a kernel running usbredir
+.SH SYNOPSIS
+.B connectkernel
+devid server port [\fI--attach <sysfs_file>\fR]
+.SH DESCRIPTION
+connectkernel is a small standalone utility which will connect to a
+remote usbredirserver and give the connection handle to the linux
+kernel, thereby importing the remote device into the running linux kernel.
+.PP
+You need to specify a unique identifier for the remote device, and a
+server and port where the device can be found.
+.PP
+Notice that an invocation of connectkernel can only be used to export a
+single USB device. If you want to connect multiple devices you will need
+to invoke it once for each remote device.
+.SH OPTIONS
+.TP
+\fB\-\-attach\fR \fIFILE\fR
+Set the file to write socket and devid to \fIFILE\fR.  The default
+is /sys/bus/platform/drivers/usbredir/attach.
+.SH AUTHOR
+Written by Jeremy White <jwhite at codeweavers.com>
+.SH REPORTING BUGS
+Report bugs to the spice-devel mailinglist:
+http://lists.freedesktop.org/mailman/listinfo/spice-devel
+.SH COPYRIGHT
+Copyright 2015 CodeWeavers, Inc.
+License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>.
+.br 
+This is free software: you are free to change and redistribute it.
+There is NO WARRANTY, to the extent permitted by law.
diff --git a/connectkernel/connectkernel.c b/connectkernel/connectkernel.c
new file mode 100644
index 0000000..607ece0
--- /dev/null
+++ b/connectkernel/connectkernel.c
@@ -0,0 +1,126 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <unistd.h>
+
+void usage(const char *argv0)
+{
+    fprintf(stderr, "%s: Connect a remote USB device to the usbredir kernel module.\n", argv0);
+    fprintf(stderr, "Usage:\n");
+    fprintf(stderr, "    %s devid server port [--attach attach]\n", argv0);
+    fprintf(stderr, "where devid is a unique identifier for this connection, server:port\n");
+    fprintf(stderr, "is the address of a TCP server that is listening, waiting to export a USBREDIR device.\n");
+    fprintf(stderr, "Generally, you invoke %s to connect to a usbredirserver process.\n", argv0);
+}
+
+
+int main(int argc, char *argv[])
+{
+	struct addrinfo hints, *res, *rp;
+        int rc;
+        int s;
+        int fd;
+        int i;
+        char buf[256 + 8];
+        char *attach_file = "/sys/bus/platform/drivers/usbredir/attach";
+        char *devid = NULL;
+        char *server = NULL;
+        char *port = NULL;
+
+
+        /* Poor man's argument parsing */
+        for (i = 1; i < argc; i++)
+        {
+            if (strcmp(argv[i], "--attach") == 0)
+            {
+                if (i == (argc - 1))
+                {
+                    fprintf(stderr, "Error: you must supply a path to the sysfs attach file.\n");
+                    exit(1);
+                }
+                i++;
+                attach_file = argv[i];
+                break;
+            }
+            else if (!devid)
+                devid = argv[i];
+            else if (!server)
+                server = argv[i];
+            else if (!port)
+                port = argv[i];
+            else
+            {
+                fprintf(stderr, "Error: too many arguments.\n");
+                usage(argv[0]);
+                exit(1);
+            }
+        }
+
+        if (!devid || !server || !port)
+        {
+            fprintf(stderr, "Error: specify device id, server and port\n");
+            usage(argv[0]);
+            exit(1);
+        }
+
+	memset(&hints, 0, sizeof(hints));
+	hints.ai_family = AF_INET;
+	hints.ai_socktype = SOCK_STREAM;
+	hints.ai_flags = AI_NUMERICSERV;
+
+	/* get all possible addresses */
+	rc = getaddrinfo(server, port, &hints, &res);
+	if (rc < 0)
+        {
+
+            fprintf(stderr, "Error resolving %s:%s\n", server, port);
+            exit(1);
+        }
+
+	for (rp = res; rp; rp = rp->ai_next)
+        {
+            s = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
+            if (s < 0)
+            {
+                perror("socket");
+                exit(2);
+            }
+
+            rc = connect(s, rp->ai_addr, rp->ai_addrlen);
+            if (rc == 0)
+                break;
+
+        }
+
+        if (! rp)
+        {
+            fprintf(stderr, "Error: unable to connect.\n");
+            exit(3);
+        }
+
+	freeaddrinfo(res);
+
+        fd = open(attach_file, O_WRONLY);
+        if (fd == -1)
+        {
+            fprintf(stderr, "Could not write to %s\n", attach_file);
+            exit(1);
+        }
+
+        snprintf(buf, sizeof(buf), "%d %s", s, devid);
+        if (write(fd, buf, strlen(buf)) < 0)
+        {
+            fprintf(stderr, "Attach of '%s' to kernel failed\n", buf);
+            exit(1);
+        }
+        close(fd);
+
+        sleep(1);
+
+        return 0;
+}
-- 
2.1.4



More information about the Spice-devel mailing list