Remove old windivert interception

This commit is contained in:
Daniel 2019-07-02 13:00:24 +02:00
parent 81eee568f2
commit 960e1bcc16
7 changed files with 0 additions and 1019 deletions

View file

@ -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
}

View file

@ -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

View file

@ -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
}

View file

@ -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}" $*

View file

@ -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)
}

View file

@ -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]))
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*
* 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 <windows.h>
#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 <stdint.h>
#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 */