summaryrefslogtreecommitdiff
path: root/src/uapi.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/uapi.go')
-rw-r--r--src/uapi.go437
1 files changed, 0 insertions, 437 deletions
diff --git a/src/uapi.go b/src/uapi.go
deleted file mode 100644
index caaa498..0000000
--- a/src/uapi.go
+++ /dev/null
@@ -1,437 +0,0 @@
-package main
-
-import (
- "bufio"
- "fmt"
- "io"
- "net"
- "strconv"
- "strings"
- "sync/atomic"
- "time"
-)
-
-type IPCError struct {
- Code int64
-}
-
-func (s *IPCError) Error() string {
- return fmt.Sprintf("IPC error: %d", s.Code)
-}
-
-func (s *IPCError) ErrorCode() int64 {
- return s.Code
-}
-
-func ipcGetOperation(device *Device, socket *bufio.ReadWriter) *IPCError {
-
- device.log.Debug.Println("UAPI: Processing get operation")
-
- // create lines
-
- lines := make([]string, 0, 100)
- send := func(line string) {
- lines = append(lines, line)
- }
-
- func() {
-
- // lock required resources
-
- 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))
- }
-
- // 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 {
- send("endpoint=" + peer.endpoint.DstToString())
- }
-
- nano := atomic.LoadInt64(&peer.stats.lastHandshakeNano)
- secs := nano / time.Second.Nanoseconds()
- nano %= time.Second.Nanoseconds()
-
- send(fmt.Sprintf("last_handshake_time_sec=%d", secs))
- send(fmt.Sprintf("last_handshake_time_nsec=%d", nano))
- send(fmt.Sprintf("tx_bytes=%d", peer.stats.txBytes))
- send(fmt.Sprintf("rx_bytes=%d", peer.stats.rxBytes))
- send(fmt.Sprintf("persistent_keepalive_interval=%d",
- atomic.LoadUint64(&peer.persistentKeepaliveInterval),
- ))
-
- for _, ip := range device.routing.table.AllowedIPs(peer) {
- send("allowed_ip=" + ip.String())
- }
-
- }
- }()
-
- // send lines (does not require resource locks)
-
- for _, line := range lines {
- _, err := socket.WriteString(line + "\n")
- if err != nil {
- return &IPCError{
- Code: ipcErrorIO,
- }
- }
- }
-
- return nil
-}
-
-func ipcSetOperation(device *Device, socket *bufio.ReadWriter) *IPCError {
- scanner := bufio.NewScanner(socket)
- logError := device.log.Error
- logDebug := device.log.Debug
-
- var peer *Peer
-
- dummy := false
- deviceConfig := true
-
- for scanner.Scan() {
-
- // parse line
-
- line := scanner.Text()
- if line == "" {
- return nil
- }
- parts := strings.Split(line, "=")
- if len(parts) != 2 {
- return &IPCError{Code: ipcErrorProtocol}
- }
- key := parts[0]
- value := parts[1]
-
- /* device configuration */
-
- if deviceConfig {
-
- switch key {
- case "private_key":
- var sk NoisePrivateKey
- err := sk.FromHex(value)
- if err != nil {
- 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":
-
- // parse port number
-
- port, err := strconv.ParseUint(value, 10, 16)
- if err != nil {
- logError.Println("Failed to parse listen_port:", err)
- return &IPCError{Code: ipcErrorInvalid}
- }
-
- // update port and rebind
-
- logDebug.Println("UAPI: Updating listen port")
-
- device.net.mutex.Lock()
- device.net.port = uint16(port)
- device.net.mutex.Unlock()
-
- if err := device.BindUpdate(); err != nil {
- logError.Println("Failed to set listen_port:", err)
- return &IPCError{Code: ipcErrorPortInUse}
- }
-
- case "fwmark":
-
- // parse fwmark field
-
- fwmark, err := func() (uint32, error) {
- if value == "" {
- return 0, nil
- }
- mark, err := strconv.ParseUint(value, 10, 32)
- return uint32(mark), err
- }()
-
- if err != nil {
- logError.Println("Invalid fwmark", err)
- return &IPCError{Code: ipcErrorInvalid}
- }
-
- logDebug.Println("UAPI: Updating fwmark")
-
- device.net.mutex.Lock()
- device.net.fwmark = uint32(fwmark)
- device.net.mutex.Unlock()
-
- if err := device.BindUpdate(); err != nil {
- logError.Println("Failed to update fwmark:", err)
- return &IPCError{Code: ipcErrorPortInUse}
- }
-
- case "public_key":
- // switch to peer configuration
- logDebug.Println("UAPI: Transition to peer configuration")
- deviceConfig = false
-
- case "replace_peers":
- if value != "true" {
- logError.Println("Failed to set replace_peers, invalid value:", value)
- return &IPCError{Code: ipcErrorInvalid}
- }
- logDebug.Println("UAPI: Removing all peers")
- device.RemoveAllPeers()
-
- default:
- logError.Println("Invalid UAPI key (device configuration):", key)
- return &IPCError{Code: ipcErrorInvalid}
- }
- }
-
- /* peer configuration */
-
- if !deviceConfig {
-
- switch key {
-
- case "public_key":
- var publicKey NoisePublicKey
- err := publicKey.FromHex(value)
- if err != nil {
- logError.Println("Failed to get peer by public_key:", err)
- return &IPCError{Code: ipcErrorInvalid}
- }
-
- // ignore peer with public key of device
-
- device.noise.mutex.RLock()
- equals := device.noise.publicKey.Equals(publicKey)
- device.noise.mutex.RUnlock()
-
- if equals {
- peer = &Peer{}
- dummy = true
- }
-
- // find peer referenced
-
- peer = device.LookupPeer(publicKey)
-
- if peer == nil {
- peer, err = device.NewPeer(publicKey)
- if err != nil {
- logError.Println("Failed to create new peer:", err)
- return &IPCError{Code: ipcErrorInvalid}
- }
- 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
-
- if value != "true" {
- logError.Println("Failed to set remove, invalid value:", value)
- return &IPCError{Code: ipcErrorInvalid}
- }
- if !dummy {
- logDebug.Println("UAPI: Removing peer:", peer.String())
- device.RemovePeer(peer.handshake.remoteStatic)
- }
- peer = &Peer{}
- dummy = true
-
- case "preshared_key":
-
- // update PSK
-
- logDebug.Println("UAPI: Updating pre-shared key for peer:", peer.String())
-
- peer.handshake.mutex.Lock()
- err := peer.handshake.presharedKey.FromHex(value)
- peer.handshake.mutex.Unlock()
-
- if err != nil {
- logError.Println("Failed to set preshared_key:", err)
- return &IPCError{Code: ipcErrorInvalid}
- }
-
- case "endpoint":
-
- // set endpoint destination
-
- logDebug.Println("UAPI: Updating endpoint for peer:", peer.String())
-
- err := func() error {
- peer.mutex.Lock()
- defer peer.mutex.Unlock()
- endpoint, err := CreateEndpoint(value)
- if err != nil {
- return err
- }
- peer.endpoint = endpoint
- peer.timer.handshakeDeadline.Reset(RekeyAttemptTime)
- return nil
- }()
-
- if err != nil {
- logError.Println("Failed to set endpoint:", value)
- return &IPCError{Code: ipcErrorInvalid}
- }
-
- case "persistent_keepalive_interval":
-
- // 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)
- return &IPCError{Code: ipcErrorInvalid}
- }
-
- old := atomic.SwapUint64(
- &peer.persistentKeepaliveInterval,
- secs,
- )
-
- // send immediate keep-alive
-
- if old == 0 && secs != 0 {
- if err != nil {
- logError.Println("Failed to get tun device status:", err)
- return &IPCError{Code: ipcErrorIO}
- }
- if device.isUp.Get() && !dummy {
- peer.SendKeepAlive()
- }
- }
-
- 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 {
- 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}
- }
-
- 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}
- }
- }
- }
-
- return nil
-}
-
-func ipcHandle(device *Device, socket net.Conn) {
-
- // create buffered read/writer
-
- defer socket.Close()
-
- buffered := func(s io.ReadWriter) *bufio.ReadWriter {
- reader := bufio.NewReader(s)
- writer := bufio.NewWriter(s)
- return bufio.NewReadWriter(reader, writer)
- }(socket)
-
- defer buffered.Flush()
-
- op, err := buffered.ReadString('\n')
- if err != nil {
- return
- }
-
- // handle operation
-
- var status *IPCError
-
- switch op {
- case "set=1\n":
- device.log.Debug.Println("Config, set operation")
- status = ipcSetOperation(device, buffered)
-
- case "get=1\n":
- device.log.Debug.Println("Config, get operation")
- status = ipcGetOperation(device, buffered)
-
- default:
- device.log.Error.Println("Invalid UAPI operation:", op)
- return
- }
-
- // write status
-
- if status != nil {
- device.log.Error.Println(status)
- fmt.Fprintf(buffered, "errno=%d\n\n", status.ErrorCode())
- } else {
- fmt.Fprintf(buffered, "errno=0\n\n")
- }
-}