Compare commits
27 Commits
Author | SHA1 | Date | |
---|---|---|---|
b801bf699f | |||
e34b880a55 | |||
ac0ef71d9f | |||
9533787aac | |||
29eaa11052 | |||
9ee285e139 | |||
ef50f7c2e4 | |||
a592bbc76a | |||
3834acfa2b | |||
c30bf38438 | |||
5f25043b94 | |||
c3c531931c | |||
32b0dc7d59 | |||
04f2be01d9 | |||
e5ea79aef8 | |||
f8d1b4c8f2 | |||
8de4eb7ba1 | |||
0507d93b3d | |||
7f135438b8 | |||
a8fce3cbbc | |||
99c4046ebf | |||
efbe826a4e | |||
416c1a58f6 | |||
f8d79d0ecc | |||
fddfe80222 | |||
876f8e320f | |||
93fe6457b3 |
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
|
||||
|
@ -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
|
||||
@ -304,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)
|
||||
})
|
||||
|
||||
@ -421,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")}
|
||||
})
|
||||
|
||||
|
21
go.mod
21
go.mod
@ -2,39 +2,36 @@ module github.com/rtr7/router7
|
||||
|
||||
go 1.13
|
||||
|
||||
replace github.com/gokrazy/gokrazy => git.narnian.us/lordwelch/gokrazy v0.0.0-20210109232047-4e1975ff77aa
|
||||
|
||||
require (
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883
|
||||
github.com/digineo/go-ping v1.0.1
|
||||
github.com/gokrazy/gokrazy v0.0.0-20210108081039-067330db5542
|
||||
github.com/digineo/go-ping v1.0.0
|
||||
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.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.35
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
|
||||
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-20210104183010-2eb08e3e575f // 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-20200625203802-6e8e738ad208
|
||||
golang.org/x/sys v0.0.0-20210108172913-0df2131ae363
|
||||
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
|
||||
)
|
||||
|
78
go.sum
78
go.sum
@ -1,7 +1,5 @@
|
||||
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=
|
||||
git.narnian.us/lordwelch/gokrazy v0.0.0-20210109232047-4e1975ff77aa h1:zJZ5VKVhe6LYdxTy3U7JPpXvFCdxumY40OV07OsTjHk=
|
||||
git.narnian.us/lordwelch/gokrazy v0.0.0-20210109232047-4e1975ff77aa/go.mod h1:tUrCiUyBdSLkNIS3w7KZA1nz7lNIS0irf1pBX6J6E44=
|
||||
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=
|
||||
@ -24,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=
|
||||
@ -43,32 +42,33 @@ 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=
|
||||
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/digineo/go-ping v1.0.0 h1:gOuD3YzkIcW/0Y2IAe27bsMKtpfNZdoX1Rnc1RGYOSI=
|
||||
github.com/digineo/go-ping v1.0.0/go.mod h1:YLDBnHoAygacawa2aubI4vXhZ4do5f62oJSvRiJVEjw=
|
||||
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.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/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/gdamore/tcell v1.1.1/go.mod h1:K1udHkiR3cOtlpKG5tZPD5XxrF7v2y7lDq7Whcj+xkQ=
|
||||
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=
|
||||
@ -82,8 +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/internal v0.0.0-20200531194636-d96421c60091 h1:gP2Z4WgsQl35mlNf4kqYW0D8KnYMC4kdsczagvVKBbg=
|
||||
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-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=
|
||||
@ -109,6 +112,7 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
|
||||
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/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=
|
||||
@ -127,6 +131,8 @@ github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51
|
||||
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=
|
||||
@ -166,6 +172,8 @@ github.com/jsimonetti/rtnetlink v0.0.0-20200117123717-f846d4f6c1f4/go.mod h1:WGu
|
||||
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=
|
||||
@ -180,11 +188,11 @@ 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=
|
||||
@ -194,16 +202,13 @@ 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 v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/lucasb-eyer/go-colorful v0.0.0-20181028223441-12d3b2882a08/go.mod h1:NXg0ArsFk0Y01623LgUqoqcouGDB+PwCCQlrwrG6xJ4=
|
||||
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/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=
|
||||
@ -217,6 +222,8 @@ github.com/mdlayher/netlink v1.0.0/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqc
|
||||
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=
|
||||
@ -248,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=
|
||||
@ -306,8 +311,7 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O
|
||||
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-20201204190810-5406288b8e4e/go.mod h1:0ha5CGekam8ZV1kxkBxSlh7gfQ7YolUj2P/VruwH0QY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
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=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rtr7/dhcp4 v0.0.0-20181120124042-778e8c2e24a5 h1:/kzTBQ20DbbhSNaBXiFEk2gPrGhY26kajwC1ro/Vlh8=
|
||||
@ -345,12 +349,12 @@ github.com/u-root/u-root v7.0.0+incompatible h1:u+KSS04pSxJGI5E7WE4Bs9+Zd75QjFv+
|
||||
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-20210104183010-2eb08e3e575f h1:p4VB7kIXpOQvVn1ZaTIVp+3vuYAXFe3OJEvjbUYJLaA=
|
||||
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/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=
|
||||
@ -410,11 +414,13 @@ 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/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 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=
|
||||
@ -425,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=
|
||||
@ -436,6 +443,7 @@ golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5h
|
||||
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/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-20190411185658-b44545bcd369/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@ -444,8 +452,6 @@ golang.org/x/sys v0.0.0-20190418153312-f0ce4c0180be/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
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-20190606203320-7fc4e5ec1444/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-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@ -455,10 +461,9 @@ golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
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-20200406155108-e3b113bbe6a4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200602100848-8d3cce7afc34/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@ -467,19 +472,22 @@ golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
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-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-20210108172913-0df2131ae363 h1:wHn06sgWHMO1VsQ8F+KzDJx/JzqfsNLnc+oEi07qD7s=
|
||||
golang.org/x/sys v0.0.0-20210108172913-0df2131ae363/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=
|
||||
@ -539,12 +547,12 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0/go.mod h1:OdE7CF6DbADk7lN8LIKRzRJTTZXIjtWgA5THM5lhBAw=
|
||||
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=
|
||||
|
@ -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
|
||||
@ -86,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
|
||||
@ -96,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 {
|
||||
@ -117,14 +117,14 @@ 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
|
||||
@ -141,7 +141,7 @@ func (c *Client) ObtainOrRenew() bool {
|
||||
c.timeoutCount++
|
||||
if c.timeoutCount > 3 {
|
||||
c.timeoutCount = 0
|
||||
c.Ack = nil // start over at DHCPDISCOVER
|
||||
c.Ack = nil // start over at DHCPDISCOVER it has failed 3 times
|
||||
}
|
||||
return true // temporary error
|
||||
}
|
||||
@ -167,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)
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
@ -544,11 +544,26 @@ func (s *Server) handleRequest(w dns.ResponseWriter, r *dns.Msg) {
|
||||
}
|
||||
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()
|
||||
s.upstream = append(append([]string{u}, s.upstream[:idx]...), s.upstream[idx+1:]...)
|
||||
// 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
|
||||
@ -584,13 +599,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