* [DEMO PATCH linux 1/3] usbip: tools: in.usbipd: add
2021-10-13 13:53 [DEMO PATCH linux 0/3] usbip: tools: support USB over vsock(7) Alyssa Ross
@ 2021-10-13 13:53 ` Alyssa Ross
2021-10-13 13:53 ` [DEMO PATCH linux 2/3] usbip: tools: usbip: record protocol Alyssa Ross
2021-10-13 13:53 ` [DEMO PATCH linux 3/3] usbip: tools: usbip: support vsock(7) connections Alyssa Ross
2 siblings, 0 replies; 4+ messages in thread
From: Alyssa Ross @ 2021-10-13 13:53 UTC (permalink / raw)
To: devel
This is an inetd-style version of usbipd, which allows it to be easily
socket-activated, and work with other types of socket. I implemented
this by just copying usbipd.c, and then deleting all the code that
created, bound, and listened on a socket. In future, this could be
made more maintainable by having it share the bulk of its code with
usbipd.
Signed-off-by: Alyssa Ross <hi@alyssa.is>
---
tools/usb/usbip/src/Makefile.am | 4 +-
tools/usb/usbip/src/in.usbipd.c | 326 ++++++++++++++++++++++++++++++++
2 files changed, 329 insertions(+), 1 deletion(-)
create mode 100644 tools/usb/usbip/src/in.usbipd.c
diff --git a/tools/usb/usbip/src/Makefile.am b/tools/usb/usbip/src/Makefile.am
index e26f39e0579d..d64613733fd5 100644
--- a/tools/usb/usbip/src/Makefile.am
+++ b/tools/usb/usbip/src/Makefile.am
@@ -3,10 +3,12 @@ AM_CPPFLAGS = -I$(top_srcdir)/libsrc -DUSBIDS_FILE='"@USBIDS_DIR@/usb.ids"'
AM_CFLAGS = @EXTRA_CFLAGS@
LDADD = $(top_builddir)/libsrc/libusbip.la
-sbin_PROGRAMS := usbip usbipd
+sbin_PROGRAMS := usbip usbipd in.usbipd
usbip_SOURCES := usbip.h utils.h usbip.c utils.c usbip_network.c \
usbip_attach.c usbip_detach.c usbip_list.c \
usbip_bind.c usbip_unbind.c usbip_port.c
usbipd_SOURCES := usbip_network.h usbipd.c usbip_network.c
+
+in_usbipd_SOURCES := usbip_network.h in.usbipd.c usbip_network.c
diff --git a/tools/usb/usbip/src/in.usbipd.c b/tools/usb/usbip/src/in.usbipd.c
new file mode 100644
index 000000000000..fc60f485fb4c
--- /dev/null
+++ b/tools/usb/usbip/src/in.usbipd.c
@@ -0,0 +1,326 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
+ * 2005-2007 Takahiro Hirofuchi
+ * Copyright (C) 2015-2016 Samsung Electronics
+ * Igor Kotrasinski <i.kotrasinsk@samsung.com>
+ * Krzysztof Opasiak <k.opasiak@samsung.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "../config.h"
+#endif
+
+#define _GNU_SOURCE
+
+#include <getopt.h>
+
+#include "usbip_host_driver.h"
+#include "usbip_device_driver.h"
+#include "usbip_network.h"
+
+#undef PROGNAME
+#define PROGNAME "in.usbipd"
+#define MAXSOCKFD 20
+
+#define MAIN_LOOP_TIMEOUT 10
+
+static const char usbip_version_string[] = PACKAGE_STRING;
+
+static const char in_usbipd_help_string[] =
+ "usage: in.usbipd [options]\n"
+ "\n"
+ " -e, --device\n"
+ " Run in device mode.\n"
+ " Rather than drive an attached device, create\n"
+ " a virtual UDC to bind gadgets to.\n"
+ "\n"
+ " -d, --debug\n"
+ " Print debugging information.\n"
+ "\n"
+ " -h, --help\n"
+ " Print this help.\n"
+ "\n"
+ " -v, --version\n"
+ " Show version.\n";
+
+static struct usbip_host_driver *driver;
+
+static void in_usbipd_help(void)
+{
+ printf("%s\n", in_usbipd_help_string);
+}
+
+static int recv_request_import(int sockfd)
+{
+ struct op_import_request req;
+ struct usbip_exported_device *edev;
+ struct usbip_usb_device pdu_udev;
+ struct list_head *i;
+ int found = 0;
+ int status = ST_OK;
+ int rc;
+
+ memset(&req, 0, sizeof(req));
+
+ rc = usbip_net_recv(sockfd, &req, sizeof(req));
+ if (rc < 0) {
+ dbg("usbip_net_recv failed: import request");
+ return -1;
+ }
+ PACK_OP_IMPORT_REQUEST(0, &req);
+
+ list_for_each(i, &driver->edev_list) {
+ edev = list_entry(i, struct usbip_exported_device, node);
+ if (!strncmp(req.busid, edev->udev.busid, SYSFS_BUS_ID_SIZE)) {
+ info("found requested device: %s", req.busid);
+ found = 1;
+ break;
+ }
+ }
+
+ if (found) {
+ /* should set TCP_NODELAY for usbip */
+ usbip_net_set_nodelay(sockfd);
+
+ /* export device needs a TCP/IP socket descriptor */
+ status = usbip_export_device(edev, sockfd);
+ if (status < 0)
+ status = ST_NA;
+ } else {
+ info("requested device not found: %s", req.busid);
+ status = ST_NODEV;
+ }
+
+ rc = usbip_net_send_op_common(sockfd, OP_REP_IMPORT, status);
+ if (rc < 0) {
+ dbg("usbip_net_send_op_common failed: %#0x", OP_REP_IMPORT);
+ return -1;
+ }
+
+ if (status) {
+ dbg("import request busid %s: failed", req.busid);
+ return -1;
+ }
+
+ memcpy(&pdu_udev, &edev->udev, sizeof(pdu_udev));
+ usbip_net_pack_usb_device(1, &pdu_udev);
+
+ rc = usbip_net_send(sockfd, &pdu_udev, sizeof(pdu_udev));
+ if (rc < 0) {
+ dbg("usbip_net_send failed: devinfo");
+ return -1;
+ }
+
+ dbg("import request busid %s: complete", req.busid);
+
+ return 0;
+}
+
+static int send_reply_devlist(int connfd)
+{
+ struct usbip_exported_device *edev;
+ struct usbip_usb_device pdu_udev;
+ struct usbip_usb_interface pdu_uinf;
+ struct op_devlist_reply reply;
+ struct list_head *j;
+ int rc, i;
+
+ /*
+ * Exclude devices that are already exported to a client from
+ * the exportable device list to avoid:
+ * - import requests for devices that are exported only to
+ * fail the request.
+ * - revealing devices that are imported by a client to
+ * another client.
+ */
+
+ reply.ndev = 0;
+ /* number of exported devices */
+ list_for_each(j, &driver->edev_list) {
+ edev = list_entry(j, struct usbip_exported_device, node);
+ if (edev->status != SDEV_ST_USED)
+ reply.ndev += 1;
+ }
+ info("exportable devices: %d", reply.ndev);
+
+ rc = usbip_net_send_op_common(connfd, OP_REP_DEVLIST, ST_OK);
+ if (rc < 0) {
+ dbg("usbip_net_send_op_common failed: %#0x", OP_REP_DEVLIST);
+ return -1;
+ }
+ PACK_OP_DEVLIST_REPLY(1, &reply);
+
+ rc = usbip_net_send(connfd, &reply, sizeof(reply));
+ if (rc < 0) {
+ dbg("usbip_net_send failed: %#0x", OP_REP_DEVLIST);
+ return -1;
+ }
+
+ list_for_each(j, &driver->edev_list) {
+ edev = list_entry(j, struct usbip_exported_device, node);
+ if (edev->status == SDEV_ST_USED)
+ continue;
+
+ dump_usb_device(&edev->udev);
+ memcpy(&pdu_udev, &edev->udev, sizeof(pdu_udev));
+ usbip_net_pack_usb_device(1, &pdu_udev);
+
+ rc = usbip_net_send(connfd, &pdu_udev, sizeof(pdu_udev));
+ if (rc < 0) {
+ dbg("usbip_net_send failed: pdu_udev");
+ return -1;
+ }
+
+ for (i = 0; i < edev->udev.bNumInterfaces; i++) {
+ dump_usb_interface(&edev->uinf[i]);
+ memcpy(&pdu_uinf, &edev->uinf[i], sizeof(pdu_uinf));
+ usbip_net_pack_usb_interface(1, &pdu_uinf);
+
+ rc = usbip_net_send(connfd, &pdu_uinf,
+ sizeof(pdu_uinf));
+ if (rc < 0) {
+ err("usbip_net_send failed: pdu_uinf");
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int recv_request_devlist(int connfd)
+{
+ struct op_devlist_request req;
+ int rc;
+
+ memset(&req, 0, sizeof(req));
+
+ rc = usbip_net_recv(connfd, &req, sizeof(req));
+ if (rc < 0) {
+ dbg("usbip_net_recv failed: devlist request");
+ return -1;
+ }
+
+ rc = send_reply_devlist(connfd);
+ if (rc < 0) {
+ dbg("send_reply_devlist failed");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int recv_pdu(int connfd)
+{
+ uint16_t code = OP_UNSPEC;
+ int ret;
+ int status;
+
+ ret = usbip_net_recv_op_common(connfd, &code, &status);
+ if (ret < 0) {
+ dbg("could not receive opcode: %#0x", code);
+ return -1;
+ }
+
+ ret = usbip_refresh_device_list(driver);
+ if (ret < 0) {
+ dbg("could not refresh device list: %d", ret);
+ return -1;
+ }
+
+ info("received request: %#0x(%d)", code, connfd);
+ switch (code) {
+ case OP_REQ_DEVLIST:
+ ret = recv_request_devlist(connfd);
+ break;
+ case OP_REQ_IMPORT:
+ ret = recv_request_import(connfd);
+ break;
+ case OP_REQ_DEVINFO:
+ case OP_REQ_CRYPKEY:
+ default:
+ err("received an unknown opcode: %#0x", code);
+ ret = -1;
+ }
+
+ if (ret == 0)
+ info("request %#0x(%d): complete", code, connfd);
+ else
+ info("request %#0x(%d): failed", code, connfd);
+
+ return ret;
+}
+
+int main(int argc, char *argv[])
+{
+ static const struct option longopts[] = {
+ { "debug", no_argument, NULL, 'd' },
+ { "device", no_argument, NULL, 'e' },
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, 'v' },
+ { NULL, 0, NULL, 0 }
+ };
+
+ enum {
+ cmd_standalone_mode = 1,
+ cmd_help,
+ cmd_version
+ } cmd;
+
+ int opt, rc = -1;
+
+ usbip_use_stderr = 1;
+ usbip_use_syslog = 0;
+
+ if (geteuid() != 0)
+ err("not running as root?");
+
+ cmd = cmd_standalone_mode;
+ driver = &host_driver;
+ for (;;) {
+ opt = getopt_long(argc, argv, "dehv", longopts, NULL);
+
+ if (opt == -1)
+ break;
+
+ switch (opt) {
+ case 'd':
+ usbip_use_debug = 1;
+ break;
+ case 'h':
+ cmd = cmd_help;
+ break;
+ case 'v':
+ cmd = cmd_version;
+ break;
+ case 'e':
+ driver = &device_driver;
+ break;
+ case '?':
+ in_usbipd_help();
+ default:
+ goto err_out;
+ }
+ }
+
+ switch (cmd) {
+ case cmd_standalone_mode:
+ rc = recv_pdu(0);
+ break;
+ case cmd_version:
+ printf(PROGNAME " (%s)\n", usbip_version_string);
+ rc = 0;
+ break;
+ case cmd_help:
+ in_usbipd_help();
+ rc = 0;
+ break;
+ default:
+ in_usbipd_help();
+ goto err_out;
+ }
+
+err_out:
+ return (rc > -1 ? EXIT_SUCCESS : EXIT_FAILURE);
+}
--
2.32.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [DEMO PATCH linux 2/3] usbip: tools: usbip: record protocol
2021-10-13 13:53 [DEMO PATCH linux 0/3] usbip: tools: support USB over vsock(7) Alyssa Ross
2021-10-13 13:53 ` [DEMO PATCH linux 1/3] usbip: tools: in.usbipd: add Alyssa Ross
@ 2021-10-13 13:53 ` Alyssa Ross
2021-10-13 13:53 ` [DEMO PATCH linux 3/3] usbip: tools: usbip: support vsock(7) connections Alyssa Ross
2 siblings, 0 replies; 4+ messages in thread
From: Alyssa Ross @ 2021-10-13 13:53 UTC (permalink / raw)
To: devel
This is the first step toward supporting protocol families other than
IP in the USB/IP client. This changes the format of the connection
records in the filesystem, so all USB/IP devices should be detached
before applying this change. The output format for "usbip port"
remains the same in the default case. If VSOCK is being used, it will
display URLs starting with usbvsock:// instead of usbip://.
Signed-off-by: Alyssa Ross <hi@alyssa.is>
---
tools/usb/usbip/libsrc/vhci_driver.c | 26 +++++++++++++------------
tools/usb/usbip/src/usbip_attach.c | 29 ++++++++++++++++++++++++----
2 files changed, 39 insertions(+), 16 deletions(-)
diff --git a/tools/usb/usbip/libsrc/vhci_driver.c b/tools/usb/usbip/libsrc/vhci_driver.c
index 8159fd98680b..98945078ccf4 100644
--- a/tools/usb/usbip/libsrc/vhci_driver.c
+++ b/tools/usb/usbip/libsrc/vhci_driver.c
@@ -184,16 +184,17 @@ static int get_ncontrollers(void)
* which is needed to properly validate the 3rd part without it being
* truncated to an acceptable length.
*/
-static int read_record(int rhport, char *host, unsigned long host_len,
- char *port, unsigned long port_len, char *busid)
+static int read_record(int rhport, char *proto, unsigned long proto_len,
+ char *host, unsigned long host_len, char *port,
+ unsigned long port_len, char *busid)
{
int part;
FILE *file;
char path[PATH_MAX+1];
char *buffer, *start, *end;
- char delim[] = {' ', ' ', '\n'};
- int max_len[] = {(int)host_len, (int)port_len, SYSFS_BUS_ID_SIZE};
- size_t buffer_len = host_len + port_len + SYSFS_BUS_ID_SIZE + 4;
+ char delim[] = {' ', ' ', ' ', '\n'};
+ int max_len[] = {(int)proto_len, (int)host_len, (int)port_len, SYSFS_BUS_ID_SIZE};
+ size_t buffer_len = proto_len + host_len + port_len + SYSFS_BUS_ID_SIZE + 5;
buffer = malloc(buffer_len);
if (!buffer)
@@ -218,7 +219,7 @@ static int read_record(int rhport, char *host, unsigned long host_len,
/* validate the length of each of the 3 parts */
start = buffer;
- for (part = 0; part < 3; part++) {
+ for (part = 0; part < 4; part++) {
end = strchr(start, delim[part]);
if (end == NULL || (end - start) > max_len[part]) {
free(buffer);
@@ -227,7 +228,7 @@ static int read_record(int rhport, char *host, unsigned long host_len,
start = end + 1;
}
- if (sscanf(buffer, "%s %s %s\n", host, port, busid) != 3) {
+ if (sscanf(buffer, "%s %s %s %s\n", proto, host, port, busid) != 4) {
err("sscanf");
free(buffer);
return -1;
@@ -426,6 +427,7 @@ int usbip_vhci_detach_device(uint8_t port)
int usbip_vhci_imported_device_dump(struct usbip_imported_device *idev)
{
char product_name[100];
+ char proto[] = "unknown protocol";
char host[NI_MAXHOST] = "unknown host";
char serv[NI_MAXSERV] = "unknown port";
char remote_busid[SYSFS_BUS_ID_SIZE];
@@ -435,8 +437,8 @@ int usbip_vhci_imported_device_dump(struct usbip_imported_device *idev)
if (idev->status == VDEV_ST_NULL || idev->status == VDEV_ST_NOTASSIGNED)
return 0;
- ret = read_record(idev->port, host, sizeof(host), serv, sizeof(serv),
- remote_busid);
+ ret = read_record(idev->port, proto, sizeof(proto), host, sizeof(host),
+ serv, sizeof(serv), remote_busid);
if (ret) {
err("read_record");
read_record_error = 1;
@@ -452,12 +454,12 @@ int usbip_vhci_imported_device_dump(struct usbip_imported_device *idev)
printf(" %s\n", product_name);
if (!read_record_error) {
- printf("%10s -> usbip://%s:%s/%s\n", idev->udev.busid,
- host, serv, remote_busid);
+ printf("%10s -> usb%s://%s:%s/%s\n", idev->udev.busid,
+ proto, host, serv, remote_busid);
printf("%10s -> remote bus/dev %03d/%03d\n", " ",
idev->busnum, idev->devnum);
} else {
- printf("%10s -> unknown host, remote port and remote busid\n",
+ printf("%10s -> unknown protocol, host, remote port and remote busid\n",
idev->udev.busid);
printf("%10s -> remote bus/dev %03d/%03d\n", " ",
idev->busnum, idev->devnum);
diff --git a/tools/usb/usbip/src/usbip_attach.c b/tools/usb/usbip/src/usbip_attach.c
index b4aeb9f1f493..b202c7513bc3 100644
--- a/tools/usb/usbip/src/usbip_attach.c
+++ b/tools/usb/usbip/src/usbip_attach.c
@@ -8,6 +8,7 @@
*/
#include <sys/stat.h>
+#include <sys/socket.h>
#include <limits.h>
#include <stdint.h>
@@ -36,7 +37,7 @@ void usbip_attach_usage(void)
}
#define MAX_BUFF 100
-static int record_connection(char *host, char *port, char *busid, int rhport)
+static int record_connection(char *proto, char *host, char *port, char *busid, int rhport)
{
int fd;
char path[PATH_MAX+1];
@@ -64,8 +65,8 @@ static int record_connection(char *host, char *port, char *busid, int rhport)
if (fd < 0)
return -1;
- snprintf(buff, MAX_BUFF, "%s %s %s\n",
- host, port, busid);
+ snprintf(buff, MAX_BUFF, "%s %s %s %s\n",
+ proto, host, port, busid);
ret = write(fd, buff, strlen(buff));
if (ret != (ssize_t) strlen(buff)) {
@@ -171,11 +172,28 @@ static int query_import_device(int sockfd, char *busid)
return import_device(sockfd, &reply.udev);
}
+static int get_protocol_family(int fd, char **proto)
+{
+ struct sockaddr addr;
+ socklen_t addrlen = sizeof addr;
+ if (getsockname(fd, &addr, &addrlen) == -1)
+ return -1;
+
+ switch (addr.sa_family) {
+ case AF_INET:
+ case AF_INET6:
+ *proto = "ip";
+ return 0;
+ }
+ return -1;
+}
+
static int attach_device(char *host, char *busid)
{
int sockfd;
int rc;
int rhport;
+ char *pf;
sockfd = usbip_net_tcp_connect(host, usbip_port_string);
if (sockfd < 0) {
@@ -183,13 +201,16 @@ static int attach_device(char *host, char *busid)
return -1;
}
+ if (get_protocol_family(sockfd, &pf) == -1)
+ return -1;
+
rhport = query_import_device(sockfd, busid);
if (rhport < 0)
return -1;
close(sockfd);
- rc = record_connection(host, usbip_port_string, busid, rhport);
+ rc = record_connection(pf, host, usbip_port_string, busid, rhport);
if (rc < 0) {
err("record connection");
return -1;
--
2.32.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [DEMO PATCH linux 3/3] usbip: tools: usbip: support vsock(7) connections
2021-10-13 13:53 [DEMO PATCH linux 0/3] usbip: tools: support USB over vsock(7) Alyssa Ross
2021-10-13 13:53 ` [DEMO PATCH linux 1/3] usbip: tools: in.usbipd: add Alyssa Ross
2021-10-13 13:53 ` [DEMO PATCH linux 2/3] usbip: tools: usbip: record protocol Alyssa Ross
@ 2021-10-13 13:53 ` Alyssa Ross
2 siblings, 0 replies; 4+ messages in thread
From: Alyssa Ross @ 2021-10-13 13:53 UTC (permalink / raw)
To: devel
"usbip list" and "usbip attach" can now both be given a "-P vsock" to
tell them to use vsock sockets instead of ip sockets.
Signed-off-by: Alyssa Ross <hi@alyssa.is>
---
tools/usb/usbip/src/usbip_attach.c | 25 +++++++++-----
tools/usb/usbip/src/usbip_list.c | 43 +++++++++++++++++-------
tools/usb/usbip/src/usbip_network.c | 51 ++++++++++++++++++++++++++++-
tools/usb/usbip/src/usbip_network.h | 4 ++-
4 files changed, 102 insertions(+), 21 deletions(-)
diff --git a/tools/usb/usbip/src/usbip_attach.c b/tools/usb/usbip/src/usbip_attach.c
index b202c7513bc3..74adf9f09d01 100644
--- a/tools/usb/usbip/src/usbip_attach.c
+++ b/tools/usb/usbip/src/usbip_attach.c
@@ -26,10 +26,11 @@
#include "usbip.h"
static const char usbip_attach_usage_string[] =
- "usbip attach <args>\n"
- " -r, --remote=<host> The machine with exported USB devices\n"
+ "usbip attach [-P|--proto] <args>\n"
+ " -P, --proto Protocol family (ip or vsock)\n"
+ " -r, --remote=<host> The machine with exported USB devices\n"
" -b, --busid=<busid> Busid of the device on <host>\n"
- " -d, --device=<devid> Id of the virtual UDC on <host>\n";
+ " -d, --device=<devid> Id of the virtual UDC on <host>\n";
void usbip_attach_usage(void)
{
@@ -184,20 +185,23 @@ static int get_protocol_family(int fd, char **proto)
case AF_INET6:
*proto = "ip";
return 0;
+ case AF_VSOCK:
+ *proto = "vsock";
+ return 0;
}
return -1;
}
-static int attach_device(char *host, char *busid)
+static int attach_device(char *proto, char *host, char *busid)
{
int sockfd;
int rc;
int rhport;
char *pf;
- sockfd = usbip_net_tcp_connect(host, usbip_port_string);
+ sockfd = usbip_net_connect(proto, host, usbip_port_string);
if (sockfd < 0) {
- err("tcp connect");
+ err("connect");
return -1;
}
@@ -222,23 +226,28 @@ static int attach_device(char *host, char *busid)
int usbip_attach(int argc, char *argv[])
{
static const struct option opts[] = {
+ { "proto", required_argument, NULL, 'P' },
{ "remote", required_argument, NULL, 'r' },
{ "busid", required_argument, NULL, 'b' },
{ "device", required_argument, NULL, 'd' },
{ NULL, 0, NULL, 0 }
};
+ char *proto = NULL;
char *host = NULL;
char *busid = NULL;
int opt;
int ret = -1;
for (;;) {
- opt = getopt_long(argc, argv, "d:r:b:", opts, NULL);
+ opt = getopt_long(argc, argv, "P:d:r:b:", opts, NULL);
if (opt == -1)
break;
switch (opt) {
+ case 'P':
+ proto = optarg;
+ break;
case 'r':
host = optarg;
break;
@@ -254,7 +263,7 @@ int usbip_attach(int argc, char *argv[])
if (!host || !busid)
goto err_out;
- ret = attach_device(host, busid);
+ ret = attach_device(proto, host, busid);
goto out;
err_out:
diff --git a/tools/usb/usbip/src/usbip_list.c b/tools/usb/usbip/src/usbip_list.c
index 3d810bcca02f..f479e15f9ae7 100644
--- a/tools/usb/usbip/src/usbip_list.c
+++ b/tools/usb/usbip/src/usbip_list.c
@@ -30,7 +30,8 @@
#include "usbip.h"
static const char usbip_list_usage_string[] =
- "usbip list [-p|--parsable] <args>\n"
+ "usbip list [-P|--proto] [-p|--parsable] <args>\n"
+ " -P, --proto Protocol family (ip or vsock)\n"
" -p, --parsable Parsable list format\n"
" -r, --remote=<host> List the exportable USB devices on <host>\n"
" -l, --local List the local USB devices\n"
@@ -125,12 +126,12 @@ static int get_exported_devices(char *host, int sockfd)
return 0;
}
-static int list_exported_devices(char *host)
+static int list_exported_devices(char *proto, char *host)
{
int rc;
int sockfd;
- sockfd = usbip_net_tcp_connect(host, usbip_port_string);
+ sockfd = usbip_net_connect(proto, host, usbip_port_string);
if (sockfd < 0) {
err("could not connect to %s:%s: %s", host,
usbip_port_string, gai_strerror(sockfd));
@@ -326,44 +327,64 @@ static int list_gadget_devices(bool parsable)
int usbip_list(int argc, char *argv[])
{
static const struct option opts[] = {
+ { "proto", required_argument, NULL, 'P' },
{ "parsable", no_argument, NULL, 'p' },
{ "remote", required_argument, NULL, 'r' },
{ "local", no_argument, NULL, 'l' },
- { "device", no_argument, NULL, 'd' },
+ { "device", no_argument, NULL, 'd' },
{ NULL, 0, NULL, 0 }
};
bool parsable = false;
+ char *proto = NULL, *host = NULL;
int opt;
+ int mode = -1;
int ret = -1;
if (usbip_names_init(USBIDS_FILE))
err("failed to open %s", USBIDS_FILE);
for (;;) {
- opt = getopt_long(argc, argv, "pr:ld", opts, NULL);
+ opt = getopt_long(argc, argv, "P:pr:ld", opts, NULL);
if (opt == -1)
break;
switch (opt) {
+ case 'P':
+ proto = optarg;
+ break;
case 'p':
parsable = true;
break;
case 'r':
- ret = list_exported_devices(optarg);
- goto out;
+ host = optarg;
+ /* fall through */
case 'l':
- ret = list_devices(parsable);
- goto out;
case 'd':
- ret = list_gadget_devices(parsable);
- goto out;
+ if (mode != -1) {
+ err("-%c and -%c are mutually exclusive", mode, opt);
+ goto out;
+ }
+ mode = opt;
+ break;
default:
goto err_out;
}
}
+ switch (mode) {
+ case 'r':
+ ret = list_exported_devices(proto, host);
+ goto out;
+ case 'l':
+ ret = list_devices(parsable);
+ goto out;
+ case 'd':
+ ret = list_gadget_devices(parsable);
+ goto out;
+ }
+
err_out:
usbip_list_usage();
out:
diff --git a/tools/usb/usbip/src/usbip_network.c b/tools/usb/usbip/src/usbip_network.c
index ed4dc8c14269..c096dbb6afb3 100644
--- a/tools/usb/usbip/src/usbip_network.c
+++ b/tools/usb/usbip/src/usbip_network.c
@@ -9,10 +9,14 @@
#include <string.h>
#include <arpa/inet.h>
+#include <errno.h>
+#include <limits.h>
#include <netdb.h>
#include <netinet/tcp.h>
#include <unistd.h>
+#include <linux/vm_sockets.h>
+
#ifdef HAVE_LIBWRAP
#include <tcpd.h>
#endif
@@ -258,7 +262,7 @@ int usbip_net_set_v6only(int sockfd)
/*
* IPv6 Ready
*/
-int usbip_net_tcp_connect(char *hostname, char *service)
+int usbip_net_ip_connect(char *hostname, char *service)
{
struct addrinfo hints, *res, *rp;
int sockfd;
@@ -301,3 +305,48 @@ int usbip_net_tcp_connect(char *hostname, char *service)
return sockfd;
}
+
+int usbip_net_vsock_connect(char *cid_s, char *port_s)
+{
+ char *cid_end, *port_end;
+ int sockfd;
+ unsigned long cid, port;
+ struct sockaddr_vm addr = { 0 };
+ socklen_t addrlen = sizeof addr;
+
+ errno = 0;
+ cid = strtoul(cid_s, &cid_end, 0);
+ port = strtoul(port_s, &port_end, 0);
+ if (*cid_end || *port_end) {
+ errno = EINVAL;
+ return EAI_SYSTEM;
+ }
+ if (errno)
+ return EAI_SYSTEM;
+ if (cid > UINT_MAX || port > UINT_MAX) {
+ errno = ERANGE;
+ return EAI_SYSTEM;
+ }
+
+ addr.svm_family = AF_VSOCK;
+ addr.svm_port = port;
+ addr.svm_cid = cid;
+
+ sockfd = socket(AF_VSOCK, SOCK_STREAM, 0);
+ if (sockfd == -1)
+ return EAI_SYSTEM;
+ if (connect(sockfd, (struct sockaddr *)&addr, addrlen) == -1)
+ return EAI_SYSTEM;
+ return sockfd;
+}
+
+int usbip_net_connect(char *proto, char *host, char *service)
+{
+ if (!proto || !strcmp(proto, "ip"))
+ return usbip_net_ip_connect(host, service);
+ if (!strcmp(proto, "vsock"))
+ return usbip_net_vsock_connect(host, service);
+
+ errno = EPROTONOSUPPORT;
+ return EAI_SYSTEM;
+}
diff --git a/tools/usb/usbip/src/usbip_network.h b/tools/usb/usbip/src/usbip_network.h
index 83b4c5344f72..fc2579525bc3 100644
--- a/tools/usb/usbip/src/usbip_network.h
+++ b/tools/usb/usbip/src/usbip_network.h
@@ -173,6 +173,8 @@ int usbip_net_set_reuseaddr(int sockfd);
int usbip_net_set_nodelay(int sockfd);
int usbip_net_set_keepalive(int sockfd);
int usbip_net_set_v6only(int sockfd);
-int usbip_net_tcp_connect(char *hostname, char *port);
+int usbip_net_ip_connect(char *hostname, char *port);
+int usbip_net_vsock_connect(char *cid, char *port);
+int usbip_net_connect(char *proto, char *host, char *port);
#endif /* __USBIP_NETWORK_H */
--
2.32.0
^ permalink raw reply [flat|nested] 4+ messages in thread