mirror of
https://github.com/safing/portmaster
synced 2025-09-02 10:39:22 +00:00
135 lines
2.9 KiB
Go
135 lines
2.9 KiB
Go
// +build windows
|
|
|
|
package windowskext
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"errors"
|
|
"net"
|
|
|
|
"github.com/tevino/abool"
|
|
|
|
"github.com/safing/portbase/log"
|
|
"github.com/safing/portmaster/network/packet"
|
|
)
|
|
|
|
// VerdictRequest is the request structure from the Kext.
|
|
type VerdictRequest struct {
|
|
id uint32 // ID from RegisterPacket
|
|
_ uint64 // Process ID - does not yet work
|
|
direction uint8
|
|
ipV6 uint8 // True: IPv6, False: IPv4
|
|
protocol uint8 // Protocol
|
|
_ uint8
|
|
localIP [4]uint32 // Source Address
|
|
remoteIP [4]uint32 // Destination Address
|
|
localPort uint16 // Source Port
|
|
remotePort uint16 // Destination port
|
|
_ uint32 // compartmentID
|
|
_ uint32 // interfaceIndex
|
|
_ uint32 // subInterfaceIndex
|
|
packetSize uint32
|
|
}
|
|
|
|
// Handler transforms received packets to the Packet interface.
|
|
func Handler(packets chan packet.Packet) {
|
|
if !ready.IsSet() {
|
|
return
|
|
}
|
|
|
|
defer close(packets)
|
|
|
|
for {
|
|
if !ready.IsSet() {
|
|
return
|
|
}
|
|
|
|
packetInfo, err := RecvVerdictRequest()
|
|
if err != nil {
|
|
// Check if we are done with processing.
|
|
if errors.Is(err, ErrKextNotReady) {
|
|
return
|
|
}
|
|
|
|
log.Warningf("failed to get packet from windows kext: %s", err)
|
|
continue
|
|
}
|
|
|
|
if packetInfo == nil {
|
|
continue
|
|
}
|
|
|
|
// log.Tracef("packet: %+v", packetInfo)
|
|
|
|
// New Packet
|
|
new := &Packet{
|
|
verdictRequest: packetInfo,
|
|
verdictSet: abool.NewBool(false),
|
|
}
|
|
|
|
info := new.Info()
|
|
info.Inbound = packetInfo.direction > 0
|
|
info.InTunnel = false
|
|
info.Protocol = packet.IPProtocol(packetInfo.protocol)
|
|
|
|
// IP version
|
|
if packetInfo.ipV6 == 1 {
|
|
info.Version = packet.IPv6
|
|
} else {
|
|
info.Version = packet.IPv4
|
|
}
|
|
|
|
// IPs
|
|
if info.Version == packet.IPv4 {
|
|
// IPv4
|
|
if info.Inbound {
|
|
// Inbound
|
|
info.Src = convertIPv4(packetInfo.remoteIP)
|
|
info.Dst = convertIPv4(packetInfo.localIP)
|
|
} else {
|
|
// Outbound
|
|
info.Src = convertIPv4(packetInfo.localIP)
|
|
info.Dst = convertIPv4(packetInfo.remoteIP)
|
|
}
|
|
} else {
|
|
// IPv6
|
|
if info.Inbound {
|
|
// Inbound
|
|
info.Src = convertIPv6(packetInfo.remoteIP)
|
|
info.Dst = convertIPv6(packetInfo.localIP)
|
|
} else {
|
|
// Outbound
|
|
info.Src = convertIPv6(packetInfo.localIP)
|
|
info.Dst = convertIPv6(packetInfo.remoteIP)
|
|
}
|
|
}
|
|
|
|
// Ports
|
|
if info.Inbound {
|
|
// Inbound
|
|
info.SrcPort = packetInfo.remotePort
|
|
info.DstPort = packetInfo.localPort
|
|
} else {
|
|
// Outbound
|
|
info.SrcPort = packetInfo.localPort
|
|
info.DstPort = packetInfo.remotePort
|
|
}
|
|
|
|
packets <- new
|
|
}
|
|
}
|
|
|
|
// convertIPv4 as needed for data from the kernel
|
|
func convertIPv4(input [4]uint32) net.IP {
|
|
addressBuf := make([]byte, 4)
|
|
binary.BigEndian.PutUint32(addressBuf, input[0])
|
|
return net.IP(addressBuf)
|
|
}
|
|
|
|
func convertIPv6(input [4]uint32) net.IP {
|
|
addressBuf := make([]byte, 16)
|
|
for i := 0; i < 4; i++ {
|
|
binary.BigEndian.PutUint32(addressBuf[i*4:i*4+4], input[i])
|
|
}
|
|
return net.IP(addressBuf)
|
|
}
|