mirror of
https://github.com/cwinfo/yggdrasil-go.git
synced 2024-11-22 08:20:28 +00:00
Refactor admin socket, export request/response structs, remove types package
This commit is contained in:
parent
dfca87ba80
commit
2d01386d6e
@ -1,7 +1,6 @@
|
|||||||
package admin
|
package admin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -9,17 +8,12 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
//"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gologme/log"
|
"github.com/gologme/log"
|
||||||
|
|
||||||
"github.com/yggdrasil-network/yggdrasil-go/src/address"
|
|
||||||
"github.com/yggdrasil-network/yggdrasil-go/src/config"
|
"github.com/yggdrasil-network/yggdrasil-go/src/config"
|
||||||
//"github.com/yggdrasil-network/yggdrasil-go/src/crypto"
|
|
||||||
//"github.com/yggdrasil-network/yggdrasil-go/src/util"
|
|
||||||
"github.com/yggdrasil-network/yggdrasil-go/src/version"
|
|
||||||
"github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil"
|
"github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -34,16 +28,26 @@ type AdminSocket struct {
|
|||||||
started bool
|
started bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Info refers to information that is returned to the admin socket handler.
|
type AdminSocketResponse struct {
|
||||||
type Info map[string]interface{}
|
Status string `json:"status"`
|
||||||
|
Request struct {
|
||||||
|
Name string `json:"request"`
|
||||||
|
KeepAlive bool `json:"keepalive"`
|
||||||
|
} `json:"request"`
|
||||||
|
Response interface{} `json:"response"`
|
||||||
|
}
|
||||||
|
|
||||||
type handler struct {
|
type handler struct {
|
||||||
args []string // List of human-readable argument names
|
args []string // List of human-readable argument names
|
||||||
handler func(Info) (Info, error) // First is input map, second is output
|
handler func(json.RawMessage) (interface{}, error) // First is input map, second is output
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListResponse struct {
|
||||||
|
List map[string][]string `json:"list"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddHandler is called for each admin function to add the handler and help documentation to the API.
|
// AddHandler is called for each admin function to add the handler and help documentation to the API.
|
||||||
func (a *AdminSocket) AddHandler(name string, args []string, handlerfunc func(Info) (Info, error)) error {
|
func (a *AdminSocket) AddHandler(name string, args []string, handlerfunc func(json.RawMessage) (interface{}, error)) error {
|
||||||
if _, ok := a.handlers[strings.ToLower(name)]; ok {
|
if _, ok := a.handlers[strings.ToLower(name)]; ok {
|
||||||
return errors.New("handler already exists")
|
return errors.New("handler already exists")
|
||||||
}
|
}
|
||||||
@ -61,70 +65,60 @@ func (a *AdminSocket) Init(c *yggdrasil.Core, state *config.NodeState, log *log.
|
|||||||
a.handlers = make(map[string]handler)
|
a.handlers = make(map[string]handler)
|
||||||
current := state.GetCurrent()
|
current := state.GetCurrent()
|
||||||
a.listenaddr = current.AdminListen
|
a.listenaddr = current.AdminListen
|
||||||
a.AddHandler("list", []string{}, func(in Info) (Info, error) {
|
_ = a.AddHandler("list", []string{}, func(_ json.RawMessage) (interface{}, error) {
|
||||||
handlers := make(map[string]interface{})
|
res := &ListResponse{}
|
||||||
for handlername, handler := range a.handlers {
|
for name, handler := range a.handlers {
|
||||||
handlers[handlername] = Info{"fields": handler.args}
|
res.List[name] = handler.args
|
||||||
}
|
}
|
||||||
return Info{"list": handlers}, nil
|
return res, nil
|
||||||
})
|
})
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *AdminSocket) SetupAdminHandlers(na *AdminSocket) {
|
func (a *AdminSocket) SetupAdminHandlers(na *AdminSocket) {
|
||||||
a.AddHandler("getSelf", []string{}, func(in Info) (Info, error) {
|
_ = a.AddHandler("getSelf", []string{}, func(in json.RawMessage) (interface{}, error) {
|
||||||
ip := a.core.Address().String()
|
req := &GetSelfRequest{}
|
||||||
subnet := a.core.Subnet()
|
res := &GetSelfResponse{}
|
||||||
self := a.core.GetSelf()
|
if err := json.Unmarshal(in, &req); err != nil {
|
||||||
return Info{
|
return nil, err
|
||||||
"self": Info{
|
|
||||||
ip: Info{
|
|
||||||
// TODO"box_pub_key": a.core.EncryptionPublicKey(),
|
|
||||||
"build_name": version.BuildName(),
|
|
||||||
"build_version": version.BuildVersion(),
|
|
||||||
"key": hex.EncodeToString(self.Key[:]),
|
|
||||||
"coords": fmt.Sprintf("%v", self.Coords),
|
|
||||||
"subnet": subnet.String(),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}, nil
|
|
||||||
})
|
|
||||||
a.AddHandler("getPeers", []string{}, func(in Info) (Info, error) {
|
|
||||||
peers := make(Info)
|
|
||||||
for _, p := range a.core.GetPeers() {
|
|
||||||
addr := address.AddrForKey(p.Key)
|
|
||||||
so := net.IP(addr[:]).String()
|
|
||||||
peers[so] = Info{
|
|
||||||
"key": hex.EncodeToString(p.Key[:]),
|
|
||||||
"port": p.Port,
|
|
||||||
"coords": fmt.Sprintf("%v", p.Coords),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return Info{"peers": peers}, nil
|
if err := a.getSelfHandler(req, res); err != nil {
|
||||||
})
|
return nil, err
|
||||||
a.AddHandler("getDHT", []string{}, func(in Info) (Info, error) {
|
|
||||||
dht := make(Info)
|
|
||||||
for _, d := range a.core.GetDHT() {
|
|
||||||
addr := address.AddrForKey(d.Key)
|
|
||||||
so := net.IP(addr[:]).String()
|
|
||||||
dht[so] = Info{
|
|
||||||
"key": hex.EncodeToString(d.Key[:]),
|
|
||||||
"port": fmt.Sprintf("%v", d.Port),
|
|
||||||
"next": fmt.Sprintf("%v", d.Next),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return Info{"dht": dht}, nil
|
return res, nil
|
||||||
})
|
})
|
||||||
a.AddHandler("getSessions", []string{}, func(in Info) (Info, error) {
|
_ = a.AddHandler("getPeers", []string{}, func(in json.RawMessage) (interface{}, error) {
|
||||||
sessions := make(Info)
|
req := &GetPeersRequest{}
|
||||||
for _, s := range a.core.GetSessions() {
|
res := &GetPeersResponse{}
|
||||||
addr := address.AddrForKey(s.Key)
|
if err := json.Unmarshal(in, &req); err != nil {
|
||||||
so := net.IP(addr[:]).String()
|
return nil, err
|
||||||
sessions[so] = Info{
|
|
||||||
"key": hex.EncodeToString(s.Key[:]),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return Info{"sessions": sessions}, nil
|
if err := a.getPeersHandler(req, res); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
})
|
||||||
|
_ = a.AddHandler("getDHT", []string{}, func(in json.RawMessage) (interface{}, error) {
|
||||||
|
req := &GetDHTRequest{}
|
||||||
|
res := &GetDHTResponse{}
|
||||||
|
if err := json.Unmarshal(in, &req); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := a.getDHTHandler(req, res); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
})
|
||||||
|
_ = a.AddHandler("getSessions", []string{}, func(in json.RawMessage) (interface{}, error) {
|
||||||
|
req := &GetSessionsRequest{}
|
||||||
|
res := &GetSessionsResponse{}
|
||||||
|
if err := json.Unmarshal(in, &req); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := a.getSessionsHandler(req, res); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,20 +203,20 @@ func (a *AdminSocket) listen() {
|
|||||||
// handleRequest calls the request handler for each request sent to the admin API.
|
// handleRequest calls the request handler for each request sent to the admin API.
|
||||||
func (a *AdminSocket) handleRequest(conn net.Conn) {
|
func (a *AdminSocket) handleRequest(conn net.Conn) {
|
||||||
decoder := json.NewDecoder(conn)
|
decoder := json.NewDecoder(conn)
|
||||||
|
decoder.DisallowUnknownFields()
|
||||||
|
|
||||||
encoder := json.NewEncoder(conn)
|
encoder := json.NewEncoder(conn)
|
||||||
encoder.SetIndent("", " ")
|
encoder.SetIndent("", " ")
|
||||||
recv := make(Info)
|
|
||||||
send := make(Info)
|
defer conn.Close()
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
r := recover()
|
r := recover()
|
||||||
if r != nil {
|
if r != nil {
|
||||||
send = Info{
|
|
||||||
"status": "error",
|
|
||||||
"error": "Check your syntax and input types",
|
|
||||||
}
|
|
||||||
a.log.Debugln("Admin socket error:", r)
|
a.log.Debugln("Admin socket error:", r)
|
||||||
if err := encoder.Encode(&send); err != nil {
|
if err := encoder.Encode(&ErrorResponse{
|
||||||
|
Error: "Check your syntax and input types",
|
||||||
|
}); err != nil {
|
||||||
a.log.Debugln("Admin socket JSON encode error:", err)
|
a.log.Debugln("Admin socket JSON encode error:", err)
|
||||||
}
|
}
|
||||||
conn.Close()
|
conn.Close()
|
||||||
@ -230,83 +224,40 @@ func (a *AdminSocket) handleRequest(conn net.Conn) {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
// Start with a clean slate on each request
|
var err error
|
||||||
recv = Info{}
|
var buf json.RawMessage
|
||||||
send = Info{}
|
_ = decoder.Decode(&buf)
|
||||||
|
var resp AdminSocketResponse
|
||||||
// Decode the input
|
resp.Status = "success"
|
||||||
if err := decoder.Decode(&recv); err != nil {
|
if err = json.Unmarshal(buf, &resp.Request); err == nil {
|
||||||
a.log.Debugln("Admin socket JSON decode error:", err)
|
if resp.Request.Name == "" {
|
||||||
return
|
resp.Status = "error"
|
||||||
}
|
resp.Response = &ErrorResponse{
|
||||||
|
Error: "No request specified",
|
||||||
// Send the request back with the response, and default to "error"
|
|
||||||
// unless the status is changed below by one of the handlers
|
|
||||||
send["request"] = recv
|
|
||||||
send["status"] = "error"
|
|
||||||
|
|
||||||
n := strings.ToLower(recv["request"].(string))
|
|
||||||
|
|
||||||
if _, ok := recv["request"]; !ok {
|
|
||||||
send["error"] = "No request sent"
|
|
||||||
goto respond
|
|
||||||
}
|
|
||||||
|
|
||||||
if h, ok := a.handlers[n]; ok {
|
|
||||||
// Check that we have all the required arguments
|
|
||||||
for _, arg := range h.args {
|
|
||||||
// An argument in [square brackets] is optional and not required,
|
|
||||||
// so we can safely ignore those
|
|
||||||
if strings.HasPrefix(arg, "[") && strings.HasSuffix(arg, "]") {
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
// Check if the field is missing
|
} else if h, ok := a.handlers[strings.ToLower(resp.Request.Name)]; ok {
|
||||||
if _, ok := recv[arg]; !ok {
|
resp.Response, err = h.handler(buf)
|
||||||
send = Info{
|
if err != nil {
|
||||||
"status": "error",
|
resp.Status = "error"
|
||||||
"error": "Expected field missing: " + arg,
|
resp.Response = &ErrorResponse{
|
||||||
"expecting": arg,
|
Error: err.Error(),
|
||||||
}
|
}
|
||||||
goto respond
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// By this point we should have all the fields we need, so call
|
|
||||||
// the handler
|
|
||||||
response, err := h.handler(recv)
|
|
||||||
if err != nil {
|
|
||||||
send["error"] = err.Error()
|
|
||||||
if response != nil {
|
|
||||||
send["response"] = response
|
|
||||||
goto respond
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
send["status"] = "success"
|
resp.Status = "error"
|
||||||
if response != nil {
|
resp.Response = &ErrorResponse{
|
||||||
send["response"] = response
|
Error: fmt.Sprintf("Unknown action '%s', try 'list' for help", resp.Request.Name),
|
||||||
goto respond
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
j, _ := json.Marshal(resp)
|
||||||
|
if err = encoder.Encode(resp); err != nil {
|
||||||
|
a.log.Debugln("Encode error:", err)
|
||||||
|
}
|
||||||
|
if !resp.Request.KeepAlive {
|
||||||
|
break
|
||||||
} else {
|
} else {
|
||||||
// Start with a clean response on each request, which defaults to an error
|
continue
|
||||||
// state. If a handler is found below then this will be overwritten
|
|
||||||
send = Info{
|
|
||||||
"request": recv,
|
|
||||||
"status": "error",
|
|
||||||
"error": fmt.Sprintf("Unknown action '%s', try 'list' for help", recv["request"].(string)),
|
|
||||||
}
|
|
||||||
goto respond
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send the response back
|
|
||||||
respond:
|
|
||||||
if err := encoder.Encode(&send); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// If "keepalive" isn't true then close the connection
|
|
||||||
if keepalive, ok := recv["keepalive"]; !ok || !keepalive.(bool) {
|
|
||||||
conn.Close()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
5
src/admin/error.go
Normal file
5
src/admin/error.go
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package admin
|
||||||
|
|
||||||
|
type ErrorResponse struct {
|
||||||
|
Error string `json:"error"`
|
||||||
|
}
|
34
src/admin/getdht.go
Normal file
34
src/admin/getdht.go
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package admin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"github.com/yggdrasil-network/yggdrasil-go/src/address"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetDHTRequest struct{}
|
||||||
|
|
||||||
|
type GetDHTResponse struct {
|
||||||
|
DHT map[string]DHTEntry `json:"dht"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DHTEntry struct {
|
||||||
|
PublicKey string `json:"key"`
|
||||||
|
Port uint64 `json:"port"`
|
||||||
|
Next uint64 `json:"next"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AdminSocket) getDHTHandler(req *GetDHTRequest, res *GetDHTResponse) error {
|
||||||
|
res.DHT = map[string]DHTEntry{}
|
||||||
|
for _, d := range a.core.GetDHT() {
|
||||||
|
addr := address.AddrForKey(d.Key)
|
||||||
|
so := net.IP(addr[:]).String()
|
||||||
|
res.DHT[so] = DHTEntry{
|
||||||
|
PublicKey: hex.EncodeToString(d.Key[:]),
|
||||||
|
Port: d.Port,
|
||||||
|
Next: d.Next,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
35
src/admin/getpeers.go
Normal file
35
src/admin/getpeers.go
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package admin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"github.com/yggdrasil-network/yggdrasil-go/src/address"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetPeersRequest struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetPeersResponse struct {
|
||||||
|
Peers map[string]PeerEntry `json:"peers"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PeerEntry struct {
|
||||||
|
PublicKey string `json:"key"`
|
||||||
|
Port uint64 `json:"port"`
|
||||||
|
Coords []uint64 `json:"coords"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AdminSocket) getPeersHandler(req *GetPeersRequest, res *GetPeersResponse) error {
|
||||||
|
res.Peers = map[string]PeerEntry{}
|
||||||
|
for _, p := range a.core.GetPeers() {
|
||||||
|
addr := address.AddrForKey(p.Key)
|
||||||
|
so := net.IP(addr[:]).String()
|
||||||
|
res.Peers[so] = PeerEntry{
|
||||||
|
PublicKey: hex.EncodeToString(p.Key),
|
||||||
|
Port: p.Port,
|
||||||
|
Coords: p.Coords,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
31
src/admin/getself.go
Normal file
31
src/admin/getself.go
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package admin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/ed25519"
|
||||||
|
"encoding/hex"
|
||||||
|
|
||||||
|
"github.com/yggdrasil-network/yggdrasil-go/src/version"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetSelfRequest struct{}
|
||||||
|
|
||||||
|
type GetSelfResponse struct {
|
||||||
|
BuildName string `json:"build_name"`
|
||||||
|
BuildVersion string `json:"build_version"`
|
||||||
|
PublicKey string `json:"key"`
|
||||||
|
Coords []uint64 `json:"coords"`
|
||||||
|
IPAddress string `json:"address"`
|
||||||
|
Subnet string `json:"subnet"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AdminSocket) getSelfHandler(req *GetSelfRequest, res *GetSelfResponse) error {
|
||||||
|
res.BuildName = version.BuildName()
|
||||||
|
res.BuildVersion = version.BuildVersion()
|
||||||
|
public := a.core.PrivateKey().Public().(ed25519.PublicKey)
|
||||||
|
res.PublicKey = hex.EncodeToString(public[:])
|
||||||
|
res.IPAddress = a.core.Address().String()
|
||||||
|
snet := a.core.Subnet()
|
||||||
|
res.Subnet = snet.String()
|
||||||
|
// TODO: res.coords
|
||||||
|
return nil
|
||||||
|
}
|
30
src/admin/getsessions.go
Normal file
30
src/admin/getsessions.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package admin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"github.com/yggdrasil-network/yggdrasil-go/src/address"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetSessionsRequest struct{}
|
||||||
|
|
||||||
|
type GetSessionsResponse struct {
|
||||||
|
Sessions map[string]SessionEntry `json:"sessions"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SessionEntry struct {
|
||||||
|
PublicKey string `json:"key"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AdminSocket) getSessionsHandler(req *GetSessionsRequest, res *GetSessionsResponse) error {
|
||||||
|
res.Sessions = map[string]SessionEntry{}
|
||||||
|
for _, s := range a.core.GetSessions() {
|
||||||
|
addr := address.AddrForKey(s.Key)
|
||||||
|
so := net.IP(addr[:]).String()
|
||||||
|
res.Sessions[so] = SessionEntry{
|
||||||
|
PublicKey: hex.EncodeToString(s.Key[:]),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
@ -22,11 +22,8 @@ import (
|
|||||||
|
|
||||||
"github.com/yggdrasil-network/yggdrasil-go/src/crypto"
|
"github.com/yggdrasil-network/yggdrasil-go/src/crypto"
|
||||||
"github.com/yggdrasil-network/yggdrasil-go/src/defaults"
|
"github.com/yggdrasil-network/yggdrasil-go/src/defaults"
|
||||||
"github.com/yggdrasil-network/yggdrasil-go/src/types"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type MTU = types.MTU
|
|
||||||
|
|
||||||
// NodeState represents the active and previous configuration of an Yggdrasil
|
// NodeState represents the active and previous configuration of an Yggdrasil
|
||||||
// node. A NodeState object is returned when starting an Yggdrasil node. Note
|
// node. A NodeState object is returned when starting an Yggdrasil node. Note
|
||||||
// that this structure and related functions are likely to disappear soon.
|
// that this structure and related functions are likely to disappear soon.
|
||||||
@ -72,7 +69,7 @@ type NodeConfig struct {
|
|||||||
PrivateKey string `comment:"Your private signing key. DO NOT share this with anyone!"`
|
PrivateKey string `comment:"Your private signing key. DO NOT share this with anyone!"`
|
||||||
LinkLocalTCPPort uint16 `comment:"The port number to be used for the link-local TCP listeners for the\nconfigured MulticastInterfaces. This option does not affect listeners\nspecified in the Listen option. Unless you plan to firewall link-local\ntraffic, it is best to leave this as the default value of 0. This\noption cannot currently be changed by reloading config during runtime."`
|
LinkLocalTCPPort uint16 `comment:"The port number to be used for the link-local TCP listeners for the\nconfigured MulticastInterfaces. This option does not affect listeners\nspecified in the Listen option. Unless you plan to firewall link-local\ntraffic, it is best to leave this as the default value of 0. This\noption cannot currently be changed by reloading config during runtime."`
|
||||||
IfName string `comment:"Local network interface name for TUN adapter, or \"auto\" to select\nan interface automatically, or \"none\" to run without TUN."`
|
IfName string `comment:"Local network interface name for TUN adapter, or \"auto\" to select\nan interface automatically, or \"none\" to run without TUN."`
|
||||||
IfMTU MTU `comment:"Maximum Transmission Unit (MTU) size for your local TUN interface.\nDefault is the largest supported size for your platform. The lowest\npossible value is 1280."`
|
IfMTU uint16 `comment:"Maximum Transmission Unit (MTU) size for your local TUN interface.\nDefault is the largest supported size for your platform. The lowest\npossible value is 1280."`
|
||||||
SessionFirewall SessionFirewall `comment:"The session firewall controls who can send/receive network traffic\nto/from. This is useful if you want to protect this node without\nresorting to using a real firewall. This does not affect traffic\nbeing routed via this node to somewhere else. Rules are prioritised as\nfollows: blacklist, whitelist, always allow outgoing, direct, remote."`
|
SessionFirewall SessionFirewall `comment:"The session firewall controls who can send/receive network traffic\nto/from. This is useful if you want to protect this node without\nresorting to using a real firewall. This does not affect traffic\nbeing routed via this node to somewhere else. Rules are prioritised as\nfollows: blacklist, whitelist, always allow outgoing, direct, remote."`
|
||||||
NodeInfoPrivacy bool `comment:"By default, nodeinfo contains some defaults including the platform,\narchitecture and Yggdrasil version. These can help when surveying\nthe network and diagnosing network routing problems. Enabling\nnodeinfo privacy prevents this, so that only items specified in\n\"NodeInfo\" are sent back if specified."`
|
NodeInfoPrivacy bool `comment:"By default, nodeinfo contains some defaults including the platform,\narchitecture and Yggdrasil version. These can help when surveying\nthe network and diagnosing network routing problems. Enabling\nnodeinfo privacy prevents this, so that only items specified in\n\"NodeInfo\" are sent back if specified."`
|
||||||
NodeInfo map[string]interface{} `comment:"Optional node info. This must be a { \"key\": \"value\", ... } map\nor set as null. This is entirely optional but, if set, is visible\nto the whole network on request."`
|
NodeInfo map[string]interface{} `comment:"Optional node info. This must be a { \"key\": \"value\", ... } map\nor set as null. This is entirely optional but, if set, is visible\nto the whole network on request."`
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
package defaults
|
package defaults
|
||||||
|
|
||||||
import "github.com/yggdrasil-network/yggdrasil-go/src/types"
|
|
||||||
|
|
||||||
// Defines which parameters are expected by default for configuration on a
|
// Defines which parameters are expected by default for configuration on a
|
||||||
// specific platform. These values are populated in the relevant defaults_*.go
|
// specific platform. These values are populated in the relevant defaults_*.go
|
||||||
// for the platform being targeted. They must be set.
|
// for the platform being targeted. They must be set.
|
||||||
@ -16,7 +14,7 @@ type platformDefaultParameters struct {
|
|||||||
DefaultMulticastInterfaces []string
|
DefaultMulticastInterfaces []string
|
||||||
|
|
||||||
// TUN/TAP
|
// TUN/TAP
|
||||||
MaximumIfMTU types.MTU
|
MaximumIfMTU uint16
|
||||||
DefaultIfMTU types.MTU
|
DefaultIfMTU uint16
|
||||||
DefaultIfName string
|
DefaultIfName string
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,34 @@
|
|||||||
package multicast
|
package multicast
|
||||||
|
|
||||||
import "github.com/yggdrasil-network/yggdrasil-go/src/admin"
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/yggdrasil-network/yggdrasil-go/src/admin"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetMulticastInterfacesRequest struct{}
|
||||||
|
type GetMulticastInterfacesResponse struct {
|
||||||
|
Interfaces []string `json:"multicast_interfaces"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Multicast) getMulticastInterfacesHandler(req *GetMulticastInterfacesRequest, res *GetMulticastInterfacesResponse) error {
|
||||||
|
res.Interfaces = []string{}
|
||||||
|
for _, v := range m.Interfaces() {
|
||||||
|
res.Interfaces = append(res.Interfaces, v.Name)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (m *Multicast) SetupAdminHandlers(a *admin.AdminSocket) {
|
func (m *Multicast) SetupAdminHandlers(a *admin.AdminSocket) {
|
||||||
a.AddHandler("getMulticastInterfaces", []string{}, func(in admin.Info) (admin.Info, error) {
|
_ = a.AddHandler("getMulticastInterfaces", []string{}, func(in json.RawMessage) (interface{}, error) {
|
||||||
var intfs []string
|
req := &GetMulticastInterfacesRequest{}
|
||||||
for _, v := range m.Interfaces() {
|
res := &GetMulticastInterfacesResponse{}
|
||||||
intfs = append(intfs, v.Name)
|
if err := json.Unmarshal(in, &req); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
return admin.Info{"multicast_interfaces": intfs}, nil
|
if err := m.getMulticastInterfacesHandler(req, res); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,57 +1,31 @@
|
|||||||
package tuntap
|
package tuntap
|
||||||
|
|
||||||
import (
|
import (
|
||||||
//"encoding/hex"
|
"encoding/json"
|
||||||
//"errors"
|
|
||||||
//"fmt"
|
|
||||||
//"net"
|
|
||||||
|
|
||||||
"github.com/yggdrasil-network/yggdrasil-go/src/admin"
|
"github.com/yggdrasil-network/yggdrasil-go/src/admin"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (t *TunAdapter) SetupAdminHandlers(a *admin.AdminSocket) {
|
type GetTUNRequest struct{}
|
||||||
a.AddHandler("getTunTap", []string{}, func(in admin.Info) (r admin.Info, e error) {
|
type GetTUNResponse map[string]uint16
|
||||||
defer func() {
|
|
||||||
if err := recover(); err != nil {
|
|
||||||
r = admin.Info{"none": admin.Info{}}
|
|
||||||
e = nil
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
return admin.Info{
|
func (t *TunAdapter) getTUNHandler(req *GetTUNRequest, res *GetTUNResponse) error {
|
||||||
t.Name(): admin.Info{
|
res = &GetTUNResponse{
|
||||||
"mtu": t.mtu,
|
t.Name(): t.MTU(),
|
||||||
},
|
}
|
||||||
}, nil
|
return nil
|
||||||
})
|
}
|
||||||
/*
|
|
||||||
// TODO: rewrite this as I'm fairly sure it doesn't work right on many
|
func (t *TunAdapter) SetupAdminHandlers(a *admin.AdminSocket) {
|
||||||
// platforms anyway, but it may require changes to Water
|
_ = a.AddHandler("getTunTap", []string{}, func(in json.RawMessage) (interface{}, error) {
|
||||||
a.AddHandler("setTunTap", []string{"name", "[tap_mode]", "[mtu]"}, func(in Info) (Info, error) {
|
req := &GetTUNRequest{}
|
||||||
// Set sane defaults
|
res := &GetTUNResponse{}
|
||||||
iftapmode := defaults.GetDefaults().DefaultIfTAPMode
|
if err := json.Unmarshal(in, &req); err != nil {
|
||||||
ifmtu := defaults.GetDefaults().DefaultIfMTU
|
return nil, err
|
||||||
// Has TAP mode been specified?
|
}
|
||||||
if tap, ok := in["tap_mode"]; ok {
|
if err := t.getTUNHandler(req, res); err != nil {
|
||||||
iftapmode = tap.(bool)
|
return nil, err
|
||||||
}
|
}
|
||||||
// Check we have enough params for MTU
|
return res, nil
|
||||||
if mtu, ok := in["mtu"]; ok {
|
})
|
||||||
if mtu.(float64) >= 1280 && ifmtu <= defaults.GetDefaults().MaximumIfMTU {
|
|
||||||
ifmtu = int(in["mtu"].(float64))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Start the TUN adapter
|
|
||||||
if err := a.startTunWithMTU(in["name"].(string), iftapmode, ifmtu); err != nil {
|
|
||||||
return Info{}, errors.New("Failed to configure adapter")
|
|
||||||
} else {
|
|
||||||
return Info{
|
|
||||||
a.core.router.tun.iface.Name(): Info{
|
|
||||||
"tap_mode": a.core.router.tun.iface.IsTAP(),
|
|
||||||
"mtu": ifmtu,
|
|
||||||
},
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
})
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
@ -23,11 +23,10 @@ import (
|
|||||||
"github.com/yggdrasil-network/yggdrasil-go/src/address"
|
"github.com/yggdrasil-network/yggdrasil-go/src/address"
|
||||||
"github.com/yggdrasil-network/yggdrasil-go/src/config"
|
"github.com/yggdrasil-network/yggdrasil-go/src/config"
|
||||||
"github.com/yggdrasil-network/yggdrasil-go/src/defaults"
|
"github.com/yggdrasil-network/yggdrasil-go/src/defaults"
|
||||||
"github.com/yggdrasil-network/yggdrasil-go/src/types"
|
|
||||||
"github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil"
|
"github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil"
|
||||||
)
|
)
|
||||||
|
|
||||||
type MTU = types.MTU
|
type MTU uint16
|
||||||
|
|
||||||
// TunAdapter represents a running TUN interface and extends the
|
// TunAdapter represents a running TUN interface and extends the
|
||||||
// yggdrasil.Adapter type. In order to use the TUN adapter with Yggdrasil, you
|
// yggdrasil.Adapter type. In order to use the TUN adapter with Yggdrasil, you
|
||||||
@ -40,7 +39,7 @@ type TunAdapter struct {
|
|||||||
log *log.Logger
|
log *log.Logger
|
||||||
addr address.Address
|
addr address.Address
|
||||||
subnet address.Subnet
|
subnet address.Subnet
|
||||||
mtu MTU
|
mtu uint16
|
||||||
iface tun.Device
|
iface tun.Device
|
||||||
phony.Inbox // Currently only used for _handlePacket from the reader, TODO: all the stuff that currently needs a mutex below
|
phony.Inbox // Currently only used for _handlePacket from the reader, TODO: all the stuff that currently needs a mutex below
|
||||||
//mutex sync.RWMutex // Protects the below
|
//mutex sync.RWMutex // Protects the below
|
||||||
@ -56,7 +55,7 @@ func (tun *TunAdapter) SetSessionGatekeeper(gatekeeper func(pubkey ed25519.Publi
|
|||||||
|
|
||||||
// Gets the maximum supported MTU for the platform based on the defaults in
|
// Gets the maximum supported MTU for the platform based on the defaults in
|
||||||
// defaults.GetDefaults().
|
// defaults.GetDefaults().
|
||||||
func getSupportedMTU(mtu MTU) MTU {
|
func getSupportedMTU(mtu uint16) uint16 {
|
||||||
if mtu < 1280 {
|
if mtu < 1280 {
|
||||||
return 1280
|
return 1280
|
||||||
}
|
}
|
||||||
@ -78,7 +77,7 @@ func (tun *TunAdapter) Name() string {
|
|||||||
// MTU gets the adapter's MTU. This can range between 1280 and 65535, although
|
// MTU gets the adapter's MTU. This can range between 1280 and 65535, although
|
||||||
// the maximum value is determined by your platform. The returned value will
|
// the maximum value is determined by your platform. The returned value will
|
||||||
// never exceed that of MaximumMTU().
|
// never exceed that of MaximumMTU().
|
||||||
func (tun *TunAdapter) MTU() MTU {
|
func (tun *TunAdapter) MTU() uint16 {
|
||||||
return getSupportedMTU(tun.mtu)
|
return getSupportedMTU(tun.mtu)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,14 +88,14 @@ func DefaultName() string {
|
|||||||
|
|
||||||
// DefaultMTU gets the default TUN interface MTU for your platform. This can
|
// DefaultMTU gets the default TUN interface MTU for your platform. This can
|
||||||
// be as high as MaximumMTU(), depending on platform, but is never lower than 1280.
|
// be as high as MaximumMTU(), depending on platform, but is never lower than 1280.
|
||||||
func DefaultMTU() MTU {
|
func DefaultMTU() uint16 {
|
||||||
return defaults.GetDefaults().DefaultIfMTU
|
return defaults.GetDefaults().DefaultIfMTU
|
||||||
}
|
}
|
||||||
|
|
||||||
// MaximumMTU returns the maximum supported TUN interface MTU for your
|
// MaximumMTU returns the maximum supported TUN interface MTU for your
|
||||||
// platform. This can be as high as 65535, depending on platform, but is never
|
// platform. This can be as high as 65535, depending on platform, but is never
|
||||||
// lower than 1280.
|
// lower than 1280.
|
||||||
func MaximumMTU() MTU {
|
func MaximumMTU() uint16 {
|
||||||
return defaults.GetDefaults().MaximumIfMTU
|
return defaults.GetDefaults().MaximumIfMTU
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,7 +150,7 @@ func (tun *TunAdapter) _start() error {
|
|||||||
}
|
}
|
||||||
mtu := current.IfMTU
|
mtu := current.IfMTU
|
||||||
if tun.core.MTU() < uint64(mtu) {
|
if tun.core.MTU() < uint64(mtu) {
|
||||||
mtu = MTU(tun.core.MTU())
|
mtu = uint16(tun.core.MTU())
|
||||||
}
|
}
|
||||||
if err := tun.setup(current.IfName, addr, mtu); err != nil {
|
if err := tun.setup(current.IfName, addr, mtu); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -16,7 +16,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Configures the "utun" adapter with the correct IPv6 address and MTU.
|
// Configures the "utun" adapter with the correct IPv6 address and MTU.
|
||||||
func (tun *TunAdapter) setup(ifname string, addr string, mtu MTU) error {
|
func (tun *TunAdapter) setup(ifname string, addr string, mtu uint16) error {
|
||||||
if ifname == "auto" {
|
if ifname == "auto" {
|
||||||
ifname = "utun"
|
ifname = "utun"
|
||||||
}
|
}
|
||||||
@ -25,8 +25,8 @@ func (tun *TunAdapter) setup(ifname string, addr string, mtu MTU) error {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
tun.iface = iface
|
tun.iface = iface
|
||||||
if mtu, err := iface.MTU(); err == nil {
|
if m, err := iface.MTU(); err == nil {
|
||||||
tun.mtu = getSupportedMTU(MTU(mtu))
|
tun.mtu = getSupportedMTU(uint16(m))
|
||||||
} else {
|
} else {
|
||||||
tun.mtu = 0
|
tun.mtu = 0
|
||||||
}
|
}
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
package types
|
|
||||||
|
|
||||||
type MTU uint16
|
|
Loading…
Reference in New Issue
Block a user