mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-05-15 00:50:25 +02:00
0645a738ad
This commit add the ability for ctrld to gather client information, including mac/ip/hostname, and send to Control-D server through a config per upstream. - Add send_client_info upstream config. - Read/Watch dnsmasq leases files on supported platforms. - Add corresponding client info to DoH query header All of these only apply for Control-D upstream, though.
173 lines
3.4 KiB
Go
173 lines
3.4 KiB
Go
package router
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"os"
|
|
"os/exec"
|
|
"sync"
|
|
"sync/atomic"
|
|
|
|
"github.com/fsnotify/fsnotify"
|
|
"github.com/kardianos/service"
|
|
|
|
"github.com/Control-D-Inc/ctrld"
|
|
)
|
|
|
|
const (
|
|
OpenWrt = "openwrt"
|
|
DDWrt = "ddwrt"
|
|
Merlin = "merlin"
|
|
Ubios = "ubios"
|
|
)
|
|
|
|
// ErrNotSupported reports the current router is not supported error.
|
|
var ErrNotSupported = errors.New("unsupported platform")
|
|
|
|
var routerPlatform atomic.Pointer[router]
|
|
|
|
type router struct {
|
|
name string
|
|
sendClientInfo bool
|
|
mac sync.Map
|
|
watcher *fsnotify.Watcher
|
|
}
|
|
|
|
// SupportedPlatforms return all platforms that can be configured to run with ctrld.
|
|
func SupportedPlatforms() []string {
|
|
return []string{DDWrt, Merlin, OpenWrt, Ubios}
|
|
}
|
|
|
|
var configureFunc = map[string]func() error{
|
|
DDWrt: setupDDWrt,
|
|
Merlin: setupMerlin,
|
|
OpenWrt: setupOpenWrt,
|
|
Ubios: setupUbiOS,
|
|
}
|
|
|
|
// Configure configures things for running ctrld on the router.
|
|
func Configure(c *ctrld.Config) error {
|
|
name := Name()
|
|
switch name {
|
|
case DDWrt, Merlin, OpenWrt, Ubios:
|
|
if c.HasUpstreamSendClientInfo() {
|
|
r := routerPlatform.Load()
|
|
r.sendClientInfo = true
|
|
watcher, err := fsnotify.NewWatcher()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
r.watcher = watcher
|
|
go r.watchClientInfoTable()
|
|
for _, file := range clientInfoFiles {
|
|
_ = readClientInfoFile(file)
|
|
_ = r.watcher.Add(file)
|
|
}
|
|
}
|
|
configure := configureFunc[name]
|
|
if err := configure(); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
default:
|
|
return ErrNotSupported
|
|
}
|
|
}
|
|
|
|
// ConfigureService performs necessary setup for running ctrld as a service on router.
|
|
func ConfigureService(sc *service.Config) error {
|
|
name := Name()
|
|
switch name {
|
|
case DDWrt:
|
|
if !ddwrtJff2Enabled() {
|
|
return ddwrtJffs2NotEnabledErr
|
|
}
|
|
case OpenWrt:
|
|
sc.Option["SysvScript"] = openWrtScript
|
|
case Merlin, Ubios:
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// PostInstall performs task after installing ctrld on router.
|
|
func PostInstall() error {
|
|
name := Name()
|
|
switch name {
|
|
case DDWrt:
|
|
return postInstallDDWrt()
|
|
case Merlin:
|
|
return postInstallMerlin()
|
|
case OpenWrt:
|
|
return postInstallOpenWrt()
|
|
case Ubios:
|
|
return postInstallUbiOS()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Cleanup cleans ctrld setup on the router.
|
|
func Cleanup() error {
|
|
name := Name()
|
|
switch name {
|
|
case DDWrt:
|
|
return cleanupDDWrt()
|
|
case Merlin:
|
|
return cleanupMerlin()
|
|
case OpenWrt:
|
|
return cleanupOpenWrt()
|
|
case Ubios:
|
|
return cleanupUbiOS()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ListenAddress returns the listener address of ctrld on router.
|
|
func ListenAddress() string {
|
|
name := Name()
|
|
switch name {
|
|
case DDWrt, Merlin, OpenWrt, Ubios:
|
|
return "127.0.0.1:5354"
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// Name returns name of the router platform.
|
|
func Name() string {
|
|
if r := routerPlatform.Load(); r != nil {
|
|
return r.name
|
|
}
|
|
r := &router{}
|
|
r.name = distroName()
|
|
routerPlatform.Store(r)
|
|
return r.name
|
|
}
|
|
|
|
func distroName() string {
|
|
switch {
|
|
case bytes.HasPrefix(uname(), []byte("DD-WRT")):
|
|
return DDWrt
|
|
case bytes.HasPrefix(uname(), []byte("ASUSWRT-Merlin")):
|
|
return Merlin
|
|
case haveFile("/etc/openwrt_version"):
|
|
return OpenWrt
|
|
case haveDir("/data/unifi"):
|
|
return Ubios
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func haveFile(file string) bool {
|
|
_, err := os.Stat(file)
|
|
return err == nil
|
|
}
|
|
|
|
func haveDir(dir string) bool {
|
|
fi, _ := os.Stat(dir)
|
|
return fi != nil && fi.IsDir()
|
|
}
|
|
|
|
func uname() []byte {
|
|
out, _ := exec.Command("uname", "-o").Output()
|
|
return out
|
|
}
|