diff options
Diffstat (limited to 'src/uapi.go')
-rw-r--r-- | src/uapi.go | 146 |
1 files changed, 95 insertions, 51 deletions
diff --git a/src/uapi.go b/src/uapi.go index 68ebe43..caaa498 100644 --- a/src/uapi.go +++ b/src/uapi.go @@ -25,32 +25,51 @@ func (s *IPCError) ErrorCode() int64 { func ipcGetOperation(device *Device, socket *bufio.ReadWriter) *IPCError { - // create lines + device.log.Debug.Println("UAPI: Processing get operation") - device.mutex.RLock() - device.net.mutex.RLock() + // create lines lines := make([]string, 0, 100) send := func(line string) { lines = append(lines, line) } - if !device.privateKey.IsZero() { - send("private_key=" + device.privateKey.ToHex()) - } + func() { - if device.net.port != 0 { - send(fmt.Sprintf("listen_port=%d", device.net.port)) - } + // lock required resources - if device.net.fwmark != 0 { - send(fmt.Sprintf("fwmark=%d", device.net.fwmark)) - } + device.net.mutex.RLock() + defer device.net.mutex.RUnlock() + + device.noise.mutex.RLock() + defer device.noise.mutex.RUnlock() + + device.routing.mutex.RLock() + defer device.routing.mutex.RUnlock() + + device.peers.mutex.Lock() + defer device.peers.mutex.Unlock() + + // serialize device related values + + if !device.noise.privateKey.IsZero() { + send("private_key=" + device.noise.privateKey.ToHex()) + } + + if device.net.port != 0 { + send(fmt.Sprintf("listen_port=%d", device.net.port)) + } + + if device.net.fwmark != 0 { + send(fmt.Sprintf("fwmark=%d", device.net.fwmark)) + } - for _, peer := range device.peers { - func() { + // serialize each peer state + + for _, peer := range device.peers.keyMap { peer.mutex.RLock() defer peer.mutex.RUnlock() + send("public_key=" + peer.handshake.remoteStatic.ToHex()) send("preshared_key=" + peer.handshake.presharedKey.ToHex()) if peer.endpoint != nil { @@ -69,16 +88,14 @@ func ipcGetOperation(device *Device, socket *bufio.ReadWriter) *IPCError { atomic.LoadUint64(&peer.persistentKeepaliveInterval), )) - for _, ip := range device.routingTable.AllowedIPs(peer) { + for _, ip := range device.routing.table.AllowedIPs(peer) { send("allowed_ip=" + ip.String()) } - }() - } - device.net.mutex.RUnlock() - device.mutex.RUnlock() + } + }() - // send lines + // send lines (does not require resource locks) for _, line := range lines { _, err := socket.WriteString(line + "\n") @@ -94,7 +111,6 @@ func ipcGetOperation(device *Device, socket *bufio.ReadWriter) *IPCError { func ipcSetOperation(device *Device, socket *bufio.ReadWriter) *IPCError { scanner := bufio.NewScanner(socket) - logInfo := device.log.Info logError := device.log.Error logDebug := device.log.Debug @@ -130,6 +146,7 @@ func ipcSetOperation(device *Device, socket *bufio.ReadWriter) *IPCError { logError.Println("Failed to set private_key:", err) return &IPCError{Code: ipcErrorInvalid} } + logDebug.Println("UAPI: Updating device private key") device.SetPrivateKey(sk) case "listen_port": @@ -144,6 +161,8 @@ func ipcSetOperation(device *Device, socket *bufio.ReadWriter) *IPCError { // update port and rebind + logDebug.Println("UAPI: Updating listen port") + device.net.mutex.Lock() device.net.port = uint16(port) device.net.mutex.Unlock() @@ -170,6 +189,8 @@ func ipcSetOperation(device *Device, socket *bufio.ReadWriter) *IPCError { return &IPCError{Code: ipcErrorInvalid} } + logDebug.Println("UAPI: Updating fwmark") + device.net.mutex.Lock() device.net.fwmark = uint32(fwmark) device.net.mutex.Unlock() @@ -181,6 +202,7 @@ func ipcSetOperation(device *Device, socket *bufio.ReadWriter) *IPCError { case "public_key": // switch to peer configuration + logDebug.Println("UAPI: Transition to peer configuration") deviceConfig = false case "replace_peers": @@ -188,6 +210,7 @@ func ipcSetOperation(device *Device, socket *bufio.ReadWriter) *IPCError { logError.Println("Failed to set replace_peers, invalid value:", value) return &IPCError{Code: ipcErrorInvalid} } + logDebug.Println("UAPI: Removing all peers") device.RemoveAllPeers() default: @@ -203,43 +226,41 @@ func ipcSetOperation(device *Device, socket *bufio.ReadWriter) *IPCError { switch key { case "public_key": - var pubKey NoisePublicKey - err := pubKey.FromHex(value) + var publicKey NoisePublicKey + err := publicKey.FromHex(value) if err != nil { logError.Println("Failed to get peer by public_key:", err) return &IPCError{Code: ipcErrorInvalid} } - // check if public key of peer equal to device + // ignore peer with public key of device - device.mutex.RLock() - if device.publicKey.Equals(pubKey) { - - // create dummy instance (not added to device) + device.noise.mutex.RLock() + equals := device.noise.publicKey.Equals(publicKey) + device.noise.mutex.RUnlock() + if equals { peer = &Peer{} dummy = true - device.mutex.RUnlock() - logInfo.Println("Ignoring peer with public key of device") + } - } else { + // find peer referenced - // find peer referenced + peer = device.LookupPeer(publicKey) - peer, _ = device.peers[pubKey] - device.mutex.RUnlock() - if peer == nil { - peer, err = device.NewPeer(pubKey) - if err != nil { - logError.Println("Failed to create new peer:", err) - return &IPCError{Code: ipcErrorInvalid} - } + if peer == nil { + peer, err = device.NewPeer(publicKey) + if err != nil { + logError.Println("Failed to create new peer:", err) + return &IPCError{Code: ipcErrorInvalid} } - peer.timer.handshakeDeadline.Reset(RekeyAttemptTime) - dummy = false - + logDebug.Println("UAPI: Created new peer:", peer.String()) } + peer.mutex.Lock() + peer.timer.handshakeDeadline.Reset(RekeyAttemptTime) + peer.mutex.Unlock() + case "remove": // remove currently selected peer from device @@ -249,7 +270,7 @@ func ipcSetOperation(device *Device, socket *bufio.ReadWriter) *IPCError { return &IPCError{Code: ipcErrorInvalid} } if !dummy { - logDebug.Println("Removing", peer.String()) + logDebug.Println("UAPI: Removing peer:", peer.String()) device.RemovePeer(peer.handshake.remoteStatic) } peer = &Peer{} @@ -259,9 +280,12 @@ func ipcSetOperation(device *Device, socket *bufio.ReadWriter) *IPCError { // update PSK - peer.mutex.Lock() + logDebug.Println("UAPI: Updating pre-shared key for peer:", peer.String()) + + peer.handshake.mutex.Lock() err := peer.handshake.presharedKey.FromHex(value) - peer.mutex.Unlock() + peer.handshake.mutex.Unlock() + if err != nil { logError.Println("Failed to set preshared_key:", err) return &IPCError{Code: ipcErrorInvalid} @@ -271,6 +295,8 @@ func ipcSetOperation(device *Device, socket *bufio.ReadWriter) *IPCError { // set endpoint destination + logDebug.Println("UAPI: Updating endpoint for peer:", peer.String()) + err := func() error { peer.mutex.Lock() defer peer.mutex.Unlock() @@ -292,6 +318,8 @@ func ipcSetOperation(device *Device, socket *bufio.ReadWriter) *IPCError { // update keep-alive interval + logDebug.Println("UAPI: Updating persistent_keepalive_interval for peer:", peer.String()) + secs, err := strconv.ParseUint(value, 10, 16) if err != nil { logError.Println("Failed to set persistent_keepalive_interval:", err) @@ -316,25 +344,41 @@ func ipcSetOperation(device *Device, socket *bufio.ReadWriter) *IPCError { } case "replace_allowed_ips": + + logDebug.Println("UAPI: Removing all allowed IPs for peer:", peer.String()) + if value != "true" { logError.Println("Failed to set replace_allowed_ips, invalid value:", value) return &IPCError{Code: ipcErrorInvalid} } - if !dummy { - device.routingTable.RemovePeer(peer) + + if dummy { + continue } + device.routing.mutex.Lock() + device.routing.table.RemovePeer(peer) + device.routing.mutex.Unlock() + case "allowed_ip": + + logDebug.Println("UAPI: Adding allowed_ip to peer:", peer.String()) + _, network, err := net.ParseCIDR(value) if err != nil { logError.Println("Failed to set allowed_ip:", err) return &IPCError{Code: ipcErrorInvalid} } - ones, _ := network.Mask.Size() - if !dummy { - device.routingTable.Insert(network.IP, uint(ones), peer) + + if dummy { + continue } + ones, _ := network.Mask.Size() + device.routing.mutex.Lock() + device.routing.table.Insert(network.IP, uint(ones), peer) + device.routing.mutex.Unlock() + default: logError.Println("Invalid UAPI key (peer configuration):", key) return &IPCError{Code: ipcErrorInvalid} |