Refactor admin socket, export request/response structs, remove types package

This commit is contained in:
Neil Alexander 2021-05-16 19:51:09 +01:00
parent dfca87ba80
commit 2d01386d6e
13 changed files with 290 additions and 218 deletions

View File

@ -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
View File

@ -0,0 +1,5 @@
package admin
type ErrorResponse struct {
Error string `json:"error"`
}

34
src/admin/getdht.go Normal file
View 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
View 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
View 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
View 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
}

View File

@ -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."`

View File

@ -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
} }

View File

@ -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
}) })
} }

View File

@ -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
}
})
*/
} }

View File

@ -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

View File

@ -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
} }

View File

@ -1,3 +0,0 @@
package types
type MTU uint16