Compare commits
35 Commits
Author | SHA1 | Date | |
---|---|---|---|
61b59517fc | |||
b801bf699f | |||
e34b880a55 | |||
ac0ef71d9f | |||
9533787aac | |||
29eaa11052 | |||
9ee285e139 | |||
ef50f7c2e4 | |||
a592bbc76a | |||
9f4380a4a3 | |||
3834acfa2b | |||
c30bf38438 | |||
5f25043b94 | |||
c3c531931c | |||
32b0dc7d59 | |||
04f2be01d9 | |||
e5ea79aef8 | |||
f8d1b4c8f2 | |||
8de4eb7ba1 | |||
0507d93b3d | |||
7f135438b8 | |||
a8fce3cbbc | |||
99c4046ebf | |||
efbe826a4e | |||
416c1a58f6 | |||
f8d79d0ecc | |||
fddfe80222 | |||
876f8e320f | |||
93fe6457b3 | |||
a34a03e036 | |||
68105841c6 | |||
1789f1e94c | |||
55ac682d36 | |||
5f01503df6 | |||
ce29a6f436 |
8
Makefile
8
Makefile
@ -20,7 +20,7 @@ ifndef DIR
|
||||
@echo variable DIR unset
|
||||
false
|
||||
endif
|
||||
go install github.com/gokrazy/tools/cmd/gokr-packer
|
||||
go install github.com/gokrazy/tools/cmd/gokr-packer@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 \
|
||||
@ -35,8 +35,8 @@ endif
|
||||
|
||||
recover: #test
|
||||
go install \
|
||||
github.com/gokrazy/tools/cmd/gokr-packer \
|
||||
github.com/rtr7/tools/cmd/rtr7-recover
|
||||
github.com/gokrazy/tools/cmd/gokr-packer@lastet \
|
||||
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 \
|
||||
@ -70,7 +70,7 @@ 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 ~/router7 image DIR=$GOKR_DIR'
|
||||
rtr7-safe-update -build_command='make -C ~/go/src/github.com/rtr7/router7 image DIR=$$GOKR_DIR'
|
||||
|
||||
# sudo ip link add link enp0s31f6 name macvtap0 type macvtap
|
||||
# sudo ip link set macvtap0 address 52:55:00:d1:55:03 up
|
||||
|
@ -68,6 +68,7 @@ func logic() error {
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
if err := logic(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
@ -17,11 +17,14 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path"
|
||||
@ -48,6 +51,45 @@ var (
|
||||
perm = flag.String("perm", "/perm", "path to replace /perm")
|
||||
)
|
||||
|
||||
func healthy() error {
|
||||
req, err := http.NewRequest("GET", "http://localhost:7733/health.json", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ctx, canc := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer canc()
|
||||
req = req.WithContext(ctx)
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if got, want := resp.StatusCode, http.StatusOK; got != want {
|
||||
b, _ := ioutil.ReadAll(resp.Body)
|
||||
return fmt.Errorf("%v: got HTTP %v (%s), want HTTP status %v",
|
||||
req.URL.String(),
|
||||
resp.Status,
|
||||
string(b),
|
||||
want)
|
||||
}
|
||||
b, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var reply struct {
|
||||
FirstError string `json:"first_error"`
|
||||
}
|
||||
if err := json.Unmarshal(b, &reply); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if reply.FirstError != "" {
|
||||
return errors.New(reply.FirstError)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func logic() error {
|
||||
leasePath := filepath.Join(*stateDir, "wire/lease.json")
|
||||
if err := os.MkdirAll(filepath.Dir(leasePath), 0755); err != nil {
|
||||
@ -94,6 +136,7 @@ func logic() error {
|
||||
Min: 10 * time.Second,
|
||||
Max: 1 * time.Minute,
|
||||
}
|
||||
ObtainOrRenew:
|
||||
for c.ObtainOrRenew() {
|
||||
if err := c.Err(); err != nil {
|
||||
dur := backoff.Duration()
|
||||
@ -124,15 +167,42 @@ func logic() error {
|
||||
if err := notify.Process(path.Join(path.Dir(os.Args[0]), "/netconfigd"), syscall.SIGUSR1); err != nil {
|
||||
log.Printf("notifying netconfig: %v", err)
|
||||
}
|
||||
select {
|
||||
case <-time.After(time.Until(c.Config().RenewAfter)):
|
||||
// fallthrough and renew the DHCP lease
|
||||
case <-usr2:
|
||||
log.Printf("SIGUSR2 received, sending DHCPRELEASE")
|
||||
if err := c.Release(); err != nil {
|
||||
return err
|
||||
|
||||
unhealthyCycles := 0
|
||||
for {
|
||||
select {
|
||||
case <-time.After(time.Until(c.Config().RenewAfter)):
|
||||
// fallthrough and renew the DHCP lease
|
||||
continue ObtainOrRenew
|
||||
|
||||
case <-time.After(1 * time.Minute):
|
||||
if err := healthy(); err == nil {
|
||||
unhealthyCycles = 0
|
||||
continue // wait another minute
|
||||
} else {
|
||||
unhealthyCycles++
|
||||
log.Printf("router unhealthy (cycle %d of 5): %v", unhealthyCycles, err)
|
||||
if unhealthyCycles < 5 {
|
||||
continue // wait until unhealthy for longer
|
||||
}
|
||||
// fallthrough
|
||||
}
|
||||
// Still not healthy? Drop DHCP lease and start from scratch.
|
||||
log.Printf("unhealthy for 5 cycles, starting over without lease")
|
||||
c.Ack = nil
|
||||
|
||||
case <-usr2:
|
||||
log.Printf("SIGUSR2 received, sending DHCPRELEASE")
|
||||
if err := c.Release(); err != nil {
|
||||
return err
|
||||
}
|
||||
// Ensure dhcp4 does start from scratch next time
|
||||
// by deleting the DHCPACK file:
|
||||
if err := os.Remove(ackFn); err != nil && !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
os.Exit(125) // quit supervision by gokrazy
|
||||
}
|
||||
os.Exit(125) // quit supervision by gokrazy
|
||||
}
|
||||
}
|
||||
return c.Err() // permanent error
|
||||
|
@ -239,6 +239,8 @@ type srv struct {
|
||||
}
|
||||
|
||||
func newSrv(permDir string) (*srv, error) {
|
||||
mayqtt := MQTT()
|
||||
|
||||
http.Handle("/metrics", promhttp.Handler())
|
||||
if err := updateListeners(); err != nil {
|
||||
return nil, err
|
||||
@ -266,18 +268,19 @@ func newSrv(permDir string) (*srv, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
serverIP = serverIP.To4()
|
||||
var domainSearch []byte
|
||||
domainSearch, err = dhcp4d.CompressNames("lan.", *domain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
options := dhcp4.Options{
|
||||
dhcp4.OptionSubnetMask: []byte{255, 255, 255, 0},
|
||||
dhcp4.OptionRouter: []byte(serverIP),
|
||||
dhcp4.OptionDomainNameServer: []byte(serverIP),
|
||||
dhcp4.OptionTimeServer: []byte(serverIP),
|
||||
dhcp4.OptionDomainName: []byte(*domain),
|
||||
dhcp4.OptionDomainSearch: domainSearch,
|
||||
dhcp4.OptionSubnetMask: []byte{255, 255, 255, 0},
|
||||
dhcp4.OptionRouter: []byte(serverIP),
|
||||
dhcp4.OptionDomainNameServer: []byte(serverIP),
|
||||
dhcp4.OptionNetworkTimeProtocolServers: []byte(serverIP),
|
||||
dhcp4.OptionDomainName: []byte(*domain),
|
||||
dhcp4.OptionDomainSearch: domainSearch,
|
||||
}
|
||||
|
||||
handler, err := dhcp4d.NewHandler(permDir, ifc, *iface, nil, options)
|
||||
@ -303,7 +306,10 @@ func newSrv(permDir string) (*srv, error) {
|
||||
http.Error(w, "missing hostname parameter", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
handler.SetHostname(hwaddr, hostname)
|
||||
if err := handler.SetHostname(hwaddr, hostname); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
http.Redirect(w, r, "/", http.StatusFound)
|
||||
})
|
||||
|
||||
@ -420,6 +426,38 @@ func newSrv(permDir string) (*srv, error) {
|
||||
if err := notify.Process(path.Join(path.Dir(os.Args[0]), "/dnsd"), syscall.SIGUSR1); err != nil {
|
||||
log.Printf("notifying dnsd: %v", err)
|
||||
}
|
||||
|
||||
// Publish the DHCP lease as JSON to MQTT, if configured:
|
||||
leaseVal := struct {
|
||||
Addr string `json:"addr"`
|
||||
HardwareAddr string `json:"hardware_addr"`
|
||||
Expiration time.Time `json:"expiration"`
|
||||
}{
|
||||
Addr: latest.Addr.String(),
|
||||
HardwareAddr: latest.HardwareAddr,
|
||||
Expiration: latest.Expiry.In(time.UTC),
|
||||
}
|
||||
leaseJSON, err := json.Marshal(leaseVal)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
// MQTT requires valid UTF-8 and some brokers don’t cope well with
|
||||
// invalid UTF-8: https://github.com/fhmq/hmq/issues/104
|
||||
identifier := strings.ToValidUTF8(latest.Hostname, "")
|
||||
if identifier == "" {
|
||||
identifier = latest.HardwareAddr
|
||||
}
|
||||
select {
|
||||
case mayqtt <- PublishRequest{
|
||||
Topic: "router7/dhcp4d/lease/" + identifier,
|
||||
Retained: true,
|
||||
Payload: leaseJSON,
|
||||
}:
|
||||
default:
|
||||
// Channel not ready? skip publishing this lease (best-effort).
|
||||
// This is an easy way of breaking circular dependencies between
|
||||
// MQTT broker and DHCP server, and avoiding deadlocks.
|
||||
}
|
||||
}
|
||||
conn, err := conn.NewUDP4BoundListener(*iface, ":67")
|
||||
if err != nil {
|
||||
|
54
cmd/dhcp4d/mayqtt.go
Normal file
54
cmd/dhcp4d/mayqtt.go
Normal file
@ -0,0 +1,54 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
|
||||
mqtt "github.com/eclipse/paho.mqtt.golang"
|
||||
)
|
||||
|
||||
type PublishRequest struct {
|
||||
Topic string
|
||||
Qos byte
|
||||
Retained bool
|
||||
Payload interface{}
|
||||
}
|
||||
|
||||
func publisherLoop(requests <-chan PublishRequest) error {
|
||||
const configFn = "/perm/dhcp4d/mqtt-broker.txt"
|
||||
b, err := ioutil.ReadFile(configFn)
|
||||
if err != nil {
|
||||
// discard requests:
|
||||
for range requests {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
// e.g. tcp://10.0.0.54:1883, which is a static DHCP lease for the dr.lan
|
||||
// Raspberry Pi, which is running an MQTT broker in my network.
|
||||
broker := strings.TrimSpace(string(b))
|
||||
log.Printf("Connecting to MQTT broker %q (configured in %s)", broker, configFn)
|
||||
opts := mqtt.NewClientOptions().AddBroker(broker)
|
||||
opts.SetClientID("dhcp4d")
|
||||
opts.SetConnectRetry(true)
|
||||
mqttClient := mqtt.NewClient(opts)
|
||||
if token := mqttClient.Connect(); token.Wait() && token.Error() != nil {
|
||||
return fmt.Errorf("MQTT connection failed: %v", token.Error())
|
||||
}
|
||||
|
||||
for r := range requests {
|
||||
// discard Token, MQTT publishing is best-effort
|
||||
_ = mqttClient.Publish(r.Topic, r.Qos, r.Retained, r.Payload)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func MQTT() chan<- PublishRequest {
|
||||
result := make(chan PublishRequest)
|
||||
go func() {
|
||||
if err := publisherLoop(result); err != nil {
|
||||
log.Print(err)
|
||||
}
|
||||
}()
|
||||
return result
|
||||
}
|
@ -34,12 +34,12 @@ import (
|
||||
|
||||
"github.com/rtr7/router7/internal/diag"
|
||||
"github.com/rtr7/router7/internal/multilisten"
|
||||
|
||||
_ "net/http/pprof"
|
||||
)
|
||||
|
||||
var httpListeners = multilisten.NewPool()
|
||||
|
||||
var perm = flag.String("perm", "/perm", "path to replace /perm")
|
||||
|
||||
func updateListeners() error {
|
||||
hosts, err := gokrazy.PrivateInterfaceAddrs()
|
||||
if err != nil {
|
||||
@ -81,10 +81,20 @@ func firstError(re *diag.EvalResult) string {
|
||||
}
|
||||
|
||||
func logic() error {
|
||||
var (
|
||||
ifname = flag.String("interface",
|
||||
"uplink0",
|
||||
"interface name to query")
|
||||
perm = flag.String("perm",
|
||||
"/perm",
|
||||
"path to replace /perm")
|
||||
)
|
||||
const (
|
||||
uplink = "uplink0" /* enp0s31f6 */
|
||||
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().
|
||||
@ -135,9 +145,6 @@ func logic() error {
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
diag.Perm = *perm
|
||||
|
||||
if err := logic(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
@ -39,20 +39,21 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
httpListeners = multilisten.NewPool()
|
||||
dnsListeners = multilisten.NewPool()
|
||||
httpListeners = multilisten.NewPool()
|
||||
dnsUDPListeners = multilisten.NewPool()
|
||||
dnsTCPListeners = multilisten.NewPool()
|
||||
|
||||
perm = flag.String("perm", "/perm", "path to replace /perm")
|
||||
domain = flag.String("domain", "lan", "domain name for your network")
|
||||
)
|
||||
|
||||
func updateListeners(mux *miekgdns.ServeMux) error {
|
||||
hosts, err := gokrazy.PrivateInterfaceAddrs()
|
||||
privateAddrs, err := gokrazy.PrivateInterfaceAddrs()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dnsListeners.ListenAndServe(hosts, func(host string) multilisten.Listener {
|
||||
dnsUDPListeners.ListenAndServe(privateAddrs, func(host string) multilisten.Listener {
|
||||
return &listenerAdapter{&miekgdns.Server{
|
||||
Addr: net.JoinHostPort(host, "53"),
|
||||
Net: "udp",
|
||||
@ -60,11 +61,19 @@ func updateListeners(mux *miekgdns.ServeMux) error {
|
||||
}}
|
||||
})
|
||||
|
||||
if net1, err := multilisten.IPv6Net1(*perm); err == nil {
|
||||
hosts = append(hosts, net1)
|
||||
dnsTCPListeners.ListenAndServe(privateAddrs, func(host string) multilisten.Listener {
|
||||
return &listenerAdapter{&miekgdns.Server{
|
||||
Addr: net.JoinHostPort(host, "53"),
|
||||
Net: "tcp",
|
||||
Handler: mux,
|
||||
}}
|
||||
})
|
||||
|
||||
if net1, err := multilisten.IPv6Net1("/perm"); err == nil {
|
||||
privateAddrs = append(privateAddrs, net1)
|
||||
}
|
||||
|
||||
httpListeners.ListenAndServe(hosts, func(host string) multilisten.Listener {
|
||||
httpListeners.ListenAndServe(privateAddrs, func(host string) multilisten.Listener {
|
||||
return &http.Server{Addr: net.JoinHostPort(host, "8053")}
|
||||
})
|
||||
|
||||
|
43
go.mod
43
go.mod
@ -5,36 +5,33 @@ go 1.13
|
||||
require (
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883
|
||||
github.com/digineo/go-ping v1.0.0
|
||||
github.com/gokrazy/gokrazy v0.0.0-20200801074800-f7c3cb7e0e6a
|
||||
github.com/gokrazy/internal v0.0.0-20200713084155-ab6fc6e02a03 // indirect
|
||||
github.com/google/go-cmp v0.5.0
|
||||
github.com/google/gopacket v1.1.18
|
||||
github.com/google/nftables v0.0.0-20200802175506-c25e4f69b425
|
||||
github.com/google/renameio v0.1.0
|
||||
github.com/insomniacslk/dhcp v0.0.0-20200806210722-3f14f7f8bd9c
|
||||
github.com/eclipse/paho.mqtt.golang v1.3.1
|
||||
github.com/gokrazy/gokrazy v0.0.0-20201006151115-caded4667633
|
||||
github.com/gokrazy/internal v0.0.0-20201230135541-e2046189e529 // indirect
|
||||
github.com/google/go-cmp v0.5.4
|
||||
github.com/google/gopacket v1.1.19
|
||||
github.com/google/nftables v0.0.0-20201230142148-715e31cb3c31
|
||||
github.com/google/renameio v1.0.0
|
||||
github.com/insomniacslk/dhcp v0.0.0-20201112113307-4de412bc85d8
|
||||
github.com/jpillora/backoff v1.0.0
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/krolaw/dhcp4 v0.0.0-20190909130307-a50d88189771
|
||||
github.com/libdns/cloudflare v0.0.0-20200528144945-97886e7873b1
|
||||
github.com/libdns/libdns v0.0.0-20200501023120-186724ffc821
|
||||
github.com/libdns/libdns v0.1.0
|
||||
github.com/mdlayher/ndp v0.0.0-20200602162440-17ab9e3e5567
|
||||
github.com/mdlayher/netlink v1.2.0 // indirect
|
||||
github.com/mdlayher/raw v0.0.0-20191009151244-50f2db8cc065
|
||||
github.com/miekg/dns v1.1.31
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
|
||||
github.com/prometheus/client_golang v1.7.1
|
||||
github.com/prometheus/common v0.11.1 // indirect
|
||||
github.com/miekg/dns v1.1.35
|
||||
github.com/prometheus/client_golang v1.9.0
|
||||
github.com/rtr7/dhcp4 v0.0.0-20181120124042-778e8c2e24a5
|
||||
github.com/sergi/go-diff v1.1.0 // indirect
|
||||
github.com/u-root/u-root v6.0.0+incompatible // indirect
|
||||
github.com/vishvananda/netlink v1.1.0
|
||||
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae // indirect
|
||||
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208
|
||||
golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed
|
||||
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e
|
||||
golang.zx2c4.com/wireguard v0.0.20200320 // indirect
|
||||
github.com/vishvananda/netlink v1.1.1-0.20200221165523-c79a4b7b4066
|
||||
github.com/vishvananda/netns v0.0.0-20201230012202-c4f3ca719c73 // indirect
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad
|
||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a
|
||||
golang.org/x/sys v0.0.0-20201223074533-0d417f636930
|
||||
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324
|
||||
golang.zx2c4.com/wireguard v0.0.20201118 // indirect
|
||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20200609130330-bd2cb7843e1b
|
||||
google.golang.org/protobuf v1.25.0 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
|
||||
)
|
||||
|
161
go.sum
161
go.sum
@ -1,4 +1,3 @@
|
||||
cloud.google.com/go v0.26.0 h1:e0WKqKTd5BnrG8aKH3J3h+QvEIQtSUcf2n5UZ5ZgLtQ=
|
||||
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=
|
||||
@ -23,6 +22,7 @@ github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6l
|
||||
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 h1:sGsd+kAXzT0bfVfzJfce04g+dSRfrs+tbQW8lweuYgw=
|
||||
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=
|
||||
@ -42,8 +42,8 @@ github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee
|
||||
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 h1:6pwm8kMQKCmgUg0ZHTm5+/YvRK0s3THD/28+T6/kk4A=
|
||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@ -56,10 +56,13 @@ github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:Htrtb
|
||||
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.1 h1:6F5FYb1hxVSZS+p0ji5xBQamc5ltOolTYRy5R15uVmI=
|
||||
github.com/eclipse/paho.mqtt.golang v1.3.1/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/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/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=
|
||||
@ -79,11 +82,11 @@ github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFG
|
||||
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-20200801074800-f7c3cb7e0e6a h1:p/pMUGI4GdWyQG6HfQPgIseILKAEpsGeVrhx2JCI7ns=
|
||||
github.com/gokrazy/gokrazy v0.0.0-20200801074800-f7c3cb7e0e6a/go.mod h1:MAXBdw3NnYx7LEQrgebujybMDDpROBGLpeeGxgz9KR4=
|
||||
github.com/gokrazy/gokrazy v0.0.0-20201006151115-caded4667633 h1:SFckkSS3iRkO3NLG2ULSqmCx8sJS5v203kLmeVZlq9A=
|
||||
github.com/gokrazy/gokrazy v0.0.0-20201006151115-caded4667633/go.mod h1:3OoNFHeXa97iZAdGQ/Aoe76TxtTPKHVTO+gipPQWGMU=
|
||||
github.com/gokrazy/internal v0.0.0-20200531194636-d96421c60091/go.mod h1:LA5TQy7LcvYGQOy75tkrYkFUhbV2nl5qEBP47PSi2JA=
|
||||
github.com/gokrazy/internal v0.0.0-20200713084155-ab6fc6e02a03 h1:H2GO8vfBaFo6msfPXPoY6KSqO1HmfDe0eiAc0LYKXOI=
|
||||
github.com/gokrazy/internal v0.0.0-20200713084155-ab6fc6e02a03/go.mod h1:LA5TQy7LcvYGQOy75tkrYkFUhbV2nl5qEBP47PSi2JA=
|
||||
github.com/gokrazy/internal v0.0.0-20201230135541-e2046189e529 h1:tnccQFzZ+1R0EYxypfTm1g+K7B2pLUURz68YLnu1bGk=
|
||||
github.com/gokrazy/internal v0.0.0-20201230135541-e2046189e529/go.mod h1:LA5TQy7LcvYGQOy75tkrYkFUhbV2nl5qEBP47PSi2JA=
|
||||
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=
|
||||
@ -97,8 +100,9 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU
|
||||
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.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
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=
|
||||
@ -107,22 +111,28 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
|
||||
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.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gopacket v1.1.16/go.mod h1:UCLx9mCmAwsVbn6qQl1WIEt2SO7Nd2fD0th1TBAsqBw=
|
||||
github.com/google/gopacket v1.1.18 h1:lum7VRA9kdlvBi7/v2p7/zcbkduHaCH/SVVyurs7OpY=
|
||||
github.com/google/gopacket v1.1.18/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM=
|
||||
github.com/google/nftables v0.0.0-20200802175506-c25e4f69b425 h1:Ob7HrdEgedxSwCofNfvAYCNiuXbcuELBXP+Y2loxpXM=
|
||||
github.com/google/nftables v0.0.0-20200802175506-c25e4f69b425/go.mod h1:cfspEyr/Ap+JDIITA+N9a0ernqG0qZ4W1aqMRgDZa1g=
|
||||
github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA=
|
||||
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-20201230142148-715e31cb3c31 h1:kyEB9geFhgDyawmvavtNu9iGW9ri/iq54XTSNIEeHxI=
|
||||
github.com/google/nftables v0.0.0-20201230142148-715e31cb3c31/go.mod h1:cfspEyr/Ap+JDIITA+N9a0ernqG0qZ4W1aqMRgDZa1g=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/renameio v1.0.0 h1:xhp2CnJmgQmpJU4RY8chagahUq5mbPPAbiSQstKpVMA=
|
||||
github.com/google/renameio v1.0.0/go.mod h1:t/HQoYBZSsWSNK35C6CO/TpPLDVWvxOHboWUAweKUpk=
|
||||
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=
|
||||
@ -148,17 +158,22 @@ github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2p
|
||||
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-20200806210722-3f14f7f8bd9c h1:sGjF7j2eY9V0tCvP2s2tZVoM/9f/I9RYdEtv3qLrtMk=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20200806210722-3f14f7f8bd9c/go.mod h1:CfMdguCK66I5DAUJgGKyNz8aB6vO5dZzkm9Xep6WGvw=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20201112113307-4de412bc85d8 h1:R1oP0/QEyvaL7dm+mBQouQ9V1X6gqQr5taZA1yaq5zQ=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20201112113307-4de412bc85d8/go.mod h1:TKl4jN3Voofo4UJIicyNhWGp/nlQqQkFxmwIFTvBkKI=
|
||||
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/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 h1:nwOc1YaOrYJ37sEBrtWZrdqzK22hiJs3GpDmP3sR2Yw=
|
||||
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 h1:7cpGGTQO6+OuYQWkueqeXuErSjs1NZtpALpv1x7Mq4g=
|
||||
github.com/jsimonetti/rtnetlink v0.0.0-20201110080708-d2c240429e6c/go.mod h1:huN4d1phzjhlOsNIjFsw2SVRbwIHj3fJDMEU2SDPTmg=
|
||||
github.com/jsimonetti/rtnetlink v0.0.0-20201216134343-bde56ed16391 h1:Dqu/4JhMV1vpXHDjzQCuDCEsjNi0xfuSmQlMOyqayKA=
|
||||
github.com/jsimonetti/rtnetlink v0.0.0-20201216134343-bde56ed16391/go.mod h1:cR77jAZG3Y3bsb8hF6fHJbFoyFukLFOkQ98S0pQz3xw=
|
||||
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=
|
||||
@ -173,18 +188,18 @@ github.com/koneu/natend v0.0.0-20150829182554-ec0926ea948d/go.mod h1:QHb4k4cr1fQ
|
||||
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/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
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/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
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.0.0-20200528144945-97886e7873b1 h1:Jx0AoxHtj2NMwxHByM8VmcqvGMa3lEu28xVDArhSi7E=
|
||||
github.com/libdns/cloudflare v0.0.0-20200528144945-97886e7873b1/go.mod h1:A9MqNmkZcd81mY7JsNysmgmj5O9vlRjfDVaNw4j9pjU=
|
||||
github.com/libdns/libdns v0.0.0-20200430163404-ee2c42449104/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40=
|
||||
github.com/libdns/libdns v0.0.0-20200501023120-186724ffc821 h1:663opx/RKxiISi1ozf0WbvweQpYBgf34dx8hKSIau3w=
|
||||
github.com/libdns/libdns v0.0.0-20200501023120-186724ffc821/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40=
|
||||
github.com/libdns/libdns v0.1.0 h1:0ctCOrVJsVzj53mop1angHp/pE3hmAhP7KiHvR0HD04=
|
||||
github.com/libdns/libdns v0.1.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/lucasb-eyer/go-colorful v0.0.0-20181028223441-12d3b2882a08/go.mod h1:NXg0ArsFk0Y01623LgUqoqcouGDB+PwCCQlrwrG6xJ4=
|
||||
@ -196,6 +211,7 @@ github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzp
|
||||
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
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/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=
|
||||
@ -203,14 +219,20 @@ github.com/mdlayher/ndp v0.0.0-20200602162440-17ab9e3e5567/go.mod h1:32w/5dDZWVS
|
||||
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 h1:mpdLgm+brq10nI9zM1BpX1kpDbh3NLl3RSnVq6ZSkfg=
|
||||
github.com/mdlayher/netlink v1.1.0/go.mod h1:H4WCitaheIsdF9yOYu8CFmCgQthAPIWZmcKp9uZHgmY=
|
||||
github.com/mdlayher/netlink v1.1.1 h1:VqG+Voq9V4uZ+04vjIrcSCWDpf91B1xxbP4QBUmUJE8=
|
||||
github.com/mdlayher/netlink v1.1.1/go.mod h1:WTYpFb/WTvlRJAyKhZL5/uy69TDDpHHu2VZmb2XgV7o=
|
||||
github.com/mdlayher/netlink v1.2.0 h1:zPolhRjfuabdf8ofZsl56eoU+92cvSlAn13lw4veCZ0=
|
||||
github.com/mdlayher/netlink v1.2.0/go.mod h1:kwVW1io0AZy9A1E2YYgaD4Cj+C+GPkU6klXCMzIJ9p8=
|
||||
github.com/mdlayher/raw v0.0.0-20190303161257-764d452d77af/go.mod h1:rC/yE65s/DoHB6BzVOUBNYBGTg772JVytyAytffIZkY=
|
||||
github.com/mdlayher/raw v0.0.0-20190606142536-fef19f00fc18/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg=
|
||||
github.com/mdlayher/raw v0.0.0-20191009151244-50f2db8cc065 h1:aFkJ6lx4FPip+S+Uw4aTegFMct9shDvP+79PsSxpm3w=
|
||||
github.com/mdlayher/raw v0.0.0-20191009151244-50f2db8cc065/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg=
|
||||
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.31 h1:sJFOl9BgwbYAWOGEwr61FU28pqsBNdpRBnhGXtO06Oo=
|
||||
github.com/miekg/dns v1.1.31/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
|
||||
github.com/miekg/dns v1.1.35 h1:oTfOaDH+mZkdcgdIjH6yBajRGtIwcwcaR+rt23ZSrJs=
|
||||
github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
|
||||
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=
|
||||
@ -233,8 +255,6 @@ github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzE
|
||||
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/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
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=
|
||||
@ -267,8 +287,9 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP
|
||||
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 h1:NTGy1Ja9pByO+xAeH/qiWnLrKtr3hJPNjaVUwnjpdpA=
|
||||
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
||||
github.com/prometheus/client_golang v1.9.0 h1:Rrch9mh17XcxvEu9D9DEpb4isxjGBtcevQjKvxPRQIU=
|
||||
github.com/prometheus/client_golang v1.9.0/go.mod h1:FqZLKOZnGdFAhOK4nqGHa7D66IdsO+O441Eve7ptJDU=
|
||||
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=
|
||||
@ -279,16 +300,16 @@ github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6T
|
||||
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 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc=
|
||||
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||
github.com/prometheus/common v0.11.1 h1:0ZISXCMRuCZcxF77aT1BXY5m74mX2vrGYl1dSwBI0Jo=
|
||||
github.com/prometheus/common v0.11.1/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
|
||||
github.com/prometheus/common v0.15.0 h1:4fgOnadei3EZvgRwxJ7RMpG1k1pOZth5Pc13tyspaKM=
|
||||
github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
|
||||
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 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFBS8=
|
||||
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.2.0 h1:wH4vA7pcjKuZzjF7lM8awk4fnuJO6idemZXoKnULUx4=
|
||||
github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/rivo/tview v0.0.0-20181226202439-36893a669792/go.mod h1:J4W+hErFfITUbyFAEXizpmkuxX7ZN56dopxHB4XQhMw=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
@ -320,19 +341,20 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
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 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
|
||||
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/u-root v6.0.0+incompatible h1:YqPGmRoRyYmeg17KIWFRSyVq6LX5T6GSzawyA6wG6EE=
|
||||
github.com/u-root/u-root v6.0.0+incompatible/go.mod h1:RYkpo8pTHrNjW08opNd/U6p/RJE7K0D8fXO0d47+3YY=
|
||||
github.com/u-root/u-root v7.0.0+incompatible h1:u+KSS04pSxJGI5E7WE4Bs9+Zd75QjFv+REkjy/aoAc8=
|
||||
github.com/u-root/u-root v7.0.0+incompatible/go.mod h1:RYkpo8pTHrNjW08opNd/U6p/RJE7K0D8fXO0d47+3YY=
|
||||
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.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0=
|
||||
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
|
||||
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-20200728191858-db3c7e526aae h1:4hwBBUfQCFe3Cym0ZtKyq7L16eZUtYKs+BaHDN6mAns=
|
||||
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||
github.com/vishvananda/netns v0.0.0-20201230012202-c4f3ca719c73 h1:JGMFiSX7pNu3l0DRO8sjxgA7ybQNE+HeuKIG23PjsN4=
|
||||
github.com/vishvananda/netns v0.0.0-20201230012202-c4f3ca719c73/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
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=
|
||||
@ -355,18 +377,18 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de h1:ikNHVSjEfnvz6sxdSPCaPt572qowuyMDMJLLm3Db3ig=
|
||||
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/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-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY=
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
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/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=
|
||||
@ -392,11 +414,15 @@ golang.org/x/net v0.0.0-20191003171128-d98b1b443823/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
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 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/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-20201216054612-986b41b23924 h1:QsnDpLLOKwHBBDa8nDws4DYNc/ryVW2vCpxCs09d4PY=
|
||||
golang.org/x/net v0.0.0-20201216054612-986b41b23924/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b h1:iFwSg7t5GZmB/Q5TjiEAsdoLDrdJRC1RiF2WhuV29Qw=
|
||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
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=
|
||||
@ -405,9 +431,10 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a h1:WXEvlFVvvGxCJLG6REjsT03iWnKLEWinaScsxF2Vm2o=
|
||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA=
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs=
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/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=
|
||||
@ -419,38 +446,53 @@ golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5h
|
||||
golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/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-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606122018-79a91cf218c4/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-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191003212358-c178f38b412c/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-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-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200406155108-e3b113bbe6a4/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 h1:Ih9Yo4hSPImZOpfGuA4bR/ORKTAbhZo2AbWNRCnevdo=
|
||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed h1:WBkVNH1zd9jg/dK4HCM4lNANnmd12EHC9z+LmcCG4ns=
|
||||
golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/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-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/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-20201214210602-f9fddec55a1e h1:AyodaIpKjppX+cBfTASF2E1US3H2JFBj920Ot3rtDjs=
|
||||
golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201218084310-7d0127a74742/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201223074533-0d417f636930 h1:vRgIt+nup/B/BwIS0g2oC0haq0iqbV3ZA+u6+0TlNCo=
|
||||
golang.org/x/sys v0.0.0-20201223074533-0d417f636930/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
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-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s=
|
||||
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 h1:Hir2P/De0WpUhtrKGGjvSb2YxUgyZ7EFOSLIcSSpiwE=
|
||||
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/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/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
@ -465,13 +507,14 @@ golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtn
|
||||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
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 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.zx2c4.com/wireguard v0.0.20200121/go.mod h1:P2HsVp8SKwZEufsnezXZA4GRX/T49/HlU7DGuelXsU4=
|
||||
golang.zx2c4.com/wireguard v0.0.20200320 h1:1vE6zVeO7fix9cJX1Z9ZQ+ikPIIx7vIyU0o0tLDD88g=
|
||||
golang.zx2c4.com/wireguard v0.0.20200320/go.mod h1:lDian4Sw4poJ04SgHh35nzMVwGSYlPumkdnHcucAQoY=
|
||||
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-20200609130330-bd2cb7843e1b h1:l4mBVCYinjzZuR5DtxHuBD6wyd4348TGiavJ5vLrhEc=
|
||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20200609130330-bd2cb7843e1b/go.mod h1:UdS9frhv65KTfwxME1xE8+rHYoFpbm36gOud1GhBe9c=
|
||||
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
|
||||
@ -508,9 +551,8 @@ gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0/go.mod h1:OdE7CF6DbADk7lN8LIKRzRJTTZXIjtW
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
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/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/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=
|
||||
@ -524,8 +566,9 @@ 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 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||
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=
|
||||
|
@ -471,3 +471,124 @@ func ipLines(args ...string) ([]string, error) {
|
||||
|
||||
return strings.Split(strings.TrimSpace(outstr), "\n"), nil
|
||||
}
|
||||
|
||||
func TestDHCPv4OldAddressDeconfigured(t *testing.T) {
|
||||
if os.Getenv("HELPER_PROCESS") == "1" {
|
||||
tmp, err := ioutil.TempDir("", "router7")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(tmp)
|
||||
|
||||
for _, golden := range []struct {
|
||||
filename, content string
|
||||
}{
|
||||
{"dhcp4/wire/lease.json", goldenDhcp4},
|
||||
{"interfaces.json", goldenInterfaces},
|
||||
} {
|
||||
if err := os.MkdirAll(filepath.Join(tmp, filepath.Dir(golden.filename)), 0755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := ioutil.WriteFile(filepath.Join(tmp, golden.filename), []byte(golden.content), 0600); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(filepath.Join(tmp, "root", "etc"), 0755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(filepath.Join(tmp, "root", "tmp"), 0755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := netconfig.Apply(tmp, filepath.Join(tmp, "root")); err != nil {
|
||||
t.Fatalf("netconfig.Apply: %v", err)
|
||||
}
|
||||
|
||||
const anotherDhcp4 = `
|
||||
{
|
||||
"valid_until":"2018-05-18T23:46:04.429895261+02:00",
|
||||
"client_ip":"85.195.199.99",
|
||||
"subnet_mask":"255.255.255.128",
|
||||
"router":"85.195.199.1",
|
||||
"dns":[
|
||||
"77.109.128.2",
|
||||
"213.144.129.20"
|
||||
]
|
||||
}
|
||||
`
|
||||
if err := ioutil.WriteFile(filepath.Join(tmp, "dhcp4/wire/lease.json"), []byte(anotherDhcp4), 0600); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := netconfig.Apply(tmp, filepath.Join(tmp, "root")); err != nil {
|
||||
t.Fatalf("netconfig.Apply: %v", err)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
const ns = "ns5" // name of the network namespace to use for this test
|
||||
|
||||
add := exec.Command("ip", "netns", "add", ns)
|
||||
add.Stderr = os.Stderr
|
||||
if err := add.Run(); err != nil {
|
||||
t.Fatalf("%v: %v", add.Args, err)
|
||||
}
|
||||
defer exec.Command("ip", "netns", "delete", ns).Run()
|
||||
|
||||
nsSetup := []*exec.Cmd{
|
||||
exec.Command("ip", "-netns", ns, "link", "add", "dummy0", "type", "dummy"),
|
||||
exec.Command("ip", "-netns", ns, "link", "add", "lan0", "type", "dummy"),
|
||||
exec.Command("ip", "-netns", ns, "link", "set", "dummy0", "address", "02:73:53:00:ca:fe"),
|
||||
exec.Command("ip", "-netns", ns, "link", "set", "lan0", "address", "02:73:53:00:b0:0c"),
|
||||
}
|
||||
|
||||
for _, cmd := range nsSetup {
|
||||
if err := cmd.Run(); err != nil {
|
||||
t.Fatalf("%v: %v", cmd.Args, err)
|
||||
}
|
||||
}
|
||||
|
||||
cmd := exec.Command("ip", "netns", "exec", ns, os.Args[0], "-test.run=^TestDHCPv4OldAddressDeconfigured$")
|
||||
cmd.Env = append(os.Environ(), "HELPER_PROCESS=1")
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
if err := cmd.Run(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
t.Run("VerifyAddresses", func(t *testing.T) {
|
||||
show := exec.Command("ip", "-netns", ns, "address", "show", "dev", "uplink0")
|
||||
show.Stderr = os.Stderr
|
||||
addrs, err := show.Output()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
oldAddrRe := regexp.MustCompile(`(?m)^\s*inet 85.195.207.62/25 brd 85.195.207.127 scope global uplink0$`)
|
||||
if oldAddrRe.MatchString(string(addrs)) {
|
||||
t.Fatalf("regexp %s unexpectedly still matches %s", oldAddrRe, string(addrs))
|
||||
}
|
||||
|
||||
addrRe := regexp.MustCompile(`(?m)^\s*inet 85.195.199.99/25 brd 85.195.199.127 scope global uplink0$`)
|
||||
if !addrRe.MatchString(string(addrs)) {
|
||||
t.Fatalf("regexp %s does not match %s", addrRe, string(addrs))
|
||||
}
|
||||
|
||||
wantRoutes := []string{
|
||||
"default via 85.195.199.1 proto dhcp src 85.195.199.99 ",
|
||||
"85.195.199.0/25 proto kernel scope link src 85.195.199.99 ",
|
||||
"85.195.199.1 proto dhcp scope link src 85.195.199.99",
|
||||
}
|
||||
|
||||
routes, err := ipLines("-netns", ns, "route", "show", "dev", "uplink0")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if diff := cmp.Diff(wantRoutes, routes); diff != "" {
|
||||
t.Fatalf("routes: diff (-want +got):\n%s", diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -44,6 +44,7 @@ type Client struct {
|
||||
|
||||
err error
|
||||
once sync.Once
|
||||
onceErr error
|
||||
connection net.PacketConn
|
||||
hardwareAddr net.HardwareAddr
|
||||
hostname string
|
||||
@ -51,6 +52,8 @@ type Client struct {
|
||||
timeNow func() time.Time
|
||||
generateXID func() uint32
|
||||
|
||||
timeoutCount int
|
||||
|
||||
// last DHCPACK packet for renewal/release
|
||||
Ack *layers.DHCPv4
|
||||
}
|
||||
@ -84,7 +87,6 @@ var errNAK = errors.New("received DHCPNAK")
|
||||
|
||||
// ObtainOrRenew returns false when encountering a permanent error.
|
||||
func (c *Client) ObtainOrRenew() bool {
|
||||
var onceErr error
|
||||
c.once.Do(func() {
|
||||
if c.timeNow == nil {
|
||||
c.timeNow = time.Now
|
||||
@ -94,13 +96,13 @@ func (c *Client) ObtainOrRenew() bool {
|
||||
LinuxSockDGRAM: true,
|
||||
})
|
||||
if err != nil {
|
||||
onceErr = err
|
||||
c.onceErr = err
|
||||
return
|
||||
}
|
||||
c.connection = conn
|
||||
}
|
||||
if c.connection == nil && c.Interface == nil {
|
||||
onceErr = fmt.Errorf("c.Interface is nil")
|
||||
c.onceErr = fmt.Errorf("c.Interface is nil")
|
||||
return
|
||||
}
|
||||
if c.hardwareAddr == nil && c.HWAddr != nil {
|
||||
@ -115,21 +117,32 @@ func (c *Client) ObtainOrRenew() bool {
|
||||
if c.hostname == "" {
|
||||
var utsname unix.Utsname
|
||||
if err := unix.Uname(&utsname); err != nil {
|
||||
onceErr = err
|
||||
c.onceErr = err
|
||||
return
|
||||
}
|
||||
c.hostname = string(utsname.Nodename[:bytes.IndexByte(utsname.Nodename[:], 0)])
|
||||
}
|
||||
})
|
||||
if onceErr != nil {
|
||||
c.err = onceErr
|
||||
if c.onceErr != nil {
|
||||
c.err = c.onceErr
|
||||
return false // permanent error
|
||||
}
|
||||
c.err = nil // clear previous error
|
||||
ack, err := c.dhcpRequest()
|
||||
if err != nil {
|
||||
if errno, ok := err.(syscall.Errno); ok && errno == syscall.EAGAIN {
|
||||
c.err = fmt.Errorf("DHCP: timeout (server(s) unreachable)")
|
||||
var serverip net.IP
|
||||
for _, opt := range c.Ack.Options {
|
||||
if opt.Type == layers.DHCPOptServerID {
|
||||
serverip = opt.Data
|
||||
}
|
||||
}
|
||||
c.err = fmt.Errorf("DHCP: timeout (server(s) unreachable: %v)", serverip)
|
||||
c.timeoutCount++
|
||||
if c.timeoutCount > 3 {
|
||||
c.timeoutCount = 0
|
||||
c.Ack = nil // start over at DHCPDISCOVER it has failed 3 times
|
||||
}
|
||||
return true // temporary error
|
||||
}
|
||||
if err == errNAK {
|
||||
@ -154,6 +167,7 @@ func (c *Client) ObtainOrRenew() bool {
|
||||
}
|
||||
}
|
||||
c.cfg.RenewAfter = c.timeNow().Add(lease.RenewalTime)
|
||||
c.timeoutCount = 0
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -104,13 +104,17 @@ 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,
|
||||
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,
|
||||
options: options,
|
||||
timeNow: time.Now,
|
||||
@ -142,14 +146,18 @@ func (h *Handler) callLeasesLocked(lease *Lease) {
|
||||
h.Leases(leases, lease)
|
||||
}
|
||||
|
||||
func (h *Handler) SetHostname(hwaddr, hostname string) {
|
||||
func (h *Handler) SetHostname(hwaddr, hostname string) error {
|
||||
h.leasesMu.Lock()
|
||||
defer h.leasesMu.Unlock()
|
||||
leaseNum := h.leasesHW[hwaddr]
|
||||
lease := h.leasesIP[leaseNum]
|
||||
if lease.HardwareAddr != hwaddr || lease.Expired(h.timeNow()) {
|
||||
return fmt.Errorf("hwaddr %v does not have a valid lease", hwaddr)
|
||||
}
|
||||
lease.Hostname = hostname
|
||||
lease.HostnameOverride = hostname
|
||||
h.callLeasesLocked(lease)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *Handler) findLease() int {
|
||||
|
@ -73,6 +73,7 @@ func (d *ping4gw) Evaluate() (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer p.Close()
|
||||
rtt, err := p.Ping(addr, timeout)
|
||||
if err != nil {
|
||||
return "", err
|
||||
@ -115,6 +116,7 @@ func (d *ping4) Evaluate() (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer p.Close()
|
||||
rtt, err := p.Ping(addr, timeout)
|
||||
if err != nil {
|
||||
return "", err
|
||||
@ -177,6 +179,7 @@ func (d *ping6gw) Evaluate() (string, error) {
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("ping.New(::): %v", err)
|
||||
}
|
||||
defer p.Close()
|
||||
rtt, err := p.Ping(addr, timeout)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("ping6(%v, %v): %v", addr, timeout, err)
|
||||
@ -251,6 +254,7 @@ func (d *ping6) Evaluate() (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer p.Close()
|
||||
ctx, canc := context.WithTimeout(context.Background(), timeout)
|
||||
defer canc()
|
||||
if strings.HasPrefix(addr.String(), "ff02::") {
|
||||
@ -274,6 +278,11 @@ func (d *ping6) Evaluate() (string, error) {
|
||||
if localAddr[reply.Address.String()] {
|
||||
continue
|
||||
}
|
||||
go func() {
|
||||
for range replies {
|
||||
// drain channel
|
||||
}
|
||||
}()
|
||||
return formatRTT(reply.Duration) + " from " + reply.Address.String(), nil
|
||||
}
|
||||
return "", fmt.Errorf("no responses to %s within %v", addr, timeout)
|
||||
|
@ -92,8 +92,8 @@ func NewServer(addr, domain string) *Server {
|
||||
// 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",
|
||||
"[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",
|
||||
@ -227,10 +227,10 @@ func (s *Server) hostByIP(n string) (string, bool) {
|
||||
return r, ok
|
||||
}
|
||||
|
||||
func (s *Server) subname(hostname, host string) (IP, bool) {
|
||||
func (s *Server) subname(domain, host string) (IP, bool) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
r, ok := s.subnames[lcHostname(strings.ToLower(hostname))][lcHostname(strings.ToLower(host))]
|
||||
r, ok := s.subnames[lcHostname(strings.ToLower(domain))][lcHostname(strings.ToLower(host))]
|
||||
return r, ok
|
||||
}
|
||||
|
||||
@ -536,22 +536,63 @@ func (s *Server) handleRequest(w dns.ResponseWriter, r *dns.Msg) {
|
||||
|
||||
s.promInc("DNS", r)
|
||||
|
||||
for idx, u := range s.upstreams() {
|
||||
in, _, err := s.client.Exchange(r, u)
|
||||
if err != nil {
|
||||
if s.sometimes.Allow() {
|
||||
log.Printf("resolving %v failed: %v", r.Question, err)
|
||||
if r.RecursionDesired {
|
||||
for idx, u := range s.upstreams() {
|
||||
in, _, err := s.client.Exchange(r, u)
|
||||
if err != nil {
|
||||
if s.sometimes.Allow() {
|
||||
log.Printf("resolving %v failed: %v", r.Question, err)
|
||||
}
|
||||
continue // fall back to next-slower upstream
|
||||
}
|
||||
continue // fall back to next-slower upstream
|
||||
if len(in.Answer) > 1 {
|
||||
if in.Answer[0].Header().Rrtype == dns.TypeCNAME {
|
||||
for i, rr := range in.Answer {
|
||||
if rr != nil && rr.Header() != nil && rr.Header().Rrtype == dns.TypeA {
|
||||
newRR, err := s.resolveSubname(string(s.domain), dns.Question{strings.ToLower(rr.Header().Name), dns.TypeA, dns.ClassINET})
|
||||
if err == nil && newRR != nil {
|
||||
in.Answer[i] = newRR
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
w.WriteMsg(in)
|
||||
if idx > 0 {
|
||||
// re-order this upstream to the front of s.upstream.
|
||||
s.upstreamMu.Lock()
|
||||
// if the upstreams were reordered in the meantime leave them alone
|
||||
if s.upstream[idx] == u {
|
||||
s.upstream = append(append([]string{u}, s.upstream[:idx]...), s.upstream[idx+1:]...)
|
||||
}
|
||||
s.upstreamMu.Unlock()
|
||||
}
|
||||
return
|
||||
}
|
||||
w.WriteMsg(in)
|
||||
if idx > 0 {
|
||||
// re-order this upstream to the front of s.upstream.
|
||||
s.upstreamMu.Lock()
|
||||
s.upstream = append(append([]string{u}, s.upstream[:idx]...), s.upstream[idx+1:]...)
|
||||
s.upstreamMu.Unlock()
|
||||
} else {
|
||||
for _, u := range s.upstreams() {
|
||||
nr := r.Copy()
|
||||
nr.Question[0].Qtype = dns.TypeSOA
|
||||
nr.RecursionDesired = true
|
||||
soa, _, err := s.client.Exchange(nr, u)
|
||||
fmt.Println(err, soa)
|
||||
fmt.Println()
|
||||
fmt.Println(soa.Ns)
|
||||
|
||||
if len(soa.Ns) > 0 {
|
||||
soa2 := soa.Ns[0].(*dns.SOA)
|
||||
in, _, err := s.client.Exchange(r, strings.TrimRight(soa2.Ns, ".")+":53")
|
||||
fmt.Println(err, in)
|
||||
if err != nil {
|
||||
if s.sometimes.Allow() {
|
||||
log.Printf("resolving %v failed: %v", r.Question, err)
|
||||
}
|
||||
continue // fall back to next-slower upstream
|
||||
}
|
||||
w.WriteMsg(in)
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
// DNS has no reply for resolving errors
|
||||
}
|
||||
@ -584,13 +625,13 @@ func (s *Server) promInc(label string, r *dns.Msg) {
|
||||
s.prom.upstream.WithLabelValues(label).Inc()
|
||||
}
|
||||
|
||||
func (s *Server) subnameHandler(hostname lcHostname) func(w dns.ResponseWriter, r *dns.Msg) {
|
||||
func (s *Server) subnameHandler(domain lcHostname) func(w dns.ResponseWriter, r *dns.Msg) {
|
||||
return func(w dns.ResponseWriter, r *dns.Msg) {
|
||||
if len(r.Question) != 1 { // TODO: answer all questions we can answer
|
||||
s.promInc("local", r)
|
||||
return
|
||||
}
|
||||
rr, err := s.resolveSubname(string(hostname), r.Question[0])
|
||||
rr, err := s.resolveSubname(string(domain), r.Question[0])
|
||||
|
||||
if err != nil {
|
||||
s.promInc("local", r)
|
||||
|
@ -75,7 +75,8 @@ func applyDhcp4(dir string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
link, err := netlink.LinkByName("uplink0")
|
||||
const linkName = "uplink0"
|
||||
link, err := netlink.LinkByName(linkName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -89,7 +90,8 @@ func applyDhcp4(dir string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
addr, err := netlink.ParseAddr(fmt.Sprintf("%s/%d", got.ClientIP, subnetSize))
|
||||
gotAddr := fmt.Sprintf("%s/%d", got.ClientIP, subnetSize)
|
||||
addr, err := netlink.ParseAddr(gotAddr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -99,8 +101,24 @@ func applyDhcp4(dir string) error {
|
||||
return fmt.Errorf("netlink.NewHandle: %v", err)
|
||||
}
|
||||
defer h.Delete()
|
||||
log.Printf("replacing address %v on %v", addr, linkName)
|
||||
if err := h.AddrReplace(link, addr); err != nil {
|
||||
return fmt.Errorf("AddrReplace(%v): %v", addr, err)
|
||||
return fmt.Errorf("AddrReplace(%v, %v): %v", linkName, addr, err)
|
||||
}
|
||||
|
||||
addrs, err := h.AddrList(link, netlink.FAMILY_V4)
|
||||
if err != nil {
|
||||
return fmt.Errorf("AddrList(%v): %v", linkName, err)
|
||||
}
|
||||
for _, addr := range addrs {
|
||||
ipnet := addr.IPNet.String() // e.g. "85.195.199.99/25"
|
||||
if ipnet == gotAddr {
|
||||
continue
|
||||
}
|
||||
log.Printf("de-configuring old IP address %s from %v", ipnet, linkName)
|
||||
if err := h.AddrDel(link, &addr); err != nil {
|
||||
return fmt.Errorf("AddrDel(%v, %v): %v", linkName, addr, err)
|
||||
}
|
||||
}
|
||||
|
||||
// from include/uapi/linux/rtnetlink.h
|
||||
|
Reference in New Issue
Block a user