wireguard-go/device/uapi.go

453 lines
10 KiB
Go
Raw Normal View History

2019-01-02 01:55:51 +01:00
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2017-2020 WireGuard LLC. All Rights Reserved.
*/
2019-03-03 04:04:41 +01:00
package device
import (
"bufio"
"errors"
"fmt"
"io"
2017-06-01 21:31:30 +02:00
"net"
"strconv"
"strings"
2017-07-17 16:16:18 +02:00
"sync/atomic"
"time"
2019-05-14 09:09:52 +02:00
"golang.zx2c4.com/wireguard/conn"
2019-05-14 09:09:52 +02:00
"golang.zx2c4.com/wireguard/ipc"
)
type IPCError struct {
int64
}
func (s IPCError) Error() string {
return fmt.Sprintf("IPC error: %d", s.int64)
}
func (s IPCError) ErrorCode() int64 {
return s.int64
}
func (device *Device) IpcGetOperation(socket *bufio.Writer) error {
lines := make([]string, 0, 100)
send := func(line string) {
lines = append(lines, line)
}
func() {
// lock required resources
device.net.RLock()
defer device.net.RUnlock()
device.staticIdentity.RLock()
defer device.staticIdentity.RUnlock()
device.peers.RLock()
defer device.peers.RUnlock()
// serialize device related values
2018-05-13 23:14:43 +02:00
if !device.staticIdentity.privateKey.IsZero() {
send("private_key=" + device.staticIdentity.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.RLock()
defer peer.RUnlock()
send("public_key=" + peer.handshake.remoteStatic.ToHex())
send("preshared_key=" + peer.handshake.presharedKey.ToHex())
send("protocol_version=1")
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))
2018-05-20 03:26:46 +02:00
send(fmt.Sprintf("tx_bytes=%d", atomic.LoadUint64(&peer.stats.txBytes)))
send(fmt.Sprintf("rx_bytes=%d", atomic.LoadUint64(&peer.stats.rxBytes)))
send(fmt.Sprintf("persistent_keepalive_interval=%d", atomic.LoadUint32(&peer.persistentKeepaliveInterval)))
2017-08-04 16:15:53 +02:00
2018-05-13 23:14:43 +02:00
for _, ip := range device.allowedips.EntriesForPeer(peer) {
send("allowed_ip=" + ip.String())
}
}
}()
2017-07-17 16:16:18 +02:00
// send lines (does not require resource locks)
for _, line := range lines {
_, err := socket.WriteString(line + "\n")
if err != nil {
2019-03-03 04:04:41 +01:00
return &IPCError{ipc.IpcErrorIO}
}
}
return nil
}
func (device *Device) IpcSetOperation(r io.Reader) error {
scanner := bufio.NewScanner(r)
2017-07-17 16:16:18 +02:00
logError := device.log.Error
logDebug := device.log.Debug
var peer *Peer
2017-08-04 16:15:53 +02:00
dummy := false
createdNewPeer := false
2017-08-04 16:15:53 +02:00
deviceConfig := true
for scanner.Scan() {
2017-07-17 16:16:18 +02:00
// parse line
line := scanner.Text()
if line == "" {
return nil
}
parts := strings.Split(line, "=")
if len(parts) != 2 {
2019-03-03 04:04:41 +01:00
return &IPCError{ipc.IpcErrorProtocol}
}
key := parts[0]
value := parts[1]
2017-08-04 16:15:53 +02:00
/* device configuration */
2017-08-04 16:15:53 +02:00
if deviceConfig {
2017-08-04 16:15:53 +02:00
switch key {
case "private_key":
var sk NoisePrivateKey
err := sk.FromMaybeZeroHex(value)
2017-09-26 14:26:12 +02:00
if err != nil {
logError.Println("Failed to set private_key:", err)
2019-03-03 04:04:41 +01:00
return &IPCError{ipc.IpcErrorInvalid}
}
2018-05-21 03:38:50 +02:00
logDebug.Println("UAPI: Updating private key")
2017-09-26 14:26:12 +02:00
device.SetPrivateKey(sk)
2017-08-04 16:15:53 +02:00
case "listen_port":
// parse port number
2017-08-04 16:15:53 +02:00
port, err := strconv.ParseUint(value, 10, 16)
if err != nil {
logError.Println("Failed to parse listen_port:", err)
2019-03-03 04:04:41 +01:00
return &IPCError{ipc.IpcErrorInvalid}
}
// update port and rebind
logDebug.Println("UAPI: Updating listen port")
device.net.Lock()
device.net.port = uint16(port)
device.net.Unlock()
if err := device.BindUpdate(); err != nil {
logError.Println("Failed to set listen_port:", err)
2019-03-03 04:04:41 +01:00
return &IPCError{ipc.IpcErrorPortInUse}
}
2017-08-04 16:15:53 +02:00
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
}()
2017-09-26 14:26:12 +02:00
if err != nil {
logError.Println("Invalid fwmark", err)
2019-03-03 04:04:41 +01:00
return &IPCError{ipc.IpcErrorInvalid}
2017-08-22 17:22:45 +02:00
}
logDebug.Println("UAPI: Updating fwmark")
if err := device.BindSetMark(uint32(fwmark)); err != nil {
logError.Println("Failed to update fwmark:", err)
2019-03-03 04:04:41 +01:00
return &IPCError{ipc.IpcErrorPortInUse}
}
2017-08-04 16:15:53 +02:00
case "public_key":
// switch to peer configuration
logDebug.Println("UAPI: Transition to peer configuration")
2017-08-04 16:15:53 +02:00
deviceConfig = false
2017-07-17 16:16:18 +02:00
2017-08-04 16:15:53 +02:00
case "replace_peers":
if value != "true" {
logError.Println("Failed to set replace_peers, invalid value:", value)
2019-03-03 04:04:41 +01:00
return &IPCError{ipc.IpcErrorInvalid}
2017-08-04 16:15:53 +02:00
}
logDebug.Println("UAPI: Removing all peers")
2017-08-04 16:15:53 +02:00
device.RemoveAllPeers()
2017-08-04 16:15:53 +02:00
default:
2018-05-21 03:38:50 +02:00
logError.Println("Invalid UAPI device key:", key)
2019-03-03 04:04:41 +01:00
return &IPCError{ipc.IpcErrorInvalid}
}
2017-08-04 16:15:53 +02:00
}
/* peer configuration */
if !deviceConfig {
switch key {
2017-08-04 16:15:53 +02:00
case "public_key":
var publicKey NoisePublicKey
err := publicKey.FromHex(value)
2017-08-04 16:15:53 +02:00
if err != nil {
2018-05-21 03:38:50 +02:00
logError.Println("Failed to get peer by public key:", err)
2019-03-03 04:04:41 +01:00
return &IPCError{ipc.IpcErrorInvalid}
2017-08-04 16:15:53 +02:00
}
// ignore peer with public key of device
2017-08-04 16:15:53 +02:00
device.staticIdentity.RLock()
2018-05-13 23:14:43 +02:00
dummy = device.staticIdentity.publicKey.Equals(publicKey)
device.staticIdentity.RUnlock()
2018-05-13 23:14:43 +02:00
if dummy {
peer = &Peer{}
2018-05-14 03:29:21 +02:00
} else {
peer = device.LookupPeer(publicKey)
}
createdNewPeer = peer == nil
if createdNewPeer {
peer, err = device.NewPeer(publicKey)
if err != nil {
logError.Println("Failed to create new peer:", err)
2019-03-03 04:04:41 +01:00
return &IPCError{ipc.IpcErrorInvalid}
}
2019-08-05 16:57:41 +02:00
if peer == nil {
dummy = true
peer = &Peer{}
} else {
logDebug.Println(peer, "- UAPI: Created")
}
2017-08-04 16:15:53 +02:00
}
case "update_only":
// allow disabling of creation
if value != "true" {
logError.Println("Failed to set update only, invalid value:", value)
return &IPCError{ipc.IpcErrorInvalid}
}
if createdNewPeer && !dummy {
device.RemovePeer(peer.handshake.remoteStatic)
peer = &Peer{}
dummy = true
}
case "remove":
// remove currently selected peer from device
2017-08-04 16:15:53 +02:00
if value != "true" {
logError.Println("Failed to set remove, invalid value:", value)
2019-03-03 04:04:41 +01:00
return &IPCError{ipc.IpcErrorInvalid}
2017-08-04 16:15:53 +02:00
}
if !dummy {
2018-05-21 03:38:50 +02:00
logDebug.Println(peer, "- UAPI: Removing")
device.RemovePeer(peer.handshake.remoteStatic)
}
peer = &Peer{}
dummy = true
case "preshared_key":
// update PSK
2018-05-21 03:38:50 +02:00
logDebug.Println(peer, "- UAPI: Updating preshared key")
peer.handshake.mutex.Lock()
err := peer.handshake.presharedKey.FromHex(value)
peer.handshake.mutex.Unlock()
2017-06-01 21:31:30 +02:00
if err != nil {
2018-05-21 03:38:50 +02:00
logError.Println("Failed to set preshared key:", err)
2019-03-03 04:04:41 +01:00
return &IPCError{ipc.IpcErrorInvalid}
2017-06-01 21:31:30 +02:00
}
case "endpoint":
// set endpoint destination
2018-05-21 03:38:50 +02:00
logDebug.Println(peer, "- UAPI: Updating endpoint")
err := func() error {
peer.Lock()
defer peer.Unlock()
endpoint, err := conn.CreateEndpoint(value)
2017-11-19 00:21:58 +01:00
if err != nil {
return err
}
peer.endpoint = endpoint
return nil
}()
if err != nil {
2019-03-19 07:34:04 +01:00
logError.Println("Failed to set endpoint:", err, ":", value)
2019-03-03 04:04:41 +01:00
return &IPCError{ipc.IpcErrorInvalid}
2017-06-01 21:31:30 +02:00
}
case "persistent_keepalive_interval":
2017-08-04 16:15:53 +02:00
// update persistent keepalive interval
2017-08-04 16:15:53 +02:00
2018-11-05 05:46:27 +01:00
logDebug.Println(peer, "- UAPI: Updating persistent keepalive interval")
2017-08-04 16:15:53 +02:00
secs, err := strconv.ParseUint(value, 10, 16)
if err != nil {
2018-05-21 03:38:50 +02:00
logError.Println("Failed to set persistent keepalive interval:", err)
2019-03-03 04:04:41 +01:00
return &IPCError{ipc.IpcErrorInvalid}
}
2017-08-04 16:15:53 +02:00
old := atomic.SwapUint32(&peer.persistentKeepaliveInterval, uint32(secs))
// send immediate keepalive if we're turning it on and before it wasn't on
2017-08-04 16:15:53 +02:00
if old == 0 && secs != 0 {
if err != nil {
logError.Println("Failed to get tun device status:", err)
2019-03-03 04:04:41 +01:00
return &IPCError{ipc.IpcErrorIO}
2017-08-04 16:15:53 +02:00
}
2017-12-29 17:42:09 +01:00
if device.isUp.Get() && !dummy {
peer.SendKeepalive()
2017-08-04 16:15:53 +02:00
}
}
case "replace_allowed_ips":
2018-05-21 03:38:50 +02:00
logDebug.Println(peer, "- UAPI: Removing all allowedips")
2017-08-04 16:15:53 +02:00
if value != "true" {
2018-05-21 03:38:50 +02:00
logError.Println("Failed to replace allowedips, invalid value:", value)
2019-03-03 04:04:41 +01:00
return &IPCError{ipc.IpcErrorInvalid}
}
if dummy {
continue
}
2018-05-13 23:14:43 +02:00
device.allowedips.RemoveByPeer(peer)
case "allowed_ip":
2018-05-21 03:38:50 +02:00
logDebug.Println(peer, "- UAPI: Adding allowedip")
_, network, err := net.ParseCIDR(value)
if err != nil {
2018-05-21 03:38:50 +02:00
logError.Println("Failed to set allowed ip:", err)
2019-03-03 04:04:41 +01:00
return &IPCError{ipc.IpcErrorInvalid}
}
if dummy {
continue
}
ones, _ := network.Mask.Size()
2018-05-13 23:14:43 +02:00
device.allowedips.Insert(network.IP, uint(ones), peer)
case "protocol_version":
if value != "1" {
logError.Println("Invalid protocol version:", value)
2019-03-03 04:04:41 +01:00
return &IPCError{ipc.IpcErrorInvalid}
}
default:
2018-05-21 03:38:50 +02:00
logError.Println("Invalid UAPI peer key:", key)
2019-03-03 04:04:41 +01:00
return &IPCError{ipc.IpcErrorInvalid}
}
}
}
return nil
}
2019-03-03 04:04:41 +01:00
func (device *Device) IpcHandle(socket net.Conn) {
2017-08-04 16:15:53 +02:00
// create buffered read/writer
2017-07-17 16:16:18 +02:00
defer socket.Close()
2017-07-17 16:16:18 +02:00
buffered := func(s io.ReadWriter) *bufio.ReadWriter {
reader := bufio.NewReader(s)
writer := bufio.NewWriter(s)
return bufio.NewReadWriter(reader, writer)
}(socket)
2017-07-17 16:16:18 +02:00
defer buffered.Flush()
2017-07-17 16:16:18 +02:00
op, err := buffered.ReadString('\n')
if err != nil {
return
}
2017-08-04 16:15:53 +02:00
// handle operation
2017-08-04 16:15:53 +02:00
var status *IPCError
switch op {
2017-07-17 16:16:18 +02:00
case "set=1\n":
err = device.IpcSetOperation(buffered.Reader)
if err != nil && !errors.As(err, &status) {
// should never happen
device.log.Error.Println("Invalid UAPI error:", err)
status = &IPCError{1}
}
2017-07-17 16:16:18 +02:00
case "get=1\n":
err = device.IpcGetOperation(buffered.Writer)
if err != nil && !errors.As(err, &status) {
// should never happen
device.log.Error.Println("Invalid UAPI error:", err)
status = &IPCError{1}
}
2017-07-17 16:16:18 +02:00
default:
device.log.Error.Println("Invalid UAPI operation:", op)
2017-08-04 16:15:53 +02:00
return
}
// write status
2017-08-04 16:15:53 +02:00
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")
2017-07-17 16:16:18 +02:00
}
}