cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

usbip_attach.c (4802B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
      4 *               2005-2007 Takahiro Hirofuchi
      5 * Copyright (C) 2015-2016 Samsung Electronics
      6 *               Igor Kotrasinski <i.kotrasinsk@samsung.com>
      7 *               Krzysztof Opasiak <k.opasiak@samsung.com>
      8 */
      9
     10#include <sys/stat.h>
     11
     12#include <limits.h>
     13#include <stdint.h>
     14#include <stdio.h>
     15#include <string.h>
     16
     17#include <fcntl.h>
     18#include <getopt.h>
     19#include <unistd.h>
     20#include <errno.h>
     21
     22#include "vhci_driver.h"
     23#include "usbip_common.h"
     24#include "usbip_network.h"
     25#include "usbip.h"
     26
     27static const char usbip_attach_usage_string[] =
     28	"usbip attach <args>\n"
     29	"    -r, --remote=<host>      The machine with exported USB devices\n"
     30	"    -b, --busid=<busid>    Busid of the device on <host>\n"
     31	"    -d, --device=<devid>    Id of the virtual UDC on <host>\n";
     32
     33void usbip_attach_usage(void)
     34{
     35	printf("usage: %s", usbip_attach_usage_string);
     36}
     37
     38#define MAX_BUFF 100
     39static int record_connection(char *host, char *port, char *busid, int rhport)
     40{
     41	int fd;
     42	char path[PATH_MAX+1];
     43	char buff[MAX_BUFF+1];
     44	int ret;
     45
     46	ret = mkdir(VHCI_STATE_PATH, 0700);
     47	if (ret < 0) {
     48		/* if VHCI_STATE_PATH exists, then it better be a directory */
     49		if (errno == EEXIST) {
     50			struct stat s;
     51
     52			ret = stat(VHCI_STATE_PATH, &s);
     53			if (ret < 0)
     54				return -1;
     55			if (!(s.st_mode & S_IFDIR))
     56				return -1;
     57		} else
     58			return -1;
     59	}
     60
     61	snprintf(path, PATH_MAX, VHCI_STATE_PATH"/port%d", rhport);
     62
     63	fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU);
     64	if (fd < 0)
     65		return -1;
     66
     67	snprintf(buff, MAX_BUFF, "%s %s %s\n",
     68			host, port, busid);
     69
     70	ret = write(fd, buff, strlen(buff));
     71	if (ret != (ssize_t) strlen(buff)) {
     72		close(fd);
     73		return -1;
     74	}
     75
     76	close(fd);
     77
     78	return 0;
     79}
     80
     81static int import_device(int sockfd, struct usbip_usb_device *udev)
     82{
     83	int rc;
     84	int port;
     85	uint32_t speed = udev->speed;
     86
     87	rc = usbip_vhci_driver_open();
     88	if (rc < 0) {
     89		err("open vhci_driver");
     90		goto err_out;
     91	}
     92
     93	do {
     94		port = usbip_vhci_get_free_port(speed);
     95		if (port < 0) {
     96			err("no free port");
     97			goto err_driver_close;
     98		}
     99
    100		dbg("got free port %d", port);
    101
    102		rc = usbip_vhci_attach_device(port, sockfd, udev->busnum,
    103					      udev->devnum, udev->speed);
    104		if (rc < 0 && errno != EBUSY) {
    105			err("import device");
    106			goto err_driver_close;
    107		}
    108	} while (rc < 0);
    109
    110	usbip_vhci_driver_close();
    111
    112	return port;
    113
    114err_driver_close:
    115	usbip_vhci_driver_close();
    116err_out:
    117	return -1;
    118}
    119
    120static int query_import_device(int sockfd, char *busid)
    121{
    122	int rc;
    123	struct op_import_request request;
    124	struct op_import_reply   reply;
    125	uint16_t code = OP_REP_IMPORT;
    126	int status;
    127
    128	memset(&request, 0, sizeof(request));
    129	memset(&reply, 0, sizeof(reply));
    130
    131	/* send a request */
    132	rc = usbip_net_send_op_common(sockfd, OP_REQ_IMPORT, 0);
    133	if (rc < 0) {
    134		err("send op_common");
    135		return -1;
    136	}
    137
    138	strncpy(request.busid, busid, SYSFS_BUS_ID_SIZE-1);
    139
    140	PACK_OP_IMPORT_REQUEST(0, &request);
    141
    142	rc = usbip_net_send(sockfd, (void *) &request, sizeof(request));
    143	if (rc < 0) {
    144		err("send op_import_request");
    145		return -1;
    146	}
    147
    148	/* receive a reply */
    149	rc = usbip_net_recv_op_common(sockfd, &code, &status);
    150	if (rc < 0) {
    151		err("Attach Request for %s failed - %s\n",
    152		    busid, usbip_op_common_status_string(status));
    153		return -1;
    154	}
    155
    156	rc = usbip_net_recv(sockfd, (void *) &reply, sizeof(reply));
    157	if (rc < 0) {
    158		err("recv op_import_reply");
    159		return -1;
    160	}
    161
    162	PACK_OP_IMPORT_REPLY(0, &reply);
    163
    164	/* check the reply */
    165	if (strncmp(reply.udev.busid, busid, SYSFS_BUS_ID_SIZE)) {
    166		err("recv different busid %s", reply.udev.busid);
    167		return -1;
    168	}
    169
    170	/* import a device */
    171	return import_device(sockfd, &reply.udev);
    172}
    173
    174static int attach_device(char *host, char *busid)
    175{
    176	int sockfd;
    177	int rc;
    178	int rhport;
    179
    180	sockfd = usbip_net_tcp_connect(host, usbip_port_string);
    181	if (sockfd < 0) {
    182		err("tcp connect");
    183		return -1;
    184	}
    185
    186	rhport = query_import_device(sockfd, busid);
    187	if (rhport < 0)
    188		return -1;
    189
    190	close(sockfd);
    191
    192	rc = record_connection(host, usbip_port_string, busid, rhport);
    193	if (rc < 0) {
    194		err("record connection");
    195		return -1;
    196	}
    197
    198	return 0;
    199}
    200
    201int usbip_attach(int argc, char *argv[])
    202{
    203	static const struct option opts[] = {
    204		{ "remote", required_argument, NULL, 'r' },
    205		{ "busid",  required_argument, NULL, 'b' },
    206		{ "device",  required_argument, NULL, 'd' },
    207		{ NULL, 0,  NULL, 0 }
    208	};
    209	char *host = NULL;
    210	char *busid = NULL;
    211	int opt;
    212	int ret = -1;
    213
    214	for (;;) {
    215		opt = getopt_long(argc, argv, "d:r:b:", opts, NULL);
    216
    217		if (opt == -1)
    218			break;
    219
    220		switch (opt) {
    221		case 'r':
    222			host = optarg;
    223			break;
    224		case 'd':
    225		case 'b':
    226			busid = optarg;
    227			break;
    228		default:
    229			goto err_out;
    230		}
    231	}
    232
    233	if (!host || !busid)
    234		goto err_out;
    235
    236	ret = attach_device(host, busid);
    237	goto out;
    238
    239err_out:
    240	usbip_attach_usage();
    241out:
    242	return ret;
    243}