Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions core/sys_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,16 @@ func InitInterface(logger *slog.Logger, ifName string) error {
}

func ConfigureAlias(logger *slog.Logger, ifName string, addr netip.Addr) error {
if addr.Is6() {
return Exec(logger, "netsh", "interface", "ipv6", "add", "address", ifName, addr.String())
}
return Exec(logger, "netsh", "interface", "ip", "add", "address", ifName, addr.String())
}

func RemoveAlias(logger *slog.Logger, ifName string, addr netip.Addr) error {
if addr.Is6() {
return Exec(logger, "netsh", "interface", "ipv6", "delete", "address", ifName, addr.String())
}
return Exec(logger, "netsh", "interface", "ip", "delete", "address", ifName, addr.String())
}

Expand Down
1 change: 1 addition & 0 deletions polyamide/device/send.go
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ func (device *Device) RoutineReadFromTUN() {
}
tce := device.GetTCElement()
tce.Buffer = bufs[i]
tce.Packet = bufs[i][offset : offset+sizes[i]]
tcBufs = append(tcBufs, tce)

bufs[i] = device.GetMessageBuffer()
Expand Down
3 changes: 1 addition & 2 deletions polyamide/device/traffic_control.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,7 @@ func (device *Device) TCBatch(batch []*TCElement, tcs *TCState) {
for i, elem := range batch {
// process TC Filters
act := TcPass
elem.ParsePacket()
if !elem.Validate() {
if !elem.ParsePacket() || !elem.Validate() {
device.Log.Errorf("Found malformed packet, dropping packet")
act = TcDrop
} else {
Expand Down
37 changes: 34 additions & 3 deletions polyamide/device/traffic_manip.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,25 @@ func (elem *TCElement) InitPacket(ver int, len uint16) {
elem.SetLength(len)
}

func (elem *TCElement) ParsePacket() {
elem.Packet = elem.Buffer[MessageTransportHeaderSize:]
func (elem *TCElement) ParsePacket() bool {
if elem == nil {
return false
}
if len(elem.Packet) == 0 {
if elem.Buffer == nil {
return false
}
elem.Packet = elem.Buffer[MessageTransportHeaderSize:]
}
if !elem.hasPacketHeader() {
return false
}
l := elem.GetLength()
elem.Packet = elem.Buffer[MessageTransportHeaderSize : MessageTransportHeaderSize+l]
if int(l) > len(elem.Packet) {
return false
}
elem.Packet = elem.Packet[:l]
return true
}

func (elem *TCElement) Incoming() bool {
Expand Down Expand Up @@ -137,6 +152,9 @@ func (elem *TCElement) Validate() bool {
if elem == nil || len(elem.Packet) == 0 {
return false
}
if !elem.hasPacketHeader() {
return false
}
ver := elem.GetIPVersion()
if ver == 4 {
if elem.GetLength() < ipv4.HeaderLen {
Expand All @@ -154,6 +172,19 @@ func (elem *TCElement) Validate() bool {
return true
}

func (elem *TCElement) hasPacketHeader() bool {
if elem == nil || len(elem.Packet) < PolyHeaderSize {
return false
}
ver := elem.GetIPVersion()
if ver == 4 {
return len(elem.Packet) >= ipv4.HeaderLen
} else if ver == 6 {
return len(elem.Packet) >= ipv6.HeaderLen
}
return true
}

func (elem *TCElement) TTLBytes() []byte {
if elem.GetIPVersion() == 4 {
return elem.Packet[8:9]
Expand Down
41 changes: 41 additions & 0 deletions polyamide/device/traffic_manip_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package device

import (
"encoding/binary"
"testing"
)

func TestParsePacketRejectsLengthBeyondReadBuffer(t *testing.T) {
var buf [MaxMessageSize]byte
packet := buf[MessageTransportHeaderSize : MessageTransportHeaderSize+2016]
packet[0] = 6 << 4
binary.BigEndian.PutUint16(packet[IPv6offsetPayloadLength:IPv6offsetPayloadLength+2], 2010)

elem := &TCElement{
Buffer: &buf,
Packet: packet,
}

if elem.ParsePacket() {
t.Fatal("expected oversized packet to be rejected")
}
}

func TestParsePacketTrimsToAdvertisedLength(t *testing.T) {
var buf [MaxMessageSize]byte
packet := buf[MessageTransportHeaderSize : MessageTransportHeaderSize+128]
packet[0] = 6 << 4
binary.BigEndian.PutUint16(packet[IPv6offsetPayloadLength:IPv6offsetPayloadLength+2], 8)

elem := &TCElement{
Buffer: &buf,
Packet: packet,
}

if !elem.ParsePacket() {
t.Fatal("expected valid packet to parse")
}
if len(elem.Packet) != 48 {
t.Fatalf("expected packet length 48, got %d", len(elem.Packet))
}
}
28 changes: 27 additions & 1 deletion polyamide/tun/tun_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
"sync"
"sync/atomic"
"time"
_ "unsafe"
"unsafe"

"golang.org/x/sys/windows"
"golang.zx2c4.com/wintun"
Expand Down Expand Up @@ -49,6 +49,9 @@ type NativeTun struct {
var (
WintunTunnelType = "WireGuard"
WintunStaticRequestedGUID *windows.GUID
modiphlpapi = windows.NewLazySystemDLL("iphlpapi.dll")
procGetIpInterfaceEntry = modiphlpapi.NewProc("GetIpInterfaceEntry")
procSetIpInterfaceEntry = modiphlpapi.NewProc("SetIpInterfaceEntry")
)

//go:linkname procyield runtime.procyield
Expand All @@ -75,6 +78,11 @@ func CreateTUNWithRequestedGUID(ifname string, requestedGUID *windows.GUID, mtu
if mtu > 0 {
forcedMTU = mtu
}
if err := setInterfaceMTU(wt.LUID(), windows.AF_INET6, forcedMTU); err != nil {
wt.Close()
return nil, fmt.Errorf("Error setting IPv6 interface MTU: %w", err)
}
_ = setInterfaceMTU(wt.LUID(), windows.AF_INET, forcedMTU)
Comment on lines +81 to +85

tun := &NativeTun{
wt: wt,
Expand Down Expand Up @@ -225,6 +233,24 @@ func (tun *NativeTun) RunningVersion() (version uint32, err error) {
return wintun.RunningVersion()
}

func setInterfaceMTU(luid uint64, family uint16, mtu int) error {
var row windows.MibIpInterfaceRow
row.Family = family
row.InterfaceLuid = luid

r1, _, _ := procGetIpInterfaceEntry.Call(uintptr(unsafe.Pointer(&row)))
if r1 != 0 {
return windows.Errno(r1)
}

row.NlMtu = uint32(mtu)
r1, _, _ = procSetIpInterfaceEntry.Call(uintptr(unsafe.Pointer(&row)))
if r1 != 0 {
return windows.Errno(r1)
}
return nil
}

func (rate *rateJuggler) update(packetLen uint64) {
now := nanotime()
total := rate.nextByteCount.Add(packetLen)
Expand Down
Loading