Compare commits
22 Commits
fdc36b64ef
...
28f5022603
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
28f5022603 | ||
|
|
15e2ab97d6 | ||
|
|
acdc5313ee | ||
|
|
16933dd2ca | ||
|
|
5603d88134 | ||
|
|
2189376204 | ||
|
|
e2d4de4768 | ||
|
|
128a7e98ef | ||
|
|
0b9afc9273 | ||
|
|
35fcfc15c8 | ||
|
|
2e5277d689 | ||
|
|
52826d6011 | ||
|
|
6e73981e36 | ||
|
|
58fa19ba32 | ||
|
|
ea317e0e7a | ||
|
|
e9cfa01d4a | ||
|
|
9f55a9f5dc | ||
|
|
4ca26a5a32 | ||
|
|
3fbc5260b3 | ||
|
|
20840d4904 | ||
|
|
07b85b9624 | ||
|
|
fe43422499 |
77
.github/workflows/go.yml
vendored
77
.github/workflows/go.yml
vendored
@@ -9,27 +9,14 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
build:
|
build:
|
||||||
name: build
|
name: test
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up Go 1.x
|
- uses: actions/setup-go@v5
|
||||||
uses: actions/setup-go@v2
|
|
||||||
with:
|
with:
|
||||||
# Run on the latest minor release of Go 1.18:
|
go-version: 'stable'
|
||||||
go-version: ^1.18
|
|
||||||
id: go
|
|
||||||
|
|
||||||
- name: Check out code into the Go module directory
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- name: Share cache with other actions
|
|
||||||
uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
path: ~/go/pkg/mod
|
|
||||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-go-
|
|
||||||
|
|
||||||
- name: Ensure all files were formatted as per gofmt
|
- name: Ensure all files were formatted as per gofmt
|
||||||
run: |
|
run: |
|
||||||
@@ -39,64 +26,24 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
go vet
|
go vet
|
||||||
|
|
||||||
- name: Build
|
- name: Build and Test
|
||||||
run: |
|
run: |
|
||||||
go build -v ./cmd/...
|
go build -v ./cmd/...
|
||||||
|
|
||||||
test:
|
|
||||||
name: test
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
|
|
||||||
- name: Set up Go 1.x
|
|
||||||
uses: actions/setup-go@v2
|
|
||||||
with:
|
|
||||||
# Run on the latest minor release of Go 1.18:
|
|
||||||
go-version: ^1.18
|
|
||||||
id: go
|
|
||||||
|
|
||||||
- name: Check out code into the Go module directory
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- name: Share cache with other actions
|
|
||||||
uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
path: ~/go/pkg/mod
|
|
||||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-go-
|
|
||||||
|
|
||||||
- name: Test
|
|
||||||
run: |
|
|
||||||
go test -v -race ./internal/...
|
go test -v -race ./internal/...
|
||||||
|
|
||||||
integrationtest:
|
integrationtest:
|
||||||
name: integrationtest
|
name: integrationtest
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up Go 1.x
|
- uses: actions/setup-go@v5
|
||||||
uses: actions/setup-go@v2
|
|
||||||
with:
|
with:
|
||||||
# Run on the latest minor release of Go 1.18:
|
go-version: 'stable'
|
||||||
go-version: ^1.18
|
|
||||||
id: go
|
|
||||||
|
|
||||||
- name: Check out code into the Go module directory
|
- uses: cachix/install-nix-action@v31
|
||||||
uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- name: Share cache with other actions
|
|
||||||
uses: actions/cache@v2
|
|
||||||
with:
|
with:
|
||||||
path: ~/go/pkg/mod
|
nix_path: nixpkgs=channel:nixos-25.05
|
||||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-go-
|
|
||||||
|
|
||||||
- name: Build Docker container with the tools our tests require
|
- name: Run tests in nix-shell
|
||||||
run: |
|
run: nix-shell --command 'make test'
|
||||||
docker build --pull --no-cache --rm -t=router7 -f travis/Dockerfile .
|
|
||||||
|
|
||||||
- name: Run tests in Docker container
|
|
||||||
run: |
|
|
||||||
exit=0; for pkg in $(go list ./integration/...); do go test -c $pkg && docker run --privileged --net=host -v $PWD:/usr/src:ro router7 /bin/sh -c "./$(basename $pkg).test -test.v" || exit=1; done; [ $exit = 0 ]
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"flag"
|
"flag"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -24,6 +25,7 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/gokrazy/gokrazy"
|
"github.com/gokrazy/gokrazy"
|
||||||
|
"github.com/gokrazy/rsync/rsyncd"
|
||||||
|
|
||||||
"github.com/rtr7/router7/internal/backup"
|
"github.com/rtr7/router7/internal/backup"
|
||||||
"github.com/rtr7/router7/internal/multilisten"
|
"github.com/rtr7/router7/internal/multilisten"
|
||||||
@@ -37,6 +39,51 @@ var (
|
|||||||
perm = flag.String("perm", "/perm", "path to replace /perm")
|
perm = flag.String("perm", "/perm", "path to replace /perm")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var rsyncListeners = multilisten.NewPool()
|
||||||
|
|
||||||
|
type rsyncListener struct {
|
||||||
|
addr string
|
||||||
|
listener net.Listener
|
||||||
|
cancel context.CancelFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *rsyncListener) ListenAndServe() error {
|
||||||
|
ln, err := net.Listen("tcp", r.addr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
r.listener = ln
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
r.cancel = cancel
|
||||||
|
rsyncServer, err := rsyncd.NewServer([]rsyncd.Module{
|
||||||
|
{
|
||||||
|
Name: "perm",
|
||||||
|
Path: "/perm",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
if err := rsyncServer.Serve(ctx, ln); err != nil {
|
||||||
|
log.Print(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *rsyncListener) Close() error {
|
||||||
|
if r.cancel != nil {
|
||||||
|
r.cancel()
|
||||||
|
r.cancel = nil
|
||||||
|
r.listener.Close()
|
||||||
|
r.listener = nil
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func updateListeners() error {
|
func updateListeners() error {
|
||||||
hosts, err := gokrazy.PrivateInterfaceAddrs()
|
hosts, err := gokrazy.PrivateInterfaceAddrs()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -46,6 +93,11 @@ func updateListeners() error {
|
|||||||
httpListeners.ListenAndServe(hosts, func(host string) multilisten.Listener {
|
httpListeners.ListenAndServe(hosts, func(host string) multilisten.Listener {
|
||||||
return &http.Server{Addr: net.JoinHostPort(host, "8077")}
|
return &http.Server{Addr: net.JoinHostPort(host, "8077")}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
rsyncListeners.ListenAndServe(hosts, func(host string) multilisten.Listener {
|
||||||
|
return &rsyncListener{addr: net.JoinHostPort(host, "8873")} // unprivileged rsync
|
||||||
|
})
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import (
|
|||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
"slices"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -100,7 +101,8 @@ func logic() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
hwaddr := iface.HardwareAddr
|
// Clone the hardware address as the backing array does not remain valid.
|
||||||
|
hwaddr := slices.Clone(iface.HardwareAddr)
|
||||||
// The interface may not have been configured by netconfigd yet and might
|
// The interface may not have been configured by netconfigd yet and might
|
||||||
// still use the old hardware address. We overwrite it with the address that
|
// still use the old hardware address. We overwrite it with the address that
|
||||||
// netconfigd is going to use to fix this issue without additional
|
// netconfigd is going to use to fix this issue without additional
|
||||||
|
|||||||
@@ -31,6 +31,9 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/gokrazy/gokrazy"
|
"github.com/gokrazy/gokrazy"
|
||||||
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||||
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
|
|
||||||
"github.com/rtr7/router7/internal/diag"
|
"github.com/rtr7/router7/internal/diag"
|
||||||
"github.com/rtr7/router7/internal/multilisten"
|
"github.com/rtr7/router7/internal/multilisten"
|
||||||
@@ -140,6 +143,23 @@ func logic() error {
|
|||||||
}
|
}
|
||||||
w.Write(b)
|
w.Write(b)
|
||||||
})
|
})
|
||||||
|
promauto.NewGaugeFunc(
|
||||||
|
prometheus.GaugeOpts{
|
||||||
|
Subsystem: "diagd",
|
||||||
|
Name: "healthy",
|
||||||
|
Help: "Whether diagd considers this machine healthy or not",
|
||||||
|
},
|
||||||
|
func() float64 {
|
||||||
|
mu.Lock()
|
||||||
|
re := mJSON.Evaluate()
|
||||||
|
mu.Unlock()
|
||||||
|
if err := firstError(re); err != "" {
|
||||||
|
log.Printf("prometheus metric reporting unhealthy: %v", err)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return 1
|
||||||
|
})
|
||||||
|
http.Handle("/metrics", promhttp.Handler())
|
||||||
if err := updateListeners(); err != nil {
|
if err := updateListeners(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
18
go.mod
18
go.mod
@@ -1,14 +1,13 @@
|
|||||||
module github.com/rtr7/router7
|
module github.com/rtr7/router7
|
||||||
|
|
||||||
go 1.21
|
go 1.24.0
|
||||||
|
|
||||||
toolchain go1.22.2
|
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883
|
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883
|
||||||
github.com/digineo/go-ping v1.0.1
|
github.com/digineo/go-ping v1.0.1
|
||||||
github.com/eclipse/paho.mqtt.golang v1.4.1
|
github.com/eclipse/paho.mqtt.golang v1.5.1
|
||||||
github.com/gokrazy/gokrazy v0.0.0-20230812092215-346db1998f83
|
github.com/gokrazy/gokrazy v0.0.0-20230812092215-346db1998f83
|
||||||
|
github.com/gokrazy/rsync v0.2.5
|
||||||
github.com/google/go-cmp v0.6.0
|
github.com/google/go-cmp v0.6.0
|
||||||
github.com/google/gopacket v1.1.19
|
github.com/google/gopacket v1.1.19
|
||||||
github.com/google/nftables v0.2.1-0.20240422065334-aa8348f7904c
|
github.com/google/nftables v0.2.1-0.20240422065334-aa8348f7904c
|
||||||
@@ -26,10 +25,10 @@ require (
|
|||||||
github.com/rtr7/dhcp4 v0.0.0-20220302171438-18c84d089b46
|
github.com/rtr7/dhcp4 v0.0.0-20220302171438-18c84d089b46
|
||||||
github.com/vishvananda/netlink v1.2.1-beta.2
|
github.com/vishvananda/netlink v1.2.1-beta.2
|
||||||
github.com/vishvananda/netns v0.0.4
|
github.com/vishvananda/netns v0.0.4
|
||||||
golang.org/x/crypto v0.31.0
|
golang.org/x/crypto v0.45.0
|
||||||
golang.org/x/net v0.23.0
|
golang.org/x/net v0.47.0
|
||||||
golang.org/x/sync v0.7.0
|
golang.org/x/sync v0.17.0
|
||||||
golang.org/x/sys v0.28.0
|
golang.org/x/sys v0.38.0
|
||||||
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9
|
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9
|
||||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20220504211119-3d4a969bb56b
|
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20220504211119-3d4a969bb56b
|
||||||
)
|
)
|
||||||
@@ -40,13 +39,14 @@ require (
|
|||||||
github.com/digineo/go-logwrap v0.0.0-20181106161722-a178c58ea3f0 // indirect
|
github.com/digineo/go-logwrap v0.0.0-20181106161722-a178c58ea3f0 // indirect
|
||||||
github.com/gokrazy/internal v0.0.0-20230211171410-9608422911d0 // indirect
|
github.com/gokrazy/internal v0.0.0-20230211171410-9608422911d0 // indirect
|
||||||
github.com/google/renameio/v2 v2.0.0 // indirect
|
github.com/google/renameio/v2 v2.0.0 // indirect
|
||||||
github.com/gorilla/websocket v1.4.2 // indirect
|
github.com/gorilla/websocket v1.5.3 // indirect
|
||||||
github.com/josharian/native v1.1.0 // indirect
|
github.com/josharian/native v1.1.0 // indirect
|
||||||
github.com/kenshaw/evdev v0.1.0 // indirect
|
github.com/kenshaw/evdev v0.1.0 // indirect
|
||||||
github.com/mdlayher/genetlink v1.3.2 // indirect
|
github.com/mdlayher/genetlink v1.3.2 // indirect
|
||||||
github.com/mdlayher/netlink v1.7.2 // indirect
|
github.com/mdlayher/netlink v1.7.2 // indirect
|
||||||
github.com/mdlayher/socket v0.5.0 // indirect
|
github.com/mdlayher/socket v0.5.0 // indirect
|
||||||
github.com/mdlayher/watchdog v0.0.0-20221003142519-49be0df7b3b5 // indirect
|
github.com/mdlayher/watchdog v0.0.0-20221003142519-49be0df7b3b5 // indirect
|
||||||
|
github.com/mmcloughlin/md4 v0.1.2 // indirect
|
||||||
github.com/prometheus/client_model v0.6.1 // indirect
|
github.com/prometheus/client_model v0.6.1 // indirect
|
||||||
github.com/prometheus/common v0.53.0 // indirect
|
github.com/prometheus/common v0.53.0 // indirect
|
||||||
github.com/prometheus/procfs v0.14.0 // indirect
|
github.com/prometheus/procfs v0.14.0 // indirect
|
||||||
|
|||||||
34
go.sum
34
go.sum
@@ -11,8 +11,8 @@ github.com/digineo/go-logwrap v0.0.0-20181106161722-a178c58ea3f0 h1:OT/LKmj81wMy
|
|||||||
github.com/digineo/go-logwrap v0.0.0-20181106161722-a178c58ea3f0/go.mod h1:DmqdumeAKGQNU5E8MN0ruT5ZGx8l/WbAsMbXCXcSEts=
|
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 h1:Yn9hwM0RY4j4D3gcmLvRJf0d7MrbucfUhnOeVDvcVyk=
|
||||||
github.com/digineo/go-ping v1.0.1/go.mod h1:uCbFC0VUqGNBNiev44BGSxfOrEAmC73GjpRje1l40Zo=
|
github.com/digineo/go-ping v1.0.1/go.mod h1:uCbFC0VUqGNBNiev44BGSxfOrEAmC73GjpRje1l40Zo=
|
||||||
github.com/eclipse/paho.mqtt.golang v1.4.1 h1:tUSpviiL5G3P9SZZJPC4ZULZJsxQKXxfENpMvdbAXAI=
|
github.com/eclipse/paho.mqtt.golang v1.5.1 h1:/VSOv3oDLlpqR2Epjn1Q7b2bSTplJIeV2ISgCl2W7nE=
|
||||||
github.com/eclipse/paho.mqtt.golang v1.4.1/go.mod h1:JGt0RsEwEX+Xa/agj90YJ9d9DH2b7upDZMK9HRbFvCA=
|
github.com/eclipse/paho.mqtt.golang v1.5.1/go.mod h1:1/yJCneuyOoCOzKSsOTUc0AJfpsItBGWvYpBLimhArU=
|
||||||
github.com/fanliao/go-promise v0.0.0-20141029170127-1890db352a72/go.mod h1:PjfxuH4FZdUyfMdtBio2lsRr1AKEaVPwelzuHuh8Lqc=
|
github.com/fanliao/go-promise v0.0.0-20141029170127-1890db352a72/go.mod h1:PjfxuH4FZdUyfMdtBio2lsRr1AKEaVPwelzuHuh8Lqc=
|
||||||
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
||||||
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
|
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
|
||||||
@@ -21,6 +21,8 @@ github.com/gokrazy/gokrazy v0.0.0-20230812092215-346db1998f83 h1:Y4sADvUYd/c0eqn
|
|||||||
github.com/gokrazy/gokrazy v0.0.0-20230812092215-346db1998f83/go.mod h1:9q5Tg+q+YvRjC3VG0gfMFut46dhbhtAnvUEp4lPjc6c=
|
github.com/gokrazy/gokrazy v0.0.0-20230812092215-346db1998f83/go.mod h1:9q5Tg+q+YvRjC3VG0gfMFut46dhbhtAnvUEp4lPjc6c=
|
||||||
github.com/gokrazy/internal v0.0.0-20230211171410-9608422911d0 h1:QTi0skQ/OM7he/5jEWA9k/DYgdwGAhw3hrUoiPGGZHM=
|
github.com/gokrazy/internal v0.0.0-20230211171410-9608422911d0 h1:QTi0skQ/OM7he/5jEWA9k/DYgdwGAhw3hrUoiPGGZHM=
|
||||||
github.com/gokrazy/internal v0.0.0-20230211171410-9608422911d0/go.mod h1:ddHcxXZ/VVQOSAWcRBbkYY58+QOw4L145ye6phyDmRA=
|
github.com/gokrazy/internal v0.0.0-20230211171410-9608422911d0/go.mod h1:ddHcxXZ/VVQOSAWcRBbkYY58+QOw4L145ye6phyDmRA=
|
||||||
|
github.com/gokrazy/rsync v0.2.5 h1:FOZ96QyRmQRPH/1SG5kpXUU4vj7x9aJtdiyb7eVQcII=
|
||||||
|
github.com/gokrazy/rsync v0.2.5/go.mod h1:dz2L8Dmv1fFpRlp6YuLNZ1UIqOfFqYir14J/8efsz6w=
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
@@ -37,8 +39,8 @@ github.com/google/renameio v1.0.1/go.mod h1:t/HQoYBZSsWSNK35C6CO/TpPLDVWvxOHboWU
|
|||||||
github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg=
|
github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg=
|
||||||
github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4=
|
github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
||||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714/go.mod h1:2Goc3h8EklBH5mspfHFxBnEoURQCGzQQH1ga9Myjvis=
|
github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714/go.mod h1:2Goc3h8EklBH5mspfHFxBnEoURQCGzQQH1ga9Myjvis=
|
||||||
github.com/insomniacslk/dhcp v0.0.0-20220822114210-de18a9d48e84 h1:MJTy6H+EpXLeAn0P5WAWeLk6dJA3V0ik6S3VJfUyQuI=
|
github.com/insomniacslk/dhcp v0.0.0-20220822114210-de18a9d48e84 h1:MJTy6H+EpXLeAn0P5WAWeLk6dJA3V0ik6S3VJfUyQuI=
|
||||||
github.com/insomniacslk/dhcp v0.0.0-20220822114210-de18a9d48e84/go.mod h1:h+MxyHxRg9NH3terB1nfRIUaQEcI0XOVkdR9LNBlp8E=
|
github.com/insomniacslk/dhcp v0.0.0-20220822114210-de18a9d48e84/go.mod h1:h+MxyHxRg9NH3terB1nfRIUaQEcI0XOVkdR9LNBlp8E=
|
||||||
@@ -93,6 +95,8 @@ github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
|
|||||||
github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
|
github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
|
||||||
github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721 h1:RlZweED6sbSArvlE924+mUcZuXKLBHA35U7LN621Bws=
|
github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721 h1:RlZweED6sbSArvlE924+mUcZuXKLBHA35U7LN621Bws=
|
||||||
github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721/go.mod h1:Ickgr2WtCLZ2MDGd4Gr0geeCH5HybhRJbonOgQpvSxc=
|
github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721/go.mod h1:Ickgr2WtCLZ2MDGd4Gr0geeCH5HybhRJbonOgQpvSxc=
|
||||||
|
github.com/mmcloughlin/md4 v0.1.2 h1:kGYl+iNbxhyz4u76ka9a+0TXP9KWt/LmnM0QhZwhcBo=
|
||||||
|
github.com/mmcloughlin/md4 v0.1.2/go.mod h1:AAxFX59fddW0IguqNzWlf1lazh1+rXeIt/Bj49cqDTQ=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU=
|
github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU=
|
||||||
@@ -131,8 +135,8 @@ gitlab.com/golang-commonmark/puny v0.0.0-20191124015043-9f83538fa04f/go.mod h1:T
|
|||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
|
golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
|
||||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
|
||||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
@@ -146,18 +150,17 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
|
|||||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20191007182048-72f939374954/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-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-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
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-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-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||||
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
|
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
|
||||||
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/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-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
|
||||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/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-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190411185658-b44545bcd369/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190411185658-b44545bcd369/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -171,7 +174,6 @@ golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/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-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-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-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -183,11 +185,11 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
|
||||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
|
golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU=
|
||||||
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
|
golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"slices"
|
||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
@@ -104,10 +105,13 @@ func (c *Client) ObtainOrRenew() bool {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if c.hardwareAddr == nil && c.HWAddr != nil {
|
if c.hardwareAddr == nil && c.HWAddr != nil {
|
||||||
c.hardwareAddr = c.HWAddr
|
// Clone the hardware address as the backing array does not remain valid.
|
||||||
|
c.hardwareAddr = slices.Clone(c.HWAddr)
|
||||||
}
|
}
|
||||||
if c.hardwareAddr == nil {
|
if c.hardwareAddr == nil {
|
||||||
c.hardwareAddr = c.Interface.HardwareAddr
|
// Defensive slices.Clone because I noticed c.hardwareAddr
|
||||||
|
// containing an unexpected MAC address (~/2025-08-15-*dhcp4-loss).
|
||||||
|
c.hardwareAddr = slices.Clone(c.Interface.HardwareAddr)
|
||||||
}
|
}
|
||||||
if c.generateXID == nil {
|
if c.generateXID == nil {
|
||||||
c.generateXID = dhcp4.XIDGenerator(c.hardwareAddr)
|
c.generateXID = dhcp4.XIDGenerator(c.hardwareAddr)
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
|
"slices"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -115,9 +116,10 @@ func NewClient(cfg ClientConfig) (*Client, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hardwareAddr := iface.HardwareAddr
|
// Clone the hardware address as the backing array does not remain valid.
|
||||||
|
hardwareAddr := slices.Clone(iface.HardwareAddr)
|
||||||
if cfg.HardwareAddr != nil {
|
if cfg.HardwareAddr != nil {
|
||||||
hardwareAddr = cfg.HardwareAddr
|
hardwareAddr = slices.Clone(cfg.HardwareAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
var duid *dhcpv6.Duid
|
var duid *dhcpv6.Duid
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ type Server struct {
|
|||||||
Mux *dns.ServeMux
|
Mux *dns.ServeMux
|
||||||
once bool
|
once bool
|
||||||
client *dns.Client
|
client *dns.Client
|
||||||
|
tcpClient *dns.Client
|
||||||
domain lcHostname
|
domain lcHostname
|
||||||
sometimes *rate.Limiter
|
sometimes *rate.Limiter
|
||||||
prom struct {
|
prom struct {
|
||||||
@@ -87,6 +88,7 @@ func NewServer(addr, domain string) *Server {
|
|||||||
server := &Server{
|
server := &Server{
|
||||||
Mux: dns.NewServeMux(),
|
Mux: dns.NewServeMux(),
|
||||||
client: &dns.Client{},
|
client: &dns.Client{},
|
||||||
|
tcpClient: &dns.Client{Net: "tcp"},
|
||||||
domain: lcHostname(strings.ToLower(domain)),
|
domain: lcHostname(strings.ToLower(domain)),
|
||||||
upstream: []string{
|
upstream: []string{
|
||||||
// https://developers.google.com/speed/public-dns/docs/using#google_public_dns_ip_addresses
|
// https://developers.google.com/speed/public-dns/docs/using#google_public_dns_ip_addresses
|
||||||
@@ -547,6 +549,18 @@ func (s *Server) handleRequest(w dns.ResponseWriter, r *dns.Msg) {
|
|||||||
}
|
}
|
||||||
continue // fall back to next-slower upstream
|
continue // fall back to next-slower upstream
|
||||||
}
|
}
|
||||||
|
if in.Truncated {
|
||||||
|
// Truncated response (exceeds UDP packet size), retry over TCP:
|
||||||
|
// https://www.rfc-editor.org/rfc/rfc2181#section-9
|
||||||
|
in, _, err = s.tcpClient.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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if len(in.Answer) > 1 {
|
if len(in.Answer) > 1 {
|
||||||
if in.Answer[0].Header().Rrtype == dns.TypeCNAME {
|
if in.Answer[0].Header().Rrtype == dns.TypeCNAME {
|
||||||
for i, rr := range in.Answer {
|
for i, rr := range in.Answer {
|
||||||
|
|||||||
@@ -36,7 +36,11 @@ func Update(ctx context.Context, zone string, record libdns.Record, provider Rec
|
|||||||
|
|
||||||
var updated []libdns.Record
|
var updated []libdns.Record
|
||||||
for _, rec := range existing {
|
for _, rec := range existing {
|
||||||
if rec.Name+"."+zone != record.Name || rec.Type != record.Type {
|
fullName := rec.Name + "." + zone
|
||||||
|
if rec.Name == "" {
|
||||||
|
fullName = zone
|
||||||
|
}
|
||||||
|
if fullName != record.Name || rec.Type != record.Type {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -327,8 +327,17 @@ func LinkAddress(dir, ifname string) (net.IP, error) {
|
|||||||
func applyBridges(cfg *InterfaceConfig) error {
|
func applyBridges(cfg *InterfaceConfig) error {
|
||||||
for _, bridge := range cfg.Bridges {
|
for _, bridge := range cfg.Bridges {
|
||||||
if _, err := netlink.LinkByName(bridge.Name); err != nil {
|
if _, err := netlink.LinkByName(bridge.Name); err != nil {
|
||||||
log.Printf("creating bridge %s", bridge.Name)
|
linkAttrs := netlink.LinkAttrs{Name: bridge.Name}
|
||||||
link := &netlink.Bridge{LinkAttrs: netlink.LinkAttrs{Name: bridge.Name}}
|
// Set the bridge MAC address at creation time to avoid a race
|
||||||
|
// condition where dhcp4 might start before the first interface is
|
||||||
|
// added to the bridge and see a random kernel-assigned MAC.
|
||||||
|
if len(bridge.InterfaceHardwareAddrs) > 0 {
|
||||||
|
if hwaddr, err := net.ParseMAC(bridge.InterfaceHardwareAddrs[0]); err == nil {
|
||||||
|
linkAttrs.HardwareAddr = hwaddr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.Printf("creating bridge %s (with hwaddr %v)", bridge.Name, linkAttrs.HardwareAddr)
|
||||||
|
link := &netlink.Bridge{LinkAttrs: linkAttrs}
|
||||||
if err := netlink.LinkAdd(link); err != nil {
|
if err := netlink.LinkAdd(link); err != nil {
|
||||||
return fmt.Errorf("netlink.LinkAdd: %v", err)
|
return fmt.Errorf("netlink.LinkAdd: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,31 @@ func NewServer() (*Server, error) {
|
|||||||
return &Server{}, nil
|
return &Server{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) UpdateDNS(b []byte) error {
|
||||||
|
m,err := ndp.ParseMessage(b)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if m.Type() != ipv6.ICMPTypeNeighborAdvertisement {
|
||||||
|
return fmt.Errorf("incorrect icmp message recieved expected %s, got %s", ipv6.ICMPTypeNeighborAdvertisement, m.Type())
|
||||||
|
}
|
||||||
|
n :=m.(*ndp.NeighborAdvertisement)
|
||||||
|
var hw net.HardwareAddr
|
||||||
|
for _,o := range n.Options {
|
||||||
|
if o.Code() == uint8(ndp.Target) {
|
||||||
|
ll := o.(*ndp.LinkLayerAddress)
|
||||||
|
hw = ll.Addr
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if hw == nil || !n.TargetAddress.IsGlobalUnicast() || !n.Solicited {
|
||||||
|
// Ignore advertisements that donot provide the MAC, are not solicited and are not global unicast addresses
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
log.Printf("found IPv6 address %s for MAC address %s", n.TargetAddress, hw)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Server) SetPrefixes(prefixes []net.IPNet) {
|
func (s *Server) SetPrefixes(prefixes []net.IPNet) {
|
||||||
s.mu.Lock()
|
s.mu.Lock()
|
||||||
if s.ifname != "" {
|
if s.ifname != "" {
|
||||||
@@ -75,6 +100,7 @@ func (s *Server) Serve(ifname string, conn net.PacketConn) error {
|
|||||||
var filter ipv6.ICMPFilter
|
var filter ipv6.ICMPFilter
|
||||||
filter.SetAll(true)
|
filter.SetAll(true)
|
||||||
filter.Accept(ipv6.ICMPTypeRouterSolicitation)
|
filter.Accept(ipv6.ICMPTypeRouterSolicitation)
|
||||||
|
filter.Accept(ipv6.ICMPTypeNeighborAdvertisement)
|
||||||
if err := s.pc.SetICMPFilter(&filter); err != nil {
|
if err := s.pc.SetICMPFilter(&filter); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -101,6 +127,9 @@ func (s *Server) Serve(ifname string, conn net.PacketConn) error {
|
|||||||
// TODO: isn’t this guaranteed by the filter above?
|
// TODO: isn’t this guaranteed by the filter above?
|
||||||
if n == 0 ||
|
if n == 0 ||
|
||||||
ipv6.ICMPType(buf[0]) != ipv6.ICMPTypeRouterSolicitation {
|
ipv6.ICMPType(buf[0]) != ipv6.ICMPTypeRouterSolicitation {
|
||||||
|
if ipv6.ICMPType(buf[0]) == ipv6.ICMPTypeNeighborAdvertisement{
|
||||||
|
s.UpdateDNS(buf)
|
||||||
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err := s.sendAdvertisement(addr); err != nil {
|
if err := s.sendAdvertisement(addr); err != nil {
|
||||||
|
|||||||
@@ -23,7 +23,9 @@ import (
|
|||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Example(t *testing.T) {
|
var t *testing.T = nil // TODO: test not currently runnable
|
||||||
|
|
||||||
|
func Example() {
|
||||||
dnsmasq := dnsmasq.Run(t, "veth0b", "ns0")
|
dnsmasq := dnsmasq.Run(t, "veth0b", "ns0")
|
||||||
defer dnsmasq.Kill()
|
defer dnsmasq.Kill()
|
||||||
// test code here
|
// test code here
|
||||||
|
|||||||
2
push
Executable file
2
push
Executable file
@@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
rsync --exclude .git -av ./docs/ router7:/perm/srv/router7.org/
|
||||||
11
shell.nix
Normal file
11
shell.nix
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
pkgs ? import <nixpkgs> { },
|
||||||
|
}:
|
||||||
|
pkgs.mkShell {
|
||||||
|
packages = with pkgs; [
|
||||||
|
dnsmasq
|
||||||
|
dig
|
||||||
|
ndisc6
|
||||||
|
nftables
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
# vim:ft=Dockerfile
|
|
||||||
FROM debian:sid
|
|
||||||
|
|
||||||
RUN echo force-unsafe-io > /etc/dpkg/dpkg.cfg.d/docker-apt-speedup
|
|
||||||
# Paper over occasional network flakiness of some mirrors.
|
|
||||||
RUN echo 'APT::Acquire::Retries "5";' > /etc/apt/apt.conf.d/80retry
|
|
||||||
|
|
||||||
# NOTE: I tried exclusively using gce_debian_mirror.storage.googleapis.com
|
|
||||||
# instead of httpredir.debian.org, but the results (Fetched 123 MB in 36s (3357
|
|
||||||
# kB/s)) are not any better than httpredir.debian.org (Fetched 123 MB in 34s
|
|
||||||
# (3608 kB/s)). Hence, let’s stick with httpredir.debian.org (default) for now.
|
|
||||||
|
|
||||||
RUN apt-get update && \
|
|
||||||
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
|
||||||
dnsmasq ndisc6 nftables dnsutils strace wireguard iproute2 && \
|
|
||||||
rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
WORKDIR /usr/src
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
loopdev=$(sudo losetup -Pf --show /tmp/router7-qemu/disk.img)
|
|
||||||
sudo mkfs.ext4 -m 1 "${loopdev}p4"
|
|
||||||
sudo mount "${loopdev}p4" /mnt
|
|
||||||
# TODO: make github.com/gokrazy/serial-busybox work with GOARCH=amd64
|
|
||||||
sudo cp ~/src/busybox-1.22.0-amd64/busybox /mnt/sh || true
|
|
||||||
cat <<'EOT' | sudo tee /mnt/interfaces.json
|
|
||||||
{
|
|
||||||
"interfaces": [
|
|
||||||
{
|
|
||||||
"hardware_addr": "52:55:00:d1:55:03",
|
|
||||||
"name": "uplink0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hardware_addr": "52:55:00:d1:55:04",
|
|
||||||
"name": "lan0",
|
|
||||||
"addr": "10.254.0.1/24"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
EOT
|
|
||||||
sudo umount /mnt
|
|
||||||
sudo losetup -d "${loopdev}"
|
|
||||||
Reference in New Issue
Block a user