Compare commits
56 Commits
9c800af52e
...
fdc36b64ef
Author | SHA1 | Date | |
---|---|---|---|
|
fdc36b64ef | ||
|
13e1c1bbb4 | ||
|
0f75b1cbef | ||
|
07325dde93 | ||
|
fc2e21cfd6 | ||
|
af27264a03 | ||
|
ed7523c311 | ||
|
fe0c57fc09 | ||
|
971b8f2521 | ||
|
ab82f05a21 | ||
|
f835cdf1d6 | ||
|
ac71701d8c | ||
|
07f1eb855e | ||
|
8a9aa00289 | ||
|
bf58d46748 | ||
|
ab5bce1356 | ||
|
95fc74327d | ||
|
c3e79d839f | ||
|
996061b126 | ||
|
05a7b11ba6 | ||
|
681ccd815c | ||
|
0b55d8980c | ||
|
b2db10d68b | ||
|
fd975db6a5 | ||
|
92f746b23a | ||
|
7bc59a8b27 | ||
|
7cda93aeb3 | ||
|
c84c18cebf | ||
|
d8992e4412 | ||
|
d30f613622 | ||
|
86f32dc7d9 | ||
|
32f37d97d7 | ||
|
b39b137e20 | ||
|
a8a12cafc9 | ||
|
c97c321740 | ||
|
196e3f9fd7 | ||
|
caea507b86 | ||
|
db15477448 | ||
|
ce66287189 | ||
|
fb08bb280c | ||
|
e17be63d46 | ||
|
ff0020b47b | ||
|
b1ba13419d | ||
|
b1e9f5824b | ||
|
225c8e6abd | ||
|
f4dd972e54 | ||
|
7d936f4844 | ||
|
f52deeed03 | ||
|
40f8eb5b1b | ||
|
2ee2a943a7 | ||
|
e8a78c2eaa | ||
|
d747f1db5f | ||
|
ef7089dc61 | ||
|
2014da4ca3 | ||
|
593cd8c12d | ||
|
8dc93c66c4 |
12
.github/workflows/go.yml
vendored
12
.github/workflows/go.yml
vendored
@ -16,8 +16,8 @@ jobs:
|
||||
- name: Set up Go 1.x
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
# Run on the latest minor release of Go 1.14:
|
||||
go-version: ^1.14
|
||||
# Run on the latest minor release of Go 1.18:
|
||||
go-version: ^1.18
|
||||
id: go
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
@ -51,8 +51,8 @@ jobs:
|
||||
- name: Set up Go 1.x
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
# Run on the latest minor release of Go 1.14:
|
||||
go-version: ^1.14
|
||||
# Run on the latest minor release of Go 1.18:
|
||||
go-version: ^1.18
|
||||
id: go
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
@ -78,8 +78,8 @@ jobs:
|
||||
- name: Set up Go 1.x
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
# Run on the latest minor release of Go 1.14:
|
||||
go-version: ^1.14
|
||||
# Run on the latest minor release of Go 1.18:
|
||||
go-version: ^1.18
|
||||
id: go
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
|
48
Makefile
48
Makefile
@ -1,10 +1,19 @@
|
||||
SUDO=GOPATH=$(shell go env GOPATH) sudo --preserve-env=GOPATH
|
||||
SUDO=GOPATH=$(shell go env GOPATH) sudo --preserve-env=GOPATH --preserve-env=PATH --preserve-env=HOME
|
||||
|
||||
PKGS := github.com/rtr7/router7/cmd/... \
|
||||
github.com/gokrazy/breakglass \
|
||||
PKGS := github.com/gokrazy/breakglass \
|
||||
github.com/gokrazy/timestamps \
|
||||
github.com/stapelberg/zkj-nas-tools/wolgw \
|
||||
github.com/gokrazy/gdns
|
||||
github.com/gokrazy/gdns \
|
||||
github.com/gokrazy/serial-busybox \
|
||||
github.com/prometheus/node_exporter \
|
||||
github.com/gokrazy/fbstatus \
|
||||
github.com/gokrazy/iptables \
|
||||
github.com/gokrazy/nsenter \
|
||||
github.com/gokrazy/podman \
|
||||
github.com/greenpau/cni-plugins/cmd/cni-nftables-portmap \
|
||||
github.com/greenpau/cni-plugins/cmd/cni-nftables-firewall \
|
||||
github.com/gokrazy/syslogd/cmd/gokr-syslogd \
|
||||
github.com/gokrazy/stat/cmd/... \
|
||||
github.com/rtr7/router7/cmd/...
|
||||
|
||||
build:
|
||||
mkdir -p result
|
||||
@ -29,14 +38,13 @@ endif
|
||||
-overwrite_boot=${DIR}/boot.img \
|
||||
-overwrite_root=${DIR}/root.img \
|
||||
-overwrite_mbr=${DIR}/mbr.img \
|
||||
-serial_console=ttyS0,115200n8 \
|
||||
-serial_console=ttyS0,115200 \
|
||||
-hostname=router7 \
|
||||
${PKGS}
|
||||
|
||||
recover: #test
|
||||
go install \
|
||||
github.com/gokrazy/tools/cmd/gokr-packer@lastet \
|
||||
github.com/rtr7/tools/cmd/rtr7-recover@latest
|
||||
go install github.com/gokrazy/tools/cmd/gokr-packer@latest
|
||||
go install github.com/rtr7/tools/cmd/rtr7-recover@latest
|
||||
GOARCH=amd64 gokr-packer \
|
||||
-gokrazy_pkgs=github.com/gokrazy/gokrazy/cmd/ntp,github.com/gokrazy/gokrazy/cmd/randomd \
|
||||
-kernel_package=github.com/rtr7/kernel \
|
||||
@ -47,16 +55,19 @@ recover: #test
|
||||
-serial_console=ttyS0,115200n8 \
|
||||
-hostname=router7 \
|
||||
${PKGS}
|
||||
${SUDO} /home/michael/go/bin/rtr7-recover \
|
||||
-boot=/tmp/recovery/boot.img \
|
||||
-root=/tmp/recovery/root.img
|
||||
${SUDO} $(which rtr7-recover) \
|
||||
--boot /tmp/recovery/boot.img \
|
||||
--root /tmp/recovery/root.img \
|
||||
--mbr /tmp/recovery/mbr.img \
|
||||
--hostname router7 \
|
||||
--interface enp0s31f6
|
||||
|
||||
test:
|
||||
# simulate recover (quick, for early for feedback)
|
||||
go build ${PKGS} github.com/rtr7/tools/cmd/...
|
||||
go test -count=1 -v -race github.com/rtr7/router7/internal/...
|
||||
go build -mod=mod ${PKGS} github.com/rtr7/tools/cmd/...
|
||||
go test -mod=mod -count=1 -v -race github.com/rtr7/router7/internal/...
|
||||
# integration tests
|
||||
${SUDO} $(shell go env GOROOT)/bin/go test -count=1 -v -race github.com/rtr7/router7/...
|
||||
${SUDO} $(shell go env GOROOT)/bin/go test -buildvcs=false -count=1 -v -race github.com/rtr7/router7/...
|
||||
|
||||
testdhcp:
|
||||
go test -v -coverprofile=/tmp/cov github.com/rtr7/router7/internal/dhcp4d
|
||||
@ -70,15 +81,17 @@ strace:
|
||||
(cd /tmp && go test -c router7) && ${SUDO} strace -f -o /tmp/st -s 2048 /tmp/router7.test -test.v #-test.race
|
||||
|
||||
update:
|
||||
rtr7-safe-update -build_command='make -C ~/go/src/github.com/rtr7/router7 image DIR=$$GOKR_DIR'
|
||||
rtr7-safe-update -build_command='make image DIR=$$GOKR_DIR'
|
||||
|
||||
# sudo ip link add link enp0s31f6 name macvtap0 type macvtap
|
||||
# sudo ip link add link enp3s0 name macvtap0 type macvtap
|
||||
# sudo ip link set macvtap0 address 52:55:00:d1:55:03 up
|
||||
# sudo chown $USER /dev/tap*
|
||||
#
|
||||
# TODO: use veth pairs for router7’s lan0?
|
||||
# e.g. get a network namespace to talk through router7
|
||||
# ip link add dev veth1 type veth peer name veth2
|
||||
qemu:
|
||||
mkdir -p /tmp/router7-qemu
|
||||
GOARCH=amd64 gokr-packer \
|
||||
-gokrazy_pkgs=github.com/gokrazy/gokrazy/cmd/ntp,github.com/gokrazy/gokrazy/cmd/randomd \
|
||||
-hostname=qemu-router7 \
|
||||
@ -98,6 +111,7 @@ qemu:
|
||||
-device virtio-net-pci,netdev=uplink,mac=52:55:00:d1:55:03 \
|
||||
-device virtio-net-pci,id=lan,mac=52:55:00:d1:55:04 \
|
||||
-device i6300esb,id=watchdog0 -watchdog-action reset \
|
||||
-bios /usr/share/edk2-ovmf/x64/OVMF_CODE.fd \
|
||||
-smp 8 \
|
||||
-machine accel=kvm \
|
||||
-m 4096 \
|
||||
|
@ -51,7 +51,7 @@ func updateListeners() error {
|
||||
|
||||
func logic() error {
|
||||
http.HandleFunc("/backup.tar.gz", func(w http.ResponseWriter, r *http.Request) {
|
||||
if err := backup.Archive(w, *perm); err != nil {
|
||||
if err := backup.Archive(w, *perm, flag.Args()); err != nil {
|
||||
log.Printf("backup.tar.gz: %v", err)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ import (
|
||||
"github.com/google/gopacket/layers"
|
||||
"github.com/google/renameio"
|
||||
"github.com/jpillora/backoff"
|
||||
rtr7dhcp4 "github.com/rtr7/dhcp4"
|
||||
"github.com/rtr7/router7/internal/dhcp4"
|
||||
"github.com/rtr7/router7/internal/netconfig"
|
||||
"github.com/rtr7/router7/internal/notify"
|
||||
@ -136,15 +137,36 @@ func logic() error {
|
||||
Min: 10 * time.Second,
|
||||
Max: 1 * time.Minute,
|
||||
}
|
||||
var lastSuccess time.Time
|
||||
if st, err := os.Stat(ackFn); err == nil {
|
||||
lastSuccess = st.ModTime()
|
||||
}
|
||||
log.Printf("last success: %v", lastSuccess)
|
||||
ObtainOrRenew:
|
||||
for c.ObtainOrRenew() {
|
||||
if err := c.Err(); err != nil {
|
||||
dur := backoff.Duration()
|
||||
// Drop the lease if we do not get a reply from the DHCP server.
|
||||
// I observed this in practice where over a period of days,
|
||||
// the dhcp4 client would hang like this:
|
||||
//
|
||||
// dhcp4.go:140: Temporary error: DHCP: read packet
|
||||
// 42:66:f1:f1:bd:e7: i/o timeout (waiting 1m0s)
|
||||
//
|
||||
// For brief periods of time, we probably want to paper over such
|
||||
// issues, but after the lease expired, we should start the DHCP
|
||||
// exchange from scratch.
|
||||
if c.Ack != nil && time.Since(lastSuccess) > rtr7dhcp4.LeaseFromACK(c.Ack).RenewalTime {
|
||||
log.Printf("Temporary error: %v (dropping lease and retrying)", err)
|
||||
c.Ack = nil
|
||||
continue
|
||||
}
|
||||
log.Printf("Temporary error: %v (waiting %v)", err, dur)
|
||||
time.Sleep(dur)
|
||||
continue
|
||||
}
|
||||
backoff.Reset()
|
||||
lastSuccess = time.Now()
|
||||
log.Printf("lease: %+v", c.Config())
|
||||
b, err := json.Marshal(c.Config())
|
||||
if err != nil {
|
||||
@ -190,6 +212,7 @@ ObtainOrRenew:
|
||||
// Still not healthy? Drop DHCP lease and start from scratch.
|
||||
log.Printf("unhealthy for 5 cycles, starting over without lease")
|
||||
c.Ack = nil
|
||||
continue ObtainOrRenew
|
||||
|
||||
case <-usr2:
|
||||
log.Printf("SIGUSR2 received, sending DHCPRELEASE")
|
||||
|
@ -97,6 +97,9 @@ var (
|
||||
}
|
||||
return dur.Truncate(1 * time.Second).String()
|
||||
},
|
||||
"zero": func(t time.Time) bool {
|
||||
return t.IsZero()
|
||||
},
|
||||
}).Parse(`<!DOCTYPE html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
@ -156,8 +159,8 @@ form {
|
||||
<th>MAC address</th>
|
||||
<th>Vendor</th>
|
||||
<th>VendorIdentifier</th>
|
||||
<th>Start</th>
|
||||
<th>Expiry</th>
|
||||
<th>Last ACK</th>
|
||||
</tr>
|
||||
{{ range $idx, $l := . }}
|
||||
<tr>
|
||||
@ -174,18 +177,15 @@ form {
|
||||
<td class="hwaddr">{{$l.HardwareAddr}}</td>
|
||||
<td>{{$l.Vendor}}</td>
|
||||
<td>{{$l.VendorIdentifier}}</td>
|
||||
<td>{{$l.Start}}</td>
|
||||
<td title="{{ timefmt $l.Expiry }}">
|
||||
{{ if $l.Expired }}
|
||||
{{ since $l.Expiry }}
|
||||
<span class="expired">expired</span>
|
||||
{{ else }}
|
||||
{{ if $l.Static }}
|
||||
<span class="static">static</span>
|
||||
{{ else }}
|
||||
{{ timefmt $l.Expiry }}
|
||||
{{ if (not (zero $l.LastACK)) }}
|
||||
{{ timefmt $l.LastACK }}
|
||||
{{ if $l.Active }}
|
||||
<span class="active">active</span>
|
||||
{{ end }}
|
||||
{{ if $l.Expired }}
|
||||
<span class="expired">expired</span>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
</td>
|
||||
@ -193,10 +193,16 @@ form {
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
<h1>Static Leases</h1>
|
||||
<table cellpadding="0" cellspacing="0">
|
||||
{{ template "table" .StaticLeases }}
|
||||
</table>
|
||||
|
||||
<h1>Dynamic Leases</h1>
|
||||
<table cellpadding="0" cellspacing="0">
|
||||
{{ template "table" .DynamicLeases }}
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
`))
|
||||
@ -371,17 +377,20 @@ func newSrv(permDir string) (*srv, error) {
|
||||
Vendor string
|
||||
Expired bool
|
||||
Static bool
|
||||
Active bool
|
||||
}
|
||||
|
||||
leasesMu.Lock()
|
||||
defer leasesMu.Unlock()
|
||||
static := make([]tmplLease, 0, len(leases))
|
||||
dynamic := make([]tmplLease, 0, len(leases))
|
||||
now := time.Now()
|
||||
tl := func(l *dhcp4d.Lease) tmplLease {
|
||||
return tmplLease{
|
||||
Lease: *l,
|
||||
Vendor: ouiDB.Lookup(l.HardwareAddr[:8]),
|
||||
Expired: l.Expired(time.Now()),
|
||||
Expired: l.Expired(now),
|
||||
Active: l.Active(now),
|
||||
Static: l.Expiry.IsZero(),
|
||||
}
|
||||
}
|
||||
@ -444,7 +453,7 @@ func newSrv(permDir string) (*srv, error) {
|
||||
Addr: latest.Addr.String(),
|
||||
HardwareAddr: latest.HardwareAddr,
|
||||
Expiration: latest.Expiry.In(time.UTC),
|
||||
Start: latest.Start.In(time.UTC),
|
||||
Start: latest.LastACK.In(time.UTC),
|
||||
VendorIdentifier: latest.VendorIdentifier,
|
||||
}
|
||||
leaseJSON, err := json.Marshal(leaseVal)
|
||||
|
@ -80,44 +80,53 @@ func firstError(re *diag.EvalResult) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func graph(uplink string, ipv6 bool) *diag.Monitor {
|
||||
const ip6allrouters = "ff02::2" // no /etc/hosts on gokrazy
|
||||
graph := diag.Link(uplink).
|
||||
Then(diag.DHCPv4().
|
||||
Then(diag.Ping4Gateway().
|
||||
Then(diag.TCP4("www.google.com:80"))))
|
||||
|
||||
if ipv6 {
|
||||
graph = graph.
|
||||
Then(diag.DHCPv6().
|
||||
Then(diag.TCP6("lan0", "www.google.com:80"))).
|
||||
Then(diag.RouterAdvertisments(uplink).
|
||||
Then(diag.Ping6Gateway().
|
||||
Then(diag.TCP6(uplink, "www.google.com:80")))).
|
||||
Then(diag.Ping6("", ip6allrouters+"%"+uplink))
|
||||
}
|
||||
return diag.NewMonitor(graph)
|
||||
}
|
||||
|
||||
func logic() error {
|
||||
var (
|
||||
ifname = flag.String("interface",
|
||||
"uplink0",
|
||||
"interface name to query")
|
||||
ipv6 = flag.Bool("ipv6",
|
||||
true,
|
||||
"whether to expect IPv6 connectivity in health.json")
|
||||
perm = flag.String("perm",
|
||||
"/perm",
|
||||
"path to replace /perm")
|
||||
)
|
||||
const (
|
||||
ip6allrouters = "ff02::2" // no /etc/hosts on gokrazy
|
||||
)
|
||||
flag.Parse()
|
||||
uplink := *ifname
|
||||
diag.Perm = *perm
|
||||
m := diag.NewMonitor(diag.Link(uplink).
|
||||
Then(diag.DHCPv4().
|
||||
Then(diag.Ping4Gateway().
|
||||
Then(diag.Ping4("google.ch").
|
||||
Then(diag.TCP4("www.google.ch:80"))))).
|
||||
Then(diag.DHCPv6().
|
||||
Then(diag.Ping6("lan0", "google.ch"))).
|
||||
Then(diag.RouterAdvertisments(uplink).
|
||||
Then(diag.Ping6Gateway().
|
||||
Then(diag.Ping6(uplink, "google.ch").
|
||||
Then(diag.TCP6("www.google.ch:80"))))).
|
||||
Then(diag.Ping6("", ip6allrouters+"%"+uplink)))
|
||||
mHumanReadable := graph(uplink, true) // for display only
|
||||
mJSON := graph(uplink, *ipv6) // for updates
|
||||
var mu sync.Mutex
|
||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
mu.Lock()
|
||||
re := m.Evaluate()
|
||||
re := mHumanReadable.Evaluate()
|
||||
mu.Unlock()
|
||||
fmt.Fprintf(w, `<!DOCTYPE html><style type="text/css">ul { list-style-type: none; }</style><ul>`)
|
||||
dump(0, w, re)
|
||||
})
|
||||
http.HandleFunc("/health.json", func(w http.ResponseWriter, r *http.Request) {
|
||||
mu.Lock()
|
||||
re := m.Evaluate()
|
||||
re := mJSON.Evaluate()
|
||||
mu.Unlock()
|
||||
reply := struct {
|
||||
FirstError string `json:"first_error"`
|
||||
|
@ -47,6 +47,8 @@ var (
|
||||
|
||||
func init() {
|
||||
var c nftables.Conn
|
||||
filter4 := &nftables.Table{Family: nftables.TableFamilyIPv4, Name: "filter"}
|
||||
filter6 := &nftables.Table{Family: nftables.TableFamilyIPv6, Name: "filter"}
|
||||
for _, metric := range []struct {
|
||||
name string
|
||||
labels prometheus.Labels
|
||||
@ -56,18 +58,34 @@ func init() {
|
||||
{
|
||||
name: "filter_forward",
|
||||
labels: prometheus.Labels{"family": "ipv4"},
|
||||
obj: &nftables.CounterObj{
|
||||
Table: &nftables.Table{Family: nftables.TableFamilyIPv4, Name: "filter"},
|
||||
Name: "fwded",
|
||||
},
|
||||
obj: &nftables.CounterObj{Table: filter4, Name: "fwded"},
|
||||
},
|
||||
{
|
||||
name: "filter_forward",
|
||||
labels: prometheus.Labels{"family": "ipv6"},
|
||||
obj: &nftables.CounterObj{
|
||||
Table: &nftables.Table{Family: nftables.TableFamilyIPv6, Name: "filter"},
|
||||
Name: "fwded",
|
||||
},
|
||||
obj: &nftables.CounterObj{Table: filter6, Name: "fwded"},
|
||||
},
|
||||
|
||||
{
|
||||
name: "filter_input",
|
||||
labels: prometheus.Labels{"family": "ipv4"},
|
||||
obj: &nftables.CounterObj{Table: filter4, Name: "inputc"},
|
||||
},
|
||||
{
|
||||
name: "filter_input",
|
||||
labels: prometheus.Labels{"family": "ipv6"},
|
||||
obj: &nftables.CounterObj{Table: filter6, Name: "inputc"},
|
||||
},
|
||||
|
||||
{
|
||||
name: "filter_output",
|
||||
labels: prometheus.Labels{"family": "ipv4"},
|
||||
obj: &nftables.CounterObj{Table: filter4, Name: "outputc"},
|
||||
},
|
||||
{
|
||||
name: "filter_output",
|
||||
labels: prometheus.Labels{"family": "ipv6"},
|
||||
obj: &nftables.CounterObj{Table: filter6, Name: "outputc"},
|
||||
},
|
||||
} {
|
||||
metric := metric // copy
|
||||
@ -75,12 +93,11 @@ func init() {
|
||||
updateCounter := func() {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
objs, err := c.GetObjReset(metric.obj)
|
||||
if err != nil ||
|
||||
len(objs) != 1 {
|
||||
obj, err := c.ResetObject(metric.obj)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if co, ok := objs[0].(*nftables.CounterObj); ok {
|
||||
if co, ok := obj.(*nftables.CounterObj); ok {
|
||||
metric.packets += co.Packets
|
||||
metric.bytes += co.Bytes
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
<!DOCTYPE html>
|
||||
<html> <head>
|
||||
<meta name="generator" content="Hugo 0.71.0-DEV" />
|
||||
<meta name="generator" content="Hugo 0.106.0-DEV">
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
@ -44,7 +44,7 @@
|
||||
</nav>
|
||||
<h1 id="router7">router7</h1>
|
||||
<p>router7 is a pure-Go implementation of a small home internet router. It comes with all the services required to make a <a href="https://www.init7.net/en/internet/fiber7/">fiber7 internet connection</a> work (DHCPv4, DHCPv6, DNS, etc.).</p>
|
||||
<p>Note that this project should be considered a (working!) tech demo. Feature requests will likely not be implemented, and see <a href="CONTRIBUTING.md">CONTRIBUTING.md</a> for details about which contributions are welcome.</p>
|
||||
<p>Note that this project should be considered a (working!) tech demo. Feature requests will likely not be implemented, and see <a href="https://github.com/rtr7/router7/blob/master/CONTRIBUTING.md">CONTRIBUTING.md</a> for details about which contributions are welcome.</p>
|
||||
<h2 id="motivation">Motivation</h2>
|
||||
<p>Before starting router7, I was using the <a href="https://omnia.turris.cz/en/">Turris Omnia</a> router running OpenWrt. That worked fine up until May 2018, when an automated update pulled in a new version of <a href="https://git.openwrt.org/?p=project/odhcp6c.git;a=shortlog">odhcp6c</a>, OpenWrt’s DHCPv6 client. That version is incompatible with fiber7’s DHCP server setup (I think there are shortcomings on both sides).</p>
|
||||
<p>It was not only quicker to develop my own router than to wait for either side to resolve the issue, but it was also a lot of fun and allowed me to really tailor my router to my needs, experimenting with a bunch of interesting ideas I had.</p>
|
||||
|
@ -52,24 +52,45 @@
|
||||
<li>Press <code>s</code> to save configuration and exit</li>
|
||||
</ul>
|
||||
<p>Connect a network cable on <code>net0</code>, the port closest to the serial console port:</p>
|
||||
<p><img src="https://github.com/rtr7/router7/raw/master/devsetup.jpg"
|
||||
<p><img src="https://raw.githubusercontent.com/rtr7/router7/master/devsetup.jpg"
|
||||
width="800" alt="router7 development setup"></p>
|
||||
<p>Next, build a router7 image:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">go get -u github.com/gokrazy/tools/cmd/gokr-packer github.com/rtr7/tools/cmd/...
|
||||
go get -u -d github.com/rtr7/router7
|
||||
mkdir /tmp/recovery
|
||||
GOARCH<span style="color:#f92672">=</span>amd64 gokr-packer <span style="color:#ae81ff">\
|
||||
</span><span style="color:#ae81ff"></span> -hostname<span style="color:#f92672">=</span>router7 <span style="color:#ae81ff">\
|
||||
</span><span style="color:#ae81ff"></span> -overwrite_boot<span style="color:#f92672">=</span>/tmp/recovery/boot.img <span style="color:#ae81ff">\
|
||||
</span><span style="color:#ae81ff"></span> -overwrite_mbr<span style="color:#f92672">=</span>/tmp/recovery/mbr.img <span style="color:#ae81ff">\
|
||||
</span><span style="color:#ae81ff"></span> -overwrite_root<span style="color:#f92672">=</span>/tmp/recovery/root.img <span style="color:#ae81ff">\
|
||||
</span><span style="color:#ae81ff"></span> -eeprom_package<span style="color:#f92672">=</span> <span style="color:#ae81ff">\
|
||||
</span><span style="color:#ae81ff"></span> -kernel_package<span style="color:#f92672">=</span>github.com/rtr7/kernel <span style="color:#ae81ff">\
|
||||
</span><span style="color:#ae81ff"></span> -firmware_package<span style="color:#f92672">=</span>github.com/rtr7/kernel <span style="color:#ae81ff">\
|
||||
</span><span style="color:#ae81ff"></span> -gokrazy_pkgs<span style="color:#f92672">=</span>github.com/gokrazy/gokrazy/cmd/ntp <span style="color:#ae81ff">\
|
||||
</span><span style="color:#ae81ff"></span> -serial_console<span style="color:#f92672">=</span>ttyS0,115200n8 <span style="color:#ae81ff">\
|
||||
</span><span style="color:#ae81ff"></span> github.com/rtr7/router7/cmd/...
|
||||
</code></pre></div><p>Run <code>rtr7-recover -boot=/tmp/recovery/boot.img -mbr=/tmp/recovery/mbr.img -root=/tmp/recovery/root.img</code> to:</p>
|
||||
<p>Next, create a router7 gokrazy instance (see <a href="https://gokrazy.org/quickstart/">gokrazy
|
||||
quickstart</a> if you’re unfamiliar with gokrazy):</p>
|
||||
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>go install github.com/gokrazy/tools/cmd/gok@main
|
||||
</span></span><span style="display:flex;"><span>go install github.com/rtr7/tools/cmd/...@latest
|
||||
</span></span><span style="display:flex;"><span>mkdir /tmp/recovery
|
||||
</span></span><span style="display:flex;"><span>gok -i router7 new
|
||||
</span></span><span style="display:flex;"><span>gok -i router7 edit
|
||||
</span></span></code></pre></div><p>Change the config until you have the following fields set:</p>
|
||||
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672">"Hostname"</span>: <span style="color:#e6db74">"router7"</span>,
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672">"Packages"</span>: [
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#e6db74">"github.com/gokrazy/fbstatus"</span>,
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#e6db74">"github.com/gokrazy/hello"</span>,
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#e6db74">"github.com/gokrazy/serial-busybox"</span>,
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#e6db74">"github.com/gokrazy/breakglass"</span>
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#e6db74">"github.com/rtr7/router7/cmd/..."</span>
|
||||
</span></span><span style="display:flex;"><span> ],
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672">"SerialConsole"</span>: <span style="color:#e6db74">"ttyS0,115200"</span>,
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672">"GokrazyPackages"</span>: [
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#e6db74">"github.com/gokrazy/gokrazy/cmd/ntp"</span>,
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#e6db74">"github.com/gokrazy/gokrazy/cmd/randomd"</span>
|
||||
</span></span><span style="display:flex;"><span> ],
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672">"KernelPackage"</span>: <span style="color:#e6db74">"github.com/rtr7/kernel"</span>,
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672">"FirmwarePackage"</span>: <span style="color:#e6db74">"github.com/rtr7/kernel"</span>,
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672">"EEPROMPackage"</span>: <span style="color:#e6db74">""</span>
|
||||
</span></span><span style="display:flex;"><span>}
|
||||
</span></span></code></pre></div><p>Then, build an image:</p>
|
||||
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>GOARCH<span style="color:#f92672">=</span>amd64 gok -i router7 overwrite <span style="color:#ae81ff">\
|
||||
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span> --boot /tmp/recovery/boot.img <span style="color:#ae81ff">\
|
||||
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span> --mbr /tmp/recovery/mbr.img <span style="color:#ae81ff">\
|
||||
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span> --root /tmp/recovery/root.img
|
||||
</span></span></code></pre></div><p>And serve the image for netboot installation:</p>
|
||||
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>rtr7-recover <span style="color:#ae81ff">\
|
||||
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span> --boot /tmp/recovery/boot.img <span style="color:#ae81ff">\
|
||||
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span> --mbr /tmp/recovery/mbr.img <span style="color:#ae81ff">\
|
||||
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span> --root /tmp/recovery/root.img
|
||||
</span></span></code></pre></div><p>Specifically, <code>rtr7-recover</code>:</p>
|
||||
<ul>
|
||||
<li>trigger a reset <a href="#rebootor">if a Teensy with the rebootor firmware is attached</a></li>
|
||||
<li>serve a DHCP lease to all clients which request PXE boot (i.e., your apu2c4)</li>
|
||||
@ -88,41 +109,40 @@ GOARCH<span style="color:#f92672">=</span>amd64 gokr-packer <span style="color:#
|
||||
<h3 id="interfaces">Interfaces</h3>
|
||||
<p>The <code>/perm/interfaces.json</code> configuration file will be <a href="https://github.com/rtr7/tools/blob/57c2cdc3b629d2fbd13564ae37f6282f6ee8427f/cmd/rtr7-recovery-init/recoveryinit.go#L320">automatically created</a> if it is not present when you run the first recovery.</p>
|
||||
<p>Example:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-json" data-lang="json">{
|
||||
<span style="color:#f92672">"interfaces"</span>: [
|
||||
{
|
||||
<span style="color:#f92672">"hardware_addr"</span>: <span style="color:#e6db74">"12:34:56:78:9a:b0"</span>,
|
||||
<span style="color:#f92672">"name"</span>: <span style="color:#e6db74">"lan0"</span>,
|
||||
<span style="color:#f92672">"addr"</span>: <span style="color:#e6db74">"192.168.0.1/24"</span>
|
||||
},
|
||||
{
|
||||
<span style="color:#f92672">"hardware_addr"</span>: <span style="color:#e6db74">"12:34:56:78:9a:b2"</span>,
|
||||
<span style="color:#f92672">"name"</span>: <span style="color:#e6db74">"uplink0"</span>
|
||||
}
|
||||
]
|
||||
}
|
||||
</code></pre></div><p>Schema: see <a href="https://github.com/rtr7/router7/blob/f86e20be5305fc0e7e77421e0f2abde98a84f2a7/internal/netconfig/netconfig.go#L183"><code>InterfaceConfig</code></a></p>
|
||||
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672">"interfaces"</span>: [
|
||||
</span></span><span style="display:flex;"><span> {
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672">"hardware_addr"</span>: <span style="color:#e6db74">"12:34:56:78:9a:b0"</span>,
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672">"name"</span>: <span style="color:#e6db74">"lan0"</span>,
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672">"addr"</span>: <span style="color:#e6db74">"192.168.0.1/24"</span>
|
||||
</span></span><span style="display:flex;"><span> },
|
||||
</span></span><span style="display:flex;"><span> {
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672">"hardware_addr"</span>: <span style="color:#e6db74">"12:34:56:78:9a:b2"</span>,
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672">"name"</span>: <span style="color:#e6db74">"uplink0"</span>
|
||||
</span></span><span style="display:flex;"><span> }
|
||||
</span></span><span style="display:flex;"><span> ]
|
||||
</span></span><span style="display:flex;"><span>}
|
||||
</span></span></code></pre></div><p>Schema: see <a href="https://github.com/rtr7/router7/blob/f86e20be5305fc0e7e77421e0f2abde98a84f2a7/internal/netconfig/netconfig.go#L183"><code>InterfaceConfig</code></a></p>
|
||||
<h3 id="port-forwarding">Port Forwarding</h3>
|
||||
<p>The <code>/perm/portforwardings.json</code> configuration file can be created to define port forwarding rules.</p>
|
||||
<p>Example:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-json" data-lang="json">{
|
||||
<span style="color:#f92672">"forwardings"</span>: [
|
||||
{
|
||||
<span style="color:#f92672">"proto"</span>: <span style="color:#e6db74">"tcp"</span>,
|
||||
<span style="color:#f92672">"port"</span>: <span style="color:#e6db74">"22"</span>,
|
||||
<span style="color:#f92672">"dest_addr"</span>: <span style="color:#e6db74">"10.0.0.10"</span>,
|
||||
<span style="color:#f92672">"dest_port"</span>: <span style="color:#e6db74">"22"</span>
|
||||
},
|
||||
{
|
||||
<span style="color:#f92672">"proto"</span>: <span style="color:#e6db74">"tcp"</span>,
|
||||
<span style="color:#f92672">"port"</span>: <span style="color:#e6db74">"80"</span>,
|
||||
<span style="color:#f92672">"dest_addr"</span>: <span style="color:#e6db74">"10.0.0.10"</span>,
|
||||
<span style="color:#f92672">"dest_port"</span>: <span style="color:#e6db74">"80"</span>
|
||||
}
|
||||
]
|
||||
}
|
||||
</code></pre></div><p>Schema: see <a href="https://github.com/rtr7/router7/blob/f86e20be5305fc0e7e77421e0f2abde98a84f2a7/internal/netconfig/netconfig.go#L431"><code>portForwardings</code></a></p>
|
||||
<p>Please be aware that Hairpinning is currently not supported (see issue <a href="https://github.com/rtr7/router7/issues/53%5D">#53 Support for Hairpinning</a>)</p>
|
||||
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672">"forwardings"</span>: [
|
||||
</span></span><span style="display:flex;"><span> {
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672">"proto"</span>: <span style="color:#e6db74">"tcp"</span>,
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672">"port"</span>: <span style="color:#e6db74">"22"</span>,
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672">"dest_addr"</span>: <span style="color:#e6db74">"10.0.0.10"</span>,
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672">"dest_port"</span>: <span style="color:#e6db74">"22"</span>
|
||||
</span></span><span style="display:flex;"><span> },
|
||||
</span></span><span style="display:flex;"><span> {
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672">"proto"</span>: <span style="color:#e6db74">"tcp"</span>,
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672">"port"</span>: <span style="color:#e6db74">"80"</span>,
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672">"dest_addr"</span>: <span style="color:#e6db74">"10.0.0.10"</span>,
|
||||
</span></span><span style="display:flex;"><span> <span style="color:#f92672">"dest_port"</span>: <span style="color:#e6db74">"80"</span>
|
||||
</span></span><span style="display:flex;"><span> }
|
||||
</span></span><span style="display:flex;"><span> ]
|
||||
</span></span><span style="display:flex;"><span>}
|
||||
</span></span></code></pre></div><p>Schema: see <a href="https://github.com/rtr7/router7/blob/f86e20be5305fc0e7e77421e0f2abde98a84f2a7/internal/netconfig/netconfig.go#L431"><code>portForwardings</code></a></p>
|
||||
<h2 id="updates">Updates</h2>
|
||||
<p>Run e.g. <code>rtr7-safe-update -updates_dir=$HOME/router7/updates</code> to:</p>
|
||||
<ul>
|
||||
@ -137,9 +157,9 @@ GOARCH<span style="color:#f92672">=</span>amd64 gokr-packer <span style="color:#
|
||||
<p>Given <code>rtr7-safe-update</code>’s safeguards, manual recovery should rarely be required.</p>
|
||||
<p>To manually roll back to an older image, invoke <code>rtr7-safe-update</code> via the
|
||||
<code>recover.bash</code> script in the image directory underneath <code>-updates_dir</code>, e.g.:</p>
|
||||
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">% cd ~/router7/updates/2018-07-03T17:33:52+02:00
|
||||
% ./recover.bash
|
||||
</code></pre></div><h2 id="rebootor">Teensy rebootor</h2>
|
||||
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>% cd ~/router7/updates/2018-07-03T17:33:52+02:00
|
||||
</span></span><span style="display:flex;"><span>% ./recover.bash
|
||||
</span></span></code></pre></div><h2 id="rebootor">Teensy rebootor</h2>
|
||||
<p>The cheap and widely-available <a href="https://www.pjrc.com/store/teensypp.html">Teensy++ USB development board</a> comes with a firmware called rebootor, which is used by the <a href="https://www.pjrc.com/teensy/loader_cli.html"><code>teensy_loader_cli</code></a> program to perform hard resets.</p>
|
||||
<p>This setup can be used to programmatically reset the apu2c4 (from <code>rtr7-recover</code>) by connecting the Teensy++ to the <a href="http://pcengines.ch/pdf/apu2.pdf">apu2c4’s reset pins</a>:</p>
|
||||
<ul>
|
||||
|
@ -1,17 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
|
||||
xmlns:xhtml="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<url>
|
||||
<loc>https://router7.org/</loc>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
</url><url>
|
||||
<loc>https://router7.org/architecture/</loc>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
</url><url>
|
||||
<loc>https://router7.org/installation/</loc>
|
||||
</url>
|
||||
|
||||
</urlset>
|
||||
</urlset>
|
||||
|
78
go.mod
78
go.mod
@ -1,39 +1,63 @@
|
||||
module github.com/rtr7/router7
|
||||
|
||||
go 1.13
|
||||
go 1.21
|
||||
|
||||
toolchain go1.22.2
|
||||
|
||||
require (
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883
|
||||
github.com/digineo/go-ping v1.0.1
|
||||
github.com/eclipse/paho.mqtt.golang v1.3.4
|
||||
github.com/gokrazy/gokrazy v0.0.0-20220221222403-63413ccafb12
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/google/go-cmp v0.5.7
|
||||
github.com/eclipse/paho.mqtt.golang v1.4.1
|
||||
github.com/gokrazy/gokrazy v0.0.0-20230812092215-346db1998f83
|
||||
github.com/google/go-cmp v0.6.0
|
||||
github.com/google/gopacket v1.1.19
|
||||
github.com/google/nftables v0.0.0-20210514154851-a285acebcad3
|
||||
github.com/google/nftables v0.2.1-0.20240422065334-aa8348f7904c
|
||||
github.com/google/renameio v1.0.1
|
||||
github.com/insomniacslk/dhcp v0.0.0-20210528123148-fb4eaaa00ad2
|
||||
github.com/insomniacslk/dhcp v0.0.0-20220822114210-de18a9d48e84
|
||||
github.com/jpillora/backoff v1.0.0
|
||||
github.com/kr/pretty v0.2.1 // indirect
|
||||
github.com/krolaw/dhcp4 v0.0.0-20190909130307-a50d88189771
|
||||
github.com/libdns/cloudflare v0.1.0
|
||||
github.com/libdns/libdns v0.2.0
|
||||
github.com/mdlayher/ndp v0.0.0-20200602162440-17ab9e3e5567
|
||||
github.com/mdlayher/netlink v1.6.0 // indirect
|
||||
github.com/mdlayher/packet v1.0.0
|
||||
github.com/miekg/dns v1.1.42
|
||||
github.com/prometheus/client_golang v1.10.0
|
||||
github.com/prometheus/common v0.25.0 // indirect
|
||||
github.com/rtr7/dhcp4 v0.0.0-20220221221838-73f36ca31019
|
||||
github.com/sergi/go-diff v1.1.0 // indirect
|
||||
github.com/u-root/uio v0.0.0-20210528151154-e40b768296a7 // indirect
|
||||
github.com/vishvananda/netlink v1.1.1-0.20200221165523-c79a4b7b4066
|
||||
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f // indirect
|
||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158
|
||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba
|
||||
golang.zx2c4.com/wireguard v0.0.20201118 // indirect
|
||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20210506160403-92e472f520a5
|
||||
github.com/libdns/libdns v0.2.1
|
||||
github.com/mdlayher/ethtool v0.1.0
|
||||
github.com/mdlayher/ndp v0.10.0
|
||||
github.com/mdlayher/packet v1.1.2
|
||||
github.com/miekg/dns v1.1.50
|
||||
github.com/prometheus/client_golang v1.19.0
|
||||
github.com/rtr7/dhcp4 v0.0.0-20220302171438-18c84d089b46
|
||||
github.com/vishvananda/netlink v1.2.1-beta.2
|
||||
github.com/vishvananda/netns v0.0.4
|
||||
golang.org/x/crypto v0.31.0
|
||||
golang.org/x/net v0.23.0
|
||||
golang.org/x/sync v0.7.0
|
||||
golang.org/x/sys v0.28.0
|
||||
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9
|
||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20220504211119-3d4a969bb56b
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/digineo/go-logwrap v0.0.0-20181106161722-a178c58ea3f0 // indirect
|
||||
github.com/gokrazy/internal v0.0.0-20230211171410-9608422911d0 // indirect
|
||||
github.com/google/renameio/v2 v2.0.0 // indirect
|
||||
github.com/gorilla/websocket v1.4.2 // indirect
|
||||
github.com/josharian/native v1.1.0 // indirect
|
||||
github.com/kenshaw/evdev v0.1.0 // indirect
|
||||
github.com/mdlayher/genetlink v1.3.2 // indirect
|
||||
github.com/mdlayher/netlink v1.7.2 // indirect
|
||||
github.com/mdlayher/socket v0.5.0 // indirect
|
||||
github.com/mdlayher/watchdog v0.0.0-20221003142519-49be0df7b3b5 // indirect
|
||||
github.com/prometheus/client_model v0.6.1 // indirect
|
||||
github.com/prometheus/common v0.53.0 // indirect
|
||||
github.com/prometheus/procfs v0.14.0 // indirect
|
||||
github.com/sergi/go-diff v1.2.0 // indirect
|
||||
github.com/stretchr/objx v0.2.0 // indirect
|
||||
github.com/u-root/uio v0.0.0-20210528114334-82958018845c // indirect
|
||||
gitlab.com/golang-commonmark/puny v0.0.0-20191124015043-9f83538fa04f // indirect
|
||||
golang.org/x/mod v0.5.1 // indirect
|
||||
golang.org/x/tools v0.1.8 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
golang.zx2c4.com/wireguard v0.0.0-20220407013110-ef5c587f782d // indirect
|
||||
google.golang.org/protobuf v1.33.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
577
go.sum
577
go.sum
@ -1,618 +1,221 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
||||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
|
||||
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
||||
github.com/anatol/vmtest v0.0.0-20210623221036-69fc760fbd4b/go.mod h1:l08qtd2JHjoYWIROnbKoKCUqIbe54ndrXwDdyiDfq30=
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ=
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
|
||||
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A=
|
||||
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
|
||||
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
|
||||
github.com/beevik/ntp v0.2.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
||||
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
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=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/digineo/go-logwrap v0.0.0-20181106161722-a178c58ea3f0 h1:OT/LKmj81wMymnWXaKaKBR9n1vPlu+GC0VVKaZP6kzs=
|
||||
github.com/digineo/go-logwrap v0.0.0-20181106161722-a178c58ea3f0/go.mod h1:DmqdumeAKGQNU5E8MN0ruT5ZGx8l/WbAsMbXCXcSEts=
|
||||
github.com/digineo/go-ping v1.0.1 h1:Yn9hwM0RY4j4D3gcmLvRJf0d7MrbucfUhnOeVDvcVyk=
|
||||
github.com/digineo/go-ping v1.0.1/go.mod h1:uCbFC0VUqGNBNiev44BGSxfOrEAmC73GjpRje1l40Zo=
|
||||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||
github.com/eclipse/paho.mqtt.golang v1.3.4 h1:/sS2PA+PgomTO1bfJSDJncox+U7X5Boa3AfhEywYdgI=
|
||||
github.com/eclipse/paho.mqtt.golang v1.3.4/go.mod h1:eTzb4gxwwyWpqBUHGQZ4ABAV7+Jgm1PklsYT/eo8Hcc=
|
||||
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
||||
github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/eclipse/paho.mqtt.golang v1.4.1 h1:tUSpviiL5G3P9SZZJPC4ZULZJsxQKXxfENpMvdbAXAI=
|
||||
github.com/eclipse/paho.mqtt.golang v1.4.1/go.mod h1:JGt0RsEwEX+Xa/agj90YJ9d9DH2b7upDZMK9HRbFvCA=
|
||||
github.com/fanliao/go-promise v0.0.0-20141029170127-1890db352a72/go.mod h1:PjfxuH4FZdUyfMdtBio2lsRr1AKEaVPwelzuHuh8Lqc=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
||||
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
|
||||
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
|
||||
github.com/gdamore/tcell/v2 v2.0.1-0.20201017141208-acf90d56d591/go.mod h1:vSVL/GV5mCSlPC6thFP5kfOFdM9MGZcalipmpTxTgQA=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/gokrazy/gokrazy v0.0.0-20220221222403-63413ccafb12 h1:QpileHiicO1opWEJN63vWdm6Cw+Ow4haC1P8YHXMSQo=
|
||||
github.com/gokrazy/gokrazy v0.0.0-20220221222403-63413ccafb12/go.mod h1:lhYUrZe1PD+q/MhoNMVoKm9F3CsE64oQhaOyoeB8qdU=
|
||||
github.com/gokrazy/internal v0.0.0-20220111191949-698f19a074ef h1:ymGWpZu9Ug4lTMlVslD+iB6K+zvSqh93sHKx/kyPwlw=
|
||||
github.com/gokrazy/internal v0.0.0-20220111191949-698f19a074ef/go.mod h1:Gc9sU6yJ/qxg3gJZ1pjfcTAULa0swdTa4TH51g1e00E=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/gokrazy/gokrazy v0.0.0-20230812092215-346db1998f83 h1:Y4sADvUYd/c0eqnqebipHHl0GMpAxOQeTzPnwI4ievM=
|
||||
github.com/gokrazy/gokrazy v0.0.0-20230812092215-346db1998f83/go.mod h1:9q5Tg+q+YvRjC3VG0gfMFut46dhbhtAnvUEp4lPjc6c=
|
||||
github.com/gokrazy/internal v0.0.0-20230211171410-9608422911d0 h1:QTi0skQ/OM7he/5jEWA9k/DYgdwGAhw3hrUoiPGGZHM=
|
||||
github.com/gokrazy/internal v0.0.0-20230211171410-9608422911d0/go.mod h1:ddHcxXZ/VVQOSAWcRBbkYY58+QOw4L145ye6phyDmRA=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
|
||||
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
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/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
|
||||
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
|
||||
github.com/google/nftables v0.0.0-20210514154851-a285acebcad3 h1:jv+t8JqcvaSeB0r4u3356q7RE5tagFbVC0Bi1x13YFc=
|
||||
github.com/google/nftables v0.0.0-20210514154851-a285acebcad3/go.mod h1:cfspEyr/Ap+JDIITA+N9a0ernqG0qZ4W1aqMRgDZa1g=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/nftables v0.2.1-0.20240422065334-aa8348f7904c h1:XJHEjE/d9/F9Sp6hvRCfh6Sl4WtCoKx7JJI2z1trH/Y=
|
||||
github.com/google/nftables v0.2.1-0.20240422065334-aa8348f7904c/go.mod h1:Fo/xFnOxWlRQtnHdNi46KbIjufTDzbKhtghpWrmsSUg=
|
||||
github.com/google/renameio v1.0.1 h1:Lh/jXZmvZxb0BBeSY5VKEfidcbcbenKjZFzM/q0fSeU=
|
||||
github.com/google/renameio v1.0.1/go.mod h1:t/HQoYBZSsWSNK35C6CO/TpPLDVWvxOHboWUAweKUpk=
|
||||
github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg=
|
||||
github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4=
|
||||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
|
||||
github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
|
||||
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
|
||||
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
|
||||
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
||||
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
||||
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
|
||||
github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714/go.mod h1:2Goc3h8EklBH5mspfHFxBnEoURQCGzQQH1ga9Myjvis=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20210528123148-fb4eaaa00ad2 h1:WDOgJoE6rb7G6A7i1/Yyh5FJeydXeUrXHMRYJo7iFak=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20210528123148-fb4eaaa00ad2/go.mod h1:h+MxyHxRg9NH3terB1nfRIUaQEcI0XOVkdR9LNBlp8E=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/josharian/native v0.0.0-20200817173448-b6b71def0850/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
||||
github.com/josharian/native v1.0.0 h1:Ts/E8zCSEsG17dUqv7joXJFybuMLjQfWE04tsBODTxk=
|
||||
github.com/josharian/native v1.0.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20220822114210-de18a9d48e84 h1:MJTy6H+EpXLeAn0P5WAWeLk6dJA3V0ik6S3VJfUyQuI=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20220822114210-de18a9d48e84/go.mod h1:h+MxyHxRg9NH3terB1nfRIUaQEcI0XOVkdR9LNBlp8E=
|
||||
github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=
|
||||
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
||||
github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=
|
||||
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
|
||||
github.com/jsimonetti/rtnetlink v0.0.0-20190606172950-9527aa82566a/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw=
|
||||
github.com/jsimonetti/rtnetlink v0.0.0-20200117123717-f846d4f6c1f4/go.mod h1:WGuG/smIU4J/54PblvSbh+xvCZmpJnFgr3ds6Z55XMQ=
|
||||
github.com/jsimonetti/rtnetlink v0.0.0-20201009170750-9c6f07d100c1/go.mod h1:hqoO/u39cqLeBLebZ8fWdE96O7FxrAsRYhnVOdgHxok=
|
||||
github.com/jsimonetti/rtnetlink v0.0.0-20201110080708-d2c240429e6c/go.mod h1:huN4d1phzjhlOsNIjFsw2SVRbwIHj3fJDMEU2SDPTmg=
|
||||
github.com/jsimonetti/rtnetlink v0.0.0-20201216134343-bde56ed16391/go.mod h1:cR77jAZG3Y3bsb8hF6fHJbFoyFukLFOkQ98S0pQz3xw=
|
||||
github.com/jsimonetti/rtnetlink v0.0.0-20201220180245-69540ac93943/go.mod h1:z4c53zj6Eex712ROyh8WI0ihysb5j2ROyV42iNogmAs=
|
||||
github.com/jsimonetti/rtnetlink v0.0.0-20210122163228-8d122574c736/go.mod h1:ZXpIyOK59ZnN7J0BV99cZUPmsqDRZ3eq5X+st7u/oSA=
|
||||
github.com/jsimonetti/rtnetlink v0.0.0-20210212075122-66c871082f2b/go.mod h1:8w9Rh8m+aHZIG69YPGGem1i5VzoyRC8nw2kA8B+ik5U=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/koneu/natend v0.0.0-20150829182554-ec0926ea948d h1:MFX8DxRnKMY/2M3H61iSsVbo/n3h0MWGmWNN1UViOU0=
|
||||
github.com/koneu/natend v0.0.0-20150829182554-ec0926ea948d/go.mod h1:QHb4k4cr1fQikUahfcRVPcEXiUgFsdIstGqlurL0XL4=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kenshaw/evdev v0.1.0 h1:wmtceEOFfilChgdNT+c/djPJ2JineVsQ0N14kGzFRUo=
|
||||
github.com/kenshaw/evdev v0.1.0/go.mod h1:B/fErKCihUyEobz0mjn2qQbHgyJKFQAxkXSvkeeA/Wo=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/krolaw/dhcp4 v0.0.0-20190909130307-a50d88189771 h1:t2c2B9g1ZVhMYduqmANSEGVD3/1WlsrEYNPtVoFlENk=
|
||||
github.com/krolaw/dhcp4 v0.0.0-20190909130307-a50d88189771/go.mod h1:0AqAH3ZogsCrvrtUpvc6EtVKbc3w6xwZhkvGLuqyi3o=
|
||||
github.com/libdns/cloudflare v0.1.0 h1:93WkJaGaiXCe353LHEP36kAWCUw0YjFqwhkBkU2/iic=
|
||||
github.com/libdns/cloudflare v0.1.0/go.mod h1:a44IP6J1YH6nvcNl1PverfJviADgXUnsozR3a7vBKN8=
|
||||
github.com/libdns/libdns v0.2.0 h1:ewg3ByWrdUrxrje8ChPVMBNcotg7H9LQYg+u5De2RzI=
|
||||
github.com/libdns/libdns v0.2.0/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40=
|
||||
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
|
||||
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
|
||||
github.com/libdns/libdns v0.2.1 h1:Wu59T7wSHRgtA0cfxC+n1c/e+O3upJGWytknkmFEDis=
|
||||
github.com/libdns/libdns v0.2.1/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40=
|
||||
github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7/go.mod h1:U6ZQobyTjI/tJyq2HG+i/dfSoFUt8/aZCM+GKtmFk/Y=
|
||||
github.com/mdlayher/ethtool v0.0.0-20210210192532-2b88debcdd43/go.mod h1:+t7E0lkKfbBsebllff1xdTmyJt8lH37niI6kwFk9OTo=
|
||||
github.com/mdlayher/genetlink v1.0.0 h1:OoHN1OdyEIkScEmRgxLEe2M9U8ClMytqA5niynLtfj0=
|
||||
github.com/mdlayher/genetlink v1.0.0/go.mod h1:0rJ0h4itni50A86M2kHcgS85ttZazNt7a8H2a2cw0Gc=
|
||||
github.com/mdlayher/ndp v0.0.0-20200602162440-17ab9e3e5567 h1:x+xs91ZJ+lr0C6sedWeREvck4uGCt+AA1kKXwsHB6jI=
|
||||
github.com/mdlayher/ndp v0.0.0-20200602162440-17ab9e3e5567/go.mod h1:32w/5dDZWVSEOxyniAgKK4d7dHTuO6TCxWmUznQe3f8=
|
||||
github.com/mdlayher/ethtool v0.1.0 h1:XAWHsmKhyPOo42qq/yTPb0eFBGUKKTR1rE0dVrWVQ0Y=
|
||||
github.com/mdlayher/ethtool v0.1.0/go.mod h1:fBMLn2UhfRGtcH5ZFjr+6GUiHEjZsItFD7fSn7jbZVQ=
|
||||
github.com/mdlayher/genetlink v1.3.2 h1:KdrNKe+CTu+IbZnm/GVUMXSqBBLqcGpRDa0xkQy56gw=
|
||||
github.com/mdlayher/genetlink v1.3.2/go.mod h1:tcC3pkCrPUGIKKsCsp0B3AdaaKuHtaxoJRz3cc+528o=
|
||||
github.com/mdlayher/ndp v0.10.0 h1:Zdwol2bq1EHY8xSnejIYkq6LEj7dLjLymJX0o/2tjGw=
|
||||
github.com/mdlayher/ndp v0.10.0/go.mod h1:Uv6IWvgvqirNUu2N3ZXJEB86xu6foyUsG0NrClSSfek=
|
||||
github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA=
|
||||
github.com/mdlayher/netlink v0.0.0-20191009155606-de872b0d824b/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M=
|
||||
github.com/mdlayher/netlink v1.0.0/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M=
|
||||
github.com/mdlayher/netlink v1.1.0/go.mod h1:H4WCitaheIsdF9yOYu8CFmCgQthAPIWZmcKp9uZHgmY=
|
||||
github.com/mdlayher/netlink v1.1.1/go.mod h1:WTYpFb/WTvlRJAyKhZL5/uy69TDDpHHu2VZmb2XgV7o=
|
||||
github.com/mdlayher/netlink v1.2.0/go.mod h1:kwVW1io0AZy9A1E2YYgaD4Cj+C+GPkU6klXCMzIJ9p8=
|
||||
github.com/mdlayher/netlink v1.2.1/go.mod h1:bacnNlfhqHqqLo4WsYeXSqfyXkInQ9JneWI68v1KwSU=
|
||||
github.com/mdlayher/netlink v1.2.2-0.20210123213345-5cc92139ae3e/go.mod h1:bacnNlfhqHqqLo4WsYeXSqfyXkInQ9JneWI68v1KwSU=
|
||||
github.com/mdlayher/netlink v1.3.0/go.mod h1:xK/BssKuwcRXHrtN04UBkwQ6dY9VviGGuriDdoPSWys=
|
||||
github.com/mdlayher/netlink v1.4.0/go.mod h1:dRJi5IABcZpBD2A3D0Mv/AiX8I9uDEu5oGkAVrekmf8=
|
||||
github.com/mdlayher/netlink v1.6.0 h1:rOHX5yl7qnlpiVkFWoqccueppMtXzeziFjWAjLg6sz0=
|
||||
github.com/mdlayher/netlink v1.6.0/go.mod h1:0o3PlBmGst1xve7wQ7j/hwpNaFaH4qCRyWCdcZk8/vA=
|
||||
github.com/mdlayher/packet v0.0.0-20220221164757-67998ac0ff93/go.mod h1:K9sWKMgN6wa78BbuJL+dT1ZZdiAfhkc2fb6XXLjHulk=
|
||||
github.com/mdlayher/packet v1.0.0 h1:InhZJbdShQYt6XV2GPj5XHxChzOfhJJOMbvnGAmOfQ8=
|
||||
github.com/mdlayher/packet v1.0.0/go.mod h1:eE7/ctqDhoiRhQ44ko5JZU2zxB88g+JH/6jmnjzPjOU=
|
||||
github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g=
|
||||
github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw=
|
||||
github.com/mdlayher/packet v1.1.2 h1:3Up1NG6LZrsgDVn6X4L9Ge/iyRyxFEFD9o6Pr3Q1nQY=
|
||||
github.com/mdlayher/packet v1.1.2/go.mod h1:GEu1+n9sG5VtiRE4SydOmX5GTwyyYlteZiFU+x0kew4=
|
||||
github.com/mdlayher/raw v0.0.0-20190606142536-fef19f00fc18/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg=
|
||||
github.com/mdlayher/raw v0.0.0-20191009151244-50f2db8cc065/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg=
|
||||
github.com/mdlayher/raw v0.1.0 h1:K4PFMVy+AFsp0Zdlrts7yNhxc/uXoPVHi9RzRvtZF2Y=
|
||||
github.com/mdlayher/raw v0.1.0/go.mod h1:yXnxvs6c0XoF/aK52/H5PjsVHmWBCFfZUfoh/Y5s9Sg=
|
||||
github.com/mdlayher/socket v0.1.1/go.mod h1:mYV5YIZAfHh4dzDVzI8x8tWLWCliuX8Mon5Awbj+qDs=
|
||||
github.com/mdlayher/socket v0.2.1 h1:F2aaOwb53VsBE+ebRS9bLd7yPOfYUMC8lOODdCBDY6w=
|
||||
github.com/mdlayher/socket v0.2.1/go.mod h1:QLlNPkFR88mRUNQIzRBMfXxwKal8H7u1h3bL1CV+f0E=
|
||||
github.com/mdlayher/watchdog v0.0.0-20201005150459-8bdc4f41966b h1:7tUBfsEEBWfFeHOB7CUfoOamak+Gx/BlirfXyPk1WjI=
|
||||
github.com/mdlayher/watchdog v0.0.0-20201005150459-8bdc4f41966b/go.mod h1:bmoJUS6qOA3uKFvF3KVuhf7mU1KQirzQMeHXtPyKEqg=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/miekg/dns v1.1.42 h1:gWGe42RGaIqXQZ+r3WUGEKBEtvPHY2SXo4dqixDNxuY=
|
||||
github.com/miekg/dns v1.1.42/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4=
|
||||
github.com/mdlayher/socket v0.5.0 h1:ilICZmJcQz70vrWVes1MFera4jGiWNocSkykwwoy3XI=
|
||||
github.com/mdlayher/socket v0.5.0/go.mod h1:WkcBFfvyG8QENs5+hfQPl1X6Jpd2yeLIYgrGFmJiJxI=
|
||||
github.com/mdlayher/watchdog v0.0.0-20221003142519-49be0df7b3b5 h1:80FAK3TW5lVymfHu3kvB1QvTZvy9Kmx1lx6sT5Ep16s=
|
||||
github.com/mdlayher/watchdog v0.0.0-20221003142519-49be0df7b3b5/go.mod h1:z0QjVpjpK4jksEkffQwS3+abQ3XFTm1bnimyDzWyUk0=
|
||||
github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
|
||||
github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
|
||||
github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721 h1:RlZweED6sbSArvlE924+mUcZuXKLBHA35U7LN621Bws=
|
||||
github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721/go.mod h1:Ickgr2WtCLZ2MDGd4Gr0geeCH5HybhRJbonOgQpvSxc=
|
||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
|
||||
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
|
||||
github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
|
||||
github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k=
|
||||
github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w=
|
||||
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
||||
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
|
||||
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
|
||||
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
||||
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
|
||||
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
|
||||
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA=
|
||||
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
|
||||
github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
|
||||
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
|
||||
github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
||||
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
|
||||
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
|
||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
|
||||
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/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
|
||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
|
||||
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
||||
github.com/prometheus/client_golang v1.10.0 h1:/o0BDeWzLWXNZ+4q5gXltUvaMpJqckTa+jTNoB+z4cg=
|
||||
github.com/prometheus/client_golang v1.10.0/go.mod h1:WJM3cc3yu7XKBKa/I8WeZm+V3eltZnBwfENSU7mdogU=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
|
||||
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
|
||||
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||
github.com/prometheus/common v0.18.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
|
||||
github.com/prometheus/common v0.25.0 h1:IjJYZJCI8HZYtqA3xYwGyDzSCy1r4CA2GRh+4vdOmtE=
|
||||
github.com/prometheus/common v0.25.0/go.mod h1:H6QK/N6XVT42whUeIdI3dp36w49c+/iMDk7UAI2qm7Q=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
||||
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4=
|
||||
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU=
|
||||
github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k=
|
||||
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||
github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE=
|
||||
github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U=
|
||||
github.com/prometheus/procfs v0.14.0 h1:Lw4VdGGoKEZilJsayHf0B+9YgLGREba2C6xr+Fdfq6s=
|
||||
github.com/prometheus/procfs v0.14.0/go.mod h1:XL+Iwz8k8ZabyZfMFHPiilCniixqQarAy5Mu67pHlNQ=
|
||||
github.com/rivo/tview v0.0.0-20201204190810-5406288b8e4e/go.mod h1:0ha5CGekam8ZV1kxkBxSlh7gfQ7YolUj2P/VruwH0QY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rtr7/dhcp4 v0.0.0-20220221221838-73f36ca31019 h1:1eD+6TplxgtMqJsDfjkk/l6IwJOnDbVy0mOWxHbM0LA=
|
||||
github.com/rtr7/dhcp4 v0.0.0-20220221221838-73f36ca31019/go.mod h1:TP2Ay48p6Jaa5RHmYYtEwnaO9oefI0mdTJMgdBHORXM=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/rtr7/dhcp4 v0.0.0-20220302171438-18c84d089b46 h1:3psQveH4RUiv5yc3p7kRySilf1nSXLQhAvJFwg4fgnE=
|
||||
github.com/rtr7/dhcp4 v0.0.0-20220302171438-18c84d089b46/go.mod h1:Ng1F/s+z0zCMsbEFEneh+30LJa9DrTfmA+REbEqcTPk=
|
||||
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
|
||||
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
|
||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
|
||||
github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
|
||||
github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/u-root/uio v0.0.0-20210528114334-82958018845c h1:BFvcl34IGnw8yvJi8hlqLFo9EshRInwWBs2M5fGWzQA=
|
||||
github.com/u-root/uio v0.0.0-20210528114334-82958018845c/go.mod h1:LpEX5FO/cB+WF4TYGY1V5qktpaZLkKkSegbr0V4eYXA=
|
||||
github.com/u-root/uio v0.0.0-20210528151154-e40b768296a7 h1:XMAtQHwKjWHIRwg+8Nj/rzUomQY1q6cM3ncA0wP8GU4=
|
||||
github.com/u-root/uio v0.0.0-20210528151154-e40b768296a7/go.mod h1:LpEX5FO/cB+WF4TYGY1V5qktpaZLkKkSegbr0V4eYXA=
|
||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/vishvananda/netlink v1.1.1-0.20200221165523-c79a4b7b4066 h1:IlMBmSoCDZ9UY3OehFgvKSIgMNnU1vbAD4Fl+y2Rbis=
|
||||
github.com/vishvananda/netlink v1.1.1-0.20200221165523-c79a4b7b4066/go.mod h1:FSQhuTO7eHT34mPzX+B04SUAjiqLxtXs1et0S6l9k4k=
|
||||
github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI=
|
||||
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/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/vishvananda/netlink v1.2.1-beta.2 h1:Llsql0lnQEbHj0I1OuKyp8otXp0r3q0mPkuhwHfStVs=
|
||||
github.com/vishvananda/netlink v1.2.1-beta.2/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
|
||||
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||
github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8=
|
||||
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
gitlab.com/golang-commonmark/puny v0.0.0-20191124015043-9f83538fa04f h1:Wku8eEdeJqIOFHtrfkYUByc4bCaTeA6fL0UJgfEiFMI=
|
||||
gitlab.com/golang-commonmark/puny v0.0.0-20191124015043-9f83538fa04f/go.mod h1:Tiuhl+njh/JIg0uS/sOJVYi0x2HEa5rc1OAaVsb5tAs=
|
||||
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
|
||||
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
|
||||
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
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-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e/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-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
|
||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38=
|
||||
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||
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-20190419010253-1f3472d942ba/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191028085509-fe3aa8a45271/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20201216054612-986b41b23924/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210504132125-bbd867fde50d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
|
||||
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
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-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190411185658-b44545bcd369/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190418153312-f0ce4c0180be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606122018-79a91cf218c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191029155521-f43be2a4598c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200121082415-34d275377bf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200602100848-8d3cce7afc34/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201005065044-765f4ea38db3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201017003518-b09fb700fbb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201117222635-ba5294a509c7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201118182958-a01c418693c7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201218084310-7d0127a74742/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210110051926-789bb1bd4061/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210123111255-9b0068b26619/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210216163648-f7da38b97c65/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210309040221-94ec62e08169/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210503173754-0981d6026fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158 h1:rm+CHSpPEEW2IsXUib1ThaHIjuBVZjxNgSKmBLFfD4c=
|
||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||
golang.org/x/sys v0.28.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 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
|
||||
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE=
|
||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 h1:ftMN5LMiBFjbzleLqtoBZk7KdJwhuybIU+FckUHgoyQ=
|
||||
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.8 h1:P1HhGGuLW4aAclzjtmJdf0mJOjVUZUzOTqkAkWL+l6w=
|
||||
golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
|
||||
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-20191204190536-9bdfabe68543/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-20210427022245-097af6e1351b/go.mod h1:a057zjmoc00UN7gVkaJt2sXVK523kMJcogDTEvPIasg=
|
||||
golang.zx2c4.com/wireguard v0.0.20201118 h1:QL8y2C7uO8T6z1GY+UX/hSeWiYEBurQkXjOTRFtCvXU=
|
||||
golang.zx2c4.com/wireguard v0.0.20201118/go.mod h1:Dz+cq5bnrai9EpgYj4GDof/+qaGzbRWbeaAOs1bUYa0=
|
||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20210506160403-92e472f520a5 h1:LpEwXnbN4q2EIPkqbG9KHBUrducJYDOOdL+eMcJAlFo=
|
||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20210506160403-92e472f520a5/go.mod h1:+1XihzyZUBJcSc5WO9SwNA7v26puQwOEDwanaxfNXPQ=
|
||||
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
golang.zx2c4.com/wireguard v0.0.0-20220407013110-ef5c587f782d h1:q4JksJ2n0fmbXC0Aj0eOs6E0AcPqnKglxWXWFqGD6x0=
|
||||
golang.zx2c4.com/wireguard v0.0.0-20220407013110-ef5c587f782d/go.mod h1:bVQfyl2sCM/QIIGHpWbFGfHPuDvqnCNkT6MQLTCjO/U=
|
||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20220504211119-3d4a969bb56b h1:9JncmKXcUwE918my+H6xmjBdhK2jM/UTUNXxhRG1BAk=
|
||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20220504211119-3d4a969bb56b/go.mod h1:yp4gl6zOlnDGOZeWeDfMwQcsdOIQnMdhuPx9mwwWBL4=
|
||||
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/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
|
||||
gopkg.in/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
|
||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
rsc.io/goversion v1.2.0 h1:SPn+NLTiAG7w30IRK/DKp1BjvpWabYgxlLp/+kx5J8w=
|
||||
rsc.io/goversion v1.2.0/go.mod h1:Eih9y/uIBS3ulggl7KNJ09xGSLcuNaLgmvvqa07sgfo=
|
||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
51
init/init.go
51
init/init.go
@ -1,51 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os/exec"
|
||||
"path"
|
||||
|
||||
"github.com/gokrazy/gokrazy"
|
||||
)
|
||||
|
||||
// buildTimestamp can be overridden by specifying e.g.
|
||||
// -ldflags "-X main.buildTimestamp=foo" when building.
|
||||
var (
|
||||
buildTimestamp = "2020-06-08T19:45:52-07:00"
|
||||
|
||||
domain string
|
||||
cmdRoot string
|
||||
perm string
|
||||
noFirewall bool
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.StringVar(&cmdRoot, "cmdroot", "/usr/bin", "path to rtr7 binaries")
|
||||
flag.StringVar(&domain, "domain", "lan", "domain name for your network")
|
||||
flag.StringVar(&perm, "perm", "/var/lib/rtr7/", "path to replace /perm")
|
||||
flag.BoolVar(&noFirewall, "nofirewall", false, "disable the rtr7 firewall")
|
||||
flag.Parse()
|
||||
log.SetFlags(log.LstdFlags | log.Lshortfile)
|
||||
|
||||
fmt.Printf("gokrazy build timestamp %s\n", buildTimestamp)
|
||||
|
||||
cmds := []*exec.Cmd{
|
||||
// exec.Command(path.Join(cmdRoot, "/ntp")),
|
||||
exec.Command(path.Join(cmdRoot, "backupd"), "-perm="+perm),
|
||||
exec.Command(path.Join(cmdRoot, "captured"), "-perm="+perm),
|
||||
exec.Command(path.Join(cmdRoot, "dhcp4"), "-perm="+perm),
|
||||
exec.Command(path.Join(cmdRoot, "dhcp4d"), fmt.Sprintf("-domain=%s", domain), "-perm="+perm),
|
||||
exec.Command(path.Join(cmdRoot, "dhcp6"), "-perm="+perm),
|
||||
exec.Command(path.Join(cmdRoot, "diagd"), "-perm="+perm),
|
||||
exec.Command(path.Join(cmdRoot, "dnsd"), fmt.Sprintf("-domain=%s", domain), "-perm="+perm),
|
||||
exec.Command(path.Join(cmdRoot, "dyndns"), "-perm="+perm),
|
||||
exec.Command(path.Join(cmdRoot, "netconfigd"), fmt.Sprintf("-nofirewall=%t", noFirewall), "-perm="+perm),
|
||||
exec.Command(path.Join(cmdRoot, "radvd"), "-perm="+perm),
|
||||
}
|
||||
if err := gokrazy.Supervise(cmds); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
select {}
|
||||
}
|
@ -28,6 +28,7 @@ import (
|
||||
|
||||
"github.com/rtr7/router7/internal/netconfig"
|
||||
"github.com/vishvananda/netlink"
|
||||
"github.com/vishvananda/netns"
|
||||
|
||||
"github.com/andreyvit/diff"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
@ -45,11 +46,21 @@ const goldenInterfaces = `
|
||||
"hardware_addr": "02:73:53:00:b0:0c",
|
||||
"spoof_hardware_addr": "02:73:53:00:b0:aa",
|
||||
"name": "lan0",
|
||||
"addr": "192.168.42.1/24"
|
||||
"addr": "192.168.42.1/24",
|
||||
"mtu": 1492
|
||||
},
|
||||
{
|
||||
"name": "wg0",
|
||||
"addr": "fe80::1/64"
|
||||
"addr": "fe80::1/64",
|
||||
"extra_addrs": [
|
||||
"10.22.100.1/24"
|
||||
],
|
||||
"extra_routes": [
|
||||
{
|
||||
"destination": "2a02:168:4a00:22::/64",
|
||||
"gateway": "fe80::2"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -137,19 +148,24 @@ func goldenNftablesRules(additionalForwarding bool) string {
|
||||
add := ""
|
||||
if additionalForwarding {
|
||||
add = `
|
||||
iifname "uplink0" tcp dport 8045 dnat to 192.168.42.22:8045`
|
||||
ip daddr != 127.0.0.0/8 ip daddr != 192.168.42.0/24 fib daddr type 2 tcp dport 8045 dnat to 192.168.42.22:8045`
|
||||
}
|
||||
return `table ip nat {
|
||||
chain router7-portforwardings {
|
||||
ip daddr != 127.0.0.0/8 ip daddr != 192.168.42.0/24 fib daddr type 2 tcp dport 8080 dnat to 192.168.42.23:9999` + add + `
|
||||
ip daddr != 127.0.0.0/8 ip daddr != 192.168.42.0/24 fib daddr type 2 tcp dport 8040-8060 dnat to 192.168.42.99:8040-8060
|
||||
ip daddr != 127.0.0.0/8 ip daddr != 192.168.42.0/24 fib daddr type 2 udp dport 53 dnat to 192.168.42.99:53
|
||||
}
|
||||
|
||||
chain prerouting {
|
||||
type nat hook prerouting priority 0; policy accept;
|
||||
iifname "uplink0" tcp dport 8080 dnat to 192.168.42.23:9999` + add + `
|
||||
iifname "uplink0" tcp dport 8040-8060 dnat to 192.168.42.99:8040-8060
|
||||
iifname "uplink0" udp dport 53 dnat to 192.168.42.99:53
|
||||
jump router7-portforwardings
|
||||
}
|
||||
|
||||
chain postrouting {
|
||||
type nat hook postrouting priority 100; policy accept;
|
||||
oifname "uplink0" masquerade
|
||||
iifname "lan0" oifname "lan0" ct status 0x20 masquerade
|
||||
}
|
||||
}
|
||||
table ip filter {
|
||||
@ -157,14 +173,11 @@ table ip filter {
|
||||
packets 23 bytes 42
|
||||
}
|
||||
|
||||
chain forward {
|
||||
type filter hook forward priority 0; policy accept;
|
||||
oifname "uplink0" tcp flags 0x2 tcp option maxseg size set rt mtu
|
||||
counter name "fwded"
|
||||
counter inputc {
|
||||
packets 23 bytes 42
|
||||
}
|
||||
}
|
||||
table ip6 filter {
|
||||
counter fwded {
|
||||
|
||||
counter outputc {
|
||||
packets 23 bytes 42
|
||||
}
|
||||
|
||||
@ -173,6 +186,45 @@ table ip6 filter {
|
||||
oifname "uplink0" tcp flags 0x2 tcp option maxseg size set rt mtu
|
||||
counter name "fwded"
|
||||
}
|
||||
|
||||
chain input {
|
||||
type filter hook input priority 0; policy accept;
|
||||
counter name "inputc"
|
||||
}
|
||||
|
||||
chain output {
|
||||
type filter hook output priority 0; policy accept;
|
||||
counter name "outputc"
|
||||
}
|
||||
}
|
||||
table ip6 filter {
|
||||
counter fwded {
|
||||
packets 23 bytes 42
|
||||
}
|
||||
|
||||
counter inputc {
|
||||
packets 23 bytes 42
|
||||
}
|
||||
|
||||
counter outputc {
|
||||
packets 23 bytes 42
|
||||
}
|
||||
|
||||
chain forward {
|
||||
type filter hook forward priority 0; policy accept;
|
||||
oifname "uplink0" tcp flags 0x2 tcp option maxseg size set rt mtu
|
||||
counter name "fwded"
|
||||
}
|
||||
|
||||
chain input {
|
||||
type filter hook input priority 0; policy accept;
|
||||
counter name "inputc"
|
||||
}
|
||||
|
||||
chain output {
|
||||
type filter hook output priority 0; policy accept;
|
||||
counter name "outputc"
|
||||
}
|
||||
}`
|
||||
}
|
||||
|
||||
@ -202,19 +254,24 @@ const goldenDhcp6 = `
|
||||
}
|
||||
`
|
||||
|
||||
type wgLink struct{}
|
||||
type wgLink struct {
|
||||
ns int
|
||||
}
|
||||
|
||||
func (w *wgLink) Type() string { return "wireguard" }
|
||||
|
||||
func (w *wgLink) Attrs() *netlink.LinkAttrs {
|
||||
attrs := netlink.NewLinkAttrs()
|
||||
attrs.Name = "wg5"
|
||||
if w.ns > 0 {
|
||||
attrs.Namespace = netlink.NsFd(w.ns)
|
||||
}
|
||||
return &attrs
|
||||
}
|
||||
|
||||
var wireGuardAvailable = func() bool {
|
||||
// The wg tool must also be available for our test to succeed:
|
||||
if _, err := exec.LookPath("wg"); err == nil {
|
||||
if _, err := exec.LookPath("wg"); err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
@ -228,7 +285,18 @@ var wireGuardAvailable = func() bool {
|
||||
}
|
||||
defer exec.Command("ip", "netns", "delete", ns).Run()
|
||||
|
||||
return netlink.LinkAdd(&wgLink{}) == nil
|
||||
nsHandle, err := netns.GetFromName(ns)
|
||||
if err != nil {
|
||||
log.Printf("GetFromName: %v", err)
|
||||
return false
|
||||
}
|
||||
|
||||
if err := netlink.LinkAdd(&wgLink{ns: int(nsHandle)}); err != nil {
|
||||
log.Printf("netlink.LinkAdd: %v", err)
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}()
|
||||
|
||||
func TestNetconfig(t *testing.T) {
|
||||
@ -330,6 +398,9 @@ func TestNetconfig(t *testing.T) {
|
||||
if !strings.Contains(string(link), "link/ether 02:73:53:00:b0:aa") {
|
||||
t.Errorf("lan0 MAC address is not 02:73:53:00:b0:aa")
|
||||
}
|
||||
if !strings.Contains(string(link), " mtu 1492 ") {
|
||||
t.Errorf("lan0 MTU is not 1492 (link: %q)", string(link))
|
||||
}
|
||||
|
||||
addrs, err := exec.Command("ip", "-netns", ns, "address", "show", "dev", "uplink0").Output()
|
||||
if err != nil {
|
||||
@ -407,11 +478,27 @@ peer: AVU3LodtnFaFnJmMyNNW7cUk4462lqnVULTFkjWYvRo=
|
||||
if !upRe.MatchString(string(out)) {
|
||||
t.Errorf("regexp %s does not match %s", upRe, string(out))
|
||||
}
|
||||
|
||||
addr4Re := regexp.MustCompile(`(?m)^\s*inet 10.22.100.1/24 brd 10.22.100.255 scope global wg0\s*$`)
|
||||
if !addr4Re.MatchString(string(out)) {
|
||||
t.Errorf("regexp %s does not match %s", addr4Re, string(out))
|
||||
}
|
||||
|
||||
addr6Re := regexp.MustCompile(`(?m)^\s*inet6 fe80::1/64 scope link\s*$`)
|
||||
if !addr6Re.MatchString(string(out)) {
|
||||
t.Errorf("regexp %s does not match %s", addr6Re, string(out))
|
||||
}
|
||||
|
||||
out, err = exec.Command("ip", "-netns", ns, "-6", "route", "show", "dev", "wg0").Output()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
extraRouteRe := regexp.MustCompile(`(?m)^\s*2a02:168:4a00:22::/64 via fe80::2 metric 1024 pref medium\s*$`)
|
||||
if !extraRouteRe.MatchString(string(out)) {
|
||||
t.Errorf("regexp %s does not match %s", extraRouteRe, string(out))
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
opts := []cmp.Option{
|
||||
|
@ -23,9 +23,10 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
)
|
||||
|
||||
func Archive(w io.Writer, dir string) error {
|
||||
func Archive(w io.Writer, dir string, excludes []string) error {
|
||||
gw, err := gzip.NewWriterLevel(w, gzip.BestSpeed)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -46,7 +47,7 @@ func Archive(w io.Writer, dir string) error {
|
||||
if path == dir {
|
||||
return nil // skip root
|
||||
}
|
||||
if last := filepath.Base(path); last == "nobackup" || last == "srv" {
|
||||
if last := filepath.Base(path); last == "nobackup" || last == "srv" || slices.Contains(excludes, path) {
|
||||
return filepath.SkipDir // skip nobackup (and srv for legacy)
|
||||
}
|
||||
rel, err := filepath.Rel(dir, path)
|
||||
@ -61,7 +62,7 @@ func Archive(w io.Writer, dir string) error {
|
||||
if err := tw.WriteHeader(hdr); err != nil {
|
||||
return err
|
||||
}
|
||||
if !info.Mode().IsDir() {
|
||||
if !info.Mode().IsDir() && !slices.Contains(excludes, path) {
|
||||
b, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -43,14 +43,18 @@ type Lease struct {
|
||||
Hostname string `json:"hostname"`
|
||||
HostnameOverride string `json:"hostname_override"`
|
||||
Expiry time.Time `json:"expiry"`
|
||||
Start time.Time `json:"start"`
|
||||
VendorIdentifier string `json:"vendor"`
|
||||
LastACK time.Time `json:"last_ack"`
|
||||
}
|
||||
|
||||
func (l *Lease) Expired(at time.Time) bool {
|
||||
return !l.Expiry.IsZero() && at.After(l.Expiry)
|
||||
}
|
||||
|
||||
func (l *Lease) Active(at time.Time) bool {
|
||||
return !l.LastACK.IsZero() && at.Before(l.LastACK.Add(leasePeriod))
|
||||
}
|
||||
|
||||
type Handler struct {
|
||||
serverIP net.IP
|
||||
start net.IP // first IP address to hand out
|
||||
@ -106,23 +110,25 @@ func NewHandler(dir string, iface *net.Interface, ifaceName string, conn net.Pac
|
||||
copy(start, serverIP)
|
||||
start[len(start)-1]++
|
||||
return &Handler{
|
||||
rawConn: conn,
|
||||
iface: iface,
|
||||
leasesHW: make(map[string]int),
|
||||
leasesIP: make(map[int]*Lease),
|
||||
serverIP: serverIP,
|
||||
start: start,
|
||||
leaseRange: 230,
|
||||
// Apple recommends a DHCP lease time of 1 hour in
|
||||
// https://support.apple.com/de-ch/HT202068,
|
||||
// so if 20 minutes ever causes any trouble,
|
||||
// we should try increasing it to 1 hour.
|
||||
LeasePeriod: 20 * time.Minute,
|
||||
rawConn: conn,
|
||||
iface: iface,
|
||||
leasesHW: make(map[string]int),
|
||||
leasesIP: make(map[int]*Lease),
|
||||
serverIP: serverIP,
|
||||
start: start,
|
||||
leaseRange: 230,
|
||||
LeasePeriod: leasePeriod,
|
||||
options: options,
|
||||
timeNow: time.Now,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Apple recommends a DHCP lease time of 1 hour in
|
||||
// https://support.apple.com/de-ch/HT202068,
|
||||
// so if 20 minutes ever causes any trouble,
|
||||
// we should try increasing it to 1 hour.
|
||||
const leasePeriod = 20 * time.Minute
|
||||
|
||||
// SetLeases overwrites the leases database with the specified leases, typically
|
||||
// loaded from persistent storage. There is no locking, so SetLeases must be
|
||||
// called before Serve.
|
||||
@ -132,6 +138,9 @@ func (h *Handler) SetLeases(leases []*Lease) {
|
||||
h.leasesHW = make(map[string]int)
|
||||
h.leasesIP = make(map[int]*Lease)
|
||||
for _, l := range leases {
|
||||
if l.LastACK.IsZero() {
|
||||
l.LastACK = l.Expiry
|
||||
}
|
||||
h.leasesHW[l.HardwareAddr] = l.Num
|
||||
h.leasesIP[l.Num] = l
|
||||
}
|
||||
@ -187,7 +196,7 @@ func (h *Handler) canLease(reqIP net.IP, hwaddr string) int {
|
||||
}
|
||||
|
||||
leaseNum := dhcp4.IPRange(h.start, reqIP) - 1
|
||||
if leaseNum < 0 || leaseNum >= h.leaseRange {
|
||||
if leaseNum < 0 {
|
||||
return -1
|
||||
}
|
||||
|
||||
@ -195,6 +204,10 @@ func (h *Handler) canLease(reqIP net.IP, hwaddr string) int {
|
||||
defer h.leasesMu.Unlock()
|
||||
l, ok := h.leasesIP[leaseNum]
|
||||
if !ok {
|
||||
if leaseNum >= h.leaseRange {
|
||||
return -1
|
||||
}
|
||||
|
||||
return leaseNum // lease available
|
||||
}
|
||||
|
||||
@ -202,6 +215,10 @@ func (h *Handler) canLease(reqIP net.IP, hwaddr string) int {
|
||||
return leaseNum // lease already owned by requestor
|
||||
}
|
||||
|
||||
if leaseNum >= h.leaseRange {
|
||||
return -1
|
||||
}
|
||||
|
||||
if l.Expired(h.timeNow()) {
|
||||
return leaseNum // lease expired
|
||||
}
|
||||
@ -344,8 +361,8 @@ func (h *Handler) serveDHCP(p dhcp4.Packet, msgType dhcp4.MessageType, options d
|
||||
HardwareAddr: hwAddr,
|
||||
Expiry: now.Add(h.leasePeriodForDevice(hwAddr)),
|
||||
Hostname: string(options[dhcp4.OptionHostName]),
|
||||
Start: now,
|
||||
VendorIdentifier: string(bytes.ToValidUTF8(bytes.ReplaceAll(options[dhcp4.OptionVendorClassIdentifier], []byte{0}, []byte{}), []byte{})),
|
||||
LastACK: h.timeNow(),
|
||||
}
|
||||
copy(lease.Addr, reqIP.To4())
|
||||
|
||||
|
@ -53,6 +53,7 @@ func TCP4(addr string) Node {
|
||||
|
||||
type tcp6 struct {
|
||||
children []Node
|
||||
ifname string
|
||||
addr string
|
||||
}
|
||||
|
||||
@ -70,7 +71,39 @@ func (d *tcp6) Children() []Node {
|
||||
}
|
||||
|
||||
func (d *tcp6) Evaluate() (string, error) {
|
||||
conn, err := net.Dial("tcp6", d.addr)
|
||||
var dialer net.Dialer
|
||||
|
||||
if d.ifname != "" {
|
||||
iface, err := net.InterfaceByName(d.ifname)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
addrs, err := iface.Addrs()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
for _, addr := range addrs {
|
||||
ipnet, ok := addr.(*net.IPNet)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
if ipnet.IP.To4() != nil {
|
||||
continue // skip IPv4 addresses
|
||||
}
|
||||
|
||||
if !global.Contains(ipnet.IP) {
|
||||
continue // skip local IPv6 addresses
|
||||
}
|
||||
|
||||
dialer.LocalAddr = &net.TCPAddr{
|
||||
IP: ipnet.IP,
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
conn, err := dialer.Dial("tcp6", d.addr)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@ -80,6 +113,9 @@ func (d *tcp6) Evaluate() (string, error) {
|
||||
|
||||
// TCP6 returns a Node which succeeds when the specified address accepts a TCPv6
|
||||
// connection.
|
||||
func TCP6(addr string) Node {
|
||||
return &tcp6{addr: addr}
|
||||
func TCP6(ifname, addr string) Node {
|
||||
return &tcp6{
|
||||
ifname: ifname,
|
||||
addr: addr,
|
||||
}
|
||||
}
|
||||
|
@ -90,14 +90,16 @@ func NewServer(addr, domain string) *Server {
|
||||
domain: lcHostname(strings.ToLower(domain)),
|
||||
upstream: []string{
|
||||
// https://developers.google.com/speed/public-dns/docs/using#google_public_dns_ip_addresses
|
||||
"1.1.1.1:53",
|
||||
"1.0.0.1:53",
|
||||
"[2606:4700:4700::1111]:53",
|
||||
"[2606:4700:4700::1001]:53",
|
||||
"8.8.8.8:53",
|
||||
"8.8.4.4:53",
|
||||
"[2001:4860:4860::8888]:53",
|
||||
"[2001:4860:4860::8844]:53",
|
||||
"45.90.28.26:53",
|
||||
"45.90.30.26:53",
|
||||
"[2a07:a8c0::54:f68e]:53",
|
||||
"[2a07:a8c1::54:f68e]:53",
|
||||
"194.242.2.4:53",
|
||||
"[2a07:e340::4]:52",
|
||||
"94.140.14.14:53",
|
||||
"94.140.15.15:53",
|
||||
"[2a10:50c0::ad1:ff]:53",
|
||||
"[2a10:50c0::ad2:ff]:53",
|
||||
},
|
||||
sometimes: rate.NewLimiter(rate.Every(1*time.Second), 1), // at most once per second
|
||||
hostname: hostname,
|
||||
@ -575,7 +577,7 @@ func (s *Server) handleRequest(w dns.ResponseWriter, r *dns.Msg) {
|
||||
nr.Question[0].Qtype = dns.TypeSOA
|
||||
nr.RecursionDesired = true
|
||||
soa, _, err := s.client.Exchange(nr, u)
|
||||
fmt.Println(err, soa)
|
||||
fmt.Println(w.RemoteAddr(), err, soa)
|
||||
fmt.Println()
|
||||
fmt.Println(soa.Ns)
|
||||
|
||||
@ -597,16 +599,24 @@ func (s *Server) handleRequest(w dns.ResponseWriter, r *dns.Msg) {
|
||||
// DNS has no reply for resolving errors
|
||||
}
|
||||
|
||||
func (s *Server) getSubname(domain string, queryName string) (IP, bool) {
|
||||
name := strings.TrimSuffix(queryName, ".")
|
||||
name = strings.TrimSuffix(name, ".lan") // trim lan domain
|
||||
name = strings.TrimSuffix(name, "."+string(s.domain)) // trim server domain
|
||||
name = strings.TrimSuffix(name, "."+strings.TrimSuffix(domain, "."+string(s.domain))) // trim function domain
|
||||
if ip, ok := s.subname(domain, name); ok {
|
||||
return ip, true
|
||||
}
|
||||
return IP{}, false
|
||||
}
|
||||
|
||||
func (s *Server) resolveSubname(domain string, q dns.Question) (dns.RR, error) {
|
||||
if q.Qclass != dns.ClassINET {
|
||||
return nil, nil
|
||||
}
|
||||
ip, ok := s.getSubname(domain, q.Name)
|
||||
if q.Qtype == dns.TypeA || q.Qtype == dns.TypeAAAA /*|| q.Qtype == dns.TypeMX*/ {
|
||||
name := strings.TrimSuffix(q.Name, ".")
|
||||
name = strings.TrimSuffix(name, ".lan") // trim lan domain
|
||||
name = strings.TrimSuffix(name, "."+string(s.domain)) // trim server domain
|
||||
name = strings.TrimSuffix(name, "."+strings.TrimSuffix(domain, "."+string(s.domain))) // trim function domain
|
||||
if ip, ok := s.subname(domain, name); ok {
|
||||
if ok {
|
||||
if q.Qtype == dns.TypeA && ip.IPv4.To4() != nil {
|
||||
return dns.NewRR(q.Name + " 3600 IN A " + ip.IPv4.String())
|
||||
}
|
||||
@ -655,7 +665,7 @@ func (s *Server) subnameHandler(domain lcHostname) func(w dns.ResponseWriter, r
|
||||
}
|
||||
|
||||
// Send an authoritative NXDOMAIN for local names:
|
||||
if r.Question[0].Qtype == dns.TypePTR || !strings.Contains(strings.TrimSuffix(r.Question[0].Name, "."), ".") || strings.HasSuffix(r.Question[0].Name, ".lan.") {
|
||||
if _, ok := s.getSubname(string(domain), r.Question[0].Name); r.Question[0].Qtype == dns.TypePTR || (r.Question[0].Qtype == dns.TypeCNAME && ok) || !strings.Contains(strings.TrimSuffix(r.Question[0].Name, "."), ".") || strings.HasSuffix(r.Question[0].Name, ".lan.") {
|
||||
s.promInc("local", r)
|
||||
m := new(dns.Msg)
|
||||
m.SetReply(r)
|
||||
|
@ -21,6 +21,7 @@ import (
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
@ -31,7 +32,7 @@ import (
|
||||
"github.com/google/nftables"
|
||||
"github.com/google/nftables/binaryutil"
|
||||
"github.com/google/nftables/expr"
|
||||
"github.com/google/renameio"
|
||||
"github.com/mdlayher/ethtool"
|
||||
"github.com/vishvananda/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
@ -62,7 +63,7 @@ func subnetMaskSize(mask string) (int, error) {
|
||||
return ones, nil
|
||||
}
|
||||
|
||||
func applyDhcp4(dir string) error {
|
||||
func applyDhcp4(dir string, cfg InterfaceConfig) error {
|
||||
b, err := ioutil.ReadFile(filepath.Join(dir, "dhcp4/wire/lease.json"))
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
@ -140,22 +141,87 @@ func applyDhcp4(dir string) error {
|
||||
return fmt.Errorf("RouteReplace(router): %v", err)
|
||||
}
|
||||
|
||||
if err := h.RouteReplace(&netlink.Route{
|
||||
LinkIndex: link.Attrs().Index,
|
||||
Dst: &net.IPNet{
|
||||
IP: net.ParseIP("0.0.0.0"),
|
||||
Mask: net.CIDRMask(0, 32),
|
||||
},
|
||||
Gw: net.ParseIP(got.Router),
|
||||
Src: net.ParseIP(got.ClientIP),
|
||||
Protocol: RTPROT_DHCP,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("RouteReplace(default): %v", err)
|
||||
if defaultViaWireguard(cfg) {
|
||||
// The default route is on a WireGuard interface, so do not install the
|
||||
// default route from the DHCP reply. Instead, set up a host route for
|
||||
// the WireGuard endpoint(s).
|
||||
|
||||
log.Printf("IPv4 traffic is routed via WireGuard, setting host route instead of default route")
|
||||
|
||||
b, err := ioutil.ReadFile(filepath.Join(dir, "wireguard.json"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var wgcfg wireguardInterfaces
|
||||
if err := json.Unmarshal(b, &wgcfg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, iface := range wgcfg.Interfaces {
|
||||
for _, p := range iface.Peers {
|
||||
addr, err := net.ResolveUDPAddr("udp", p.Endpoint)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf(" WireGuard endpoint %s", addr.IP)
|
||||
|
||||
router := net.ParseIP(got.Router)
|
||||
if addr.IP.Equal(router) {
|
||||
continue // endpoint == router, no route required
|
||||
}
|
||||
|
||||
if err := h.RouteReplace(&netlink.Route{
|
||||
LinkIndex: link.Attrs().Index,
|
||||
Dst: &net.IPNet{
|
||||
IP: addr.IP,
|
||||
Mask: net.CIDRMask(32, 32),
|
||||
},
|
||||
Gw: net.ParseIP(got.Router),
|
||||
Src: net.ParseIP(got.ClientIP),
|
||||
Protocol: RTPROT_DHCP,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("RouteReplace(default): %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if err := h.RouteReplace(&netlink.Route{
|
||||
LinkIndex: link.Attrs().Index,
|
||||
Dst: &net.IPNet{
|
||||
IP: net.ParseIP("0.0.0.0"),
|
||||
Mask: net.CIDRMask(0, 32),
|
||||
},
|
||||
Gw: net.ParseIP(got.Router),
|
||||
Src: net.ParseIP(got.ClientIP),
|
||||
Protocol: RTPROT_DHCP,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("RouteReplace(default): %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func defaultViaWireguard(cfg InterfaceConfig) bool {
|
||||
for _, iface := range cfg.Interfaces {
|
||||
if !strings.HasPrefix(iface.Name, "wg") {
|
||||
continue
|
||||
}
|
||||
for _, route := range iface.ExtraRoutes {
|
||||
_, n, err := net.ParseCIDR(route.Destination)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
ones, bits := n.Mask.Size()
|
||||
if n.IP.Equal(net.IPv4zero) && ones == 0 && bits == 32 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func applyDhcp6(dir string) error {
|
||||
b, err := ioutil.ReadFile(filepath.Join(dir, "dhcp6/wire/lease.json"))
|
||||
if err != nil {
|
||||
@ -194,11 +260,26 @@ func applyDhcp6(dir string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type Route struct {
|
||||
Destination string `json:"destination"` // e.g. 2a02:168:4a00:22::/64
|
||||
Gateway string `json:"gateway"` // e.g. fe80::1
|
||||
}
|
||||
|
||||
type InterfaceDetails struct {
|
||||
HardwareAddr string `json:"hardware_addr"` // e.g. dc:9b:9c:ee:72:fd
|
||||
SpoofHardwareAddr string `json:"spoof_hardware_addr"` // e.g. dc:9b:9c:ee:72:fd
|
||||
Name string `json:"name"` // e.g. uplink0, or lan0
|
||||
Addr string `json:"addr"` // e.g. 192.168.42.1/24
|
||||
HardwareAddr string `json:"hardware_addr"` // e.g. dc:9b:9c:ee:72:fd
|
||||
SpoofHardwareAddr string `json:"spoof_hardware_addr"` // e.g. dc:9b:9c:ee:72:fd
|
||||
Name string `json:"name"` // e.g. uplink0, or lan0
|
||||
Addr string `json:"addr"` // e.g. 192.168.42.1/24
|
||||
ExtraAddrs []string `json:"extra_addrs"` // e.g. ["192.168.23.1/24"]
|
||||
ExtraRoutes []Route `json:"extra_routes"`
|
||||
MTU int `json:"mtu"` // e.g. 1492 for PPPoE connections
|
||||
// FEC optionally allows configuring forward error correction, e.g. RS for
|
||||
// reed-solomon forward error correction, or Off to disable.
|
||||
//
|
||||
// Some network card and SFP module combinations (e.g. Mellanox ConnectX-4
|
||||
// with a Flexoptix P.B1625G.10.AD) need to explicitly be configured to use
|
||||
// RS forward error correction, otherwise they won’t link.
|
||||
FEC string `json:"fec"`
|
||||
}
|
||||
|
||||
type BridgeDetails struct {
|
||||
@ -301,18 +382,101 @@ func applyBridges(cfg *InterfaceConfig) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func applyInterfaces(dir, root string) error {
|
||||
b, err := ioutil.ReadFile(filepath.Join(dir, "interfaces.json"))
|
||||
func applyInterfaceFEC(details InterfaceDetails) error {
|
||||
if details.FEC == "" {
|
||||
return nil // nothing to do
|
||||
}
|
||||
|
||||
desired := ethtool.FECModes(unix.ETHTOOL_FEC_RS)
|
||||
switch strings.ToLower(details.FEC) {
|
||||
case "rs":
|
||||
desired = unix.ETHTOOL_FEC_RS
|
||||
case "baser":
|
||||
desired = unix.ETHTOOL_FEC_BASER
|
||||
case "off":
|
||||
desired = unix.ETHTOOL_FEC_OFF
|
||||
case "none":
|
||||
desired = unix.ETHTOOL_FEC_NONE
|
||||
case "llrs":
|
||||
desired = unix.ETHTOOL_FEC_LLRS
|
||||
case "auto":
|
||||
desired = 0
|
||||
default:
|
||||
return fmt.Errorf("unknown FEC value %q, expected one of RS, BaseR, LLRS, Auto, None, Off", details.FEC)
|
||||
}
|
||||
|
||||
cl, err := ethtool.New()
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
defer cl.Close()
|
||||
|
||||
li, err := cl.LinkInfo(ethtool.Interface{Name: details.Name})
|
||||
if err != nil {
|
||||
return fmt.Errorf("LinkInfo(%s): %v", details.Name, err)
|
||||
}
|
||||
|
||||
fec, err := cl.FEC(li.Interface)
|
||||
if err != nil {
|
||||
return fmt.Errorf("FEC(%s): %v", li.Interface.Name, err)
|
||||
}
|
||||
log.Printf("FEC supported/configured: [%v], active: %v", fec.Supported(), fec.Active)
|
||||
// fec.Active is not set when there is no link, so we compare
|
||||
// supported/configured instead.
|
||||
if fec.Supported() == desired {
|
||||
return nil // already matching the desired configuration
|
||||
}
|
||||
|
||||
log.Printf("setting FEC to %v", desired)
|
||||
if err := cl.SetFEC(ethtool.FEC{
|
||||
Interface: li.Interface,
|
||||
Modes: desired,
|
||||
Auto: strings.ToLower(details.FEC) == "auto",
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func createResolvConfIfMissing(root, contents string) error {
|
||||
fn := filepath.Join(root, "tmp", "resolv.conf")
|
||||
|
||||
// Explicitly check for the file's existance
|
||||
// just so that we can avoid printing an error
|
||||
// in the normal case (file exists).
|
||||
st, err := os.Lstat(fn)
|
||||
if err == nil {
|
||||
if st.Mode()&os.ModeSymlink != 0 {
|
||||
// File is a symbolic link (at boot, gokrazy links /tmp/resolv.conf to /proc/net/pnp).
|
||||
// Delete the link and fallthrough to create the file.
|
||||
if err := os.Remove(fn); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return nil // regular file already exists, do not overwrite
|
||||
}
|
||||
} else if !os.IsNotExist(err) {
|
||||
return err // unexpected error
|
||||
}
|
||||
|
||||
// /tmp/resolv.conf does not exist yet, create it.
|
||||
|
||||
// This is os.WriteFile, but with O_EXCL set
|
||||
// so that we do not accidentally clobber the file
|
||||
// in case another process (e.g. tailscaled) just wrote it.
|
||||
f, err := os.OpenFile(fn, os.O_WRONLY|os.O_CREATE|os.O_TRUNC|os.O_EXCL, 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var cfg InterfaceConfig
|
||||
if err := json.Unmarshal(b, &cfg); err != nil {
|
||||
return err
|
||||
_, err = f.Write([]byte(contents))
|
||||
if err1 := f.Close(); err1 != nil && err == nil {
|
||||
err = err1
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func applyInterfaces(dir, root string, cfg InterfaceConfig) error {
|
||||
byName := make(map[string]InterfaceDetails)
|
||||
byHardwareAddr := make(map[string]InterfaceDetails)
|
||||
for _, details := range cfg.Interfaces {
|
||||
@ -364,6 +528,12 @@ func applyInterfaces(dir, root string) error {
|
||||
attr.Name = details.Name
|
||||
}
|
||||
|
||||
if details.MTU != 0 {
|
||||
if err := netlink.LinkSetMTU(l, details.MTU); err != nil {
|
||||
return fmt.Errorf("LinkSetMTU(%d): %v", details.MTU, err)
|
||||
}
|
||||
}
|
||||
|
||||
if spoof := details.SpoofHardwareAddr; spoof != "" {
|
||||
hwaddr, err := net.ParseMAC(spoof)
|
||||
if err != nil {
|
||||
@ -374,6 +544,11 @@ func applyInterfaces(dir, root string) error {
|
||||
}
|
||||
}
|
||||
|
||||
if err := applyInterfaceFEC(details); err != nil {
|
||||
// TODO: turn this into returning an error once proven stable
|
||||
log.Printf("applyInterfaceFEC: %v", err)
|
||||
}
|
||||
|
||||
if attr.OperState != netlink.OperUp {
|
||||
// Set the interface to up, which is required by all other configuration.
|
||||
if err := netlink.LinkSetUp(l); err != nil {
|
||||
@ -392,16 +567,43 @@ func applyInterfaces(dir, root string) error {
|
||||
}
|
||||
|
||||
if details.Name == "lan0" {
|
||||
b := []byte("nameserver " + addr.IP.String() + "\n")
|
||||
fn := filepath.Join(root, "tmp", "resolv.conf")
|
||||
if err := os.Remove(fn); err != nil && !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
if err := renameio.WriteFile(fn, b, 0644); err != nil {
|
||||
// Use dnsd for the system's own DNS resolution.
|
||||
resolvConf := "nameserver " + addr.IP.String() + "\n"
|
||||
if err := createResolvConfIfMissing(root, resolvConf); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, addr := range details.ExtraAddrs {
|
||||
log.Printf("replacing extra address %v on %v", addr, attr.Name)
|
||||
addr, err := netlink.ParseAddr(addr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("ParseAddr(%q): %v", addr, err)
|
||||
}
|
||||
|
||||
if err := netlink.AddrReplace(l, addr); err != nil {
|
||||
return fmt.Errorf("AddrReplace(%s, %v): %v", attr.Name, addr, err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, route := range details.ExtraRoutes {
|
||||
_, dst, err := net.ParseCIDR(route.Destination)
|
||||
if err != nil {
|
||||
return fmt.Errorf("ParseCIDR(%q): %v", route.Destination, err)
|
||||
}
|
||||
r := &netlink.Route{Dst: dst}
|
||||
if route.Gateway != "" {
|
||||
r.Gw = net.ParseIP(route.Gateway)
|
||||
}
|
||||
r.LinkIndex = attr.Index
|
||||
|
||||
log.Printf("replacing extra route %v on %v", r, attr.Name)
|
||||
|
||||
if err := netlink.RouteReplace(r); err != nil {
|
||||
return fmt.Errorf("RouteReplace(%v): %v", r, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -412,7 +614,76 @@ func nfifname(n string) []byte {
|
||||
return b
|
||||
}
|
||||
|
||||
func portForwardExpr(ifname string, proto uint8, portMin, portMax uint16, dest net.IP, dportMin, dportMax uint16) []expr.Any {
|
||||
// matchUplinkIP is conceptually equivalent to "ip daddr <uplink0-ip>", but
|
||||
// without actually using the IP address of the uplink0 interface (which would
|
||||
// mean that rules need to change when the IP address changes).
|
||||
//
|
||||
// Instead, it uses “fib daddr type local” to match all locally-configured IP
|
||||
// addresses and then excludes the loopback and LAN IP addresses.
|
||||
func matchUplinkIP(lan0ip net.IP) []expr.Any {
|
||||
return []expr.Any{
|
||||
// [ payload load 4b @ network header + 16 => reg 1 ]
|
||||
&expr.Payload{
|
||||
DestRegister: 1,
|
||||
Base: expr.PayloadBaseNetworkHeader,
|
||||
Offset: 16, // TODO
|
||||
Len: 4, // TODO
|
||||
},
|
||||
// [ bitwise reg 1 = (reg=1 & 0x000000ff ) ^ 0x00000000 ]
|
||||
&expr.Bitwise{
|
||||
DestRegister: 1,
|
||||
SourceRegister: 1,
|
||||
Len: 4,
|
||||
Mask: []byte{0xff, 0x00, 0x00, 0x00}, // 255.0.0.0, i.e. /8
|
||||
Xor: []byte{0x00, 0x00, 0x00, 0x00},
|
||||
},
|
||||
// [ cmp neq reg 1 0x0000007f ]
|
||||
&expr.Cmp{
|
||||
Op: expr.CmpOpNeq,
|
||||
Register: 1,
|
||||
Data: []byte{0x7f, 0x00, 0x00, 0x00},
|
||||
},
|
||||
|
||||
// [ payload load 4b @ network header + 16 => reg 1 ]
|
||||
&expr.Payload{
|
||||
DestRegister: 1,
|
||||
Base: expr.PayloadBaseNetworkHeader,
|
||||
Offset: 16, // TODO
|
||||
Len: 4, // TODO
|
||||
},
|
||||
// [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
|
||||
&expr.Bitwise{
|
||||
DestRegister: 1,
|
||||
SourceRegister: 1,
|
||||
Len: 4,
|
||||
Mask: []byte{0xff, 0xff, 0xff, 0x00}, // 255.255.255.0, i.e. /24
|
||||
Xor: []byte{0x00, 0x00, 0x00, 0x00},
|
||||
},
|
||||
// [ cmp neq reg 1 0x0000000a ]
|
||||
&expr.Cmp{
|
||||
Op: expr.CmpOpNeq,
|
||||
Register: 1,
|
||||
// Turn the lan0 IP address (e.g. 192.168.42.1)
|
||||
// into a netmask like 192.168.42.0/24.
|
||||
Data: []byte{lan0ip[0], lan0ip[1], lan0ip[2], 0},
|
||||
},
|
||||
|
||||
// [ fib daddr type => reg 1 ]
|
||||
&expr.Fib{
|
||||
Register: 1,
|
||||
FlagDADDR: true,
|
||||
ResultADDRTYPE: true,
|
||||
},
|
||||
// [ cmp eq reg 1 0x00000002 ]
|
||||
&expr.Cmp{
|
||||
Op: expr.CmpOpEq,
|
||||
Register: 1,
|
||||
Data: []byte{0x02, 0x00, 0x00, 0x00},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func portForwardExpr(lan0ip net.IP, proto uint8, portMin, portMax uint16, dest net.IP, dportMin, dportMax uint16) []expr.Any {
|
||||
var cmp []expr.Any
|
||||
if portMin == portMax {
|
||||
cmp = []expr.Any{
|
||||
@ -439,16 +710,7 @@ func portForwardExpr(ifname string, proto uint8, portMin, portMax uint16, dest n
|
||||
},
|
||||
}
|
||||
}
|
||||
ex := []expr.Any{
|
||||
// [ meta load iifname => reg 1 ]
|
||||
&expr.Meta{Key: expr.MetaKeyIIFNAME, Register: 1},
|
||||
// [ cmp eq reg 1 0x696c7075 0x00306b6e 0x00000000 0x00000000 ]
|
||||
&expr.Cmp{
|
||||
Op: expr.CmpOpEq,
|
||||
Register: 1,
|
||||
Data: nfifname(ifname),
|
||||
},
|
||||
|
||||
ex := append(matchUplinkIP(lan0ip),
|
||||
// [ meta load l4proto => reg 1 ]
|
||||
&expr.Meta{Key: expr.MetaKeyL4PROTO, Register: 1},
|
||||
// [ cmp eq reg 1 0x00000006 ]
|
||||
@ -464,8 +726,7 @@ func portForwardExpr(ifname string, proto uint8, portMin, portMax uint16, dest n
|
||||
Base: expr.PayloadBaseTransportHeader,
|
||||
Offset: 2, // TODO
|
||||
Len: 2, // TODO
|
||||
},
|
||||
}
|
||||
})
|
||||
ex = append(ex, cmp...)
|
||||
ex = append(ex,
|
||||
// [ immediate reg 1 0x0217a8c0 ]
|
||||
@ -559,6 +820,15 @@ func applyPortForwardings(dir, ifname string, c *nftables.Conn, nat *nftables.Ta
|
||||
return err
|
||||
}
|
||||
|
||||
lan0ip, err := LinkAddress(dir, "lan0")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
lan0ip = lan0ip.To4()
|
||||
if got, want := len(lan0ip), net.IPv4len; got != want {
|
||||
return fmt.Errorf("lan0 does not have an IPv4 address configured: len %d != %d", got, want)
|
||||
}
|
||||
|
||||
for _, fw := range cfg.Forwardings {
|
||||
for _, proto := range strings.Split(fw.Proto, ",") {
|
||||
var p uint8
|
||||
@ -583,7 +853,7 @@ func applyPortForwardings(dir, ifname string, c *nftables.Conn, nat *nftables.Ta
|
||||
c.AddRule(&nftables.Rule{
|
||||
Table: nat,
|
||||
Chain: prerouting,
|
||||
Exprs: portForwardExpr(ifname, p, min, max, net.ParseIP(fw.DestAddr), dmin, dmax),
|
||||
Exprs: portForwardExpr(lan0ip, p, min, max, net.ParseIP(fw.DestAddr), dmin, dmax),
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -594,35 +864,13 @@ func applyPortForwardings(dir, ifname string, c *nftables.Conn, nat *nftables.Ta
|
||||
var DefaultCounterObj = &nftables.CounterObj{}
|
||||
|
||||
func getCounterObj(c *nftables.Conn, o *nftables.CounterObj) *nftables.CounterObj {
|
||||
objs, err := c.GetObj(o)
|
||||
obj, err := c.GetObject(o)
|
||||
if err != nil {
|
||||
o.Bytes = DefaultCounterObj.Bytes
|
||||
o.Packets = DefaultCounterObj.Packets
|
||||
return o
|
||||
}
|
||||
{
|
||||
// TODO: remove this workaround once travis has workers with a newer kernel
|
||||
// than its current Ubuntu trusty kernel (Linux 4.4.0):
|
||||
var filtered []nftables.Obj
|
||||
for _, obj := range objs {
|
||||
co, ok := obj.(*nftables.CounterObj)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if co.Table.Name != o.Table.Name {
|
||||
continue
|
||||
}
|
||||
filtered = append(filtered, obj)
|
||||
}
|
||||
objs = filtered
|
||||
}
|
||||
if got, want := len(objs), 1; got != want {
|
||||
log.Printf("could not carry counter values: unexpected number of objects in table %v: got %d, want %d", o.Table.Name, got, want)
|
||||
o.Bytes = DefaultCounterObj.Bytes
|
||||
o.Packets = DefaultCounterObj.Packets
|
||||
return o
|
||||
}
|
||||
if co, ok := objs[0].(*nftables.CounterObj); ok {
|
||||
if co, ok := obj.(*nftables.CounterObj); ok {
|
||||
return co
|
||||
}
|
||||
o.Bytes = DefaultCounterObj.Bytes
|
||||
@ -630,14 +878,99 @@ func getCounterObj(c *nftables.Conn, o *nftables.CounterObj) *nftables.CounterOb
|
||||
return o
|
||||
}
|
||||
|
||||
func hairpinDNAT() []expr.Any {
|
||||
return []expr.Any{
|
||||
// [ meta load oifname => reg 1 ]
|
||||
&expr.Meta{Key: expr.MetaKeyIIFNAME, Register: 1},
|
||||
// [ cmp eq reg 1 0x306e616c 0x00000000 0x00000000 0x00000000 ]
|
||||
&expr.Cmp{
|
||||
Op: expr.CmpOpEq,
|
||||
Register: 1,
|
||||
Data: nfifname("lan0"),
|
||||
},
|
||||
|
||||
// [ meta load oifname => reg 1 ]
|
||||
&expr.Meta{Key: expr.MetaKeyOIFNAME, Register: 1},
|
||||
// [ cmp eq reg 1 0x306e616c 0x00000000 0x00000000 0x00000000 ]
|
||||
&expr.Cmp{
|
||||
Op: expr.CmpOpEq,
|
||||
Register: 1,
|
||||
Data: nfifname("lan0"),
|
||||
},
|
||||
|
||||
// [ ct load status => reg 1 ]
|
||||
&expr.Ct{
|
||||
Register: 1,
|
||||
SourceRegister: false,
|
||||
Key: expr.CtKeySTATUS,
|
||||
},
|
||||
// [ bitwise reg 1 = (reg=1 & 0x00000020 ) ^ 0x00000000 ]
|
||||
&expr.Bitwise{
|
||||
DestRegister: 1,
|
||||
SourceRegister: 1,
|
||||
Len: 4,
|
||||
Mask: []byte{0x20, 0x00, 0x00, 0x00},
|
||||
Xor: []byte{0x00, 0x00, 0x00, 0x00},
|
||||
},
|
||||
|
||||
// [ cmp neq reg 1 0x00000000 ]
|
||||
&expr.Cmp{
|
||||
Op: expr.CmpOpNeq,
|
||||
Register: 1,
|
||||
Data: []byte{0x00, 0x00, 0x00, 0x00},
|
||||
},
|
||||
// [ masq ]
|
||||
&expr.Masq{},
|
||||
}
|
||||
}
|
||||
|
||||
const pfChain = "router7-portforwardings"
|
||||
|
||||
// Only update port forwarding if there are existing rules.
|
||||
// This is required to not stomp over podman port forwarding, for example.
|
||||
func updatePortforwardingsOnly(dir, ifname string) error {
|
||||
c := &nftables.Conn{}
|
||||
|
||||
nat, err := c.ListTable("nat")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
chain, err := c.ListChain(nat, pfChain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf("rules already configured, only updating port forwardings")
|
||||
|
||||
c.FlushChain(chain)
|
||||
if err := applyPortForwardings(dir, ifname, c, nat, chain); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.Flush()
|
||||
}
|
||||
|
||||
func applyFirewall(dir, ifname string) error {
|
||||
c := &nftables.Conn{}
|
||||
|
||||
if err := updatePortforwardingsOnly(dir, ifname); err != nil {
|
||||
log.Printf("could not update port forwardings (%v), creating ruleset from scratch", err)
|
||||
} else {
|
||||
return nil // keep existing ruleset
|
||||
}
|
||||
|
||||
c.FlushRuleset()
|
||||
|
||||
nat := c.AddTable(&nftables.Table{
|
||||
Family: nftables.TableFamilyIPv4,
|
||||
Name: "nat",
|
||||
Name: "nat-gokrazy",
|
||||
})
|
||||
|
||||
pf := c.AddChain(&nftables.Chain{
|
||||
Name: pfChain,
|
||||
Table: nat,
|
||||
Type: nftables.ChainTypeNAT,
|
||||
})
|
||||
|
||||
prerouting := c.AddChain(&nftables.Chain{
|
||||
@ -648,6 +981,17 @@ func applyFirewall(dir, ifname string) error {
|
||||
Type: nftables.ChainTypeNAT,
|
||||
})
|
||||
|
||||
c.AddRule(&nftables.Rule{
|
||||
Table: nat,
|
||||
Chain: prerouting,
|
||||
Exprs: []expr.Any{
|
||||
&expr.Verdict{
|
||||
Kind: expr.VerdictJump,
|
||||
Chain: pfChain,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
postrouting := c.AddChain(&nftables.Chain{
|
||||
Name: "postrouting",
|
||||
Hooknum: nftables.ChainHookPostrouting,
|
||||
@ -673,18 +1017,24 @@ func applyFirewall(dir, ifname string) error {
|
||||
},
|
||||
})
|
||||
|
||||
if err := applyPortForwardings(dir, ifname, c, nat, prerouting); err != nil {
|
||||
c.AddRule(&nftables.Rule{
|
||||
Table: nat,
|
||||
Chain: postrouting,
|
||||
Exprs: hairpinDNAT(),
|
||||
})
|
||||
|
||||
if err := applyPortForwardings(dir, ifname, c, nat, pf); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
filter4 := c.AddTable(&nftables.Table{
|
||||
Family: nftables.TableFamilyIPv4,
|
||||
Name: "filter",
|
||||
Name: "filter-gokrazy",
|
||||
})
|
||||
|
||||
filter6 := c.AddTable(&nftables.Table{
|
||||
Family: nftables.TableFamilyIPv6,
|
||||
Name: "filter",
|
||||
Name: "filter-gokrazy",
|
||||
})
|
||||
|
||||
for _, filter := range []*nftables.Table{filter4, filter6} {
|
||||
@ -782,6 +1132,56 @@ func applyFirewall(dir, ifname string) error {
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
input := c.AddChain(&nftables.Chain{
|
||||
Name: "input",
|
||||
Hooknum: nftables.ChainHookInput,
|
||||
Priority: nftables.ChainPriorityFilter,
|
||||
Table: filter,
|
||||
Type: nftables.ChainTypeFilter,
|
||||
})
|
||||
|
||||
counterObj = getCounterObj(c, &nftables.CounterObj{
|
||||
Table: filter,
|
||||
Name: "inputc",
|
||||
})
|
||||
counter = c.AddObj(counterObj).(*nftables.CounterObj)
|
||||
c.AddRule(&nftables.Rule{
|
||||
Table: filter,
|
||||
Chain: input,
|
||||
Exprs: []expr.Any{
|
||||
// [ counter name input ]
|
||||
&expr.Objref{
|
||||
Type: NFT_OBJECT_COUNTER,
|
||||
Name: counter.Name,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
output := c.AddChain(&nftables.Chain{
|
||||
Name: "output",
|
||||
Hooknum: nftables.ChainHookOutput,
|
||||
Priority: nftables.ChainPriorityFilter,
|
||||
Table: filter,
|
||||
Type: nftables.ChainTypeFilter,
|
||||
})
|
||||
|
||||
counterObj = getCounterObj(c, &nftables.CounterObj{
|
||||
Table: filter,
|
||||
Name: "outputc",
|
||||
})
|
||||
counter = c.AddObj(counterObj).(*nftables.CounterObj)
|
||||
c.AddRule(&nftables.Rule{
|
||||
Table: filter,
|
||||
Chain: output,
|
||||
Exprs: []expr.Any{
|
||||
// [ counter name output ]
|
||||
&expr.Objref{
|
||||
Type: NFT_OBJECT_COUNTER,
|
||||
Name: counter.Name,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return c.Flush()
|
||||
@ -806,6 +1206,8 @@ func applySysctl(ifname string) error {
|
||||
sysctls := []string{
|
||||
"net.ipv4.ip_forward=1",
|
||||
"net.ipv6.conf.all.forwarding=1",
|
||||
"net.ipv4.icmp_ratelimit=0",
|
||||
"net.ipv6.icmp.ratelimit=0",
|
||||
}
|
||||
if ifname != "" {
|
||||
sysctls = append(sysctls, "net.ipv6.conf."+ifname+".accept_ra=2")
|
||||
@ -823,10 +1225,20 @@ func applySysctl(ifname string) error {
|
||||
}
|
||||
|
||||
func Apply(dir, root string, firewall bool) error {
|
||||
var cfg InterfaceConfig
|
||||
b, err := ioutil.ReadFile(filepath.Join(dir, "interfaces.json"))
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
if err == nil || os.IsNotExist(err) {
|
||||
if err := json.Unmarshal(b, &cfg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: split into two parts: delay the up until later
|
||||
if err := applyInterfaces(dir, root); err != nil {
|
||||
return fmt.Errorf("interfaces: %v", err)
|
||||
// TODO: split apply into two parts: delay the up until later
|
||||
if err := applyInterfaces(dir, root, cfg); err != nil {
|
||||
return fmt.Errorf("interfaces: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
var errors []error
|
||||
@ -835,7 +1247,7 @@ func Apply(dir, root string, firewall bool) error {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
if err := applyDhcp4(dir); err != nil {
|
||||
if err := applyDhcp4(dir, cfg); err != nil {
|
||||
appendError(fmt.Errorf("dhcp4: %v", err))
|
||||
}
|
||||
|
||||
@ -868,6 +1280,24 @@ func Apply(dir, root string, firewall bool) error {
|
||||
if err := applyFirewall(dir, ifname); err != nil {
|
||||
appendError(fmt.Errorf("firewall: %v", err))
|
||||
}
|
||||
} else {
|
||||
if _, err := os.Stat("/user/nft"); err == nil {
|
||||
log.Println("Applying custom firewall")
|
||||
cmd := &exec.Cmd{
|
||||
Path: "/user/nft",
|
||||
Args: []string{"/user/nft", "-ef", "/etc/firewall.nft"},
|
||||
Env: cleanEnviron(os.Environ()),
|
||||
Stdout: os.Stdout,
|
||||
Stderr: os.Stderr,
|
||||
}
|
||||
if err := cmd.Run(); err != nil {
|
||||
appendError(fmt.Errorf("firewall: nft: %v", err))
|
||||
} else {
|
||||
log.Println("Custom firewall successfully applied:", cmd.ProcessState.ExitCode())
|
||||
}
|
||||
} else {
|
||||
log.Println("Firewall Disabled")
|
||||
}
|
||||
}
|
||||
|
||||
if err := applyWireGuard(dir); err != nil {
|
||||
@ -879,3 +1309,12 @@ func Apply(dir, root string, firewall bool) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func cleanEnviron(environ []string) []string {
|
||||
for i, env := range environ {
|
||||
if strings.Contains(env, "GOKRAZY") {
|
||||
environ[i] = ""
|
||||
}
|
||||
}
|
||||
return environ
|
||||
}
|
||||
|
@ -18,6 +18,8 @@ package radvd
|
||||
import (
|
||||
"log"
|
||||
"net"
|
||||
"net/netip"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@ -92,6 +94,10 @@ func (s *Server) Serve(ifname string, conn net.PacketConn) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !strings.HasSuffix(addr.String(), "%"+ifname) {
|
||||
log.Printf("ignoring off-interface request from %v", addr)
|
||||
continue
|
||||
}
|
||||
// TODO: isn’t this guaranteed by the filter above?
|
||||
if n == 0 ||
|
||||
ipv6.ICMPType(buf[0]) != ipv6.ICMPTypeRouterSolicitation {
|
||||
@ -144,21 +150,21 @@ func (s *Server) sendAdvertisement(addr net.Addr) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var linkLocal net.IP
|
||||
var linkLocal netip.Addr
|
||||
for _, addr := range addrs {
|
||||
ipnet, ok := addr.(*net.IPNet)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if ipv6LinkLocal.Contains(ipnet.IP) {
|
||||
linkLocal = ipnet.IP
|
||||
linkLocal, _ = netip.AddrFromSlice(ipnet.IP)
|
||||
break
|
||||
}
|
||||
}
|
||||
if !linkLocal.Equal(net.IPv6zero) {
|
||||
if linkLocal.IsValid() && !linkLocal.IsUnspecified() {
|
||||
options = append(options, &ndp.RecursiveDNSServer{
|
||||
Lifetime: 30 * time.Minute,
|
||||
Servers: []net.IP{linkLocal},
|
||||
Servers: []netip.Addr{linkLocal},
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -170,13 +176,14 @@ func (s *Server) sendAdvertisement(addr net.Addr) error {
|
||||
ones = 64
|
||||
}
|
||||
|
||||
addr, _ := netip.AddrFromSlice(prefix.IP)
|
||||
options = append(options, &ndp.PrefixInformation{
|
||||
PrefixLength: uint8(ones),
|
||||
OnLink: true,
|
||||
AutonomousAddressConfiguration: true,
|
||||
ValidLifetime: 2 * time.Hour,
|
||||
PreferredLifetime: 30 * time.Minute,
|
||||
Prefix: prefix.IP,
|
||||
Prefix: addr,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -19,29 +19,62 @@ Connect your serial adapter ([usbcom1a](https://pcengines.ch/usbcom1a.htm) works
|
||||
|
||||
Connect a network cable on `net0`, the port closest to the serial console port:
|
||||
|
||||
<img src="https://github.com/rtr7/router7/raw/master/devsetup.jpg"
|
||||
<img src="https://raw.githubusercontent.com/rtr7/router7/master/devsetup.jpg"
|
||||
width="800" alt="router7 development setup">
|
||||
|
||||
Next, build a router7 image:
|
||||
Next, create a router7 gokrazy instance (see [gokrazy
|
||||
quickstart](https://gokrazy.org/quickstart/) if you’re unfamiliar with gokrazy):
|
||||
|
||||
```shell
|
||||
go get -u github.com/gokrazy/tools/cmd/gokr-packer github.com/rtr7/tools/cmd/...
|
||||
go get -u -d github.com/rtr7/router7
|
||||
```bash
|
||||
go install github.com/gokrazy/tools/cmd/gok@main
|
||||
go install github.com/rtr7/tools/cmd/...@latest
|
||||
mkdir /tmp/recovery
|
||||
GOARCH=amd64 gokr-packer \
|
||||
-hostname=router7 \
|
||||
-overwrite_boot=/tmp/recovery/boot.img \
|
||||
-overwrite_mbr=/tmp/recovery/mbr.img \
|
||||
-overwrite_root=/tmp/recovery/root.img \
|
||||
-eeprom_package= \
|
||||
-kernel_package=github.com/rtr7/kernel \
|
||||
-firmware_package=github.com/rtr7/kernel \
|
||||
-gokrazy_pkgs=github.com/gokrazy/gokrazy/cmd/ntp \
|
||||
-serial_console=ttyS0,115200n8 \
|
||||
github.com/rtr7/router7/cmd/...
|
||||
gok -i router7 new
|
||||
gok -i router7 edit
|
||||
```
|
||||
|
||||
Run `rtr7-recover -boot=/tmp/recovery/boot.img -mbr=/tmp/recovery/mbr.img -root=/tmp/recovery/root.img` to:
|
||||
Change the config until you have the following fields set:
|
||||
|
||||
```json
|
||||
{
|
||||
"Hostname": "router7",
|
||||
"Packages": [
|
||||
"github.com/gokrazy/fbstatus",
|
||||
"github.com/gokrazy/hello",
|
||||
"github.com/gokrazy/serial-busybox",
|
||||
"github.com/gokrazy/breakglass"
|
||||
"github.com/rtr7/router7/cmd/..."
|
||||
],
|
||||
"SerialConsole": "ttyS0,115200",
|
||||
"GokrazyPackages": [
|
||||
"github.com/gokrazy/gokrazy/cmd/ntp",
|
||||
"github.com/gokrazy/gokrazy/cmd/randomd"
|
||||
],
|
||||
"KernelPackage": "github.com/rtr7/kernel",
|
||||
"FirmwarePackage": "github.com/rtr7/kernel",
|
||||
"EEPROMPackage": ""
|
||||
}
|
||||
```
|
||||
|
||||
Then, build an image:
|
||||
|
||||
```bash
|
||||
GOARCH=amd64 gok -i router7 overwrite \
|
||||
--boot /tmp/recovery/boot.img \
|
||||
--mbr /tmp/recovery/mbr.img \
|
||||
--root /tmp/recovery/root.img
|
||||
```
|
||||
|
||||
And serve the image for netboot installation:
|
||||
|
||||
```bash
|
||||
rtr7-recover \
|
||||
--boot /tmp/recovery/boot.img \
|
||||
--mbr /tmp/recovery/mbr.img \
|
||||
--root /tmp/recovery/root.img
|
||||
```
|
||||
|
||||
Specifically, `rtr7-recover`:
|
||||
|
||||
* trigger a reset [if a Teensy with the rebootor firmware is attached](#rebootor)
|
||||
* serve a DHCP lease to all clients which request PXE boot (i.e., your apu2c4)
|
||||
@ -107,8 +140,6 @@ Example:
|
||||
Schema: see [`portForwardings`](
|
||||
https://github.com/rtr7/router7/blob/f86e20be5305fc0e7e77421e0f2abde98a84f2a7/internal/netconfig/netconfig.go#L431)
|
||||
|
||||
Please be aware that Hairpinning is currently not supported (see issue [#53 Support for Hairpinning](https://github.com/rtr7/router7/issues/53]))
|
||||
|
||||
## Updates
|
||||
|
||||
Run e.g. `rtr7-safe-update -updates_dir=$HOME/router7/updates` to:
|
||||
|
Loading…
x
Reference in New Issue
Block a user