From 58861a7cbcd8f745ec0cc99e7dced13da07eff68 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Wed, 18 Jan 2017 22:24:27 -0500 Subject: initial commit --- .gitignore | 2 + Makefile | 24 +++++++++ systemd-timesyncd-wait.go | 29 +++++++++++ systemd-timesyncd-wait.service | 11 ++++ systemd-timesyncd-wait.socket | 7 +++ systemd-timesyncd-wrap.go | 98 +++++++++++++++++++++++++++++++++++ systemd-timesyncd.service.d-wait.conf | 7 +++ 7 files changed, 178 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 systemd-timesyncd-wait.go create mode 100644 systemd-timesyncd-wait.service create mode 100644 systemd-timesyncd-wait.socket create mode 100644 systemd-timesyncd-wrap.go create mode 100644 systemd-timesyncd.service.d-wait.conf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f2c3279 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/systemd-timesyncd-wait +/systemd-timesyncd-wrap diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..282ed1a --- /dev/null +++ b/Makefile @@ -0,0 +1,24 @@ +files.out.all += systemd-timesyncd-wait systemd-timesyncd-wrap +files.sys.all += /usr/lib/systemd/systemd-timesyncd-wait +files.sys.all += /usr/lib/systemd/systemd-timesyncd-wrap +files.sys.all += /usr/lib/systemd/system/systemd-timesyncd-wait.socket +files.sys.all += /usr/lib/systemd/system/systemd-timesyncd-wait.service +files.sys.all += /usr/lib/systemd/system/systemd-timesyncd.service.d/wait.conf + +outdir = . +srcdir = . +all: $(addprefix $(outdir)/,$(files.out.all)) +clean: + rm -f -- $(addprefix $(outdir)/,$(files.out.all)) +install: $(addprefix $(DESTDIR),$(files.sys.all)) +.PHONY: all clean install + +$(outdir)/%: $(srcdir)/%.go + go build -o $@ $< + +$(DESTDIR)/usr/lib/systemd/%: $(outdir)/% + install -DTm755 $< $@ +$(DESTDIR)/usr/lib/systemd/system/%: $(srcdir)/% + install -DTm644 $< $@ +$(DESTDIR)/usr/lib/systemd/system/systemd-timesyncd.service.d/wait.conf: systemd-timesyncd.service.d-wait.conf + install -DTm644 $< $@ diff --git a/systemd-timesyncd-wait.go b/systemd-timesyncd-wait.go new file mode 100644 index 0000000..9275502 --- /dev/null +++ b/systemd-timesyncd-wait.go @@ -0,0 +1,29 @@ +package main + +import ( + "net" + "os" +) + +func main() { + sync_sockname := "/run/timesyncd/time-sync.sock" + + sync_sock, err := net.ListenUnixgram("unixgram", &net.UnixAddr{Net: "unixgram", Name: sync_sockname}) + if err != nil { + os.Stderr.WriteString(err.Error()) + os.Stderr.Write([]byte{'\n'}) + os.Exit(127) + } + + var dat [4096]byte + n, err := sync_sock.Read(dat[:]) + if err != nil { + os.Stderr.WriteString(err.Error()) + os.Stderr.Write([]byte{'\n'}) + os.Exit(127) + } + if string(dat[:n]) != "READY=1" { + os.Exit(127) + } + os.Exit(0) +} diff --git a/systemd-timesyncd-wait.service b/systemd-timesyncd-wait.service new file mode 100644 index 0000000..3237130 --- /dev/null +++ b/systemd-timesyncd-wait.service @@ -0,0 +1,11 @@ +[Unit] +Description=Network Time Synchronized +DefaultDependencies=no +After=systemd-timesyncd-wait.socket +Before=time-sync.target +Wants=time-sync.target systemd-timesyncd-wait.socket + +[Service] +Type=oneshot +ExecStart=/usr/lib/systemd/systemd-timesyncd-wait +TimeoutStartSec=infinity diff --git a/systemd-timesyncd-wait.socket b/systemd-timesyncd-wait.socket new file mode 100644 index 0000000..3112218 --- /dev/null +++ b/systemd-timesyncd-wait.socket @@ -0,0 +1,7 @@ +[Unit] +Description=Network Time Synchronized Socket +DefaultDependencies=no +After=systemd-remount-fs.service systemd-tmpfiles-setup.service + +[Socket] +ListenDatagram=/run/timesyncd/time-sync.sock diff --git a/systemd-timesyncd-wrap.go b/systemd-timesyncd-wrap.go new file mode 100644 index 0000000..3d5971b --- /dev/null +++ b/systemd-timesyncd-wrap.go @@ -0,0 +1,98 @@ +package main + +import ( + "net" + "os" + "strings" + "sync" + "syscall" +) + +func socketUnixgram(name string) (*net.UnixConn, error) { + fd, err := syscall.Socket(syscall.AF_UNIX, syscall.SOCK_DGRAM|syscall.SOCK_CLOEXEC, 0) + if err != nil { + return nil, err + } + conn, err := net.FileConn(os.NewFile(uintptr(fd), name)) + if err != nil { + return nil, err + } + unixConn := conn.(*net.UnixConn) + return unixConn, nil +} + +func sendmsg(dat, oob []byte, sockname string) error { + writer, err := socketUnixgram(sockname) + if err != nil { + return err + } + _, _, err = writer.WriteMsgUnix(dat, oob, &net.UnixAddr{Net: "unixgram", Name: sockname}) + return err +} + +func main() { + sync_sockname := "/run/timesyncd/time-sync.sock" + fake_sockname := "/run/timesyncd/notify.sock" + real_sockname := os.Getenv("NOTIFY_SOCKET") + + fake_sock, err := net.ListenUnixgram("unixgram", &net.UnixAddr{Net: "unixgram", Name: fake_sockname}) + if err != nil { + os.Stderr.WriteString(err.Error()) + os.Stderr.Write([]byte{'\n'}) + os.Exit(127) + } + + os.Setenv("NOTIFY_SOCKET", fake_sockname) + proc, err := os.StartProcess(os.Args[1], os.Args[1:], &os.ProcAttr{}) + if err != nil { + os.Stderr.WriteString(err.Error()) + os.Stderr.Write([]byte{'\n'}) + os.Exit(127) + } + + var wg sync.WaitGroup + wg.Add(1) + go func() { + synced := false + var dat [4096]byte + oob := make([]byte, syscall.CmsgSpace(syscall.SizeofUcred)+syscall.CmsgSpace(8*768)) + for { + n, oobn, flags, _, err := fake_sock.ReadMsgUnix(dat[:], oob[:]) + if err != nil { + break + } + if flags&syscall.MSG_TRUNC != 0 { + continue + } + if !synced { + for _, line := range strings.Split(string(dat[:n]), "\n") { + if strings.HasPrefix(line, "STATUS=Synchronized") { + _ = sendmsg([]byte(line), nil, sync_sockname) + synced = true + break + } + } + } + _ = sendmsg(dat[:n], oob[:oobn], real_sockname) + } + wg.Done() + }() + + state, err := proc.Wait() + _ = fake_sock.Close() + wg.Wait() + + if err != nil { + os.Stderr.WriteString(err.Error()) + os.Stderr.Write([]byte{'\n'}) + os.Exit(127) + } + status := state.Sys().(syscall.WaitStatus) + if status.Exited() { + os.Exit(status.ExitStatus()) + } + if status.Signaled() { + self, _ := os.FindProcess(os.Getpid()) + self.Signal(status.Signal()) + } +} diff --git a/systemd-timesyncd.service.d-wait.conf b/systemd-timesyncd.service.d-wait.conf new file mode 100644 index 0000000..8342e53 --- /dev/null +++ b/systemd-timesyncd.service.d-wait.conf @@ -0,0 +1,7 @@ +[Unit] +Wants=systemd-timesyncd-wait.socket +After=systemd-timesyncd-wait.socket + +[Service] +Sockets= +ExecStart=/usr/lib/systemd/systemd-timesyncd-wrap /usr/lib/systemd/systemd-timesyncd -- cgit v1.1-4-g5e80