aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--README.md2
-rw-r--r--conn/bind_linux.go2
-rw-r--r--conn/bind_std.go79
-rw-r--r--conn/bind_windows.go2
-rw-r--r--conn/bindtest/bindtest.go2
-rw-r--r--conn/conn.go3
-rw-r--r--device/allowedips.go3
-rw-r--r--device/allowedips_rand_test.go3
-rw-r--r--device/allowedips_test.go3
-rw-r--r--device/device_test.go2
-rw-r--r--device/endpoint_test.go3
-rw-r--r--device/logger.go8
-rw-r--r--device/pools.go12
-rw-r--r--device/pools_test.go4
-rw-r--r--device/uapi.go16
-rw-r--r--go.mod9
-rw-r--r--go.sum23
-rw-r--r--ratelimiter/ratelimiter.go3
-rw-r--r--ratelimiter/ratelimiter_test.go3
-rw-r--r--tun/netstack/examples/http_client.go2
-rw-r--r--tun/netstack/examples/http_server.go2
-rw-r--r--tun/netstack/examples/ping_client.go76
-rw-r--r--tun/netstack/go.mod17
-rw-r--r--tun/netstack/go.sum27
-rw-r--r--tun/netstack/tun.go284
-rw-r--r--tun/tuntest/tuntest.go2
-rw-r--r--version.go2
27 files changed, 439 insertions, 155 deletions
diff --git a/README.md b/README.md
index 8d19556..30ea3ac 100644
--- a/README.md
+++ b/README.md
@@ -46,7 +46,7 @@ This will run on OpenBSD. It does not yet support sticky sockets. Fwmark is mapp
## Building
-This requires an installation of [go](https://golang.org) ≥ 1.17.
+This requires an installation of [go](https://golang.org) ≥ 1.18.
```
$ git clone https://git.zx2c4.com/wireguard-go
diff --git a/conn/bind_linux.go b/conn/bind_linux.go
index b3d755c..f11f031 100644
--- a/conn/bind_linux.go
+++ b/conn/bind_linux.go
@@ -8,13 +8,13 @@ package conn
import (
"errors"
"net"
+ "net/netip"
"strconv"
"sync"
"syscall"
"unsafe"
"golang.org/x/sys/unix"
- "golang.zx2c4.com/go118/netip"
)
type ipv4Source struct {
diff --git a/conn/bind_std.go b/conn/bind_std.go
index de03b10..b6a7ab3 100644
--- a/conn/bind_std.go
+++ b/conn/bind_std.go
@@ -8,10 +8,9 @@ package conn
import (
"errors"
"net"
+ "net/netip"
"sync"
"syscall"
-
- "golang.zx2c4.com/go118/netip"
)
// StdNetBind is meant to be a temporary solution on platforms for which
@@ -28,49 +27,38 @@ type StdNetBind struct {
func NewStdNetBind() Bind { return &StdNetBind{} }
-type StdNetEndpoint net.UDPAddr
+type StdNetEndpoint netip.AddrPort
var (
_ Bind = (*StdNetBind)(nil)
- _ Endpoint = (*StdNetEndpoint)(nil)
+ _ Endpoint = StdNetEndpoint{}
)
func (*StdNetBind) ParseEndpoint(s string) (Endpoint, error) {
e, err := netip.ParseAddrPort(s)
- return (*StdNetEndpoint)(&net.UDPAddr{
- IP: e.Addr().AsSlice(),
- Port: int(e.Port()),
- Zone: e.Addr().Zone(),
- }), err
+ return asEndpoint(e), err
}
-func (*StdNetEndpoint) ClearSrc() {}
+func (StdNetEndpoint) ClearSrc() {}
-func (e *StdNetEndpoint) DstIP() netip.Addr {
- a, _ := netip.AddrFromSlice((*net.UDPAddr)(e).IP)
- return a
+func (e StdNetEndpoint) DstIP() netip.Addr {
+ return (netip.AddrPort)(e).Addr()
}
-func (e *StdNetEndpoint) SrcIP() netip.Addr {
+func (e StdNetEndpoint) SrcIP() netip.Addr {
return netip.Addr{} // not supported
}
-func (e *StdNetEndpoint) DstToBytes() []byte {
- addr := (*net.UDPAddr)(e)
- out := addr.IP.To4()
- if out == nil {
- out = addr.IP
- }
- out = append(out, byte(addr.Port&0xff))
- out = append(out, byte((addr.Port>>8)&0xff))
- return out
+func (e StdNetEndpoint) DstToBytes() []byte {
+ b, _ := (netip.AddrPort)(e).MarshalBinary()
+ return b
}
-func (e *StdNetEndpoint) DstToString() string {
- return (*net.UDPAddr)(e).String()
+func (e StdNetEndpoint) DstToString() string {
+ return (netip.AddrPort)(e).String()
}
-func (e *StdNetEndpoint) SrcToString() string {
+func (e StdNetEndpoint) SrcToString() string {
return ""
}
@@ -163,32 +151,30 @@ func (bind *StdNetBind) Close() error {
func (*StdNetBind) makeReceiveIPv4(conn *net.UDPConn) ReceiveFunc {
return func(buff []byte) (int, Endpoint, error) {
- n, endpoint, err := conn.ReadFromUDP(buff)
- if endpoint != nil {
- endpoint.IP = endpoint.IP.To4()
- }
- return n, (*StdNetEndpoint)(endpoint), err
+ n, endpoint, err := conn.ReadFromUDPAddrPort(buff)
+ return n, asEndpoint(endpoint), err
}
}
func (*StdNetBind) makeReceiveIPv6(conn *net.UDPConn) ReceiveFunc {
return func(buff []byte) (int, Endpoint, error) {
- n, endpoint, err := conn.ReadFromUDP(buff)
- return n, (*StdNetEndpoint)(endpoint), err
+ n, endpoint, err := conn.ReadFromUDPAddrPort(buff)
+ return n, asEndpoint(endpoint), err
}
}
func (bind *StdNetBind) Send(buff []byte, endpoint Endpoint) error {
var err error
- nend, ok := endpoint.(*StdNetEndpoint)
+ nend, ok := endpoint.(StdNetEndpoint)
if !ok {
return ErrWrongEndpointType
}
+ addrPort := netip.AddrPort(nend)
bind.mu.Lock()
blackhole := bind.blackhole4
conn := bind.ipv4
- if nend.IP.To4() == nil {
+ if addrPort.Addr().Is6() {
blackhole = bind.blackhole6
conn = bind.ipv6
}
@@ -200,6 +186,27 @@ func (bind *StdNetBind) Send(buff []byte, endpoint Endpoint) error {
if conn == nil {
return syscall.EAFNOSUPPORT
}
- _, err = conn.WriteToUDP(buff, (*net.UDPAddr)(nend))
+ _, err = conn.WriteToUDPAddrPort(buff, addrPort)
return err
}
+
+// endpointPool contains a re-usable set of mapping from netip.AddrPort to Endpoint.
+// This exists to reduce allocations: Putting a netip.AddrPort in an Endpoint allocates,
+// but Endpoints are immutable, so we can re-use them.
+var endpointPool = sync.Pool{
+ New: func() any {
+ return make(map[netip.AddrPort]Endpoint)
+ },
+}
+
+// asEndpoint returns an Endpoint containing ap.
+func asEndpoint(ap netip.AddrPort) Endpoint {
+ m := endpointPool.Get().(map[netip.AddrPort]Endpoint)
+ defer endpointPool.Put(m)
+ e, ok := m[ap]
+ if !ok {
+ e = Endpoint(StdNetEndpoint(ap))
+ m[ap] = e
+ }
+ return e
+}
diff --git a/conn/bind_windows.go b/conn/bind_windows.go
index 476e277..9268bc1 100644
--- a/conn/bind_windows.go
+++ b/conn/bind_windows.go
@@ -9,13 +9,13 @@ import (
"encoding/binary"
"io"
"net"
+ "net/netip"
"strconv"
"sync"
"sync/atomic"
"unsafe"
"golang.org/x/sys/windows"
- "golang.zx2c4.com/go118/netip"
"golang.zx2c4.com/wireguard/conn/winrio"
)
diff --git a/conn/bindtest/bindtest.go b/conn/bindtest/bindtest.go
index 6fc1972..b38cae6 100644
--- a/conn/bindtest/bindtest.go
+++ b/conn/bindtest/bindtest.go
@@ -9,9 +9,9 @@ import (
"fmt"
"math/rand"
"net"
+ "net/netip"
"os"
- "golang.zx2c4.com/go118/netip"
"golang.zx2c4.com/wireguard/conn"
)
diff --git a/conn/conn.go b/conn/conn.go
index 35fb6b1..5a93b2b 100644
--- a/conn/conn.go
+++ b/conn/conn.go
@@ -9,11 +9,10 @@ package conn
import (
"errors"
"fmt"
+ "net/netip"
"reflect"
"runtime"
"strings"
-
- "golang.zx2c4.com/go118/netip"
)
// A ReceiveFunc receives a single inbound packet from the network.
diff --git a/device/allowedips.go b/device/allowedips.go
index 06c5465..3cac694 100644
--- a/device/allowedips.go
+++ b/device/allowedips.go
@@ -11,10 +11,9 @@ import (
"errors"
"math/bits"
"net"
+ "net/netip"
"sync"
"unsafe"
-
- "golang.zx2c4.com/go118/netip"
)
type parentIndirection struct {
diff --git a/device/allowedips_rand_test.go b/device/allowedips_rand_test.go
index ff56fe6..0d3eecb 100644
--- a/device/allowedips_rand_test.go
+++ b/device/allowedips_rand_test.go
@@ -8,10 +8,9 @@ package device
import (
"math/rand"
"net"
+ "net/netip"
"sort"
"testing"
-
- "golang.zx2c4.com/go118/netip"
)
const (
diff --git a/device/allowedips_test.go b/device/allowedips_test.go
index 68f382b..225c788 100644
--- a/device/allowedips_test.go
+++ b/device/allowedips_test.go
@@ -8,9 +8,8 @@ package device
import (
"math/rand"
"net"
+ "net/netip"
"testing"
-
- "golang.zx2c4.com/go118/netip"
)
type testPairCommonBits struct {
diff --git a/device/device_test.go b/device/device_test.go
index b484ca2..ab7236e 100644
--- a/device/device_test.go
+++ b/device/device_test.go
@@ -11,6 +11,7 @@ import (
"fmt"
"io"
"math/rand"
+ "net/netip"
"runtime"
"runtime/pprof"
"sync"
@@ -18,7 +19,6 @@ import (
"testing"
"time"
- "golang.zx2c4.com/go118/netip"
"golang.zx2c4.com/wireguard/conn"
"golang.zx2c4.com/wireguard/conn/bindtest"
"golang.zx2c4.com/wireguard/tun/tuntest"
diff --git a/device/endpoint_test.go b/device/endpoint_test.go
index f1ae47e..b265be6 100644
--- a/device/endpoint_test.go
+++ b/device/endpoint_test.go
@@ -7,8 +7,7 @@ package device
import (
"math/rand"
-
- "golang.zx2c4.com/go118/netip"
+ "net/netip"
)
type DummyEndpoint struct {
diff --git a/device/logger.go b/device/logger.go
index c79c971..29073e9 100644
--- a/device/logger.go
+++ b/device/logger.go
@@ -16,8 +16,8 @@ import (
// They do not require a trailing newline in the format.
// If nil, that level of logging will be silent.
type Logger struct {
- Verbosef func(format string, args ...interface{})
- Errorf func(format string, args ...interface{})
+ Verbosef func(format string, args ...any)
+ Errorf func(format string, args ...any)
}
// Log levels for use with NewLogger.
@@ -28,14 +28,14 @@ const (
)
// Function for use in Logger for discarding logged lines.
-func DiscardLogf(format string, args ...interface{}) {}
+func DiscardLogf(format string, args ...any) {}
// NewLogger constructs a Logger that writes to stdout.
// It logs at the specified log level and above.
// It decorates log lines with the log level, date, time, and prepend.
func NewLogger(level int, prepend string) *Logger {
logger := &Logger{DiscardLogf, DiscardLogf}
- logf := func(prefix string) func(string, ...interface{}) {
+ logf := func(prefix string) func(string, ...any) {
return log.New(os.Stdout, prefix+": "+prepend, log.Ldate|log.Ltime).Printf
}
if level >= LogLevelVerbose {
diff --git a/device/pools.go b/device/pools.go
index f1d1fa0..f40477b 100644
--- a/device/pools.go
+++ b/device/pools.go
@@ -18,13 +18,13 @@ type WaitPool struct {
max uint32
}
-func NewWaitPool(max uint32, new func() interface{}) *WaitPool {
+func NewWaitPool(max uint32, new func() any) *WaitPool {
p := &WaitPool{pool: sync.Pool{New: new}, max: max}
p.cond = sync.Cond{L: &p.lock}
return p
}
-func (p *WaitPool) Get() interface{} {
+func (p *WaitPool) Get() any {
if p.max != 0 {
p.lock.Lock()
for atomic.LoadUint32(&p.count) >= p.max {
@@ -36,7 +36,7 @@ func (p *WaitPool) Get() interface{} {
return p.pool.Get()
}
-func (p *WaitPool) Put(x interface{}) {
+func (p *WaitPool) Put(x any) {
p.pool.Put(x)
if p.max == 0 {
return
@@ -46,13 +46,13 @@ func (p *WaitPool) Put(x interface{}) {
}
func (device *Device) PopulatePools() {
- device.pool.messageBuffers = NewWaitPool(PreallocatedBuffersPerPool, func() interface{} {
+ device.pool.messageBuffers = NewWaitPool(PreallocatedBuffersPerPool, func() any {
return new([MaxMessageSize]byte)
})
- device.pool.inboundElements = NewWaitPool(PreallocatedBuffersPerPool, func() interface{} {
+ device.pool.inboundElements = NewWaitPool(PreallocatedBuffersPerPool, func() any {
return new(QueueInboundElement)
})
- device.pool.outboundElements = NewWaitPool(PreallocatedBuffersPerPool, func() interface{} {
+ device.pool.outboundElements = NewWaitPool(PreallocatedBuffersPerPool, func() any {
return new(QueueOutboundElement)
})
}
diff --git a/device/pools_test.go b/device/pools_test.go
index b0840e1..17e2298 100644
--- a/device/pools_test.go
+++ b/device/pools_test.go
@@ -26,7 +26,7 @@ func TestWaitPool(t *testing.T) {
if workers-4 <= 0 {
t.Skip("Not enough cores")
}
- p := NewWaitPool(uint32(workers-4), func() interface{} { return make([]byte, 16) })
+ p := NewWaitPool(uint32(workers-4), func() any { return make([]byte, 16) })
wg.Add(workers)
max := uint32(0)
updateMax := func() {
@@ -71,7 +71,7 @@ func BenchmarkWaitPool(b *testing.B) {
if workers-4 <= 0 {
b.Skip("Not enough cores")
}
- p := NewWaitPool(uint32(workers-4), func() interface{} { return make([]byte, 16) })
+ p := NewWaitPool(uint32(workers-4), func() any { return make([]byte, 16) })
wg.Add(workers)
b.ResetTimer()
for i := 0; i < workers; i++ {
diff --git a/device/uapi.go b/device/uapi.go
index 1994d46..30dd97e 100644
--- a/device/uapi.go
+++ b/device/uapi.go
@@ -12,13 +12,13 @@ import (
"fmt"
"io"
"net"
+ "net/netip"
"strconv"
"strings"
"sync"
"sync/atomic"
"time"
- "golang.zx2c4.com/go118/netip"
"golang.zx2c4.com/wireguard/ipc"
)
@@ -39,12 +39,12 @@ func (s IPCError) ErrorCode() int64 {
return s.code
}
-func ipcErrorf(code int64, msg string, args ...interface{}) *IPCError {
+func ipcErrorf(code int64, msg string, args ...any) *IPCError {
return &IPCError{code: code, err: fmt.Errorf(msg, args...)}
}
var byteBufferPool = &sync.Pool{
- New: func() interface{} { return new(bytes.Buffer) },
+ New: func() any { return new(bytes.Buffer) },
}
// IpcGetOperation implements the WireGuard configuration protocol "get" operation.
@@ -56,7 +56,7 @@ func (device *Device) IpcGetOperation(w io.Writer) error {
buf := byteBufferPool.Get().(*bytes.Buffer)
buf.Reset()
defer byteBufferPool.Put(buf)
- sendf := func(format string, args ...interface{}) {
+ sendf := func(format string, args ...any) {
fmt.Fprintf(buf, format, args...)
buf.WriteByte('\n')
}
@@ -161,12 +161,10 @@ func (device *Device) IpcSetOperation(r io.Reader) (err error) {
peer.handlePostConfig()
return nil
}
- parts := strings.Split(line, "=")
- if len(parts) != 2 {
- return ipcErrorf(ipc.IpcErrorProtocol, "failed to parse line %q, found %d =-separated parts, want 2", line, len(parts))
+ key, value, ok := strings.Cut(line, "=")
+ if !ok {
+ return ipcErrorf(ipc.IpcErrorProtocol, "failed to parse line %q", line)
}
- key := parts[0]
- value := parts[1]
if key == "public_key" {
if deviceConfig {
diff --git a/go.mod b/go.mod
index b510960..4fcb2fa 100644
--- a/go.mod
+++ b/go.mod
@@ -1,11 +1,10 @@
module golang.zx2c4.com/wireguard
-go 1.17
+go 1.18
require (
- golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa
- golang.org/x/net v0.0.0-20211111083644-e5c967477495
- golang.org/x/sys v0.0.0-20211110154304-99a53858aa08
- golang.zx2c4.com/go118/netip v0.0.0-20211111135330-a4a02eeacf9d
+ golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd
+ golang.org/x/net v0.0.0-20220225172249-27dd8689420f
+ golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86
golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224
)
diff --git a/go.sum b/go.sum
index 78f7367..3e4e323 100644
--- a/go.sum
+++ b/go.sum
@@ -1,19 +1,8 @@
-golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa h1:idItI2DDfCokpg0N51B2VtiLdJ4vAuXC9fnCb2gACo4=
-golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20211111083644-e5c967477495 h1:cjxxlQm6d4kYbhpZ2ghvmI8xnq0AG+jXmzrhzfkyu5A=
-golang.org/x/net v0.0.0-20211111083644-e5c967477495/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211110154304-99a53858aa08 h1:WecRHqgE09JBkh/584XIE6PMz5KKE/vER4izNUi30AQ=
-golang.org/x/sys v0.0.0-20211110154304-99a53858aa08/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
-golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.zx2c4.com/go118/netip v0.0.0-20211111135330-a4a02eeacf9d h1:9+v0G0naRhLPOJEeJOL6NuXTtAHHwmkyZlgQJ0XcQ8I=
-golang.zx2c4.com/go118/netip v0.0.0-20211111135330-a4a02eeacf9d/go.mod h1:5yyfuiqVIJ7t+3MqrpTQ+QqRkMWiESiyDvPNvKYCecg=
+golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd h1:XcWmESyNjXJMLahc3mqVQJcgSTDxFxhETVlfk9uGc38=
+golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc=
+golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
+golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86 h1:A9i04dxx7Cribqbs8jf3FQLogkL/CV2YN7hj9KWJCkc=
+golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 h1:Ug9qvr1myri/zFN6xL17LSCBGFDnphBBhzmILHsM5TY=
golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
diff --git a/ratelimiter/ratelimiter.go b/ratelimiter/ratelimiter.go
index 8e78d5e..1e3c252 100644
--- a/ratelimiter/ratelimiter.go
+++ b/ratelimiter/ratelimiter.go
@@ -6,10 +6,9 @@
package ratelimiter
import (
+ "net/netip"
"sync"
"time"
-
- "golang.zx2c4.com/go118/netip"
)
const (
diff --git a/ratelimiter/ratelimiter_test.go b/ratelimiter/ratelimiter_test.go
index 3e06ff7..ca7db72 100644
--- a/ratelimiter/ratelimiter_test.go
+++ b/ratelimiter/ratelimiter_test.go
@@ -6,10 +6,9 @@
package ratelimiter
import (
+ "net/netip"
"testing"
"time"
-
- "golang.zx2c4.com/go118/netip"
)
type result struct {
diff --git a/tun/netstack/examples/http_client.go b/tun/netstack/examples/http_client.go
index b39b453..352c1e4 100644
--- a/tun/netstack/examples/http_client.go
+++ b/tun/netstack/examples/http_client.go
@@ -12,8 +12,8 @@ import (
"io"
"log"
"net/http"
+ "net/netip"
- "golang.zx2c4.com/go118/netip"
"golang.zx2c4.com/wireguard/conn"
"golang.zx2c4.com/wireguard/device"
"golang.zx2c4.com/wireguard/tun/netstack"
diff --git a/tun/netstack/examples/http_server.go b/tun/netstack/examples/http_server.go
index 40f7804..0fdf4cd 100644
--- a/tun/netstack/examples/http_server.go
+++ b/tun/netstack/examples/http_server.go
@@ -13,8 +13,8 @@ import (
"log"
"net"
"net/http"
+ "net/netip"
- "golang.zx2c4.com/go118/netip"
"golang.zx2c4.com/wireguard/conn"
"golang.zx2c4.com/wireguard/device"
"golang.zx2c4.com/wireguard/tun/netstack"
diff --git a/tun/netstack/examples/ping_client.go b/tun/netstack/examples/ping_client.go
new file mode 100644
index 0000000..a1bc7f8
--- /dev/null
+++ b/tun/netstack/examples/ping_client.go
@@ -0,0 +1,76 @@
+//go:build ignore
+// +build ignore
+
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ */
+
+package main
+
+import (
+ "bytes"
+ "log"
+ "math/rand"
+ "net/netip"
+ "time"
+
+ "golang.org/x/net/icmp"
+ "golang.org/x/net/ipv4"
+
+ "golang.zx2c4.com/wireguard/conn"
+ "golang.zx2c4.com/wireguard/device"
+ "golang.zx2c4.com/wireguard/tun/netstack"
+)
+
+func main() {
+ tun, tnet, err := netstack.CreateNetTUN(
+ []netip.Addr{netip.MustParseAddr("192.168.4.29")},
+ []netip.Addr{netip.MustParseAddr("8.8.8.8")},
+ 1420)
+ if err != nil {
+ log.Panic(err)
+ }
+ dev := device.NewDevice(tun, conn.NewDefaultBind(), device.NewLogger(device.LogLevelVerbose, ""))
+ dev.IpcSet(`private_key=a8dac1d8a70a751f0f699fb14ba1cff7b79cf4fbd8f09f44c6e6a90d0369604f
+public_key=25123c5dcd3328ff645e4f2a3fce0d754400d3887a0cb7c56f0267e20fbf3c5b
+endpoint=163.172.161.0:12912
+allowed_ip=0.0.0.0/0
+`)
+ err = dev.Up()
+ if err != nil {
+ log.Panic(err)
+ }
+
+ socket, err := tnet.Dial("ping4", "zx2c4.com")
+ if err != nil {
+ log.Panic(err)
+ }
+ requestPing := icmp.Echo{
+ Seq: rand.Intn(1 << 16),
+ Data: []byte("gopher burrow"),
+ }
+ icmpBytes, _ := (&icmp.Message{Type: ipv4.ICMPTypeEcho, Code: 0, Body: &requestPing}).Marshal(nil)
+ socket.SetReadDeadline(time.Now().Add(time.Second * 10))
+ start := time.Now()
+ _, err = socket.Write(icmpBytes)
+ if err != nil {
+ log.Panic(err)
+ }
+ n, err := socket.Read(icmpBytes[:])
+ if err != nil {
+ log.Panic(err)
+ }
+ replyPacket, err := icmp.ParseMessage(1, icmpBytes[:n])
+ if err != nil {
+ log.Panic(err)
+ }
+ replyPing, ok := replyPacket.Body.(*icmp.Echo)
+ if !ok {
+ log.Panicf("invalid reply type: %v", replyPacket)
+ }
+ if !bytes.Equal(replyPing.Data, requestPing.Data) || replyPing.Seq != requestPing.Seq {
+ log.Panicf("invalid ping reply: %v", replyPing)
+ }
+ log.Printf("Ping latency: %v", time.Since(start))
+}
diff --git a/tun/netstack/go.mod b/tun/netstack/go.mod
index 46b57ba..18aa993 100644
--- a/tun/netstack/go.mod
+++ b/tun/netstack/go.mod
@@ -1,12 +1,17 @@
module golang.zx2c4.com/wireguard/tun/netstack
-go 1.16
+go 1.18
require (
- golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6
- golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 // indirect
- golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect
- golang.zx2c4.com/go118/netip v0.0.0-20211105124833-002a02cb0e53
- golang.zx2c4.com/wireguard v0.0.0-20210424170727-c9db4b7aaa22
+ golang.org/x/net v0.0.0-20220225172249-27dd8689420f
+ golang.zx2c4.com/wireguard v0.0.0-20220316235147-5aff28b14c24
gvisor.dev/gvisor v0.0.0-20211020211948-f76a604701b6
)
+
+require (
+ github.com/google/btree v1.0.1 // indirect
+ golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd // indirect
+ golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86 // indirect
+ golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect
+ golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 // indirect
+)
diff --git a/tun/netstack/go.sum b/tun/netstack/go.sum
index 01bfbc7..845c7e0 100644
--- a/tun/netstack/go.sum
+++ b/tun/netstack/go.sum
@@ -559,8 +559,9 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g=
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
+golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd h1:XcWmESyNjXJMLahc3mqVQJcgSTDxFxhETVlfk9uGc38=
+golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -638,8 +639,8 @@ golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6 h1:0PC75Fz/kyMGhL0e1QnypqK2kQMqKt9csD1GnMJR+Zk=
-golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
+golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc=
+golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -726,11 +727,9 @@ golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210309040221-94ec62e08169/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210314195730-07df6a141424/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw=
-golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86 h1:A9i04dxx7Cribqbs8jf3FQLogkL/CV2YN7hj9KWJCkc=
+golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -741,13 +740,11 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE=
-golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -805,12 +802,10 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.zx2c4.com/go118/netip v0.0.0-20211104120624-f0ae7a6e37c5 h1:mV4w4F7AtWXoDNkko9odoTdWpNwyDh8jx+S1fOZKDLg=
-golang.zx2c4.com/go118/netip v0.0.0-20211104120624-f0ae7a6e37c5/go.mod h1:5yyfuiqVIJ7t+3MqrpTQ+QqRkMWiESiyDvPNvKYCecg=
-golang.zx2c4.com/go118/netip v0.0.0-20211105124833-002a02cb0e53 h1:nFvpdzrHF9IPo9xPgayHWObCATpQYKky8VSSdt9lf9E=
-golang.zx2c4.com/go118/netip v0.0.0-20211105124833-002a02cb0e53/go.mod h1:5yyfuiqVIJ7t+3MqrpTQ+QqRkMWiESiyDvPNvKYCecg=
-golang.zx2c4.com/wireguard v0.0.0-20210424170727-c9db4b7aaa22 h1:ytS28bw9HtZVDRMDxviC6ryCJuccw+zXhh04u2IRWJw=
-golang.zx2c4.com/wireguard v0.0.0-20210424170727-c9db4b7aaa22/go.mod h1:a057zjmoc00UN7gVkaJt2sXVK523kMJcogDTEvPIasg=
+golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 h1:Ug9qvr1myri/zFN6xL17LSCBGFDnphBBhzmILHsM5TY=
+golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
+golang.zx2c4.com/wireguard v0.0.0-20220316235147-5aff28b14c24 h1:KwsvzlnmErwMd3BXoBSEuL8qU72QxFM/uOUAgZmavRc=
+golang.zx2c4.com/wireguard v0.0.0-20220316235147-5aff28b14c24/go.mod h1:bVQfyl2sCM/QIIGHpWbFGfHPuDvqnCNkT6MQLTCjO/U=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
diff --git a/tun/netstack/tun.go b/tun/netstack/tun.go
index fb7f07d..c26d8ed 100644
--- a/tun/netstack/tun.go
+++ b/tun/netstack/tun.go
@@ -13,12 +13,13 @@ import (
"fmt"
"io"
"net"
+ "net/netip"
"os"
+ "regexp"
"strconv"
"strings"
"time"
- "golang.zx2c4.com/go118/netip"
"golang.zx2c4.com/wireguard/tun"
"golang.org/x/net/dns/dnsmessage"
@@ -29,8 +30,10 @@ import (
"gvisor.dev/gvisor/pkg/tcpip/network/ipv4"
"gvisor.dev/gvisor/pkg/tcpip/network/ipv6"
"gvisor.dev/gvisor/pkg/tcpip/stack"
+ "gvisor.dev/gvisor/pkg/tcpip/transport/icmp"
"gvisor.dev/gvisor/pkg/tcpip/transport/tcp"
"gvisor.dev/gvisor/pkg/tcpip/transport/udp"
+ "gvisor.dev/gvisor/pkg/waiter"
)
type netTun struct {
@@ -101,7 +104,7 @@ func (e *endpoint) AddHeader(tcpip.LinkAddress, tcpip.LinkAddress, tcpip.Network
func CreateNetTUN(localAddresses, dnsServers []netip.Addr, mtu int) (tun.Device, *Net, error) {
opts := stack.Options{
NetworkProtocols: []stack.NetworkProtocolFactory{ipv4.NewProtocol, ipv6.NewProtocol},
- TransportProtocols: []stack.TransportProtocolFactory{tcp.NewProtocol, udp.NewProtocol},
+ TransportProtocols: []stack.TransportProtocolFactory{tcp.NewProtocol, udp.NewProtocol, icmp.NewProtocol6, icmp.NewProtocol4},
HandleLocal: true,
}
dev := &netTun{
@@ -227,7 +230,8 @@ func (net *Net) DialContextTCP(ctx context.Context, addr *net.TCPAddr) (*gonet.T
if addr == nil {
return net.DialContextTCPAddrPort(ctx, netip.AddrPort{})
}
- return net.DialContextTCPAddrPort(ctx, netip.AddrPortFrom(netip.AddrFromSlice(addr.IP), uint16(addr.Port)))
+ ip, _ := netip.AddrFromSlice(addr.IP)
+ return net.DialContextTCPAddrPort(ctx, netip.AddrPortFrom(ip, uint16(addr.Port)))
}
func (net *Net) DialTCPAddrPort(addr netip.AddrPort) (*gonet.TCPConn, error) {
@@ -239,7 +243,8 @@ func (net *Net) DialTCP(addr *net.TCPAddr) (*gonet.TCPConn, error) {
if addr == nil {
return net.DialTCPAddrPort(netip.AddrPort{})
}
- return net.DialTCPAddrPort(netip.AddrPortFrom(netip.AddrFromSlice(addr.IP), uint16(addr.Port)))
+ ip, _ := netip.AddrFromSlice(addr.IP)
+ return net.DialTCPAddrPort(netip.AddrPortFrom(ip, uint16(addr.Port)))
}
func (net *Net) ListenTCPAddrPort(addr netip.AddrPort) (*gonet.TCPListener, error) {
@@ -251,7 +256,8 @@ func (net *Net) ListenTCP(addr *net.TCPAddr) (*gonet.TCPListener, error) {
if addr == nil {
return net.ListenTCPAddrPort(netip.AddrPort{})
}
- return net.ListenTCPAddrPort(netip.AddrPortFrom(netip.AddrFromSlice(addr.IP), uint16(addr.Port)))
+ ip, _ := netip.AddrFromSlice(addr.IP)
+ return net.ListenTCPAddrPort(netip.AddrPortFrom(ip, uint16(addr.Port)))
}
func (net *Net) DialUDPAddrPort(laddr, raddr netip.AddrPort) (*gonet.UDPConn, error) {
@@ -270,17 +276,222 @@ func (net *Net) DialUDPAddrPort(laddr, raddr netip.AddrPort) (*gonet.UDPConn, er
return gonet.DialUDP(net.stack, lfa, rfa, pn)
}
+func (net *Net) ListenUDPAddrPort(laddr netip.AddrPort) (*gonet.UDPConn, error) {
+ return net.DialUDPAddrPort(laddr, netip.AddrPort{})
+}
+
func (net *Net) DialUDP(laddr, raddr *net.UDPAddr) (*gonet.UDPConn, error) {
var la, ra netip.AddrPort
if laddr != nil {
- la = netip.AddrPortFrom(netip.AddrFromSlice(laddr.IP), uint16(laddr.Port))
+ ip, _ := netip.AddrFromSlice(laddr.IP)
+ la = netip.AddrPortFrom(ip, uint16(laddr.Port))
}
if raddr != nil {
- ra = netip.AddrPortFrom(netip.AddrFromSlice(raddr.IP), uint16(raddr.Port))
+ ip, _ := netip.AddrFromSlice(raddr.IP)
+ ra = netip.AddrPortFrom(ip, uint16(raddr.Port))
}
return net.DialUDPAddrPort(la, ra)
}
+func (net *Net) ListenUDP(laddr *net.UDPAddr) (*gonet.UDPConn, error) {
+ return net.DialUDP(laddr, nil)
+}
+
+type PingConn struct {
+ laddr PingAddr
+ raddr PingAddr
+ wq waiter.Queue
+ ep tcpip.Endpoint
+ deadline *time.Timer
+}
+
+type PingAddr struct{ addr netip.Addr }
+
+func (ia PingAddr) String() string {
+ return ia.addr.String()
+}
+
+func (ia PingAddr) Network() string {
+ if ia.addr.Is4() {
+ return "ping4"
+ } else if ia.addr.Is6() {
+ return "ping6"
+ }
+ return "ping"
+}
+
+func (ia PingAddr) Addr() netip.Addr {
+ return ia.addr
+}
+
+func PingAddrFromAddr(addr netip.Addr) *PingAddr {
+ return &PingAddr{addr}
+}
+
+func (net *Net) DialPingAddr(laddr, raddr netip.Addr) (*PingConn, error) {
+ if !laddr.IsValid() && !raddr.IsValid() {
+ return nil, errors.New("ping dial: invalid address")
+ }
+ v6 := laddr.Is6() || raddr.Is6()
+ bind := laddr.IsValid()
+ if !bind {
+ if v6 {
+ laddr = netip.IPv6Unspecified()
+ } else {
+ laddr = netip.IPv4Unspecified()
+ }
+ }
+
+ tn := icmp.ProtocolNumber4
+ pn := ipv4.ProtocolNumber
+ if v6 {
+ tn = icmp.ProtocolNumber6
+ pn = ipv6.ProtocolNumber
+ }
+
+ pc := &PingConn{
+ laddr: PingAddr{laddr},
+ deadline: time.NewTimer(time.Hour << 10),
+ }
+ pc.deadline.Stop()
+
+ ep, tcpipErr := net.stack.NewEndpoint(tn, pn, &pc.wq)
+ if tcpipErr != nil {
+ return nil, fmt.Errorf("ping socket: endpoint: %s", tcpipErr)
+ }
+ pc.ep = ep
+
+ if bind {
+ fa, _ := convertToFullAddr(netip.AddrPortFrom(laddr, 0))
+ if tcpipErr = pc.ep.Bind(fa); tcpipErr != nil {
+ return nil, fmt.Errorf("ping bind: %s", tcpipErr)
+ }
+ }
+
+ if raddr.IsValid() {
+ pc.raddr = PingAddr{raddr}
+ fa, _ := convertToFullAddr(netip.AddrPortFrom(raddr, 0))
+ if tcpipErr = pc.ep.Connect(fa); tcpipErr != nil {
+ return nil, fmt.Errorf("ping connect: %s", tcpipErr)
+ }
+ }
+
+ return pc, nil
+}
+
+func (net *Net) ListenPingAddr(laddr netip.Addr) (*PingConn, error) {
+ return net.DialPingAddr(laddr, netip.Addr{})
+}
+
+func (net *Net) DialPing(laddr, raddr *PingAddr) (*PingConn, error) {
+ var la, ra netip.Addr
+ if laddr != nil {
+ la = laddr.addr
+ }
+ if raddr != nil {
+ ra = raddr.addr
+ }
+ return net.DialPingAddr(la, ra)
+}
+
+func (net *Net) ListenPing(laddr *PingAddr) (*PingConn, error) {
+ var la netip.Addr
+ if laddr != nil {
+ la = laddr.addr
+ }
+ return net.ListenPingAddr(la)
+}
+
+func (pc *PingConn) LocalAddr() net.Addr {
+ return pc.laddr
+}
+
+func (pc *PingConn) RemoteAddr() net.Addr {
+ return pc.raddr
+}
+
+func (pc *PingConn) Close() error {
+ pc.deadline.Reset(0)
+ pc.ep.Close()
+ return nil
+}
+
+func (pc *PingConn) SetWriteDeadline(t time.Time) error {
+ return errors.New("not implemented")
+}
+
+func (pc *PingConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
+ var na netip.Addr
+ switch v := addr.(type) {
+ case *PingAddr:
+ na = v.addr
+ case *net.IPAddr:
+ na, _ = netip.AddrFromSlice(v.IP)
+ default:
+ return 0, fmt.Errorf("ping write: wrong net.Addr type")
+ }
+ if !((na.Is4() && pc.laddr.addr.Is4()) || (na.Is6() && pc.laddr.addr.Is6())) {
+ return 0, fmt.Errorf("ping write: mismatched protocols")
+ }
+
+ buf := buffer.NewViewFromBytes(p)
+ rdr := buf.Reader()
+ rfa, _ := convertToFullAddr(netip.AddrPortFrom(na, 0))
+ // won't block, no deadlines
+ n64, tcpipErr := pc.ep.Write(&rdr, tcpip.WriteOptions{
+ To: &rfa,
+ })
+ if tcpipErr != nil {
+ return int(n64), fmt.Errorf("ping write: %s", tcpipErr)
+ }
+
+ return int(n64), nil
+}
+
+func (pc *PingConn) Write(p []byte) (n int, err error) {
+ return pc.WriteTo(p, &pc.raddr)
+}
+
+func (pc *PingConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
+ e, notifyCh := waiter.NewChannelEntry(nil)
+ pc.wq.EventRegister(&e, waiter.EventIn)
+ defer pc.wq.EventUnregister(&e)
+
+ select {
+ case <-pc.deadline.C:
+ return 0, nil, os.ErrDeadlineExceeded
+ case <-notifyCh:
+ }
+
+ w := tcpip.SliceWriter(p)
+
+ res, tcpipErr := pc.ep.Read(&w, tcpip.ReadOptions{
+ NeedRemoteAddr: true,
+ })
+ if tcpipErr != nil {
+ return 0, nil, fmt.Errorf("ping read: %s", tcpipErr)
+ }
+
+ remoteAddr, _ := netip.AddrFromSlice([]byte(res.RemoteAddr.Addr))
+ return res.Count, &PingAddr{remoteAddr}, nil
+}
+
+func (pc *PingConn) Read(p []byte) (n int, err error) {
+ n, _, err = pc.ReadFrom(p)
+ return
+}
+
+func (pc *PingConn) SetDeadline(t time.Time) error {
+ // pc.SetWriteDeadline is unimplemented
+
+ return pc.SetReadDeadline(t)
+}
+
+func (pc *PingConn) SetReadDeadline(t time.Time) error {
+ pc.deadline.Reset(t.Sub(time.Now()))
+ return nil
+}
+
var (
errNoSuchHost = errors.New("no such host")
errLameReferral = errors.New("lame referral")
@@ -479,7 +690,10 @@ func (tnet *Net) exchange(ctx context.Context, server netip.Addr, q dnsmessage.Q
return dnsmessage.Parser{}, dnsmessage.Header{}, err
}
if d, ok := ctx.Deadline(); ok && !d.IsZero() {
- c.SetDeadline(d)
+ err := c.SetDeadline(d)
+ if err != nil {
+ return dnsmessage.Parser{}, dnsmessage.Header{}, err
+ }
}
var p dnsmessage.Parser
var h dnsmessage.Header
@@ -755,33 +969,38 @@ func partialDeadline(now, deadline time.Time, addrsRemaining int) (time.Time, er
return now.Add(timeout), nil
}
+var protoSplitter = regexp.MustCompile(`^(tcp|udp|ping)(4|6)?$`)
+
func (tnet *Net) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
if ctx == nil {
panic("nil context")
}
- var acceptV4, acceptV6, useUDP bool
- if len(network) == 3 {
+ var acceptV4, acceptV6 bool
+ matches := protoSplitter.FindStringSubmatch(network)
+ if matches == nil {
+ return nil, &net.OpError{Op: "dial", Err: net.UnknownNetworkError(network)}
+ } else if len(matches[2]) == 0 {
acceptV4 = true
acceptV6 = true
- } else if len(network) == 4 {
- acceptV4 = network[3] == '4'
- acceptV6 = network[3] == '6'
- }
- if !acceptV4 && !acceptV6 {
- return nil, &net.OpError{Op: "dial", Err: net.UnknownNetworkError(network)}
- }
- if network[:3] == "udp" {
- useUDP = true
- } else if network[:3] != "tcp" {
- return nil, &net.OpError{Op: "dial", Err: net.UnknownNetworkError(network)}
- }
- host, sport, err := net.SplitHostPort(address)
- if err != nil {
- return nil, &net.OpError{Op: "dial", Err: err}
+ } else {
+ acceptV4 = matches[2][0] == '4'
+ acceptV6 = !acceptV4
}
- port, err := strconv.Atoi(sport)
- if err != nil || port < 0 || port > 65535 {
- return nil, &net.OpError{Op: "dial", Err: errNumericPort}
+ var host string
+ var port int
+ if matches[1] == "ping" {
+ host = address
+ } else {
+ var sport string
+ var err error
+ host, sport, err = net.SplitHostPort(address)
+ if err != nil {
+ return nil, &net.OpError{Op: "dial", Err: err}
+ }
+ port, err = strconv.Atoi(sport)
+ if err != nil || port < 0 || port > 65535 {
+ return nil, &net.OpError{Op: "dial", Err: errNumericPort}
+ }
}
allAddr, err := tnet.LookupContextHost(ctx, host)
if err != nil {
@@ -829,10 +1048,13 @@ func (tnet *Net) DialContext(ctx context.Context, network, address string) (net.
}
var c net.Conn
- if useUDP {
- c, err = tnet.DialUDPAddrPort(netip.AddrPort{}, addr)
- } else {
+ switch matches[1] {
+ case "tcp":
c, err = tnet.DialContextTCPAddrPort(dialCtx, addr)
+ case "udp":
+ c, err = tnet.DialUDPAddrPort(netip.AddrPort{}, addr)
+ case "ping":
+ c, err = tnet.DialPingAddr(netip.Addr{}, addr.Addr())
}
if err == nil {
return c, nil
diff --git a/tun/tuntest/tuntest.go b/tun/tuntest/tuntest.go
index bdf0467..8196c34 100644
--- a/tun/tuntest/tuntest.go
+++ b/tun/tuntest/tuntest.go
@@ -8,9 +8,9 @@ package tuntest
import (
"encoding/binary"
"io"
+ "net/netip"
"os"
- "golang.zx2c4.com/go118/netip"
"golang.zx2c4.com/wireguard/tun"
)
diff --git a/version.go b/version.go
index 0c53f39..79f0884 100644
--- a/version.go
+++ b/version.go
@@ -1,3 +1,3 @@
package main
-const Version = "0.0.20211016"
+const Version = "0.0.20220316"