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 }