aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorOdd Stranne <odd@mullvad.net>2019-05-03 16:50:42 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2019-05-03 16:52:41 +0200
commite370be2b6dc850471fc01b142c028bb7818eeb10 (patch)
tree9eb2a8125f81fa878f592965e9a7d215ea1778f3
parentui: add toolbar after adding it to the tabs (diff)
downloadwireguard-windows-e370be2b6dc850471fc01b142c028bb7818eeb10.tar.xz
wireguard-windows-e370be2b6dc850471fc01b142c028bb7818eeb10.zip
firewall: introduce incomplete untested prototype
This doesn't support NDP yet, and some major things are still left to be decided, but this is the beginning of something that can be debugged into shape. Signed-off-by: Odd Stranne <odd@mullvad.net> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com> Signed-off-by: Aleksandar Pesic <peske.nis@gmail.com>
-rw-r--r--service/firewall/blocker.go232
-rw-r--r--service/firewall/helpers.go198
-rw-r--r--service/firewall/mksyscall.go8
-rw-r--r--service/firewall/rules.go973
-rw-r--r--service/firewall/syscall_windows.go39
-rw-r--r--service/firewall/types_windows.go417
-rw-r--r--service/firewall/types_windows_386.go106
-rw-r--r--service/firewall/types_windows_amd64.go103
-rw-r--r--service/firewall/types_windows_test.go602
-rw-r--r--service/firewall/zsyscall_windows.go179
10 files changed, 2857 insertions, 0 deletions
diff --git a/service/firewall/blocker.go b/service/firewall/blocker.go
new file mode 100644
index 00000000..66162448
--- /dev/null
+++ b/service/firewall/blocker.go
@@ -0,0 +1,232 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
+ */
+
+package firewall
+
+import (
+ "errors"
+ "unsafe"
+
+ "golang.org/x/sys/windows"
+)
+
+type wfpObjectInstaller func(uintptr) error
+
+//
+// Fundamental WireGuard specific WFP objects.
+//
+type baseObjects struct {
+ provider windows.GUID
+ whitelist windows.GUID
+ blacklist windows.GUID
+}
+
+var wfpSession uintptr
+
+func createWfpSession() (uintptr, error) {
+ sessionDisplayData, err := createWtFwpmDisplayData0("WireGuard", "WireGuard dynamic session")
+ if err != nil {
+ return 0, err
+ }
+
+ session := wtFwpmSession0{
+ displayData: *sessionDisplayData,
+ flags: cFWPM_SESSION_FLAG_DYNAMIC,
+ txnWaitTimeoutInMSec: windows.INFINITE,
+ }
+
+ sessionHandle := uintptr(0)
+
+ err = fwpmEngineOpen0(nil, cRPC_C_AUTHN_WINNT, nil, &session, unsafe.Pointer(&sessionHandle))
+ if err != nil {
+ return 0, err
+ }
+
+ return sessionHandle, nil
+}
+
+func registerBaseObjects(session uintptr) (*baseObjects, error) {
+ // {48E29F38-7492-4436-8F92-29D78A8D29D3}
+ providerGuid := windows.GUID{
+ Data1: 0x48e29f38,
+ Data2: 0x7492,
+ Data3: 0x4436,
+ Data4: [8]byte{0x8f, 0x92, 0x29, 0xd7, 0x8a, 0x8d, 0x29, 0xd3},
+ }
+ // {FE3DB7F8-4658-4DE5-8DA9-CE5086A8266B}
+ whitelistGuid := windows.GUID{
+ Data1: 0xfe3db7f8,
+ Data2: 0x4658,
+ Data3: 0x4de5,
+ Data4: [8]byte{0x8d, 0xa9, 0xce, 0x50, 0x86, 0xa8, 0x26, 0x6b},
+ }
+ // {CE1DD58F-A7BF-46BD-B048-9C5518346CE9}
+ blacklistGuid := windows.GUID{
+ Data1: 0xce1dd58f,
+ Data2: 0xa7bf,
+ Data3: 0x46bd,
+ Data4: [8]byte{0xb0, 0x48, 0x9c, 0x55, 0x18, 0x34, 0x6c, 0xe9},
+ }
+
+ //
+ // Register provider.
+ //
+ {
+ displayData, err := createWtFwpmDisplayData0("WireGuard", "The WireGuard provider")
+ if err != nil {
+ return nil, err
+ }
+ provider := wtFwpmProvider0{
+ providerKey: providerGuid,
+ displayData: *displayData,
+ }
+ err = fwpmProviderAdd0(session, &provider, 0)
+ if err != nil {
+ //TODO: cleanup entire call chain of these if failure?
+ return nil, err
+ }
+ }
+
+ //
+ // Register whitelist sublayer.
+ //
+ {
+ displayData, err := createWtFwpmDisplayData0("WireGuard whitelist", "Permissive filters")
+ if err != nil {
+ return nil, err
+ }
+ sublayer := wtFwpmSublayer0{
+ subLayerKey: whitelistGuid,
+ displayData: *displayData,
+ providerKey: &providerGuid,
+ weight: ^uint16(0),
+ }
+ err = fwpmSubLayerAdd0(session, &sublayer, 0)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ //
+ // Register blacklist sublayer.
+ //
+ {
+ displayData, err := createWtFwpmDisplayData0("WireGuard blacklist", "Blocking filters")
+ if err != nil {
+ return nil, err
+ }
+ sublayer := wtFwpmSublayer0{
+ subLayerKey: blacklistGuid,
+ displayData: *displayData,
+ providerKey: &providerGuid,
+ weight: (^uint16(0)) - 1,
+ }
+ err = fwpmSubLayerAdd0(session, &sublayer, 0)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ return &baseObjects{
+ providerGuid,
+ whitelistGuid,
+ blacklistGuid,
+ }, nil
+}
+
+func EnableFirewall(luid uint64, restrictDNS bool, restrictAll bool) error {
+ if wfpSession != 0 {
+ return errors.New("The firewall has already been enabled")
+ }
+
+ session, err := createWfpSession()
+ if err != nil {
+ return err
+ }
+
+ objectInstaller := func(session uintptr) error {
+ baseObjects, err := registerBaseObjects(session)
+ if err != nil {
+ return err
+ }
+
+ err = permitTunInterface(session, baseObjects, luid)
+ if err != nil {
+ return err
+ }
+
+ err = permitWireGuardService(session, baseObjects)
+ if err != nil {
+ return err
+ }
+
+ err = permitLoopback(session, baseObjects)
+ if err != nil {
+ return err
+ }
+
+ /* We actually don't want to allow lan explicitly. This is controlled by the restrictAll rule.
+ * TODO: consider removing those functions or just rethinking about how this all works.
+
+ err = permitLanIpv4(session, baseObjects)
+ if err != nil {
+ return err
+ }
+
+ err = permitLanIpv6(session, baseObjects)
+ if err != nil {
+ return err
+ }
+
+ */
+
+ err = permitDhcpIpv4(session, baseObjects)
+ if err != nil {
+ return err
+ }
+
+ err = permitDhcpIpv6(session, baseObjects)
+ if err != nil {
+ return err
+ }
+
+ err = permitNdp(session, baseObjects)
+ if err != nil {
+ return err
+ }
+
+ if restrictDNS {
+ err = blockDnsUnmatched(session, baseObjects)
+ if err != nil {
+ return err
+ }
+ }
+
+ if restrictAll {
+ err = blockAllUnmatched(session, baseObjects)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+ }
+
+ err = runTransaction(session, objectInstaller)
+ if err != nil {
+ fwpmEngineClose0(session)
+ return err
+ }
+
+ wfpSession = session
+ return nil
+}
+
+func DisableFirewall() {
+ if wfpSession != 0 {
+ fwpmEngineClose0(wfpSession)
+ wfpSession = 0
+ }
+}
diff --git a/service/firewall/helpers.go b/service/firewall/helpers.go
new file mode 100644
index 00000000..642080cc
--- /dev/null
+++ b/service/firewall/helpers.go
@@ -0,0 +1,198 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
+ */
+
+package firewall
+
+import (
+ "fmt"
+ "unsafe"
+
+ "golang.org/x/sys/windows"
+)
+
+func (bb *wtFwpByteBlob) free() {
+ if bb != nil {
+ fwpmFreeMemory0(unsafe.Pointer(&bb))
+ }
+}
+
+func (m wtFwpMatchType) String() string {
+ switch m {
+ case cFWP_MATCH_EQUAL:
+ return "FWP_MATCH_EQUAL"
+ case cFWP_MATCH_GREATER:
+ return "FWP_MATCH_GREATER"
+ case cFWP_MATCH_LESS:
+ return "FWP_MATCH_LESS"
+ case cFWP_MATCH_GREATER_OR_EQUAL:
+ return "FWP_MATCH_GREATER_OR_EQUAL"
+ case cFWP_MATCH_LESS_OR_EQUAL:
+ return "FWP_MATCH_LESS_OR_EQUAL"
+ case cFWP_MATCH_RANGE:
+ return "FWP_MATCH_RANGE"
+ case cFWP_MATCH_FLAGS_ALL_SET:
+ return "FWP_MATCH_FLAGS_ALL_SET"
+ case cFWP_MATCH_FLAGS_ANY_SET:
+ return "FWP_MATCH_FLAGS_ANY_SET"
+ case cFWP_MATCH_FLAGS_NONE_SET:
+ return "FWP_MATCH_FLAGS_NONE_SET"
+ case cFWP_MATCH_EQUAL_CASE_INSENSITIVE:
+ return "FWP_MATCH_EQUAL_CASE_INSENSITIVE"
+ case cFWP_MATCH_NOT_EQUAL:
+ return "FWP_MATCH_NOT_EQUAL"
+ case cFWP_MATCH_PREFIX:
+ return "FWP_MATCH_PREFIX"
+ case cFWP_MATCH_NOT_PREFIX:
+ return "FWP_MATCH_NOT_PREFIX"
+ case cFWP_MATCH_TYPE_MAX:
+ return "FWP_MATCH_TYPE_MAX"
+ default:
+ return fmt.Sprintf("FwpMatchType_UNKNOWN(%d)", m)
+ }
+}
+
+func (ff wtFwpmFilterFlags) String() string {
+ switch ff {
+ case cFWPM_FILTER_FLAG_NONE:
+ return "FWPM_FILTER_FLAG_NONE"
+ case cFWPM_FILTER_FLAG_PERSISTENT:
+ return "FWPM_FILTER_FLAG_PERSISTENT"
+ case cFWPM_FILTER_FLAG_BOOTTIME:
+ return "FWPM_FILTER_FLAG_BOOTTIME"
+ case cFWPM_FILTER_FLAG_HAS_PROVIDER_CONTEXT:
+ return "FWPM_FILTER_FLAG_HAS_PROVIDER_CONTEXT"
+ case cFWPM_FILTER_FLAG_CLEAR_ACTION_RIGHT:
+ return "FWPM_FILTER_FLAG_CLEAR_ACTION_RIGHT"
+ case cFWPM_FILTER_FLAG_PERMIT_IF_CALLOUT_UNREGISTERED:
+ return "FWPM_FILTER_FLAG_PERMIT_IF_CALLOUT_UNREGISTERED"
+ case cFWPM_FILTER_FLAG_DISABLED:
+ return "FWPM_FILTER_FLAG_DISABLED"
+ case cFWPM_FILTER_FLAG_INDEXED:
+ return "FWPM_FILTER_FLAG_INDEXED"
+ case cFWPM_FILTER_FLAG_HAS_SECURITY_REALM_PROVIDER_CONTEXT:
+ return "FWPM_FILTER_FLAG_HAS_SECURITY_REALM_PROVIDER_CONTEXT"
+ case cFWPM_FILTER_FLAG_SYSTEMOS_ONLY:
+ return "FWPM_FILTER_FLAG_SYSTEMOS_ONLY"
+ case cFWPM_FILTER_FLAG_GAMEOS_ONLY:
+ return "FWPM_FILTER_FLAG_GAMEOS_ONLY"
+ case cFWPM_FILTER_FLAG_SILENT_MODE:
+ return "FWPM_FILTER_FLAG_SILENT_MODE"
+ case cFWPM_FILTER_FLAG_IPSEC_NO_ACQUIRE_INITIATE:
+ return "FWPM_FILTER_FLAG_IPSEC_NO_ACQUIRE_INITIATE"
+ default:
+ return fmt.Sprintf("FwpmFilterFlags_UNKNOWN(%d)", ff)
+ }
+}
+
+func (dt wtFwpDataType) String() string {
+ switch dt {
+ case cFWP_EMPTY:
+ return "FWP_EMPTY"
+ case cFWP_UINT8:
+ return "FWP_UINT8"
+ case cFWP_UINT16:
+ return "FWP_UINT16"
+ case cFWP_UINT32:
+ return "FWP_UINT32"
+ case cFWP_UINT64:
+ return "FWP_UINT64"
+ case cFWP_INT8:
+ return "FWP_INT8"
+ case cFWP_INT16:
+ return "FWP_INT16"
+ case cFWP_INT32:
+ return "FWP_INT32"
+ case cFWP_INT64:
+ return "FWP_INT64"
+ case cFWP_FLOAT:
+ return "FWP_FLOAT"
+ case cFWP_DOUBLE:
+ return "FWP_DOUBLE"
+ case cFWP_BYTE_ARRAY16_TYPE:
+ return "FWP_BYTE_ARRAY16_TYPE"
+ case cFWP_BYTE_BLOB_TYPE:
+ return "FWP_BYTE_BLOB_TYPE"
+ case cFWP_SID:
+ return "FWP_SID"
+ case cFWP_SECURITY_DESCRIPTOR_TYPE:
+ return "FWP_SECURITY_DESCRIPTOR_TYPE"
+ case cFWP_TOKEN_INFORMATION_TYPE:
+ return "FWP_TOKEN_INFORMATION_TYPE"
+ case cFWP_TOKEN_ACCESS_INFORMATION_TYPE:
+ return "FWP_TOKEN_ACCESS_INFORMATION_TYPE"
+ case cFWP_UNICODE_STRING_TYPE:
+ return "FWP_UNICODE_STRING_TYPE"
+ case cFWP_BYTE_ARRAY6_TYPE:
+ return "FWP_BYTE_ARRAY6_TYPE"
+ case cFWP_BITMAP_INDEX_TYPE:
+ return "FWP_BITMAP_INDEX_TYPE"
+ case cFWP_BITMAP_ARRAY64_TYPE:
+ return "FWP_BITMAP_ARRAY64_TYPE"
+ case cFWP_SINGLE_DATA_TYPE_MAX:
+ return "FWP_SINGLE_DATA_TYPE_MAX"
+ case cFWP_V4_ADDR_MASK:
+ return "FWP_V4_ADDR_MASK"
+ case cFWP_V6_ADDR_MASK:
+ return "FWP_V6_ADDR_MASK"
+ case cFWP_RANGE_TYPE:
+ return "FWP_RANGE_TYPE"
+ case cFWP_DATA_TYPE_MAX:
+ return "FWP_DATA_TYPE_MAX"
+ default:
+ return fmt.Sprintf("FwpDataType_UNKNOWN(%d)", dt)
+ }
+}
+
+func runTransaction(session uintptr, operation wfpObjectInstaller) error {
+ err := fwpmTransactionBegin0(session, 0)
+ if err != nil {
+ return err
+ }
+
+ err = operation(session)
+ if err != nil {
+ fwpmTransactionAbort0(session)
+ return err
+ }
+
+ err = fwpmTransactionCommit0(session)
+ if err != nil {
+ fwpmTransactionAbort0(session)
+ return err
+ }
+
+ return nil
+}
+
+func createWtFwpmDisplayData0(name, description string) (*wtFwpmDisplayData0, error) {
+ namePtr, err := windows.UTF16PtrFromString(name)
+ if err != nil {
+ return nil, err
+ }
+
+ descriptionPtr, err := windows.UTF16PtrFromString(description)
+ if err != nil {
+ return nil, err
+ }
+
+ return &wtFwpmDisplayData0{
+ name: namePtr,
+ description: descriptionPtr,
+ }, nil
+}
+
+func filterWeightMax() wtFwpValue0 {
+ return wtFwpValue0{
+ _type: cFWP_UINT8,
+ value: 15,
+ }
+}
+
+func filterWeightMin() wtFwpValue0 {
+ return wtFwpValue0{
+ _type: cFWP_UINT8,
+ value: 0,
+ }
+}
diff --git a/service/firewall/mksyscall.go b/service/firewall/mksyscall.go
new file mode 100644
index 00000000..5e4bcaa0
--- /dev/null
+++ b/service/firewall/mksyscall.go
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
+ */
+
+package firewall
+
+//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go syscall_windows.go
diff --git a/service/firewall/rules.go b/service/firewall/rules.go
new file mode 100644
index 00000000..5a27d287
--- /dev/null
+++ b/service/firewall/rules.go
@@ -0,0 +1,973 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
+ */
+
+package firewall
+
+import (
+ "golang.org/x/sys/windows"
+ "os"
+ "unsafe"
+)
+
+func permitTunInterface(session uintptr, baseObjects *baseObjects, ifLuid uint64) error {
+ ifaceCondition := wtFwpmFilterCondition0{
+ fieldKey: cFWPM_CONDITION_IP_LOCAL_INTERFACE,
+ matchType: cFWP_MATCH_EQUAL,
+ conditionValue: wtFwpConditionValue0{
+ _type: cFWP_UINT64,
+ value: (uintptr)(unsafe.Pointer(&ifLuid)),
+ },
+ }
+
+ filter := wtFwpmFilter0{
+ providerKey: &baseObjects.provider,
+ subLayerKey: baseObjects.whitelist,
+ weight: filterWeightMax(),
+ numFilterConditions: 1,
+ filterCondition: (*wtFwpmFilterCondition0)(unsafe.Pointer(&ifaceCondition)),
+ action: wtFwpmAction0{
+ _type: cFWP_ACTION_PERMIT,
+ },
+ }
+
+ filterId := uint64(0)
+
+ //
+ // #1 Permit outbound IPv4 traffic.
+ //
+ {
+ displayData, err := createWtFwpmDisplayData0("Permit outbound IPv4 traffic on TUN", "")
+ if err != nil {
+ return err
+ }
+
+ filter.displayData = *displayData
+ filter.layerKey = cFWPM_LAYER_ALE_AUTH_CONNECT_V4
+
+ err = fwpmFilterAdd0(session, &filter, 0, &filterId)
+ if err != nil {
+ return err
+ }
+ }
+
+ //
+ // #2 Permit inbound IPv4 traffic.
+ //
+ {
+ displayData, err := createWtFwpmDisplayData0("Permit inbound IPv4 traffic on TUN", "")
+ if err != nil {
+ return err
+ }
+
+ filter.displayData = *displayData
+ filter.layerKey = cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4
+
+ err = fwpmFilterAdd0(session, &filter, 0, &filterId)
+ if err != nil {
+ return err
+ }
+ }
+
+ //
+ // #3 Permit outbound IPv6 traffic.
+ //
+ {
+ displayData, err := createWtFwpmDisplayData0("Permit outbound IPv6 traffic on TUN", "")
+ if err != nil {
+ return err
+ }
+
+ filter.displayData = *displayData
+ filter.layerKey = cFWPM_LAYER_ALE_AUTH_CONNECT_V6
+
+ err = fwpmFilterAdd0(session, &filter, 0, &filterId)
+ if err != nil {
+ return err
+ }
+ }
+
+ //
+ // #4 Permit inbound IPv6 traffic.
+ //
+ {
+ displayData, err := createWtFwpmDisplayData0("Permit inbound IPv6 traffic on TUN", "")
+ if err != nil {
+ return err
+ }
+
+ filter.displayData = *displayData
+ filter.layerKey = cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6
+
+ err = fwpmFilterAdd0(session, &filter, 0, &filterId)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func getCurrentProcessSecurityDescriptor() (uintptr, error) {
+ procHandle, err := windows.GetCurrentProcess()
+ if err != nil {
+ panic(err)
+ }
+
+ sd := uintptr(0)
+ err = getSecurityInfo(procHandle, cSE_KERNEL_OBJECT, 0, nil, nil, nil, nil, &sd)
+ if err != nil {
+ return 0, err
+ }
+
+ return sd, nil
+}
+
+func getCurrentProcessAppId() (*wtFwpByteBlob, error) {
+ currentFile, err := os.Executable()
+ if err != nil {
+ return nil, err
+ }
+
+ curFilePtr, err := windows.UTF16PtrFromString(currentFile)
+ if err != nil {
+ return nil, err
+ }
+
+ var appId *wtFwpByteBlob
+ err = fwpmGetAppIdFromFileName0(curFilePtr, unsafe.Pointer(&appId))
+ if err != nil {
+ return nil, err
+ }
+ return appId, nil
+}
+
+func permitWireGuardService(session uintptr, baseObjects *baseObjects) error {
+ var conditions [2]wtFwpmFilterCondition0
+
+ //
+ // First condition is the exe path of the current process.
+ //
+ appId, err := getCurrentProcessAppId()
+ if err != nil {
+ return err
+ }
+ defer appId.free()
+
+ conditions[0] = wtFwpmFilterCondition0{
+ fieldKey: cFWPM_CONDITION_ALE_APP_ID,
+ matchType: cFWP_MATCH_EQUAL,
+ conditionValue: wtFwpConditionValue0{
+ _type: cFWP_BYTE_BLOB_TYPE,
+ value: uintptr(unsafe.Pointer(appId)),
+ },
+ }
+
+ //
+ // Second condition is the SECURITY_DESCRIPTOR of the current process.
+ // This prevents low privileged applications hosted in the same exe from matching this filter.
+ //
+ sd, err := getCurrentProcessSecurityDescriptor()
+ if err != nil {
+ return err
+ }
+ defer windows.LocalFree(windows.Handle(sd))
+
+ conditions[1] = wtFwpmFilterCondition0{
+ fieldKey: cFWPM_CONDITION_ALE_USER_ID,
+ matchType: cFWP_MATCH_EQUAL,
+ conditionValue: wtFwpConditionValue0{
+ _type: cFWP_SECURITY_DESCRIPTOR_TYPE,
+ value: sd,
+ },
+ }
+
+ //
+ // Assemble the filter.
+ //
+ filter := wtFwpmFilter0{
+ providerKey: &baseObjects.provider,
+ subLayerKey: baseObjects.whitelist,
+ weight: filterWeightMax(),
+ numFilterConditions: uint32(len(conditions)),
+ filterCondition: (*wtFwpmFilterCondition0)(unsafe.Pointer(&conditions)),
+ action: wtFwpmAction0{
+ _type: cFWP_ACTION_PERMIT,
+ },
+ }
+
+ filterId := uint64(0)
+
+ //
+ // #1 Permit outbound IPv4 traffic.
+ //
+ {
+ displayData, err := createWtFwpmDisplayData0("Permit unrestricted outbound traffic for WireGuard service (IPv4)", "")
+ if err != nil {
+ return err
+ }
+
+ filter.displayData = *displayData
+ filter.layerKey = cFWPM_LAYER_ALE_AUTH_CONNECT_V4
+
+ err = fwpmFilterAdd0(session, &filter, 0, &filterId)
+ if err != nil {
+ return err
+ }
+ }
+
+ //
+ // #2 Permit inbound IPv4 traffic.
+ //
+ {
+ displayData, err := createWtFwpmDisplayData0("Permit unrestricted inbound traffic for WireGuard service (IPv4)", "")
+ if err != nil {
+ return err
+ }
+
+ filter.displayData = *displayData
+ filter.layerKey = cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4
+
+ err = fwpmFilterAdd0(session, &filter, 0, &filterId)
+ if err != nil {
+ return err
+ }
+ }
+
+ //
+ // #3 Permit outbound IPv6 traffic.
+ //
+ {
+ displayData, err := createWtFwpmDisplayData0("Permit unrestricted outbound traffic for WireGuard service (IPv6)", "")
+ if err != nil {
+ return err
+ }
+
+ filter.displayData = *displayData
+ filter.layerKey = cFWPM_LAYER_ALE_AUTH_CONNECT_V6
+
+ err = fwpmFilterAdd0(session, &filter, 0, &filterId)
+ if err != nil {
+ return err
+ }
+ }
+
+ //
+ // #4 Permit inbound IPv6 traffic.
+ //
+ {
+ displayData, err := createWtFwpmDisplayData0("Permit unrestricted inbound traffic for WireGuard service (IPv6)", "")
+ if err != nil {
+ return err
+ }
+
+ filter.displayData = *displayData
+ filter.layerKey = cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6
+
+ err = fwpmFilterAdd0(session, &filter, 0, &filterId)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+//
+// Permit all private nets and any combination of sender/receiver.
+//
+func permitLanIpv4(session uintptr, baseObjects *baseObjects) error {
+ privateNetworks := [4]wtFwpV4AddrAndMask{
+ {0x0a000000, 0xff000000},
+ {0xac100000, 0xfff00000},
+ {0xc0a80000, 0xffff0000},
+ {0xa9fe0000, 0xffff0000},
+ }
+
+ var conditions [8]wtFwpmFilterCondition0
+
+ //
+ // Repeating a condition type is evaluated as logical OR.
+ //
+
+ for idx, addr := range privateNetworks {
+ conditions[idx].fieldKey = cFWPM_CONDITION_IP_LOCAL_ADDRESS
+ conditions[idx].matchType = cFWP_MATCH_EQUAL
+ conditions[idx].conditionValue._type = cFWP_V4_ADDR_MASK
+ conditions[idx].conditionValue.value = uintptr(unsafe.Pointer(&addr))
+
+ conditions[4+idx].fieldKey = cFWPM_CONDITION_IP_REMOTE_ADDRESS
+ conditions[4+idx].matchType = cFWP_MATCH_EQUAL
+ conditions[4+idx].conditionValue._type = cFWP_V4_ADDR_MASK
+ conditions[4+idx].conditionValue.value = uintptr(unsafe.Pointer(&addr))
+ }
+
+ //
+ // Assemble the filter.
+ //
+ filter := wtFwpmFilter0{
+ providerKey: &baseObjects.provider,
+ subLayerKey: baseObjects.whitelist,
+ weight: filterWeightMax(),
+ numFilterConditions: uint32(len(conditions)),
+ filterCondition: (*wtFwpmFilterCondition0)(unsafe.Pointer(&conditions)),
+ action: wtFwpmAction0{
+ _type: cFWP_ACTION_PERMIT,
+ },
+ }
+
+ filterId := uint64(0)
+
+ //
+ // #1 Permit outbound LAN traffic.
+ //
+ {
+ displayData, err := createWtFwpmDisplayData0("Permit outbound LAN traffic (IPv4)", "")
+ if err != nil {
+ return err
+ }
+
+ filter.displayData = *displayData
+ filter.layerKey = cFWPM_LAYER_ALE_AUTH_CONNECT_V4
+
+ err = fwpmFilterAdd0(session, &filter, 0, &filterId)
+ if err != nil {
+ return err
+ }
+ }
+
+ //
+ // #2 Permit inbound LAN traffic.
+ //
+ {
+ displayData, err := createWtFwpmDisplayData0("Permit inbound LAN traffic (IPv4)", "")
+ if err != nil {
+ return err
+ }
+
+ filter.displayData = *displayData
+ filter.layerKey = cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4
+
+ err = fwpmFilterAdd0(session, &filter, 0, &filterId)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func permitLanIpv6(session uintptr, baseObjects *baseObjects) error {
+ privateNetwork := wtFwpV6AddrAndMask{[16]uint8{0xfe, 0x80}, 10}
+
+ var conditions [2]wtFwpmFilterCondition0
+
+ conditions[0].fieldKey = cFWPM_CONDITION_IP_LOCAL_ADDRESS
+ conditions[0].matchType = cFWP_MATCH_EQUAL
+ conditions[0].conditionValue._type = cFWP_V6_ADDR_MASK
+ conditions[0].conditionValue.value = uintptr(unsafe.Pointer(&privateNetwork))
+
+ conditions[1].fieldKey = cFWPM_CONDITION_IP_REMOTE_ADDRESS
+ conditions[1].matchType = cFWP_MATCH_EQUAL
+ conditions[1].conditionValue._type = cFWP_V6_ADDR_MASK
+ conditions[1].conditionValue.value = uintptr(unsafe.Pointer(&privateNetwork))
+
+ filter := wtFwpmFilter0{
+ providerKey: &baseObjects.provider,
+ subLayerKey: baseObjects.whitelist,
+ weight: filterWeightMax(),
+ numFilterConditions: uint32(len(conditions)),
+ filterCondition: (*wtFwpmFilterCondition0)(unsafe.Pointer(&conditions)),
+ action: wtFwpmAction0{
+ _type: cFWP_ACTION_PERMIT,
+ },
+ }
+
+ filterId := uint64(0)
+
+ //
+ // #1 Permit outbound LAN traffic.
+ //
+ {
+ displayData, err := createWtFwpmDisplayData0("Permit outbound LAN traffic (IPv6)", "")
+ if err != nil {
+ return err
+ }
+
+ filter.displayData = *displayData
+ filter.layerKey = cFWPM_LAYER_ALE_AUTH_CONNECT_V6
+
+ err = fwpmFilterAdd0(session, &filter, 0, &filterId)
+ if err != nil {
+ return err
+ }
+ }
+
+ //
+ // #2 Permit inbound LAN traffic.
+ //
+ {
+ displayData, err := createWtFwpmDisplayData0("Permit inbound LAN traffic (IPv6)", "")
+ if err != nil {
+ return err
+ }
+
+ filter.displayData = *displayData
+ filter.layerKey = cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6
+
+ err = fwpmFilterAdd0(session, &filter, 0, &filterId)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func permitLoopback(session uintptr, baseObjects *baseObjects) error {
+ condition := wtFwpmFilterCondition0{
+ fieldKey: cFWPM_CONDITION_INTERFACE_TYPE,
+ matchType: cFWP_MATCH_EQUAL,
+ conditionValue: wtFwpConditionValue0{
+ _type: cFWP_UINT32,
+ value: uintptr(cIF_TYPE_SOFTWARE_LOOPBACK),
+ },
+ }
+
+ filter := wtFwpmFilter0{
+ providerKey: &baseObjects.provider,
+ subLayerKey: baseObjects.whitelist,
+ weight: filterWeightMax(),
+ numFilterConditions: 1,
+ filterCondition: (*wtFwpmFilterCondition0)(unsafe.Pointer(&condition)),
+ action: wtFwpmAction0{
+ _type: cFWP_ACTION_PERMIT,
+ },
+ }
+
+ filterId := uint64(0)
+
+ //
+ // #1 Permit outbound IPv4 on loopback.
+ //
+ {
+ displayData, err := createWtFwpmDisplayData0("Permit outbound on loopback (IPv4)", "")
+ if err != nil {
+ return err
+ }
+
+ filter.displayData = *displayData
+ filter.layerKey = cFWPM_LAYER_ALE_AUTH_CONNECT_V4
+
+ err = fwpmFilterAdd0(session, &filter, 0, &filterId)
+ if err != nil {
+ return err
+ }
+ }
+
+ //
+ // #2 Permit inbound IPv4 on loopback.
+ //
+ {
+ displayData, err := createWtFwpmDisplayData0("Permit inbound on loopback (IPv4)", "")
+ if err != nil {
+ return err
+ }
+
+ filter.displayData = *displayData
+ filter.layerKey = cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4
+
+ err = fwpmFilterAdd0(session, &filter, 0, &filterId)
+ if err != nil {
+ return err
+ }
+ }
+
+ //
+ // #3 Permit outbound IPv6 on loopback.
+ //
+ {
+ displayData, err := createWtFwpmDisplayData0("Permit outbound on loopback (IPv6)", "")
+ if err != nil {
+ return err
+ }
+
+ filter.displayData = *displayData
+ filter.layerKey = cFWPM_LAYER_ALE_AUTH_CONNECT_V6
+
+ err = fwpmFilterAdd0(session, &filter, 0, &filterId)
+ if err != nil {
+ return err
+ }
+ }
+
+ //
+ // #4 Permit inbound IPv6 on loopback.
+ //
+ {
+ displayData, err := createWtFwpmDisplayData0("Permit inbound on loopback (IPv6)", "")
+ if err != nil {
+ return err
+ }
+
+ filter.displayData = *displayData
+ filter.layerKey = cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6
+
+ err = fwpmFilterAdd0(session, &filter, 0, &filterId)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func permitDhcpIpv4(session uintptr, baseObjects *baseObjects) error {
+ //
+ // #1 Outbound DHCP request on IPv4.
+ //
+ {
+ var conditions [4]wtFwpmFilterCondition0
+
+ conditions[0].fieldKey = cFWPM_CONDITION_IP_PROTOCOL
+ conditions[0].matchType = cFWP_MATCH_EQUAL
+ conditions[0].conditionValue._type = cFWP_UINT8
+ conditions[0].conditionValue.value = uintptr(cIPPROTO_UDP)
+
+ conditions[1].fieldKey = cFWPM_CONDITION_IP_LOCAL_PORT
+ conditions[1].matchType = cFWP_MATCH_EQUAL
+ conditions[1].conditionValue._type = cFWP_UINT16
+ conditions[1].conditionValue.value = uintptr(68)
+
+ conditions[2].fieldKey = cFWPM_CONDITION_IP_REMOTE_PORT
+ conditions[2].matchType = cFWP_MATCH_EQUAL
+ conditions[2].conditionValue._type = cFWP_UINT16
+ conditions[2].conditionValue.value = uintptr(67)
+
+ conditions[3].fieldKey = cFWPM_CONDITION_IP_REMOTE_ADDRESS
+ conditions[3].matchType = cFWP_MATCH_EQUAL
+ conditions[3].conditionValue._type = cFWP_UINT32
+ conditions[3].conditionValue.value = uintptr(0xffffffff)
+
+ displayData, err := createWtFwpmDisplayData0("Permit outbound DHCP request (IPv4)", "")
+ if err != nil {
+ return err
+ }
+
+ filter := wtFwpmFilter0{
+ displayData: *displayData,
+ providerKey: &baseObjects.provider,
+ layerKey: cFWPM_LAYER_ALE_AUTH_CONNECT_V4,
+ subLayerKey: baseObjects.whitelist,
+ weight: filterWeightMax(),
+ numFilterConditions: uint32(len(conditions)),
+ filterCondition: (*wtFwpmFilterCondition0)(unsafe.Pointer(&conditions)),
+ action: wtFwpmAction0{
+ _type: cFWP_ACTION_PERMIT,
+ },
+ }
+
+ filterId := uint64(0)
+
+ err = fwpmFilterAdd0(session, &filter, 0, &filterId)
+ if err != nil {
+ return err
+ }
+ }
+
+ //
+ // #2 Inbound DHCP response on IPv4.
+ //
+ {
+ var conditions [3]wtFwpmFilterCondition0
+
+ conditions[0].fieldKey = cFWPM_CONDITION_IP_PROTOCOL
+ conditions[0].matchType = cFWP_MATCH_EQUAL
+ conditions[0].conditionValue._type = cFWP_UINT8
+ conditions[0].conditionValue.value = uintptr(cIPPROTO_UDP)
+
+ conditions[1].fieldKey = cFWPM_CONDITION_IP_LOCAL_PORT
+ conditions[1].matchType = cFWP_MATCH_EQUAL
+ conditions[1].conditionValue._type = cFWP_UINT16
+ conditions[1].conditionValue.value = uintptr(68)
+
+ conditions[2].fieldKey = cFWPM_CONDITION_IP_REMOTE_PORT
+ conditions[2].matchType = cFWP_MATCH_EQUAL
+ conditions[2].conditionValue._type = cFWP_UINT16
+ conditions[2].conditionValue.value = uintptr(67)
+
+ displayData, err := createWtFwpmDisplayData0("Permit inbound DHCP response (IPv4)", "")
+ if err != nil {
+ return err
+ }
+
+ filter := wtFwpmFilter0{
+ displayData: *displayData,
+ providerKey: &baseObjects.provider,
+ layerKey: cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4,
+ subLayerKey: baseObjects.whitelist,
+ weight: filterWeightMax(),
+ numFilterConditions: uint32(len(conditions)),
+ filterCondition: (*wtFwpmFilterCondition0)(unsafe.Pointer(&conditions)),
+ action: wtFwpmAction0{
+ _type: cFWP_ACTION_PERMIT,
+ },
+ }
+
+ filterId := uint64(0)
+
+ err = fwpmFilterAdd0(session, &filter, 0, &filterId)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func permitDhcpIpv6(session uintptr, baseObjects *baseObjects) error {
+ privateNetwork := wtFwpV6AddrAndMask{[16]uint8{0xfe, 0x80}, 10}
+
+ //
+ // #1 Outbound DHCP request on IPv6.
+ //
+ {
+ linkLocalDhcpMulticast := wtFwpByteArray16{[16]uint8{0xFF, 0x02, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x2}}
+ siteLocalDhcpMulticast := wtFwpByteArray16{[16]uint8{0xFF, 0x05, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x3}}
+
+ var conditions [6]wtFwpmFilterCondition0
+
+ conditions[0].fieldKey = cFWPM_CONDITION_IP_PROTOCOL
+ conditions[0].matchType = cFWP_MATCH_EQUAL
+ conditions[0].conditionValue._type = cFWP_UINT8
+ conditions[0].conditionValue.value = uintptr(cIPPROTO_UDP)
+
+ conditions[1].fieldKey = cFWPM_CONDITION_IP_REMOTE_ADDRESS
+ conditions[1].matchType = cFWP_MATCH_EQUAL
+ conditions[1].conditionValue._type = cFWP_BYTE_ARRAY16_TYPE
+ conditions[1].conditionValue.value = uintptr(unsafe.Pointer(&linkLocalDhcpMulticast))
+
+ // Repeat the condition type for logical OR.
+ conditions[2].fieldKey = cFWPM_CONDITION_IP_REMOTE_ADDRESS
+ conditions[2].matchType = cFWP_MATCH_EQUAL
+ conditions[2].conditionValue._type = cFWP_BYTE_ARRAY16_TYPE
+ conditions[2].conditionValue.value = uintptr(unsafe.Pointer(&siteLocalDhcpMulticast))
+
+ conditions[3].fieldKey = cFWPM_CONDITION_IP_REMOTE_PORT
+ conditions[3].matchType = cFWP_MATCH_EQUAL
+ conditions[3].conditionValue._type = cFWP_UINT16
+ conditions[3].conditionValue.value = uintptr(547)
+
+ conditions[4].fieldKey = cFWPM_CONDITION_IP_LOCAL_ADDRESS
+ conditions[4].matchType = cFWP_MATCH_EQUAL
+ conditions[4].conditionValue._type = cFWP_V6_ADDR_MASK
+ conditions[4].conditionValue.value = uintptr(unsafe.Pointer(&privateNetwork))
+
+ conditions[5].fieldKey = cFWPM_CONDITION_IP_LOCAL_PORT
+ conditions[5].matchType = cFWP_MATCH_EQUAL
+ conditions[5].conditionValue._type = cFWP_UINT16
+ conditions[5].conditionValue.value = uintptr(546)
+
+ displayData, err := createWtFwpmDisplayData0("Permit outbound DHCP request (IPv6)", "")
+ if err != nil {
+ return err
+ }
+
+ filter := wtFwpmFilter0{
+ displayData: *displayData,
+ providerKey: &baseObjects.provider,
+ layerKey: cFWPM_LAYER_ALE_AUTH_CONNECT_V6,
+ subLayerKey: baseObjects.whitelist,
+ weight: filterWeightMax(),
+ numFilterConditions: uint32(len(conditions)),
+ filterCondition: (*wtFwpmFilterCondition0)(unsafe.Pointer(&conditions)),
+ action: wtFwpmAction0{
+ _type: cFWP_ACTION_PERMIT,
+ },
+ }
+
+ filterId := uint64(0)
+
+ err = fwpmFilterAdd0(session, &filter, 0, &filterId)
+ if err != nil {
+ return err
+ }
+ }
+
+ //
+ // #2 Inbound DHCP response on IPv6.
+ //
+ {
+ var conditions [5]wtFwpmFilterCondition0
+
+ conditions[0].fieldKey = cFWPM_CONDITION_IP_PROTOCOL
+ conditions[0].matchType = cFWP_MATCH_EQUAL
+ conditions[0].conditionValue._type = cFWP_UINT8
+ conditions[0].conditionValue.value = uintptr(cIPPROTO_UDP)
+
+ conditions[1].fieldKey = cFWPM_CONDITION_IP_REMOTE_ADDRESS
+ conditions[1].matchType = cFWP_MATCH_EQUAL
+ conditions[1].conditionValue._type = cFWP_V6_ADDR_MASK
+ conditions[1].conditionValue.value = uintptr(unsafe.Pointer(&privateNetwork))
+
+ conditions[2].fieldKey = cFWPM_CONDITION_IP_REMOTE_PORT
+ conditions[2].matchType = cFWP_MATCH_EQUAL
+ conditions[2].conditionValue._type = cFWP_UINT16
+ conditions[2].conditionValue.value = uintptr(547)
+
+ conditions[3].fieldKey = cFWPM_CONDITION_IP_LOCAL_ADDRESS
+ conditions[3].matchType = cFWP_MATCH_EQUAL
+ conditions[3].conditionValue._type = cFWP_V6_ADDR_MASK
+ conditions[3].conditionValue.value = uintptr(unsafe.Pointer(&privateNetwork))
+
+ conditions[4].fieldKey = cFWPM_CONDITION_IP_LOCAL_PORT
+ conditions[4].matchType = cFWP_MATCH_EQUAL
+ conditions[4].conditionValue._type = cFWP_UINT16
+ conditions[4].conditionValue.value = uintptr(546)
+
+ displayData, err := createWtFwpmDisplayData0("Permit inbound DHCP response (IPv6)", "")
+ if err != nil {
+ return err
+ }
+
+ filter := wtFwpmFilter0{
+ displayData: *displayData,
+ providerKey: &baseObjects.provider,
+ layerKey: cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6,
+ subLayerKey: baseObjects.whitelist,
+ weight: filterWeightMax(),
+ numFilterConditions: uint32(len(conditions)),
+ filterCondition: (*wtFwpmFilterCondition0)(unsafe.Pointer(&conditions)),
+ action: wtFwpmAction0{
+ _type: cFWP_ACTION_PERMIT,
+ },
+ }
+
+ filterId := uint64(0)
+
+ err = fwpmFilterAdd0(session, &filter, 0, &filterId)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func permitNdp(session uintptr, baseObjects *baseObjects) error {
+
+ /* TODO: Objective is:
+ * icmpv6 133: must be outgoing, dst must be FF02::2/128, hop limit must be 255
+ * icmpv6 134: must be incoming, src must be FE80::/10, hop limit must be 255
+ * icmpv6 135: either incoming or outgoing, hop limit must be 255
+ * icmpv6 136: either incoming or outgoing, hop limit must be 255
+ * icmpv6 137: must be incoming, src must be FE80::/10, hop limit must be 255
+ */
+
+ //
+ // #1 out: icmp icmp_type=133 dhost=linkLocal|siteLocal ttl=255
+ //
+ {
+ var conditions [5]wtFwpmFilterCondition0
+
+ conditions[0].fieldKey = cFWPM_CONDITION_IP_PROTOCOL
+ conditions[0].matchType = cFWP_MATCH_EQUAL
+ conditions[0].conditionValue._type = cFWP_UINT8
+ conditions[0].conditionValue.value = uintptr(cIPPROTO_ICMP)
+
+ conditions[1].fieldKey = cFWPM_CONDITION_ICMP_TYPE // TODO: This could be wrong, it might be _CODE
+ conditions[1].matchType = cFWP_MATCH_EQUAL
+ conditions[1].conditionValue._type = cFWP_UINT16
+ conditions[1].conditionValue.value = uintptr(133)
+ }
+
+ return nil
+}
+
+// Block all traffic except what is explicitly permitted by other rules.
+func blockAllUnmatched(session uintptr, baseObjects *baseObjects) error {
+ filter := wtFwpmFilter0{
+ providerKey: &baseObjects.provider,
+ subLayerKey: baseObjects.whitelist,
+ weight: filterWeightMin(),
+ action: wtFwpmAction0{
+ _type: cFWP_ACTION_BLOCK,
+ },
+ }
+
+ filterId := uint64(0)
+
+ //
+ // #1 Block outbound traffic on IPv4.
+ //
+ {
+ displayData, err := createWtFwpmDisplayData0("Block all outbound (IPv4)", "")
+ if err != nil {
+ return err
+ }
+
+ filter.displayData = *displayData
+ filter.layerKey = cFWPM_LAYER_ALE_AUTH_CONNECT_V4
+
+ err = fwpmFilterAdd0(session, &filter, 0, &filterId)
+ if err != nil {
+ return err
+ }
+ }
+
+ //
+ // #2 Block inbound traffic on IPv4.
+ //
+ {
+ displayData, err := createWtFwpmDisplayData0("Block all inbound (IPv4)", "")
+ if err != nil {
+ return err
+ }
+
+ filter.displayData = *displayData
+ filter.layerKey = cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4
+
+ err = fwpmFilterAdd0(session, &filter, 0, &filterId)
+ if err != nil {
+ return err
+ }
+ }
+
+ //
+ // #3 Block outbound traffic on IPv6.
+ //
+ {
+ displayData, err := createWtFwpmDisplayData0("Block all outbound (IPv6)", "")
+ if err != nil {
+ return err
+ }
+
+ filter.displayData = *displayData
+ filter.layerKey = cFWPM_LAYER_ALE_AUTH_CONNECT_V6
+
+ err = fwpmFilterAdd0(session, &filter, 0, &filterId)
+ if err != nil {
+ return err
+ }
+ }
+
+ //
+ // #4 Block inbound traffic on IPv6.
+ //
+ {
+ displayData, err := createWtFwpmDisplayData0("Block all inbound (IPv6)", "")
+ if err != nil {
+ return err
+ }
+
+ filter.displayData = *displayData
+ filter.layerKey = cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6
+
+ err = fwpmFilterAdd0(session, &filter, 0, &filterId)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+// Block all DNS except what is matched by a permissive rule.
+func blockDnsUnmatched(session uintptr, baseObjects *baseObjects) error {
+ condition := wtFwpmFilterCondition0{
+ fieldKey: cFWPM_CONDITION_IP_REMOTE_PORT,
+ matchType: cFWP_MATCH_EQUAL,
+ conditionValue: wtFwpConditionValue0{
+ _type: cFWP_UINT16,
+ value: uintptr(53),
+ },
+ }
+
+ filter := wtFwpmFilter0{
+ providerKey: &baseObjects.provider,
+ subLayerKey: baseObjects.blacklist,
+ weight: filterWeightMin(),
+ numFilterConditions: 1,
+ filterCondition: (*wtFwpmFilterCondition0)(unsafe.Pointer(&condition)),
+ action: wtFwpmAction0{
+ _type: cFWP_ACTION_BLOCK,
+ },
+ }
+
+ filterId := uint64(0)
+
+ //
+ // #1 Block IPv4 outbound DNS.
+ //
+ {
+ displayData, err := createWtFwpmDisplayData0("Block DNS outbound (IPv4)", "")
+ if err != nil {
+ return err
+ }
+
+ filter.displayData = *displayData
+ filter.layerKey = cFWPM_LAYER_ALE_AUTH_CONNECT_V4
+
+ err = fwpmFilterAdd0(session, &filter, 0, &filterId)
+ if err != nil {
+ return err
+ }
+ }
+
+ //
+ // #2 Block IPv4 inbound DNS.
+ //
+ {
+ displayData, err := createWtFwpmDisplayData0("Block DNS inbound (IPv4)", "")
+ if err != nil {
+ return err
+ }
+
+ filter.displayData = *displayData
+ filter.layerKey = cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4
+
+ err = fwpmFilterAdd0(session, &filter, 0, &filterId)
+ if err != nil {
+ return err
+ }
+ }
+
+ //
+ // #3 Block IPv6 outbound DNS.
+ //
+ {
+ displayData, err := createWtFwpmDisplayData0("Block DNS outbound (IPv6)", "")
+ if err != nil {
+ return err
+ }
+
+ filter.displayData = *displayData
+ filter.layerKey = cFWPM_LAYER_ALE_AUTH_CONNECT_V6
+
+ err = fwpmFilterAdd0(session, &filter, 0, &filterId)
+ if err != nil {
+ return err
+ }
+ }
+
+ //
+ // #4 Block IPv6 inbound DNS.
+ //
+ {
+ displayData, err := createWtFwpmDisplayData0("Block DNS inbound (IPv6)", "")
+ if err != nil {
+ return err
+ }
+
+ filter.displayData = *displayData
+ filter.layerKey = cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6
+
+ err = fwpmFilterAdd0(session, &filter, 0, &filterId)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
diff --git a/service/firewall/syscall_windows.go b/service/firewall/syscall_windows.go
new file mode 100644
index 00000000..924c4b82
--- /dev/null
+++ b/service/firewall/syscall_windows.go
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
+ */
+
+package firewall
+
+// https://docs.microsoft.com/en-us/windows/desktop/api/fwpmu/nf-fwpmu-fwpmengineopen0
+//sys fwpmEngineOpen0(serverName *uint16, authnService wtRpcCAuthN, authIdentity *wtSecWinntAuthIdentityW, session *wtFwpmSession0, engineHandle unsafe.Pointer) (err error) [failretval!=0] = fwpuclnt.FwpmEngineOpen0
+
+// https://docs.microsoft.com/en-us/windows/desktop/api/fwpmu/nf-fwpmu-fwpmengineclose0
+//sys fwpmEngineClose0(engineHandle uintptr) (err error) [failretval!=0] = fwpuclnt.FwpmEngineClose0
+
+// https://docs.microsoft.com/en-us/windows/desktop/api/fwpmu/nf-fwpmu-fwpmsublayeradd0
+//sys fwpmSubLayerAdd0(engineHandle uintptr, subLayer *wtFwpmSublayer0, sd uintptr) (err error) [failretval!=0] = fwpuclnt.FwpmSubLayerAdd0
+
+// https://docs.microsoft.com/en-us/windows/desktop/api/fwpmu/nf-fwpmu-fwpmgetappidfromfilename0
+//sys fwpmGetAppIdFromFileName0(fileName *uint16, appId unsafe.Pointer) (err error) [failretval!=0] = fwpuclnt.FwpmGetAppIdFromFileName0
+
+// https://docs.microsoft.com/en-us/windows/desktop/api/fwpmu/nf-fwpmu-fwpmfreememory0
+//sys fwpmFreeMemory0(p unsafe.Pointer) = fwpuclnt.FwpmFreeMemory0
+
+// https://docs.microsoft.com/en-us/windows/desktop/api/fwpmu/nf-fwpmu-fwpmfilteradd0
+//sys fwpmFilterAdd0(engineHandle uintptr, filter *wtFwpmFilter0, sd uintptr, id *uint64) (err error) [failretval!=0] = fwpuclnt.FwpmFilterAdd0
+
+// https://docs.microsoft.com/en-us/windows/desktop/api/Fwpmu/nf-fwpmu-fwpmtransactionbegin0
+//sys fwpmTransactionBegin0(engineHandle uintptr, flags uint32) (err error) [failretval!=0] = fwpuclnt.FwpmTransactionBegin0
+
+// https://docs.microsoft.com/en-us/windows/desktop/api/fwpmu/nf-fwpmu-fwpmtransactioncommit0
+//sys fwpmTransactionCommit0(engineHandle uintptr) (err error) [failretval!=0] = fwpuclnt.FwpmTransactionCommit0
+
+// https://docs.microsoft.com/en-us/windows/desktop/api/fwpmu/nf-fwpmu-fwpmtransactionabort0
+//sys fwpmTransactionAbort0(engineHandle uintptr) (err error) [failretval!=0] = fwpuclnt.FwpmTransactionAbort0
+
+// https://docs.microsoft.com/en-us/windows/desktop/api/fwpmu/nf-fwpmu-fwpmprovideradd0
+//sys fwpmProviderAdd0(engineHandle uintptr, provider *wtFwpmProvider0, sd uintptr) (err error) [failretval!=0] = fwpuclnt.FwpmProviderAdd0
+
+// https://docs.microsoft.com/sv-se/windows/desktop/api/aclapi/nf-aclapi-getsecurityinfo
+//sys getSecurityInfo(handle windows.Handle, objectType wtObjectType, si uint32, sidOwner *windows.SID, sidGroup *windows.SID, dacl *uintptr, sacl *uintptr, securityDescriptor *uintptr) (err error) [failretval!=0] = advapi32.GetSecurityInfo
diff --git a/service/firewall/types_windows.go b/service/firewall/types_windows.go
new file mode 100644
index 00000000..1d28772d
--- /dev/null
+++ b/service/firewall/types_windows.go
@@ -0,0 +1,417 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
+ */
+
+package firewall
+
+import "golang.org/x/sys/windows"
+
+const (
+ anysizeArray = 1 // ANYSIZE_ARRAY defined in winnt.h
+
+ wtFwpBitmapArray64_Size = 8
+
+ wtFwpByteArray16_Size = 16
+
+ wtFwpByteArray6_Size = 6
+
+ wtFwpmAction0_Size = 20
+
+ wtFwpmAction0_filterType_Offset = 4
+
+ wtFwpV4AddrAndMask_Size = 8
+
+ wtFwpV4AddrAndMask_mask_Offset = 4
+
+ wtFwpV6AddrAndMask_Size = 17
+
+ wtFwpV6AddrAndMask_prefixLength_Offset = 16
+)
+
+type wtFwpActionFlag uint32
+
+const (
+ cFWP_ACTION_FLAG_TERMINATING wtFwpActionFlag = 0x00001000
+ cFWP_ACTION_FLAG_NON_TERMINATING wtFwpActionFlag = 0x00002000
+ cFWP_ACTION_FLAG_CALLOUT wtFwpActionFlag = 0x00004000
+)
+
+// FWP_ACTION_TYPE defined in fwptypes.h
+type wtFwpActionType uint32
+
+const (
+ cFWP_ACTION_BLOCK wtFwpActionType = wtFwpActionType(0x00000001 | cFWP_ACTION_FLAG_TERMINATING)
+ cFWP_ACTION_PERMIT wtFwpActionType = wtFwpActionType(0x00000002 | cFWP_ACTION_FLAG_TERMINATING)
+ cFWP_ACTION_CALLOUT_TERMINATING wtFwpActionType = wtFwpActionType(0x00000003 | cFWP_ACTION_FLAG_CALLOUT | cFWP_ACTION_FLAG_TERMINATING)
+ cFWP_ACTION_CALLOUT_INSPECTION wtFwpActionType = wtFwpActionType(0x00000004 | cFWP_ACTION_FLAG_CALLOUT | cFWP_ACTION_FLAG_NON_TERMINATING)
+ cFWP_ACTION_CALLOUT_UNKNOWN wtFwpActionType = wtFwpActionType(0x00000005 | cFWP_ACTION_FLAG_CALLOUT)
+ cFWP_ACTION_CONTINUE wtFwpActionType = wtFwpActionType(0x00000006 | cFWP_ACTION_FLAG_NON_TERMINATING)
+ //wtFWP_ACTION_NONE wtFwpActionType = 0x00000007
+ //wtFWP_ACTION_NONE_NO_MATCH wtFwpActionType = 0x00000008
+ //wtFWP_ACTION_BITMAP_INDEX_SET wtFwpActionType = 0x00000009
+)
+
+// FWP_BYTE_BLOB defined in fwptypes.h
+// (https://docs.microsoft.com/en-us/windows/desktop/api/fwptypes/ns-fwptypes-fwp_byte_blob_)
+type wtFwpByteBlob struct {
+ size uint32
+ data *uint8
+}
+
+// FWP_MATCH_TYPE defined in fwptypes.h
+// (https://docs.microsoft.com/en-us/windows/desktop/api/fwptypes/ne-fwptypes-fwp_match_type_)
+type wtFwpMatchType uint32
+
+const (
+ cFWP_MATCH_EQUAL wtFwpMatchType = 0
+ cFWP_MATCH_GREATER wtFwpMatchType = cFWP_MATCH_EQUAL + 1
+ cFWP_MATCH_LESS wtFwpMatchType = cFWP_MATCH_GREATER + 1
+ cFWP_MATCH_GREATER_OR_EQUAL wtFwpMatchType = cFWP_MATCH_LESS + 1
+ cFWP_MATCH_LESS_OR_EQUAL wtFwpMatchType = cFWP_MATCH_GREATER_OR_EQUAL + 1
+ cFWP_MATCH_RANGE wtFwpMatchType = cFWP_MATCH_LESS_OR_EQUAL + 1
+ cFWP_MATCH_FLAGS_ALL_SET wtFwpMatchType = cFWP_MATCH_RANGE + 1
+ cFWP_MATCH_FLAGS_ANY_SET wtFwpMatchType = cFWP_MATCH_FLAGS_ALL_SET + 1
+ cFWP_MATCH_FLAGS_NONE_SET wtFwpMatchType = cFWP_MATCH_FLAGS_ANY_SET + 1
+ cFWP_MATCH_EQUAL_CASE_INSENSITIVE wtFwpMatchType = cFWP_MATCH_FLAGS_NONE_SET + 1
+ cFWP_MATCH_NOT_EQUAL wtFwpMatchType = cFWP_MATCH_EQUAL_CASE_INSENSITIVE + 1
+ cFWP_MATCH_PREFIX wtFwpMatchType = cFWP_MATCH_NOT_EQUAL + 1
+ cFWP_MATCH_NOT_PREFIX wtFwpMatchType = cFWP_MATCH_PREFIX + 1
+ cFWP_MATCH_TYPE_MAX wtFwpMatchType = cFWP_MATCH_NOT_PREFIX + 1
+)
+
+// FWPM_ACTION0 defined in fwpmtypes.h
+// (https://docs.microsoft.com/en-us/windows/desktop/api/fwpmtypes/ns-fwpmtypes-fwpm_action0_)
+type wtFwpmAction0 struct {
+ _type wtFwpActionType
+ filterType windows.GUID // Windows type: GUID
+}
+
+// Defined in fwpmu.h. 4cd62a49-59c3-4969-b7f3-bda5d32890a4
+var cFWPM_CONDITION_IP_LOCAL_INTERFACE = windows.GUID{
+ Data1: 0x4cd62a49,
+ Data2: 0x59c3,
+ Data3: 0x4969,
+ Data4: [8]byte{0xb7, 0xf3, 0xbd, 0xa5, 0xd3, 0x28, 0x90, 0xa4},
+}
+
+// Defined in fwpmu.h. b235ae9a-1d64-49b8-a44c-5ff3d9095045
+var cFWPM_CONDITION_IP_REMOTE_ADDRESS = windows.GUID{
+ Data1: 0xb235ae9a,
+ Data2: 0x1d64,
+ Data3: 0x49b8,
+ Data4: [8]byte{0xa4, 0x4c, 0x5f, 0xf3, 0xd9, 0x09, 0x50, 0x45},
+}
+
+// Defined in fwpmu.h. daf8cd14-e09e-4c93-a5ae-c5c13b73ffca
+var cFWPM_CONDITION_INTERFACE_TYPE = windows.GUID{
+ Data1: 0xdaf8cd14,
+ Data2: 0xe09e,
+ Data3: 0x4c93,
+ Data4: [8]byte{0xa5, 0xae, 0xc5, 0xc1, 0x3b, 0x73, 0xff, 0xca},
+}
+
+// Defined in fwpmu.h. 3971ef2b-623e-4f9a-8cb1-6e79b806b9a7
+var cFWPM_CONDITION_IP_PROTOCOL = windows.GUID{
+ Data1: 0x3971ef2b,
+ Data2: 0x623e,
+ Data3: 0x4f9a,
+ Data4: [8]byte{0x8c, 0xb1, 0x6e, 0x79, 0xb8, 0x06, 0xb9, 0xa7},
+}
+
+// Defined in fwpmu.h. 0c1ba1af-5765-453f-af22-a8f791ac775b
+var cFWPM_CONDITION_IP_LOCAL_PORT = windows.GUID{
+ Data1: 0x0c1ba1af,
+ Data2: 0x5765,
+ Data3: 0x453f,
+ Data4: [8]byte{0xaf, 0x22, 0xa8, 0xf7, 0x91, 0xac, 0x77, 0x5b},
+}
+
+// Defined in fwpmu.h. c35a604d-d22b-4e1a-91b4-68f674ee674b
+var cFWPM_CONDITION_IP_REMOTE_PORT = windows.GUID{
+ Data1: 0xc35a604d,
+ Data2: 0xd22b,
+ Data3: 0x4e1a,
+ Data4: [8]byte{0x91, 0xb4, 0x68, 0xf6, 0x74, 0xee, 0x67, 0x4b},
+}
+
+// Defined in fwpmu.h. d78e1e87-8644-4ea5-9437-d809ecefc971
+var cFWPM_CONDITION_ALE_APP_ID = windows.GUID{
+ Data1: 0xd78e1e87,
+ Data2: 0x8644,
+ Data3: 0x4ea5,
+ Data4: [8]byte{0x94, 0x37, 0xd8, 0x09, 0xec, 0xef, 0xc9, 0x71},
+}
+
+// af043a0a-b34d-4f86-979c-c90371af6e66
+var cFWPM_CONDITION_ALE_USER_ID = windows.GUID{
+ Data1: 0xaf043a0a,
+ Data2: 0xb34d,
+ Data3: 0x4f86,
+ Data4: [8]byte{0x97, 0x9c, 0xc9, 0x03, 0x71, 0xaf, 0x6e, 0x66},
+}
+
+// d9ee00de-c1ef-4617-bfe3-ffd8f5a08957
+var cFWPM_CONDITION_IP_LOCAL_ADDRESS = windows.GUID{
+ Data1: 0xd9ee00de,
+ Data2: 0xc1ef,
+ Data3: 0x4617,
+ Data4: [8]byte{0xbf, 0xe3, 0xff, 0xd8, 0xf5, 0xa0, 0x89, 0x57},
+}
+
+var cFWPM_CONDITION_ICMP_TYPE = cFWPM_CONDITION_IP_LOCAL_PORT
+
+// Defined in fwpmtypes.h
+type wtFwpmFilterFlags uint32
+
+const (
+ cFWPM_FILTER_FLAG_NONE wtFwpmFilterFlags = 0x00000000
+ cFWPM_FILTER_FLAG_PERSISTENT wtFwpmFilterFlags = 0x00000001
+ cFWPM_FILTER_FLAG_BOOTTIME wtFwpmFilterFlags = 0x00000002
+ cFWPM_FILTER_FLAG_HAS_PROVIDER_CONTEXT wtFwpmFilterFlags = 0x00000004
+ cFWPM_FILTER_FLAG_CLEAR_ACTION_RIGHT wtFwpmFilterFlags = 0x00000008
+ cFWPM_FILTER_FLAG_PERMIT_IF_CALLOUT_UNREGISTERED wtFwpmFilterFlags = 0x00000010
+ cFWPM_FILTER_FLAG_DISABLED wtFwpmFilterFlags = 0x00000020
+ cFWPM_FILTER_FLAG_INDEXED wtFwpmFilterFlags = 0x00000040
+ cFWPM_FILTER_FLAG_HAS_SECURITY_REALM_PROVIDER_CONTEXT wtFwpmFilterFlags = 0x00000080
+ cFWPM_FILTER_FLAG_SYSTEMOS_ONLY wtFwpmFilterFlags = 0x00000100
+ cFWPM_FILTER_FLAG_GAMEOS_ONLY wtFwpmFilterFlags = 0x00000200
+ cFWPM_FILTER_FLAG_SILENT_MODE wtFwpmFilterFlags = 0x00000400
+ cFWPM_FILTER_FLAG_IPSEC_NO_ACQUIRE_INITIATE wtFwpmFilterFlags = 0x00000800
+)
+
+// FWPM_LAYER_ALE_AUTH_CONNECT_V4 (c38d57d1-05a7-4c33-904f-7fbceee60e82) defined in fwpmu.h
+var cFWPM_LAYER_ALE_AUTH_CONNECT_V4 = windows.GUID{
+ Data1: 0xc38d57d1,
+ Data2: 0x05a7,
+ Data3: 0x4c33,
+ Data4: [8]byte{0x90, 0x4f, 0x7f, 0xbc, 0xee, 0xe6, 0x0e, 0x82},
+}
+
+// e1cd9fe7-f4b5-4273-96c0-592e487b8650
+var cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4 = windows.GUID{
+ Data1: 0xe1cd9fe7,
+ Data2: 0xf4b5,
+ Data3: 0x4273,
+ Data4: [8]byte{0x96, 0xc0, 0x59, 0x2e, 0x48, 0x7b, 0x86, 0x50},
+}
+
+// FWPM_LAYER_ALE_AUTH_CONNECT_V6 (4a72393b-319f-44bc-84c3-ba54dcb3b6b4) defined in fwpmu.h
+var cFWPM_LAYER_ALE_AUTH_CONNECT_V6 = windows.GUID{
+ Data1: 0x4a72393b,
+ Data2: 0x319f,
+ Data3: 0x44bc,
+ Data4: [8]byte{0x84, 0xc3, 0xba, 0x54, 0xdc, 0xb3, 0xb6, 0xb4},
+}
+
+// a3b42c97-9f04-4672-b87e-cee9c483257f
+var cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6 = windows.GUID{
+ Data1: 0xa3b42c97,
+ Data2: 0x9f04,
+ Data3: 0x4672,
+ Data4: [8]byte{0xb8, 0x7e, 0xce, 0xe9, 0xc4, 0x83, 0x25, 0x7f},
+}
+
+// FWP_BITMAP_ARRAY64 defined in fwtypes.h
+type wtFwpBitmapArray64 struct {
+ bitmapArray64 [8]uint8 // Windows type: [8]UINT8
+}
+
+// FWP_BYTE_ARRAY6 defined in fwtypes.h
+// (https://docs.microsoft.com/en-us/windows/desktop/api/fwptypes/ns-fwptypes-fwp_byte_array6_)
+type wtFwpByteArray6 struct {
+ byteArray6 [6]uint8 // Windows type: [6]UINT8
+}
+
+// FWP_BYTE_ARRAY16 defined in fwptypes.h
+// (https://docs.microsoft.com/en-us/windows/desktop/api/fwptypes/ns-fwptypes-fwp_byte_array16_)
+type wtFwpByteArray16 struct {
+ byteArray16 [16]uint8 // Windows type [16]UINT8
+}
+
+// FWP_CONDITION_VALUE0 defined in fwptypes.h
+// (https://docs.microsoft.com/en-us/windows/desktop/api/fwptypes/ns-fwptypes-fwp_condition_value0_).
+type wtFwpConditionValue0 wtFwpValue0
+
+// FWP_DATA_TYPE defined in fwptypes.h
+// (https://docs.microsoft.com/en-us/windows/desktop/api/fwptypes/ne-fwptypes-fwp_data_type_)
+type wtFwpDataType uint
+
+const (
+ cFWP_EMPTY wtFwpDataType = 0
+ cFWP_UINT8 wtFwpDataType = cFWP_EMPTY + 1
+ cFWP_UINT16 wtFwpDataType = cFWP_UINT8 + 1
+ cFWP_UINT32 wtFwpDataType = cFWP_UINT16 + 1
+ cFWP_UINT64 wtFwpDataType = cFWP_UINT32 + 1
+ cFWP_INT8 wtFwpDataType = cFWP_UINT64 + 1
+ cFWP_INT16 wtFwpDataType = cFWP_INT8 + 1
+ cFWP_INT32 wtFwpDataType = cFWP_INT16 + 1
+ cFWP_INT64 wtFwpDataType = cFWP_INT32 + 1
+ cFWP_FLOAT wtFwpDataType = cFWP_INT64 + 1
+ cFWP_DOUBLE wtFwpDataType = cFWP_FLOAT + 1
+ cFWP_BYTE_ARRAY16_TYPE wtFwpDataType = cFWP_DOUBLE + 1
+ cFWP_BYTE_BLOB_TYPE wtFwpDataType = cFWP_BYTE_ARRAY16_TYPE + 1
+ cFWP_SID wtFwpDataType = cFWP_BYTE_BLOB_TYPE + 1
+ cFWP_SECURITY_DESCRIPTOR_TYPE wtFwpDataType = cFWP_SID + 1
+ cFWP_TOKEN_INFORMATION_TYPE wtFwpDataType = cFWP_SECURITY_DESCRIPTOR_TYPE + 1
+ cFWP_TOKEN_ACCESS_INFORMATION_TYPE wtFwpDataType = cFWP_TOKEN_INFORMATION_TYPE + 1
+ cFWP_UNICODE_STRING_TYPE wtFwpDataType = cFWP_TOKEN_ACCESS_INFORMATION_TYPE + 1
+ cFWP_BYTE_ARRAY6_TYPE wtFwpDataType = cFWP_UNICODE_STRING_TYPE + 1
+ cFWP_BITMAP_INDEX_TYPE wtFwpDataType = cFWP_BYTE_ARRAY6_TYPE + 1
+ cFWP_BITMAP_ARRAY64_TYPE wtFwpDataType = cFWP_BITMAP_INDEX_TYPE + 1
+ cFWP_SINGLE_DATA_TYPE_MAX wtFwpDataType = 0xff
+ cFWP_V4_ADDR_MASK wtFwpDataType = cFWP_SINGLE_DATA_TYPE_MAX + 1
+ cFWP_V6_ADDR_MASK wtFwpDataType = cFWP_V4_ADDR_MASK + 1
+ cFWP_RANGE_TYPE wtFwpDataType = cFWP_V6_ADDR_MASK + 1
+ cFWP_DATA_TYPE_MAX wtFwpDataType = cFWP_RANGE_TYPE + 1
+)
+
+// FWP_V4_ADDR_AND_MASK defined in fwptypes.h
+// (https://docs.microsoft.com/en-us/windows/desktop/api/fwptypes/ns-fwptypes-fwp_v4_addr_and_mask_).
+type wtFwpV4AddrAndMask struct {
+ addr uint32
+ mask uint32
+}
+
+// FWP_V6_ADDR_AND_MASK defined in fwptypes.h
+// (https://docs.microsoft.com/en-us/windows/desktop/api/fwptypes/ns-fwptypes-fwp_v6_addr_and_mask_).
+type wtFwpV6AddrAndMask struct {
+ addr [16]uint8
+ prefixLength uint8
+}
+
+// FWP_VALUE0 defined in fwptypes.h
+// (https://docs.microsoft.com/en-us/windows/desktop/api/fwptypes/ns-fwptypes-fwp_value0_)
+type wtFwpValue0 struct {
+ _type wtFwpDataType
+ value uintptr
+}
+
+// FWPM_DISPLAY_DATA0 defined in fwptypes.h
+// (https://docs.microsoft.com/en-us/windows/desktop/api/fwptypes/ns-fwptypes-fwpm_display_data0_).
+type wtFwpmDisplayData0 struct {
+ name *uint16 // Windows type: *wchar_t
+ description *uint16 // Windows type: *wchar_t
+}
+
+// FWPM_FILTER_CONDITION0 defined in fwpmtypes.h
+// (https://docs.microsoft.com/en-us/windows/desktop/api/fwpmtypes/ns-fwpmtypes-fwpm_filter_condition0_).
+type wtFwpmFilterCondition0 struct {
+ fieldKey windows.GUID // Windows type: GUID
+ matchType wtFwpMatchType
+ conditionValue wtFwpConditionValue0
+}
+
+// FWPM_PROVIDER0 defined in fwpmtypes.h
+// (https://docs.microsoft.com/en-us/windows/desktop/api/fwpmtypes/ns-fwpmtypes-fwpm_provider0_)
+type wtFwpProvider0 struct {
+ providerKey windows.GUID // Windows type: GUID
+ displayData wtFwpmDisplayData0
+ flags uint32
+ providerData wtFwpByteBlob
+ serviceName *uint16 // Windows type: *wchar_t
+}
+
+type wtFwpmSessionFlagsValue uint32
+
+const (
+ cFWPM_SESSION_FLAG_DYNAMIC wtFwpmSessionFlagsValue = 0x00000001 // FWPM_SESSION_FLAG_DYNAMIC defined in fwpmtypes.h
+)
+
+// FWPM_SESSION0 defined in fwpmtypes.h
+// (https://docs.microsoft.com/en-us/windows/desktop/api/fwpmtypes/ns-fwpmtypes-fwpm_session0_).
+type wtFwpmSession0 struct {
+ sessionKey windows.GUID // Windows type: GUID
+ displayData wtFwpmDisplayData0
+ flags wtFwpmSessionFlagsValue // Windows type UINT32
+ txnWaitTimeoutInMSec uint32
+ processId uint32 // Windows type: DWORD
+ sid *windows.SID
+ username *uint16 // Windows type: *wchar_t
+ kernelMode uint8 // Windows type: BOOL
+}
+
+type wtFwpmSublayerFlags uint32
+
+const (
+ cFWPM_SUBLAYER_FLAG_PERSISTENT wtFwpmSublayerFlags = 0x00000001 // FWPM_SUBLAYER_FLAG_PERSISTENT defined in fwpmtypes.h
+)
+
+// FWPM_SUBLAYER0 defined in fwpmtypes.h
+// (https://docs.microsoft.com/en-us/windows/desktop/api/fwpmtypes/ns-fwpmtypes-fwpm_sublayer0_)
+type wtFwpmSublayer0 struct {
+ subLayerKey windows.GUID // Windows type: GUID
+ displayData wtFwpmDisplayData0
+ flags wtFwpmSublayerFlags
+ providerKey *windows.GUID // Windows type: *GUID
+ providerData wtFwpByteBlob
+ weight uint16
+}
+
+// Defined in rpcdce.h
+type wtRpcCAuthN uint32
+
+const (
+ cRPC_C_AUTHN_NONE wtRpcCAuthN = 0
+ cRPC_C_AUTHN_DCE_PRIVATE wtRpcCAuthN = 1
+ cRPC_C_AUTHN_DCE_PUBLIC wtRpcCAuthN = 2
+ cRPC_C_AUTHN_DEC_PUBLIC wtRpcCAuthN = 4
+ cRPC_C_AUTHN_GSS_NEGOTIATE wtRpcCAuthN = 9
+ cRPC_C_AUTHN_WINNT wtRpcCAuthN = 10
+ cRPC_C_AUTHN_GSS_SCHANNEL wtRpcCAuthN = 14
+ cRPC_C_AUTHN_GSS_KERBEROS wtRpcCAuthN = 16
+ cRPC_C_AUTHN_DPA wtRpcCAuthN = 17
+ cRPC_C_AUTHN_MSN wtRpcCAuthN = 18
+ cRPC_C_AUTHN_DIGEST wtRpcCAuthN = 21
+ cRPC_C_AUTHN_KERNEL wtRpcCAuthN = 20
+ cRPC_C_AUTHN_NEGO_EXTENDER wtRpcCAuthN = 30
+ cRPC_C_AUTHN_PKU2U wtRpcCAuthN = 31
+ cRPC_C_AUTHN_LIVE_SSP wtRpcCAuthN = 32
+ cRPC_C_AUTHN_LIVEXP_SSP wtRpcCAuthN = 35
+ cRPC_C_AUTHN_CLOUD_AP wtRpcCAuthN = 36
+ cRPC_C_AUTHN_MSONLINE wtRpcCAuthN = 82
+ cRPC_C_AUTHN_MQ wtRpcCAuthN = 100
+ cRPC_C_AUTHN_DEFAULT wtRpcCAuthN = 0xFFFFFFFF
+)
+
+// SEC_WINNT_AUTH_IDENTITY_W defined in rpcdce.h
+// (https://docs.microsoft.com/en-us/windows/desktop/api/rpcdce/ns-rpcdce-_sec_winnt_auth_identity_w).
+type wtSecWinntAuthIdentityW struct {
+ User *uint16 // Windows type: unsigned short
+ UserLength int32 // Windows type: long
+ Domain *uint16 // Windows type: unsigned short
+ DomainLength int32 // Windows type: long
+ Password *uint16 // Windows type: unsigned short
+ PasswordLength int32 // Windows type: long
+ Flags int32 // Windows type: long
+}
+
+// FWPM_PROVIDER0 defined in fwpmtypes.h
+// (https://docs.microsoft.com/sv-se/windows/desktop/api/fwpmtypes/ns-fwpmtypes-fwpm_provider0_).
+type wtFwpmProvider0 struct {
+ providerKey windows.GUID
+ displayData wtFwpmDisplayData0
+ flags uint32
+ providerData wtFwpByteBlob
+ serviceName *uint16
+}
+
+type wtObjectType uint32
+
+const (
+ cSE_KERNEL_OBJECT wtObjectType = 6
+)
+
+type wtIfType uint32
+
+const (
+ cIF_TYPE_SOFTWARE_LOOPBACK wtIfType = 24
+)
+
+type wtIpProto uint32
+
+const (
+ cIPPROTO_ICMP wtIpProto = 1
+ cIPPROTO_TCP wtIpProto = 6
+ cIPPROTO_UDP wtIpProto = 17
+)
diff --git a/service/firewall/types_windows_386.go b/service/firewall/types_windows_386.go
new file mode 100644
index 00000000..7a474912
--- /dev/null
+++ b/service/firewall/types_windows_386.go
@@ -0,0 +1,106 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
+ */
+
+package firewall
+
+import "golang.org/x/sys/windows"
+
+const (
+ wtFwpByteBlob_Size = 8
+
+ wtFwpByteBlob_data_Offset = 4
+
+ wtFwpConditionValue0_Size = 8
+
+ wtFwpConditionValue0_uint8_Offset = 4
+
+ wtFwpmDisplayData0_Size = 8
+
+ wtFwpmDisplayData0_description_Offset = 4
+
+ wtFwpmFilter0_Size = 152
+
+ wtFwpmFilter0_displayData_Offset = 16
+ wtFwpmFilter0_flags_Offset = 24
+ wtFwpmFilter0_providerKey_Offset = 28
+ wtFwpmFilter0_providerData_Offset = 32
+ wtFwpmFilter0_layerKey_Offset = 40
+ wtFwpmFilter0_subLayerKey_Offset = 56
+ wtFwpmFilter0_weight_Offset = 72
+ wtFwpmFilter0_numFilterConditions_Offset = 80
+ wtFwpmFilter0_filterCondition_Offset = 84
+ wtFwpmFilter0_action_Offset = 88
+ wtFwpmFilter0_providerContextKey_Offset = 112
+ wtFwpmFilter0_reserved_Offset = 128
+ wtFwpmFilter0_filterId_Offset = 136
+ wtFwpmFilter0_effectiveWeight_Offset = 144
+
+ wtFwpmFilterCondition0_Size = 28
+
+ wtFwpmFilterCondition0_matchType_Offset = 16
+ wtFwpmFilterCondition0_conditionValue_Offset = 20
+
+ wtFwpmSession0_Size = 48
+
+ wtFwpmSession0_displayData_Offset = 16
+ wtFwpmSession0_flags_Offset = 24
+ wtFwpmSession0_txnWaitTimeoutInMSec_Offset = 28
+ wtFwpmSession0_processId_Offset = 32
+ wtFwpmSession0_sid_Offset = 36
+ wtFwpmSession0_username_Offset = 40
+ wtFwpmSession0_kernelMode_Offset = 44
+
+ wtFwpmSublayer0_Size = 44
+
+ wtFwpmSublayer0_displayData_Offset = 16
+ wtFwpmSublayer0_flags_Offset = 24
+ wtFwpmSublayer0_providerKey_Offset = 28
+ wtFwpmSublayer0_providerData_Offset = 32
+ wtFwpmSublayer0_weight_Offset = 40
+
+ wtFwpProvider0_Size = 40
+
+ wtFwpProvider0_displayData_Offset = 16
+ wtFwpProvider0_flags_Offset = 24
+ wtFwpProvider0_providerData_Offset = 28
+ wtFwpProvider0_serviceName_Offset = 36
+
+ wtFwpTokenInformation_Size = 16
+
+ wtFwpValue0_Size = 8
+
+ wtFwpValue0_value_Offset = 4
+
+ wtSecWinntAuthIdentityW_Size = 28
+
+ wtSecWinntAuthIdentityW_UserLength_Offset = 4
+ wtSecWinntAuthIdentityW_Domain_Offset = 8
+ wtSecWinntAuthIdentityW_DomainLength_Offset = 12
+ wtSecWinntAuthIdentityW_Password_Offset = 16
+ wtSecWinntAuthIdentityW_PasswordLength_Offset = 20
+ wtSecWinntAuthIdentityW_Flags_Offset = 24
+)
+
+// FWPM_FILTER0 defined in fwpmtypes.h
+// (https://docs.microsoft.com/en-us/windows/desktop/api/fwpmtypes/ns-fwpmtypes-fwpm_filter0_).
+type wtFwpmFilter0 struct {
+ filterKey windows.GUID // Windows type: GUID
+ displayData wtFwpmDisplayData0
+ flags uint32
+ providerKey *windows.GUID // Windows type: *GUID
+ providerData wtFwpByteBlob
+ layerKey windows.GUID // Windows type: GUID
+ subLayerKey windows.GUID // Windows type: GUID
+ weight wtFwpValue0
+ numFilterConditions uint32
+ filterCondition *wtFwpmFilterCondition0
+ action wtFwpmAction0
+ offset1 [4]byte // Layout correction field
+ providerContextKey windows.GUID // Windows type: GUID
+ reserved *windows.GUID // Windows type: *GUID
+ offset2 [4]byte // Layout correction field
+ filterId uint64
+ effectiveWeight wtFwpValue0
+}
diff --git a/service/firewall/types_windows_amd64.go b/service/firewall/types_windows_amd64.go
new file mode 100644
index 00000000..036bfa15
--- /dev/null
+++ b/service/firewall/types_windows_amd64.go
@@ -0,0 +1,103 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
+ */
+
+package firewall
+
+import "golang.org/x/sys/windows"
+
+const (
+ wtFwpByteBlob_Size = 16
+
+ wtFwpByteBlob_data_Offset = 8
+
+ wtFwpConditionValue0_Size = 16
+
+ wtFwpConditionValue0_uint8_Offset = 8
+
+ wtFwpmDisplayData0_Size = 16
+
+ wtFwpmDisplayData0_description_Offset = 8
+
+ wtFwpmFilter0_Size = 200
+
+ wtFwpmFilter0_displayData_Offset = 16
+ wtFwpmFilter0_flags_Offset = 32
+ wtFwpmFilter0_providerKey_Offset = 40
+ wtFwpmFilter0_providerData_Offset = 48
+ wtFwpmFilter0_layerKey_Offset = 64
+ wtFwpmFilter0_subLayerKey_Offset = 80
+ wtFwpmFilter0_weight_Offset = 96
+ wtFwpmFilter0_numFilterConditions_Offset = 112
+ wtFwpmFilter0_filterCondition_Offset = 120
+ wtFwpmFilter0_action_Offset = 128
+ wtFwpmFilter0_providerContextKey_Offset = 152
+ wtFwpmFilter0_reserved_Offset = 168
+ wtFwpmFilter0_filterId_Offset = 176
+ wtFwpmFilter0_effectiveWeight_Offset = 184
+
+ wtFwpmFilterCondition0_Size = 40
+
+ wtFwpmFilterCondition0_matchType_Offset = 16
+ wtFwpmFilterCondition0_conditionValue_Offset = 24
+
+ wtFwpmSession0_Size = 72
+
+ wtFwpmSession0_displayData_Offset = 16
+ wtFwpmSession0_flags_Offset = 32
+ wtFwpmSession0_txnWaitTimeoutInMSec_Offset = 36
+ wtFwpmSession0_processId_Offset = 40
+ wtFwpmSession0_sid_Offset = 48
+ wtFwpmSession0_username_Offset = 56
+ wtFwpmSession0_kernelMode_Offset = 64
+
+ wtFwpmSublayer0_Size = 72
+
+ wtFwpmSublayer0_displayData_Offset = 16
+ wtFwpmSublayer0_flags_Offset = 32
+ wtFwpmSublayer0_providerKey_Offset = 40
+ wtFwpmSublayer0_providerData_Offset = 48
+ wtFwpmSublayer0_weight_Offset = 64
+
+ wtFwpProvider0_Size = 64
+
+ wtFwpProvider0_displayData_Offset = 16
+ wtFwpProvider0_flags_Offset = 32
+ wtFwpProvider0_providerData_Offset = 40
+ wtFwpProvider0_serviceName_Offset = 56
+
+ wtFwpValue0_Size = 16
+
+ wtFwpValue0_value_Offset = 8
+
+ wtSecWinntAuthIdentityW_Size = 48
+
+ wtSecWinntAuthIdentityW_UserLength_Offset = 8
+ wtSecWinntAuthIdentityW_Domain_Offset = 16
+ wtSecWinntAuthIdentityW_DomainLength_Offset = 24
+ wtSecWinntAuthIdentityW_Password_Offset = 32
+ wtSecWinntAuthIdentityW_PasswordLength_Offset = 40
+ wtSecWinntAuthIdentityW_Flags_Offset = 44
+)
+
+// FWPM_FILTER0 defined in fwpmtypes.h
+// (https://docs.microsoft.com/en-us/windows/desktop/api/fwpmtypes/ns-fwpmtypes-fwpm_filter0_).
+type wtFwpmFilter0 struct {
+ filterKey windows.GUID // Windows type: GUID
+ displayData wtFwpmDisplayData0
+ flags wtFwpmFilterFlags // Windows type: UINT32
+ providerKey *windows.GUID // Windows type: *GUID
+ providerData wtFwpByteBlob
+ layerKey windows.GUID // Windows type: GUID
+ subLayerKey windows.GUID // Windows type: GUID
+ weight wtFwpValue0
+ numFilterConditions uint32
+ filterCondition *wtFwpmFilterCondition0
+ action wtFwpmAction0
+ offset1 [4]byte // Layout correction field
+ providerContextKey windows.GUID // Windows type: GUID
+ reserved *windows.GUID // Windows type: *GUID
+ filterId uint64
+ effectiveWeight wtFwpValue0
+}
diff --git a/service/firewall/types_windows_test.go b/service/firewall/types_windows_test.go
new file mode 100644
index 00000000..6ff6e09d
--- /dev/null
+++ b/service/firewall/types_windows_test.go
@@ -0,0 +1,602 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
+ */
+
+package firewall
+
+import (
+ "testing"
+ "unsafe"
+)
+
+func TestWtFwpByteBlobSize(t *testing.T) {
+
+ const actualWtFwpByteBlobSize = unsafe.Sizeof(wtFwpByteBlob{})
+
+ if actualWtFwpByteBlobSize != wtFwpByteBlob_Size {
+ t.Errorf("Size of FwpByteBlob is %d, although %d is expected.", actualWtFwpByteBlobSize,
+ wtFwpByteBlob_Size)
+ }
+}
+
+func TestWtFwpByteBlobOffsets(t *testing.T) {
+
+ s := wtFwpByteBlob{}
+ sp := uintptr(unsafe.Pointer(&s))
+
+ offset := uintptr(unsafe.Pointer(&s.data)) - sp
+
+ if offset != wtFwpByteBlob_data_Offset {
+ t.Errorf("FwpByteBlob.data offset is %d although %d is expected", offset, wtFwpByteBlob_data_Offset)
+ return
+ }
+}
+
+func TestWtFwpmAction0Size(t *testing.T) {
+
+ const actualWtFwpmAction0Size = unsafe.Sizeof(wtFwpmAction0{})
+
+ if actualWtFwpmAction0Size != wtFwpmAction0_Size {
+ t.Errorf("Size of wtFwpmAction0 is %d, although %d is expected.", actualWtFwpmAction0Size,
+ wtFwpmAction0_Size)
+ }
+}
+
+func TestWtFwpmAction0Offsets(t *testing.T) {
+
+ s := wtFwpmAction0{}
+ sp := uintptr(unsafe.Pointer(&s))
+
+ offset := uintptr(unsafe.Pointer(&s.filterType)) - sp
+
+ if offset != wtFwpmAction0_filterType_Offset {
+ t.Errorf("wtFwpmAction0.filterType offset is %d although %d is expected", offset,
+ wtFwpmAction0_filterType_Offset)
+ return
+ }
+}
+
+func TestWtFwpBitmapArray64Size(t *testing.T) {
+
+ const actualWtFwpBitmapArray64Size = unsafe.Sizeof(wtFwpBitmapArray64{})
+
+ if actualWtFwpBitmapArray64Size != wtFwpBitmapArray64_Size {
+ t.Errorf("Size of wtFwpBitmapArray64 is %d, although %d is expected.", actualWtFwpBitmapArray64Size,
+ wtFwpBitmapArray64_Size)
+ }
+}
+
+func TestWtFwpByteArray6Size(t *testing.T) {
+
+ const actualWtFwpByteArray6Size = unsafe.Sizeof(wtFwpByteArray6{})
+
+ if actualWtFwpByteArray6Size != wtFwpByteArray6_Size {
+ t.Errorf("Size of wtFwpByteArray6 is %d, although %d is expected.", actualWtFwpByteArray6Size,
+ wtFwpByteArray6_Size)
+ }
+}
+
+func TestWtFwpByteArray16Size(t *testing.T) {
+
+ const actualWtFwpByteArray16Size = unsafe.Sizeof(wtFwpByteArray16{})
+
+ if actualWtFwpByteArray16Size != wtFwpByteArray16_Size {
+ t.Errorf("Size of wtFwpByteArray16 is %d, although %d is expected.", actualWtFwpByteArray16Size,
+ wtFwpByteArray16_Size)
+ }
+}
+
+func TestWtFwpConditionValue0Size(t *testing.T) {
+
+ const actualWtFwpConditionValue0Size = unsafe.Sizeof(wtFwpConditionValue0{})
+
+ if actualWtFwpConditionValue0Size != wtFwpConditionValue0_Size {
+ t.Errorf("Size of wtFwpConditionValue0 is %d, although %d is expected.", actualWtFwpConditionValue0Size,
+ wtFwpConditionValue0_Size)
+ }
+}
+
+func TestWtFwpConditionValue0Offsets(t *testing.T) {
+
+ s := wtFwpConditionValue0{}
+ sp := uintptr(unsafe.Pointer(&s))
+
+ offset := uintptr(unsafe.Pointer(&s.value)) - sp
+
+ if offset != wtFwpConditionValue0_uint8_Offset {
+ t.Errorf("wtFwpConditionValue0.value offset is %d although %d is expected", offset, wtFwpConditionValue0_uint8_Offset)
+ return
+ }
+}
+
+func TestWtFwpV4AddrAndMaskSize(t *testing.T) {
+
+ const actualWtFwpV4AddrAndMaskSize = unsafe.Sizeof(wtFwpV4AddrAndMask{})
+
+ if actualWtFwpV4AddrAndMaskSize != wtFwpV4AddrAndMask_Size {
+ t.Errorf("Size of wtFwpV4AddrAndMask is %d, although %d is expected.", actualWtFwpV4AddrAndMaskSize,
+ wtFwpV4AddrAndMask_Size)
+ }
+}
+
+func TestWtFwpV4AddrAndMaskOffsets(t *testing.T) {
+
+ s := wtFwpV4AddrAndMask{}
+ sp := uintptr(unsafe.Pointer(&s))
+
+ offset := uintptr(unsafe.Pointer(&s.mask)) - sp
+
+ if offset != wtFwpV4AddrAndMask_mask_Offset {
+ t.Errorf("wtFwpV4AddrAndMask.mask offset is %d although %d is expected", offset,
+ wtFwpV4AddrAndMask_mask_Offset)
+ return
+ }
+}
+
+func TestWtFwpV6AddrAndMaskSize(t *testing.T) {
+
+ const actualWtFwpV6AddrAndMaskSize = unsafe.Sizeof(wtFwpV6AddrAndMask{})
+
+ if actualWtFwpV6AddrAndMaskSize != wtFwpV6AddrAndMask_Size {
+ t.Errorf("Size of wtFwpV6AddrAndMask is %d, although %d is expected.", actualWtFwpV6AddrAndMaskSize,
+ wtFwpV6AddrAndMask_Size)
+ }
+}
+
+func TestWtFwpV6AddrAndMaskOffsets(t *testing.T) {
+
+ s := wtFwpV6AddrAndMask{}
+ sp := uintptr(unsafe.Pointer(&s))
+
+ offset := uintptr(unsafe.Pointer(&s.prefixLength)) - sp
+
+ if offset != wtFwpV6AddrAndMask_prefixLength_Offset {
+ t.Errorf("wtFwpV6AddrAndMask.prefixLength offset is %d although %d is expected", offset,
+ wtFwpV6AddrAndMask_prefixLength_Offset)
+ return
+ }
+}
+
+func TestWtFwpValue0Size(t *testing.T) {
+
+ const actualWtFwpValue0Size = unsafe.Sizeof(wtFwpValue0{})
+
+ if actualWtFwpValue0Size != wtFwpValue0_Size {
+ t.Errorf("Size of wtFwpValue0 is %d, although %d is expected.", actualWtFwpValue0Size, wtFwpValue0_Size)
+ }
+}
+
+func TestWtFwpValue0Offsets(t *testing.T) {
+
+ s := wtFwpValue0{}
+ sp := uintptr(unsafe.Pointer(&s))
+
+ offset := uintptr(unsafe.Pointer(&s.value)) - sp
+
+ if offset != wtFwpValue0_value_Offset {
+ t.Errorf("wtFwpValue0.value offset is %d although %d is expected", offset, wtFwpValue0_value_Offset)
+ return
+ }
+}
+
+func TestWtFwpmDisplayData0Size(t *testing.T) {
+
+ const actualWtFwpmDisplayData0Size = unsafe.Sizeof(wtFwpmDisplayData0{})
+
+ if actualWtFwpmDisplayData0Size != wtFwpmDisplayData0_Size {
+ t.Errorf("Size of wtFwpmDisplayData0 is %d, although %d is expected.", actualWtFwpmDisplayData0Size,
+ wtFwpmDisplayData0_Size)
+ }
+}
+
+func TestWtFwpmDisplayData0Offsets(t *testing.T) {
+
+ s := wtFwpmDisplayData0{}
+ sp := uintptr(unsafe.Pointer(&s))
+
+ offset := uintptr(unsafe.Pointer(&s.description)) - sp
+
+ if offset != wtFwpmDisplayData0_description_Offset {
+ t.Errorf("wtFwpmDisplayData0.description offset is %d although %d is expected", offset,
+ wtFwpmDisplayData0_description_Offset)
+ return
+ }
+}
+
+func TestWtFwpmFilterCondition0Size(t *testing.T) {
+
+ const actualWtFwpmFilterCondition0Size = unsafe.Sizeof(wtFwpmFilterCondition0{})
+
+ if actualWtFwpmFilterCondition0Size != wtFwpmFilterCondition0_Size {
+ t.Errorf("Size of wtFwpmFilterCondition0 is %d, although %d is expected.",
+ actualWtFwpmFilterCondition0Size, wtFwpmFilterCondition0_Size)
+ }
+}
+
+func TestWtFwpmFilterCondition0Offsets(t *testing.T) {
+
+ s := wtFwpmFilterCondition0{}
+ sp := uintptr(unsafe.Pointer(&s))
+
+ offset := uintptr(unsafe.Pointer(&s.matchType)) - sp
+
+ if offset != wtFwpmFilterCondition0_matchType_Offset {
+ t.Errorf("wtFwpmFilterCondition0.matchType offset is %d although %d is expected", offset,
+ wtFwpmFilterCondition0_matchType_Offset)
+ return
+ }
+
+ offset = uintptr(unsafe.Pointer(&s.conditionValue)) - sp
+
+ if offset != wtFwpmFilterCondition0_conditionValue_Offset {
+ t.Errorf("wtFwpmFilterCondition0.conditionValue offset is %d although %d is expected", offset,
+ wtFwpmFilterCondition0_conditionValue_Offset)
+ return
+ }
+}
+
+func TestWtFwpmFilter0Size(t *testing.T) {
+
+ const actualWtFwpmFilter0Size = unsafe.Sizeof(wtFwpmFilter0{})
+
+ if actualWtFwpmFilter0Size != wtFwpmFilter0_Size {
+ t.Errorf("Size of wtFwpmFilter0 is %d, although %d is expected.", actualWtFwpmFilter0Size,
+ wtFwpmFilter0_Size)
+ }
+}
+
+func TestWtFwpmFilter0Offsets(t *testing.T) {
+
+ s := wtFwpmFilter0{}
+ sp := uintptr(unsafe.Pointer(&s))
+
+ offset := uintptr(unsafe.Pointer(&s.displayData)) - sp
+
+ if offset != wtFwpmFilter0_displayData_Offset {
+ t.Errorf("wtFwpmFilter0.displayData offset is %d although %d is expected", offset,
+ wtFwpmFilter0_displayData_Offset)
+ return
+ }
+
+ offset = uintptr(unsafe.Pointer(&s.flags)) - sp
+
+ if offset != wtFwpmFilter0_flags_Offset {
+ t.Errorf("wtFwpmFilter0.flags offset is %d although %d is expected", offset, wtFwpmFilter0_flags_Offset)
+ return
+ }
+
+ offset = uintptr(unsafe.Pointer(&s.providerKey)) - sp
+
+ if offset != wtFwpmFilter0_providerKey_Offset {
+ t.Errorf("wtFwpmFilter0.providerKey offset is %d although %d is expected", offset,
+ wtFwpmFilter0_providerKey_Offset)
+ return
+ }
+
+ offset = uintptr(unsafe.Pointer(&s.providerData)) - sp
+
+ if offset != wtFwpmFilter0_providerData_Offset {
+ t.Errorf("wtFwpmFilter0.providerData offset is %d although %d is expected", offset,
+ wtFwpmFilter0_providerData_Offset)
+ return
+ }
+
+ offset = uintptr(unsafe.Pointer(&s.layerKey)) - sp
+
+ if offset != wtFwpmFilter0_layerKey_Offset {
+ t.Errorf("wtFwpmFilter0.layerKey offset is %d although %d is expected", offset,
+ wtFwpmFilter0_layerKey_Offset)
+ return
+ }
+
+ offset = uintptr(unsafe.Pointer(&s.subLayerKey)) - sp
+
+ if offset != wtFwpmFilter0_subLayerKey_Offset {
+ t.Errorf("wtFwpmFilter0.subLayerKey offset is %d although %d is expected", offset,
+ wtFwpmFilter0_subLayerKey_Offset)
+ return
+ }
+
+ offset = uintptr(unsafe.Pointer(&s.weight)) - sp
+
+ if offset != wtFwpmFilter0_weight_Offset {
+ t.Errorf("wtFwpmFilter0.weight offset is %d although %d is expected", offset,
+ wtFwpmFilter0_weight_Offset)
+ return
+ }
+
+ offset = uintptr(unsafe.Pointer(&s.numFilterConditions)) - sp
+
+ if offset != wtFwpmFilter0_numFilterConditions_Offset {
+ t.Errorf("wtFwpmFilter0.numFilterConditions offset is %d although %d is expected", offset,
+ wtFwpmFilter0_numFilterConditions_Offset)
+ return
+ }
+
+ offset = uintptr(unsafe.Pointer(&s.filterCondition)) - sp
+
+ if offset != wtFwpmFilter0_filterCondition_Offset {
+ t.Errorf("wtFwpmFilter0.filterCondition offset is %d although %d is expected", offset,
+ wtFwpmFilter0_filterCondition_Offset)
+ return
+ }
+
+ offset = uintptr(unsafe.Pointer(&s.action)) - sp
+
+ if offset != wtFwpmFilter0_action_Offset {
+ t.Errorf("wtFwpmFilter0.action offset is %d although %d is expected", offset,
+ wtFwpmFilter0_action_Offset)
+ return
+ }
+
+ offset = uintptr(unsafe.Pointer(&s.providerContextKey)) - sp
+
+ if offset != wtFwpmFilter0_providerContextKey_Offset {
+ t.Errorf("wtFwpmFilter0.providerContextKey offset is %d although %d is expected", offset,
+ wtFwpmFilter0_providerContextKey_Offset)
+ return
+ }
+
+ offset = uintptr(unsafe.Pointer(&s.reserved)) - sp
+
+ if offset != wtFwpmFilter0_reserved_Offset {
+ t.Errorf("wtFwpmFilter0.reserved offset is %d although %d is expected", offset,
+ wtFwpmFilter0_reserved_Offset)
+ return
+ }
+
+ offset = uintptr(unsafe.Pointer(&s.filterId)) - sp
+
+ if offset != wtFwpmFilter0_filterId_Offset {
+ t.Errorf("wtFwpmFilter0.filterId offset is %d although %d is expected", offset,
+ wtFwpmFilter0_filterId_Offset)
+ return
+ }
+
+ offset = uintptr(unsafe.Pointer(&s.effectiveWeight)) - sp
+
+ if offset != wtFwpmFilter0_effectiveWeight_Offset {
+ t.Errorf("wtFwpmFilter0.effectiveWeight offset is %d although %d is expected", offset,
+ wtFwpmFilter0_effectiveWeight_Offset)
+ return
+ }
+}
+
+func TestWtFwpProvider0Size(t *testing.T) {
+
+ const actualWtFwpProvider0Size = unsafe.Sizeof(wtFwpProvider0{})
+
+ if actualWtFwpProvider0Size != wtFwpProvider0_Size {
+ t.Errorf("Size of wtFwpProvider0 is %d, although %d is expected.", actualWtFwpProvider0Size,
+ wtFwpProvider0_Size)
+ }
+}
+
+func TestWtFwpProvider0Offsets(t *testing.T) {
+
+ s := wtFwpProvider0{}
+ sp := uintptr(unsafe.Pointer(&s))
+
+ offset := uintptr(unsafe.Pointer(&s.displayData)) - sp
+
+ if offset != wtFwpProvider0_displayData_Offset {
+ t.Errorf("wtFwpProvider0.displayData offset is %d although %d is expected", offset,
+ wtFwpProvider0_displayData_Offset)
+ return
+ }
+
+ offset = uintptr(unsafe.Pointer(&s.flags)) - sp
+
+ if offset != wtFwpProvider0_flags_Offset {
+ t.Errorf("wtFwpProvider0.flags offset is %d although %d is expected", offset,
+ wtFwpProvider0_flags_Offset)
+ return
+ }
+
+ offset = uintptr(unsafe.Pointer(&s.providerData)) - sp
+
+ if offset != wtFwpProvider0_providerData_Offset {
+ t.Errorf("wtFwpProvider0.providerData offset is %d although %d is expected", offset,
+ wtFwpProvider0_providerData_Offset)
+ return
+ }
+
+ offset = uintptr(unsafe.Pointer(&s.serviceName)) - sp
+
+ if offset != wtFwpProvider0_serviceName_Offset {
+ t.Errorf("wtFwpProvider0.serviceName offset is %d although %d is expected", offset,
+ wtFwpProvider0_serviceName_Offset)
+ return
+ }
+}
+
+func TestWtFwpmSession0Size(t *testing.T) {
+
+ const actualWtFwpmSession0Size = unsafe.Sizeof(wtFwpmSession0{})
+
+ if actualWtFwpmSession0Size != wtFwpmSession0_Size {
+ t.Errorf("Size of wtFwpmSession0 is %d, although %d is expected.", actualWtFwpmSession0Size,
+ wtFwpmSession0_Size)
+ }
+}
+
+func TestWtFwpmSession0Offsets(t *testing.T) {
+
+ s := wtFwpmSession0{}
+ sp := uintptr(unsafe.Pointer(&s))
+
+ offset := uintptr(unsafe.Pointer(&s.displayData)) - sp
+
+ if offset != wtFwpmSession0_displayData_Offset {
+ t.Errorf("wtFwpmSession0.displayData offset is %d although %d is expected", offset,
+ wtFwpmSession0_displayData_Offset)
+ return
+ }
+
+ offset = uintptr(unsafe.Pointer(&s.flags)) - sp
+
+ if offset != wtFwpmSession0_flags_Offset {
+ t.Errorf("wtFwpmSession0.flags offset is %d although %d is expected", offset, wtFwpmSession0_flags_Offset)
+ return
+ }
+
+ offset = uintptr(unsafe.Pointer(&s.txnWaitTimeoutInMSec)) - sp
+
+ if offset != wtFwpmSession0_txnWaitTimeoutInMSec_Offset {
+ t.Errorf("wtFwpmSession0.txnWaitTimeoutInMSec offset is %d although %d is expected", offset,
+ wtFwpmSession0_txnWaitTimeoutInMSec_Offset)
+ return
+ }
+
+ offset = uintptr(unsafe.Pointer(&s.processId)) - sp
+
+ if offset != wtFwpmSession0_processId_Offset {
+ t.Errorf("wtFwpmSession0.processId offset is %d although %d is expected", offset,
+ wtFwpmSession0_processId_Offset)
+ return
+ }
+
+ offset = uintptr(unsafe.Pointer(&s.sid)) - sp
+
+ if offset != wtFwpmSession0_sid_Offset {
+ t.Errorf("wtFwpmSession0.sid offset is %d although %d is expected", offset, wtFwpmSession0_sid_Offset)
+ return
+ }
+
+ offset = uintptr(unsafe.Pointer(&s.username)) - sp
+
+ if offset != wtFwpmSession0_username_Offset {
+ t.Errorf("wtFwpmSession0.username offset is %d although %d is expected", offset,
+ wtFwpmSession0_username_Offset)
+ return
+ }
+
+ offset = uintptr(unsafe.Pointer(&s.kernelMode)) - sp
+
+ if offset != wtFwpmSession0_kernelMode_Offset {
+ t.Errorf("wtFwpmSession0.kernelMode offset is %d although %d is expected", offset,
+ wtFwpmSession0_kernelMode_Offset)
+ return
+ }
+}
+
+func TestWtFwpmSublayer0Size(t *testing.T) {
+
+ const actualWtFwpmSublayer0Size = unsafe.Sizeof(wtFwpmSublayer0{})
+
+ if actualWtFwpmSublayer0Size != wtFwpmSublayer0_Size {
+ t.Errorf("Size of wtFwpmSublayer0 is %d, although %d is expected.", actualWtFwpmSublayer0Size,
+ wtFwpmSublayer0_Size)
+ }
+}
+
+func TestWtFwpmSublayer0Offsets(t *testing.T) {
+
+ s := wtFwpmSublayer0{}
+ sp := uintptr(unsafe.Pointer(&s))
+
+ offset := uintptr(unsafe.Pointer(&s.displayData)) - sp
+
+ if offset != wtFwpmSublayer0_displayData_Offset {
+ t.Errorf("wtFwpmSublayer0.displayData offset is %d although %d is expected", offset,
+ wtFwpmSublayer0_displayData_Offset)
+ return
+ }
+
+ offset = uintptr(unsafe.Pointer(&s.flags)) - sp
+
+ if offset != wtFwpmSublayer0_flags_Offset {
+ t.Errorf("wtFwpmSublayer0.flags offset is %d although %d is expected", offset,
+ wtFwpmSublayer0_flags_Offset)
+ return
+ }
+
+ offset = uintptr(unsafe.Pointer(&s.providerKey)) - sp
+
+ if offset != wtFwpmSublayer0_providerKey_Offset {
+ t.Errorf("wtFwpmSublayer0.providerKey offset is %d although %d is expected", offset,
+ wtFwpmSublayer0_providerKey_Offset)
+ return
+ }
+
+ offset = uintptr(unsafe.Pointer(&s.providerData)) - sp
+
+ if offset != wtFwpmSublayer0_providerData_Offset {
+ t.Errorf("wtFwpmSublayer0.providerData offset is %d although %d is expected", offset,
+ wtFwpmSublayer0_providerData_Offset)
+ return
+ }
+
+ offset = uintptr(unsafe.Pointer(&s.weight)) - sp
+
+ if offset != wtFwpmSublayer0_weight_Offset {
+ t.Errorf("wtFwpmSublayer0.weight offset is %d although %d is expected", offset,
+ wtFwpmSublayer0_weight_Offset)
+ return
+ }
+}
+
+func TestWtSecWinntAuthIdentityWSize(t *testing.T) {
+
+ const actualWtSecWinntAuthIdentityWSize = unsafe.Sizeof(wtSecWinntAuthIdentityW{})
+
+ if actualWtSecWinntAuthIdentityWSize != wtSecWinntAuthIdentityW_Size {
+ t.Errorf("Size of wtSecWinntAuthIdentityW is %d, although %d is expected.",
+ actualWtSecWinntAuthIdentityWSize, wtSecWinntAuthIdentityW_Size)
+ }
+}
+
+func TestWtSecWinntAuthIdentityWOffsets(t *testing.T) {
+
+ s := wtSecWinntAuthIdentityW{}
+ sp := uintptr(unsafe.Pointer(&s))
+
+ offset := uintptr(unsafe.Pointer(&s.UserLength)) - sp
+
+ if offset != wtSecWinntAuthIdentityW_UserLength_Offset {
+ t.Errorf("wtSecWinntAuthIdentityW.UserLength offset is %d although %d is expected", offset,
+ wtSecWinntAuthIdentityW_UserLength_Offset)
+ return
+ }
+
+ offset = uintptr(unsafe.Pointer(&s.Domain)) - sp
+
+ if offset != wtSecWinntAuthIdentityW_Domain_Offset {
+ t.Errorf("wtSecWinntAuthIdentityW.Domain offset is %d although %d is expected", offset,
+ wtSecWinntAuthIdentityW_Domain_Offset)
+ return
+ }
+
+ offset = uintptr(unsafe.Pointer(&s.DomainLength)) - sp
+
+ if offset != wtSecWinntAuthIdentityW_DomainLength_Offset {
+ t.Errorf("wtSecWinntAuthIdentityW.DomainLength offset is %d although %d is expected", offset,
+ wtSecWinntAuthIdentityW_DomainLength_Offset)
+ return
+ }
+
+ offset = uintptr(unsafe.Pointer(&s.Password)) - sp
+
+ if offset != wtSecWinntAuthIdentityW_Password_Offset {
+ t.Errorf("wtSecWinntAuthIdentityW.Password offset is %d although %d is expected", offset,
+ wtSecWinntAuthIdentityW_Password_Offset)
+ return
+ }
+
+ offset = uintptr(unsafe.Pointer(&s.PasswordLength)) - sp
+
+ if offset != wtSecWinntAuthIdentityW_PasswordLength_Offset {
+ t.Errorf("wtSecWinntAuthIdentityW.PasswordLength offset is %d although %d is expected", offset,
+ wtSecWinntAuthIdentityW_PasswordLength_Offset)
+ return
+ }
+
+ offset = uintptr(unsafe.Pointer(&s.Flags)) - sp
+
+ if offset != wtSecWinntAuthIdentityW_Flags_Offset {
+ t.Errorf("wtSecWinntAuthIdentityW.Flags offset is %d although %d is expected", offset,
+ wtSecWinntAuthIdentityW_Flags_Offset)
+ return
+ }
+}
diff --git a/service/firewall/zsyscall_windows.go b/service/firewall/zsyscall_windows.go
new file mode 100644
index 00000000..badbacb5
--- /dev/null
+++ b/service/firewall/zsyscall_windows.go
@@ -0,0 +1,179 @@
+// Code generated by 'go generate'; DO NOT EDIT.
+
+package firewall
+
+import (
+ "syscall"
+ "unsafe"
+
+ "golang.org/x/sys/windows"
+)
+
+var _ unsafe.Pointer
+
+// Do the interface allocations only once for common
+// Errno values.
+const (
+ errnoERROR_IO_PENDING = 997
+)
+
+var (
+ errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
+)
+
+// errnoErr returns common boxed Errno values, to prevent
+// allocations at runtime.
+func errnoErr(e syscall.Errno) error {
+ switch e {
+ case 0:
+ return nil
+ case errnoERROR_IO_PENDING:
+ return errERROR_IO_PENDING
+ }
+ // TODO: add more here, after collecting data on the common
+ // error values see on Windows. (perhaps when running
+ // all.bat?)
+ return e
+}
+
+var (
+ modfwpuclnt = windows.NewLazySystemDLL("fwpuclnt.dll")
+ modadvapi32 = windows.NewLazySystemDLL("advapi32.dll")
+
+ procFwpmEngineOpen0 = modfwpuclnt.NewProc("FwpmEngineOpen0")
+ procFwpmEngineClose0 = modfwpuclnt.NewProc("FwpmEngineClose0")
+ procFwpmSubLayerAdd0 = modfwpuclnt.NewProc("FwpmSubLayerAdd0")
+ procFwpmGetAppIdFromFileName0 = modfwpuclnt.NewProc("FwpmGetAppIdFromFileName0")
+ procFwpmFreeMemory0 = modfwpuclnt.NewProc("FwpmFreeMemory0")
+ procFwpmFilterAdd0 = modfwpuclnt.NewProc("FwpmFilterAdd0")
+ procFwpmTransactionBegin0 = modfwpuclnt.NewProc("FwpmTransactionBegin0")
+ procFwpmTransactionCommit0 = modfwpuclnt.NewProc("FwpmTransactionCommit0")
+ procFwpmTransactionAbort0 = modfwpuclnt.NewProc("FwpmTransactionAbort0")
+ procFwpmProviderAdd0 = modfwpuclnt.NewProc("FwpmProviderAdd0")
+ procGetSecurityInfo = modadvapi32.NewProc("GetSecurityInfo")
+)
+
+func fwpmEngineOpen0(serverName *uint16, authnService wtRpcCAuthN, authIdentity *wtSecWinntAuthIdentityW, session *wtFwpmSession0, engineHandle unsafe.Pointer) (err error) {
+ r1, _, e1 := syscall.Syscall6(procFwpmEngineOpen0.Addr(), 5, uintptr(unsafe.Pointer(serverName)), uintptr(authnService), uintptr(unsafe.Pointer(authIdentity)), uintptr(unsafe.Pointer(session)), uintptr(engineHandle), 0)
+ if r1 != 0 {
+ if e1 != 0 {
+ err = errnoErr(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func fwpmEngineClose0(engineHandle uintptr) (err error) {
+ r1, _, e1 := syscall.Syscall(procFwpmEngineClose0.Addr(), 1, uintptr(engineHandle), 0, 0)
+ if r1 != 0 {
+ if e1 != 0 {
+ err = errnoErr(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func fwpmSubLayerAdd0(engineHandle uintptr, subLayer *wtFwpmSublayer0, sd uintptr) (err error) {
+ r1, _, e1 := syscall.Syscall(procFwpmSubLayerAdd0.Addr(), 3, uintptr(engineHandle), uintptr(unsafe.Pointer(subLayer)), uintptr(sd))
+ if r1 != 0 {
+ if e1 != 0 {
+ err = errnoErr(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func fwpmGetAppIdFromFileName0(fileName *uint16, appId unsafe.Pointer) (err error) {
+ r1, _, e1 := syscall.Syscall(procFwpmGetAppIdFromFileName0.Addr(), 2, uintptr(unsafe.Pointer(fileName)), uintptr(appId), 0)
+ if r1 != 0 {
+ if e1 != 0 {
+ err = errnoErr(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func fwpmFreeMemory0(p unsafe.Pointer) {
+ syscall.Syscall(procFwpmFreeMemory0.Addr(), 1, uintptr(p), 0, 0)
+ return
+}
+
+func fwpmFilterAdd0(engineHandle uintptr, filter *wtFwpmFilter0, sd uintptr, id *uint64) (err error) {
+ r1, _, e1 := syscall.Syscall6(procFwpmFilterAdd0.Addr(), 4, uintptr(engineHandle), uintptr(unsafe.Pointer(filter)), uintptr(sd), uintptr(unsafe.Pointer(id)), 0, 0)
+ if r1 != 0 {
+ if e1 != 0 {
+ err = errnoErr(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func fwpmTransactionBegin0(engineHandle uintptr, flags uint32) (err error) {
+ r1, _, e1 := syscall.Syscall(procFwpmTransactionBegin0.Addr(), 2, uintptr(engineHandle), uintptr(flags), 0)
+ if r1 != 0 {
+ if e1 != 0 {
+ err = errnoErr(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func fwpmTransactionCommit0(engineHandle uintptr) (err error) {
+ r1, _, e1 := syscall.Syscall(procFwpmTransactionCommit0.Addr(), 1, uintptr(engineHandle), 0, 0)
+ if r1 != 0 {
+ if e1 != 0 {
+ err = errnoErr(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func fwpmTransactionAbort0(engineHandle uintptr) (err error) {
+ r1, _, e1 := syscall.Syscall(procFwpmTransactionAbort0.Addr(), 1, uintptr(engineHandle), 0, 0)
+ if r1 != 0 {
+ if e1 != 0 {
+ err = errnoErr(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func fwpmProviderAdd0(engineHandle uintptr, provider *wtFwpmProvider0, sd uintptr) (err error) {
+ r1, _, e1 := syscall.Syscall(procFwpmProviderAdd0.Addr(), 3, uintptr(engineHandle), uintptr(unsafe.Pointer(provider)), uintptr(sd))
+ if r1 != 0 {
+ if e1 != 0 {
+ err = errnoErr(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func getSecurityInfo(handle windows.Handle, objectType wtObjectType, si uint32, sidOwner *windows.SID, sidGroup *windows.SID, dacl *uintptr, sacl *uintptr, securityDescriptor *uintptr) (err error) {
+ r1, _, e1 := syscall.Syscall9(procGetSecurityInfo.Addr(), 8, uintptr(handle), uintptr(objectType), uintptr(si), uintptr(unsafe.Pointer(sidOwner)), uintptr(unsafe.Pointer(sidGroup)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(sacl)), uintptr(unsafe.Pointer(securityDescriptor)), 0)
+ if r1 != 0 {
+ if e1 != 0 {
+ err = errnoErr(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}