diff --git a/firewall/interception/windivert/handler.go b/firewall/interception/windivert/handler.go deleted file mode 100644 index cbf890ac..00000000 --- a/firewall/interception/windivert/handler.go +++ /dev/null @@ -1,154 +0,0 @@ -package windivert - -import ( - "errors" - "fmt" - - "github.com/google/gopacket" - "github.com/google/gopacket/layers" - - "github.com/Safing/safing-core/log" - "github.com/Safing/safing-core/network/packet" - - "github.com/tevino/abool" -) - -func (wd *WinDivert) Packets(packets chan packet.Packet) error { - go wd.packetHandler(packets) - return nil -} - -func (wd *WinDivert) packetHandler(packets chan packet.Packet) { - defer close(packets) - - for { - if !wd.valid.IsSet() { - return - } - - packetData, packetAddress, err := wd.Recv() - if err != nil { - log.Warningf("failed to get packet from windivert: %s", err) - continue - } - - ipHeader, tpcUdpHeader, payload, err := parseIpPacket(packetData) - if err != nil { - log.Warningf("failed to parse packet from windivert: %s", err) - log.Warningf("failed packet payload (%d): %s", len(packetData), string(packetData)) - continue - } - - new := &Packet{ - windivert: wd, - packetData: packetData, - packetAddress: packetAddress, - verdictSet: abool.NewBool(false), - } - new.IPHeader = ipHeader - new.TCPUDPHeader = tpcUdpHeader - new.Payload = payload - if packetAddress.Direction == directionInbound { - new.Direction = packet.InBound - } else { - new.Direction = packet.OutBound - } - - packets <- new - } -} - -func parseIpPacket(packetData []byte) (ipHeader *packet.IPHeader, tpcUdpHeader *packet.TCPUDPHeader, payload []byte, err error) { - - var parsedPacket gopacket.Packet - - if len(packetData) == 0 { - return nil, nil, nil, errors.New("empty packet") - } - - switch packetData[0] >> 4 { - case 4: - parsedPacket = gopacket.NewPacket(packetData, layers.LayerTypeIPv4, gopacket.DecodeOptions{Lazy: true, NoCopy: true}) - if ipv4Layer := parsedPacket.Layer(layers.LayerTypeIPv4); ipv4Layer != nil { - ipv4, _ := ipv4Layer.(*layers.IPv4) - ipHeader = &packet.IPHeader{ - Version: 4, - Protocol: packet.IPProtocol(ipv4.Protocol), - Tos: ipv4.TOS, - TTL: ipv4.TTL, - Src: ipv4.SrcIP, - Dst: ipv4.DstIP, - } - } else { - var err error - if errLayer := parsedPacket.ErrorLayer(); errLayer != nil { - err = errLayer.Error() - } - return nil, nil, nil, fmt.Errorf("failed to parse IPv4 packet: %s", err) - } - case 6: - parsedPacket = gopacket.NewPacket(packetData, layers.LayerTypeIPv6, gopacket.DecodeOptions{Lazy: true, NoCopy: true}) - if ipv6Layer := parsedPacket.Layer(layers.LayerTypeIPv6); ipv6Layer != nil { - ipv6, _ := ipv6Layer.(*layers.IPv6) - ipHeader = &packet.IPHeader{ - Version: 6, - Protocol: packet.IPProtocol(ipv6.NextHeader), - Tos: ipv6.TrafficClass, - TTL: ipv6.HopLimit, - Src: ipv6.SrcIP, - Dst: ipv6.DstIP, - } - } else { - var err error - if errLayer := parsedPacket.ErrorLayer(); errLayer != nil { - err = errLayer.Error() - } - return nil, nil, nil, fmt.Errorf("failed to parse IPv6 packet: %s", err) - } - default: - return nil, nil, nil, errors.New("unknown IP version") - } - - switch ipHeader.Protocol { - case packet.TCP: - if tcpLayer := parsedPacket.Layer(layers.LayerTypeTCP); tcpLayer != nil { - tcp, _ := tcpLayer.(*layers.TCP) - tpcUdpHeader = &packet.TCPUDPHeader{ - SrcPort: uint16(tcp.SrcPort), - DstPort: uint16(tcp.DstPort), - Checksum: tcp.Checksum, - } - } else { - var err error - if errLayer := parsedPacket.ErrorLayer(); errLayer != nil { - err = errLayer.Error() - } - return nil, nil, nil, fmt.Errorf("could not parse TCP layer: %s", err) - } - case packet.UDP: - if udpLayer := parsedPacket.Layer(layers.LayerTypeUDP); udpLayer != nil { - udp, _ := udpLayer.(*layers.UDP) - tpcUdpHeader = &packet.TCPUDPHeader{ - SrcPort: uint16(udp.SrcPort), - DstPort: uint16(udp.DstPort), - Checksum: udp.Checksum, - } - } else { - var err error - if errLayer := parsedPacket.ErrorLayer(); errLayer != nil { - err = errLayer.Error() - } - return nil, nil, nil, fmt.Errorf("could not parse UDP layer: %s", err) - } - } - - if appLayer := parsedPacket.ApplicationLayer(); appLayer != nil { - payload = appLayer.Payload() - } - - if errLayer := parsedPacket.ErrorLayer(); errLayer != nil { - return nil, nil, nil, errLayer.Error() - } - - return -} diff --git a/firewall/interception/windivert/notes.md b/firewall/interception/windivert/notes.md deleted file mode 100644 index 8074f4ea..00000000 --- a/firewall/interception/windivert/notes.md +++ /dev/null @@ -1,32 +0,0 @@ -# Notes - -## Interception - -- use windivert DLL -- cgo or loadDLL? - -- netfilter exmaple: https://reqrypt.org/samples/netfilter.html -- v1.4 docs: https://reqrypt.org/windivert-doc.html#divert_recv_ex -- source: https://github.com/basil00/Divert - -- other GO package wrapping this: https://github.com/clmul/go-windivert/blob/master/divert_windows.go - -## Packet/Process Attribution - -- use Iphlpapi.dll - - GetExtendedTcpTable - - GetOwnerModuleFromTcpEntry - - GetExtendedUdpTable - - GetOwnerModuleFromUdpEntry - - for generic IP? - -## Helpful resources - -Calling Windows APIs -https://stackoverflow.com/questions/33709033/golang-how-can-i-call-win32-api-without-cgo#33709631 - -GetExtendedTcpTable (from Iphlpapi.dll) -https://msdn.microsoft.com/en-us/library/windows/desktop/aa365928(v=vs.85).aspx - -GetUdpTable Example -https://stackoverflow.com/questions/49167311/how-to-convert-uintptr-to-go-struct diff --git a/firewall/interception/windivert/packet.go b/firewall/interception/windivert/packet.go deleted file mode 100644 index 80dfd6f0..00000000 --- a/firewall/interception/windivert/packet.go +++ /dev/null @@ -1,55 +0,0 @@ -package windivert - -import ( - "github.com/Safing/safing-core/network/packet" - "github.com/tevino/abool" -) - -type Packet struct { - packet.PacketBase - - windivert *WinDivert - packetData []byte - packetAddress *WinDivertAddress - - verdictSet *abool.AtomicBool -} - -func (pkt *Packet) Accept() error { - if pkt.verdictSet.SetToIf(false, true) { - return pkt.windivert.Send(pkt.packetData, pkt.packetAddress) - } - return nil -} - -func (pkt *Packet) Block() error { - if pkt.verdictSet.SetToIf(false, true) { - // TODO: implement blocking mechanism - return nil - } - return nil -} - -func (pkt *Packet) Drop() error { - return nil -} - -func (pkt *Packet) PermanentAccept() error { - return pkt.Accept() -} - -func (pkt *Packet) PermanentBlock() error { - return pkt.Block() -} - -func (pkt *Packet) PermanentDrop() error { - return pkt.Drop() -} - -func (pkt *Packet) RerouteToNameserver() error { - return nil -} - -func (pkt *Packet) RerouteToTunnel() error { - return nil -} diff --git a/firewall/interception/windivert/test/build b/firewall/interception/windivert/test/build deleted file mode 100644 index 38994f5e..00000000 --- a/firewall/interception/windivert/test/build +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/bash - -# get build data -if [[ "$BUILD_COMMIT" == "" ]]; then - BUILD_COMMIT=$(git describe --all --long --abbrev=99 --dirty 2>/dev/null) -fi -if [[ "$BUILD_USER" == "" ]]; then - BUILD_USER=$(id -un) -fi -if [[ "$BUILD_HOST" == "" ]]; then - BUILD_HOST=$(hostname -f) -fi -if [[ "$BUILD_DATE" == "" ]]; then - BUILD_DATE=$(date +%d.%m.%Y) -fi -if [[ "$BUILD_SOURCE" == "" ]]; then - BUILD_SOURCE=$(git remote -v | grep origin | cut -f2 | cut -d" " -f1 | head -n 1) -fi -if [[ "$BUILD_SOURCE" == "" ]]; then - BUILD_SOURCE=$(git remote -v | cut -f2 | cut -d" " -f1 | head -n 1) -fi -BUILD_BUILDOPTIONS=$(echo $* | sed "s/ /ยง/g") - -# check -if [[ "$BUILD_COMMIT" == "" ]]; then - echo "could not automatically determine BUILD_COMMIT, please supply manually as environment variable." - exit 1 -fi -if [[ "$BUILD_USER" == "" ]]; then - echo "could not automatically determine BUILD_USER, please supply manually as environment variable." - exit 1 -fi -if [[ "$BUILD_HOST" == "" ]]; then - echo "could not automatically determine BUILD_HOST, please supply manually as environment variable." - exit 1 -fi -if [[ "$BUILD_DATE" == "" ]]; then - echo "could not automatically determine BUILD_DATE, please supply manually as environment variable." - exit 1 -fi -if [[ "$BUILD_SOURCE" == "" ]]; then - echo "could not automatically determine BUILD_SOURCE, please supply manually as environment variable." - exit 1 -fi - -echo "Please notice, that this build script includes metadata into the build." -echo "This information is useful for debugging and license compliance." -echo "Run the compiled binary with the -v flag to see the information included." - -# build -if [[ "$BUILD_PATH" == "" ]]; then - BUILD_PATH=$(go list) -fi -go build -ldflags "-X ${BUILD_PATH}/meta.commit=${BUILD_COMMIT} -X ${BUILD_PATH}/meta.buildOptions=${BUILD_BUILDOPTIONS} -X ${BUILD_PATH}/meta.buildUser=${BUILD_USER} -X ${BUILD_PATH}/meta.buildHost=${BUILD_HOST} -X ${BUILD_PATH}/meta.buildDate=${BUILD_DATE} -X ${BUILD_PATH}/meta.buildSource=${BUILD_SOURCE}" $* diff --git a/firewall/interception/windivert/test/main.go b/firewall/interception/windivert/test/main.go deleted file mode 100644 index 0c75fcce..00000000 --- a/firewall/interception/windivert/test/main.go +++ /dev/null @@ -1,66 +0,0 @@ -package main - -import ( - "fmt" - "os" - "os/signal" - "runtime/pprof" - "syscall" - "time" - - "github.com/Safing/safing-core/firewall/interception/windivert" - "github.com/Safing/safing-core/log" - "github.com/Safing/safing-core/modules" - "github.com/Safing/safing-core/network/packet" -) - -func main() { - modules.RegisterLogger(log.Logger) - - wd, err := windivert.New("C:/WinDivert.dll", "") - if err != nil { - panic(err) - } - defer wd.Close() - - packets := make(chan packet.Packet, 1000) - wd.Packets(packets) - go func() { - for pkt := range packets { - log.Infof("pkt: %s", pkt) - if pkt.GetIPHeader().Protocol == 0 || pkt.GetIPHeader().Protocol == 128 { - pl := pkt.GetPayload() - log.Infof("payload (%d): %s", len(pl), string(pl)) - } - pkt.Accept() - } - }() - - // SHUTDOWN - // catch interrupt for clean shutdown - signalCh := make(chan os.Signal) - signal.Notify( - signalCh, - os.Interrupt, - os.Kill, - syscall.SIGHUP, - syscall.SIGINT, - syscall.SIGTERM, - syscall.SIGQUIT, - syscall.SIGKILL, - syscall.SIGSEGV, - ) - select { - case <-signalCh: - log.Warning("program was interrupted, shutting down.") - modules.InitiateFullShutdown() - case <-modules.GlobalShutdown: - } - - // wait for shutdown to complete, panic after timeout - time.Sleep(5 * time.Second) - fmt.Println("===== TAKING TOO LONG FOR SHUTDOWN - PRINTING STACK TRACES =====") - pprof.Lookup("goroutine").WriteTo(os.Stdout, 1) - os.Exit(1) - -} diff --git a/firewall/interception/windivert/windivert.go b/firewall/interception/windivert/windivert.go deleted file mode 100644 index 2c931692..00000000 --- a/firewall/interception/windivert/windivert.go +++ /dev/null @@ -1,248 +0,0 @@ -package windivert - -import ( - "errors" - "fmt" - "strings" - "unsafe" - - "golang.org/x/sys/windows" - - "github.com/tevino/abool" -) - -type WinDivert struct { - dll *windows.DLL - handle uintptr - - open *windows.Proc - recv *windows.Proc - send *windows.Proc - close *windows.Proc - setParam *windows.Proc - getParam *windows.Proc - helperCalcChecksums *windows.Proc - helperCheckFilter *windows.Proc - - valid *abool.AtomicBool -} - -// copied from windivert.h -type WinDivertAddress struct { - Timestamp int64 /* Packet's timestamp. */ - IfIdx uint32 /* Packet's interface index. */ - SubIfIdx uint32 /* Packet's sub-interface index. */ - Direction uint8 /* Packet's direction. */ - Loopback uint8 /* Packet is loopback? */ - Impostor uint8 /* Packet is impostor? */ - PseudoIPChecksum uint8 /* Packet has pseudo IPv4 checksum? */ - PseudoTCPChecksum uint8 /* Packet has pseudo TCP checksum? */ - PseudoUDPChecksum uint8 /* Packet has pseudo UDP checksum? */ - Reserved uint8 -} - -// copied from windivert.h -const ( - directionInbound uint8 = 1 - directionOutbound uint8 = 0 - - // Divert layers - layerNetwork uintptr = 0 /* Network layer. */ - layerNetworkForward uintptr = 1 /* Network layer (forwarded packets) */ - - // Divert parameters - flagSniff uintptr = 1 - flagDrop uintptr = 2 - flagDebug uintptr = 4 - - paramQueueLen uintptr = 0 /* Packet queue length. */ - paramQueueTime uintptr = 1 /* Packet queue time. */ - paramQueueSize uintptr = 2 /* Packet queue size. */ - - rvInvalidHandle int = -1 - rvFalse uintptr = 0 - rvTrue uintptr = 1 -) - -func New(dllLocation, filter string) (*WinDivert, error) { - - new := &WinDivert{} - var err error - - // load dll - new.dll, err = windows.LoadDLL(dllLocation) - if err != nil { - return nil, err - } - - // load functions - new.open, err = new.dll.FindProc("WinDivertOpen") - if err != nil { - return nil, fmt.Errorf("could not find proc WinDivertOpen: %s", err) - } - new.recv, err = new.dll.FindProc("WinDivertRecv") - if err != nil { - return nil, fmt.Errorf("could not find proc WinDivertRecv: %s", err) - } - new.send, err = new.dll.FindProc("WinDivertSend") - if err != nil { - return nil, fmt.Errorf("could not find proc WinDivertSend: %s", err) - } - new.close, err = new.dll.FindProc("WinDivertClose") - if err != nil { - return nil, fmt.Errorf("could not find proc WinDivertClose: %s", err) - } - new.setParam, err = new.dll.FindProc("WinDivertSetParam") - if err != nil { - return nil, fmt.Errorf("could not find proc WinDivertSetParam: %s", err) - } - new.getParam, err = new.dll.FindProc("WinDivertGetParam") - if err != nil { - return nil, fmt.Errorf("could not find proc WinDivertGetParam: %s", err) - } - new.helperCalcChecksums, err = new.dll.FindProc("WinDivertHelperCalcChecksums") - if err != nil { - return nil, fmt.Errorf("could not find proc WinDivertHelperCalcChecksums: %s", err) - } - new.helperCheckFilter, err = new.dll.FindProc("WinDivertHelperCheckFilter") - if err != nil { - return nil, fmt.Errorf("could not find proc WinDivertHelperCheckFilter: %s", err) - } - - // default filter - if filter == "" { - filter = "true" - } - - // open - err = new.Open(filter) - if err != nil { - return nil, fmt.Errorf("could not open new windivert handle: %s", err) - } - - return new, nil - -} - -func (wd *WinDivert) Open(filter string) error { - - r1, _, lastErr := wd.open.Call( - stringToPtr(filter), // __in const char *filter - layerNetwork, // __in WINDIVERT_LAYER layer - 0, // __in INT16 priority - 0, // __in UINT64 flags - ) - if int(r1) == rvInvalidHandle { - return lastErr - } - - wd.handle = r1 - wd.valid = abool.NewBool(true) - return nil -} - -func (wd *WinDivert) Recv() ([]byte, *WinDivertAddress, error) { - buf := make([]byte, 4096) // TODO: we can do this better - address := &WinDivertAddress{} - readLen := 0 - - r1, _, lastErr := wd.recv.Call( - wd.handle, // __in HANDLE handle - byteSliceToPtr(buf), // __out PVOID pPacket - uintptr(len(buf)), // __in UINT packetLen - uintptr(unsafe.Pointer(address)), // __out_opt PWINDIVERT_ADDRESS pAddr - uintptr(unsafe.Pointer(&readLen)), // __out_opt UINT *readLen - ) - if r1 == rvFalse { - return nil, nil, lastErr - } - if readLen == 0 { - return nil, nil, errors.New("empty read") - } - - return buf[:readLen], address, nil -} - -func (wd *WinDivert) Send(packetData []byte, address *WinDivertAddress) error { - writeLen := 0 - - r1, _, lastErr := wd.send.Call( - wd.handle, // __in HANDLE handle - byteSliceToPtr(packetData), // __in PVOID pPacket - uintptr(len(packetData)), // __in UINT packetLen - uintptr(unsafe.Pointer(address)), // __in PWINDIVERT_ADDRESS pAddr - uintptr(unsafe.Pointer(&writeLen)), // __out_opt UINT *writeLen - ) - if r1 == rvFalse { - return lastErr - } - return nil -} - -func (wd *WinDivert) Close() error { - r1, _, lastErr := wd.close.Call( - wd.handle, // __in HANDLE handle - ) - if r1 == rvFalse { - return lastErr - } - return nil -} - -func (wd *WinDivert) SetParam(param, value uintptr) error { - r1, _, lastErr := wd.setParam.Call( - wd.handle, // __in HANDLE handle - param, // __in WINDIVERT_PARAM param - value, // __in UINT64 value - ) - if r1 == rvFalse { - return lastErr - } - return nil -} - -func (wd *WinDivert) GetParam(param uintptr) (uint64, error) { - var value uint64 - - r1, _, lastErr := wd.getParam.Call( - wd.handle, // __in HANDLE handle - param, // __in WINDIVERT_PARAM param - uintptr(unsafe.Pointer(&value)), // __out UINT64 *pValue - ) - if r1 == rvFalse { - return 0, lastErr - } - return value, nil -} - -func (wd *WinDivert) HelperCalcChecksums(packetData []byte, address *WinDivertAddress, flags uintptr) error { - r1, _, lastErr := wd.setParam.Call( - byteSliceToPtr(packetData), // __inout PVOID pPacket - uintptr(len(packetData)), // __in UINT packetLen - uintptr(unsafe.Pointer(address)), // __in_opt PWINDIVERT_ADDRESS pAddr - flags, // __in UINT64 flags - ) - if r1 == rvFalse { - return lastErr - } - return nil -} - -// func (wd *WinDivert) HelperCheckFilter() { -// // __in const char *filter -// // __in WINDIVERT_LAYER layer -// // __out_opt const char **errorStr -// // __out_opt UINT *errorPos -// } - -func stringToPtr(s string) uintptr { - if !strings.HasSuffix(s, "\x00") { - s = s + "\x00" - } - a := []byte(s) - return uintptr(unsafe.Pointer(&a[0])) -} - -func byteSliceToPtr(a []byte) uintptr { - return uintptr(unsafe.Pointer(&a[0])) -} diff --git a/firewall/interception/windivert/windivert.h b/firewall/interception/windivert/windivert.h deleted file mode 100644 index 6f344fa7..00000000 --- a/firewall/interception/windivert/windivert.h +++ /dev/null @@ -1,410 +0,0 @@ -/* - * windivert.h - * (C) 2018, all rights reserved, - * - * This file is part of WinDivert. - * - * WinDivert is free software: you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License as published by the - * Free Software Foundation, either version 3 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - * - * WinDivert is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., 51 - * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __WINDIVERT_H -#define __WINDIVERT_H - -#ifndef WINDIVERT_KERNEL -#include -#endif /* WINDIVERT_KERNEL */ - -#ifndef WINDIVERTEXPORT -#define WINDIVERTEXPORT __declspec(dllimport) -#endif /* WINDIVERTEXPORT */ - -#ifdef __MINGW32__ -#define __in -#define __in_opt -#define __out -#define __out_opt -#define __inout -#define __inout_opt -#include -#define INT8 int8_t -#define UINT8 uint8_t -#define INT16 int16_t -#define UINT16 uint16_t -#define INT32 int32_t -#define UINT32 uint32_t -#define INT64 int64_t -#define UINT64 uint64_t -#endif /* __MINGW32__ */ - -#ifdef __cplusplus -extern "C" { -#endif - -/****************************************************************************/ -/* WINDIVERT API */ -/****************************************************************************/ - -/* - * Divert address. - */ -typedef struct -{ - INT64 Timestamp; /* Packet's timestamp. */ - UINT32 IfIdx; /* Packet's interface index. */ - UINT32 SubIfIdx; /* Packet's sub-interface index. */ - UINT8 Direction:1; /* Packet's direction. */ - UINT8 Loopback:1; /* Packet is loopback? */ - UINT8 Impostor:1; /* Packet is impostor? */ - UINT8 PseudoIPChecksum:1; /* Packet has pseudo IPv4 checksum? */ - UINT8 PseudoTCPChecksum:1; /* Packet has pseudo TCP checksum? */ - UINT8 PseudoUDPChecksum:1; /* Packet has pseudo UDP checksum? */ - UINT8 Reserved:2; -} WINDIVERT_ADDRESS, *PWINDIVERT_ADDRESS; - -#define WINDIVERT_DIRECTION_OUTBOUND 0 -#define WINDIVERT_DIRECTION_INBOUND 1 - -/* - * Divert layers. - */ -typedef enum -{ - WINDIVERT_LAYER_NETWORK = 0, /* Network layer. */ - WINDIVERT_LAYER_NETWORK_FORWARD = 1 /* Network layer (forwarded packets) */ -} WINDIVERT_LAYER, *PWINDIVERT_LAYER; - -/* - * Divert flags. - */ -#define WINDIVERT_FLAG_SNIFF 1 -#define WINDIVERT_FLAG_DROP 2 -#define WINDIVERT_FLAG_DEBUG 4 - -/* - * Divert parameters. - */ -typedef enum -{ - WINDIVERT_PARAM_QUEUE_LEN = 0, /* Packet queue length. */ - WINDIVERT_PARAM_QUEUE_TIME = 1, /* Packet queue time. */ - WINDIVERT_PARAM_QUEUE_SIZE = 2 /* Packet queue size. */ -} WINDIVERT_PARAM, *PWINDIVERT_PARAM; -#define WINDIVERT_PARAM_MAX WINDIVERT_PARAM_QUEUE_SIZE - -#ifndef WINDIVERT_KERNEL - -/* - * Open a WinDivert handle. - */ -extern WINDIVERTEXPORT HANDLE WinDivertOpen( - __in const char *filter, - __in WINDIVERT_LAYER layer, - __in INT16 priority, - __in UINT64 flags); - -/* - * Receive (read) a packet from a WinDivert handle. - */ -extern WINDIVERTEXPORT BOOL WinDivertRecv( - __in HANDLE handle, - __out PVOID pPacket, - __in UINT packetLen, - __out_opt PWINDIVERT_ADDRESS pAddr, - __out_opt UINT *readLen); - -/* - * Receive (read) a packet from a WinDivert handle. - */ -extern WINDIVERTEXPORT BOOL WinDivertRecvEx( - __in HANDLE handle, - __out PVOID pPacket, - __in UINT packetLen, - __in UINT64 flags, - __out_opt PWINDIVERT_ADDRESS pAddr, - __out_opt UINT *readLen, - __inout_opt LPOVERLAPPED lpOverlapped); - -/* - * Send (write/inject) a packet to a WinDivert handle. - */ -extern WINDIVERTEXPORT BOOL WinDivertSend( - __in HANDLE handle, - __in PVOID pPacket, - __in UINT packetLen, - __in PWINDIVERT_ADDRESS pAddr, - __out_opt UINT *writeLen); - -/* - * Send (write/inject) a packet to a WinDivert handle. - */ -extern WINDIVERTEXPORT BOOL WinDivertSendEx( - __in HANDLE handle, - __in PVOID pPacket, - __in UINT packetLen, - __in UINT64 flags, - __in PWINDIVERT_ADDRESS pAddr, - __out_opt UINT *writeLen, - __inout_opt LPOVERLAPPED lpOverlapped); - -/* - * Close a WinDivert handle. - */ -extern WINDIVERTEXPORT BOOL WinDivertClose( - __in HANDLE handle); - -/* - * Set a WinDivert handle parameter. - */ -extern WINDIVERTEXPORT BOOL WinDivertSetParam( - __in HANDLE handle, - __in WINDIVERT_PARAM param, - __in UINT64 value); - -/* - * Get a WinDivert handle parameter. - */ -extern WINDIVERTEXPORT BOOL WinDivertGetParam( - __in HANDLE handle, - __in WINDIVERT_PARAM param, - __out UINT64 *pValue); - -#endif /* WINDIVERT_KERNEL */ - -/****************************************************************************/ -/* WINDIVERT HELPER API */ -/****************************************************************************/ - -/* - * IPv4/IPv6/ICMP/ICMPv6/TCP/UDP header definitions. - */ -typedef struct -{ - UINT8 HdrLength:4; - UINT8 Version:4; - UINT8 TOS; - UINT16 Length; - UINT16 Id; - UINT16 FragOff0; - UINT8 TTL; - UINT8 Protocol; - UINT16 Checksum; - UINT32 SrcAddr; - UINT32 DstAddr; -} WINDIVERT_IPHDR, *PWINDIVERT_IPHDR; - -#define WINDIVERT_IPHDR_GET_FRAGOFF(hdr) \ - (((hdr)->FragOff0) & 0xFF1F) -#define WINDIVERT_IPHDR_GET_MF(hdr) \ - ((((hdr)->FragOff0) & 0x0020) != 0) -#define WINDIVERT_IPHDR_GET_DF(hdr) \ - ((((hdr)->FragOff0) & 0x0040) != 0) -#define WINDIVERT_IPHDR_GET_RESERVED(hdr) \ - ((((hdr)->FragOff0) & 0x0080) != 0) - -#define WINDIVERT_IPHDR_SET_FRAGOFF(hdr, val) \ - do \ - { \ - (hdr)->FragOff0 = (((hdr)->FragOff0) & 0x00E0) | \ - ((val) & 0xFF1F); \ - } \ - while (FALSE) -#define WINDIVERT_IPHDR_SET_MF(hdr, val) \ - do \ - { \ - (hdr)->FragOff0 = (((hdr)->FragOff0) & 0xFFDF) | \ - (((val) & 0x0001) << 5); \ - } \ - while (FALSE) -#define WINDIVERT_IPHDR_SET_DF(hdr, val) \ - do \ - { \ - (hdr)->FragOff0 = (((hdr)->FragOff0) & 0xFFBF) | \ - (((val) & 0x0001) << 6); \ - } \ - while (FALSE) -#define WINDIVERT_IPHDR_SET_RESERVED(hdr, val) \ - do \ - { \ - (hdr)->FragOff0 = (((hdr)->FragOff0) & 0xFF7F) | \ - (((val) & 0x0001) << 7); \ - } \ - while (FALSE) - -typedef struct -{ - UINT8 TrafficClass0:4; - UINT8 Version:4; - UINT8 FlowLabel0:4; - UINT8 TrafficClass1:4; - UINT16 FlowLabel1; - UINT16 Length; - UINT8 NextHdr; - UINT8 HopLimit; - UINT32 SrcAddr[4]; - UINT32 DstAddr[4]; -} WINDIVERT_IPV6HDR, *PWINDIVERT_IPV6HDR; - -#define WINDIVERT_IPV6HDR_GET_TRAFFICCLASS(hdr) \ - ((((hdr)->TrafficClass0) << 4) | ((hdr)->TrafficClass1)) -#define WINDIVERT_IPV6HDR_GET_FLOWLABEL(hdr) \ - ((((UINT32)(hdr)->FlowLabel0) << 16) | ((UINT32)(hdr)->FlowLabel1)) - -#define WINDIVERT_IPV6HDR_SET_TRAFFICCLASS(hdr, val) \ - do \ - { \ - (hdr)->TrafficClass0 = ((UINT8)(val) >> 4); \ - (hdr)->TrafficClass1 = (UINT8)(val); \ - } \ - while (FALSE) -#define WINDIVERT_IPV6HDR_SET_FLOWLABEL(hdr, val) \ - do \ - { \ - (hdr)->FlowLabel0 = (UINT8)((val) >> 16); \ - (hdr)->FlowLabel1 = (UINT16)(val); \ - } \ - while (FALSE) - -typedef struct -{ - UINT8 Type; - UINT8 Code; - UINT16 Checksum; - UINT32 Body; -} WINDIVERT_ICMPHDR, *PWINDIVERT_ICMPHDR; - -typedef struct -{ - UINT8 Type; - UINT8 Code; - UINT16 Checksum; - UINT32 Body; -} WINDIVERT_ICMPV6HDR, *PWINDIVERT_ICMPV6HDR; - -typedef struct -{ - UINT16 SrcPort; - UINT16 DstPort; - UINT32 SeqNum; - UINT32 AckNum; - UINT16 Reserved1:4; - UINT16 HdrLength:4; - UINT16 Fin:1; - UINT16 Syn:1; - UINT16 Rst:1; - UINT16 Psh:1; - UINT16 Ack:1; - UINT16 Urg:1; - UINT16 Reserved2:2; - UINT16 Window; - UINT16 Checksum; - UINT16 UrgPtr; -} WINDIVERT_TCPHDR, *PWINDIVERT_TCPHDR; - -typedef struct -{ - UINT16 SrcPort; - UINT16 DstPort; - UINT16 Length; - UINT16 Checksum; -} WINDIVERT_UDPHDR, *PWINDIVERT_UDPHDR; - -#ifndef WINDIVERT_KERNEL - -/* - * Flags for WinDivertHelperCalcChecksums() - */ -#define WINDIVERT_HELPER_NO_IP_CHECKSUM 1 -#define WINDIVERT_HELPER_NO_ICMP_CHECKSUM 2 -#define WINDIVERT_HELPER_NO_ICMPV6_CHECKSUM 4 -#define WINDIVERT_HELPER_NO_TCP_CHECKSUM 8 -#define WINDIVERT_HELPER_NO_UDP_CHECKSUM 16 - -/* - * Parse IPv4/IPv6/ICMP/ICMPv6/TCP/UDP headers from a raw packet. - */ -extern WINDIVERTEXPORT BOOL WinDivertHelperParsePacket( - __in PVOID pPacket, - __in UINT packetLen, - __out_opt PWINDIVERT_IPHDR *ppIpHdr, - __out_opt PWINDIVERT_IPV6HDR *ppIpv6Hdr, - __out_opt PWINDIVERT_ICMPHDR *ppIcmpHdr, - __out_opt PWINDIVERT_ICMPV6HDR *ppIcmpv6Hdr, - __out_opt PWINDIVERT_TCPHDR *ppTcpHdr, - __out_opt PWINDIVERT_UDPHDR *ppUdpHdr, - __out_opt PVOID *ppData, - __out_opt UINT *pDataLen); - -/* - * Parse an IPv4 address. - */ -extern WINDIVERTEXPORT BOOL WinDivertHelperParseIPv4Address( - __in const char *addrStr, - __out_opt UINT32 *pAddr); - -/* - * Parse an IPv6 address. - */ -extern WINDIVERTEXPORT BOOL WinDivertHelperParseIPv6Address( - __in const char *addrStr, - __out_opt UINT32 *pAddr); - -/* - * Calculate IPv4/IPv6/ICMP/ICMPv6/TCP/UDP checksums. - */ -extern WINDIVERTEXPORT UINT WinDivertHelperCalcChecksums( - __inout PVOID pPacket, - __in UINT packetLen, - __in_opt PWINDIVERT_ADDRESS pAddr, - __in UINT64 flags); - -/* - * Check the given filter string. - */ -extern WINDIVERTEXPORT BOOL WinDivertHelperCheckFilter( - __in const char *filter, - __in WINDIVERT_LAYER layer, - __out_opt const char **errorStr, - __out_opt UINT *errorPos); - -/* - * Evaluate the given filter string. - */ -extern WINDIVERTEXPORT BOOL WinDivertHelperEvalFilter( - __in const char *filter, - __in WINDIVERT_LAYER layer, - __in PVOID pPacket, - __in UINT packetLen, - __in PWINDIVERT_ADDRESS pAddr); - -#endif /* WINDIVERT_KERNEL */ - -#ifdef __cplusplus -} -#endif - -#endif /* __WINDIVERT_H */