为什么NdisFSendNetBufferLists仅在从FilterSendNetBufferLists调用时才起作用?

问题描述

我有一个NDIS筛选器驱动程序(请参阅https://pastebin.com/c5r87NNw)和一个用户空间应用程序。

我想使用过滤器驱动程序(在功能 curl --location --request POST 'https://login.microsoftonline.com/{client-id-of-app-registered-in-b2c}/oauth2/v2.0/token' \ --header 'Content-Type: application/x-www-form-urlencoded' \ --header 'Cookie: x-ms-gateway-slice=prod; stsservicecookie=ests; fpc=AmqL7OwikMNGgdpvjdkb0OLnguDtAQAAABl14NYOAAAAd_wwNgEAAABCeeDWDgAAAA' \ --data-urlencode 'grant_type=client_credentials' \ --data-urlencode 'client_secret={secret-of-app}' \ --data-urlencode 'client_id={client-id-of-app-registered-in-b2c}' \ --data-urlencode 'scope=https://graph.microsoft.com/.default' 中)发送任意数据包。我在功能SendData中通过DbgPrint可以看到我已经收到了数据包,但是在 WireShark 中找不到该数据包。

只要来自FilterReceiveNetBufferLists的代码被调用或直接粘贴到SendData函数中,它就可以正常工作。但是现在,由于FilterSendNetBufferLists的执行是由用户空间应用程序触发的,因此它不再起作用。

您有什么可能的猜测吗?

解决方法

Wireshark是一件有趣的事情,因为它不一定告诉您确切的事实。如果可能的话,我建议在另一台PC上运行Wireshark,这将使您对电线上的实际情况有更清晰的了解。 (从最纯粹的角度来看:请禁用另一台PC的硬件卸载,尤其是RSC,因此另一台PC的NIC不会在捕获数据包之前先处理它们。)

较旧版本的Wireshark具有名为NPF的NDIS5协议驱动程序。这个家伙坐在所有过滤器驱动程序的上方,因此他通常不会看到任何Tx流量。但是作为这种情况的特殊让步,NDIS将把Tx路径循环回到Rx路径(设置了NDIS_NBL_FLAGS_IS_LOOPBACK_PACKET标志),因此像NPF这样的旧驱动程序可以在其Rx路径中看到Tx数据包的副本。

最近,npcap项目将旧的NPF驱动程序转换为名为NPCAP的NDIS6 LWF。由于多种原因,此驱动程序要好得多,但要记住的一件事是,作为过滤器驱动程序,它位于过滤器堆栈中的某个位置。如果它位于您的LWF之上,那么它将看不到您传输(或修改)的任何数据包。

使用!ndiskd.miniport进行检查,以查看计算机上的wireshark是什么样的:它是一个名为NPF的协议,还是一个名为NPCAP的筛选器驱动程序。如果是后者,它是在过滤器驱动程序之上还是之下?

无论如何,这就是说,您不能完全将Wireshark与要测试的驱动程序放在同一盒子上。在单独的机器上进行数据包捕获会更好,更容易。

对于您的代码,请确保您的FilterSendNetBufferListsComplete处理程序正在查找所有NBL,并删除其NET_BUFFER_LIST :: SourceHandle等于您的OriginalNdisFilterHandle的NBL。那些应该被释放回NdisFreeNetBufferList(或缓存以供以后重用,但是NDIS已经做了不错的缓存工作)。您可能已经有了该代码,但并没有将其添加到pastebin中。

我看不到任何会导致Tx总是失败的东西。您确实需要跟踪过滤器的暂停状态,并在暂停时阻止(或排队)Tx操作。因此,您的SendData函数可以这样编写:

NTSTATUS SendData(MY_FILTER *filter) {
    if (!ExAcquireRundownProtection(&filter->PauseRundown)) {
        return STATUS_NDIS_PAUSED;
    }

    . . . allocate and send NBL . . .;

    return STATUS_SUCCESS;
}

void FilterSendNetBufferListsComplete(MY_FILTER *filter,NET_BUFFER_LIST *nblChain) {
    for (auto nbl = nblChain; nbl; nbl = nbl->Next) {
        if (nbl->SourceHandle == filter->NdisHandle) {
            . . . detach NBL from chain . . .;
            . . . free NBL back to NDIS . . .;
            ExReleaseRundownProtection(&filter->PauseRundown);
        }
    }
}

void FilterPause(MY_FILTER *filter) {
    ExWaitForRundownProtectionRelease(&filter->PauseRundown);
}

void FilterRestart(MY_FILTER *filter) {
    ExReInitializeRundownProtection(&filter->PauseRundown);
}

如果弄错了,那么有时在发送数据包时NDIS将崩溃。如果您不幸在数据路径暂停的情况下发送它们,则某些数据包也将悄悄地无法发送。 (解决此问题不会神奇地导致数据包始终能够成功传输-这只是意味着它不再安静了:当NIC尚未准备就绪时,尝试发送数据包时会看到STATUS_NDIS_PAUSED。 )

,

我成功了:错误出在我的OriginalNdisFilterHandle中。我在函数FilterAttach中进行了设置,但并不认为该函数会被多次调用。因此,该变量的值有误。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...