aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/manager
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2021-08-13 00:25:13 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2021-08-13 00:25:13 +0200
commit9f92a337376794baaff9b7e60e715a0f102549ba (patch)
treea73c2c3f16a1785a6abdb7abb004c47f35d63a33 /manager
parentembeddable-dll-service: allow falling back to wireguard-go (diff)
downloadwireguard-windows-9f92a337376794baaff9b7e60e715a0f102549ba.tar.xz
wireguard-windows-9f92a337376794baaff9b7e60e715a0f102549ba.zip
manager: make multiple tunnels mode automatic
Rather than having to set a registry knob to enable multiple tunnels, it is now automatic. If an additional activated tunnel has the same route subnets or interface IP addresses as a previous tunnel, that previous one is stopped. But if there's no overlap, then they coexist. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to 'manager')
-rw-r--r--manager/ipc_server.go69
1 files changed, 37 insertions, 32 deletions
diff --git a/manager/ipc_server.go b/manager/ipc_server.go
index fe195094..ba785ced 100644
--- a/manager/ipc_server.go
+++ b/manager/ipc_server.go
@@ -108,44 +108,49 @@ func (s *ManagerService) RuntimeConfig(tunnelName string) (*conf.Config, error)
}
func (s *ManagerService) Start(tunnelName string) error {
- // TODO: Rather than being lazy and gating this behind a knob (yuck!), we should instead keep track of the routes
- // of each tunnel, and only deactivate in the case of a tunnel with identical routes being added.
- if !conf.AdminBool("MultipleSimultaneousTunnels") {
- trackedTunnelsLock.Lock()
- tt := make([]string, 0, len(trackedTunnels))
- var inTransition string
- for t, state := range trackedTunnels {
- tt = append(tt, t)
- if len(t) > 0 && (state == TunnelStarting || state == TunnelUnknown) {
- inTransition = t
- break
- }
+ c, err := conf.LoadFromName(tunnelName)
+ if err != nil {
+ return err
+ }
+
+ // Figure out which tunnels have intersecting addresses/routes and stop those.
+ trackedTunnelsLock.Lock()
+ tt := make([]string, 0, len(trackedTunnels))
+ var inTransition string
+ for t, state := range trackedTunnels {
+ c2, err := conf.LoadFromName(t)
+ if err != nil || !c.IntersectsWith(c2) {
+ // If we can't get the config, assume it doesn't intersect.
+ continue
+ }
+ tt = append(tt, t)
+ if len(t) > 0 && (state == TunnelStarting || state == TunnelUnknown) {
+ inTransition = t
+ break
}
- trackedTunnelsLock.Unlock()
- if len(inTransition) != 0 {
- return fmt.Errorf("Please allow the tunnel ā€˜%sā€™ to finish activating", inTransition)
+ }
+ trackedTunnelsLock.Unlock()
+ if len(inTransition) != 0 {
+ return fmt.Errorf("Please allow the tunnel ā€˜%sā€™ to finish activating", inTransition)
+ }
+
+ // Stop those intersecting tunnels asynchronously.
+ go func() {
+ for _, t := range tt {
+ s.Stop(t)
}
- go func() {
- for _, t := range tt {
+ for _, t := range tt {
+ state, err := s.State(t)
+ if err == nil && (state == TunnelStarted || state == TunnelStarting) {
+ log.Printf("[%s] Trying again to stop zombie tunnel", t)
s.Stop(t)
+ time.Sleep(time.Millisecond * 100)
}
- for _, t := range tt {
- state, err := s.State(t)
- if err == nil && (state == TunnelStarted || state == TunnelStarting) {
- log.Printf("[%s] Trying again to stop zombie tunnel", t)
- s.Stop(t)
- time.Sleep(time.Millisecond * 100)
- }
- }
- }()
- }
+ }
+ }()
time.AfterFunc(time.Second*10, cleanupStaleNetworkInterfaces)
- // After that process is started -- it's somewhat asynchronous -- we install the new one.
- c, err := conf.LoadFromName(tunnelName)
- if err != nil {
- return err
- }
+ // After the stop process has begun, but before it's finished, we install the new one.
path, err := c.Path()
if err != nil {
return err