mirror of
https://github.com/yggdrasil-network/yggdrasil-go.git
synced 2025-04-28 06:05:06 +03:00
Merge branch 'develop' into secure_address_generation
This commit is contained in:
commit
5b77793ba6
26 changed files with 470 additions and 134 deletions
12
.github/workflows/ci.yml
vendored
12
.github/workflows/ci.yml
vendored
|
@ -17,10 +17,10 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/setup-go@v5
|
- uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: 1.21
|
go-version: stable
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: golangci-lint
|
- name: golangci-lint
|
||||||
uses: golangci/golangci-lint-action@v3
|
uses: golangci/golangci-lint-action@v6
|
||||||
with:
|
with:
|
||||||
args: --issues-exit-code=1
|
args: --issues-exit-code=1
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ jobs:
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
goversion: ["1.21", "1.22"]
|
goversion: ["1.21", "1.22", "1.23"]
|
||||||
|
|
||||||
name: Build & Test (Linux, Go ${{ matrix.goversion }})
|
name: Build & Test (Linux, Go ${{ matrix.goversion }})
|
||||||
needs: [lint]
|
needs: [lint]
|
||||||
|
@ -75,7 +75,7 @@ jobs:
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
goversion: ["1.21", "1.22"]
|
goversion: ["1.21", "1.22", "1.23"]
|
||||||
|
|
||||||
name: Build & Test (Windows, Go ${{ matrix.goversion }})
|
name: Build & Test (Windows, Go ${{ matrix.goversion }})
|
||||||
needs: [lint]
|
needs: [lint]
|
||||||
|
@ -99,7 +99,7 @@ jobs:
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
goversion: ["1.21", "1.22"]
|
goversion: ["1.21", "1.22", "1.23"]
|
||||||
|
|
||||||
name: Build & Test (macOS, Go ${{ matrix.goversion }})
|
name: Build & Test (macOS, Go ${{ matrix.goversion }})
|
||||||
needs: [lint]
|
needs: [lint]
|
||||||
|
@ -123,7 +123,7 @@ jobs:
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
goversion: ["1.21", "1.22"]
|
goversion: ["1.21", "1.22", "1.23"]
|
||||||
goos:
|
goos:
|
||||||
- freebsd
|
- freebsd
|
||||||
- openbsd
|
- openbsd
|
||||||
|
|
|
@ -2,9 +2,10 @@ run:
|
||||||
build-tags:
|
build-tags:
|
||||||
- lint
|
- lint
|
||||||
issues-exit-code: 0 # TODO: change this to 1 when we want it to fail builds
|
issues-exit-code: 0 # TODO: change this to 1 when we want it to fail builds
|
||||||
skip-dirs:
|
issues:
|
||||||
|
exclude-dirs:
|
||||||
- contrib/
|
- contrib/
|
||||||
- misc/
|
- misc/
|
||||||
linters:
|
linters:
|
||||||
disable:
|
disable:
|
||||||
- gocyclo
|
- gocyclo
|
||||||
|
|
10
cmd/yggdrasil/chuser_other.go
Normal file
10
cmd/yggdrasil/chuser_other.go
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
//go:build !aix && !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris
|
||||||
|
// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
func chuser(user string) error {
|
||||||
|
return errors.New("setting uid/gid is not supported on this platform")
|
||||||
|
}
|
87
cmd/yggdrasil/chuser_unix.go
Normal file
87
cmd/yggdrasil/chuser_unix.go
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
|
||||||
|
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
osuser "os/user"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
func chuser(user string) error {
|
||||||
|
group := ""
|
||||||
|
if i := strings.IndexByte(user, ':'); i >= 0 {
|
||||||
|
user, group = user[:i], user[i+1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
u := (*osuser.User)(nil)
|
||||||
|
g := (*osuser.Group)(nil)
|
||||||
|
|
||||||
|
if user != "" {
|
||||||
|
if _, err := strconv.ParseUint(user, 10, 32); err == nil {
|
||||||
|
u, err = osuser.LookupId(user)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to lookup user by id %q: %v", user, err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
u, err = osuser.Lookup(user)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to lookup user by name %q: %v", user, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if group != "" {
|
||||||
|
if _, err := strconv.ParseUint(group, 10, 32); err == nil {
|
||||||
|
g, err = osuser.LookupGroupId(group)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to lookup group by id %q: %v", user, err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
g, err = osuser.LookupGroup(group)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to lookup group by name %q: %v", user, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if g != nil {
|
||||||
|
gid, _ := strconv.ParseUint(g.Gid, 10, 32)
|
||||||
|
var err error
|
||||||
|
if gid < math.MaxInt {
|
||||||
|
err = syscall.Setgid(int(gid))
|
||||||
|
} else {
|
||||||
|
err = errors.New("gid too big")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to setgid %d: %v", gid, err)
|
||||||
|
}
|
||||||
|
} else if u != nil {
|
||||||
|
gid, _ := strconv.ParseUint(u.Gid, 10, 32)
|
||||||
|
err := syscall.Setgid(int(uint32(gid)))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to setgid %d: %v", gid, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if u != nil {
|
||||||
|
uid, _ := strconv.ParseUint(u.Uid, 10, 32)
|
||||||
|
var err error
|
||||||
|
if uid < math.MaxInt {
|
||||||
|
err = syscall.Setuid(int(uid))
|
||||||
|
} else {
|
||||||
|
err = errors.New("uid too big")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to setuid %d: %v", uid, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -53,6 +53,7 @@ func main() {
|
||||||
getsnet := flag.Bool("subnet", false, "use in combination with either -useconf or -useconffile, outputs your IPv6 subnet")
|
getsnet := flag.Bool("subnet", false, "use in combination with either -useconf or -useconffile, outputs your IPv6 subnet")
|
||||||
getpkey := flag.Bool("publickey", false, "use in combination with either -useconf or -useconffile, outputs your public key")
|
getpkey := flag.Bool("publickey", false, "use in combination with either -useconf or -useconffile, outputs your public key")
|
||||||
loglevel := flag.String("loglevel", "info", "loglevel to enable")
|
loglevel := flag.String("loglevel", "info", "loglevel to enable")
|
||||||
|
chuserto := flag.String("user", "", "user (and, optionally, group) to set UID/GID to")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
|
@ -286,6 +287,14 @@ func main() {
|
||||||
<-done
|
<-done
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Change user if requested
|
||||||
|
if *chuserto != "" {
|
||||||
|
err = chuser(*chuserto)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Block until we are told to shut down.
|
// Block until we are told to shut down.
|
||||||
<-ctx.Done()
|
<-ctx.Done()
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,6 @@ func (cmdLineEnv *CmdLineEnv) parseFlagsAndArgs() {
|
||||||
fmt.Println("Examples:")
|
fmt.Println("Examples:")
|
||||||
fmt.Println(" - ", os.Args[0], "list")
|
fmt.Println(" - ", os.Args[0], "list")
|
||||||
fmt.Println(" - ", os.Args[0], "getPeers")
|
fmt.Println(" - ", os.Args[0], "getPeers")
|
||||||
fmt.Println(" - ", os.Args[0], "setTunTap name=auto mtu=1500 tap_mode=false")
|
|
||||||
fmt.Println(" - ", os.Args[0], "-endpoint=tcp://localhost:9001 getPeers")
|
fmt.Println(" - ", os.Args[0], "-endpoint=tcp://localhost:9001 getPeers")
|
||||||
fmt.Println(" - ", os.Args[0], "-endpoint=unix:///var/run/ygg.sock getPeers")
|
fmt.Println(" - ", os.Args[0], "-endpoint=unix:///var/run/ygg.sock getPeers")
|
||||||
}
|
}
|
||||||
|
|
|
@ -174,7 +174,7 @@ func run() int {
|
||||||
if err := json.Unmarshal(recv.Response, &resp); err != nil {
|
if err := json.Unmarshal(recv.Response, &resp); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
table.SetHeader([]string{"URI", "State", "Dir", "IP Address", "Uptime", "RTT", "RX", "TX", "Pr", "Last Error"})
|
table.SetHeader([]string{"URI", "State", "Dir", "IP Address", "Uptime", "RTT", "RX", "TX", "Pr", "Cost", "Last Error"})
|
||||||
for _, peer := range resp.Peers {
|
for _, peer := range resp.Peers {
|
||||||
state, lasterr, dir, rtt := "Up", "-", "Out", "-"
|
state, lasterr, dir, rtt := "Up", "-", "Out", "-"
|
||||||
if !peer.Up {
|
if !peer.Up {
|
||||||
|
@ -200,6 +200,7 @@ func run() int {
|
||||||
peer.RXBytes.String(),
|
peer.RXBytes.String(),
|
||||||
peer.TXBytes.String(),
|
peer.TXBytes.String(),
|
||||||
fmt.Sprintf("%d", peer.Priority),
|
fmt.Sprintf("%d", peer.Priority),
|
||||||
|
fmt.Sprintf("%d", peer.Cost),
|
||||||
lasterr,
|
lasterr,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ set -ef
|
||||||
PKGSRC=${PKGSRC:-github.com/yggdrasil-network/yggdrasil-go/src/version}
|
PKGSRC=${PKGSRC:-github.com/yggdrasil-network/yggdrasil-go/src/version}
|
||||||
PKGNAME=${PKGNAME:-$(sh contrib/semver/name.sh)}
|
PKGNAME=${PKGNAME:-$(sh contrib/semver/name.sh)}
|
||||||
PKGVER=${PKGVER:-$(sh contrib/semver/version.sh --bare)}
|
PKGVER=${PKGVER:-$(sh contrib/semver/version.sh --bare)}
|
||||||
|
GOVER=$(go version | { read _ _ version _; echo ${version#go}; })
|
||||||
|
|
||||||
LDFLAGS="-X $PKGSRC.buildName=$PKGNAME -X $PKGSRC.buildVersion=$PKGVER"
|
LDFLAGS="-X $PKGSRC.buildName=$PKGNAME -X $PKGSRC.buildVersion=$PKGVER"
|
||||||
ARGS="-v"
|
ARGS="-v"
|
||||||
|
@ -33,6 +34,15 @@ if [ ! $IOS ] && [ ! $ANDROID ]; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
ver_le() {
|
||||||
|
printf "$1\n$2\n" | sort -VC
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ $ANDROID ] && ver_le 1.23.0 $GOVER ; then
|
||||||
|
# github.com/wlynxg/anet library relies on //go:linkname
|
||||||
|
LDFLAGS="$LDFLAGS -checklinkname=0"
|
||||||
|
fi
|
||||||
|
|
||||||
if [ $IOS ]; then
|
if [ $IOS ]; then
|
||||||
echo "Building framework for iOS"
|
echo "Building framework for iOS"
|
||||||
go get golang.org/x/mobile/bind
|
go get golang.org/x/mobile/bind
|
||||||
|
|
|
@ -15,8 +15,6 @@ import (
|
||||||
"github.com/yggdrasil-network/yggdrasil-go/src/multicast"
|
"github.com/yggdrasil-network/yggdrasil-go/src/multicast"
|
||||||
"github.com/yggdrasil-network/yggdrasil-go/src/tun"
|
"github.com/yggdrasil-network/yggdrasil-go/src/tun"
|
||||||
"github.com/yggdrasil-network/yggdrasil-go/src/version"
|
"github.com/yggdrasil-network/yggdrasil-go/src/version"
|
||||||
|
|
||||||
_ "golang.org/x/mobile/bind"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Yggdrasil mobile package is meant to "plug the gap" for mobile support, as
|
// Yggdrasil mobile package is meant to "plug the gap" for mobile support, as
|
||||||
|
|
25
go.mod
25
go.mod
|
@ -3,24 +3,24 @@ module github.com/yggdrasil-network/yggdrasil-go
|
||||||
go 1.21
|
go 1.21
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Arceliar/ironwood v0.0.0-20240529054413-b8e59574e2b2
|
github.com/Arceliar/ironwood v0.0.0-20241016082300-f6fb9da97a17
|
||||||
github.com/Arceliar/phony v0.0.0-20220903101357-530938a4b13d
|
github.com/Arceliar/phony v0.0.0-20220903101357-530938a4b13d
|
||||||
github.com/cheggaaa/pb/v3 v3.1.5
|
github.com/cheggaaa/pb/v3 v3.1.5
|
||||||
|
github.com/coder/websocket v1.8.12
|
||||||
github.com/gologme/log v1.3.0
|
github.com/gologme/log v1.3.0
|
||||||
github.com/hashicorp/go-syslog v1.0.0
|
github.com/hashicorp/go-syslog v1.0.0
|
||||||
github.com/hjson/hjson-go/v4 v4.4.0
|
github.com/hjson/hjson-go/v4 v4.4.0
|
||||||
github.com/kardianos/minwinsvc v1.0.2
|
github.com/kardianos/minwinsvc v1.0.2
|
||||||
github.com/quic-go/quic-go v0.45.1
|
github.com/quic-go/quic-go v0.46.0
|
||||||
github.com/vishvananda/netlink v1.1.0
|
github.com/vishvananda/netlink v1.3.0
|
||||||
github.com/wlynxg/anet v0.0.4-0.20240806025826-e684438fc7c6
|
github.com/wlynxg/anet v0.0.5
|
||||||
golang.org/x/crypto v0.25.0
|
golang.org/x/crypto v0.28.0
|
||||||
golang.org/x/mobile v0.0.0-20240716161057-1ad2df20a8b6
|
golang.org/x/net v0.30.0
|
||||||
golang.org/x/net v0.27.0
|
golang.org/x/sys v0.26.0
|
||||||
golang.org/x/sys v0.22.0
|
golang.org/x/text v0.19.0
|
||||||
golang.org/x/text v0.16.0
|
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2
|
||||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173
|
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173
|
||||||
golang.zx2c4.com/wireguard/windows v0.5.3
|
golang.zx2c4.com/wireguard/windows v0.5.3
|
||||||
nhooyr.io/websocket v1.8.11
|
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
@ -34,9 +34,8 @@ require (
|
||||||
go.uber.org/mock v0.4.0 // indirect
|
go.uber.org/mock v0.4.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
|
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
|
||||||
golang.org/x/mod v0.19.0 // indirect
|
golang.org/x/mod v0.19.0 // indirect
|
||||||
golang.org/x/sync v0.7.0 // indirect
|
golang.org/x/sync v0.8.0 // indirect
|
||||||
golang.org/x/tools v0.23.0 // indirect
|
golang.org/x/tools v0.23.0 // indirect
|
||||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
@ -45,5 +44,5 @@ require (
|
||||||
github.com/mattn/go-isatty v0.0.19 // indirect
|
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||||
github.com/olekukonko/tablewriter v0.0.5
|
github.com/olekukonko/tablewriter v0.0.5
|
||||||
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f // indirect
|
github.com/vishvananda/netns v0.0.4 // indirect
|
||||||
)
|
)
|
||||||
|
|
51
go.sum
51
go.sum
|
@ -1,5 +1,5 @@
|
||||||
github.com/Arceliar/ironwood v0.0.0-20240529054413-b8e59574e2b2 h1:SBdYBKeXYUUFef5wi2CMhYmXFVGiYaRpTvbki0Bu+JQ=
|
github.com/Arceliar/ironwood v0.0.0-20241016082300-f6fb9da97a17 h1:uOvHqPwu09ndYZQDUL6QvyDcz0M9kwooKYa/PEfLwIU=
|
||||||
github.com/Arceliar/ironwood v0.0.0-20240529054413-b8e59574e2b2/go.mod h1:6WP4799FX0OuWdENGQAh+0RXp9FLh0y7NZ7tM9cJyXk=
|
github.com/Arceliar/ironwood v0.0.0-20241016082300-f6fb9da97a17/go.mod h1:6WP4799FX0OuWdENGQAh+0RXp9FLh0y7NZ7tM9cJyXk=
|
||||||
github.com/Arceliar/phony v0.0.0-20220903101357-530938a4b13d h1:UK9fsWbWqwIQkMCz1CP+v5pGbsGoWAw6g4AyvMpm1EM=
|
github.com/Arceliar/phony v0.0.0-20220903101357-530938a4b13d h1:UK9fsWbWqwIQkMCz1CP+v5pGbsGoWAw6g4AyvMpm1EM=
|
||||||
github.com/Arceliar/phony v0.0.0-20220903101357-530938a4b13d/go.mod h1:BCnxhRf47C/dy/e/D2pmB8NkB3dQVIrkD98b220rx5Q=
|
github.com/Arceliar/phony v0.0.0-20220903101357-530938a4b13d/go.mod h1:BCnxhRf47C/dy/e/D2pmB8NkB3dQVIrkD98b220rx5Q=
|
||||||
github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow=
|
github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow=
|
||||||
|
@ -14,6 +14,8 @@ github.com/cheggaaa/pb/v3 v3.1.5/go.mod h1:CrxkeghYTXi1lQBEI7jSn+3svI3cuc19haAj6
|
||||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||||
|
github.com/coder/websocket v1.8.12 h1:5bUXkEPPIbewrnkU8LTCLVaxi4N4J8ahufH2vlo4NAo=
|
||||||
|
github.com/coder/websocket v1.8.12/go.mod h1:LNVeNrXQZfe5qhS9ALED3uA+l5pPqvwXg3CKoDBB2gs=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
@ -56,8 +58,8 @@ github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE=
|
||||||
github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg=
|
github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/quic-go/quic-go v0.45.1 h1:tPfeYCk+uZHjmDRwHHQmvHRYL2t44ROTujLeFVBmjCA=
|
github.com/quic-go/quic-go v0.46.0 h1:uuwLClEEyk1DNvchH8uCByQVjo3yKL9opKulExNDs7Y=
|
||||||
github.com/quic-go/quic-go v0.45.1/go.mod h1:1dLehS7TIR64+vxGR70GDcatWTOtMX2PUtnKsjbTurI=
|
github.com/quic-go/quic-go v0.46.0/go.mod h1:1dLehS7TIR64+vxGR70GDcatWTOtMX2PUtnKsjbTurI=
|
||||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
@ -65,13 +67,12 @@ github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd
|
||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/twmb/murmur3 v1.1.6 h1:mqrRot1BRxm+Yct+vavLMou2/iJt0tNVTTC0QoIjaZg=
|
github.com/twmb/murmur3 v1.1.6 h1:mqrRot1BRxm+Yct+vavLMou2/iJt0tNVTTC0QoIjaZg=
|
||||||
github.com/twmb/murmur3 v1.1.6/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ=
|
github.com/twmb/murmur3 v1.1.6/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ=
|
||||||
github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0=
|
github.com/vishvananda/netlink v1.3.0 h1:X7l42GfcV4S6E4vHTsw48qbrV+9PVojNfIhZcwQdrZk=
|
||||||
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
|
github.com/vishvananda/netlink v1.3.0/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs=
|
||||||
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
|
github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8=
|
||||||
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f h1:p4VB7kIXpOQvVn1ZaTIVp+3vuYAXFe3OJEvjbUYJLaA=
|
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
|
||||||
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
github.com/wlynxg/anet v0.0.5 h1:J3VJGi1gvo0JwZ/P1/Yc/8p63SoW98B5dHkYDmpgvvU=
|
||||||
github.com/wlynxg/anet v0.0.4-0.20240806025826-e684438fc7c6 h1:c/wkXIJvpg2oot7iFqPESTBAO9UvhWTBnW97y9aPgyU=
|
github.com/wlynxg/anet v0.0.5/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA=
|
||||||
github.com/wlynxg/anet v0.0.4-0.20240806025826-e684438fc7c6/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA=
|
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
|
go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
|
||||||
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
|
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
|
||||||
|
@ -79,12 +80,10 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||||
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
|
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
|
||||||
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
|
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
|
||||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
|
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
|
||||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
||||||
golang.org/x/mobile v0.0.0-20240716161057-1ad2df20a8b6 h1:/VlmIrkuLf2wzPjkZ8imSpckHoW7Y71h66dxbLHSpi8=
|
|
||||||
golang.org/x/mobile v0.0.0-20240716161057-1ad2df20a8b6/go.mod h1:TCsc78+c4cqb8IKEosz2LwJ6YRNkIjMuAYeHYjchGDE=
|
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8=
|
golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8=
|
||||||
|
@ -95,29 +94,29 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
|
||||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||||
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
|
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
|
||||||
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
|
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/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-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
|
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
|
||||||
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
|
@ -131,8 +130,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
|
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
|
||||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
@ -156,5 +155,3 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gvisor.dev/gvisor v0.0.0-20230927004350-cbd86285d259 h1:TbRPT0HtzFP3Cno1zZo7yPzEEnfu8EjLfl6IU9VfqkQ=
|
gvisor.dev/gvisor v0.0.0-20230927004350-cbd86285d259 h1:TbRPT0HtzFP3Cno1zZo7yPzEEnfu8EjLfl6IU9VfqkQ=
|
||||||
gvisor.dev/gvisor v0.0.0-20230927004350-cbd86285d259/go.mod h1:AVgIgHMwK63XvmAzWG9vLQ41YnVHN0du0tEC46fI7yY=
|
gvisor.dev/gvisor v0.0.0-20230927004350-cbd86285d259/go.mod h1:AVgIgHMwK63XvmAzWG9vLQ41YnVHN0du0tEC46fI7yY=
|
||||||
nhooyr.io/websocket v1.8.11 h1:f/qXNc2/3DpoSZkHt1DQu6rj4zGC8JmkkLkWss0MgN0=
|
|
||||||
nhooyr.io/websocket v1.8.11/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c=
|
|
||||||
|
|
|
@ -238,27 +238,27 @@ func (a *AdminSocket) listen() {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
switch strings.ToLower(u.Scheme) {
|
switch strings.ToLower(u.Scheme) {
|
||||||
case "unix":
|
case "unix":
|
||||||
if _, err := os.Stat(listenaddr[7:]); err == nil {
|
if _, err := os.Stat(u.Path); err == nil {
|
||||||
a.log.Debugln("Admin socket", listenaddr[7:], "already exists, trying to clean up")
|
a.log.Debugln("Admin socket", u.Path, "already exists, trying to clean up")
|
||||||
if _, err := net.DialTimeout("unix", listenaddr[7:], time.Second*2); err == nil || err.(net.Error).Timeout() {
|
if _, err := net.DialTimeout("unix", u.Path, time.Second*2); err == nil || err.(net.Error).Timeout() {
|
||||||
a.log.Errorln("Admin socket", listenaddr[7:], "already exists and is in use by another process")
|
a.log.Errorln("Admin socket", u.Path, "already exists and is in use by another process")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
} else {
|
} else {
|
||||||
if err := os.Remove(listenaddr[7:]); err == nil {
|
if err := os.Remove(u.Path); err == nil {
|
||||||
a.log.Debugln(listenaddr[7:], "was cleaned up")
|
a.log.Debugln(u.Path, "was cleaned up")
|
||||||
} else {
|
} else {
|
||||||
a.log.Errorln(listenaddr[7:], "already exists and was not cleaned up:", err)
|
a.log.Errorln(u.Path, "already exists and was not cleaned up:", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
a.listener, err = net.Listen("unix", listenaddr[7:])
|
a.listener, err = net.Listen("unix", u.Path)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
switch listenaddr[7:8] {
|
switch u.Path[:1] {
|
||||||
case "@": // maybe abstract namespace
|
case "@": // maybe abstract namespace
|
||||||
default:
|
default:
|
||||||
if err := os.Chmod(listenaddr[7:], 0660); err != nil {
|
if err := os.Chmod(u.Path, 0660); err != nil {
|
||||||
a.log.Warnln("WARNING:", listenaddr[:7], "may have unsafe permissions!")
|
a.log.Warnln("WARNING:", u.Path, "may have unsafe permissions!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ package admin
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"net"
|
"net"
|
||||||
"sort"
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/yggdrasil-network/yggdrasil-go/src/address"
|
"github.com/yggdrasil-network/yggdrasil-go/src/address"
|
||||||
|
@ -35,8 +35,8 @@ func (a *AdminSocket) getPathsHandler(_ *GetPathsRequest, res *GetPathsResponse)
|
||||||
Sequence: p.Sequence,
|
Sequence: p.Sequence,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
sort.SliceStable(res.Paths, func(i, j int) bool {
|
slices.SortStableFunc(res.Paths, func(a, b PathEntry) int {
|
||||||
return strings.Compare(res.Paths[i].PublicKey, res.Paths[j].PublicKey) < 0
|
return strings.Compare(a.PublicKey, b.PublicKey)
|
||||||
})
|
})
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,8 @@ package admin
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"net"
|
"net"
|
||||||
"sort"
|
"slices"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/yggdrasil-network/yggdrasil-go/src/address"
|
"github.com/yggdrasil-network/yggdrasil-go/src/address"
|
||||||
|
@ -24,6 +25,7 @@ type PeerEntry struct {
|
||||||
PublicKey string `json:"key"`
|
PublicKey string `json:"key"`
|
||||||
Port uint64 `json:"port"`
|
Port uint64 `json:"port"`
|
||||||
Priority uint64 `json:"priority"`
|
Priority uint64 `json:"priority"`
|
||||||
|
Cost uint64 `json:"cost"`
|
||||||
RXBytes DataUnit `json:"bytes_recvd,omitempty"`
|
RXBytes DataUnit `json:"bytes_recvd,omitempty"`
|
||||||
TXBytes DataUnit `json:"bytes_sent,omitempty"`
|
TXBytes DataUnit `json:"bytes_sent,omitempty"`
|
||||||
Uptime float64 `json:"uptime,omitempty"`
|
Uptime float64 `json:"uptime,omitempty"`
|
||||||
|
@ -41,6 +43,7 @@ func (a *AdminSocket) getPeersHandler(_ *GetPeersRequest, res *GetPeersResponse)
|
||||||
Up: p.Up,
|
Up: p.Up,
|
||||||
Inbound: p.Inbound,
|
Inbound: p.Inbound,
|
||||||
Priority: uint64(p.Priority), // can't be uint8 thanks to gobind
|
Priority: uint64(p.Priority), // can't be uint8 thanks to gobind
|
||||||
|
Cost: p.Cost,
|
||||||
URI: p.URI,
|
URI: p.URI,
|
||||||
RXBytes: DataUnit(p.RXBytes),
|
RXBytes: DataUnit(p.RXBytes),
|
||||||
TXBytes: DataUnit(p.TXBytes),
|
TXBytes: DataUnit(p.TXBytes),
|
||||||
|
@ -59,17 +62,26 @@ func (a *AdminSocket) getPeersHandler(_ *GetPeersRequest, res *GetPeersResponse)
|
||||||
}
|
}
|
||||||
res.Peers = append(res.Peers, peer)
|
res.Peers = append(res.Peers, peer)
|
||||||
}
|
}
|
||||||
sort.Slice(res.Peers, func(i, j int) bool {
|
slices.SortStableFunc(res.Peers, func(a, b PeerEntry) int {
|
||||||
if res.Peers[i].Inbound == res.Peers[j].Inbound {
|
if !a.Inbound && b.Inbound {
|
||||||
if res.Peers[i].PublicKey == res.Peers[j].PublicKey {
|
return -1
|
||||||
if res.Peers[i].Priority == res.Peers[j].Priority {
|
|
||||||
return res.Peers[i].Uptime > res.Peers[j].Uptime
|
|
||||||
}
|
|
||||||
return res.Peers[i].Priority < res.Peers[j].Priority
|
|
||||||
}
|
|
||||||
return res.Peers[i].PublicKey < res.Peers[j].PublicKey
|
|
||||||
}
|
}
|
||||||
return !res.Peers[i].Inbound && res.Peers[j].Inbound
|
if a.Inbound && !b.Inbound {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
if d := strings.Compare(a.PublicKey, b.PublicKey); d != 0 {
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
if d := a.Priority - b.Priority; d != 0 {
|
||||||
|
return int(d)
|
||||||
|
}
|
||||||
|
if d := a.Cost - b.Cost; d != 0 {
|
||||||
|
return int(d)
|
||||||
|
}
|
||||||
|
if d := a.Uptime - b.Uptime; d != 0 {
|
||||||
|
return int(d)
|
||||||
|
}
|
||||||
|
return 0
|
||||||
})
|
})
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ package admin
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"net"
|
"net"
|
||||||
"sort"
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/yggdrasil-network/yggdrasil-go/src/address"
|
"github.com/yggdrasil-network/yggdrasil-go/src/address"
|
||||||
|
@ -36,8 +36,8 @@ func (a *AdminSocket) getSessionsHandler(_ *GetSessionsRequest, res *GetSessions
|
||||||
Uptime: s.Uptime.Seconds(),
|
Uptime: s.Uptime.Seconds(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
sort.SliceStable(res.Sessions, func(i, j int) bool {
|
slices.SortStableFunc(res.Sessions, func(a, b SessionEntry) int {
|
||||||
return strings.Compare(res.Sessions[i].PublicKey, res.Sessions[j].PublicKey) < 0
|
return strings.Compare(a.PublicKey, b.PublicKey)
|
||||||
})
|
})
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ package admin
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"net"
|
"net"
|
||||||
"sort"
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/yggdrasil-network/yggdrasil-go/src/address"
|
"github.com/yggdrasil-network/yggdrasil-go/src/address"
|
||||||
|
@ -34,8 +34,8 @@ func (a *AdminSocket) getTreeHandler(_ *GetTreeRequest, res *GetTreeResponse) er
|
||||||
Sequence: d.Sequence,
|
Sequence: d.Sequence,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
sort.SliceStable(res.Tree, func(i, j int) bool {
|
slices.SortStableFunc(res.Tree, func(a, b TreeEntry) int {
|
||||||
return strings.Compare(res.Tree[i].PublicKey, res.Tree[j].PublicKey) < 0
|
return strings.Compare(a.PublicKey, b.PublicKey)
|
||||||
})
|
})
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ type PeerInfo struct {
|
||||||
Coords []uint64
|
Coords []uint64
|
||||||
Port uint64
|
Port uint64
|
||||||
Priority uint8
|
Priority uint8
|
||||||
|
Cost uint64
|
||||||
RXBytes uint64
|
RXBytes uint64
|
||||||
TXBytes uint64
|
TXBytes uint64
|
||||||
Uptime time.Duration
|
Uptime time.Duration
|
||||||
|
@ -94,6 +95,7 @@ func (c *Core) GetPeers() []PeerInfo {
|
||||||
peerinfo.Port = p.Port
|
peerinfo.Port = p.Port
|
||||||
peerinfo.Priority = p.Priority
|
peerinfo.Priority = p.Priority
|
||||||
peerinfo.Latency = p.Latency
|
peerinfo.Latency = p.Latency
|
||||||
|
peerinfo.Cost = p.Cost
|
||||||
}
|
}
|
||||||
peers = append(peers, peerinfo)
|
peers = append(peers, peerinfo)
|
||||||
}
|
}
|
||||||
|
@ -148,7 +150,14 @@ func (c *Core) GetSessions() []SessionInfo {
|
||||||
// parsed from a string of the form e.g. "tcp://a.b.c.d:e". In the case of a
|
// parsed from a string of the form e.g. "tcp://a.b.c.d:e". In the case of a
|
||||||
// link-local address, the interface should be provided as the second argument.
|
// link-local address, the interface should be provided as the second argument.
|
||||||
func (c *Core) Listen(u *url.URL, sintf string) (*Listener, error) {
|
func (c *Core) Listen(u *url.URL, sintf string) (*Listener, error) {
|
||||||
return c.links.listen(u, sintf)
|
return c.links.listen(u, sintf, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListenLocal starts a listener, like the Listen function, but is used for
|
||||||
|
// more trustworthy situations where you want to ignore AllowedPublicKeys, i.e.
|
||||||
|
// with multicast listeners.
|
||||||
|
func (c *Core) ListenLocal(u *url.URL, sintf string) (*Listener, error) {
|
||||||
|
return c.links.listen(u, sintf, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Address gets the IPv6 address of the Yggdrasil node. This is always a /128
|
// Address gets the IPv6 address of the Yggdrasil node. This is always a /128
|
||||||
|
|
|
@ -127,7 +127,7 @@ func New(cert *tls.Certificate, logger Logger, opts ...SetupOption) (*Core, erro
|
||||||
c.log.Errorf("Invalid listener URI %q specified, ignoring\n", listenaddr)
|
c.log.Errorf("Invalid listener URI %q specified, ignoring\n", listenaddr)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if _, err = c.links.listen(u, ""); err != nil {
|
if _, err = c.links.listen(u, "", false); err != nil {
|
||||||
c.log.Errorf("Failed to start listener %q: %s\n", listenaddr, err)
|
c.log.Errorf("Failed to start listener %q: %s\n", listenaddr, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,27 @@ func GetLoggerWithPrefix(prefix string, verbose bool) *log.Logger {
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func require_NoError(t *testing.T, err error) {
|
||||||
|
t.Helper()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func require_Equal[T comparable](t *testing.T, a, b T) {
|
||||||
|
t.Helper()
|
||||||
|
if a != b {
|
||||||
|
t.Fatalf("%v != %v", a, b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func require_True(t *testing.T, a bool) {
|
||||||
|
t.Helper()
|
||||||
|
if !a {
|
||||||
|
t.Fatal("expected true")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// CreateAndConnectTwo creates two nodes. nodeB connects to nodeA.
|
// CreateAndConnectTwo creates two nodes. nodeB connects to nodeA.
|
||||||
// Verbosity flag is passed to logger.
|
// Verbosity flag is passed to logger.
|
||||||
func CreateAndConnectTwo(t testing.TB, verbose bool) (nodeA *Core, nodeB *Core) {
|
func CreateAndConnectTwo(t testing.TB, verbose bool) (nodeA *Core, nodeB *Core) {
|
||||||
|
@ -201,3 +222,69 @@ func BenchmarkCore_Start_Transfer(b *testing.B) {
|
||||||
}
|
}
|
||||||
<-done
|
<-done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAllowedPublicKeys(t *testing.T) {
|
||||||
|
logger := GetLoggerWithPrefix("", false)
|
||||||
|
cfgA, cfgB := config.GenerateConfig(), config.GenerateConfig()
|
||||||
|
require_NoError(t, cfgA.GenerateSelfSignedCertificate())
|
||||||
|
require_NoError(t, cfgB.GenerateSelfSignedCertificate())
|
||||||
|
|
||||||
|
nodeA, err := New(cfgA.Certificate, logger, AllowedPublicKey("abcdef"))
|
||||||
|
require_NoError(t, err)
|
||||||
|
defer nodeA.Stop()
|
||||||
|
|
||||||
|
nodeB, err := New(cfgB.Certificate, logger)
|
||||||
|
require_NoError(t, err)
|
||||||
|
defer nodeB.Stop()
|
||||||
|
|
||||||
|
u, err := url.Parse("tcp://localhost:0")
|
||||||
|
require_NoError(t, err)
|
||||||
|
|
||||||
|
l, err := nodeA.Listen(u, "")
|
||||||
|
require_NoError(t, err)
|
||||||
|
|
||||||
|
u, err = url.Parse("tcp://" + l.Addr().String())
|
||||||
|
require_NoError(t, err)
|
||||||
|
|
||||||
|
require_NoError(t, nodeB.AddPeer(u, ""))
|
||||||
|
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
|
||||||
|
peers := nodeB.GetPeers()
|
||||||
|
require_Equal(t, len(peers), 1)
|
||||||
|
require_True(t, !peers[0].Up)
|
||||||
|
require_True(t, peers[0].LastError != nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAllowedPublicKeysLocal(t *testing.T) {
|
||||||
|
logger := GetLoggerWithPrefix("", false)
|
||||||
|
cfgA, cfgB := config.GenerateConfig(), config.GenerateConfig()
|
||||||
|
require_NoError(t, cfgA.GenerateSelfSignedCertificate())
|
||||||
|
require_NoError(t, cfgB.GenerateSelfSignedCertificate())
|
||||||
|
|
||||||
|
nodeA, err := New(cfgA.Certificate, logger, AllowedPublicKey("abcdef"))
|
||||||
|
require_NoError(t, err)
|
||||||
|
defer nodeA.Stop()
|
||||||
|
|
||||||
|
nodeB, err := New(cfgB.Certificate, logger)
|
||||||
|
require_NoError(t, err)
|
||||||
|
defer nodeB.Stop()
|
||||||
|
|
||||||
|
u, err := url.Parse("tcp://localhost:0")
|
||||||
|
require_NoError(t, err)
|
||||||
|
|
||||||
|
l, err := nodeA.ListenLocal(u, "")
|
||||||
|
require_NoError(t, err)
|
||||||
|
|
||||||
|
u, err = url.Parse("tcp://" + l.Addr().String())
|
||||||
|
require_NoError(t, err)
|
||||||
|
|
||||||
|
require_NoError(t, nodeB.AddPeer(u, ""))
|
||||||
|
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
|
||||||
|
peers := nodeB.GetPeers()
|
||||||
|
require_Equal(t, len(peers), 1)
|
||||||
|
require_True(t, peers[0].Up)
|
||||||
|
require_True(t, peers[0].LastError == nil)
|
||||||
|
}
|
||||||
|
|
|
@ -108,7 +108,9 @@ func (l *links) shutdown() {
|
||||||
_ = listener.listener.Close()
|
_ = listener.listener.Close()
|
||||||
}
|
}
|
||||||
for _, link := range l._links {
|
for _, link := range l._links {
|
||||||
_ = link._conn.Close()
|
if link._conn != nil {
|
||||||
|
_ = link._conn.Close()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -334,7 +336,7 @@ func (l *links) add(u *url.URL, sintf string, linkType linkType) error {
|
||||||
|
|
||||||
// Give the connection to the handler. The handler will block
|
// Give the connection to the handler. The handler will block
|
||||||
// for the lifetime of the connection.
|
// for the lifetime of the connection.
|
||||||
if err = l.handler(linkType, options, lc, resetBackoff); err != nil && err != io.EOF {
|
if err = l.handler(linkType, options, lc, resetBackoff, false); err != nil && err != io.EOF {
|
||||||
l.core.log.Debugf("Link %s error: %s\n", info.uri, err)
|
l.core.log.Debugf("Link %s error: %s\n", info.uri, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -357,8 +359,9 @@ func (l *links) add(u *url.URL, sintf string, linkType linkType) error {
|
||||||
if backoffNow() {
|
if backoffNow() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
// Ephemeral or incoming connections don't reconnect.
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
})
|
})
|
||||||
|
@ -392,7 +395,7 @@ func (l *links) remove(u *url.URL, sintf string, _ linkType) error {
|
||||||
return retErr
|
return retErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *links) listen(u *url.URL, sintf string) (*Listener, error) {
|
func (l *links) listen(u *url.URL, sintf string, local bool) (*Listener, error) {
|
||||||
ctx, cancel := context.WithCancel(l.core.ctx)
|
ctx, cancel := context.WithCancel(l.core.ctx)
|
||||||
var protocol linkProtocol
|
var protocol linkProtocol
|
||||||
switch strings.ToLower(u.Scheme) {
|
switch strings.ToLower(u.Scheme) {
|
||||||
|
@ -420,7 +423,10 @@ func (l *links) listen(u *url.URL, sintf string) (*Listener, error) {
|
||||||
li := &Listener{
|
li := &Listener{
|
||||||
listener: listener,
|
listener: listener,
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
Cancel: cancel,
|
Cancel: func() {
|
||||||
|
cancel()
|
||||||
|
_ = listener.Close()
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var options linkOptions
|
var options linkOptions
|
||||||
|
@ -516,7 +522,7 @@ func (l *links) listen(u *url.URL, sintf string) (*Listener, error) {
|
||||||
|
|
||||||
// Give the connection to the handler. The handler will block
|
// Give the connection to the handler. The handler will block
|
||||||
// for the lifetime of the connection.
|
// for the lifetime of the connection.
|
||||||
switch err = l.handler(linkTypeIncoming, options, lc, nil); {
|
switch err = l.handler(linkTypeIncoming, options, lc, nil, local); {
|
||||||
case err == nil:
|
case err == nil:
|
||||||
case errors.Is(err, io.EOF):
|
case errors.Is(err, io.EOF):
|
||||||
case errors.Is(err, net.ErrClosed):
|
case errors.Is(err, net.ErrClosed):
|
||||||
|
@ -557,7 +563,7 @@ func (l *links) connect(ctx context.Context, u *url.URL, info linkInfo, options
|
||||||
return dialer.dial(ctx, u, info, options)
|
return dialer.dial(ctx, u, info, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *links) handler(linkType linkType, options linkOptions, conn net.Conn, success func()) error {
|
func (l *links) handler(linkType linkType, options linkOptions, conn net.Conn, success func(), local bool) error {
|
||||||
meta := version_getBaseMetadata()
|
meta := version_getBaseMetadata()
|
||||||
meta.publicKey = l.core.public
|
meta.publicKey = l.core.public
|
||||||
meta.priority = options.priority
|
meta.priority = options.priority
|
||||||
|
@ -600,19 +606,21 @@ func (l *links) handler(linkType linkType, options linkOptions, conn net.Conn, s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check if we're authorized to connect to this key / IP
|
// Check if we're authorized to connect to this key / IP
|
||||||
var allowed map[[32]byte]struct{}
|
if !local {
|
||||||
phony.Block(l.core, func() {
|
var allowed map[[32]byte]struct{}
|
||||||
allowed = l.core.config._allowedPublicKeys
|
phony.Block(l.core, func() {
|
||||||
})
|
allowed = l.core.config._allowedPublicKeys
|
||||||
isallowed := len(allowed) == 0
|
})
|
||||||
for k := range allowed {
|
isallowed := len(allowed) == 0
|
||||||
if bytes.Equal(k[:], meta.publicKey) {
|
for k := range allowed {
|
||||||
isallowed = true
|
if bytes.Equal(k[:], meta.publicKey) {
|
||||||
break
|
isallowed = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if linkType == linkTypeIncoming && !isallowed {
|
||||||
|
return fmt.Errorf("node public key %q is not in AllowedPublicKeys", hex.EncodeToString(meta.publicKey))
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if linkType == linkTypeIncoming && !isallowed {
|
|
||||||
return fmt.Errorf("node public key %q is not in AllowedPublicKeys", hex.EncodeToString(meta.publicKey))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dir := "outbound"
|
dir := "outbound"
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Arceliar/phony"
|
"github.com/Arceliar/phony"
|
||||||
"nhooyr.io/websocket"
|
"github.com/coder/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
type linkWS struct {
|
type linkWS struct {
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
"github.com/Arceliar/phony"
|
"github.com/Arceliar/phony"
|
||||||
"nhooyr.io/websocket"
|
"github.com/coder/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
type linkWSS struct {
|
type linkWSS struct {
|
||||||
|
|
|
@ -190,6 +190,8 @@ func (m *Multicast) _getAllowedInterfaces() map[string]*interfaceInfo {
|
||||||
switch {
|
switch {
|
||||||
case iface.Flags&net.FlagUp == 0:
|
case iface.Flags&net.FlagUp == 0:
|
||||||
continue // Ignore interfaces that are down
|
continue // Ignore interfaces that are down
|
||||||
|
case iface.Flags&net.FlagRunning == 0:
|
||||||
|
continue // Ignore interfaces that are not running
|
||||||
case iface.Flags&net.FlagMulticast == 0:
|
case iface.Flags&net.FlagMulticast == 0:
|
||||||
continue // Ignore non-multicast interfaces
|
continue // Ignore non-multicast interfaces
|
||||||
case iface.Flags&net.FlagPointToPoint != 0:
|
case iface.Flags&net.FlagPointToPoint != 0:
|
||||||
|
@ -325,7 +327,7 @@ func (m *Multicast) _announce() {
|
||||||
Host: net.JoinHostPort(addrIP.String(), fmt.Sprintf("%d", info.port)),
|
Host: net.JoinHostPort(addrIP.String(), fmt.Sprintf("%d", info.port)),
|
||||||
RawQuery: v.Encode(),
|
RawQuery: v.Encode(),
|
||||||
}
|
}
|
||||||
if li, err := m.core.Listen(u, iface.Name); err == nil {
|
if li, err := m.core.ListenLocal(u, iface.Name); err == nil {
|
||||||
m.log.Debugln("Started multicasting on", iface.Name)
|
m.log.Debugln("Started multicasting on", iface.Name)
|
||||||
// Store the listener so that we can stop it later if needed
|
// Store the listener so that we can stop it later if needed
|
||||||
linfo = &listenerInfo{listener: li, time: time.Now(), port: info.port}
|
linfo = &listenerInfo{listener: li, time: time.Now(), port: info.port}
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
package tun
|
package tun
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
wgtun "golang.zx2c4.com/wireguard/tun"
|
||||||
|
)
|
||||||
|
|
||||||
const TUN_OFFSET_BYTES = 80 // sizeof(virtio_net_hdr)
|
const TUN_OFFSET_BYTES = 80 // sizeof(virtio_net_hdr)
|
||||||
|
|
||||||
func (tun *TunAdapter) read() {
|
func (tun *TunAdapter) read() {
|
||||||
|
@ -12,6 +18,10 @@ func (tun *TunAdapter) read() {
|
||||||
for {
|
for {
|
||||||
n, err := tun.iface.Read(bufs, sizes, TUN_OFFSET_BYTES)
|
n, err := tun.iface.Read(bufs, sizes, TUN_OFFSET_BYTES)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if errors.Is(err, wgtun.ErrTooManySegments) {
|
||||||
|
tun.log.Debugln("TUN segments dropped: %v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
tun.log.Errorln("Error reading TUN:", err)
|
tun.log.Errorln("Error reading TUN:", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//go:build openbsd || freebsd
|
//go:build freebsd
|
||||||
// +build openbsd freebsd
|
// +build freebsd
|
||||||
|
|
||||||
package tun
|
package tun
|
||||||
|
|
||||||
|
@ -54,11 +54,6 @@ struct in6_ifreq {
|
||||||
290 };
|
290 };
|
||||||
*/
|
*/
|
||||||
|
|
||||||
type in6_ifreq_mtu struct {
|
|
||||||
ifr_name [syscall.IFNAMSIZ]byte
|
|
||||||
ifru_mtu int
|
|
||||||
}
|
|
||||||
|
|
||||||
type in6_ifreq_addr struct {
|
type in6_ifreq_addr struct {
|
||||||
ifr_name [syscall.IFNAMSIZ]byte
|
ifr_name [syscall.IFNAMSIZ]byte
|
||||||
ifru_addr sockaddr_in6
|
ifru_addr sockaddr_in6
|
||||||
|
@ -112,26 +107,6 @@ func (tun *TunAdapter) setupAddress(addr string) error {
|
||||||
tun.log.Infof("Interface IPv6: %s", addr)
|
tun.log.Infof("Interface IPv6: %s", addr)
|
||||||
tun.log.Infof("Interface MTU: %d", tun.mtu)
|
tun.log.Infof("Interface MTU: %d", tun.mtu)
|
||||||
|
|
||||||
// Create the MTU request
|
|
||||||
var ir in6_ifreq_mtu
|
|
||||||
copy(ir.ifr_name[:], tun.Name())
|
|
||||||
ir.ifru_mtu = int(tun.mtu)
|
|
||||||
|
|
||||||
// Set the MTU
|
|
||||||
if _, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(sfd), uintptr(syscall.SIOCSIFMTU), uintptr(unsafe.Pointer(&ir))); errno != 0 {
|
|
||||||
err = errno
|
|
||||||
tun.log.Errorf("Error in SIOCSIFMTU: %v", errno)
|
|
||||||
|
|
||||||
// Fall back to ifconfig to set the MTU
|
|
||||||
cmd := exec.Command("ifconfig", tun.Name(), "mtu", string(tun.mtu))
|
|
||||||
tun.log.Warnf("Using ifconfig as fallback: %v", strings.Join(cmd.Args, " "))
|
|
||||||
output, err := cmd.CombinedOutput()
|
|
||||||
if err != nil {
|
|
||||||
tun.log.Errorf("SIOCSIFMTU fallback failed: %v.", err)
|
|
||||||
tun.log.Traceln(string(output))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the address request
|
// Create the address request
|
||||||
// FIXME: I don't work!
|
// FIXME: I don't work!
|
||||||
var ar in6_ifreq_addr
|
var ar in6_ifreq_addr
|
122
src/tun/tun_openbsd.go
Normal file
122
src/tun/tun_openbsd.go
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
//go:build openbsd
|
||||||
|
// +build openbsd
|
||||||
|
|
||||||
|
package tun
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
|
||||||
|
wgtun "golang.zx2c4.com/wireguard/tun"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
SIOCAIFADDR_IN6 = 0x8080691a
|
||||||
|
ND6_INFINITE_LIFETIME = 0xffffffff
|
||||||
|
)
|
||||||
|
|
||||||
|
type in6_addrlifetime struct {
|
||||||
|
ia6t_expire int64
|
||||||
|
ia6t_preferred int64
|
||||||
|
ia6t_vltime uint32
|
||||||
|
ia6t_pltime uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// Match types from the net package, effectively being [16]byte for IPv6 addresses.
|
||||||
|
type in6_addr [16]uint8
|
||||||
|
|
||||||
|
type sockaddr_in6 struct {
|
||||||
|
sin6_len uint8
|
||||||
|
sin6_family uint8
|
||||||
|
sin6_port uint16
|
||||||
|
sin6_flowinfo uint32
|
||||||
|
sin6_addr in6_addr
|
||||||
|
sin6_scope_id uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sa6 *sockaddr_in6) setSockaddr(addr [/*16*/]byte /* net.IP or net.IPMask */) {
|
||||||
|
sa6.sin6_len = uint8(unsafe.Sizeof(*sa6))
|
||||||
|
sa6.sin6_family = unix.AF_INET6
|
||||||
|
|
||||||
|
for i := range sa6.sin6_addr {
|
||||||
|
sa6.sin6_addr[i] = addr[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type in6_aliasreq struct {
|
||||||
|
ifra_name [syscall.IFNAMSIZ]byte
|
||||||
|
ifra_addr sockaddr_in6
|
||||||
|
ifra_dstaddr sockaddr_in6
|
||||||
|
ifra_prefixmask sockaddr_in6
|
||||||
|
ifra_flags int32
|
||||||
|
ifra_lifetime in6_addrlifetime
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configures the TUN adapter with the correct IPv6 address and MTU.
|
||||||
|
func (tun *TunAdapter) setup(ifname string, addr string, mtu uint64) error {
|
||||||
|
iface, err := wgtun.CreateTUN(ifname, int(mtu))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create TUN: %w", err)
|
||||||
|
}
|
||||||
|
tun.iface = iface
|
||||||
|
if mtu, err := iface.MTU(); err == nil {
|
||||||
|
tun.mtu = getSupportedMTU(uint64(mtu))
|
||||||
|
} else {
|
||||||
|
tun.mtu = 0
|
||||||
|
}
|
||||||
|
if addr != "" {
|
||||||
|
return tun.setupAddress(addr)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configures the "utun" adapter from an existing file descriptor.
|
||||||
|
func (tun *TunAdapter) setupFD(fd int32, addr string, mtu uint64) error {
|
||||||
|
return fmt.Errorf("setup via FD not supported on this platform")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tun *TunAdapter) setupAddress(addr string) error {
|
||||||
|
var sfd int
|
||||||
|
var err error
|
||||||
|
|
||||||
|
ip, prefix, err := net.ParseCIDR(addr)
|
||||||
|
if err != nil {
|
||||||
|
tun.log.Errorf("Error in ParseCIDR: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create system socket
|
||||||
|
if sfd, err = unix.Socket(unix.AF_INET6, unix.SOCK_DGRAM, 0); err != nil {
|
||||||
|
tun.log.Printf("Create AF_INET6 socket failed: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Friendly output
|
||||||
|
tun.log.Infof("Interface name: %s", tun.Name())
|
||||||
|
tun.log.Infof("Interface IPv6: %s", addr)
|
||||||
|
tun.log.Infof("Interface MTU: %d", tun.mtu)
|
||||||
|
|
||||||
|
// Create the address request
|
||||||
|
var ar in6_aliasreq
|
||||||
|
copy(ar.ifra_name[:], tun.Name())
|
||||||
|
|
||||||
|
ar.ifra_addr.setSockaddr(ip)
|
||||||
|
|
||||||
|
prefixmask := net.CIDRMask(prefix.Mask.Size())
|
||||||
|
ar.ifra_prefixmask.setSockaddr(prefixmask)
|
||||||
|
|
||||||
|
ar.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME
|
||||||
|
ar.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME
|
||||||
|
|
||||||
|
// Set the interface address
|
||||||
|
if err = unix.IoctlSetInt(sfd, SIOCAIFADDR_IN6, int(uintptr(unsafe.Pointer(&ar)))); err != nil {
|
||||||
|
tun.log.Errorf("Error in SIOCAIFADDR_IN6: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue