diff --git a/docker/images/visor/install-preq.sh b/docker/images/visor/install-preq.sh
index 8c8293c825..feb3838b5c 100755
--- a/docker/images/visor/install-preq.sh
+++ b/docker/images/visor/install-preq.sh
@@ -2,12 +2,12 @@
if type apt >/dev/null; then
apt-get update && apt-get install -y --no-install-recommends \
- ca-certificates &&
+ ca-certificates iptables &&
rm -rf /var/lib/apt/lists/*
fi
if type apk >/dev/null; then
apk update
- apk add --no-cache ca-certificates openssl iproute2 bash
+ apk add --no-cache ca-certificates openssl iproute2 bash iptables
update-ca-certificates --fresh
fi
diff --git a/go.mod b/go.mod
index bf7b33efa2..371f8705c6 100644
--- a/go.mod
+++ b/go.mod
@@ -43,7 +43,7 @@ require (
golang.org/x/net v0.14.0
golang.org/x/sync v0.3.0
golang.org/x/sys v0.11.0
- golang.zx2c4.com/wireguard v0.0.0-20230704135630-469159ecf7d1
+ golang.zx2c4.com/wireguard v0.0.0-20230223181233-21636207a675
)
require (
diff --git a/go.sum b/go.sum
index 5307a88a02..a63dc333b3 100644
--- a/go.sum
+++ b/go.sum
@@ -451,6 +451,8 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg=
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
+golang.zx2c4.com/wireguard v0.0.0-20230223181233-21636207a675 h1:/J/RVnr7ng4fWPRH3xa4WtBJ1Jp+Auu4YNLmGiPv5QU=
+golang.zx2c4.com/wireguard v0.0.0-20230223181233-21636207a675/go.mod h1:whfbyDBt09xhCYQWtO2+3UVjlaq6/9hDZrjg2ZE6SyA=
golang.zx2c4.com/wireguard v0.0.0-20230704135630-469159ecf7d1 h1:EY138uSo1JYlDq+97u1FtcOUwPpIU6WL1Lkt7WpYjPA=
golang.zx2c4.com/wireguard v0.0.0-20230704135630-469159ecf7d1/go.mod h1:tqur9LnfstdR9ep2LaJT4lFUl0EjlHtge+gAjmsHUG4=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
diff --git a/internal/vpn/tun_device_windows.go b/internal/vpn/tun_device_windows.go
index c80d6b041b..bc49187e5c 100644
--- a/internal/vpn/tun_device_windows.go
+++ b/internal/vpn/tun_device_windows.go
@@ -34,13 +34,11 @@ func newTUNDevice() (TUNDevice, error) {
}
func (t *tunDevice) Read(buf []byte) (int, error) {
- validBuf := [][]byte{buf}
- return t.tun.Read(validBuf, []int{len(buf) + 1}, 0)
+ return t.tun.Read(buf, 0)
}
func (t *tunDevice) Write(buf []byte) (int, error) {
- validBuf := [][]byte{buf}
- return t.tun.Write(validBuf, 0)
+ return t.tun.Write(buf, 0)
}
func (t *tunDevice) Close() error {
diff --git a/scripts/win_installer/Product.wxs b/scripts/win_installer/Product.wxs
index df26c756ce..d501deb236 100644
--- a/scripts/win_installer/Product.wxs
+++ b/scripts/win_installer/Product.wxs
@@ -21,11 +21,9 @@
-
-
+ =
- NOT NEWERVERSIONDETECTED
+ NEWERVERSIONDETECTED
diff --git a/vendor/golang.zx2c4.com/wireguard/conn/bind_std.go b/vendor/golang.zx2c4.com/wireguard/conn/bind_std.go
deleted file mode 100644
index c701ef8724..0000000000
--- a/vendor/golang.zx2c4.com/wireguard/conn/bind_std.go
+++ /dev/null
@@ -1,408 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2017-2023 WireGuard LLC. All Rights Reserved.
- */
-
-package conn
-
-import (
- "context"
- "errors"
- "net"
- "net/netip"
- "runtime"
- "strconv"
- "sync"
- "syscall"
-
- "golang.org/x/net/ipv4"
- "golang.org/x/net/ipv6"
-)
-
-var (
- _ Bind = (*StdNetBind)(nil)
-)
-
-// StdNetBind implements Bind for all platforms. While Windows has its own Bind
-// (see bind_windows.go), it may fall back to StdNetBind.
-// TODO: Remove usage of ipv{4,6}.PacketConn when net.UDPConn has comparable
-// methods for sending and receiving multiple datagrams per-syscall. See the
-// proposal in https://github.com/golang/go/issues/45886#issuecomment-1218301564.
-type StdNetBind struct {
- mu sync.Mutex // protects all fields except as specified
- ipv4 *net.UDPConn
- ipv6 *net.UDPConn
- ipv4PC *ipv4.PacketConn // will be nil on non-Linux
- ipv6PC *ipv6.PacketConn // will be nil on non-Linux
-
- // these three fields are not guarded by mu
- udpAddrPool sync.Pool
- ipv4MsgsPool sync.Pool
- ipv6MsgsPool sync.Pool
-
- blackhole4 bool
- blackhole6 bool
-}
-
-func NewStdNetBind() Bind {
- return &StdNetBind{
- udpAddrPool: sync.Pool{
- New: func() any {
- return &net.UDPAddr{
- IP: make([]byte, 16),
- }
- },
- },
-
- ipv4MsgsPool: sync.Pool{
- New: func() any {
- msgs := make([]ipv4.Message, IdealBatchSize)
- for i := range msgs {
- msgs[i].Buffers = make(net.Buffers, 1)
- msgs[i].OOB = make([]byte, srcControlSize)
- }
- return &msgs
- },
- },
-
- ipv6MsgsPool: sync.Pool{
- New: func() any {
- msgs := make([]ipv6.Message, IdealBatchSize)
- for i := range msgs {
- msgs[i].Buffers = make(net.Buffers, 1)
- msgs[i].OOB = make([]byte, srcControlSize)
- }
- return &msgs
- },
- },
- }
-}
-
-type StdNetEndpoint struct {
- // AddrPort is the endpoint destination.
- netip.AddrPort
- // src is the current sticky source address and interface index, if
- // supported. Typically this is a PKTINFO structure from/for control
- // messages, see unix.PKTINFO for an example.
- src []byte
-}
-
-var (
- _ Bind = (*StdNetBind)(nil)
- _ Endpoint = &StdNetEndpoint{}
-)
-
-func (*StdNetBind) ParseEndpoint(s string) (Endpoint, error) {
- e, err := netip.ParseAddrPort(s)
- if err != nil {
- return nil, err
- }
- return &StdNetEndpoint{
- AddrPort: e,
- }, nil
-}
-
-func (e *StdNetEndpoint) ClearSrc() {
- if e.src != nil {
- // Truncate src, no need to reallocate.
- e.src = e.src[:0]
- }
-}
-
-func (e *StdNetEndpoint) DstIP() netip.Addr {
- return e.AddrPort.Addr()
-}
-
-// See sticky_default,linux, etc for implementations of SrcIP and SrcIfidx.
-
-func (e *StdNetEndpoint) DstToBytes() []byte {
- b, _ := e.AddrPort.MarshalBinary()
- return b
-}
-
-func (e *StdNetEndpoint) DstToString() string {
- return e.AddrPort.String()
-}
-
-func listenNet(network string, port int) (*net.UDPConn, int, error) {
- conn, err := listenConfig().ListenPacket(context.Background(), network, ":"+strconv.Itoa(port))
- if err != nil {
- return nil, 0, err
- }
-
- // Retrieve port.
- laddr := conn.LocalAddr()
- uaddr, err := net.ResolveUDPAddr(
- laddr.Network(),
- laddr.String(),
- )
- if err != nil {
- return nil, 0, err
- }
- return conn.(*net.UDPConn), uaddr.Port, nil
-}
-
-func (s *StdNetBind) Open(uport uint16) ([]ReceiveFunc, uint16, error) {
- s.mu.Lock()
- defer s.mu.Unlock()
-
- var err error
- var tries int
-
- if s.ipv4 != nil || s.ipv6 != nil {
- return nil, 0, ErrBindAlreadyOpen
- }
-
- // Attempt to open ipv4 and ipv6 listeners on the same port.
- // If uport is 0, we can retry on failure.
-again:
- port := int(uport)
- var v4conn, v6conn *net.UDPConn
- var v4pc *ipv4.PacketConn
- var v6pc *ipv6.PacketConn
-
- v4conn, port, err = listenNet("udp4", port)
- if err != nil && !errors.Is(err, syscall.EAFNOSUPPORT) {
- return nil, 0, err
- }
-
- // Listen on the same port as we're using for ipv4.
- v6conn, port, err = listenNet("udp6", port)
- if uport == 0 && errors.Is(err, syscall.EADDRINUSE) && tries < 100 {
- v4conn.Close()
- tries++
- goto again
- }
- if err != nil && !errors.Is(err, syscall.EAFNOSUPPORT) {
- v4conn.Close()
- return nil, 0, err
- }
- var fns []ReceiveFunc
- if v4conn != nil {
- if runtime.GOOS == "linux" {
- v4pc = ipv4.NewPacketConn(v4conn)
- s.ipv4PC = v4pc
- }
- fns = append(fns, s.makeReceiveIPv4(v4pc, v4conn))
- s.ipv4 = v4conn
- }
- if v6conn != nil {
- if runtime.GOOS == "linux" {
- v6pc = ipv6.NewPacketConn(v6conn)
- s.ipv6PC = v6pc
- }
- fns = append(fns, s.makeReceiveIPv6(v6pc, v6conn))
- s.ipv6 = v6conn
- }
- if len(fns) == 0 {
- return nil, 0, syscall.EAFNOSUPPORT
- }
-
- return fns, uint16(port), nil
-}
-
-func (s *StdNetBind) makeReceiveIPv4(pc *ipv4.PacketConn, conn *net.UDPConn) ReceiveFunc {
- return func(bufs [][]byte, sizes []int, eps []Endpoint) (n int, err error) {
- msgs := s.ipv4MsgsPool.Get().(*[]ipv4.Message)
- defer s.ipv4MsgsPool.Put(msgs)
- for i := range bufs {
- (*msgs)[i].Buffers[0] = bufs[i]
- }
- var numMsgs int
- if runtime.GOOS == "linux" {
- numMsgs, err = pc.ReadBatch(*msgs, 0)
- if err != nil {
- return 0, err
- }
- } else {
- msg := &(*msgs)[0]
- msg.N, msg.NN, _, msg.Addr, err = conn.ReadMsgUDP(msg.Buffers[0], msg.OOB)
- if err != nil {
- return 0, err
- }
- numMsgs = 1
- }
- for i := 0; i < numMsgs; i++ {
- msg := &(*msgs)[i]
- sizes[i] = msg.N
- addrPort := msg.Addr.(*net.UDPAddr).AddrPort()
- ep := &StdNetEndpoint{AddrPort: addrPort} // TODO: remove allocation
- getSrcFromControl(msg.OOB[:msg.NN], ep)
- eps[i] = ep
- }
- return numMsgs, nil
- }
-}
-
-func (s *StdNetBind) makeReceiveIPv6(pc *ipv6.PacketConn, conn *net.UDPConn) ReceiveFunc {
- return func(bufs [][]byte, sizes []int, eps []Endpoint) (n int, err error) {
- msgs := s.ipv6MsgsPool.Get().(*[]ipv6.Message)
- defer s.ipv6MsgsPool.Put(msgs)
- for i := range bufs {
- (*msgs)[i].Buffers[0] = bufs[i]
- }
- var numMsgs int
- if runtime.GOOS == "linux" {
- numMsgs, err = pc.ReadBatch(*msgs, 0)
- if err != nil {
- return 0, err
- }
- } else {
- msg := &(*msgs)[0]
- msg.N, msg.NN, _, msg.Addr, err = conn.ReadMsgUDP(msg.Buffers[0], msg.OOB)
- if err != nil {
- return 0, err
- }
- numMsgs = 1
- }
- for i := 0; i < numMsgs; i++ {
- msg := &(*msgs)[i]
- sizes[i] = msg.N
- addrPort := msg.Addr.(*net.UDPAddr).AddrPort()
- ep := &StdNetEndpoint{AddrPort: addrPort} // TODO: remove allocation
- getSrcFromControl(msg.OOB[:msg.NN], ep)
- eps[i] = ep
- }
- return numMsgs, nil
- }
-}
-
-// TODO: When all Binds handle IdealBatchSize, remove this dynamic function and
-// rename the IdealBatchSize constant to BatchSize.
-func (s *StdNetBind) BatchSize() int {
- if runtime.GOOS == "linux" {
- return IdealBatchSize
- }
- return 1
-}
-
-func (s *StdNetBind) Close() error {
- s.mu.Lock()
- defer s.mu.Unlock()
-
- var err1, err2 error
- if s.ipv4 != nil {
- err1 = s.ipv4.Close()
- s.ipv4 = nil
- s.ipv4PC = nil
- }
- if s.ipv6 != nil {
- err2 = s.ipv6.Close()
- s.ipv6 = nil
- s.ipv6PC = nil
- }
- s.blackhole4 = false
- s.blackhole6 = false
- if err1 != nil {
- return err1
- }
- return err2
-}
-
-func (s *StdNetBind) Send(bufs [][]byte, endpoint Endpoint) error {
- s.mu.Lock()
- blackhole := s.blackhole4
- conn := s.ipv4
- var (
- pc4 *ipv4.PacketConn
- pc6 *ipv6.PacketConn
- )
- is6 := false
- if endpoint.DstIP().Is6() {
- blackhole = s.blackhole6
- conn = s.ipv6
- pc6 = s.ipv6PC
- is6 = true
- } else {
- pc4 = s.ipv4PC
- }
- s.mu.Unlock()
-
- if blackhole {
- return nil
- }
- if conn == nil {
- return syscall.EAFNOSUPPORT
- }
- if is6 {
- return s.send6(conn, pc6, endpoint, bufs)
- } else {
- return s.send4(conn, pc4, endpoint, bufs)
- }
-}
-
-func (s *StdNetBind) send4(conn *net.UDPConn, pc *ipv4.PacketConn, ep Endpoint, bufs [][]byte) error {
- ua := s.udpAddrPool.Get().(*net.UDPAddr)
- as4 := ep.DstIP().As4()
- copy(ua.IP, as4[:])
- ua.IP = ua.IP[:4]
- ua.Port = int(ep.(*StdNetEndpoint).Port())
- msgs := s.ipv4MsgsPool.Get().(*[]ipv4.Message)
- for i, buf := range bufs {
- (*msgs)[i].Buffers[0] = buf
- (*msgs)[i].Addr = ua
- setSrcControl(&(*msgs)[i].OOB, ep.(*StdNetEndpoint))
- }
- var (
- n int
- err error
- start int
- )
- if runtime.GOOS == "linux" {
- for {
- n, err = pc.WriteBatch((*msgs)[start:len(bufs)], 0)
- if err != nil || n == len((*msgs)[start:len(bufs)]) {
- break
- }
- start += n
- }
- } else {
- for i, buf := range bufs {
- _, _, err = conn.WriteMsgUDP(buf, (*msgs)[i].OOB, ua)
- if err != nil {
- break
- }
- }
- }
- s.udpAddrPool.Put(ua)
- s.ipv4MsgsPool.Put(msgs)
- return err
-}
-
-func (s *StdNetBind) send6(conn *net.UDPConn, pc *ipv6.PacketConn, ep Endpoint, bufs [][]byte) error {
- ua := s.udpAddrPool.Get().(*net.UDPAddr)
- as16 := ep.DstIP().As16()
- copy(ua.IP, as16[:])
- ua.IP = ua.IP[:16]
- ua.Port = int(ep.(*StdNetEndpoint).Port())
- msgs := s.ipv6MsgsPool.Get().(*[]ipv6.Message)
- for i, buf := range bufs {
- (*msgs)[i].Buffers[0] = buf
- (*msgs)[i].Addr = ua
- setSrcControl(&(*msgs)[i].OOB, ep.(*StdNetEndpoint))
- }
- var (
- n int
- err error
- start int
- )
- if runtime.GOOS == "linux" {
- for {
- n, err = pc.WriteBatch((*msgs)[start:len(bufs)], 0)
- if err != nil || n == len((*msgs)[start:len(bufs)]) {
- break
- }
- start += n
- }
- } else {
- for i, buf := range bufs {
- _, _, err = conn.WriteMsgUDP(buf, (*msgs)[i].OOB, ua)
- if err != nil {
- break
- }
- }
- }
- s.udpAddrPool.Put(ua)
- s.ipv6MsgsPool.Put(msgs)
- return err
-}
diff --git a/vendor/golang.zx2c4.com/wireguard/conn/bind_windows.go b/vendor/golang.zx2c4.com/wireguard/conn/bind_windows.go
deleted file mode 100644
index d5095e004b..0000000000
--- a/vendor/golang.zx2c4.com/wireguard/conn/bind_windows.go
+++ /dev/null
@@ -1,601 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2017-2023 WireGuard LLC. All Rights Reserved.
- */
-
-package conn
-
-import (
- "encoding/binary"
- "io"
- "net"
- "net/netip"
- "strconv"
- "sync"
- "sync/atomic"
- "unsafe"
-
- "golang.org/x/sys/windows"
-
- "golang.zx2c4.com/wireguard/conn/winrio"
-)
-
-const (
- packetsPerRing = 1024
- bytesPerPacket = 2048 - 32
- receiveSpins = 15
-)
-
-type ringPacket struct {
- addr WinRingEndpoint
- data [bytesPerPacket]byte
-}
-
-type ringBuffer struct {
- packets uintptr
- head, tail uint32
- id winrio.BufferId
- iocp windows.Handle
- isFull bool
- cq winrio.Cq
- mu sync.Mutex
- overlapped windows.Overlapped
-}
-
-func (rb *ringBuffer) Push() *ringPacket {
- for rb.isFull {
- panic("ring is full")
- }
- ret := (*ringPacket)(unsafe.Pointer(rb.packets + (uintptr(rb.tail%packetsPerRing) * unsafe.Sizeof(ringPacket{}))))
- rb.tail += 1
- if rb.tail%packetsPerRing == rb.head%packetsPerRing {
- rb.isFull = true
- }
- return ret
-}
-
-func (rb *ringBuffer) Return(count uint32) {
- if rb.head%packetsPerRing == rb.tail%packetsPerRing && !rb.isFull {
- return
- }
- rb.head += count
- rb.isFull = false
-}
-
-type afWinRingBind struct {
- sock windows.Handle
- rx, tx ringBuffer
- rq winrio.Rq
- mu sync.Mutex
- blackhole bool
-}
-
-// WinRingBind uses Windows registered I/O for fast ring buffered networking.
-type WinRingBind struct {
- v4, v6 afWinRingBind
- mu sync.RWMutex
- isOpen atomic.Uint32 // 0, 1, or 2
-}
-
-func NewDefaultBind() Bind { return NewWinRingBind() }
-
-func NewWinRingBind() Bind {
- if !winrio.Initialize() {
- return NewStdNetBind()
- }
- return new(WinRingBind)
-}
-
-type WinRingEndpoint struct {
- family uint16
- data [30]byte
-}
-
-var (
- _ Bind = (*WinRingBind)(nil)
- _ Endpoint = (*WinRingEndpoint)(nil)
-)
-
-func (*WinRingBind) ParseEndpoint(s string) (Endpoint, error) {
- host, port, err := net.SplitHostPort(s)
- if err != nil {
- return nil, err
- }
- host16, err := windows.UTF16PtrFromString(host)
- if err != nil {
- return nil, err
- }
- port16, err := windows.UTF16PtrFromString(port)
- if err != nil {
- return nil, err
- }
- hints := windows.AddrinfoW{
- Flags: windows.AI_NUMERICHOST,
- Family: windows.AF_UNSPEC,
- Socktype: windows.SOCK_DGRAM,
- Protocol: windows.IPPROTO_UDP,
- }
- var addrinfo *windows.AddrinfoW
- err = windows.GetAddrInfoW(host16, port16, &hints, &addrinfo)
- if err != nil {
- return nil, err
- }
- defer windows.FreeAddrInfoW(addrinfo)
- if (addrinfo.Family != windows.AF_INET && addrinfo.Family != windows.AF_INET6) || addrinfo.Addrlen > unsafe.Sizeof(WinRingEndpoint{}) {
- return nil, windows.ERROR_INVALID_ADDRESS
- }
- var dst [unsafe.Sizeof(WinRingEndpoint{})]byte
- copy(dst[:], unsafe.Slice((*byte)(unsafe.Pointer(addrinfo.Addr)), addrinfo.Addrlen))
- return (*WinRingEndpoint)(unsafe.Pointer(&dst[0])), nil
-}
-
-func (*WinRingEndpoint) ClearSrc() {}
-
-func (e *WinRingEndpoint) DstIP() netip.Addr {
- switch e.family {
- case windows.AF_INET:
- return netip.AddrFrom4(*(*[4]byte)(e.data[2:6]))
- case windows.AF_INET6:
- return netip.AddrFrom16(*(*[16]byte)(e.data[6:22]))
- }
- return netip.Addr{}
-}
-
-func (e *WinRingEndpoint) SrcIP() netip.Addr {
- return netip.Addr{} // not supported
-}
-
-func (e *WinRingEndpoint) DstToBytes() []byte {
- switch e.family {
- case windows.AF_INET:
- b := make([]byte, 0, 6)
- b = append(b, e.data[2:6]...)
- b = append(b, e.data[1], e.data[0])
- return b
- case windows.AF_INET6:
- b := make([]byte, 0, 18)
- b = append(b, e.data[6:22]...)
- b = append(b, e.data[1], e.data[0])
- return b
- }
- return nil
-}
-
-func (e *WinRingEndpoint) DstToString() string {
- switch e.family {
- case windows.AF_INET:
- return netip.AddrPortFrom(netip.AddrFrom4(*(*[4]byte)(e.data[2:6])), binary.BigEndian.Uint16(e.data[0:2])).String()
- case windows.AF_INET6:
- var zone string
- if scope := *(*uint32)(unsafe.Pointer(&e.data[22])); scope > 0 {
- zone = strconv.FormatUint(uint64(scope), 10)
- }
- return netip.AddrPortFrom(netip.AddrFrom16(*(*[16]byte)(e.data[6:22])).WithZone(zone), binary.BigEndian.Uint16(e.data[0:2])).String()
- }
- return ""
-}
-
-func (e *WinRingEndpoint) SrcToString() string {
- return ""
-}
-
-func (ring *ringBuffer) CloseAndZero() {
- if ring.cq != 0 {
- winrio.CloseCompletionQueue(ring.cq)
- ring.cq = 0
- }
- if ring.iocp != 0 {
- windows.CloseHandle(ring.iocp)
- ring.iocp = 0
- }
- if ring.id != 0 {
- winrio.DeregisterBuffer(ring.id)
- ring.id = 0
- }
- if ring.packets != 0 {
- windows.VirtualFree(ring.packets, 0, windows.MEM_RELEASE)
- ring.packets = 0
- }
- ring.head = 0
- ring.tail = 0
- ring.isFull = false
-}
-
-func (bind *afWinRingBind) CloseAndZero() {
- bind.rx.CloseAndZero()
- bind.tx.CloseAndZero()
- if bind.sock != 0 {
- windows.CloseHandle(bind.sock)
- bind.sock = 0
- }
- bind.blackhole = false
-}
-
-func (bind *WinRingBind) closeAndZero() {
- bind.isOpen.Store(0)
- bind.v4.CloseAndZero()
- bind.v6.CloseAndZero()
-}
-
-func (ring *ringBuffer) Open() error {
- var err error
- packetsLen := unsafe.Sizeof(ringPacket{}) * packetsPerRing
- ring.packets, err = windows.VirtualAlloc(0, packetsLen, windows.MEM_COMMIT|windows.MEM_RESERVE, windows.PAGE_READWRITE)
- if err != nil {
- return err
- }
- ring.id, err = winrio.RegisterPointer(unsafe.Pointer(ring.packets), uint32(packetsLen))
- if err != nil {
- return err
- }
- ring.iocp, err = windows.CreateIoCompletionPort(windows.InvalidHandle, 0, 0, 0)
- if err != nil {
- return err
- }
- ring.cq, err = winrio.CreateIOCPCompletionQueue(packetsPerRing, ring.iocp, 0, &ring.overlapped)
- if err != nil {
- return err
- }
- return nil
-}
-
-func (bind *afWinRingBind) Open(family int32, sa windows.Sockaddr) (windows.Sockaddr, error) {
- var err error
- bind.sock, err = winrio.Socket(family, windows.SOCK_DGRAM, windows.IPPROTO_UDP)
- if err != nil {
- return nil, err
- }
- err = bind.rx.Open()
- if err != nil {
- return nil, err
- }
- err = bind.tx.Open()
- if err != nil {
- return nil, err
- }
- bind.rq, err = winrio.CreateRequestQueue(bind.sock, packetsPerRing, 1, packetsPerRing, 1, bind.rx.cq, bind.tx.cq, 0)
- if err != nil {
- return nil, err
- }
- err = windows.Bind(bind.sock, sa)
- if err != nil {
- return nil, err
- }
- sa, err = windows.Getsockname(bind.sock)
- if err != nil {
- return nil, err
- }
- return sa, nil
-}
-
-func (bind *WinRingBind) Open(port uint16) (recvFns []ReceiveFunc, selectedPort uint16, err error) {
- bind.mu.Lock()
- defer bind.mu.Unlock()
- defer func() {
- if err != nil {
- bind.closeAndZero()
- }
- }()
- if bind.isOpen.Load() != 0 {
- return nil, 0, ErrBindAlreadyOpen
- }
- var sa windows.Sockaddr
- sa, err = bind.v4.Open(windows.AF_INET, &windows.SockaddrInet4{Port: int(port)})
- if err != nil {
- return nil, 0, err
- }
- sa, err = bind.v6.Open(windows.AF_INET6, &windows.SockaddrInet6{Port: sa.(*windows.SockaddrInet4).Port})
- if err != nil {
- return nil, 0, err
- }
- selectedPort = uint16(sa.(*windows.SockaddrInet6).Port)
- for i := 0; i < packetsPerRing; i++ {
- err = bind.v4.InsertReceiveRequest()
- if err != nil {
- return nil, 0, err
- }
- err = bind.v6.InsertReceiveRequest()
- if err != nil {
- return nil, 0, err
- }
- }
- bind.isOpen.Store(1)
- return []ReceiveFunc{bind.receiveIPv4, bind.receiveIPv6}, selectedPort, err
-}
-
-func (bind *WinRingBind) Close() error {
- bind.mu.RLock()
- if bind.isOpen.Load() != 1 {
- bind.mu.RUnlock()
- return nil
- }
- bind.isOpen.Store(2)
- windows.PostQueuedCompletionStatus(bind.v4.rx.iocp, 0, 0, nil)
- windows.PostQueuedCompletionStatus(bind.v4.tx.iocp, 0, 0, nil)
- windows.PostQueuedCompletionStatus(bind.v6.rx.iocp, 0, 0, nil)
- windows.PostQueuedCompletionStatus(bind.v6.tx.iocp, 0, 0, nil)
- bind.mu.RUnlock()
- bind.mu.Lock()
- defer bind.mu.Unlock()
- bind.closeAndZero()
- return nil
-}
-
-// TODO: When all Binds handle IdealBatchSize, remove this dynamic function and
-// rename the IdealBatchSize constant to BatchSize.
-func (bind *WinRingBind) BatchSize() int {
- // TODO: implement batching in and out of the ring
- return 1
-}
-
-func (bind *WinRingBind) SetMark(mark uint32) error {
- return nil
-}
-
-func (bind *afWinRingBind) InsertReceiveRequest() error {
- packet := bind.rx.Push()
- dataBuffer := &winrio.Buffer{
- Id: bind.rx.id,
- Offset: uint32(uintptr(unsafe.Pointer(&packet.data[0])) - bind.rx.packets),
- Length: uint32(len(packet.data)),
- }
- addressBuffer := &winrio.Buffer{
- Id: bind.rx.id,
- Offset: uint32(uintptr(unsafe.Pointer(&packet.addr)) - bind.rx.packets),
- Length: uint32(unsafe.Sizeof(packet.addr)),
- }
- bind.mu.Lock()
- defer bind.mu.Unlock()
- return winrio.ReceiveEx(bind.rq, dataBuffer, 1, nil, addressBuffer, nil, nil, 0, uintptr(unsafe.Pointer(packet)))
-}
-
-//go:linkname procyield runtime.procyield
-func procyield(cycles uint32)
-
-func (bind *afWinRingBind) Receive(buf []byte, isOpen *atomic.Uint32) (int, Endpoint, error) {
- if isOpen.Load() != 1 {
- return 0, nil, net.ErrClosed
- }
- bind.rx.mu.Lock()
- defer bind.rx.mu.Unlock()
-
- var err error
- var count uint32
- var results [1]winrio.Result
-retry:
- count = 0
- for tries := 0; count == 0 && tries < receiveSpins; tries++ {
- if tries > 0 {
- if isOpen.Load() != 1 {
- return 0, nil, net.ErrClosed
- }
- procyield(1)
- }
- count = winrio.DequeueCompletion(bind.rx.cq, results[:])
- }
- if count == 0 {
- err = winrio.Notify(bind.rx.cq)
- if err != nil {
- return 0, nil, err
- }
- var bytes uint32
- var key uintptr
- var overlapped *windows.Overlapped
- err = windows.GetQueuedCompletionStatus(bind.rx.iocp, &bytes, &key, &overlapped, windows.INFINITE)
- if err != nil {
- return 0, nil, err
- }
- if isOpen.Load() != 1 {
- return 0, nil, net.ErrClosed
- }
- count = winrio.DequeueCompletion(bind.rx.cq, results[:])
- if count == 0 {
- return 0, nil, io.ErrNoProgress
- }
- }
- bind.rx.Return(1)
- err = bind.InsertReceiveRequest()
- if err != nil {
- return 0, nil, err
- }
- // We limit the MTU well below the 65k max for practicality, but this means a remote host can still send us
- // huge packets. Just try again when this happens. The infinite loop this could cause is still limited to
- // attacker bandwidth, just like the rest of the receive path.
- if windows.Errno(results[0].Status) == windows.WSAEMSGSIZE {
- if isOpen.Load() != 1 {
- return 0, nil, net.ErrClosed
- }
- goto retry
- }
- if results[0].Status != 0 {
- return 0, nil, windows.Errno(results[0].Status)
- }
- packet := (*ringPacket)(unsafe.Pointer(uintptr(results[0].RequestContext)))
- ep := packet.addr
- n := copy(buf, packet.data[:results[0].BytesTransferred])
- return n, &ep, nil
-}
-
-func (bind *WinRingBind) receiveIPv4(bufs [][]byte, sizes []int, eps []Endpoint) (int, error) {
- bind.mu.RLock()
- defer bind.mu.RUnlock()
- n, ep, err := bind.v4.Receive(bufs[0], &bind.isOpen)
- sizes[0] = n
- eps[0] = ep
- return 1, err
-}
-
-func (bind *WinRingBind) receiveIPv6(bufs [][]byte, sizes []int, eps []Endpoint) (int, error) {
- bind.mu.RLock()
- defer bind.mu.RUnlock()
- n, ep, err := bind.v6.Receive(bufs[0], &bind.isOpen)
- sizes[0] = n
- eps[0] = ep
- return 1, err
-}
-
-func (bind *afWinRingBind) Send(buf []byte, nend *WinRingEndpoint, isOpen *atomic.Uint32) error {
- if isOpen.Load() != 1 {
- return net.ErrClosed
- }
- if len(buf) > bytesPerPacket {
- return io.ErrShortBuffer
- }
- bind.tx.mu.Lock()
- defer bind.tx.mu.Unlock()
- var results [packetsPerRing]winrio.Result
- count := winrio.DequeueCompletion(bind.tx.cq, results[:])
- if count == 0 && bind.tx.isFull {
- err := winrio.Notify(bind.tx.cq)
- if err != nil {
- return err
- }
- var bytes uint32
- var key uintptr
- var overlapped *windows.Overlapped
- err = windows.GetQueuedCompletionStatus(bind.tx.iocp, &bytes, &key, &overlapped, windows.INFINITE)
- if err != nil {
- return err
- }
- if isOpen.Load() != 1 {
- return net.ErrClosed
- }
- count = winrio.DequeueCompletion(bind.tx.cq, results[:])
- if count == 0 {
- return io.ErrNoProgress
- }
- }
- if count > 0 {
- bind.tx.Return(count)
- }
- packet := bind.tx.Push()
- packet.addr = *nend
- copy(packet.data[:], buf)
- dataBuffer := &winrio.Buffer{
- Id: bind.tx.id,
- Offset: uint32(uintptr(unsafe.Pointer(&packet.data[0])) - bind.tx.packets),
- Length: uint32(len(buf)),
- }
- addressBuffer := &winrio.Buffer{
- Id: bind.tx.id,
- Offset: uint32(uintptr(unsafe.Pointer(&packet.addr)) - bind.tx.packets),
- Length: uint32(unsafe.Sizeof(packet.addr)),
- }
- bind.mu.Lock()
- defer bind.mu.Unlock()
- return winrio.SendEx(bind.rq, dataBuffer, 1, nil, addressBuffer, nil, nil, 0, 0)
-}
-
-func (bind *WinRingBind) Send(bufs [][]byte, endpoint Endpoint) error {
- nend, ok := endpoint.(*WinRingEndpoint)
- if !ok {
- return ErrWrongEndpointType
- }
- bind.mu.RLock()
- defer bind.mu.RUnlock()
- for _, buf := range bufs {
- switch nend.family {
- case windows.AF_INET:
- if bind.v4.blackhole {
- continue
- }
- if err := bind.v4.Send(buf, nend, &bind.isOpen); err != nil {
- return err
- }
- case windows.AF_INET6:
- if bind.v6.blackhole {
- continue
- }
- if err := bind.v6.Send(buf, nend, &bind.isOpen); err != nil {
- return err
- }
- }
- }
- return nil
-}
-
-func (s *StdNetBind) BindSocketToInterface4(interfaceIndex uint32, blackhole bool) error {
- s.mu.Lock()
- defer s.mu.Unlock()
- sysconn, err := s.ipv4.SyscallConn()
- if err != nil {
- return err
- }
- err2 := sysconn.Control(func(fd uintptr) {
- err = bindSocketToInterface4(windows.Handle(fd), interfaceIndex)
- })
- if err2 != nil {
- return err2
- }
- if err != nil {
- return err
- }
- s.blackhole4 = blackhole
- return nil
-}
-
-func (s *StdNetBind) BindSocketToInterface6(interfaceIndex uint32, blackhole bool) error {
- s.mu.Lock()
- defer s.mu.Unlock()
- sysconn, err := s.ipv6.SyscallConn()
- if err != nil {
- return err
- }
- err2 := sysconn.Control(func(fd uintptr) {
- err = bindSocketToInterface6(windows.Handle(fd), interfaceIndex)
- })
- if err2 != nil {
- return err2
- }
- if err != nil {
- return err
- }
- s.blackhole6 = blackhole
- return nil
-}
-
-func (bind *WinRingBind) BindSocketToInterface4(interfaceIndex uint32, blackhole bool) error {
- bind.mu.RLock()
- defer bind.mu.RUnlock()
- if bind.isOpen.Load() != 1 {
- return net.ErrClosed
- }
- err := bindSocketToInterface4(bind.v4.sock, interfaceIndex)
- if err != nil {
- return err
- }
- bind.v4.blackhole = blackhole
- return nil
-}
-
-func (bind *WinRingBind) BindSocketToInterface6(interfaceIndex uint32, blackhole bool) error {
- bind.mu.RLock()
- defer bind.mu.RUnlock()
- if bind.isOpen.Load() != 1 {
- return net.ErrClosed
- }
- err := bindSocketToInterface6(bind.v6.sock, interfaceIndex)
- if err != nil {
- return err
- }
- bind.v6.blackhole = blackhole
- return nil
-}
-
-func bindSocketToInterface4(handle windows.Handle, interfaceIndex uint32) error {
- const IP_UNICAST_IF = 31
- /* MSDN says for IPv4 this needs to be in net byte order, so that it's like an IP address with leading zeros. */
- var bytes [4]byte
- binary.BigEndian.PutUint32(bytes[:], interfaceIndex)
- interfaceIndex = *(*uint32)(unsafe.Pointer(&bytes[0]))
- err := windows.SetsockoptInt(handle, windows.IPPROTO_IP, IP_UNICAST_IF, int(interfaceIndex))
- if err != nil {
- return err
- }
- return nil
-}
-
-func bindSocketToInterface6(handle windows.Handle, interfaceIndex uint32) error {
- const IPV6_UNICAST_IF = 31
- return windows.SetsockoptInt(handle, windows.IPPROTO_IPV6, IPV6_UNICAST_IF, int(interfaceIndex))
-}
diff --git a/vendor/golang.zx2c4.com/wireguard/conn/boundif_android.go b/vendor/golang.zx2c4.com/wireguard/conn/boundif_android.go
deleted file mode 100644
index dd3ca5b076..0000000000
--- a/vendor/golang.zx2c4.com/wireguard/conn/boundif_android.go
+++ /dev/null
@@ -1,34 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2017-2023 WireGuard LLC. All Rights Reserved.
- */
-
-package conn
-
-func (s *StdNetBind) PeekLookAtSocketFd4() (fd int, err error) {
- sysconn, err := s.ipv4.SyscallConn()
- if err != nil {
- return -1, err
- }
- err = sysconn.Control(func(f uintptr) {
- fd = int(f)
- })
- if err != nil {
- return -1, err
- }
- return
-}
-
-func (s *StdNetBind) PeekLookAtSocketFd6() (fd int, err error) {
- sysconn, err := s.ipv6.SyscallConn()
- if err != nil {
- return -1, err
- }
- err = sysconn.Control(func(f uintptr) {
- fd = int(f)
- })
- if err != nil {
- return -1, err
- }
- return
-}
diff --git a/vendor/golang.zx2c4.com/wireguard/conn/conn.go b/vendor/golang.zx2c4.com/wireguard/conn/conn.go
deleted file mode 100644
index a1f57d2b1d..0000000000
--- a/vendor/golang.zx2c4.com/wireguard/conn/conn.go
+++ /dev/null
@@ -1,133 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2017-2023 WireGuard LLC. All Rights Reserved.
- */
-
-// Package conn implements WireGuard's network connections.
-package conn
-
-import (
- "errors"
- "fmt"
- "net/netip"
- "reflect"
- "runtime"
- "strings"
-)
-
-const (
- IdealBatchSize = 128 // maximum number of packets handled per read and write
-)
-
-// A ReceiveFunc receives at least one packet from the network and writes them
-// into packets. On a successful read it returns the number of elements of
-// sizes, packets, and endpoints that should be evaluated. Some elements of
-// sizes may be zero, and callers should ignore them. Callers must pass a sizes
-// and eps slice with a length greater than or equal to the length of packets.
-// These lengths must not exceed the length of the associated Bind.BatchSize().
-type ReceiveFunc func(packets [][]byte, sizes []int, eps []Endpoint) (n int, err error)
-
-// A Bind listens on a port for both IPv6 and IPv4 UDP traffic.
-//
-// A Bind interface may also be a PeekLookAtSocketFd or BindSocketToInterface,
-// depending on the platform-specific implementation.
-type Bind interface {
- // Open puts the Bind into a listening state on a given port and reports the actual
- // port that it bound to. Passing zero results in a random selection.
- // fns is the set of functions that will be called to receive packets.
- Open(port uint16) (fns []ReceiveFunc, actualPort uint16, err error)
-
- // Close closes the Bind listener.
- // All fns returned by Open must return net.ErrClosed after a call to Close.
- Close() error
-
- // SetMark sets the mark for each packet sent through this Bind.
- // This mark is passed to the kernel as the socket option SO_MARK.
- SetMark(mark uint32) error
-
- // Send writes one or more packets in bufs to address ep. The length of
- // bufs must not exceed BatchSize().
- Send(bufs [][]byte, ep Endpoint) error
-
- // ParseEndpoint creates a new endpoint from a string.
- ParseEndpoint(s string) (Endpoint, error)
-
- // BatchSize is the number of buffers expected to be passed to
- // the ReceiveFuncs, and the maximum expected to be passed to SendBatch.
- BatchSize() int
-}
-
-// BindSocketToInterface is implemented by Bind objects that support being
-// tied to a single network interface. Used by wireguard-windows.
-type BindSocketToInterface interface {
- BindSocketToInterface4(interfaceIndex uint32, blackhole bool) error
- BindSocketToInterface6(interfaceIndex uint32, blackhole bool) error
-}
-
-// PeekLookAtSocketFd is implemented by Bind objects that support having their
-// file descriptor peeked at. Used by wireguard-android.
-type PeekLookAtSocketFd interface {
- PeekLookAtSocketFd4() (fd int, err error)
- PeekLookAtSocketFd6() (fd int, err error)
-}
-
-// An Endpoint maintains the source/destination caching for a peer.
-//
-// dst: the remote address of a peer ("endpoint" in uapi terminology)
-// src: the local address from which datagrams originate going to the peer
-type Endpoint interface {
- ClearSrc() // clears the source address
- SrcToString() string // returns the local source address (ip:port)
- DstToString() string // returns the destination address (ip:port)
- DstToBytes() []byte // used for mac2 cookie calculations
- DstIP() netip.Addr
- SrcIP() netip.Addr
-}
-
-var (
- ErrBindAlreadyOpen = errors.New("bind is already open")
- ErrWrongEndpointType = errors.New("endpoint type does not correspond with bind type")
-)
-
-func (fn ReceiveFunc) PrettyName() string {
- name := runtime.FuncForPC(reflect.ValueOf(fn).Pointer()).Name()
- // 0. cheese/taco.beansIPv6.func12.func21218-fm
- name = strings.TrimSuffix(name, "-fm")
- // 1. cheese/taco.beansIPv6.func12.func21218
- if idx := strings.LastIndexByte(name, '/'); idx != -1 {
- name = name[idx+1:]
- // 2. taco.beansIPv6.func12.func21218
- }
- for {
- var idx int
- for idx = len(name) - 1; idx >= 0; idx-- {
- if name[idx] < '0' || name[idx] > '9' {
- break
- }
- }
- if idx == len(name)-1 {
- break
- }
- const dotFunc = ".func"
- if !strings.HasSuffix(name[:idx+1], dotFunc) {
- break
- }
- name = name[:idx+1-len(dotFunc)]
- // 3. taco.beansIPv6.func12
- // 4. taco.beansIPv6
- }
- if idx := strings.LastIndexByte(name, '.'); idx != -1 {
- name = name[idx+1:]
- // 5. beansIPv6
- }
- if name == "" {
- return fmt.Sprintf("%p", fn)
- }
- if strings.HasSuffix(name, "IPv4") {
- return "v4"
- }
- if strings.HasSuffix(name, "IPv6") {
- return "v6"
- }
- return name
-}
diff --git a/vendor/golang.zx2c4.com/wireguard/conn/controlfns.go b/vendor/golang.zx2c4.com/wireguard/conn/controlfns.go
deleted file mode 100644
index 4f7d90fa10..0000000000
--- a/vendor/golang.zx2c4.com/wireguard/conn/controlfns.go
+++ /dev/null
@@ -1,43 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2017-2023 WireGuard LLC. All Rights Reserved.
- */
-
-package conn
-
-import (
- "net"
- "syscall"
-)
-
-// UDP socket read/write buffer size (7MB). The value of 7MB is chosen as it is
-// the max supported by a default configuration of macOS. Some platforms will
-// silently clamp the value to other maximums, such as linux clamping to
-// net.core.{r,w}mem_max (see _linux.go for additional implementation that works
-// around this limitation)
-const socketBufferSize = 7 << 20
-
-// controlFn is the callback function signature from net.ListenConfig.Control.
-// It is used to apply platform specific configuration to the socket prior to
-// bind.
-type controlFn func(network, address string, c syscall.RawConn) error
-
-// controlFns is a list of functions that are called from the listen config
-// that can apply socket options.
-var controlFns = []controlFn{}
-
-// listenConfig returns a net.ListenConfig that applies the controlFns to the
-// socket prior to bind. This is used to apply socket buffer sizing and packet
-// information OOB configuration for sticky sockets.
-func listenConfig() *net.ListenConfig {
- return &net.ListenConfig{
- Control: func(network, address string, c syscall.RawConn) error {
- for _, fn := range controlFns {
- if err := fn(network, address, c); err != nil {
- return err
- }
- }
- return nil
- },
- }
-}
diff --git a/vendor/golang.zx2c4.com/wireguard/conn/controlfns_linux.go b/vendor/golang.zx2c4.com/wireguard/conn/controlfns_linux.go
deleted file mode 100644
index a2396fe899..0000000000
--- a/vendor/golang.zx2c4.com/wireguard/conn/controlfns_linux.go
+++ /dev/null
@@ -1,61 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2017-2023 WireGuard LLC. All Rights Reserved.
- */
-
-package conn
-
-import (
- "fmt"
- "runtime"
- "syscall"
-
- "golang.org/x/sys/unix"
-)
-
-func init() {
- controlFns = append(controlFns,
-
- // Attempt to set the socket buffer size beyond net.core.{r,w}mem_max by
- // using SO_*BUFFORCE. This requires CAP_NET_ADMIN, and is allowed here to
- // fail silently - the result of failure is lower performance on very fast
- // links or high latency links.
- func(network, address string, c syscall.RawConn) error {
- return c.Control(func(fd uintptr) {
- // Set up to *mem_max
- _ = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_RCVBUF, socketBufferSize)
- _ = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_SNDBUF, socketBufferSize)
- // Set beyond *mem_max if CAP_NET_ADMIN
- _ = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_RCVBUFFORCE, socketBufferSize)
- _ = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_SNDBUFFORCE, socketBufferSize)
- })
- },
-
- // Enable receiving of the packet information (IP_PKTINFO for IPv4,
- // IPV6_PKTINFO for IPv6) that is used to implement sticky socket support.
- func(network, address string, c syscall.RawConn) error {
- var err error
- switch network {
- case "udp4":
- if runtime.GOOS != "android" {
- c.Control(func(fd uintptr) {
- err = unix.SetsockoptInt(int(fd), unix.IPPROTO_IP, unix.IP_PKTINFO, 1)
- })
- }
- case "udp6":
- c.Control(func(fd uintptr) {
- if runtime.GOOS != "android" {
- err = unix.SetsockoptInt(int(fd), unix.IPPROTO_IPV6, unix.IPV6_RECVPKTINFO, 1)
- if err != nil {
- return
- }
- }
- err = unix.SetsockoptInt(int(fd), unix.IPPROTO_IPV6, unix.IPV6_V6ONLY, 1)
- })
- default:
- err = fmt.Errorf("unhandled network: %s: %w", network, unix.EINVAL)
- }
- return err
- },
- )
-}
diff --git a/vendor/golang.zx2c4.com/wireguard/conn/controlfns_unix.go b/vendor/golang.zx2c4.com/wireguard/conn/controlfns_unix.go
deleted file mode 100644
index 91692c0a65..0000000000
--- a/vendor/golang.zx2c4.com/wireguard/conn/controlfns_unix.go
+++ /dev/null
@@ -1,35 +0,0 @@
-//go:build !windows && !linux && !wasm
-
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2017-2023 WireGuard LLC. All Rights Reserved.
- */
-
-package conn
-
-import (
- "syscall"
-
- "golang.org/x/sys/unix"
-)
-
-func init() {
- controlFns = append(controlFns,
- func(network, address string, c syscall.RawConn) error {
- return c.Control(func(fd uintptr) {
- _ = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_RCVBUF, socketBufferSize)
- _ = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_SNDBUF, socketBufferSize)
- })
- },
-
- func(network, address string, c syscall.RawConn) error {
- var err error
- if network == "udp6" {
- c.Control(func(fd uintptr) {
- err = unix.SetsockoptInt(int(fd), unix.IPPROTO_IPV6, unix.IPV6_V6ONLY, 1)
- })
- }
- return err
- },
- )
-}
diff --git a/vendor/golang.zx2c4.com/wireguard/conn/controlfns_windows.go b/vendor/golang.zx2c4.com/wireguard/conn/controlfns_windows.go
deleted file mode 100644
index c3bdf7d3a9..0000000000
--- a/vendor/golang.zx2c4.com/wireguard/conn/controlfns_windows.go
+++ /dev/null
@@ -1,23 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2017-2023 WireGuard LLC. All Rights Reserved.
- */
-
-package conn
-
-import (
- "syscall"
-
- "golang.org/x/sys/windows"
-)
-
-func init() {
- controlFns = append(controlFns,
- func(network, address string, c syscall.RawConn) error {
- return c.Control(func(fd uintptr) {
- _ = windows.SetsockoptInt(windows.Handle(fd), windows.SOL_SOCKET, windows.SO_RCVBUF, socketBufferSize)
- _ = windows.SetsockoptInt(windows.Handle(fd), windows.SOL_SOCKET, windows.SO_SNDBUF, socketBufferSize)
- })
- },
- )
-}
diff --git a/vendor/golang.zx2c4.com/wireguard/conn/default.go b/vendor/golang.zx2c4.com/wireguard/conn/default.go
deleted file mode 100644
index b6f761b9ed..0000000000
--- a/vendor/golang.zx2c4.com/wireguard/conn/default.go
+++ /dev/null
@@ -1,10 +0,0 @@
-//go:build !windows
-
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2017-2023 WireGuard LLC. All Rights Reserved.
- */
-
-package conn
-
-func NewDefaultBind() Bind { return NewStdNetBind() }
diff --git a/vendor/golang.zx2c4.com/wireguard/conn/mark_default.go b/vendor/golang.zx2c4.com/wireguard/conn/mark_default.go
deleted file mode 100644
index 31023844a2..0000000000
--- a/vendor/golang.zx2c4.com/wireguard/conn/mark_default.go
+++ /dev/null
@@ -1,12 +0,0 @@
-//go:build !linux && !openbsd && !freebsd
-
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2017-2023 WireGuard LLC. All Rights Reserved.
- */
-
-package conn
-
-func (s *StdNetBind) SetMark(mark uint32) error {
- return nil
-}
diff --git a/vendor/golang.zx2c4.com/wireguard/conn/mark_unix.go b/vendor/golang.zx2c4.com/wireguard/conn/mark_unix.go
deleted file mode 100644
index d9e46eea7f..0000000000
--- a/vendor/golang.zx2c4.com/wireguard/conn/mark_unix.go
+++ /dev/null
@@ -1,65 +0,0 @@
-//go:build linux || openbsd || freebsd
-
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2017-2023 WireGuard LLC. All Rights Reserved.
- */
-
-package conn
-
-import (
- "runtime"
-
- "golang.org/x/sys/unix"
-)
-
-var fwmarkIoctl int
-
-func init() {
- switch runtime.GOOS {
- case "linux", "android":
- fwmarkIoctl = 36 /* unix.SO_MARK */
- case "freebsd":
- fwmarkIoctl = 0x1015 /* unix.SO_USER_COOKIE */
- case "openbsd":
- fwmarkIoctl = 0x1021 /* unix.SO_RTABLE */
- }
-}
-
-func (s *StdNetBind) SetMark(mark uint32) error {
- var operr error
- if fwmarkIoctl == 0 {
- return nil
- }
- if s.ipv4 != nil {
- fd, err := s.ipv4.SyscallConn()
- if err != nil {
- return err
- }
- err = fd.Control(func(fd uintptr) {
- operr = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, fwmarkIoctl, int(mark))
- })
- if err == nil {
- err = operr
- }
- if err != nil {
- return err
- }
- }
- if s.ipv6 != nil {
- fd, err := s.ipv6.SyscallConn()
- if err != nil {
- return err
- }
- err = fd.Control(func(fd uintptr) {
- operr = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, fwmarkIoctl, int(mark))
- })
- if err == nil {
- err = operr
- }
- if err != nil {
- return err
- }
- }
- return nil
-}
diff --git a/vendor/golang.zx2c4.com/wireguard/conn/sticky_default.go b/vendor/golang.zx2c4.com/wireguard/conn/sticky_default.go
deleted file mode 100644
index 1fa8a0c4bb..0000000000
--- a/vendor/golang.zx2c4.com/wireguard/conn/sticky_default.go
+++ /dev/null
@@ -1,41 +0,0 @@
-//go:build !linux || android
-
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2017-2023 WireGuard LLC. All Rights Reserved.
- */
-
-package conn
-
-import "net/netip"
-
-func (e *StdNetEndpoint) SrcIP() netip.Addr {
- return netip.Addr{}
-}
-
-func (e *StdNetEndpoint) SrcIfidx() int32 {
- return 0
-}
-
-func (e *StdNetEndpoint) SrcToString() string {
- return ""
-}
-
-// TODO: macOS, FreeBSD and other BSDs likely do support this feature set, but
-// use alternatively named flags and need ports and require testing.
-
-// getSrcFromControl parses the control for PKTINFO and if found updates ep with
-// the source information found.
-func getSrcFromControl(control []byte, ep *StdNetEndpoint) {
-}
-
-// setSrcControl parses the control for PKTINFO and if found updates ep with
-// the source information found.
-func setSrcControl(control *[]byte, ep *StdNetEndpoint) {
-}
-
-// srcControlSize returns the recommended buffer size for pooling sticky control
-// data.
-const srcControlSize = 0
-
-const StdNetSupportsStickySockets = false
diff --git a/vendor/golang.zx2c4.com/wireguard/conn/sticky_linux.go b/vendor/golang.zx2c4.com/wireguard/conn/sticky_linux.go
deleted file mode 100644
index a30ccc715c..0000000000
--- a/vendor/golang.zx2c4.com/wireguard/conn/sticky_linux.go
+++ /dev/null
@@ -1,110 +0,0 @@
-//go:build linux && !android
-
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2017-2023 WireGuard LLC. All Rights Reserved.
- */
-
-package conn
-
-import (
- "net/netip"
- "unsafe"
-
- "golang.org/x/sys/unix"
-)
-
-func (e *StdNetEndpoint) SrcIP() netip.Addr {
- switch len(e.src) {
- case unix.CmsgSpace(unix.SizeofInet4Pktinfo):
- info := (*unix.Inet4Pktinfo)(unsafe.Pointer(&e.src[unix.CmsgLen(0)]))
- return netip.AddrFrom4(info.Spec_dst)
- case unix.CmsgSpace(unix.SizeofInet6Pktinfo):
- info := (*unix.Inet6Pktinfo)(unsafe.Pointer(&e.src[unix.CmsgLen(0)]))
- // TODO: set zone. in order to do so we need to check if the address is
- // link local, and if it is perform a syscall to turn the ifindex into a
- // zone string because netip uses string zones.
- return netip.AddrFrom16(info.Addr)
- }
- return netip.Addr{}
-}
-
-func (e *StdNetEndpoint) SrcIfidx() int32 {
- switch len(e.src) {
- case unix.CmsgSpace(unix.SizeofInet4Pktinfo):
- info := (*unix.Inet4Pktinfo)(unsafe.Pointer(&e.src[unix.CmsgLen(0)]))
- return info.Ifindex
- case unix.CmsgSpace(unix.SizeofInet6Pktinfo):
- info := (*unix.Inet6Pktinfo)(unsafe.Pointer(&e.src[unix.CmsgLen(0)]))
- return int32(info.Ifindex)
- }
- return 0
-}
-
-func (e *StdNetEndpoint) SrcToString() string {
- return e.SrcIP().String()
-}
-
-// getSrcFromControl parses the control for PKTINFO and if found updates ep with
-// the source information found.
-func getSrcFromControl(control []byte, ep *StdNetEndpoint) {
- ep.ClearSrc()
-
- var (
- hdr unix.Cmsghdr
- data []byte
- rem []byte = control
- err error
- )
-
- for len(rem) > unix.SizeofCmsghdr {
- hdr, data, rem, err = unix.ParseOneSocketControlMessage(rem)
- if err != nil {
- return
- }
-
- if hdr.Level == unix.IPPROTO_IP &&
- hdr.Type == unix.IP_PKTINFO {
-
- if ep.src == nil || cap(ep.src) < unix.CmsgSpace(unix.SizeofInet4Pktinfo) {
- ep.src = make([]byte, 0, unix.CmsgSpace(unix.SizeofInet4Pktinfo))
- }
- ep.src = ep.src[:unix.CmsgSpace(unix.SizeofInet4Pktinfo)]
-
- hdrBuf := unsafe.Slice((*byte)(unsafe.Pointer(&hdr)), unix.SizeofCmsghdr)
- copy(ep.src, hdrBuf)
- copy(ep.src[unix.CmsgLen(0):], data)
- return
- }
-
- if hdr.Level == unix.IPPROTO_IPV6 &&
- hdr.Type == unix.IPV6_PKTINFO {
-
- if ep.src == nil || cap(ep.src) < unix.CmsgSpace(unix.SizeofInet6Pktinfo) {
- ep.src = make([]byte, 0, unix.CmsgSpace(unix.SizeofInet6Pktinfo))
- }
-
- ep.src = ep.src[:unix.CmsgSpace(unix.SizeofInet6Pktinfo)]
-
- hdrBuf := unsafe.Slice((*byte)(unsafe.Pointer(&hdr)), unix.SizeofCmsghdr)
- copy(ep.src, hdrBuf)
- copy(ep.src[unix.CmsgLen(0):], data)
- return
- }
- }
-}
-
-// setSrcControl sets an IP{V6}_PKTINFO in control based on the source address
-// and source ifindex found in ep. control's len will be set to 0 in the event
-// that ep is a default value.
-func setSrcControl(control *[]byte, ep *StdNetEndpoint) {
- if cap(*control) < len(ep.src) {
- return
- }
- *control = (*control)[:0]
- *control = append(*control, ep.src...)
-}
-
-var srcControlSize = unix.CmsgSpace(unix.SizeofInet6Pktinfo)
-
-const StdNetSupportsStickySockets = true
diff --git a/vendor/golang.zx2c4.com/wireguard/conn/winrio/rio_windows.go b/vendor/golang.zx2c4.com/wireguard/conn/winrio/rio_windows.go
deleted file mode 100644
index d1037bba90..0000000000
--- a/vendor/golang.zx2c4.com/wireguard/conn/winrio/rio_windows.go
+++ /dev/null
@@ -1,254 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2017-2023 WireGuard LLC. All Rights Reserved.
- */
-
-package winrio
-
-import (
- "log"
- "sync"
- "syscall"
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-const (
- MsgDontNotify = 1
- MsgDefer = 2
- MsgWaitAll = 4
- MsgCommitOnly = 8
-
- MaxCqSize = 0x8000000
-
- invalidBufferId = 0xFFFFFFFF
- invalidCq = 0
- invalidRq = 0
- corruptCq = 0xFFFFFFFF
-)
-
-var extensionFunctionTable struct {
- cbSize uint32
- rioReceive uintptr
- rioReceiveEx uintptr
- rioSend uintptr
- rioSendEx uintptr
- rioCloseCompletionQueue uintptr
- rioCreateCompletionQueue uintptr
- rioCreateRequestQueue uintptr
- rioDequeueCompletion uintptr
- rioDeregisterBuffer uintptr
- rioNotify uintptr
- rioRegisterBuffer uintptr
- rioResizeCompletionQueue uintptr
- rioResizeRequestQueue uintptr
-}
-
-type Cq uintptr
-
-type Rq uintptr
-
-type BufferId uintptr
-
-type Buffer struct {
- Id BufferId
- Offset uint32
- Length uint32
-}
-
-type Result struct {
- Status int32
- BytesTransferred uint32
- SocketContext uint64
- RequestContext uint64
-}
-
-type notificationCompletionType uint32
-
-const (
- eventCompletion notificationCompletionType = 1
- iocpCompletion notificationCompletionType = 2
-)
-
-type eventNotificationCompletion struct {
- completionType notificationCompletionType
- event windows.Handle
- notifyReset uint32
-}
-
-type iocpNotificationCompletion struct {
- completionType notificationCompletionType
- iocp windows.Handle
- key uintptr
- overlapped *windows.Overlapped
-}
-
-var (
- initialized sync.Once
- available bool
-)
-
-func Initialize() bool {
- initialized.Do(func() {
- var (
- err error
- socket windows.Handle
- cq Cq
- )
- defer func() {
- if err == nil {
- return
- }
- if maj, _, _ := windows.RtlGetNtVersionNumbers(); maj <= 7 {
- return
- }
- log.Printf("Registered I/O is unavailable: %v", err)
- }()
- socket, err = Socket(windows.AF_INET, windows.SOCK_DGRAM, windows.IPPROTO_UDP)
- if err != nil {
- return
- }
- defer windows.CloseHandle(socket)
- WSAID_MULTIPLE_RIO := &windows.GUID{0x8509e081, 0x96dd, 0x4005, [8]byte{0xb1, 0x65, 0x9e, 0x2e, 0xe8, 0xc7, 0x9e, 0x3f}}
- const SIO_GET_MULTIPLE_EXTENSION_FUNCTION_POINTER = 0xc8000024
- ob := uint32(0)
- err = windows.WSAIoctl(socket, SIO_GET_MULTIPLE_EXTENSION_FUNCTION_POINTER,
- (*byte)(unsafe.Pointer(WSAID_MULTIPLE_RIO)), uint32(unsafe.Sizeof(*WSAID_MULTIPLE_RIO)),
- (*byte)(unsafe.Pointer(&extensionFunctionTable)), uint32(unsafe.Sizeof(extensionFunctionTable)),
- &ob, nil, 0)
- if err != nil {
- return
- }
-
- // While we should be able to stop here, after getting the function pointers, some anti-virus actually causes
- // failures in RIOCreateRequestQueue, so keep going to be certain this is supported.
- var iocp windows.Handle
- iocp, err = windows.CreateIoCompletionPort(windows.InvalidHandle, 0, 0, 0)
- if err != nil {
- return
- }
- defer windows.CloseHandle(iocp)
- var overlapped windows.Overlapped
- cq, err = CreateIOCPCompletionQueue(2, iocp, 0, &overlapped)
- if err != nil {
- return
- }
- defer CloseCompletionQueue(cq)
- _, err = CreateRequestQueue(socket, 1, 1, 1, 1, cq, cq, 0)
- if err != nil {
- return
- }
- available = true
- })
- return available
-}
-
-func Socket(af, typ, proto int32) (windows.Handle, error) {
- return windows.WSASocket(af, typ, proto, nil, 0, windows.WSA_FLAG_REGISTERED_IO)
-}
-
-func CloseCompletionQueue(cq Cq) {
- _, _, _ = syscall.Syscall(extensionFunctionTable.rioCloseCompletionQueue, 1, uintptr(cq), 0, 0)
-}
-
-func CreateEventCompletionQueue(queueSize uint32, event windows.Handle, notifyReset bool) (Cq, error) {
- notificationCompletion := &eventNotificationCompletion{
- completionType: eventCompletion,
- event: event,
- }
- if notifyReset {
- notificationCompletion.notifyReset = 1
- }
- ret, _, err := syscall.Syscall(extensionFunctionTable.rioCreateCompletionQueue, 2, uintptr(queueSize), uintptr(unsafe.Pointer(notificationCompletion)), 0)
- if ret == invalidCq {
- return 0, err
- }
- return Cq(ret), nil
-}
-
-func CreateIOCPCompletionQueue(queueSize uint32, iocp windows.Handle, key uintptr, overlapped *windows.Overlapped) (Cq, error) {
- notificationCompletion := &iocpNotificationCompletion{
- completionType: iocpCompletion,
- iocp: iocp,
- key: key,
- overlapped: overlapped,
- }
- ret, _, err := syscall.Syscall(extensionFunctionTable.rioCreateCompletionQueue, 2, uintptr(queueSize), uintptr(unsafe.Pointer(notificationCompletion)), 0)
- if ret == invalidCq {
- return 0, err
- }
- return Cq(ret), nil
-}
-
-func CreatePolledCompletionQueue(queueSize uint32) (Cq, error) {
- ret, _, err := syscall.Syscall(extensionFunctionTable.rioCreateCompletionQueue, 2, uintptr(queueSize), 0, 0)
- if ret == invalidCq {
- return 0, err
- }
- return Cq(ret), nil
-}
-
-func CreateRequestQueue(socket windows.Handle, maxOutstandingReceive, maxReceiveDataBuffers, maxOutstandingSend, maxSendDataBuffers uint32, receiveCq, sendCq Cq, socketContext uintptr) (Rq, error) {
- ret, _, err := syscall.Syscall9(extensionFunctionTable.rioCreateRequestQueue, 8, uintptr(socket), uintptr(maxOutstandingReceive), uintptr(maxReceiveDataBuffers), uintptr(maxOutstandingSend), uintptr(maxSendDataBuffers), uintptr(receiveCq), uintptr(sendCq), socketContext, 0)
- if ret == invalidRq {
- return 0, err
- }
- return Rq(ret), nil
-}
-
-func DequeueCompletion(cq Cq, results []Result) uint32 {
- var array uintptr
- if len(results) > 0 {
- array = uintptr(unsafe.Pointer(&results[0]))
- }
- ret, _, _ := syscall.Syscall(extensionFunctionTable.rioDequeueCompletion, 3, uintptr(cq), array, uintptr(len(results)))
- if ret == corruptCq {
- panic("cq is corrupt")
- }
- return uint32(ret)
-}
-
-func DeregisterBuffer(id BufferId) {
- _, _, _ = syscall.Syscall(extensionFunctionTable.rioDeregisterBuffer, 1, uintptr(id), 0, 0)
-}
-
-func RegisterBuffer(buffer []byte) (BufferId, error) {
- var buf unsafe.Pointer
- if len(buffer) > 0 {
- buf = unsafe.Pointer(&buffer[0])
- }
- return RegisterPointer(buf, uint32(len(buffer)))
-}
-
-func RegisterPointer(ptr unsafe.Pointer, size uint32) (BufferId, error) {
- ret, _, err := syscall.Syscall(extensionFunctionTable.rioRegisterBuffer, 2, uintptr(ptr), uintptr(size), 0)
- if ret == invalidBufferId {
- return 0, err
- }
- return BufferId(ret), nil
-}
-
-func SendEx(rq Rq, buf *Buffer, dataBufferCount uint32, localAddress, remoteAddress, controlContext, flags *Buffer, sflags uint32, requestContext uintptr) error {
- ret, _, err := syscall.Syscall9(extensionFunctionTable.rioSendEx, 9, uintptr(rq), uintptr(unsafe.Pointer(buf)), uintptr(dataBufferCount), uintptr(unsafe.Pointer(localAddress)), uintptr(unsafe.Pointer(remoteAddress)), uintptr(unsafe.Pointer(controlContext)), uintptr(unsafe.Pointer(flags)), uintptr(sflags), requestContext)
- if ret == 0 {
- return err
- }
- return nil
-}
-
-func ReceiveEx(rq Rq, buf *Buffer, dataBufferCount uint32, localAddress, remoteAddress, controlContext, flags *Buffer, sflags uint32, requestContext uintptr) error {
- ret, _, err := syscall.Syscall9(extensionFunctionTable.rioReceiveEx, 9, uintptr(rq), uintptr(unsafe.Pointer(buf)), uintptr(dataBufferCount), uintptr(unsafe.Pointer(localAddress)), uintptr(unsafe.Pointer(remoteAddress)), uintptr(unsafe.Pointer(controlContext)), uintptr(unsafe.Pointer(flags)), uintptr(sflags), requestContext)
- if ret == 0 {
- return err
- }
- return nil
-}
-
-func Notify(cq Cq) error {
- ret, _, _ := syscall.Syscall(extensionFunctionTable.rioNotify, 1, uintptr(cq), 0, 0)
- if ret != 0 {
- return windows.Errno(ret)
- }
- return nil
-}
diff --git a/vendor/golang.zx2c4.com/wireguard/rwcancel/rwcancel.go b/vendor/golang.zx2c4.com/wireguard/rwcancel/rwcancel.go
index e397c0e8ae..63e1510b10 100644
--- a/vendor/golang.zx2c4.com/wireguard/rwcancel/rwcancel.go
+++ b/vendor/golang.zx2c4.com/wireguard/rwcancel/rwcancel.go
@@ -1,4 +1,4 @@
-//go:build !windows && !wasm
+//go:build !windows && !js
/* SPDX-License-Identifier: MIT
*
diff --git a/vendor/golang.zx2c4.com/wireguard/rwcancel/rwcancel_stub.go b/vendor/golang.zx2c4.com/wireguard/rwcancel/rwcancel_stub.go
index 2a98b2b4ad..182940b32e 100644
--- a/vendor/golang.zx2c4.com/wireguard/rwcancel/rwcancel_stub.go
+++ b/vendor/golang.zx2c4.com/wireguard/rwcancel/rwcancel_stub.go
@@ -1,4 +1,4 @@
-//go:build windows || wasm
+//go:build windows || js
// SPDX-License-Identifier: MIT
diff --git a/vendor/golang.zx2c4.com/wireguard/tun/checksum.go b/vendor/golang.zx2c4.com/wireguard/tun/checksum.go
deleted file mode 100644
index f4f847164a..0000000000
--- a/vendor/golang.zx2c4.com/wireguard/tun/checksum.go
+++ /dev/null
@@ -1,42 +0,0 @@
-package tun
-
-import "encoding/binary"
-
-// TODO: Explore SIMD and/or other assembly optimizations.
-func checksumNoFold(b []byte, initial uint64) uint64 {
- ac := initial
- i := 0
- n := len(b)
- for n >= 4 {
- ac += uint64(binary.BigEndian.Uint32(b[i : i+4]))
- n -= 4
- i += 4
- }
- for n >= 2 {
- ac += uint64(binary.BigEndian.Uint16(b[i : i+2]))
- n -= 2
- i += 2
- }
- if n == 1 {
- ac += uint64(b[i]) << 8
- }
- return ac
-}
-
-func checksum(b []byte, initial uint64) uint16 {
- ac := checksumNoFold(b, initial)
- ac = (ac >> 16) + (ac & 0xffff)
- ac = (ac >> 16) + (ac & 0xffff)
- ac = (ac >> 16) + (ac & 0xffff)
- ac = (ac >> 16) + (ac & 0xffff)
- return uint16(ac)
-}
-
-func pseudoHeaderChecksumNoFold(protocol uint8, srcAddr, dstAddr []byte, totalLen uint16) uint64 {
- sum := checksumNoFold(srcAddr, 0)
- sum = checksumNoFold(dstAddr, sum)
- sum = checksumNoFold([]byte{0, protocol}, sum)
- tmp := make([]byte, 2)
- binary.BigEndian.PutUint16(tmp, totalLen)
- return checksumNoFold(tmp, sum)
-}
diff --git a/vendor/golang.zx2c4.com/wireguard/tun/errors.go b/vendor/golang.zx2c4.com/wireguard/tun/errors.go
deleted file mode 100644
index 75ae3a434a..0000000000
--- a/vendor/golang.zx2c4.com/wireguard/tun/errors.go
+++ /dev/null
@@ -1,12 +0,0 @@
-package tun
-
-import (
- "errors"
-)
-
-var (
- // ErrTooManySegments is returned by Device.Read() when segmentation
- // overflows the length of supplied buffers. This error should not cause
- // reads to cease.
- ErrTooManySegments = errors.New("too many segments")
-)
diff --git a/vendor/golang.zx2c4.com/wireguard/tun/tcp_offload_linux.go b/vendor/golang.zx2c4.com/wireguard/tun/tcp_offload_linux.go
deleted file mode 100644
index 39a7180c5a..0000000000
--- a/vendor/golang.zx2c4.com/wireguard/tun/tcp_offload_linux.go
+++ /dev/null
@@ -1,627 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2017-2023 WireGuard LLC. All Rights Reserved.
- */
-
-package tun
-
-import (
- "bytes"
- "encoding/binary"
- "errors"
- "io"
- "unsafe"
-
- "golang.org/x/sys/unix"
- "golang.zx2c4.com/wireguard/conn"
-)
-
-const tcpFlagsOffset = 13
-
-const (
- tcpFlagFIN uint8 = 0x01
- tcpFlagPSH uint8 = 0x08
- tcpFlagACK uint8 = 0x10
-)
-
-// virtioNetHdr is defined in the kernel in include/uapi/linux/virtio_net.h. The
-// kernel symbol is virtio_net_hdr.
-type virtioNetHdr struct {
- flags uint8
- gsoType uint8
- hdrLen uint16
- gsoSize uint16
- csumStart uint16
- csumOffset uint16
-}
-
-func (v *virtioNetHdr) decode(b []byte) error {
- if len(b) < virtioNetHdrLen {
- return io.ErrShortBuffer
- }
- copy(unsafe.Slice((*byte)(unsafe.Pointer(v)), virtioNetHdrLen), b[:virtioNetHdrLen])
- return nil
-}
-
-func (v *virtioNetHdr) encode(b []byte) error {
- if len(b) < virtioNetHdrLen {
- return io.ErrShortBuffer
- }
- copy(b[:virtioNetHdrLen], unsafe.Slice((*byte)(unsafe.Pointer(v)), virtioNetHdrLen))
- return nil
-}
-
-const (
- // virtioNetHdrLen is the length in bytes of virtioNetHdr. This matches the
- // shape of the C ABI for its kernel counterpart -- sizeof(virtio_net_hdr).
- virtioNetHdrLen = int(unsafe.Sizeof(virtioNetHdr{}))
-)
-
-// flowKey represents the key for a flow.
-type flowKey struct {
- srcAddr, dstAddr [16]byte
- srcPort, dstPort uint16
- rxAck uint32 // varying ack values should not be coalesced. Treat them as separate flows.
-}
-
-// tcpGROTable holds flow and coalescing information for the purposes of GRO.
-type tcpGROTable struct {
- itemsByFlow map[flowKey][]tcpGROItem
- itemsPool [][]tcpGROItem
-}
-
-func newTCPGROTable() *tcpGROTable {
- t := &tcpGROTable{
- itemsByFlow: make(map[flowKey][]tcpGROItem, conn.IdealBatchSize),
- itemsPool: make([][]tcpGROItem, conn.IdealBatchSize),
- }
- for i := range t.itemsPool {
- t.itemsPool[i] = make([]tcpGROItem, 0, conn.IdealBatchSize)
- }
- return t
-}
-
-func newFlowKey(pkt []byte, srcAddr, dstAddr, tcphOffset int) flowKey {
- key := flowKey{}
- addrSize := dstAddr - srcAddr
- copy(key.srcAddr[:], pkt[srcAddr:dstAddr])
- copy(key.dstAddr[:], pkt[dstAddr:dstAddr+addrSize])
- key.srcPort = binary.BigEndian.Uint16(pkt[tcphOffset:])
- key.dstPort = binary.BigEndian.Uint16(pkt[tcphOffset+2:])
- key.rxAck = binary.BigEndian.Uint32(pkt[tcphOffset+8:])
- return key
-}
-
-// lookupOrInsert looks up a flow for the provided packet and metadata,
-// returning the packets found for the flow, or inserting a new one if none
-// is found.
-func (t *tcpGROTable) lookupOrInsert(pkt []byte, srcAddrOffset, dstAddrOffset, tcphOffset, tcphLen, bufsIndex int) ([]tcpGROItem, bool) {
- key := newFlowKey(pkt, srcAddrOffset, dstAddrOffset, tcphOffset)
- items, ok := t.itemsByFlow[key]
- if ok {
- return items, ok
- }
- // TODO: insert() performs another map lookup. This could be rearranged to avoid.
- t.insert(pkt, srcAddrOffset, dstAddrOffset, tcphOffset, tcphLen, bufsIndex)
- return nil, false
-}
-
-// insert an item in the table for the provided packet and packet metadata.
-func (t *tcpGROTable) insert(pkt []byte, srcAddrOffset, dstAddrOffset, tcphOffset, tcphLen, bufsIndex int) {
- key := newFlowKey(pkt, srcAddrOffset, dstAddrOffset, tcphOffset)
- item := tcpGROItem{
- key: key,
- bufsIndex: uint16(bufsIndex),
- gsoSize: uint16(len(pkt[tcphOffset+tcphLen:])),
- iphLen: uint8(tcphOffset),
- tcphLen: uint8(tcphLen),
- sentSeq: binary.BigEndian.Uint32(pkt[tcphOffset+4:]),
- pshSet: pkt[tcphOffset+tcpFlagsOffset]&tcpFlagPSH != 0,
- }
- items, ok := t.itemsByFlow[key]
- if !ok {
- items = t.newItems()
- }
- items = append(items, item)
- t.itemsByFlow[key] = items
-}
-
-func (t *tcpGROTable) updateAt(item tcpGROItem, i int) {
- items, _ := t.itemsByFlow[item.key]
- items[i] = item
-}
-
-func (t *tcpGROTable) deleteAt(key flowKey, i int) {
- items, _ := t.itemsByFlow[key]
- items = append(items[:i], items[i+1:]...)
- t.itemsByFlow[key] = items
-}
-
-// tcpGROItem represents bookkeeping data for a TCP packet during the lifetime
-// of a GRO evaluation across a vector of packets.
-type tcpGROItem struct {
- key flowKey
- sentSeq uint32 // the sequence number
- bufsIndex uint16 // the index into the original bufs slice
- numMerged uint16 // the number of packets merged into this item
- gsoSize uint16 // payload size
- iphLen uint8 // ip header len
- tcphLen uint8 // tcp header len
- pshSet bool // psh flag is set
-}
-
-func (t *tcpGROTable) newItems() []tcpGROItem {
- var items []tcpGROItem
- items, t.itemsPool = t.itemsPool[len(t.itemsPool)-1], t.itemsPool[:len(t.itemsPool)-1]
- return items
-}
-
-func (t *tcpGROTable) reset() {
- for k, items := range t.itemsByFlow {
- items = items[:0]
- t.itemsPool = append(t.itemsPool, items)
- delete(t.itemsByFlow, k)
- }
-}
-
-// canCoalesce represents the outcome of checking if two TCP packets are
-// candidates for coalescing.
-type canCoalesce int
-
-const (
- coalescePrepend canCoalesce = -1
- coalesceUnavailable canCoalesce = 0
- coalesceAppend canCoalesce = 1
-)
-
-// tcpPacketsCanCoalesce evaluates if pkt can be coalesced with the packet
-// described by item. This function makes considerations that match the kernel's
-// GRO self tests, which can be found in tools/testing/selftests/net/gro.c.
-func tcpPacketsCanCoalesce(pkt []byte, iphLen, tcphLen uint8, seq uint32, pshSet bool, gsoSize uint16, item tcpGROItem, bufs [][]byte, bufsOffset int) canCoalesce {
- pktTarget := bufs[item.bufsIndex][bufsOffset:]
- if tcphLen != item.tcphLen {
- // cannot coalesce with unequal tcp options len
- return coalesceUnavailable
- }
- if tcphLen > 20 {
- if !bytes.Equal(pkt[iphLen+20:iphLen+tcphLen], pktTarget[item.iphLen+20:iphLen+tcphLen]) {
- // cannot coalesce with unequal tcp options
- return coalesceUnavailable
- }
- }
- if pkt[0]>>4 == 6 {
- if pkt[0] != pktTarget[0] || pkt[1]>>4 != pktTarget[1]>>4 {
- // cannot coalesce with unequal Traffic class values
- return coalesceUnavailable
- }
- if pkt[7] != pktTarget[7] {
- // cannot coalesce with unequal Hop limit values
- return coalesceUnavailable
- }
- } else {
- if pkt[1] != pktTarget[1] {
- // cannot coalesce with unequal ToS values
- return coalesceUnavailable
- }
- if pkt[6]>>5 != pktTarget[6]>>5 {
- // cannot coalesce with unequal DF or reserved bits. MF is checked
- // further up the stack.
- return coalesceUnavailable
- }
- if pkt[8] != pktTarget[8] {
- // cannot coalesce with unequal TTL values
- return coalesceUnavailable
- }
- }
- // seq adjacency
- lhsLen := item.gsoSize
- lhsLen += item.numMerged * item.gsoSize
- if seq == item.sentSeq+uint32(lhsLen) { // pkt aligns following item from a seq num perspective
- if item.pshSet {
- // We cannot append to a segment that has the PSH flag set, PSH
- // can only be set on the final segment in a reassembled group.
- return coalesceUnavailable
- }
- if len(pktTarget[iphLen+tcphLen:])%int(item.gsoSize) != 0 {
- // A smaller than gsoSize packet has been appended previously.
- // Nothing can come after a smaller packet on the end.
- return coalesceUnavailable
- }
- if gsoSize > item.gsoSize {
- // We cannot have a larger packet following a smaller one.
- return coalesceUnavailable
- }
- return coalesceAppend
- } else if seq+uint32(gsoSize) == item.sentSeq { // pkt aligns in front of item from a seq num perspective
- if pshSet {
- // We cannot prepend with a segment that has the PSH flag set, PSH
- // can only be set on the final segment in a reassembled group.
- return coalesceUnavailable
- }
- if gsoSize < item.gsoSize {
- // We cannot have a larger packet following a smaller one.
- return coalesceUnavailable
- }
- if gsoSize > item.gsoSize && item.numMerged > 0 {
- // There's at least one previous merge, and we're larger than all
- // previous. This would put multiple smaller packets on the end.
- return coalesceUnavailable
- }
- return coalescePrepend
- }
- return coalesceUnavailable
-}
-
-func tcpChecksumValid(pkt []byte, iphLen uint8, isV6 bool) bool {
- srcAddrAt := ipv4SrcAddrOffset
- addrSize := 4
- if isV6 {
- srcAddrAt = ipv6SrcAddrOffset
- addrSize = 16
- }
- tcpTotalLen := uint16(len(pkt) - int(iphLen))
- tcpCSumNoFold := pseudoHeaderChecksumNoFold(unix.IPPROTO_TCP, pkt[srcAddrAt:srcAddrAt+addrSize], pkt[srcAddrAt+addrSize:srcAddrAt+addrSize*2], tcpTotalLen)
- return ^checksum(pkt[iphLen:], tcpCSumNoFold) == 0
-}
-
-// coalesceResult represents the result of attempting to coalesce two TCP
-// packets.
-type coalesceResult int
-
-const (
- coalesceInsufficientCap coalesceResult = 0
- coalescePSHEnding coalesceResult = 1
- coalesceItemInvalidCSum coalesceResult = 2
- coalescePktInvalidCSum coalesceResult = 3
- coalesceSuccess coalesceResult = 4
-)
-
-// coalesceTCPPackets attempts to coalesce pkt with the packet described by
-// item, returning the outcome. This function may swap bufs elements in the
-// event of a prepend as item's bufs index is already being tracked for writing
-// to a Device.
-func coalesceTCPPackets(mode canCoalesce, pkt []byte, pktBuffsIndex int, gsoSize uint16, seq uint32, pshSet bool, item *tcpGROItem, bufs [][]byte, bufsOffset int, isV6 bool) coalesceResult {
- var pktHead []byte // the packet that will end up at the front
- headersLen := item.iphLen + item.tcphLen
- coalescedLen := len(bufs[item.bufsIndex][bufsOffset:]) + len(pkt) - int(headersLen)
-
- // Copy data
- if mode == coalescePrepend {
- pktHead = pkt
- if cap(pkt)-bufsOffset < coalescedLen {
- // We don't want to allocate a new underlying array if capacity is
- // too small.
- return coalesceInsufficientCap
- }
- if pshSet {
- return coalescePSHEnding
- }
- if item.numMerged == 0 {
- if !tcpChecksumValid(bufs[item.bufsIndex][bufsOffset:], item.iphLen, isV6) {
- return coalesceItemInvalidCSum
- }
- }
- if !tcpChecksumValid(pkt, item.iphLen, isV6) {
- return coalescePktInvalidCSum
- }
- item.sentSeq = seq
- extendBy := coalescedLen - len(pktHead)
- bufs[pktBuffsIndex] = append(bufs[pktBuffsIndex], make([]byte, extendBy)...)
- copy(bufs[pktBuffsIndex][bufsOffset+len(pkt):], bufs[item.bufsIndex][bufsOffset+int(headersLen):])
- // Flip the slice headers in bufs as part of prepend. The index of item
- // is already being tracked for writing.
- bufs[item.bufsIndex], bufs[pktBuffsIndex] = bufs[pktBuffsIndex], bufs[item.bufsIndex]
- } else {
- pktHead = bufs[item.bufsIndex][bufsOffset:]
- if cap(pktHead)-bufsOffset < coalescedLen {
- // We don't want to allocate a new underlying array if capacity is
- // too small.
- return coalesceInsufficientCap
- }
- if item.numMerged == 0 {
- if !tcpChecksumValid(bufs[item.bufsIndex][bufsOffset:], item.iphLen, isV6) {
- return coalesceItemInvalidCSum
- }
- }
- if !tcpChecksumValid(pkt, item.iphLen, isV6) {
- return coalescePktInvalidCSum
- }
- if pshSet {
- // We are appending a segment with PSH set.
- item.pshSet = pshSet
- pktHead[item.iphLen+tcpFlagsOffset] |= tcpFlagPSH
- }
- extendBy := len(pkt) - int(headersLen)
- bufs[item.bufsIndex] = append(bufs[item.bufsIndex], make([]byte, extendBy)...)
- copy(bufs[item.bufsIndex][bufsOffset+len(pktHead):], pkt[headersLen:])
- }
-
- if gsoSize > item.gsoSize {
- item.gsoSize = gsoSize
- }
- hdr := virtioNetHdr{
- flags: unix.VIRTIO_NET_HDR_F_NEEDS_CSUM, // this turns into CHECKSUM_PARTIAL in the skb
- hdrLen: uint16(headersLen),
- gsoSize: uint16(item.gsoSize),
- csumStart: uint16(item.iphLen),
- csumOffset: 16,
- }
-
- // Recalculate the total len (IPv4) or payload len (IPv6). Recalculate the
- // (IPv4) header checksum.
- if isV6 {
- hdr.gsoType = unix.VIRTIO_NET_HDR_GSO_TCPV6
- binary.BigEndian.PutUint16(pktHead[4:], uint16(coalescedLen)-uint16(item.iphLen)) // set new payload len
- } else {
- hdr.gsoType = unix.VIRTIO_NET_HDR_GSO_TCPV4
- pktHead[10], pktHead[11] = 0, 0 // clear checksum field
- binary.BigEndian.PutUint16(pktHead[2:], uint16(coalescedLen)) // set new total length
- iphCSum := ^checksum(pktHead[:item.iphLen], 0) // compute checksum
- binary.BigEndian.PutUint16(pktHead[10:], iphCSum) // set checksum field
- }
- hdr.encode(bufs[item.bufsIndex][bufsOffset-virtioNetHdrLen:])
-
- // Calculate the pseudo header checksum and place it at the TCP checksum
- // offset. Downstream checksum offloading will combine this with computation
- // of the tcp header and payload checksum.
- addrLen := 4
- addrOffset := ipv4SrcAddrOffset
- if isV6 {
- addrLen = 16
- addrOffset = ipv6SrcAddrOffset
- }
- srcAddrAt := bufsOffset + addrOffset
- srcAddr := bufs[item.bufsIndex][srcAddrAt : srcAddrAt+addrLen]
- dstAddr := bufs[item.bufsIndex][srcAddrAt+addrLen : srcAddrAt+addrLen*2]
- psum := pseudoHeaderChecksumNoFold(unix.IPPROTO_TCP, srcAddr, dstAddr, uint16(coalescedLen-int(item.iphLen)))
- binary.BigEndian.PutUint16(pktHead[hdr.csumStart+hdr.csumOffset:], checksum([]byte{}, psum))
-
- item.numMerged++
- return coalesceSuccess
-}
-
-const (
- ipv4FlagMoreFragments uint8 = 0x20
-)
-
-const (
- ipv4SrcAddrOffset = 12
- ipv6SrcAddrOffset = 8
- maxUint16 = 1<<16 - 1
-)
-
-// tcpGRO evaluates the TCP packet at pktI in bufs for coalescing with
-// existing packets tracked in table. It will return false when pktI is not
-// coalesced, otherwise true. This indicates to the caller if bufs[pktI]
-// should be written to the Device.
-func tcpGRO(bufs [][]byte, offset int, pktI int, table *tcpGROTable, isV6 bool) (pktCoalesced bool) {
- pkt := bufs[pktI][offset:]
- if len(pkt) > maxUint16 {
- // A valid IPv4 or IPv6 packet will never exceed this.
- return false
- }
- iphLen := int((pkt[0] & 0x0F) * 4)
- if isV6 {
- iphLen = 40
- ipv6HPayloadLen := int(binary.BigEndian.Uint16(pkt[4:]))
- if ipv6HPayloadLen != len(pkt)-iphLen {
- return false
- }
- } else {
- totalLen := int(binary.BigEndian.Uint16(pkt[2:]))
- if totalLen != len(pkt) {
- return false
- }
- }
- if len(pkt) < iphLen {
- return false
- }
- tcphLen := int((pkt[iphLen+12] >> 4) * 4)
- if tcphLen < 20 || tcphLen > 60 {
- return false
- }
- if len(pkt) < iphLen+tcphLen {
- return false
- }
- if !isV6 {
- if pkt[6]&ipv4FlagMoreFragments != 0 || pkt[6]<<3 != 0 || pkt[7] != 0 {
- // no GRO support for fragmented segments for now
- return false
- }
- }
- tcpFlags := pkt[iphLen+tcpFlagsOffset]
- var pshSet bool
- // not a candidate if any non-ACK flags (except PSH+ACK) are set
- if tcpFlags != tcpFlagACK {
- if pkt[iphLen+tcpFlagsOffset] != tcpFlagACK|tcpFlagPSH {
- return false
- }
- pshSet = true
- }
- gsoSize := uint16(len(pkt) - tcphLen - iphLen)
- // not a candidate if payload len is 0
- if gsoSize < 1 {
- return false
- }
- seq := binary.BigEndian.Uint32(pkt[iphLen+4:])
- srcAddrOffset := ipv4SrcAddrOffset
- addrLen := 4
- if isV6 {
- srcAddrOffset = ipv6SrcAddrOffset
- addrLen = 16
- }
- items, existing := table.lookupOrInsert(pkt, srcAddrOffset, srcAddrOffset+addrLen, iphLen, tcphLen, pktI)
- if !existing {
- return false
- }
- for i := len(items) - 1; i >= 0; i-- {
- // In the best case of packets arriving in order iterating in reverse is
- // more efficient if there are multiple items for a given flow. This
- // also enables a natural table.deleteAt() in the
- // coalesceItemInvalidCSum case without the need for index tracking.
- // This algorithm makes a best effort to coalesce in the event of
- // unordered packets, where pkt may land anywhere in items from a
- // sequence number perspective, however once an item is inserted into
- // the table it is never compared across other items later.
- item := items[i]
- can := tcpPacketsCanCoalesce(pkt, uint8(iphLen), uint8(tcphLen), seq, pshSet, gsoSize, item, bufs, offset)
- if can != coalesceUnavailable {
- result := coalesceTCPPackets(can, pkt, pktI, gsoSize, seq, pshSet, &item, bufs, offset, isV6)
- switch result {
- case coalesceSuccess:
- table.updateAt(item, i)
- return true
- case coalesceItemInvalidCSum:
- // delete the item with an invalid csum
- table.deleteAt(item.key, i)
- case coalescePktInvalidCSum:
- // no point in inserting an item that we can't coalesce
- return false
- default:
- }
- }
- }
- // failed to coalesce with any other packets; store the item in the flow
- table.insert(pkt, srcAddrOffset, srcAddrOffset+addrLen, iphLen, tcphLen, pktI)
- return false
-}
-
-func isTCP4NoIPOptions(b []byte) bool {
- if len(b) < 40 {
- return false
- }
- if b[0]>>4 != 4 {
- return false
- }
- if b[0]&0x0F != 5 {
- return false
- }
- if b[9] != unix.IPPROTO_TCP {
- return false
- }
- return true
-}
-
-func isTCP6NoEH(b []byte) bool {
- if len(b) < 60 {
- return false
- }
- if b[0]>>4 != 6 {
- return false
- }
- if b[6] != unix.IPPROTO_TCP {
- return false
- }
- return true
-}
-
-// handleGRO evaluates bufs for GRO, and writes the indices of the resulting
-// packets into toWrite. toWrite, tcp4Table, and tcp6Table should initially be
-// empty (but non-nil), and are passed in to save allocs as the caller may reset
-// and recycle them across vectors of packets.
-func handleGRO(bufs [][]byte, offset int, tcp4Table, tcp6Table *tcpGROTable, toWrite *[]int) error {
- for i := range bufs {
- if offset < virtioNetHdrLen || offset > len(bufs[i])-1 {
- return errors.New("invalid offset")
- }
- var coalesced bool
- switch {
- case isTCP4NoIPOptions(bufs[i][offset:]): // ipv4 packets w/IP options do not coalesce
- coalesced = tcpGRO(bufs, offset, i, tcp4Table, false)
- case isTCP6NoEH(bufs[i][offset:]): // ipv6 packets w/extension headers do not coalesce
- coalesced = tcpGRO(bufs, offset, i, tcp6Table, true)
- }
- if !coalesced {
- hdr := virtioNetHdr{}
- err := hdr.encode(bufs[i][offset-virtioNetHdrLen:])
- if err != nil {
- return err
- }
- *toWrite = append(*toWrite, i)
- }
- }
- return nil
-}
-
-// tcpTSO splits packets from in into outBuffs, writing the size of each
-// element into sizes. It returns the number of buffers populated, and/or an
-// error.
-func tcpTSO(in []byte, hdr virtioNetHdr, outBuffs [][]byte, sizes []int, outOffset int) (int, error) {
- iphLen := int(hdr.csumStart)
- srcAddrOffset := ipv6SrcAddrOffset
- addrLen := 16
- if hdr.gsoType == unix.VIRTIO_NET_HDR_GSO_TCPV4 {
- in[10], in[11] = 0, 0 // clear ipv4 header checksum
- srcAddrOffset = ipv4SrcAddrOffset
- addrLen = 4
- }
- tcpCSumAt := int(hdr.csumStart + hdr.csumOffset)
- in[tcpCSumAt], in[tcpCSumAt+1] = 0, 0 // clear tcp checksum
- firstTCPSeqNum := binary.BigEndian.Uint32(in[hdr.csumStart+4:])
- nextSegmentDataAt := int(hdr.hdrLen)
- i := 0
- for ; nextSegmentDataAt < len(in); i++ {
- if i == len(outBuffs) {
- return i - 1, ErrTooManySegments
- }
- nextSegmentEnd := nextSegmentDataAt + int(hdr.gsoSize)
- if nextSegmentEnd > len(in) {
- nextSegmentEnd = len(in)
- }
- segmentDataLen := nextSegmentEnd - nextSegmentDataAt
- totalLen := int(hdr.hdrLen) + segmentDataLen
- sizes[i] = totalLen
- out := outBuffs[i][outOffset:]
-
- copy(out, in[:iphLen])
- if hdr.gsoType == unix.VIRTIO_NET_HDR_GSO_TCPV4 {
- // For IPv4 we are responsible for incrementing the ID field,
- // updating the total len field, and recalculating the header
- // checksum.
- if i > 0 {
- id := binary.BigEndian.Uint16(out[4:])
- id += uint16(i)
- binary.BigEndian.PutUint16(out[4:], id)
- }
- binary.BigEndian.PutUint16(out[2:], uint16(totalLen))
- ipv4CSum := ^checksum(out[:iphLen], 0)
- binary.BigEndian.PutUint16(out[10:], ipv4CSum)
- } else {
- // For IPv6 we are responsible for updating the payload length field.
- binary.BigEndian.PutUint16(out[4:], uint16(totalLen-iphLen))
- }
-
- // TCP header
- copy(out[hdr.csumStart:hdr.hdrLen], in[hdr.csumStart:hdr.hdrLen])
- tcpSeq := firstTCPSeqNum + uint32(hdr.gsoSize*uint16(i))
- binary.BigEndian.PutUint32(out[hdr.csumStart+4:], tcpSeq)
- if nextSegmentEnd != len(in) {
- // FIN and PSH should only be set on last segment
- clearFlags := tcpFlagFIN | tcpFlagPSH
- out[hdr.csumStart+tcpFlagsOffset] &^= clearFlags
- }
-
- // payload
- copy(out[hdr.hdrLen:], in[nextSegmentDataAt:nextSegmentEnd])
-
- // TCP checksum
- tcpHLen := int(hdr.hdrLen - hdr.csumStart)
- tcpLenForPseudo := uint16(tcpHLen + segmentDataLen)
- tcpCSumNoFold := pseudoHeaderChecksumNoFold(unix.IPPROTO_TCP, in[srcAddrOffset:srcAddrOffset+addrLen], in[srcAddrOffset+addrLen:srcAddrOffset+addrLen*2], tcpLenForPseudo)
- tcpCSum := ^checksum(out[hdr.csumStart:totalLen], tcpCSumNoFold)
- binary.BigEndian.PutUint16(out[hdr.csumStart+hdr.csumOffset:], tcpCSum)
-
- nextSegmentDataAt += int(hdr.gsoSize)
- }
- return i, nil
-}
-
-func gsoNoneChecksum(in []byte, cSumStart, cSumOffset uint16) error {
- cSumAt := cSumStart + cSumOffset
- // The initial value at the checksum offset should be summed with the
- // checksum we compute. This is typically the pseudo-header checksum.
- initial := binary.BigEndian.Uint16(in[cSumAt:])
- in[cSumAt], in[cSumAt+1] = 0, 0
- binary.BigEndian.PutUint16(in[cSumAt:], ^checksum(in[cSumStart:], uint64(initial)))
- return nil
-}
diff --git a/vendor/golang.zx2c4.com/wireguard/tun/tun.go b/vendor/golang.zx2c4.com/wireguard/tun/tun.go
index 0ae53d0733..01051b938e 100644
--- a/vendor/golang.zx2c4.com/wireguard/tun/tun.go
+++ b/vendor/golang.zx2c4.com/wireguard/tun/tun.go
@@ -18,36 +18,12 @@ const (
)
type Device interface {
- // File returns the file descriptor of the device.
- File() *os.File
-
- // Read one or more packets from the Device (without any additional headers).
- // On a successful read it returns the number of packets read, and sets
- // packet lengths within the sizes slice. len(sizes) must be >= len(bufs).
- // A nonzero offset can be used to instruct the Device on where to begin
- // reading into each element of the bufs slice.
- Read(bufs [][]byte, sizes []int, offset int) (n int, err error)
-
- // Write one or more packets to the device (without any additional headers).
- // On a successful write it returns the number of packets written. A nonzero
- // offset can be used to instruct the Device on where to begin writing from
- // each packet contained within the bufs slice.
- Write(bufs [][]byte, offset int) (int, error)
-
- // MTU returns the MTU of the Device.
- MTU() (int, error)
-
- // Name returns the current name of the Device.
- Name() (string, error)
-
- // Events returns a channel of type Event, which is fed Device events.
- Events() <-chan Event
-
- // Close stops the Device and closes the Event channel.
- Close() error
-
- // BatchSize returns the preferred/max number of packets that can be read or
- // written in a single read/write call. BatchSize must not change over the
- // lifetime of a Device.
- BatchSize() int
+ File() *os.File // returns the file descriptor of the device
+ Read([]byte, int) (int, error) // read a packet from the device (without any additional headers)
+ Write([]byte, int) (int, error) // writes a packet to the device (without any additional headers)
+ Flush() error // flush all previous writes to the device
+ MTU() (int, error) // returns the MTU of the device
+ Name() (string, error) // fetches and returns the current name
+ Events() <-chan Event // returns a constant channel of events related to the device
+ Close() error // stops the device and closes the event channel
}
diff --git a/vendor/golang.zx2c4.com/wireguard/tun/tun_darwin.go b/vendor/golang.zx2c4.com/wireguard/tun/tun_darwin.go
index c9a6c0bc45..7411a69463 100644
--- a/vendor/golang.zx2c4.com/wireguard/tun/tun_darwin.go
+++ b/vendor/golang.zx2c4.com/wireguard/tun/tun_darwin.go
@@ -8,7 +8,6 @@ package tun
import (
"errors"
"fmt"
- "io"
"net"
"os"
"sync"
@@ -16,6 +15,7 @@ import (
"time"
"unsafe"
+ "golang.org/x/net/ipv6"
"golang.org/x/sys/unix"
)
@@ -33,7 +33,7 @@ type NativeTun struct {
func retryInterfaceByIndex(index int) (iface *net.Interface, err error) {
for i := 0; i < 20; i++ {
iface, err = net.InterfaceByIndex(index)
- if err != nil && errors.Is(err, unix.ENOMEM) {
+ if err != nil && errors.Is(err, syscall.ENOMEM) {
time.Sleep(time.Duration(i) * time.Second / 3)
continue
}
@@ -55,7 +55,7 @@ func (tun *NativeTun) routineRouteListener(tunIfindex int) {
retry:
n, err := unix.Read(tun.routeSocket, data)
if err != nil {
- if errno, ok := err.(unix.Errno); ok && errno == unix.EINTR {
+ if errno, ok := err.(syscall.Errno); ok && errno == syscall.EINTR {
goto retry
}
tun.errors <- err
@@ -217,46 +217,45 @@ func (tun *NativeTun) Events() <-chan Event {
return tun.events
}
-func (tun *NativeTun) Read(bufs [][]byte, sizes []int, offset int) (int, error) {
- // TODO: the BSDs look very similar in Read() and Write(). They should be
- // collapsed, with platform-specific files containing the varying parts of
- // their implementations.
+func (tun *NativeTun) Read(buff []byte, offset int) (int, error) {
select {
case err := <-tun.errors:
return 0, err
default:
- buf := bufs[0][offset-4:]
- n, err := tun.tunFile.Read(buf[:])
+ buff := buff[offset-4:]
+ n, err := tun.tunFile.Read(buff[:])
if n < 4 {
return 0, err
}
- sizes[0] = n - 4
- return 1, err
+ return n - 4, err
}
}
-func (tun *NativeTun) Write(bufs [][]byte, offset int) (int, error) {
- if offset < 4 {
- return 0, io.ErrShortBuffer
- }
- for i, buf := range bufs {
- buf = buf[offset-4:]
- buf[0] = 0x00
- buf[1] = 0x00
- buf[2] = 0x00
- switch buf[4] >> 4 {
- case 4:
- buf[3] = unix.AF_INET
- case 6:
- buf[3] = unix.AF_INET6
- default:
- return i, unix.EAFNOSUPPORT
- }
- if _, err := tun.tunFile.Write(buf); err != nil {
- return i, err
- }
+func (tun *NativeTun) Write(buff []byte, offset int) (int, error) {
+ // reserve space for header
+
+ buff = buff[offset-4:]
+
+ // add packet information header
+
+ buff[0] = 0x00
+ buff[1] = 0x00
+ buff[2] = 0x00
+
+ if buff[4]>>4 == ipv6.Version {
+ buff[3] = unix.AF_INET6
+ } else {
+ buff[3] = unix.AF_INET
}
- return len(bufs), nil
+
+ // write
+
+ return tun.tunFile.Write(buff)
+}
+
+func (tun *NativeTun) Flush() error {
+ // TODO: can flushing be implemented by buffering and using sendmmsg?
+ return nil
}
func (tun *NativeTun) Close() error {
@@ -319,10 +318,6 @@ func (tun *NativeTun) MTU() (int, error) {
return int(ifr.MTU), nil
}
-func (tun *NativeTun) BatchSize() int {
- return 1
-}
-
func socketCloexec(family, sotype, proto int) (fd int, err error) {
// See go/src/net/sys_cloexec.go for background.
syscall.ForkLock.RLock()
diff --git a/vendor/golang.zx2c4.com/wireguard/tun/tun_freebsd.go b/vendor/golang.zx2c4.com/wireguard/tun/tun_freebsd.go
index 7c65fd9992..42431aa3ee 100644
--- a/vendor/golang.zx2c4.com/wireguard/tun/tun_freebsd.go
+++ b/vendor/golang.zx2c4.com/wireguard/tun/tun_freebsd.go
@@ -333,46 +333,45 @@ func (tun *NativeTun) Events() <-chan Event {
return tun.events
}
-func (tun *NativeTun) Read(bufs [][]byte, sizes []int, offset int) (int, error) {
+func (tun *NativeTun) Read(buff []byte, offset int) (int, error) {
select {
case err := <-tun.errors:
return 0, err
default:
- buf := bufs[0][offset-4:]
- n, err := tun.tunFile.Read(buf[:])
+ buff := buff[offset-4:]
+ n, err := tun.tunFile.Read(buff[:])
if n < 4 {
return 0, err
}
- sizes[0] = n - 4
- return 1, err
+ return n - 4, err
}
}
-func (tun *NativeTun) Write(bufs [][]byte, offset int) (int, error) {
+func (tun *NativeTun) Write(buf []byte, offset int) (int, error) {
if offset < 4 {
return 0, io.ErrShortBuffer
}
- for i, buf := range bufs {
- buf = buf[offset-4:]
- if len(buf) < 5 {
- return i, io.ErrShortBuffer
- }
- buf[0] = 0x00
- buf[1] = 0x00
- buf[2] = 0x00
- switch buf[4] >> 4 {
- case 4:
- buf[3] = unix.AF_INET
- case 6:
- buf[3] = unix.AF_INET6
- default:
- return i, unix.EAFNOSUPPORT
- }
- if _, err := tun.tunFile.Write(buf); err != nil {
- return i, err
- }
+ buf = buf[offset-4:]
+ if len(buf) < 5 {
+ return 0, io.ErrShortBuffer
+ }
+ buf[0] = 0x00
+ buf[1] = 0x00
+ buf[2] = 0x00
+ switch buf[4] >> 4 {
+ case 4:
+ buf[3] = unix.AF_INET
+ case 6:
+ buf[3] = unix.AF_INET6
+ default:
+ return 0, unix.EAFNOSUPPORT
}
- return len(bufs), nil
+ return tun.tunFile.Write(buf)
+}
+
+func (tun *NativeTun) Flush() error {
+ // TODO: can flushing be implemented by buffering and using sendmmsg?
+ return nil
}
func (tun *NativeTun) Close() error {
@@ -429,7 +428,3 @@ func (tun *NativeTun) MTU() (int, error) {
}
return int(*(*int32)(unsafe.Pointer(&ifr.MTU))), nil
}
-
-func (tun *NativeTun) BatchSize() int {
- return 1
-}
diff --git a/vendor/golang.zx2c4.com/wireguard/tun/tun_linux.go b/vendor/golang.zx2c4.com/wireguard/tun/tun_linux.go
index 12cd49f747..25dbc0749b 100644
--- a/vendor/golang.zx2c4.com/wireguard/tun/tun_linux.go
+++ b/vendor/golang.zx2c4.com/wireguard/tun/tun_linux.go
@@ -17,8 +17,9 @@ import (
"time"
"unsafe"
+ "golang.org/x/net/ipv6"
"golang.org/x/sys/unix"
- "golang.zx2c4.com/wireguard/conn"
+
"golang.zx2c4.com/wireguard/rwcancel"
)
@@ -32,25 +33,17 @@ type NativeTun struct {
index int32 // if index
errors chan error // async error handling
events chan Event // device related events
+ nopi bool // the device was passed IFF_NO_PI
netlinkSock int
netlinkCancel *rwcancel.RWCancel
hackListenerClosed sync.Mutex
statusListenersShutdown chan struct{}
- batchSize int
- vnetHdr bool
closeOnce sync.Once
nameOnce sync.Once // guards calling initNameCache, which sets following fields
nameCache string // name of interface
nameErr error
-
- readOpMu sync.Mutex // readOpMu guards readBuff
- readBuff [virtioNetHdrLen + 65535]byte // if vnetHdr every read() is prefixed by virtioNetHdr
-
- writeOpMu sync.Mutex // writeOpMu guards toWrite, tcp4GROTable, tcp6GROTable
- toWrite []int
- tcp4GROTable, tcp6GROTable *tcpGROTable
}
func (tun *NativeTun) File() *os.File {
@@ -330,142 +323,57 @@ func (tun *NativeTun) nameSlow() (string, error) {
return unix.ByteSliceToString(ifr[:]), nil
}
-func (tun *NativeTun) Write(bufs [][]byte, offset int) (int, error) {
- tun.writeOpMu.Lock()
- defer func() {
- tun.tcp4GROTable.reset()
- tun.tcp6GROTable.reset()
- tun.writeOpMu.Unlock()
- }()
- var (
- errs error
- total int
- )
- tun.toWrite = tun.toWrite[:0]
- if tun.vnetHdr {
- err := handleGRO(bufs, offset, tun.tcp4GROTable, tun.tcp6GROTable, &tun.toWrite)
- if err != nil {
- return 0, err
- }
- offset -= virtioNetHdrLen
+func (tun *NativeTun) Write(buf []byte, offset int) (int, error) {
+ if tun.nopi {
+ buf = buf[offset:]
} else {
- for i := range bufs {
- tun.toWrite = append(tun.toWrite, i)
- }
- }
- for _, bufsI := range tun.toWrite {
- n, err := tun.tunFile.Write(bufs[bufsI][offset:])
- if errors.Is(err, syscall.EBADFD) {
- return total, os.ErrClosed
- }
- if err != nil {
- errs = errors.Join(errs, err)
+ // reserve space for header
+ buf = buf[offset-4:]
+
+ // add packet information header
+ buf[0] = 0x00
+ buf[1] = 0x00
+ if buf[4]>>4 == ipv6.Version {
+ buf[2] = 0x86
+ buf[3] = 0xdd
} else {
- total += n
+ buf[2] = 0x08
+ buf[3] = 0x00
}
}
- return total, errs
-}
-// handleVirtioRead splits in into bufs, leaving offset bytes at the front of
-// each buffer. It mutates sizes to reflect the size of each element of bufs,
-// and returns the number of packets read.
-func handleVirtioRead(in []byte, bufs [][]byte, sizes []int, offset int) (int, error) {
- var hdr virtioNetHdr
- err := hdr.decode(in)
- if err != nil {
- return 0, err
- }
- in = in[virtioNetHdrLen:]
- if hdr.gsoType == unix.VIRTIO_NET_HDR_GSO_NONE {
- if hdr.flags&unix.VIRTIO_NET_HDR_F_NEEDS_CSUM != 0 {
- // This means CHECKSUM_PARTIAL in skb context. We are responsible
- // for computing the checksum starting at hdr.csumStart and placing
- // at hdr.csumOffset.
- err = gsoNoneChecksum(in, hdr.csumStart, hdr.csumOffset)
- if err != nil {
- return 0, err
- }
- }
- if len(in) > len(bufs[0][offset:]) {
- return 0, fmt.Errorf("read len %d overflows bufs element len %d", len(in), len(bufs[0][offset:]))
- }
- n := copy(bufs[0][offset:], in)
- sizes[0] = n
- return 1, nil
- }
- if hdr.gsoType != unix.VIRTIO_NET_HDR_GSO_TCPV4 && hdr.gsoType != unix.VIRTIO_NET_HDR_GSO_TCPV6 {
- return 0, fmt.Errorf("unsupported virtio GSO type: %d", hdr.gsoType)
- }
-
- ipVersion := in[0] >> 4
- switch ipVersion {
- case 4:
- if hdr.gsoType != unix.VIRTIO_NET_HDR_GSO_TCPV4 {
- return 0, fmt.Errorf("ip header version: %d, GSO type: %d", ipVersion, hdr.gsoType)
- }
- case 6:
- if hdr.gsoType != unix.VIRTIO_NET_HDR_GSO_TCPV6 {
- return 0, fmt.Errorf("ip header version: %d, GSO type: %d", ipVersion, hdr.gsoType)
- }
- default:
- return 0, fmt.Errorf("invalid ip header version: %d", ipVersion)
- }
-
- if len(in) <= int(hdr.csumStart+12) {
- return 0, errors.New("packet is too short")
- }
- // Don't trust hdr.hdrLen from the kernel as it can be equal to the length
- // of the entire first packet when the kernel is handling it as part of a
- // FORWARD path. Instead, parse the TCP header length and add it onto
- // csumStart, which is synonymous for IP header length.
- tcpHLen := uint16(in[hdr.csumStart+12] >> 4 * 4)
- if tcpHLen < 20 || tcpHLen > 60 {
- // A TCP header must be between 20 and 60 bytes in length.
- return 0, fmt.Errorf("tcp header len is invalid: %d", tcpHLen)
- }
- hdr.hdrLen = hdr.csumStart + tcpHLen
-
- if len(in) < int(hdr.hdrLen) {
- return 0, fmt.Errorf("length of packet (%d) < virtioNetHdr.hdrLen (%d)", len(in), hdr.hdrLen)
- }
-
- if hdr.hdrLen < hdr.csumStart {
- return 0, fmt.Errorf("virtioNetHdr.hdrLen (%d) < virtioNetHdr.csumStart (%d)", hdr.hdrLen, hdr.csumStart)
- }
- cSumAt := int(hdr.csumStart + hdr.csumOffset)
- if cSumAt+1 >= len(in) {
- return 0, fmt.Errorf("end of checksum offset (%d) exceeds packet length (%d)", cSumAt+1, len(in))
+ n, err := tun.tunFile.Write(buf)
+ if errors.Is(err, syscall.EBADFD) {
+ err = os.ErrClosed
}
+ return n, err
+}
- return tcpTSO(in, hdr, bufs, sizes, offset)
+func (tun *NativeTun) Flush() error {
+ // TODO: can flushing be implemented by buffering and using sendmmsg?
+ return nil
}
-func (tun *NativeTun) Read(bufs [][]byte, sizes []int, offset int) (int, error) {
- tun.readOpMu.Lock()
- defer tun.readOpMu.Unlock()
+func (tun *NativeTun) Read(buf []byte, offset int) (n int, err error) {
select {
- case err := <-tun.errors:
- return 0, err
+ case err = <-tun.errors:
default:
- readInto := bufs[0][offset:]
- if tun.vnetHdr {
- readInto = tun.readBuff[:]
- }
- n, err := tun.tunFile.Read(readInto)
- if errors.Is(err, syscall.EBADFD) {
- err = os.ErrClosed
- }
- if err != nil {
- return 0, err
- }
- if tun.vnetHdr {
- return handleVirtioRead(readInto[:n], bufs, sizes, offset)
+ if tun.nopi {
+ n, err = tun.tunFile.Read(buf[offset:])
} else {
- sizes[0] = n
- return 1, nil
+ buff := buf[offset-4:]
+ n, err = tun.tunFile.Read(buff[:])
+ if errors.Is(err, syscall.EBADFD) {
+ err = os.ErrClosed
+ }
+ if n < 4 {
+ n = 0
+ } else {
+ n -= 4
+ }
}
}
+ return
}
func (tun *NativeTun) Events() <-chan Event {
@@ -491,50 +399,6 @@ func (tun *NativeTun) Close() error {
return err2
}
-func (tun *NativeTun) BatchSize() int {
- return tun.batchSize
-}
-
-const (
- // TODO: support TSO with ECN bits
- tunOffloads = unix.TUN_F_CSUM | unix.TUN_F_TSO4 | unix.TUN_F_TSO6
-)
-
-func (tun *NativeTun) initFromFlags(name string) error {
- sc, err := tun.tunFile.SyscallConn()
- if err != nil {
- return err
- }
- if e := sc.Control(func(fd uintptr) {
- var (
- ifr *unix.Ifreq
- )
- ifr, err = unix.NewIfreq(name)
- if err != nil {
- return
- }
- err = unix.IoctlIfreq(int(fd), unix.TUNGETIFF, ifr)
- if err != nil {
- return
- }
- got := ifr.Uint16()
- if got&unix.IFF_VNET_HDR != 0 {
- err = unix.IoctlSetInt(int(fd), unix.TUNSETOFFLOAD, tunOffloads)
- if err != nil {
- return
- }
- tun.vnetHdr = true
- tun.batchSize = conn.IdealBatchSize
- } else {
- tun.batchSize = 1
- }
- }); e != nil {
- return e
- }
- return err
-}
-
-// CreateTUN creates a Device with the provided name and MTU.
func CreateTUN(name string, mtu int) (Device, error) {
nfd, err := unix.Open(cloneDevicePath, unix.O_RDWR|unix.O_CLOEXEC, 0)
if err != nil {
@@ -544,16 +408,25 @@ func CreateTUN(name string, mtu int) (Device, error) {
return nil, err
}
- ifr, err := unix.NewIfreq(name)
- if err != nil {
- return nil, err
+ var ifr [ifReqSize]byte
+ var flags uint16 = unix.IFF_TUN // | unix.IFF_NO_PI (disabled for TUN status hack)
+ nameBytes := []byte(name)
+ if len(nameBytes) >= unix.IFNAMSIZ {
+ unix.Close(nfd)
+ return nil, fmt.Errorf("interface name too long: %w", unix.ENAMETOOLONG)
}
- // IFF_VNET_HDR enables the "tun status hack" via routineHackListener()
- // where a null write will return EINVAL indicating the TUN is up.
- ifr.SetUint16(unix.IFF_TUN | unix.IFF_NO_PI | unix.IFF_VNET_HDR)
- err = unix.IoctlIfreq(nfd, unix.TUNSETIFF, ifr)
- if err != nil {
- return nil, err
+ copy(ifr[:], nameBytes)
+ *(*uint16)(unsafe.Pointer(&ifr[unix.IFNAMSIZ])) = flags
+
+ _, _, errno := unix.Syscall(
+ unix.SYS_IOCTL,
+ uintptr(nfd),
+ uintptr(unix.TUNSETIFF),
+ uintptr(unsafe.Pointer(&ifr[0])),
+ )
+ if errno != 0 {
+ unix.Close(nfd)
+ return nil, errno
}
err = unix.SetNonblock(nfd, true)
@@ -568,16 +441,13 @@ func CreateTUN(name string, mtu int) (Device, error) {
return CreateTUNFromFile(fd, mtu)
}
-// CreateTUNFromFile creates a Device from an os.File with the provided MTU.
func CreateTUNFromFile(file *os.File, mtu int) (Device, error) {
tun := &NativeTun{
tunFile: file,
events: make(chan Event, 5),
errors: make(chan error, 5),
statusListenersShutdown: make(chan struct{}),
- tcp4GROTable: newTCPGROTable(),
- tcp6GROTable: newTCPGROTable(),
- toWrite: make([]int, 0, conn.IdealBatchSize),
+ nopi: false,
}
name, err := tun.Name()
@@ -585,12 +455,8 @@ func CreateTUNFromFile(file *os.File, mtu int) (Device, error) {
return nil, err
}
- err = tun.initFromFlags(name)
- if err != nil {
- return nil, err
- }
-
// start event listener
+
tun.index, err = getIFIndex(name)
if err != nil {
return nil, err
@@ -619,8 +485,6 @@ func CreateTUNFromFile(file *os.File, mtu int) (Device, error) {
return tun, nil
}
-// CreateUnmonitoredTUNFromFD creates a Device from the provided file
-// descriptor.
func CreateUnmonitoredTUNFromFD(fd int) (Device, string, error) {
err := unix.SetNonblock(fd, true)
if err != nil {
@@ -628,20 +492,14 @@ func CreateUnmonitoredTUNFromFD(fd int) (Device, string, error) {
}
file := os.NewFile(uintptr(fd), "/dev/tun")
tun := &NativeTun{
- tunFile: file,
- events: make(chan Event, 5),
- errors: make(chan error, 5),
- tcp4GROTable: newTCPGROTable(),
- tcp6GROTable: newTCPGROTable(),
- toWrite: make([]int, 0, conn.IdealBatchSize),
+ tunFile: file,
+ events: make(chan Event, 5),
+ errors: make(chan error, 5),
+ nopi: true,
}
name, err := tun.Name()
if err != nil {
return nil, "", err
}
- err = tun.initFromFlags(name)
- if err != nil {
- return nil, "", err
- }
- return tun, name, err
+ return tun, name, nil
}
diff --git a/vendor/golang.zx2c4.com/wireguard/tun/tun_openbsd.go b/vendor/golang.zx2c4.com/wireguard/tun/tun_openbsd.go
index ae571b90c3..e7fd79c5b0 100644
--- a/vendor/golang.zx2c4.com/wireguard/tun/tun_openbsd.go
+++ b/vendor/golang.zx2c4.com/wireguard/tun/tun_openbsd.go
@@ -8,13 +8,13 @@ package tun
import (
"errors"
"fmt"
- "io"
"net"
"os"
"sync"
"syscall"
"unsafe"
+ "golang.org/x/net/ipv6"
"golang.org/x/sys/unix"
)
@@ -204,43 +204,45 @@ func (tun *NativeTun) Events() <-chan Event {
return tun.events
}
-func (tun *NativeTun) Read(bufs [][]byte, sizes []int, offset int) (int, error) {
+func (tun *NativeTun) Read(buff []byte, offset int) (int, error) {
select {
case err := <-tun.errors:
return 0, err
default:
- buf := bufs[0][offset-4:]
- n, err := tun.tunFile.Read(buf[:])
+ buff := buff[offset-4:]
+ n, err := tun.tunFile.Read(buff[:])
if n < 4 {
return 0, err
}
- sizes[0] = n - 4
- return 1, err
+ return n - 4, err
}
}
-func (tun *NativeTun) Write(bufs [][]byte, offset int) (int, error) {
- if offset < 4 {
- return 0, io.ErrShortBuffer
- }
- for i, buf := range bufs {
- buf = buf[offset-4:]
- buf[0] = 0x00
- buf[1] = 0x00
- buf[2] = 0x00
- switch buf[4] >> 4 {
- case 4:
- buf[3] = unix.AF_INET
- case 6:
- buf[3] = unix.AF_INET6
- default:
- return i, unix.EAFNOSUPPORT
- }
- if _, err := tun.tunFile.Write(buf); err != nil {
- return i, err
- }
+func (tun *NativeTun) Write(buff []byte, offset int) (int, error) {
+ // reserve space for header
+
+ buff = buff[offset-4:]
+
+ // add packet information header
+
+ buff[0] = 0x00
+ buff[1] = 0x00
+ buff[2] = 0x00
+
+ if buff[4]>>4 == ipv6.Version {
+ buff[3] = unix.AF_INET6
+ } else {
+ buff[3] = unix.AF_INET
}
- return len(bufs), nil
+
+ // write
+
+ return tun.tunFile.Write(buff)
+}
+
+func (tun *NativeTun) Flush() error {
+ // TODO: can flushing be implemented by buffering and using sendmmsg?
+ return nil
}
func (tun *NativeTun) Close() error {
@@ -327,7 +329,3 @@ func (tun *NativeTun) MTU() (int, error) {
return int(*(*int32)(unsafe.Pointer(&ifr.MTU))), nil
}
-
-func (tun *NativeTun) BatchSize() int {
- return 1
-}
diff --git a/vendor/golang.zx2c4.com/wireguard/tun/tun_windows.go b/vendor/golang.zx2c4.com/wireguard/tun/tun_windows.go
index 0cb4ce1925..d5abb14898 100644
--- a/vendor/golang.zx2c4.com/wireguard/tun/tun_windows.go
+++ b/vendor/golang.zx2c4.com/wireguard/tun/tun_windows.go
@@ -15,6 +15,7 @@ import (
_ "unsafe"
"golang.org/x/sys/windows"
+
"golang.zx2c4.com/wintun"
)
@@ -43,7 +44,6 @@ type NativeTun struct {
closeOnce sync.Once
close atomic.Bool
forcedMTU int
- outSizes []int
}
var (
@@ -134,14 +134,9 @@ func (tun *NativeTun) ForceMTU(mtu int) {
}
}
-func (tun *NativeTun) BatchSize() int {
- // TODO: implement batching with wintun
- return 1
-}
-
// Note: Read() and Write() assume the caller comes only from a single thread; there's no locking.
-func (tun *NativeTun) Read(bufs [][]byte, sizes []int, offset int) (int, error) {
+func (tun *NativeTun) Read(buff []byte, offset int) (int, error) {
tun.running.Add(1)
defer tun.running.Done()
retry:
@@ -158,11 +153,10 @@ retry:
switch err {
case nil:
packetSize := len(packet)
- copy(bufs[0][offset:], packet)
- sizes[0] = packetSize
+ copy(buff[offset:], packet)
tun.session.ReleaseReceivePacket(packet)
tun.rate.update(uint64(packetSize))
- return 1, nil
+ return packetSize, nil
case windows.ERROR_NO_MORE_ITEMS:
if !shouldSpin || uint64(nanotime()-start) >= spinloopDuration {
windows.WaitForSingleObject(tun.readWait, windows.INFINITE)
@@ -179,33 +173,33 @@ retry:
}
}
-func (tun *NativeTun) Write(bufs [][]byte, offset int) (int, error) {
+func (tun *NativeTun) Flush() error {
+ return nil
+}
+
+func (tun *NativeTun) Write(buff []byte, offset int) (int, error) {
tun.running.Add(1)
defer tun.running.Done()
if tun.close.Load() {
return 0, os.ErrClosed
}
- for i, buf := range bufs {
- packetSize := len(buf) - offset
- tun.rate.update(uint64(packetSize))
+ packetSize := len(buff) - offset
+ tun.rate.update(uint64(packetSize))
- packet, err := tun.session.AllocateSendPacket(packetSize)
- switch err {
- case nil:
- // TODO: Explore options to eliminate this copy.
- copy(packet, buf[offset:])
- tun.session.SendPacket(packet)
- continue
- case windows.ERROR_HANDLE_EOF:
- return i, os.ErrClosed
- case windows.ERROR_BUFFER_OVERFLOW:
- continue // Dropping when ring is full.
- default:
- return i, fmt.Errorf("Write failed: %w", err)
- }
+ packet, err := tun.session.AllocateSendPacket(packetSize)
+ if err == nil {
+ copy(packet, buff[offset:])
+ tun.session.SendPacket(packet)
+ return packetSize, nil
+ }
+ switch err {
+ case windows.ERROR_HANDLE_EOF:
+ return 0, os.ErrClosed
+ case windows.ERROR_BUFFER_OVERFLOW:
+ return 0, nil // Dropping when ring is full.
}
- return len(bufs), nil
+ return 0, fmt.Errorf("Write failed: %w", err)
}
// LUID returns Windows interface instance ID.
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 52dc5b2726..feb2d3d1b9 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -551,10 +551,8 @@ golang.org/x/tools/internal/typesinternal
# golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2
## explicit; go 1.17
golang.zx2c4.com/wintun
-# golang.zx2c4.com/wireguard v0.0.0-20230704135630-469159ecf7d1
-## explicit; go 1.20
-golang.zx2c4.com/wireguard/conn
-golang.zx2c4.com/wireguard/conn/winrio
+# golang.zx2c4.com/wireguard v0.0.0-20230223181233-21636207a675
+## explicit; go 1.19
golang.zx2c4.com/wireguard/rwcancel
golang.zx2c4.com/wireguard/tun
# google.golang.org/protobuf v1.31.0