2017-05-30 22:36:49 +02:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bufio"
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
2017-06-01 21:31:30 +02:00
|
|
|
"net"
|
2017-06-04 21:48:15 +02:00
|
|
|
"strconv"
|
2017-06-29 14:39:21 +02:00
|
|
|
"strings"
|
2017-07-17 16:16:18 +02:00
|
|
|
"sync/atomic"
|
|
|
|
"syscall"
|
2017-05-30 22:36:49 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
2017-07-17 16:16:18 +02:00
|
|
|
ipcErrorIO = syscall.EIO
|
|
|
|
ipcErrorNoPeer = syscall.EPROTO
|
|
|
|
ipcErrorNoKeyValue = syscall.EPROTO
|
|
|
|
ipcErrorInvalidKey = syscall.EPROTO
|
|
|
|
ipcErrorInvalidValue = syscall.EPROTO
|
2017-05-30 22:36:49 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
type IPCError struct {
|
2017-07-17 16:16:18 +02:00
|
|
|
Code syscall.Errno
|
2017-05-30 22:36:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *IPCError) Error() string {
|
|
|
|
return fmt.Sprintf("IPC error: %d", s.Code)
|
|
|
|
}
|
|
|
|
|
2017-07-17 16:16:18 +02:00
|
|
|
func (s *IPCError) ErrorCode() uintptr {
|
|
|
|
return uintptr(s.Code)
|
2017-05-30 22:36:49 +02:00
|
|
|
}
|
|
|
|
|
2017-07-17 16:16:18 +02:00
|
|
|
func ipcGetOperation(device *Device, socket *bufio.ReadWriter) *IPCError {
|
2017-06-28 23:45:45 +02:00
|
|
|
|
|
|
|
// create lines
|
|
|
|
|
2017-07-17 16:16:18 +02:00
|
|
|
device.mutex.RLock()
|
|
|
|
|
2017-06-28 23:45:45 +02:00
|
|
|
lines := make([]string, 0, 100)
|
|
|
|
send := func(line string) {
|
|
|
|
lines = append(lines, line)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !device.privateKey.IsZero() {
|
|
|
|
send("private_key=" + device.privateKey.ToHex())
|
|
|
|
}
|
|
|
|
|
2017-06-30 14:41:08 +02:00
|
|
|
send(fmt.Sprintf("listen_port=%d", device.net.addr.Port))
|
2017-06-28 23:45:45 +02:00
|
|
|
|
|
|
|
for _, peer := range device.peers {
|
|
|
|
func() {
|
|
|
|
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.String())
|
|
|
|
}
|
2017-07-08 09:23:10 +02:00
|
|
|
send(fmt.Sprintf("tx_bytes=%d", peer.txBytes))
|
|
|
|
send(fmt.Sprintf("rx_bytes=%d", peer.rxBytes))
|
2017-07-17 16:16:18 +02:00
|
|
|
send(fmt.Sprintf("persistent_keepalive_interval=%d",
|
|
|
|
atomic.LoadUint64(&peer.persistentKeepaliveInterval),
|
|
|
|
))
|
2017-06-28 23:45:45 +02:00
|
|
|
for _, ip := range device.routingTable.AllowedIPs(peer) {
|
|
|
|
send("allowed_ip=" + ip.String())
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
}
|
|
|
|
|
2017-07-17 16:16:18 +02:00
|
|
|
device.mutex.RUnlock()
|
|
|
|
|
2017-06-28 23:45:45 +02:00
|
|
|
// send lines
|
|
|
|
|
|
|
|
for _, line := range lines {
|
|
|
|
_, err := socket.WriteString(line + "\n")
|
|
|
|
if err != nil {
|
2017-07-17 16:16:18 +02:00
|
|
|
return &IPCError{
|
|
|
|
Code: ipcErrorIO,
|
|
|
|
}
|
2017-06-28 23:45:45 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
2017-05-30 22:36:49 +02:00
|
|
|
}
|
|
|
|
|
2017-06-04 21:48:15 +02:00
|
|
|
func ipcSetOperation(device *Device, socket *bufio.ReadWriter) *IPCError {
|
2017-05-30 22:36:49 +02:00
|
|
|
scanner := bufio.NewScanner(socket)
|
2017-07-17 16:16:18 +02:00
|
|
|
logError := device.log.Error
|
|
|
|
logDebug := device.log.Debug
|
2017-05-30 22:36:49 +02:00
|
|
|
|
2017-06-29 14:39:21 +02:00
|
|
|
var peer *Peer
|
2017-05-30 22:36:49 +02:00
|
|
|
for scanner.Scan() {
|
|
|
|
|
2017-07-17 16:16:18 +02:00
|
|
|
// parse line
|
2017-05-30 22:36:49 +02:00
|
|
|
|
|
|
|
line := scanner.Text()
|
2017-06-29 14:39:21 +02:00
|
|
|
if line == "" {
|
|
|
|
return nil
|
2017-05-30 22:36:49 +02:00
|
|
|
}
|
2017-06-29 14:39:21 +02:00
|
|
|
parts := strings.Split(line, "=")
|
|
|
|
if len(parts) != 2 {
|
2017-05-30 22:36:49 +02:00
|
|
|
return &IPCError{Code: ipcErrorNoKeyValue}
|
|
|
|
}
|
2017-06-29 14:39:21 +02:00
|
|
|
key := parts[0]
|
|
|
|
value := parts[1]
|
2017-05-30 22:36:49 +02:00
|
|
|
|
|
|
|
switch key {
|
|
|
|
|
2017-07-17 16:16:18 +02:00
|
|
|
/* interface configuration */
|
2017-05-30 22:36:49 +02:00
|
|
|
|
|
|
|
case "private_key":
|
|
|
|
if value == "" {
|
2017-06-29 14:39:21 +02:00
|
|
|
device.mutex.Lock()
|
2017-06-04 21:48:15 +02:00
|
|
|
device.privateKey = NoisePrivateKey{}
|
2017-06-29 14:39:21 +02:00
|
|
|
device.mutex.Unlock()
|
2017-05-30 22:36:49 +02:00
|
|
|
} else {
|
2017-06-30 14:41:08 +02:00
|
|
|
var sk NoisePrivateKey
|
|
|
|
err := sk.FromHex(value)
|
2017-05-30 22:36:49 +02:00
|
|
|
if err != nil {
|
2017-07-17 16:16:18 +02:00
|
|
|
logError.Println("Failed to set private_key:", err)
|
2017-06-29 14:39:21 +02:00
|
|
|
return &IPCError{Code: ipcErrorInvalidValue}
|
2017-05-30 22:36:49 +02:00
|
|
|
}
|
2017-06-30 14:41:08 +02:00
|
|
|
device.SetPrivateKey(sk)
|
2017-05-30 22:36:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
case "listen_port":
|
2017-06-29 14:39:21 +02:00
|
|
|
var port int
|
|
|
|
_, err := fmt.Sscanf(value, "%d", &port)
|
|
|
|
if err != nil || port > (1<<16) || port < 0 {
|
2017-07-17 16:16:18 +02:00
|
|
|
logError.Println("Failed to set listen_port:", err)
|
2017-06-29 14:39:21 +02:00
|
|
|
return &IPCError{Code: ipcErrorInvalidValue}
|
2017-05-30 22:36:49 +02:00
|
|
|
}
|
2017-06-30 14:41:08 +02:00
|
|
|
device.net.mutex.Lock()
|
|
|
|
device.net.addr.Port = port
|
|
|
|
device.net.conn, err = net.ListenUDP("udp", device.net.addr)
|
|
|
|
device.net.mutex.Unlock()
|
2017-07-17 16:16:18 +02:00
|
|
|
if err != nil {
|
|
|
|
logError.Println("Failed to create UDP listener:", err)
|
|
|
|
return &IPCError{Code: ipcErrorInvalidValue}
|
|
|
|
}
|
2017-05-30 22:36:49 +02:00
|
|
|
|
|
|
|
case "fwmark":
|
2017-07-17 16:16:18 +02:00
|
|
|
logError.Println("FWMark not handled yet")
|
2017-05-30 22:36:49 +02:00
|
|
|
|
|
|
|
case "public_key":
|
|
|
|
var pubKey NoisePublicKey
|
|
|
|
err := pubKey.FromHex(value)
|
|
|
|
if err != nil {
|
2017-07-17 16:16:18 +02:00
|
|
|
logError.Println("Failed to get peer by public_key:", err)
|
2017-06-29 14:39:21 +02:00
|
|
|
return &IPCError{Code: ipcErrorInvalidValue}
|
2017-05-30 22:36:49 +02:00
|
|
|
}
|
2017-06-29 14:39:21 +02:00
|
|
|
device.mutex.RLock()
|
2017-06-04 21:48:15 +02:00
|
|
|
found, ok := device.peers[pubKey]
|
2017-06-29 14:39:21 +02:00
|
|
|
device.mutex.RUnlock()
|
2017-05-30 22:36:49 +02:00
|
|
|
if ok {
|
|
|
|
peer = found
|
|
|
|
} else {
|
2017-06-24 15:34:17 +02:00
|
|
|
peer = device.NewPeer(pubKey)
|
2017-05-30 22:36:49 +02:00
|
|
|
}
|
2017-06-29 14:39:21 +02:00
|
|
|
if peer == nil {
|
2017-07-17 16:16:18 +02:00
|
|
|
panic(errors.New("bug: failed to find / create peer"))
|
2017-06-29 14:39:21 +02:00
|
|
|
}
|
2017-05-30 22:36:49 +02:00
|
|
|
|
|
|
|
case "replace_peers":
|
2017-06-29 14:39:21 +02:00
|
|
|
if value == "true" {
|
2017-06-04 21:48:15 +02:00
|
|
|
device.RemoveAllPeers()
|
|
|
|
} else {
|
2017-07-17 16:16:18 +02:00
|
|
|
logError.Println("Failed to set replace_peers, invalid value:", value)
|
2017-06-04 21:48:15 +02:00
|
|
|
return &IPCError{Code: ipcErrorInvalidValue}
|
2017-06-01 21:31:30 +02:00
|
|
|
}
|
2017-05-30 22:36:49 +02:00
|
|
|
|
|
|
|
default:
|
2017-07-17 16:16:18 +02:00
|
|
|
|
|
|
|
/* peer configuration */
|
2017-05-30 22:36:49 +02:00
|
|
|
|
|
|
|
if peer == nil {
|
2017-07-17 16:16:18 +02:00
|
|
|
logError.Println("No peer referenced, before peer operation")
|
2017-05-30 22:36:49 +02:00
|
|
|
return &IPCError{Code: ipcErrorNoPeer}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch key {
|
|
|
|
|
|
|
|
case "remove":
|
|
|
|
peer.mutex.Lock()
|
2017-06-29 14:39:21 +02:00
|
|
|
device.RemovePeer(peer.handshake.remoteStatic)
|
|
|
|
peer.mutex.Unlock()
|
2017-07-17 16:16:18 +02:00
|
|
|
logDebug.Println("Removing", peer.String())
|
2017-05-30 22:36:49 +02:00
|
|
|
peer = nil
|
|
|
|
|
|
|
|
case "preshared_key":
|
2017-06-01 21:31:30 +02:00
|
|
|
err := func() error {
|
2017-05-30 22:36:49 +02:00
|
|
|
peer.mutex.Lock()
|
|
|
|
defer peer.mutex.Unlock()
|
2017-06-24 15:34:17 +02:00
|
|
|
return peer.handshake.presharedKey.FromHex(value)
|
2017-05-30 22:36:49 +02:00
|
|
|
}()
|
2017-06-01 21:31:30 +02:00
|
|
|
if err != nil {
|
2017-07-17 16:16:18 +02:00
|
|
|
logError.Println("Failed to set preshared_key:", err)
|
2017-06-29 14:39:21 +02:00
|
|
|
return &IPCError{Code: ipcErrorInvalidValue}
|
2017-06-01 21:31:30 +02:00
|
|
|
}
|
2017-05-30 22:36:49 +02:00
|
|
|
|
|
|
|
case "endpoint":
|
2017-06-30 14:41:08 +02:00
|
|
|
addr, err := net.ResolveUDPAddr("udp", value)
|
|
|
|
if err != nil {
|
2017-07-17 16:16:18 +02:00
|
|
|
logError.Println("Failed to set endpoint:", value)
|
2017-06-29 14:39:21 +02:00
|
|
|
return &IPCError{Code: ipcErrorInvalidValue}
|
2017-06-01 21:31:30 +02:00
|
|
|
}
|
|
|
|
peer.mutex.Lock()
|
2017-06-30 14:41:08 +02:00
|
|
|
peer.endpoint = addr
|
2017-06-01 21:31:30 +02:00
|
|
|
peer.mutex.Unlock()
|
2017-05-30 22:36:49 +02:00
|
|
|
|
|
|
|
case "persistent_keepalive_interval":
|
2017-06-04 21:48:15 +02:00
|
|
|
secs, err := strconv.ParseInt(value, 10, 64)
|
|
|
|
if secs < 0 || err != nil {
|
2017-07-17 16:16:18 +02:00
|
|
|
logError.Println("Failed to set persistent_keepalive_interval:", err)
|
2017-06-04 21:48:15 +02:00
|
|
|
return &IPCError{Code: ipcErrorInvalidValue}
|
|
|
|
}
|
2017-07-17 16:16:18 +02:00
|
|
|
atomic.StoreUint64(
|
|
|
|
&peer.persistentKeepaliveInterval,
|
|
|
|
uint64(secs),
|
|
|
|
)
|
2017-05-30 22:36:49 +02:00
|
|
|
|
|
|
|
case "replace_allowed_ips":
|
2017-06-29 14:39:21 +02:00
|
|
|
if value == "true" {
|
2017-06-04 21:48:15 +02:00
|
|
|
device.routingTable.RemovePeer(peer)
|
|
|
|
} else {
|
2017-07-17 16:16:18 +02:00
|
|
|
logError.Println("Failed to set replace_allowed_ips, invalid value:", value)
|
2017-06-04 21:48:15 +02:00
|
|
|
return &IPCError{Code: ipcErrorInvalidValue}
|
|
|
|
}
|
2017-05-30 22:36:49 +02:00
|
|
|
|
|
|
|
case "allowed_ip":
|
2017-06-04 21:48:15 +02:00
|
|
|
_, network, err := net.ParseCIDR(value)
|
|
|
|
if err != nil {
|
2017-07-17 16:16:18 +02:00
|
|
|
logError.Println("Failed to set allowed_ip:", err)
|
2017-06-04 21:48:15 +02:00
|
|
|
return &IPCError{Code: ipcErrorInvalidValue}
|
|
|
|
}
|
|
|
|
ones, _ := network.Mask.Size()
|
2017-07-17 16:16:18 +02:00
|
|
|
logError.Println(network, ones, network.IP)
|
2017-06-04 21:48:15 +02:00
|
|
|
device.routingTable.Insert(network.IP, uint(ones), peer)
|
2017-05-30 22:36:49 +02:00
|
|
|
|
|
|
|
default:
|
2017-07-17 16:16:18 +02:00
|
|
|
logError.Println("Invalid UAPI key:", key)
|
2017-05-30 22:36:49 +02:00
|
|
|
return &IPCError{Code: ipcErrorInvalidKey}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2017-06-29 14:39:21 +02:00
|
|
|
func ipcHandle(device *Device, socket net.Conn) {
|
2017-05-30 22:36:49 +02:00
|
|
|
|
2017-07-17 16:16:18 +02:00
|
|
|
defer socket.Close()
|
2017-05-30 22:36:49 +02:00
|
|
|
|
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-06-28 23:45:45 +02:00
|
|
|
|
2017-07-17 16:16:18 +02:00
|
|
|
defer buffered.Flush()
|
2017-05-30 22:36:49 +02:00
|
|
|
|
2017-07-17 16:16:18 +02:00
|
|
|
op, err := buffered.ReadString('\n')
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2017-05-30 22:36:49 +02:00
|
|
|
|
2017-07-17 16:16:18 +02:00
|
|
|
switch op {
|
2017-05-30 22:36:49 +02:00
|
|
|
|
2017-07-17 16:16:18 +02:00
|
|
|
case "set=1\n":
|
|
|
|
device.log.Debug.Println("Config, set operation")
|
|
|
|
err := ipcSetOperation(device, buffered)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Fprintf(buffered, "errno=%d\n\n", err.ErrorCode())
|
|
|
|
} else {
|
|
|
|
fmt.Fprintf(buffered, "errno=0\n\n")
|
|
|
|
}
|
|
|
|
return
|
2017-05-30 22:36:49 +02:00
|
|
|
|
2017-07-17 16:16:18 +02:00
|
|
|
case "get=1\n":
|
|
|
|
device.log.Debug.Println("Config, get operation")
|
|
|
|
err := ipcGetOperation(device, buffered)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Fprintf(buffered, "errno=%d\n\n", err.ErrorCode())
|
|
|
|
} else {
|
|
|
|
fmt.Fprintf(buffered, "errno=0\n\n")
|
2017-05-30 22:36:49 +02:00
|
|
|
}
|
2017-07-17 16:16:18 +02:00
|
|
|
return
|
|
|
|
|
|
|
|
default:
|
|
|
|
device.log.Error.Println("Invalid UAPI operation:", op)
|
2017-05-30 22:36:49 +02:00
|
|
|
|
2017-07-17 16:16:18 +02:00
|
|
|
}
|
2017-05-30 22:36:49 +02:00
|
|
|
}
|