This patch was enforced by the WHCK logo testing. In order to pass the Windows Filtering Platform tests we need to add a persistent system provider.
Signed-off-by: Sorin Vinturis <svintu...@cloudbasesolutions.com> Reported-by: Sorin Vinturis <svintu...@cloudbasesolutions.com> Reported-at: https://github.com/openvswitch/ovs-issues/issues/65 --- datapath-windows/ovsext/Datapath.c | 2 + datapath-windows/ovsext/Switch.c | 1 - datapath-windows/ovsext/Switch.h | 1 + datapath-windows/ovsext/TunnelFilter.c | 198 ++++++++++++++++++++++++++++++--- datapath-windows/ovsext/TunnelIntf.h | 4 + 5 files changed, 192 insertions(+), 14 deletions(-) diff --git a/datapath-windows/ovsext/Datapath.c b/datapath-windows/ovsext/Datapath.c index a818ab9..12410ef 100644 --- a/datapath-windows/ovsext/Datapath.c +++ b/datapath-windows/ovsext/Datapath.c @@ -356,6 +356,7 @@ OvsInit() gOvsCtrlLock = &ovsCtrlLockObj; NdisAllocateSpinLock(gOvsCtrlLock); OvsInitEventQueue(); + OvsTunnelAddSystemProvider(); } VOID @@ -366,6 +367,7 @@ OvsCleanup() NdisFreeSpinLock(gOvsCtrlLock); gOvsCtrlLock = NULL; } + OvsTunnelRemoveSystemProvider(); } VOID diff --git a/datapath-windows/ovsext/Switch.c b/datapath-windows/ovsext/Switch.c index 2b68037..a228d8e 100644 --- a/datapath-windows/ovsext/Switch.c +++ b/datapath-windows/ovsext/Switch.c @@ -26,7 +26,6 @@ #include "Event.h" #include "Flow.h" #include "IpHelper.h" -#include "TunnelIntf.h" #include "Oid.h" #ifdef OVS_DBG_MOD diff --git a/datapath-windows/ovsext/Switch.h b/datapath-windows/ovsext/Switch.h index 61f74c4..7960072 100644 --- a/datapath-windows/ovsext/Switch.h +++ b/datapath-windows/ovsext/Switch.h @@ -23,6 +23,7 @@ #include "NetProto.h" #include "BufferMgmt.h" +#include "TunnelIntf.h" #define OVS_MAX_VPORT_ARRAY_SIZE 1024 #define OVS_MAX_PID_ARRAY_SIZE 1024 diff --git a/datapath-windows/ovsext/TunnelFilter.c b/datapath-windows/ovsext/TunnelFilter.c index 7250c24..86b98b2 100644 --- a/datapath-windows/ovsext/TunnelFilter.c +++ b/datapath-windows/ovsext/TunnelFilter.c @@ -40,6 +40,25 @@ #define INITGUID #include <guiddef.h> +#define FWP_ERR_NOT_FOUND 0xC0220007L + +/* Infinite timeout */ +#define INFINITE 0xFFFFFFFF + +/* + * The provider name should always match the provider string from the install + * file. + */ +#define OVS_TUNNEL_PROVIDER_NAME L"Open vSwitch" + +/* + * The provider description should always contain the OVS service description + * string from the install file. + */ +#define OVS_TUNNEL_PROVIDER_DESC L"Open vSwitch Extension tunnel provider" + +/* The session name isn't required but it's useful for diagnostics. */ +#define OVS_TUNNEL_SESSION_NAME L"OVS tunnel session" /* Configurable parameters (addresses and ports are in host order) */ UINT16 configNewDestPort = VXLAN_UDP_PORT; @@ -65,6 +84,15 @@ DEFINE_GUID( 0x94, 0xc9, 0xf0, 0xd5, 0x25, 0xbb, 0xc1, 0x69 ); +/* 6fc957d7-14e7-47c7-812b-4668be994ba1 */ +DEFINE_GUID( + OVS_TUNNEL_PROVIDER_KEY, + 0x6fc957d7, + 0x14e7, + 0x47c7, + 0x81, 0x2b, 0x46, 0x68, 0xbe, 0x99, 0x4b, 0xa1 + ); + /* bfd4814c-9650-4de3-a536-1eedb9e9ba6a */ DEFINE_GUID( OVS_TUNNEL_FILTER_KEY, @@ -79,7 +107,7 @@ DEFINE_GUID( */ PDEVICE_OBJECT gDeviceObject; -HANDLE gEngineHandle; +HANDLE gEngineHandle = NULL; UINT32 gCalloutIdV4; @@ -187,6 +215,137 @@ OvsTunnelRemoveFilter(const GUID *filterKey, return status; } +VOID +OvsTunnelAddSystemProvider(VOID) +{ + NTSTATUS status = STATUS_SUCCESS; + BOOLEAN inTransaction = FALSE; + FWPM_PROVIDER0 provider; + FWPM_SESSION session = { 0 }; + + do { + /* The session name isn't required but may be useful for diagnostics. */ + session.displayData.name = OVS_TUNNEL_SESSION_NAME; + /* + * Set an infinite wait timeout, so we don't have to handle FWP_E_TIMEOUT + * errors while waiting to acquire the transaction lock. + */ + session.txnWaitTimeoutInMSec = INFINITE; + session.flags = FWPM_SESSION_FLAG_DYNAMIC; + + /* The authentication service should always be RPC_C_AUTHN_DEFAULT. */ + status = FwpmEngineOpen(NULL, + RPC_C_AUTHN_DEFAULT, + NULL, + &session, + &gEngineHandle); + + if (!NT_SUCCESS(status)) { + break; + } + + status = FwpmTransactionBegin(gEngineHandle, 0); + if (!NT_SUCCESS(status)) { + break; + } + inTransaction = TRUE; + + memset(&provider, 0, sizeof(provider)); + provider.providerKey = OVS_TUNNEL_PROVIDER_KEY; + provider.displayData.name = OVS_TUNNEL_PROVIDER_NAME; + provider.displayData.description = OVS_TUNNEL_PROVIDER_DESC; + /* + * Since we always want the provider to be present, it's easiest to add + * it as persistent objects during install. Alternatively, we could add + * non-persistent objects every time our service starts. + */ + provider.flags = FWPM_PROVIDER_FLAG_PERSISTENT; + + status = FwpmProviderAdd(gEngineHandle, + &provider, + NULL); + if (!NT_SUCCESS(status)) { + break; + } + + status = FwpmTransactionCommit(gEngineHandle); + if (!NT_SUCCESS(status)) { + break; + } + + inTransaction = FALSE; + } while (inTransaction); + + if (!NT_SUCCESS(status)) { + if (inTransaction){ + FwpmTransactionAbort(gEngineHandle); + } + if (gEngineHandle) { + FwpmEngineClose(gEngineHandle); + gEngineHandle = NULL; + } + } +} + +VOID +OvsTunnelRemoveSystemProvider(VOID) +{ + NTSTATUS status = STATUS_SUCCESS; + BOOLEAN inTransaction = FALSE; + + do { + /* The authentication service should always be RPC_C_AUTHN_DEFAULT. */ + if (NULL == gEngineHandle) { + FWPM_SESSION session = { 0 }; + + /* The session name isn't required but may be useful for diagnostics. */ + session.displayData.name = OVS_TUNNEL_SESSION_NAME; + /* + * Set an infinite wait timeout, so we don't have to handle FWP_E_TIMEOUT + * errors while waiting to acquire the transaction lock. + */ + session.txnWaitTimeoutInMSec = INFINITE; + session.flags = FWPM_SESSION_FLAG_DYNAMIC; + + status = FwpmEngineOpen(NULL, + RPC_C_AUTHN_DEFAULT, + NULL, + &session, + &gEngineHandle); + if (!NT_SUCCESS(status)) { + break; + } + } + + status = FwpmTransactionBegin(gEngineHandle, 0); + if (!NT_SUCCESS(status)) { + break; + } + inTransaction = TRUE; + + status = FwpmProviderDeleteByKey(gEngineHandle, + &OVS_TUNNEL_PROVIDER_KEY); + if (!NT_SUCCESS(status)) { + break; + } + + status = FwpmTransactionCommit(gEngineHandle); + if (!NT_SUCCESS(status)) { + break; + } + + inTransaction = FALSE; + } while (inTransaction); + + if (inTransaction){ + FwpmTransactionAbort(gEngineHandle); + } + if (gEngineHandle) { + FwpmEngineClose(gEngineHandle); + gEngineHandle = NULL; + } +} + /* * -------------------------------------------------------------------------- * This function registers callouts and filters that intercept UDP traffic at @@ -278,18 +437,27 @@ OvsTunnelRegisterCallouts(VOID *deviceObject) BOOLEAN engineOpened = FALSE; BOOLEAN inTransaction = FALSE; - FWPM_SESSION session = {0}; + if (NULL == gEngineHandle) { + FWPM_SESSION session = {0}; - session.flags = FWPM_SESSION_FLAG_DYNAMIC; + /* The session name isn't required but may be useful for diagnostics. */ + session.displayData.name = OVS_TUNNEL_SESSION_NAME; + /* + * Set an infinite wait timeout, so we don't have to handle FWP_E_TIMEOUT + * errors while waiting to acquire the transaction lock. + */ + session.txnWaitTimeoutInMSec = INFINITE; + session.flags = FWPM_SESSION_FLAG_DYNAMIC; - status = FwpmEngineOpen(NULL, - RPC_C_AUTHN_WINNT, - NULL, - &session, - &gEngineHandle); + status = FwpmEngineOpen(NULL, + RPC_C_AUTHN_WINNT, + NULL, + &session, + &gEngineHandle); - if (!NT_SUCCESS(status)) { - goto Exit; + if (!NT_SUCCESS(status)) { + goto Exit; + } } engineOpened = TRUE; @@ -307,13 +475,18 @@ OvsTunnelRegisterCallouts(VOID *deviceObject) L"Sub-Layer for use by Datagram-Data OVS callouts"; OvsTunnelSubLayer.flags = 0; OvsTunnelSubLayer.weight = FWP_EMPTY; /* auto-weight */ + /* + * Link all objects to the tunnel provider. When multiple providers are + * installed on a computer, this makes it easy to determine who added what. + */ + OvsTunnelSubLayer.providerKey = (GUID*) &OVS_TUNNEL_PROVIDER_KEY; status = FwpmSubLayerAdd(gEngineHandle, &OvsTunnelSubLayer, NULL); if (!NT_SUCCESS(status)) { goto Exit; } - // In order to use this callout a socket must be opened + /* In order to use this callout a socket must be opened. */ status = OvsTunnelRegisterDatagramDataCallouts(&FWPM_LAYER_DATAGRAM_DATA_V4, &OVS_TUNNEL_CALLOUT_V4, deviceObject, @@ -348,9 +521,8 @@ OvsTunnelUnregisterCallouts(VOID) { OvsTunnelRemoveFilter(&OVS_TUNNEL_FILTER_KEY, &OVS_TUNNEL_SUBLAYER); - FwpmEngineClose(gEngineHandle); - gEngineHandle = NULL; FwpsCalloutUnregisterById(gCalloutIdV4); + FwpmCalloutDeleteById(gEngineHandle, gCalloutIdV4); } VOID diff --git a/datapath-windows/ovsext/TunnelIntf.h b/datapath-windows/ovsext/TunnelIntf.h index c622720..0718a0a 100644 --- a/datapath-windows/ovsext/TunnelIntf.h +++ b/datapath-windows/ovsext/TunnelIntf.h @@ -22,4 +22,8 @@ NTSTATUS OvsTunnelFilterInitialize(PDRIVER_OBJECT driverObject); VOID OvsTunnelFilterUninitialize(PDRIVER_OBJECT driverObject); +VOID OvsTunnelAddSystemProvider(VOID); + +VOID OvsTunnelRemoveSystemProvider(VOID); + #endif /* __TUNNEL_INTF_H_ */ -- 1.9.0.msysgit.0 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev