Compare commits

...

20 Commits

Author SHA1 Message Date
Neil Alexander
edf179ed26 Yggdrasil 0.5.7 2024-08-05 19:18:38 +01:00
Neil Alexander
9950d1225d Improve link and handshake errors 2024-08-01 21:53:48 +01:00
Revertron
4fbdeb4e3f Fixed Windows service life-cycle. (#1153)
This fix fixes two issues:
https://github.com/yggdrasil-network/yggdrasil-go/issues/993 &
https://github.com/yggdrasil-network/yggdrasil-go/issues/1098
2024-07-25 13:55:14 +01:00
Vasyl Gello
5ea16e63a1 Implement websocket (ws:// and wss://) links (#1152)
ws:// can be listened and dialed
wss:// is a convenience link for ws:// that supports dialing to ws://
peer.

---------

Signed-off-by: Vasyl Gello <vasek.gello@gmail.com>
Co-authored-by: Neil Alexander <neilalexander@users.noreply.github.com>
2024-07-23 22:58:11 +01:00
Neil Alexander
da7ebde828 Update dependencies 2024-07-20 15:37:31 +01:00
Neil
02d92ff81c TUN vectorised reads/writes (#1145)
This PR updates the Wireguard dependency and updates to use new
vectorised reads/writes, which should reduce the number of syscalls and
improve performance.

This will only make a difference on Linux as this is the only platform
for which the Wireguard TUN library supports vectorised reads/writes.
For other platforms, single reads and writes will be performed as usual.

---------

Co-authored-by: Neil Alexander <neilalexander@users.noreply.github.com>
2024-07-20 15:24:30 +01:00
Neil Alexander
04c0acf71b Various clean-ups 2024-07-20 12:31:58 +01:00
Neil Alexander
8ecc402d7c Allow multiple connections to the same link-local address
Note that this may mean that currently we end up with two links to each multicast-discovered peer, one incoming and one outgoing
2024-07-20 11:31:08 +01:00
Neil Alexander
c505097be0 Update mobile build for iOS/macOS framework generation 2024-06-26 23:17:11 +01:00
Neil
fec96a38a4 Release: Yggdrasil v0.5.6 (#1144)
* Changelog updates for Yggdrasil v0.5.6

* Fix spelling error

---------

Co-authored-by: Neil Alexander <neilalexander@users.noreply.github.com>
Co-authored-by: Arceliar <Arceliar@users.noreply.github.com>
2024-05-30 23:30:05 +01:00
Neil
f788a18bef Measure RTT, report in getPeers (#1143)
Co-authored-by: Neil Alexander <neilalexander@users.noreply.github.com>
2024-05-30 22:46:06 +01:00
Neil Alexander
fcefb20993 Fix interval check when sending multicast beacons 2024-05-28 10:03:48 +01:00
Neil Alexander
2831d73f73 Try to fix WiX for Windows MSI builds 2024-05-27 22:52:48 +01:00
Neil Alexander
c2811c0cdc Update more GHA actions due to deprecations 2024-05-27 22:14:28 +01:00
Neil Alexander
5d9c5b3c9b Minimum Go 1.21, update quic-go, update some CI actions 2024-05-27 22:03:41 +01:00
Paul Donald
f56f9c124c Minor Fixes (#1107)
* Minor comment fixes.

* Optimize PeerEntry for memory efficiency

* Improve NodeConfig for memory alignment
2024-05-27 21:57:28 +01:00
trashpile-shenanigans
5da1fbe397 Bump minimum required go version to 1.20 in documentation as required by quic-go dependency (#1138) 2024-05-27 21:53:52 +01:00
Arceliar
6f3a0a71d4 update ironwood and other dependencies 2024-05-25 06:16:11 -05:00
Arceliar
6cbe56adfe fix incorrect pool use 2024-05-25 06:15:36 -05:00
Arceliar
2d644eabc3 update ironwood (updates bloom dependency) 2024-03-21 21:33:07 -05:00
37 changed files with 501 additions and 211 deletions

View File

@@ -15,10 +15,10 @@ jobs:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/setup-go@v3
- uses: actions/setup-go@v5
with:
go-version: 1.21
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
with:
@@ -34,7 +34,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
@@ -51,17 +51,17 @@ jobs:
strategy:
fail-fast: false
matrix:
goversion: ["1.20", "1.21"]
goversion: ["1.21", "1.22"]
name: Build & Test (Linux, Go ${{ matrix.goversion }})
needs: [lint]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v3
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.goversion }}
@@ -75,17 +75,17 @@ jobs:
strategy:
fail-fast: false
matrix:
goversion: ["1.20", "1.21"]
goversion: ["1.21", "1.22"]
name: Build & Test (Windows, Go ${{ matrix.goversion }})
needs: [lint]
runs-on: windows-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v3
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.goversion }}
@@ -99,17 +99,17 @@ jobs:
strategy:
fail-fast: false
matrix:
goversion: ["1.20", "1.21"]
goversion: ["1.21", "1.22"]
name: Build & Test (macOS, Go ${{ matrix.goversion }})
needs: [lint]
runs-on: macos-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v3
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.goversion }}
@@ -123,7 +123,7 @@ jobs:
strategy:
fail-fast: false
matrix:
goversion: ["1.20", "1.21"]
goversion: ["1.21", "1.22"]
goos:
- freebsd
- openbsd
@@ -133,10 +133,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v3
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.goversion }}

View File

@@ -18,14 +18,14 @@ jobs:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v3
uses: actions/setup-go@v5
with:
go-version: "1.20"
go-version: "stable"
- name: Build package
env:
@@ -33,7 +33,7 @@ jobs:
run: sh contrib/deb/generate.sh
- name: Upload artifacts
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: Debian package (${{ matrix.pkgarch }})
path: "*.deb"
@@ -49,14 +49,14 @@ jobs:
runs-on: macos-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v3
uses: actions/setup-go@v5
with:
go-version: "1.20"
go-version: "stable"
- name: Build package
env:
@@ -64,7 +64,7 @@ jobs:
run: sh contrib/macos/create-pkg.sh
- name: Upload artifacts
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: macOS package (${{ matrix.pkgarch }})
path: "*.pkg"
@@ -80,20 +80,23 @@ jobs:
runs-on: windows-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v3
uses: actions/setup-go@v5
with:
go-version: "1.20"
go-version: "stable"
- name: Setup .NET Core SDK
uses: actions/setup-dotnet@v4
- name: Build package
run: sh contrib/msi/build-msi.sh ${{ matrix.pkgarch }}
- name: Upload artifacts
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: Windows package (${{ matrix.pkgarch }})
path: "*.msi"
@@ -109,20 +112,20 @@ jobs:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
fetch-depth: 0
path: yggdrasil
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
repository: neilalexander/vyatta-yggdrasil
path: vyatta-yggdrasil
- name: Set up Go
uses: actions/setup-go@v3
uses: actions/setup-go@v5
with:
go-version: "1.20"
go-version: "stable"
- name: Build package
env:
@@ -130,7 +133,7 @@ jobs:
run: cd /home/runner/work/yggdrasil-go/yggdrasil-go/vyatta-yggdrasil && ./build-${{ matrix.pkgarch }}
- name: Upload artifacts
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: Router package (${{ matrix.pkgarch }})
path: "/home/runner/work/yggdrasil-go/yggdrasil-go/vyatta-yggdrasil/*.deb"

