This commit is contained in:
Daniel
2024-11-27 16:16:15 +01:00
parent f91003d077
commit 706ce222d0
35 changed files with 1138 additions and 601 deletions

View File

@@ -1,12 +1,14 @@
package main
package cmdbase
import (
"context"
"errors"
"flag"
"fmt"
"io"
"log/slog"
"os"
"os/exec"
"runtime"
"runtime/pprof"
"time"
@@ -15,14 +17,12 @@ import (
"github.com/safing/portmaster/base/log"
"github.com/safing/portmaster/service"
"github.com/safing/portmaster/service/mgr"
"github.com/safing/portmaster/spn/conf"
)
var printStackOnExit bool
func init() {
flag.BoolVar(&printStackOnExit, "print-stack-on-exit", false, "prints the stack before of shutting down")
}
var (
RebootOnRestart bool
PrintStackOnExit bool
)
type SystemService interface {
Run()
@@ -30,21 +30,47 @@ type SystemService interface {
RestartService() error
}
func cmdRun(cmd *cobra.Command, args []string) {
// Run platform specific setup or switches.
runPlatformSpecifics(cmd, args)
type ServiceInstance interface {
Ready() bool
Start() error
Stop() error
Restart()
Shutdown()
Ctx() context.Context
IsShuttingDown() bool
ShuttingDown() <-chan struct{}
ShutdownCtx() context.Context
IsShutDown() bool
ShutdownComplete() <-chan struct{}
ExitCode() int
ShouldRestartIsSet() bool
CommandLineOperationIsSet() bool
CommandLineOperationExecute() error
}
// SETUP
var (
SvcFactory func(*service.ServiceConfig) (ServiceInstance, error)
SvcConfig *service.ServiceConfig
)
// Enable SPN client mode.
// TODO: Move this to service config.
conf.EnableClient(true)
conf.EnableIntegration(true)
func RunService(cmd *cobra.Command, args []string) {
if SvcFactory == nil || SvcConfig == nil {
fmt.Fprintln(os.Stderr, "internal error: service not set up in cmdbase")
os.Exit(1)
}
// Start logging.
// Note: Must be created before the service instance, so that they use the right logger.
err := log.Start(SvcConfig.LogLevel, SvcConfig.LogToStdout, SvcConfig.LogDir)
if err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(4)
}
// Create instance.
// Instance modules might request a cmdline execution of a function.
var execCmdLine bool
instance, err := service.New(svcCfg)
instance, err := SvcFactory(SvcConfig)
switch {
case err == nil:
// Continue
@@ -59,13 +85,13 @@ func cmdRun(cmd *cobra.Command, args []string) {
switch {
case !execCmdLine:
// Run service.
case instance.CommandLineOperation == nil:
case !instance.CommandLineOperationIsSet():
fmt.Println("command line operation execution requested, but not set")
os.Exit(3)
default:
// Run the function and exit.
fmt.Println("executing cmdline op")
err = instance.CommandLineOperation()
err = instance.CommandLineOperationExecute()
if err != nil {
fmt.Fprintf(os.Stderr, "command line operation failed: %s\n", err)
os.Exit(3)
@@ -75,16 +101,6 @@ func cmdRun(cmd *cobra.Command, args []string) {
// START
// FIXME: fix color and duplicate level when logging with slog
// FIXME: check for tty for color enabling
// Start logging.
err = log.Start(svcCfg.LogLevel, svcCfg.LogToStdout, svcCfg.LogDir)
if err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(4)
}
// Create system service.
service := NewSystemService(instance)
@@ -102,7 +118,7 @@ func cmdRun(cmd *cobra.Command, args []string) {
select {
case <-instance.ShutdownComplete():
// Print stack on shutdown, if enabled.
if printStackOnExit {
if PrintStackOnExit {
printStackTo(log.GlobalWriter, "PRINTING STACK ON EXIT")
}
case <-time.After(3 * time.Minute):
@@ -110,9 +126,22 @@ func cmdRun(cmd *cobra.Command, args []string) {
}
// Check if restart was triggered and send start service command if true.
if instance.ShouldRestart && service.IsService() {
if err := service.RestartService(); err != nil {
slog.Error("failed to restart service", "err", err)
if instance.ShouldRestartIsSet() && service.IsService() {
// Check if we should reboot instead.
var rebooting bool
if RebootOnRestart {
// Trigger system reboot and record success.
rebooting = triggerSystemReboot()
if !rebooting {
log.Warningf("updates: rebooting failed, only restarting service instead")
}
}
// Restart service if not rebooting.
if !rebooting {
if err := service.RestartService(); err != nil {
slog.Error("failed to restart service", "err", err)
}
}
}
@@ -138,3 +167,19 @@ func printStackTo(writer io.Writer, msg string) {
slog.Error("failed to write stack trace", "err", err)
}
}
func triggerSystemReboot() (success bool) {
switch runtime.GOOS {
case "linux":
err := exec.Command("systemctl", "reboot").Run()
if err != nil {
log.Errorf("updates: triggering reboot with systemctl failed: %s", err)
return false
}
default:
log.Warningf("updates: rebooting is not support on %s", runtime.GOOS)
return false
}
return true
}

View File

@@ -1,4 +1,4 @@
package main
package cmdbase
import (
"fmt"
@@ -9,17 +9,15 @@ import (
"syscall"
processInfo "github.com/shirou/gopsutil/process"
"github.com/spf13/cobra"
"github.com/safing/portmaster/base/log"
"github.com/safing/portmaster/service"
)
type LinuxSystemService struct {
instance *service.Instance
instance ServiceInstance
}
func NewSystemService(instance *service.Instance) *LinuxSystemService {
func NewSystemService(instance ServiceInstance) *LinuxSystemService {
return &LinuxSystemService{instance: instance}
}
@@ -30,7 +28,7 @@ func (s *LinuxSystemService) Run() {
slog.Error("failed to start", "err", err)
// Print stack on start failure, if enabled.
if printStackOnExit {
if PrintStackOnExit {
printStackTo(log.GlobalWriter, "PRINTING STACK ON START FAILURE")
}
@@ -62,7 +60,7 @@ wait:
continue wait
} else {
// Trigger shutdown.
fmt.Printf(" <SIGNAL: %v>", sig) // CLI output.
fmt.Printf(" <SIGNAL: %v>\n", sig) // CLI output.
slog.Warn("received stop signal", "signal", sig)
s.instance.Shutdown()
break wait
@@ -128,18 +126,3 @@ func (s *LinuxSystemService) IsService() bool {
// Check if the parent process ID is 1 == init system
return ppid == 1
}
func runPlatformSpecifics(cmd *cobra.Command, args []string) {
// If recover-iptables flag is set, run the recover-iptables command.
// This is for backwards compatibility
if recoverIPTables {
exitCode := 0
err := recover(cmd, args)
if err != nil {
fmt.Printf("failed: %s", err)
exitCode = 1
}
os.Exit(exitCode)
}
}

View File

@@ -1,4 +1,4 @@
package main
package cmdbase
// Based on the official Go examples from
// https://github.com/golang/sys/blob/master/windows/svc/example
@@ -13,21 +13,19 @@ import (
"os/signal"
"syscall"
"github.com/spf13/cobra"
"golang.org/x/sys/windows/svc"
"golang.org/x/sys/windows/svc/debug"
"github.com/safing/portmaster/base/log"
"github.com/safing/portmaster/service"
)
const serviceName = "PortmasterCore"
type WindowsSystemService struct {
instance *service.Instance
instance ServiceInstance
}
func NewSystemService(instance *service.Instance) *WindowsSystemService {
func NewSystemService(instance ServiceInstance) *WindowsSystemService {
return &WindowsSystemService{instance: instance}
}
@@ -67,7 +65,7 @@ func (s *WindowsSystemService) Execute(args []string, changeRequests <-chan svc.
fmt.Printf("failed to start: %s\n", err)
// Print stack on start failure, if enabled.
if printStackOnExit {
if PrintStackOnExit {
printStackTo(log.GlobalWriter, "PRINTING STACK ON START FAILURE")
}
@@ -102,7 +100,7 @@ waitSignal:
select {
case sig := <-signalCh:
// Trigger shutdown.
fmt.Printf(" <SIGNAL: %v>", sig) // CLI output.
fmt.Printf(" <SIGNAL: %v>\n", sig) // CLI output.
slog.Warn("received stop signal", "signal", sig)
break waitSignal
@@ -112,7 +110,7 @@ waitSignal:
changes <- c.CurrentStatus
case svc.Stop, svc.Shutdown:
fmt.Printf(" <SERVICE CMD: %v>", serviceCmdName(c.Cmd)) // CLI output.
fmt.Printf(" <SERVICE CMD: %v>\n", serviceCmdName(c.Cmd)) // CLI output.
slog.Warn("received service shutdown command", "cmd", c.Cmd)
break waitSignal
@@ -201,8 +199,6 @@ sc.exe start $serviceName`
return nil
}
func runPlatformSpecifics(cmd *cobra.Command, args []string)
func serviceCmdName(cmd svc.Cmd) string {
switch cmd {
case svc.Stop:

View File

@@ -1,4 +1,4 @@
package main
package cmdbase
import (
"fmt"
@@ -12,32 +12,28 @@ import (
"github.com/safing/portmaster/service/updates"
)
var updateCmd = &cobra.Command{
var UpdateCmd = &cobra.Command{
Use: "update",
Short: "Force an update of all components.",
RunE: update,
}
func init() {
rootCmd.AddCommand(updateCmd)
}
func update(cmd *cobra.Command, args []string) error {
// Finalize config.
err := svcCfg.Init()
err := SvcConfig.Init()
if err != nil {
return fmt.Errorf("internal configuration error: %w", err)
}
// Force logging to stdout.
svcCfg.LogToStdout = true
SvcConfig.LogToStdout = true
// Start logging.
_ = log.Start(svcCfg.LogLevel, svcCfg.LogToStdout, svcCfg.LogDir)
_ = log.Start(SvcConfig.LogLevel, SvcConfig.LogToStdout, SvcConfig.LogDir)
defer log.Shutdown()
// Create updaters.
instance := &updateDummyInstance{}
binaryUpdateConfig, intelUpdateConfig, err := service.MakeUpdateConfigs(svcCfg)
binaryUpdateConfig, intelUpdateConfig, err := service.MakeUpdateConfigs(SvcConfig)
if err != nil {
return fmt.Errorf("init updater config: %w", err)
}

20
cmds/cmdbase/version.go Normal file
View File

@@ -0,0 +1,20 @@
package cmdbase
import (
"fmt"
"github.com/spf13/cobra"
"github.com/safing/portmaster/base/info"
)
var VersionCmd = &cobra.Command{
Use: "version",
Short: "Show version and related metadata.",
RunE: Version,
}
func Version(cmd *cobra.Command, args []string) error {
fmt.Println(info.FullVersion())
return nil
}

View File

@@ -1,158 +1,94 @@
package main
import (
"errors"
"flag"
"fmt"
"io"
"log/slog"
"os"
"os/signal"
"runtime"
"runtime/pprof"
"syscall"
"time"
"github.com/spf13/cobra"
"github.com/safing/portmaster/base/info"
"github.com/safing/portmaster/base/log"
"github.com/safing/portmaster/base/metrics"
"github.com/safing/portmaster/service/mgr"
"github.com/safing/portmaster/cmds/cmdbase"
"github.com/safing/portmaster/service"
"github.com/safing/portmaster/service/configure"
"github.com/safing/portmaster/service/updates"
"github.com/safing/portmaster/spn"
"github.com/safing/portmaster/spn/conf"
)
var (
rootCmd = &cobra.Command{
Use: "spn-hub",
PersistentPreRun: initializeGlobals,
Run: cmdbase.RunService,
}
binDir string
dataDir string
logToStdout bool
logDir string
logLevel string
)
func init() {
// flag.BoolVar(&updates.RebootOnRestart, "reboot-on-restart", false, "reboot server on auto-upgrade")
// FIXME
// Add persisent flags for all commands.
rootCmd.PersistentFlags().StringVar(&binDir, "bin-dir", "", "set directory for executable binaries (rw/ro)")
rootCmd.PersistentFlags().StringVar(&dataDir, "data-dir", "", "set directory for variable data (rw)")
// Add flags for service only.
rootCmd.Flags().BoolVar(&logToStdout, "log-stdout", false, "log to stdout instead of file")
rootCmd.Flags().StringVar(&logDir, "log-dir", "", "set directory for logs")
rootCmd.Flags().StringVar(&logLevel, "log", "", "set log level to [trace|debug|info|warning|error|critical]")
rootCmd.Flags().BoolVar(&cmdbase.PrintStackOnExit, "print-stack-on-exit", false, "prints the stack before of shutting down")
rootCmd.Flags().BoolVar(&cmdbase.RebootOnRestart, "reboot-on-restart", false, "reboot server instead of service restart")
// Add other commands.
rootCmd.AddCommand(cmdbase.VersionCmd)
rootCmd.AddCommand(cmdbase.UpdateCmd)
}
var sigUSR1 = syscall.Signal(0xa)
func main() {
flag.Parse()
// Add Go's default flag set.
// TODO: Move flags throughout Portmaster to here and add their values to the service config.
rootCmd.Flags().AddGoFlagSet(flag.CommandLine)
// Set name and license.
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
func initializeGlobals(cmd *cobra.Command, args []string) {
// Set version info.
info.Set("SPN Hub", "", "GPLv3")
// Configure metrics.
_ = metrics.SetNamespace("hub")
// Configure user agent and updates.
// Configure user agent.
updates.UserAgent = fmt.Sprintf("SPN Hub (%s %s)", runtime.GOOS, runtime.GOARCH)
// helper.IntelOnly()
// Set SPN public hub mode.
conf.EnablePublicHub(true)
// Start logger with default log level.
_ = log.Start(log.WarningLevel)
// FIXME: Use service?
// Create instance.
var execCmdLine bool
instance, err := spn.New()
switch {
case err == nil:
// Continue
case errors.Is(err, mgr.ErrExecuteCmdLineOp):
execCmdLine = true
default:
fmt.Printf("error creating an instance: %s\n", err)
os.Exit(2)
// Configure service.
cmdbase.SvcFactory = func(svcCfg *service.ServiceConfig) (cmdbase.ServiceInstance, error) {
svc, err := service.New(svcCfg)
return svc, err
}
cmdbase.SvcConfig = &service.ServiceConfig{
BinDir: binDir,
DataDir: dataDir,
// Execute command line operation, if requested or available.
switch {
case !execCmdLine:
// Run service.
case instance.CommandLineOperation == nil:
fmt.Println("command line operation execution requested, but not set")
os.Exit(3)
default:
// Run the function and exit.
err = instance.CommandLineOperation()
if err != nil {
fmt.Fprintf(os.Stderr, "command line operation failed: %s\n", err)
os.Exit(3)
}
os.Exit(0)
}
LogToStdout: logToStdout,
LogDir: logDir,
LogLevel: logLevel,
// Start
go func() {
err = instance.Start()
if err != nil {
fmt.Printf("instance start failed: %s\n", err)
os.Exit(1)
}
}()
// Wait for signal.
signalCh := make(chan os.Signal, 1)
signal.Notify(
signalCh,
os.Interrupt,
syscall.SIGHUP,
syscall.SIGINT,
syscall.SIGTERM,
syscall.SIGQUIT,
sigUSR1,
)
select {
case sig := <-signalCh:
// Only print and continue to wait if SIGUSR1
if sig == sigUSR1 {
printStackTo(os.Stderr, "PRINTING STACK ON REQUEST")
} else {
fmt.Println(" <INTERRUPT>") // CLI output.
slog.Warn("program was interrupted, stopping")
}
case <-instance.ShutdownComplete():
log.Shutdown()
os.Exit(instance.ExitCode())
}
// Catch signals during shutdown.
// Rapid unplanned disassembly after 5 interrupts.
go func() {
forceCnt := 5
for {
<-signalCh
forceCnt--
if forceCnt > 0 {
fmt.Printf(" <INTERRUPT> again, but already shutting down - %d more to force\n", forceCnt)
} else {
printStackTo(os.Stderr, "PRINTING STACK ON FORCED EXIT")
os.Exit(1)
}
}
}()
// Rapid unplanned disassembly after 3 minutes.
go func() {
time.Sleep(3 * time.Minute)
printStackTo(os.Stderr, "PRINTING STACK - TAKING TOO LONG FOR SHUTDOWN")
os.Exit(1)
}()
// Stop instance.
if err := instance.Stop(); err != nil {
slog.Error("failed to stop", "err", err)
}
log.Shutdown()
os.Exit(instance.ExitCode())
}
func printStackTo(writer io.Writer, msg string) {
_, err := fmt.Fprintf(writer, "===== %s =====\n", msg)
if err == nil {
err = pprof.Lookup("goroutine").WriteTo(writer, 1)
}
if err != nil {
slog.Error("failed to write stack trace", "err", err)
BinariesIndexURLs: configure.DefaultStableBinaryIndexURLs,
IntelIndexURLs: configure.DefaultIntelIndexURLs,
VerifyBinaryUpdates: configure.BinarySigningTrustStore,
VerifyIntelUpdates: configure.BinarySigningTrustStore,
}
}

View File

@@ -1,41 +1,75 @@
package main
import (
"errors"
"flag"
"fmt"
"io"
"log/slog"
"os"
"os/signal"
"runtime"
"runtime/pprof"
"syscall"
"time"
"github.com/safing/portmaster/base/api"
"github.com/safing/portmaster/base/info"
"github.com/safing/portmaster/base/log"
"github.com/safing/portmaster/base/metrics"
"github.com/safing/portmaster/service/mgr"
"github.com/safing/portmaster/cmds/cmdbase"
"github.com/safing/portmaster/service"
"github.com/safing/portmaster/service/configure"
"github.com/safing/portmaster/service/updates"
"github.com/safing/portmaster/spn"
"github.com/safing/portmaster/spn/captain"
"github.com/safing/portmaster/spn/conf"
"github.com/safing/portmaster/spn/sluice"
"github.com/spf13/cobra"
)
var sigUSR1 = syscall.Signal(0xa)
var (
rootCmd = &cobra.Command{
Use: "observation-hub",
PersistentPreRun: initializeGlobals,
Run: cmdbase.RunService,
}
binDir string
dataDir string
logToStdout bool
logDir string
logLevel string
)
func init() {
// Add persisent flags for all commands.
rootCmd.PersistentFlags().StringVar(&binDir, "bin-dir", "", "set directory for executable binaries (rw/ro)")
rootCmd.PersistentFlags().StringVar(&dataDir, "data-dir", "", "set directory for variable data (rw)")
// Add flags for service only.
rootCmd.Flags().BoolVar(&logToStdout, "log-stdout", false, "log to stdout instead of file")
rootCmd.Flags().StringVar(&logDir, "log-dir", "", "set directory for logs")
rootCmd.Flags().StringVar(&logLevel, "log", "", "set log level to [trace|debug|info|warning|error|critical]")
rootCmd.Flags().BoolVar(&cmdbase.PrintStackOnExit, "print-stack-on-exit", false, "prints the stack before of shutting down")
rootCmd.Flags().BoolVar(&cmdbase.RebootOnRestart, "reboot-on-restart", false, "reboot server instead of service restart")
// Add other commands.
rootCmd.AddCommand(cmdbase.VersionCmd)
rootCmd.AddCommand(cmdbase.UpdateCmd)
}
func main() {
flag.Parse()
// Add Go's default flag set.
// TODO: Move flags throughout Portmaster to here and add their values to the service config.
rootCmd.Flags().AddGoFlagSet(flag.CommandLine)
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
func initializeGlobals(cmd *cobra.Command, args []string) {
// Set version info.
info.Set("SPN Observation Hub", "", "GPLv3")
// Configure metrics.
_ = metrics.SetNamespace("observer")
// Configure user agent and updates.
// Configure user agent.
updates.UserAgent = fmt.Sprintf("SPN Observation Hub (%s %s)", runtime.GOOS, runtime.GOARCH)
// Configure SPN mode.
@@ -46,129 +80,37 @@ func main() {
sluice.EnableListener = false
api.EnableServer = false
// Start logger with default log level.
_ = log.Start(log.WarningLevel)
// Configure service.
cmdbase.SvcFactory = func(svcCfg *service.ServiceConfig) (cmdbase.ServiceInstance, error) {
svc, err := service.New(svcCfg)
// Create instance.
var execCmdLine bool
instance, err := spn.New()
switch {
case err == nil:
// Continue
case errors.Is(err, mgr.ErrExecuteCmdLineOp):
execCmdLine = true
default:
fmt.Printf("error creating an instance: %s\n", err)
os.Exit(2)
}
// Add additional modules.
observer, err := New(instance)
if err != nil {
fmt.Printf("error creating an instance: create observer module: %s\n", err)
os.Exit(2)
}
instance.AddModule(observer)
_, err = NewApprise(instance)
if err != nil {
fmt.Printf("error creating an instance: create apprise module: %s\n", err)
os.Exit(2)
}
instance.AddModule(observer)
// FIXME: Use service?
// Execute command line operation, if requested or available.
switch {
case !execCmdLine:
// Run service.
case instance.CommandLineOperation == nil:
fmt.Println("command line operation execution requested, but not set")
os.Exit(3)
default:
// Run the function and exit.
err = instance.CommandLineOperation()
// Add additional modules.
observer, err := New(svc)
if err != nil {
fmt.Fprintf(os.Stderr, "command line operation failed: %s\n", err)
os.Exit(3)
fmt.Printf("error creating an instance: create observer module: %s\n", err)
os.Exit(2)
}
os.Exit(0)
}
// Start
go func() {
err = instance.Start()
svc.AddModule(observer)
_, err = NewApprise(svc)
if err != nil {
fmt.Printf("instance start failed: %s\n", err)
os.Exit(1)
fmt.Printf("error creating an instance: create apprise module: %s\n", err)
os.Exit(2)
}
}()
svc.AddModule(observer)
// Wait for signal.
signalCh := make(chan os.Signal, 1)
signal.Notify(
signalCh,
os.Interrupt,
syscall.SIGHUP,
syscall.SIGINT,
syscall.SIGTERM,
syscall.SIGQUIT,
sigUSR1,
)
select {
case sig := <-signalCh:
// Only print and continue to wait if SIGUSR1
if sig == sigUSR1 {
printStackTo(os.Stderr, "PRINTING STACK ON REQUEST")
} else {
fmt.Println(" <INTERRUPT>") // CLI output.
slog.Warn("program was interrupted, stopping")
}
case <-instance.ShuttingDown():
log.Shutdown()
os.Exit(instance.ExitCode())
return svc, err
}
cmdbase.SvcConfig = &service.ServiceConfig{
BinDir: binDir,
DataDir: dataDir,
// Catch signals during shutdown.
// Rapid unplanned disassembly after 5 interrupts.
go func() {
forceCnt := 5
for {
<-signalCh
forceCnt--
if forceCnt > 0 {
fmt.Printf(" <INTERRUPT> again, but already shutting down - %d more to force\n", forceCnt)
} else {
printStackTo(os.Stderr, "PRINTING STACK ON FORCED EXIT")
os.Exit(1)
}
}
}()
LogToStdout: logToStdout,
LogDir: logDir,
LogLevel: logLevel,
// Rapid unplanned disassembly after 3 minutes.
go func() {
time.Sleep(3 * time.Minute)
printStackTo(os.Stderr, "PRINTING STACK - TAKING TOO LONG FOR SHUTDOWN")
os.Exit(1)
}()
// Stop instance.
if err := instance.Stop(); err != nil {
slog.Error("failed to stop", "err", err)
}
log.Shutdown()
os.Exit(instance.ExitCode())
}
func printStackTo(writer io.Writer, msg string) {
_, err := fmt.Fprintf(writer, "===== %s =====\n", msg)
if err == nil {
err = pprof.Lookup("goroutine").WriteTo(writer, 1)
}
if err != nil {
slog.Error("failed to write stack trace", "err", err)
BinariesIndexURLs: configure.DefaultStableBinaryIndexURLs,
IntelIndexURLs: configure.DefaultIntelIndexURLs,
VerifyBinaryUpdates: configure.BinarySigningTrustStore,
VerifyIntelUpdates: configure.BinarySigningTrustStore,
}
}

View File

@@ -10,7 +10,9 @@ import (
"github.com/safing/portmaster/base/info"
"github.com/safing/portmaster/base/metrics"
"github.com/safing/portmaster/cmds/cmdbase"
"github.com/safing/portmaster/service"
"github.com/safing/portmaster/service/configure"
"github.com/safing/portmaster/service/updates"
)
@@ -18,7 +20,7 @@ var (
rootCmd = &cobra.Command{
Use: "portmaster-core",
PersistentPreRun: initializeGlobals,
Run: cmdRun,
Run: mainRun,
}
binDir string
@@ -28,14 +30,10 @@ var (
logDir string
logLevel string
svcCfg *service.ServiceConfig
printVersion bool
)
func init() {
// Add Go's default flag set.
// TODO: Move flags throughout Portmaster to here and add their values to the service config.
rootCmd.Flags().AddGoFlagSet(flag.CommandLine)
// Add persisent flags for all commands.
rootCmd.PersistentFlags().StringVar(&binDir, "bin-dir", "", "set directory for executable binaries (rw/ro)")
rootCmd.PersistentFlags().StringVar(&dataDir, "data-dir", "", "set directory for variable data (rw)")
@@ -44,17 +42,32 @@ func init() {
rootCmd.Flags().BoolVar(&logToStdout, "log-stdout", false, "log to stdout instead of file")
rootCmd.Flags().StringVar(&logDir, "log-dir", "", "set directory for logs")
rootCmd.Flags().StringVar(&logLevel, "log", "", "set log level to [trace|debug|info|warning|error|critical]")
rootCmd.Flags().BoolVar(&printVersion, "version", false, "print version (backward compatibility; use command instead)")
rootCmd.Flags().BoolVar(&cmdbase.PrintStackOnExit, "print-stack-on-exit", false, "prints the stack before of shutting down")
// Add other commands.
rootCmd.AddCommand(cmdbase.VersionCmd)
rootCmd.AddCommand(cmdbase.UpdateCmd)
}
func main() {
// Add Go's default flag set.
// TODO: Move flags throughout Portmaster to here and add their values to the service config.
rootCmd.Flags().AddGoFlagSet(flag.CommandLine)
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
func mainRun(cmd *cobra.Command, args []string) {
runPlatformSpecifics(cmd, args)
cmdbase.RunService(cmd, args)
}
func initializeGlobals(cmd *cobra.Command, args []string) {
// set information
// Set version info.
info.Set("Portmaster", "", "GPLv3")
// Configure metrics.
@@ -63,8 +76,12 @@ func initializeGlobals(cmd *cobra.Command, args []string) {
// Configure user agent.
updates.UserAgent = fmt.Sprintf("Portmaster Core (%s %s)", runtime.GOOS, runtime.GOARCH)
// Create service config.
svcCfg = &service.ServiceConfig{
// Configure service.
cmdbase.SvcFactory = func(svcCfg *service.ServiceConfig) (cmdbase.ServiceInstance, error) {
svc, err := service.New(svcCfg)
return svc, err
}
cmdbase.SvcConfig = &service.ServiceConfig{
BinDir: binDir,
DataDir: dataDir,
@@ -72,9 +89,18 @@ func initializeGlobals(cmd *cobra.Command, args []string) {
LogDir: logDir,
LogLevel: logLevel,
BinariesIndexURLs: service.DefaultStableBinaryIndexURLs,
IntelIndexURLs: service.DefaultIntelIndexURLs,
VerifyBinaryUpdates: service.BinarySigningTrustStore,
VerifyIntelUpdates: service.BinarySigningTrustStore,
BinariesIndexURLs: configure.DefaultStableBinaryIndexURLs,
IntelIndexURLs: configure.DefaultIntelIndexURLs,
VerifyBinaryUpdates: configure.BinarySigningTrustStore,
VerifyIntelUpdates: configure.BinarySigningTrustStore,
}
}
func runFlagCmd(fn func(cmd *cobra.Command, args []string) error, cmd *cobra.Command, args []string) {
if err := fn(cmd, args); err != nil {
fmt.Printf("failed: %s\n", err)
os.Exit(1)
}
os.Exit(0)
}

View File

@@ -0,0 +1,21 @@
package main
import (
"github.com/safing/portmaster/cmds/cmdbase"
"github.com/spf13/cobra"
)
var recoverIPTablesFlag bool
func init() {
rootCmd.Flags().BoolVar(&recoverIPTablesFlag, "recover-iptables", false, "recovers ip table rules (backward compatibility; use command instead)")
}
func runPlatformSpecifics(cmd *cobra.Command, args []string) {
switch {
case printVersion:
runFlagCmd(cmdbase.Version, cmd, args)
case recoverIPTablesFlag:
runFlagCmd(recoverIPTables, cmd, args)
}
}

View File

@@ -0,0 +1,13 @@
package main
import (
"github.com/safing/portmaster/cmds/cmdbase"
"github.com/spf13/cobra"
)
func runPlatformSpecifics(cmd *cobra.Command, args []string) {
switch {
case printVersion:
runFlagCmd(cmdbase.Version, cmd, args)
}
}

View File

@@ -2,7 +2,6 @@ package main
import (
"errors"
"flag"
"fmt"
"os"
"strings"
@@ -13,23 +12,17 @@ import (
"github.com/safing/portmaster/service/firewall/interception"
)
var (
recoverCmd = &cobra.Command{
Use: "recover-iptables",
Short: "Force an update of all components.",
RunE: update,
}
recoverIPTables bool
)
var recoverCmd = &cobra.Command{
Use: "recover-iptables",
Short: "Clean up Portmaster rules in iptables",
RunE: recoverIPTables,
}
func init() {
rootCmd.AddCommand(recoverCmd)
flag.BoolVar(&recoverIPTables, "recover-iptables", false, "recovers ip table rules (backward compatibility; use command instead)")
}
func recover(cmd *cobra.Command, args []string) error {
func recoverIPTables(cmd *cobra.Command, args []string) error {
// interception.DeactiveNfqueueFirewall uses coreos/go-iptables
// which shells out to the /sbin/iptables binary. As a result,
// we don't get the errno of the actual error and need to parse the

View File

@@ -6,7 +6,7 @@ import (
)
func setupDatabases(path string) error {
err := database.InitializeWithPath(path)
err := database.Initialize(path)
if err != nil {
return err
}

View File

@@ -37,13 +37,12 @@ func main() {
}
// Start logging.
err := log.Start()
err := log.Start("trace", true, "")
if err != nil {
fmt.Printf("failed to start logging: %s\n", err)
os.Exit(1)
}
defer log.Shutdown()
log.SetLogLevel(log.TraceLevel)
log.Info("starting traffic generator")
// Execute requests