mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-08-10 13:20:33 +02:00
internal/router: use max-cache-ttl=0 on some routers
On some routers, dnsmasq config may change cache-size dynamically after ctrld starts, causing dnsmasq crashes. Fixing this by using max-cache-ttl, which have the same effect with setting cache-size=0 but won't conflict with existing routers config.
This commit is contained in:
@@ -1,12 +1,9 @@
|
|||||||
package dnsmasq
|
package dnsmasq
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"html/template"
|
"html/template"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -24,6 +21,8 @@ add-subnet=32,128
|
|||||||
{{- end}}
|
{{- end}}
|
||||||
{{- if .CacheDisabled}}
|
{{- if .CacheDisabled}}
|
||||||
cache-size=0
|
cache-size=0
|
||||||
|
{{- else}}
|
||||||
|
max-cache-ttl=0
|
||||||
{{- end}}
|
{{- end}}
|
||||||
`
|
`
|
||||||
|
|
||||||
@@ -72,11 +71,18 @@ type Upstream struct {
|
|||||||
Port int
|
Port int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ConfTmpl generates dnsmasq configuration from ctrld config.
|
||||||
func ConfTmpl(tmplText string, cfg *ctrld.Config) (string, error) {
|
func ConfTmpl(tmplText string, cfg *ctrld.Config) (string, error) {
|
||||||
return ConfTmplWitchCacheDisabled(tmplText, cfg, true)
|
return ConfTmplWithCacheDisabled(tmplText, cfg, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ConfTmplWitchCacheDisabled(tmplText string, cfg *ctrld.Config, cacheDisabled bool) (string, error) {
|
// ConfTmplWithCacheDisabled is like ConfTmpl, but the caller can control whether
|
||||||
|
// dnsmasq cache is disabled using cacheDisabled parameter.
|
||||||
|
//
|
||||||
|
// Generally, the caller should use ConfTmpl, but on some routers which dnsmasq config may be changed
|
||||||
|
// after ctrld started (like EdgeOS/Ubios, Firewalla ...), dnsmasq cache should not be disabled because
|
||||||
|
// the cache-size=0 generated by ctrld will conflict with router's generated config.
|
||||||
|
func ConfTmplWithCacheDisabled(tmplText string, cfg *ctrld.Config, cacheDisabled bool) (string, error) {
|
||||||
listener := cfg.FirstListener()
|
listener := cfg.FirstListener()
|
||||||
if listener == nil {
|
if listener == nil {
|
||||||
return "", errors.New("missing listener")
|
return "", errors.New("missing listener")
|
||||||
@@ -89,11 +95,14 @@ func ConfTmplWitchCacheDisabled(tmplText string, cfg *ctrld.Config, cacheDisable
|
|||||||
return confTmpl(tmplText, upstreams, cfg.HasUpstreamSendClientInfo(), cacheDisabled)
|
return confTmpl(tmplText, upstreams, cfg.HasUpstreamSendClientInfo(), cacheDisabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FirewallaConfTmpl generates dnsmasq config for Firewalla routers.
|
||||||
func FirewallaConfTmpl(tmplText string, cfg *ctrld.Config) (string, error) {
|
func FirewallaConfTmpl(tmplText string, cfg *ctrld.Config) (string, error) {
|
||||||
|
// If ctrld listen on all interfaces, generating config for all of them.
|
||||||
if lc := cfg.FirstListener(); lc != nil && (lc.IP == "0.0.0.0" || lc.IP == "") {
|
if lc := cfg.FirstListener(); lc != nil && (lc.IP == "0.0.0.0" || lc.IP == "") {
|
||||||
return confTmpl(tmplText, firewallaUpstreams(lc.Port), cfg.HasUpstreamSendClientInfo(), true)
|
return confTmpl(tmplText, firewallaUpstreams(lc.Port), cfg.HasUpstreamSendClientInfo(), false)
|
||||||
}
|
}
|
||||||
return ConfTmpl(tmplText, cfg)
|
// Otherwise, generating config for the specific listener from ctrld's config.
|
||||||
|
return ConfTmplWithCacheDisabled(tmplText, cfg, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func confTmpl(tmplText string, upstreams []Upstream, sendClientInfo, cacheDisabled bool) (string, error) {
|
func confTmpl(tmplText string, upstreams []Upstream, sendClientInfo, cacheDisabled bool) (string, error) {
|
||||||
@@ -136,20 +145,6 @@ func firewallaDnsmasqConfFiles() ([]string, error) {
|
|||||||
return filepath.Glob("/home/pi/firerouter/etc/dnsmasq.dns.*.conf")
|
return filepath.Glob("/home/pi/firerouter/etc/dnsmasq.dns.*.conf")
|
||||||
}
|
}
|
||||||
|
|
||||||
// firewallUpdateConf updates all firewall config files using given function.
|
|
||||||
func firewallUpdateConf(update func(conf string) error) error {
|
|
||||||
confFiles, err := firewallaDnsmasqConfFiles()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for _, conf := range confFiles {
|
|
||||||
if err := update(conf); err != nil {
|
|
||||||
return fmt.Errorf("%s: %w", conf, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// FirewallaSelfInterfaces returns list of interfaces that will be configured with default dnsmasq setup on Firewalla.
|
// FirewallaSelfInterfaces returns list of interfaces that will be configured with default dnsmasq setup on Firewalla.
|
||||||
func FirewallaSelfInterfaces() []*net.Interface {
|
func FirewallaSelfInterfaces() []*net.Interface {
|
||||||
matches, err := firewallaDnsmasqConfFiles()
|
matches, err := firewallaDnsmasqConfFiles()
|
||||||
@@ -166,32 +161,3 @@ func FirewallaSelfInterfaces() []*net.Interface {
|
|||||||
}
|
}
|
||||||
return ifaces
|
return ifaces
|
||||||
}
|
}
|
||||||
|
|
||||||
// FirewallaDisableCache comments out "cache-size" line in all firewalla dnsmasq config files.
|
|
||||||
func FirewallaDisableCache() error {
|
|
||||||
return firewallUpdateConf(DisableCache)
|
|
||||||
}
|
|
||||||
|
|
||||||
// FirewallaEnableCache un-comments out "cache-size" line in all firewalla dnsmasq config files.
|
|
||||||
func FirewallaEnableCache() error {
|
|
||||||
return firewallUpdateConf(EnableCache)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DisableCache comments out "cache-size" line in dnsmasq config file.
|
|
||||||
func DisableCache(conf string) error {
|
|
||||||
return replaceFileContent(conf, "\ncache-size=", "\n#cache-size=")
|
|
||||||
}
|
|
||||||
|
|
||||||
// EnableCache un-comments "cache-size" line in dnsmasq config file.
|
|
||||||
func EnableCache(conf string) error {
|
|
||||||
return replaceFileContent(conf, "\n#cache-size=", "\ncache-size=")
|
|
||||||
}
|
|
||||||
|
|
||||||
func replaceFileContent(filename, old, new string) error {
|
|
||||||
content, err := os.ReadFile(filename)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
content = bytes.ReplaceAll(content, []byte(old), []byte(new))
|
|
||||||
return os.WriteFile(filename, content, 0644)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ func (e *EdgeOS) setupUSG() error {
|
|||||||
sb.WriteString(line)
|
sb.WriteString(line)
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := dnsmasq.ConfTmplWitchCacheDisabled(dnsmasq.ConfigContentTmpl, e.cfg, false)
|
data, err := dnsmasq.ConfTmplWithCacheDisabled(dnsmasq.ConfigContentTmpl, e.cfg, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -127,7 +127,7 @@ func (e *EdgeOS) setupUSG() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *EdgeOS) setupUDM() error {
|
func (e *EdgeOS) setupUDM() error {
|
||||||
data, err := dnsmasq.ConfTmplWitchCacheDisabled(dnsmasq.ConfigContentTmpl, e.cfg, false)
|
data, err := dnsmasq.ConfTmplWithCacheDisabled(dnsmasq.ConfigContentTmpl, e.cfg, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,11 +65,6 @@ func (f *Firewalla) Setup() error {
|
|||||||
return fmt.Errorf("writing ctrld config: %w", err)
|
return fmt.Errorf("writing ctrld config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable dnsmasq cache.
|
|
||||||
if err := dnsmasq.FirewallaDisableCache(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Restart dnsmasq service.
|
// Restart dnsmasq service.
|
||||||
if err := restartDNSMasq(); err != nil {
|
if err := restartDNSMasq(); err != nil {
|
||||||
return fmt.Errorf("restartDNSMasq: %w", err)
|
return fmt.Errorf("restartDNSMasq: %w", err)
|
||||||
@@ -87,11 +82,6 @@ func (f *Firewalla) Cleanup() error {
|
|||||||
return fmt.Errorf("removing ctrld config: %w", err)
|
return fmt.Errorf("removing ctrld config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable dnsmasq cache.
|
|
||||||
if err := dnsmasq.FirewallaEnableCache(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Restart dnsmasq service.
|
// Restart dnsmasq service.
|
||||||
if err := restartDNSMasq(); err != nil {
|
if err := restartDNSMasq(); err != nil {
|
||||||
return fmt.Errorf("restartDNSMasq: %w", err)
|
return fmt.Errorf("restartDNSMasq: %w", err)
|
||||||
|
|||||||
@@ -51,17 +51,13 @@ func (u *Ubios) Setup() error {
|
|||||||
if u.cfg.FirstListener().IsDirectDnsListener() {
|
if u.cfg.FirstListener().IsDirectDnsListener() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
data, err := dnsmasq.ConfTmpl(dnsmasq.ConfigContentTmpl, u.cfg)
|
data, err := dnsmasq.ConfTmplWithCacheDisabled(dnsmasq.ConfigContentTmpl, u.cfg, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := os.WriteFile(ubiosDNSMasqConfigPath, []byte(data), 0600); err != nil {
|
if err := os.WriteFile(ubiosDNSMasqConfigPath, []byte(data), 0600); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Disable dnsmasq cache.
|
|
||||||
if err := dnsmasq.DisableCache(ubiosDNSMasqDnsConfigPath); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// Restart dnsmasq service.
|
// Restart dnsmasq service.
|
||||||
if err := restartDNSMasq(); err != nil {
|
if err := restartDNSMasq(); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -77,10 +73,6 @@ func (u *Ubios) Cleanup() error {
|
|||||||
if err := os.Remove(ubiosDNSMasqConfigPath); err != nil {
|
if err := os.Remove(ubiosDNSMasqConfigPath); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Enable dnsmasq cache.
|
|
||||||
if err := dnsmasq.EnableCache(ubiosDNSMasqDnsConfigPath); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// Restart dnsmasq service.
|
// Restart dnsmasq service.
|
||||||
if err := restartDNSMasq(); err != nil {
|
if err := restartDNSMasq(); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
Reference in New Issue
Block a user