View File

@@ -26,6 +26,45 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- in case of vulnerabilities.
-->
## [0.5.7] - 2024-08-05
### Added
* WebSocket support for peerings, by using the new `ws://` scheme in `Listen` and `Peers`
* Additionally, the `wss://` scheme can be used to connect to a WebSocket peer behind a HTTPS reverse proxy
### Changed
* On Linux, the TUN adapter now uses vectorised reads/writes where possible, which should reduce the amount of CPU time spent on syscalls and potentially improve throughput
* Link error handling has been improved and various link error messages have been rewritten to be clearer
* Upgrade dependencies
### Fixed
* Multiple multicast connections to the same remote machine should now work correctly
* You may get two connections in some cases, one inbound and one outbound, this is known and will not cause problems
* Running as a Windows service should be more reliable with service startup and shutdown bugs fixed
## [0.5.6] - 2024-05-30
* Go 1.21 is now required to build Yggdrasil
### Added
* The `getPeers` endpoint now reports the RTT/latency of directly connected peers
### Changed
* The tree parent selection algorithm now prefers the lowest latency peers instead of the most stable
* Session key exchange logic has been changed to improve throughput and reduce occasional jitter
### Fixed
* Bloom filter hashing now works correctly on big-endian architectures
* Incorrect buffer pool usage has been fixed, reducing memory allocations
* The multicast beacon interval now backs off correctly, reducing the number of beacons sent
* A denial-of-service vulnerability in the QUIC library has been fixed with a dependency update
## [0.5.5] - 2024-01-27
### Added
@@ -189,7 +228,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
### Changed
* Go 1.17 is now required to build Yggdrasil
* Go 1.20 is now required to build Yggdrasil
## [0.4.3] - 2022-02-06

View File

