2018-05-20 22:32:17 +00:00
|
|
|
package main
|
|
|
|
|
2018-12-08 01:56:04 +00:00
|
|
|
import (
|
2018-12-10 10:54:41 +00:00
|
|
|
"bytes"
|
2018-12-08 01:56:04 +00:00
|
|
|
"encoding/json"
|
|
|
|
"errors"
|
|
|
|
"flag"
|
|
|
|
"fmt"
|
2018-12-10 10:54:41 +00:00
|
|
|
"log"
|
2018-12-08 01:56:04 +00:00
|
|
|
"net"
|
|
|
|
"net/url"
|
|
|
|
"os"
|
|
|
|
"strings"
|
2022-09-03 09:50:43 +00:00
|
|
|
"time"
|
2018-05-20 22:32:17 +00:00
|
|
|
|
2022-09-03 09:50:43 +00:00
|
|
|
"github.com/olekukonko/tablewriter"
|
|
|
|
"github.com/yggdrasil-network/yggdrasil-go/src/admin"
|
|
|
|
"github.com/yggdrasil-network/yggdrasil-go/src/core"
|
2022-09-24 11:22:38 +00:00
|
|
|
"github.com/yggdrasil-network/yggdrasil-go/src/multicast"
|
2022-09-24 13:41:47 +00:00
|
|
|
"github.com/yggdrasil-network/yggdrasil-go/src/tun"
|
2019-08-10 21:31:22 +00:00
|
|
|
"github.com/yggdrasil-network/yggdrasil-go/src/version"
|
2018-12-08 01:56:04 +00:00
|
|
|
)
|
2018-07-07 11:08:52 +00:00
|
|
|
|
2018-05-20 22:32:17 +00:00
|
|
|
func main() {
|
2019-12-25 23:45:24 +00:00
|
|
|
// makes sure we can use defer and still return an error code to the OS
|
|
|
|
os.Exit(run())
|
|
|
|
}
|
|
|
|
|
|
|
|
func run() int {
|
2018-12-10 10:54:41 +00:00
|
|
|
logbuffer := &bytes.Buffer{}
|
|
|
|
logger := log.New(logbuffer, "", log.Flags())
|
2021-08-02 21:47:38 +00:00
|
|
|
|
2019-12-25 23:45:24 +00:00
|
|
|
defer func() int {
|
2018-12-10 11:29:42 +00:00
|
|
|
if r := recover(); r != nil {
|
|
|
|
logger.Println("Fatal error:", r)
|
|
|
|
fmt.Print(logbuffer)
|
2019-12-25 23:45:24 +00:00
|
|
|
return 1
|
2018-12-10 11:29:42 +00:00
|
|
|
}
|
2019-12-25 23:45:24 +00:00
|
|
|
return 0
|
2018-12-10 11:29:42 +00:00
|
|
|
}()
|
2018-12-10 10:54:41 +00:00
|
|
|
|
2021-08-02 21:47:38 +00:00
|
|
|
cmdLineEnv := newCmdLineEnv()
|
|
|
|
cmdLineEnv.parseFlagsAndArgs()
|
|
|
|
|
|
|
|
if cmdLineEnv.ver {
|
2019-08-14 19:09:02 +00:00
|
|
|
fmt.Println("Build name:", version.BuildName())
|
|
|
|
fmt.Println("Build version:", version.BuildVersion())
|
|
|
|
fmt.Println("To get the version number of the running Yggdrasil node, run", os.Args[0], "getSelf")
|
2019-12-25 23:45:24 +00:00
|
|
|
return 0
|
2019-08-10 21:31:22 +00:00
|
|
|
}
|
|
|
|
|
2021-08-02 21:47:38 +00:00
|
|
|
if len(cmdLineEnv.args) == 0 {
|
2018-12-09 13:33:18 +00:00
|
|
|
flag.Usage()
|
2019-12-25 23:45:24 +00:00
|
|
|
return 0
|
2018-05-21 06:28:03 +00:00
|
|
|
}
|
2018-05-20 22:46:02 +00:00
|
|
|
|
2021-08-02 21:47:38 +00:00
|
|
|
cmdLineEnv.setEndpoint(logger)
|
2018-12-10 11:09:10 +00:00
|
|
|
|
2021-08-02 21:47:38 +00:00
|
|
|
var conn net.Conn
|
2022-09-03 09:50:43 +00:00
|
|
|
u, err := url.Parse(cmdLineEnv.endpoint)
|
2021-08-02 21:47:38 +00:00
|
|
|
if err == nil {
|
|
|
|
switch strings.ToLower(u.Scheme) {
|
|
|
|
case "unix":
|
2022-09-03 09:50:43 +00:00
|
|
|
logger.Println("Connecting to UNIX socket", cmdLineEnv.endpoint[7:])
|
|
|
|
conn, err = net.Dial("unix", cmdLineEnv.endpoint[7:])
|
2021-08-02 21:47:38 +00:00
|
|
|
case "tcp":
|
|
|
|
logger.Println("Connecting to TCP socket", u.Host)
|
|
|
|
conn, err = net.Dial("tcp", u.Host)
|
|
|
|
default:
|
|
|
|
logger.Println("Unknown protocol or malformed address - check your endpoint")
|
|
|
|
err = errors.New("protocol not supported")
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
logger.Println("Connecting to TCP socket", u.Host)
|
2022-09-03 09:50:43 +00:00
|
|
|
conn, err = net.Dial("tcp", cmdLineEnv.endpoint)
|
2021-08-02 21:47:38 +00:00
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
2022-09-03 09:50:43 +00:00
|
|
|
logger.Println("Connected")
|
|
|
|
defer conn.Close()
|
2021-08-02 21:47:38 +00:00
|
|
|
|
2022-09-03 09:50:43 +00:00
|
|
|
decoder := json.NewDecoder(conn)
|
|
|
|
encoder := json.NewEncoder(conn)
|
|
|
|
send := &admin.AdminSocketRequest{}
|
|
|
|
recv := &admin.AdminSocketResponse{}
|
2022-09-24 20:28:09 +00:00
|
|
|
args := map[string]string{}
|
2022-09-03 09:50:43 +00:00
|
|
|
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
|
2018-05-21 13:25:11 +00:00
|
|
|
}
|
2022-09-03 09:50:43 +00:00
|
|
|
logger.Printf("Sending request: %v\n", a)
|
|
|
|
send.Name = a
|
|
|
|
continue
|
2021-08-02 21:47:38 +00:00
|
|
|
}
|
2022-09-24 20:28:09 +00:00
|
|
|
tokens := strings.SplitN(a, "=", 2)
|
2022-09-03 09:50:43 +00:00
|
|
|
switch {
|
|
|
|
case len(tokens) == 1:
|
2022-09-24 20:28:09 +00:00
|
|
|
logger.Println("Ignoring invalid argument:", a)
|
2022-09-03 09:50:43 +00:00
|
|
|
default:
|
2022-09-24 20:28:09 +00:00
|
|
|
args[tokens[0]] = tokens[1]
|
2021-08-02 21:47:38 +00:00
|
|
|
}
|
|
|
|
}
|
2022-09-24 20:28:09 +00:00
|
|
|
if send.Arguments, err = json.Marshal(args); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2022-09-03 09:50:43 +00:00
|
|
|
if err := encoder.Encode(&send); err != nil {
|
|
|
|
panic(err)
|
2021-08-02 21:47:38 +00:00
|
|
|
}
|
2022-09-03 09:50:43 +00:00
|
|
|
logger.Printf("Request sent")
|
|
|
|
if err := decoder.Decode(&recv); err != nil {
|
|
|
|
panic(err)
|
2021-08-02 21:47:38 +00:00
|
|
|
}
|
2022-09-03 09:50:43 +00:00
|
|
|
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")
|
2021-08-02 21:47:38 +00:00
|
|
|
}
|
2022-09-03 09:50:43 +00:00
|
|
|
return 1
|
2021-08-02 21:47:38 +00:00
|
|
|
}
|
2022-09-03 09:50:43 +00:00
|
|
|
if cmdLineEnv.injson {
|
|
|
|
if json, err := json.MarshalIndent(recv.Response, "", " "); err == nil {
|
|
|
|
fmt.Println(string(json))
|
2021-08-02 21:47:38 +00:00
|
|
|
}
|
2022-09-03 09:50:43 +00:00
|
|
|
return 0
|
2021-08-02 21:47:38 +00:00
|
|
|
}
|
|
|
|
|
2022-09-03 09:50:43 +00:00
|
|
|
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)
|
2022-09-24 11:22:38 +00:00
|
|
|
table.SetAutoWrapText(false)
|
2021-08-02 21:47:38 +00:00
|
|
|
|
2022-09-24 20:28:09 +00:00
|
|
|
switch strings.ToLower(send.Name) {
|
2022-09-03 09:50:43 +00:00
|
|
|
case "list":
|
|
|
|
var resp admin.ListResponse
|
|
|
|
if err := json.Unmarshal(recv.Response, &resp); err != nil {
|
|
|
|
panic(err)
|
2021-08-02 21:47:38 +00:00
|
|
|
}
|
2022-09-24 11:22:38 +00:00
|
|
|
table.SetHeader([]string{"Command", "Arguments", "Description"})
|
2022-09-03 09:50:43 +00:00
|
|
|
for _, entry := range resp.List {
|
2022-09-24 11:22:38 +00:00
|
|
|
for i := range entry.Fields {
|
|
|
|
entry.Fields[i] = entry.Fields[i] + "=..."
|
|
|
|
}
|
|
|
|
table.Append([]string{entry.Command, strings.Join(entry.Fields, ", "), entry.Description})
|
2021-08-02 21:47:38 +00:00
|
|
|
}
|
2022-09-03 09:50:43 +00:00
|
|
|
table.Render()
|
2021-08-02 21:47:38 +00:00
|
|
|
|
2022-09-03 09:50:43 +00:00
|
|
|
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)
|
|
|
|
}
|
2022-10-26 17:25:48 +00:00
|
|
|
table.SetHeader([]string{"Port", "Public Key", "IP Address", "Uptime", "RX", "TX", "Pr", "URI"})
|
2022-09-03 09:50:43 +00:00
|
|
|
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(),
|
2022-10-26 17:25:48 +00:00
|
|
|
fmt.Sprintf("%d", peer.Priority),
|
2022-10-02 12:15:11 +00:00
|
|
|
peer.Remote,
|
2022-09-03 09:50:43 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
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)
|
|
|
|
}
|
2022-09-03 15:55:57 +00:00
|
|
|
table.SetHeader([]string{"Public Key", "IP Address", "Uptime", "RX", "TX"})
|
2022-09-03 09:50:43 +00:00
|
|
|
for _, p := range resp.Sessions {
|
|
|
|
table.Append([]string{
|
|
|
|
p.PublicKey,
|
|
|
|
p.IPAddress,
|
2022-09-03 15:55:57 +00:00
|
|
|
(time.Duration(p.Uptime) * time.Second).String(),
|
|
|
|
p.RXBytes.String(),
|
|
|
|
p.TXBytes.String(),
|
2022-09-03 09:50:43 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
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
|
2021-08-02 21:47:38 +00:00
|
|
|
}
|
|
|
|
|
2022-09-24 11:22:38 +00:00
|
|
|
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()
|
|
|
|
|
|
|
|
case "gettun":
|
2022-09-24 13:41:47 +00:00
|
|
|
var resp tun.GetTUNResponse
|
2022-09-24 11:22:38 +00:00
|
|
|
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()
|
|
|
|
|
2022-10-02 12:15:11 +00:00
|
|
|
case "addpeer", "removepeer":
|
|
|
|
|
2022-09-03 09:50:43 +00:00
|
|
|
default:
|
2022-09-24 11:22:38 +00:00
|
|
|
fmt.Println(string(recv.Response))
|
2018-05-20 22:32:17 +00:00
|
|
|
}
|
|
|
|
|
2022-09-03 09:50:43 +00:00
|
|
|
return 0
|
2018-05-20 22:32:17 +00:00
|
|
|
}
|