VirtualBox

Ignore:
Timestamp:
Jul 7, 2015 8:09:37 PM (9 years ago)
Author:
vboxsync
Message:

NetFlt/Win: Host IP address notifications (#7661)

Location:
trunk/src/VBox/HostDrivers/VBoxNetFlt
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostDrivers/VBoxNetFlt/Makefile.kmk

    r56293 r56846  
    6161        $(PATH_SDK_$(VBOX_WINDDK_WLH)_LIB)/hal.lib \
    6262        $(PATH_SDK_$(VBOX_WINDDK_WLH)_LIB)/ndis.lib \
     63        $(PATH_SDK_$(VBOX_WINDDK_WLH)_LIB)/tdi.lib \
    6364        $(PATH_STAGE_LIB)/RuntimeR0Drv$(VBOX_SUFF_LIB)
    6465 VBoxNetFlt_LIBS = \
  • trunk/src/VBox/HostDrivers/VBoxNetFlt/win/drv/VBoxNetFltCmn-win.h

    r56293 r56846  
    5656#include <iprt/time.h>
    5757#include <iprt/net.h>
     58#include <iprt/list.h>
    5859
    5960RT_C_DECLS_BEGIN
     
    375376    /* Protocol info */
    376377    VBOXNETFLTGLOBALS_PT Pt;
     378    /** lock protecting the filter list */
     379    NDIS_SPIN_LOCK lockFilters;
     380    /** the head of filter list */
     381    RTLISTANCHOR listFilters;
     382    /** IP address change notifier handle */
     383    HANDLE hNotifier;
    377384#endif
    378385} VBOXNETFLTGLOBALS_WIN, *PVBOXNETFLTGLOBALS_WIN;
     
    457464    /** packet filter flags set by us */
    458465    ULONG fOurSetFilter;
     466    /** our own list of filters, needed by notifier */
     467    RTLISTNODE node;
    459468#else
    460469    volatile ULONG cTxSuccess;
  • trunk/src/VBox/HostDrivers/VBoxNetFlt/win/drv/VBoxNetFltRt-win.cpp

    r56293 r56846  
    1818#include <VBox/intnetinline.h>
    1919#include <iprt/thread.h>
     20
     21RT_C_DECLS_BEGIN
     22#include <tdikrnl.h>
     23RT_C_DECLS_END
     24#include <mstcpip.h>
    2025
    2126/** represents the job element of the job queue
     
    16781683    vboxNetFltWinMpDeregister(&g_VBoxNetFltGlobalsWin.Mp);
    16791684
     1685#ifndef VBOXNETADP
     1686    NdisFreeSpinLock(&g_VBoxNetFltGlobalsWin.lockFilters);
     1687#endif /* VBOXNETADP */
     1688
    16801689    LogFlow((__FUNCTION__" <== DO (0x%x)\n", DriverObject));
    16811690
     
    17291738            g_VBoxNetFltGlobalsWin.fPacketIsLoopedBack = NDIS_FLAGS_IS_LOOPBACK_PACKET;
    17301739
     1740#ifndef VBOXNETADP
     1741            RTListInit(&g_VBoxNetFltGlobalsWin.listFilters);
     1742            NdisAllocateSpinLock(&g_VBoxNetFltGlobalsWin.lockFilters);
     1743#endif
     1744
    17311745            Status = vboxNetFltWinMpRegister(&g_VBoxNetFltGlobalsWin.Mp, DriverObject, RegistryPath);
    17321746            Assert(Status == STATUS_SUCCESS);
     
    17491763                }
    17501764                vboxNetFltWinMpDeregister(&g_VBoxNetFltGlobalsWin.Mp);
     1765#ifndef VBOXNETADP
     1766                NdisFreeSpinLock(&g_VBoxNetFltGlobalsWin.lockFilters);
     1767#endif /* VBOXNETADP */
    17511768            }
    17521769            vboxNetFltWinJobFiniQueue(&g_VBoxJobQueue);
     
    32723289}
    32733290
     3291#ifndef VBOXNETADP
     3292
     3293DECLINLINE(bool) vboxNetFltWinIsAddrLinkLocal4(PCRTNETADDRIPV4 pAddr)
     3294{
     3295    return (pAddr->s.Lo == 0xfea9); /* 169.254 */
     3296}
     3297
     3298DECLINLINE(bool) vboxNetFltWinIsAddrLinkLocal6(PCRTNETADDRIPV6 pAddr)
     3299{
     3300    return ((pAddr->au8[0] == 0xfe) && ((pAddr->au8[1] & 0xc0) == 0x80));
     3301}
     3302
     3303void vboxNetFltWinNotifyHostAddress(PTA_ADDRESS pAddress, bool fAdded)
     3304{
     3305#ifdef DEBUG
     3306    char szBuf[128];
     3307#endif /* DEBUG */
     3308    void *pvAddr = NULL;
     3309    INTNETADDRTYPE enmAddrType = kIntNetAddrType_Invalid;
     3310
     3311    LogFlow(("==>vboxNetFltWinNotifyHostAddress: AddrType=%d %s\n",
     3312             pAddress->AddressType, fAdded ? "added" : "deleted"));
     3313    if (pAddress->AddressType == TDI_ADDRESS_TYPE_IP)
     3314    {
     3315        PTDI_ADDRESS_IP pTdiAddrIp = (PTDI_ADDRESS_IP)pAddress->Address;
     3316        /*
     3317         * Note that we do not get loopback addresses here. If we did we should
     3318         * have checked and ignored them too.
     3319         */
     3320        if (!vboxNetFltWinIsAddrLinkLocal4((PCRTNETADDRIPV4)(&pTdiAddrIp->in_addr)))
     3321        {
     3322            pvAddr = &pTdiAddrIp->in_addr;
     3323            enmAddrType = kIntNetAddrType_IPv4;
     3324        }
     3325    }
     3326    else if (pAddress->AddressType == TDI_ADDRESS_TYPE_IP6)
     3327    {
     3328        PTDI_ADDRESS_IP6 pTdiAddrIp6 = (PTDI_ADDRESS_IP6)pAddress->Address;
     3329        if (!vboxNetFltWinIsAddrLinkLocal6((PCRTNETADDRIPV6)(pTdiAddrIp6->sin6_addr)))
     3330        {
     3331            pvAddr = pTdiAddrIp6->sin6_addr;
     3332            enmAddrType = kIntNetAddrType_IPv6;
     3333        }
     3334    }
     3335    else
     3336    {
     3337        Log2(("vboxNetFltWinNotifyHostAddress: ignoring irrelevant address type %d\n",
     3338              pAddress->AddressType));
     3339        LogFlow(("<==vboxNetFltWinNotifyHostAddress\n"));
     3340        return;
     3341    }
     3342    if (pvAddr)
     3343    {
     3344        NdisAcquireSpinLock(&g_VBoxNetFltGlobalsWin.lockFilters);
     3345        /* At this point the list must contain at least one element. */
     3346        PVBOXNETFLTWIN pFilter   = NULL;
     3347        PVBOXNETFLTINS pInstance = NULL;
     3348        RTListForEach(&g_VBoxNetFltGlobalsWin.listFilters, pFilter, VBOXNETFLTWIN, node)
     3349        {
     3350            pInstance = RT_FROM_MEMBER(pFilter, VBOXNETFLTINS, u.s.WinIf);
     3351            if (vboxNetFltWinReferenceWinIf(pInstance))
     3352            {
     3353                if (pInstance->pSwitchPort && pInstance->pSwitchPort->pfnNotifyHostAddress)
     3354                    break;
     3355                vboxNetFltWinDereferenceWinIf(pInstance);
     3356            }
     3357            else
     3358                Log2(("vboxNetFltWinNotifyHostAddress: failed to retain filter instance %p\n", pInstance));
     3359            pInstance = NULL;
     3360        }
     3361        NdisReleaseSpinLock(&g_VBoxNetFltGlobalsWin.lockFilters);
     3362        if (pInstance)
     3363        {
     3364            if (enmAddrType == kIntNetAddrType_IPv4)
     3365                Log2(("vboxNetFltWin%sAddressHandler: %RTnaipv4\n",
     3366                      fAdded ? "Add" : "Del", *(PCRTNETADDRIPV4)pvAddr));
     3367            else
     3368                Log2(("vboxNetFltWin%sAddressHandler: %RTnaipv6\n",
     3369                      fAdded ? "Add" : "Del", pvAddr));
     3370            pInstance->pSwitchPort->pfnNotifyHostAddress(pInstance->pSwitchPort, fAdded,
     3371                                                         enmAddrType, pvAddr);
     3372            vboxNetFltWinDereferenceWinIf(pInstance);
     3373        }
     3374        else
     3375            Log2(("vboxNetFltWinNotifyHostAddress: no filters require notification\n"));
     3376    }
     3377    else
     3378        Log2(("vboxNetFltWinNotifyHostAddress: ignoring link-local address (%s)\n", szBuf));
     3379    LogFlow(("<==vboxNetFltWinNotifyHostAddress\n"));
     3380}
     3381
     3382void vboxNetFltWinAddAddressHandler(PTA_ADDRESS Address,
     3383                                    PUNICODE_STRING DeviceName,
     3384                                    PTDI_PNP_CONTEXT Context)
     3385{
     3386    vboxNetFltWinNotifyHostAddress(Address, true);
     3387}
     3388
     3389void vboxNetFltWinDelAddressHandler(PTA_ADDRESS Address,
     3390                                    PUNICODE_STRING DeviceName,
     3391                                    PTDI_PNP_CONTEXT Context)
     3392{
     3393    vboxNetFltWinNotifyHostAddress(Address, false);
     3394}
     3395
     3396void vboxNetFltWinRegisterIpAddrNotifier(PVBOXNETFLTINS pThis)
     3397{
     3398    LogFlow(("==>vboxNetFltWinRegisterIpAddrNotifier: instance=%p pThis->pSwitchPort=%p pThis->pSwitchPort->pfnNotifyHostAddress=%p\n",
     3399             pThis, pThis->pSwitchPort, pThis->pSwitchPort ? pThis->pSwitchPort->pfnNotifyHostAddress : NULL));
     3400    if (pThis->pSwitchPort && pThis->pSwitchPort->pfnNotifyHostAddress)
     3401    {
     3402        NdisAcquireSpinLock(&g_VBoxNetFltGlobalsWin.lockFilters);
     3403        bool fRegisterHandlers = RTListIsEmpty(&g_VBoxNetFltGlobalsWin.listFilters);
     3404        RTListPrepend(&g_VBoxNetFltGlobalsWin.listFilters, &pThis->u.s.WinIf.node);
     3405        NdisReleaseSpinLock(&g_VBoxNetFltGlobalsWin.lockFilters);
     3406
     3407        if (fRegisterHandlers)
     3408        {
     3409            TDI_CLIENT_INTERFACE_INFO Info;
     3410            UNICODE_STRING ClientName = RTL_CONSTANT_STRING(L"VBoxNetFlt");
     3411            memset(&Info, 0, sizeof(Info));
     3412            Info.MajorTdiVersion = 2;
     3413            Info.MinorTdiVersion = 0;
     3414            Info.ClientName = &ClientName;
     3415            Info.AddAddressHandlerV2 = vboxNetFltWinAddAddressHandler;
     3416            Info.DelAddressHandlerV2 = vboxNetFltWinDelAddressHandler;
     3417            Assert(!g_VBoxNetFltGlobalsWin.hNotifier);
     3418            NTSTATUS Status = TdiRegisterPnPHandlers(&Info, sizeof(Info), &g_VBoxNetFltGlobalsWin.hNotifier);
     3419            Log2(("vboxNetFltWinRegisterIpAddrNotifier: TdiRegisterPnPHandlers returned %d\n", Status));
     3420        }
     3421        else
     3422            Log2(("vboxNetFltWinRegisterIpAddrNotifier: already registed\n"));
     3423    }
     3424    else
     3425        Log2(("vboxNetFltWinRegisterIpAddrNotifier: this instance does not require notifications, ignoring...\n"));
     3426    LogFlow(("<==vboxNetFltWinRegisterIpAddrNotifier: notifier=%p\n", g_VBoxNetFltGlobalsWin.hNotifier));
     3427}
     3428
     3429void vboxNetFltWinUnregisterIpAddrNotifier(PVBOXNETFLTINS pThis)
     3430{
     3431    LogFlow(("==>vboxNetFltWinUnregisterIpAddrNotifier: notifier=%p\n", g_VBoxNetFltGlobalsWin.hNotifier));
     3432    if (pThis->pSwitchPort && pThis->pSwitchPort->pfnNotifyHostAddress)
     3433    {
     3434        NdisAcquireSpinLock(&g_VBoxNetFltGlobalsWin.lockFilters);
     3435        /* At this point the list must contain at least one element. */
     3436        Assert(!RTListIsEmpty(&g_VBoxNetFltGlobalsWin.listFilters));
     3437        RTListNodeRemove(&pThis->u.s.WinIf.node);
     3438        HANDLE hNotifier = NULL;
     3439        if (RTListIsEmpty(&g_VBoxNetFltGlobalsWin.listFilters))
     3440        {
     3441            /*
     3442             * The list has become empty, so we need to deregister handlers. We
     3443             * grab hNotifier and reset it while still holding the lock. This
     3444             * guaranties that we won't interfere with setting it in
     3445             * vboxNetFltWinRegisterIpAddrNotifier(). It is inconceivable that
     3446             * vboxNetFltWinUnregisterIpAddrNotifier() will be called for the
     3447             * same filter instance while it is still being processed by
     3448             * vboxNetFltWinRegisterIpAddrNotifier(). This would require trunk
     3449             * destruction in the middle of its creation. It is possible that
     3450             * vboxNetFltWinUnregisterIpAddrNotifier() is called for another
     3451             * filter instance, but in such case we won't even get here as the
     3452             * list won't be empty.
     3453             */
     3454            hNotifier = g_VBoxNetFltGlobalsWin.hNotifier;
     3455            g_VBoxNetFltGlobalsWin.hNotifier = NULL;
     3456        }
     3457        NdisReleaseSpinLock(&g_VBoxNetFltGlobalsWin.lockFilters);
     3458        if (hNotifier)
     3459        {
     3460            NTSTATUS Status = TdiDeregisterPnPHandlers(hNotifier);
     3461            Log2(("vboxNetFltWinUnregisterIpAddrNotifier: TdiDeregisterPnPHandlers(%p) returned %d\n",
     3462                  hNotifier, Status));
     3463        }
     3464        else
     3465            Log2(("vboxNetFltWinUnregisterIpAddrNotifier: filters remain, do not deregister handlers yet\n"));
     3466    }
     3467    else
     3468        Log2(("vboxNetFltWinUnregisterIpAddrNotifier: this instance did not require notifications, ignoring...\n"));
     3469    LogFlow(("<==vboxNetFltWinUnregisterIpAddrNotifier\n"));
     3470}
     3471#else /* VBOXNETADP */
     3472#define vboxNetFltWinRegisterIpAddrNotifier(x)
     3473#define vboxNetFltWinUnregisterIpAddrNotifier(x)
     3474#endif /* VBOXNETADP */
     3475
    32743476int vboxNetFltOsDisconnectIt(PVBOXNETFLTINS pThis)
    32753477{
    32763478    NDIS_STATUS Status = vboxNetFltWinDisconnectIt(pThis);
     3479    Log2(("vboxNetFltOsDisconnectIt: pThis=%p pThis->pSwitchPort=%p pThis->pSwitchPort->pfnNotifyHostAddress=%p\n",
     3480          pThis, pThis->pSwitchPort, pThis->pSwitchPort ? pThis->pSwitchPort->pfnNotifyHostAddress : NULL));
     3481    vboxNetFltWinUnregisterIpAddrNotifier(pThis);
    32773482    return Status == NDIS_STATUS_SUCCESS ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
    32783483}
     
    33403545int vboxNetFltOsConnectIt(PVBOXNETFLTINS pThis)
    33413546{
     3547    Log2(("vboxNetFltOsConnectIt: pThis=%p pThis->pSwitchPort=%p pThis->pSwitchPort->pfnNotifyHostAddress=%p\n",
     3548          pThis, pThis->pSwitchPort, pThis->pSwitchPort ? pThis->pSwitchPort->pfnNotifyHostAddress : NULL));
     3549    vboxNetFltWinRegisterIpAddrNotifier(pThis);
    33423550    return vboxNetFltWinConnectIt(pThis);
    33433551}
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette