github.com/tailscale/wireguard-go@v0.0.20201119-0.20210522003738-46b531feb08a/device/uapi.go (about)

     1  /* SPDX-License-Identifier: MIT
     2   *
     3   * Copyright (C) 2017-2021 WireGuard LLC. All Rights Reserved.
     4   */
     5  
     6  package device
     7  
     8  import (
     9  	"bufio"
    10  	"bytes"
    11  	"errors"
    12  	"fmt"
    13  	"io"
    14  	"net"
    15  	"strconv"
    16  	"strings"
    17  	"sync"
    18  	"sync/atomic"
    19  	"time"
    20  
    21  	"github.com/tailscale/wireguard-go/ipc"
    22  )
    23  
    24  type IPCError struct {
    25  	code int64 // error code
    26  	err  error // underlying/wrapped error
    27  }
    28  
    29  func (s IPCError) Error() string {
    30  	return fmt.Sprintf("IPC error %d: %v", s.code, s.err)
    31  }
    32  
    33  func (s IPCError) Unwrap() error {
    34  	return s.err
    35  }
    36  
    37  func (s IPCError) ErrorCode() int64 {
    38  	return s.code
    39  }
    40  
    41  func ipcErrorf(code int64, msg string, args ...interface{}) *IPCError {
    42  	return &IPCError{code: code, err: fmt.Errorf(msg, args...)}
    43  }
    44  
    45  var byteBufferPool = &sync.Pool{
    46  	New: func() interface{} { return new(bytes.Buffer) },
    47  }
    48  
    49  // IpcGetOperation implements the WireGuard configuration protocol "get" operation.
    50  // See https://www.wireguard.com/xplatform/#configuration-protocol for details.
    51  func (device *Device) IpcGetOperation(w io.Writer) error {
    52  	device.ipcMutex.RLock()
    53  	defer device.ipcMutex.RUnlock()
    54  
    55  	buf := byteBufferPool.Get().(*bytes.Buffer)
    56  	buf.Reset()
    57  	defer byteBufferPool.Put(buf)
    58  	sendf := func(format string, args ...interface{}) {
    59  		fmt.Fprintf(buf, format, args...)
    60  		buf.WriteByte('\n')
    61  	}
    62  	keyf := func(prefix string, key *[32]byte) {
    63  		buf.Grow(len(key)*2 + 2 + len(prefix))
    64  		buf.WriteString(prefix)
    65  		buf.WriteByte('=')
    66  		const hex = "0123456789abcdef"
    67  		for i := 0; i < len(key); i++ {
    68  			buf.WriteByte(hex[key[i]>>4])
    69  			buf.WriteByte(hex[key[i]&0xf])
    70  		}
    71  		buf.WriteByte('\n')
    72  	}
    73  
    74  	func() {
    75  
    76  		// lock required resources
    77  
    78  		device.net.RLock()
    79  		defer device.net.RUnlock()
    80  
    81  		device.staticIdentity.RLock()
    82  		defer device.staticIdentity.RUnlock()
    83  
    84  		device.peers.RLock()
    85  		defer device.peers.RUnlock()
    86  
    87  		// serialize device related values
    88  
    89  		if !device.staticIdentity.privateKey.IsZero() {
    90  			keyf("private_key", (*[32]byte)(&device.staticIdentity.privateKey))
    91  		}
    92  
    93  		if device.net.port != 0 {
    94  			sendf("listen_port=%d", device.net.port)
    95  		}
    96  
    97  		if device.net.fwmark != 0 {
    98  			sendf("fwmark=%d", device.net.fwmark)
    99  		}
   100  
   101  		// serialize each peer state
   102  
   103  		for _, peer := range device.peers.keyMap {
   104  			peer.RLock()
   105  			defer peer.RUnlock()
   106  
   107  			keyf("public_key", (*[32]byte)(&peer.handshake.remoteStatic))
   108  			keyf("preshared_key", (*[32]byte)(&peer.handshake.presharedKey))
   109  			sendf("protocol_version=1")
   110  			if peer.endpoint != nil {
   111  				sendf("endpoint=%s", peer.endpoint.DstToString())
   112  			}
   113  
   114  			nano := atomic.LoadInt64(&peer.stats.lastHandshakeNano)
   115  			secs := nano / time.Second.Nanoseconds()
   116  			nano %= time.Second.Nanoseconds()
   117  
   118  			sendf("last_handshake_time_sec=%d", secs)
   119  			sendf("last_handshake_time_nsec=%d", nano)
   120  			sendf("tx_bytes=%d", atomic.LoadUint64(&peer.stats.txBytes))
   121  			sendf("rx_bytes=%d", atomic.LoadUint64(&peer.stats.rxBytes))
   122  			sendf("persistent_keepalive_interval=%d", atomic.LoadUint32(&peer.persistentKeepaliveInterval))
   123  
   124  			device.allowedips.EntriesForPeer(peer, func(ip net.IP, cidr uint) bool {
   125  				sendf("allowed_ip=%s/%d", ip.String(), cidr)
   126  				return true
   127  			})
   128  		}
   129  	}()
   130  
   131  	// send lines (does not require resource locks)
   132  	if _, err := w.Write(buf.Bytes()); err != nil {
   133  		return ipcErrorf(ipc.IpcErrorIO, "failed to write output: %w", err)
   134  	}
   135  
   136  	return nil
   137  }
   138  
   139  // IpcSetOperation implements the WireGuard configuration protocol "set" operation.
   140  // See https://www.wireguard.com/xplatform/#configuration-protocol for details.
   141  func (device *Device) IpcSetOperation(r io.Reader) (err error) {
   142  	device.ipcMutex.Lock()
   143  	defer device.ipcMutex.Unlock()
   144  
   145  	defer func() {
   146  		if err != nil {
   147  			device.log.Errorf("%v", err)
   148  		}
   149  	}()
   150  
   151  	peer := new(ipcSetPeer)
   152  	deviceConfig := true
   153  
   154  	scanner := bufio.NewScanner(r)
   155  	for scanner.Scan() {
   156  		line := scanner.Text()
   157  		if line == "" {
   158  			// Blank line means terminate operation.
   159  			return nil
   160  		}
   161  		parts := strings.Split(line, "=")
   162  		if len(parts) != 2 {
   163  			return ipcErrorf(ipc.IpcErrorProtocol, "failed to parse line %q, found %d =-separated parts, want 2", line, len(parts))
   164  		}
   165  		key := parts[0]
   166  		value := parts[1]
   167  
   168  		if key == "public_key" {
   169  			if deviceConfig {
   170  				deviceConfig = false
   171  			}
   172  			peer.handlePostConfig()
   173  			// Load/create the peer we are now configuring.
   174  			err := device.handlePublicKeyLine(peer, value)
   175  			if err != nil {
   176  				return err
   177  			}
   178  			continue
   179  		}
   180  
   181  		var err error
   182  		if deviceConfig {
   183  			err = device.handleDeviceLine(key, value)
   184  		} else {
   185  			err = device.handlePeerLine(peer, key, value)
   186  		}
   187  		if err != nil {
   188  			return err
   189  		}
   190  	}
   191  	peer.handlePostConfig()
   192  
   193  	if err := scanner.Err(); err != nil {
   194  		return ipcErrorf(ipc.IpcErrorIO, "failed to read input: %w", err)
   195  	}
   196  	return nil
   197  }
   198  
   199  func (device *Device) handleDeviceLine(key, value string) error {
   200  	switch key {
   201  	case "private_key":
   202  		var sk NoisePrivateKey
   203  		err := sk.FromMaybeZeroHex(value)
   204  		if err != nil {
   205  			return ipcErrorf(ipc.IpcErrorInvalid, "failed to set private_key: %w", err)
   206  		}
   207  		device.log.Verbosef("UAPI: Updating private key")
   208  		device.SetPrivateKey(sk)
   209  
   210  	case "listen_port":
   211  		port, err := strconv.ParseUint(value, 10, 16)
   212  		if err != nil {
   213  			return ipcErrorf(ipc.IpcErrorInvalid, "failed to parse listen_port: %w", err)
   214  		}
   215  
   216  		// update port and rebind
   217  		device.log.Verbosef("UAPI: Updating listen port")
   218  
   219  		device.net.Lock()
   220  		device.net.port = uint16(port)
   221  		device.net.Unlock()
   222  
   223  		if err := device.BindUpdate(); err != nil {
   224  			return ipcErrorf(ipc.IpcErrorPortInUse, "failed to set listen_port: %w", err)
   225  		}
   226  
   227  	case "fwmark":
   228  		mark, err := strconv.ParseUint(value, 10, 32)
   229  		if err != nil {
   230  			return ipcErrorf(ipc.IpcErrorInvalid, "invalid fwmark: %w", err)
   231  		}
   232  
   233  		device.log.Verbosef("UAPI: Updating fwmark")
   234  		if err := device.BindSetMark(uint32(mark)); err != nil {
   235  			return ipcErrorf(ipc.IpcErrorPortInUse, "failed to update fwmark: %w", err)
   236  		}
   237  
   238  	case "replace_peers":
   239  		if value != "true" {
   240  			return ipcErrorf(ipc.IpcErrorInvalid, "failed to set replace_peers, invalid value: %v", value)
   241  		}
   242  		device.log.Verbosef("UAPI: Removing all peers")
   243  		device.RemoveAllPeers()
   244  
   245  	default:
   246  		return ipcErrorf(ipc.IpcErrorInvalid, "invalid UAPI device key: %v", key)
   247  	}
   248  
   249  	return nil
   250  }
   251  
   252  // An ipcSetPeer is the current state of an IPC set operation on a peer.
   253  type ipcSetPeer struct {
   254  	*Peer        // Peer is the current peer being operated on
   255  	dummy   bool // dummy reports whether this peer is a temporary, placeholder peer
   256  	created bool // new reports whether this is a newly created peer
   257  }
   258  
   259  func (peer *ipcSetPeer) handlePostConfig() {
   260  	if peer.Peer != nil && !peer.dummy && peer.Peer.device.isUp() {
   261  		peer.SendStagedPackets()
   262  	}
   263  }
   264  
   265  func (device *Device) handlePublicKeyLine(peer *ipcSetPeer, value string) error {
   266  	// Load/create the peer we are configuring.
   267  	var publicKey NoisePublicKey
   268  	err := publicKey.FromHex(value)
   269  	if err != nil {
   270  		return ipcErrorf(ipc.IpcErrorInvalid, "failed to get peer by public key: %w", err)
   271  	}
   272  
   273  	// Ignore peer with the same public key as this device.
   274  	device.staticIdentity.RLock()
   275  	peer.dummy = device.staticIdentity.publicKey.Equals(publicKey)
   276  	device.staticIdentity.RUnlock()
   277  
   278  	if peer.dummy {
   279  		peer.Peer = &Peer{}
   280  	} else {
   281  		peer.Peer = device.LookupPeer(publicKey)
   282  	}
   283  
   284  	peer.created = peer.Peer == nil
   285  	if peer.created {
   286  		peer.Peer, err = device.NewPeer(publicKey)
   287  		if err != nil {
   288  			return ipcErrorf(ipc.IpcErrorInvalid, "failed to create new peer: %w", err)
   289  		}
   290  		device.log.Verbosef("%v - UAPI: Created", peer.Peer)
   291  	}
   292  	return nil
   293  }
   294  
   295  func (device *Device) handlePeerLine(peer *ipcSetPeer, key, value string) error {
   296  	switch key {
   297  	case "update_only":
   298  		// allow disabling of creation
   299  		if value != "true" {
   300  			return ipcErrorf(ipc.IpcErrorInvalid, "failed to set update only, invalid value: %v", value)
   301  		}
   302  		if peer.created && !peer.dummy {
   303  			device.RemovePeer(peer.handshake.remoteStatic)
   304  			peer.Peer = &Peer{}
   305  			peer.dummy = true
   306  		}
   307  
   308  	case "remove":
   309  		// remove currently selected peer from device
   310  		if value != "true" {
   311  			return ipcErrorf(ipc.IpcErrorInvalid, "failed to set remove, invalid value: %v", value)
   312  		}
   313  		if !peer.dummy {
   314  			device.log.Verbosef("%v - UAPI: Removing", peer.Peer)
   315  			device.RemovePeer(peer.handshake.remoteStatic)
   316  		}
   317  		peer.Peer = &Peer{}
   318  		peer.dummy = true
   319  
   320  	case "preshared_key":
   321  		device.log.Verbosef("%v - UAPI: Updating preshared key", peer.Peer)
   322  
   323  		peer.handshake.mutex.Lock()
   324  		err := peer.handshake.presharedKey.FromHex(value)
   325  		peer.handshake.mutex.Unlock()
   326  
   327  		if err != nil {
   328  			return ipcErrorf(ipc.IpcErrorInvalid, "failed to set preshared key: %w", err)
   329  		}
   330  
   331  	case "endpoint":
   332  		device.log.Verbosef("%v - UAPI: Updating endpoint", peer.Peer)
   333  		endpoint, err := device.net.bind.ParseEndpoint(value)
   334  		if err != nil {
   335  			return ipcErrorf(ipc.IpcErrorInvalid, "failed to set endpoint %v: %w", value, err)
   336  		}
   337  		peer.Lock()
   338  		defer peer.Unlock()
   339  		peer.endpoint = endpoint
   340  
   341  	case "persistent_keepalive_interval":
   342  		device.log.Verbosef("%v - UAPI: Updating persistent keepalive interval", peer.Peer)
   343  
   344  		secs, err := strconv.ParseUint(value, 10, 16)
   345  		if err != nil {
   346  			return ipcErrorf(ipc.IpcErrorInvalid, "failed to set persistent keepalive interval: %w", err)
   347  		}
   348  
   349  		old := atomic.SwapUint32(&peer.persistentKeepaliveInterval, uint32(secs))
   350  
   351  		// Send immediate keepalive if we're turning it on and before it wasn't on.
   352  		if old == 0 && secs != 0 {
   353  			if err != nil {
   354  				return ipcErrorf(ipc.IpcErrorIO, "failed to get tun device status: %w", err)
   355  			}
   356  			if device.isUp() && !peer.dummy {
   357  				peer.SendKeepalive()
   358  			}
   359  		}
   360  
   361  	case "replace_allowed_ips":
   362  		device.log.Verbosef("%v - UAPI: Removing all allowedips", peer.Peer)
   363  		if value != "true" {
   364  			return ipcErrorf(ipc.IpcErrorInvalid, "failed to replace allowedips, invalid value: %v", value)
   365  		}
   366  		if peer.dummy {
   367  			return nil
   368  		}
   369  		device.allowedips.RemoveByPeer(peer.Peer)
   370  
   371  	case "allowed_ip":
   372  		device.log.Verbosef("%v - UAPI: Adding allowedip", peer.Peer)
   373  
   374  		_, network, err := net.ParseCIDR(value)
   375  		if err != nil {
   376  			return ipcErrorf(ipc.IpcErrorInvalid, "failed to set allowed ip: %w", err)
   377  		}
   378  		if peer.dummy {
   379  			return nil
   380  		}
   381  		ones, _ := network.Mask.Size()
   382  		device.allowedips.Insert(network.IP, uint(ones), peer.Peer)
   383  
   384  	case "protocol_version":
   385  		if value != "1" {
   386  			return ipcErrorf(ipc.IpcErrorInvalid, "invalid protocol version: %v", value)
   387  		}
   388  
   389  	default:
   390  		return ipcErrorf(ipc.IpcErrorInvalid, "invalid UAPI peer key: %v", key)
   391  	}
   392  
   393  	return nil
   394  }
   395  
   396  func (device *Device) IpcGet() (string, error) {
   397  	buf := new(strings.Builder)
   398  	if err := device.IpcGetOperation(buf); err != nil {
   399  		return "", err
   400  	}
   401  	return buf.String(), nil
   402  }
   403  
   404  func (device *Device) IpcSet(uapiConf string) error {
   405  	return device.IpcSetOperation(strings.NewReader(uapiConf))
   406  }
   407  
   408  func (device *Device) IpcHandle(socket net.Conn) {
   409  	defer socket.Close()
   410  
   411  	buffered := func(s io.ReadWriter) *bufio.ReadWriter {
   412  		reader := bufio.NewReader(s)
   413  		writer := bufio.NewWriter(s)
   414  		return bufio.NewReadWriter(reader, writer)
   415  	}(socket)
   416  
   417  	for {
   418  		op, err := buffered.ReadString('\n')
   419  		if err != nil {
   420  			return
   421  		}
   422  
   423  		// handle operation
   424  		switch op {
   425  		case "set=1\n":
   426  			err = device.IpcSetOperation(buffered.Reader)
   427  		case "get=1\n":
   428  			var nextByte byte
   429  			nextByte, err = buffered.ReadByte()
   430  			if err != nil {
   431  				return
   432  			}
   433  			if nextByte != '\n' {
   434  				err = ipcErrorf(ipc.IpcErrorInvalid, "trailing character in UAPI get: %q", nextByte)
   435  				break
   436  			}
   437  			err = device.IpcGetOperation(buffered.Writer)
   438  		default:
   439  			device.log.Errorf("invalid UAPI operation: %v", op)
   440  			return
   441  		}
   442  
   443  		// write status
   444  		var status *IPCError
   445  		if err != nil && !errors.As(err, &status) {
   446  			// shouldn't happen
   447  			status = ipcErrorf(ipc.IpcErrorUnknown, "other UAPI error: %w", err)
   448  		}
   449  		if status != nil {
   450  			device.log.Errorf("%v", status)
   451  			fmt.Fprintf(buffered, "errno=%d\n\n", status.ErrorCode())
   452  		} else {
   453  			fmt.Fprintf(buffered, "errno=0\n\n")
   454  		}
   455  		buffered.Flush()
   456  	}
   457  }