// tera-netd is the minimal privileged dual-Ethernet configuration adapter. package main import ( "context" "errors" "log" "net" "os" "os/signal" "path/filepath" "syscall" "time" "tera-clone/services/tera-api/internal/networkconfig" "tera-clone/services/tera-api/internal/networkconfig/netsocket" ) func main() { controller, err := networkconfig.NewOSController(networkconfig.OSOptions{ InterfacesPath: getenv("TERA_NETD_INTERFACES", networkconfig.DefaultInterfacesPath), RoutingPath: getenv("TERA_NETD_ROUTING_SCRIPT", networkconfig.DefaultRoutingPath), ConfigPath: getenv("TERA_NETD_CONFIG", networkconfig.DefaultConfigPath), PendingPath: getenv("TERA_NETD_PENDING", networkconfig.DefaultPendingPath), HostnamePath: getenv("TERA_NETD_HOSTNAME_FILE", networkconfig.DefaultHostnamePath), HostnameCommandPath: getenv("TERA_NETD_HOSTNAME_COMMAND", "/bin/hostname"), IfdownPath: getenv("TERA_NETD_IFDOWN", "/sbin/ifdown"), IfupPath: getenv("TERA_NETD_IFUP", "/sbin/ifup"), IPPath: getenv("TERA_NETD_IP", "/sbin/ip"), PingPath: getenv("TERA_NETD_PING", "/bin/ping"), ShellPath: getenv("TERA_NETD_SHELL", "/bin/sh"), SysClassRoot: getenv("TERA_NETD_SYS_CLASS_ROOT", "/sys/class/net"), }) if err != nil { log.Fatalf("tera-netd setup failed: %v", err) } recoveryContext, cancelRecovery := context.WithTimeout(context.Background(), 30*time.Second) if err := controller.Recover(recoveryContext); err != nil { log.Printf("tera-netd recovery incomplete; starting control socket for operator retry: %v", err) } cancelRecovery() monitorContext, stopMonitor := context.WithCancel(context.Background()) defer stopMonitor() go controller.RunOOBMonitor(monitorContext) socketPath := getenv("TERA_NETD_SOCKET", netsocket.DefaultSocketPath) listener, err := listen(socketPath) if err != nil { log.Fatalf("tera-netd socket setup failed: %v", err) } defer func() { _ = listener.Close() _ = os.Remove(socketPath) }() server := netsocket.Server{Controller: controller} done := make(chan error, 1) go func() { done <- server.Serve(listener) }() log.Printf("tera-netd serving network control on %s", socketPath) signals := make(chan os.Signal, 1) signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM) select { case signal := <-signals: log.Printf("tera-netd stopping after %s", signal) _ = listener.Close() if err := <-done; err != nil { log.Printf("tera-netd stop error: %v", err) } case err := <-done: if err != nil { log.Fatalf("tera-netd failed: %v", err) } } } func listen(socketPath string) (net.Listener, error) { if socketPath == "" || !filepath.IsAbs(socketPath) { return nil, errors.New("TERA_NETD_SOCKET must be an absolute path") } if err := os.MkdirAll(filepath.Dir(socketPath), 0o750); err != nil { return nil, err } if info, err := os.Lstat(socketPath); err == nil { if info.Mode()&os.ModeSocket == 0 { return nil, errors.New("refusing to replace non-socket network control path") } if err := os.Remove(socketPath); err != nil { return nil, err } } else if !os.IsNotExist(err) { return nil, err } listener, err := net.Listen("unix", socketPath) if err != nil { return nil, err } if err := os.Chmod(socketPath, 0o660); err != nil { _ = listener.Close() return nil, err } return listener, nil } func getenv(key, fallback string) string { if value := os.Getenv(key); value != "" { return value } return fallback }