aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/service/install.go
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2019-02-25 18:47:03 +0100
committerJason A. Donenfeld <Jason@zx2c4.com>2019-02-28 08:05:02 +0100
commitab3263502a3eb2ba008e7aab61709cb11c8aac1e (patch)
tree2184c0d2782f81ace9b2e78e4bbc554a534fc393 /service/install.go
parentconf: introduce configuration management (diff)
downloadwireguard-windows-ab3263502a3eb2ba008e7aab61709cb11c8aac1e.tar.xz
wireguard-windows-ab3263502a3eb2ba008e7aab61709cb11c8aac1e.zip
service: introduce base of services
Diffstat (limited to 'service/install.go')
-rw-r--r--service/install.go196
1 files changed, 196 insertions, 0 deletions
diff --git a/service/install.go b/service/install.go
new file mode 100644
index 00000000..32131f94
--- /dev/null
+++ b/service/install.go
@@ -0,0 +1,196 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
+ */
+
+package service
+
+import (
+ "errors"
+ "golang.org/x/sys/windows"
+ "golang.org/x/sys/windows/svc"
+ svcdbg "golang.org/x/sys/windows/svc/debug"
+ "golang.org/x/sys/windows/svc/mgr"
+ "golang.zx2c4.com/wireguard/windows/conf"
+ "os"
+ "time"
+)
+
+var cachedServiceManager *mgr.Mgr
+
+func serviceManager() (*mgr.Mgr, error) {
+ if cachedServiceManager != nil {
+ return cachedServiceManager, nil
+ }
+ m, err := mgr.Connect()
+ if err != nil {
+ return nil, err
+ }
+ cachedServiceManager = m
+ return cachedServiceManager, nil
+}
+
+func InstallManager() error {
+ m, err := serviceManager()
+ if err != nil {
+ return err
+ }
+ path, err := os.Executable()
+ if err != nil {
+ return nil
+ }
+
+ //TODO: Do we want to bail if executable isn't being run from the right location?
+
+ serviceName := "WireGuard Manager"
+ service, err := m.OpenService(serviceName)
+ if err == nil {
+ status, err := service.Query()
+ if err != nil {
+ service.Close()
+ return err
+ }
+ if status.State != svc.Stopped {
+ service.Close()
+ return errors.New("Manager already installed and running")
+ }
+ err = service.Delete()
+ service.Close()
+ if err != nil {
+ return err
+ }
+ for {
+ service, err = m.OpenService(serviceName)
+ if err != nil {
+ break
+ }
+ service.Close()
+ time.Sleep(time.Second)
+ }
+ }
+
+ config := mgr.Config{
+ ServiceType: windows.SERVICE_WIN32_OWN_PROCESS,
+ StartType: mgr.StartAutomatic,
+ ErrorControl: mgr.ErrorNormal,
+ DisplayName: serviceName,
+ }
+
+ service, err = m.CreateService(serviceName, path, config, "/managerservice")
+ if err != nil {
+ return err
+ }
+ service.Start()
+ return service.Close()
+}
+
+func UninstallManager() error {
+ m, err := serviceManager()
+ if err != nil {
+ return err
+ }
+ serviceName := "WireGuard Manager"
+ service, err := m.OpenService(serviceName)
+ if err != nil {
+ return err
+ }
+ service.Control(svc.Stop)
+ err = service.Delete()
+ err2 := service.Close()
+ if err != nil {
+ return err
+ }
+ return err2
+}
+
+func RunManager() error {
+ return svc.Run("WireGuard Manager", &managerService{})
+}
+
+func InstallTunnel(configPath string) error {
+ m, err := serviceManager()
+ if err != nil {
+ return err
+ }
+ path, err := os.Executable()
+ if err != nil {
+ return nil
+ }
+
+ name, err := conf.NameFromPath(configPath)
+ if err != nil {
+ return err
+ }
+
+ serviceName := "WireGuard Tunnel: " + name
+ service, err := m.OpenService(serviceName)
+ if err == nil {
+ status, err := service.Query()
+ if err != nil {
+ service.Close()
+ return err
+ }
+ if status.State != svc.Stopped {
+ service.Close()
+ return errors.New("Tunnel already installed and running")
+ }
+ err = service.Delete()
+ service.Close()
+ if err != nil {
+ return err
+ }
+ for {
+ service, err = m.OpenService(serviceName)
+ if err != nil {
+ break
+ }
+ service.Close()
+ time.Sleep(time.Second)
+ }
+ }
+
+ config := mgr.Config{
+ ServiceType: windows.SERVICE_WIN32_OWN_PROCESS,
+ StartType: mgr.StartAutomatic,
+ ErrorControl: mgr.ErrorNormal,
+ DisplayName: serviceName,
+ }
+
+ service, err = m.CreateService(serviceName, path, config, "/tunnelservice", configPath)
+ if err != nil {
+ return err
+ }
+ service.Start()
+ return service.Close()
+}
+
+func UninstallTunnel(name string) error {
+ m, err := serviceManager()
+ if err != nil {
+ return err
+ }
+ serviceName := "WireGuard Tunnel: " + name
+ service, err := m.OpenService(serviceName)
+ if err != nil {
+ return err
+ }
+ service.Control(svc.Stop)
+ err = service.Delete()
+ err2 := service.Close()
+ if err != nil {
+ return err
+ }
+ return err2
+}
+
+func RunTunnel(confPath string, debug bool) error {
+ name, err := conf.NameFromPath(confPath)
+ if err != nil {
+ return err
+ }
+ if debug {
+ return svcdbg.Run("WireGuard Tunnel: "+name, &tunnelService{confPath, true})
+ } else {
+ return svc.Run("WireGuard Tunnel: "+name, &tunnelService{confPath, false})
+ }
+}