mirror of
https://github.com/espressif/openthread.git
synced 2026-10-09 01:07:39 +00:00
Python Sniffer Implementation for Windows (#1147)
* Initial function loading of new listener interface. * Additional changes for Node sniffer interface * Use Interface Index instead of GUID * Initialize Handle in sniffer * Put Channel in the sniffer message
This commit is contained in:
@@ -39,12 +39,19 @@ typedef VOID (*fp_otvmpCloseHandle)(_In_ HANDLE handle);
|
||||
typedef DWORD (*fp_otvmpAddVirtualBus)(_In_ HANDLE handle, _Inout_ ULONG* pBusNumber, _Out_ ULONG* pIfIndex);
|
||||
typedef DWORD (*fp_otvmpRemoveVirtualBus)(_In_ HANDLE handle, ULONG BusNumber);
|
||||
typedef DWORD (*fp_otvmpSetAdapterTopologyGuid)(_In_ HANDLE handle, DWORD BusNumber, _In_ const GUID* pTopologyGuid);
|
||||
typedef void (*fp_otvmpListenerCallback)(_In_opt_ PVOID aContext, _In_ ULONG SourceInterfaceIndex, _In_reads_bytes_(FrameLength) PUCHAR FrameBuffer, _In_ UCHAR FrameLength, _In_ UCHAR Channel);
|
||||
typedef HANDLE (*fp_otvmpListenerCreate)(_In_ const GUID* pAdapterTopologyGuid);
|
||||
typedef void (*fp_otvmpListenerDestroy)(_In_opt_ HANDLE pHandle);
|
||||
typedef void(*fp_otvmpListenerRegister)(_In_ HANDLE pHandle, _In_opt_ fp_otvmpListenerCallback Callback, _In_opt_ PVOID Context);
|
||||
|
||||
fp_otvmpOpenHandle otvmpOpenHandle = nullptr;
|
||||
fp_otvmpCloseHandle otvmpCloseHandle = nullptr;
|
||||
fp_otvmpAddVirtualBus otvmpAddVirtualBus = nullptr;
|
||||
fp_otvmpRemoveVirtualBus otvmpRemoveVirtualBus = nullptr;
|
||||
fp_otvmpSetAdapterTopologyGuid otvmpSetAdapterTopologyGuid = nullptr;
|
||||
fp_otvmpListenerCreate otvmpListenerCreate = nullptr;
|
||||
fp_otvmpListenerDestroy otvmpListenerDestroy = nullptr;
|
||||
fp_otvmpListenerRegister otvmpListenerRegister = nullptr;
|
||||
|
||||
HMODULE gVmpModule = nullptr;
|
||||
HANDLE gVmpHandle = nullptr;
|
||||
@@ -53,6 +60,8 @@ ULONG gNextBusNumber = 1;
|
||||
GUID gTopologyGuid = {0};
|
||||
|
||||
volatile LONG gNumberOfInterfaces = 0;
|
||||
CRITICAL_SECTION gCS;
|
||||
vector<otNode*> gNodes;
|
||||
|
||||
otApiInstance *gApiInstance = nullptr;
|
||||
|
||||
@@ -119,18 +128,27 @@ otApiInstance* GetApiInstance()
|
||||
otvmpAddVirtualBus = (fp_otvmpAddVirtualBus)GetProcAddress(gVmpModule, "otvmpAddVirtualBus");
|
||||
otvmpRemoveVirtualBus = (fp_otvmpRemoveVirtualBus)GetProcAddress(gVmpModule, "otvmpRemoveVirtualBus");
|
||||
otvmpSetAdapterTopologyGuid = (fp_otvmpSetAdapterTopologyGuid)GetProcAddress(gVmpModule, "otvmpSetAdapterTopologyGuid");
|
||||
otvmpListenerCreate = (fp_otvmpListenerCreate)GetProcAddress(gVmpModule, "otvmpListenerCreate");
|
||||
otvmpListenerDestroy = (fp_otvmpListenerDestroy)GetProcAddress(gVmpModule, "otvmpListenerDestroy");
|
||||
otvmpListenerRegister = (fp_otvmpListenerRegister)GetProcAddress(gVmpModule, "otvmpListenerRegister");
|
||||
|
||||
assert(otvmpOpenHandle);
|
||||
assert(otvmpCloseHandle);
|
||||
assert(otvmpAddVirtualBus);
|
||||
assert(otvmpRemoveVirtualBus);
|
||||
assert(otvmpSetAdapterTopologyGuid);
|
||||
assert(otvmpListenerCreate);
|
||||
assert(otvmpListenerDestroy);
|
||||
assert(otvmpListenerRegister);
|
||||
|
||||
if (otvmpOpenHandle == nullptr) printf("otvmpOpenHandle is null!\r\n");
|
||||
if (otvmpCloseHandle == nullptr) printf("otvmpCloseHandle is null!\r\n");
|
||||
if (otvmpAddVirtualBus == nullptr) printf("otvmpAddVirtualBus is null!\r\n");
|
||||
if (otvmpRemoveVirtualBus == nullptr) printf("otvmpRemoveVirtualBus is null!\r\n");
|
||||
if (otvmpSetAdapterTopologyGuid == nullptr) printf("otvmpSetAdapterTopologyGuid is null!\r\n");
|
||||
if (otvmpListenerCreate == nullptr) printf("otvmpListenerCreate is null!\r\n");
|
||||
if (otvmpListenerDestroy == nullptr) printf("otvmpListenerDestroy is null!\r\n");
|
||||
if (otvmpListenerRegister == nullptr) printf("otvmpListenerRegister is null!\r\n");
|
||||
|
||||
(VOID)otvmpOpenHandle(&gVmpHandle);
|
||||
if (gVmpHandle == nullptr)
|
||||
@@ -146,6 +164,8 @@ otApiInstance* GetApiInstance()
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
InitializeCriticalSection(&gCS);
|
||||
|
||||
auto offset = getenv("INSTANCE");
|
||||
if (offset)
|
||||
{
|
||||
@@ -187,6 +207,8 @@ void Unload()
|
||||
otApiFinalize(gApiInstance);
|
||||
gApiInstance = nullptr;
|
||||
|
||||
DeleteCriticalSection(&gCS);
|
||||
|
||||
WSACleanup();
|
||||
|
||||
printf("Topology destroyed\r\n");
|
||||
@@ -263,6 +285,7 @@ typedef struct otNode
|
||||
{
|
||||
uint32_t mId;
|
||||
DWORD mBusIndex;
|
||||
DWORD mInterfaceIndex;
|
||||
otInstance* mInstance;
|
||||
HANDLE mEnergyScanEvent;
|
||||
HANDLE mPanIdConflictEvent;
|
||||
@@ -762,12 +785,17 @@ OTNODEAPI otNode* OTCALL otNodeInit(uint32_t id)
|
||||
printf("%d: New Device " GUID_FORMAT " in compartment %d\r\n", id, GUID_ARG(DeviceGuid), Compartment);
|
||||
|
||||
node->mId = id;
|
||||
node->mInterfaceIndex = ifIndex;
|
||||
node->mBusIndex = newBusIndex;
|
||||
node->mInstance = instance;
|
||||
|
||||
node->mEnergyScanEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
|
||||
node->mPanIdConflictEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
|
||||
|
||||
EnterCriticalSection(&gCS);
|
||||
gNodes.push_back(node);
|
||||
LeaveCriticalSection(&gCS);
|
||||
|
||||
InitializeCriticalSection(&node->mCS);
|
||||
|
||||
otSetStateChangedCallback(instance, otNodeStateChangedCallback, node);
|
||||
@@ -795,6 +823,17 @@ OTNODEAPI int32_t OTCALL otNodeFinalize(otNode* aNode)
|
||||
CloseHandle(aNode->mEnergyScanEvent);
|
||||
otSetStateChangedCallback(aNode->mInstance, nullptr, nullptr);
|
||||
|
||||
EnterCriticalSection(&gCS);
|
||||
for (uint32_t i = 0; i < gNodes.size(); i++)
|
||||
{
|
||||
if (gNodes[i] == aNode)
|
||||
{
|
||||
gNodes.erase(gNodes.begin() + i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection(&gCS);
|
||||
|
||||
// Free the instance
|
||||
otFreeMemory(aNode->mInstance);
|
||||
aNode->mInstance = nullptr;
|
||||
@@ -2056,3 +2095,178 @@ OTNODEAPI int32_t OTCALL otNodeSetMaxChildren(otNode* aNode, uint8_t aMaxChildre
|
||||
otLogFuncExit();
|
||||
return result;
|
||||
}
|
||||
|
||||
typedef struct otMacFrameEntry
|
||||
{
|
||||
otMacFrame Frame;
|
||||
LIST_ENTRY Link;
|
||||
} otMacFrameEntry;
|
||||
|
||||
typedef struct otListener
|
||||
{
|
||||
HANDLE mListener;
|
||||
CRITICAL_SECTION mCS;
|
||||
HANDLE mStopEvent;
|
||||
HANDLE mFramesUpdatedEvent;
|
||||
LIST_ENTRY mFrames; // List of otMacFrameEntry
|
||||
} otListener;
|
||||
|
||||
void
|
||||
otListenerCallback(
|
||||
_In_opt_ PVOID aContext,
|
||||
_In_ ULONG SourceInterfaceIndex,
|
||||
_In_reads_bytes_(FrameLength) PUCHAR FrameBuffer,
|
||||
_In_ UCHAR FrameLength,
|
||||
_In_ UCHAR Channel
|
||||
)
|
||||
{
|
||||
otListener* aListener = (otListener*)aContext;
|
||||
assert(aListener);
|
||||
|
||||
if (FrameLength)
|
||||
{
|
||||
otMacFrameEntry* entry = new otMacFrameEntry;
|
||||
entry->Frame.buffer[0] = Channel;
|
||||
memcpy_s(entry->Frame.buffer + 1, sizeof(entry->Frame.buffer) - 1, FrameBuffer, FrameLength);
|
||||
entry->Frame.length = FrameLength + 1;
|
||||
entry->Frame.nodeid = (uint32_t)-1;
|
||||
|
||||
// Look up the Node ID from by interface guid
|
||||
EnterCriticalSection(&gCS);
|
||||
for (uint32_t i = 0; i < gNodes.size(); i++)
|
||||
{
|
||||
if (gNodes[i]->mInterfaceIndex == SourceInterfaceIndex)
|
||||
{
|
||||
entry->Frame.nodeid = gNodes[i]->mId;
|
||||
break;
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection(&gCS);
|
||||
|
||||
// Push the frame on the list to process
|
||||
EnterCriticalSection(&aListener->mCS);
|
||||
InsertTailList(&aListener->mFrames, &entry->Link);
|
||||
LeaveCriticalSection(&aListener->mCS);
|
||||
|
||||
// Set event indicating we have a new frame to process
|
||||
SetEvent(aListener->mFramesUpdatedEvent);
|
||||
}
|
||||
}
|
||||
|
||||
OTNODEAPI otListener* OTCALL otListenerInit(uint32_t /* nodeid */)
|
||||
{
|
||||
otLogFuncEntry();
|
||||
|
||||
auto ApiInstance = GetApiInstance();
|
||||
if (ApiInstance == nullptr)
|
||||
{
|
||||
printf("GetApiInstance failed!\r\n");
|
||||
otLogFuncExitMsg("GetApiInstance failed");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
InterlockedIncrement(&gNumberOfInterfaces);
|
||||
|
||||
otListener *listener = new otListener();
|
||||
assert(listener);
|
||||
|
||||
InitializeCriticalSection(&listener->mCS);
|
||||
listener->mStopEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
|
||||
listener->mFramesUpdatedEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
|
||||
InitializeListHead(&listener->mFrames);
|
||||
|
||||
// Create the listener
|
||||
listener->mListener = otvmpListenerCreate(&gTopologyGuid);
|
||||
assert(listener->mListener);
|
||||
|
||||
// Register for callbacks
|
||||
otvmpListenerRegister(listener->mListener, otListenerCallback, listener);
|
||||
|
||||
printf("S: Sniffer started\r\n");
|
||||
|
||||
otLogFuncExit();
|
||||
|
||||
return listener;
|
||||
}
|
||||
|
||||
OTNODEAPI int32_t OTCALL otListenerFinalize(otListener* aListener)
|
||||
{
|
||||
otLogFuncEntry();
|
||||
if (aListener != nullptr)
|
||||
{
|
||||
// Set stop event to prevent cancel any pending otListenerRead calls
|
||||
SetEvent(aListener->mStopEvent);
|
||||
|
||||
// Unregisters (and waits for callbacks to complete) and cleans up the handle
|
||||
otvmpListenerDestroy(aListener->mListener);
|
||||
aListener->mListener = nullptr;
|
||||
|
||||
// Clean up left over frames
|
||||
PLIST_ENTRY Link = aListener->mFrames.Flink;
|
||||
while (Link != &aListener->mFrames)
|
||||
{
|
||||
otMacFrameEntry *entry = CONTAINING_RECORD(Link, otMacFrameEntry, Link);
|
||||
Link = Link->Flink;
|
||||
delete entry;
|
||||
}
|
||||
|
||||
// Clean up everything else
|
||||
CloseHandle(aListener->mFramesUpdatedEvent);
|
||||
aListener->mFramesUpdatedEvent = nullptr;
|
||||
CloseHandle(aListener->mStopEvent);
|
||||
aListener->mStopEvent = nullptr;
|
||||
DeleteCriticalSection(&aListener->mCS);
|
||||
delete aListener;
|
||||
|
||||
printf("S: Sniffer stopped\r\n");
|
||||
|
||||
if (0 == InterlockedDecrement(&gNumberOfInterfaces))
|
||||
{
|
||||
// Uninitialize everything else if this is the last ref
|
||||
Unload();
|
||||
}
|
||||
}
|
||||
otLogFuncExit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
OTNODEAPI int32_t OTCALL otListenerRead(otListener* aListener, otMacFrame *aFrame)
|
||||
{
|
||||
do
|
||||
{
|
||||
bool exit = false;
|
||||
|
||||
EnterCriticalSection(&aListener->mCS);
|
||||
|
||||
// If we have a pending frame, return it now
|
||||
if (!IsListEmpty(&aListener->mFrames))
|
||||
{
|
||||
PLIST_ENTRY Link = RemoveHeadList(&aListener->mFrames);
|
||||
otMacFrameEntry *entry = CONTAINING_RECORD(Link, otMacFrameEntry, Link);
|
||||
*aFrame = entry->Frame;
|
||||
delete entry;
|
||||
exit = true;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&aListener->mCS);
|
||||
|
||||
if (exit) break;
|
||||
|
||||
// Wait for the shutdown or frames updated event
|
||||
auto waitResult = WaitForMultipleObjects(2, &aListener->mStopEvent, FALSE, INFINITE);
|
||||
|
||||
if (waitResult == WAIT_OBJECT_0 + 1) // mFramesUpdatedEvent
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else // mStopEvent
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
} while (true);
|
||||
|
||||
//printf("S: Sniffer read %d bytes from node %d\r\n", aFrame->length, aFrame->nodeid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user