mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-02-03 22:18:39 +00:00
On routers where we want to wait for NTP by checking nvram key. Before waiting, we clean up the router to ensure it's restored to original state. However, router.Cleanup is not idempotent, causing dnsmasq restarted. On tomato/ddwrt, restarting have no delay, and spawning new dnsmasq process immediately. On merlin, somehow it takes time to spawn new dnsmasq process, causing ctrld wrongly think there's no one listening on port 53. Fixing this by ensuring router.Cleanup is idempotent. While at it, also adding "ntp_done" to nvram key, which is now using on latest ddwrt.
50 lines
1.3 KiB
Go
50 lines
1.3 KiB
Go
package ntp
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"os/exec"
|
|
"time"
|
|
|
|
"tailscale.com/logtail/backoff"
|
|
|
|
"github.com/Control-D-Inc/ctrld/internal/router/nvram"
|
|
)
|
|
|
|
// WaitNvram waits NTP synced by checking "ntp_ready" value using nvram.
|
|
func WaitNvram() error {
|
|
// Wait until `ntp_ready=1` set.
|
|
b := backoff.NewBackoff("ntp.Wait", func(format string, args ...any) {}, 10*time.Second)
|
|
for {
|
|
// ddwrt use "ntp_done": https://github.com/mirror/dd-wrt/blob/a08c693527ab3204bf7bebd408a7c9a83b6ede47/src/router/rc/ntp.c#L100
|
|
for _, key := range []string{"ntp_ready", "ntp_done"} {
|
|
out, err := nvram.Run("get", key)
|
|
if err != nil {
|
|
return fmt.Errorf("PreStart: nvram: %w", err)
|
|
}
|
|
if out == "1" {
|
|
return nil
|
|
}
|
|
}
|
|
b.BackOff(context.Background(), errors.New("ntp not ready"))
|
|
}
|
|
}
|
|
|
|
// WaitUpstart waits NTP synced by checking upstart task "ntpsync" is in "stop/waiting" state.
|
|
func WaitUpstart() error {
|
|
// Wait until `initctl status ntpsync` returns stop state.
|
|
b := backoff.NewBackoff("ntp.WaitUpstart", func(format string, args ...any) {}, 10*time.Second)
|
|
for {
|
|
out, err := exec.Command("initctl", "status", "ntpsync").CombinedOutput()
|
|
if err != nil {
|
|
return fmt.Errorf("exec.Command: %w", err)
|
|
}
|
|
if bytes.Contains(out, []byte("stop/waiting")) {
|
|
return nil
|
|
}
|
|
b.BackOff(context.Background(), errors.New("ntp not ready"))
|
|
}
|
|
}
|