mirror of
				https://github.com/yggdrasil-network/yggdrasil-go.git
				synced 2025-11-04 11:15:07 +03:00 
			
		
		
		
	WIP moving IP-specific checks from tuntap to core
This commit is contained in:
		
							parent
							
								
									bb66851c2b
								
							
						
					
					
						commit
						1147ee1934
					
				
					 9 changed files with 339 additions and 220 deletions
				
			
		| 
						 | 
					@ -46,7 +46,7 @@ type Session struct {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *Core) GetSelf() Self {
 | 
					func (c *Core) GetSelf() Self {
 | 
				
			||||||
	var self Self
 | 
						var self Self
 | 
				
			||||||
	s := c.PacketConn.PacketConn.Debug.GetSelf()
 | 
						s := c.pc.PacketConn.Debug.GetSelf()
 | 
				
			||||||
	self.Key = s.Key
 | 
						self.Key = s.Key
 | 
				
			||||||
	self.Root = s.Root
 | 
						self.Root = s.Root
 | 
				
			||||||
	self.Coords = s.Coords
 | 
						self.Coords = s.Coords
 | 
				
			||||||
| 
						 | 
					@ -55,7 +55,7 @@ func (c *Core) GetSelf() Self {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *Core) GetPeers() []Peer {
 | 
					func (c *Core) GetPeers() []Peer {
 | 
				
			||||||
	var peers []Peer
 | 
						var peers []Peer
 | 
				
			||||||
	ps := c.PacketConn.PacketConn.Debug.GetPeers()
 | 
						ps := c.pc.PacketConn.Debug.GetPeers()
 | 
				
			||||||
	for _, p := range ps {
 | 
						for _, p := range ps {
 | 
				
			||||||
		var info Peer
 | 
							var info Peer
 | 
				
			||||||
		info.Key = p.Key
 | 
							info.Key = p.Key
 | 
				
			||||||
| 
						 | 
					@ -69,7 +69,7 @@ func (c *Core) GetPeers() []Peer {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *Core) GetDHT() []DHTEntry {
 | 
					func (c *Core) GetDHT() []DHTEntry {
 | 
				
			||||||
	var dhts []DHTEntry
 | 
						var dhts []DHTEntry
 | 
				
			||||||
	ds := c.PacketConn.PacketConn.Debug.GetDHT()
 | 
						ds := c.pc.PacketConn.Debug.GetDHT()
 | 
				
			||||||
	for _, d := range ds {
 | 
						for _, d := range ds {
 | 
				
			||||||
		var info DHTEntry
 | 
							var info DHTEntry
 | 
				
			||||||
		info.Key = d.Key
 | 
							info.Key = d.Key
 | 
				
			||||||
| 
						 | 
					@ -82,7 +82,7 @@ func (c *Core) GetDHT() []DHTEntry {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *Core) GetPaths() []PathEntry {
 | 
					func (c *Core) GetPaths() []PathEntry {
 | 
				
			||||||
	var paths []PathEntry
 | 
						var paths []PathEntry
 | 
				
			||||||
	ps := c.PacketConn.PacketConn.Debug.GetPaths()
 | 
						ps := c.pc.PacketConn.Debug.GetPaths()
 | 
				
			||||||
	for _, p := range ps {
 | 
						for _, p := range ps {
 | 
				
			||||||
		var info PathEntry
 | 
							var info PathEntry
 | 
				
			||||||
		info.Key = p.Key
 | 
							info.Key = p.Key
 | 
				
			||||||
| 
						 | 
					@ -94,7 +94,7 @@ func (c *Core) GetPaths() []PathEntry {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *Core) GetSessions() []Session {
 | 
					func (c *Core) GetSessions() []Session {
 | 
				
			||||||
	var sessions []Session
 | 
						var sessions []Session
 | 
				
			||||||
	ss := c.PacketConn.Debug.GetSessions()
 | 
						ss := c.pc.Debug.GetSessions()
 | 
				
			||||||
	for _, s := range ss {
 | 
						for _, s := range ss {
 | 
				
			||||||
		var info Session
 | 
							var info Session
 | 
				
			||||||
		info.Key = s.Key
 | 
							info.Key = s.Key
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,11 +25,13 @@ type Core struct {
 | 
				
			||||||
	// We're going to keep our own copy of the provided config - that way we can
 | 
						// 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
 | 
						// guarantee that it will be covered by the mutex
 | 
				
			||||||
	phony.Inbox
 | 
						phony.Inbox
 | 
				
			||||||
	*iw.PacketConn
 | 
						pc *iw.PacketConn
 | 
				
			||||||
	config       *config.NodeConfig // Config
 | 
						config       *config.NodeConfig // Config
 | 
				
			||||||
	secret       ed25519.PrivateKey
 | 
						secret       ed25519.PrivateKey
 | 
				
			||||||
	public       ed25519.PublicKey
 | 
						public       ed25519.PublicKey
 | 
				
			||||||
	links        links
 | 
						links        links
 | 
				
			||||||
 | 
						proto     protoHandler
 | 
				
			||||||
 | 
						store       keyStore
 | 
				
			||||||
	log          *log.Logger
 | 
						log          *log.Logger
 | 
				
			||||||
	addPeerTimer *time.Timer
 | 
						addPeerTimer *time.Timer
 | 
				
			||||||
	ctx          context.Context
 | 
						ctx          context.Context
 | 
				
			||||||
| 
						 | 
					@ -59,8 +61,10 @@ func (c *Core) _init() error {
 | 
				
			||||||
	c.public = c.secret.Public().(ed25519.PublicKey)
 | 
						c.public = c.secret.Public().(ed25519.PublicKey)
 | 
				
			||||||
	// TODO check public against current.PublicKey, error if they don't match
 | 
						// 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.ctx, c.ctxCancel = context.WithCancel(context.Background())
 | 
				
			||||||
 | 
						c.store.init(c)
 | 
				
			||||||
 | 
						c.proto.init(c)
 | 
				
			||||||
	return err
 | 
						return err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -160,7 +164,7 @@ func (c *Core) Stop() {
 | 
				
			||||||
func (c *Core) _stop() {
 | 
					func (c *Core) _stop() {
 | 
				
			||||||
	c.log.Infoln("Stopping...")
 | 
						c.log.Infoln("Stopping...")
 | 
				
			||||||
	c.ctxCancel()
 | 
						c.ctxCancel()
 | 
				
			||||||
	c.PacketConn.Close()
 | 
						c.pc.Close()
 | 
				
			||||||
	if c.addPeerTimer != nil {
 | 
						if c.addPeerTimer != nil {
 | 
				
			||||||
		c.addPeerTimer.Stop()
 | 
							c.addPeerTimer.Stop()
 | 
				
			||||||
		c.addPeerTimer = nil
 | 
							c.addPeerTimer = nil
 | 
				
			||||||
| 
						 | 
					@ -173,3 +177,20 @@ func (c *Core) _stop() {
 | 
				
			||||||
	*/
 | 
						*/
 | 
				
			||||||
	c.log.Infoln("Stopped")
 | 
						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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										295
									
								
								src/core/keystore.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										295
									
								
								src/core/keystore.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -20,8 +20,6 @@ import (
 | 
				
			||||||
	//"github.com/Arceliar/phony" // TODO? use instead of mutexes
 | 
						//"github.com/Arceliar/phony" // TODO? use instead of mutexes
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type keyArray [ed25519.PublicKeySize]byte
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type links struct {
 | 
					type links struct {
 | 
				
			||||||
	core    *Core
 | 
						core    *Core
 | 
				
			||||||
	mutex   sync.RWMutex // protects links below
 | 
						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",
 | 
						intf.links.core.log.Infof("Connected %s: %s, source %s",
 | 
				
			||||||
		strings.ToUpper(intf.info.linkType), themString, intf.info.local)
 | 
							strings.ToUpper(intf.info.linkType), themString, intf.info.local)
 | 
				
			||||||
	// Run the handler
 | 
						// 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'
 | 
						// TODO don't report an error if it's just a 'use of closed network connection'
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		intf.links.core.log.Infof("Disconnected %s: %s, source %s; error: %s",
 | 
							intf.links.core.log.Infof("Disconnected %s: %s, source %s; error: %s",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,4 @@
 | 
				
			||||||
package tuntap
 | 
					package core
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"encoding/hex"
 | 
						"encoding/hex"
 | 
				
			||||||
| 
						 | 
					@ -129,7 +129,7 @@ func (m *nodeinfo) _sendReq(key keyArray, callback func(nodeinfo NodeInfoPayload
 | 
				
			||||||
	if callback != nil {
 | 
						if callback != nil {
 | 
				
			||||||
		m._addCallback(key, callback)
 | 
							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) {
 | 
					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) {
 | 
					func (m *nodeinfo) _sendRes(key keyArray) {
 | 
				
			||||||
	bs := append([]byte{typeSessionProto, typeProtoNodeInfoResponse}, m._getNodeInfo()...)
 | 
						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
 | 
					// Admin socket stuff
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,4 @@
 | 
				
			||||||
package tuntap
 | 
					package core
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"encoding/hex"
 | 
						"encoding/hex"
 | 
				
			||||||
| 
						 | 
					@ -31,15 +31,15 @@ type reqInfo struct {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type protoHandler struct {
 | 
					type protoHandler struct {
 | 
				
			||||||
	phony.Inbox
 | 
						phony.Inbox
 | 
				
			||||||
	tun      *TunAdapter
 | 
						core    *Core
 | 
				
			||||||
	nodeinfo nodeinfo
 | 
						nodeinfo nodeinfo
 | 
				
			||||||
	sreqs    map[keyArray]*reqInfo
 | 
						sreqs    map[keyArray]*reqInfo
 | 
				
			||||||
	preqs    map[keyArray]*reqInfo
 | 
						preqs    map[keyArray]*reqInfo
 | 
				
			||||||
	dreqs    map[keyArray]*reqInfo
 | 
						dreqs    map[keyArray]*reqInfo
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (p *protoHandler) init(tun *TunAdapter) {
 | 
					func (p *protoHandler) init(core *Core) {
 | 
				
			||||||
	p.tun = tun
 | 
						p.core = core
 | 
				
			||||||
	p.nodeinfo.init(p)
 | 
						p.nodeinfo.init(p)
 | 
				
			||||||
	p.sreqs = make(map[keyArray]*reqInfo)
 | 
						p.sreqs = make(map[keyArray]*reqInfo)
 | 
				
			||||||
	p.preqs = 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) {
 | 
					func (p *protoHandler) _handleGetSelfRequest(key keyArray) {
 | 
				
			||||||
	self := p.tun.core.GetSelf()
 | 
						self := p.core.GetSelf()
 | 
				
			||||||
	res := map[string]string{
 | 
						res := map[string]string{
 | 
				
			||||||
		"key":    hex.EncodeToString(self.Key[:]),
 | 
							"key":    hex.EncodeToString(self.Key[:]),
 | 
				
			||||||
		"coords": fmt.Sprintf("%v", self.Coords),
 | 
							"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) {
 | 
					func (p *protoHandler) _handleGetPeersRequest(key keyArray) {
 | 
				
			||||||
	peers := p.tun.core.GetPeers()
 | 
						peers := p.core.GetPeers()
 | 
				
			||||||
	var bs []byte
 | 
						var bs []byte
 | 
				
			||||||
	for _, pinfo := range peers {
 | 
						for _, pinfo := range peers {
 | 
				
			||||||
		tmp := append(bs, pinfo.Key[:]...)
 | 
							tmp := append(bs, pinfo.Key[:]...)
 | 
				
			||||||
		const responseOverhead = 2 // 1 debug type, 1 getpeers type
 | 
							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
 | 
								break
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		bs = tmp
 | 
							bs = tmp
 | 
				
			||||||
| 
						 | 
					@ -186,12 +186,12 @@ func (p *protoHandler) sendGetDHTRequest(key keyArray, callback func([]byte)) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (p *protoHandler) _handleGetDHTRequest(key keyArray) {
 | 
					func (p *protoHandler) _handleGetDHTRequest(key keyArray) {
 | 
				
			||||||
	dinfos := p.tun.core.GetDHT()
 | 
						dinfos := p.core.GetDHT()
 | 
				
			||||||
	var bs []byte
 | 
						var bs []byte
 | 
				
			||||||
	for _, dinfo := range dinfos {
 | 
						for _, dinfo := range dinfos {
 | 
				
			||||||
		tmp := append(bs, dinfo.Key[:]...)
 | 
							tmp := append(bs, dinfo.Key[:]...)
 | 
				
			||||||
		const responseOverhead = 2 // 1 debug type, 1 getdht type
 | 
							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
 | 
								break
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		bs = tmp
 | 
							bs = tmp
 | 
				
			||||||
| 
						 | 
					@ -209,7 +209,7 @@ func (p *protoHandler) _handleGetDHTResponse(key keyArray, bs []byte) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (p *protoHandler) _sendDebug(key keyArray, dType uint8, data []byte) {
 | 
					func (p *protoHandler) _sendDebug(key keyArray, dType uint8, data []byte) {
 | 
				
			||||||
	bs := append([]byte{typeSessionProto, typeProtoDebug, dType}, data...)
 | 
						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
 | 
					// Admin socket stuff
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,4 @@
 | 
				
			||||||
package tuntap
 | 
					package core
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Out-of-band packet types
 | 
					// Out-of-band packet types
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
| 
						 | 
					@ -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)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -189,41 +189,3 @@ func (tun *TunAdapter) _stop() error {
 | 
				
			||||||
	return nil
 | 
						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
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue