|
Hans de Goede |
1b1995 |
From bcc4748db3e991fbaa032fe9c0726288a8f1008d Mon Sep 17 00:00:00 2001
|
|
Hans de Goede |
1b1995 |
From: Hans de Goede <hdegoede@redhat.com>
|
|
Hans de Goede |
1b1995 |
Date: Thu, 12 Jan 2012 16:54:04 +0100
|
|
Hans de Goede |
1b1995 |
Subject: [PATCH 120/140] usb-redir: Add the posibility to filter out certain
|
|
Hans de Goede |
1b1995 |
devices from redirecion
|
|
Hans de Goede |
1b1995 |
|
|
Hans de Goede |
1b1995 |
This patch adds the posibility to filter out certain devices from redirecion.
|
|
Hans de Goede |
1b1995 |
To use this pass the filter property to -device usb-redir. The filter
|
|
Hans de Goede |
1b1995 |
property takes a string consisting of filter rules, the format for a rule is:
|
|
Hans de Goede |
1b1995 |
<class>:<vendor>:<product>:<version>:<allow>
|
|
Hans de Goede |
1b1995 |
|
|
Hans de Goede |
1b1995 |
-1 can be used to allow any value for a field.
|
|
Hans de Goede |
1b1995 |
|
|
Hans de Goede |
1b1995 |
Muliple rules can be concatonated using | as a separator. Note that if
|
|
Hans de Goede |
1b1995 |
a device matches none of the passed in rules, redirecting it will not be
|
|
Hans de Goede |
1b1995 |
allowed!
|
|
Hans de Goede |
1b1995 |
|
|
Hans de Goede |
1b1995 |
Example:
|
|
Hans de Goede |
1b1995 |
-device usb-redir,filter='-1:0x0781:0x5567:-1:0|0x08:-1:-1:-1:1'
|
|
Hans de Goede |
1b1995 |
|
|
Hans de Goede |
1b1995 |
This example will deny the Sandisk Cruzer Blade being redirected, as it
|
|
Hans de Goede |
1b1995 |
has a usb id of 0781:5567, it will allow any other usb mass storage devices,
|
|
Hans de Goede |
1b1995 |
and it will deny any other devices (the default for devices not matching any
|
|
Hans de Goede |
1b1995 |
of the rules.
|
|
Hans de Goede |
1b1995 |
|
|
Hans de Goede |
1b1995 |
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
|
Hans de Goede |
1b1995 |
---
|
|
Hans de Goede |
1b1995 |
configure | 2 +-
|
|
Hans de Goede |
1b1995 |
usb-redir.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++++------
|
|
Hans de Goede |
1b1995 |
2 files changed, 106 insertions(+), 11 deletions(-)
|
|
Hans de Goede |
1b1995 |
|
|
Hans de Goede |
1b1995 |
diff --git a/configure b/configure
|
|
Hans de Goede |
1b1995 |
index 7ecf44e..c7e37df 100755
|
|
Hans de Goede |
1b1995 |
--- a/configure
|
|
Hans de Goede |
1b1995 |
+++ b/configure
|
|
Hans de Goede |
1b1995 |
@@ -2541,7 +2541,7 @@ fi
|
|
Hans de Goede |
1b1995 |
|
|
Hans de Goede |
1b1995 |
# check for usbredirparser for usb network redirection support
|
|
Hans de Goede |
1b1995 |
if test "$usb_redir" != "no" ; then
|
|
Hans de Goede |
1b1995 |
- if $pkg_config libusbredirparser >/dev/null 2>&1 ; then
|
|
Hans de Goede |
1b1995 |
+ if $pkg_config --atleast-version=0.3.3 libusbredirparser >/dev/null 2>&1 ; then
|
|
Hans de Goede |
1b1995 |
usb_redir="yes"
|
|
Hans de Goede |
1b1995 |
usb_redir_cflags=$($pkg_config --cflags libusbredirparser 2>/dev/null)
|
|
Hans de Goede |
1b1995 |
usb_redir_libs=$($pkg_config --libs libusbredirparser 2>/dev/null)
|
|
Hans de Goede |
1b1995 |
diff --git a/usb-redir.c b/usb-redir.c
|
|
Hans de Goede |
1b1995 |
index 6e92f14..85f40d6 100644
|
|
Hans de Goede |
1b1995 |
--- a/usb-redir.c
|
|
Hans de Goede |
1b1995 |
+++ b/usb-redir.c
|
|
Hans de Goede |
1b1995 |
@@ -34,6 +34,7 @@
|
|
Hans de Goede |
1b1995 |
#include <sys/ioctl.h>
|
|
Hans de Goede |
1b1995 |
#include <signal.h>
|
|
Hans de Goede |
1b1995 |
#include <usbredirparser.h>
|
|
Hans de Goede |
1b1995 |
+#include <usbredirfilter.h>
|
|
Hans de Goede |
1b1995 |
|
|
Hans de Goede |
1b1995 |
#include "hw/usb.h"
|
|
Hans de Goede |
1b1995 |
|
|
Hans de Goede |
1b1995 |
@@ -72,6 +73,7 @@ struct USBRedirDevice {
|
|
Hans de Goede |
1b1995 |
/* Properties */
|
|
Hans de Goede |
1b1995 |
CharDriverState *cs;
|
|
Hans de Goede |
1b1995 |
uint8_t debug;
|
|
Hans de Goede |
1b1995 |
+ char *filter_str;
|
|
Hans de Goede |
1b1995 |
/* Data passed from chardev the fd_read cb to the usbredirparser read cb */
|
|
Hans de Goede |
1b1995 |
const uint8_t *read_buf;
|
|
Hans de Goede |
1b1995 |
int read_buf_size;
|
|
Hans de Goede |
1b1995 |
@@ -84,6 +86,11 @@ struct USBRedirDevice {
|
|
Hans de Goede |
1b1995 |
struct endp_data endpoint[MAX_ENDPOINTS];
|
|
Hans de Goede |
1b1995 |
uint32_t packet_id;
|
|
Hans de Goede |
1b1995 |
QTAILQ_HEAD(, AsyncURB) asyncq;
|
|
Hans de Goede |
1b1995 |
+ /* Data for device filtering */
|
|
Hans de Goede |
1b1995 |
+ struct usb_redir_device_connect_header device_info;
|
|
Hans de Goede |
1b1995 |
+ struct usb_redir_interface_info_header interface_info;
|
|
Hans de Goede |
1b1995 |
+ struct usbredirfilter_rule *filter_rules;
|
|
Hans de Goede |
1b1995 |
+ int filter_rules_count;
|
|
Hans de Goede |
1b1995 |
};
|
|
Hans de Goede |
1b1995 |
|
|
Hans de Goede |
1b1995 |
struct AsyncURB {
|
|
Hans de Goede |
1b1995 |
@@ -790,6 +797,7 @@ static int usbredir_handle_control(USBDevice *udev, USBPacket *p,
|
|
Hans de Goede |
1b1995 |
static void usbredir_open_close_bh(void *opaque)
|
|
Hans de Goede |
1b1995 |
{
|
|
Hans de Goede |
1b1995 |
USBRedirDevice *dev = opaque;
|
|
Hans de Goede |
1b1995 |
+ uint32_t caps[USB_REDIR_CAPS_SIZE] = { 0, };
|
|
Hans de Goede |
1b1995 |
|
|
Hans de Goede |
1b1995 |
usbredir_device_disconnect(dev);
|
|
Hans de Goede |
1b1995 |
|
|
Hans de Goede |
1b1995 |
@@ -820,7 +828,9 @@ static void usbredir_open_close_bh(void *opaque)
|
|
Hans de Goede |
1b1995 |
dev->parser->interrupt_packet_func = usbredir_interrupt_packet;
|
|
Hans de Goede |
1b1995 |
dev->read_buf = NULL;
|
|
Hans de Goede |
1b1995 |
dev->read_buf_size = 0;
|
|
Hans de Goede |
1b1995 |
- usbredirparser_init(dev->parser, VERSION, NULL, 0, 0);
|
|
Hans de Goede |
1b1995 |
+
|
|
Hans de Goede |
1b1995 |
+ usbredirparser_caps_set_cap(caps, usb_redir_cap_connect_device_version);
|
|
Hans de Goede |
1b1995 |
+ usbredirparser_init(dev->parser, VERSION, caps, USB_REDIR_CAPS_SIZE, 0);
|
|
Hans de Goede |
1b1995 |
usbredirparser_do_write(dev->parser);
|
|
Hans de Goede |
1b1995 |
}
|
|
Hans de Goede |
1b1995 |
}
|
|
Hans de Goede |
1b1995 |
@@ -908,6 +918,17 @@ static int usbredir_initfn(USBDevice *udev)
|
|
Hans de Goede |
1b1995 |
return -1;
|
|
Hans de Goede |
1b1995 |
}
|
|
Hans de Goede |
1b1995 |
|
|
Hans de Goede |
1b1995 |
+ if (dev->filter_str) {
|
|
Hans de Goede |
1b1995 |
+ i = usbredirfilter_string_to_rules(dev->filter_str, ":", "|",
|
|
Hans de Goede |
1b1995 |
+ &dev->filter_rules,
|
|
Hans de Goede |
1b1995 |
+ &dev->filter_rules_count);
|
|
Hans de Goede |
1b1995 |
+ if (i) {
|
|
Hans de Goede |
1b1995 |
+ qerror_report(QERR_INVALID_PARAMETER_VALUE, "filter",
|
|
Hans de Goede |
1b1995 |
+ "a usb device filter string");
|
|
Hans de Goede |
1b1995 |
+ return -1;
|
|
Hans de Goede |
1b1995 |
+ }
|
|
Hans de Goede |
1b1995 |
+ }
|
|
Hans de Goede |
1b1995 |
+
|
|
Hans de Goede |
1b1995 |
dev->open_close_bh = qemu_bh_new(usbredir_open_close_bh, dev);
|
|
Hans de Goede |
1b1995 |
dev->attach_timer = qemu_new_timer_ms(vm_clock, usbredir_do_attach, dev);
|
|
Hans de Goede |
1b1995 |
|
|
Hans de Goede |
1b1995 |
@@ -956,6 +977,44 @@ static void usbredir_handle_destroy(USBDevice *udev)
|
|
Hans de Goede |
1b1995 |
if (dev->parser) {
|
|
Hans de Goede |
1b1995 |
usbredirparser_destroy(dev->parser);
|
|
Hans de Goede |
1b1995 |
}
|
|
Hans de Goede |
1b1995 |
+
|
|
Hans de Goede |
1b1995 |
+ free(dev->filter_rules);
|
|
Hans de Goede |
1b1995 |
+}
|
|
Hans de Goede |
1b1995 |
+
|
|
Hans de Goede |
1b1995 |
+static int usbredir_check_filter(USBRedirDevice *dev)
|
|
Hans de Goede |
1b1995 |
+{
|
|
Hans de Goede |
1b1995 |
+ if (dev->interface_info.interface_count == 0) {
|
|
Hans de Goede |
1b1995 |
+ ERROR("No interface info for device\n");
|
|
Hans de Goede |
1b1995 |
+ return -1;
|
|
Hans de Goede |
1b1995 |
+ }
|
|
Hans de Goede |
1b1995 |
+
|
|
Hans de Goede |
1b1995 |
+ if (dev->filter_rules) {
|
|
Hans de Goede |
1b1995 |
+ if (!usbredirparser_peer_has_cap(dev->parser,
|
|
Hans de Goede |
1b1995 |
+ usb_redir_cap_connect_device_version)) {
|
|
Hans de Goede |
1b1995 |
+ ERROR("Device filter specified and peer does not have the "
|
|
Hans de Goede |
1b1995 |
+ "connect_device_version capability\n");
|
|
Hans de Goede |
1b1995 |
+ return -1;
|
|
Hans de Goede |
1b1995 |
+ }
|
|
Hans de Goede |
1b1995 |
+
|
|
Hans de Goede |
1b1995 |
+ if (usbredirfilter_check(
|
|
Hans de Goede |
1b1995 |
+ dev->filter_rules,
|
|
Hans de Goede |
1b1995 |
+ dev->filter_rules_count,
|
|
Hans de Goede |
1b1995 |
+ dev->device_info.device_class,
|
|
Hans de Goede |
1b1995 |
+ dev->device_info.device_subclass,
|
|
Hans de Goede |
1b1995 |
+ dev->device_info.device_protocol,
|
|
Hans de Goede |
1b1995 |
+ dev->interface_info.interface_class,
|
|
Hans de Goede |
1b1995 |
+ dev->interface_info.interface_subclass,
|
|
Hans de Goede |
1b1995 |
+ dev->interface_info.interface_protocol,
|
|
Hans de Goede |
1b1995 |
+ dev->interface_info.interface_count,
|
|
Hans de Goede |
1b1995 |
+ dev->device_info.vendor_id,
|
|
Hans de Goede |
1b1995 |
+ dev->device_info.product_id,
|
|
Hans de Goede |
1b1995 |
+ dev->device_info.device_version_bcd,
|
|
Hans de Goede |
1b1995 |
+ 0) != 0) {
|
|
Hans de Goede |
1b1995 |
+ return -1;
|
|
Hans de Goede |
1b1995 |
+ }
|
|
Hans de Goede |
1b1995 |
+ }
|
|
Hans de Goede |
1b1995 |
+
|
|
Hans de Goede |
1b1995 |
+ return 0;
|
|
Hans de Goede |
1b1995 |
}
|
|
Hans de Goede |
1b1995 |
|
|
Hans de Goede |
1b1995 |
/*
|
|
Hans de Goede |
1b1995 |
@@ -984,6 +1043,7 @@ static void usbredir_device_connect(void *priv,
|
|
Hans de Goede |
1b1995 |
struct usb_redir_device_connect_header *device_connect)
|
|
Hans de Goede |
1b1995 |
{
|
|
Hans de Goede |
1b1995 |
USBRedirDevice *dev = priv;
|
|
Hans de Goede |
1b1995 |
+ const char *speed;
|
|
Hans de Goede |
1b1995 |
|
|
Hans de Goede |
1b1995 |
if (qemu_timer_pending(dev->attach_timer) || dev->dev.attached) {
|
|
Hans de Goede |
1b1995 |
ERROR("Received device connect while already connected\n");
|
|
Hans de Goede |
1b1995 |
@@ -992,26 +1052,48 @@ static void usbredir_device_connect(void *priv,
|
|
Hans de Goede |
1b1995 |
|
|
Hans de Goede |
1b1995 |
switch (device_connect->speed) {
|
|
Hans de Goede |
1b1995 |
case usb_redir_speed_low:
|
|
Hans de Goede |
1b1995 |
- DPRINTF("attaching low speed device\n");
|
|
Hans de Goede |
1b1995 |
+ speed = "low speed";
|
|
Hans de Goede |
1b1995 |
dev->dev.speed = USB_SPEED_LOW;
|
|
Hans de Goede |
1b1995 |
break;
|
|
Hans de Goede |
1b1995 |
case usb_redir_speed_full:
|
|
Hans de Goede |
1b1995 |
- DPRINTF("attaching full speed device\n");
|
|
Hans de Goede |
1b1995 |
+ speed = "full speed";
|
|
Hans de Goede |
1b1995 |
dev->dev.speed = USB_SPEED_FULL;
|
|
Hans de Goede |
1b1995 |
break;
|
|
Hans de Goede |
1b1995 |
case usb_redir_speed_high:
|
|
Hans de Goede |
1b1995 |
- DPRINTF("attaching high speed device\n");
|
|
Hans de Goede |
1b1995 |
+ speed = "high speed";
|
|
Hans de Goede |
1b1995 |
dev->dev.speed = USB_SPEED_HIGH;
|
|
Hans de Goede |
1b1995 |
break;
|
|
Hans de Goede |
1b1995 |
case usb_redir_speed_super:
|
|
Hans de Goede |
1b1995 |
- DPRINTF("attaching super speed device\n");
|
|
Hans de Goede |
1b1995 |
+ speed = "super speed";
|
|
Hans de Goede |
1b1995 |
dev->dev.speed = USB_SPEED_SUPER;
|
|
Hans de Goede |
1b1995 |
break;
|
|
Hans de Goede |
1b1995 |
default:
|
|
Hans de Goede |
1b1995 |
- DPRINTF("attaching unknown speed device, assuming full speed\n");
|
|
Hans de Goede |
1b1995 |
+ speed = "unknown speed";
|
|
Hans de Goede |
1b1995 |
dev->dev.speed = USB_SPEED_FULL;
|
|
Hans de Goede |
1b1995 |
}
|
|
Hans de Goede |
1b1995 |
+
|
|
Hans de Goede |
1b1995 |
+ if (usbredirparser_peer_has_cap(dev->parser,
|
|
Hans de Goede |
1b1995 |
+ usb_redir_cap_connect_device_version)) {
|
|
Hans de Goede |
1b1995 |
+ INFO("attaching %s device %04x:%04x version %d.%d class %02x\n",
|
|
Hans de Goede |
1b1995 |
+ speed, device_connect->vendor_id, device_connect->product_id,
|
|
Hans de Goede |
1b1995 |
+ device_connect->device_version_bcd >> 8,
|
|
Hans de Goede |
1b1995 |
+ device_connect->device_version_bcd & 0xff,
|
|
Hans de Goede |
1b1995 |
+ device_connect->device_class);
|
|
Hans de Goede |
1b1995 |
+ } else {
|
|
Hans de Goede |
1b1995 |
+ INFO("attaching %s device %04x:%04x class %02x\n", speed,
|
|
Hans de Goede |
1b1995 |
+ device_connect->vendor_id, device_connect->product_id,
|
|
Hans de Goede |
1b1995 |
+ device_connect->device_class);
|
|
Hans de Goede |
1b1995 |
+ }
|
|
Hans de Goede |
1b1995 |
+
|
|
Hans de Goede |
1b1995 |
dev->dev.speedmask = (1 << dev->dev.speed);
|
|
Hans de Goede |
1b1995 |
+ dev->device_info = *device_connect;
|
|
Hans de Goede |
1b1995 |
+
|
|
Hans de Goede |
1b1995 |
+ if (usbredir_check_filter(dev)) {
|
|
Hans de Goede |
1b1995 |
+ WARNING("Device %04x:%04x rejected by device filter, not attaching\n",
|
|
Hans de Goede |
1b1995 |
+ device_connect->vendor_id, device_connect->product_id);
|
|
Hans de Goede |
1b1995 |
+ return;
|
|
Hans de Goede |
1b1995 |
+ }
|
|
Hans de Goede |
1b1995 |
+
|
|
Hans de Goede |
1b1995 |
qemu_mod_timer(dev->attach_timer, dev->next_attach_time);
|
|
Hans de Goede |
1b1995 |
}
|
|
Hans de Goede |
1b1995 |
|
|
Hans de Goede |
1b1995 |
@@ -1038,15 +1120,27 @@ static void usbredir_device_disconnect(void *priv)
|
|
Hans de Goede |
1b1995 |
for (i = 0; i < MAX_ENDPOINTS; i++) {
|
|
Hans de Goede |
1b1995 |
QTAILQ_INIT(&dev->endpoint[i].bufpq);
|
|
Hans de Goede |
1b1995 |
}
|
|
Hans de Goede |
1b1995 |
+ dev->interface_info.interface_count = 0;
|
|
Hans de Goede |
1b1995 |
}
|
|
Hans de Goede |
1b1995 |
|
|
Hans de Goede |
1b1995 |
static void usbredir_interface_info(void *priv,
|
|
Hans de Goede |
1b1995 |
struct usb_redir_interface_info_header *interface_info)
|
|
Hans de Goede |
1b1995 |
{
|
|
Hans de Goede |
1b1995 |
- /* The intention is to allow specifying acceptable interface classes
|
|
Hans de Goede |
1b1995 |
- for redirection on the cmdline and in the future verify this here,
|
|
Hans de Goede |
1b1995 |
- and disconnect (or never connect) the device if a not accepted
|
|
Hans de Goede |
1b1995 |
- interface class is detected */
|
|
Hans de Goede |
1b1995 |
+ USBRedirDevice *dev = priv;
|
|
Hans de Goede |
1b1995 |
+
|
|
Hans de Goede |
1b1995 |
+ dev->interface_info = *interface_info;
|
|
Hans de Goede |
1b1995 |
+
|
|
Hans de Goede |
1b1995 |
+ /*
|
|
Hans de Goede |
1b1995 |
+ * If we receive interface info after the device has already been
|
|
Hans de Goede |
1b1995 |
+ * connected (ie on a set_config), re-check the filter.
|
|
Hans de Goede |
1b1995 |
+ */
|
|
Hans de Goede |
1b1995 |
+ if (qemu_timer_pending(dev->attach_timer) || dev->dev.attached) {
|
|
Hans de Goede |
1b1995 |
+ if (usbredir_check_filter(dev)) {
|
|
Hans de Goede |
1b1995 |
+ ERROR("Device no longer matches filter after interface info "
|
|
Hans de Goede |
1b1995 |
+ "change, disconnecting!\n");
|
|
Hans de Goede |
1b1995 |
+ usbredir_device_disconnect(dev);
|
|
Hans de Goede |
1b1995 |
+ }
|
|
Hans de Goede |
1b1995 |
+ }
|
|
Hans de Goede |
1b1995 |
}
|
|
Hans de Goede |
1b1995 |
|
|
Hans de Goede |
1b1995 |
static void usbredir_ep_info(void *priv,
|
|
Hans de Goede |
1b1995 |
@@ -1356,6 +1450,7 @@ static struct USBDeviceInfo usbredir_dev_info = {
|
|
Hans de Goede |
1b1995 |
.qdev.props = (Property[]) {
|
|
Hans de Goede |
1b1995 |
DEFINE_PROP_CHR("chardev", USBRedirDevice, cs),
|
|
Hans de Goede |
1b1995 |
DEFINE_PROP_UINT8("debug", USBRedirDevice, debug, 0),
|
|
Hans de Goede |
1b1995 |
+ DEFINE_PROP_STRING("filter", USBRedirDevice, filter_str),
|
|
Hans de Goede |
1b1995 |
DEFINE_PROP_END_OF_LIST(),
|
|
Hans de Goede |
1b1995 |
},
|
|
Hans de Goede |
1b1995 |
};
|
|
Hans de Goede |
1b1995 |
--
|
|
Hans de Goede |
1b1995 |
1.7.9.3
|
|
Hans de Goede |
1b1995 |
|