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_unbind.c (2892B)


      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 */
      6
      7#include <libudev.h>
      8
      9#include <errno.h>
     10#include <stdio.h>
     11#include <string.h>
     12
     13#include <getopt.h>
     14
     15#include "usbip_common.h"
     16#include "utils.h"
     17#include "usbip.h"
     18#include "sysfs_utils.h"
     19
     20static const char usbip_unbind_usage_string[] =
     21	"usbip unbind <args>\n"
     22	"    -b, --busid=<busid>    Unbind " USBIP_HOST_DRV_NAME ".ko from "
     23	"device on <busid>\n";
     24
     25void usbip_unbind_usage(void)
     26{
     27	printf("usage: %s", usbip_unbind_usage_string);
     28}
     29
     30static int unbind_device(char *busid)
     31{
     32	char bus_type[] = "usb";
     33	int rc, ret = -1;
     34
     35	char unbind_attr_name[] = "unbind";
     36	char unbind_attr_path[SYSFS_PATH_MAX];
     37	char rebind_attr_name[] = "rebind";
     38	char rebind_attr_path[SYSFS_PATH_MAX];
     39
     40	struct udev *udev;
     41	struct udev_device *dev;
     42	const char *driver;
     43
     44	/* Create libudev context. */
     45	udev = udev_new();
     46
     47	/* Check whether the device with this bus ID exists. */
     48	dev = udev_device_new_from_subsystem_sysname(udev, "usb", busid);
     49	if (!dev) {
     50		err("device with the specified bus ID does not exist");
     51		goto err_close_udev;
     52	}
     53
     54	/* Check whether the device is using usbip-host driver. */
     55	driver = udev_device_get_driver(dev);
     56	if (!driver || strcmp(driver, "usbip-host")) {
     57		err("device is not bound to usbip-host driver");
     58		goto err_close_udev;
     59	}
     60
     61	/* Unbind device from driver. */
     62	snprintf(unbind_attr_path, sizeof(unbind_attr_path), "%s/%s/%s/%s/%s/%s",
     63		 SYSFS_MNT_PATH, SYSFS_BUS_NAME, bus_type, SYSFS_DRIVERS_NAME,
     64		 USBIP_HOST_DRV_NAME, unbind_attr_name);
     65
     66	rc = write_sysfs_attribute(unbind_attr_path, busid, strlen(busid));
     67	if (rc < 0) {
     68		err("error unbinding device %s from driver", busid);
     69		goto err_close_udev;
     70	}
     71
     72	/* Notify driver of unbind. */
     73	rc = modify_match_busid(busid, 0);
     74	if (rc < 0) {
     75		err("unable to unbind device on %s", busid);
     76		goto err_close_udev;
     77	}
     78
     79	/* Trigger new probing. */
     80	snprintf(rebind_attr_path, sizeof(unbind_attr_path), "%s/%s/%s/%s/%s/%s",
     81			SYSFS_MNT_PATH, SYSFS_BUS_NAME, bus_type, SYSFS_DRIVERS_NAME,
     82			USBIP_HOST_DRV_NAME, rebind_attr_name);
     83
     84	rc = write_sysfs_attribute(rebind_attr_path, busid, strlen(busid));
     85	if (rc < 0) {
     86		err("error rebinding");
     87		goto err_close_udev;
     88	}
     89
     90	ret = 0;
     91	info("unbind device on busid %s: complete", busid);
     92
     93err_close_udev:
     94	udev_device_unref(dev);
     95	udev_unref(udev);
     96
     97	return ret;
     98}
     99
    100int usbip_unbind(int argc, char *argv[])
    101{
    102	static const struct option opts[] = {
    103		{ "busid", required_argument, NULL, 'b' },
    104		{ NULL,    0,                 NULL,  0  }
    105	};
    106
    107	int opt;
    108	int ret = -1;
    109
    110	for (;;) {
    111		opt = getopt_long(argc, argv, "b:", opts, NULL);
    112
    113		if (opt == -1)
    114			break;
    115
    116		switch (opt) {
    117		case 'b':
    118			ret = unbind_device(optarg);
    119			goto out;
    120		default:
    121			goto err_out;
    122		}
    123	}
    124
    125err_out:
    126	usbip_unbind_usage();
    127out:
    128	return ret;
    129}