mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-02-03 22:18:39 +00:00
internal/router: support openwrt 24.10
openwrt 24.10 changes the dnsmasq default config path, causing breaking changes to softwares which depends on old behavior. This commit adds a workaround for the issue, by querying the actual config directory from ubus service list, instead of relying on the default hardcode one.
This commit is contained in:
committed by
Cuong Manh Le
parent
043a28eb33
commit
8ccaeeab60
@@ -2,10 +2,13 @@ package openwrt
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/kardianos/service"
|
"github.com/kardianos/service"
|
||||||
@@ -15,10 +18,13 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Name = "openwrt"
|
Name = "openwrt"
|
||||||
openwrtDNSMasqConfigPath = "/tmp/dnsmasq.d/ctrld.conf"
|
openwrtDNSMasqConfigName = "ctrld.conf"
|
||||||
|
openwrtDNSMasqDefaultConfigDir = "/tmp/dnsmasq.d"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var openwrtDnsmasqDefaultConfigPath = filepath.Join(openwrtDNSMasqDefaultConfigDir, openwrtDNSMasqConfigName)
|
||||||
|
|
||||||
type Openwrt struct {
|
type Openwrt struct {
|
||||||
cfg *ctrld.Config
|
cfg *ctrld.Config
|
||||||
dnsmasqCacheSize string
|
dnsmasqCacheSize string
|
||||||
@@ -67,7 +73,7 @@ func (o *Openwrt) Setup() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := os.WriteFile(openwrtDNSMasqConfigPath, []byte(data), 0600); err != nil {
|
if err := os.WriteFile(dnsmasqConfPathFromUbus(), []byte(data), 0600); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Restart dnsmasq service.
|
// Restart dnsmasq service.
|
||||||
@@ -82,7 +88,7 @@ func (o *Openwrt) Cleanup() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// Remove the custom dnsmasq config
|
// Remove the custom dnsmasq config
|
||||||
if err := os.Remove(openwrtDNSMasqConfigPath); err != nil {
|
if err := os.Remove(dnsmasqConfPathFromUbus()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,3 +132,60 @@ func uci(args ...string) (string, error) {
|
|||||||
}
|
}
|
||||||
return strings.TrimSpace(stdout.String()), nil
|
return strings.TrimSpace(stdout.String()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// openwrtServiceList represents openwrt services config.
|
||||||
|
type openwrtServiceList struct {
|
||||||
|
Dnsmasq dnsmasqConf `json:"dnsmasq"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// dnsmasqConf represents dnsmasq config.
|
||||||
|
type dnsmasqConf struct {
|
||||||
|
Instances map[string]confInstances `json:"instances"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// confInstances represents an instance config of a service.
|
||||||
|
type confInstances struct {
|
||||||
|
Mount map[string]string `json:"mount"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// dnsmasqConfPath returns the dnsmasq config path.
|
||||||
|
//
|
||||||
|
// Since version 24.10, openwrt makes some changes to dnsmasq to support
|
||||||
|
// multiple instances of dnsmasq. This change causes breaking changes to
|
||||||
|
// software which depends on the default dnsmasq path.
|
||||||
|
//
|
||||||
|
// There are some discussion/PRs in openwrt repo to address this:
|
||||||
|
//
|
||||||
|
// - https://github.com/openwrt/openwrt/pull/16806
|
||||||
|
// - https://github.com/openwrt/openwrt/pull/16890
|
||||||
|
//
|
||||||
|
// In the meantime, workaround this problem by querying the actual config path
|
||||||
|
// by querying ubus service list.
|
||||||
|
func dnsmasqConfPath(r io.Reader) string {
|
||||||
|
var svc openwrtServiceList
|
||||||
|
if err := json.NewDecoder(r).Decode(&svc); err != nil {
|
||||||
|
return openwrtDnsmasqDefaultConfigPath
|
||||||
|
}
|
||||||
|
for _, inst := range svc.Dnsmasq.Instances {
|
||||||
|
for mount := range inst.Mount {
|
||||||
|
dirName := filepath.Base(mount)
|
||||||
|
parts := strings.Split(dirName, ".")
|
||||||
|
if len(parts) < 2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if parts[0] == "dnsmasq" && parts[len(parts)-1] == "d" {
|
||||||
|
return filepath.Join(mount, openwrtDNSMasqConfigName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return openwrtDnsmasqDefaultConfigPath
|
||||||
|
}
|
||||||
|
|
||||||
|
// dnsmasqConfPathFromUbus get dnsmasq config path from ubus service list.
|
||||||
|
func dnsmasqConfPathFromUbus() string {
|
||||||
|
output, err := exec.Command("ubus", "call", "service", "list").Output()
|
||||||
|
if err != nil {
|
||||||
|
return openwrtDnsmasqDefaultConfigPath
|
||||||
|
}
|
||||||
|
return dnsmasqConfPath(bytes.NewReader(output))
|
||||||
|
}
|
||||||
|
|||||||
58
internal/router/openwrt/openwrt_test.go
Normal file
58
internal/router/openwrt/openwrt_test.go
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
package openwrt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Sample output from https://github.com/openwrt/openwrt/pull/16806#issuecomment-2448255734
|
||||||
|
const ubusDnsmasqBefore2410 = `{
|
||||||
|
"dnsmasq": {
|
||||||
|
"instances": {
|
||||||
|
"guest_dns": {
|
||||||
|
"mount": {
|
||||||
|
"/tmp/dnsmasq.d": "0",
|
||||||
|
"/var/run/dnsmasq/": "1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`
|
||||||
|
|
||||||
|
const ubusDnsmasq2410 = `{
|
||||||
|
"dnsmasq": {
|
||||||
|
"instances": {
|
||||||
|
"guest_dns": {
|
||||||
|
"mount": {
|
||||||
|
"/tmp/dnsmasq.guest_dns.d": "0",
|
||||||
|
"/var/run/dnsmasq/": "1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`
|
||||||
|
|
||||||
|
func Test_dnsmasqConfPath(t *testing.T) {
|
||||||
|
var dnsmasq2410expected = filepath.Join("/tmp/dnsmasq.guest_dns.d", openwrtDNSMasqConfigName)
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
in io.Reader
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{"empty", strings.NewReader(""), openwrtDnsmasqDefaultConfigPath},
|
||||||
|
{"invalid", strings.NewReader("}}"), openwrtDnsmasqDefaultConfigPath},
|
||||||
|
{"before 24.10", strings.NewReader(ubusDnsmasqBefore2410), openwrtDnsmasqDefaultConfigPath},
|
||||||
|
{"24.10", strings.NewReader(ubusDnsmasq2410), dnsmasq2410expected},
|
||||||
|
}
|
||||||
|
for _, tc := range tests {
|
||||||
|
tc := tc
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
if got := dnsmasqConfPath(tc.in); got != tc.expected {
|
||||||
|
t.Errorf("dnsmasqConfPath() = %v, want %v", got, tc.expected)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user