"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