mirror of
https://github.com/nmap/nmap.git
synced 2025-12-10 09:49:05 +00:00
279 lines
8.2 KiB
Diff
279 lines
8.2 KiB
Diff
From b91a93895633da9b8184691effc487d8b0c8e82c Mon Sep 17 00:00:00 2001
|
|
From: Daniel Miller <daniel@bonsaiviking.com>
|
|
Date: Sun, 20 Sep 2015 18:45:22 +0000
|
|
Subject: [PATCH] Use a mutex on Windows to avoid a hang when accessing WinPCAP
|
|
driver
|
|
|
|
Reported by multiple users on Windows 8.1 and Windows Server 2012 R2.
|
|
Seems to hang when the WinPCAP driver is accessed via OpenServiceA by
|
|
multiple processes at once. Users report that this change, which uses a
|
|
mutex to avoid concurrent access, fixes the hang.
|
|
---
|
|
libpcap/fad-win32.c | 35 ++++++++++++++++++++++++++++++++++
|
|
libpcap/inet.c | 40 +++++++++++++++++++++++++++++++++++++++
|
|
libpcap/pcap-win32.c | 25 ++++++++++++++++++++++++
|
|
3 files changed, 100 insertions(+)
|
|
|
|
diff --git a/libpcap/fad-win32.c b/libpcap/fad-win32.c
|
|
index 0c856b1..f849d40 100644
|
|
--- a/libpcap/fad-win32.c
|
|
+++ b/libpcap/fad-win32.c
|
|
@@ -49,6 +49,8 @@ pcap_add_if_win32(pcap_if_t **devlist, char *name, const char *desc,
|
|
npf_if_addr if_addrs[MAX_NETWORK_ADDRESSES];
|
|
LONG if_addr_size;
|
|
int res = 0;
|
|
+ HANDLE pcapMutex;
|
|
+ DWORD wait;
|
|
|
|
if_addr_size = MAX_NETWORK_ADDRESSES;
|
|
|
|
@@ -65,6 +67,8 @@ pcap_add_if_win32(pcap_if_t **devlist, char *name, const char *desc,
|
|
/*
|
|
* Get the list of addresses for the interface.
|
|
*/
|
|
+ pcapMutex = CreateMutex(NULL, 0, "Global\\DnetPcapHangAvoidanceMutex");
|
|
+ wait = WaitForSingleObject(pcapMutex, INFINITE);
|
|
if (!PacketGetNetInfoEx((void *)name, if_addrs, &if_addr_size)) {
|
|
/*
|
|
* Failure.
|
|
@@ -75,8 +79,16 @@ pcap_add_if_win32(pcap_if_t **devlist, char *name, const char *desc,
|
|
*
|
|
* We return an entry with an empty address list.
|
|
*/
|
|
+ if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) {
|
|
+ ReleaseMutex(pcapMutex);
|
|
+ }
|
|
+ CloseHandle(pcapMutex);
|
|
return (0);
|
|
}
|
|
+ if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) {
|
|
+ ReleaseMutex(pcapMutex);
|
|
+ }
|
|
+ CloseHandle(pcapMutex);
|
|
|
|
/*
|
|
* Now add the addresses.
|
|
@@ -127,6 +139,11 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
|
|
char *AdaptersName;
|
|
ULONG NameLength;
|
|
char *name;
|
|
+ HANDLE pcapMutex;
|
|
+ DWORD wait;
|
|
+
|
|
+ pcapMutex = CreateMutex(NULL, 0, "Global\\DnetPcapHangAvoidanceMutex");
|
|
+ wait = WaitForSingleObject(pcapMutex, INFINITE);
|
|
|
|
/*
|
|
* Find out how big a buffer we need.
|
|
@@ -149,6 +166,10 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
|
|
if (!PacketGetAdapterNames(NULL, &NameLength))
|
|
{
|
|
DWORD last_error = GetLastError();
|
|
+ if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) {
|
|
+ ReleaseMutex(pcapMutex);
|
|
+ }
|
|
+ CloseHandle(pcapMutex);
|
|
|
|
if (last_error != ERROR_INSUFFICIENT_BUFFER)
|
|
{
|
|
@@ -158,6 +179,10 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
|
|
return (-1);
|
|
}
|
|
}
|
|
+ if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) {
|
|
+ ReleaseMutex(pcapMutex);
|
|
+ }
|
|
+ CloseHandle(pcapMutex);
|
|
|
|
if (NameLength > 0)
|
|
AdaptersName = (char*) malloc(NameLength);
|
|
@@ -172,13 +197,23 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf)
|
|
return (-1);
|
|
}
|
|
|
|
+ pcapMutex = CreateMutex(NULL, 0, "Global\\DnetPcapHangAvoidanceMutex");
|
|
+ wait = WaitForSingleObject(pcapMutex, INFINITE);
|
|
if (!PacketGetAdapterNames(AdaptersName, &NameLength)) {
|
|
snprintf(errbuf, PCAP_ERRBUF_SIZE,
|
|
"PacketGetAdapterNames: %s",
|
|
pcap_win32strerror());
|
|
free(AdaptersName);
|
|
+ if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) {
|
|
+ ReleaseMutex(pcapMutex);
|
|
+ }
|
|
+ CloseHandle(pcapMutex);
|
|
return (-1);
|
|
}
|
|
+ if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) {
|
|
+ ReleaseMutex(pcapMutex);
|
|
+ }
|
|
+ CloseHandle(pcapMutex);
|
|
|
|
/*
|
|
* "PacketGetAdapterNames()" returned a list of
|
|
diff --git a/libpcap/inet.c b/libpcap/inet.c
|
|
index e7d2104..359557f 100644
|
|
--- a/libpcap/inet.c
|
|
+++ b/libpcap/inet.c
|
|
@@ -983,8 +983,12 @@ pcap_lookupdev(errbuf)
|
|
{
|
|
DWORD dwVersion;
|
|
DWORD dwWindowsMajorVersion;
|
|
+ HANDLE pcapMutex;
|
|
+ DWORD wait;
|
|
dwVersion = GetVersion(); /* get the OS version */
|
|
dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
|
|
+ pcapMutex = CreateMutex(NULL, 0, "Global\\DnetPcapHangAvoidanceMutex");
|
|
+ wait = WaitForSingleObject(pcapMutex, INFINITE);
|
|
|
|
if (dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4) {
|
|
/*
|
|
@@ -994,9 +998,21 @@ pcap_lookupdev(errbuf)
|
|
static char AdaptersName[8192];
|
|
|
|
if (PacketGetAdapterNames(AdaptersName,&NameLength) )
|
|
+ {
|
|
+ if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) {
|
|
+ ReleaseMutex(pcapMutex);
|
|
+ }
|
|
+ CloseHandle(pcapMutex);
|
|
return (AdaptersName);
|
|
+ }
|
|
else
|
|
+ {
|
|
+ if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) {
|
|
+ ReleaseMutex(pcapMutex);
|
|
+ }
|
|
+ CloseHandle(pcapMutex);
|
|
return NULL;
|
|
+ }
|
|
} else {
|
|
/*
|
|
* Windows NT (NT 4.0, W2K, WXP). Convert the names to UNICODE for backward compatibility
|
|
@@ -1016,12 +1032,20 @@ pcap_lookupdev(errbuf)
|
|
|
|
if ( !PacketGetAdapterNames((PTSTR)TAdaptersName,&NameLength) )
|
|
{
|
|
+ if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) {
|
|
+ ReleaseMutex(pcapMutex);
|
|
+ }
|
|
+ CloseHandle(pcapMutex);
|
|
(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
|
|
"PacketGetAdapterNames: %s",
|
|
pcap_win32strerror());
|
|
free(TAdaptersName);
|
|
return NULL;
|
|
}
|
|
+ if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) {
|
|
+ ReleaseMutex(pcapMutex);
|
|
+ }
|
|
+ CloseHandle(pcapMutex);
|
|
|
|
|
|
tAstr = (char*)TAdaptersName;
|
|
@@ -1056,6 +1080,10 @@ pcap_lookupdev(errbuf)
|
|
free(TAdaptersName);
|
|
return (char *)(AdaptersName);
|
|
}
|
|
+ if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) {
|
|
+ ReleaseMutex(pcapMutex);
|
|
+ }
|
|
+ CloseHandle(pcapMutex);
|
|
}
|
|
|
|
|
|
@@ -1073,11 +1101,23 @@ pcap_lookupnet(device, netp, maskp, errbuf)
|
|
LONG if_addr_size = 1;
|
|
struct sockaddr_in *t_addr;
|
|
unsigned int i;
|
|
+ HANDLE pcapMutex;
|
|
+ DWORD wait;
|
|
|
|
+ pcapMutex = CreateMutex(NULL, 0, "Global\\DnetPcapHangAvoidanceMutex");
|
|
+ wait = WaitForSingleObject(pcapMutex, INFINITE);
|
|
if (!PacketGetNetInfoEx((void *)device, if_addrs, &if_addr_size)) {
|
|
+ if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) {
|
|
+ ReleaseMutex(pcapMutex);
|
|
+ }
|
|
+ CloseHandle(pcapMutex);
|
|
*netp = *maskp = 0;
|
|
return (0);
|
|
}
|
|
+ if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) {
|
|
+ ReleaseMutex(pcapMutex);
|
|
+ }
|
|
+ CloseHandle(pcapMutex);
|
|
|
|
for(i=0; i<MAX_NETWORK_ADDRESSES; i++)
|
|
{
|
|
diff --git a/libpcap/pcap-win32.c b/libpcap/pcap-win32.c
|
|
index f449f79..2e83e75 100644
|
|
--- a/libpcap/pcap-win32.c
|
|
+++ b/libpcap/pcap-win32.c
|
|
@@ -492,8 +492,16 @@ pcap_inject_win32(pcap_t *p, const void *buf, size_t size){
|
|
static void
|
|
pcap_cleanup_win32(pcap_t *p)
|
|
{
|
|
+ HANDLE pcapMutex;
|
|
+ DWORD wait;
|
|
if (p->adapter != NULL) {
|
|
+ pcapMutex = CreateMutex(NULL, 0, "Global\\DnetPcapHangAvoidanceMutex");
|
|
+ wait = WaitForSingleObject(pcapMutex, INFINITE);
|
|
PacketCloseAdapter(p->adapter);
|
|
+ if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) {
|
|
+ ReleaseMutex(pcapMutex);
|
|
+ }
|
|
+ CloseHandle(pcapMutex);
|
|
p->adapter = NULL;
|
|
}
|
|
if (p->Packet) {
|
|
@@ -508,6 +516,8 @@ pcap_activate_win32(pcap_t *p)
|
|
{
|
|
struct pcap_win *pw = p->priv;
|
|
NetType type;
|
|
+ HANDLE pcapMutex;
|
|
+ DWORD wait;
|
|
|
|
if (p->opt.rfmon) {
|
|
/*
|
|
@@ -521,11 +531,18 @@ pcap_activate_win32(pcap_t *p)
|
|
/* Init WinSock */
|
|
wsockinit();
|
|
|
|
+ pcapMutex = CreateMutex(NULL, 0, "Global\\DnetPcapHangAvoidanceMutex");
|
|
+ wait = WaitForSingleObject(pcapMutex, INFINITE);
|
|
+
|
|
p->adapter = PacketOpenAdapter(p->opt.source);
|
|
|
|
if (p->adapter == NULL)
|
|
{
|
|
/* Adapter detected but we are not able to open it. Return failure. */
|
|
+ if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) {
|
|
+ ReleaseMutex(pcapMutex);
|
|
+ }
|
|
+ CloseHandle(pcapMutex);
|
|
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Error opening adapter: %s", pcap_win32strerror());
|
|
return PCAP_ERROR;
|
|
}
|
|
@@ -533,9 +550,17 @@ pcap_activate_win32(pcap_t *p)
|
|
/*get network type*/
|
|
if(PacketGetNetType (p->adapter,&type) == FALSE)
|
|
{
|
|
+ if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) {
|
|
+ ReleaseMutex(pcapMutex);
|
|
+ }
|
|
+ CloseHandle(pcapMutex);
|
|
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Cannot determine the network type: %s", pcap_win32strerror());
|
|
goto bad;
|
|
}
|
|
+ if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) {
|
|
+ ReleaseMutex(pcapMutex);
|
|
+ }
|
|
+ CloseHandle(pcapMutex);
|
|
|
|
/*Set the linktype*/
|
|
switch (type.LinkType)
|
|
--
|
|
1.9.1
|
|
|