diff --git a/src/core/api.go b/src/core/api.go index f28b592..bfccd66 100644 --- a/src/core/api.go +++ b/src/core/api.go @@ -46,7 +46,7 @@ type Session struct { func (c *Core) GetSelf() Self { var self Self - s := c.PacketConn.PacketConn.Debug.GetSelf() + s := c.pc.PacketConn.Debug.GetSelf() self.Key = s.Key self.Root = s.Root self.Coords = s.Coords @@ -55,7 +55,7 @@ func (c *Core) GetSelf() Self { func (c *Core) GetPeers() []Peer { var peers []Peer - ps := c.PacketConn.PacketConn.Debug.GetPeers() + ps := c.pc.PacketConn.Debug.GetPeers() for _, p := range ps { var info Peer info.Key = p.Key @@ -69,7 +69,7 @@ func (c *Core) GetPeers() []Peer { func (c *Core) GetDHT() []DHTEntry { var dhts []DHTEntry - ds := c.PacketConn.PacketConn.Debug.GetDHT() + ds := c.pc.PacketConn.Debug.GetDHT() for _, d := range ds { var info DHTEntry info.Key = d.Key @@ -82,7 +82,7 @@ func (c *Core) GetDHT() []DHTEntry { func (c *Core) GetPaths() []PathEntry { var paths []PathEntry - ps := c.PacketConn.PacketConn.Debug.GetPaths() + ps := c.pc.PacketConn.Debug.GetPaths() for _, p := range ps { var info PathEntry info.Key = p.Key @@ -94,7 +94,7 @@ func (c *Core) GetPaths() []PathEntry { func (c *Core) GetSessions() []Session { var sessions []Session - ss := c.PacketConn.Debug.GetSessions() + ss := c.pc.Debug.GetSessions() for _, s := range ss { var info Session info.Key = s.Key diff --git a/src/core/core.go b/src/core/core.go index bd2478f..cb34d89 100644 --- a/src/core/core.go +++ b/src/core/core.go @@ -25,11 +25,13 @@ type Core struct { // We're going to keep our own copy of the provided config - that way we can // guarantee that it will be covered by the mutex phony.Inbox - *iw.PacketConn + pc *iw.PacketConn config *config.NodeConfig // Config secret ed25519.PrivateKey public ed25519.PublicKey links links + proto protoHandler + store keyStore log *log.Logger addPeerTimer *time.Timer ctx context.Context @@ -59,8 +61,10 @@ func (c *Core) _init() error { c.public = c.secret.Public().(ed25519.PublicKey) // TODO check public against current.PublicKey, error if they don't match - c.PacketConn, err = iw.NewPacketConn(c.secret) + c.pc, err = iw.NewPacketConn(c.secret) c.ctx, c.ctxCancel = context.WithCancel(context.Background()) + c.store.init(c) + c.proto.init(c) return err } @@ -160,7 +164,7 @@ func (c *Core) Stop() { func (c *Core) _stop() { c.log.Infoln("Stopping...") c.ctxCancel() - c.PacketConn.Close() + c.pc.Close() if c.addPeerTimer != nil { c.addPeerTimer.Stop() c.addPeerTimer = nil @@ -173,3 +177,20 @@ func (c *Core) _stop() { */ c.log.Infoln("Stopped") } + +// Implement io.ReadWriteCloser + +func (c *Core) Read(p []byte) (n int, err error) { + n, err = c.store.readPC(p) + return +} + +func (c *Core) Write(p []byte) (n int, err error) { + n, err = c.store.writePC(p) + return +} + +func (c *Core) Close() error { + c.Stop() + return nil +} diff --git a/src/core/keystore.go b/src/core/keystore.go new file mode 100644 index 0000000..4342488 --- /dev/null +++ b/src/core/keystore.go @@ -0,0 +1,295 @@ +package core + +import ( + "crypto/ed25519" + "errors" + "fmt" + "sync" + "time" + + iwt "github.com/Arceliar/ironwood/types" + + "github.com/yggdrasil-network/yggdrasil-go/src/address" +) + +const keyStoreTimeout = 2 * time.Minute + +type keyArray [ed25519.PublicKeySize]byte + +type keyStore struct { + core *Core + address address.Address + subnet address.Subnet + mutex sync.Mutex + keyToInfo map[keyArray]*keyInfo + addrToInfo map[address.Address]*keyInfo + addrBuffer map[address.Address]*buffer + subnetToInfo map[address.Subnet]*keyInfo + subnetBuffer map[address.Subnet]*buffer + buf []byte // scratch space to prefix with typeSessionTraffic before sending +} + +type keyInfo struct { + key keyArray + address address.Address + subnet address.Subnet + timeout *time.Timer // From calling a time.AfterFunc to do cleanup +} + +type buffer struct { + packets [][]byte + timeout *time.Timer +} + +func (k *keyStore) init(core *Core) { + k.core = core + k.address = *address.AddrForKey(k.core.public) + k.subnet = *address.SubnetForKey(k.core.public) + k.core.pc.SetOutOfBandHandler(k.oobHandler) + k.keyToInfo = make(map[keyArray]*keyInfo) + k.addrToInfo = make(map[address.Address]*keyInfo) + k.addrBuffer = make(map[address.Address]*buffer) + k.subnetToInfo = make(map[address.Subnet]*keyInfo) + k.subnetBuffer = make(map[address.Subnet]*buffer) +} + +func (k *keyStore) sendToAddress(addr address.Address, bs []byte) { + k.mutex.Lock() + if info := k.addrToInfo[addr]; info != nil { + k.resetTimeout(info) + k.mutex.Unlock() + _, _ = k.core.pc.WriteTo(bs, iwt.Addr(info.key[:])) + } else { + var buf *buffer + if buf = k.addrBuffer[addr]; buf == nil { + buf = new(buffer) + k.addrBuffer[addr] = buf + } + msg := append([]byte(nil), bs...) + buf.packets = append(buf.packets, msg) + if buf.timeout != nil { + buf.timeout.Stop() + } + buf.timeout = time.AfterFunc(keyStoreTimeout, func() { + k.mutex.Lock() + defer k.mutex.Unlock() + if nbuf := k.addrBuffer[addr]; nbuf == buf { + delete(k.addrBuffer, addr) + } + }) + k.mutex.Unlock() + k.sendKeyLookup(addr.GetKey()) + } +} + +func (k *keyStore) sendToSubnet(subnet address.Subnet, bs []byte) { + k.mutex.Lock() + if info := k.subnetToInfo[subnet]; info != nil { + k.resetTimeout(info) + k.mutex.Unlock() + _, _ = k.core.pc.WriteTo(bs, iwt.Addr(info.key[:])) + } else { + var buf *buffer + if buf = k.subnetBuffer[subnet]; buf == nil { + buf = new(buffer) + k.subnetBuffer[subnet] = buf + } + msg := append([]byte(nil), bs...) + buf.packets = append(buf.packets, msg) + if buf.timeout != nil { + buf.timeout.Stop() + } + buf.timeout = time.AfterFunc(keyStoreTimeout, func() { + k.mutex.Lock() + defer k.mutex.Unlock() + if nbuf := k.subnetBuffer[subnet]; nbuf == buf { + delete(k.subnetBuffer, subnet) + } + }) + k.mutex.Unlock() + k.sendKeyLookup(subnet.GetKey()) + } +} + +func (k *keyStore) update(key ed25519.PublicKey) *keyInfo { + k.mutex.Lock() + var kArray keyArray + copy(kArray[:], key) + var info *keyInfo + if info = k.keyToInfo[kArray]; info == nil { + info = new(keyInfo) + info.key = kArray + info.address = *address.AddrForKey(ed25519.PublicKey(info.key[:])) + info.subnet = *address.SubnetForKey(ed25519.PublicKey(info.key[:])) + k.keyToInfo[info.key] = info + k.addrToInfo[info.address] = info + k.subnetToInfo[info.subnet] = info + k.resetTimeout(info) + k.mutex.Unlock() + if buf := k.addrBuffer[info.address]; buf != nil { + for _, bs := range buf.packets { + _, _ = k.core.pc.WriteTo(bs, iwt.Addr(info.key[:])) + } + delete(k.addrBuffer, info.address) + } + if buf := k.subnetBuffer[info.subnet]; buf != nil { + for _, bs := range buf.packets { + _, _ = k.core.pc.WriteTo(bs, iwt.Addr(info.key[:])) + } + delete(k.subnetBuffer, info.subnet) + } + } else { + k.resetTimeout(info) + k.mutex.Unlock() + } + return info +} + +func (k *keyStore) resetTimeout(info *keyInfo) { + if info.timeout != nil { + info.timeout.Stop() + } + info.timeout = time.AfterFunc(keyStoreTimeout, func() { + k.mutex.Lock() + defer k.mutex.Unlock() + if nfo := k.keyToInfo[info.key]; nfo == info { + delete(k.keyToInfo, info.key) + } + if nfo := k.addrToInfo[info.address]; nfo == info { + delete(k.addrToInfo, info.address) + } + if nfo := k.subnetToInfo[info.subnet]; nfo == info { + delete(k.subnetToInfo, info.subnet) + } + }) +} + +func (k *keyStore) oobHandler(fromKey, toKey ed25519.PublicKey, data []byte) { + if len(data) != 1+ed25519.SignatureSize { + return + } + sig := data[1:] + switch data[0] { + case typeKeyLookup: + snet := *address.SubnetForKey(toKey) + if snet == k.subnet && ed25519.Verify(fromKey, toKey[:], sig) { + // This is looking for at least our subnet (possibly our address) + // Send a response + k.sendKeyResponse(fromKey) + } + case typeKeyResponse: + // TODO keep a list of something to match against... + // Ignore the response if it doesn't match anything of interest... + if ed25519.Verify(fromKey, toKey[:], sig) { + k.update(fromKey) + } + } +} + +func (k *keyStore) sendKeyLookup(partial ed25519.PublicKey) { + sig := ed25519.Sign(k.core.secret, partial[:]) + bs := append([]byte{typeKeyLookup}, sig...) + _ = k.core.pc.SendOutOfBand(partial, bs) +} + +func (k *keyStore) sendKeyResponse(dest ed25519.PublicKey) { + sig := ed25519.Sign(k.core.secret, dest[:]) + bs := append([]byte{typeKeyResponse}, sig...) + _ = k.core.pc.SendOutOfBand(dest, bs) +} + +func (k *keyStore) maxSessionMTU() uint64 { + const sessionTypeOverhead = 1 + return k.core.pc.MTU() - sessionTypeOverhead +} + +func (k *keyStore) readPC(p []byte) (int, error) { + for { + bs := p + n, from, err := k.core.pc.ReadFrom(bs) + if err != nil { + return n, err + } + if n == 0 { + continue + } + switch bs[0] { + case typeSessionTraffic: + // This is what we want to handle here + case typeSessionProto: + var key keyArray + copy(key[:], from.(iwt.Addr)) + data := append([]byte(nil), bs[1:n]...) + k.core.proto.handleProto(nil, key, data) + continue + default: + continue + } + bs = bs[1:n] + if len(bs) == 0 { + continue + } + if bs[0]&0xf0 != 0x60 { + continue // not IPv6 + } + if len(bs) < 40 { + continue + } + /* TODO ICMP packet too big + if len(bs) > int(tun.MTU()) { + ptb := &icmp.PacketTooBig{ + MTU: int(tun.mtu), + Data: bs[:40], + } + if packet, err := CreateICMPv6(bs[8:24], bs[24:40], ipv6.ICMPTypePacketTooBig, 0, ptb); err == nil { + _, _ = tun.core.WriteTo(packet, from) + } + continue + } + */ + var srcAddr, dstAddr address.Address + var srcSubnet, dstSubnet address.Subnet + copy(srcAddr[:], bs[8:]) + copy(dstAddr[:], bs[24:]) + copy(srcSubnet[:], bs[8:]) + copy(dstSubnet[:], bs[24:]) + if dstAddr != k.address && dstSubnet != k.subnet { + continue // bad local address/subnet + } + info := k.update(ed25519.PublicKey(from.(iwt.Addr))) + if srcAddr != info.address && srcSubnet != info.subnet { + continue // bad remote address/subnet + } + n = copy(p, bs) + return n, nil + } +} + +func (k *keyStore) writePC(bs []byte) (int, error) { + if bs[0]&0xf0 != 0x60 { + return 0, errors.New("not an IPv6 packet") // not IPv6 + } + if len(bs) < 40 { + strErr := fmt.Sprint("undersized IPv6 packet, length:", len(bs)) + return 0, errors.New(strErr) + } + var srcAddr, dstAddr address.Address + var srcSubnet, dstSubnet address.Subnet + copy(srcAddr[:], bs[8:]) + copy(dstAddr[:], bs[24:]) + copy(srcSubnet[:], bs[8:]) + copy(dstSubnet[:], bs[24:]) + if srcAddr != k.address && srcSubnet != k.subnet { + return 0, errors.New("wrong source address") + } + k.buf = append(k.buf[:0], typeSessionTraffic) + k.buf = append(k.buf, bs...) + if dstAddr.IsValid() { + k.sendToAddress(dstAddr, k.buf) + } else if dstSubnet.IsValid() { + k.sendToSubnet(dstSubnet, k.buf) + } else { + return 0, errors.New("invalid destination address") + } + return len(bs), nil +} diff --git a/src/core/link.go b/src/core/link.go index c0eb509..295a8ad 100644 --- a/src/core/link.go +++ b/src/core/link.go @@ -20,8 +20,6 @@ import ( //"github.com/Arceliar/phony" // TODO? use instead of mutexes ) -type keyArray [ed25519.PublicKeySize]byte - type links struct { core *Core mutex sync.RWMutex // protects links below @@ -231,7 +229,7 @@ func (intf *link) handler() (chan struct{}, error) { intf.links.core.log.Infof("Connected %s: %s, source %s", strings.ToUpper(intf.info.linkType), themString, intf.info.local) // Run the handler - err = intf.links.core.PacketConn.HandleConn(ed25519.PublicKey(intf.info.key[:]), intf.conn) + err = intf.links.core.pc.HandleConn(ed25519.PublicKey(intf.info.key[:]), intf.conn) // TODO don't report an error if it's just a 'use of closed network connection' if err != nil { intf.links.core.log.Infof("Disconnected %s: %s, source %s; error: %s", diff --git a/src/tuntap/nodeinfo.go b/src/core/nodeinfo.go similarity index 96% rename from src/tuntap/nodeinfo.go rename to src/core/nodeinfo.go index a61a442..3064471 100644 --- a/src/tuntap/nodeinfo.go +++ b/src/core/nodeinfo.go @@ -1,4 +1,4 @@ -package tuntap +package core import ( "encoding/hex" @@ -129,7 +129,7 @@ func (m *nodeinfo) _sendReq(key keyArray, callback func(nodeinfo NodeInfoPayload if callback != nil { m._addCallback(key, callback) } - _, _ = m.proto.tun.core.WriteTo([]byte{typeSessionProto, typeProtoNodeInfoRequest}, iwt.Addr(key[:])) + _, _ = m.proto.core.pc.WriteTo([]byte{typeSessionProto, typeProtoNodeInfoRequest}, iwt.Addr(key[:])) } func (m *nodeinfo) handleReq(from phony.Actor, key keyArray) { @@ -146,7 +146,7 @@ func (m *nodeinfo) handleRes(from phony.Actor, key keyArray, info NodeInfoPayloa func (m *nodeinfo) _sendRes(key keyArray) { bs := append([]byte{typeSessionProto, typeProtoNodeInfoResponse}, m._getNodeInfo()...) - _, _ = m.proto.tun.core.WriteTo(bs, iwt.Addr(key[:])) + _, _ = m.proto.core.pc.WriteTo(bs, iwt.Addr(key[:])) } // Admin socket stuff diff --git a/src/tuntap/proto.go b/src/core/proto.go similarity index 95% rename from src/tuntap/proto.go rename to src/core/proto.go index 62b2156..24d54ca 100644 --- a/src/tuntap/proto.go +++ b/src/core/proto.go @@ -1,4 +1,4 @@ -package tuntap +package core import ( "encoding/hex" @@ -31,15 +31,15 @@ type reqInfo struct { type protoHandler struct { phony.Inbox - tun *TunAdapter + core *Core nodeinfo nodeinfo sreqs map[keyArray]*reqInfo preqs map[keyArray]*reqInfo dreqs map[keyArray]*reqInfo } -func (p *protoHandler) init(tun *TunAdapter) { - p.tun = tun +func (p *protoHandler) init(core *Core) { + p.core = core p.nodeinfo.init(p) p.sreqs = make(map[keyArray]*reqInfo) p.preqs = make(map[keyArray]*reqInfo) @@ -103,7 +103,7 @@ func (p *protoHandler) sendGetSelfRequest(key keyArray, callback func([]byte)) { } func (p *protoHandler) _handleGetSelfRequest(key keyArray) { - self := p.tun.core.GetSelf() + self := p.core.GetSelf() res := map[string]string{ "key": hex.EncodeToString(self.Key[:]), "coords": fmt.Sprintf("%v", self.Coords), @@ -144,12 +144,12 @@ func (p *protoHandler) sendGetPeersRequest(key keyArray, callback func([]byte)) } func (p *protoHandler) _handleGetPeersRequest(key keyArray) { - peers := p.tun.core.GetPeers() + peers := p.core.GetPeers() var bs []byte for _, pinfo := range peers { tmp := append(bs, pinfo.Key[:]...) const responseOverhead = 2 // 1 debug type, 1 getpeers type - if uint64(len(tmp))+responseOverhead > p.tun.maxSessionMTU() { + if uint64(len(tmp))+responseOverhead > p.core.store.maxSessionMTU() { break } bs = tmp @@ -186,12 +186,12 @@ func (p *protoHandler) sendGetDHTRequest(key keyArray, callback func([]byte)) { } func (p *protoHandler) _handleGetDHTRequest(key keyArray) { - dinfos := p.tun.core.GetDHT() + dinfos := p.core.GetDHT() var bs []byte for _, dinfo := range dinfos { tmp := append(bs, dinfo.Key[:]...) const responseOverhead = 2 // 1 debug type, 1 getdht type - if uint64(len(tmp))+responseOverhead > p.tun.maxSessionMTU() { + if uint64(len(tmp))+responseOverhead > p.core.store.maxSessionMTU() { break } bs = tmp @@ -209,7 +209,7 @@ func (p *protoHandler) _handleGetDHTResponse(key keyArray, bs []byte) { func (p *protoHandler) _sendDebug(key keyArray, dType uint8, data []byte) { bs := append([]byte{typeSessionProto, typeProtoDebug, dType}, data...) - _, _ = p.tun.core.WriteTo(bs, iwt.Addr(key[:])) + _, _ = p.core.pc.WriteTo(bs, iwt.Addr(key[:])) } // Admin socket stuff diff --git a/src/tuntap/types.go b/src/core/types.go similarity index 96% rename from src/tuntap/types.go rename to src/core/types.go index a8084e0..e325b55 100644 --- a/src/tuntap/types.go +++ b/src/core/types.go @@ -1,4 +1,4 @@ -package tuntap +package core // Out-of-band packet types const ( diff --git a/src/tuntap/keystore.go b/src/tuntap/keystore.go deleted file mode 100644 index 2eb7920..0000000 --- a/src/tuntap/keystore.go +++ /dev/null @@ -1,157 +0,0 @@ -package tuntap - -import ( - "crypto/ed25519" - "sync" - "time" - - iwt "github.com/Arceliar/ironwood/types" - - "github.com/yggdrasil-network/yggdrasil-go/src/address" -) - -const keyStoreTimeout = 2 * time.Minute - -type keyStore struct { - tun *TunAdapter - mutex sync.Mutex - keyToInfo map[keyArray]*keyInfo - addrToInfo map[address.Address]*keyInfo - addrBuffer map[address.Address]*buffer - subnetToInfo map[address.Subnet]*keyInfo - subnetBuffer map[address.Subnet]*buffer -} - -type keyArray [ed25519.PublicKeySize]byte - -type keyInfo struct { - key keyArray - address address.Address - subnet address.Subnet - timeout *time.Timer // From calling a time.AfterFunc to do cleanup -} - -type buffer struct { - packets [][]byte - timeout *time.Timer -} - -func (k *keyStore) init(tun *TunAdapter) { - k.tun = tun - k.keyToInfo = make(map[keyArray]*keyInfo) - k.addrToInfo = make(map[address.Address]*keyInfo) - k.addrBuffer = make(map[address.Address]*buffer) - k.subnetToInfo = make(map[address.Subnet]*keyInfo) - k.subnetBuffer = make(map[address.Subnet]*buffer) -} - -func (k *keyStore) sendToAddress(addr address.Address, bs []byte) { - k.mutex.Lock() - if info := k.addrToInfo[addr]; info != nil { - k.resetTimeout(info) - k.mutex.Unlock() - _, _ = k.tun.core.WriteTo(bs, iwt.Addr(info.key[:])) - } else { - var buf *buffer - if buf = k.addrBuffer[addr]; buf == nil { - buf = new(buffer) - k.addrBuffer[addr] = buf - } - msg := append([]byte(nil), bs...) - buf.packets = append(buf.packets, msg) - if buf.timeout != nil { - buf.timeout.Stop() - } - buf.timeout = time.AfterFunc(keyStoreTimeout, func() { - k.mutex.Lock() - defer k.mutex.Unlock() - if nbuf := k.addrBuffer[addr]; nbuf == buf { - delete(k.addrBuffer, addr) - } - }) - k.mutex.Unlock() - k.tun.sendKeyLookup(addr.GetKey()) - } -} - -func (k *keyStore) sendToSubnet(subnet address.Subnet, bs []byte) { - k.mutex.Lock() - if info := k.subnetToInfo[subnet]; info != nil { - k.resetTimeout(info) - k.mutex.Unlock() - _, _ = k.tun.core.WriteTo(bs, iwt.Addr(info.key[:])) - } else { - var buf *buffer - if buf = k.subnetBuffer[subnet]; buf == nil { - buf = new(buffer) - k.subnetBuffer[subnet] = buf - } - msg := append([]byte(nil), bs...) - buf.packets = append(buf.packets, msg) - if buf.timeout != nil { - buf.timeout.Stop() - } - buf.timeout = time.AfterFunc(keyStoreTimeout, func() { - k.mutex.Lock() - defer k.mutex.Unlock() - if nbuf := k.subnetBuffer[subnet]; nbuf == buf { - delete(k.subnetBuffer, subnet) - } - }) - k.mutex.Unlock() - k.tun.sendKeyLookup(subnet.GetKey()) - } -} - -func (k *keyStore) update(key ed25519.PublicKey) *keyInfo { - k.mutex.Lock() - var kArray keyArray - copy(kArray[:], key) - var info *keyInfo - if info = k.keyToInfo[kArray]; info == nil { - info = new(keyInfo) - info.key = kArray - info.address = *address.AddrForKey(ed25519.PublicKey(info.key[:])) - info.subnet = *address.SubnetForKey(ed25519.PublicKey(info.key[:])) - k.keyToInfo[info.key] = info - k.addrToInfo[info.address] = info - k.subnetToInfo[info.subnet] = info - k.resetTimeout(info) - k.mutex.Unlock() - if buf := k.addrBuffer[info.address]; buf != nil { - for _, bs := range buf.packets { - _, _ = k.tun.core.WriteTo(bs, iwt.Addr(info.key[:])) - } - delete(k.addrBuffer, info.address) - } - if buf := k.subnetBuffer[info.subnet]; buf != nil { - for _, bs := range buf.packets { - _, _ = k.tun.core.WriteTo(bs, iwt.Addr(info.key[:])) - } - delete(k.subnetBuffer, info.subnet) - } - } else { - k.resetTimeout(info) - k.mutex.Unlock() - } - return info -} - -func (k *keyStore) resetTimeout(info *keyInfo) { - if info.timeout != nil { - info.timeout.Stop() - } - info.timeout = time.AfterFunc(keyStoreTimeout, func() { - k.mutex.Lock() - defer k.mutex.Unlock() - if nfo := k.keyToInfo[info.key]; nfo == info { - delete(k.keyToInfo, info.key) - } - if nfo := k.addrToInfo[info.address]; nfo == info { - delete(k.addrToInfo, info.address) - } - if nfo := k.subnetToInfo[info.subnet]; nfo == info { - delete(k.subnetToInfo, info.subnet) - } - }) -} diff --git a/src/tuntap/tun.go b/src/tuntap/tun.go index f53f6de..7b20bfb 100644 --- a/src/tuntap/tun.go +++ b/src/tuntap/tun.go @@ -189,41 +189,3 @@ func (tun *TunAdapter) _stop() error { return nil } -func (tun *TunAdapter) oobHandler(fromKey, toKey ed25519.PublicKey, data []byte) { - if len(data) != 1+ed25519.SignatureSize { - return - } - sig := data[1:] - switch data[0] { - case typeKeyLookup: - snet := *address.SubnetForKey(toKey) - if snet == tun.subnet && ed25519.Verify(fromKey, toKey[:], sig) { - // This is looking for at least our subnet (possibly our address) - // Send a response - tun.sendKeyResponse(fromKey) - } - case typeKeyResponse: - // TODO keep a list of something to match against... - // Ignore the response if it doesn't match anything of interest... - if ed25519.Verify(fromKey, toKey[:], sig) { - tun.store.update(fromKey) - } - } -} - -func (tun *TunAdapter) sendKeyLookup(partial ed25519.PublicKey) { - sig := ed25519.Sign(tun.core.PrivateKey(), partial[:]) - bs := append([]byte{typeKeyLookup}, sig...) - _ = tun.core.SendOutOfBand(partial, bs) -} - -func (tun *TunAdapter) sendKeyResponse(dest ed25519.PublicKey) { - sig := ed25519.Sign(tun.core.PrivateKey(), dest[:]) - bs := append([]byte{typeKeyResponse}, sig...) - _ = tun.core.SendOutOfBand(dest, bs) -} - -func (tun *TunAdapter) maxSessionMTU() uint64 { - const sessionTypeOverhead = 1 - return tun.core.MTU() - sessionTypeOverhead -}