2017-05-30 22:36:49 +02:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bufio"
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"log"
|
2017-06-01 21:31:30 +02:00
|
|
|
"net"
|
2017-06-04 21:48:15 +02:00
|
|
|
"strconv"
|
|
|
|
"time"
|
2017-05-30 22:36:49 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
/* todo : use real error code
|
|
|
|
* Many of which will be the same
|
|
|
|
*/
|
|
|
|
const (
|
|
|
|
ipcErrorNoPeer = 0
|
|
|
|
ipcErrorNoKeyValue = 1
|
|
|
|
ipcErrorInvalidKey = 2
|
2017-06-04 21:48:15 +02:00
|
|
|
ipcErrorInvalidValue = 2
|
2017-05-30 22:36:49 +02:00
|
|
|
ipcErrorInvalidPrivateKey = 3
|
|
|
|
ipcErrorInvalidPublicKey = 4
|
|
|
|
ipcErrorInvalidPort = 5
|
2017-06-01 21:31:30 +02:00
|
|
|
ipcErrorInvalidIPAddress = 6
|
2017-05-30 22:36:49 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
type IPCError struct {
|
|
|
|
Code int
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *IPCError) Error() string {
|
|
|
|
return fmt.Sprintf("IPC error: %d", s.Code)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *IPCError) ErrorCode() int {
|
|
|
|
return s.Code
|
|
|
|
}
|
|
|
|
|
|
|
|
func ipcGetOperation(socket *bufio.ReadWriter, dev *Device) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
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-06-04 21:48:15 +02:00
|
|
|
device.mutex.Lock()
|
|
|
|
defer device.mutex.Unlock()
|
2017-05-30 22:36:49 +02:00
|
|
|
|
|
|
|
for scanner.Scan() {
|
|
|
|
var key string
|
|
|
|
var value string
|
|
|
|
var peer *Peer
|
|
|
|
|
|
|
|
// Parse line
|
|
|
|
|
|
|
|
line := scanner.Text()
|
|
|
|
if line == "\n" {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
fmt.Println(line)
|
|
|
|
n, err := fmt.Sscanf(line, "%s=%s\n", &key, &value)
|
|
|
|
if n != 2 || err != nil {
|
|
|
|
fmt.Println(err, n)
|
|
|
|
return &IPCError{Code: ipcErrorNoKeyValue}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch key {
|
|
|
|
|
|
|
|
/* Interface configuration */
|
|
|
|
|
|
|
|
case "private_key":
|
|
|
|
if value == "" {
|
2017-06-04 21:48:15 +02:00
|
|
|
device.privateKey = NoisePrivateKey{}
|
2017-05-30 22:36:49 +02:00
|
|
|
} else {
|
2017-06-04 21:48:15 +02:00
|
|
|
err := device.privateKey.FromHex(value)
|
2017-05-30 22:36:49 +02:00
|
|
|
if err != nil {
|
|
|
|
return &IPCError{Code: ipcErrorInvalidPrivateKey}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
case "listen_port":
|
2017-06-04 21:48:15 +02:00
|
|
|
_, err := fmt.Sscanf(value, "%ud", &device.listenPort)
|
2017-05-30 22:36:49 +02:00
|
|
|
if err != nil {
|
|
|
|
return &IPCError{Code: ipcErrorInvalidPort}
|
|
|
|
}
|
|
|
|
|
|
|
|
case "fwmark":
|
|
|
|
panic(nil) // not handled yet
|
|
|
|
|
|
|
|
case "public_key":
|
|
|
|
var pubKey NoisePublicKey
|
|
|
|
err := pubKey.FromHex(value)
|
|
|
|
if err != nil {
|
|
|
|
return &IPCError{Code: ipcErrorInvalidPublicKey}
|
|
|
|
}
|
2017-06-04 21:48:15 +02:00
|
|
|
found, ok := device.peers[pubKey]
|
2017-05-30 22:36:49 +02:00
|
|
|
if ok {
|
|
|
|
peer = found
|
|
|
|
} else {
|
|
|
|
newPeer := &Peer{
|
|
|
|
publicKey: pubKey,
|
|
|
|
}
|
|
|
|
peer = newPeer
|
2017-06-04 21:48:15 +02:00
|
|
|
device.peers[pubKey] = newPeer
|
2017-05-30 22:36:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
case "replace_peers":
|
2017-06-01 21:31:30 +02:00
|
|
|
if key == "true" {
|
2017-06-04 21:48:15 +02:00
|
|
|
device.RemoveAllPeers()
|
|
|
|
} else if key == "false" {
|
|
|
|
} else {
|
|
|
|
return &IPCError{Code: ipcErrorInvalidValue}
|
2017-06-01 21:31:30 +02:00
|
|
|
}
|
2017-05-30 22:36:49 +02:00
|
|
|
|
|
|
|
default:
|
|
|
|
/* Peer configuration */
|
|
|
|
|
|
|
|
if peer == nil {
|
|
|
|
return &IPCError{Code: ipcErrorNoPeer}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch key {
|
|
|
|
|
|
|
|
case "remove":
|
|
|
|
peer.mutex.Lock()
|
2017-06-04 21:48:15 +02:00
|
|
|
device.RemovePeer(peer.publicKey)
|
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-01 21:31:30 +02:00
|
|
|
return peer.presharedKey.FromHex(value)
|
2017-05-30 22:36:49 +02:00
|
|
|
}()
|
2017-06-01 21:31:30 +02:00
|
|
|
if err != nil {
|
|
|
|
return &IPCError{Code: ipcErrorInvalidPublicKey}
|
|
|
|
}
|
2017-05-30 22:36:49 +02:00
|
|
|
|
|
|
|
case "endpoint":
|
2017-06-01 21:31:30 +02:00
|
|
|
ip := net.ParseIP(value)
|
|
|
|
if ip == nil {
|
|
|
|
return &IPCError{Code: ipcErrorInvalidIPAddress}
|
|
|
|
}
|
|
|
|
peer.mutex.Lock()
|
|
|
|
peer.endpoint = ip
|
|
|
|
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 {
|
|
|
|
return &IPCError{Code: ipcErrorInvalidValue}
|
|
|
|
}
|
|
|
|
peer.mutex.Lock()
|
|
|
|
peer.persistentKeepaliveInterval = time.Duration(secs) * time.Second
|
|
|
|
peer.mutex.Unlock()
|
2017-05-30 22:36:49 +02:00
|
|
|
|
|
|
|
case "replace_allowed_ips":
|
2017-06-04 21:48:15 +02:00
|
|
|
if key == "true" {
|
|
|
|
device.routingTable.RemovePeer(peer)
|
|
|
|
} else if key == "false" {
|
|
|
|
} else {
|
|
|
|
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 {
|
|
|
|
return &IPCError{Code: ipcErrorInvalidValue}
|
|
|
|
}
|
|
|
|
ones, _ := network.Mask.Size()
|
|
|
|
device.routingTable.Insert(network.IP, uint(ones), peer)
|
2017-05-30 22:36:49 +02:00
|
|
|
|
|
|
|
/* Invalid key */
|
|
|
|
|
|
|
|
default:
|
|
|
|
return &IPCError{Code: ipcErrorInvalidKey}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func ipcListen(dev *Device, socket io.ReadWriter) error {
|
|
|
|
|
|
|
|
buffered := func(s io.ReadWriter) *bufio.ReadWriter {
|
|
|
|
reader := bufio.NewReader(s)
|
|
|
|
writer := bufio.NewWriter(s)
|
|
|
|
return bufio.NewReadWriter(reader, writer)
|
|
|
|
}(socket)
|
|
|
|
|
|
|
|
for {
|
|
|
|
op, err := buffered.ReadString('\n')
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
log.Println(op)
|
|
|
|
|
|
|
|
switch op {
|
|
|
|
|
|
|
|
case "set=1\n":
|
|
|
|
err := ipcSetOperation(dev, buffered)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Fprintf(buffered, "errno=%d\n", err.ErrorCode())
|
|
|
|
return err
|
|
|
|
} else {
|
|
|
|
fmt.Fprintf(buffered, "errno=0\n")
|
|
|
|
}
|
|
|
|
buffered.Flush()
|
|
|
|
|
|
|
|
case "get=1\n":
|
|
|
|
|
|
|
|
default:
|
|
|
|
return errors.New("handle this please")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|