mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-02-03 22:18:39 +00:00
internal/router: change dnsmasq config manipulation on Merlin
Generally, using /jffs/scripts/dnsmasq.postconf is the right way to add custom configuration to dnsmasq on Merlin. However, we have seen many reports that the postconf does not work on their devices. This commit changes how dnsmasq config manipulation is done on Merlin, so it's expected to work on all Merlin devices: - Writing /jffs/scripts/dnsmasq.postconf script - Copy current dnsmasq.conf to /jffs/configs/dnsmasq.conf - Run postconf script directly on /jffs/configs/dnsmasq.conf - Restart dnsmasq This way, the /jffs/configs/dnsmasq.conf will contain both current dnsmasq config, and also custom config added by ctrld, without worrying about conflicting, because configuration was added by postconf. See (1) for more details about custom config files on Merlin. (1) https://github.com/RMerl/asuswrt-merlin.ng/wiki/Custom-config-files
This commit is contained in:
committed by
Cuong Manh Le
parent
c6365e6b74
commit
a9ed70200b
@@ -26,6 +26,8 @@ max-cache-ttl=0
|
||||
{{- end}}
|
||||
`
|
||||
|
||||
const MerlinConfPath = "/tmp/etc/dnsmasq.conf"
|
||||
const MerlinJffsConfPath = "/jffs/configs/dnsmasq.conf"
|
||||
const MerlinPostConfPath = "/jffs/scripts/dnsmasq.postconf"
|
||||
const MerlinPostConfMarker = `# GENERATED BY ctrld - EOF`
|
||||
const MerlinPostConfTmpl = `# GENERATED BY ctrld - DO NOT MODIFY
|
||||
|
||||
@@ -3,6 +3,7 @@ package merlin
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
@@ -73,30 +74,42 @@ func (m *Merlin) Setup() error {
|
||||
if val, _ := nvram.Run("get", nvram.CtrldSetupKey); val == "1" {
|
||||
return nil
|
||||
}
|
||||
buf, err := os.ReadFile(dnsmasq.MerlinPostConfPath)
|
||||
// Already setup.
|
||||
if bytes.Contains(buf, []byte(dnsmasq.MerlinPostConfMarker)) {
|
||||
return nil
|
||||
}
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
|
||||
if err := m.writeDnsmasqPostconf(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
data, err := dnsmasq.ConfTmpl(dnsmasq.MerlinPostConfTmpl, m.cfg)
|
||||
// Copy current dnsmasq config to /jffs/configs/dnsmasq.conf,
|
||||
// Then we will run postconf script on this file.
|
||||
//
|
||||
// Normally, adding postconf script is enough. However, we see
|
||||
// reports on some Merlin devices that postconf scripts does not
|
||||
// work, but manipulating the config directly via /jffs/configs does.
|
||||
src, err := os.Open(dnsmasq.MerlinConfPath)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("failed to open dnsmasq config: %w", err)
|
||||
}
|
||||
data = strings.Join([]string{
|
||||
data,
|
||||
"\n",
|
||||
dnsmasq.MerlinPostConfMarker,
|
||||
"\n",
|
||||
string(buf),
|
||||
}, "\n")
|
||||
// Write dnsmasq post conf file.
|
||||
if err := os.WriteFile(dnsmasq.MerlinPostConfPath, []byte(data), 0750); err != nil {
|
||||
return err
|
||||
defer src.Close()
|
||||
|
||||
dst, err := os.Create(dnsmasq.MerlinJffsConfPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create %s: %w", dnsmasq.MerlinJffsConfPath, err)
|
||||
}
|
||||
defer dst.Close()
|
||||
|
||||
if _, err := io.Copy(dst, src); err != nil {
|
||||
return fmt.Errorf("failed to copy current dnsmasq config: %w", err)
|
||||
}
|
||||
if err := dst.Close(); err != nil {
|
||||
return fmt.Errorf("failed to save %s: %w", dnsmasq.MerlinJffsConfPath, err)
|
||||
}
|
||||
|
||||
// Run postconf script on /jffs/configs/dnsmasq.conf directly.
|
||||
cmd := exec.Command("/bin/sh", dnsmasq.MerlinPostConfPath, dnsmasq.MerlinJffsConfPath)
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("failed to run post conf: %s: %w", string(out), err)
|
||||
}
|
||||
|
||||
// Restart dnsmasq service.
|
||||
if err := restartDNSMasq(); err != nil {
|
||||
return err
|
||||
@@ -130,6 +143,10 @@ func (m *Merlin) Cleanup() error {
|
||||
if err := os.WriteFile(dnsmasq.MerlinPostConfPath, merlinParsePostConf(buf), 0750); err != nil {
|
||||
return err
|
||||
}
|
||||
// Remove /jffs/configs/dnsmasq.conf file.
|
||||
if err := os.Remove(dnsmasq.MerlinJffsConfPath); err != nil && !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
// Restart dnsmasq service.
|
||||
if err := restartDNSMasq(); err != nil {
|
||||
return err
|
||||
@@ -137,6 +154,31 @@ func (m *Merlin) Cleanup() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Merlin) writeDnsmasqPostconf() error {
|
||||
buf, err := os.ReadFile(dnsmasq.MerlinPostConfPath)
|
||||
// Already setup.
|
||||
if bytes.Contains(buf, []byte(dnsmasq.MerlinPostConfMarker)) {
|
||||
return nil
|
||||
}
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
data, err := dnsmasq.ConfTmpl(dnsmasq.MerlinPostConfTmpl, m.cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data = strings.Join([]string{
|
||||
data,
|
||||
"\n",
|
||||
dnsmasq.MerlinPostConfMarker,
|
||||
"\n",
|
||||
string(buf),
|
||||
}, "\n")
|
||||
// Write dnsmasq post conf file.
|
||||
return os.WriteFile(dnsmasq.MerlinPostConfPath, []byte(data), 0750)
|
||||
}
|
||||
|
||||
func restartDNSMasq() error {
|
||||
if out, err := exec.Command("service", "restart_dnsmasq").CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("restart_dnsmasq: %s, %w", string(out), err)
|
||||
|
||||
Reference in New Issue
Block a user