mirror of
https://github.com/safing/portmaster
synced 2025-09-01 18:19:12 +00:00
Remove old windivert interception
This commit is contained in:
parent
81eee568f2
commit
960e1bcc16
7 changed files with 0 additions and 1019 deletions
|
@ -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
|
||||
}
|
|
@ -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
|
|
@ -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
|
||||
}
|
|
@ -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}" $*
|
|
@ -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)
|
||||
|
||||
}
|
|
@ -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]))
|
||||
}
|
|
@ -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 */
|
Loading…
Add table
Reference in a new issue