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_list.c (9190B)


      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/types.h>
     11#include <libudev.h>
     12
     13#include <errno.h>
     14#include <stdbool.h>
     15#include <stdint.h>
     16#include <stdio.h>
     17#include <stdlib.h>
     18#include <string.h>
     19
     20#include <getopt.h>
     21#include <netdb.h>
     22#include <unistd.h>
     23
     24#include <dirent.h>
     25
     26#include <linux/usb/ch9.h>
     27
     28#include "usbip_common.h"
     29#include "usbip_network.h"
     30#include "usbip.h"
     31
     32static const char usbip_list_usage_string[] =
     33	"usbip list [-p|--parsable] <args>\n"
     34	"    -p, --parsable         Parsable list format\n"
     35	"    -r, --remote=<host>    List the exportable USB devices on <host>\n"
     36	"    -l, --local            List the local USB devices\n"
     37	"    -d, --device           List the local USB gadgets bound to usbip-vudc\n";
     38
     39void usbip_list_usage(void)
     40{
     41	printf("usage: %s", usbip_list_usage_string);
     42}
     43
     44static int get_exported_devices(char *host, int sockfd)
     45{
     46	char product_name[100];
     47	char class_name[100];
     48	struct op_devlist_reply reply;
     49	uint16_t code = OP_REP_DEVLIST;
     50	struct usbip_usb_device udev;
     51	struct usbip_usb_interface uintf;
     52	unsigned int i;
     53	int rc, j;
     54	int status;
     55
     56	rc = usbip_net_send_op_common(sockfd, OP_REQ_DEVLIST, 0);
     57	if (rc < 0) {
     58		dbg("usbip_net_send_op_common failed");
     59		return -1;
     60	}
     61
     62	rc = usbip_net_recv_op_common(sockfd, &code, &status);
     63	if (rc < 0) {
     64		err("Exported Device List Request failed - %s\n",
     65		    usbip_op_common_status_string(status));
     66		return -1;
     67	}
     68
     69	memset(&reply, 0, sizeof(reply));
     70	rc = usbip_net_recv(sockfd, &reply, sizeof(reply));
     71	if (rc < 0) {
     72		dbg("usbip_net_recv_op_devlist failed");
     73		return -1;
     74	}
     75	PACK_OP_DEVLIST_REPLY(0, &reply);
     76	dbg("exportable devices: %d\n", reply.ndev);
     77
     78	if (reply.ndev == 0) {
     79		info("no exportable devices found on %s", host);
     80		return 0;
     81	}
     82
     83	printf("Exportable USB devices\n");
     84	printf("======================\n");
     85	printf(" - %s\n", host);
     86
     87	for (i = 0; i < reply.ndev; i++) {
     88		memset(&udev, 0, sizeof(udev));
     89		rc = usbip_net_recv(sockfd, &udev, sizeof(udev));
     90		if (rc < 0) {
     91			dbg("usbip_net_recv failed: usbip_usb_device[%d]", i);
     92			return -1;
     93		}
     94		usbip_net_pack_usb_device(0, &udev);
     95
     96		usbip_names_get_product(product_name, sizeof(product_name),
     97					udev.idVendor, udev.idProduct);
     98		usbip_names_get_class(class_name, sizeof(class_name),
     99				      udev.bDeviceClass, udev.bDeviceSubClass,
    100				      udev.bDeviceProtocol);
    101		printf("%11s: %s\n", udev.busid, product_name);
    102		printf("%11s: %s\n", "", udev.path);
    103		printf("%11s: %s\n", "", class_name);
    104
    105		for (j = 0; j < udev.bNumInterfaces; j++) {
    106			rc = usbip_net_recv(sockfd, &uintf, sizeof(uintf));
    107			if (rc < 0) {
    108				err("usbip_net_recv failed: usbip_usb_intf[%d]",
    109						j);
    110
    111				return -1;
    112			}
    113			usbip_net_pack_usb_interface(0, &uintf);
    114
    115			usbip_names_get_class(class_name, sizeof(class_name),
    116					uintf.bInterfaceClass,
    117					uintf.bInterfaceSubClass,
    118					uintf.bInterfaceProtocol);
    119			printf("%11s: %2d - %s\n", "", j, class_name);
    120		}
    121
    122		printf("\n");
    123	}
    124
    125	return 0;
    126}
    127
    128static int list_exported_devices(char *host)
    129{
    130	int rc;
    131	int sockfd;
    132
    133	sockfd = usbip_net_tcp_connect(host, usbip_port_string);
    134	if (sockfd < 0) {
    135		err("could not connect to %s:%s: %s", host,
    136		    usbip_port_string, gai_strerror(sockfd));
    137		return -1;
    138	}
    139	dbg("connected to %s:%s", host, usbip_port_string);
    140
    141	rc = get_exported_devices(host, sockfd);
    142	if (rc < 0) {
    143		err("failed to get device list from %s", host);
    144		return -1;
    145	}
    146
    147	close(sockfd);
    148
    149	return 0;
    150}
    151
    152static void print_device(const char *busid, const char *vendor,
    153			 const char *product, bool parsable)
    154{
    155	if (parsable)
    156		printf("busid=%s#usbid=%.4s:%.4s#", busid, vendor, product);
    157	else
    158		printf(" - busid %s (%.4s:%.4s)\n", busid, vendor, product);
    159}
    160
    161static void print_product_name(char *product_name, bool parsable)
    162{
    163	if (!parsable)
    164		printf("   %s\n", product_name);
    165}
    166
    167static int list_devices(bool parsable)
    168{
    169	struct udev *udev;
    170	struct udev_enumerate *enumerate;
    171	struct udev_list_entry *devices, *dev_list_entry;
    172	struct udev_device *dev;
    173	const char *path;
    174	const char *idVendor;
    175	const char *idProduct;
    176	const char *bConfValue;
    177	const char *bNumIntfs;
    178	const char *busid;
    179	char product_name[128];
    180	int ret = -1;
    181	const char *devpath;
    182
    183	/* Create libudev context. */
    184	udev = udev_new();
    185
    186	/* Create libudev device enumeration. */
    187	enumerate = udev_enumerate_new(udev);
    188
    189	/* Take only USB devices that are not hubs and do not have
    190	 * the bInterfaceNumber attribute, i.e. are not interfaces.
    191	 */
    192	udev_enumerate_add_match_subsystem(enumerate, "usb");
    193	udev_enumerate_add_nomatch_sysattr(enumerate, "bDeviceClass", "09");
    194	udev_enumerate_add_nomatch_sysattr(enumerate, "bInterfaceNumber", NULL);
    195	udev_enumerate_scan_devices(enumerate);
    196
    197	devices = udev_enumerate_get_list_entry(enumerate);
    198
    199	/* Show information about each device. */
    200	udev_list_entry_foreach(dev_list_entry, devices) {
    201		path = udev_list_entry_get_name(dev_list_entry);
    202		dev = udev_device_new_from_syspath(udev, path);
    203
    204		/* Ignore devices attached to vhci_hcd */
    205		devpath = udev_device_get_devpath(dev);
    206		if (strstr(devpath, USBIP_VHCI_DRV_NAME)) {
    207			dbg("Skip the device %s already attached to %s\n",
    208			    devpath, USBIP_VHCI_DRV_NAME);
    209			continue;
    210		}
    211
    212		/* Get device information. */
    213		idVendor = udev_device_get_sysattr_value(dev, "idVendor");
    214		idProduct = udev_device_get_sysattr_value(dev, "idProduct");
    215		bConfValue = udev_device_get_sysattr_value(dev,
    216				"bConfigurationValue");
    217		bNumIntfs = udev_device_get_sysattr_value(dev,
    218				"bNumInterfaces");
    219		busid = udev_device_get_sysname(dev);
    220		if (!idVendor || !idProduct || !bConfValue || !bNumIntfs) {
    221			err("problem getting device attributes: %s",
    222			    strerror(errno));
    223			goto err_out;
    224		}
    225
    226		/* Get product name. */
    227		usbip_names_get_product(product_name, sizeof(product_name),
    228					strtol(idVendor, NULL, 16),
    229					strtol(idProduct, NULL, 16));
    230
    231		/* Print information. */
    232		print_device(busid, idVendor, idProduct, parsable);
    233		print_product_name(product_name, parsable);
    234
    235		printf("\n");
    236
    237		udev_device_unref(dev);
    238	}
    239
    240	ret = 0;
    241
    242err_out:
    243	udev_enumerate_unref(enumerate);
    244	udev_unref(udev);
    245
    246	return ret;
    247}
    248
    249static int list_gadget_devices(bool parsable)
    250{
    251	int ret = -1;
    252	struct udev *udev;
    253	struct udev_enumerate *enumerate;
    254	struct udev_list_entry *devices, *dev_list_entry;
    255	struct udev_device *dev;
    256	const char *path;
    257	const char *driver;
    258
    259	const struct usb_device_descriptor *d_desc;
    260	const char *descriptors;
    261	char product_name[128];
    262
    263	uint16_t idVendor;
    264	char idVendor_buf[8];
    265	uint16_t idProduct;
    266	char idProduct_buf[8];
    267	const char *busid;
    268
    269	udev = udev_new();
    270	enumerate = udev_enumerate_new(udev);
    271
    272	udev_enumerate_add_match_subsystem(enumerate, "platform");
    273
    274	udev_enumerate_scan_devices(enumerate);
    275	devices = udev_enumerate_get_list_entry(enumerate);
    276
    277	udev_list_entry_foreach(dev_list_entry, devices) {
    278		path = udev_list_entry_get_name(dev_list_entry);
    279		dev = udev_device_new_from_syspath(udev, path);
    280
    281		driver = udev_device_get_driver(dev);
    282		/* We only have mechanism to enumerate gadgets bound to vudc */
    283		if (driver == NULL || strcmp(driver, USBIP_DEVICE_DRV_NAME))
    284			continue;
    285
    286		/* Get device information. */
    287		descriptors = udev_device_get_sysattr_value(dev,
    288				VUDC_DEVICE_DESCR_FILE);
    289
    290		if (!descriptors) {
    291			err("problem getting device attributes: %s",
    292			    strerror(errno));
    293			goto err_out;
    294		}
    295
    296		d_desc = (const struct usb_device_descriptor *) descriptors;
    297
    298		idVendor = le16toh(d_desc->idVendor);
    299		sprintf(idVendor_buf, "0x%4x", idVendor);
    300		idProduct = le16toh(d_desc->idProduct);
    301		sprintf(idProduct_buf, "0x%4x", idVendor);
    302		busid = udev_device_get_sysname(dev);
    303
    304		/* Get product name. */
    305		usbip_names_get_product(product_name, sizeof(product_name),
    306					le16toh(idVendor),
    307					le16toh(idProduct));
    308
    309		/* Print information. */
    310		print_device(busid, idVendor_buf, idProduct_buf, parsable);
    311		print_product_name(product_name, parsable);
    312
    313		printf("\n");
    314
    315		udev_device_unref(dev);
    316	}
    317	ret = 0;
    318
    319err_out:
    320	udev_enumerate_unref(enumerate);
    321	udev_unref(udev);
    322
    323	return ret;
    324}
    325
    326int usbip_list(int argc, char *argv[])
    327{
    328	static const struct option opts[] = {
    329		{ "parsable", no_argument,       NULL, 'p' },
    330		{ "remote",   required_argument, NULL, 'r' },
    331		{ "local",    no_argument,       NULL, 'l' },
    332		{ "device",    no_argument,       NULL, 'd' },
    333		{ NULL,       0,                 NULL,  0  }
    334	};
    335
    336	bool parsable = false;
    337	int opt;
    338	int ret = -1;
    339
    340	if (usbip_names_init(USBIDS_FILE))
    341		err("failed to open %s", USBIDS_FILE);
    342
    343	for (;;) {
    344		opt = getopt_long(argc, argv, "pr:ld", opts, NULL);
    345
    346		if (opt == -1)
    347			break;
    348
    349		switch (opt) {
    350		case 'p':
    351			parsable = true;
    352			break;
    353		case 'r':
    354			ret = list_exported_devices(optarg);
    355			goto out;
    356		case 'l':
    357			ret = list_devices(parsable);
    358			goto out;
    359		case 'd':
    360			ret = list_gadget_devices(parsable);
    361			goto out;
    362		default:
    363			goto err_out;
    364		}
    365	}
    366
    367err_out:
    368	usbip_list_usage();
    369out:
    370	usbip_names_free();
    371
    372	return ret;
    373}