Skip to content

Commit 9f835d9

Browse files
committed
Fix #294 for ethernet layer branch
Seems to solve the network-stop problem, see #326
1 parent b83e741 commit 9f835d9

File tree

1 file changed

+121
-108
lines changed

1 file changed

+121
-108
lines changed

sys/windivert.c

Lines changed: 121 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,8 @@ extern VOID windivert_create(IN WDFDEVICE device, IN WDFREQUEST request,
339339
static NTSTATUS windivert_install_sublayer(layer_t layer);
340340
static NTSTATUS windivert_install_callouts(context_t context, UINT8 layer,
341341
UINT64 flags);
342+
static NTSTATUS windivert_install_callout(context_t context, UINT idx,
343+
layer_t layer, UINT32 *callout_id_ptr);
342344
static void windivert_uninstall_callouts(context_t context,
343345
context_state_t state);
344346
extern VOID windivert_cleanup(IN WDFFILEOBJECT object);
@@ -1224,6 +1226,7 @@ extern NTSTATUS DriverEntry(IN PDRIVER_OBJECT driver_obj,
12241226
if (!NT_SUCCESS(status))
12251227
{
12261228
DEBUG_ERROR("failed to begin WFP transaction", status);
1229+
FwpmTransactionAbort0(engine_handle);
12271230
goto driver_entry_exit;
12281231
}
12291232
status = windivert_install_sublayer(
@@ -1347,6 +1350,7 @@ extern NTSTATUS DriverEntry(IN PDRIVER_OBJECT driver_obj,
13471350
if (!NT_SUCCESS(status))
13481351
{
13491352
DEBUG_ERROR("failed to commit WFP transaction", status);
1353+
FwpmTransactionAbort0(engine_handle);
13501354
goto driver_entry_exit;
13511355
}
13521356

@@ -1482,6 +1486,7 @@ static void windivert_driver_unload(void)
14821486
if (!NT_SUCCESS(status))
14831487
{
14841488
DEBUG_ERROR("failed to commit WFP transaction", status);
1489+
FwpmTransactionAbort0(engine_handle);
14851490
}
14861491
FwpmEngineClose0(engine_handle);
14871492
}
@@ -1653,17 +1658,10 @@ static NTSTATUS windivert_install_callouts(context_t context, UINT8 layer,
16531658
KLOCK_QUEUE_HANDLE lock_handle;
16541659
UINT8 i, j;
16551660
layer_t layers[WINDIVERT_CONTEXT_MAXLAYERS];
1656-
UINT32 callout_ids[WINDIVERT_CONTEXT_MAXLAYERS] = {0};
1661+
UINT32 *callout_ids[WINDIVERT_CONTEXT_MAXLAYERS] = {NULL};
16571662
BOOL inbound, outbound, ipv4, ipv6, bind, connect, listen,
16581663
accept, close;
16591664
HANDLE engine = NULL;
1660-
FWPS_CALLOUT0 scallout;
1661-
FWPM_CALLOUT0 mcallout;
1662-
FWPM_FILTER0 filter;
1663-
UINT64 weight;
1664-
UINT32 priority;
1665-
GUID callout_guid, filter_guid;
1666-
WDFDEVICE device;
16671665
NTSTATUS status = STATUS_SUCCESS;
16681666

16691667
inbound = ((flags & WINDIVERT_FILTER_FLAG_INBOUND) != 0);
@@ -1723,10 +1721,12 @@ static NTSTATUS windivert_install_callouts(context_t context, UINT8 layer,
17231721
case WINDIVERT_LAYER_FLOW:
17241722
if (ipv4)
17251723
{
1724+
callout_ids[i] = &context->flow_v4_callout_id;
17261725
layers[i++] = WINDIVERT_LAYER_FLOW_ESTABLISHED_IPV4;
17271726
}
17281727
if (ipv6)
17291728
{
1729+
callout_ids[i] = &context->flow_v6_callout_id;
17301730
layers[i++] = WINDIVERT_LAYER_FLOW_ESTABLISHED_IPV6;
17311731
}
17321732
break;
@@ -1769,7 +1769,6 @@ static NTSTATUS windivert_install_callouts(context_t context, UINT8 layer,
17691769
{
17701770
layers[i++] = WINDIVERT_LAYER_AUTH_RECV_ACCEPT_IPV6;
17711771
}
1772-
17731772
if (ipv6 && close)
17741773
{
17751774
layers[i++] = WINDIVERT_LAYER_RESOURCE_RELEASE_IPV6;
@@ -1778,64 +1777,23 @@ static NTSTATUS windivert_install_callouts(context_t context, UINT8 layer,
17781777
break;
17791778

17801779
case WINDIVERT_LAYER_REFLECT:
1781-
return STATUS_SUCCESS;
1780+
break;
17821781

17831782
default:
17841783
return STATUS_INVALID_PARAMETER;
17851784
}
17861785

17871786
if (i == 0)
17881787
{
1789-
// Nothing to do...
17901788
return STATUS_SUCCESS;
17911789
}
17921790

1793-
// Register the callouts:
17941791
KeAcquireInStackQueuedSpinLock(&context->lock, &lock_handle);
1795-
for (j = 0; j < i; j++)
1796-
{
1797-
if (context->state != WINDIVERT_CONTEXT_STATE_OPEN)
1798-
{
1799-
KeReleaseInStackQueuedSpinLock(&lock_handle);
1800-
status = STATUS_INVALID_DEVICE_STATE;
1801-
goto windivert_install_callouts_error;
1802-
}
1803-
device = context->device;
1804-
RtlCopyMemory(&callout_guid, &context->callout_guid[j],
1805-
sizeof(callout_guid));
1806-
KeReleaseInStackQueuedSpinLock(&lock_handle);
1807-
1808-
RtlZeroMemory(&scallout, sizeof(scallout));
1809-
scallout.calloutKey = callout_guid;
1810-
scallout.classifyFn = layers[j]->classify;
1811-
scallout.notifyFn = windivert_notify;
1812-
scallout.flowDeleteFn = layers[j]->flow_delete;
1813-
1814-
status = FwpsCalloutRegister0(WdfDeviceWdmGetDeviceObject(device),
1815-
&scallout, callout_ids + j);
1816-
if (!NT_SUCCESS(status))
1817-
{
1818-
goto windivert_install_callouts_error;
1819-
}
1820-
1821-
DEBUG("REGISTER: callout %ls", layers[j]->callout_name);
1822-
1823-
KeAcquireInStackQueuedSpinLock(&context->lock, &lock_handle);
1824-
context->installed[j] = TRUE;
1825-
if (layers[j] == WINDIVERT_LAYER_FLOW_ESTABLISHED_IPV4)
1826-
{
1827-
context->flow_v4_callout_id = callout_ids[j];
1828-
}
1829-
else if (layers[j] == WINDIVERT_LAYER_FLOW_ESTABLISHED_IPV6)
1830-
{
1831-
context->flow_v6_callout_id = callout_ids[j];
1832-
}
1833-
}
18341792
if (context->state != WINDIVERT_CONTEXT_STATE_OPEN)
18351793
{
18361794
KeReleaseInStackQueuedSpinLock(&lock_handle);
18371795
status = STATUS_INVALID_DEVICE_STATE;
1838-
goto windivert_install_callouts_error;
1796+
return status;
18391797
}
18401798
engine = context->engine_handle;
18411799
KeReleaseInStackQueuedSpinLock(&lock_handle);
@@ -1849,82 +1807,136 @@ static NTSTATUS windivert_install_callouts(context_t context, UINT8 layer,
18491807
if (!NT_SUCCESS(status))
18501808
{
18511809
DEBUG_ERROR("failed to begin WFP transaction", status);
1852-
goto windivert_install_callouts_error;
1810+
engine = NULL;
1811+
goto windivert_install_callouts_exit;
18531812
}
18541813
for (j = 0; j < i; j++)
18551814
{
1856-
KeAcquireInStackQueuedSpinLock(&context->lock, &lock_handle);
1857-
if (context->state != WINDIVERT_CONTEXT_STATE_OPEN)
1858-
{
1859-
KeReleaseInStackQueuedSpinLock(&lock_handle);
1860-
status = STATUS_INVALID_DEVICE_STATE;
1861-
goto windivert_install_callouts_error;
1862-
}
1863-
priority = context->priority;
1864-
RtlCopyMemory(&callout_guid, &context->callout_guid[j],
1865-
sizeof(callout_guid));
1866-
RtlCopyMemory(&filter_guid, &context->filter_guid[j],
1867-
sizeof(filter_guid));
1868-
KeReleaseInStackQueuedSpinLock(&lock_handle);
1869-
1870-
weight = (UINT64)priority;
1871-
1872-
RtlZeroMemory(&mcallout, sizeof(mcallout));
1873-
mcallout.calloutKey = callout_guid;
1874-
mcallout.displayData.name = layers[j]->callout_name;
1875-
mcallout.displayData.description = layers[j]->callout_desc;
1876-
mcallout.applicableLayer = *(layers[j]->layer_guid);
1877-
RtlZeroMemory(&filter, sizeof(filter));
1878-
filter.filterKey = filter_guid;
1879-
filter.layerKey = *(layers[j]->layer_guid);
1880-
filter.displayData.name = layers[j]->filter_name;
1881-
filter.displayData.description = layers[j]->filter_desc;
1882-
filter.action.type = FWP_ACTION_CALLOUT_UNKNOWN;
1883-
filter.action.calloutKey = callout_guid;
1884-
filter.subLayerKey = *(layers[j]->sublayer_guid);
1885-
filter.weight.type = FWP_UINT64;
1886-
filter.weight.uint64 = &weight;
1887-
filter.rawContext = (UINT64)context;
1888-
1889-
status = FwpmCalloutAdd0(engine, &mcallout, NULL, NULL);
1815+
status = windivert_install_callout(context, j, layers[j],
1816+
callout_ids[j]);
18901817
if (!NT_SUCCESS(status))
18911818
{
1892-
DEBUG_ERROR("failed to add WFP callout", status);
1893-
goto windivert_install_callouts_error;
1819+
goto windivert_install_callouts_exit;
18941820
}
1895-
status = FwpmFilterAdd0(engine, &filter, NULL, NULL);
1896-
if (!NT_SUCCESS(status))
1897-
{
1898-
DEBUG_ERROR("failed to add WFP filter", status);
1899-
goto windivert_install_callouts_error;
1900-
}
1901-
1902-
DEBUG("INSTALL: callout %ls", layers[j]->callout_name);
19031821
}
19041822
status = FwpmTransactionCommit0(engine);
19051823
if (!NT_SUCCESS(status))
19061824
{
19071825
DEBUG_ERROR("failed to commit WFP transaction", status);
1908-
goto windivert_install_callouts_error;
1826+
goto windivert_install_callouts_exit;
19091827
}
1828+
engine = NULL;
19101829

1911-
return status;
1912-
1913-
windivert_install_callouts_error:
1830+
windivert_install_callouts_exit:
19141831

19151832
if (engine != NULL)
19161833
{
19171834
FwpmTransactionAbort0(engine);
19181835
}
1919-
for (j = 0; j < i; j++)
1836+
if (!NT_SUCCESS(status))
19201837
{
1921-
if (callout_ids[j] == 0)
1922-
{
1923-
continue;
1924-
}
1925-
FwpsCalloutUnregisterById0(callout_ids[j]);
1838+
windivert_uninstall_callouts(context, WINDIVERT_CONTEXT_STATE_OPEN);
1839+
}
1840+
1841+
return status;
1842+
}
1843+
1844+
/*
1845+
* Register a WFP callout.
1846+
*/
1847+
static NTSTATUS windivert_install_callout(context_t context, UINT idx,
1848+
layer_t layer, UINT32 *callout_id_ptr)
1849+
{
1850+
KLOCK_QUEUE_HANDLE lock_handle;
1851+
FWPS_CALLOUT0 scallout;
1852+
FWPM_CALLOUT0 mcallout;
1853+
FWPM_FILTER0 filter;
1854+
UINT64 weight;
1855+
UINT32 priority;
1856+
GUID callout_guid, filter_guid;
1857+
UINT32 callout_id;
1858+
WDFDEVICE device;
1859+
HANDLE engine;
1860+
NTSTATUS status;
1861+
1862+
KeAcquireInStackQueuedSpinLock(&context->lock, &lock_handle);
1863+
if (context->state != WINDIVERT_CONTEXT_STATE_OPEN)
1864+
{
1865+
KeReleaseInStackQueuedSpinLock(&lock_handle);
1866+
status = STATUS_INVALID_DEVICE_STATE;
1867+
return status;
1868+
}
1869+
priority = context->priority;
1870+
callout_guid = context->callout_guid[idx];
1871+
filter_guid = context->filter_guid[idx];
1872+
device = context->device;
1873+
engine = context->engine_handle;
1874+
KeReleaseInStackQueuedSpinLock(&lock_handle);
1875+
1876+
weight = (UINT64)priority;
1877+
1878+
RtlZeroMemory(&scallout, sizeof(scallout));
1879+
scallout.calloutKey = callout_guid;
1880+
scallout.classifyFn = layer->classify;
1881+
scallout.notifyFn = windivert_notify;
1882+
scallout.flowDeleteFn = layer->flow_delete;
1883+
RtlZeroMemory(&mcallout, sizeof(mcallout));
1884+
mcallout.calloutKey = callout_guid;
1885+
mcallout.displayData.name = layer->callout_name;
1886+
mcallout.displayData.description = layer->callout_desc;
1887+
mcallout.applicableLayer = *(layer->layer_guid);
1888+
RtlZeroMemory(&filter, sizeof(filter));
1889+
filter.filterKey = filter_guid;
1890+
filter.layerKey = *(layer->layer_guid);
1891+
filter.displayData.name = layer->filter_name;
1892+
filter.displayData.description = layer->filter_desc;
1893+
filter.action.type = FWP_ACTION_CALLOUT_UNKNOWN;
1894+
filter.action.calloutKey = callout_guid;
1895+
filter.subLayerKey = *(layer->sublayer_guid);
1896+
filter.weight.type = FWP_UINT64;
1897+
filter.weight.uint64 = &weight;
1898+
filter.rawContext = (UINT64)context;
1899+
status = FwpsCalloutRegister0(WdfDeviceWdmGetDeviceObject(device),
1900+
&scallout, &callout_id);
1901+
if (!NT_SUCCESS(status))
1902+
{
1903+
DEBUG_ERROR("failed to install WFP callout", status);
1904+
return status;
1905+
}
1906+
if (callout_id_ptr != NULL)
1907+
{
1908+
KeAcquireInStackQueuedSpinLock(&context->lock, &lock_handle);
1909+
*callout_id_ptr = callout_id;
1910+
KeReleaseInStackQueuedSpinLock(&lock_handle);
1911+
}
1912+
status = FwpmCalloutAdd0(engine, &mcallout, NULL, NULL);
1913+
if (!NT_SUCCESS(status))
1914+
{
1915+
DEBUG_ERROR("failed to add WFP callout", status);
1916+
goto windivert_install_callout_error;
1917+
}
1918+
status = FwpmFilterAdd0(engine, &filter, NULL, NULL);
1919+
if (!NT_SUCCESS(status))
1920+
{
1921+
DEBUG_ERROR("failed to add WFP filter", status);
1922+
goto windivert_install_callout_error;
19261923
}
19271924

1925+
KeAcquireInStackQueuedSpinLock(&context->lock, &lock_handle);
1926+
if (context->state != WINDIVERT_CONTEXT_STATE_OPEN)
1927+
{
1928+
KeReleaseInStackQueuedSpinLock(&lock_handle);
1929+
FwpsCalloutUnregisterByKey0(&callout_guid);
1930+
status = STATUS_INVALID_DEVICE_STATE;
1931+
return status;
1932+
}
1933+
context->installed[idx] = TRUE;
1934+
KeReleaseInStackQueuedSpinLock(&lock_handle);
1935+
1936+
return STATUS_SUCCESS;
1937+
1938+
windivert_install_callout_error:
1939+
FwpsCalloutUnregisterByKey0(&callout_guid);
19281940
return status;
19291941
}
19301942

@@ -2939,7 +2951,7 @@ static NTSTATUS windivert_write(context_t context, WDFREQUEST request,
29392951
{
29402952
case WINDIVERT_LAYER_ETHERNET:
29412953

2942-
// Ethernet inject requires the WFP filters to remain valid.
2954+
// Ethernet inject requires the WFP filters to be valid.
29432955
// Thus, we increment the ref count for the context object
29442956
// until the inject is completed. This prevents the filter
29452957
// from being removed until the injection has completed.
@@ -2969,6 +2981,7 @@ static NTSTATUS windivert_write(context_t context, WDFREQUEST request,
29692981
addr[i].Ethernet.IfIdx, addr[i].Ethernet.SubIfIdx,
29702982
buffers, windivert_inject_complete, object);
29712983
}
2984+
29722985
if (!NT_SUCCESS(status))
29732986
{
29742987
WdfObjectDereference(object);

0 commit comments

Comments
 (0)