107 lines
2.3 KiB
Go
107 lines
2.3 KiB
Go
|
package wguser
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"encoding/hex"
|
||
|
"fmt"
|
||
|
"io"
|
||
|
"os"
|
||
|
"strings"
|
||
|
|
||
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||
|
)
|
||
|
|
||
|
// configureDevice configures a device specified by its path.
|
||
|
func (c *Client) configureDevice(device string, cfg wgtypes.Config) error {
|
||
|
conn, err := c.dial(device)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
defer conn.Close()
|
||
|
|
||
|
// Start with set command.
|
||
|
var buf bytes.Buffer
|
||
|
buf.WriteString("set=1\n")
|
||
|
|
||
|
// Add any necessary configuration from cfg, then finish with an empty line.
|
||
|
writeConfig(&buf, cfg)
|
||
|
buf.WriteString("\n")
|
||
|
|
||
|
// Apply configuration for the device and then check the error number.
|
||
|
if _, err := io.Copy(conn, &buf); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
res := make([]byte, 32)
|
||
|
n, err := conn.Read(res)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
// errno=0 indicates success, anything else returns an error number that
|
||
|
// matches definitions from errno.h.
|
||
|
str := strings.TrimSpace(string(res[:n]))
|
||
|
if str != "errno=0" {
|
||
|
// TODO(mdlayher): return actual errno on Linux?
|
||
|
return os.NewSyscallError("read", fmt.Errorf("wguser: %s", str))
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// writeConfig writes textual configuration to w as specified by cfg.
|
||
|
func writeConfig(w io.Writer, cfg wgtypes.Config) {
|
||
|
if cfg.PrivateKey != nil {
|
||
|
fmt.Fprintf(w, "private_key=%s\n", hexKey(*cfg.PrivateKey))
|
||
|
}
|
||
|
|
||
|
if cfg.ListenPort != nil {
|
||
|
fmt.Fprintf(w, "listen_port=%d\n", *cfg.ListenPort)
|
||
|
}
|
||
|
|
||
|
if cfg.FirewallMark != nil {
|
||
|
fmt.Fprintf(w, "fwmark=%d\n", *cfg.FirewallMark)
|
||
|
}
|
||
|
|
||
|
if cfg.ReplacePeers {
|
||
|
fmt.Fprintln(w, "replace_peers=true")
|
||
|
}
|
||
|
|
||
|
for _, p := range cfg.Peers {
|
||
|
fmt.Fprintf(w, "public_key=%s\n", hexKey(p.PublicKey))
|
||
|
|
||
|
if p.Remove {
|
||
|
fmt.Fprintln(w, "remove=true")
|
||
|
}
|
||
|
|
||
|
if p.UpdateOnly {
|
||
|
fmt.Fprintln(w, "update_only=true")
|
||
|
}
|
||
|
|
||
|
if p.PresharedKey != nil {
|
||
|
fmt.Fprintf(w, "preshared_key=%s\n", hexKey(*p.PresharedKey))
|
||
|
}
|
||
|
|
||
|
if p.Endpoint != nil {
|
||
|
fmt.Fprintf(w, "endpoint=%s\n", p.Endpoint.String())
|
||
|
}
|
||
|
|
||
|
if p.PersistentKeepaliveInterval != nil {
|
||
|
fmt.Fprintf(w, "persistent_keepalive_interval=%d\n", int(p.PersistentKeepaliveInterval.Seconds()))
|
||
|
}
|
||
|
|
||
|
if p.ReplaceAllowedIPs {
|
||
|
fmt.Fprintln(w, "replace_allowed_ips=true")
|
||
|
}
|
||
|
|
||
|
for _, ip := range p.AllowedIPs {
|
||
|
fmt.Fprintf(w, "allowed_ip=%s\n", ip.String())
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// hexKey encodes a wgtypes.Key into a hexadecimal string.
|
||
|
func hexKey(k wgtypes.Key) string {
|
||
|
return hex.EncodeToString(k[:])
|
||
|
}
|