@@ -24,7 +24,7 @@ or tools in the `contrib` folder.
If you want to build from source, as opposed to installing one of the pre-built
packages:
1. Install [Go](https://golang.org) (requires Go 1.17 or later)
1. Install [Go](https://golang.org) (requires Go 1.21 or later)
2. Clone this repository
2. Run `./build`

View File

@@ -53,13 +53,13 @@ func main() {
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")
flag.Parse()
done := make(chan struct{})
defer close(done)
// Catch interrupts from the operating system to exit gracefully.
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
// Capture the service being stopped on Windows.
minwinsvc.SetOnExit(cancel)
// Create a new logger that logs output to stdout.
var logger *log.Logger
switch *logto {
@@ -188,7 +188,7 @@ func main() {
n := &node{}
// Setup the Yggdrasil node itself.
// Set up the Yggdrasil node itself.
{
options := []core.SetupOption{
core.NodeInfo(cfg.NodeInfo),
@@ -221,7 +221,7 @@ func main() {
logger.Printf("Your IPv6 subnet is %s", subnet.String())
}
// Setup the admin socket.
// Set up the admin socket.
{
options := []admin.SetupOption{
admin.ListenAddress(cfg.AdminListen),
@@ -237,7 +237,7 @@ func main() {
}
}
// Setup the multicast module.
// Set up the multicast module.
{
options := []multicast.SetupOption{}
for _, intf := range cfg.MulticastInterfaces {
@@ -258,7 +258,7 @@ func main() {
}
}
// Setup the TUN module.
// Set up the TUN module.
{
options := []tun.SetupOption{
tun.InterfaceName(cfg.IfName),
@@ -271,6 +271,14 @@ func main() {
n.tun.SetupAdminHandlers(n.admin)
}
}
//Windows service shutdown
minwinsvc.SetOnExit(func() {
logger.Infof("Shutting down service ...")
cancel()
// Wait for all parts to shutdown properly
<-done
})
// Block until we are told to shut down.
<-ctx.Done()

View File

@@ -174,11 +174,13 @@ func run() int {
if err := json.Unmarshal(recv.Response, &resp); err != nil {
panic(err)
}
table.SetHeader([]string{"URI", "State", "Dir", "IP Address", "Uptime", "RX", "TX", "Pr", "Last Error"})
table.SetHeader([]string{"URI", "State", "Dir", "IP Address", "Uptime", "RTT", "RX", "TX", "Pr", "Last Error"})
for _, peer := range resp.Peers {
state, lasterr, dir := "Up", "-", "Out"
state, lasterr, dir, rtt := "Up", "-", "Out", "-"
if !peer.Up {
state, lasterr = "Down", fmt.Sprintf("%s ago: %s", peer.LastErrorTime.Round(time.Second), peer.LastError)
} else if rttms := float64(peer.Latency.Microseconds()) / 1000; rttms > 0 {
rtt = fmt.Sprintf("%.02fms", rttms)
}
if peer.Inbound {
dir = "In"
@@ -194,6 +196,7 @@ func run() int {
dir,
peer.IPAddress,
(time.Duration(peer.Uptime) * time.Second).String(),
rtt,
peer.RXBytes.String(),
peer.TXBytes.String(),
fmt.Sprintf("%d", peer.Priority),

View File

@@ -53,7 +53,7 @@ func (m *Yggdrasil) StartJSON(configjson []byte) error {
if err := m.config.UnmarshalHJSON(configjson); err != nil {
return err
}
// Setup the Yggdrasil node itself.
// Set up the Yggdrasil node itself.
{
options := []core.SetupOption{}
for _, peer := range m.config.Peers {
@@ -85,7 +85,7 @@ func (m *Yggdrasil) StartJSON(configjson []byte) error {
logger.Infof("Your IPv6 subnet is %s", subnet.String())
}
// Setup the multicast module.
// Set up the multicast module.
if len(m.config.MulticastInterfaces) > 0 {
var err error
logger.Infof("Initializing multicast %s", "")

View File

@@ -1,5 +1,5 @@
//go:build ios
// +build ios
//go:build ios || darwin
// +build ios darwin
package mobile

View File

@@ -1,5 +1,5 @@
//go:build !android && !ios
// +build !android,!ios
//go:build !android && !ios && !darwin
// +build !android,!ios,!darwin
package mobile

View File

@@ -1,7 +1,7 @@
#!/bin/sh
# This script generates an MSI file for Yggdrasil for a given architecture. It
# needs to run on Windows within MSYS2 and Go 1.17 or later must be installed on
# needs to run on Windows within MSYS2 and Go 1.21 or later must be installed on
# the system and within the PATH. This is ran currently by GitHub Actions (see
# the workflows in the repository).
#
@@ -16,20 +16,7 @@ then
fi
# Download the wix tools!
if [ ! -d wixbin ];
then
curl -LO https://wixtoolset.org/downloads/v3.14.0.3910/wix314-binaries.zip
if [ `md5sum wix314-binaries.zip | cut -f 1 -d " "` != "34f655cf108086838dd5a76d4318063b" ];
then
echo "wix package didn't match expected checksum"
exit 1
fi
mkdir -p wixbin
unzip -o wix314-binaries.zip -d wixbin || (
echo "failed to unzip WiX"
exit 1
)
fi
dotnet tool install --global wix --version 5.0.0
# Build Yggdrasil!
[ "${PKGARCH}" == "x64" ] && GOOS=windows GOARCH=amd64 CGO_ENABLED=0 ./build
@@ -61,6 +48,11 @@ PKGVERSIONMS=$(echo $PKGVERSION | tr - .)
if [ ! -d wintun ];
then
curl -o wintun.zip https://www.wintun.net/builds/wintun-0.14.1.zip
if [ `sha256sum wintun.zip | cut -f 1 -d " "` != "07c256185d6ee3652e09fa55c0b673e2624b565e02c4b9091c79ca7d2f24ef51" ];
then
echo "wintun package didn't match expected checksum"
exit 1
fi
unzip wintun.zip
fi
if [ $PKGARCH = "x64" ]; then
@@ -101,7 +93,7 @@ cat > wix.xml << EOF
Description="Yggdrasil Network Installer"
Comments="Yggdrasil Network standalone router for Windows."
Manufacturer="github.com/yggdrasil-network"
InstallerVersion="200"
InstallerVersion="500"
InstallScope="perMachine"
Languages="1033"
Compressed="yes"
@@ -205,5 +197,5 @@ EOF
# Generate the MSI
CANDLEFLAGS="-nologo"
LIGHTFLAGS="-nologo -spdb -sice:ICE71 -sice:ICE61"
wixbin/candle $CANDLEFLAGS -out ${PKGNAME}-${PKGVERSION}-${PKGARCH}.wixobj -arch ${PKGARCH} wix.xml && \
wixbin/light $LIGHTFLAGS -ext WixUtilExtension.dll -out ${PKGNAME}-${PKGVERSION}-${PKGARCH}.msi ${PKGNAME}-${PKGVERSION}-${PKGARCH}.wixobj
candle $CANDLEFLAGS -out ${PKGNAME}-${PKGVERSION}-${PKGARCH}.wixobj -arch ${PKGARCH} wix.xml && \
light $LIGHTFLAGS -ext WixUtilExtension.dll -out ${PKGNAME}-${PKGVERSION}-${PKGARCH}.msi ${PKGNAME}-${PKGVERSION}-${PKGARCH}.wixobj

37
go.mod
View File

@@ -1,39 +1,40 @@
module github.com/yggdrasil-network/yggdrasil-go
go 1.20
go 1.21
require (
github.com/Arceliar/ironwood v0.0.0-20240115190409-ddd1fa67c018
github.com/Arceliar/ironwood v0.0.0-20240529054413-b8e59574e2b2
github.com/Arceliar/phony v0.0.0-20220903101357-530938a4b13d
github.com/cheggaaa/pb/v3 v3.1.4
github.com/cheggaaa/pb/v3 v3.1.5
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.40.1
github.com/quic-go/quic-go v0.45.1
github.com/vishvananda/netlink v1.1.0
golang.org/x/crypto v0.18.0
golang.org/x/mobile v0.0.0-20231006135142-2b44d11868fe
golang.org/x/net v0.20.0
golang.org/x/sys v0.16.0
golang.org/x/text v0.14.0
golang.zx2c4.com/wireguard v0.0.0-20230223181233-21636207a675
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
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173
golang.zx2c4.com/wireguard/windows v0.5.3
nhooyr.io/websocket v1.8.11
)
require (
github.com/bits-and-blooms/bitset v1.5.0 // indirect
github.com/bits-and-blooms/bloom/v3 v3.3.1 // indirect
github.com/bits-and-blooms/bitset v1.13.0 // indirect
github.com/bits-and-blooms/bloom/v3 v3.7.0 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/onsi/ginkgo/v2 v2.9.5 // indirect
github.com/quic-go/qtls-go1-20 v0.4.1 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
go.uber.org/mock v0.3.0 // indirect
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect
golang.org/x/mod v0.13.0 // indirect
golang.org/x/tools v0.14.0 // indirect
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/tools v0.23.0 // indirect
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
)
@@ -41,7 +42,7 @@ require (
github.com/VividCortex/ewma v1.2.0 // indirect
github.com/fatih/color v1.15.0 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mattn/go-runewidth v0.0.14 // 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
)

103
go.sum
View File

@@ -1,16 +1,16 @@
github.com/Arceliar/ironwood v0.0.0-20240115190409-ddd1fa67c018 h1:7r/T7qJht4CaPl74AgU7dG5N6g7+2230/9BhrbtRijk=
github.com/Arceliar/ironwood v0.0.0-20240115190409-ddd1fa67c018/go.mod h1:5x7fWW0mshe9WQ1lvSMmmHBYC3BeHH9gpwW5tz7cbfw=
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/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=
github.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4=
github.com/bits-and-blooms/bitset v1.3.1/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
github.com/bits-and-blooms/bitset v1.5.0 h1:NpE8frKRLGHIcEzkR+gZhiioW1+WbYV6fKwD6ZIpQT8=
github.com/bits-and-blooms/bitset v1.5.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
github.com/bits-and-blooms/bloom/v3 v3.3.1 h1:K2+A19bXT8gJR5mU7y+1yW6hsKfNCjcP2uNfLFKncjQ=
github.com/bits-and-blooms/bloom/v3 v3.3.1/go.mod h1:bhUUknWd5khVbTe4UgMCSiOOVJzr3tMoijSK3WwvW90=
github.com/cheggaaa/pb/v3 v3.1.4 h1:DN8j4TVVdKu3WxVwcRKu0sG00IIU6FewoABZzXbRQeo=
github.com/cheggaaa/pb/v3 v3.1.4/go.mod h1:6wVjILNBaXMs8c21qRiaUM8BR82erfgau1DQ4iUXmSA=
github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE=
github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
github.com/bits-and-blooms/bloom/v3 v3.7.0 h1:VfknkqV4xI+PsaDIsoHueyxVDZrfvMn56jeWUzvzdls=
github.com/bits-and-blooms/bloom/v3 v3.7.0/go.mod h1:VKlUSvp0lFIYqxJjzdnSsZEw4iHb1kOL2tfHTgyJBHg=
github.com/cheggaaa/pb/v3 v3.1.5 h1:QuuUzeM2WsAqG2gMqtzaWithDJv0i+i6UlnwSCI4QLk=
github.com/cheggaaa/pb/v3 v3.1.5/go.mod h1:CrxkeghYTXi1lQBEI7jSn+3svI3cuc19haAj6jM60XI=
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=
@@ -20,12 +20,17 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/gologme/log v1.3.0 h1:l781G4dE+pbigClDSDzSaaYKtiueHCILUa/qSDsmHAo=
github.com/gologme/log v1.3.0/go.mod h1:yKT+DvIPdDdDoPtqFrFxheooyVmoqi0BAsw+erN3wA4=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/hashicorp/go-syslog v1.0.0 h1:KaodqZuhUoZereWVIYmpUgZysurB1kBLX2j0MwMrUAE=
@@ -41,19 +46,18 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q=
github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k=
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/qtls-go1-20 v0.4.1 h1:D33340mCNDAIKBqXuAvexTNMUByrYmFYVfKfDN5nfFs=
github.com/quic-go/qtls-go1-20 v0.4.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
github.com/quic-go/quic-go v0.40.1 h1:X3AGzUNFs0jVuO3esAGnTfvdgvL4fq655WaOi1snv1Q=
github.com/quic-go/quic-go v0.40.1/go.mod h1:PeN7kuVJ4xZbxSv/4OX6S1USOX8MJvydwpTx31vx60c=
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/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=
@@ -67,32 +71,35 @@ github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17
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/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo=
go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db h1:D/cFflL63o2KSLJIwjlcIt8PR064j/xsmdEJL/YvY/o=
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
golang.org/x/mobile v0.0.0-20231006135142-2b44d11868fe h1:lrXv4yHeD9FA8PSJATWowP1QvexpyAPWmPia+Kbzql8=
golang.org/x/mobile v0.0.0-20231006135142-2b44d11868fe/go.mod h1:BrnXpEObnFxpaT75Jo9hsCazwOWcp7nVIa8NNuH5cuA=
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/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.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8=
golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
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/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.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.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=
@@ -104,34 +111,48 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/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.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.8.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/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=
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
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 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
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/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=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc=
golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg=
golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg=
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
golang.zx2c4.com/wireguard v0.0.0-20230223181233-21636207a675 h1:/J/RVnr7ng4fWPRH3xa4WtBJ1Jp+Auu4YNLmGiPv5QU=
golang.zx2c4.com/wireguard v0.0.0-20230223181233-21636207a675/go.mod h1:whfbyDBt09xhCYQWtO2+3UVjlaq6/9hDZrjg2ZE6SyA=
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 h1:/jFs0duh4rdb8uIfPMv78iAJGcPKDeqAFnaLBropIC4=
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173/go.mod h1:tkCQ4FQXmpAgYVh++1cq16/dH4QJtmvpRv19DWGAHSA=
golang.zx2c4.com/wireguard/windows v0.5.3 h1:On6j2Rpn3OEMXqBq00QEDC7bWSZrPIHKIus8eIuExIE=
golang.zx2c4.com/wireguard/windows v0.5.3/go.mod h1:9TEe8TJmtwyQebdFwAkEWOPr3prrtqm+REGFifP60hI=
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
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=

View File

@@ -12,7 +12,7 @@ type AddPeerRequest struct {
type AddPeerResponse struct{}
func (a *AdminSocket) addPeerHandler(req *AddPeerRequest, res *AddPeerResponse) error {
func (a *AdminSocket) addPeerHandler(req *AddPeerRequest, _ *AddPeerResponse) error {
u, err := url.Parse(req.Uri)
if err != nil {
return fmt.Errorf("unable to parse peering URI: %w", err)

View File

@@ -201,10 +201,6 @@ func (a *AdminSocket) SetupAdminHandlers() {
return res, nil
},
)
//_ = a.AddHandler("getNodeInfo", []string{"key"}, t.proto.nodeinfo.nodeInfoAdminHandler)
//_ = a.AddHandler("debug_remoteGetSelf", []string{"key"}, t.proto.getSelfHandler)
//_ = a.AddHandler("debug_remoteGetPeers", []string{"key"}, t.proto.getPeersHandler)
//_ = a.AddHandler("debug_remoteGetDHT", []string{"key"}, t.proto.getDHTHandler)
}
// IsStarted returns true if the module has been started.
@@ -269,7 +265,6 @@ func (a *AdminSocket) listen() {
case "tcp":
a.listener, err = net.Listen("tcp", u.Host)
default:
// err = errors.New(fmt.Sprint("protocol not supported: ", u.Scheme))
a.listener, err = net.Listen("tcp", listenaddr)
}
} else {
@@ -309,23 +304,6 @@ func (a *AdminSocket) handleRequest(conn net.Conn) {
defer conn.Close()
/*
defer func() {
r := recover()
if r != nil {
fmt.Println("ERROR:", r)
a.log.Debugln("Admin socket error:", r)
if err := encoder.Encode(&ErrorResponse{
Error: "Check your syntax and input types",
}); err != nil {
fmt.Println("ERROR 2:", err)
a.log.Debugln("Admin socket JSON encode error:", err)
}
conn.Close()
}
}()
*/
for {
var err error
var buf json.RawMessage

View File

@@ -23,7 +23,7 @@ type PathEntry struct {
Sequence uint64 `json:"sequence"`
}
func (a *AdminSocket) getPathsHandler(req *GetPathsRequest, res *GetPathsResponse) error {
func (a *AdminSocket) getPathsHandler(_ *GetPathsRequest, res *GetPathsResponse) error {
paths := a.core.GetPaths()
res.Paths = make([]PathEntry, 0, len(paths))
for _, p := range paths {

View File

@@ -27,11 +27,12 @@ type PeerEntry struct {
RXBytes DataUnit `json:"bytes_recvd,omitempty"`
TXBytes DataUnit `json:"bytes_sent,omitempty"`
Uptime float64 `json:"uptime,omitempty"`
LastError string `json:"last_error,omitempty"`
Latency time.Duration `json:"latency_ms,omitempty"`
LastErrorTime time.Duration `json:"last_error_time,omitempty"`
LastError string `json:"last_error,omitempty"`
}
func (a *AdminSocket) getPeersHandler(req *GetPeersRequest, res *GetPeersResponse) error {
func (a *AdminSocket) getPeersHandler(_ *GetPeersRequest, res *GetPeersResponse) error {
peers := a.core.GetPeers()
res.Peers = make([]PeerEntry, 0, len(peers))
for _, p := range peers {
@@ -45,6 +46,9 @@ func (a *AdminSocket) getPeersHandler(req *GetPeersRequest, res *GetPeersRespons
TXBytes: DataUnit(p.TXBytes),
Uptime: p.Uptime.Seconds(),
}
if p.Latency > 0 {
peer.Latency = p.Latency
}
if addr := address.AddrForKey(p.Key); addr != nil {
peer.PublicKey = hex.EncodeToString(p.Key)
peer.IPAddress = net.IP(addr[:]).String()

View File

@@ -17,7 +17,7 @@ type GetSelfResponse struct {
Subnet string `json:"subnet"`
}
func (a *AdminSocket) getSelfHandler(req *GetSelfRequest, res *GetSelfResponse) error {
func (a *AdminSocket) getSelfHandler(_ *GetSelfRequest, res *GetSelfResponse) error {
self := a.core.GetSelf()
snet := a.core.Subnet()
res.BuildName = version.BuildName()

View File

@@ -23,7 +23,7 @@ type SessionEntry struct {
Uptime float64 `json:"uptime"`
}
func (a *AdminSocket) getSessionsHandler(req *GetSessionsRequest, res *GetSessionsResponse) error {
func (a *AdminSocket) getSessionsHandler(_ *GetSessionsRequest, res *GetSessionsResponse) error {
sessions := a.core.GetSessions()
res.Sessions = make([]SessionEntry, 0, len(sessions))
for _, s := range sessions {

View File

@@ -20,11 +20,9 @@ type TreeEntry struct {
PublicKey string `json:"key"`
Parent string `json:"parent"`
Sequence uint64 `json:"sequence"`
//Port uint64 `json:"port"`
//Rest uint64 `json:"rest"`
}
func (a *AdminSocket) getTreeHandler(req *GetTreeRequest, res *GetTreeResponse) error {
func (a *AdminSocket) getTreeHandler(_ *GetTreeRequest, res *GetTreeResponse) error {
tree := a.core.GetTree()
res.Tree = make([]TreeEntry, 0, len(tree))
for _, d := range tree {
@@ -34,8 +32,6 @@ func (a *AdminSocket) getTreeHandler(req *GetTreeRequest, res *GetTreeResponse)
PublicKey: hex.EncodeToString(d.Key[:]),
Parent: hex.EncodeToString(d.Parent[:]),
Sequence: d.Sequence,
//Port: d.Port,
//Rest: d.Rest,
})
}
sort.SliceStable(res.Tree, func(i, j int) bool {

View File

@@ -12,7 +12,7 @@ type RemovePeerRequest struct {
type RemovePeerResponse struct{}
func (a *AdminSocket) removePeerHandler(req *RemovePeerRequest, res *RemovePeerResponse) error {
func (a *AdminSocket) removePeerHandler(req *RemovePeerRequest, _ *RemovePeerResponse) error {
u, err := url.Parse(req.Uri)
if err != nil {
return fmt.Errorf("unable to parse peering URI: %w", err)

View File

@@ -51,9 +51,9 @@ type NodeConfig struct {
AllowedPublicKeys []string `comment:"List of peer public keys to allow incoming peering connections\nfrom. If left empty/undefined then all connections will be allowed\nby default. This does not affect outgoing peerings, nor does it\naffect link-local peers discovered via multicast."`
IfName string `comment:"Local network interface name for TUN adapter, or \"auto\" to select\nan interface automatically, or \"none\" to run without TUN."`
IfMTU uint64 `comment:"Maximum Transmission Unit (MTU) size for your local TUN interface.\nDefault is the largest supported size for your platform. The lowest\npossible value is 1280."`
LogLookups bool `json:",omitempty"`
NodeInfoPrivacy bool `comment:"By default, nodeinfo contains some defaults including the platform,\narchitecture and Yggdrasil version. These can help when surveying\nthe network and diagnosing network routing problems. Enabling\nnodeinfo privacy prevents this, so that only items specified in\n\"NodeInfo\" are sent back if specified."`
NodeInfo map[string]interface{} `comment:"Optional node info. This must be a { \"key\": \"value\", ... } map\nor set as null. This is entirely optional but, if set, is visible\nto the whole network on request."`
LogLookups bool `json:",omitempty"`
}
type MulticastInterfaceConfig struct {

View File

@@ -33,6 +33,7 @@ type PeerInfo struct {
RXBytes uint64
TXBytes uint64
Uptime time.Duration
Latency time.Duration
}
type TreeEntryInfo struct {
@@ -92,6 +93,7 @@ func (c *Core) GetPeers() []PeerInfo {
peerinfo.Root = p.Root
peerinfo.Port = p.Port
peerinfo.Priority = p.Priority
peerinfo.Latency = p.Latency
}
peers = append(peers, peerinfo)
}

View File

@@ -212,7 +212,7 @@ func (c *Core) ReadFrom(p []byte) (n int, from net.Addr, err error) {
func (c *Core) WriteTo(p []byte, addr net.Addr) (n int, err error) {
buf := allocBytes(0)
defer freeBytes(buf)
defer func() { freeBytes(buf) }()
buf = append(buf, typeSessionTraffic)
buf = append(buf, p...)
n, err = c.PacketConn.WriteTo(buf, addr)

View File

@@ -7,7 +7,6 @@ import (
"fmt"
"io"
"net"
"net/netip"
"net/url"
"strconv"
"strings"
@@ -38,6 +37,8 @@ type links struct {
unix *linkUNIX // UNIX interface support
socks *linkSOCKS // SOCKS interface support
quic *linkQUIC // QUIC interface support
ws *linkWS // WS interface support
wss *linkWSS // WSS interface support
// _links can only be modified safely from within the links actor
_links map[linkInfo]*link // *link is nil if connection in progress
}
@@ -63,7 +64,7 @@ type link struct {
// The remaining fields can only be modified safely from within the links actor
_conn *linkConn // Connected link, if any, nil if not connected
_err error // Last error on the connection, if any
_errtime time.Time // Last time an error occured
_errtime time.Time // Last time an error occurred
}
type linkOptions struct {
@@ -98,6 +99,8 @@ func (l *links) init(c *Core) error {
l.unix = l.newLinkUNIX()
l.socks = l.newLinkSOCKS()
l.quic = l.newLinkQUIC()
l.ws = l.newLinkWS()
l.wss = l.newLinkWSS()
l._links = make(map[linkInfo]*link)
var listeners []ListenAddress
@@ -137,7 +140,7 @@ const ErrLinkAlreadyConfigured = linkError("peer is already configured")
const ErrLinkNotConfigured = linkError("peer is not configured")
const ErrLinkPriorityInvalid = linkError("priority value is invalid")
const ErrLinkPinnedKeyInvalid = linkError("pinned public key is invalid")
const ErrLinkPasswordInvalid = linkError("password is invalid")
const ErrLinkPasswordInvalid = linkError("invalid password supplied")
const ErrLinkUnrecognisedSchema = linkError("link schema unknown")
const ErrLinkMaxBackoffInvalid = linkError("max backoff duration invalid")
@@ -360,9 +363,11 @@ func (l *links) add(u *url.URL, sintf string, linkType linkType) error {
_ = lc.Close()
phony.Block(l, func() {
state._conn = nil
if state._err = err; state._err != nil {
state._errtime = time.Now()
if err == nil {
err = fmt.Errorf("remote side closed the connection")
}
state._err = err
state._errtime = time.Now()
})
// If the link is persistently configured, back off if needed
@@ -379,7 +384,7 @@ func (l *links) add(u *url.URL, sintf string, linkType linkType) error {
return retErr
}
func (l *links) remove(u *url.URL, sintf string, linkType linkType) error {
func (l *links) remove(u *url.URL, sintf string, _ linkType) error {
var retErr error
phony.Block(l, func() {
// Generate the link info and see whether we think we already
@@ -418,6 +423,10 @@ func (l *links) listen(u *url.URL, sintf string) (*Listener, error) {
protocol = l.unix
case "quic":
protocol = l.quic
case "ws":
protocol = l.ws
case "wss":
protocol = l.wss
default:
cancel()
return nil, ErrLinkUnrecognisedSchema
@@ -546,6 +555,10 @@ func (l *links) connect(ctx context.Context, u *url.URL, info linkInfo, options
dialer = l.unix
case "quic":
dialer = l.quic
case "ws":
dialer = l.ws
case "wss":
dialer = l.wss
default:
return nil, ErrLinkUnrecognisedSchema
}
@@ -567,7 +580,7 @@ func (l *links) handler(linkType linkType, options linkOptions, conn net.Conn, s
switch {
case err != nil:
return fmt.Errorf("write handshake: %w", err)
case err == nil && n != len(metaBytes):
case n != len(metaBytes):
return fmt.Errorf("incomplete handshake send")
}
meta = version_metadata{}
@@ -636,21 +649,11 @@ func (l *links) handler(linkType linkType, options linkOptions, conn net.Conn, s
l.core.log.Infof("Disconnected %s: %s, source %s; error: %s",
dir, remoteStr, localStr, err)
}
return nil
return err
}
func urlForLinkInfo(u url.URL) url.URL {
u.RawQuery = ""
if host, _, err := net.SplitHostPort(u.Host); err == nil {
if addr, err := netip.ParseAddr(host); err == nil {
// For peers that look like multicast peers (i.e.
// link-local addresses), we will ignore the port number,
// otherwise we might open multiple connections to them.
if addr.IsLinkLocalUnicast() {
u.Host = fmt.Sprintf("[%s]", addr.String())
}
}
}
return u
}

View File

@@ -28,6 +28,6 @@ func (t *linkTCP) tcpContext(network, address string, c syscall.RawConn) error {
}
}
func (t *linkTCP) getControl(sintf string) func(string, string, syscall.RawConn) error {
func (t *linkTCP) getControl(_ string) func(string, string, syscall.RawConn) error {
return t.tcpContext
}

123
src/core/link_ws.go Normal file
View File

@@ -0,0 +1,123 @@
package core
import (
"context"
"net"
"net/http"
"net/url"
"time"
"github.com/Arceliar/phony"
"nhooyr.io/websocket"
)
type linkWS struct {
phony.Inbox
*links
}
type linkWSConn struct {
net.Conn
}
type linkWSListener struct {
ch chan *linkWSConn
ctx context.Context
httpServer *http.Server
listener net.Listener
}
type wsServer struct {
ch chan *linkWSConn
ctx context.Context
}
func (l *linkWSListener) Accept() (net.Conn, error) {
qs := <-l.ch
if qs == nil {
return nil, context.Canceled
}
return qs, nil
}
func (l *linkWSListener) Addr() net.Addr {
return l.listener.Addr()
}
func (l *linkWSListener) Close() error {
if err := l.httpServer.Shutdown(l.ctx); err != nil {
return err
}
return l.listener.Close()
}
func (s *wsServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/health" || r.URL.Path == "/healthz" {
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte("OK"))
return
}
c, err := websocket.Accept(w, r, &websocket.AcceptOptions{
Subprotocols: []string{"ygg-ws"},
})
if err != nil {
return
}
if c.Subprotocol() != "ygg-ws" {
c.Close(websocket.StatusPolicyViolation, "client must speak the ygg-ws subprotocol")
return
}
s.ch <- &linkWSConn{
Conn: websocket.NetConn(s.ctx, c, websocket.MessageBinary),
}
}
func (l *links) newLinkWS() *linkWS {
lt := &linkWS{
links: l,
}
return lt
}
func (l *linkWS) dial(ctx context.Context, url *url.URL, info linkInfo, options linkOptions) (net.Conn, error) {
wsconn, _, err := websocket.Dial(ctx, url.String(), &websocket.DialOptions{
Subprotocols: []string{"ygg-ws"},
})
if err != nil {
return nil, err
}
return &linkWSConn{
Conn: websocket.NetConn(ctx, wsconn, websocket.MessageBinary),
}, nil
}
func (l *linkWS) listen(ctx context.Context, url *url.URL, _ string) (net.Listener, error) {
nl, err := net.Listen("tcp", url.Host)
if err != nil {
return nil, err
}
ch := make(chan *linkWSConn)
httpServer := &http.Server{
Handler: &wsServer{
ch: ch,
ctx: ctx,
},
BaseContext: func(_ net.Listener) context.Context { return ctx },
ReadTimeout: time.Second * 10,
WriteTimeout: time.Second * 10,
}
lwl := &linkWSListener{
ch: ch,
ctx: ctx,
httpServer: httpServer,
listener: nl,
}
go lwl.httpServer.Serve(nl) // nolint:errcheck
return lwl, nil
}

43
src/core/link_wss.go Normal file
View File

@@ -0,0 +1,43 @@
package core
import (
"context"
"fmt"
"net"
"net/url"
"github.com/Arceliar/phony"
"nhooyr.io/websocket"
)
type linkWSS struct {
phony.Inbox
*links
}
type linkWSSConn struct {
net.Conn
}
func (l *links) newLinkWSS() *linkWSS {
lwss := &linkWSS{
links: l,
}
return lwss
}
func (l *linkWSS) dial(ctx context.Context, url *url.URL, info linkInfo, options linkOptions) (net.Conn, error) {
wsconn, _, err := websocket.Dial(ctx, url.String(), &websocket.DialOptions{
Subprotocols: []string{"ygg-ws"},
})
if err != nil {
return nil, err
}
return &linkWSSConn{
Conn: websocket.NetConn(ctx, wsconn, websocket.MessageBinary),
}, nil
}
func (l *linkWSS) listen(ctx context.Context, url *url.URL, _ string) (net.Listener, error) {
return nil, fmt.Errorf("WSS listener not supported, use WS listener behind reverse proxy instead")
}

View File

@@ -8,7 +8,6 @@ import (
"bytes"
"crypto/ed25519"
"encoding/binary"
"fmt"
"io"
"golang.org/x/crypto/blake2b"
@@ -38,6 +37,16 @@ const (
metaPriority // uint8
)
type handshakeError string
func (e handshakeError) Error() string { return string(e) }
const ErrHandshakeInvalidPreamble = handshakeError("invalid handshake, remote side is not Yggdrasil")
const ErrHandshakeInvalidLength = handshakeError("invalid handshake length, possible version mismatch")
const ErrHandshakeInvalidPassword = handshakeError("invalid password supplied, check your config")
const ErrHandshakeHashFailure = handshakeError("invalid hash length")
const ErrHandshakeIncorrectPassword = handshakeError("password does not match remote side")
// Gets a base metadata with no keys set, but with the correct version numbers.
func version_getBaseMetadata() version_metadata {
return version_metadata{
@@ -77,7 +86,7 @@ func (m *version_metadata) encode(privateKey ed25519.PrivateKey, password []byte
return nil, err
}
if n != ed25519.PublicKeySize {
return nil, fmt.Errorf("hash writer only wrote %d bytes", n)
return nil, ErrHandshakeHashFailure
}
hash := hasher.Sum(nil)
bs = append(bs, ed25519.Sign(privateKey, hash)...)
@@ -94,11 +103,11 @@ func (m *version_metadata) decode(r io.Reader, password []byte) error {
}
meta := [4]byte{'m', 'e', 't', 'a'}
if !bytes.Equal(bh[:4], meta[:]) {
return fmt.Errorf("invalid handshake preamble")
return ErrHandshakeInvalidPreamble
}
hl := binary.BigEndian.Uint16(bh[4:6])
if hl < ed25519.SignatureSize {
return fmt.Errorf("invalid handshake length")
return ErrHandshakeInvalidLength
}
bs := make([]byte, hl)
if _, err := io.ReadFull(r, bs); err != nil {
@@ -132,15 +141,15 @@ func (m *version_metadata) decode(r io.Reader, password []byte) error {
hasher, err := blake2b.New512(password)
if err != nil {
return fmt.Errorf("invalid password supplied")
return ErrHandshakeInvalidPassword
}
n, err := hasher.Write(m.publicKey)
if err != nil || n != ed25519.PublicKeySize {
return fmt.Errorf("failed to generate hash")
return ErrHandshakeHashFailure
}
hash := hasher.Sum(nil)
if !ed25519.Verify(m.publicKey, hash, sig) {
return fmt.Errorf("password is incorrect")
return ErrHandshakeIncorrectPassword
}
return nil
}

View File

@@ -11,7 +11,7 @@ type GetMulticastInterfacesResponse struct {
Interfaces []string `json:"multicast_interfaces"`
}
func (m *Multicast) getMulticastInterfacesHandler(req *GetMulticastInterfacesRequest, res *GetMulticastInterfacesResponse) error {
func (m *Multicast) getMulticastInterfacesHandler(_ *GetMulticastInterfacesRequest, res *GetMulticastInterfacesResponse) error {
res.Interfaces = []string{}
for _, v := range m.Interfaces() {
res.Interfaces = append(res.Interfaces, v.Name)

View File

@@ -358,6 +358,7 @@ func (m *Multicast) _announce() {
if linfo.interval.Seconds() < 15 {
linfo.interval += time.Second
}
linfo.time = time.Now()
break
}
}

View File

@@ -1,42 +1,60 @@
package tun
const TUN_OFFSET_BYTES = 4
const TUN_OFFSET_BYTES = 80 // sizeof(virtio_net_hdr)
func (tun *TunAdapter) read() {
var buf [TUN_OFFSET_BYTES + 65535]byte
vs := tun.iface.BatchSize()
bufs := make([][]byte, vs)
sizes := make([]int, vs)
for i := range bufs {
bufs[i] = make([]byte, TUN_OFFSET_BYTES+65535)
}
for {
n, err := tun.iface.Read(buf[:], TUN_OFFSET_BYTES)
if n <= TUN_OFFSET_BYTES || err != nil {
n, err := tun.iface.Read(bufs, sizes, TUN_OFFSET_BYTES)
if err != nil {
tun.log.Errorln("Error reading TUN:", err)
ferr := tun.iface.Flush()
if ferr != nil {
tun.log.Errorln("Unable to flush packets:", ferr)
}
return
}
begin := TUN_OFFSET_BYTES
end := begin + n
bs := buf[begin:end]
if _, err := tun.rwc.Write(bs); err != nil {
tun.log.Debugln("Unable to send packet:", err)
for i, b := range bufs[:n] {
if _, err := tun.rwc.Write(b[TUN_OFFSET_BYTES : TUN_OFFSET_BYTES+sizes[i]]); err != nil {
tun.log.Debugln("Unable to send packet:", err)
}
}
}
}
func (tun *TunAdapter) write() {
var buf [TUN_OFFSET_BYTES + 65535]byte
func (tun *TunAdapter) queue() {
for {
bs := buf[TUN_OFFSET_BYTES:]
n, err := tun.rwc.Read(bs)
p := bufPool.Get().([]byte)[:bufPoolSize]
n, err := tun.rwc.Read(p)
if err != nil {
tun.log.Errorln("Exiting TUN writer due to core read error:", err)
return
}
tun.ch <- p[:n]
}
}
func (tun *TunAdapter) write() {
vs := cap(tun.ch)
bufs := make([][]byte, vs)
for i := range bufs {
bufs[i] = make([]byte, TUN_OFFSET_BYTES+65535)
}
for {
n := len(tun.ch)
if n == 0 {
n = 1 // Nothing queued up yet, wait for it instead
}
for i := 0; i < n; i++ {
msg := <-tun.ch
bufs[i] = append(bufs[i][:TUN_OFFSET_BYTES], msg...)
bufPool.Put(msg) // nolint:staticcheck
}
if !tun.isEnabled {
continue // Nothing to do, the tun isn't enabled
}
bs = buf[:TUN_OFFSET_BYTES+n]
if _, err = tun.iface.Write(bs, TUN_OFFSET_BYTES); err != nil {
if _, err := tun.iface.Write(bufs[:n], TUN_OFFSET_BYTES); err != nil {
tun.Act(nil, func() {
if !tun.isOpen {
tun.log.Errorln("TUN iface write error:", err)

View File

@@ -10,9 +10,11 @@ import (
"fmt"
"io"
"net"
"sync"
"time"
"github.com/Arceliar/phony"
"golang.zx2c4.com/wireguard/tun"
wgtun "golang.zx2c4.com/wireguard/tun"
"github.com/yggdrasil-network/yggdrasil-go/src/address"
"github.com/yggdrasil-network/yggdrasil-go/src/config"
@@ -39,7 +41,7 @@ type TunAdapter struct {
addr address.Address
subnet address.Subnet
mtu uint64
iface tun.Device
iface wgtun.Device
phony.Inbox // Currently only used for _handlePacket from the reader, TODO: all the stuff that currently needs a mutex below
isOpen bool
isEnabled bool // Used by the writer to drop sessionTraffic if not enabled
@@ -48,6 +50,7 @@ type TunAdapter struct {
name InterfaceName
mtu InterfaceMTU
}
ch chan []byte
}
// Gets the maximum supported MTU for the platform based on the defaults in
@@ -62,6 +65,20 @@ func getSupportedMTU(mtu uint64) uint64 {
return mtu
}
func waitForTUNUp(ch <-chan wgtun.Event) bool {
t := time.After(time.Second * 5)
for {
select {
case ev := <-ch:
if ev == wgtun.EventUp {
return true
}
case <-t:
return false
}
}
}
// Name returns the name of the adapter, e.g. "tun0". On Windows, this may
// return a canonical adapter name instead.
func (tun *TunAdapter) Name() string {
@@ -145,6 +162,8 @@ func (tun *TunAdapter) _start() error {
tun.rwc.SetMTU(tun.MTU())
tun.isOpen = true
tun.isEnabled = true
tun.ch = make(chan []byte, tun.iface.BatchSize())
go tun.queue()
go tun.read()
go tun.write()
return nil
@@ -178,3 +197,12 @@ func (tun *TunAdapter) _stop() error {
}
return nil
}
const bufPoolSize = TUN_OFFSET_BYTES + 65535
var bufPool = sync.Pool{
New: func() any {
b := [bufPoolSize]byte{}
return b[:]
},
}

View File

@@ -80,6 +80,9 @@ func (tun *TunAdapter) setup(ifname string, addr string, mtu uint64) error {
if err != nil {
return fmt.Errorf("failed to create TUN: %w", err)
}
if !waitForTUNUp(iface.Events()) {
return fmt.Errorf("TUN did not come up in time")
}
tun.iface = iface
if mtu, err := iface.MTU(); err == nil {
tun.mtu = getSupportedMTU(uint64(mtu))

View File

@@ -27,6 +27,9 @@ func (tun *TunAdapter) setup(ifname string, addr string, mtu uint64) error {
if err != nil {
return fmt.Errorf("failed to create TUN: %w", err)
}
if !waitForTUNUp(iface.Events()) {
return fmt.Errorf("TUN did not come up in time")
}
tun.iface = iface
if m, err := iface.MTU(); err == nil {
tun.mtu = getSupportedMTU(uint64(m))
@@ -55,6 +58,9 @@ func (tun *TunAdapter) setupFD(fd int32, addr string, mtu uint64) error {
unix.Close(dfd)
return fmt.Errorf("failed to create TUN from FD: %w", err)
}
if !waitForTUNUp(iface.Events()) {
return fmt.Errorf("TUN did not come up in time")
}
tun.iface = iface
if m, err := iface.MTU(); err == nil {
tun.mtu = getSupportedMTU(uint64(m))

View File

@@ -21,6 +21,9 @@ func (tun *TunAdapter) setup(ifname string, addr string, mtu uint64) error {
if err != nil {
return fmt.Errorf("failed to create TUN: %w", err)
}
if !waitForTUNUp(iface.Events()) {
return fmt.Errorf("TUN did not come up in time")
}
tun.iface = iface
if mtu, err := iface.MTU(); err == nil {
tun.mtu = getSupportedMTU(uint64(mtu))

View File

@@ -18,6 +18,9 @@ func (tun *TunAdapter) setup(ifname string, addr string, mtu uint64) error {
if err != nil {
return fmt.Errorf("failed to create TUN: %w", err)
}
if !waitForTUNUp(iface.Events()) {
return fmt.Errorf("TUN did not come up in time")
}
tun.iface = iface
if mtu, err := iface.MTU(); err == nil {
tun.mtu = getSupportedMTU(uint64(mtu))

View File

@@ -34,6 +34,9 @@ func (tun *TunAdapter) setup(ifname string, addr string, mtu uint64) error {
if iface, err = wgtun.CreateTUNWithRequestedGUID(ifname, &guid, int(mtu)); err != nil {
return err
}
if !waitForTUNUp(iface.Events()) {
return fmt.Errorf("TUN did not come up in time")
}
tun.iface = iface
if addr != "" {
if err = tun.setupAddress(addr); err != nil {