aboutsummaryrefslogtreecommitdiffstats
path: root/src/device.go
diff options
context:
space:
mode:
authorMathias Hall-Andersen <mathias@hall-andersen.dk>2018-01-26 22:52:32 +0100
committerMathias Hall-Andersen <mathias@hall-andersen.dk>2018-01-26 22:52:32 +0100
commitf73d2fb2d96bc3fbc8bc4cce452e3c19689de01e (patch)
tree52e392cf6313e7e9e5e87539fcb5e88817e47f37 /src/device.go
parentFixed potential DoS issue (diff)
downloadwireguard-go-f73d2fb2d96bc3fbc8bc4cce452e3c19689de01e.tar.xz
wireguard-go-f73d2fb2d96bc3fbc8bc4cce452e3c19689de01e.zip
Added initial version of peer teardown
There is a double lock issue with device.Close which has yet to be resolved.
Diffstat (limited to 'src/device.go')
-rw-r--r--src/device.go111
1 files changed, 87 insertions, 24 deletions
diff --git a/src/device.go b/src/device.go
index 5f8e91b..f1c09c6 100644
--- a/src/device.go
+++ b/src/device.go
@@ -9,7 +9,7 @@ import (
)
type Device struct {
- isUp AtomicBool // device is up (TUN interface up)?
+ isUp AtomicBool // device is (going) up
isClosed AtomicBool // device is closed? (acting as guard)
log *Logger // collection of loggers for levels
idCounter uint // for assigning debug ids to peers
@@ -18,6 +18,11 @@ type Device struct {
device TUNDevice
mtu int32
}
+ state struct {
+ mutex deadlock.Mutex
+ changing AtomicBool
+ current bool
+ }
pool struct {
messageBuffers sync.Pool
}
@@ -46,37 +51,86 @@ type Device struct {
mac CookieChecker
}
-func (device *Device) Up() {
- device.mutex.Lock()
- defer device.mutex.Unlock()
+func deviceUpdateState(device *Device) {
- device.net.mutex.Lock()
- defer device.net.mutex.Unlock()
+ // check if state already being updated (guard)
- if device.isUp.Swap(true) {
+ if device.state.changing.Swap(true) {
return
}
- unsafeUpdateBind(device)
+ // compare to current state of device
+
+ device.state.mutex.Lock()
+
+ newIsUp := device.isUp.Get()
+
+ if newIsUp == device.state.current {
+ device.state.mutex.Unlock()
+ device.state.changing.Set(false)
+ return
+ }
+
+ device.state.mutex.Unlock()
+
+ // change state of device
+
+ switch newIsUp {
+ case true:
+
+ // start listener
+
+ if err := device.BindUpdate(); err != nil {
+ device.isUp.Set(false)
+ break
+ }
+
+ // start every peer
+
+ for _, peer := range device.peers {
+ peer.Start()
+ }
+
+ case false:
+
+ // stop listening
+
+ device.BindClose()
- for _, peer := range device.peers {
- peer.Start()
+ // stop every peer
+
+ for _, peer := range device.peers {
+ peer.Stop()
+ }
}
+
+ // update state variables
+ // and check for state change in the mean time
+
+ device.state.current = newIsUp
+ device.state.changing.Set(false)
+ deviceUpdateState(device)
}
-func (device *Device) Down() {
- device.mutex.Lock()
- defer device.mutex.Unlock()
+func (device *Device) Up() {
+
+ // closed device cannot be brought up
- if !device.isUp.Swap(false) {
+ if device.isClosed.Get() {
return
}
- closeBind(device)
+ device.state.mutex.Lock()
+ device.isUp.Set(true)
+ device.state.mutex.Unlock()
+ deviceUpdateState(device)
+}
- for _, peer := range device.peers {
- peer.Stop()
- }
+func (device *Device) Down() {
+ device.state.mutex.Lock()
+ device.isUp.Set(false)
+ device.state.mutex.Unlock()
+ deviceUpdateState(device)
}
/* Warning:
@@ -87,7 +141,6 @@ func removePeerUnsafe(device *Device, key NoisePublicKey) {
if !ok {
return
}
- peer.Stop()
device.routingTable.RemovePeer(peer)
delete(device.peers, key)
}
@@ -231,20 +284,30 @@ func (device *Device) RemovePeer(key NoisePublicKey) {
func (device *Device) RemoveAllPeers() {
device.mutex.Lock()
defer device.mutex.Unlock()
- for key := range device.peers {
- removePeerUnsafe(device, key)
+
+ for key, peer := range device.peers {
+ peer.Stop()
+ peer, ok := device.peers[key]
+ if !ok {
+ return
+ }
+ device.routingTable.RemovePeer(peer)
+ delete(device.peers, key)
}
}
func (device *Device) Close() {
+ device.log.Info.Println("Device closing")
if device.isClosed.Swap(true) {
return
}
- device.log.Info.Println("Closing device")
- device.RemoveAllPeers()
device.signal.stop.Broadcast()
device.tun.device.Close()
- closeBind(device)
+ device.BindClose()
+ device.isUp.Set(false)
+ println("remove")
+ device.RemoveAllPeers()
+ device.log.Info.Println("Interface closed")
}
func (device *Device) Wait() chan struct{} {