mirror of
https://github.com/yggdrasil-network/yggdrasil-go.git
synced 2024-11-27 12:05:23 +00:00
WIP moving IP-specific checks from tuntap to core
This commit is contained in:
parent
bb66851c2b
commit
1147ee1934
@ -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…
Reference in New Issue
Block a user