From 2d01386d6e821350ee396e703e389b429573bd6a Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Sun, 16 May 2021 19:51:09 +0100 Subject: [PATCH 1/3] Refactor admin socket, export request/response structs, remove types package --- src/admin/admin.go | 235 ++++++++++++++++----------------------- src/admin/error.go | 5 + src/admin/getdht.go | 34 ++++++ src/admin/getpeers.go | 35 ++++++ src/admin/getself.go | 31 ++++++ src/admin/getsessions.go | 30 +++++ src/config/config.go | 5 +- src/defaults/defaults.go | 6 +- src/multicast/admin.go | 33 +++++- src/tuntap/admin.go | 70 ++++-------- src/tuntap/tun.go | 15 ++- src/tuntap/tun_darwin.go | 6 +- src/types/types.go | 3 - 13 files changed, 290 insertions(+), 218 deletions(-) create mode 100644 src/admin/error.go create mode 100644 src/admin/getdht.go create mode 100644 src/admin/getpeers.go create mode 100644 src/admin/getself.go create mode 100644 src/admin/getsessions.go delete mode 100644 src/types/types.go diff --git a/src/admin/admin.go b/src/admin/admin.go index a702adfd..855b0545 100644 --- a/src/admin/admin.go +++ b/src/admin/admin.go @@ -1,7 +1,6 @@ package admin import ( - "encoding/hex" "encoding/json" "errors" "fmt" @@ -9,17 +8,12 @@ import ( "net/url" "os" - //"strconv" "strings" "time" "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/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" ) @@ -34,16 +28,26 @@ type AdminSocket struct { started bool } -// Info refers to information that is returned to the admin socket handler. -type Info map[string]interface{} +type AdminSocketResponse struct { + Status string `json:"status"` + Request struct { + Name string `json:"request"` + KeepAlive bool `json:"keepalive"` + } `json:"request"` + Response interface{} `json:"response"` +} type handler struct { - args []string // List of human-readable argument names - handler func(Info) (Info, error) // First is input map, second is output + args []string // List of human-readable argument names + 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. -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 { 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) current := state.GetCurrent() a.listenaddr = current.AdminListen - a.AddHandler("list", []string{}, func(in Info) (Info, error) { - handlers := make(map[string]interface{}) - for handlername, handler := range a.handlers { - handlers[handlername] = Info{"fields": handler.args} + _ = a.AddHandler("list", []string{}, func(_ json.RawMessage) (interface{}, error) { + res := &ListResponse{} + for name, handler := range a.handlers { + res.List[name] = handler.args } - return Info{"list": handlers}, nil + return res, nil }) return nil } func (a *AdminSocket) SetupAdminHandlers(na *AdminSocket) { - a.AddHandler("getSelf", []string{}, func(in Info) (Info, error) { - ip := a.core.Address().String() - subnet := a.core.Subnet() - self := a.core.GetSelf() - return Info{ - "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), - } + _ = a.AddHandler("getSelf", []string{}, func(in json.RawMessage) (interface{}, error) { + req := &GetSelfRequest{} + res := &GetSelfResponse{} + if err := json.Unmarshal(in, &req); err != nil { + return nil, err } - return Info{"peers": peers}, nil - }) - 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), - } + if err := a.getSelfHandler(req, res); err != nil { + return nil, err } - return Info{"dht": dht}, nil + return res, nil }) - a.AddHandler("getSessions", []string{}, func(in Info) (Info, error) { - sessions := make(Info) - for _, s := range a.core.GetSessions() { - addr := address.AddrForKey(s.Key) - so := net.IP(addr[:]).String() - sessions[so] = Info{ - "key": hex.EncodeToString(s.Key[:]), - } + _ = a.AddHandler("getPeers", []string{}, func(in json.RawMessage) (interface{}, error) { + req := &GetPeersRequest{} + res := &GetPeersResponse{} + if err := json.Unmarshal(in, &req); err != nil { + return nil, err } - 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. func (a *AdminSocket) handleRequest(conn net.Conn) { decoder := json.NewDecoder(conn) + decoder.DisallowUnknownFields() + encoder := json.NewEncoder(conn) encoder.SetIndent("", " ") - recv := make(Info) - send := make(Info) + + defer conn.Close() defer func() { r := recover() if r != nil { - send = Info{ - "status": "error", - "error": "Check your syntax and input types", - } 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) } conn.Close() @@ -230,83 +224,40 @@ func (a *AdminSocket) handleRequest(conn net.Conn) { }() for { - // Start with a clean slate on each request - recv = Info{} - send = Info{} - - // Decode the input - if err := decoder.Decode(&recv); err != nil { - a.log.Debugln("Admin socket JSON decode error:", err) - return - } - - // 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 + var err error + var buf json.RawMessage + _ = decoder.Decode(&buf) + var resp AdminSocketResponse + resp.Status = "success" + if err = json.Unmarshal(buf, &resp.Request); err == nil { + if resp.Request.Name == "" { + resp.Status = "error" + resp.Response = &ErrorResponse{ + Error: "No request specified", } - // Check if the field is missing - if _, ok := recv[arg]; !ok { - send = Info{ - "status": "error", - "error": "Expected field missing: " + arg, - "expecting": arg, + } else if h, ok := a.handlers[strings.ToLower(resp.Request.Name)]; ok { + resp.Response, err = h.handler(buf) + if err != nil { + resp.Status = "error" + resp.Response = &ErrorResponse{ + 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 { - send["status"] = "success" - if response != nil { - send["response"] = response - goto respond + resp.Status = "error" + resp.Response = &ErrorResponse{ + Error: fmt.Sprintf("Unknown action '%s', try 'list' for help", resp.Request.Name), } } + } + j, _ := json.Marshal(resp) + if err = encoder.Encode(resp); err != nil { + a.log.Debugln("Encode error:", err) + } + if !resp.Request.KeepAlive { + break } else { - // Start with a clean response on each request, which defaults to an error - // 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() + continue } } } diff --git a/src/admin/error.go b/src/admin/error.go new file mode 100644 index 00000000..2c8016eb --- /dev/null +++ b/src/admin/error.go @@ -0,0 +1,5 @@ +package admin + +type ErrorResponse struct { + Error string `json:"error"` +} diff --git a/src/admin/getdht.go b/src/admin/getdht.go new file mode 100644 index 00000000..2796e4ff --- /dev/null +++ b/src/admin/getdht.go @@ -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 +} diff --git a/src/admin/getpeers.go b/src/admin/getpeers.go new file mode 100644 index 00000000..9f53cf23 --- /dev/null +++ b/src/admin/getpeers.go @@ -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 +} diff --git a/src/admin/getself.go b/src/admin/getself.go new file mode 100644 index 00000000..895411bf --- /dev/null +++ b/src/admin/getself.go @@ -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 +} diff --git a/src/admin/getsessions.go b/src/admin/getsessions.go new file mode 100644 index 00000000..3a0c19b6 --- /dev/null +++ b/src/admin/getsessions.go @@ -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 +} diff --git a/src/config/config.go b/src/config/config.go index 91507baa..4aa9a213 100644 --- a/src/config/config.go +++ b/src/config/config.go @@ -22,11 +22,8 @@ import ( "github.com/yggdrasil-network/yggdrasil-go/src/crypto" "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 // node. A NodeState object is returned when starting an Yggdrasil node. Note // 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!"` 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."` - 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."` 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."` diff --git a/src/defaults/defaults.go b/src/defaults/defaults.go index a0d372e4..57248088 100644 --- a/src/defaults/defaults.go +++ b/src/defaults/defaults.go @@ -1,7 +1,5 @@ package defaults -import "github.com/yggdrasil-network/yggdrasil-go/src/types" - // Defines which parameters are expected by default for configuration on a // specific platform. These values are populated in the relevant defaults_*.go // for the platform being targeted. They must be set. @@ -16,7 +14,7 @@ type platformDefaultParameters struct { DefaultMulticastInterfaces []string // TUN/TAP - MaximumIfMTU types.MTU - DefaultIfMTU types.MTU + MaximumIfMTU uint16 + DefaultIfMTU uint16 DefaultIfName string } diff --git a/src/multicast/admin.go b/src/multicast/admin.go index cafee07f..2ae6ec08 100644 --- a/src/multicast/admin.go +++ b/src/multicast/admin.go @@ -1,13 +1,34 @@ 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) { - a.AddHandler("getMulticastInterfaces", []string{}, func(in admin.Info) (admin.Info, error) { - var intfs []string - for _, v := range m.Interfaces() { - intfs = append(intfs, v.Name) + _ = a.AddHandler("getMulticastInterfaces", []string{}, func(in json.RawMessage) (interface{}, error) { + req := &GetMulticastInterfacesRequest{} + res := &GetMulticastInterfacesResponse{} + 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 }) } diff --git a/src/tuntap/admin.go b/src/tuntap/admin.go index 67f80e04..5b50ff24 100644 --- a/src/tuntap/admin.go +++ b/src/tuntap/admin.go @@ -1,57 +1,31 @@ package tuntap import ( - //"encoding/hex" - //"errors" - //"fmt" - //"net" + "encoding/json" "github.com/yggdrasil-network/yggdrasil-go/src/admin" ) -func (t *TunAdapter) SetupAdminHandlers(a *admin.AdminSocket) { - a.AddHandler("getTunTap", []string{}, func(in admin.Info) (r admin.Info, e error) { - defer func() { - if err := recover(); err != nil { - r = admin.Info{"none": admin.Info{}} - e = nil - } - }() +type GetTUNRequest struct{} +type GetTUNResponse map[string]uint16 - return admin.Info{ - t.Name(): admin.Info{ - "mtu": t.mtu, - }, - }, nil - }) - /* - // TODO: rewrite this as I'm fairly sure it doesn't work right on many - // platforms anyway, but it may require changes to Water - a.AddHandler("setTunTap", []string{"name", "[tap_mode]", "[mtu]"}, func(in Info) (Info, error) { - // Set sane defaults - iftapmode := defaults.GetDefaults().DefaultIfTAPMode - ifmtu := defaults.GetDefaults().DefaultIfMTU - // Has TAP mode been specified? - if tap, ok := in["tap_mode"]; ok { - iftapmode = tap.(bool) - } - // Check we have enough params for MTU - 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 - } - }) - */ +func (t *TunAdapter) getTUNHandler(req *GetTUNRequest, res *GetTUNResponse) error { + res = &GetTUNResponse{ + t.Name(): t.MTU(), + } + return nil +} + +func (t *TunAdapter) SetupAdminHandlers(a *admin.AdminSocket) { + _ = a.AddHandler("getTunTap", []string{}, func(in json.RawMessage) (interface{}, error) { + req := &GetTUNRequest{} + res := &GetTUNResponse{} + if err := json.Unmarshal(in, &req); err != nil { + return nil, err + } + if err := t.getTUNHandler(req, res); err != nil { + return nil, err + } + return res, nil + }) } diff --git a/src/tuntap/tun.go b/src/tuntap/tun.go index 6d41f59b..a2f93e31 100644 --- a/src/tuntap/tun.go +++ b/src/tuntap/tun.go @@ -23,11 +23,10 @@ import ( "github.com/yggdrasil-network/yggdrasil-go/src/address" "github.com/yggdrasil-network/yggdrasil-go/src/config" "github.com/yggdrasil-network/yggdrasil-go/src/defaults" - "github.com/yggdrasil-network/yggdrasil-go/src/types" "github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil" ) -type MTU = types.MTU +type MTU uint16 // TunAdapter represents a running TUN interface and extends the // yggdrasil.Adapter type. In order to use the TUN adapter with Yggdrasil, you @@ -40,7 +39,7 @@ type TunAdapter struct { log *log.Logger addr address.Address subnet address.Subnet - mtu MTU + mtu uint16 iface tun.Device 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 @@ -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 // defaults.GetDefaults(). -func getSupportedMTU(mtu MTU) MTU { +func getSupportedMTU(mtu uint16) uint16 { if mtu < 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 // the maximum value is determined by your platform. The returned value will // never exceed that of MaximumMTU(). -func (tun *TunAdapter) MTU() MTU { +func (tun *TunAdapter) MTU() uint16 { return getSupportedMTU(tun.mtu) } @@ -89,14 +88,14 @@ func DefaultName() string { // 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. -func DefaultMTU() MTU { +func DefaultMTU() uint16 { return defaults.GetDefaults().DefaultIfMTU } // MaximumMTU returns the maximum supported TUN interface MTU for your // platform. This can be as high as 65535, depending on platform, but is never // lower than 1280. -func MaximumMTU() MTU { +func MaximumMTU() uint16 { return defaults.GetDefaults().MaximumIfMTU } @@ -151,7 +150,7 @@ func (tun *TunAdapter) _start() error { } mtu := current.IfMTU 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 { return err diff --git a/src/tuntap/tun_darwin.go b/src/tuntap/tun_darwin.go index b984e164..b398eb19 100644 --- a/src/tuntap/tun_darwin.go +++ b/src/tuntap/tun_darwin.go @@ -16,7 +16,7 @@ import ( ) // 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" { ifname = "utun" } @@ -25,8 +25,8 @@ func (tun *TunAdapter) setup(ifname string, addr string, mtu MTU) error { panic(err) } tun.iface = iface - if mtu, err := iface.MTU(); err == nil { - tun.mtu = getSupportedMTU(MTU(mtu)) + if m, err := iface.MTU(); err == nil { + tun.mtu = getSupportedMTU(uint16(m)) } else { tun.mtu = 0 } diff --git a/src/types/types.go b/src/types/types.go deleted file mode 100644 index 5d1c024f..00000000 --- a/src/types/types.go +++ /dev/null @@ -1,3 +0,0 @@ -package types - -type MTU uint16 From 416eadbcff01821c9e41313b018cbe930e06a078 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Sun, 16 May 2021 20:00:45 +0100 Subject: [PATCH 2/3] Use uint64 for MTU for forward-compatibility --- src/admin/admin.go | 1 - src/config/config.go | 2 +- src/defaults/defaults.go | 4 ++-- src/tuntap/admin.go | 2 +- src/tuntap/tun.go | 12 ++++++------ src/tuntap/tun_bsd.go | 4 ++-- src/tuntap/tun_darwin.go | 4 ++-- src/tuntap/tun_linux.go | 4 ++-- src/tuntap/tun_other.go | 4 ++-- src/tuntap/tun_windows.go | 6 +++--- 10 files changed, 21 insertions(+), 22 deletions(-) diff --git a/src/admin/admin.go b/src/admin/admin.go index 855b0545..fc9d09c3 100644 --- a/src/admin/admin.go +++ b/src/admin/admin.go @@ -250,7 +250,6 @@ func (a *AdminSocket) handleRequest(conn net.Conn) { } } } - j, _ := json.Marshal(resp) if err = encoder.Encode(resp); err != nil { a.log.Debugln("Encode error:", err) } diff --git a/src/config/config.go b/src/config/config.go index 4aa9a213..49cc8a2a 100644 --- a/src/config/config.go +++ b/src/config/config.go @@ -69,7 +69,7 @@ type NodeConfig struct { 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."` IfName string `comment:"Local network interface name for TUN adapter, or \"auto\" to select\nan interface automatically, or \"none\" to run without TUN."` - 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."` + IfMTU uint64 `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."` 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."` diff --git a/src/defaults/defaults.go b/src/defaults/defaults.go index 57248088..a885c5dd 100644 --- a/src/defaults/defaults.go +++ b/src/defaults/defaults.go @@ -14,7 +14,7 @@ type platformDefaultParameters struct { DefaultMulticastInterfaces []string // TUN/TAP - MaximumIfMTU uint16 - DefaultIfMTU uint16 + MaximumIfMTU uint64 + DefaultIfMTU uint64 DefaultIfName string } diff --git a/src/tuntap/admin.go b/src/tuntap/admin.go index 5b50ff24..15a7463a 100644 --- a/src/tuntap/admin.go +++ b/src/tuntap/admin.go @@ -7,7 +7,7 @@ import ( ) type GetTUNRequest struct{} -type GetTUNResponse map[string]uint16 +type GetTUNResponse map[string]uint64 func (t *TunAdapter) getTUNHandler(req *GetTUNRequest, res *GetTUNResponse) error { res = &GetTUNResponse{ diff --git a/src/tuntap/tun.go b/src/tuntap/tun.go index a2f93e31..a5e8f9e1 100644 --- a/src/tuntap/tun.go +++ b/src/tuntap/tun.go @@ -39,7 +39,7 @@ type TunAdapter struct { log *log.Logger addr address.Address subnet address.Subnet - mtu uint16 + mtu uint64 iface tun.Device 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 @@ -55,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 // defaults.GetDefaults(). -func getSupportedMTU(mtu uint16) uint16 { +func getSupportedMTU(mtu uint64) uint64 { if mtu < 1280 { return 1280 } @@ -77,7 +77,7 @@ func (tun *TunAdapter) Name() string { // 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 // never exceed that of MaximumMTU(). -func (tun *TunAdapter) MTU() uint16 { +func (tun *TunAdapter) MTU() uint64 { return getSupportedMTU(tun.mtu) } @@ -88,14 +88,14 @@ func DefaultName() string { // 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. -func DefaultMTU() uint16 { +func DefaultMTU() uint64 { return defaults.GetDefaults().DefaultIfMTU } // MaximumMTU returns the maximum supported TUN interface MTU for your // platform. This can be as high as 65535, depending on platform, but is never // lower than 1280. -func MaximumMTU() uint16 { +func MaximumMTU() uint64 { return defaults.GetDefaults().MaximumIfMTU } @@ -150,7 +150,7 @@ func (tun *TunAdapter) _start() error { } mtu := current.IfMTU if tun.core.MTU() < uint64(mtu) { - mtu = uint16(tun.core.MTU()) + mtu = tun.core.MTU() } if err := tun.setup(current.IfName, addr, mtu); err != nil { return err diff --git a/src/tuntap/tun_bsd.go b/src/tuntap/tun_bsd.go index 4710e8cd..75158857 100644 --- a/src/tuntap/tun_bsd.go +++ b/src/tuntap/tun_bsd.go @@ -73,14 +73,14 @@ type in6_ifreq_lifetime struct { } // Configures the TUN 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 uint64) error { iface, err := wgtun.CreateTUN(ifname, int(mtu)) if err != nil { panic(err) } tun.iface = iface if mtu, err := iface.MTU(); err == nil { - tun.mtu = getSupportedMTU(MTU(mtu)) + tun.mtu = getSupportedMTU(uint64(mtu)) } else { tun.mtu = 0 } diff --git a/src/tuntap/tun_darwin.go b/src/tuntap/tun_darwin.go index b398eb19..609b42e3 100644 --- a/src/tuntap/tun_darwin.go +++ b/src/tuntap/tun_darwin.go @@ -16,7 +16,7 @@ import ( ) // Configures the "utun" adapter with the correct IPv6 address and MTU. -func (tun *TunAdapter) setup(ifname string, addr string, mtu uint16) error { +func (tun *TunAdapter) setup(ifname string, addr string, mtu uint64) error { if ifname == "auto" { ifname = "utun" } @@ -26,7 +26,7 @@ func (tun *TunAdapter) setup(ifname string, addr string, mtu uint16) error { } tun.iface = iface if m, err := iface.MTU(); err == nil { - tun.mtu = getSupportedMTU(uint16(m)) + tun.mtu = getSupportedMTU(uint64(m)) } else { tun.mtu = 0 } diff --git a/src/tuntap/tun_linux.go b/src/tuntap/tun_linux.go index ad7b64ef..0a845368 100644 --- a/src/tuntap/tun_linux.go +++ b/src/tuntap/tun_linux.go @@ -10,7 +10,7 @@ import ( ) // Configures the TUN 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 uint64) error { if ifname == "auto" { ifname = "\000" } @@ -20,7 +20,7 @@ func (tun *TunAdapter) setup(ifname string, addr string, mtu MTU) error { } tun.iface = iface if mtu, err := iface.MTU(); err == nil { - tun.mtu = getSupportedMTU(MTU(mtu)) + tun.mtu = getSupportedMTU(uint64(mtu)) } else { tun.mtu = 0 } diff --git a/src/tuntap/tun_other.go b/src/tuntap/tun_other.go index 8a27f57b..c0321267 100644 --- a/src/tuntap/tun_other.go +++ b/src/tuntap/tun_other.go @@ -10,14 +10,14 @@ import ( ) // Configures the TUN adapter with the correct IPv6 address and MTU. -func (tun *TunAdapter) setup(ifname string, addr string, mtu int) error { +func (tun *TunAdapter) setup(ifname string, addr string, mtu uint64) error { iface, err := wgtun.CreateTUN(ifname, mtu) if err != nil { panic(err) } tun.iface = iface if mtu, err := iface.MTU(); err == nil { - tun.mtu = getSupportedMTU(mtu) + tun.mtu = getSupportedMTU(uint64(mtu)) } else { tun.mtu = 0 } diff --git a/src/tuntap/tun_windows.go b/src/tuntap/tun_windows.go index 8eb21658..7b7ee710 100644 --- a/src/tuntap/tun_windows.go +++ b/src/tuntap/tun_windows.go @@ -19,7 +19,7 @@ import ( // This is to catch Windows platforms // Configures the TUN 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 uint64) error { if ifname == "auto" { ifname = defaults.GetDefaults().DefaultIfName } @@ -43,14 +43,14 @@ func (tun *TunAdapter) setup(ifname string, addr string, mtu MTU) error { return err } if mtu, err := iface.MTU(); err == nil { - tun.mtu = MTU(mtu) + tun.mtu = uint64(mtu) } return nil }) } // Sets the MTU of the TAP adapter. -func (tun *TunAdapter) setupMTU(mtu MTU) error { +func (tun *TunAdapter) setupMTU(mtu uint64) error { if tun.iface == nil || tun.Name() == "" { return errors.New("Can't configure MTU as TUN adapter is not present") } From 6413e95c48a880225e953ef278911c9fb3cd06fa Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Sun, 16 May 2021 20:05:22 +0100 Subject: [PATCH 3/3] Fix bug --- src/tuntap/tun.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tuntap/tun.go b/src/tuntap/tun.go index 26aa552e..97d0ba8b 100644 --- a/src/tuntap/tun.go +++ b/src/tuntap/tun.go @@ -224,7 +224,7 @@ func (tun *TunAdapter) sendKeyResponse(dest ed25519.PublicKey) { tun.core.SendOutOfBand(dest, bs) } -func (tun *TunAdapter) maxSessionMTU() MTU { +func (tun *TunAdapter) maxSessionMTU() uint64 { const sessionTypeOverhead = 1 - return MTU(tun.core.MTU() - sessionTypeOverhead) + return tun.core.MTU() - sessionTypeOverhead }