mirror of
https://github.com/yggdrasil-network/yggdrasil-go.git
synced 2025-04-30 07:05:06 +03:00
Merge branch 'develop' into develop
This commit is contained in:
commit
d66ddf7b96
59 changed files with 2197 additions and 2030 deletions
|
@ -8,10 +8,11 @@ import (
|
|||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"os/signal"
|
||||
"regexp"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
|
@ -27,18 +28,17 @@ import (
|
|||
"github.com/yggdrasil-network/yggdrasil-go/src/admin"
|
||||
"github.com/yggdrasil-network/yggdrasil-go/src/config"
|
||||
"github.com/yggdrasil-network/yggdrasil-go/src/defaults"
|
||||
"github.com/yggdrasil-network/yggdrasil-go/src/ipv6rwc"
|
||||
|
||||
"github.com/yggdrasil-network/yggdrasil-go/src/core"
|
||||
"github.com/yggdrasil-network/yggdrasil-go/src/ipv6rwc"
|
||||
"github.com/yggdrasil-network/yggdrasil-go/src/multicast"
|
||||
"github.com/yggdrasil-network/yggdrasil-go/src/tuntap"
|
||||
"github.com/yggdrasil-network/yggdrasil-go/src/tun"
|
||||
"github.com/yggdrasil-network/yggdrasil-go/src/version"
|
||||
)
|
||||
|
||||
type node struct {
|
||||
core core.Core
|
||||
config *config.NodeConfig
|
||||
tuntap *tuntap.TunAdapter
|
||||
core *core.Core
|
||||
tun *tun.TunAdapter
|
||||
multicast *multicast.Multicast
|
||||
admin *admin.AdminSocket
|
||||
}
|
||||
|
@ -51,10 +51,10 @@ func readConfig(log *log.Logger, useconf bool, useconffile string, normaliseconf
|
|||
var err error
|
||||
if useconffile != "" {
|
||||
// Read the file from the filesystem
|
||||
conf, err = ioutil.ReadFile(useconffile)
|
||||
conf, err = os.ReadFile(useconffile)
|
||||
} else {
|
||||
// Read the file from stdin.
|
||||
conf, err = ioutil.ReadAll(os.Stdin)
|
||||
conf, err = io.ReadAll(os.Stdin)
|
||||
}
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
@ -81,48 +81,6 @@ func readConfig(log *log.Logger, useconf bool, useconffile string, normaliseconf
|
|||
if err := hjson.Unmarshal(conf, &dat); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// Check if we have old field names
|
||||
if _, ok := dat["TunnelRouting"]; ok {
|
||||
log.Warnln("WARNING: Tunnel routing is no longer supported")
|
||||
}
|
||||
if old, ok := dat["SigningPrivateKey"]; ok {
|
||||
log.Warnln("WARNING: The \"SigningPrivateKey\" configuration option has been renamed to \"PrivateKey\"")
|
||||
if _, ok := dat["PrivateKey"]; !ok {
|
||||
if privstr, err := hex.DecodeString(old.(string)); err == nil {
|
||||
priv := ed25519.PrivateKey(privstr)
|
||||
pub := priv.Public().(ed25519.PublicKey)
|
||||
dat["PrivateKey"] = hex.EncodeToString(priv[:])
|
||||
dat["PublicKey"] = hex.EncodeToString(pub[:])
|
||||
} else {
|
||||
log.Warnln("WARNING: The \"SigningPrivateKey\" configuration option contains an invalid value and will be ignored")
|
||||
}
|
||||
}
|
||||
}
|
||||
if oldmc, ok := dat["MulticastInterfaces"]; ok {
|
||||
if oldmcvals, ok := oldmc.([]interface{}); ok {
|
||||
var newmc []config.MulticastInterfaceConfig
|
||||
for _, oldmcval := range oldmcvals {
|
||||
if str, ok := oldmcval.(string); ok {
|
||||
newmc = append(newmc, config.MulticastInterfaceConfig{
|
||||
Regex: str,
|
||||
Beacon: true,
|
||||
Listen: true,
|
||||
})
|
||||
}
|
||||
}
|
||||
if newmc != nil {
|
||||
if oldport, ok := dat["LinkLocalTCPPort"]; ok {
|
||||
// numbers parse to float64 by default
|
||||
if port, ok := oldport.(float64); ok {
|
||||
for idx := range newmc {
|
||||
newmc[idx].Port = uint16(port)
|
||||
}
|
||||
}
|
||||
}
|
||||
dat["MulticastInterfaces"] = newmc
|
||||
}
|
||||
}
|
||||
}
|
||||
// Sanitise the config
|
||||
confJson, err := json.Marshal(dat)
|
||||
if err != nil {
|
||||
|
@ -261,7 +219,7 @@ func run(args yggArgs, ctx context.Context, done chan struct{}) {
|
|||
return
|
||||
case args.autoconf:
|
||||
// Use an autoconf-generated config, this will give us random keys and
|
||||
// port numbers, and will use an automatically selected TUN/TAP interface.
|
||||
// port numbers, and will use an automatically selected TUN interface.
|
||||
cfg = defaults.GenerateConfig()
|
||||
case args.useconffile != "" || args.useconf:
|
||||
// Read the configuration from either stdin or from the filesystem
|
||||
|
@ -327,45 +285,86 @@ func run(args yggArgs, ctx context.Context, done chan struct{}) {
|
|||
fmt.Println(ipnet.String())
|
||||
}
|
||||
return
|
||||
default:
|
||||
}
|
||||
|
||||
// Setup the Yggdrasil node itself. The node{} type includes a Core, so we
|
||||
// don't need to create this manually.
|
||||
n := node{config: cfg}
|
||||
// Now start Yggdrasil - this starts the DHT, router, switch and other core
|
||||
// components needed for Yggdrasil to operate
|
||||
if err = n.core.Start(cfg, logger); err != nil {
|
||||
logger.Errorln("An error occurred during startup")
|
||||
panic(err)
|
||||
n := &node{}
|
||||
|
||||
// Setup the Yggdrasil node itself.
|
||||
{
|
||||
sk, err := hex.DecodeString(cfg.PrivateKey)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
options := []core.SetupOption{}
|
||||
for _, addr := range cfg.Listen {
|
||||
options = append(options, core.ListenAddress(addr))
|
||||
}
|
||||
for _, peer := range cfg.Peers {
|
||||
options = append(options, core.Peer{URI: peer})
|
||||
}
|
||||
for intf, peers := range cfg.InterfacePeers {
|
||||
for _, peer := range peers {
|
||||
options = append(options, core.Peer{URI: peer, SourceInterface: intf})
|
||||
}
|
||||
}
|
||||
for _, allowed := range cfg.AllowedPublicKeys {
|
||||
k, err := hex.DecodeString(allowed)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
options = append(options, core.AllowedPublicKey(k[:]))
|
||||
}
|
||||
if n.core, err = core.New(sk[:], logger, options...); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
// Register the session firewall gatekeeper function
|
||||
// Allocate our modules
|
||||
n.admin = &admin.AdminSocket{}
|
||||
n.multicast = &multicast.Multicast{}
|
||||
n.tuntap = &tuntap.TunAdapter{}
|
||||
// Start the admin socket
|
||||
if err := n.admin.Init(&n.core, cfg, logger, nil); err != nil {
|
||||
logger.Errorln("An error occurred initialising admin socket:", err)
|
||||
} else if err := n.admin.Start(); err != nil {
|
||||
logger.Errorln("An error occurred starting admin socket:", err)
|
||||
|
||||
// Setup the admin socket.
|
||||
{
|
||||
options := []admin.SetupOption{
|
||||
admin.ListenAddress(cfg.AdminListen),
|
||||
}
|
||||
if n.admin, err = admin.New(n.core, logger, options...); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if n.admin != nil {
|
||||
n.admin.SetupAdminHandlers()
|
||||
}
|
||||
}
|
||||
n.admin.SetupAdminHandlers(n.admin)
|
||||
// Start the multicast interface
|
||||
if err := n.multicast.Init(&n.core, cfg, logger, nil); err != nil {
|
||||
logger.Errorln("An error occurred initialising multicast:", err)
|
||||
} else if err := n.multicast.Start(); err != nil {
|
||||
logger.Errorln("An error occurred starting multicast:", err)
|
||||
|
||||
// Setup the multicast module.
|
||||
{
|
||||
options := []multicast.SetupOption{}
|
||||
for _, intf := range cfg.MulticastInterfaces {
|
||||
options = append(options, multicast.MulticastInterface{
|
||||
Regex: regexp.MustCompile(intf.Regex),
|
||||
Beacon: intf.Beacon,
|
||||
Listen: intf.Listen,
|
||||
Port: intf.Port,
|
||||
})
|
||||
}
|
||||
if n.multicast, err = multicast.New(n.core, logger, options...); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if n.admin != nil && n.multicast != nil {
|
||||
n.multicast.SetupAdminHandlers(n.admin)
|
||||
}
|
||||
}
|
||||
n.multicast.SetupAdminHandlers(n.admin)
|
||||
// Start the TUN/TAP interface
|
||||
rwc := ipv6rwc.NewReadWriteCloser(&n.core)
|
||||
if err := n.tuntap.Init(rwc, cfg, logger, nil); err != nil {
|
||||
logger.Errorln("An error occurred initialising TUN/TAP:", err)
|
||||
} else if err := n.tuntap.Start(); err != nil {
|
||||
logger.Errorln("An error occurred starting TUN/TAP:", err)
|
||||
|
||||
// Setup the TUN module.
|
||||
{
|
||||
options := []tun.SetupOption{
|
||||
tun.InterfaceName(cfg.IfName),
|
||||
tun.InterfaceMTU(cfg.IfMTU),
|
||||
}
|
||||
if n.tun, err = tun.New(ipv6rwc.NewReadWriteCloser(n.core), logger, options...); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if n.admin != nil && n.tun != nil {
|
||||
n.tun.SetupAdminHandlers(n.admin)
|
||||
}
|
||||
}
|
||||
n.tuntap.SetupAdminHandlers(n.admin)
|
||||
|
||||
// Make some nice output that tells us what our IPv6 address and subnet are.
|
||||
// This is just logged to stdout for the user.
|
||||
address := n.core.Address()
|
||||
|
@ -384,7 +383,7 @@ func run(args yggArgs, ctx context.Context, done chan struct{}) {
|
|||
func (n *node) shutdown() {
|
||||
_ = n.admin.Stop()
|
||||
_ = n.multicast.Stop()
|
||||
_ = n.tuntap.Stop()
|
||||
_ = n.tun.Stop()
|
||||
n.core.Stop()
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"bytes"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
|
@ -15,9 +14,9 @@ import (
|
|||
)
|
||||
|
||||
type CmdLineEnv struct {
|
||||
args []string
|
||||
endpoint, server string
|
||||
injson, verbose, ver bool
|
||||
args []string
|
||||
endpoint, server string
|
||||
injson, ver bool
|
||||
}
|
||||
|
||||
func newCmdLineEnv() CmdLineEnv {
|
||||
|
@ -47,7 +46,6 @@ func (cmdLineEnv *CmdLineEnv) parseFlagsAndArgs() {
|
|||
|
||||
server := flag.String("endpoint", cmdLineEnv.endpoint, "Admin socket endpoint")
|
||||
injson := flag.Bool("json", false, "Output in JSON format (as opposed to pretty-print)")
|
||||
verbose := flag.Bool("v", false, "Verbose output (includes public keys)")
|
||||
ver := flag.Bool("version", false, "Prints the version of this build")
|
||||
|
||||
flag.Parse()
|
||||
|
@ -55,13 +53,12 @@ func (cmdLineEnv *CmdLineEnv) parseFlagsAndArgs() {
|
|||
cmdLineEnv.args = flag.Args()
|
||||
cmdLineEnv.server = *server
|
||||
cmdLineEnv.injson = *injson
|
||||
cmdLineEnv.verbose = *verbose
|
||||
cmdLineEnv.ver = *ver
|
||||
}
|
||||
|
||||
func (cmdLineEnv *CmdLineEnv) setEndpoint(logger *log.Logger) {
|
||||
if cmdLineEnv.server == cmdLineEnv.endpoint {
|
||||
if config, err := ioutil.ReadFile(defaults.GetDefaults().DefaultConfigFile); err == nil {
|
||||
if config, err := os.ReadFile(defaults.GetDefaults().DefaultConfigFile); err == nil {
|
||||
if bytes.Equal(config[0:2], []byte{0xFF, 0xFE}) ||
|
||||
bytes.Equal(config[0:2], []byte{0xFE, 0xFF}) {
|
||||
utf := unicode.UTF16(unicode.BigEndian, unicode.UseBOM)
|
||||
|
|
|
@ -10,15 +10,17 @@ import (
|
|||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/olekukonko/tablewriter"
|
||||
"github.com/yggdrasil-network/yggdrasil-go/src/admin"
|
||||
"github.com/yggdrasil-network/yggdrasil-go/src/core"
|
||||
"github.com/yggdrasil-network/yggdrasil-go/src/multicast"
|
||||
"github.com/yggdrasil-network/yggdrasil-go/src/tun"
|
||||
"github.com/yggdrasil-network/yggdrasil-go/src/version"
|
||||
)
|
||||
|
||||
type admin_info map[string]interface{}
|
||||
|
||||
func main() {
|
||||
// makes sure we can use defer and still return an error code to the OS
|
||||
os.Exit(run())
|
||||
|
@ -54,103 +56,13 @@ func run() int {
|
|||
|
||||
cmdLineEnv.setEndpoint(logger)
|
||||
|
||||
conn := connect(cmdLineEnv.endpoint, logger)
|
||||
logger.Println("Connected")
|
||||
defer conn.Close()
|
||||
|
||||
decoder := json.NewDecoder(conn)
|
||||
encoder := json.NewEncoder(conn)
|
||||
send := make(admin_info)
|
||||
recv := make(admin_info)
|
||||
|
||||
for c, a := range cmdLineEnv.args {
|
||||
if c == 0 {
|
||||
if strings.HasPrefix(a, "-") {
|
||||
logger.Printf("Ignoring flag %s as it should be specified before other parameters\n", a)
|
||||
continue
|
||||
}
|
||||
logger.Printf("Sending request: %v\n", a)
|
||||
send["request"] = a
|
||||
continue
|
||||
}
|
||||
tokens := strings.Split(a, "=")
|
||||
if len(tokens) == 1 {
|
||||
send[tokens[0]] = true
|
||||
} else if len(tokens) > 2 {
|
||||
send[tokens[0]] = strings.Join(tokens[1:], "=")
|
||||
} else if len(tokens) == 2 {
|
||||
if i, err := strconv.Atoi(tokens[1]); err == nil {
|
||||
logger.Printf("Sending parameter %s: %d\n", tokens[0], i)
|
||||
send[tokens[0]] = i
|
||||
} else {
|
||||
switch strings.ToLower(tokens[1]) {
|
||||
case "true":
|
||||
send[tokens[0]] = true
|
||||
case "false":
|
||||
send[tokens[0]] = false
|
||||
default:
|
||||
send[tokens[0]] = tokens[1]
|
||||
}
|
||||
logger.Printf("Sending parameter %s: %v\n", tokens[0], send[tokens[0]])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := encoder.Encode(&send); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
logger.Printf("Request sent")
|
||||
|
||||
if err := decoder.Decode(&recv); err == nil {
|
||||
logger.Printf("Response received")
|
||||
if recv["status"] == "error" {
|
||||
if err, ok := recv["error"]; ok {
|
||||
fmt.Println("Admin socket returned an error:", err)
|
||||
} else {
|
||||
fmt.Println("Admin socket returned an error but didn't specify any error text")
|
||||
}
|
||||
return 1
|
||||
}
|
||||
if _, ok := recv["request"]; !ok {
|
||||
fmt.Println("Missing request in response (malformed response?)")
|
||||
return 1
|
||||
}
|
||||
if _, ok := recv["response"]; !ok {
|
||||
fmt.Println("Missing response body (malformed response?)")
|
||||
return 1
|
||||
}
|
||||
res := recv["response"].(map[string]interface{})
|
||||
|
||||
if cmdLineEnv.injson {
|
||||
if json, err := json.MarshalIndent(res, "", " "); err == nil {
|
||||
fmt.Println(string(json))
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
handleAll(recv, cmdLineEnv.verbose)
|
||||
} else {
|
||||
logger.Println("Error receiving response:", err)
|
||||
}
|
||||
|
||||
if v, ok := recv["status"]; ok && v != "success" {
|
||||
return 1
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func connect(endpoint string, logger *log.Logger) net.Conn {
|
||||
var conn net.Conn
|
||||
|
||||
u, err := url.Parse(endpoint)
|
||||
|
||||
u, err := url.Parse(cmdLineEnv.endpoint)
|
||||
if err == nil {
|
||||
switch strings.ToLower(u.Scheme) {
|
||||
case "unix":
|
||||
logger.Println("Connecting to UNIX socket", endpoint[7:])
|
||||
conn, err = net.Dial("unix", endpoint[7:])
|
||||
logger.Println("Connecting to UNIX socket", cmdLineEnv.endpoint[7:])
|
||||
conn, err = net.Dial("unix", cmdLineEnv.endpoint[7:])
|
||||
case "tcp":
|
||||
logger.Println("Connecting to TCP socket", u.Host)
|
||||
conn, err = net.Dial("tcp", u.Host)
|
||||
|
@ -160,298 +72,208 @@ func connect(endpoint string, logger *log.Logger) net.Conn {
|
|||
}
|
||||
} else {
|
||||
logger.Println("Connecting to TCP socket", u.Host)
|
||||
conn, err = net.Dial("tcp", endpoint)
|
||||
conn, err = net.Dial("tcp", cmdLineEnv.endpoint)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return conn
|
||||
}
|
||||
logger.Println("Connected")
|
||||
defer conn.Close()
|
||||
|
||||
func handleAll(recv map[string]interface{}, verbose bool) {
|
||||
req := recv["request"].(map[string]interface{})
|
||||
res := recv["response"].(map[string]interface{})
|
||||
|
||||
switch strings.ToLower(req["request"].(string)) {
|
||||
case "dot":
|
||||
handleDot(res)
|
||||
case "list", "getpeers", "getswitchpeers", "getdht", "getsessions", "dhtping":
|
||||
handleVariousInfo(res, verbose)
|
||||
case "gettuntap", "settuntap":
|
||||
handleGetAndSetTunTap(res)
|
||||
case "getself":
|
||||
handleGetSelf(res, verbose)
|
||||
case "getswitchqueues":
|
||||
handleGetSwitchQueues(res)
|
||||
case "addpeer", "removepeer", "addallowedencryptionpublickey", "removeallowedencryptionpublickey", "addsourcesubnet", "addroute", "removesourcesubnet", "removeroute":
|
||||
handleAddsAndRemoves(res)
|
||||
case "getallowedencryptionpublickeys":
|
||||
handleGetAllowedEncryptionPublicKeys(res)
|
||||
case "getmulticastinterfaces":
|
||||
handleGetMulticastInterfaces(res)
|
||||
case "getsourcesubnets":
|
||||
handleGetSourceSubnets(res)
|
||||
case "getroutes":
|
||||
handleGetRoutes(res)
|
||||
case "settunnelrouting":
|
||||
fallthrough
|
||||
case "gettunnelrouting":
|
||||
handleGetTunnelRouting(res)
|
||||
default:
|
||||
if json, err := json.MarshalIndent(recv["response"], "", " "); err == nil {
|
||||
decoder := json.NewDecoder(conn)
|
||||
encoder := json.NewEncoder(conn)
|
||||
send := &admin.AdminSocketRequest{}
|
||||
recv := &admin.AdminSocketResponse{}
|
||||
args := map[string]string{}
|
||||
for c, a := range cmdLineEnv.args {
|
||||
if c == 0 {
|
||||
if strings.HasPrefix(a, "-") {
|
||||
logger.Printf("Ignoring flag %s as it should be specified before other parameters\n", a)
|
||||
continue
|
||||
}
|
||||
logger.Printf("Sending request: %v\n", a)
|
||||
send.Name = a
|
||||
continue
|
||||
}
|
||||
tokens := strings.SplitN(a, "=", 2)
|
||||
switch {
|
||||
case len(tokens) == 1:
|
||||
logger.Println("Ignoring invalid argument:", a)
|
||||
default:
|
||||
args[tokens[0]] = tokens[1]
|
||||
}
|
||||
}
|
||||
if send.Arguments, err = json.Marshal(args); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := encoder.Encode(&send); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
logger.Printf("Request sent")
|
||||
if err := decoder.Decode(&recv); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if recv.Status == "error" {
|
||||
if err := recv.Error; err != "" {
|
||||
fmt.Println("Admin socket returned an error:", err)
|
||||
} else {
|
||||
fmt.Println("Admin socket returned an error but didn't specify any error text")
|
||||
}
|
||||
return 1
|
||||
}
|
||||
if cmdLineEnv.injson {
|
||||
if json, err := json.MarshalIndent(recv.Response, "", " "); err == nil {
|
||||
fmt.Println(string(json))
|
||||
}
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
func handleDot(res map[string]interface{}) {
|
||||
fmt.Println(res["dot"])
|
||||
}
|
||||
table := tablewriter.NewWriter(os.Stdout)
|
||||
table.SetAlignment(tablewriter.ALIGN_LEFT)
|
||||
table.SetAutoFormatHeaders(false)
|
||||
table.SetCenterSeparator("")
|
||||
table.SetColumnSeparator("")
|
||||
table.SetRowSeparator("")
|
||||
table.SetHeaderLine(false)
|
||||
table.SetBorder(false)
|
||||
table.SetTablePadding("\t") // pad with tabs
|
||||
table.SetNoWhiteSpace(true)
|
||||
table.SetAutoWrapText(false)
|
||||
|
||||
func handleVariousInfo(res map[string]interface{}, verbose bool) {
|
||||
maxWidths := make(map[string]int)
|
||||
var keyOrder []string
|
||||
keysOrdered := false
|
||||
|
||||
for _, tlv := range res {
|
||||
for slk, slv := range tlv.(map[string]interface{}) {
|
||||
if !keysOrdered {
|
||||
for k := range slv.(map[string]interface{}) {
|
||||
if !verbose {
|
||||
if k == "box_pub_key" || k == "box_sig_key" || k == "nodeinfo" || k == "was_mtu_fixed" {
|
||||
continue
|
||||
}
|
||||
}
|
||||
keyOrder = append(keyOrder, fmt.Sprint(k))
|
||||
}
|
||||
sort.Strings(keyOrder)
|
||||
keysOrdered = true
|
||||
}
|
||||
for k, v := range slv.(map[string]interface{}) {
|
||||
if len(fmt.Sprint(slk)) > maxWidths["key"] {
|
||||
maxWidths["key"] = len(fmt.Sprint(slk))
|
||||
}
|
||||
if len(fmt.Sprint(v)) > maxWidths[k] {
|
||||
maxWidths[k] = len(fmt.Sprint(v))
|
||||
if maxWidths[k] < len(k) {
|
||||
maxWidths[k] = len(k)
|
||||
}
|
||||
}
|
||||
switch strings.ToLower(send.Name) {
|
||||
case "list":
|
||||
var resp admin.ListResponse
|
||||
if err := json.Unmarshal(recv.Response, &resp); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
table.SetHeader([]string{"Command", "Arguments", "Description"})
|
||||
for _, entry := range resp.List {
|
||||
for i := range entry.Fields {
|
||||
entry.Fields[i] = entry.Fields[i] + "=..."
|
||||
}
|
||||
table.Append([]string{entry.Command, strings.Join(entry.Fields, ", "), entry.Description})
|
||||
}
|
||||
table.Render()
|
||||
|
||||
case "getself":
|
||||
var resp admin.GetSelfResponse
|
||||
if err := json.Unmarshal(recv.Response, &resp); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
table.Append([]string{"Build name:", resp.BuildName})
|
||||
table.Append([]string{"Build version:", resp.BuildVersion})
|
||||
table.Append([]string{"IPv6 address:", resp.IPAddress})
|
||||
table.Append([]string{"IPv6 subnet:", resp.Subnet})
|
||||
table.Append([]string{"Coordinates:", fmt.Sprintf("%v", resp.Coords)})
|
||||
table.Append([]string{"Public key:", resp.PublicKey})
|
||||
table.Render()
|
||||
|
||||
case "getpeers":
|
||||
var resp admin.GetPeersResponse
|
||||
if err := json.Unmarshal(recv.Response, &resp); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
table.SetHeader([]string{"Port", "Public Key", "IP Address", "Uptime", "RX", "TX", "URI"})
|
||||
for _, peer := range resp.Peers {
|
||||
table.Append([]string{
|
||||
fmt.Sprintf("%d", peer.Port),
|
||||
peer.PublicKey,
|
||||
peer.IPAddress,
|
||||
(time.Duration(peer.Uptime) * time.Second).String(),
|
||||
peer.RXBytes.String(),
|
||||
peer.TXBytes.String(),
|
||||
peer.Remote,
|
||||
})
|
||||
}
|
||||
table.Render()
|
||||
|
||||
case "getdht":
|
||||
var resp admin.GetDHTResponse
|
||||
if err := json.Unmarshal(recv.Response, &resp); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
table.SetHeader([]string{"Public Key", "IP Address", "Port", "Rest"})
|
||||
for _, dht := range resp.DHT {
|
||||
table.Append([]string{
|
||||
dht.PublicKey,
|
||||
dht.IPAddress,
|
||||
fmt.Sprintf("%d", dht.Port),
|
||||
fmt.Sprintf("%d", dht.Rest),
|
||||
})
|
||||
}
|
||||
table.Render()
|
||||
|
||||
case "getpaths":
|
||||
var resp admin.GetPathsResponse
|
||||
if err := json.Unmarshal(recv.Response, &resp); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
table.SetHeader([]string{"Public Key", "IP Address", "Path"})
|
||||
for _, p := range resp.Paths {
|
||||
table.Append([]string{
|
||||
p.PublicKey,
|
||||
p.IPAddress,
|
||||
fmt.Sprintf("%v", p.Path),
|
||||
})
|
||||
}
|
||||
table.Render()
|
||||
|
||||
case "getsessions":
|
||||
var resp admin.GetSessionsResponse
|
||||
if err := json.Unmarshal(recv.Response, &resp); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
table.SetHeader([]string{"Public Key", "IP Address", "Uptime", "RX", "TX"})
|
||||
for _, p := range resp.Sessions {
|
||||
table.Append([]string{
|
||||
p.PublicKey,
|
||||
p.IPAddress,
|
||||
(time.Duration(p.Uptime) * time.Second).String(),
|
||||
p.RXBytes.String(),
|
||||
p.TXBytes.String(),
|
||||
})
|
||||
}
|
||||
table.Render()
|
||||
|
||||
case "getnodeinfo":
|
||||
var resp core.GetNodeInfoResponse
|
||||
if err := json.Unmarshal(recv.Response, &resp); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for _, v := range resp {
|
||||
fmt.Println(string(v))
|
||||
break
|
||||
}
|
||||
|
||||
if len(keyOrder) > 0 {
|
||||
fmt.Printf("%-"+fmt.Sprint(maxWidths["key"])+"s ", "")
|
||||
for _, v := range keyOrder {
|
||||
fmt.Printf("%-"+fmt.Sprint(maxWidths[v])+"s ", v)
|
||||
}
|
||||
fmt.Println()
|
||||
case "getmulticastinterfaces":
|
||||
var resp multicast.GetMulticastInterfacesResponse
|
||||
if err := json.Unmarshal(recv.Response, &resp); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
table.SetHeader([]string{"Interface"})
|
||||
for _, p := range resp.Interfaces {
|
||||
table.Append([]string{p})
|
||||
}
|
||||
table.Render()
|
||||
|
||||
for slk, slv := range tlv.(map[string]interface{}) {
|
||||
fmt.Printf("%-"+fmt.Sprint(maxWidths["key"])+"s ", slk)
|
||||
for _, k := range keyOrder {
|
||||
preformatted := slv.(map[string]interface{})[k]
|
||||
var formatted string
|
||||
switch k {
|
||||
case "bytes_sent", "bytes_recvd":
|
||||
formatted = fmt.Sprintf("%d", uint(preformatted.(float64)))
|
||||
case "uptime", "last_seen":
|
||||
seconds := uint(preformatted.(float64)) % 60
|
||||
minutes := uint(preformatted.(float64)/60) % 60
|
||||
hours := uint(preformatted.(float64) / 60 / 60)
|
||||
formatted = fmt.Sprintf("%02d:%02d:%02d", hours, minutes, seconds)
|
||||
default:
|
||||
formatted = fmt.Sprint(preformatted)
|
||||
}
|
||||
fmt.Printf("%-"+fmt.Sprint(maxWidths[k])+"s ", formatted)
|
||||
}
|
||||
fmt.Println()
|
||||
case "gettun":
|
||||
var resp tun.GetTUNResponse
|
||||
if err := json.Unmarshal(recv.Response, &resp); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
table.Append([]string{"TUN enabled:", fmt.Sprintf("%#v", resp.Enabled)})
|
||||
if resp.Enabled {
|
||||
table.Append([]string{"Interface name:", resp.Name})
|
||||
table.Append([]string{"Interface MTU:", fmt.Sprintf("%d", resp.MTU)})
|
||||
}
|
||||
table.Render()
|
||||
|
||||
case "addpeer", "removepeer":
|
||||
|
||||
default:
|
||||
fmt.Println(string(recv.Response))
|
||||
}
|
||||
}
|
||||
|
||||
func handleGetAndSetTunTap(res map[string]interface{}) {
|
||||
for k, v := range res {
|
||||
fmt.Println("Interface name:", k)
|
||||
if mtu, ok := v.(map[string]interface{})["mtu"].(float64); ok {
|
||||
fmt.Println("Interface MTU:", mtu)
|
||||
}
|
||||
if tap_mode, ok := v.(map[string]interface{})["tap_mode"].(bool); ok {
|
||||
fmt.Println("TAP mode:", tap_mode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func handleGetSelf(res map[string]interface{}, verbose bool) {
|
||||
for k, v := range res["self"].(map[string]interface{}) {
|
||||
if buildname, ok := v.(map[string]interface{})["build_name"].(string); ok && buildname != "unknown" {
|
||||
fmt.Println("Build name:", buildname)
|
||||
}
|
||||
if buildversion, ok := v.(map[string]interface{})["build_version"].(string); ok && buildversion != "unknown" {
|
||||
fmt.Println("Build version:", buildversion)
|
||||
}
|
||||
fmt.Println("IPv6 address:", k)
|
||||
if subnet, ok := v.(map[string]interface{})["subnet"].(string); ok {
|
||||
fmt.Println("IPv6 subnet:", subnet)
|
||||
}
|
||||
if boxSigKey, ok := v.(map[string]interface{})["key"].(string); ok {
|
||||
fmt.Println("Public key:", boxSigKey)
|
||||
}
|
||||
if coords, ok := v.(map[string]interface{})["coords"].(string); ok {
|
||||
fmt.Println("Coords:", coords)
|
||||
}
|
||||
if verbose {
|
||||
if nodeID, ok := v.(map[string]interface{})["node_id"].(string); ok {
|
||||
fmt.Println("Node ID:", nodeID)
|
||||
}
|
||||
if boxPubKey, ok := v.(map[string]interface{})["box_pub_key"].(string); ok {
|
||||
fmt.Println("Public encryption key:", boxPubKey)
|
||||
}
|
||||
if boxSigKey, ok := v.(map[string]interface{})["box_sig_key"].(string); ok {
|
||||
fmt.Println("Public signing key:", boxSigKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func handleGetSwitchQueues(res map[string]interface{}) {
|
||||
maximumqueuesize := float64(4194304)
|
||||
portqueues := make(map[float64]float64)
|
||||
portqueuesize := make(map[float64]float64)
|
||||
portqueuepackets := make(map[float64]float64)
|
||||
v := res["switchqueues"].(map[string]interface{})
|
||||
if queuecount, ok := v["queues_count"].(float64); ok {
|
||||
fmt.Printf("Active queue count: %d queues\n", uint(queuecount))
|
||||
}
|
||||
if queuesize, ok := v["queues_size"].(float64); ok {
|
||||
fmt.Printf("Active queue size: %d bytes\n", uint(queuesize))
|
||||
}
|
||||
if highestqueuecount, ok := v["highest_queues_count"].(float64); ok {
|
||||
fmt.Printf("Highest queue count: %d queues\n", uint(highestqueuecount))
|
||||
}
|
||||
if highestqueuesize, ok := v["highest_queues_size"].(float64); ok {
|
||||
fmt.Printf("Highest queue size: %d bytes\n", uint(highestqueuesize))
|
||||
}
|
||||
if m, ok := v["maximum_queues_size"].(float64); ok {
|
||||
maximumqueuesize = m
|
||||
fmt.Printf("Maximum queue size: %d bytes\n", uint(maximumqueuesize))
|
||||
}
|
||||
if queues, ok := v["queues"].([]interface{}); ok {
|
||||
if len(queues) != 0 {
|
||||
fmt.Println("Active queues:")
|
||||
for _, v := range queues {
|
||||
queueport := v.(map[string]interface{})["queue_port"].(float64)
|
||||
queuesize := v.(map[string]interface{})["queue_size"].(float64)
|
||||
queuepackets := v.(map[string]interface{})["queue_packets"].(float64)
|
||||
queueid := v.(map[string]interface{})["queue_id"].(string)
|
||||
portqueues[queueport]++
|
||||
portqueuesize[queueport] += queuesize
|
||||
portqueuepackets[queueport] += queuepackets
|
||||
queuesizepercent := (100 / maximumqueuesize) * queuesize
|
||||
fmt.Printf("- Switch port %d, Stream ID: %v, size: %d bytes (%d%% full), %d packets\n",
|
||||
uint(queueport), []byte(queueid), uint(queuesize),
|
||||
uint(queuesizepercent), uint(queuepackets))
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(portqueuesize) > 0 && len(portqueuepackets) > 0 {
|
||||
fmt.Println("Aggregated statistics by switchport:")
|
||||
for k, v := range portqueuesize {
|
||||
queuesizepercent := (100 / (portqueues[k] * maximumqueuesize)) * v
|
||||
fmt.Printf("- Switch port %d, size: %d bytes (%d%% full), %d packets\n",
|
||||
uint(k), uint(v), uint(queuesizepercent), uint(portqueuepackets[k]))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func handleAddsAndRemoves(res map[string]interface{}) {
|
||||
if _, ok := res["added"]; ok {
|
||||
for _, v := range res["added"].([]interface{}) {
|
||||
fmt.Println("Added:", fmt.Sprint(v))
|
||||
}
|
||||
}
|
||||
if _, ok := res["not_added"]; ok {
|
||||
for _, v := range res["not_added"].([]interface{}) {
|
||||
fmt.Println("Not added:", fmt.Sprint(v))
|
||||
}
|
||||
}
|
||||
if _, ok := res["removed"]; ok {
|
||||
for _, v := range res["removed"].([]interface{}) {
|
||||
fmt.Println("Removed:", fmt.Sprint(v))
|
||||
}
|
||||
}
|
||||
if _, ok := res["not_removed"]; ok {
|
||||
for _, v := range res["not_removed"].([]interface{}) {
|
||||
fmt.Println("Not removed:", fmt.Sprint(v))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func handleGetAllowedEncryptionPublicKeys(res map[string]interface{}) {
|
||||
if _, ok := res["allowed_box_pubs"]; !ok {
|
||||
fmt.Println("All connections are allowed")
|
||||
} else if res["allowed_box_pubs"] == nil {
|
||||
fmt.Println("All connections are allowed")
|
||||
} else {
|
||||
fmt.Println("Connections are allowed only from the following public box keys:")
|
||||
for _, v := range res["allowed_box_pubs"].([]interface{}) {
|
||||
fmt.Println("-", v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func handleGetMulticastInterfaces(res map[string]interface{}) {
|
||||
if _, ok := res["multicast_interfaces"]; !ok {
|
||||
fmt.Println("No multicast interfaces found")
|
||||
} else if res["multicast_interfaces"] == nil {
|
||||
fmt.Println("No multicast interfaces found")
|
||||
} else {
|
||||
fmt.Println("Multicast peer discovery is active on:")
|
||||
for _, v := range res["multicast_interfaces"].([]interface{}) {
|
||||
fmt.Println("-", v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func handleGetSourceSubnets(res map[string]interface{}) {
|
||||
if _, ok := res["source_subnets"]; !ok {
|
||||
fmt.Println("No source subnets found")
|
||||
} else if res["source_subnets"] == nil {
|
||||
fmt.Println("No source subnets found")
|
||||
} else {
|
||||
fmt.Println("Source subnets:")
|
||||
for _, v := range res["source_subnets"].([]interface{}) {
|
||||
fmt.Println("-", v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func handleGetRoutes(res map[string]interface{}) {
|
||||
if routes, ok := res["routes"].(map[string]interface{}); !ok {
|
||||
fmt.Println("No routes found")
|
||||
} else {
|
||||
if res["routes"] == nil || len(routes) == 0 {
|
||||
fmt.Println("No routes found")
|
||||
} else {
|
||||
fmt.Println("Routes:")
|
||||
for k, v := range routes {
|
||||
if pv, ok := v.(string); ok {
|
||||
fmt.Println("-", k, " via ", pv)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func handleGetTunnelRouting(res map[string]interface{}) {
|
||||
if enabled, ok := res["enabled"].(bool); !ok {
|
||||
fmt.Println("Tunnel routing is disabled")
|
||||
} else if !enabled {
|
||||
fmt.Println("Tunnel routing is disabled")
|
||||
} else {
|
||||
fmt.Println("Tunnel routing is enabled")
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue