mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-02-03 22:18:39 +00:00
126 lines
2.8 KiB
Go
126 lines
2.8 KiB
Go
package synology
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/kardianos/service"
|
|
"tailscale.com/logtail/backoff"
|
|
|
|
"github.com/Control-D-Inc/ctrld"
|
|
"github.com/Control-D-Inc/ctrld/internal/router/dnsmasq"
|
|
"github.com/Control-D-Inc/ctrld/internal/router/ntp"
|
|
)
|
|
|
|
const (
|
|
Name = "synology"
|
|
|
|
synologyDNSMasqConfigPath = "/etc/dhcpd/dhcpd-zzz-ctrld.conf"
|
|
synologyDhcpdInfoPath = "/etc/dhcpd/dhcpd-zzz-ctrld.info"
|
|
)
|
|
|
|
type Synology struct {
|
|
cfg *ctrld.Config
|
|
useUpstart bool
|
|
}
|
|
|
|
// New returns a router.Router for configuring/setup/run ctrld on Ubios routers.
|
|
func New(cfg *ctrld.Config) *Synology {
|
|
return &Synology{
|
|
cfg: cfg,
|
|
useUpstart: service.Platform() == "linux-upstart",
|
|
}
|
|
}
|
|
|
|
func (s *Synology) ConfigureService(svc *service.Config) error {
|
|
svc.Option["LogOutput"] = true
|
|
return nil
|
|
}
|
|
|
|
func (s *Synology) Install(_ *service.Config) error {
|
|
return nil
|
|
}
|
|
|
|
func (s *Synology) Uninstall(_ *service.Config) error {
|
|
return nil
|
|
}
|
|
|
|
func (s *Synology) PreRun() error {
|
|
if s.useUpstart {
|
|
if err := ntp.WaitUpstart(); err != nil {
|
|
return err
|
|
}
|
|
return waitDhcpServer()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *Synology) Setup() error {
|
|
if s.cfg.FirstListener().IsDirectDnsListener() {
|
|
return nil
|
|
}
|
|
data, err := dnsmasq.ConfTmpl(dnsmasq.ConfigContentTmpl, s.cfg)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := os.WriteFile(synologyDNSMasqConfigPath, []byte(data), 0600); err != nil {
|
|
return err
|
|
}
|
|
if err := os.WriteFile(synologyDhcpdInfoPath, []byte(`enable="yes"`), 0600); err != nil {
|
|
return err
|
|
}
|
|
if err := restartDNSMasq(); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *Synology) Cleanup() error {
|
|
if s.cfg.FirstListener().IsDirectDnsListener() {
|
|
return nil
|
|
}
|
|
// Remove the custom config files.
|
|
for _, f := range []string{synologyDNSMasqConfigPath, synologyDhcpdInfoPath} {
|
|
if err := os.Remove(f); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
// Restart dnsmasq service.
|
|
if err := restartDNSMasq(); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func restartDNSMasq() error {
|
|
if out, err := exec.Command("/etc/rc.network", "nat-restart-dhcp").CombinedOutput(); err != nil {
|
|
return fmt.Errorf("synologyRestartDNSMasq: %s - %w", string(out), err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func waitDhcpServer() error {
|
|
// Wait until `initctl status dhcpserver` returns running state.
|
|
b := backoff.NewBackoff("waitDhcpServer", func(format string, args ...any) {}, 10*time.Second)
|
|
for {
|
|
out, err := exec.Command("initctl", "status", "dhcpserver").CombinedOutput()
|
|
if err != nil {
|
|
if strings.Contains(err.Error(), "Unknown job") {
|
|
// dhcpserver service does not exist.
|
|
return nil
|
|
}
|
|
return fmt.Errorf("exec.Command: %w", err)
|
|
}
|
|
if bytes.Contains(out, []byte("start/running")) {
|
|
return nil
|
|
}
|
|
b.BackOff(context.Background(), errors.New("ntp not ready"))
|
|
}
|
|
}
|