VBoxUSBFilterMgr.cpp revision f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * VirtualBox Ring-0 USB Filter Manager.
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * Copyright (C) 2007 Oracle Corporation
c55c68b6a3324172e9dc207926215845880b0f90vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
c55c68b6a3324172e9dc207926215845880b0f90vboxsync * available from http://www.virtualbox.org. This file is free software;
c55c68b6a3324172e9dc207926215845880b0f90vboxsync * you can redistribute it and/or modify it under the terms of the GNU
c55c68b6a3324172e9dc207926215845880b0f90vboxsync * General Public License (GPL) as published by the Free Software
c55c68b6a3324172e9dc207926215845880b0f90vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
c55c68b6a3324172e9dc207926215845880b0f90vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
c55c68b6a3324172e9dc207926215845880b0f90vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
59190ecd61435d19ba3515b876272aee7bd12298vboxsync/*******************************************************************************
59190ecd61435d19ba3515b876272aee7bd12298vboxsync* Header Files *
59190ecd61435d19ba3515b876272aee7bd12298vboxsync*******************************************************************************/
59190ecd61435d19ba3515b876272aee7bd12298vboxsync/*******************************************************************************
59190ecd61435d19ba3515b876272aee7bd12298vboxsync* Defined Constants And Macros *
59190ecd61435d19ba3515b876272aee7bd12298vboxsync*******************************************************************************/
59190ecd61435d19ba3515b876272aee7bd12298vboxsync/** @def VBOXUSBFILTERMGR_LOCK
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * Locks the filter list. Careful with scoping since this may
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * create a temporary variable. Don't call twice in the same function.
59190ecd61435d19ba3515b876272aee7bd12298vboxsync/** @def VBOXUSBFILTERMGR_UNLOCK
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * Unlocks the filter list.
59190ecd61435d19ba3515b876272aee7bd12298vboxsync do { int rc2 = RTSemFastMutexRequest(g_Mtx); AssertRC(rc2); } while (0)
59190ecd61435d19ba3515b876272aee7bd12298vboxsync do { int rc2 = RTSemFastMutexRelease(g_Mtx); AssertRC(rc2); } while (0)
59190ecd61435d19ba3515b876272aee7bd12298vboxsync/*******************************************************************************
59190ecd61435d19ba3515b876272aee7bd12298vboxsync* Structures and Typedefs *
59190ecd61435d19ba3515b876272aee7bd12298vboxsync*******************************************************************************/
59190ecd61435d19ba3515b876272aee7bd12298vboxsync/** Pointer to an VBoxUSB filter. */
59190ecd61435d19ba3515b876272aee7bd12298vboxsync/** Pointer to PVBOXUSBFILTER. */
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync * VBoxUSB internal filter representation.
59190ecd61435d19ba3515b876272aee7bd12298vboxsync /** The core filter. */
59190ecd61435d19ba3515b876272aee7bd12298vboxsync /** The filter owner. */
59190ecd61435d19ba3515b876272aee7bd12298vboxsync /** The filter Id. */
59190ecd61435d19ba3515b876272aee7bd12298vboxsync /** Pointer to the next filter in the list. */
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * VBoxUSB filter list.
59190ecd61435d19ba3515b876272aee7bd12298vboxsync /** The head pointer. */
59190ecd61435d19ba3515b876272aee7bd12298vboxsync /** The tail pointer. */
59190ecd61435d19ba3515b876272aee7bd12298vboxsync/** Pointer to a VBOXUSBFILTERLIST. */
59190ecd61435d19ba3515b876272aee7bd12298vboxsync/*******************************************************************************
59190ecd61435d19ba3515b876272aee7bd12298vboxsync* Global Variables *
59190ecd61435d19ba3515b876272aee7bd12298vboxsync*******************************************************************************/
59190ecd61435d19ba3515b876272aee7bd12298vboxsync/** Spinlock protecting the filter lists. */
59190ecd61435d19ba3515b876272aee7bd12298vboxsync/** Mutex protecting the filter lists. */
59190ecd61435d19ba3515b876272aee7bd12298vboxsync/** The per-type filter lists.
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * @remark The first entry is empty (USBFILTERTYPE_INVALID). */
59190ecd61435d19ba3515b876272aee7bd12298vboxsyncstatic VBOXUSBFILTERLIST g_aLists[USBFILTERTYPE_END];
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync * Initializes the VBoxUSB filter manager.
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * @returns IPRT status code.
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync int rc = RTSpinlockCreate(&g_Spinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "VBoxUSBFilter");
59190ecd61435d19ba3515b876272aee7bd12298vboxsync /* not really required, but anyway... */
59190ecd61435d19ba3515b876272aee7bd12298vboxsync for (unsigned i = USBFILTERTYPE_FIRST; i < RT_ELEMENTS(g_aLists); i++)
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * Internal worker that frees a filter.
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * @param pFilter The filter to free.
59190ecd61435d19ba3515b876272aee7bd12298vboxsyncstatic void vboxUSBFilterFree(PVBOXUSBFILTER pFilter)
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * Terminates the VBoxUSB filter manager.
59190ecd61435d19ba3515b876272aee7bd12298vboxsync for (unsigned i = USBFILTERTYPE_FIRST; i < RT_ELEMENTS(g_aLists); i++)
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * Adds a new filter.
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * The filter will be validate, duplicated and added.
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * @returns IPRT status code.
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * @param pFilter The filter.
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * @param Owner The filter owner. Must be non-zero.
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * @param puId Where to store the filter ID.
df294ff29aab74013667896ef2d4f5bd1f782143vboxsyncint VBoxUSBFilterAdd(PCUSBFILTER pFilter, VBOXUSBFILTER_CONTEXT Owner, uintptr_t *puId)
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * Validate input.
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * Allocate a new filter.
59190ecd61435d19ba3515b876272aee7bd12298vboxsync PVBOXUSBFILTER pNew = (PVBOXUSBFILTER)RTMemAlloc(sizeof(*pNew));
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * Insert it.
59190ecd61435d19ba3515b876272aee7bd12298vboxsync PVBOXUSBFILTERLIST pList = &g_aLists[pFilter->enmType];
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * Removes an existing filter.
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * The filter will be validate, duplicated and added.
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * @returns IPRT status code.
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * @retval VINF_SUCCESS if successfully removed.
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * @retval VERR_FILE_NOT_FOUND if the specified filter/owner cannot be found.
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * @param Owner The filter owner.
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * @param uId The ID of the filter that's to be removed.
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * Returned by VBoxUSBFilterAdd().
df294ff29aab74013667896ef2d4f5bd1f782143vboxsyncint VBoxUSBFilterRemove(VBOXUSBFILTER_CONTEXT Owner, uintptr_t uId)
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * Validate input.
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * Locate and unlink it.
59190ecd61435d19ba3515b876272aee7bd12298vboxsync for (unsigned i = USBFILTERTYPE_FIRST; !pCur && i < RT_ELEMENTS(g_aLists); i++)
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * Free it (if found).
df294ff29aab74013667896ef2d4f5bd1f782143vboxsyncVBOXUSBFILTER_CONTEXT VBoxUSBFilterGetOwner(uintptr_t uId)
df294ff29aab74013667896ef2d4f5bd1f782143vboxsync * Validate input.
df294ff29aab74013667896ef2d4f5bd1f782143vboxsync VBOXUSBFILTER_CONTEXT Owner = VBOXUSBFILTER_CONTEXT_NIL;
df294ff29aab74013667896ef2d4f5bd1f782143vboxsync for (unsigned i = USBFILTERTYPE_FIRST; i < RT_ELEMENTS(g_aLists); i++)
df294ff29aab74013667896ef2d4f5bd1f782143vboxsync for (PVBOXUSBFILTER pCur = g_aLists[i].pHead; pCur; pCur = pCur->pNext)
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * Removes all filters belonging to the specified owner.
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * This is typically called when an owner disconnects or
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * terminates unexpectedly.
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * @param Owner The owner
df294ff29aab74013667896ef2d4f5bd1f782143vboxsyncvoid VBoxUSBFilterRemoveOwner(VBOXUSBFILTER_CONTEXT Owner)
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * Collect the filters that should be freed.
59190ecd61435d19ba3515b876272aee7bd12298vboxsync for (unsigned i = USBFILTERTYPE_FIRST; i < RT_ELEMENTS(g_aLists); i++)
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * Free any filters we've found.
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * Match the specified device against the filters.
df294ff29aab74013667896ef2d4f5bd1f782143vboxsync * Unlike the VBoxUSBFilterMatch, returns Owner also if exclude filter is matched
df294ff29aab74013667896ef2d4f5bd1f782143vboxsync * @returns Owner on if matched, VBOXUSBFILTER_CONTEXT_NIL it not matched.
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * @param pDevice The device data as a filter structure.
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * See USBFilterMatch for how to construct this.
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * @param puId Where to store the filter id (optional).
df294ff29aab74013667896ef2d4f5bd1f782143vboxsync * @param pfFilter Where to store whether the device must be filtered or not
df294ff29aab74013667896ef2d4f5bd1f782143vboxsyncVBOXUSBFILTER_CONTEXT VBoxUSBFilterMatchEx(PCUSBFILTER pDevice, uintptr_t *puId, bool fRemoveFltIfOneShot, bool *pfFilter, bool *pfIsOneShot)
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * Validate input.
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * Search the lists for a match.
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * (The lists are ordered by priority.)
59190ecd61435d19ba3515b876272aee7bd12298vboxsync for (unsigned i = USBFILTERTYPE_FIRST; i < RT_ELEMENTS(g_aLists); i++)
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * Take list specific actions and return.
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * The code does NOT implement the case where there are two or more
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync * filter clients, and one of them is releasing a device that's
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * requested by some of the others. It's just too much work for a
59190ecd61435d19ba3515b876272aee7bd12298vboxsync * situation that noone will encounter.
df294ff29aab74013667896ef2d4f5bd1f782143vboxsync /* unlink */
df294ff29aab74013667896ef2d4f5bd1f782143vboxsync * Match the specified device against the filters.
df294ff29aab74013667896ef2d4f5bd1f782143vboxsync * @returns Owner on if matched, VBOXUSBFILTER_CONTEXT_NIL it not matched.
df294ff29aab74013667896ef2d4f5bd1f782143vboxsync * @param pDevice The device data as a filter structure.
df294ff29aab74013667896ef2d4f5bd1f782143vboxsync * See USBFilterMatch for how to construct this.
df294ff29aab74013667896ef2d4f5bd1f782143vboxsync * @param puId Where to store the filter id (optional).
df294ff29aab74013667896ef2d4f5bd1f782143vboxsyncVBOXUSBFILTER_CONTEXT VBoxUSBFilterMatch(PCUSBFILTER pDevice, uintptr_t *puId)
df294ff29aab74013667896ef2d4f5bd1f782143vboxsync bool fFilter = false;
df294ff29aab74013667896ef2d4f5bd1f782143vboxsync VBOXUSBFILTER_CONTEXT Owner = VBoxUSBFilterMatchEx(pDevice, puId,
df294ff29aab74013667896ef2d4f5bd1f782143vboxsync true, /* remove filter is it's a one-shot*/