diff --git a/build b/build index 583bf610..c7214438 100755 --- a/build +++ b/build @@ -9,13 +9,11 @@ PKGVER=${PKGVER:-$(sh contrib/semver/version.sh --bare)} LDFLAGS="-X $PKGSRC.buildName=$PKGNAME -X $PKGSRC.buildVersion=$PKGVER" ARGS="-v" -while getopts "uaitc:l:dro:p" option +while getopts "utc:l:dro:p" option do case "$option" in u) UPX=true;; - i) IOS=true;; - a) ANDROID=true;; t) TABLES=true;; c) GCFLAGS="$GCFLAGS $OPTARG";; l) LDFLAGS="$LDFLAGS $OPTARG";; @@ -30,25 +28,11 @@ if [ -z $TABLES ] && [ -z $DEBUG ]; then LDFLAGS="$LDFLAGS -s -w" fi -if [ $IOS ]; then - echo "Building framework for iOS" - go get golang.org/x/mobile/bind - gomobile bind -target ios -tags mobile -o Yggdrasil.framework -ldflags="$LDFLAGS $STRIP" -gcflags="$GCFLAGS" \ - github.com/yggdrasil-network/yggdrasil-extras/src/mobile \ - github.com/yggdrasil-network/yggdrasil-go/src/config -elif [ $ANDROID ]; then - echo "Building aar for Android" - go get golang.org/x/mobile/bind - gomobile bind -target android -tags mobile -o yggdrasil.aar -ldflags="$LDFLAGS $STRIP" -gcflags="$GCFLAGS" \ - github.com/yggdrasil-network/yggdrasil-extras/src/mobile \ - github.com/yggdrasil-network/yggdrasil-go/src/config -else - for CMD in yggdrasil yggdrasilctl ; do - echo "Building: $CMD" - go build $ARGS -ldflags="$LDFLAGS" -gcflags="$GCFLAGS" ./cmd/$CMD +for CMD in yggdrasil yggdrasilctl ; do + echo "Building: $CMD" + go build $ARGS -ldflags="$LDFLAGS" -gcflags="$GCFLAGS" ./cmd/$CMD - if [ $UPX ]; then - upx --brute $CMD - fi - done -fi + if [ $UPX ]; then + upx --brute $CMD + fi +done diff --git a/contrib/mobile/build b/contrib/mobile/build new file mode 100755 index 00000000..49fbd8f8 --- /dev/null +++ b/contrib/mobile/build @@ -0,0 +1,52 @@ +#!/bin/sh + +set -ef + +[ ! -d contrib/mobile ] && (echo "Must run contrib/mobile/build.sh [-i] [-a] from the repository top level folder"; exit 1) + +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)} + +LDFLAGS="-X $PKGSRC.buildName=$PKGNAME -X $PKGSRC.buildVersion=$PKGVER" +ARGS="-v" + +while getopts "aitc:l:d" option +do + case "$option" + in + i) IOS=true;; + a) ANDROID=true;; + t) TABLES=true;; + c) GCFLAGS="$GCFLAGS $OPTARG";; + l) LDFLAGS="$LDFLAGS $OPTARG";; + d) ARGS="$ARGS -tags debug" DEBUG=true;; + esac +done + +if [ -z $TABLES ] && [ -z $DEBUG ]; then + LDFLAGS="$LDFLAGS -s -w" +fi + +if [ ! $IOS ] && [ ! $ANDROID ]; then + echo "Must specify -a (Android), -i (iOS) or both" + exit 1 +fi + +if [ $IOS ]; then + echo "Building framework for iOS" + go get golang.org/x/mobile/bind + gomobile bind \ + -target ios -tags mobile -o Yggdrasil.xcframework \ + -ldflags="$LDFLAGS $STRIP" -gcflags="$GCFLAGS" \ + ./contrib/mobile ./src/config; +fi + +if [ $ANDROID ]; then + echo "Building aar for Android" + go get golang.org/x/mobile/bind + gomobile bind \ + -target android -tags mobile -o yggdrasil.aar \ + -ldflags="$LDFLAGS $STRIP" -gcflags="$GCFLAGS" \ + ./contrib/mobile ./src/config; +fi diff --git a/contrib/mobile/mobile.go b/contrib/mobile/mobile.go new file mode 100644 index 00000000..ba7cfdf6 --- /dev/null +++ b/contrib/mobile/mobile.go @@ -0,0 +1,178 @@ +package mobile + +import ( + "encoding/hex" + "encoding/json" + "fmt" + "net" + + "github.com/gologme/log" + + "github.com/yggdrasil-network/yggdrasil-go/src/address" + "github.com/yggdrasil-network/yggdrasil-go/src/config" + "github.com/yggdrasil-network/yggdrasil-go/src/core" + "github.com/yggdrasil-network/yggdrasil-go/src/defaults" + "github.com/yggdrasil-network/yggdrasil-go/src/ipv6rwc" + "github.com/yggdrasil-network/yggdrasil-go/src/multicast" + "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 +// Gomobile will not create headers for Swift/Obj-C etc if they have complex +// (non-native) types. Therefore for iOS we will expose some nice simple +// functions. Note that in the case of iOS we handle reading/writing to/from TUN +// in Swift therefore we use the "dummy" TUN interface instead. +type Yggdrasil struct { + core core.Core + iprwc *ipv6rwc.ReadWriteCloser + config *config.NodeConfig + multicast multicast.Multicast + log MobileLogger +} + +// StartAutoconfigure starts a node with a randomly generated config +func (m *Yggdrasil) StartAutoconfigure() error { + return m.StartJSON([]byte("{}")) +} + +// StartJSON starts a node with the given JSON config. You can get JSON config +// (rather than HJSON) by using the GenerateConfigJSON() function +func (m *Yggdrasil) StartJSON(configjson []byte) error { + logger := log.New(m.log, "", 0) + logger.EnableLevel("error") + logger.EnableLevel("warn") + logger.EnableLevel("info") + m.config = defaults.GenerateConfig() + if err := json.Unmarshal(configjson, &m.config); err != nil { + return err + } + m.config.IfName = "none" + if err := m.core.Start(m.config, logger); err != nil { + logger.Errorln("An error occured starting Yggdrasil:", err) + return err + } + mtu := m.config.IfMTU + m.iprwc = ipv6rwc.NewReadWriteCloser(&m.core) + if m.iprwc.MaxMTU() < mtu { + mtu = m.iprwc.MaxMTU() + } + m.iprwc.SetMTU(mtu) + if len(m.config.MulticastInterfaces) > 0 { + if err := m.multicast.Init(&m.core, m.config, logger, nil); err != nil { + logger.Errorln("An error occurred initialising multicast:", err) + return err + } + if err := m.multicast.Start(); err != nil { + logger.Errorln("An error occurred starting multicast:", err) + return err + } + } + return nil +} + +// Send sends a packet to Yggdrasil. It should be a fully formed +// IPv6 packet +func (m *Yggdrasil) Send(p []byte) error { + if m.iprwc == nil { + return nil + } + _, _ = m.iprwc.Write(p) + return nil +} + +// Recv waits for and reads a packet coming from Yggdrasil. It +// will be a fully formed IPv6 packet +func (m *Yggdrasil) Recv() ([]byte, error) { + if m.iprwc == nil { + return nil, nil + } + var buf [65535]byte + n, _ := m.iprwc.Read(buf[:]) + return buf[:n], nil +} + +// Stop the mobile Yggdrasil instance +func (m *Yggdrasil) Stop() error { + logger := log.New(m.log, "", 0) + logger.EnableLevel("info") + logger.Infof("Stop the mobile Yggdrasil instance %s", "") + if err := m.multicast.Stop(); err != nil { + return err + } + m.core.Stop() + return nil +} + +// GenerateConfigJSON generates mobile-friendly configuration in JSON format +func GenerateConfigJSON() []byte { + nc := defaults.GenerateConfig() + nc.IfName = "none" + if json, err := json.Marshal(nc); err == nil { + return json + } + return nil +} + +// GetAddressString gets the node's IPv6 address +func (m *Yggdrasil) GetAddressString() string { + ip := m.core.Address() + return ip.String() +} + +// GetSubnetString gets the node's IPv6 subnet in CIDR notation +func (m *Yggdrasil) GetSubnetString() string { + subnet := m.core.Subnet() + return subnet.String() +} + +// GetPublicKeyString gets the node's public key in hex form +func (m *Yggdrasil) GetPublicKeyString() string { + return hex.EncodeToString(m.core.GetSelf().Key) +} + +// GetCoordsString gets the node's coordinates +func (m *Yggdrasil) GetCoordsString() string { + return fmt.Sprintf("%v", m.core.GetSelf().Coords) +} + +func (m *Yggdrasil) GetPeersJSON() (result string) { + peers := []struct { + core.Peer + IP string + }{} + for _, v := range m.core.GetPeers() { + a := address.AddrForKey(v.Key) + ip := net.IP(a[:]).String() + peers = append(peers, struct { + core.Peer + IP string + }{ + Peer: v, + IP: ip, + }) + } + if res, err := json.Marshal(peers); err == nil { + return string(res) + } else { + return "{}" + } +} + +func (m *Yggdrasil) GetDHTJSON() (result string) { + if res, err := json.Marshal(m.core.GetDHT()); err == nil { + return string(res) + } else { + return "{}" + } +} + +// GetMTU returns the configured node MTU. This must be called AFTER Start. +func (m *Yggdrasil) GetMTU() int { + return int(m.core.MTU()) +} + +func GetVersion() string { + return version.BuildVersion() +} diff --git a/contrib/mobile/mobile_android.go b/contrib/mobile/mobile_android.go new file mode 100644 index 00000000..f3206aca --- /dev/null +++ b/contrib/mobile/mobile_android.go @@ -0,0 +1,12 @@ +// +build android + +package mobile + +import "log" + +type MobileLogger struct{} + +func (nsl MobileLogger) Write(p []byte) (n int, err error) { + log.Println(string(p)) + return len(p), nil +} diff --git a/contrib/mobile/mobile_ios.go b/contrib/mobile/mobile_ios.go new file mode 100644 index 00000000..253bbc0b --- /dev/null +++ b/contrib/mobile/mobile_ios.go @@ -0,0 +1,27 @@ +// +build ios + +package mobile + +/* +#cgo CFLAGS: -x objective-c +#cgo LDFLAGS: -framework Foundation +#import +void Log(const char *text) { + NSString *nss = [NSString stringWithUTF8String:text]; + NSLog(@"%@", nss); +} +*/ +import "C" +import ( + "unsafe" +) + +type MobileLogger struct { +} + +func (nsl MobileLogger) Write(p []byte) (n int, err error) { + p = append(p, 0) + cstr := (*C.char)(unsafe.Pointer(&p[0])) + C.Log(cstr) + return len(p), nil +} diff --git a/contrib/mobile/mobile_other.go b/contrib/mobile/mobile_other.go new file mode 100644 index 00000000..7b7ed74a --- /dev/null +++ b/contrib/mobile/mobile_other.go @@ -0,0 +1,13 @@ +// +build !android,!ios + +package mobile + +import "fmt" + +type MobileLogger struct { +} + +func (nsl MobileLogger) Write(p []byte) (n int, err error) { + fmt.Print(string(p)) + return len(p), nil +} diff --git a/contrib/mobile/mobile_test.go b/contrib/mobile/mobile_test.go new file mode 100644 index 00000000..19916407 --- /dev/null +++ b/contrib/mobile/mobile_test.go @@ -0,0 +1,16 @@ +package mobile + +import "testing" + +func TestStartYggdrasil(t *testing.T) { + ygg := &Yggdrasil{} + if err := ygg.StartAutoconfigure(); err != nil { + t.Fatalf("Failed to start Yggdrasil: %s", err) + } + t.Log("Address:", ygg.GetAddressString()) + t.Log("Subnet:", ygg.GetSubnetString()) + t.Log("Coords:", ygg.GetCoordsString()) + if err := ygg.Stop(); err != nil { + t.Fatalf("Failed to stop Yggdrasil: %s", err) + } +} diff --git a/go.mod b/go.mod index 398504cb..ac3ca589 100644 --- a/go.mod +++ b/go.mod @@ -18,8 +18,9 @@ require ( github.com/vishvananda/netlink v1.1.0 github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f // indirect golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a // indirect - golang.org/x/net v0.0.0-20210610132358-84b48f89b13b - golang.org/x/sys v0.0.0-20210611083646-a4fc73990273 + golang.org/x/mobile v0.0.0-20211103151657-e68c98865fb2 + golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d + golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e golang.org/x/text v0.3.7-0.20210503195748-5c7c50ebbd4f golang.zx2c4.com/wireguard v0.0.0-20210604143328-f9b48a961cd2 golang.zx2c4.com/wireguard/windows v0.3.14 diff --git a/go.sum b/go.sum index 5d11fad6..c295eacc 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,7 @@ github.com/Arceliar/ironwood v0.0.0-20210619124114-6ad55cae5031 h1:DZVDfYhVdu+0w github.com/Arceliar/ironwood v0.0.0-20210619124114-6ad55cae5031/go.mod h1:RP72rucOFm5udrnEzTmIWLRVGQiV/fSUAQXJ0RST/nk= github.com/Arceliar/phony v0.0.0-20210209235338-dde1a8dca979 h1:WndgpSW13S32VLQ3ugUxx2EnnWmgba1kCqPkd4Gk1yQ= github.com/Arceliar/phony v0.0.0-20210209235338-dde1a8dca979/go.mod h1:6Lkn+/zJilRMsKmbmG1RPoamiArC6HS73xbwRyp3UyI= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA= github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow= github.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4= @@ -38,18 +39,35 @@ github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYp 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/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= +golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20211103151657-e68c98865fb2 h1:SFpMH29/c2+VPCOcOlLPQiAVqU2sXiFvwfdtQfVEEJ8= +golang.org/x/mobile v0.0.0-20211103151657-e68c98865fb2/go.mod h1:pe2sM7Uk+2Su1y7u/6Z8KJ24D7lepUjFZbhFOrmDfuQ= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +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-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210610132358-84b48f89b13b h1:k+E048sYJHyVnsr1GDrRZWQ32D2C7lWs9JRc0bel53A= -golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d h1:20cMwl2fHAzkJMEA+8J4JgqBQcQGzbisXo31MIeenXI= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -62,8 +80,8 @@ golang.org/x/sys v0.0.0-20210309040221-94ec62e08169/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210611083646-a4fc73990273 h1:faDu4veV+8pcThn4fewv6TVlNCezafGoC1gM/mxQLbQ= -golang.org/x/sys v0.0.0-20210611083646-a4fc73990273/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e h1:WUoyKPm6nCo1BnNUvPGnFG3T5DUVem42yDJZZ4CNxMA= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -72,6 +90,14 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7-0.20210503195748-5c7c50ebbd4f h1:yQJrRE0hDxDFmZLlRaw+3vusO4fwNHgHIjUOMO7bHYI= golang.org/x/text v0.3.7-0.20210503195748-5c7c50ebbd4f/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.8-0.20211022200916-316ba0b74098 h1:YuekqPskqwCCPM79F1X5Dhv4ezTCj+Ki1oNwiafxkA0= +golang.org/x/tools v0.1.8-0.20211022200916-316ba0b74098/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.zx2c4.com/wireguard v0.0.0-20210510202332-9844c74f67ec/go.mod h1:a057zjmoc00UN7gVkaJt2sXVK523kMJcogDTEvPIasg= golang.zx2c4.com/wireguard v0.0.0-20210604143328-f9b48a961cd2 h1:wfOOSvHgIzTZ9h5Vb6yUFZNn7uf3bT7PeYsHOO7tYDM= golang.zx2c4.com/wireguard v0.0.0-20210604143328-f9b48a961cd2/go.mod h1:laHzsbfMhGSobUmruXWAyMKKHSqvIcrqZJMyHD+/3O8=