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:
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.21
|
||||
go-version: stable
|
||||
- uses: actions/checkout@v4
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v3
|
||||
uses: golangci/golangci-lint-action@v6
|
||||
with:
|
||||
args: --issues-exit-code=1
|
||||
|
||||
|
@ -51,7 +51,7 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
goversion: ["1.21", "1.22"]
|
||||
goversion: ["1.21", "1.22", "1.23"]
|
||||
|
||||
name: Build & Test (Linux, Go ${{ matrix.goversion }})
|
||||
needs: [lint]
|
||||
|
@ -75,7 +75,7 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
goversion: ["1.21", "1.22"]
|
||||
goversion: ["1.21", "1.22", "1.23"]
|
||||
|
||||
name: Build & Test (Windows, Go ${{ matrix.goversion }})
|
||||
needs: [lint]
|
||||
|
@ -99,7 +99,7 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
goversion: ["1.21", "1.22"]
|
||||
goversion: ["1.21", "1.22", "1.23"]
|
||||
|
||||
name: Build & Test (macOS, Go ${{ matrix.goversion }})
|
||||
needs: [lint]
|
||||
|
@ -123,7 +123,7 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
goversion: ["1.21", "1.22"]
|
||||
goversion: ["1.21", "1.22", "1.23"]
|
||||
goos:
|
||||
- freebsd
|
||||
- openbsd
|
||||
|
|
|
@ -2,7 +2,8 @@ run:
|
|||
build-tags:
|
||||
- lint
|
||||
issues-exit-code: 0 # TODO: change this to 1 when we want it to fail builds
|
||||
skip-dirs:
|
||||
issues:
|
||||
exclude-dirs:
|
||||
- contrib/
|
||||
- misc/
|
||||
linters:
|
||||
|
|
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")
|
||||
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")
|
||||
chuserto := flag.String("user", "", "user (and, optionally, group) to set UID/GID to")
|
||||
flag.Parse()
|
||||
|
||||
done := make(chan struct{})
|
||||
|
@ -286,6 +287,14 @@ func main() {
|
|||
<-done
|
||||
})
|
||||
|
||||
// Change user if requested
|
||||
if *chuserto != "" {
|
||||
err = chuser(*chuserto)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Block until we are told to shut down.
|
||||
<-ctx.Done()
|
||||
|
||||
|
|
|
@ -38,7 +38,6 @@ func (cmdLineEnv *CmdLineEnv) parseFlagsAndArgs() {
|
|||
fmt.Println("Examples:")
|
||||
fmt.Println(" - ", os.Args[0], "list")
|
||||
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=unix:///var/run/ygg.sock getPeers")
|
||||
}
|
||||
|
|
|
@ -174,7 +174,7 @@ func run() int {
|
|||
if err := json.Unmarshal(recv.Response, &resp); err != nil {
|
||||
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 {
|
||||
state, lasterr, dir, rtt := "Up", "-", "Out", "-"
|
||||
if !peer.Up {
|
||||
|
@ -200,6 +200,7 @@ func run() int {
|
|||
peer.RXBytes.String(),
|
||||
peer.TXBytes.String(),
|
||||
fmt.Sprintf("%d", peer.Priority),
|
||||
fmt.Sprintf("%d", peer.Cost),
|
||||
lasterr,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ set -ef
|
|||
PKGSRC=${PKGSRC:-github.com/yggdrasil-network/yggdrasil-go/src/version}
|
||||
PKGNAME=${PKGNAME:-$(sh contrib/semver/name.sh)}
|
||||
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"
|
||||
ARGS="-v"
|
||||
|
@ -33,6 +34,15 @@ if [ ! $IOS ] && [ ! $ANDROID ]; then
|
|||
exit 1
|
||||
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
|
||||
echo "Building framework for iOS"
|
||||
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/tun"
|
||||
"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
|
||||
|
|
25
go.mod
25
go.mod
|
@ -3,24 +3,24 @@ module github.com/yggdrasil-network/yggdrasil-go
|
|||
go 1.21
|
||||
|
||||
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/cheggaaa/pb/v3 v3.1.5
|
||||
github.com/coder/websocket v1.8.12
|
||||
github.com/gologme/log v1.3.0
|
||||
github.com/hashicorp/go-syslog v1.0.0
|
||||
github.com/hjson/hjson-go/v4 v4.4.0
|
||||
github.com/kardianos/minwinsvc v1.0.2
|
||||
github.com/quic-go/quic-go v0.45.1
|
||||
github.com/vishvananda/netlink v1.1.0
|
||||
github.com/wlynxg/anet v0.0.4-0.20240806025826-e684438fc7c6
|
||||
golang.org/x/crypto v0.25.0
|
||||
golang.org/x/mobile v0.0.0-20240716161057-1ad2df20a8b6
|
||||
golang.org/x/net v0.27.0
|
||||
golang.org/x/sys v0.22.0
|
||||
golang.org/x/text v0.16.0
|
||||
github.com/quic-go/quic-go v0.46.0
|
||||
github.com/vishvananda/netlink v1.3.0
|
||||
github.com/wlynxg/anet v0.0.5
|
||||
golang.org/x/crypto v0.28.0
|
||||
golang.org/x/net v0.30.0
|
||||
golang.org/x/sys v0.26.0
|
||||
golang.org/x/text v0.19.0
|
||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2
|
||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173
|
||||
golang.zx2c4.com/wireguard/windows v0.5.3
|
||||
nhooyr.io/websocket v1.8.11
|
||||
)
|
||||
|
||||
require (
|
||||
|
@ -34,9 +34,8 @@ require (
|
|||
go.uber.org/mock v0.4.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // 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.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
|
@ -45,5 +44,5 @@ require (
|
|||
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||
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-20240529054413-b8e59574e2b2/go.mod h1:6WP4799FX0OuWdENGQAh+0RXp9FLh0y7NZ7tM9cJyXk=
|
||||
github.com/Arceliar/ironwood v0.0.0-20241016082300-f6fb9da97a17 h1:uOvHqPwu09ndYZQDUL6QvyDcz0M9kwooKYa/PEfLwIU=
|
||||
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/go.mod h1:BCnxhRf47C/dy/e/D2pmB8NkB3dQVIrkD98b220rx5Q=
|
||||
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/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/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.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
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.45.1/go.mod h1:1dLehS7TIR64+vxGR70GDcatWTOtMX2PUtnKsjbTurI=
|
||||
github.com/quic-go/quic-go v0.46.0 h1:uuwLClEEyk1DNvchH8uCByQVjo3yKL9opKulExNDs7Y=
|
||||
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/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
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/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/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0=
|
||||
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
|
||||
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
|
||||
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f h1:p4VB7kIXpOQvVn1ZaTIVp+3vuYAXFe3OJEvjbUYJLaA=
|
||||
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||
github.com/wlynxg/anet v0.0.4-0.20240806025826-e684438fc7c6 h1:c/wkXIJvpg2oot7iFqPESTBAO9UvhWTBnW97y9aPgyU=
|
||||
github.com/wlynxg/anet v0.0.4-0.20240806025826-e684438fc7c6/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA=
|
||||
github.com/vishvananda/netlink v1.3.0 h1:X7l42GfcV4S6E4vHTsw48qbrV+9PVojNfIhZcwQdrZk=
|
||||
github.com/vishvananda/netlink v1.3.0/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs=
|
||||
github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8=
|
||||
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
|
||||
github.com/wlynxg/anet v0.0.5 h1:J3VJGi1gvo0JwZ/P1/Yc/8p63SoW98B5dHkYDmpgvvU=
|
||||
github.com/wlynxg/anet v0.0.5/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA=
|
||||
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/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.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.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
|
||||
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
|
||||
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
|
||||
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/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.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
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.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
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.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
|
||||
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
|
||||
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-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.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||
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-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-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-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-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.2.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.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.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
|
||||
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
|
||||
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-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
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.14.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.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
|
||||
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/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
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=
|
||||
gvisor.dev/gvisor v0.0.0-20230927004350-cbd86285d259 h1:TbRPT0HtzFP3Cno1zZo7yPzEEnfu8EjLfl6IU9VfqkQ=
|
||||
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 {
|
||||
switch strings.ToLower(u.Scheme) {
|
||||
case "unix":
|
||||
if _, err := os.Stat(listenaddr[7:]); err == nil {
|
||||
a.log.Debugln("Admin socket", listenaddr[7:], "already exists, trying to clean up")
|
||||
if _, err := net.DialTimeout("unix", listenaddr[7:], 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")
|
||||
if _, err := os.Stat(u.Path); err == nil {
|
||||
a.log.Debugln("Admin socket", u.Path, "already exists, trying to clean up")
|
||||
if _, err := net.DialTimeout("unix", u.Path, time.Second*2); err == nil || err.(net.Error).Timeout() {
|
||||
a.log.Errorln("Admin socket", u.Path, "already exists and is in use by another process")
|
||||
os.Exit(1)
|
||||
} else {
|
||||
if err := os.Remove(listenaddr[7:]); err == nil {
|
||||
a.log.Debugln(listenaddr[7:], "was cleaned up")
|
||||
if err := os.Remove(u.Path); err == nil {
|
||||
a.log.Debugln(u.Path, "was cleaned up")
|
||||
} 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
a.listener, err = net.Listen("unix", listenaddr[7:])
|
||||
a.listener, err = net.Listen("unix", u.Path)
|
||||
if err == nil {
|
||||
switch listenaddr[7:8] {
|
||||
switch u.Path[:1] {
|
||||
case "@": // maybe abstract namespace
|
||||
default:
|
||||
if err := os.Chmod(listenaddr[7:], 0660); err != nil {
|
||||
a.log.Warnln("WARNING:", listenaddr[:7], "may have unsafe permissions!")
|
||||
if err := os.Chmod(u.Path, 0660); err != nil {
|
||||
a.log.Warnln("WARNING:", u.Path, "may have unsafe permissions!")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ package admin
|
|||
import (
|
||||
"encoding/hex"
|
||||
"net"
|
||||
"sort"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/yggdrasil-network/yggdrasil-go/src/address"
|
||||
|
@ -35,8 +35,8 @@ func (a *AdminSocket) getPathsHandler(_ *GetPathsRequest, res *GetPathsResponse)
|
|||
Sequence: p.Sequence,
|
||||
})
|
||||
}
|
||||
sort.SliceStable(res.Paths, func(i, j int) bool {
|
||||
return strings.Compare(res.Paths[i].PublicKey, res.Paths[j].PublicKey) < 0
|
||||
slices.SortStableFunc(res.Paths, func(a, b PathEntry) int {
|
||||
return strings.Compare(a.PublicKey, b.PublicKey)
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -3,7 +3,8 @@ package admin
|
|||
import (
|
||||
"encoding/hex"
|
||||
"net"
|
||||
"sort"
|
||||
"slices"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/yggdrasil-network/yggdrasil-go/src/address"
|
||||
|
@ -24,6 +25,7 @@ type PeerEntry struct {
|
|||
PublicKey string `json:"key"`
|
||||
Port uint64 `json:"port"`
|
||||
Priority uint64 `json:"priority"`
|
||||
Cost uint64 `json:"cost"`
|
||||
RXBytes DataUnit `json:"bytes_recvd,omitempty"`
|
||||
TXBytes DataUnit `json:"bytes_sent,omitempty"`
|
||||
Uptime float64 `json:"uptime,omitempty"`
|
||||
|
@ -41,6 +43,7 @@ func (a *AdminSocket) getPeersHandler(_ *GetPeersRequest, res *GetPeersResponse)
|
|||
Up: p.Up,
|
||||
Inbound: p.Inbound,
|
||||
Priority: uint64(p.Priority), // can't be uint8 thanks to gobind
|
||||
Cost: p.Cost,
|
||||
URI: p.URI,
|
||||
RXBytes: DataUnit(p.RXBytes),
|
||||
TXBytes: DataUnit(p.TXBytes),
|
||||
|
@ -59,17 +62,26 @@ func (a *AdminSocket) getPeersHandler(_ *GetPeersRequest, res *GetPeersResponse)
|
|||
}
|
||||
res.Peers = append(res.Peers, peer)
|
||||
}
|
||||
sort.Slice(res.Peers, func(i, j int) bool {
|
||||
if res.Peers[i].Inbound == res.Peers[j].Inbound {
|
||||
if res.Peers[i].PublicKey == res.Peers[j].PublicKey {
|
||||
if res.Peers[i].Priority == res.Peers[j].Priority {
|
||||
return res.Peers[i].Uptime > res.Peers[j].Uptime
|
||||
slices.SortStableFunc(res.Peers, func(a, b PeerEntry) int {
|
||||
if !a.Inbound && b.Inbound {
|
||||
return -1
|
||||
}
|
||||
return res.Peers[i].Priority < res.Peers[j].Priority
|
||||
if a.Inbound && !b.Inbound {
|
||||
return 1
|
||||
}
|
||||
return res.Peers[i].PublicKey < res.Peers[j].PublicKey
|
||||
if d := strings.Compare(a.PublicKey, b.PublicKey); d != 0 {
|
||||
return d
|
||||
}
|
||||
return !res.Peers[i].Inbound && res.Peers[j].Inbound
|
||||
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
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ package admin
|
|||
import (
|
||||
"encoding/hex"
|
||||
"net"
|
||||
"sort"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/yggdrasil-network/yggdrasil-go/src/address"
|
||||
|
@ -36,8 +36,8 @@ func (a *AdminSocket) getSessionsHandler(_ *GetSessionsRequest, res *GetSessions
|
|||
Uptime: s.Uptime.Seconds(),
|
||||
})
|
||||
}
|
||||
sort.SliceStable(res.Sessions, func(i, j int) bool {
|
||||
return strings.Compare(res.Sessions[i].PublicKey, res.Sessions[j].PublicKey) < 0
|
||||
slices.SortStableFunc(res.Sessions, func(a, b SessionEntry) int {
|
||||
return strings.Compare(a.PublicKey, b.PublicKey)
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ package admin
|
|||
import (
|
||||
"encoding/hex"
|
||||
"net"
|
||||
"sort"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/yggdrasil-network/yggdrasil-go/src/address"
|
||||
|
@ -34,8 +34,8 @@ func (a *AdminSocket) getTreeHandler(_ *GetTreeRequest, res *GetTreeResponse) er
|
|||
Sequence: d.Sequence,
|
||||
})
|
||||
}
|
||||
sort.SliceStable(res.Tree, func(i, j int) bool {
|
||||
return strings.Compare(res.Tree[i].PublicKey, res.Tree[j].PublicKey) < 0
|
||||
slices.SortStableFunc(res.Tree, func(a, b TreeEntry) int {
|
||||
return strings.Compare(a.PublicKey, b.PublicKey)
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ type PeerInfo struct {
|
|||
Coords []uint64
|
||||
Port uint64
|
||||
Priority uint8
|
||||
Cost uint64
|
||||
RXBytes uint64
|
||||
TXBytes uint64
|
||||
Uptime time.Duration
|
||||
|
@ -94,6 +95,7 @@ func (c *Core) GetPeers() []PeerInfo {
|
|||
peerinfo.Port = p.Port
|
||||
peerinfo.Priority = p.Priority
|
||||
peerinfo.Latency = p.Latency
|
||||
peerinfo.Cost = p.Cost
|
||||
}
|
||||
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
|
||||
// link-local address, the interface should be provided as the second argument.
|
||||
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
|
||||
|
|
|
@ -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)
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,27 @@ func GetLoggerWithPrefix(prefix string, verbose bool) *log.Logger {
|
|||
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.
|
||||
// Verbosity flag is passed to logger.
|
||||
func CreateAndConnectTwo(t testing.TB, verbose bool) (nodeA *Core, nodeB *Core) {
|
||||
|
@ -201,3 +222,69 @@ func BenchmarkCore_Start_Transfer(b *testing.B) {
|
|||
}
|
||||
<-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,8 +108,10 @@ func (l *links) shutdown() {
|
|||
_ = listener.listener.Close()
|
||||
}
|
||||
for _, link := range l._links {
|
||||
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
|
||||
// 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)
|
||||
}
|
||||
|
||||
|
@ -357,8 +359,9 @@ func (l *links) add(u *url.URL, sintf string, linkType linkType) error {
|
|||
if backoffNow() {
|
||||
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
|
||||
}
|
||||
|
||||
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)
|
||||
var protocol linkProtocol
|
||||
switch strings.ToLower(u.Scheme) {
|
||||
|
@ -420,7 +423,10 @@ func (l *links) listen(u *url.URL, sintf string) (*Listener, error) {
|
|||
li := &Listener{
|
||||
listener: listener,
|
||||
ctx: ctx,
|
||||
Cancel: cancel,
|
||||
Cancel: func() {
|
||||
cancel()
|
||||
_ = listener.Close()
|
||||
},
|
||||
}
|
||||
|
||||
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
|
||||
// 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 errors.Is(err, io.EOF):
|
||||
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)
|
||||
}
|
||||
|
||||
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.publicKey = l.core.public
|
||||
meta.priority = options.priority
|
||||
|
@ -600,6 +606,7 @@ func (l *links) handler(linkType linkType, options linkOptions, conn net.Conn, s
|
|||
}
|
||||
}
|
||||
// Check if we're authorized to connect to this key / IP
|
||||
if !local {
|
||||
var allowed map[[32]byte]struct{}
|
||||
phony.Block(l.core, func() {
|
||||
allowed = l.core.config._allowedPublicKeys
|
||||
|
@ -614,6 +621,7 @@ func (l *links) handler(linkType linkType, options linkOptions, conn net.Conn, s
|
|||
if linkType == linkTypeIncoming && !isallowed {
|
||||
return fmt.Errorf("node public key %q is not in AllowedPublicKeys", hex.EncodeToString(meta.publicKey))
|
||||
}
|
||||
}
|
||||
|
||||
dir := "outbound"
|
||||
if linkType == linkTypeIncoming {
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/Arceliar/phony"
|
||||
"nhooyr.io/websocket"
|
||||
"github.com/coder/websocket"
|
||||
)
|
||||
|
||||
type linkWS struct {
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
"net/url"
|
||||
|
||||
"github.com/Arceliar/phony"
|
||||
"nhooyr.io/websocket"
|
||||
"github.com/coder/websocket"
|
||||
)
|
||||
|
||||
type linkWSS struct {
|
||||
|
|
|
@ -190,6 +190,8 @@ func (m *Multicast) _getAllowedInterfaces() map[string]*interfaceInfo {
|
|||
switch {
|
||||
case iface.Flags&net.FlagUp == 0:
|
||||
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:
|
||||
continue // Ignore non-multicast interfaces
|
||||
case iface.Flags&net.FlagPointToPoint != 0:
|
||||
|
@ -325,7 +327,7 @@ func (m *Multicast) _announce() {
|
|||
Host: net.JoinHostPort(addrIP.String(), fmt.Sprintf("%d", info.port)),
|
||||
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)
|
||||
// Store the listener so that we can stop it later if needed
|
||||
linfo = &listenerInfo{listener: li, time: time.Now(), port: info.port}
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
package tun
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
wgtun "golang.zx2c4.com/wireguard/tun"
|
||||
)
|
||||
|
||||
const TUN_OFFSET_BYTES = 80 // sizeof(virtio_net_hdr)
|
||||
|
||||
func (tun *TunAdapter) read() {
|
||||
|
@ -12,6 +18,10 @@ func (tun *TunAdapter) read() {
|
|||
for {
|
||||
n, err := tun.iface.Read(bufs, sizes, TUN_OFFSET_BYTES)
|
||||
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)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//go:build openbsd || freebsd
|
||||
// +build openbsd freebsd
|
||||
//go:build freebsd
|
||||
// +build freebsd
|
||||
|
||||
package tun
|
||||
|
||||
|
@ -54,11 +54,6 @@ struct in6_ifreq {
|
|||
290 };
|
||||
*/
|
||||
|
||||
type in6_ifreq_mtu struct {
|
||||
ifr_name [syscall.IFNAMSIZ]byte
|
||||
ifru_mtu int
|
||||
}
|
||||
|
||||
type in6_ifreq_addr struct {
|
||||
ifr_name [syscall.IFNAMSIZ]byte
|
||||
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 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
|
||||
// FIXME: I don't work!
|
||||
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